Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem

This commit is contained in:
John W. Linville 2012-07-20 12:30:48 -04:00
commit 90b90f60c4
163 changed files with 5139 additions and 2915 deletions

View file

@ -404,7 +404,6 @@
!Finclude/net/mac80211.h ieee80211_get_tkip_p1k
!Finclude/net/mac80211.h ieee80211_get_tkip_p1k_iv
!Finclude/net/mac80211.h ieee80211_get_tkip_p2k
!Finclude/net/mac80211.h ieee80211_key_removed
</chapter>
<chapter id="powersave">

View file

@ -46,6 +46,25 @@ config BCMA_DRIVER_MIPS
If unsure, say N
config BCMA_SFLASH
bool
depends on BCMA_DRIVER_MIPS && BROKEN
default y
config BCMA_NFLASH
bool
depends on BCMA_DRIVER_MIPS && BROKEN
default y
config BCMA_DRIVER_GMAC_CMN
bool "BCMA Broadcom GBIT MAC COMMON core driver"
depends on BCMA
help
Driver for the Broadcom GBIT MAC COMMON core attached to Broadcom
specific Advanced Microcontroller Bus.
If unsure, say N
config BCMA_DEBUG
bool "BCMA debugging"
depends on BCMA

View file

@ -1,8 +1,11 @@
bcma-y += main.o scan.o core.o sprom.o
bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o
bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o
bcma-y += driver_pci.o
bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o
bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o
bcma-$(CONFIG_BCMA_HOST_SOC) += host_soc.o
obj-$(CONFIG_BCMA) += bcma.o

View file

@ -51,6 +51,28 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc);
u32 bcma_pmu_alp_clock(struct bcma_drv_cc *cc);
u32 bcma_pmu_get_clockcpu(struct bcma_drv_cc *cc);
#ifdef CONFIG_BCMA_SFLASH
/* driver_chipcommon_sflash.c */
int bcma_sflash_init(struct bcma_drv_cc *cc);
#else
static inline int bcma_sflash_init(struct bcma_drv_cc *cc)
{
bcma_err(cc->core->bus, "Serial flash not supported\n");
return 0;
}
#endif /* CONFIG_BCMA_SFLASH */
#ifdef CONFIG_BCMA_NFLASH
/* driver_chipcommon_nflash.c */
int bcma_nflash_init(struct bcma_drv_cc *cc);
#else
static inline int bcma_nflash_init(struct bcma_drv_cc *cc)
{
bcma_err(cc->core->bus, "NAND flash not supported\n");
return 0;
}
#endif /* CONFIG_BCMA_NFLASH */
#ifdef CONFIG_BCMA_HOST_PCI
/* host_pci.c */
extern int __init bcma_host_pci_init(void);

View file

@ -0,0 +1,19 @@
/*
* Broadcom specific AMBA
* ChipCommon NAND flash interface
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include <linux/bcma/bcma.h>
#include <linux/bcma/bcma_driver_chipcommon.h>
#include <linux/delay.h>
#include "bcma_private.h"
/* Initialize NAND flash access */
int bcma_nflash_init(struct bcma_drv_cc *cc)
{
bcma_err(cc->core->bus, "NAND flash support is broken\n");
return 0;
}

View file

@ -0,0 +1,19 @@
/*
* Broadcom specific AMBA
* ChipCommon serial flash interface
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include <linux/bcma/bcma.h>
#include <linux/bcma/bcma_driver_chipcommon.h>
#include <linux/delay.h>
#include "bcma_private.h"
/* Initialize serial flash access */
int bcma_sflash_init(struct bcma_drv_cc *cc)
{
bcma_err(cc->core->bus, "Serial flash support is broken\n");
return 0;
}

View file

@ -0,0 +1,14 @@
/*
* Broadcom specific AMBA
* GBIT MAC COMMON Core
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include "bcma_private.h"
#include <linux/bcma/bcma.h>
void __devinit bcma_core_gmac_cmn_init(struct bcma_drv_gmac_cmn *gc)
{
mutex_init(&gc->phy_mutex);
}

View file

@ -185,10 +185,11 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
case BCMA_CC_FLASHT_STSER:
case BCMA_CC_FLASHT_ATSER:
bcma_err(bus, "Serial flash not supported.\n");
bcma_debug(bus, "Found serial flash\n");
bcma_sflash_init(&bus->drv_cc);
break;
case BCMA_CC_FLASHT_PARA:
bcma_info(bus, "found parallel flash.\n");
bcma_debug(bus, "Found parallel flash\n");
bus->drv_cc.pflash.window = 0x1c000000;
bus->drv_cc.pflash.window_size = 0x02000000;
@ -199,7 +200,15 @@ static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
bus->drv_cc.pflash.buswidth = 2;
break;
default:
bcma_err(bus, "flash not supported.\n");
bcma_err(bus, "Flash type not supported\n");
}
if (bus->drv_cc.core->id.rev == 38 ||
bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
if (bus->drv_cc.capabilities & BCMA_CC_CAP_NFLASH) {
bcma_debug(bus, "Found NAND flash\n");
bcma_nflash_init(&bus->drv_cc);
}
}
}

View file

@ -61,6 +61,13 @@ static struct bus_type bcma_bus_type = {
.dev_attrs = bcma_device_attrs,
};
static u16 bcma_cc_core_id(struct bcma_bus *bus)
{
if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
return BCMA_CORE_4706_CHIPCOMMON;
return BCMA_CORE_CHIPCOMMON;
}
struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
{
struct bcma_device *core;
@ -91,10 +98,12 @@ static int bcma_register_cores(struct bcma_bus *bus)
list_for_each_entry(core, &bus->cores, list) {
/* We support that cores ourself */
switch (core->id.id) {
case BCMA_CORE_4706_CHIPCOMMON:
case BCMA_CORE_CHIPCOMMON:
case BCMA_CORE_PCI:
case BCMA_CORE_PCIE:
case BCMA_CORE_MIPS_74K:
case BCMA_CORE_4706_MAC_GBIT_COMMON:
continue;
}
@ -157,7 +166,7 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
}
/* Init CC core */
core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
core = bcma_find_core(bus, bcma_cc_core_id(bus));
if (core) {
bus->drv_cc.core = core;
bcma_core_chipcommon_init(&bus->drv_cc);
@ -177,6 +186,13 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
bcma_core_pci_init(&bus->drv_pci);
}
/* Init GBIT MAC COMMON core */
core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
if (core) {
bus->drv_gmac_cmn.core = core;
bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn);
}
/* Try to get SPROM */
err = bcma_sprom_get(bus);
if (err == -ENOENT) {
@ -208,7 +224,7 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
bcma_init_bus(bus);
match.manuf = BCMA_MANUF_BCM;
match.id = BCMA_CORE_CHIPCOMMON;
match.id = bcma_cc_core_id(bus);
match.class = BCMA_CL_SIM;
match.rev = BCMA_ANY_REV;
@ -232,7 +248,7 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
}
/* Init CC core */
core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
core = bcma_find_core(bus, bcma_cc_core_id(bus));
if (core) {
bus->drv_cc.core = core;
bcma_core_chipcommon_init(&bus->drv_cc);
@ -271,8 +287,7 @@ int bcma_bus_resume(struct bcma_bus *bus)
struct bcma_device *core;
/* Init CC core */
core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON);
if (core) {
if (bus->drv_cc.core) {
bus->drv_cc.setup_done = false;
bcma_core_chipcommon_init(&bus->drv_cc);
}

View file

@ -21,6 +21,7 @@ struct bcma_device_id_name {
};
static const struct bcma_device_id_name bcma_arm_device_names[] = {
{ BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" },
{ BCMA_CORE_ARM_1176, "ARM 1176" },
{ BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" },
{ BCMA_CORE_ARM_CM3, "ARM CM3" },
@ -33,7 +34,6 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = {
{ BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" },
{ BCMA_CORE_AMEMC, "AMEMC (DDR)" },
{ BCMA_CORE_ALTA, "ALTA (I2S)" },
{ BCMA_CORE_4706_MAC_GBIT_COMMON, "BCM4706 GBit MAC Common" },
{ BCMA_CORE_INVALID, "Invalid" },
{ BCMA_CORE_CHIPCOMMON, "ChipCommon" },
{ BCMA_CORE_ILINE20, "ILine 20" },
@ -295,11 +295,15 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
/* check if component is a core at all */
if (wrappers[0] + wrappers[1] == 0) {
/* we could save addrl of the router
if (cid == BCMA_CORE_OOB_ROUTER)
*/
bcma_erom_skip_component(bus, eromptr);
return -ENXIO;
/* Some specific cores don't need wrappers */
switch (core->id.id) {
case BCMA_CORE_4706_MAC_GBIT_COMMON:
/* Not used yet: case BCMA_CORE_OOB_ROUTER: */
break;
default:
bcma_erom_skip_component(bus, eromptr);
return -ENXIO;
}
}
if (bcma_erom_is_bridge(bus, eromptr)) {
@ -487,7 +491,7 @@ int bcma_bus_scan(struct bcma_bus *bus)
core->id.manuf, core->id.id, core->id.rev,
core->id.class);
list_add(&core->list, &bus->cores);
list_add_tail(&core->list, &bus->cores);
}
if (bus->hosttype == BCMA_HOSTTYPE_SOC)
@ -542,7 +546,7 @@ int __init bcma_bus_scan_early(struct bcma_bus *bus,
core->id.manuf, core->id.id, core->id.rev,
core->id.class);
list_add(&core->list, &bus->cores);
list_add_tail(&core->list, &bus->cores);
err = 0;
break;
}

View file

@ -27,7 +27,7 @@
#define SCAN_CIB_NMW 0x0007C000
#define SCAN_CIB_NMW_SHIFT 14
#define SCAN_CIB_NSW 0x00F80000
#define SCAN_CIB_NSW_SHIFT 17
#define SCAN_CIB_NSW_SHIFT 19
#define SCAN_CIB_REV 0xFF000000
#define SCAN_CIB_REV_SHIFT 24

View file

@ -81,6 +81,18 @@ config BT_HCIUART_LL
Say Y here to compile support for HCILL protocol.
config BT_HCIUART_3WIRE
bool "Three-wire UART (H5) protocol support"
depends on BT_HCIUART
help
The HCI Three-wire UART Transport Layer makes it possible to
user the Bluetooth HCI over a serial port interface. The HCI
Three-wire UART Transport Layer assumes that the UART
communication may have bit errors, overrun errors or burst
errors and thereby making CTS/RTS lines unnecessary.
Say Y here to compile support for Three-wire UART protocol.
config BT_HCIBCM203X
tristate "HCI BCM203x USB driver"
depends on USB

View file

@ -28,4 +28,5 @@ hci_uart-$(CONFIG_BT_HCIUART_H4) += hci_h4.o
hci_uart-$(CONFIG_BT_HCIUART_BCSP) += hci_bcsp.o
hci_uart-$(CONFIG_BT_HCIUART_LL) += hci_ll.o
hci_uart-$(CONFIG_BT_HCIUART_ATH3K) += hci_ath.o
hci_uart-$(CONFIG_BT_HCIUART_3WIRE) += hci_h5.o
hci_uart-objs := $(hci_uart-y)

View file

@ -621,7 +621,6 @@ static int bluecard_hci_flush(struct hci_dev *hdev)
static int bluecard_hci_open(struct hci_dev *hdev)
{
bluecard_info_t *info = hci_get_drvdata(hdev);
unsigned int iobase = info->p_dev->resource[0]->start;
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state)))
bluecard_hci_set_baud_rate(hdev, DEFAULT_BAUD_RATE);
@ -630,6 +629,8 @@ static int bluecard_hci_open(struct hci_dev *hdev)
return 0;
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) {
unsigned int iobase = info->p_dev->resource[0]->start;
/* Enable LED */
outb(0x08 | 0x20, iobase + 0x30);
}
@ -641,7 +642,6 @@ static int bluecard_hci_open(struct hci_dev *hdev)
static int bluecard_hci_close(struct hci_dev *hdev)
{
bluecard_info_t *info = hci_get_drvdata(hdev);
unsigned int iobase = info->p_dev->resource[0]->start;
if (!test_and_clear_bit(HCI_RUNNING, &(hdev->flags)))
return 0;
@ -649,6 +649,8 @@ static int bluecard_hci_close(struct hci_dev *hdev)
bluecard_hci_flush(hdev);
if (test_bit(CARD_HAS_PCCARD_ID, &(info->hw_state))) {
unsigned int iobase = info->p_dev->resource[0]->start;
/* Disable LED */
outb(0x00, iobase + 0x30);
}

View file

@ -664,7 +664,7 @@ static int bt3c_check_config(struct pcmcia_device *p_dev, void *priv_data)
{
int *try = priv_data;
if (try == 0)
if (!try)
p_dev->io_lines = 16;
if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))

View file

@ -47,10 +47,11 @@ EXPORT_SYMBOL_GPL(btmrvl_interrupt);
bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
{
struct hci_event_hdr *hdr = (void *) skb->data;
struct hci_ev_cmd_complete *ec;
u16 opcode, ocf, ogf;
if (hdr->evt == HCI_EV_CMD_COMPLETE) {
struct hci_ev_cmd_complete *ec;
u16 opcode, ocf, ogf;
ec = (void *) (skb->data + HCI_EVENT_HDR_SIZE);
opcode = __le16_to_cpu(ec->opcode);
ocf = hci_opcode_ocf(opcode);
@ -64,7 +65,8 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
}
if (ogf == OGF) {
BT_DBG("vendor event skipped: ogf 0x%4.4x", ogf);
BT_DBG("vendor event skipped: ogf 0x%4.4x ocf 0x%4.4x",
ogf, ocf);
kfree_skb(skb);
return false;
}

View file

@ -568,8 +568,9 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
if (type == HCI_EVENT_PKT) {
if (btmrvl_check_evtpkt(priv, skb))
hci_recv_frame(skb);
} else
} else {
hci_recv_frame(skb);
}
hdev->stat.byte_rx += buf_len;
break;

View file

@ -593,7 +593,7 @@ static int btuart_check_config(struct pcmcia_device *p_dev, void *priv_data)
{
int *try = priv_data;
if (try == 0)
if (!try)
p_dev->io_lines = 16;
if ((p_dev->resource[0]->end != 8) || (p_dev->resource[0]->start == 0))

View file

@ -586,29 +586,31 @@ static int dtl1_confcheck(struct pcmcia_device *p_dev, void *priv_data)
static int dtl1_config(struct pcmcia_device *link)
{
dtl1_info_t *info = link->priv;
int i;
int ret;
/* Look for a generic full-sized window */
link->resource[0]->end = 8;
if (pcmcia_loop_config(link, dtl1_confcheck, NULL) < 0)
ret = pcmcia_loop_config(link, dtl1_confcheck, NULL);
if (ret)
goto failed;
i = pcmcia_request_irq(link, dtl1_interrupt);
if (i != 0)
ret = pcmcia_request_irq(link, dtl1_interrupt);
if (ret)
goto failed;
i = pcmcia_enable_device(link);
if (i != 0)
ret = pcmcia_enable_device(link);
if (ret)
goto failed;
if (dtl1_open(info) != 0)
ret = dtl1_open(info);
if (ret)
goto failed;
return 0;
failed:
dtl1_detach(link);
return -ENODEV;
return ret;
}
static const struct pcmcia_device_id dtl1_ids[] = {

747
drivers/bluetooth/hci_h5.c Normal file
View file

@ -0,0 +1,747 @@
/*
*
* Bluetooth HCI Three-wire UART driver
*
* Copyright (C) 2012 Intel Corporation
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/skbuff.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include "hci_uart.h"
#define HCI_3WIRE_ACK_PKT 0
#define HCI_3WIRE_LINK_PKT 15
/* Sliding window size */
#define H5_TX_WIN_MAX 4
#define H5_ACK_TIMEOUT msecs_to_jiffies(250)
#define H5_SYNC_TIMEOUT msecs_to_jiffies(100)
/*
* Maximum Three-wire packet:
* 4 byte header + max value for 12-bit length + 2 bytes for CRC
*/
#define H5_MAX_LEN (4 + 0xfff + 2)
/* Convenience macros for reading Three-wire header values */
#define H5_HDR_SEQ(hdr) ((hdr)[0] & 0x07)
#define H5_HDR_ACK(hdr) (((hdr)[0] >> 3) & 0x07)
#define H5_HDR_CRC(hdr) (((hdr)[0] >> 6) & 0x01)
#define H5_HDR_RELIABLE(hdr) (((hdr)[0] >> 7) & 0x01)
#define H5_HDR_PKT_TYPE(hdr) ((hdr)[1] & 0x0f)
#define H5_HDR_LEN(hdr) ((((hdr)[1] >> 4) & 0xff) + ((hdr)[2] << 4))
#define SLIP_DELIMITER 0xc0
#define SLIP_ESC 0xdb
#define SLIP_ESC_DELIM 0xdc
#define SLIP_ESC_ESC 0xdd
/* H5 state flags */
enum {
H5_RX_ESC, /* SLIP escape mode */
H5_TX_ACK_REQ, /* Pending ack to send */
};
struct h5 {
struct sk_buff_head unack; /* Unack'ed packets queue */
struct sk_buff_head rel; /* Reliable packets queue */
struct sk_buff_head unrel; /* Unreliable packets queue */
unsigned long flags;
struct sk_buff *rx_skb; /* Receive buffer */
size_t rx_pending; /* Expecting more bytes */
u8 rx_ack; /* Last ack number received */
int (*rx_func) (struct hci_uart *hu, u8 c);
struct timer_list timer; /* Retransmission timer */
u8 tx_seq; /* Next seq number to send */
u8 tx_ack; /* Next ack number to send */
u8 tx_win; /* Sliding window size */
enum {
H5_UNINITIALIZED,
H5_INITIALIZED,
H5_ACTIVE,
} state;
enum {
H5_AWAKE,
H5_SLEEPING,
H5_WAKING_UP,
} sleep;
};
static void h5_reset_rx(struct h5 *h5);
static void h5_link_control(struct hci_uart *hu, const void *data, size_t len)
{
struct h5 *h5 = hu->priv;
struct sk_buff *nskb;
nskb = alloc_skb(3, GFP_ATOMIC);
if (!nskb)
return;
bt_cb(nskb)->pkt_type = HCI_3WIRE_LINK_PKT;
memcpy(skb_put(nskb, len), data, len);
skb_queue_tail(&h5->unrel, nskb);
}
static u8 h5_cfg_field(struct h5 *h5)
{
u8 field = 0;
/* Sliding window size (first 3 bits) */
field |= (h5->tx_win & 7);
return field;
}
static void h5_timed_event(unsigned long arg)
{
const unsigned char sync_req[] = { 0x01, 0x7e };
unsigned char conf_req[] = { 0x03, 0xfc, 0x01 };
struct hci_uart *hu = (struct hci_uart *) arg;
struct h5 *h5 = hu->priv;
struct sk_buff *skb;
unsigned long flags;
BT_DBG("%s", hu->hdev->name);
if (h5->state == H5_UNINITIALIZED)
h5_link_control(hu, sync_req, sizeof(sync_req));
if (h5->state == H5_INITIALIZED) {
conf_req[2] = h5_cfg_field(h5);
h5_link_control(hu, conf_req, sizeof(conf_req));
}
if (h5->state != H5_ACTIVE) {
mod_timer(&h5->timer, jiffies + H5_SYNC_TIMEOUT);
goto wakeup;
}
if (h5->sleep != H5_AWAKE) {
h5->sleep = H5_SLEEPING;
goto wakeup;
}
BT_DBG("hu %p retransmitting %u pkts", hu, h5->unack.qlen);
spin_lock_irqsave_nested(&h5->unack.lock, flags, SINGLE_DEPTH_NESTING);
while ((skb = __skb_dequeue_tail(&h5->unack)) != NULL) {
h5->tx_seq = (h5->tx_seq - 1) & 0x07;
skb_queue_head(&h5->rel, skb);
}
spin_unlock_irqrestore(&h5->unack.lock, flags);
wakeup:
hci_uart_tx_wakeup(hu);
}
static int h5_open(struct hci_uart *hu)
{
struct h5 *h5;
const unsigned char sync[] = { 0x01, 0x7e };
BT_DBG("hu %p", hu);
h5 = kzalloc(sizeof(*h5), GFP_KERNEL);
if (!h5)
return -ENOMEM;
hu->priv = h5;
skb_queue_head_init(&h5->unack);
skb_queue_head_init(&h5->rel);
skb_queue_head_init(&h5->unrel);
h5_reset_rx(h5);
init_timer(&h5->timer);
h5->timer.function = h5_timed_event;
h5->timer.data = (unsigned long) hu;
h5->tx_win = H5_TX_WIN_MAX;
set_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags);
/* Send initial sync request */
h5_link_control(hu, sync, sizeof(sync));
mod_timer(&h5->timer, jiffies + H5_SYNC_TIMEOUT);
return 0;
}
static int h5_close(struct hci_uart *hu)
{
struct h5 *h5 = hu->priv;
skb_queue_purge(&h5->unack);
skb_queue_purge(&h5->rel);
skb_queue_purge(&h5->unrel);
del_timer(&h5->timer);
kfree(h5);
return 0;
}
static void h5_pkt_cull(struct h5 *h5)
{
struct sk_buff *skb, *tmp;
unsigned long flags;
int i, to_remove;
u8 seq;
spin_lock_irqsave(&h5->unack.lock, flags);
to_remove = skb_queue_len(&h5->unack);
if (to_remove == 0)
goto unlock;
seq = h5->tx_seq;
while (to_remove > 0) {
if (h5->rx_ack == seq)
break;
to_remove--;
seq = (seq - 1) % 8;
}
if (seq != h5->rx_ack)
BT_ERR("Controller acked invalid packet");
i = 0;
skb_queue_walk_safe(&h5->unack, skb, tmp) {
if (i++ >= to_remove)
break;
__skb_unlink(skb, &h5->unack);
kfree_skb(skb);
}
if (skb_queue_empty(&h5->unack))
del_timer(&h5->timer);
unlock:
spin_unlock_irqrestore(&h5->unack.lock, flags);
}
static void h5_handle_internal_rx(struct hci_uart *hu)
{
struct h5 *h5 = hu->priv;
const unsigned char sync_req[] = { 0x01, 0x7e };
const unsigned char sync_rsp[] = { 0x02, 0x7d };
unsigned char conf_req[] = { 0x03, 0xfc, 0x01 };
const unsigned char conf_rsp[] = { 0x04, 0x7b };
const unsigned char wakeup_req[] = { 0x05, 0xfa };
const unsigned char woken_req[] = { 0x06, 0xf9 };
const unsigned char sleep_req[] = { 0x07, 0x78 };
const unsigned char *hdr = h5->rx_skb->data;
const unsigned char *data = &h5->rx_skb->data[4];
BT_DBG("%s", hu->hdev->name);
if (H5_HDR_PKT_TYPE(hdr) != HCI_3WIRE_LINK_PKT)
return;
if (H5_HDR_LEN(hdr) < 2)
return;
conf_req[2] = h5_cfg_field(h5);
if (memcmp(data, sync_req, 2) == 0) {
h5_link_control(hu, sync_rsp, 2);
} else if (memcmp(data, sync_rsp, 2) == 0) {
h5->state = H5_INITIALIZED;
h5_link_control(hu, conf_req, 3);
} else if (memcmp(data, conf_req, 2) == 0) {
h5_link_control(hu, conf_rsp, 2);
h5_link_control(hu, conf_req, 3);
} else if (memcmp(data, conf_rsp, 2) == 0) {
if (H5_HDR_LEN(hdr) > 2)
h5->tx_win = (data[2] & 7);
BT_DBG("Three-wire init complete. tx_win %u", h5->tx_win);
h5->state = H5_ACTIVE;
hci_uart_init_ready(hu);
return;
} else if (memcmp(data, sleep_req, 2) == 0) {
BT_DBG("Peer went to sleep");
h5->sleep = H5_SLEEPING;
return;
} else if (memcmp(data, woken_req, 2) == 0) {
BT_DBG("Peer woke up");
h5->sleep = H5_AWAKE;
} else if (memcmp(data, wakeup_req, 2) == 0) {
BT_DBG("Peer requested wakeup");
h5_link_control(hu, woken_req, 2);
h5->sleep = H5_AWAKE;
} else {
BT_DBG("Link Control: 0x%02hhx 0x%02hhx", data[0], data[1]);
return;
}
hci_uart_tx_wakeup(hu);
}
static void h5_complete_rx_pkt(struct hci_uart *hu)
{
struct h5 *h5 = hu->priv;
const unsigned char *hdr = h5->rx_skb->data;
if (H5_HDR_RELIABLE(hdr)) {
h5->tx_ack = (h5->tx_ack + 1) % 8;
set_bit(H5_TX_ACK_REQ, &h5->flags);
hci_uart_tx_wakeup(hu);
}
h5->rx_ack = H5_HDR_ACK(hdr);
h5_pkt_cull(h5);
switch (H5_HDR_PKT_TYPE(hdr)) {
case HCI_EVENT_PKT:
case HCI_ACLDATA_PKT:
case HCI_SCODATA_PKT:
bt_cb(h5->rx_skb)->pkt_type = H5_HDR_PKT_TYPE(hdr);
/* Remove Three-wire header */
skb_pull(h5->rx_skb, 4);
hci_recv_frame(h5->rx_skb);
h5->rx_skb = NULL;
break;
default:
h5_handle_internal_rx(hu);
break;
}
h5_reset_rx(h5);
}
static int h5_rx_crc(struct hci_uart *hu, unsigned char c)
{
struct h5 *h5 = hu->priv;
h5_complete_rx_pkt(hu);
h5_reset_rx(h5);
return 0;
}
static int h5_rx_payload(struct hci_uart *hu, unsigned char c)
{
struct h5 *h5 = hu->priv;
const unsigned char *hdr = h5->rx_skb->data;
if (H5_HDR_CRC(hdr)) {
h5->rx_func = h5_rx_crc;
h5->rx_pending = 2;
} else {
h5_complete_rx_pkt(hu);
h5_reset_rx(h5);
}
return 0;
}
static int h5_rx_3wire_hdr(struct hci_uart *hu, unsigned char c)
{
struct h5 *h5 = hu->priv;
const unsigned char *hdr = h5->rx_skb->data;
BT_DBG("%s rx: seq %u ack %u crc %u rel %u type %u len %u",
hu->hdev->name, H5_HDR_SEQ(hdr), H5_HDR_ACK(hdr),
H5_HDR_CRC(hdr), H5_HDR_RELIABLE(hdr), H5_HDR_PKT_TYPE(hdr),
H5_HDR_LEN(hdr));
if (((hdr[0] + hdr[1] + hdr[2] + hdr[3]) & 0xff) != 0xff) {
BT_ERR("Invalid header checksum");
h5_reset_rx(h5);
return 0;
}
if (H5_HDR_RELIABLE(hdr) && H5_HDR_SEQ(hdr) != h5->tx_ack) {
BT_ERR("Out-of-order packet arrived (%u != %u)",
H5_HDR_SEQ(hdr), h5->tx_ack);
h5_reset_rx(h5);
return 0;
}
if (h5->state != H5_ACTIVE &&
H5_HDR_PKT_TYPE(hdr) != HCI_3WIRE_LINK_PKT) {
BT_ERR("Non-link packet received in non-active state");
h5_reset_rx(h5);
}
h5->rx_func = h5_rx_payload;
h5->rx_pending = H5_HDR_LEN(hdr);
return 0;
}
static int h5_rx_pkt_start(struct hci_uart *hu, unsigned char c)
{
struct h5 *h5 = hu->priv;
if (c == SLIP_DELIMITER)
return 1;
h5->rx_func = h5_rx_3wire_hdr;
h5->rx_pending = 4;
h5->rx_skb = bt_skb_alloc(H5_MAX_LEN, GFP_ATOMIC);
if (!h5->rx_skb) {
BT_ERR("Can't allocate mem for new packet");
h5_reset_rx(h5);
return -ENOMEM;
}
h5->rx_skb->dev = (void *) hu->hdev;
return 0;
}
static int h5_rx_delimiter(struct hci_uart *hu, unsigned char c)
{
struct h5 *h5 = hu->priv;
if (c == SLIP_DELIMITER)
h5->rx_func = h5_rx_pkt_start;
return 1;
}
static void h5_unslip_one_byte(struct h5 *h5, unsigned char c)
{
const u8 delim = SLIP_DELIMITER, esc = SLIP_ESC;
const u8 *byte = &c;
if (!test_bit(H5_RX_ESC, &h5->flags) && c == SLIP_ESC) {
set_bit(H5_RX_ESC, &h5->flags);
return;
}
if (test_and_clear_bit(H5_RX_ESC, &h5->flags)) {
switch (c) {
case SLIP_ESC_DELIM:
byte = &delim;
break;
case SLIP_ESC_ESC:
byte = &esc;
break;
default:
BT_ERR("Invalid esc byte 0x%02hhx", c);
h5_reset_rx(h5);
return;
}
}
memcpy(skb_put(h5->rx_skb, 1), byte, 1);
h5->rx_pending--;
BT_DBG("unsliped 0x%02hhx, rx_pending %zu", *byte, h5->rx_pending);
}
static void h5_reset_rx(struct h5 *h5)
{
if (h5->rx_skb) {
kfree_skb(h5->rx_skb);
h5->rx_skb = NULL;
}
h5->rx_func = h5_rx_delimiter;
h5->rx_pending = 0;
clear_bit(H5_RX_ESC, &h5->flags);
}
static int h5_recv(struct hci_uart *hu, void *data, int count)
{
struct h5 *h5 = hu->priv;
unsigned char *ptr = data;
BT_DBG("%s pending %zu count %d", hu->hdev->name, h5->rx_pending,
count);
while (count > 0) {
int processed;
if (h5->rx_pending > 0) {
if (*ptr == SLIP_DELIMITER) {
BT_ERR("Too short H5 packet");
h5_reset_rx(h5);
continue;
}
h5_unslip_one_byte(h5, *ptr);
ptr++; count--;
continue;
}
processed = h5->rx_func(hu, *ptr);
if (processed < 0)
return processed;
ptr += processed;
count -= processed;
}
return 0;
}
static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
struct h5 *h5 = hu->priv;
if (skb->len > 0xfff) {
BT_ERR("Packet too long (%u bytes)", skb->len);
kfree_skb(skb);
return 0;
}
if (h5->state != H5_ACTIVE) {
BT_ERR("Ignoring HCI data in non-active state");
kfree_skb(skb);
return 0;
}
switch (bt_cb(skb)->pkt_type) {
case HCI_ACLDATA_PKT:
case HCI_COMMAND_PKT:
skb_queue_tail(&h5->rel, skb);
break;
case HCI_SCODATA_PKT:
skb_queue_tail(&h5->unrel, skb);
break;
default:
BT_ERR("Unknown packet type %u", bt_cb(skb)->pkt_type);
kfree_skb(skb);
break;
}
return 0;
}
static void h5_slip_delim(struct sk_buff *skb)
{
const char delim = SLIP_DELIMITER;
memcpy(skb_put(skb, 1), &delim, 1);
}
static void h5_slip_one_byte(struct sk_buff *skb, u8 c)
{
const char esc_delim[2] = { SLIP_ESC, SLIP_ESC_DELIM };
const char esc_esc[2] = { SLIP_ESC, SLIP_ESC_ESC };
switch (c) {
case SLIP_DELIMITER:
memcpy(skb_put(skb, 2), &esc_delim, 2);
break;
case SLIP_ESC:
memcpy(skb_put(skb, 2), &esc_esc, 2);
break;
default:
memcpy(skb_put(skb, 1), &c, 1);
}
}
static bool valid_packet_type(u8 type)
{
switch (type) {
case HCI_ACLDATA_PKT:
case HCI_COMMAND_PKT:
case HCI_SCODATA_PKT:
case HCI_3WIRE_LINK_PKT:
case HCI_3WIRE_ACK_PKT:
return true;
default:
return false;
}
}
static struct sk_buff *h5_prepare_pkt(struct hci_uart *hu, u8 pkt_type,
const u8 *data, size_t len)
{
struct h5 *h5 = hu->priv;
struct sk_buff *nskb;
u8 hdr[4];
int i;
if (!valid_packet_type(pkt_type)) {
BT_ERR("Unknown packet type %u", pkt_type);
return NULL;
}
/*
* Max len of packet: (original len + 4 (H5 hdr) + 2 (crc)) * 2
* (because bytes 0xc0 and 0xdb are escaped, worst case is when
* the packet is all made of 0xc0 and 0xdb) + 2 (0xc0
* delimiters at start and end).
*/
nskb = alloc_skb((len + 6) * 2 + 2, GFP_ATOMIC);
if (!nskb)
return NULL;
bt_cb(nskb)->pkt_type = pkt_type;
h5_slip_delim(nskb);
hdr[0] = h5->tx_ack << 3;
clear_bit(H5_TX_ACK_REQ, &h5->flags);
/* Reliable packet? */
if (pkt_type == HCI_ACLDATA_PKT || pkt_type == HCI_COMMAND_PKT) {
hdr[0] |= 1 << 7;
hdr[0] |= h5->tx_seq;
h5->tx_seq = (h5->tx_seq + 1) % 8;
}
hdr[1] = pkt_type | ((len & 0x0f) << 4);
hdr[2] = len >> 4;
hdr[3] = ~((hdr[0] + hdr[1] + hdr[2]) & 0xff);
BT_DBG("%s tx: seq %u ack %u crc %u rel %u type %u len %u",
hu->hdev->name, H5_HDR_SEQ(hdr), H5_HDR_ACK(hdr),
H5_HDR_CRC(hdr), H5_HDR_RELIABLE(hdr), H5_HDR_PKT_TYPE(hdr),
H5_HDR_LEN(hdr));
for (i = 0; i < 4; i++)
h5_slip_one_byte(nskb, hdr[i]);
for (i = 0; i < len; i++)
h5_slip_one_byte(nskb, data[i]);
h5_slip_delim(nskb);
return nskb;
}
static struct sk_buff *h5_dequeue(struct hci_uart *hu)
{
struct h5 *h5 = hu->priv;
unsigned long flags;
struct sk_buff *skb, *nskb;
if (h5->sleep != H5_AWAKE) {
const unsigned char wakeup_req[] = { 0x05, 0xfa };
if (h5->sleep == H5_WAKING_UP)
return NULL;
h5->sleep = H5_WAKING_UP;
BT_DBG("Sending wakeup request");
mod_timer(&h5->timer, jiffies + HZ / 100);
return h5_prepare_pkt(hu, HCI_3WIRE_LINK_PKT, wakeup_req, 2);
}
if ((skb = skb_dequeue(&h5->unrel)) != NULL) {
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
skb->data, skb->len);
if (nskb) {
kfree_skb(skb);
return nskb;
}
skb_queue_head(&h5->unrel, skb);
BT_ERR("Could not dequeue pkt because alloc_skb failed");
}
spin_lock_irqsave_nested(&h5->unack.lock, flags, SINGLE_DEPTH_NESTING);
if (h5->unack.qlen >= h5->tx_win)
goto unlock;
if ((skb = skb_dequeue(&h5->rel)) != NULL) {
nskb = h5_prepare_pkt(hu, bt_cb(skb)->pkt_type,
skb->data, skb->len);
if (nskb) {
__skb_queue_tail(&h5->unack, skb);
mod_timer(&h5->timer, jiffies + H5_ACK_TIMEOUT);
spin_unlock_irqrestore(&h5->unack.lock, flags);
return nskb;
}
skb_queue_head(&h5->rel, skb);
BT_ERR("Could not dequeue pkt because alloc_skb failed");
}
unlock:
spin_unlock_irqrestore(&h5->unack.lock, flags);
if (test_bit(H5_TX_ACK_REQ, &h5->flags))
return h5_prepare_pkt(hu, HCI_3WIRE_ACK_PKT, NULL, 0);
return NULL;
}
static int h5_flush(struct hci_uart *hu)
{
BT_DBG("hu %p", hu);
return 0;
}
static struct hci_uart_proto h5p = {
.id = HCI_UART_3WIRE,
.open = h5_open,
.close = h5_close,
.recv = h5_recv,
.enqueue = h5_enqueue,
.dequeue = h5_dequeue,
.flush = h5_flush,
};
int __init h5_init(void)
{
int err = hci_uart_register_proto(&h5p);
if (!err)
BT_INFO("HCI Three-wire UART (H5) protocol initialized");
else
BT_ERR("HCI Three-wire UART (H5) protocol init failed");
return err;
}
int __exit h5_deinit(void)
{
return hci_uart_unregister_proto(&h5p);
}

View file

@ -156,6 +156,35 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
return 0;
}
static void hci_uart_init_work(struct work_struct *work)
{
struct hci_uart *hu = container_of(work, struct hci_uart, init_ready);
int err;
if (!test_and_clear_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))
return;
err = hci_register_dev(hu->hdev);
if (err < 0) {
BT_ERR("Can't register HCI device");
hci_free_dev(hu->hdev);
hu->hdev = NULL;
hu->proto->close(hu);
}
set_bit(HCI_UART_REGISTERED, &hu->flags);
}
int hci_uart_init_ready(struct hci_uart *hu)
{
if (!test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))
return -EALREADY;
schedule_work(&hu->init_ready);
return 0;
}
/* ------- Interface to HCI layer ------ */
/* Initialize device */
static int hci_uart_open(struct hci_dev *hdev)
@ -264,6 +293,8 @@ static int hci_uart_tty_open(struct tty_struct *tty)
hu->tty = tty;
tty->receive_room = 65536;
INIT_WORK(&hu->init_ready, hci_uart_init_work);
spin_lock_init(&hu->rx_lock);
/* Flush any pending characters in the driver and line discipline. */
@ -286,28 +317,30 @@ static int hci_uart_tty_open(struct tty_struct *tty)
static void hci_uart_tty_close(struct tty_struct *tty)
{
struct hci_uart *hu = (void *)tty->disc_data;
struct hci_dev *hdev;
BT_DBG("tty %p", tty);
/* Detach from the tty */
tty->disc_data = NULL;
if (hu) {
struct hci_dev *hdev = hu->hdev;
if (!hu)
return;
if (hdev)
hci_uart_close(hdev);
hdev = hu->hdev;
if (hdev)
hci_uart_close(hdev);
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
if (hdev) {
if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
if (hdev) {
if (test_bit(HCI_UART_REGISTERED, &hu->flags))
hci_unregister_dev(hdev);
hci_free_dev(hdev);
}
hu->proto->close(hu);
hci_free_dev(hdev);
}
kfree(hu);
hu->proto->close(hu);
}
kfree(hu);
}
/* hci_uart_tty_wakeup()
@ -401,12 +434,17 @@ static int hci_uart_register_dev(struct hci_uart *hu)
else
hdev->dev_type = HCI_BREDR;
if (test_bit(HCI_UART_INIT_PENDING, &hu->hdev_flags))
return 0;
if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device");
hci_free_dev(hdev);
return -ENODEV;
}
set_bit(HCI_UART_REGISTERED, &hu->flags);
return 0;
}
@ -558,6 +596,9 @@ static int __init hci_uart_init(void)
#ifdef CONFIG_BT_HCIUART_ATH3K
ath_init();
#endif
#ifdef CONFIG_BT_HCIUART_3WIRE
h5_init();
#endif
return 0;
}
@ -578,6 +619,9 @@ static void __exit hci_uart_exit(void)
#ifdef CONFIG_BT_HCIUART_ATH3K
ath_deinit();
#endif
#ifdef CONFIG_BT_HCIUART_3WIRE
h5_deinit();
#endif
/* Release tty registration of line discipline */
if ((err = tty_unregister_ldisc(N_HCI)))

View file

@ -47,6 +47,7 @@
#define HCI_UART_RAW_DEVICE 0
#define HCI_UART_RESET_ON_INIT 1
#define HCI_UART_CREATE_AMP 2
#define HCI_UART_INIT_PENDING 3
struct hci_uart;
@ -66,6 +67,8 @@ struct hci_uart {
unsigned long flags;
unsigned long hdev_flags;
struct work_struct init_ready;
struct hci_uart_proto *proto;
void *priv;
@ -76,6 +79,7 @@ struct hci_uart {
/* HCI_UART proto flag bits */
#define HCI_UART_PROTO_SET 0
#define HCI_UART_REGISTERED 1
/* TX states */
#define HCI_UART_SENDING 1
@ -84,6 +88,7 @@ struct hci_uart {
int hci_uart_register_proto(struct hci_uart_proto *p);
int hci_uart_unregister_proto(struct hci_uart_proto *p);
int hci_uart_tx_wakeup(struct hci_uart *hu);
int hci_uart_init_ready(struct hci_uart *hu);
#ifdef CONFIG_BT_HCIUART_H4
int h4_init(void);
@ -104,3 +109,8 @@ int ll_deinit(void);
int ath_init(void);
int ath_deinit(void);
#endif
#ifdef CONFIG_BT_HCIUART_3WIRE
int h5_init(void);
int h5_deinit(void);
#endif

View file

@ -216,6 +216,7 @@ void ath_printk(const char *level, const struct ath_common *common,
* used exclusively for WLAN-BT coexistence starting from
* AR9462.
* @ATH_DBG_DFS: radar datection
* @ATH_DBG_WOW: Wake on Wireless
* @ATH_DBG_ANY: enable all debugging
*
* The debug level is used to control the amount and type of debugging output
@ -243,6 +244,7 @@ enum ATH_DEBUG {
ATH_DBG_BSTUCK = 0x00008000,
ATH_DBG_MCI = 0x00010000,
ATH_DBG_DFS = 0x00020000,
ATH_DBG_WOW = 0x00040000,
ATH_DBG_ANY = 0xffffffff
};

View file

@ -594,7 +594,7 @@ ath5k_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue,
qi.tqi_aifs = params->aifs;
qi.tqi_cw_min = params->cw_min;
qi.tqi_cw_max = params->cw_max;
qi.tqi_burst_time = params->txop;
qi.tqi_burst_time = params->txop * 32;
ATH5K_DBG(ah, ATH5K_DEBUG_ANY,
"Configure tx [queue %d], "

View file

@ -966,11 +966,11 @@ static int ath6kl_set_probed_ssids(struct ath6kl *ar,
return 0;
}
static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
static int ath6kl_cfg80211_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request)
{
struct ath6kl *ar = ath6kl_priv(ndev);
struct ath6kl_vif *vif = netdev_priv(ndev);
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(request->wdev);
struct ath6kl *ar = ath6kl_priv(vif->ndev);
s8 n_channels = 0;
u16 *channels = NULL;
int ret = 0;
@ -1487,14 +1487,14 @@ static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
return 0;
}
static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
char *name,
enum nl80211_iftype type,
u32 *flags,
struct vif_params *params)
static struct wireless_dev *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
char *name,
enum nl80211_iftype type,
u32 *flags,
struct vif_params *params)
{
struct ath6kl *ar = wiphy_priv(wiphy);
struct net_device *ndev;
struct wireless_dev *wdev;
u8 if_idx, nw_type;
if (ar->num_vif == ar->vif_max) {
@ -1507,20 +1507,20 @@ static struct net_device *ath6kl_cfg80211_add_iface(struct wiphy *wiphy,
return ERR_PTR(-EINVAL);
}
ndev = ath6kl_interface_add(ar, name, type, if_idx, nw_type);
if (!ndev)
wdev = ath6kl_interface_add(ar, name, type, if_idx, nw_type);
if (!wdev)
return ERR_PTR(-ENOMEM);
ar->num_vif++;
return ndev;
return wdev;
}
static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy,
struct net_device *ndev)
struct wireless_dev *wdev)
{
struct ath6kl *ar = wiphy_priv(wiphy);
struct ath6kl_vif *vif = netdev_priv(ndev);
struct ath6kl_vif *vif = netdev_priv(wdev->netdev);
spin_lock_bh(&ar->list_lock);
list_del(&vif->list);
@ -2975,14 +2975,14 @@ static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
}
static int ath6kl_remain_on_channel(struct wiphy *wiphy,
struct net_device *dev,
struct wireless_dev *wdev,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type,
unsigned int duration,
u64 *cookie)
{
struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev);
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
struct ath6kl *ar = ath6kl_priv(vif->ndev);
u32 id;
/* TODO: if already pending or ongoing remain-on-channel,
@ -2999,11 +2999,11 @@ static int ath6kl_remain_on_channel(struct wiphy *wiphy,
}
static int ath6kl_cancel_remain_on_channel(struct wiphy *wiphy,
struct net_device *dev,
struct wireless_dev *wdev,
u64 cookie)
{
struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev);
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
struct ath6kl *ar = ath6kl_priv(vif->ndev);
if (cookie != vif->last_roc_id)
return -ENOENT;
@ -3134,15 +3134,15 @@ static bool ath6kl_is_p2p_go_ssid(const u8 *buf, size_t len)
return false;
}
static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
enum nl80211_channel_type channel_type,
bool channel_type_valid, unsigned int wait,
const u8 *buf, size_t len, bool no_cck,
bool dont_wait_for_ack, u64 *cookie)
{
struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev);
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
struct ath6kl *ar = ath6kl_priv(vif->ndev);
u32 id;
const struct ieee80211_mgmt *mgmt;
bool more_data, queued;
@ -3187,10 +3187,10 @@ static int ath6kl_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
}
static void ath6kl_mgmt_frame_register(struct wiphy *wiphy,
struct net_device *dev,
struct wireless_dev *wdev,
u16 frame_type, bool reg)
{
struct ath6kl_vif *vif = netdev_priv(dev);
struct ath6kl_vif *vif = ath6kl_vif_from_wdev(wdev);
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: frame_type=0x%x reg=%d\n",
__func__, frame_type, reg);
@ -3477,9 +3477,9 @@ void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif)
ar->num_vif--;
}
struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
enum nl80211_iftype type, u8 fw_vif_idx,
u8 nw_type)
struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, char *name,
enum nl80211_iftype type,
u8 fw_vif_idx, u8 nw_type)
{
struct net_device *ndev;
struct ath6kl_vif *vif;
@ -3533,7 +3533,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
list_add_tail(&vif->list, &ar->vif_list);
spin_unlock_bh(&ar->list_lock);
return ndev;
return &vif->wdev;
err:
aggr_module_destroy(vif->aggr_cntxt);

View file

@ -25,9 +25,9 @@ enum ath6kl_cfg_suspend_mode {
ATH6KL_CFG_SUSPEND_SCHED_SCAN,
};
struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name,
enum nl80211_iftype type,
u8 fw_vif_idx, u8 nw_type);
struct wireless_dev *ath6kl_interface_add(struct ath6kl *ar, char *name,
enum nl80211_iftype type,
u8 fw_vif_idx, u8 nw_type);
void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
enum wmi_phy_mode mode);
void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted);

View file

@ -56,7 +56,7 @@ EXPORT_SYMBOL(ath6kl_core_rx_complete);
int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
{
struct ath6kl_bmi_target_info targ_info;
struct net_device *ndev;
struct wireless_dev *wdev;
int ret = 0, i;
switch (htc_type) {
@ -187,12 +187,12 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
rtnl_lock();
/* Add an initial station interface */
ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0,
wdev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0,
INFRA_NETWORK);
rtnl_unlock();
if (!ndev) {
if (!wdev) {
ath6kl_err("Failed to instantiate a network device\n");
ret = -ENOMEM;
wiphy_unregister(ar->wiphy);
@ -200,7 +200,7 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
}
ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
__func__, ndev->name, ndev, ar);
__func__, wdev->netdev->name, wdev->netdev, ar);
return ret;

View file

@ -589,6 +589,11 @@ struct ath6kl_vif {
struct list_head mc_filter;
};
static inline struct ath6kl_vif *ath6kl_vif_from_wdev(struct wireless_dev *wdev)
{
return container_of(wdev, struct ath6kl_vif, wdev);
}
#define WOW_LIST_ID 0
#define WOW_HOST_REQ_DELAY 500 /* ms */

View file

@ -474,7 +474,7 @@ static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap,
return -EINVAL;
}
id = vif->last_roc_id;
cfg80211_ready_on_channel(vif->ndev, id, chan, NL80211_CHAN_NO_HT,
cfg80211_ready_on_channel(&vif->wdev, id, chan, NL80211_CHAN_NO_HT,
dur, GFP_ATOMIC);
return 0;
@ -513,7 +513,7 @@ static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi,
else
id = vif->last_roc_id; /* timeout on uncanceled r-o-c */
vif->last_cancel_roc_id = 0;
cfg80211_remain_on_channel_expired(vif->ndev, id, chan,
cfg80211_remain_on_channel_expired(&vif->wdev, id, chan,
NL80211_CHAN_NO_HT, GFP_ATOMIC);
return 0;
@ -533,7 +533,7 @@ static int ath6kl_wmi_tx_status_event_rx(struct wmi *wmi, u8 *datap, int len,
ath6kl_dbg(ATH6KL_DBG_WMI, "tx_status: id=%x ack_status=%u\n",
id, ev->ack_status);
if (wmi->last_mgmt_tx_frame) {
cfg80211_mgmt_tx_status(vif->ndev, id,
cfg80211_mgmt_tx_status(&vif->wdev, id,
wmi->last_mgmt_tx_frame,
wmi->last_mgmt_tx_frame_len,
!!ev->ack_status, GFP_ATOMIC);
@ -568,7 +568,7 @@ static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len,
dlen, freq, vif->probe_req_report);
if (vif->probe_req_report || vif->nw_type == AP_NETWORK)
cfg80211_rx_mgmt(vif->ndev, freq, 0,
cfg80211_rx_mgmt(&vif->wdev, freq, 0,
ev->data, dlen, GFP_ATOMIC);
return 0;
@ -608,7 +608,7 @@ static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len,
return -EINVAL;
}
ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq);
cfg80211_rx_mgmt(vif->ndev, freq, 0,
cfg80211_rx_mgmt(&vif->wdev, freq, 0,
ev->data, dlen, GFP_ATOMIC);
return 0;

View file

@ -64,7 +64,7 @@ config ATH9K_DEBUGFS
config ATH9K_DFS_CERTIFIED
bool "Atheros DFS support for certified platforms"
depends on ATH9K && EXPERT
depends on ATH9K && CFG80211_CERTIFICATION_ONUS
default n
---help---
This option enables DFS support for initiating radiation on

View file

@ -17,6 +17,7 @@ ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += \
dfs.o \
dfs_pattern_detector.o \
dfs_pri_detector.o
ath9k-$(CONFIG_PM_SLEEP) += wow.o
obj-$(CONFIG_ATH9K) += ath9k.o

View file

@ -26,101 +26,74 @@
static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
{
if (AR_SREV_9271(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271,
ARRAY_SIZE(ar9271Modes_9271), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271,
ARRAY_SIZE(ar9271Common_9271), 2);
INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg,
ARRAY_SIZE(ar9271Modes_9271_ANI_reg), 5);
INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271);
INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271);
INIT_INI_ARRAY(&ah->iniModes_9271_ANI_reg, ar9271Modes_9271_ANI_reg);
return;
}
if (ah->config.pcie_clock_req)
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9280PciePhy_clkreq_off_L1_9280,
ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280), 2);
ar9280PciePhy_clkreq_off_L1_9280);
else
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9280PciePhy_clkreq_always_on_L1_9280,
ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2);
ar9280PciePhy_clkreq_always_on_L1_9280);
#ifdef CONFIG_PM_SLEEP
INIT_INI_ARRAY(&ah->iniPcieSerdesWow,
ar9280PciePhy_awow);
#endif
if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1,
ARRAY_SIZE(ar9287Modes_9287_1_1), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1,
ARRAY_SIZE(ar9287Common_9287_1_1), 2);
INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1);
INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1);
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2,
ARRAY_SIZE(ar9285Modes_9285_1_2), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2,
ARRAY_SIZE(ar9285Common_9285_1_2), 2);
INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2);
INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2);
} else if (AR_SREV_9280_20_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2,
ARRAY_SIZE(ar9280Modes_9280_2), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2,
ARRAY_SIZE(ar9280Common_9280_2), 2);
INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2);
INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2);
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9280Modes_fast_clock_9280_2,
ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
ar9280Modes_fast_clock_9280_2);
} else if (AR_SREV_9160_10_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160,
ARRAY_SIZE(ar5416Modes_9160), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160,
ARRAY_SIZE(ar5416Common_9160), 2);
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160);
if (AR_SREV_9160_11(ah)) {
INIT_INI_ARRAY(&ah->iniAddac,
ar5416Addac_9160_1_1,
ARRAY_SIZE(ar5416Addac_9160_1_1), 2);
ar5416Addac_9160_1_1);
} else {
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160,
ARRAY_SIZE(ar5416Addac_9160), 2);
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160);
}
} else if (AR_SREV_9100_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100,
ARRAY_SIZE(ar5416Modes_9100), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100,
ARRAY_SIZE(ar5416Common_9100), 2);
INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100,
ARRAY_SIZE(ar5416Bank6_9100), 3);
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100,
ARRAY_SIZE(ar5416Addac_9100), 2);
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100);
INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100);
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100);
} else {
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes,
ARRAY_SIZE(ar5416Modes), 5);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common,
ARRAY_SIZE(ar5416Common), 2);
INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC,
ARRAY_SIZE(ar5416Bank6TPC), 3);
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac,
ARRAY_SIZE(ar5416Addac), 2);
INIT_INI_ARRAY(&ah->iniModes, ar5416Modes);
INIT_INI_ARRAY(&ah->iniCommon, ar5416Common);
INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC);
INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac);
}
if (!AR_SREV_9280_20_OR_LATER(ah)) {
/* Common for AR5416, AR913x, AR9160 */
INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain,
ARRAY_SIZE(ar5416BB_RfGain), 3);
INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain);
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0,
ARRAY_SIZE(ar5416Bank0), 2);
INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1,
ARRAY_SIZE(ar5416Bank1), 2);
INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2,
ARRAY_SIZE(ar5416Bank2), 2);
INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3,
ARRAY_SIZE(ar5416Bank3), 3);
INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7,
ARRAY_SIZE(ar5416Bank7), 2);
INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0);
INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1);
INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2);
INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3);
INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7);
/* Common for AR5416, AR9160 */
if (!AR_SREV_9100(ah))
INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6,
ARRAY_SIZE(ar5416Bank6), 3);
INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6);
/* Common for AR913x, AR9160 */
if (!AR_SREV_5416(ah))
INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100,
ARRAY_SIZE(ar5416Bank6TPC_9100), 3);
INIT_INI_ARRAY(&ah->iniBank6TPC,
ar5416Bank6TPC_9100);
}
/* iniAddac needs to be modified for these chips */
@ -143,13 +116,9 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
}
if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniCckfirNormal,
ar9287Common_normal_cck_fir_coeff_9287_1_1,
ARRAY_SIZE(ar9287Common_normal_cck_fir_coeff_9287_1_1),
2);
ar9287Common_normal_cck_fir_coeff_9287_1_1);
INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
ar9287Common_japan_2484_cck_fir_coeff_9287_1_1,
ARRAY_SIZE(ar9287Common_japan_2484_cck_fir_coeff_9287_1_1),
2);
ar9287Common_japan_2484_cck_fir_coeff_9287_1_1);
}
}
@ -163,20 +132,16 @@ static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_backoff_13db_rxgain_9280_2,
ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 5);
ar9280Modes_backoff_13db_rxgain_9280_2);
else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_backoff_23db_rxgain_9280_2,
ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 5);
ar9280Modes_backoff_23db_rxgain_9280_2);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_original_rxgain_9280_2,
ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 5);
ar9280Modes_original_rxgain_9280_2);
} else {
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9280Modes_original_rxgain_9280_2,
ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 5);
ar9280Modes_original_rxgain_9280_2);
}
}
@ -186,16 +151,13 @@ static void ar9280_20_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
AR5416_EEP_MINOR_VER_19) {
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_high_power_tx_gain_9280_2,
ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 5);
ar9280Modes_high_power_tx_gain_9280_2);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_original_tx_gain_9280_2,
ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 5);
ar9280Modes_original_tx_gain_9280_2);
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9280Modes_original_tx_gain_9280_2,
ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 5);
ar9280Modes_original_tx_gain_9280_2);
}
}
@ -203,12 +165,10 @@ static void ar9271_hw_init_txgain_ini(struct ath_hw *ah, u32 txgain_type)
{
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9271Modes_high_power_tx_gain_9271,
ARRAY_SIZE(ar9271Modes_high_power_tx_gain_9271), 5);
ar9271Modes_high_power_tx_gain_9271);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9271Modes_normal_power_tx_gain_9271,
ARRAY_SIZE(ar9271Modes_normal_power_tx_gain_9271), 5);
ar9271Modes_normal_power_tx_gain_9271);
}
static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
@ -217,8 +177,7 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
if (AR_SREV_9287_11_OR_LATER(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9287Modes_rx_gain_9287_1_1,
ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 5);
ar9287Modes_rx_gain_9287_1_1);
else if (AR_SREV_9280_20(ah))
ar9280_20_hw_init_rxgain_ini(ah);
@ -226,8 +185,7 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
ar9271_hw_init_txgain_ini(ah, txgain_type);
} else if (AR_SREV_9287_11_OR_LATER(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9287Modes_tx_gain_9287_1_1,
ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 5);
ar9287Modes_tx_gain_9287_1_1);
} else if (AR_SREV_9280_20(ah)) {
ar9280_20_hw_init_txgain_ini(ah, txgain_type);
} else if (AR_SREV_9285_12_OR_LATER(ah)) {
@ -235,26 +193,18 @@ static void ar9002_hw_init_mode_gain_regs(struct ath_hw *ah)
if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) {
if (AR_SREV_9285E_20(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_XE2_0_high_power,
ARRAY_SIZE(
ar9285Modes_XE2_0_high_power), 5);
ar9285Modes_XE2_0_high_power);
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_high_power_tx_gain_9285_1_2,
ARRAY_SIZE(
ar9285Modes_high_power_tx_gain_9285_1_2), 5);
ar9285Modes_high_power_tx_gain_9285_1_2);
}
} else {
if (AR_SREV_9285E_20(ah)) {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_XE2_0_normal_power,
ARRAY_SIZE(
ar9285Modes_XE2_0_normal_power), 5);
ar9285Modes_XE2_0_normal_power);
} else {
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9285Modes_original_tx_gain_9285_1_2,
ARRAY_SIZE(
ar9285Modes_original_tx_gain_9285_1_2), 5);
ar9285Modes_original_tx_gain_9285_1_2);
}
}
}

View file

@ -925,6 +925,20 @@ static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = {
{0x00004044, 0x00000000},
};
static const u32 ar9280PciePhy_awow[][2] = {
/* Addr allmodes */
{0x00004040, 0x9248fd00},
{0x00004040, 0x24924924},
{0x00004040, 0xa8000019},
{0x00004040, 0x13160820},
{0x00004040, 0xe5980560},
{0x00004040, 0xc01dcffd},
{0x00004040, 0x1aaabe41},
{0x00004040, 0xbe105554},
{0x00004040, 0x00043007},
{0x00004044, 0x00000000},
};
static const u32 ar9285Modes_9285_1_2[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},

View file

@ -131,8 +131,9 @@ static const struct ar9300_eeprom ar9300_default = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@ -331,8 +332,9 @@ static const struct ar9300_eeprom ar9300_default = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080),
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@ -704,8 +706,9 @@ static const struct ar9300_eeprom ar9300_x113 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080),
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@ -904,8 +907,9 @@ static const struct ar9300_eeprom ar9300_x113 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@ -1278,8 +1282,9 @@ static const struct ar9300_eeprom ar9300_h112 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080),
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@ -1478,8 +1483,9 @@ static const struct ar9300_eeprom ar9300_h112 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@ -1852,8 +1858,9 @@ static const struct ar9300_eeprom ar9300_x112 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0c80c080),
.papdRateMaskHt40 = LE32(0x0080c080),
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@ -2052,8 +2059,9 @@ static const struct ar9300_eeprom ar9300_x112 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@ -2425,8 +2433,9 @@ static const struct ar9300_eeprom ar9300_h116 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0c80C080),
.papdRateMaskHt40 = LE32(0x0080C080),
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext1 = {
@ -2625,8 +2634,9 @@ static const struct ar9300_eeprom ar9300_h116 = {
.thresh62 = 28,
.papdRateMaskHt20 = LE32(0x0cf0e0e0),
.papdRateMaskHt40 = LE32(0x6cf0e0e0),
.xlna_bias_strength = 0,
.futureModal = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
},
},
.base_ext2 = {
@ -2971,14 +2981,6 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
return (pBase->txrxMask >> 4) & 0xf;
case EEP_RX_MASK:
return pBase->txrxMask & 0xf;
case EEP_DRIVE_STRENGTH:
#define AR9300_EEP_BASE_DRIV_STRENGTH 0x1
return pBase->miscConfiguration & AR9300_EEP_BASE_DRIV_STRENGTH;
case EEP_INTERNAL_REGULATOR:
/* Bit 4 is internal regulator flag */
return (pBase->featureEnable & 0x10) >> 4;
case EEP_SWREG:
return le32_to_cpu(pBase->swreg);
case EEP_PAPRD:
return !!(pBase->featureEnable & BIT(5));
case EEP_CHAIN_MASK_REDUCE:
@ -2989,8 +2991,6 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
return eep->modalHeader5G.antennaGain;
case EEP_ANTENNA_GAIN_2G:
return eep->modalHeader2G.antennaGain;
case EEP_QUICK_DROP:
return pBase->miscConfiguration & BIT(1);
default:
return 0;
}
@ -3260,10 +3260,20 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah,
int it;
u16 checksum, mchecksum;
struct ath_common *common = ath9k_hw_common(ah);
struct ar9300_eeprom *eep;
eeprom_read_op read;
if (ath9k_hw_use_flash(ah))
return ar9300_eeprom_restore_flash(ah, mptr, mdata_size);
if (ath9k_hw_use_flash(ah)) {
u8 txrx;
ar9300_eeprom_restore_flash(ah, mptr, mdata_size);
/* check if eeprom contains valid data */
eep = (struct ar9300_eeprom *) mptr;
txrx = eep->baseEepHeader.txrxMask;
if (txrx != 0 && txrx != 0xff)
return 0;
}
word = kzalloc(2048, GFP_KERNEL);
if (!word)
@ -3493,19 +3503,20 @@ static int ath9k_hw_ar9300_get_eeprom_rev(struct ath_hw *ah)
return 0;
}
static s32 ar9003_hw_xpa_bias_level_get(struct ath_hw *ah, bool is2ghz)
static struct ar9300_modal_eep_header *ar9003_modal_header(struct ath_hw *ah,
bool is2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
if (is2ghz)
return eep->modalHeader2G.xpaBiasLvl;
return &eep->modalHeader2G;
else
return eep->modalHeader5G.xpaBiasLvl;
return &eep->modalHeader5G;
}
static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
{
int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz);
int bias = ar9003_modal_header(ah, is2ghz)->xpaBiasLvl;
if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
@ -3521,57 +3532,26 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
}
}
static u16 ar9003_switch_com_spdt_get(struct ath_hw *ah, bool is_2ghz)
static u16 ar9003_switch_com_spdt_get(struct ath_hw *ah, bool is2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
__le16 val;
if (is_2ghz)
val = eep->modalHeader2G.switchcomspdt;
else
val = eep->modalHeader5G.switchcomspdt;
return le16_to_cpu(val);
return le16_to_cpu(ar9003_modal_header(ah, is2ghz)->switchcomspdt);
}
static u32 ar9003_hw_ant_ctrl_common_get(struct ath_hw *ah, bool is2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
__le32 val;
if (is2ghz)
val = eep->modalHeader2G.antCtrlCommon;
else
val = eep->modalHeader5G.antCtrlCommon;
return le32_to_cpu(val);
return le32_to_cpu(ar9003_modal_header(ah, is2ghz)->antCtrlCommon);
}
static u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
__le32 val;
if (is2ghz)
val = eep->modalHeader2G.antCtrlCommon2;
else
val = eep->modalHeader5G.antCtrlCommon2;
return le32_to_cpu(val);
return le32_to_cpu(ar9003_modal_header(ah, is2ghz)->antCtrlCommon2);
}
static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah,
int chain,
static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, int chain,
bool is2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
__le16 val = 0;
if (chain >= 0 && chain < AR9300_MAX_CHAINS) {
if (is2ghz)
val = eep->modalHeader2G.antCtrlChain[chain];
else
val = eep->modalHeader5G.antCtrlChain[chain];
}
__le16 val = ar9003_modal_header(ah, is2ghz)->antCtrlChain[chain];
return le16_to_cpu(val);
}
@ -3681,11 +3661,12 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
static void ar9003_hw_drive_strength_apply(struct ath_hw *ah)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader;
int drive_strength;
unsigned long reg;
drive_strength = ath9k_hw_ar9300_get_eeprom(ah, EEP_DRIVE_STRENGTH);
drive_strength = pBase->miscConfiguration & BIT(0);
if (!drive_strength)
return;
@ -3815,11 +3796,11 @@ static bool is_pmu_set(struct ath_hw *ah, u32 pmu_reg, int pmu_set)
void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
{
int internal_regulator =
ath9k_hw_ar9300_get_eeprom(ah, EEP_INTERNAL_REGULATOR);
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader;
u32 reg_val;
if (internal_regulator) {
if (pBase->featureEnable & BIT(4)) {
if (AR_SREV_9330(ah) || AR_SREV_9485(ah)) {
int reg_pmu_set;
@ -3863,11 +3844,11 @@ void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
return;
} else if (AR_SREV_9462(ah)) {
reg_val = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
reg_val = le32_to_cpu(pBase->swreg);
REG_WRITE(ah, AR_PHY_PMU1, reg_val);
} else {
/* Internal regulator is ON. Write swreg register. */
reg_val = ath9k_hw_ar9300_get_eeprom(ah, EEP_SWREG);
reg_val = le32_to_cpu(pBase->swreg);
REG_WRITE(ah, AR_RTC_REG_CONTROL1,
REG_READ(ah, AR_RTC_REG_CONTROL1) &
(~AR_RTC_REG_CONTROL1_SWREG_PROGRAM));
@ -3909,6 +3890,9 @@ static void ar9003_hw_apply_tuning_caps(struct ath_hw *ah)
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
u8 tuning_caps_param = eep->baseEepHeader.params_for_tuning_caps[0];
if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
return;
if (eep->baseEepHeader.featureEnable & 0x40) {
tuning_caps_param &= 0x7f;
REG_RMW_FIELD(ah, AR_CH0_XTAL, AR_CH0_XTAL_CAPINDAC,
@ -3921,10 +3905,11 @@ static void ar9003_hw_apply_tuning_caps(struct ath_hw *ah)
static void ar9003_hw_quick_drop_apply(struct ath_hw *ah, u16 freq)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
int quick_drop = ath9k_hw_ar9300_get_eeprom(ah, EEP_QUICK_DROP);
struct ar9300_base_eep_hdr *pBase = &eep->baseEepHeader;
int quick_drop;
s32 t[3], f[3] = {5180, 5500, 5785};
if (!quick_drop)
if (!(pBase->miscConfiguration & BIT(1)))
return;
if (freq < 4000)
@ -3938,13 +3923,11 @@ static void ar9003_hw_quick_drop_apply(struct ath_hw *ah, u16 freq)
REG_RMW_FIELD(ah, AR_PHY_AGC, AR_PHY_AGC_QUICK_DROP, quick_drop);
}
static void ar9003_hw_txend_to_xpa_off_apply(struct ath_hw *ah, u16 freq)
static void ar9003_hw_txend_to_xpa_off_apply(struct ath_hw *ah, bool is2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
u32 value;
value = (freq < 4000) ? eep->modalHeader2G.txEndToXpaOff :
eep->modalHeader5G.txEndToXpaOff;
value = ar9003_modal_header(ah, is2ghz)->txEndToXpaOff;
REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL,
AR_PHY_XPA_TIMING_CTL_TX_END_XPAB_OFF, value);
@ -3952,19 +3935,63 @@ static void ar9003_hw_txend_to_xpa_off_apply(struct ath_hw *ah, u16 freq)
AR_PHY_XPA_TIMING_CTL_TX_END_XPAA_OFF, value);
}
static void ar9003_hw_xpa_timing_control_apply(struct ath_hw *ah, bool is2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
u8 xpa_ctl;
if (!(eep->baseEepHeader.featureEnable & 0x80))
return;
if (!AR_SREV_9300(ah) && !AR_SREV_9340(ah) && !AR_SREV_9580(ah))
return;
xpa_ctl = ar9003_modal_header(ah, is2ghz)->txFrameToXpaOn;
if (is2ghz)
REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL,
AR_PHY_XPA_TIMING_CTL_FRAME_XPAB_ON, xpa_ctl);
else
REG_RMW_FIELD(ah, AR_PHY_XPA_TIMING_CTL,
AR_PHY_XPA_TIMING_CTL_FRAME_XPAA_ON, xpa_ctl);
}
static void ar9003_hw_xlna_bias_strength_apply(struct ath_hw *ah, bool is2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
u8 bias;
if (!(eep->baseEepHeader.featureEnable & 0x40))
return;
if (!AR_SREV_9300(ah))
return;
bias = ar9003_modal_header(ah, is2ghz)->xlna_bias_strength;
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS,
bias & 0x3);
bias >>= 2;
REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS,
bias & 0x3);
bias >>= 2;
REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, AR_PHY_65NM_RXTX4_XLNA_BIAS,
bias & 0x3);
}
static void ath9k_hw_ar9300_set_board_values(struct ath_hw *ah,
struct ath9k_channel *chan)
{
ar9003_hw_xpa_bias_level_apply(ah, IS_CHAN_2GHZ(chan));
ar9003_hw_ant_ctrl_apply(ah, IS_CHAN_2GHZ(chan));
bool is2ghz = IS_CHAN_2GHZ(chan);
ar9003_hw_xpa_timing_control_apply(ah, is2ghz);
ar9003_hw_xpa_bias_level_apply(ah, is2ghz);
ar9003_hw_ant_ctrl_apply(ah, is2ghz);
ar9003_hw_drive_strength_apply(ah);
ar9003_hw_xlna_bias_strength_apply(ah, is2ghz);
ar9003_hw_atten_apply(ah, chan);
ar9003_hw_quick_drop_apply(ah, chan->channel);
if (!AR_SREV_9330(ah) && !AR_SREV_9340(ah) && !AR_SREV_9550(ah))
ar9003_hw_internal_regulator_apply(ah);
if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah))
ar9003_hw_apply_tuning_caps(ah);
ar9003_hw_txend_to_xpa_off_apply(ah, chan->channel);
ar9003_hw_apply_tuning_caps(ah);
ar9003_hw_txend_to_xpa_off_apply(ah, is2ghz);
}
static void ath9k_hw_ar9300_set_addac(struct ath_hw *ah,
@ -5100,14 +5127,9 @@ s32 ar9003_hw_get_rx_gain_idx(struct ath_hw *ah)
return (eep->baseEepHeader.txrxgain) & 0xf; /* bits 3:0 */
}
u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz)
u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is2ghz)
{
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
if (is_2ghz)
return eep->modalHeader2G.spurChans;
else
return eep->modalHeader5G.spurChans;
return ar9003_modal_header(ah, is2ghz)->spurChans;
}
unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah,

View file

@ -231,7 +231,8 @@ struct ar9300_modal_eep_header {
__le32 papdRateMaskHt20;
__le32 papdRateMaskHt40;
__le16 switchcomspdt;
u8 futureModal[8];
u8 xlna_bias_strength;
u8 futureModal[7];
} __packed;
struct ar9300_cal_data_per_freq_op_loop {

View file

@ -44,462 +44,310 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
ar9462_2p0_baseband_core_txfir_coeff_japan_2484
if (AR_SREV_9330_11(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
ar9331_1p1_mac_core,
ARRAY_SIZE(ar9331_1p1_mac_core), 2);
ar9331_1p1_mac_core);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar9331_1p1_mac_postamble,
ARRAY_SIZE(ar9331_1p1_mac_postamble), 5);
ar9331_1p1_mac_postamble);
/* bb */
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar9331_1p1_baseband_core,
ARRAY_SIZE(ar9331_1p1_baseband_core), 2);
ar9331_1p1_baseband_core);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar9331_1p1_baseband_postamble,
ARRAY_SIZE(ar9331_1p1_baseband_postamble), 5);
ar9331_1p1_baseband_postamble);
/* radio */
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar9331_1p1_radio_core,
ARRAY_SIZE(ar9331_1p1_radio_core), 2);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0);
ar9331_1p1_radio_core);
/* soc */
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar9331_1p1_soc_preamble,
ARRAY_SIZE(ar9331_1p1_soc_preamble), 2);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
ar9331_1p1_soc_preamble);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
ar9331_1p1_soc_postamble,
ARRAY_SIZE(ar9331_1p1_soc_postamble), 2);
ar9331_1p1_soc_postamble);
/* rx/tx gain */
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9331_common_rx_gain_1p1,
ARRAY_SIZE(ar9331_common_rx_gain_1p1), 2);
ar9331_common_rx_gain_1p1);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_lowest_ob_db_tx_gain_1p1,
ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
5);
ar9331_modes_lowest_ob_db_tx_gain_1p1);
/* additional clock settings */
if (ah->is_clk_25mhz)
INIT_INI_ARRAY(&ah->iniAdditional,
ar9331_1p1_xtal_25M,
ARRAY_SIZE(ar9331_1p1_xtal_25M), 2);
ar9331_1p1_xtal_25M);
else
INIT_INI_ARRAY(&ah->iniAdditional,
ar9331_1p1_xtal_40M,
ARRAY_SIZE(ar9331_1p1_xtal_40M), 2);
ar9331_1p1_xtal_40M);
} else if (AR_SREV_9330_12(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
ar9331_1p2_mac_core,
ARRAY_SIZE(ar9331_1p2_mac_core), 2);
ar9331_1p2_mac_core);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar9331_1p2_mac_postamble,
ARRAY_SIZE(ar9331_1p2_mac_postamble), 5);
ar9331_1p2_mac_postamble);
/* bb */
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar9331_1p2_baseband_core,
ARRAY_SIZE(ar9331_1p2_baseband_core), 2);
ar9331_1p2_baseband_core);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar9331_1p2_baseband_postamble,
ARRAY_SIZE(ar9331_1p2_baseband_postamble), 5);
ar9331_1p2_baseband_postamble);
/* radio */
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar9331_1p2_radio_core,
ARRAY_SIZE(ar9331_1p2_radio_core), 2);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], NULL, 0, 0);
ar9331_1p2_radio_core);
/* soc */
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar9331_1p2_soc_preamble,
ARRAY_SIZE(ar9331_1p2_soc_preamble), 2);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
ar9331_1p2_soc_preamble);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
ar9331_1p2_soc_postamble,
ARRAY_SIZE(ar9331_1p2_soc_postamble), 2);
ar9331_1p2_soc_postamble);
/* rx/tx gain */
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9331_common_rx_gain_1p2,
ARRAY_SIZE(ar9331_common_rx_gain_1p2), 2);
ar9331_common_rx_gain_1p2);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_lowest_ob_db_tx_gain_1p2,
ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
5);
ar9331_modes_lowest_ob_db_tx_gain_1p2);
/* additional clock settings */
if (ah->is_clk_25mhz)
INIT_INI_ARRAY(&ah->iniAdditional,
ar9331_1p2_xtal_25M,
ARRAY_SIZE(ar9331_1p2_xtal_25M), 2);
ar9331_1p2_xtal_25M);
else
INIT_INI_ARRAY(&ah->iniAdditional,
ar9331_1p2_xtal_40M,
ARRAY_SIZE(ar9331_1p2_xtal_40M), 2);
ar9331_1p2_xtal_40M);
} else if (AR_SREV_9340(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
ar9340_1p0_mac_core,
ARRAY_SIZE(ar9340_1p0_mac_core), 2);
ar9340_1p0_mac_core);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar9340_1p0_mac_postamble,
ARRAY_SIZE(ar9340_1p0_mac_postamble), 5);
ar9340_1p0_mac_postamble);
/* bb */
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar9340_1p0_baseband_core,
ARRAY_SIZE(ar9340_1p0_baseband_core), 2);
ar9340_1p0_baseband_core);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar9340_1p0_baseband_postamble,
ARRAY_SIZE(ar9340_1p0_baseband_postamble), 5);
ar9340_1p0_baseband_postamble);
/* radio */
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar9340_1p0_radio_core,
ARRAY_SIZE(ar9340_1p0_radio_core), 2);
ar9340_1p0_radio_core);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
ar9340_1p0_radio_postamble,
ARRAY_SIZE(ar9340_1p0_radio_postamble), 5);
ar9340_1p0_radio_postamble);
/* soc */
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar9340_1p0_soc_preamble,
ARRAY_SIZE(ar9340_1p0_soc_preamble), 2);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
ar9340_1p0_soc_preamble);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
ar9340_1p0_soc_postamble,
ARRAY_SIZE(ar9340_1p0_soc_postamble), 5);
ar9340_1p0_soc_postamble);
/* rx/tx gain */
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9340Common_wo_xlna_rx_gain_table_1p0,
ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
5);
ar9340Common_wo_xlna_rx_gain_table_1p0);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_high_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_high_ob_db_tx_gain_table_1p0),
5);
ar9340Modes_high_ob_db_tx_gain_table_1p0);
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9340Modes_fast_clock_1p0,
ARRAY_SIZE(ar9340Modes_fast_clock_1p0),
3);
ar9340Modes_fast_clock_1p0);
if (!ah->is_clk_25mhz)
INIT_INI_ARRAY(&ah->iniAdditional,
ar9340_1p0_radio_core_40M,
ARRAY_SIZE(ar9340_1p0_radio_core_40M),
2);
ar9340_1p0_radio_core_40M);
} else if (AR_SREV_9485_11(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
ar9485_1_1_mac_core,
ARRAY_SIZE(ar9485_1_1_mac_core), 2);
ar9485_1_1_mac_core);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar9485_1_1_mac_postamble,
ARRAY_SIZE(ar9485_1_1_mac_postamble), 5);
ar9485_1_1_mac_postamble);
/* bb */
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_1,
ARRAY_SIZE(ar9485_1_1), 2);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_1);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar9485_1_1_baseband_core,
ARRAY_SIZE(ar9485_1_1_baseband_core), 2);
ar9485_1_1_baseband_core);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar9485_1_1_baseband_postamble,
ARRAY_SIZE(ar9485_1_1_baseband_postamble), 5);
ar9485_1_1_baseband_postamble);
/* radio */
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar9485_1_1_radio_core,
ARRAY_SIZE(ar9485_1_1_radio_core), 2);
ar9485_1_1_radio_core);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
ar9485_1_1_radio_postamble,
ARRAY_SIZE(ar9485_1_1_radio_postamble), 2);
ar9485_1_1_radio_postamble);
/* soc */
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar9485_1_1_soc_preamble,
ARRAY_SIZE(ar9485_1_1_soc_preamble), 2);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0);
ar9485_1_1_soc_preamble);
/* rx/tx gain */
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9485Common_wo_xlna_rx_gain_1_1,
ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2);
ar9485Common_wo_xlna_rx_gain_1_1);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485_modes_lowest_ob_db_tx_gain_1_1,
ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
5);
ar9485_modes_lowest_ob_db_tx_gain_1_1);
/* Load PCIE SERDES settings from INI */
/* Awake Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9485_1_1_pcie_phy_clkreq_disable_L1,
ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
2);
ar9485_1_1_pcie_phy_clkreq_disable_L1);
/* Sleep Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
ar9485_1_1_pcie_phy_clkreq_disable_L1,
ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
2);
ar9485_1_1_pcie_phy_clkreq_disable_L1);
} else if (AR_SREV_9462_20(ah)) {
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_2p0_mac_core,
ARRAY_SIZE(ar9462_2p0_mac_core), 2);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], ar9462_2p0_mac_core);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar9462_2p0_mac_postamble,
ARRAY_SIZE(ar9462_2p0_mac_postamble), 5);
ar9462_2p0_mac_postamble);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar9462_2p0_baseband_core,
ARRAY_SIZE(ar9462_2p0_baseband_core), 2);
ar9462_2p0_baseband_core);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar9462_2p0_baseband_postamble,
ARRAY_SIZE(ar9462_2p0_baseband_postamble), 5);
ar9462_2p0_baseband_postamble);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar9462_2p0_radio_core,
ARRAY_SIZE(ar9462_2p0_radio_core), 2);
ar9462_2p0_radio_core);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
ar9462_2p0_radio_postamble,
ARRAY_SIZE(ar9462_2p0_radio_postamble), 5);
ar9462_2p0_radio_postamble);
INIT_INI_ARRAY(&ah->ini_radio_post_sys2ant,
ar9462_2p0_radio_postamble_sys2ant,
ARRAY_SIZE(ar9462_2p0_radio_postamble_sys2ant),
5);
ar9462_2p0_radio_postamble_sys2ant);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar9462_2p0_soc_preamble,
ARRAY_SIZE(ar9462_2p0_soc_preamble), 2);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
ar9462_2p0_soc_preamble);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
ar9462_2p0_soc_postamble,
ARRAY_SIZE(ar9462_2p0_soc_postamble), 5);
ar9462_2p0_soc_postamble);
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_common_rx_gain_table_2p0,
ARRAY_SIZE(ar9462_common_rx_gain_table_2p0), 2);
ar9462_common_rx_gain_table_2p0);
/* Awake -> Sleep Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdes,
PCIE_PLL_ON_CREQ_DIS_L1_2P0,
ARRAY_SIZE(PCIE_PLL_ON_CREQ_DIS_L1_2P0),
2);
PCIE_PLL_ON_CREQ_DIS_L1_2P0);
/* Sleep -> Awake Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
PCIE_PLL_ON_CREQ_DIS_L1_2P0,
ARRAY_SIZE(PCIE_PLL_ON_CREQ_DIS_L1_2P0),
2);
PCIE_PLL_ON_CREQ_DIS_L1_2P0);
/* Fast clock modal settings */
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9462_modes_fast_clock_2p0,
ARRAY_SIZE(ar9462_modes_fast_clock_2p0), 3);
ar9462_modes_fast_clock_2p0);
INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
AR9462_BB_CTX_COEFJ(2p0),
ARRAY_SIZE(AR9462_BB_CTX_COEFJ(2p0)), 2);
AR9462_BB_CTX_COEFJ(2p0));
INIT_INI_ARRAY(&ah->ini_japan2484, AR9462_BBC_TXIFR_COEFFJ,
ARRAY_SIZE(AR9462_BBC_TXIFR_COEFFJ), 2);
INIT_INI_ARRAY(&ah->ini_japan2484, AR9462_BBC_TXIFR_COEFFJ);
} else if (AR_SREV_9550(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
ar955x_1p0_mac_core,
ARRAY_SIZE(ar955x_1p0_mac_core), 2);
ar955x_1p0_mac_core);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar955x_1p0_mac_postamble,
ARRAY_SIZE(ar955x_1p0_mac_postamble), 5);
ar955x_1p0_mac_postamble);
/* bb */
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar955x_1p0_baseband_core,
ARRAY_SIZE(ar955x_1p0_baseband_core), 2);
ar955x_1p0_baseband_core);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar955x_1p0_baseband_postamble,
ARRAY_SIZE(ar955x_1p0_baseband_postamble), 5);
ar955x_1p0_baseband_postamble);
/* radio */
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar955x_1p0_radio_core,
ARRAY_SIZE(ar955x_1p0_radio_core), 2);
ar955x_1p0_radio_core);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
ar955x_1p0_radio_postamble,
ARRAY_SIZE(ar955x_1p0_radio_postamble), 5);
ar955x_1p0_radio_postamble);
/* soc */
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar955x_1p0_soc_preamble,
ARRAY_SIZE(ar955x_1p0_soc_preamble), 2);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
ar955x_1p0_soc_preamble);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
ar955x_1p0_soc_postamble,
ARRAY_SIZE(ar955x_1p0_soc_postamble), 5);
ar955x_1p0_soc_postamble);
/* rx/tx gain */
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar955x_1p0_common_wo_xlna_rx_gain_table,
ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_table),
2);
ar955x_1p0_common_wo_xlna_rx_gain_table);
INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
ar955x_1p0_common_wo_xlna_rx_gain_bounds,
ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_bounds),
5);
ar955x_1p0_common_wo_xlna_rx_gain_bounds);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar955x_1p0_modes_xpa_tx_gain_table,
ARRAY_SIZE(ar955x_1p0_modes_xpa_tx_gain_table),
9);
ar955x_1p0_modes_xpa_tx_gain_table);
/* Fast clock modal settings */
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar955x_1p0_modes_fast_clock,
ARRAY_SIZE(ar955x_1p0_modes_fast_clock), 3);
ar955x_1p0_modes_fast_clock);
} else if (AR_SREV_9580(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
ar9580_1p0_mac_core,
ARRAY_SIZE(ar9580_1p0_mac_core), 2);
ar9580_1p0_mac_core);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar9580_1p0_mac_postamble,
ARRAY_SIZE(ar9580_1p0_mac_postamble), 5);
ar9580_1p0_mac_postamble);
/* bb */
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar9580_1p0_baseband_core,
ARRAY_SIZE(ar9580_1p0_baseband_core), 2);
ar9580_1p0_baseband_core);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar9580_1p0_baseband_postamble,
ARRAY_SIZE(ar9580_1p0_baseband_postamble), 5);
ar9580_1p0_baseband_postamble);
/* radio */
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar9580_1p0_radio_core,
ARRAY_SIZE(ar9580_1p0_radio_core), 2);
ar9580_1p0_radio_core);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
ar9580_1p0_radio_postamble,
ARRAY_SIZE(ar9580_1p0_radio_postamble), 5);
ar9580_1p0_radio_postamble);
/* soc */
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar9580_1p0_soc_preamble,
ARRAY_SIZE(ar9580_1p0_soc_preamble), 2);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
ar9580_1p0_soc_preamble);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
ar9580_1p0_soc_postamble,
ARRAY_SIZE(ar9580_1p0_soc_postamble), 5);
ar9580_1p0_soc_postamble);
/* rx/tx gain */
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_rx_gain_table,
ARRAY_SIZE(ar9580_1p0_rx_gain_table), 2);
ar9580_1p0_rx_gain_table);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_low_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
5);
ar9580_1p0_low_ob_db_tx_gain_table);
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9580_1p0_modes_fast_clock,
ARRAY_SIZE(ar9580_1p0_modes_fast_clock),
3);
ar9580_1p0_modes_fast_clock);
} else {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
ar9300_2p2_mac_core,
ARRAY_SIZE(ar9300_2p2_mac_core), 2);
ar9300_2p2_mac_core);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
ar9300_2p2_mac_postamble,
ARRAY_SIZE(ar9300_2p2_mac_postamble), 5);
ar9300_2p2_mac_postamble);
/* bb */
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
ar9300_2p2_baseband_core,
ARRAY_SIZE(ar9300_2p2_baseband_core), 2);
ar9300_2p2_baseband_core);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
ar9300_2p2_baseband_postamble,
ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5);
ar9300_2p2_baseband_postamble);
/* radio */
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
ar9300_2p2_radio_core,
ARRAY_SIZE(ar9300_2p2_radio_core), 2);
ar9300_2p2_radio_core);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
ar9300_2p2_radio_postamble,
ARRAY_SIZE(ar9300_2p2_radio_postamble), 5);
ar9300_2p2_radio_postamble);
/* soc */
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
ar9300_2p2_soc_preamble,
ARRAY_SIZE(ar9300_2p2_soc_preamble), 2);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
ar9300_2p2_soc_preamble);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
ar9300_2p2_soc_postamble,
ARRAY_SIZE(ar9300_2p2_soc_postamble), 5);
ar9300_2p2_soc_postamble);
/* rx/tx gain */
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_rx_gain_table_2p2,
ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2);
ar9300Common_rx_gain_table_2p2);
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
5);
ar9300Modes_lowest_ob_db_tx_gain_table_2p2);
/* Load PCIE SERDES settings from INI */
/* Awake Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdes,
ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
2);
ar9300PciePhy_pll_on_clkreq_disable_L1_2p2);
/* Sleep Setting */
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
2);
ar9300PciePhy_pll_on_clkreq_disable_L1_2p2);
/* Fast clock modal settings */
INIT_INI_ARRAY(&ah->iniModesFastClock,
ar9300Modes_fast_clock_2p2,
ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
3);
ar9300Modes_fast_clock_2p2);
}
}
@ -507,156 +355,110 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah)
{
if (AR_SREV_9330_12(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_lowest_ob_db_tx_gain_1p2,
ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p2),
5);
ar9331_modes_lowest_ob_db_tx_gain_1p2);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_lowest_ob_db_tx_gain_1p1,
ARRAY_SIZE(ar9331_modes_lowest_ob_db_tx_gain_1p1),
5);
ar9331_modes_lowest_ob_db_tx_gain_1p1);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
5);
ar9340Modes_lowest_ob_db_tx_gain_table_1p0);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485_modes_lowest_ob_db_tx_gain_1_1,
ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
5);
ar9485_modes_lowest_ob_db_tx_gain_1_1);
else if (AR_SREV_9550(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar955x_1p0_modes_xpa_tx_gain_table,
ARRAY_SIZE(ar955x_1p0_modes_xpa_tx_gain_table),
9);
ar955x_1p0_modes_xpa_tx_gain_table);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_lowest_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_lowest_ob_db_tx_gain_table),
5);
ar9580_1p0_lowest_ob_db_tx_gain_table);
else if (AR_SREV_9462_20(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9462_modes_low_ob_db_tx_gain_table_2p0,
ARRAY_SIZE(ar9462_modes_low_ob_db_tx_gain_table_2p0),
5);
ar9462_modes_low_ob_db_tx_gain_table_2p0);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
5);
ar9300Modes_lowest_ob_db_tx_gain_table_2p2);
}
static void ar9003_tx_gain_table_mode1(struct ath_hw *ah)
{
if (AR_SREV_9330_12(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_high_ob_db_tx_gain_1p2,
ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p2),
5);
ar9331_modes_high_ob_db_tx_gain_1p2);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_high_ob_db_tx_gain_1p1,
ARRAY_SIZE(ar9331_modes_high_ob_db_tx_gain_1p1),
5);
ar9331_modes_high_ob_db_tx_gain_1p1);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
5);
ar9340Modes_high_ob_db_tx_gain_table_1p0);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485Modes_high_ob_db_tx_gain_1_1,
ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
5);
ar9485Modes_high_ob_db_tx_gain_1_1);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_high_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_high_ob_db_tx_gain_table),
5);
ar9580_1p0_high_ob_db_tx_gain_table);
else if (AR_SREV_9550(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar955x_1p0_modes_no_xpa_tx_gain_table,
ARRAY_SIZE(ar955x_1p0_modes_no_xpa_tx_gain_table),
9);
ar955x_1p0_modes_no_xpa_tx_gain_table);
else if (AR_SREV_9462_20(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9462_modes_high_ob_db_tx_gain_table_2p0,
ARRAY_SIZE(ar9462_modes_high_ob_db_tx_gain_table_2p0),
5);
ar9462_modes_high_ob_db_tx_gain_table_2p0);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_high_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
5);
ar9300Modes_high_ob_db_tx_gain_table_2p2);
}
static void ar9003_tx_gain_table_mode2(struct ath_hw *ah)
{
if (AR_SREV_9330_12(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_low_ob_db_tx_gain_1p2,
ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p2),
5);
ar9331_modes_low_ob_db_tx_gain_1p2);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_low_ob_db_tx_gain_1p1,
ARRAY_SIZE(ar9331_modes_low_ob_db_tx_gain_1p1),
5);
ar9331_modes_low_ob_db_tx_gain_1p1);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
5);
ar9340Modes_low_ob_db_tx_gain_table_1p0);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485Modes_low_ob_db_tx_gain_1_1,
ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
5);
ar9485Modes_low_ob_db_tx_gain_1_1);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_low_ob_db_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_low_ob_db_tx_gain_table),
5);
ar9580_1p0_low_ob_db_tx_gain_table);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_low_ob_db_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
5);
ar9300Modes_low_ob_db_tx_gain_table_2p2);
}
static void ar9003_tx_gain_table_mode3(struct ath_hw *ah)
{
if (AR_SREV_9330_12(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_high_power_tx_gain_1p2,
ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p2),
5);
ar9331_modes_high_power_tx_gain_1p2);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9331_modes_high_power_tx_gain_1p1,
ARRAY_SIZE(ar9331_modes_high_power_tx_gain_1p1),
5);
ar9331_modes_high_power_tx_gain_1p1);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
5);
ar9340Modes_high_power_tx_gain_table_1p0);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485Modes_high_power_tx_gain_1_1,
ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
5);
ar9485Modes_high_power_tx_gain_1_1);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_high_power_tx_gain_table,
ARRAY_SIZE(ar9580_1p0_high_power_tx_gain_table),
5);
ar9580_1p0_high_power_tx_gain_table);
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_high_power_tx_gain_table_2p2,
ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
5);
ar9300Modes_high_power_tx_gain_table_2p2);
}
static void ar9003_tx_gain_table_mode4(struct ath_hw *ah)
{
if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9340Modes_mixed_ob_db_tx_gain_table_1p0);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_mixed_ob_db_tx_gain_table);
}
static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
@ -675,6 +477,9 @@ static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
case 3:
ar9003_tx_gain_table_mode3(ah);
break;
case 4:
ar9003_tx_gain_table_mode4(ah);
break;
}
}
@ -682,104 +487,67 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
{
if (AR_SREV_9330_12(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9331_common_rx_gain_1p2,
ARRAY_SIZE(ar9331_common_rx_gain_1p2),
2);
ar9331_common_rx_gain_1p2);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9331_common_rx_gain_1p1,
ARRAY_SIZE(ar9331_common_rx_gain_1p1),
2);
ar9331_common_rx_gain_1p1);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9340Common_rx_gain_table_1p0,
ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
2);
ar9340Common_rx_gain_table_1p0);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9485Common_wo_xlna_rx_gain_1_1,
ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
2);
ar9485Common_wo_xlna_rx_gain_1_1);
else if (AR_SREV_9550(ah)) {
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar955x_1p0_common_rx_gain_table,
ARRAY_SIZE(ar955x_1p0_common_rx_gain_table),
2);
ar955x_1p0_common_rx_gain_table);
INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
ar955x_1p0_common_rx_gain_bounds,
ARRAY_SIZE(ar955x_1p0_common_rx_gain_bounds),
5);
ar955x_1p0_common_rx_gain_bounds);
} else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_rx_gain_table,
ARRAY_SIZE(ar9580_1p0_rx_gain_table),
2);
ar9580_1p0_rx_gain_table);
else if (AR_SREV_9462_20(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_common_rx_gain_table_2p0,
ARRAY_SIZE(ar9462_common_rx_gain_table_2p0),
2);
ar9462_common_rx_gain_table_2p0);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_rx_gain_table_2p2,
ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
2);
ar9300Common_rx_gain_table_2p2);
}
static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
{
if (AR_SREV_9330_12(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9331_common_wo_xlna_rx_gain_1p2,
ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p2),
2);
ar9331_common_wo_xlna_rx_gain_1p2);
else if (AR_SREV_9330_11(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9331_common_wo_xlna_rx_gain_1p1,
ARRAY_SIZE(ar9331_common_wo_xlna_rx_gain_1p1),
2);
ar9331_common_wo_xlna_rx_gain_1p1);
else if (AR_SREV_9340(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9340Common_wo_xlna_rx_gain_table_1p0,
ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
2);
ar9340Common_wo_xlna_rx_gain_table_1p0);
else if (AR_SREV_9485_11(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9485Common_wo_xlna_rx_gain_1_1,
ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
2);
ar9485Common_wo_xlna_rx_gain_1_1);
else if (AR_SREV_9462_20(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_common_wo_xlna_rx_gain_table_2p0,
ARRAY_SIZE(ar9462_common_wo_xlna_rx_gain_table_2p0),
2);
ar9462_common_wo_xlna_rx_gain_table_2p0);
else if (AR_SREV_9550(ah)) {
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar955x_1p0_common_wo_xlna_rx_gain_table,
ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_table),
2);
ar955x_1p0_common_wo_xlna_rx_gain_table);
INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
ar955x_1p0_common_wo_xlna_rx_gain_bounds,
ARRAY_SIZE(ar955x_1p0_common_wo_xlna_rx_gain_bounds),
5);
ar955x_1p0_common_wo_xlna_rx_gain_bounds);
} else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_wo_xlna_rx_gain_table,
ARRAY_SIZE(ar9580_1p0_wo_xlna_rx_gain_table),
2);
ar9580_1p0_wo_xlna_rx_gain_table);
else
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9300Common_wo_xlna_rx_gain_table_2p2,
ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
2);
ar9300Common_wo_xlna_rx_gain_table_2p2);
}
static void ar9003_rx_gain_table_mode2(struct ath_hw *ah)
{
if (AR_SREV_9462_20(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9462_common_mixed_rx_gain_table_2p0,
ARRAY_SIZE(ar9462_common_mixed_rx_gain_table_2p0), 2);
ar9462_common_mixed_rx_gain_table_2p0);
}
static void ar9003_rx_gain_table_apply(struct ath_hw *ah)

View file

@ -117,8 +117,8 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
ah->is_clk_25mhz) {
u32 chan_frac;
channelSel = (freq * 2) / 75;
chan_frac = (((freq * 2) % 75) * 0x20000) / 75;
channelSel = freq / 75;
chan_frac = ((freq % 75) * 0x20000) / 75;
channelSel = (channelSel << 17) | chan_frac;
} else {
channelSel = CHANSEL_5G(freq);

View file

@ -633,6 +633,8 @@
#define AR_PHY_65NM_CH0_BIAS2 0x160c4
#define AR_PHY_65NM_CH0_BIAS4 0x160cc
#define AR_PHY_65NM_CH0_RXTX4 0x1610c
#define AR_PHY_65NM_CH1_RXTX4 0x1650c
#define AR_PHY_65NM_CH2_RXTX4 0x1690c
#define AR_CH0_TOP (AR_SREV_9300(ah) ? 0x16288 : \
((AR_SREV_9462(ah) ? 0x1628c : 0x16280)))
@ -876,6 +878,9 @@
#define AR_PHY_65NM_CH0_RXTX4_THERM_ON 0x10000000
#define AR_PHY_65NM_CH0_RXTX4_THERM_ON_S 28
#define AR_PHY_65NM_RXTX4_XLNA_BIAS 0xC0000000
#define AR_PHY_65NM_RXTX4_XLNA_BIAS_S 30
/*
* Channel 1 Register Map
*/

View file

@ -297,6 +297,8 @@ struct ath_tx {
struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
struct ath_descdma txdma;
struct ath_txq *txq_map[WME_NUM_AC];
u32 txq_max_pending[WME_NUM_AC];
u16 max_aggr_framelen[WME_NUM_AC][4][32];
};
struct ath_rx_edma {
@ -341,6 +343,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs);
void ath_tx_cleanup(struct ath_softc *sc);
int ath_txq_update(struct ath_softc *sc, int qnum,
struct ath9k_tx_queue_info *q);
void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop);
int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath_tx_control *txctl);
void ath_tx_tasklet(struct ath_softc *sc);
@ -360,7 +363,7 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
struct ath_vif {
int av_bslot;
bool is_bslot_active, primary_sta_vif;
bool primary_sta_vif;
__le64 tsf_adjust; /* TSF adjustment for staggered beacons */
struct ath_buf *av_bcbuf;
};
@ -386,6 +389,7 @@ struct ath_beacon_config {
u16 dtim_period;
u16 bmiss_timeout;
u8 dtim_count;
bool enable_beacon;
};
struct ath_beacon {
@ -397,7 +401,6 @@ struct ath_beacon {
u32 beaconq;
u32 bmisscnt;
u32 ast_be_xmit;
u32 bc_tstamp;
struct ieee80211_vif *bslot[ATH_BCBUF];
int slottime;
@ -411,12 +414,14 @@ struct ath_beacon {
bool tx_last;
};
void ath_beacon_tasklet(unsigned long data);
void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
int ath_beaconq_config(struct ath_softc *sc);
void ath_set_beacon(struct ath_softc *sc);
void ath9k_beacon_tasklet(unsigned long data);
bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
u32 changed);
void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif);
void ath9k_set_beacon(struct ath_softc *sc);
void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
/*******************/
@ -442,9 +447,12 @@ void ath_rx_poll(unsigned long data);
void ath_start_rx_poll(struct ath_softc *sc, u8 nbeacon);
void ath_paprd_calibrate(struct work_struct *work);
void ath_ani_calibrate(unsigned long data);
void ath_start_ani(struct ath_common *common);
void ath_start_ani(struct ath_softc *sc);
void ath_stop_ani(struct ath_softc *sc);
void ath_check_ani(struct ath_softc *sc);
int ath_update_survey_stats(struct ath_softc *sc);
void ath_update_survey_nf(struct ath_softc *sc, int channel);
void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
/**********/
/* BTCOEX */
@ -510,6 +518,12 @@ static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
}
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
struct ath9k_wow_pattern {
u8 pattern_bytes[MAX_PATTERN_SIZE];
u8 mask_bytes[MAX_PATTERN_SIZE];
u32 pattern_len;
};
/********************/
/* LED Control */
/********************/
@ -613,7 +627,6 @@ enum sc_op_flags {
SC_OP_INVALID,
SC_OP_BEACONS,
SC_OP_RXFLUSH,
SC_OP_TSF_RESET,
SC_OP_ANI_RUN,
SC_OP_PRIM_STA_VIF,
SC_OP_HW_RESET,
@ -711,6 +724,13 @@ struct ath_softc {
struct ath_ant_comb ant_comb;
u8 ant_tx, ant_rx;
struct dfs_pattern_detector *dfs_detector;
u32 wow_enabled;
#ifdef CONFIG_PM_SLEEP
atomic_t wow_got_bmiss_intr;
atomic_t wow_sleep_proc_intr; /* in the middle of WoW sleep ? */
u32 wow_intr_before_sleep;
#endif
};
void ath9k_tasklet(unsigned long data);

View file

@ -30,7 +30,7 @@ static void ath9k_reset_beacon_status(struct ath_softc *sc)
* the operating mode of the station (AP or AdHoc). Parameters are AIFS
* settings and channel width min/max
*/
int ath_beaconq_config(struct ath_softc *sc)
static void ath9k_beaconq_config(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
@ -38,6 +38,7 @@ int ath_beaconq_config(struct ath_softc *sc)
struct ath_txq *txq;
ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
/* Always burst out beacon and CAB traffic. */
qi.tqi_aifs = 1;
@ -56,12 +57,9 @@ int ath_beaconq_config(struct ath_softc *sc)
}
if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
ath_err(common,
"Unable to update h/w beacon queue parameters\n");
return 0;
ath_err(common, "Unable to update h/w beacon queue parameters\n");
} else {
ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
return 1;
}
}
@ -70,7 +68,7 @@ int ath_beaconq_config(struct ath_softc *sc)
* up rate codes, and channel flags. Beacons are always sent out at the
* lowest rate, and are not retried.
*/
static void ath_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
static void ath9k_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
struct ath_buf *bf, int rateidx)
{
struct sk_buff *skb = bf->bf_mpdu;
@ -81,8 +79,6 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
u8 chainmask = ah->txchainmask;
u8 rate = 0;
ath9k_reset_beacon_status(sc);
sband = &sc->sbands[common->hw->conf.channel->band];
rate = sband->bitrates[rateidx].hw_value;
if (vif->bss_conf.use_short_preamble)
@ -111,7 +107,7 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ieee80211_vif *vif,
ath9k_hw_set_txdesc(ah, bf->bf_desc, &info);
}
static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
static void ath9k_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct ath_softc *sc = hw->priv;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@ -128,28 +124,22 @@ static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
}
}
static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath_softc *sc = hw->priv;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_buf *bf;
struct ath_vif *avp;
struct ath_vif *avp = (void *)vif->drv_priv;
struct sk_buff *skb;
struct ath_txq *cabq;
struct ath_txq *cabq = sc->beacon.cabq;
struct ieee80211_tx_info *info;
struct ieee80211_mgmt *mgmt_hdr;
int cabq_depth;
ath9k_reset_beacon_status(sc);
avp = (void *)vif->drv_priv;
cabq = sc->beacon.cabq;
if ((avp->av_bcbuf == NULL) || !avp->is_bslot_active)
if (avp->av_bcbuf == NULL)
return NULL;
/* Release the old beacon first */
bf = avp->av_bcbuf;
skb = bf->bf_mpdu;
if (skb) {
@ -159,14 +149,14 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
bf->bf_buf_addr = 0;
}
/* Get a new beacon from mac80211 */
skb = ieee80211_beacon_get(hw, vif);
bf->bf_mpdu = skb;
if (skb == NULL)
return NULL;
((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
avp->tsf_adjust;
bf->bf_mpdu = skb;
mgmt_hdr = (struct ieee80211_mgmt *)skb->data;
mgmt_hdr->u.beacon.timestamp = avp->tsf_adjust;
info = IEEE80211_SKB_CB(skb);
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
@ -212,61 +202,52 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
}
}
ath_beacon_setup(sc, vif, bf, info->control.rates[0].idx);
ath9k_beacon_setup(sc, vif, bf, info->control.rates[0].idx);
while (skb) {
ath_tx_cabq(hw, skb);
ath9k_tx_cabq(hw, skb);
skb = ieee80211_get_buffered_bc(hw, vif);
}
return bf;
}
int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif)
void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_vif *avp;
struct ath_buf *bf;
struct sk_buff *skb;
struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
__le64 tstamp;
struct ath_vif *avp = (void *)vif->drv_priv;
int slot;
avp = (void *)vif->drv_priv;
avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf, struct ath_buf, list);
list_del(&avp->av_bcbuf->list);
/* Allocate a beacon descriptor if we haven't done so. */
if (!avp->av_bcbuf) {
/* Allocate beacon state for hostap/ibss. We know
* a buffer is available. */
avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf,
struct ath_buf, list);
list_del(&avp->av_bcbuf->list);
if (ath9k_uses_beacons(vif->type)) {
int slot;
/*
* Assign the vif to a beacon xmit slot. As
* above, this cannot fail to find one.
*/
avp->av_bslot = 0;
for (slot = 0; slot < ATH_BCBUF; slot++)
if (sc->beacon.bslot[slot] == NULL) {
avp->av_bslot = slot;
avp->is_bslot_active = false;
/* NB: keep looking for a double slot */
if (slot == 0 || !sc->beacon.bslot[slot-1])
break;
}
BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
sc->beacon.bslot[avp->av_bslot] = vif;
sc->nbcnvifs++;
for (slot = 0; slot < ATH_BCBUF; slot++) {
if (sc->beacon.bslot[slot] == NULL) {
avp->av_bslot = slot;
break;
}
}
/* release the previous beacon frame, if it already exists. */
bf = avp->av_bcbuf;
if (bf->bf_mpdu != NULL) {
skb = bf->bf_mpdu;
sc->beacon.bslot[avp->av_bslot] = vif;
sc->nbcnvifs++;
ath_dbg(common, CONFIG, "Added interface at beacon slot: %d\n",
avp->av_bslot);
}
void ath9k_beacon_remove_slot(struct ath_softc *sc, struct ieee80211_vif *vif)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_vif *avp = (void *)vif->drv_priv;
struct ath_buf *bf = avp->av_bcbuf;
ath_dbg(common, CONFIG, "Removing interface at beacon slot: %d\n",
avp->av_bslot);
tasklet_disable(&sc->bcon_tasklet);
if (bf && bf->bf_mpdu) {
struct sk_buff *skb = bf->bf_mpdu;
dma_unmap_single(sc->dev, bf->bf_buf_addr,
skb->len, DMA_TO_DEVICE);
dev_kfree_skb_any(skb);
@ -274,99 +255,74 @@ int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif)
bf->bf_buf_addr = 0;
}
/* NB: the beacon data buffer must be 32-bit aligned. */
skb = ieee80211_beacon_get(sc->hw, vif);
if (skb == NULL)
return -ENOMEM;
avp->av_bcbuf = NULL;
sc->beacon.bslot[avp->av_bslot] = NULL;
sc->nbcnvifs--;
list_add_tail(&bf->list, &sc->beacon.bbuf);
tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
sc->beacon.bc_tstamp = (u32) le64_to_cpu(tstamp);
/* Calculate a TSF adjustment factor required for staggered beacons. */
if (avp->av_bslot > 0) {
u64 tsfadjust;
int intval;
intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
/*
* Calculate the TSF offset for this beacon slot, i.e., the
* number of usecs that need to be added to the timestamp field
* in Beacon and Probe Response frames. Beacon slot 0 is
* processed at the correct offset, so it does not require TSF
* adjustment. Other slots are adjusted to get the timestamp
* close to the TBTT for the BSS.
*/
tsfadjust = TU_TO_USEC(intval * avp->av_bslot) / ATH_BCBUF;
avp->tsf_adjust = cpu_to_le64(tsfadjust);
ath_dbg(common, BEACON,
"stagger beacons, bslot %d intval %u tsfadjust %llu\n",
avp->av_bslot, intval, (unsigned long long)tsfadjust);
((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
avp->tsf_adjust;
} else
avp->tsf_adjust = cpu_to_le64(0);
bf->bf_mpdu = skb;
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
skb->len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
bf->bf_buf_addr = 0;
ath_err(common, "dma_mapping_error on beacon alloc\n");
return -ENOMEM;
}
avp->is_bslot_active = true;
return 0;
tasklet_enable(&sc->bcon_tasklet);
}
void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
static int ath9k_beacon_choose_slot(struct ath_softc *sc)
{
if (avp->av_bcbuf != NULL) {
struct ath_buf *bf;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
u16 intval;
u32 tsftu;
u64 tsf;
int slot;
avp->is_bslot_active = false;
if (avp->av_bslot != -1) {
sc->beacon.bslot[avp->av_bslot] = NULL;
sc->nbcnvifs--;
avp->av_bslot = -1;
}
bf = avp->av_bcbuf;
if (bf->bf_mpdu != NULL) {
struct sk_buff *skb = bf->bf_mpdu;
dma_unmap_single(sc->dev, bf->bf_buf_addr,
skb->len, DMA_TO_DEVICE);
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
bf->bf_buf_addr = 0;
}
list_add_tail(&bf->list, &sc->beacon.bbuf);
avp->av_bcbuf = NULL;
if (sc->sc_ah->opmode != NL80211_IFTYPE_AP) {
ath_dbg(common, BEACON, "slot 0, tsf: %llu\n",
ath9k_hw_gettsf64(sc->sc_ah));
return 0;
}
intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
tsf = ath9k_hw_gettsf64(sc->sc_ah);
tsf += TU_TO_USEC(sc->sc_ah->config.sw_beacon_response_time);
tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF);
slot = (tsftu % (intval * ATH_BCBUF)) / intval;
ath_dbg(common, BEACON, "slot: %d tsf: %llu tsftu: %u\n",
slot, tsf, tsftu / ATH_BCBUF);
return slot;
}
void ath_beacon_tasklet(unsigned long data)
void ath9k_set_tsfadjust(struct ath_softc *sc, struct ieee80211_vif *vif)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
struct ath_vif *avp = (void *)vif->drv_priv;
u64 tsfadjust;
if (avp->av_bslot == 0)
return;
tsfadjust = cur_conf->beacon_interval * avp->av_bslot / ATH_BCBUF;
avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
ath_dbg(common, CONFIG, "tsfadjust is: %llu for bslot: %d\n",
(unsigned long long)tsfadjust, avp->av_bslot);
}
void ath9k_beacon_tasklet(unsigned long data)
{
struct ath_softc *sc = (struct ath_softc *)data;
struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath_buf *bf = NULL;
struct ieee80211_vif *vif;
bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA);
int slot;
u32 bfaddr, bc = 0;
if (work_pending(&sc->hw_reset_work)) {
if (test_bit(SC_OP_HW_RESET, &sc->sc_flags)) {
ath_dbg(common, RESET,
"reset work is pending, skip beaconing now\n");
return;
}
/*
* Check if the previous beacon has gone out. If
* not don't try to post another, skip this period
@ -390,55 +346,25 @@ void ath_beacon_tasklet(unsigned long data)
} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
ath_dbg(common, BSTUCK, "beacon is officially stuck\n");
sc->beacon.bmisscnt = 0;
set_bit(SC_OP_TSF_RESET, &sc->sc_flags);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
ath9k_queue_reset(sc, RESET_TYPE_BEACON_STUCK);
}
return;
}
/*
* Generate beacon frames. we are sending frames
* staggered so calculate the slot for this frame based
* on the tsf to safeguard against missing an swba.
*/
slot = ath9k_beacon_choose_slot(sc);
vif = sc->beacon.bslot[slot];
if (!vif || !vif->bss_conf.enable_beacon)
return;
if (ah->opmode == NL80211_IFTYPE_AP) {
u16 intval;
u32 tsftu;
u64 tsf;
bf = ath9k_beacon_generate(sc->hw, vif);
WARN_ON(!bf);
intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
tsf = ath9k_hw_gettsf64(ah);
tsf += TU_TO_USEC(ah->config.sw_beacon_response_time);
tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF);
slot = (tsftu % (intval * ATH_BCBUF)) / intval;
vif = sc->beacon.bslot[slot];
ath_dbg(common, BEACON,
"slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
slot, tsf, tsftu / ATH_BCBUF, intval, vif);
} else {
slot = 0;
vif = sc->beacon.bslot[slot];
}
bfaddr = 0;
if (vif) {
bf = ath_beacon_generate(sc->hw, vif);
if (bf != NULL) {
bfaddr = bf->bf_daddr;
bc = 1;
}
if (sc->beacon.bmisscnt != 0) {
ath_dbg(common, BSTUCK,
"resume beacon xmit after %u misses\n",
sc->beacon.bmisscnt);
sc->beacon.bmisscnt = 0;
}
if (sc->beacon.bmisscnt != 0) {
ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n",
sc->beacon.bmisscnt);
sc->beacon.bmisscnt = 0;
}
/*
@ -458,39 +384,40 @@ void ath_beacon_tasklet(unsigned long data)
* set to ATH_BCBUF so this check is a noop.
*/
if (sc->beacon.updateslot == UPDATE) {
sc->beacon.updateslot = COMMIT; /* commit next beacon */
sc->beacon.updateslot = COMMIT;
sc->beacon.slotupdate = slot;
} else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) {
} else if (sc->beacon.updateslot == COMMIT &&
sc->beacon.slotupdate == slot) {
ah->slottime = sc->beacon.slottime;
ath9k_hw_init_global_settings(ah);
sc->beacon.updateslot = OK;
}
if (bfaddr != 0) {
if (bf) {
ath9k_reset_beacon_status(sc);
ath_dbg(common, BEACON,
"Transmitting beacon for slot: %d\n", slot);
/* NB: cabq traffic should already be queued and primed */
ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
if (!edma)
ath9k_hw_txstart(ah, sc->beacon.beaconq);
sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */
}
}
static void ath9k_beacon_init(struct ath_softc *sc,
u32 next_beacon,
u32 beacon_period)
static void ath9k_beacon_init(struct ath_softc *sc, u32 nexttbtt, u32 intval)
{
if (test_bit(SC_OP_TSF_RESET, &sc->sc_flags)) {
ath9k_ps_wakeup(sc);
ath9k_hw_reset_tsf(sc->sc_ah);
}
struct ath_hw *ah = sc->sc_ah;
ath9k_hw_beaconinit(sc->sc_ah, next_beacon, beacon_period);
if (test_bit(SC_OP_TSF_RESET, &sc->sc_flags)) {
ath9k_ps_restore(sc);
clear_bit(SC_OP_TSF_RESET, &sc->sc_flags);
}
ath9k_hw_disable_interrupts(ah);
ath9k_hw_reset_tsf(ah);
ath9k_beaconq_config(sc);
ath9k_hw_beaconinit(ah, nexttbtt, intval);
sc->beacon.bmisscnt = 0;
ath9k_hw_set_interrupts(ah);
ath9k_hw_enable_interrupts(ah);
}
/*
@ -498,32 +425,27 @@ static void ath9k_beacon_init(struct ath_softc *sc,
* burst together. For the former arrange for the SWBA to be delivered for each
* slot. Slots that are not occupied will generate nothing.
*/
static void ath_beacon_config_ap(struct ath_softc *sc,
struct ath_beacon_config *conf)
static void ath9k_beacon_config_ap(struct ath_softc *sc,
struct ath_beacon_config *conf)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
u32 nexttbtt, intval;
/* NB: the beacon interval is kept internally in TU's */
intval = TU_TO_USEC(conf->beacon_interval);
intval /= ATH_BCBUF; /* for staggered beacons */
intval /= ATH_BCBUF;
nexttbtt = intval;
/*
* In AP mode we enable the beacon timers and SWBA interrupts to
* prepare beacon frames.
*/
ah->imask |= ATH9K_INT_SWBA;
ath_beaconq_config(sc);
if (conf->enable_beacon)
ah->imask |= ATH9K_INT_SWBA;
else
ah->imask &= ~ATH9K_INT_SWBA;
/* Set the computed AP beacon timers */
ath_dbg(common, BEACON, "AP nexttbtt: %u intval: %u conf_intval: %u\n",
nexttbtt, intval, conf->beacon_interval);
ath9k_hw_disable_interrupts(ah);
set_bit(SC_OP_TSF_RESET, &sc->sc_flags);
ath9k_beacon_init(sc, nexttbtt, intval);
sc->beacon.bmisscnt = 0;
ath9k_hw_set_interrupts(ah);
ath9k_hw_enable_interrupts(ah);
}
/*
@ -534,8 +456,8 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
* we'll receive a BMISS interrupt when we stop seeing beacons from the AP
* we've associated with.
*/
static void ath_beacon_config_sta(struct ath_softc *sc,
struct ath_beacon_config *conf)
static void ath9k_beacon_config_sta(struct ath_softc *sc,
struct ath_beacon_config *conf)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
@ -547,7 +469,7 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
int num_beacons, offset, dtim_dec_count, cfp_dec_count;
/* No need to configure beacon if we are not associated */
if (!common->curaid) {
if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
ath_dbg(common, BEACON,
"STA is not yet associated..skipping beacon config\n");
return;
@ -654,97 +576,65 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
ath9k_hw_enable_interrupts(ah);
}
static void ath_beacon_config_adhoc(struct ath_softc *sc,
struct ath_beacon_config *conf)
static void ath9k_beacon_config_adhoc(struct ath_softc *sc,
struct ath_beacon_config *conf)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
u32 tsf, intval, nexttbtt;
u32 intval, nexttbtt;
ath9k_reset_beacon_status(sc);
if (!test_bit(SC_OP_BEACONS, &sc->sc_flags))
ath9k_hw_settsf64(ah, sc->beacon.bc_tstamp);
intval = TU_TO_USEC(conf->beacon_interval);
tsf = roundup(ath9k_hw_gettsf32(ah) + TU_TO_USEC(FUDGE), intval);
nexttbtt = tsf + intval;
nexttbtt = intval;
ath_dbg(common, BEACON, "IBSS nexttbtt %u intval %u (%u)\n",
if (conf->enable_beacon)
ah->imask |= ATH9K_INT_SWBA;
else
ah->imask &= ~ATH9K_INT_SWBA;
ath_dbg(common, BEACON, "IBSS nexttbtt: %u intval: %u conf_intval: %u\n",
nexttbtt, intval, conf->beacon_interval);
/*
* In IBSS mode enable the beacon timers but only enable SWBA interrupts
* if we need to manually prepare beacon frames. Otherwise we use a
* self-linked tx descriptor and let the hardware deal with things.
*/
ah->imask |= ATH9K_INT_SWBA;
ath_beaconq_config(sc);
/* Set the computed ADHOC beacon timers */
ath9k_hw_disable_interrupts(ah);
ath9k_beacon_init(sc, nexttbtt, intval);
sc->beacon.bmisscnt = 0;
ath9k_hw_set_interrupts(ah);
ath9k_hw_enable_interrupts(ah);
}
static bool ath9k_allow_beacon_config(struct ath_softc *sc,
struct ieee80211_vif *vif)
bool ath9k_allow_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
{
struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
struct ath_vif *avp = (void *)vif->drv_priv;
/*
* Can not have different beacon interval on multiple
* AP interface case
*/
if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
(sc->nbcnvifs > 1) &&
(vif->type == NL80211_IFTYPE_AP) &&
(cur_conf->beacon_interval != bss_conf->beacon_int)) {
ath_dbg(common, CONFIG,
"Changing beacon interval of multiple AP interfaces !\n");
return false;
if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
if ((vif->type != NL80211_IFTYPE_AP) ||
(sc->nbcnvifs > 1)) {
ath_dbg(common, CONFIG,
"An AP interface is already present !\n");
return false;
}
}
/*
* Can not configure station vif's beacon config
* while on AP opmode
*/
if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
(vif->type != NL80211_IFTYPE_AP)) {
ath_dbg(common, CONFIG,
"STA vif's beacon not allowed on AP mode\n");
return false;
}
/*
* Do not allow beacon config if HW was already configured
* with another STA vif
*/
if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) &&
(vif->type == NL80211_IFTYPE_STATION) &&
test_bit(SC_OP_BEACONS, &sc->sc_flags) &&
!avp->primary_sta_vif) {
ath_dbg(common, CONFIG,
"Beacon already configured for a station interface\n");
return false;
if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
if ((vif->type == NL80211_IFTYPE_STATION) &&
test_bit(SC_OP_BEACONS, &sc->sc_flags) &&
!avp->primary_sta_vif) {
ath_dbg(common, CONFIG,
"Beacon already configured for a station interface\n");
return false;
}
}
return true;
}
void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
static void ath9k_cache_beacon_config(struct ath_softc *sc,
struct ieee80211_bss_conf *bss_conf)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
if (!ath9k_allow_beacon_config(sc, vif))
return;
ath_dbg(common, BEACON,
"Caching beacon data for BSS: %pM\n", bss_conf->bssid);
/* Setup the beacon configuration parameters */
cur_conf->beacon_interval = bss_conf->beacon_int;
cur_conf->dtim_period = bss_conf->dtim_period;
cur_conf->listen_interval = 1;
@ -769,73 +659,62 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
if (cur_conf->dtim_period == 0)
cur_conf->dtim_period = 1;
ath_set_beacon(sc);
}
static bool ath_has_valid_bslot(struct ath_softc *sc)
void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif,
u32 changed)
{
struct ath_vif *avp;
int slot;
bool found = false;
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
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 (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) {
ath9k_cache_beacon_config(sc, bss_conf);
ath9k_set_beacon(sc);
set_bit(SC_OP_BEACONS, &sc->sc_flags);
} else {
/*
* Take care of multiple interfaces when
* enabling/disabling SWBA.
*/
if (changed & BSS_CHANGED_BEACON_ENABLED) {
if (!bss_conf->enable_beacon &&
(sc->nbcnvifs <= 1)) {
cur_conf->enable_beacon = false;
} else if (bss_conf->enable_beacon) {
cur_conf->enable_beacon = true;
ath9k_cache_beacon_config(sc, bss_conf);
}
}
if (cur_conf->beacon_interval) {
ath9k_set_beacon(sc);
if (cur_conf->enable_beacon)
set_bit(SC_OP_BEACONS, &sc->sc_flags);
else
clear_bit(SC_OP_BEACONS, &sc->sc_flags);
}
}
return found;
}
void ath_set_beacon(struct ath_softc *sc)
void ath9k_set_beacon(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
switch (sc->sc_ah->opmode) {
case NL80211_IFTYPE_AP:
if (ath_has_valid_bslot(sc))
ath_beacon_config_ap(sc, cur_conf);
ath9k_beacon_config_ap(sc, cur_conf);
break;
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_MESH_POINT:
ath_beacon_config_adhoc(sc, cur_conf);
ath9k_beacon_config_adhoc(sc, cur_conf);
break;
case NL80211_IFTYPE_STATION:
ath_beacon_config_sta(sc, cur_conf);
ath9k_beacon_config_sta(sc, cur_conf);
break;
default:
ath_dbg(common, CONFIG, "Unsupported beaconing mode\n");
return;
}
set_bit(SC_OP_BEACONS, &sc->sc_flags);
}
void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
{
struct ath_hw *ah = sc->sc_ah;
if (!ath_has_valid_bslot(sc)) {
clear_bit(SC_OP_BEACONS, &sc->sc_flags);
return;
}
ath9k_ps_wakeup(sc);
if (status) {
/* Re-enable beaconing */
ah->imask |= ATH9K_INT_SWBA;
ath9k_hw_set_interrupts(ah);
} else {
/* Disable SWBA interrupt */
ah->imask &= ~ATH9K_INT_SWBA;
ath9k_hw_set_interrupts(ah);
tasklet_kill(&sc->bcon_tasklet);
ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
}
ath9k_ps_restore(sc);
}

View file

@ -30,10 +30,10 @@ struct ar5416IniArray {
u32 ia_columns;
};
#define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \
#define INIT_INI_ARRAY(iniarray, array) do { \
(iniarray)->ia_array = (u32 *)(array); \
(iniarray)->ia_rows = (rows); \
(iniarray)->ia_columns = (columns); \
(iniarray)->ia_rows = ARRAY_SIZE(array); \
(iniarray)->ia_columns = ARRAY_SIZE(array[0]); \
} while (0)
#define INI_RA(iniarray, row, column) \

View file

@ -206,10 +206,9 @@ static ssize_t write_file_disable_ani(struct file *file,
if (disable_ani) {
clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
del_timer_sync(&common->ani.timer);
ath_stop_ani(sc);
} else {
set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
ath_start_ani(common);
ath_check_ani(sc);
}
return count;
@ -1556,6 +1555,14 @@ int ath9k_init_debug(struct ath_hw *ah)
&fops_interrupt);
debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_xmit);
debugfs_create_u32("qlen_bk", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
&sc->tx.txq_max_pending[WME_AC_BK]);
debugfs_create_u32("qlen_be", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
&sc->tx.txq_max_pending[WME_AC_BE]);
debugfs_create_u32("qlen_vi", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
&sc->tx.txq_max_pending[WME_AC_VI]);
debugfs_create_u32("qlen_vo", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
&sc->tx.txq_max_pending[WME_AC_VO]);
debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_stations);
debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc,

View file

@ -32,6 +32,19 @@ struct ath_buf;
#define RESET_STAT_INC(sc, type) do { } while (0)
#endif
enum ath_reset_type {
RESET_TYPE_BB_HANG,
RESET_TYPE_BB_WATCHDOG,
RESET_TYPE_FATAL_INT,
RESET_TYPE_TX_ERROR,
RESET_TYPE_TX_HANG,
RESET_TYPE_PLL_HANG,
RESET_TYPE_MAC_HANG,
RESET_TYPE_BEACON_STUCK,
RESET_TYPE_MCI,
__RESET_TYPE_MAX
};
#ifdef CONFIG_ATH9K_DEBUGFS
/**
@ -209,17 +222,6 @@ struct ath_rx_stats {
u32 rx_frags;
};
enum ath_reset_type {
RESET_TYPE_BB_HANG,
RESET_TYPE_BB_WATCHDOG,
RESET_TYPE_FATAL_INT,
RESET_TYPE_TX_ERROR,
RESET_TYPE_TX_HANG,
RESET_TYPE_PLL_HANG,
RESET_TYPE_MAC_HANG,
__RESET_TYPE_MAX
};
struct ath_stats {
struct ath_interrupt_stats istats;
struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];

View file

@ -241,16 +241,12 @@ enum eeprom_param {
EEP_TEMPSENSE_SLOPE,
EEP_TEMPSENSE_SLOPE_PAL_ON,
EEP_PWR_TABLE_OFFSET,
EEP_DRIVE_STRENGTH,
EEP_INTERNAL_REGULATOR,
EEP_SWREG,
EEP_PAPRD,
EEP_MODAL_VER,
EEP_ANT_DIV_CTL1,
EEP_CHAIN_MASK_REDUCE,
EEP_ANTENNA_GAIN_2G,
EEP_ANTENNA_GAIN_5G,
EEP_QUICK_DROP
};
enum ar5416_rates {

View file

@ -1111,7 +1111,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
!test_bit(OP_ANI_RUNNING, &priv->op_flags)) {
ath9k_hw_set_tsfadjust(priv->ah, 1);
ath9k_hw_set_tsfadjust(priv->ah, true);
ath9k_htc_start_ani(priv);
}
@ -1351,7 +1351,7 @@ static int ath9k_htc_conf_tx(struct ieee80211_hw *hw,
qi.tqi_aifs = params->aifs;
qi.tqi_cwmin = params->cw_min;
qi.tqi_cwmax = params->cw_max;
qi.tqi_burstTime = params->txop;
qi.tqi_burstTime = params->txop * 32;
qnum = get_hw_qnum(queue, priv->hwq_map);

View file

@ -671,10 +671,6 @@ static int __ath9k_hw_init(struct ath_hw *ah)
if (!AR_SREV_9300_20_OR_LATER(ah))
ah->ani_function &= ~ATH9K_ANI_MRC_CCK;
/* disable ANI for 9340 */
if (AR_SREV_9340(ah))
ah->config.enable_ani = false;
ath9k_hw_init_mode_regs(ah);
if (!ah->is_pciexpress)
@ -2589,6 +2585,14 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
}
if (AR_SREV_9280_20_OR_LATER(ah)) {
pCap->hw_caps |= ATH9K_HW_WOW_DEVICE_CAPABLE |
ATH9K_HW_WOW_PATTERN_MATCH_EXACT;
if (AR_SREV_9280(ah))
pCap->hw_caps |= ATH9K_HW_WOW_PATTERN_MATCH_DWORD;
}
return 0;
}
@ -2908,9 +2912,9 @@ void ath9k_hw_reset_tsf(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_reset_tsf);
void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting)
void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set)
{
if (setting)
if (set)
ah->misc_mode |= AR_PCU_TX_ADD_TSF;
else
ah->misc_mode &= ~AR_PCU_TX_ADD_TSF;

View file

@ -180,6 +180,37 @@
#define PAPRD_TABLE_SZ 24
#define PAPRD_IDEAL_AGC2_PWR_RANGE 0xe0
/*
* Wake on Wireless
*/
/* Keep Alive Frame */
#define KAL_FRAME_LEN 28
#define KAL_FRAME_TYPE 0x2 /* data frame */
#define KAL_FRAME_SUB_TYPE 0x4 /* null data frame */
#define KAL_DURATION_ID 0x3d
#define KAL_NUM_DATA_WORDS 6
#define KAL_NUM_DESC_WORDS 12
#define KAL_ANTENNA_MODE 1
#define KAL_TO_DS 1
#define KAL_DELAY 4 /*delay of 4ms between 2 KAL frames */
#define KAL_TIMEOUT 900
#define MAX_PATTERN_SIZE 256
#define MAX_PATTERN_MASK_SIZE 32
#define MAX_NUM_PATTERN 8
#define MAX_NUM_USER_PATTERN 6 /* deducting the disassociate and
deauthenticate packets */
/*
* WoW trigger mapping to hardware code
*/
#define AH_WOW_USER_PATTERN_EN BIT(0)
#define AH_WOW_MAGIC_PATTERN_EN BIT(1)
#define AH_WOW_LINK_CHANGE BIT(2)
#define AH_WOW_BEACON_MISS BIT(3)
enum ath_hw_txq_subtype {
ATH_TXQ_AC_BE = 0,
ATH_TXQ_AC_BK = 1,
@ -212,8 +243,22 @@ enum ath9k_hw_caps {
ATH9K_HW_CAP_RTT = BIT(14),
ATH9K_HW_CAP_MCI = BIT(15),
ATH9K_HW_CAP_DFS = BIT(16),
ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(17),
ATH9K_HW_WOW_PATTERN_MATCH_EXACT = BIT(18),
ATH9K_HW_WOW_PATTERN_MATCH_DWORD = BIT(19),
};
/*
* WoW device capabilities
* @ATH9K_HW_WOW_DEVICE_CAPABLE: device revision is capable of WoW.
* @ATH9K_HW_WOW_PATTERN_MATCH_EXACT: device is capable of matching
* an exact user defined pattern or de-authentication/disassoc pattern.
* @ATH9K_HW_WOW_PATTERN_MATCH_DWORD: device requires the first four
* bytes of the pattern for user defined pattern, de-authentication and
* disassociation patterns for all types of possible frames recieved
* of those types.
*/
struct ath9k_hw_capabilities {
u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */
u16 rts_aggr_limit;
@ -815,6 +860,9 @@ struct ath_hw {
struct ar5416IniArray iniBank7;
struct ar5416IniArray iniAddac;
struct ar5416IniArray iniPcieSerdes;
#ifdef CONFIG_PM_SLEEP
struct ar5416IniArray iniPcieSerdesWow;
#endif
struct ar5416IniArray iniPcieSerdesLowPower;
struct ar5416IniArray iniModesFastClock;
struct ar5416IniArray iniAdditional;
@ -863,6 +911,9 @@ struct ath_hw {
/* Enterprise mode cap */
u32 ent_mode;
#ifdef CONFIG_PM_SLEEP
u32 wow_event_mask;
#endif
bool is_clk_25mhz;
int (*get_mac_revision)(void);
int (*external_reset)(void);
@ -943,7 +994,7 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah);
u64 ath9k_hw_gettsf64(struct ath_hw *ah);
void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
void ath9k_hw_reset_tsf(struct ath_hw *ah);
void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set);
void ath9k_hw_init_global_settings(struct ath_hw *ah);
u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah);
void ath9k_hw_set11nmac2040(struct ath_hw *ah);
@ -1061,6 +1112,37 @@ ath9k_hw_get_btcoex_scheme(struct ath_hw *ah)
}
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
#ifdef CONFIG_PM_SLEEP
const char *ath9k_hw_wow_event_to_string(u32 wow_event);
void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern,
u8 *user_mask, int pattern_count,
int pattern_len);
u32 ath9k_hw_wow_wakeup(struct ath_hw *ah);
void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable);
#else
static inline const char *ath9k_hw_wow_event_to_string(u32 wow_event)
{
return NULL;
}
static inline void ath9k_hw_wow_apply_pattern(struct ath_hw *ah,
u8 *user_pattern,
u8 *user_mask,
int pattern_count,
int pattern_len)
{
}
static inline u32 ath9k_hw_wow_wakeup(struct ath_hw *ah)
{
return 0;
}
static inline void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable)
{
}
#endif
#define ATH9K_CLOCK_RATE_CCK 22
#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40
#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44

View file

@ -434,6 +434,7 @@ static int ath9k_init_queues(struct ath_softc *sc)
for (i = 0; i < WME_NUM_AC; i++) {
sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
sc->tx.txq_map[i]->mac80211_qnum = i;
sc->tx.txq_max_pending[i] = ATH_MAX_QDEPTH;
}
return 0;
}
@ -558,7 +559,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
spin_lock_init(&sc->debug.samp_lock);
#endif
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
(unsigned long)sc);
INIT_WORK(&sc->hw_reset_work, ath_reset_work);
@ -713,6 +714,24 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
#ifdef CONFIG_PM_SLEEP
if ((ah->caps.hw_caps & ATH9K_HW_WOW_DEVICE_CAPABLE) &&
device_can_wakeup(sc->dev)) {
hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT;
hw->wiphy->wowlan.n_patterns = MAX_NUM_USER_PATTERN;
hw->wiphy->wowlan.pattern_min_len = 1;
hw->wiphy->wowlan.pattern_max_len = MAX_PATTERN_SIZE;
}
atomic_set(&sc->wow_sleep_proc_intr, -1);
atomic_set(&sc->wow_got_bmiss_intr, -1);
#endif
hw->queues = 4;
hw->max_rates = 4;
hw->channel_change_time = 5000;

View file

@ -50,8 +50,7 @@ void ath_tx_complete_poll_work(struct work_struct *work)
if (needreset) {
ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
"tx hung, resetting the chip\n");
RESET_STAT_INC(sc, RESET_TYPE_TX_HANG);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
ath9k_queue_reset(sc, RESET_TYPE_TX_HANG);
return;
}
@ -69,6 +68,7 @@ void ath_hw_check(struct work_struct *work)
unsigned long flags;
int busy;
u8 is_alive, nbeacon = 1;
enum ath_reset_type type;
ath9k_ps_wakeup(sc);
is_alive = ath9k_hw_check_alive(sc->sc_ah);
@ -78,7 +78,7 @@ void ath_hw_check(struct work_struct *work)
else if (!is_alive && AR_SREV_9300(sc->sc_ah)) {
ath_dbg(common, RESET,
"DCU stuck is detected. Schedule chip reset\n");
RESET_STAT_INC(sc, RESET_TYPE_MAC_HANG);
type = RESET_TYPE_MAC_HANG;
goto sched_reset;
}
@ -90,7 +90,7 @@ void ath_hw_check(struct work_struct *work)
busy, sc->hw_busy_count + 1);
if (busy >= 99) {
if (++sc->hw_busy_count >= 3) {
RESET_STAT_INC(sc, RESET_TYPE_BB_HANG);
type = RESET_TYPE_BB_HANG;
goto sched_reset;
}
} else if (busy >= 0) {
@ -102,7 +102,7 @@ void ath_hw_check(struct work_struct *work)
goto out;
sched_reset:
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
ath9k_queue_reset(sc, type);
out:
ath9k_ps_restore(sc);
}
@ -119,8 +119,7 @@ static bool ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
count++;
if (count == 3) {
ath_dbg(common, RESET, "PLL WAR, resetting the chip\n");
RESET_STAT_INC(sc, RESET_TYPE_PLL_HANG);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
ath9k_queue_reset(sc, RESET_TYPE_PLL_HANG);
count = 0;
return true;
}
@ -432,26 +431,72 @@ void ath_ani_calibrate(unsigned long data)
}
}
void ath_start_ani(struct ath_common *common)
void ath_start_ani(struct ath_softc *sc)
{
struct ath_hw *ah = common->ah;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
unsigned long timestamp = jiffies_to_msecs(jiffies);
struct ath_softc *sc = (struct ath_softc *) common->priv;
if (!test_bit(SC_OP_ANI_RUN, &sc->sc_flags))
return;
if (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
if (common->disable_ani ||
!test_bit(SC_OP_ANI_RUN, &sc->sc_flags) ||
(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
return;
common->ani.longcal_timer = timestamp;
common->ani.shortcal_timer = timestamp;
common->ani.checkani_timer = timestamp;
ath_dbg(common, ANI, "Starting ANI\n");
mod_timer(&common->ani.timer,
jiffies + msecs_to_jiffies((u32)ah->config.ani_poll_interval));
}
void ath_stop_ani(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
ath_dbg(common, ANI, "Stopping ANI\n");
del_timer_sync(&common->ani.timer);
}
void ath_check_ani(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
/*
* Check for the various conditions in which ANI has to
* be stopped.
*/
if (ah->opmode == NL80211_IFTYPE_ADHOC) {
if (!cur_conf->enable_beacon)
goto stop_ani;
} else if (ah->opmode == NL80211_IFTYPE_AP) {
if (!cur_conf->enable_beacon) {
/*
* Disable ANI only when there are no
* associated stations.
*/
if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
goto stop_ani;
}
} else if (ah->opmode == NL80211_IFTYPE_STATION) {
if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
goto stop_ani;
}
if (!test_bit(SC_OP_ANI_RUN, &sc->sc_flags)) {
set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
ath_start_ani(sc);
}
return;
stop_ani:
clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
ath_stop_ani(sc);
}
void ath_update_survey_nf(struct ath_softc *sc, int channel)
{
struct ath_hw *ah = sc->sc_ah;

View file

@ -19,6 +19,9 @@
#include "ath9k.h"
#include "btcoex.h"
static void ath9k_set_assoc_state(struct ath_softc *sc,
struct ieee80211_vif *vif);
u8 ath9k_parse_mpdudensity(u8 mpdudensity)
{
/*
@ -167,8 +170,6 @@ static void ath_cancel_work(struct ath_softc *sc)
static void ath_restart_work(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9485(sc->sc_ah) ||
@ -177,21 +178,18 @@ static void ath_restart_work(struct ath_softc *sc)
msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
ath_start_rx_poll(sc, 3);
if (!common->disable_ani)
ath_start_ani(common);
ath_start_ani(sc);
}
static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
bool ret = true;
ieee80211_stop_queues(sc->hw);
sc->hw_busy_count = 0;
del_timer_sync(&common->ani.timer);
ath_stop_ani(sc);
del_timer_sync(&sc->rx_poll_timer);
ath9k_debug_samp_bb_mac(sc);
@ -236,7 +234,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
if (!test_bit(SC_OP_BEACONS, &sc->sc_flags))
goto work;
ath_set_beacon(sc);
ath9k_set_beacon(sc);
if (ah->opmode == NL80211_IFTYPE_STATION &&
test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
@ -365,6 +363,7 @@ void ath9k_tasklet(unsigned long data)
struct ath_softc *sc = (struct ath_softc *)data;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
enum ath_reset_type type;
unsigned long flags;
u32 status = sc->intrstatus;
u32 rxmask;
@ -374,18 +373,13 @@ void ath9k_tasklet(unsigned long data)
if ((status & ATH9K_INT_FATAL) ||
(status & ATH9K_INT_BB_WATCHDOG)) {
#ifdef CONFIG_ATH9K_DEBUGFS
enum ath_reset_type type;
if (status & ATH9K_INT_FATAL)
type = RESET_TYPE_FATAL_INT;
else
type = RESET_TYPE_BB_WATCHDOG;
RESET_STAT_INC(sc, type);
#endif
set_bit(SC_OP_HW_RESET, &sc->sc_flags);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
ath9k_queue_reset(sc, type);
goto out;
}
@ -493,6 +487,17 @@ irqreturn_t ath_isr(int irq, void *dev)
if (status & SCHED_INTR)
sched = true;
#ifdef CONFIG_PM_SLEEP
if (status & ATH9K_INT_BMISS) {
if (atomic_read(&sc->wow_sleep_proc_intr) == 0) {
ath_dbg(common, ANY, "during WoW we got a BMISS\n");
atomic_inc(&sc->wow_got_bmiss_intr);
atomic_dec(&sc->wow_sleep_proc_intr);
}
ath_dbg(common, INTERRUPT, "beacon miss interrupt\n");
}
#endif
/*
* If a FATAL or RXORN interrupt is received, we have to reset the
* chip immediately.
@ -575,6 +580,15 @@ static int ath_reset(struct ath_softc *sc, bool retry_tx)
return r;
}
void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type)
{
#ifdef CONFIG_ATH9K_DEBUGFS
RESET_STAT_INC(sc, type);
#endif
set_bit(SC_OP_HW_RESET, &sc->sc_flags);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
}
void ath_reset_work(struct work_struct *work)
{
struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
@ -841,16 +855,6 @@ bool ath9k_uses_beacons(int type)
}
}
static void ath9k_reclaim_beacon(struct ath_softc *sc,
struct ieee80211_vif *vif)
{
struct ath_vif *avp = (void *)vif->drv_priv;
ath9k_set_beaconing_status(sc, false);
ath_beacon_return(sc, avp);
ath9k_set_beaconing_status(sc, true);
}
static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{
struct ath9k_vif_iter_data *iter_data = data;
@ -882,6 +886,18 @@ static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
}
}
static void ath9k_sta_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{
struct ath_softc *sc = data;
struct ath_vif *avp = (void *)vif->drv_priv;
if (vif->type != NL80211_IFTYPE_STATION)
return;
if (avp->primary_sta_vif)
ath9k_set_assoc_state(sc, vif);
}
/* Called with sc->mutex held. */
void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@ -915,21 +931,18 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_vif_iter_data iter_data;
enum nl80211_iftype old_opmode = ah->opmode;
ath9k_calculate_iter_data(hw, vif, &iter_data);
/* Set BSSID mask. */
memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
ath_hw_setbssidmask(common);
/* Set op-mode & TSF */
if (iter_data.naps > 0) {
ath9k_hw_set_tsfadjust(ah, 1);
set_bit(SC_OP_TSF_RESET, &sc->sc_flags);
ath9k_hw_set_tsfadjust(ah, true);
ah->opmode = NL80211_IFTYPE_AP;
} else {
ath9k_hw_set_tsfadjust(ah, 0);
clear_bit(SC_OP_TSF_RESET, &sc->sc_flags);
ath9k_hw_set_tsfadjust(ah, false);
if (iter_data.nmeshes)
ah->opmode = NL80211_IFTYPE_MESH_POINT;
@ -941,9 +954,8 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
ah->opmode = NL80211_IFTYPE_STATION;
}
/*
* Enable MIB interrupts when there are hardware phy counters.
*/
ath9k_hw_setopmode(ah);
if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0)
ah->imask |= ATH9K_INT_TSFOOR;
else
@ -951,34 +963,15 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
ath9k_hw_set_interrupts(ah);
/* Set up ANI */
if (iter_data.naps > 0) {
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
if (!common->disable_ani) {
set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
ath_start_ani(common);
}
} else {
clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
del_timer_sync(&common->ani.timer);
}
}
/* Called with sc->mutex held, vif counts set up properly. */
static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath_softc *sc = hw->priv;
ath9k_calculate_summary_state(hw, vif);
if (ath9k_uses_beacons(vif->type)) {
/* Reserve a beacon slot for the vif */
ath9k_set_beaconing_status(sc, false);
ath_beacon_alloc(sc, vif);
ath9k_set_beaconing_status(sc, true);
/*
* If we are changing the opmode to STATION,
* a beacon sync needs to be done.
*/
if (ah->opmode == NL80211_IFTYPE_STATION &&
old_opmode == NL80211_IFTYPE_AP &&
test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
ieee80211_iterate_active_interfaces_atomic(sc->hw,
ath9k_sta_vif_iter, sc);
}
}
@ -1021,7 +1014,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
sc->nvifs++;
ath9k_do_vif_add_setup(hw, vif);
ath9k_calculate_summary_state(hw, vif);
if (ath9k_uses_beacons(vif->type))
ath9k_beacon_assign_slot(sc, vif);
out:
mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
@ -1038,6 +1034,7 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
int ret = 0;
ath_dbg(common, CONFIG, "Change Interface\n");
mutex_lock(&sc->mutex);
ath9k_ps_wakeup(sc);
@ -1050,15 +1047,16 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
}
}
/* Clean up old vif stuff */
if (ath9k_uses_beacons(vif->type))
ath9k_reclaim_beacon(sc, vif);
ath9k_beacon_remove_slot(sc, vif);
/* Add new settings */
vif->type = new_type;
vif->p2p = p2p;
ath9k_do_vif_add_setup(hw, vif);
ath9k_calculate_summary_state(hw, vif);
if (ath9k_uses_beacons(vif->type))
ath9k_beacon_assign_slot(sc, vif);
out:
ath9k_ps_restore(sc);
mutex_unlock(&sc->mutex);
@ -1078,9 +1076,8 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
sc->nvifs--;
/* Reclaim beacon resources */
if (ath9k_uses_beacons(vif->type))
ath9k_reclaim_beacon(sc, vif);
ath9k_beacon_remove_slot(sc, vif);
ath9k_calculate_summary_state(hw, NULL);
@ -1377,21 +1374,18 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw,
qi.tqi_aifs = params->aifs;
qi.tqi_cwmin = params->cw_min;
qi.tqi_cwmax = params->cw_max;
qi.tqi_burstTime = params->txop;
qi.tqi_burstTime = params->txop * 32;
ath_dbg(common, CONFIG,
"Configure tx [queue/halq] [%d/%d], aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
queue, txq->axq_qnum, params->aifs, params->cw_min,
params->cw_max, params->txop);
ath_update_max_aggr_framelen(sc, queue, qi.tqi_burstTime);
ret = ath_txq_update(sc, txq->axq_qnum, &qi);
if (ret)
ath_err(common, "TXQ Update failed\n");
if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)
if (queue == WME_AC_BE && !ret)
ath_beaconq_config(sc);
mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
@ -1460,86 +1454,53 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
return ret;
}
static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
static void ath9k_set_assoc_state(struct ath_softc *sc,
struct ieee80211_vif *vif)
{
struct ath_softc *sc = data;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
struct ath_vif *avp = (void *)vif->drv_priv;
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
unsigned long flags;
set_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags);
avp->primary_sta_vif = true;
/*
* Skip iteration if primary station vif's bss info
* was not changed
* Set the AID, BSSID and do beacon-sync only when
* the HW opmode is STATION.
*
* But the primary bit is set above in any case.
*/
if (test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
return;
if (bss_conf->assoc) {
set_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags);
avp->primary_sta_vif = true;
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
common->curaid = bss_conf->aid;
ath9k_hw_write_associd(sc->sc_ah);
ath_dbg(common, CONFIG, "Bss Info ASSOC %d, bssid: %pM\n",
bss_conf->aid, common->curbssid);
ath_beacon_config(sc, vif);
/*
* Request a re-configuration of Beacon related timers
* on the receipt of the first Beacon frame (i.e.,
* after time sync with the AP).
*/
spin_lock_irqsave(&sc->sc_pm_lock, flags);
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
/* Reset rssi stats */
sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
ath_start_rx_poll(sc, 3);
if (!common->disable_ani) {
set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
ath_start_ani(common);
}
}
}
static void ath9k_config_bss(struct ath_softc *sc, struct ieee80211_vif *vif)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
struct ath_vif *avp = (void *)vif->drv_priv;
if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
return;
/* Reconfigure bss info */
if (avp->primary_sta_vif && !bss_conf->assoc) {
ath_dbg(common, CONFIG, "Bss Info DISASSOC %d, bssid %pM\n",
common->curaid, common->curbssid);
clear_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags);
clear_bit(SC_OP_BEACONS, &sc->sc_flags);
avp->primary_sta_vif = false;
memset(common->curbssid, 0, ETH_ALEN);
common->curaid = 0;
}
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
common->curaid = bss_conf->aid;
ath9k_hw_write_associd(sc->sc_ah);
ieee80211_iterate_active_interfaces_atomic(
sc->hw, ath9k_bss_iter, sc);
sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
/*
* None of station vifs are associated.
* Clear bssid & aid
*/
if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
ath9k_hw_write_associd(sc->sc_ah);
clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
del_timer_sync(&common->ani.timer);
del_timer_sync(&sc->rx_poll_timer);
memset(&sc->caldata, 0, sizeof(sc->caldata));
}
spin_lock_irqsave(&sc->sc_pm_lock, flags);
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
ath_dbg(common, CONFIG,
"Primary Station interface: %pM, BSSID: %pM\n",
vif->addr, common->curbssid);
}
static void ath9k_bss_assoc_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
{
struct ath_softc *sc = data;
struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
if (test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags))
return;
if (bss_conf->assoc)
ath9k_set_assoc_state(sc, vif);
}
static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
@ -1547,6 +1508,11 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *bss_conf,
u32 changed)
{
#define CHECK_ANI \
(BSS_CHANGED_ASSOC | \
BSS_CHANGED_IBSS | \
BSS_CHANGED_BEACON_ENABLED)
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
@ -1557,53 +1523,41 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
mutex_lock(&sc->mutex);
if (changed & BSS_CHANGED_ASSOC) {
ath9k_config_bss(sc, vif);
ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",
bss_conf->bssid, bss_conf->assoc);
ath_dbg(common, CONFIG, "BSSID: %pM aid: 0x%x\n",
common->curbssid, common->curaid);
}
if (avp->primary_sta_vif && !bss_conf->assoc) {
clear_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags);
avp->primary_sta_vif = false;
if (changed & BSS_CHANGED_IBSS) {
/* There can be only one vif available */
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
common->curaid = bss_conf->aid;
ath9k_hw_write_associd(sc->sc_ah);
if (ah->opmode == NL80211_IFTYPE_STATION)
clear_bit(SC_OP_BEACONS, &sc->sc_flags);
}
if (bss_conf->ibss_joined) {
sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
ieee80211_iterate_active_interfaces_atomic(sc->hw,
ath9k_bss_assoc_iter, sc);
if (!common->disable_ani) {
set_bit(SC_OP_ANI_RUN, &sc->sc_flags);
ath_start_ani(common);
}
} else {
clear_bit(SC_OP_ANI_RUN, &sc->sc_flags);
del_timer_sync(&common->ani.timer);
del_timer_sync(&sc->rx_poll_timer);
if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags) &&
ah->opmode == NL80211_IFTYPE_STATION) {
memset(common->curbssid, 0, ETH_ALEN);
common->curaid = 0;
ath9k_hw_write_associd(sc->sc_ah);
}
}
/*
* In case of AP mode, the HW TSF has to be reset
* when the beacon interval changes.
*/
if ((changed & BSS_CHANGED_BEACON_INT) &&
(vif->type == NL80211_IFTYPE_AP))
set_bit(SC_OP_TSF_RESET, &sc->sc_flags);
if (changed & BSS_CHANGED_IBSS) {
memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
common->curaid = bss_conf->aid;
ath9k_hw_write_associd(sc->sc_ah);
}
/* Configure beaconing (AP, IBSS, MESH) */
if (ath9k_uses_beacons(vif->type) &&
((changed & BSS_CHANGED_BEACON) ||
(changed & BSS_CHANGED_BEACON_ENABLED) ||
(changed & BSS_CHANGED_BEACON_INT))) {
ath9k_set_beaconing_status(sc, false);
if (bss_conf->enable_beacon)
ath_beacon_alloc(sc, vif);
else
avp->is_bslot_active = false;
ath_beacon_config(sc, vif);
ath9k_set_beaconing_status(sc, true);
if ((changed & BSS_CHANGED_BEACON_ENABLED) ||
(changed & BSS_CHANGED_BEACON_INT)) {
if (ah->opmode == NL80211_IFTYPE_AP &&
bss_conf->enable_beacon)
ath9k_set_tsfadjust(sc, vif);
if (ath9k_allow_beacon_config(sc, vif))
ath9k_beacon_config(sc, vif, changed);
}
if (changed & BSS_CHANGED_ERP_SLOT) {
@ -1625,8 +1579,13 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
}
}
if (changed & CHECK_ANI)
ath_check_ani(sc);
mutex_unlock(&sc->mutex);
ath9k_ps_restore(sc);
#undef CHECK_ANI
}
static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
@ -1855,10 +1814,11 @@ static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
if (!vif)
return 0;
avp = (void *)vif->drv_priv;
if (!avp->is_bslot_active)
if (!vif->bss_conf.enable_beacon)
return 0;
avp = (void *)vif->drv_priv;
if (!sc->beacon.tx_processed && !edma) {
tasklet_disable(&sc->bcon_tasklet);
@ -1912,12 +1872,29 @@ static u32 fill_chainmask(u32 cap, u32 new)
return filled;
}
static bool validate_antenna_mask(struct ath_hw *ah, u32 val)
{
switch (val & 0x7) {
case 0x1:
case 0x3:
case 0x7:
return true;
case 0x2:
return (ah->caps.rx_chainmask == 1);
default:
return false;
}
}
static int ath9k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
if (!rx_ant || !tx_ant)
if (ah->caps.rx_chainmask != 1)
rx_ant |= tx_ant;
if (!validate_antenna_mask(ah, rx_ant) || !tx_ant)
return -EINVAL;
sc->ant_rx = rx_ant;
@ -2075,6 +2052,362 @@ static void ath9k_get_et_stats(struct ieee80211_hw *hw,
#endif
#ifdef CONFIG_PM_SLEEP
static void ath9k_wow_map_triggers(struct ath_softc *sc,
struct cfg80211_wowlan *wowlan,
u32 *wow_triggers)
{
if (wowlan->disconnect)
*wow_triggers |= AH_WOW_LINK_CHANGE |
AH_WOW_BEACON_MISS;
if (wowlan->magic_pkt)
*wow_triggers |= AH_WOW_MAGIC_PATTERN_EN;
if (wowlan->n_patterns)
*wow_triggers |= AH_WOW_USER_PATTERN_EN;
sc->wow_enabled = *wow_triggers;
}
static void ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_hw_capabilities *pcaps = &ah->caps;
int pattern_count = 0;
int i, byte_cnt;
u8 dis_deauth_pattern[MAX_PATTERN_SIZE];
u8 dis_deauth_mask[MAX_PATTERN_SIZE];
memset(dis_deauth_pattern, 0, MAX_PATTERN_SIZE);
memset(dis_deauth_mask, 0, MAX_PATTERN_SIZE);
/*
* Create Dissassociate / Deauthenticate packet filter
*
* 2 bytes 2 byte 6 bytes 6 bytes 6 bytes
* +--------------+----------+---------+--------+--------+----
* + Frame Control+ Duration + DA + SA + BSSID +
* +--------------+----------+---------+--------+--------+----
*
* The above is the management frame format for disassociate/
* deauthenticate pattern, from this we need to match the first byte
* of 'Frame Control' and DA, SA, and BSSID fields
* (skipping 2nd byte of FC and Duration feild.
*
* Disassociate pattern
* --------------------
* Frame control = 00 00 1010
* DA, SA, BSSID = x:x:x:x:x:x
* Pattern will be A0000000 | x:x:x:x:x:x | x:x:x:x:x:x
* | x:x:x:x:x:x -- 22 bytes
*
* Deauthenticate pattern
* ----------------------
* Frame control = 00 00 1100
* DA, SA, BSSID = x:x:x:x:x:x
* Pattern will be C0000000 | x:x:x:x:x:x | x:x:x:x:x:x
* | x:x:x:x:x:x -- 22 bytes
*/
/* Create Disassociate Pattern first */
byte_cnt = 0;
/* Fill out the mask with all FF's */
for (i = 0; i < MAX_PATTERN_MASK_SIZE; i++)
dis_deauth_mask[i] = 0xff;
/* copy the first byte of frame control field */
dis_deauth_pattern[byte_cnt] = 0xa0;
byte_cnt++;
/* skip 2nd byte of frame control and Duration field */
byte_cnt += 3;
/*
* need not match the destination mac address, it can be a broadcast
* mac address or an unicast to this station
*/
byte_cnt += 6;
/* copy the source mac address */
memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN);
byte_cnt += 6;
/* copy the bssid, its same as the source mac address */
memcpy((dis_deauth_pattern + byte_cnt), common->curbssid, ETH_ALEN);
/* Create Disassociate pattern mask */
if (pcaps->hw_caps & ATH9K_HW_WOW_PATTERN_MATCH_EXACT) {
if (pcaps->hw_caps & ATH9K_HW_WOW_PATTERN_MATCH_DWORD) {
/*
* for AR9280, because of hardware limitation, the
* first 4 bytes have to be matched for all patterns.
* the mask for disassociation and de-auth pattern
* matching need to enable the first 4 bytes.
* also the duration field needs to be filled.
*/
dis_deauth_mask[0] = 0xf0;
/*
* fill in duration field
FIXME: what is the exact value ?
*/
dis_deauth_pattern[2] = 0xff;
dis_deauth_pattern[3] = 0xff;
} else {
dis_deauth_mask[0] = 0xfe;
}
dis_deauth_mask[1] = 0x03;
dis_deauth_mask[2] = 0xc0;
} else {
dis_deauth_mask[0] = 0xef;
dis_deauth_mask[1] = 0x3f;
dis_deauth_mask[2] = 0x00;
dis_deauth_mask[3] = 0xfc;
}
ath_dbg(common, WOW, "Adding disassoc/deauth patterns for WoW\n");
ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask,
pattern_count, byte_cnt);
pattern_count++;
/*
* for de-authenticate pattern, only the first byte of the frame
* control field gets changed from 0xA0 to 0xC0
*/
dis_deauth_pattern[0] = 0xC0;
ath9k_hw_wow_apply_pattern(ah, dis_deauth_pattern, dis_deauth_mask,
pattern_count, byte_cnt);
}
static void ath9k_wow_add_pattern(struct ath_softc *sc,
struct cfg80211_wowlan *wowlan)
{
struct ath_hw *ah = sc->sc_ah;
struct ath9k_wow_pattern *wow_pattern = NULL;
struct cfg80211_wowlan_trig_pkt_pattern *patterns = wowlan->patterns;
int mask_len;
s8 i = 0;
if (!wowlan->n_patterns)
return;
/*
* Add the new user configured patterns
*/
for (i = 0; i < wowlan->n_patterns; i++) {
wow_pattern = kzalloc(sizeof(*wow_pattern), GFP_KERNEL);
if (!wow_pattern)
return;
/*
* TODO: convert the generic user space pattern to
* appropriate chip specific/802.11 pattern.
*/
mask_len = DIV_ROUND_UP(wowlan->patterns[i].pattern_len, 8);
memset(wow_pattern->pattern_bytes, 0, MAX_PATTERN_SIZE);
memset(wow_pattern->mask_bytes, 0, MAX_PATTERN_SIZE);
memcpy(wow_pattern->pattern_bytes, patterns[i].pattern,
patterns[i].pattern_len);
memcpy(wow_pattern->mask_bytes, patterns[i].mask, mask_len);
wow_pattern->pattern_len = patterns[i].pattern_len;
/*
* just need to take care of deauth and disssoc pattern,
* make sure we don't overwrite them.
*/
ath9k_hw_wow_apply_pattern(ah, wow_pattern->pattern_bytes,
wow_pattern->mask_bytes,
i + 2,
wow_pattern->pattern_len);
kfree(wow_pattern);
}
}
static int ath9k_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wowlan)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
u32 wow_triggers_enabled = 0;
int ret = 0;
mutex_lock(&sc->mutex);
ath_cancel_work(sc);
del_timer_sync(&common->ani.timer);
del_timer_sync(&sc->rx_poll_timer);
if (test_bit(SC_OP_INVALID, &sc->sc_flags)) {
ath_dbg(common, ANY, "Device not present\n");
ret = -EINVAL;
goto fail_wow;
}
if (WARN_ON(!wowlan)) {
ath_dbg(common, WOW, "None of the WoW triggers enabled\n");
ret = -EINVAL;
goto fail_wow;
}
if (!device_can_wakeup(sc->dev)) {
ath_dbg(common, WOW, "device_can_wakeup failed, WoW is not enabled\n");
ret = 1;
goto fail_wow;
}
/*
* none of the sta vifs are associated
* and we are not currently handling multivif
* cases, for instance we have to seperately
* configure 'keep alive frame' for each
* STA.
*/
if (!test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
ath_dbg(common, WOW, "None of the STA vifs are associated\n");
ret = 1;
goto fail_wow;
}
if (sc->nvifs > 1) {
ath_dbg(common, WOW, "WoW for multivif is not yet supported\n");
ret = 1;
goto fail_wow;
}
ath9k_wow_map_triggers(sc, wowlan, &wow_triggers_enabled);
ath_dbg(common, WOW, "WoW triggers enabled 0x%x\n",
wow_triggers_enabled);
ath9k_ps_wakeup(sc);
ath9k_stop_btcoex(sc);
/*
* Enable wake up on recieving disassoc/deauth
* frame by default.
*/
ath9k_wow_add_disassoc_deauth_pattern(sc);
if (wow_triggers_enabled & AH_WOW_USER_PATTERN_EN)
ath9k_wow_add_pattern(sc, wowlan);
spin_lock_bh(&sc->sc_pcu_lock);
/*
* To avoid false wake, we enable beacon miss interrupt only
* when we go to sleep. We save the current interrupt mask
* so we can restore it after the system wakes up
*/
sc->wow_intr_before_sleep = ah->imask;
ah->imask &= ~ATH9K_INT_GLOBAL;
ath9k_hw_disable_interrupts(ah);
ah->imask = ATH9K_INT_BMISS | ATH9K_INT_GLOBAL;
ath9k_hw_set_interrupts(ah);
ath9k_hw_enable_interrupts(ah);
spin_unlock_bh(&sc->sc_pcu_lock);
/*
* we can now sync irq and kill any running tasklets, since we already
* disabled interrupts and not holding a spin lock
*/
synchronize_irq(sc->irq);
tasklet_kill(&sc->intr_tq);
ath9k_hw_wow_enable(ah, wow_triggers_enabled);
ath9k_ps_restore(sc);
ath_dbg(common, ANY, "WoW enabled in ath9k\n");
atomic_inc(&sc->wow_sleep_proc_intr);
fail_wow:
mutex_unlock(&sc->mutex);
return ret;
}
static int ath9k_resume(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
u32 wow_status;
mutex_lock(&sc->mutex);
ath9k_ps_wakeup(sc);
spin_lock_bh(&sc->sc_pcu_lock);
ath9k_hw_disable_interrupts(ah);
ah->imask = sc->wow_intr_before_sleep;
ath9k_hw_set_interrupts(ah);
ath9k_hw_enable_interrupts(ah);
spin_unlock_bh(&sc->sc_pcu_lock);
wow_status = ath9k_hw_wow_wakeup(ah);
if (atomic_read(&sc->wow_got_bmiss_intr) == 0) {
/*
* some devices may not pick beacon miss
* as the reason they woke up so we add
* that here for that shortcoming.
*/
wow_status |= AH_WOW_BEACON_MISS;
atomic_dec(&sc->wow_got_bmiss_intr);
ath_dbg(common, ANY, "Beacon miss interrupt picked up during WoW sleep\n");
}
atomic_dec(&sc->wow_sleep_proc_intr);
if (wow_status) {
ath_dbg(common, ANY, "Waking up due to WoW triggers %s with WoW status = %x\n",
ath9k_hw_wow_event_to_string(wow_status), wow_status);
}
ath_restart_work(sc);
ath9k_start_btcoex(sc);
ath9k_ps_restore(sc);
mutex_unlock(&sc->mutex);
return 0;
}
static void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled)
{
struct ath_softc *sc = hw->priv;
mutex_lock(&sc->mutex);
device_init_wakeup(sc->dev, 1);
device_set_wakeup_enable(sc->dev, enabled);
mutex_unlock(&sc->mutex);
}
#endif
struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx,
.start = ath9k_start,
@ -2104,6 +2437,12 @@ struct ieee80211_ops ath9k_ops = {
.set_antenna = ath9k_set_antenna,
.get_antenna = ath9k_get_antenna,
#ifdef CONFIG_PM_SLEEP
.suspend = ath9k_suspend,
.resume = ath9k_resume,
.set_wakeup = ath9k_set_wakeup,
#endif
#ifdef CONFIG_ATH9K_DEBUGFS
.get_et_sset_count = ath9k_get_et_sset_count,
.get_et_stats = ath9k_get_et_stats,

View file

@ -202,7 +202,7 @@ static void ath_mci_cal_msg(struct ath_softc *sc, u8 opcode, u8 *rx_payload)
case MCI_GPM_BT_CAL_REQ:
if (mci_hw->bt_state == MCI_BT_AWAKE) {
ar9003_mci_state(ah, MCI_STATE_SET_BT_CAL_START);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
ath9k_queue_reset(sc, RESET_TYPE_MCI);
}
ath_dbg(common, MCI, "MCI State : %d\n", mci_hw->bt_state);
break;

View file

@ -313,6 +313,9 @@ static int ath_pci_suspend(struct device *device)
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ath_softc *sc = hw->priv;
if (sc->wow_enabled)
return 0;
/* The device has to be moved to FULLSLEEP forcibly.
* Otherwise the chip never moved to full sleep,
* when no interface is up.

View file

@ -553,7 +553,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
sc->ps_flags &= ~PS_BEACON_SYNC;
ath_dbg(common, PS,
"Reconfigure Beacon timers based on timestamp from the AP\n");
ath_set_beacon(sc);
ath9k_set_beacon(sc);
}
if (ath_beacon_dtim_pending_cab(skb)) {

View file

@ -696,9 +696,12 @@
#define AR_WA_BIT7 (1 << 7)
#define AR_WA_BIT23 (1 << 23)
#define AR_WA_D3_L1_DISABLE (1 << 14)
#define AR_WA_UNTIE_RESET_EN (1 << 15) /* Enable PCI Reset
to POR (power-on-reset) */
#define AR_WA_D3_TO_L1_DISABLE_REAL (1 << 16)
#define AR_WA_ASPM_TIMER_BASED_DISABLE (1 << 17)
#define AR_WA_RESET_EN (1 << 18) /* Sw Control to enable PCI-Reset to POR (bit 15) */
#define AR_WA_RESET_EN (1 << 18) /* Enable PCI-Reset to
POR (bit 15) */
#define AR_WA_ANALOG_SHIFT (1 << 20)
#define AR_WA_POR_SHORT (1 << 21) /* PCI-E Phy reset control */
#define AR_WA_BIT22 (1 << 22)
@ -1032,6 +1035,8 @@ enum {
#define AR_PCIE_PM_CTRL (AR_SREV_9340(ah) ? 0x4004 : 0x4014)
#define AR_PCIE_PM_CTRL_ENA 0x00080000
#define AR_PCIE_PHY_REG3 0x18c08
#define AR_NUM_GPIO 14
#define AR928X_NUM_GPIO 10
#define AR9285_NUM_GPIO 12
@ -1235,6 +1240,8 @@ enum {
#define AR_RTC_PLL_CLKSEL 0x00000300
#define AR_RTC_PLL_CLKSEL_S 8
#define AR_RTC_PLL_BYPASS 0x00010000
#define AR_RTC_PLL_NOPWD 0x00040000
#define AR_RTC_PLL_NOPWD_S 18
#define PLL3 0x16188
#define PLL3_DO_MEAS_MASK 0x40000000
@ -1887,6 +1894,8 @@ enum {
#define AR_PCU_MISC_MODE2_HWWAR2 0x02000000
#define AR_PCU_MISC_MODE2_RESERVED2 0xFFFE0000
#define AR_PCU_MISC_MODE3 0x83d0
#define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358
#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400
#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000
@ -1909,6 +1918,140 @@ enum {
#define AR_RATE_DURATION_32 0x8780
#define AR_RATE_DURATION(_n) (AR_RATE_DURATION_0 + ((_n)<<2))
/* WoW - Wake On Wireless */
#define AR_PMCTRL_AUX_PWR_DET 0x10000000 /* Puts Chip in L2 state */
#define AR_PMCTRL_D3COLD_VAUX 0x00800000
#define AR_PMCTRL_HOST_PME_EN 0x00400000 /* Send OOB WAKE_L on WoW
event */
#define AR_PMCTRL_WOW_PME_CLR 0x00200000 /* Clear WoW event */
#define AR_PMCTRL_PWR_STATE_MASK 0x0f000000 /* Power State Mask */
#define AR_PMCTRL_PWR_STATE_D1D3 0x0f000000 /* Activate D1 and D3 */
#define AR_PMCTRL_PWR_STATE_D1D3_REAL 0x0f000000 /* Activate D1 and D3 */
#define AR_PMCTRL_PWR_STATE_D0 0x08000000 /* Activate D0 */
#define AR_PMCTRL_PWR_PM_CTRL_ENA 0x00008000 /* Enable power mgmt */
#define AR_WOW_BEACON_TIMO_MAX 0xffffffff
/*
* MAC WoW Registers
*/
#define AR_WOW_PATTERN 0x825C
#define AR_WOW_COUNT 0x8260
#define AR_WOW_BCN_EN 0x8270
#define AR_WOW_BCN_TIMO 0x8274
#define AR_WOW_KEEP_ALIVE_TIMO 0x8278
#define AR_WOW_KEEP_ALIVE 0x827c
#define AR_WOW_US_SCALAR 0x8284
#define AR_WOW_KEEP_ALIVE_DELAY 0x8288
#define AR_WOW_PATTERN_MATCH 0x828c
#define AR_WOW_PATTERN_OFF1 0x8290 /* pattern bytes 0 -> 3 */
#define AR_WOW_PATTERN_OFF2 0x8294 /* pattern bytes 4 -> 7 */
/* for AR9285 or later version of chips */
#define AR_WOW_EXACT 0x829c
#define AR_WOW_LENGTH1 0x8360
#define AR_WOW_LENGTH2 0X8364
/* register to enable match for less than 256 bytes packets */
#define AR_WOW_PATTERN_MATCH_LT_256B 0x8368
#define AR_SW_WOW_CONTROL 0x20018
#define AR_SW_WOW_ENABLE 0x1
#define AR_SWITCH_TO_REFCLK 0x2
#define AR_RESET_CONTROL 0x4
#define AR_RESET_VALUE_MASK 0x8
#define AR_HW_WOW_DISABLE 0x10
#define AR_CLR_MAC_INTERRUPT 0x20
#define AR_CLR_KA_INTERRUPT 0x40
/* AR_WOW_PATTERN register values */
#define AR_WOW_BACK_OFF_SHIFT(x) ((x & 0xf) << 28) /* in usecs */
#define AR_WOW_MAC_INTR_EN 0x00040000
#define AR_WOW_MAGIC_EN 0x00010000
#define AR_WOW_PATTERN_EN(x) (x & 0xff)
#define AR_WOW_PAT_FOUND_SHIFT 8
#define AR_WOW_PATTERN_FOUND(x) (x & (0xff << AR_WOW_PAT_FOUND_SHIFT))
#define AR_WOW_PATTERN_FOUND_MASK ((0xff) << AR_WOW_PAT_FOUND_SHIFT)
#define AR_WOW_MAGIC_PAT_FOUND 0x00020000
#define AR_WOW_MAC_INTR 0x00080000
#define AR_WOW_KEEP_ALIVE_FAIL 0x00100000
#define AR_WOW_BEACON_FAIL 0x00200000
#define AR_WOW_STATUS(x) (x & (AR_WOW_PATTERN_FOUND_MASK | \
AR_WOW_MAGIC_PAT_FOUND | \
AR_WOW_KEEP_ALIVE_FAIL | \
AR_WOW_BEACON_FAIL))
#define AR_WOW_CLEAR_EVENTS(x) (x & ~(AR_WOW_PATTERN_EN(0xff) | \
AR_WOW_MAGIC_EN | \
AR_WOW_MAC_INTR_EN | \
AR_WOW_BEACON_FAIL | \
AR_WOW_KEEP_ALIVE_FAIL))
/* AR_WOW_COUNT register values */
#define AR_WOW_AIFS_CNT(x) (x & 0xff)
#define AR_WOW_SLOT_CNT(x) ((x & 0xff) << 8)
#define AR_WOW_KEEP_ALIVE_CNT(x) ((x & 0xff) << 16)
/* AR_WOW_BCN_EN register */
#define AR_WOW_BEACON_FAIL_EN 0x00000001
/* AR_WOW_BCN_TIMO rgister */
#define AR_WOW_BEACON_TIMO 0x40000000 /* valid if BCN_EN is set */
/* AR_WOW_KEEP_ALIVE_TIMO register */
#define AR_WOW_KEEP_ALIVE_TIMO_VALUE
#define AR_WOW_KEEP_ALIVE_NEVER 0xffffffff
/* AR_WOW_KEEP_ALIVE register */
#define AR_WOW_KEEP_ALIVE_AUTO_DIS 0x00000001
#define AR_WOW_KEEP_ALIVE_FAIL_DIS 0x00000002
/* AR_WOW_KEEP_ALIVE_DELAY register */
#define AR_WOW_KEEP_ALIVE_DELAY_VALUE 0x000003e8 /* 1 msec */
/*
* keep it long for beacon workaround - ensure no false alarm
*/
#define AR_WOW_BMISSTHRESHOLD 0x20
/* AR_WOW_PATTERN_MATCH register */
#define AR_WOW_PAT_END_OF_PKT(x) (x & 0xf)
#define AR_WOW_PAT_OFF_MATCH(x) ((x & 0xf) << 8)
/*
* default values for Wow Configuration for backoff, aifs, slot, keep-alive
* to be programmed into various registers.
*/
#define AR_WOW_PAT_BACKOFF 0x00000004 /* AR_WOW_PATTERN_REG */
#define AR_WOW_CNT_AIFS_CNT 0x00000022 /* AR_WOW_COUNT_REG */
#define AR_WOW_CNT_SLOT_CNT 0x00000009 /* AR_WOW_COUNT_REG */
/*
* Keepalive count applicable for AR9280 2.0 and above.
*/
#define AR_WOW_CNT_KA_CNT 0x00000008 /* AR_WOW_COUNT register */
/* WoW - Transmit buffer for keep alive frames */
#define AR_WOW_TRANSMIT_BUFFER 0xe000 /* E000 - EFFC */
#define AR_WOW_TXBUF(i) (AR_WOW_TRANSMIT_BUFFER + ((i) << 2))
#define AR_WOW_KA_DESC_WORD2 0xe000
#define AR_WOW_KA_DATA_WORD0 0xe030
/* WoW Transmit Buffer for patterns */
#define AR_WOW_TB_PATTERN(i) (0xe100 + (i << 8))
#define AR_WOW_TB_MASK(i) (0xec00 + (i << 5))
/* Currently Pattern 0-7 are supported - so bit 0-7 are set */
#define AR_WOW_PATTERN_SUPPORTED 0xff
#define AR_WOW_LENGTH_MAX 0xff
#define AR_WOW_LEN1_SHIFT(_i) ((0x3 - ((_i) & 0x3)) << 0x3)
#define AR_WOW_LENGTH1_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN1_SHIFT(_i))
#define AR_WOW_LEN2_SHIFT(_i) ((0x7 - ((_i) & 0x7)) << 0x3)
#define AR_WOW_LENGTH2_MASK(_i) (AR_WOW_LENGTH_MAX << AR_WOW_LEN2_SHIFT(_i))
#define AR9271_CORE_CLOCK 117 /* clock to 117Mhz */
#define AR9271_TARGET_BAUD_RATE 19200 /* 115200 */

View file

@ -0,0 +1,532 @@
/*
* Copyright (c) 2012 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/export.h>
#include "ath9k.h"
#include "reg.h"
#include "hw-ops.h"
const char *ath9k_hw_wow_event_to_string(u32 wow_event)
{
if (wow_event & AH_WOW_MAGIC_PATTERN_EN)
return "Magic pattern";
if (wow_event & AH_WOW_USER_PATTERN_EN)
return "User pattern";
if (wow_event & AH_WOW_LINK_CHANGE)
return "Link change";
if (wow_event & AH_WOW_BEACON_MISS)
return "Beacon miss";
return "unknown reason";
}
EXPORT_SYMBOL(ath9k_hw_wow_event_to_string);
static void ath9k_hw_config_serdes_wow_sleep(struct ath_hw *ah)
{
int i;
for (i = 0; i < ah->iniPcieSerdesWow.ia_rows; i++)
REG_WRITE(ah, INI_RA(&ah->iniPcieSerdesWow, i, 0),
INI_RA(&ah->iniPcieSerdesWow, i, 1));
usleep_range(1000, 1500);
}
static void ath9k_hw_set_powermode_wow_sleep(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
/* set rx disable bit */
REG_WRITE(ah, AR_CR, AR_CR_RXD);
if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0, AH_WAIT_TIMEOUT)) {
ath_err(common, "Failed to stop Rx DMA in 10ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW));
return;
} else {
if (!AR_SREV_9300_20_OR_LATER(ah))
REG_WRITE(ah, AR_RXDP, 0x0);
}
/* AR9280 WoW has sleep issue, do not set it to sleep */
if (AR_SREV_9280_20(ah))
return;
REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_ON_INT);
}
static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
u8 sta_mac_addr[ETH_ALEN], ap_mac_addr[ETH_ALEN];
u32 ctl[13] = {0};
u32 data_word[KAL_NUM_DATA_WORDS];
u8 i;
u32 wow_ka_data_word0;
memcpy(sta_mac_addr, common->macaddr, ETH_ALEN);
memcpy(ap_mac_addr, common->curbssid, ETH_ALEN);
/* set the transmit buffer */
ctl[0] = (KAL_FRAME_LEN | (MAX_RATE_POWER << 16));
if (!(AR_SREV_9300_20_OR_LATER(ah)))
ctl[0] += (KAL_ANTENNA_MODE << 25);
ctl[1] = 0;
ctl[3] = 0xb; /* OFDM_6M hardware value for this rate */
ctl[4] = 0;
ctl[7] = (ah->txchainmask) << 2;
if (AR_SREV_9300_20_OR_LATER(ah))
ctl[2] = 0xf << 16; /* tx_tries 0 */
else
ctl[2] = 0x7 << 16; /* tx_tries 0 */
for (i = 0; i < KAL_NUM_DESC_WORDS; i++)
REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]);
/* for AR9300 family 13 descriptor words */
if (AR_SREV_9300_20_OR_LATER(ah))
REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + i * 4), ctl[i]);
data_word[0] = (KAL_FRAME_TYPE << 2) | (KAL_FRAME_SUB_TYPE << 4) |
(KAL_TO_DS << 8) | (KAL_DURATION_ID << 16);
data_word[1] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) |
(ap_mac_addr[1] << 8) | (ap_mac_addr[0]);
data_word[2] = (sta_mac_addr[1] << 24) | (sta_mac_addr[0] << 16) |
(ap_mac_addr[5] << 8) | (ap_mac_addr[4]);
data_word[3] = (sta_mac_addr[5] << 24) | (sta_mac_addr[4] << 16) |
(sta_mac_addr[3] << 8) | (sta_mac_addr[2]);
data_word[4] = (ap_mac_addr[3] << 24) | (ap_mac_addr[2] << 16) |
(ap_mac_addr[1] << 8) | (ap_mac_addr[0]);
data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]);
if (AR_SREV_9462_20_OR_LATER(ah)) {
/* AR9462 2.0 has an extra descriptor word (time based
* discard) compared to other chips */
REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0);
wow_ka_data_word0 = AR_WOW_TXBUF(13);
} else {
wow_ka_data_word0 = AR_WOW_TXBUF(12);
}
for (i = 0; i < KAL_NUM_DATA_WORDS; i++)
REG_WRITE(ah, (wow_ka_data_word0 + i*4), data_word[i]);
}
void ath9k_hw_wow_apply_pattern(struct ath_hw *ah, u8 *user_pattern,
u8 *user_mask, int pattern_count,
int pattern_len)
{
int i;
u32 pattern_val, mask_val;
u32 set, clr;
/* FIXME: should check count by querying the hardware capability */
if (pattern_count >= MAX_NUM_PATTERN)
return;
REG_SET_BIT(ah, AR_WOW_PATTERN, BIT(pattern_count));
/* set the registers for pattern */
for (i = 0; i < MAX_PATTERN_SIZE; i += 4) {
memcpy(&pattern_val, user_pattern, 4);
REG_WRITE(ah, (AR_WOW_TB_PATTERN(pattern_count) + i),
pattern_val);
user_pattern += 4;
}
/* set the registers for mask */
for (i = 0; i < MAX_PATTERN_MASK_SIZE; i += 4) {
memcpy(&mask_val, user_mask, 4);
REG_WRITE(ah, (AR_WOW_TB_MASK(pattern_count) + i), mask_val);
user_mask += 4;
}
/* set the pattern length to be matched
*
* AR_WOW_LENGTH1_REG1
* bit 31:24 pattern 0 length
* bit 23:16 pattern 1 length
* bit 15:8 pattern 2 length
* bit 7:0 pattern 3 length
*
* AR_WOW_LENGTH1_REG2
* bit 31:24 pattern 4 length
* bit 23:16 pattern 5 length
* bit 15:8 pattern 6 length
* bit 7:0 pattern 7 length
*
* the below logic writes out the new
* pattern length for the corresponding
* pattern_count, while masking out the
* other fields
*/
ah->wow_event_mask |= BIT(pattern_count + AR_WOW_PAT_FOUND_SHIFT);
if (!AR_SREV_9285_12_OR_LATER(ah))
return;
if (pattern_count < 4) {
/* Pattern 0-3 uses AR_WOW_LENGTH1 register */
set = (pattern_len & AR_WOW_LENGTH_MAX) <<
AR_WOW_LEN1_SHIFT(pattern_count);
clr = AR_WOW_LENGTH1_MASK(pattern_count);
REG_RMW(ah, AR_WOW_LENGTH1, set, clr);
} else {
/* Pattern 4-7 uses AR_WOW_LENGTH2 register */
set = (pattern_len & AR_WOW_LENGTH_MAX) <<
AR_WOW_LEN2_SHIFT(pattern_count);
clr = AR_WOW_LENGTH2_MASK(pattern_count);
REG_RMW(ah, AR_WOW_LENGTH2, set, clr);
}
}
EXPORT_SYMBOL(ath9k_hw_wow_apply_pattern);
u32 ath9k_hw_wow_wakeup(struct ath_hw *ah)
{
u32 wow_status = 0;
u32 val = 0, rval;
/*
* read the WoW status register to know
* the wakeup reason
*/
rval = REG_READ(ah, AR_WOW_PATTERN);
val = AR_WOW_STATUS(rval);
/*
* mask only the WoW events that we have enabled. Sometimes
* we have spurious WoW events from the AR_WOW_PATTERN
* register. This mask will clean it up.
*/
val &= ah->wow_event_mask;
if (val) {
if (val & AR_WOW_MAGIC_PAT_FOUND)
wow_status |= AH_WOW_MAGIC_PATTERN_EN;
if (AR_WOW_PATTERN_FOUND(val))
wow_status |= AH_WOW_USER_PATTERN_EN;
if (val & AR_WOW_KEEP_ALIVE_FAIL)
wow_status |= AH_WOW_LINK_CHANGE;
if (val & AR_WOW_BEACON_FAIL)
wow_status |= AH_WOW_BEACON_MISS;
}
/*
* set and clear WOW_PME_CLEAR registers for the chip to
* generate next wow signal.
* disable D3 before accessing other registers ?
*/
/* do we need to check the bit value 0x01000000 (7-10) ?? */
REG_RMW(ah, AR_PCIE_PM_CTRL, AR_PMCTRL_WOW_PME_CLR,
AR_PMCTRL_PWR_STATE_D1D3);
/*
* clear all events
*/
REG_WRITE(ah, AR_WOW_PATTERN,
AR_WOW_CLEAR_EVENTS(REG_READ(ah, AR_WOW_PATTERN)));
/*
* tie reset register for AR9002 family of chipsets
* NB: not tieing it back might have some repurcussions.
*/
if (!AR_SREV_9300_20_OR_LATER(ah)) {
REG_SET_BIT(ah, AR_WA, AR_WA_UNTIE_RESET_EN |
AR_WA_POR_SHORT | AR_WA_RESET_EN);
}
/*
* restore the beacon threshold to init value
*/
REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR);
/*
* Restore the way the PCI-E reset, Power-On-Reset, external
* PCIE_POR_SHORT pins are tied to its original value.
* Previously just before WoW sleep, we untie the PCI-E
* reset to our Chip's Power On Reset so that any PCI-E
* reset from the bus will not reset our chip
*/
if (AR_SREV_9280_20_OR_LATER(ah) && ah->is_pciexpress)
ath9k_hw_configpcipowersave(ah, false);
ah->wow_event_mask = 0;
return wow_status;
}
EXPORT_SYMBOL(ath9k_hw_wow_wakeup);
void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable)
{
u32 wow_event_mask;
u32 set, clr;
/*
* wow_event_mask is a mask to the AR_WOW_PATTERN register to
* indicate which WoW events we have enabled. The WoW events
* are from the 'pattern_enable' in this function and
* 'pattern_count' of ath9k_hw_wow_apply_pattern()
*/
wow_event_mask = ah->wow_event_mask;
/*
* Untie Power-on-Reset from the PCI-E-Reset. When we are in
* WOW sleep, we do want the Reset from the PCI-E to disturb
* our hw state
*/
if (ah->is_pciexpress) {
/*
* we need to untie the internal POR (power-on-reset)
* to the external PCI-E reset. We also need to tie
* the PCI-E Phy reset to the PCI-E reset.
*/
if (AR_SREV_9300_20_OR_LATER(ah)) {
set = AR_WA_RESET_EN | AR_WA_POR_SHORT;
clr = AR_WA_UNTIE_RESET_EN | AR_WA_D3_L1_DISABLE;
REG_RMW(ah, AR_WA, set, clr);
} else {
if (AR_SREV_9285(ah) || AR_SREV_9287(ah))
set = AR9285_WA_DEFAULT;
else
set = AR9280_WA_DEFAULT;
/*
* In AR9280 and AR9285, bit 14 in WA register
* (disable L1) should only be set when device
* enters D3 state and be cleared when device
* comes back to D0
*/
if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE)
set |= AR_WA_D3_L1_DISABLE;
clr = AR_WA_UNTIE_RESET_EN;
set |= AR_WA_RESET_EN | AR_WA_POR_SHORT;
REG_RMW(ah, AR_WA, set, clr);
/*
* for WoW sleep, we reprogram the SerDes so that the
* PLL and CLK REQ are both enabled. This uses more
* power but otherwise WoW sleep is unstable and the
* chip may disappear.
*/
if (AR_SREV_9285_12_OR_LATER(ah))
ath9k_hw_config_serdes_wow_sleep(ah);
}
}
/*
* set the power states appropriately and enable PME
*/
set = AR_PMCTRL_HOST_PME_EN | AR_PMCTRL_PWR_PM_CTRL_ENA |
AR_PMCTRL_AUX_PWR_DET | AR_PMCTRL_WOW_PME_CLR;
/*
* set and clear WOW_PME_CLEAR registers for the chip
* to generate next wow signal.
*/
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set);
clr = AR_PMCTRL_WOW_PME_CLR;
REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr);
/*
* Setup for:
* - beacon misses
* - magic pattern
* - keep alive timeout
* - pattern matching
*/
/*
* Program default values for pattern backoff, aifs/slot/KAL count,
* beacon miss timeout, KAL timeout, etc.
*/
set = AR_WOW_BACK_OFF_SHIFT(AR_WOW_PAT_BACKOFF);
REG_SET_BIT(ah, AR_WOW_PATTERN, set);
set = AR_WOW_AIFS_CNT(AR_WOW_CNT_AIFS_CNT) |
AR_WOW_SLOT_CNT(AR_WOW_CNT_SLOT_CNT) |
AR_WOW_KEEP_ALIVE_CNT(AR_WOW_CNT_KA_CNT);
REG_SET_BIT(ah, AR_WOW_COUNT, set);
if (pattern_enable & AH_WOW_BEACON_MISS)
set = AR_WOW_BEACON_TIMO;
/* We are not using beacon miss, program a large value */
else
set = AR_WOW_BEACON_TIMO_MAX;
REG_WRITE(ah, AR_WOW_BCN_TIMO, set);
/*
* Keep alive timo in ms except AR9280
*/
if (!pattern_enable || AR_SREV_9280(ah))
set = AR_WOW_KEEP_ALIVE_NEVER;
else
set = KAL_TIMEOUT * 32;
REG_WRITE(ah, AR_WOW_KEEP_ALIVE_TIMO, set);
/*
* Keep alive delay in us. based on 'power on clock',
* therefore in usec
*/
set = KAL_DELAY * 1000;
REG_WRITE(ah, AR_WOW_KEEP_ALIVE_DELAY, set);
/*
* Create keep alive pattern to respond to beacons
*/
ath9k_wow_create_keep_alive_pattern(ah);
/*
* Configure MAC WoW Registers
*/
set = 0;
/* Send keep alive timeouts anyway */
clr = AR_WOW_KEEP_ALIVE_AUTO_DIS;
if (pattern_enable & AH_WOW_LINK_CHANGE)
wow_event_mask |= AR_WOW_KEEP_ALIVE_FAIL;
else
set = AR_WOW_KEEP_ALIVE_FAIL_DIS;
/*
* FIXME: For now disable keep alive frame
* failure. This seems to sometimes trigger
* unnecessary wake up with AR9485 chipsets.
*/
set = AR_WOW_KEEP_ALIVE_FAIL_DIS;
REG_RMW(ah, AR_WOW_KEEP_ALIVE, set, clr);
/*
* we are relying on a bmiss failure. ensure we have
* enough threshold to prevent false positives
*/
REG_RMW_FIELD(ah, AR_RSSI_THR, AR_RSSI_THR_BM_THR,
AR_WOW_BMISSTHRESHOLD);
set = 0;
clr = 0;
if (pattern_enable & AH_WOW_BEACON_MISS) {
set = AR_WOW_BEACON_FAIL_EN;
wow_event_mask |= AR_WOW_BEACON_FAIL;
} else {
clr = AR_WOW_BEACON_FAIL_EN;
}
REG_RMW(ah, AR_WOW_BCN_EN, set, clr);
set = 0;
clr = 0;
/*
* Enable the magic packet registers
*/
if (pattern_enable & AH_WOW_MAGIC_PATTERN_EN) {
set = AR_WOW_MAGIC_EN;
wow_event_mask |= AR_WOW_MAGIC_PAT_FOUND;
} else {
clr = AR_WOW_MAGIC_EN;
}
set |= AR_WOW_MAC_INTR_EN;
REG_RMW(ah, AR_WOW_PATTERN, set, clr);
/*
* For AR9285 and later version of chipsets
* enable WoW pattern match for packets less
* than 256 bytes for all patterns
*/
if (AR_SREV_9285_12_OR_LATER(ah))
REG_WRITE(ah, AR_WOW_PATTERN_MATCH_LT_256B,
AR_WOW_PATTERN_SUPPORTED);
/*
* Set the power states appropriately and enable PME
*/
clr = 0;
set = AR_PMCTRL_PWR_STATE_D1D3 | AR_PMCTRL_HOST_PME_EN |
AR_PMCTRL_PWR_PM_CTRL_ENA;
/*
* This is needed for AR9300 chipsets to wake-up
* the host.
*/
if (AR_SREV_9300_20_OR_LATER(ah))
clr = AR_PCIE_PM_CTRL_ENA;
REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr);
if (AR_SREV_9462(ah)) {
/*
* this is needed to prevent the chip waking up
* the host within 3-4 seconds with certain
* platform/BIOS. The fix is to enable
* D1 & D3 to match original definition and
* also match the OTP value. Anyway this
* is more related to SW WOW.
*/
clr = AR_PMCTRL_PWR_STATE_D1D3;
REG_CLR_BIT(ah, AR_PCIE_PM_CTRL, clr);
set = AR_PMCTRL_PWR_STATE_D1D3_REAL;
REG_SET_BIT(ah, AR_PCIE_PM_CTRL, set);
}
REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PRESERVE_SEQNUM);
if (AR_SREV_9300_20_OR_LATER(ah)) {
/* to bring down WOW power low margin */
set = BIT(13);
REG_SET_BIT(ah, AR_PCIE_PHY_REG3, set);
/* HW WoW */
clr = BIT(5);
REG_CLR_BIT(ah, AR_PCU_MISC_MODE3, clr);
}
ath9k_hw_set_powermode_wow_sleep(ah);
ah->wow_event_mask = wow_event_mask;
}
EXPORT_SYMBOL(ath9k_hw_wow_enable);

View file

@ -29,6 +29,8 @@
#define HT_LTF(_ns) (4 * (_ns))
#define SYMBOL_TIME(_ns) ((_ns) << 2) /* ns * 4 us */
#define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5) /* ns * 3.6 us */
#define TIME_SYMBOLS(t) ((t) >> 2)
#define TIME_SYMBOLS_HALFGI(t) (((t) * 5 - 4) / 18)
#define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2)
#define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18)
@ -74,33 +76,6 @@ enum {
MCS_HT40_SGI,
};
static int ath_max_4ms_framelen[4][32] = {
[MCS_HT20] = {
3212, 6432, 9648, 12864, 19300, 25736, 28952, 32172,
6424, 12852, 19280, 25708, 38568, 51424, 57852, 64280,
9628, 19260, 28896, 38528, 57792, 65532, 65532, 65532,
12828, 25656, 38488, 51320, 65532, 65532, 65532, 65532,
},
[MCS_HT20_SGI] = {
3572, 7144, 10720, 14296, 21444, 28596, 32172, 35744,
7140, 14284, 21428, 28568, 42856, 57144, 64288, 65532,
10700, 21408, 32112, 42816, 64228, 65532, 65532, 65532,
14256, 28516, 42780, 57040, 65532, 65532, 65532, 65532,
},
[MCS_HT40] = {
6680, 13360, 20044, 26724, 40092, 53456, 60140, 65532,
13348, 26700, 40052, 53400, 65532, 65532, 65532, 65532,
20004, 40008, 60016, 65532, 65532, 65532, 65532, 65532,
26644, 53292, 65532, 65532, 65532, 65532, 65532, 65532,
},
[MCS_HT40_SGI] = {
7420, 14844, 22272, 29696, 44544, 59396, 65532, 65532,
14832, 29668, 44504, 59340, 65532, 65532, 65532, 65532,
22232, 44464, 65532, 65532, 65532, 65532, 65532, 65532,
29616, 59232, 65532, 65532, 65532, 65532, 65532, 65532,
}
};
/*********************/
/* Aggregation logic */
/*********************/
@ -614,10 +589,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
rcu_read_unlock();
if (needreset) {
RESET_STAT_INC(sc, RESET_TYPE_TX_ERROR);
ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
}
if (needreset)
ath9k_queue_reset(sc, RESET_TYPE_TX_ERROR);
}
static bool ath_lookup_legacy(struct ath_buf *bf)
@ -650,6 +623,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
struct ieee80211_tx_rate *rates;
u32 max_4ms_framelen, frmlen;
u16 aggr_limit, bt_aggr_limit, legacy = 0;
int q = tid->ac->txq->mac80211_qnum;
int i;
skb = bf->bf_mpdu;
@ -658,8 +632,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
/*
* Find the lowest frame length among the rate series that will have a
* 4ms transmit duration.
* TODO - TXOP limit needs to be considered.
* 4ms (or TXOP limited) transmit duration.
*/
max_4ms_framelen = ATH_AMPDU_LIMIT_MAX;
@ -682,7 +655,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
modeidx++;
frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx];
frmlen = sc->tx.max_aggr_framelen[q][modeidx][rates[i].idx];
max_4ms_framelen = min(max_4ms_framelen, frmlen);
}
@ -929,6 +902,44 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, int pktlen,
return duration;
}
static int ath_max_framelen(int usec, int mcs, bool ht40, bool sgi)
{
int streams = HT_RC_2_STREAMS(mcs);
int symbols, bits;
int bytes = 0;
symbols = sgi ? TIME_SYMBOLS_HALFGI(usec) : TIME_SYMBOLS(usec);
bits = symbols * bits_per_symbol[mcs % 8][ht40] * streams;
bits -= OFDM_PLCP_BITS;
bytes = bits / 8;
bytes -= L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
if (bytes > 65532)
bytes = 65532;
return bytes;
}
void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop)
{
u16 *cur_ht20, *cur_ht20_sgi, *cur_ht40, *cur_ht40_sgi;
int mcs;
/* 4ms is the default (and maximum) duration */
if (!txop || txop > 4096)
txop = 4096;
cur_ht20 = sc->tx.max_aggr_framelen[queue][MCS_HT20];
cur_ht20_sgi = sc->tx.max_aggr_framelen[queue][MCS_HT20_SGI];
cur_ht40 = sc->tx.max_aggr_framelen[queue][MCS_HT40];
cur_ht40_sgi = sc->tx.max_aggr_framelen[queue][MCS_HT40_SGI];
for (mcs = 0; mcs < 32; mcs++) {
cur_ht20[mcs] = ath_max_framelen(txop, mcs, false, false);
cur_ht20_sgi[mcs] = ath_max_framelen(txop, mcs, false, true);
cur_ht40[mcs] = ath_max_framelen(txop, mcs, true, false);
cur_ht40_sgi[mcs] = ath_max_framelen(txop, mcs, true, true);
}
}
static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_info *info, int len)
{
@ -1403,16 +1414,6 @@ int ath_txq_update(struct ath_softc *sc, int qnum,
int error = 0;
struct ath9k_tx_queue_info qi;
if (qnum == sc->beacon.beaconq) {
/*
* XXX: for beacon queue, we just save the parameter.
* It will be picked up by ath_beaconq_config when
* it's necessary.
*/
sc->beacon.beacon_qi = *qinfo;
return 0;
}
BUG_ON(sc->tx.txq[qnum].axq_qnum != qnum);
ath9k_hw_get_txq_props(ah, qnum, &qi);
@ -1586,7 +1587,8 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
struct ath_atx_ac *ac, *ac_tmp, *last_ac;
struct ath_atx_tid *tid, *last_tid;
if (work_pending(&sc->hw_reset_work) || list_empty(&txq->axq_acq) ||
if (test_bit(SC_OP_HW_RESET, &sc->sc_flags) ||
list_empty(&txq->axq_acq) ||
txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
return;
@ -1988,7 +1990,8 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
ath_txq_lock(sc, txq);
if (txq == sc->tx.txq_map[q] &&
++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
++txq->pending_frames > sc->tx.txq_max_pending[q] &&
!txq->stopped) {
ieee80211_stop_queue(sc->hw, q);
txq->stopped = true;
}
@ -2047,7 +2050,8 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
if (WARN_ON(--txq->pending_frames < 0))
txq->pending_frames = 0;
if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
if (txq->stopped &&
txq->pending_frames < sc->tx.txq_max_pending[q]) {
ieee80211_wake_queue(sc->hw, q);
txq->stopped = false;
}
@ -2191,7 +2195,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
ath_txq_lock(sc, txq);
for (;;) {
if (work_pending(&sc->hw_reset_work))
if (test_bit(SC_OP_HW_RESET, &sc->sc_flags))
break;
if (list_empty(&txq->axq_q)) {
@ -2274,7 +2278,7 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
int status;
for (;;) {
if (work_pending(&sc->hw_reset_work))
if (test_bit(SC_OP_HW_RESET, &sc->sc_flags))
break;
status = ath9k_hw_txprocdesc(ah, NULL, (void *)&ts);

View file

@ -870,13 +870,6 @@ struct b43_wl {
* handler, only. This basically is just the IRQ mask register. */
spinlock_t hardirq_lock;
/* The number of queues that were registered with the mac80211 subsystem
* initially. This is a backup copy of hw->queues in case hw->queues has
* to be dynamically lowered at runtime (Firmware does not support QoS).
* hw->queues has to be restored to the original value before unregistering
* from the mac80211 subsystem. */
u16 mac80211_initially_registered_queues;
/* Set this if we call ieee80211_register_hw() and check if we call
* ieee80211_unregister_hw(). */
bool hw_registred;

View file

@ -2359,6 +2359,8 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx)
if (err)
goto err_load;
fw->opensource = (ctx->req_type == B43_FWTYPE_OPENSOURCE);
return 0;
err_no_ucode:
@ -2434,6 +2436,10 @@ static void b43_request_firmware(struct work_struct *work)
goto out;
start_ieee80211:
wl->hw->queues = B43_QOS_QUEUE_NUM;
if (!modparam_qos || dev->fw.opensource)
wl->hw->queues = 1;
err = ieee80211_register_hw(wl->hw);
if (err)
goto err_one_core_detach;
@ -2537,11 +2543,9 @@ static int b43_upload_microcode(struct b43_wldev *dev)
dev->fw.hdr_format = B43_FW_HDR_410;
else
dev->fw.hdr_format = B43_FW_HDR_351;
dev->fw.opensource = (fwdate == 0xFFFF);
WARN_ON(dev->fw.opensource != (fwdate == 0xFFFF));
/* Default to use-all-queues. */
dev->wl->hw->queues = dev->wl->mac80211_initially_registered_queues;
dev->qos_enabled = !!modparam_qos;
dev->qos_enabled = dev->wl->hw->queues > 1;
/* Default to firmware/hardware crypto acceleration. */
dev->hwcrypto_enabled = true;
@ -2559,14 +2563,8 @@ static int b43_upload_microcode(struct b43_wldev *dev)
/* Disable hardware crypto and fall back to software crypto. */
dev->hwcrypto_enabled = false;
}
if (!(fwcapa & B43_FWCAPA_QOS)) {
b43info(dev->wl, "QoS not supported by firmware\n");
/* Disable QoS. Tweak hw->queues to 1. It will be restored before
* ieee80211_unregister to make sure the networking core can
* properly free possible resources. */
dev->wl->hw->queues = 1;
dev->qos_enabled = false;
}
/* adding QoS support should use an offline discovery mechanism */
WARN(fwcapa & B43_FWCAPA_QOS, "QoS in OpenFW not supported\n");
} else {
b43info(dev->wl, "Loading firmware version %u.%u "
"(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n",
@ -5298,8 +5296,6 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
hw->queues = modparam_qos ? B43_QOS_QUEUE_NUM : 1;
wl->mac80211_initially_registered_queues = hw->queues;
wl->hw_registred = false;
hw->max_rates = 2;
SET_IEEE80211_DEV(hw, dev->dev);
@ -5374,10 +5370,6 @@ static void b43_bcma_remove(struct bcma_device *core)
B43_WARN_ON(!wl);
if (wl->current_dev == wldev && wl->hw_registred) {
/* Restore the queues count before unregistering, because firmware detect
* might have modified it. Restoring is important, so the networking
* stack can properly free resources. */
wl->hw->queues = wl->mac80211_initially_registered_queues;
b43_leds_stop(wldev);
ieee80211_unregister_hw(wl->hw);
}
@ -5452,10 +5444,6 @@ static void b43_ssb_remove(struct ssb_device *sdev)
B43_WARN_ON(!wl);
if (wl->current_dev == wldev && wl->hw_registred) {
/* Restore the queues count before unregistering, because firmware detect
* might have modified it. Restoring is important, so the networking
* stack can properly free resources. */
wl->hw->queues = wl->mac80211_initially_registered_queues;
b43_leds_stop(wldev);
ieee80211_unregister_hw(wl->hw);
}

View file

@ -663,7 +663,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
u32 uninitialized_var(macstat);
u16 chanid;
u16 phytype;
int padding;
int padding, rate_idx;
memset(&status, 0, sizeof(status));
@ -766,16 +766,17 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
}
if (phystat0 & B43_RX_PHYST0_OFDM)
status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
phytype == B43_PHYTYPE_A);
else
status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
if (unlikely(status.rate_idx == -1)) {
rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
if (unlikely(rate_idx == -1)) {
/* PLCP seems to be corrupted.
* Drop the frame, if we are not interested in corrupted frames. */
if (!(dev->wl->filter_flags & FIF_PLCPFAIL))
goto drop;
}
status.rate_idx = rate_idx;
status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
/*

View file

@ -691,9 +691,10 @@ __brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
}
static s32
brcmf_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
brcmf_cfg80211_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request)
{
struct net_device *ndev = request->wdev->netdev;
s32 err = 0;
WL_TRACE("Enter\n");
@ -919,9 +920,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
set_bit(WL_STATUS_CONNECTING, &cfg_priv->status);
if (params->bssid)
WL_CONN("BSSID: %02X %02X %02X %02X %02X %02X\n",
params->bssid[0], params->bssid[1], params->bssid[2],
params->bssid[3], params->bssid[4], params->bssid[5]);
WL_CONN("BSSID: %pM\n", params->bssid);
else
WL_CONN("No BSSID specified\n");

View file

@ -663,9 +663,6 @@ brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
/* patch the first MPDU */
if (count == 1) {
u8 plcp0, plcp3, is40, sgi;
struct ieee80211_sta *sta;
sta = tx_info->control.sta;
if (rr) {
plcp0 = plcp[0];
@ -1195,8 +1192,8 @@ static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a)
bool rc;
rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL ||
tx_info->control.sta == ampdu_pars->sta);
rc = rc && (tx_info->rate_driver_data[0] == NULL || ampdu_pars->sta == NULL ||
tx_info->rate_driver_data[0] == ampdu_pars->sta);
rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
return rc;
}
@ -1210,8 +1207,8 @@ static void dma_cb_fn_ampdu(void *txi, void *arg_a)
struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
(tx_info->control.sta == sta || sta == NULL))
tx_info->control.sta = NULL;
(tx_info->rate_driver_data[0] == sta || sta == NULL))
tx_info->rate_driver_data[0] = NULL;
}
/*

View file

@ -267,6 +267,7 @@ static void brcms_set_basic_rate(struct brcm_rateset *rs, u16 rate, bool is_br)
static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct brcms_info *wl = hw->priv;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
spin_lock_bh(&wl->lock);
if (!wl->pub->up) {
@ -275,6 +276,7 @@ static void brcms_ops_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
goto done;
}
brcms_c_sendpkt_mac80211(wl->wlc, skb, hw);
tx_info->rate_driver_data[0] = tx_info->control.sta;
done:
spin_unlock_bh(&wl->lock);
}

View file

@ -893,7 +893,7 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs)
tx_info = IEEE80211_SKB_CB(p);
h = (struct ieee80211_hdr *)((u8 *) (txh + 1) + D11_PHY_HDR_LEN);
if (tx_info->control.sta)
if (tx_info->rate_driver_data[0])
scb = &wlc->pri_scb;
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {

View file

@ -5359,7 +5359,7 @@ il_mac_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
if (changes & BSS_CHANGED_ASSOC) {
D_MAC80211("ASSOC %d\n", bss_conf->assoc);
if (bss_conf->assoc) {
il->timestamp = bss_conf->last_tsf;
il->timestamp = bss_conf->sync_tsf;
if (!il_is_rfkill(il))
il->ops->post_associate(il);

View file

@ -1905,6 +1905,7 @@ struct iwl_bt_cmd {
#define IWLAGN_BT_PRIO_BOOST_MAX 0xFF
#define IWLAGN_BT_PRIO_BOOST_MIN 0x00
#define IWLAGN_BT_PRIO_BOOST_DEFAULT 0xF0
#define IWLAGN_BT_PRIO_BOOST_DEFAULT32 0xF0F0F0F0
#define IWLAGN_BT_MAX_KILL_DEFAULT 5

View file

@ -265,6 +265,8 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
bt_cmd_v2.tx_prio_boost = 0;
bt_cmd_v2.rx_prio_boost = 0;
} else {
/* older version only has 8 bits */
WARN_ON(priv->cfg->bt_params->bt_prio_boost & ~0xFF);
bt_cmd_v1.prio_boost =
priv->cfg->bt_params->bt_prio_boost;
bt_cmd_v1.tx_prio_boost = 0;

View file

@ -1232,7 +1232,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
struct iwl_trans_config trans_cfg;
static const u8 no_reclaim_cmds[] = {
REPLY_RX_PHY_CMD,
REPLY_RX,
REPLY_RX_MPDU_CMD,
REPLY_COMPRESSED_BA,
STATISTICS_NOTIFICATION,

View file

@ -88,7 +88,6 @@ const char *iwl_dvm_cmd_strings[REPLY_MAX] = {
IWL_CMD_ENTRY(REPLY_PHY_CALIBRATION_CMD),
IWL_CMD_ENTRY(REPLY_RX_PHY_CMD),
IWL_CMD_ENTRY(REPLY_RX_MPDU_CMD),
IWL_CMD_ENTRY(REPLY_RX),
IWL_CMD_ENTRY(REPLY_COMPRESSED_BA),
IWL_CMD_ENTRY(CALIBRATION_CFG_CMD),
IWL_CMD_ENTRY(CALIBRATION_RES_NOTIFICATION),
@ -895,8 +894,7 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv,
return max_rssi - agc - IWLAGN_RSSI_OFFSET;
}
/* Called for REPLY_RX (legacy ABG frames), or
* REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
/* Called for REPLY_RX_MPDU_CMD */
static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd)
@ -911,37 +909,17 @@ static int iwlagn_rx_reply_rx(struct iwl_priv *priv,
u32 ampdu_status;
u32 rate_n_flags;
/**
* REPLY_RX and REPLY_RX_MPDU_CMD are handled differently.
* REPLY_RX: physical layer info is in this buffer
* REPLY_RX_MPDU_CMD: physical layer info was sent in separate
* command and cached in priv->last_phy_res
*
* Here we set up local variables depending on which command is
* received.
*/
if (pkt->hdr.cmd == REPLY_RX) {
phy_res = (struct iwl_rx_phy_res *)pkt->data;
header = (struct ieee80211_hdr *)(pkt->data + sizeof(*phy_res)
+ phy_res->cfg_phy_cnt);
len = le16_to_cpu(phy_res->byte_count);
rx_pkt_status = *(__le32 *)(pkt->data + sizeof(*phy_res) +
phy_res->cfg_phy_cnt + len);
ampdu_status = le32_to_cpu(rx_pkt_status);
} else {
if (!priv->last_phy_res_valid) {
IWL_ERR(priv, "MPDU frame without cached PHY data\n");
return 0;
}
phy_res = &priv->last_phy_res;
amsdu = (struct iwl_rx_mpdu_res_start *)pkt->data;
header = (struct ieee80211_hdr *)(pkt->data + sizeof(*amsdu));
len = le16_to_cpu(amsdu->byte_count);
rx_pkt_status = *(__le32 *)(pkt->data + sizeof(*amsdu) + len);
ampdu_status = iwlagn_translate_rx_status(priv,
le32_to_cpu(rx_pkt_status));
if (!priv->last_phy_res_valid) {
IWL_ERR(priv, "MPDU frame without cached PHY data\n");
return 0;
}
phy_res = &priv->last_phy_res;
amsdu = (struct iwl_rx_mpdu_res_start *)pkt->data;
header = (struct ieee80211_hdr *)(pkt->data + sizeof(*amsdu));
len = le16_to_cpu(amsdu->byte_count);
rx_pkt_status = *(__le32 *)(pkt->data + sizeof(*amsdu) + len);
ampdu_status = iwlagn_translate_rx_status(priv,
le32_to_cpu(rx_pkt_status));
if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d\n",

View file

@ -1447,7 +1447,7 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
if (changes & BSS_CHANGED_ASSOC) {
if (bss_conf->assoc) {
priv->timestamp = bss_conf->last_tsf;
priv->timestamp = bss_conf->sync_tsf;
ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
} else {
/*

View file

@ -177,7 +177,7 @@ struct iwl_base_params {
struct iwl_bt_params {
bool advanced_bt_coexist;
u8 bt_init_traffic_load;
u8 bt_prio_boost;
u32 bt_prio_boost;
u16 agg_time_limit;
bool bt_sco_disable;
bool bt_session_2;

View file

@ -458,6 +458,7 @@ struct iwl_trans {
/* The following fields are internal only */
struct kmem_cache *dev_cmd_pool;
size_t dev_cmd_headroom;
char dev_cmd_pool_name[50];
/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */

View file

@ -112,7 +112,7 @@ static const struct iwl_bt_params iwl2030_bt_params = {
.advanced_bt_coexist = true,
.agg_time_limit = BT_AGG_THRESHOLD_DEF,
.bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
.bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT,
.bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT32,
.bt_sco_disable = true,
.bt_session_2 = true,
};

View file

@ -2080,7 +2080,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
{
struct iwl_trans_pcie *trans_pcie;
struct iwl_trans *trans;
char cmd_pool_name[100];
u16 pci_cmd;
int err;
@ -2178,12 +2177,12 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
init_waitqueue_head(&trans->wait_command_queue);
spin_lock_init(&trans->reg_lock);
snprintf(cmd_pool_name, sizeof(cmd_pool_name), "iwl_cmd_pool:%s",
dev_name(trans->dev));
snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
"iwl_cmd_pool:%s", dev_name(trans->dev));
trans->dev_cmd_headroom = 0;
trans->dev_cmd_pool =
kmem_cache_create(cmd_pool_name,
kmem_cache_create(trans->dev_cmd_pool_name,
sizeof(struct iwl_device_cmd)
+ trans->dev_cmd_headroom,
sizeof(void *),

View file

@ -805,7 +805,6 @@ void lbs_scan_done(struct lbs_private *priv)
}
static int lbs_cfg_scan(struct wiphy *wiphy,
struct net_device *dev,
struct cfg80211_scan_request *request)
{
struct lbs_private *priv = wiphy_priv(wiphy);
@ -2181,13 +2180,15 @@ int lbs_reg_notifier(struct wiphy *wiphy,
struct regulatory_request *request)
{
struct lbs_private *priv = wiphy_priv(wiphy);
int ret;
int ret = 0;
lbs_deb_enter_args(LBS_DEB_CFG80211, "cfg80211 regulatory domain "
"callback for domain %c%c\n", request->alpha2[0],
request->alpha2[1]);
ret = lbs_set_11d_domain_info(priv, request, wiphy->bands);
memcpy(priv->country_code, request->alpha2, sizeof(request->alpha2));
if (lbs_iface_active(priv))
ret = lbs_set_11d_domain_info(priv);
lbs_deb_leave(LBS_DEB_CFG80211);
return ret;

View file

@ -733,15 +733,13 @@ int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf)
* to the firmware
*
* @priv: pointer to &struct lbs_private
* @request: cfg80211 regulatory request structure
* @bands: the device's supported bands and channels
*
* returns: 0 on success, error code on failure
*/
int lbs_set_11d_domain_info(struct lbs_private *priv,
struct regulatory_request *request,
struct ieee80211_supported_band **bands)
int lbs_set_11d_domain_info(struct lbs_private *priv)
{
struct wiphy *wiphy = priv->wdev->wiphy;
struct ieee80211_supported_band **bands = wiphy->bands;
struct cmd_ds_802_11d_domain_info cmd;
struct mrvl_ie_domain_param_set *domain = &cmd.domain;
struct ieee80211_country_ie_triplet *t;
@ -752,21 +750,23 @@ int lbs_set_11d_domain_info(struct lbs_private *priv,
u8 first_channel = 0, next_chan = 0, max_pwr = 0;
u8 i, flag = 0;
size_t triplet_size;
int ret;
int ret = 0;
lbs_deb_enter(LBS_DEB_11D);
if (!priv->country_code[0])
goto out;
memset(&cmd, 0, sizeof(cmd));
cmd.action = cpu_to_le16(CMD_ACT_SET);
lbs_deb_11d("Setting country code '%c%c'\n",
request->alpha2[0], request->alpha2[1]);
priv->country_code[0], priv->country_code[1]);
domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
/* Set country code */
domain->country_code[0] = request->alpha2[0];
domain->country_code[1] = request->alpha2[1];
domain->country_code[0] = priv->country_code[0];
domain->country_code[1] = priv->country_code[1];
domain->country_code[2] = ' ';
/* Now set up the channel triplets; firmware is somewhat picky here
@ -848,6 +848,7 @@ int lbs_set_11d_domain_info(struct lbs_private *priv,
ret = lbs_cmd_with_response(priv, CMD_802_11D_DOMAIN_INFO, &cmd);
out:
lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
return ret;
}
@ -1019,9 +1020,9 @@ static void lbs_submit_command(struct lbs_private *priv,
if (ret) {
netdev_info(priv->dev, "DNLD_CMD: hw_host_to_card failed: %d\n",
ret);
/* Let the timer kick in and retry, and potentially reset
the whole thing if the condition persists */
timeo = HZ/4;
/* Reset dnld state machine, report failure */
priv->dnld_sent = DNLD_RES_RECEIVED;
lbs_complete_command(priv, cmdnode, ret);
}
if (command == CMD_802_11_DEEP_SLEEP) {

View file

@ -128,9 +128,7 @@ int lbs_set_monitor_mode(struct lbs_private *priv, int enable);
int lbs_get_rssi(struct lbs_private *priv, s8 *snr, s8 *nf);
int lbs_set_11d_domain_info(struct lbs_private *priv,
struct regulatory_request *request,
struct ieee80211_supported_band **bands);
int lbs_set_11d_domain_info(struct lbs_private *priv);
int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value);

View file

@ -49,6 +49,7 @@ struct lbs_private {
bool wiphy_registered;
struct cfg80211_scan_request *scan_req;
u8 assoc_bss[ETH_ALEN];
u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
u8 disassoc_reason;
/* Mesh */

View file

@ -4,9 +4,7 @@
#include <linux/sched.h>
#include <linux/firmware.h>
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/sched.h>
#include "dev.h"
#include "decl.h"

View file

@ -309,7 +309,6 @@ static void if_usb_disconnect(struct usb_interface *intf)
cardp->surprise_removed = 1;
if (priv) {
priv->surpriseremoved = 1;
lbs_stop_card(priv);
lbs_remove_card(priv);
}

View file

@ -152,6 +152,12 @@ int lbs_start_iface(struct lbs_private *priv)
goto err;
}
ret = lbs_set_11d_domain_info(priv);
if (ret) {
lbs_deb_net("set 11d domain info failed\n");
goto err;
}
lbs_update_channel(priv);
priv->iface_running = true;

View file

@ -1540,11 +1540,6 @@ static int hwsim_tx_info_frame_received_nl(struct sk_buff *skb_2,
/* now send back TX status */
txi = IEEE80211_SKB_CB(skb);
if (txi->control.vif)
hwsim_check_magic(txi->control.vif);
if (txi->control.sta)
hwsim_check_sta_magic(txi->control.sta);
ieee80211_tx_info_clear_status(txi);
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {

View file

@ -48,10 +48,9 @@ static const struct ieee80211_iface_combination mwifiex_iface_comb_ap_sta = {
* Others -> IEEE80211_HT_PARAM_CHA_SEC_NONE
*/
static u8
mwifiex_cfg80211_channel_type_to_sec_chan_offset(enum nl80211_channel_type
channel_type)
mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type)
{
switch (channel_type) {
switch (chan_type) {
case NL80211_CHAN_NO_HT:
case NL80211_CHAN_HT20:
return IEEE80211_HT_PARAM_CHA_SEC_NONE;
@ -338,79 +337,6 @@ static int mwifiex_reg_notifier(struct wiphy *wiphy,
return 0;
}
/*
* This function sets the RF channel.
*
* This function creates multiple IOCTL requests, populates them accordingly
* and issues them to set the band/channel and frequency.
*/
static int
mwifiex_set_rf_channel(struct mwifiex_private *priv,
struct ieee80211_channel *chan,
enum nl80211_channel_type channel_type)
{
struct mwifiex_chan_freq_power cfp;
u32 config_bands = 0;
struct wiphy *wiphy = priv->wdev->wiphy;
struct mwifiex_adapter *adapter = priv->adapter;
if (chan) {
/* Set appropriate bands */
if (chan->band == IEEE80211_BAND_2GHZ) {
if (channel_type == NL80211_CHAN_NO_HT)
if (priv->adapter->config_bands == BAND_B ||
priv->adapter->config_bands == BAND_G)
config_bands =
priv->adapter->config_bands;
else
config_bands = BAND_B | BAND_G;
else
config_bands = BAND_B | BAND_G | BAND_GN;
} else {
if (channel_type == NL80211_CHAN_NO_HT)
config_bands = BAND_A;
else
config_bands = BAND_AN | BAND_A;
}
if (!((config_bands | adapter->fw_bands) &
~adapter->fw_bands)) {
adapter->config_bands = config_bands;
if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
adapter->adhoc_start_band = config_bands;
if ((config_bands & BAND_GN) ||
(config_bands & BAND_AN))
adapter->adhoc_11n_enabled = true;
else
adapter->adhoc_11n_enabled = false;
}
}
adapter->sec_chan_offset =
mwifiex_cfg80211_channel_type_to_sec_chan_offset
(channel_type);
adapter->channel_type = channel_type;
mwifiex_send_domain_info_cmd_fw(wiphy);
}
wiphy_dbg(wiphy, "info: setting band %d, chan offset %d, mode %d\n",
config_bands, adapter->sec_chan_offset, priv->bss_mode);
if (!chan)
return 0;
memset(&cfp, 0, sizeof(cfp));
cfp.freq = chan->center_freq;
cfp.channel = ieee80211_frequency_to_channel(chan->center_freq);
if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) {
if (mwifiex_bss_set_channel(priv, &cfp))
return -EFAULT;
return mwifiex_drv_change_adhoc_chan(priv, cfp.channel);
}
return 0;
}
/*
* This function sets the fragmentation threshold.
*
@ -626,7 +552,7 @@ static int
mwifiex_dump_station_info(struct mwifiex_private *priv,
struct station_info *sinfo)
{
struct mwifiex_rate_cfg rate;
u32 rate;
sinfo->filled = STATION_INFO_RX_BYTES | STATION_INFO_TX_BYTES |
STATION_INFO_RX_PACKETS | STATION_INFO_TX_PACKETS |
@ -652,9 +578,9 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
/*
* Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid
* MCS index values for us are 0 to 7.
* MCS index values for us are 0 to 15.
*/
if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 8)) {
if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) {
sinfo->txrate.mcs = priv->tx_rate;
sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
/* 40MHz rate */
@ -672,7 +598,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
sinfo->tx_packets = priv->stats.tx_packets;
sinfo->signal = priv->bcn_rssi_avg;
/* bit rate is in 500 kb/s units. Convert it to 100kb/s units */
sinfo->txrate.legacy = rate.rate * 5;
sinfo->txrate.legacy = rate * 5;
if (priv->bss_mode == NL80211_IFTYPE_STATION) {
sinfo->filled |= STATION_INFO_BSS_PARAM;
@ -827,8 +753,8 @@ static const u32 mwifiex_cipher_suites[] = {
/*
* CFG802.11 operation handler for setting bit rates.
*
* Function selects legacy bang B/G/BG from corresponding bitrates selection.
* Currently only 2.4GHz band is supported.
* Function configures data rates to firmware using bitrate mask
* provided by cfg80211.
*/
static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
struct net_device *dev,
@ -836,43 +762,36 @@ static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy,
const struct cfg80211_bitrate_mask *mask)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
int index = 0, mode = 0, i;
struct mwifiex_adapter *adapter = priv->adapter;
u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
enum ieee80211_band band;
/* Currently only 2.4GHz is supported */
for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {
/*
* Rates below 6 Mbps in the table are CCK rates; 802.11b
* and from 6 they are OFDM; 802.11G
*/
if (mwifiex_rates[i].bitrate == 60) {
index = 1 << i;
break;
}
if (!priv->media_connected) {
dev_err(priv->adapter->dev,
"Can not set Tx data rate in disconnected state\n");
return -EINVAL;
}
if (mask->control[IEEE80211_BAND_2GHZ].legacy < index) {
mode = BAND_B;
} else {
mode = BAND_G;
if (mask->control[IEEE80211_BAND_2GHZ].legacy % index)
mode |= BAND_B;
}
band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
if (!((mode | adapter->fw_bands) & ~adapter->fw_bands)) {
adapter->config_bands = mode;
if (priv->bss_mode == NL80211_IFTYPE_ADHOC) {
adapter->adhoc_start_band = mode;
adapter->adhoc_11n_enabled = false;
}
}
adapter->sec_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
adapter->channel_type = NL80211_CHAN_NO_HT;
memset(bitmap_rates, 0, sizeof(bitmap_rates));
wiphy_debug(wiphy, "info: device configured in 802.11%s%s mode\n",
(mode & BAND_B) ? "b" : "", (mode & BAND_G) ? "g" : "");
/* Fill HR/DSSS rates. */
if (band == IEEE80211_BAND_2GHZ)
bitmap_rates[0] = mask->control[band].legacy & 0x000f;
return 0;
/* Fill OFDM rates */
if (band == IEEE80211_BAND_2GHZ)
bitmap_rates[1] = (mask->control[band].legacy & 0x0ff0) >> 4;
else
bitmap_rates[1] = mask->control[band].legacy;
/* Fill MCS rates */
bitmap_rates[2] = mask->control[band].mcs[0];
if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2)
bitmap_rates[2] |= mask->control[band].mcs[1] << 8;
return mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG,
HostCmd_ACT_GEN_SET, 0, bitmap_rates);
}
/*
@ -1007,6 +926,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
{
struct mwifiex_uap_bss_param *bss_cfg;
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
u8 config_bands = 0;
if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP)
return -1;
@ -1047,13 +967,25 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,
(u8)ieee80211_frequency_to_channel(params->channel->center_freq);
bss_cfg->band_cfg = BAND_CONFIG_MANUAL;
if (mwifiex_set_rf_channel(priv, params->channel,
params->channel_type)) {
kfree(bss_cfg);
wiphy_err(wiphy, "Failed to set band config information!\n");
return -1;
/* Set appropriate bands */
if (params->channel->band == IEEE80211_BAND_2GHZ) {
if (params->channel_type == NL80211_CHAN_NO_HT)
config_bands = BAND_B | BAND_G;
else
config_bands = BAND_B | BAND_G | BAND_GN;
} else {
if (params->channel_type == NL80211_CHAN_NO_HT)
config_bands = BAND_A;
else
config_bands = BAND_AN | BAND_A;
}
if (!((config_bands | priv->adapter->fw_bands) &
~priv->adapter->fw_bands))
priv->adapter->config_bands = config_bands;
mwifiex_send_domain_info_cmd_fw(wiphy);
if (mwifiex_set_secure_params(priv, bss_cfg, params)) {
kfree(bss_cfg);
wiphy_err(wiphy, "Failed to parse secuirty parameters!\n");
@ -1187,7 +1119,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
struct cfg80211_ssid req_ssid;
int ret, auth_type = 0;
struct cfg80211_bss *bss = NULL;
u8 is_scanning_required = 0;
u8 is_scanning_required = 0, config_bands = 0;
memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));
@ -1206,9 +1138,19 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
/* disconnect before try to associate */
mwifiex_deauthenticate(priv, NULL);
if (channel)
ret = mwifiex_set_rf_channel(priv, channel,
priv->adapter->channel_type);
if (channel) {
if (mode == NL80211_IFTYPE_STATION) {
if (channel->band == IEEE80211_BAND_2GHZ)
config_bands = BAND_B | BAND_G | BAND_GN;
else
config_bands = BAND_A | BAND_AN;
if (!((config_bands | priv->adapter->fw_bands) &
~priv->adapter->fw_bands))
priv->adapter->config_bands = config_bands;
}
mwifiex_send_domain_info_cmd_fw(priv->wdev->wiphy);
}
/* As this is new association, clear locally stored
* keys and security related flags */
@ -1372,6 +1314,76 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
return ret;
}
/*
* This function sets following parameters for ibss network.
* - channel
* - start band
* - 11n flag
* - secondary channel offset
*/
static int mwifiex_set_ibss_params(struct mwifiex_private *priv,
struct cfg80211_ibss_params *params)
{
struct wiphy *wiphy = priv->wdev->wiphy;
struct mwifiex_adapter *adapter = priv->adapter;
int index = 0, i;
u8 config_bands = 0;
if (params->channel->band == IEEE80211_BAND_2GHZ) {
if (!params->basic_rates) {
config_bands = BAND_B | BAND_G;
} else {
for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) {
/*
* Rates below 6 Mbps in the table are CCK
* rates; 802.11b and from 6 they are OFDM;
* 802.11G
*/
if (mwifiex_rates[i].bitrate == 60) {
index = 1 << i;
break;
}
}
if (params->basic_rates < index) {
config_bands = BAND_B;
} else {
config_bands = BAND_G;
if (params->basic_rates % index)
config_bands |= BAND_B;
}
}
if (params->channel_type != NL80211_CHAN_NO_HT)
config_bands |= BAND_GN;
} else {
if (params->channel_type == NL80211_CHAN_NO_HT)
config_bands = BAND_A;
else
config_bands = BAND_AN | BAND_A;
}
if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) {
adapter->config_bands = config_bands;
adapter->adhoc_start_band = config_bands;
if ((config_bands & BAND_GN) || (config_bands & BAND_AN))
adapter->adhoc_11n_enabled = true;
else
adapter->adhoc_11n_enabled = false;
}
adapter->sec_chan_offset =
mwifiex_chan_type_to_sec_chan_offset(params->channel_type);
priv->adhoc_channel =
ieee80211_frequency_to_channel(params->channel->center_freq);
wiphy_dbg(wiphy, "info: set ibss band %d, chan %d, chan offset %d\n",
config_bands, priv->adhoc_channel, adapter->sec_chan_offset);
return 0;
}
/*
* CFG802.11 operation handler to join an IBSS.
*
@ -1394,6 +1406,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n",
(char *) params->ssid, params->bssid);
mwifiex_set_ibss_params(priv, params);
ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid,
params->bssid, priv->bss_mode,
params->channel, NULL, params->privacy);
@ -1440,9 +1454,10 @@ mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
* it also informs the results.
*/
static int
mwifiex_cfg80211_scan(struct wiphy *wiphy, struct net_device *dev,
mwifiex_cfg80211_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request)
{
struct net_device *dev = request->wdev->netdev;
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
int i;
struct ieee80211_channel *chan;
@ -1576,11 +1591,11 @@ mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info,
/*
* create a new virtual interface with the given name
*/
struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
char *name,
enum nl80211_iftype type,
u32 *flags,
struct vif_params *params)
struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
char *name,
enum nl80211_iftype type,
u32 *flags,
struct vif_params *params)
{
struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
struct mwifiex_private *priv;
@ -1701,16 +1716,16 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
#ifdef CONFIG_DEBUG_FS
mwifiex_dev_debugfs_init(priv);
#endif
return dev;
return wdev;
}
EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
/*
* del_virtual_intf: remove the virtual interface determined by dev
*/
int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)
int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev);
#ifdef CONFIG_DEBUG_FS
mwifiex_dev_debugfs_remove(priv);
@ -1722,11 +1737,11 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)
if (netif_carrier_ok(priv->netdev))
netif_carrier_off(priv->netdev);
if (dev->reg_state == NETREG_REGISTERED)
unregister_netdevice(dev);
if (wdev->netdev->reg_state == NETREG_REGISTERED)
unregister_netdevice(wdev->netdev);
if (dev->reg_state == NETREG_UNREGISTERED)
free_netdev(dev);
if (wdev->netdev->reg_state == NETREG_UNREGISTERED)
free_netdev(wdev->netdev);
/* Clear the priv in adapter */
priv->netdev = NULL;
@ -1818,6 +1833,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
wiphy->features = NL80211_FEATURE_HT_IBSS;
/* Reserve space for mwifiex specific private data for BSS */
wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);

View file

@ -166,23 +166,6 @@ u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, u8 index,
return rate;
}
/*
* This function maps a data rate value into corresponding index in supported
* rates table.
*/
u8 mwifiex_data_rate_to_index(u32 rate)
{
u16 *ptr;
if (rate) {
ptr = memchr(mwifiex_data_rates, rate,
sizeof(mwifiex_data_rates));
if (ptr)
return (u8) (ptr - mwifiex_data_rates);
}
return 0;
}
/*
* This function returns the current active data rates.
*
@ -276,20 +259,6 @@ mwifiex_is_rate_auto(struct mwifiex_private *priv)
return false;
}
/*
* This function converts rate bitmap into rate index.
*/
int mwifiex_get_rate_index(u16 *rate_bitmap, int size)
{
int i;
for (i = 0; i < size * 8; i++)
if (rate_bitmap[i / 16] & (1 << (i % 16)))
return i;
return 0;
}
/*
* This function gets the supported data rates.
*

View file

@ -41,16 +41,7 @@
#define MWIFIEX_AMPDU_DEF_RXWINSIZE 16
#define MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff
#define MWIFIEX_RATE_INDEX_HRDSSS0 0
#define MWIFIEX_RATE_INDEX_HRDSSS3 3
#define MWIFIEX_RATE_INDEX_OFDM0 4
#define MWIFIEX_RATE_INDEX_OFDM7 11
#define MWIFIEX_RATE_INDEX_MCS0 12
#define MWIFIEX_RATE_BITMAP_OFDM0 16
#define MWIFIEX_RATE_BITMAP_OFDM7 23
#define MWIFIEX_RATE_BITMAP_MCS0 32
#define MWIFIEX_RATE_BITMAP_MCS127 159
#define MWIFIEX_RX_DATA_BUF_SIZE (4 * 1024)
#define MWIFIEX_RX_CMD_BUF_SIZE (2 * 1024)

View file

@ -225,7 +225,6 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define HostCmd_CMD_BBP_REG_ACCESS 0x001a
#define HostCmd_CMD_RF_REG_ACCESS 0x001b
#define HostCmd_CMD_PMIC_REG_ACCESS 0x00ad
#define HostCmd_CMD_802_11_RF_CHANNEL 0x001d
#define HostCmd_CMD_RF_TX_PWR 0x001e
#define HostCmd_CMD_RF_ANTENNA 0x0020
#define HostCmd_CMD_802_11_DEAUTHENTICATE 0x0024
@ -1292,14 +1291,6 @@ struct host_cmd_tlv_channel_band {
u8 channel;
} __packed;
struct host_cmd_ds_802_11_rf_channel {
__le16 action;
__le16 current_channel;
__le16 rf_type;
__le16 reserved;
u8 reserved_1[32];
} __packed;
struct host_cmd_ds_version_ext {
u8 version_str_sel;
char version_str[128];
@ -1384,7 +1375,6 @@ struct host_cmd_ds_command {
struct host_cmd_ds_802_11_rssi_info rssi_info;
struct host_cmd_ds_802_11_rssi_info_rsp rssi_info_rsp;
struct host_cmd_ds_802_11_snmp_mib smib;
struct host_cmd_ds_802_11_rf_channel rf_channel;
struct host_cmd_ds_tx_rate_query tx_rate;
struct host_cmd_ds_tx_rate_cfg tx_rate_cfg;
struct host_cmd_ds_txpwr_cfg txp_cfg;

View file

@ -344,7 +344,6 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
adapter->adhoc_awake_period = 0;
memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
adapter->arp_filter_size = 0;
adapter->channel_type = NL80211_CHAN_HT20;
adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
}

View file

@ -225,12 +225,6 @@ struct mwifiex_ds_encrypt_key {
u8 wapi_rxpn[WAPI_RXPN_LEN];
};
struct mwifiex_rate_cfg {
u32 action;
u32 is_rate_auto;
u32 rate;
};
struct mwifiex_power_cfg {
u32 is_power_auto;
u32 power_level;

View file

@ -377,7 +377,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context)
goto done;
err_add_intf:
mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev);
mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
rtnl_unlock();
err_init_fw:
pr_debug("info: %s: unregister device\n", __func__);
@ -844,7 +844,7 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem)
rtnl_lock();
if (priv->wdev && priv->netdev)
mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev);
mwifiex_del_virtual_intf(adapter->wiphy, priv->wdev);
rtnl_unlock();
}

View file

@ -678,7 +678,6 @@ struct mwifiex_adapter {
u8 hw_dev_mcs_support;
u8 adhoc_11n_enabled;
u8 sec_chan_offset;
enum nl80211_channel_type channel_type;
struct mwifiex_dbg dbg;
u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE];
u32 arp_filter_size;
@ -824,9 +823,7 @@ int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask,
u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv,
u8 *rates);
u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates);
u8 mwifiex_data_rate_to_index(u32 rate);
u8 mwifiex_is_rate_auto(struct mwifiex_private *priv);
int mwifiex_get_rate_index(u16 *rateBitmap, int size);
extern u16 region_code_index[MWIFIEX_MAX_REGION_CODE];
void mwifiex_save_curr_bcn(struct mwifiex_private *priv);
void mwifiex_free_curr_bcn(struct mwifiex_private *priv);
@ -945,16 +942,13 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
int mwifiex_enable_hs(struct mwifiex_adapter *adapter);
int mwifiex_disable_auto_ds(struct mwifiex_private *priv);
int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
struct mwifiex_rate_cfg *rate);
int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, u32 *rate);
int mwifiex_request_scan(struct mwifiex_private *priv,
struct cfg80211_ssid *req_ssid);
int mwifiex_scan_networks(struct mwifiex_private *priv,
const struct mwifiex_user_scan_cfg *user_scan_in);
int mwifiex_set_radio(struct mwifiex_private *priv, u8 option);
int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel);
int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,
int key_len, u8 key_index, const u8 *mac_addr,
int disable);
@ -993,8 +987,6 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv,
int mwifiex_main_process(struct mwifiex_adapter *);
int mwifiex_bss_set_channel(struct mwifiex_private *,
struct mwifiex_chan_freq_power *cfp);
int mwifiex_get_bss_info(struct mwifiex_private *,
struct mwifiex_bss_info *);
int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
@ -1005,10 +997,12 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc);
struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy,
char *name, enum nl80211_iftype type,
u32 *flags, struct vif_params *params);
int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev);
struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
char *name,
enum nl80211_iftype type,
u32 *flags,
struct vif_params *params);
int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev);
void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config);

View file

@ -744,40 +744,6 @@ static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private *priv,
return 0;
}
/*
* This function prepares command to set/get RF channel.
*
* Preparation includes -
* - Setting command ID, action and proper size
* - Setting RF type and current RF channel (for SET only)
* - Ensuring correct endian-ness
*/
static int mwifiex_cmd_802_11_rf_channel(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
u16 cmd_action, u16 *channel)
{
struct host_cmd_ds_802_11_rf_channel *rf_chan =
&cmd->params.rf_channel;
uint16_t rf_type = le16_to_cpu(rf_chan->rf_type);
cmd->command = cpu_to_le16(HostCmd_CMD_802_11_RF_CHANNEL);
cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rf_channel)
+ S_DS_GEN);
if (cmd_action == HostCmd_ACT_GEN_SET) {
if ((priv->adapter->adhoc_start_band & BAND_A) ||
(priv->adapter->adhoc_start_band & BAND_AN))
rf_chan->rf_type =
cpu_to_le16(HostCmd_SCAN_RADIO_TYPE_A);
rf_type = le16_to_cpu(rf_chan->rf_type);
SET_SECONDARYCHAN(rf_type, priv->adapter->sec_chan_offset);
rf_chan->current_channel = cpu_to_le16(*channel);
}
rf_chan->action = cpu_to_le16(cmd_action);
return 0;
}
/*
* This function prepares command to set/get IBSS coalescing status.
*
@ -1169,10 +1135,6 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
S_DS_GEN);
ret = 0;
break;
case HostCmd_CMD_802_11_RF_CHANNEL:
ret = mwifiex_cmd_802_11_rf_channel(priv, cmd_ptr, cmd_action,
data_buf);
break;
case HostCmd_CMD_FUNC_INIT:
if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET)
priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY;

View file

@ -267,12 +267,10 @@ static int mwifiex_ret_get_log(struct mwifiex_private *priv,
*
* Based on the new rate bitmaps, the function re-evaluates if
* auto data rate has been activated. If not, it sends another
* query to the firmware to get the current Tx data rate and updates
* the driver value.
* query to the firmware to get the current Tx data rate.
*/
static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
struct mwifiex_rate_cfg *ds_rate)
struct host_cmd_ds_command *resp)
{
struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg;
struct mwifiex_rate_scope *rate_scope;
@ -280,7 +278,6 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
u16 tlv, tlv_buf_len;
u8 *tlv_buf;
u32 i;
int ret = 0;
tlv_buf = ((u8 *)rate_cfg) +
sizeof(struct host_cmd_ds_tx_rate_cfg);
@ -318,33 +315,11 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv,
if (priv->is_data_rate_auto)
priv->data_rate = 0;
else
ret = mwifiex_send_cmd_async(priv,
HostCmd_CMD_802_11_TX_RATE_QUERY,
HostCmd_ACT_GEN_GET, 0, NULL);
return mwifiex_send_cmd_async(priv,
HostCmd_CMD_802_11_TX_RATE_QUERY,
HostCmd_ACT_GEN_GET, 0, NULL);
if (!ds_rate)
return ret;
if (le16_to_cpu(rate_cfg->action) == HostCmd_ACT_GEN_GET) {
if (priv->is_data_rate_auto) {
ds_rate->is_rate_auto = 1;
return ret;
}
ds_rate->rate = mwifiex_get_rate_index(priv->bitmap_rates,
sizeof(priv->bitmap_rates));
if (ds_rate->rate >= MWIFIEX_RATE_BITMAP_OFDM0 &&
ds_rate->rate <= MWIFIEX_RATE_BITMAP_OFDM7)
ds_rate->rate -= (MWIFIEX_RATE_BITMAP_OFDM0 -
MWIFIEX_RATE_INDEX_OFDM0);
if (ds_rate->rate >= MWIFIEX_RATE_BITMAP_MCS0 &&
ds_rate->rate <= MWIFIEX_RATE_BITMAP_MCS127)
ds_rate->rate -= (MWIFIEX_RATE_BITMAP_MCS0 -
MWIFIEX_RATE_INDEX_MCS0);
}
return ret;
return 0;
}
/*
@ -655,34 +630,6 @@ static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv,
return 0;
}
/*
* This function handles the command response of get RF channel.
*
* Handling includes changing the header fields into CPU format
* and saving the new channel in driver.
*/
static int mwifiex_ret_802_11_rf_channel(struct mwifiex_private *priv,
struct host_cmd_ds_command *resp,
u16 *data_buf)
{
struct host_cmd_ds_802_11_rf_channel *rf_channel =
&resp->params.rf_channel;
u16 new_channel = le16_to_cpu(rf_channel->current_channel);
if (priv->curr_bss_params.bss_descriptor.channel != new_channel) {
dev_dbg(priv->adapter->dev, "cmd: Channel Switch: %d to %d\n",
priv->curr_bss_params.bss_descriptor.channel,
new_channel);
/* Update the channel again */
priv->curr_bss_params.bss_descriptor.channel = new_channel;
}
if (data_buf)
*data_buf = new_channel;
return 0;
}
/*
* This function handles the command response of get extended version.
*
@ -878,7 +825,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
ret = mwifiex_ret_mac_multicast_adr(priv, resp);
break;
case HostCmd_CMD_TX_RATE_CFG:
ret = mwifiex_ret_tx_rate_cfg(priv, resp, data_buf);
ret = mwifiex_ret_tx_rate_cfg(priv, resp);
break;
case HostCmd_CMD_802_11_SCAN:
ret = mwifiex_ret_802_11_scan(priv, resp);
@ -929,9 +876,6 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
case HostCmd_CMD_802_11_TX_RATE_QUERY:
ret = mwifiex_ret_802_11_tx_rate_query(priv, resp);
break;
case HostCmd_CMD_802_11_RF_CHANNEL:
ret = mwifiex_ret_802_11_rf_channel(priv, resp, data_buf);
break;
case HostCmd_CMD_VERSION_EXT:
ret = mwifiex_ret_ver_ext(priv, resp, data_buf);
break;

View file

@ -496,298 +496,25 @@ int mwifiex_disable_auto_ds(struct mwifiex_private *priv)
}
EXPORT_SYMBOL_GPL(mwifiex_disable_auto_ds);
/*
* IOCTL request handler to set/get active channel.
*
* This function performs validity checking on channel/frequency
* compatibility and returns failure if not valid.
*/
int mwifiex_bss_set_channel(struct mwifiex_private *priv,
struct mwifiex_chan_freq_power *chan)
{
struct mwifiex_adapter *adapter = priv->adapter;
struct mwifiex_chan_freq_power *cfp = NULL;
if (!chan)
return -1;
if (!chan->channel && !chan->freq)
return -1;
if (adapter->adhoc_start_band & BAND_AN)
adapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN;
else if (adapter->adhoc_start_band & BAND_A)
adapter->adhoc_start_band = BAND_G | BAND_B;
if (chan->channel) {
if (chan->channel <= MAX_CHANNEL_BAND_BG)
cfp = mwifiex_get_cfp(priv, 0, (u16) chan->channel, 0);
if (!cfp) {
cfp = mwifiex_get_cfp(priv, BAND_A,
(u16) chan->channel, 0);
if (cfp) {
if (adapter->adhoc_11n_enabled)
adapter->adhoc_start_band = BAND_A
| BAND_AN;
else
adapter->adhoc_start_band = BAND_A;
}
}
} else {
if (chan->freq <= MAX_FREQUENCY_BAND_BG)
cfp = mwifiex_get_cfp(priv, 0, 0, chan->freq);
if (!cfp) {
cfp = mwifiex_get_cfp(priv, BAND_A, 0, chan->freq);
if (cfp) {
if (adapter->adhoc_11n_enabled)
adapter->adhoc_start_band = BAND_A
| BAND_AN;
else
adapter->adhoc_start_band = BAND_A;
}
}
}
if (!cfp || !cfp->channel) {
dev_err(adapter->dev, "invalid channel/freq\n");
return -1;
}
priv->adhoc_channel = (u8) cfp->channel;
chan->channel = cfp->channel;
chan->freq = cfp->freq;
return 0;
}
/*
* IOCTL request handler to set/get Ad-Hoc channel.
*
* This function prepares the correct firmware command and
* issues it to set or get the ad-hoc channel.
*/
static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv,
u16 action, u16 *channel)
{
if (action == HostCmd_ACT_GEN_GET) {
if (!priv->media_connected) {
*channel = priv->adhoc_channel;
return 0;
}
} else {
priv->adhoc_channel = (u8) *channel;
}
return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_RF_CHANNEL,
action, 0, channel);
}
/*
* IOCTL request handler to change Ad-Hoc channel.
*
* This function allocates the IOCTL request buffer, fills it
* with requisite parameters and calls the IOCTL handler.
*
* The function follows the following steps to perform the change -
* - Get current IBSS information
* - Get current channel
* - If no change is required, return
* - If not connected, change channel and return
* - If connected,
* - Disconnect
* - Change channel
* - Perform specific SSID scan with same SSID
* - Start/Join the IBSS
*/
int
mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel)
{
int ret;
struct mwifiex_bss_info bss_info;
struct mwifiex_ssid_bssid ssid_bssid;
u16 curr_chan = 0;
struct cfg80211_bss *bss = NULL;
struct ieee80211_channel *chan;
enum ieee80211_band band;
memset(&bss_info, 0, sizeof(bss_info));
/* Get BSS information */
if (mwifiex_get_bss_info(priv, &bss_info))
return -1;
/* Get current channel */
ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_GET,
&curr_chan);
if (curr_chan == channel) {
ret = 0;
goto done;
}
dev_dbg(priv->adapter->dev, "cmd: updating channel from %d to %d\n",
curr_chan, channel);
if (!bss_info.media_connected) {
ret = 0;
goto done;
}
/* Do disonnect */
memset(&ssid_bssid, 0, ETH_ALEN);
ret = mwifiex_deauthenticate(priv, ssid_bssid.bssid);
ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_SET,
&channel);
/* Do specific SSID scanning */
if (mwifiex_request_scan(priv, &bss_info.ssid)) {
ret = -1;
goto done;
}
band = mwifiex_band_to_radio_type(priv->curr_bss_params.band);
chan = __ieee80211_get_channel(priv->wdev->wiphy,
ieee80211_channel_to_frequency(channel,
band));
/* Find the BSS we want using available scan results */
bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid,
bss_info.ssid.ssid, bss_info.ssid.ssid_len,
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
if (!bss)
wiphy_warn(priv->wdev->wiphy, "assoc: bss %pM not in scan results\n",
bss_info.bssid);
ret = mwifiex_bss_start(priv, bss, &bss_info.ssid);
done:
return ret;
}
/*
* IOCTL request handler to get rate.
*
* This function prepares the correct firmware command and
* issues it to get the current rate if it is connected,
* otherwise, the function returns the lowest supported rate
* for the band.
*/
static int mwifiex_rate_ioctl_get_rate_value(struct mwifiex_private *priv,
struct mwifiex_rate_cfg *rate_cfg)
{
rate_cfg->is_rate_auto = priv->is_data_rate_auto;
return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,
HostCmd_ACT_GEN_GET, 0, NULL);
}
/*
* IOCTL request handler to set rate.
*
* This function prepares the correct firmware command and
* issues it to set the current rate.
*
* The function also performs validation checking on the supplied value.
*/
static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv,
struct mwifiex_rate_cfg *rate_cfg)
{
u8 rates[MWIFIEX_SUPPORTED_RATES];
u8 *rate;
int rate_index, ret;
u16 bitmap_rates[MAX_BITMAP_RATES_SIZE];
u32 i;
struct mwifiex_adapter *adapter = priv->adapter;
if (rate_cfg->is_rate_auto) {
memset(bitmap_rates, 0, sizeof(bitmap_rates));
/* Support all HR/DSSS rates */
bitmap_rates[0] = 0x000F;
/* Support all OFDM rates */
bitmap_rates[1] = 0x00FF;
/* Support all HT-MCSs rate */
for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates) - 3; i++)
bitmap_rates[i + 2] = 0xFFFF;
bitmap_rates[9] = 0x3FFF;
} else {
memset(rates, 0, sizeof(rates));
mwifiex_get_active_data_rates(priv, rates);
rate = rates;
for (i = 0; (rate[i] && i < MWIFIEX_SUPPORTED_RATES); i++) {
dev_dbg(adapter->dev, "info: rate=%#x wanted=%#x\n",
rate[i], rate_cfg->rate);
if ((rate[i] & 0x7f) == (rate_cfg->rate & 0x7f))
break;
}
if ((i == MWIFIEX_SUPPORTED_RATES) || !rate[i]) {
dev_err(adapter->dev, "fixed data rate %#x is out "
"of range\n", rate_cfg->rate);
return -1;
}
memset(bitmap_rates, 0, sizeof(bitmap_rates));
rate_index = mwifiex_data_rate_to_index(rate_cfg->rate);
/* Only allow b/g rates to be set */
if (rate_index >= MWIFIEX_RATE_INDEX_HRDSSS0 &&
rate_index <= MWIFIEX_RATE_INDEX_HRDSSS3) {
bitmap_rates[0] = 1 << rate_index;
} else {
rate_index -= 1; /* There is a 0x00 in the table */
if (rate_index >= MWIFIEX_RATE_INDEX_OFDM0 &&
rate_index <= MWIFIEX_RATE_INDEX_OFDM7)
bitmap_rates[1] = 1 << (rate_index -
MWIFIEX_RATE_INDEX_OFDM0);
}
}
ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG,
HostCmd_ACT_GEN_SET, 0, bitmap_rates);
return ret;
}
/*
* IOCTL request handler to set/get rate.
*
* This function can be used to set/get either the rate value or the
* rate index.
*/
static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv,
struct mwifiex_rate_cfg *rate_cfg)
{
int status;
if (!rate_cfg)
return -1;
if (rate_cfg->action == HostCmd_ACT_GEN_GET)
status = mwifiex_rate_ioctl_get_rate_value(priv, rate_cfg);
else
status = mwifiex_rate_ioctl_set_rate_value(priv, rate_cfg);
return status;
}
/*
* Sends IOCTL request to get the data rate.
*
* This function allocates the IOCTL request buffer, fills it
* with requisite parameters and calls the IOCTL handler.
*/
int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
struct mwifiex_rate_cfg *rate)
int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, u32 *rate)
{
int ret;
memset(rate, 0, sizeof(struct mwifiex_rate_cfg));
rate->action = HostCmd_ACT_GEN_GET;
ret = mwifiex_rate_ioctl_cfg(priv, rate);
ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,
HostCmd_ACT_GEN_GET, 0, NULL);
if (!ret) {
if (rate->is_rate_auto)
rate->rate = mwifiex_index_to_data_rate(priv,
priv->tx_rate,
priv->tx_htinfo
);
if (priv->is_data_rate_auto)
*rate = mwifiex_index_to_data_rate(priv, priv->tx_rate,
priv->tx_htinfo);
else
rate->rate = priv->data_rate;
} else {
ret = -1;
*rate = priv->data_rate;
}
return ret;

View file

@ -1665,7 +1665,9 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force)
info = IEEE80211_SKB_CB(skb);
if (ieee80211_is_data(wh->frame_control)) {
sta = info->control.sta;
rcu_read_lock();
sta = ieee80211_find_sta_by_ifaddr(hw, wh->addr1,
wh->addr2);
if (sta) {
sta_info = MWL8K_STA(sta);
BUG_ON(sta_info == NULL);
@ -1682,6 +1684,7 @@ mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int limit, int force)
sta_info->is_ampdu_allowed = true;
}
}
rcu_read_unlock();
}
ieee80211_tx_info_clear_status(info);

View file

@ -138,7 +138,7 @@ static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev,
return err;
}
static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev,
static int orinoco_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request)
{
struct orinoco_private *priv = wiphy_priv(wiphy);

View file

@ -484,7 +484,7 @@ static int rndis_change_virtual_intf(struct wiphy *wiphy,
enum nl80211_iftype type, u32 *flags,
struct vif_params *params);
static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
static int rndis_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request);
static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed);
@ -1941,9 +1941,10 @@ static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm)
}
#define SCAN_DELAY_JIFFIES (6 * HZ)
static int rndis_scan(struct wiphy *wiphy, struct net_device *dev,
static int rndis_scan(struct wiphy *wiphy,
struct cfg80211_scan_request *request)
{
struct net_device *dev = request->wdev->netdev;
struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev);
int ret;

View file

@ -102,7 +102,7 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
/* Update the AID, this is needed for dynamic PS support */
rt2x00dev->aid = bss_conf->assoc ? bss_conf->aid : 0;
rt2x00dev->last_beacon = bss_conf->last_tsf;
rt2x00dev->last_beacon = bss_conf->sync_tsf;
/* Update global beacon interval time, this is needed for PS support */
rt2x00dev->beacon_int = bss_conf->beacon_int;

View file

@ -167,7 +167,7 @@ static const u8 tid_to_ac[] = {
0, /* IEEE80211_AC_VO */
};
u8 rtl_tid_to_ac(struct ieee80211_hw *hw, u8 tid)
u8 rtl_tid_to_ac(u8 tid)
{
return tid_to_ac[tid];
}

View file

@ -138,7 +138,7 @@ int rtl_send_smps_action(struct ieee80211_hw *hw,
enum ieee80211_smps_mode smps);
u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie);
void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len);
u8 rtl_tid_to_ac(struct ieee80211_hw *hw, u8 tid);
u8 rtl_tid_to_ac(u8 tid);
extern struct attribute_group rtl_attribute_group;
int rtlwifi_rate_mapping(struct ieee80211_hw *hw,
bool isht, u8 desc_rate, bool first_ampdu);

View file

@ -480,7 +480,7 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw)
/* we juse use em for BE/BK/VI/VO */
for (tid = 7; tid >= 0; tid--) {
u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(hw, tid)];
u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)];
struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
while (!mac->act_scanning &&
rtlpriv->psc.rfpwr_state == ERFON) {

View file

@ -3345,21 +3345,21 @@ void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw)
switch (rtlhal->macphymode) {
case DUALMAC_SINGLEPHY:
rtlphy->rf_type = RF_2T2R;
rtlhal->version |= CHIP_92D_SINGLEPHY;
rtlhal->version |= RF_TYPE_2T2R;
rtlhal->bandset = BAND_ON_BOTH;
rtlhal->current_bandtype = BAND_ON_2_4G;
break;
case SINGLEMAC_SINGLEPHY:
rtlphy->rf_type = RF_2T2R;
rtlhal->version |= CHIP_92D_SINGLEPHY;
rtlhal->version |= RF_TYPE_2T2R;
rtlhal->bandset = BAND_ON_BOTH;
rtlhal->current_bandtype = BAND_ON_2_4G;
break;
case DUALMAC_DUALPHY:
rtlphy->rf_type = RF_1T1R;
rtlhal->version &= (~CHIP_92D_SINGLEPHY);
rtlhal->version &= RF_TYPE_1T1R;
/* Now we let MAC0 run on 5G band. */
if (rtlhal->interfaceindex == 0) {
rtlhal->bandset = BAND_ON_5G;

Some files were not shown because too many files have changed in this diff Show more