Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
This commit is contained in:
commit
90b90f60c4
163 changed files with 5139 additions and 2915 deletions
|
@ -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">
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
19
drivers/bcma/driver_chipcommon_nflash.c
Normal file
19
drivers/bcma/driver_chipcommon_nflash.c
Normal 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;
|
||||
}
|
19
drivers/bcma/driver_chipcommon_sflash.c
Normal file
19
drivers/bcma/driver_chipcommon_sflash.c
Normal 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;
|
||||
}
|
14
drivers/bcma/driver_gmac_cmn.c
Normal file
14
drivers/bcma/driver_gmac_cmn.c
Normal 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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
747
drivers/bluetooth/hci_h5.c
Normal 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);
|
||||
}
|
|
@ -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)))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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], "
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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 */
|
||||
|
|
532
drivers/net/wireless/ath/ath9k/wow.c
Normal file
532
drivers/net/wireless/ath/ath9k/wow.c
Normal 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);
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -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");
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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 {
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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 *),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue