mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 14:43:16 +00:00
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
4205e6ef4e
@ -17,10 +17,12 @@ HCI
|
||||
HCI registers as an nfc device with NFC Core. Requests coming from userspace are
|
||||
routed through netlink sockets to NFC Core and then to HCI. From this point,
|
||||
they are translated in a sequence of HCI commands sent to the HCI layer in the
|
||||
host controller (the chip). The sending context blocks while waiting for the
|
||||
response to arrive.
|
||||
host controller (the chip). Commands can be executed synchronously (the sending
|
||||
context blocks waiting for response) or asynchronously (the response is returned
|
||||
from HCI Rx context).
|
||||
HCI events can also be received from the host controller. They will be handled
|
||||
and a translation will be forwarded to NFC Core as needed.
|
||||
and a translation will be forwarded to NFC Core as needed. There are hooks to
|
||||
let the HCI driver handle proprietary events or override standard behavior.
|
||||
HCI uses 2 execution contexts:
|
||||
- one for executing commands : nfc_hci_msg_tx_work(). Only one command
|
||||
can be executing at any given moment.
|
||||
@ -33,6 +35,8 @@ The Session initialization is an HCI standard which must unfortunately
|
||||
support proprietary gates. This is the reason why the driver will pass a list
|
||||
of proprietary gates that must be part of the session. HCI will ensure all
|
||||
those gates have pipes connected when the hci device is set up.
|
||||
In case the chip supports pre-opened gates and pseudo-static pipes, the driver
|
||||
can pass that information to HCI core.
|
||||
|
||||
HCI Gates and Pipes
|
||||
-------------------
|
||||
@ -46,6 +50,13 @@ without knowing the pipe connected to it.
|
||||
Driver interface
|
||||
----------------
|
||||
|
||||
A driver is generally written in two parts : the physical link management and
|
||||
the HCI management. This makes it easier to maintain a driver for a chip that
|
||||
can be connected using various phy (i2c, spi, ...)
|
||||
|
||||
HCI Management
|
||||
--------------
|
||||
|
||||
A driver would normally register itself with HCI and provide the following
|
||||
entry points:
|
||||
|
||||
@ -53,58 +64,113 @@ struct nfc_hci_ops {
|
||||
int (*open)(struct nfc_hci_dev *hdev);
|
||||
void (*close)(struct nfc_hci_dev *hdev);
|
||||
int (*hci_ready) (struct nfc_hci_dev *hdev);
|
||||
int (*xmit)(struct nfc_hci_dev *hdev, struct sk_buff *skb);
|
||||
int (*start_poll)(struct nfc_hci_dev *hdev, u32 protocols);
|
||||
int (*target_from_gate)(struct nfc_hci_dev *hdev, u8 gate,
|
||||
struct nfc_target *target);
|
||||
int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb);
|
||||
int (*start_poll) (struct nfc_hci_dev *hdev,
|
||||
u32 im_protocols, u32 tm_protocols);
|
||||
int (*dep_link_up)(struct nfc_hci_dev *hdev, struct nfc_target *target,
|
||||
u8 comm_mode, u8 *gb, size_t gb_len);
|
||||
int (*dep_link_down)(struct nfc_hci_dev *hdev);
|
||||
int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate,
|
||||
struct nfc_target *target);
|
||||
int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate,
|
||||
struct nfc_target *target);
|
||||
int (*data_exchange) (struct nfc_hci_dev *hdev,
|
||||
struct nfc_target *target,
|
||||
struct sk_buff *skb, struct sk_buff **res_skb);
|
||||
int (*im_transceive) (struct nfc_hci_dev *hdev,
|
||||
struct nfc_target *target, struct sk_buff *skb,
|
||||
data_exchange_cb_t cb, void *cb_context);
|
||||
int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb);
|
||||
int (*check_presence)(struct nfc_hci_dev *hdev,
|
||||
struct nfc_target *target);
|
||||
int (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event,
|
||||
struct sk_buff *skb);
|
||||
};
|
||||
|
||||
- open() and close() shall turn the hardware on and off.
|
||||
- hci_ready() is an optional entry point that is called right after the hci
|
||||
session has been set up. The driver can use it to do additional initialization
|
||||
that must be performed using HCI commands.
|
||||
- xmit() shall simply write a frame to the chip.
|
||||
- xmit() shall simply write a frame to the physical link.
|
||||
- start_poll() is an optional entrypoint that shall set the hardware in polling
|
||||
mode. This must be implemented only if the hardware uses proprietary gates or a
|
||||
mechanism slightly different from the HCI standard.
|
||||
- dep_link_up() is called after a p2p target has been detected, to finish
|
||||
the p2p connection setup with hardware parameters that need to be passed back
|
||||
to nfc core.
|
||||
- dep_link_down() is called to bring the p2p link down.
|
||||
- target_from_gate() is an optional entrypoint to return the nfc protocols
|
||||
corresponding to a proprietary gate.
|
||||
- complete_target_discovered() is an optional entry point to let the driver
|
||||
perform additional proprietary processing necessary to auto activate the
|
||||
discovered target.
|
||||
- data_exchange() must be implemented by the driver if proprietary HCI commands
|
||||
- im_transceive() must be implemented by the driver if proprietary HCI commands
|
||||
are required to send data to the tag. Some tag types will require custom
|
||||
commands, others can be written to using the standard HCI commands. The driver
|
||||
can check the tag type and either do proprietary processing, or return 1 to ask
|
||||
for standard processing.
|
||||
for standard processing. The data exchange command itself must be sent
|
||||
asynchronously.
|
||||
- tm_send() is called to send data in the case of a p2p connection
|
||||
- check_presence() is an optional entry point that will be called regularly
|
||||
by the core to check that an activated tag is still in the field. If this is
|
||||
not implemented, the core will not be able to push tag_lost events to the user
|
||||
space
|
||||
- event_received() is called to handle an event coming from the chip. Driver
|
||||
can handle the event or return 1 to let HCI attempt standard processing.
|
||||
|
||||
On the rx path, the driver is responsible to push incoming HCP frames to HCI
|
||||
using nfc_hci_recv_frame(). HCI will take care of re-aggregation and handling
|
||||
This must be done from a context that can sleep.
|
||||
|
||||
SHDLC
|
||||
-----
|
||||
PHY Management
|
||||
--------------
|
||||
|
||||
Most chips use shdlc to ensure integrity and delivery ordering of the HCP
|
||||
frames between the host controller (the chip) and hosts (entities connected
|
||||
to the chip, like the cpu). In order to simplify writing the driver, an shdlc
|
||||
layer is available for use by the driver.
|
||||
When used, the driver actually registers with shdlc, and shdlc will register
|
||||
with HCI. HCI sees shdlc as the driver and thus send its HCP frames
|
||||
through shdlc->xmit.
|
||||
SHDLC adds a new execution context (nfc_shdlc_sm_work()) to run its state
|
||||
machine and handle both its rx and tx path.
|
||||
The physical link (i2c, ...) management is defined by the following struture:
|
||||
|
||||
struct nfc_phy_ops {
|
||||
int (*write)(void *dev_id, struct sk_buff *skb);
|
||||
int (*enable)(void *dev_id);
|
||||
void (*disable)(void *dev_id);
|
||||
};
|
||||
|
||||
enable(): turn the phy on (power on), make it ready to transfer data
|
||||
disable(): turn the phy off
|
||||
write(): Send a data frame to the chip. Note that to enable higher
|
||||
layers such as an llc to store the frame for re-emission, this function must
|
||||
not alter the skb. It must also not return a positive result (return 0 for
|
||||
success, negative for failure).
|
||||
|
||||
Data coming from the chip shall be sent directly to nfc_hci_recv_frame().
|
||||
|
||||
LLC
|
||||
---
|
||||
|
||||
Communication between the CPU and the chip often requires some link layer
|
||||
protocol. Those are isolated as modules managed by the HCI layer. There are
|
||||
currently two modules : nop (raw transfert) and shdlc.
|
||||
A new llc must implement the following functions:
|
||||
|
||||
struct nfc_llc_ops {
|
||||
void *(*init) (struct nfc_hci_dev *hdev, xmit_to_drv_t xmit_to_drv,
|
||||
rcv_to_hci_t rcv_to_hci, int tx_headroom,
|
||||
int tx_tailroom, int *rx_headroom, int *rx_tailroom,
|
||||
llc_failure_t llc_failure);
|
||||
void (*deinit) (struct nfc_llc *llc);
|
||||
int (*start) (struct nfc_llc *llc);
|
||||
int (*stop) (struct nfc_llc *llc);
|
||||
void (*rcv_from_drv) (struct nfc_llc *llc, struct sk_buff *skb);
|
||||
int (*xmit_from_hci) (struct nfc_llc *llc, struct sk_buff *skb);
|
||||
};
|
||||
|
||||
- init() : allocate and init your private storage
|
||||
- deinit() : cleanup
|
||||
- start() : establish the logical connection
|
||||
- stop () : terminate the logical connection
|
||||
- rcv_from_drv() : handle data coming from the chip, going to HCI
|
||||
- xmit_from_hci() : handle data sent by HCI, going to the chip
|
||||
|
||||
The llc must be registered with nfc before it can be used. Do that by
|
||||
calling nfc_llc_register(const char *name, struct nfc_llc_ops *ops);
|
||||
|
||||
Again, note that the llc does not handle the physical link. It is thus very
|
||||
easy to mix any physical link with any llc for a given chip driver.
|
||||
|
||||
Included Drivers
|
||||
----------------
|
||||
@ -117,10 +183,12 @@ Execution Contexts
|
||||
|
||||
The execution contexts are the following:
|
||||
- IRQ handler (IRQH):
|
||||
fast, cannot sleep. stores incoming frames into an shdlc rx queue
|
||||
fast, cannot sleep. sends incoming frames to HCI where they are passed to
|
||||
the current llc. In case of shdlc, the frame is queued in shdlc rx queue.
|
||||
|
||||
- SHDLC State Machine worker (SMW)
|
||||
handles shdlc rx & tx queues. Dispatches HCI cmd responses.
|
||||
Only when llc_shdlc is used: handles shdlc rx & tx queues.
|
||||
Dispatches HCI cmd responses.
|
||||
|
||||
- HCI Tx Cmd worker (MSGTXWQ)
|
||||
Serializes execution of HCI commands. Completes execution in case of response
|
||||
@ -166,6 +234,15 @@ waiting command execution. Response processing involves invoking the completion
|
||||
callback that was provided by nfc_hci_msg_tx_work() when it sent the command.
|
||||
The completion callback will then wake the syscall context.
|
||||
|
||||
It is also possible to execute the command asynchronously using this API:
|
||||
|
||||
static int nfc_hci_execute_cmd_async(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
|
||||
const u8 *param, size_t param_len,
|
||||
data_exchange_cb_t cb, void *cb_context)
|
||||
|
||||
The workflow is the same, except that the API call returns immediately, and
|
||||
the callback will be called with the result from the SMW context.
|
||||
|
||||
Workflow receiving an HCI event or command
|
||||
------------------------------------------
|
||||
|
||||
|
@ -1,32 +1,15 @@
|
||||
Kernel driver for the NXP Semiconductors PN544 Near Field
|
||||
Communication chip
|
||||
|
||||
Author: Jari Vanhala
|
||||
Contact: Matti Aaltonen (matti.j.aaltonen at nokia.com)
|
||||
|
||||
General
|
||||
-------
|
||||
|
||||
The PN544 is an integrated transmission module for contactless
|
||||
communication. The driver goes under drives/nfc/ and is compiled as a
|
||||
module named "pn544". It registers a misc device and creates a device
|
||||
file named "/dev/pn544".
|
||||
module named "pn544".
|
||||
|
||||
Host Interfaces: I2C, SPI and HSU, this driver supports currently only I2C.
|
||||
|
||||
The Interface
|
||||
-------------
|
||||
|
||||
The driver offers a sysfs interface for a hardware test and an IOCTL
|
||||
interface for selecting between two operating modes. There are read,
|
||||
write and poll functions for transferring messages. The two operating
|
||||
modes are the normal (HCI) mode and the firmware update mode.
|
||||
|
||||
PN544 is controlled by sending messages from the userspace to the
|
||||
chip. The main function of the driver is just to pass those messages
|
||||
without caring about the message content.
|
||||
|
||||
|
||||
Protocols
|
||||
---------
|
||||
|
||||
@ -47,68 +30,3 @@ and third (LSB) bytes of the message. The maximum FW message length is
|
||||
|
||||
For the ETSI HCI specification see
|
||||
http://www.etsi.org/WebSite/Technologies/ProtocolSpecification.aspx
|
||||
|
||||
The Hardware Test
|
||||
-----------------
|
||||
|
||||
The idea of the test is that it can performed by reading from the
|
||||
corresponding sysfs file. The test is implemented in the board file
|
||||
and it should test that PN544 can be put into the firmware update
|
||||
mode. If the test is not implemented the sysfs file does not get
|
||||
created.
|
||||
|
||||
Example:
|
||||
> cat /sys/module/pn544/drivers/i2c\:pn544/3-002b/nfc_test
|
||||
1
|
||||
|
||||
Normal Operation
|
||||
----------------
|
||||
|
||||
PN544 is powered up when the device file is opened, otherwise it's
|
||||
turned off. Only one instance can use the device at a time.
|
||||
|
||||
Userspace applications control PN544 with HCI messages. The hardware
|
||||
sends an interrupt when data is available for reading. Data is
|
||||
physically read when the read function is called by a userspace
|
||||
application. Poll() checks the read interrupt state. Configuration and
|
||||
self testing are also done from the userspace using read and write.
|
||||
|
||||
Example platform data:
|
||||
|
||||
static int rx71_pn544_nfc_request_resources(struct i2c_client *client)
|
||||
{
|
||||
/* Get and setup the HW resources for the device */
|
||||
}
|
||||
|
||||
static void rx71_pn544_nfc_free_resources(void)
|
||||
{
|
||||
/* Release the HW resources */
|
||||
}
|
||||
|
||||
static void rx71_pn544_nfc_enable(int fw)
|
||||
{
|
||||
/* Turn the device on */
|
||||
}
|
||||
|
||||
static int rx71_pn544_nfc_test(void)
|
||||
{
|
||||
/*
|
||||
* Put the device into the FW update mode
|
||||
* and then back to the normal mode.
|
||||
* Check the behavior and return one on success,
|
||||
* zero on failure.
|
||||
*/
|
||||
}
|
||||
|
||||
static void rx71_pn544_nfc_disable(void)
|
||||
{
|
||||
/* turn the power off */
|
||||
}
|
||||
|
||||
static struct pn544_nfc_platform_data rx71_nfc_data = {
|
||||
.request_resources = rx71_pn544_nfc_request_resources,
|
||||
.free_resources = rx71_pn544_nfc_free_resources,
|
||||
.enable = rx71_pn544_nfc_enable,
|
||||
.test = rx71_pn544_nfc_test,
|
||||
.disable = rx71_pn544_nfc_disable,
|
||||
};
|
||||
|
@ -62,7 +62,7 @@ static int __init uart8250_init_bcma(void)
|
||||
|
||||
p->mapbase = (unsigned int) bcma_port->regs;
|
||||
p->membase = (void *) bcma_port->regs;
|
||||
p->irq = bcma_port->irq + 2;
|
||||
p->irq = bcma_port->irq;
|
||||
p->uartclk = bcma_port->baud_base;
|
||||
p->regshift = bcma_port->reg_shift;
|
||||
p->iotype = UPIO_MEM;
|
||||
|
@ -31,6 +31,8 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
|
||||
int bcma_bus_suspend(struct bcma_bus *bus);
|
||||
int bcma_bus_resume(struct bcma_bus *bus);
|
||||
#endif
|
||||
struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
|
||||
u8 unit);
|
||||
|
||||
/* scan.c */
|
||||
int bcma_bus_scan(struct bcma_bus *bus);
|
||||
|
@ -329,7 +329,7 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
|
||||
return;
|
||||
}
|
||||
|
||||
irq = bcma_core_mips_irq(cc->core);
|
||||
irq = bcma_core_irq(cc->core);
|
||||
|
||||
/* Determine the registers of the UARTs */
|
||||
cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
|
||||
|
@ -74,28 +74,41 @@ static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
|
||||
return dev->core_index;
|
||||
flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);
|
||||
|
||||
return flag & 0x1F;
|
||||
if (flag)
|
||||
return flag & 0x1F;
|
||||
else
|
||||
return 0x3f;
|
||||
}
|
||||
|
||||
/* Get the MIPS IRQ assignment for a specified device.
|
||||
* If unassigned, 0 is returned.
|
||||
* If disabled, 5 is returned.
|
||||
* If not supported, 6 is returned.
|
||||
*/
|
||||
unsigned int bcma_core_mips_irq(struct bcma_device *dev)
|
||||
static unsigned int bcma_core_mips_irq(struct bcma_device *dev)
|
||||
{
|
||||
struct bcma_device *mdev = dev->bus->drv_mips.core;
|
||||
u32 irqflag;
|
||||
unsigned int irq;
|
||||
|
||||
irqflag = bcma_core_mips_irqflag(dev);
|
||||
if (irqflag == 0x3f)
|
||||
return 6;
|
||||
|
||||
for (irq = 1; irq <= 4; irq++)
|
||||
for (irq = 0; irq <= 4; irq++)
|
||||
if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
|
||||
(1 << irqflag))
|
||||
return irq;
|
||||
|
||||
return 0;
|
||||
return 5;
|
||||
}
|
||||
EXPORT_SYMBOL(bcma_core_mips_irq);
|
||||
|
||||
unsigned int bcma_core_irq(struct bcma_device *dev)
|
||||
{
|
||||
unsigned int mips_irq = bcma_core_mips_irq(dev);
|
||||
return mips_irq <= 4 ? mips_irq + 2 : 0;
|
||||
}
|
||||
EXPORT_SYMBOL(bcma_core_irq);
|
||||
|
||||
static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
|
||||
{
|
||||
@ -114,7 +127,7 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
|
||||
bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
|
||||
bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
|
||||
~(1 << irqflag));
|
||||
else
|
||||
else if (oldirq != 5)
|
||||
bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);
|
||||
|
||||
/* assign the new one */
|
||||
@ -123,9 +136,9 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
|
||||
bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
|
||||
(1 << irqflag));
|
||||
} else {
|
||||
u32 oldirqflag = bcma_read32(mdev,
|
||||
BCMA_MIPS_MIPS74K_INTMASK(irq));
|
||||
if (oldirqflag) {
|
||||
u32 irqinitmask = bcma_read32(mdev,
|
||||
BCMA_MIPS_MIPS74K_INTMASK(irq));
|
||||
if (irqinitmask) {
|
||||
struct bcma_device *core;
|
||||
|
||||
/* backplane irq line is in use, find out who uses
|
||||
@ -133,7 +146,7 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
|
||||
*/
|
||||
list_for_each_entry(core, &bus->cores, list) {
|
||||
if ((1 << bcma_core_mips_irqflag(core)) ==
|
||||
oldirqflag) {
|
||||
irqinitmask) {
|
||||
bcma_core_mips_set_irq(core, 0);
|
||||
break;
|
||||
}
|
||||
@ -143,15 +156,31 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
|
||||
1 << irqflag);
|
||||
}
|
||||
|
||||
bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n",
|
||||
dev->id.id, oldirq + 2, irq + 2);
|
||||
bcma_debug(bus, "set_irq: core 0x%04x, irq %d => %d\n",
|
||||
dev->id.id, oldirq <= 4 ? oldirq + 2 : 0, irq + 2);
|
||||
}
|
||||
|
||||
static void bcma_core_mips_set_irq_name(struct bcma_bus *bus, unsigned int irq,
|
||||
u16 coreid, u8 unit)
|
||||
{
|
||||
struct bcma_device *core;
|
||||
|
||||
core = bcma_find_core_unit(bus, coreid, unit);
|
||||
if (!core) {
|
||||
bcma_warn(bus,
|
||||
"Can not find core (id: 0x%x, unit %i) for IRQ configuration.\n",
|
||||
coreid, unit);
|
||||
return;
|
||||
}
|
||||
|
||||
bcma_core_mips_set_irq(core, irq);
|
||||
}
|
||||
|
||||
static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
|
||||
{
|
||||
int i;
|
||||
static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
|
||||
printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
|
||||
printk(KERN_DEBUG KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
|
||||
for (i = 0; i <= 6; i++)
|
||||
printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
|
||||
printk("\n");
|
||||
@ -227,6 +256,32 @@ void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
|
||||
mcore->early_setup_done = true;
|
||||
}
|
||||
|
||||
static void bcma_fix_i2s_irqflag(struct bcma_bus *bus)
|
||||
{
|
||||
struct bcma_device *cpu, *pcie, *i2s;
|
||||
|
||||
/* Fixup the interrupts in 4716/4748 for i2s core (2010 Broadcom SDK)
|
||||
* (IRQ flags > 7 are ignored when setting the interrupt masks)
|
||||
*/
|
||||
if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4716 &&
|
||||
bus->chipinfo.id != BCMA_CHIP_ID_BCM4748)
|
||||
return;
|
||||
|
||||
cpu = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
|
||||
pcie = bcma_find_core(bus, BCMA_CORE_PCIE);
|
||||
i2s = bcma_find_core(bus, BCMA_CORE_I2S);
|
||||
if (cpu && pcie && i2s &&
|
||||
bcma_aread32(cpu, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
|
||||
bcma_aread32(pcie, BCMA_MIPS_OOBSELINA74) == 0x08060504 &&
|
||||
bcma_aread32(i2s, BCMA_MIPS_OOBSELOUTA30) == 0x88) {
|
||||
bcma_awrite32(cpu, BCMA_MIPS_OOBSELINA74, 0x07060504);
|
||||
bcma_awrite32(pcie, BCMA_MIPS_OOBSELINA74, 0x07060504);
|
||||
bcma_awrite32(i2s, BCMA_MIPS_OOBSELOUTA30, 0x87);
|
||||
bcma_debug(bus,
|
||||
"Moved i2s interrupt to oob line 7 instead of 8\n");
|
||||
}
|
||||
}
|
||||
|
||||
void bcma_core_mips_init(struct bcma_drv_mips *mcore)
|
||||
{
|
||||
struct bcma_bus *bus;
|
||||
@ -236,43 +291,55 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
|
||||
if (mcore->setup_done)
|
||||
return;
|
||||
|
||||
bcma_info(bus, "Initializing MIPS core...\n");
|
||||
bcma_debug(bus, "Initializing MIPS core...\n");
|
||||
|
||||
bcma_core_mips_early_init(mcore);
|
||||
|
||||
mcore->assigned_irqs = 1;
|
||||
bcma_fix_i2s_irqflag(bus);
|
||||
|
||||
/* Assign IRQs to all cores on the bus */
|
||||
list_for_each_entry(core, &bus->cores, list) {
|
||||
int mips_irq;
|
||||
if (core->irq)
|
||||
continue;
|
||||
|
||||
mips_irq = bcma_core_mips_irq(core);
|
||||
if (mips_irq > 4)
|
||||
core->irq = 0;
|
||||
else
|
||||
core->irq = mips_irq + 2;
|
||||
if (core->irq > 5)
|
||||
continue;
|
||||
switch (core->id.id) {
|
||||
case BCMA_CORE_PCI:
|
||||
case BCMA_CORE_PCIE:
|
||||
case BCMA_CORE_ETHERNET:
|
||||
case BCMA_CORE_ETHERNET_GBIT:
|
||||
case BCMA_CORE_MAC_GBIT:
|
||||
case BCMA_CORE_80211:
|
||||
case BCMA_CORE_USB20_HOST:
|
||||
/* These devices get their own IRQ line if available,
|
||||
* the rest goes on IRQ0
|
||||
*/
|
||||
if (mcore->assigned_irqs <= 4)
|
||||
bcma_core_mips_set_irq(core,
|
||||
mcore->assigned_irqs++);
|
||||
break;
|
||||
switch (bus->chipinfo.id) {
|
||||
case BCMA_CHIP_ID_BCM4716:
|
||||
case BCMA_CHIP_ID_BCM4748:
|
||||
bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_PCIE, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
|
||||
break;
|
||||
case BCMA_CHIP_ID_BCM5356:
|
||||
case BCMA_CHIP_ID_BCM47162:
|
||||
case BCMA_CHIP_ID_BCM53572:
|
||||
bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
|
||||
break;
|
||||
case BCMA_CHIP_ID_BCM5357:
|
||||
case BCMA_CHIP_ID_BCM4749:
|
||||
bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_80211, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_MAC_GBIT, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_USB20_HOST, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_CHIPCOMMON, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_I2S, 0);
|
||||
break;
|
||||
case BCMA_CHIP_ID_BCM4706:
|
||||
bcma_core_mips_set_irq_name(bus, 1, BCMA_CORE_PCIE, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 2, BCMA_CORE_4706_MAC_GBIT,
|
||||
0);
|
||||
bcma_core_mips_set_irq_name(bus, 3, BCMA_CORE_PCIE, 1);
|
||||
bcma_core_mips_set_irq_name(bus, 4, BCMA_CORE_USB20_HOST, 0);
|
||||
bcma_core_mips_set_irq_name(bus, 0, BCMA_CORE_4706_CHIPCOMMON,
|
||||
0);
|
||||
break;
|
||||
default:
|
||||
list_for_each_entry(core, &bus->cores, list) {
|
||||
core->irq = bcma_core_irq(core);
|
||||
}
|
||||
bcma_err(bus,
|
||||
"Unknown device (0x%x) found, can not configure IRQs\n",
|
||||
bus->chipinfo.id);
|
||||
}
|
||||
bcma_info(bus, "IRQ reconfiguration done\n");
|
||||
bcma_debug(bus, "IRQ reconfiguration done\n");
|
||||
bcma_core_mips_dump_irq(bus);
|
||||
|
||||
mcore->setup_done = true;
|
||||
|
@ -94,19 +94,19 @@ static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev,
|
||||
if (dev == 0) {
|
||||
/* we support only two functions on device 0 */
|
||||
if (func > 1)
|
||||
return -EINVAL;
|
||||
goto out;
|
||||
|
||||
/* accesses to config registers with offsets >= 256
|
||||
* requires indirect access.
|
||||
*/
|
||||
if (off >= PCI_CONFIG_SPACE_SIZE) {
|
||||
addr = (func << 12);
|
||||
addr |= (off & 0x0FFF);
|
||||
addr |= (off & 0x0FFC);
|
||||
val = bcma_pcie_read_config(pc, addr);
|
||||
} else {
|
||||
addr = BCMA_CORE_PCI_PCICFG0;
|
||||
addr |= (func << 8);
|
||||
addr |= (off & 0xfc);
|
||||
addr |= (off & 0xFC);
|
||||
val = pcicore_read32(pc, addr);
|
||||
}
|
||||
} else {
|
||||
@ -119,11 +119,9 @@ static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev,
|
||||
goto out;
|
||||
|
||||
if (mips_busprobe32(val, mmio)) {
|
||||
val = 0xffffffff;
|
||||
val = 0xFFFFFFFF;
|
||||
goto unmap;
|
||||
}
|
||||
|
||||
val = readl(mmio);
|
||||
}
|
||||
val >>= (8 * (off & 3));
|
||||
|
||||
@ -151,7 +149,7 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
|
||||
const void *buf, int len)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
u32 addr = 0, val = 0;
|
||||
u32 addr, val;
|
||||
void __iomem *mmio = 0;
|
||||
u16 chipid = pc->core->bus->chipinfo.id;
|
||||
|
||||
@ -159,16 +157,22 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
|
||||
if (unlikely(len != 1 && len != 2 && len != 4))
|
||||
goto out;
|
||||
if (dev == 0) {
|
||||
/* we support only two functions on device 0 */
|
||||
if (func > 1)
|
||||
goto out;
|
||||
|
||||
/* accesses to config registers with offsets >= 256
|
||||
* requires indirect access.
|
||||
*/
|
||||
if (off < PCI_CONFIG_SPACE_SIZE) {
|
||||
addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0;
|
||||
if (off >= PCI_CONFIG_SPACE_SIZE) {
|
||||
addr = (func << 12);
|
||||
addr |= (off & 0x0FFC);
|
||||
val = bcma_pcie_read_config(pc, addr);
|
||||
} else {
|
||||
addr = BCMA_CORE_PCI_PCICFG0;
|
||||
addr |= (func << 8);
|
||||
addr |= (off & 0xfc);
|
||||
mmio = ioremap_nocache(addr, sizeof(val));
|
||||
if (!mmio)
|
||||
goto out;
|
||||
addr |= (off & 0xFC);
|
||||
val = pcicore_read32(pc, addr);
|
||||
}
|
||||
} else {
|
||||
addr = bcma_get_cfgspace_addr(pc, dev, func, off);
|
||||
@ -180,19 +184,17 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
|
||||
goto out;
|
||||
|
||||
if (mips_busprobe32(val, mmio)) {
|
||||
val = 0xffffffff;
|
||||
val = 0xFFFFFFFF;
|
||||
goto unmap;
|
||||
}
|
||||
}
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
val = readl(mmio);
|
||||
val &= ~(0xFF << (8 * (off & 3)));
|
||||
val |= *((const u8 *)buf) << (8 * (off & 3));
|
||||
break;
|
||||
case 2:
|
||||
val = readl(mmio);
|
||||
val &= ~(0xFFFF << (8 * (off & 3)));
|
||||
val |= *((const u16 *)buf) << (8 * (off & 3));
|
||||
break;
|
||||
@ -200,13 +202,14 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev,
|
||||
val = *((const u32 *)buf);
|
||||
break;
|
||||
}
|
||||
if (dev == 0 && !addr) {
|
||||
if (dev == 0) {
|
||||
/* accesses to config registers with offsets >= 256
|
||||
* requires indirect access.
|
||||
*/
|
||||
addr = (func << 12);
|
||||
addr |= (off & 0x0FFF);
|
||||
bcma_pcie_write_config(pc, addr, val);
|
||||
if (off >= PCI_CONFIG_SPACE_SIZE)
|
||||
bcma_pcie_write_config(pc, addr, val);
|
||||
else
|
||||
pcicore_write32(pc, addr, val);
|
||||
} else {
|
||||
writel(val, mmio);
|
||||
|
||||
@ -276,7 +279,7 @@ static u8 bcma_find_pci_capability(struct bcma_drv_pci *pc, unsigned int dev,
|
||||
/* check for Header type 0 */
|
||||
bcma_extpci_read_config(pc, dev, func, PCI_HEADER_TYPE, &byte_val,
|
||||
sizeof(u8));
|
||||
if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL)
|
||||
if ((byte_val & 0x7F) != PCI_HEADER_TYPE_NORMAL)
|
||||
return cap_ptr;
|
||||
|
||||
/* check if the capability pointer field exists */
|
||||
@ -426,7 +429,7 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
||||
/* Reset RC */
|
||||
usleep_range(3000, 5000);
|
||||
pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE);
|
||||
usleep_range(1000, 2000);
|
||||
msleep(50);
|
||||
pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST |
|
||||
BCMA_CORE_PCI_CTL_RST_OE);
|
||||
|
||||
@ -488,6 +491,17 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
||||
|
||||
bcma_core_pci_enable_crs(pc);
|
||||
|
||||
if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706 ||
|
||||
bus->chipinfo.id == BCMA_CHIP_ID_BCM4716) {
|
||||
u16 val16;
|
||||
bcma_extpci_read_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL,
|
||||
&val16, sizeof(val16));
|
||||
val16 |= (2 << 5); /* Max payload size of 512 */
|
||||
val16 |= (2 << 12); /* MRRS 512 */
|
||||
bcma_extpci_write_config(pc, 0, 0, BCMA_CORE_PCI_CFG_DEVCTRL,
|
||||
&val16, sizeof(val16));
|
||||
}
|
||||
|
||||
/* Enable PCI bridge BAR0 memory & master access */
|
||||
tmp = PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
|
||||
bcma_extpci_write_config(pc, 0, 0, PCI_COMMAND, &tmp, sizeof(tmp));
|
||||
@ -576,7 +590,7 @@ int bcma_core_pci_plat_dev_init(struct pci_dev *dev)
|
||||
pr_info("PCI: Fixing up device %s\n", pci_name(dev));
|
||||
|
||||
/* Fix up interrupt lines */
|
||||
dev->irq = bcma_core_mips_irq(pc_host->pdev->core) + 2;
|
||||
dev->irq = bcma_core_irq(pc_host->pdev->core);
|
||||
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
|
||||
|
||||
return 0;
|
||||
@ -595,6 +609,6 @@ int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev)
|
||||
|
||||
pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
|
||||
pci_ops);
|
||||
return bcma_core_mips_irq(pc_host->pdev->core) + 2;
|
||||
return bcma_core_irq(pc_host->pdev->core);
|
||||
}
|
||||
EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq);
|
||||
|
@ -81,8 +81,8 @@ struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bcma_find_core);
|
||||
|
||||
static struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
|
||||
u8 unit)
|
||||
struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
|
||||
u8 unit)
|
||||
{
|
||||
struct bcma_device *core;
|
||||
|
||||
|
@ -77,10 +77,15 @@ static struct usb_device_id ath3k_table[] = {
|
||||
{ USB_DEVICE(0x0CF3, 0x311D) },
|
||||
{ USB_DEVICE(0x13d3, 0x3375) },
|
||||
{ USB_DEVICE(0x04CA, 0x3005) },
|
||||
{ USB_DEVICE(0x04CA, 0x3006) },
|
||||
{ USB_DEVICE(0x04CA, 0x3008) },
|
||||
{ USB_DEVICE(0x13d3, 0x3362) },
|
||||
{ USB_DEVICE(0x0CF3, 0xE004) },
|
||||
{ USB_DEVICE(0x0930, 0x0219) },
|
||||
{ USB_DEVICE(0x0489, 0xe057) },
|
||||
{ USB_DEVICE(0x13d3, 0x3393) },
|
||||
{ USB_DEVICE(0x0489, 0xe04e) },
|
||||
{ USB_DEVICE(0x0489, 0xe056) },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xE02C) },
|
||||
@ -104,10 +109,15 @@ static struct usb_device_id ath3k_blist_tbl[] = {
|
||||
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU22 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
|
||||
|
@ -135,10 +135,15 @@ static struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
|
||||
|
@ -240,13 +240,14 @@ static const struct ath_ops ath5k_common_ops = {
|
||||
* Driver Initialization *
|
||||
\***********************/
|
||||
|
||||
static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
|
||||
static void ath5k_reg_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct ath5k_hw *ah = hw->priv;
|
||||
struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah);
|
||||
|
||||
return ath_reg_notifier_apply(wiphy, request, regulatory);
|
||||
ath_reg_notifier_apply(wiphy, request, regulatory);
|
||||
}
|
||||
|
||||
/********************\
|
||||
|
@ -3492,8 +3492,8 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
|
||||
ath6kl_cfg80211_stop(vif);
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_reg_notify(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
static void ath6kl_cfg80211_reg_notify(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct ath6kl *ar = wiphy_priv(wiphy);
|
||||
u32 rates[IEEE80211_NUM_BANDS];
|
||||
@ -3506,17 +3506,13 @@ static int ath6kl_cfg80211_reg_notify(struct wiphy *wiphy,
|
||||
request->processed ? " processed" : "",
|
||||
request->initiator, request->user_reg_hint_type);
|
||||
|
||||
/*
|
||||
* As firmware is not able intersect regdoms, we can only listen to
|
||||
* cellular hints.
|
||||
*/
|
||||
if (request->user_reg_hint_type != NL80211_USER_REG_HINT_CELL_BASE)
|
||||
return -EOPNOTSUPP;
|
||||
return;
|
||||
|
||||
ret = ath6kl_wmi_set_regdomain_cmd(ar->wmi, request->alpha2);
|
||||
if (ret) {
|
||||
ath6kl_err("failed to set regdomain: %d\n", ret);
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3536,10 +3532,8 @@ static int ath6kl_cfg80211_reg_notify(struct wiphy *wiphy,
|
||||
if (ret) {
|
||||
ath6kl_err("failed to start scan for a regdomain change: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif)
|
||||
|
@ -86,29 +86,25 @@ static int ath_ahb_probe(struct platform_device *pdev)
|
||||
|
||||
if (!pdev->dev.platform_data) {
|
||||
dev_err(&pdev->dev, "no platform data specified\n");
|
||||
ret = -EINVAL;
|
||||
goto err_out;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "no memory resource found\n");
|
||||
ret = -ENXIO;
|
||||
goto err_out;
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
mem = ioremap_nocache(res->start, resource_size(res));
|
||||
mem = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res));
|
||||
if (mem == NULL) {
|
||||
dev_err(&pdev->dev, "ioremap failed\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_out;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "no IRQ resource found\n");
|
||||
ret = -ENXIO;
|
||||
goto err_iounmap;
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
irq = res->start;
|
||||
@ -116,8 +112,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
|
||||
hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
|
||||
if (hw == NULL) {
|
||||
dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_iounmap;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
SET_IEEE80211_DEV(hw, &pdev->dev);
|
||||
@ -156,9 +151,6 @@ static int ath_ahb_probe(struct platform_device *pdev)
|
||||
err_free_hw:
|
||||
ieee80211_free_hw(hw);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
err_iounmap:
|
||||
iounmap(mem);
|
||||
err_out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -168,12 +160,10 @@ static int ath_ahb_remove(struct platform_device *pdev)
|
||||
|
||||
if (hw) {
|
||||
struct ath_softc *sc = hw->priv;
|
||||
void __iomem *mem = sc->mem;
|
||||
|
||||
ath9k_deinit_device(sc);
|
||||
free_irq(sc->irq, sc);
|
||||
ieee80211_free_hw(sc->hw);
|
||||
iounmap(mem);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,8 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel,
|
||||
ath_dbg(common, ANI, "**** ofdmlevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
|
||||
aniState->ofdmNoiseImmunityLevel,
|
||||
immunityLevel, BEACON_RSSI(ah),
|
||||
aniState->rssiThrLow, aniState->rssiThrHigh);
|
||||
ATH9K_ANI_RSSI_THR_LOW,
|
||||
ATH9K_ANI_RSSI_THR_HIGH);
|
||||
|
||||
if (!scan)
|
||||
aniState->ofdmNoiseImmunityLevel = immunityLevel;
|
||||
@ -173,7 +174,7 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel,
|
||||
|
||||
weak_sig = entry_ofdm->ofdm_weak_signal_on;
|
||||
if (ah->opmode == NL80211_IFTYPE_STATION &&
|
||||
BEACON_RSSI(ah) <= aniState->rssiThrHigh)
|
||||
BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_HIGH)
|
||||
weak_sig = true;
|
||||
|
||||
if (aniState->ofdmWeakSigDetect != weak_sig)
|
||||
@ -216,11 +217,11 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel,
|
||||
|
||||
ath_dbg(common, ANI, "**** ccklevel %d=>%d, rssi=%d[lo=%d hi=%d]\n",
|
||||
aniState->cckNoiseImmunityLevel, immunityLevel,
|
||||
BEACON_RSSI(ah), aniState->rssiThrLow,
|
||||
aniState->rssiThrHigh);
|
||||
BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW,
|
||||
ATH9K_ANI_RSSI_THR_HIGH);
|
||||
|
||||
if (ah->opmode == NL80211_IFTYPE_STATION &&
|
||||
BEACON_RSSI(ah) <= aniState->rssiThrLow &&
|
||||
BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW &&
|
||||
immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
|
||||
immunityLevel = ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI;
|
||||
|
||||
@ -418,9 +419,6 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
return;
|
||||
|
||||
aniState = &ah->curchan->ani;
|
||||
if (WARN_ON(!aniState))
|
||||
return;
|
||||
|
||||
if (!ath9k_hw_ani_read_counters(ah))
|
||||
return;
|
||||
|
||||
@ -489,23 +487,6 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);
|
||||
|
||||
void ath9k_hw_ani_setup(struct ath_hw *ah)
|
||||
{
|
||||
int i;
|
||||
|
||||
static const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
|
||||
static const int coarseHigh[] = { -14, -14, -14, -14, -12 };
|
||||
static const int coarseLow[] = { -64, -64, -64, -64, -70 };
|
||||
static const int firpwr[] = { -78, -78, -78, -78, -80 };
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
ah->totalSizeDesired[i] = totalSizeDesired[i];
|
||||
ah->coarse_high[i] = coarseHigh[i];
|
||||
ah->coarse_low[i] = coarseLow[i];
|
||||
ah->firpwr[i] = firpwr[i];
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_hw_ani_init(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
@ -531,8 +512,6 @@ void ath9k_hw_ani_init(struct ath_hw *ah)
|
||||
|
||||
ani->ofdmsTurn = true;
|
||||
|
||||
ani->rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
|
||||
ani->rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
|
||||
ani->ofdmWeakSigDetect = ATH9K_ANI_USE_OFDM_WEAK_SIG;
|
||||
ani->cckNoiseImmunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
|
||||
ani->ofdmNoiseImmunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
|
||||
|
@ -104,7 +104,6 @@ struct ath9k_ani_default {
|
||||
};
|
||||
|
||||
struct ar5416AniState {
|
||||
struct ath9k_channel *c;
|
||||
u8 noiseImmunityLevel;
|
||||
u8 ofdmNoiseImmunityLevel;
|
||||
u8 cckNoiseImmunityLevel;
|
||||
@ -113,15 +112,9 @@ struct ar5416AniState {
|
||||
u8 spurImmunityLevel;
|
||||
u8 firstepLevel;
|
||||
u8 ofdmWeakSigDetect;
|
||||
u8 cckWeakSigThreshold;
|
||||
u32 listenTime;
|
||||
int32_t rssiThrLow;
|
||||
int32_t rssiThrHigh;
|
||||
u32 ofdmPhyErrCount;
|
||||
u32 cckPhyErrCount;
|
||||
int16_t pktRssi[2];
|
||||
int16_t ofdmErrRssi[2];
|
||||
int16_t cckErrRssi[2];
|
||||
struct ath9k_ani_default iniDef;
|
||||
};
|
||||
|
||||
@ -147,7 +140,6 @@ struct ar5416Stats {
|
||||
|
||||
void ath9k_enable_mib_counters(struct ath_hw *ah);
|
||||
void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_setup(struct ath_hw *ah);
|
||||
void ath9k_hw_ani_init(struct ath_hw *ah);
|
||||
|
||||
#endif /* ANI_H */
|
||||
|
@ -466,7 +466,7 @@ static const u32 ar5416Bank0[][2] = {
|
||||
};
|
||||
|
||||
static const u32 ar5416BB_RfGain[][3] = {
|
||||
/* Addr 5G_HT20 5G_HT40 */
|
||||
/* Addr 5G 2G */
|
||||
{0x00009a00, 0x00000000, 0x00000000},
|
||||
{0x00009a04, 0x00000040, 0x00000040},
|
||||
{0x00009a08, 0x00000080, 0x00000080},
|
||||
@ -546,12 +546,12 @@ static const u32 ar5416Bank2[][2] = {
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank3[][3] = {
|
||||
/* Addr 5G_HT20 5G_HT40 */
|
||||
/* Addr 5G 2G */
|
||||
{0x000098f0, 0x01400018, 0x01c00018},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank6[][3] = {
|
||||
/* Addr 5G_HT20 5G_HT40 */
|
||||
/* Addr 5G 2G */
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
@ -588,7 +588,7 @@ static const u32 ar5416Bank6[][3] = {
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank6TPC[][3] = {
|
||||
/* Addr 5G_HT20 5G_HT40 */
|
||||
/* Addr 5G 2G */
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
|
@ -470,16 +470,15 @@ static void ar5008_hw_spur_mitigate(struct ath_hw *ah,
|
||||
static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah)
|
||||
{
|
||||
#define ATH_ALLOC_BANK(bank, size) do { \
|
||||
bank = kzalloc((sizeof(u32) * size), GFP_KERNEL); \
|
||||
if (!bank) { \
|
||||
ath_err(common, "Cannot allocate RF banks\n"); \
|
||||
return -ENOMEM; \
|
||||
} \
|
||||
bank = devm_kzalloc(ah->dev, sizeof(u32) * size, GFP_KERNEL); \
|
||||
if (!bank) \
|
||||
goto error; \
|
||||
} while (0);
|
||||
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
return 0;
|
||||
|
||||
ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows);
|
||||
ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows);
|
||||
@ -492,35 +491,12 @@ static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah)
|
||||
|
||||
return 0;
|
||||
#undef ATH_ALLOC_BANK
|
||||
error:
|
||||
ath_err(common, "Cannot allocate RF banks\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ar5008_hw_rf_free_ext_banks - Free memory for analog bank scratch buffers
|
||||
* @ah: atheros hardware struture
|
||||
* For the external AR2133/AR5133 radios banks.
|
||||
*/
|
||||
static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah)
|
||||
{
|
||||
#define ATH_FREE_BANK(bank) do { \
|
||||
kfree(bank); \
|
||||
bank = NULL; \
|
||||
} while (0);
|
||||
|
||||
BUG_ON(AR_SREV_9280_20_OR_LATER(ah));
|
||||
|
||||
ATH_FREE_BANK(ah->analogBank0Data);
|
||||
ATH_FREE_BANK(ah->analogBank1Data);
|
||||
ATH_FREE_BANK(ah->analogBank2Data);
|
||||
ATH_FREE_BANK(ah->analogBank3Data);
|
||||
ATH_FREE_BANK(ah->analogBank6Data);
|
||||
ATH_FREE_BANK(ah->analogBank6TPCData);
|
||||
ATH_FREE_BANK(ah->analogBank7Data);
|
||||
ATH_FREE_BANK(ah->bank6Temp);
|
||||
|
||||
#undef ATH_FREE_BANK
|
||||
}
|
||||
|
||||
/* *
|
||||
* ar5008_hw_set_rf_regs - programs rf registers based on EEPROM
|
||||
* @ah: atheros hardware structure
|
||||
@ -1380,7 +1356,7 @@ static void ar5008_hw_set_radar_conf(struct ath_hw *ah)
|
||||
conf->radar_inband = 8;
|
||||
}
|
||||
|
||||
void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
|
||||
int ar5008_hw_attach_phy_ops(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
|
||||
static const u32 ar5416_cca_regs[6] = {
|
||||
@ -1391,12 +1367,15 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
|
||||
AR_PHY_CH1_EXT_CCA,
|
||||
AR_PHY_CH2_EXT_CCA
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = ar5008_hw_rf_alloc_ext_banks(ah);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv_ops->rf_set_freq = ar5008_hw_set_channel;
|
||||
priv_ops->spur_mitigate_freq = ar5008_hw_spur_mitigate;
|
||||
|
||||
priv_ops->rf_alloc_ext_banks = ar5008_hw_rf_alloc_ext_banks;
|
||||
priv_ops->rf_free_ext_banks = ar5008_hw_rf_free_ext_banks;
|
||||
priv_ops->set_rf_regs = ar5008_hw_set_rf_regs;
|
||||
priv_ops->set_channel_regs = ar5008_hw_set_channel_regs;
|
||||
priv_ops->init_bb = ar5008_hw_init_bb;
|
||||
@ -1421,4 +1400,5 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
|
||||
ar5008_hw_set_nf_limits(ah);
|
||||
ar5008_hw_set_radar_conf(ah);
|
||||
memcpy(ah->nf_regs, ar5416_cca_regs, sizeof(ah->nf_regs));
|
||||
return 0;
|
||||
}
|
||||
|
@ -460,7 +460,7 @@ static const u32 ar5416Common_9100[][2] = {
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank6_9100[][3] = {
|
||||
/* Addr 5G_HT20 5G_HT40 */
|
||||
/* Addr 5G 2G */
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
@ -497,7 +497,7 @@ static const u32 ar5416Bank6_9100[][3] = {
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank6TPC_9100[][3] = {
|
||||
/* Addr 5G_HT20 5G_HT40 */
|
||||
/* Addr 5G 2G */
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
|
@ -23,13 +23,13 @@
|
||||
|
||||
/* General hardware code for the A5008/AR9001/AR9002 hadware families */
|
||||
|
||||
static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
|
||||
static int ar9002_hw_init_mode_regs(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9271(ah)) {
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ah->config.pcie_clock_req)
|
||||
@ -102,9 +102,9 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
|
||||
u32 size = sizeof(u32) * addac->ia_rows * addac->ia_columns;
|
||||
u32 *data;
|
||||
|
||||
data = kmalloc(size, GFP_KERNEL);
|
||||
data = devm_kzalloc(ah->dev, size, GFP_KERNEL);
|
||||
if (!data)
|
||||
return;
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(data, addac->ia_array, size);
|
||||
addac->ia_array = data;
|
||||
@ -120,6 +120,7 @@ static void ar9002_hw_init_mode_regs(struct ath_hw *ah)
|
||||
INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
|
||||
ar9287Common_japan_2484_cck_fir_coeff_9287_1_1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ar9280_20_hw_init_rxgain_ini(struct ath_hw *ah)
|
||||
@ -409,22 +410,30 @@ void ar9002_hw_enable_async_fifo(struct ath_hw *ah)
|
||||
}
|
||||
|
||||
/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
|
||||
void ar9002_hw_attach_ops(struct ath_hw *ah)
|
||||
int ar9002_hw_attach_ops(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
|
||||
struct ath_hw_ops *ops = ath9k_hw_ops(ah);
|
||||
int ret;
|
||||
|
||||
ret = ar9002_hw_init_mode_regs(ah);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
priv_ops->init_mode_regs = ar9002_hw_init_mode_regs;
|
||||
priv_ops->init_mode_gain_regs = ar9002_hw_init_mode_gain_regs;
|
||||
|
||||
ops->config_pci_powersave = ar9002_hw_configpcipowersave;
|
||||
|
||||
ar5008_hw_attach_phy_ops(ah);
|
||||
ret = ar5008_hw_attach_phy_ops(ah);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah))
|
||||
ar9002_hw_attach_phy_ops(ah);
|
||||
|
||||
ar9002_hw_attach_calib_ops(ah);
|
||||
ar9002_hw_attach_mac_ops(ah);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
|
@ -555,14 +555,73 @@ static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah,
|
||||
REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval);
|
||||
}
|
||||
|
||||
static void ar9002_hw_spectral_scan_config(struct ath_hw *ah,
|
||||
struct ath_spec_scan *param)
|
||||
{
|
||||
u8 count;
|
||||
|
||||
if (!param->enabled) {
|
||||
REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_ENABLE);
|
||||
return;
|
||||
}
|
||||
REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_FFT_ENA);
|
||||
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE);
|
||||
|
||||
if (param->short_repeat)
|
||||
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
|
||||
else
|
||||
REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
|
||||
|
||||
/* on AR92xx, the highest bit of count will make the the chip send
|
||||
* spectral samples endlessly. Check if this really was intended,
|
||||
* and fix otherwise.
|
||||
*/
|
||||
count = param->count;
|
||||
if (param->endless)
|
||||
count = 0x80;
|
||||
else if (count & 0x80)
|
||||
count = 0x7f;
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_COUNT, count);
|
||||
REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_PERIOD, param->period);
|
||||
REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_FFT_PERIOD, param->fft_period);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ar9002_hw_spectral_scan_trigger(struct ath_hw *ah)
|
||||
{
|
||||
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE);
|
||||
/* Activate spectral scan */
|
||||
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_ACTIVE);
|
||||
}
|
||||
|
||||
static void ar9002_hw_spectral_scan_wait(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
/* Poll for spectral scan complete */
|
||||
if (!ath9k_hw_wait(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_ACTIVE,
|
||||
0, AH_WAIT_TIMEOUT)) {
|
||||
ath_err(common, "spectral scan wait failed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
|
||||
struct ath_hw_ops *ops = ath9k_hw_ops(ah);
|
||||
|
||||
priv_ops->set_rf_regs = NULL;
|
||||
priv_ops->rf_alloc_ext_banks = NULL;
|
||||
priv_ops->rf_free_ext_banks = NULL;
|
||||
priv_ops->rf_set_freq = ar9002_hw_set_channel;
|
||||
priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate;
|
||||
priv_ops->olc_init = ar9002_olc_init;
|
||||
@ -571,6 +630,9 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
|
||||
|
||||
ops->antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get;
|
||||
ops->antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set;
|
||||
ops->spectral_scan_config = ar9002_hw_spectral_scan_config;
|
||||
ops->spectral_scan_trigger = ar9002_hw_spectral_scan_trigger;
|
||||
ops->spectral_scan_wait = ar9002_hw_spectral_scan_wait;
|
||||
|
||||
ar9002_hw_set_nf_limits(ah);
|
||||
}
|
||||
|
@ -744,6 +744,186 @@ static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
|
||||
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
};
|
||||
|
||||
static const u32 ar9300Modes_mixed_ob_db_tx_gain_table_2p2[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
||||
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
|
||||
{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
|
||||
{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
|
||||
{0x0000a514, 0x1c000223, 0x1c000223, 0x11000400, 0x11000400},
|
||||
{0x0000a518, 0x21002220, 0x21002220, 0x15000402, 0x15000402},
|
||||
{0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
|
||||
{0x0000a520, 0x2b022220, 0x2b022220, 0x1b000603, 0x1b000603},
|
||||
{0x0000a524, 0x2f022222, 0x2f022222, 0x1f000a02, 0x1f000a02},
|
||||
{0x0000a528, 0x34022225, 0x34022225, 0x23000a04, 0x23000a04},
|
||||
{0x0000a52c, 0x3a02222a, 0x3a02222a, 0x26000a20, 0x26000a20},
|
||||
{0x0000a530, 0x3e02222c, 0x3e02222c, 0x2a000e20, 0x2a000e20},
|
||||
{0x0000a534, 0x4202242a, 0x4202242a, 0x2e000e22, 0x2e000e22},
|
||||
{0x0000a538, 0x4702244a, 0x4702244a, 0x31000e24, 0x31000e24},
|
||||
{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x34001640, 0x34001640},
|
||||
{0x0000a540, 0x4e02246c, 0x4e02246c, 0x38001660, 0x38001660},
|
||||
{0x0000a544, 0x52022470, 0x52022470, 0x3b001861, 0x3b001861},
|
||||
{0x0000a548, 0x55022490, 0x55022490, 0x3e001a81, 0x3e001a81},
|
||||
{0x0000a54c, 0x59022492, 0x59022492, 0x42001a83, 0x42001a83},
|
||||
{0x0000a550, 0x5d022692, 0x5d022692, 0x44001c84, 0x44001c84},
|
||||
{0x0000a554, 0x61022892, 0x61022892, 0x48001ce3, 0x48001ce3},
|
||||
{0x0000a558, 0x65024890, 0x65024890, 0x4c001ce5, 0x4c001ce5},
|
||||
{0x0000a55c, 0x69024892, 0x69024892, 0x50001ce9, 0x50001ce9},
|
||||
{0x0000a560, 0x6e024c92, 0x6e024c92, 0x54001ceb, 0x54001ceb},
|
||||
{0x0000a564, 0x74026e92, 0x74026e92, 0x56001eec, 0x56001eec},
|
||||
{0x0000a568, 0x74026e92, 0x74026e92, 0x56001eec, 0x56001eec},
|
||||
{0x0000a56c, 0x74026e92, 0x74026e92, 0x56001eec, 0x56001eec},
|
||||
{0x0000a570, 0x74026e92, 0x74026e92, 0x56001eec, 0x56001eec},
|
||||
{0x0000a574, 0x74026e92, 0x74026e92, 0x56001eec, 0x56001eec},
|
||||
{0x0000a578, 0x74026e92, 0x74026e92, 0x56001eec, 0x56001eec},
|
||||
{0x0000a57c, 0x74026e92, 0x74026e92, 0x56001eec, 0x56001eec},
|
||||
{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
|
||||
{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
|
||||
{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
|
||||
{0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
|
||||
{0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
|
||||
{0x0000a594, 0x1c800223, 0x1c800223, 0x11800400, 0x11800400},
|
||||
{0x0000a598, 0x21802220, 0x21802220, 0x15800402, 0x15800402},
|
||||
{0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
|
||||
{0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800603, 0x1b800603},
|
||||
{0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800a02, 0x1f800a02},
|
||||
{0x0000a5a8, 0x34822225, 0x34822225, 0x23800a04, 0x23800a04},
|
||||
{0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x26800a20, 0x26800a20},
|
||||
{0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2a800e20, 0x2a800e20},
|
||||
{0x0000a5b4, 0x4282242a, 0x4282242a, 0x2e800e22, 0x2e800e22},
|
||||
{0x0000a5b8, 0x4782244a, 0x4782244a, 0x31800e24, 0x31800e24},
|
||||
{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x34801640, 0x34801640},
|
||||
{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38801660, 0x38801660},
|
||||
{0x0000a5c4, 0x52822470, 0x52822470, 0x3b801861, 0x3b801861},
|
||||
{0x0000a5c8, 0x55822490, 0x55822490, 0x3e801a81, 0x3e801a81},
|
||||
{0x0000a5cc, 0x59822492, 0x59822492, 0x42801a83, 0x42801a83},
|
||||
{0x0000a5d0, 0x5d822692, 0x5d822692, 0x44801c84, 0x44801c84},
|
||||
{0x0000a5d4, 0x61822892, 0x61822892, 0x48801ce3, 0x48801ce3},
|
||||
{0x0000a5d8, 0x65824890, 0x65824890, 0x4c801ce5, 0x4c801ce5},
|
||||
{0x0000a5dc, 0x69824892, 0x69824892, 0x50801ce9, 0x50801ce9},
|
||||
{0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x54801ceb, 0x54801ceb},
|
||||
{0x0000a5e4, 0x74826e92, 0x74826e92, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5e8, 0x74826e92, 0x74826e92, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5ec, 0x74826e92, 0x74826e92, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f0, 0x74826e92, 0x74826e92, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f4, 0x74826e92, 0x74826e92, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5f8, 0x74826e92, 0x74826e92, 0x56801eec, 0x56801eec},
|
||||
{0x0000a5fc, 0x74826e92, 0x74826e92, 0x56801eec, 0x56801eec},
|
||||
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
|
||||
{0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
|
||||
{0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
|
||||
{0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
|
||||
{0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
|
||||
{0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
|
||||
{0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||
{0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||
{0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||
{0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||
{0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||
{0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
{0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
{0x00016044, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4},
|
||||
{0x00016048, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001},
|
||||
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
{0x00016444, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4},
|
||||
{0x00016448, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001},
|
||||
{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
{0x00016844, 0x012492d4, 0x012492d4, 0x056db2e4, 0x056db2e4},
|
||||
{0x00016848, 0x66480001, 0x66480001, 0x8e480001, 0x8e480001},
|
||||
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
};
|
||||
|
||||
static const u32 ar9300Modes_type5_tx_gain_table_2p2[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
||||
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
|
||||
{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
|
||||
{0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202},
|
||||
{0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400},
|
||||
{0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402},
|
||||
{0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404},
|
||||
{0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603},
|
||||
{0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02},
|
||||
{0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04},
|
||||
{0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20},
|
||||
{0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20},
|
||||
{0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22},
|
||||
{0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24},
|
||||
{0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640},
|
||||
{0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660},
|
||||
{0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861},
|
||||
{0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81},
|
||||
{0x0000a54c, 0x5e08442e, 0x5e08442e, 0x47001a83, 0x47001a83},
|
||||
{0x0000a550, 0x620a4431, 0x620a4431, 0x4a001c84, 0x4a001c84},
|
||||
{0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3},
|
||||
{0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5},
|
||||
{0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9},
|
||||
{0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb},
|
||||
{0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
|
||||
{0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
|
||||
{0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
|
||||
{0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000},
|
||||
{0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501},
|
||||
{0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501},
|
||||
{0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03},
|
||||
{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
|
||||
{0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04},
|
||||
{0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
{0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016048, 0x65240001, 0x65240001, 0x66480001, 0x66480001},
|
||||
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016448, 0x65240001, 0x65240001, 0x66480001, 0x66480001},
|
||||
{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016848, 0x65240001, 0x65240001, 0x66480001, 0x66480001},
|
||||
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
};
|
||||
|
||||
static const u32 ar9300Common_rx_gain_table_2p2[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x0000a000, 0x00010000},
|
||||
|
@ -32,7 +32,6 @@ struct coeff {
|
||||
|
||||
enum ar9003_cal_types {
|
||||
IQ_MISMATCH_CAL = BIT(0),
|
||||
TEMP_COMP_CAL = BIT(1),
|
||||
};
|
||||
|
||||
static void ar9003_hw_setup_calibration(struct ath_hw *ah,
|
||||
@ -49,7 +48,7 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah,
|
||||
*/
|
||||
REG_RMW_FIELD(ah, AR_PHY_TIMING4,
|
||||
AR_PHY_TIMING4_IQCAL_LOG_COUNT_MAX,
|
||||
currCal->calData->calCountMax);
|
||||
currCal->calData->calCountMax);
|
||||
REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
|
||||
|
||||
ath_dbg(common, CALIBRATE,
|
||||
@ -58,14 +57,8 @@ static void ar9003_hw_setup_calibration(struct ath_hw *ah,
|
||||
/* Kick-off cal */
|
||||
REG_SET_BIT(ah, AR_PHY_TIMING4, AR_PHY_TIMING4_DO_CAL);
|
||||
break;
|
||||
case TEMP_COMP_CAL:
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
|
||||
AR_PHY_65NM_CH0_THERM_LOCAL, 1);
|
||||
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_THERM,
|
||||
AR_PHY_65NM_CH0_THERM_START, 1);
|
||||
|
||||
ath_dbg(common, CALIBRATE,
|
||||
"starting Temperature Compensation Calibration\n");
|
||||
default:
|
||||
ath_err(common, "Invalid calibration type\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -323,6 +316,14 @@ static const struct ath9k_percal_data iq_cal_single_sample = {
|
||||
static void ar9003_hw_init_cal_settings(struct ath_hw *ah)
|
||||
{
|
||||
ah->iq_caldata.calData = &iq_cal_single_sample;
|
||||
|
||||
if (AR_SREV_9300_20_OR_LATER(ah)) {
|
||||
ah->enabled_cals |= TX_IQ_CAL;
|
||||
if (AR_SREV_9485_OR_LATER(ah) && !AR_SREV_9340(ah))
|
||||
ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
|
||||
}
|
||||
|
||||
ah->supp_cals = IQ_MISMATCH_CAL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -959,22 +960,70 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
|
||||
AR_PHY_65NM_RXRF_AGC_AGC_CAL_OVR, 0);
|
||||
}
|
||||
|
||||
static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah))
|
||||
return;
|
||||
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (!(ah->rxchainmask & (1 << i)))
|
||||
continue;
|
||||
ar9003_hw_manual_peak_cal(ah, i, IS_CHAN_2GHZ(chan));
|
||||
}
|
||||
}
|
||||
|
||||
static void ar9003_hw_cl_cal_post_proc(struct ath_hw *ah, bool is_reusable)
|
||||
{
|
||||
u32 cl_idx[AR9300_MAX_CHAINS] = { AR_PHY_CL_TAB_0,
|
||||
AR_PHY_CL_TAB_1,
|
||||
AR_PHY_CL_TAB_2 };
|
||||
struct ath9k_hw_cal_data *caldata = ah->caldata;
|
||||
bool txclcal_done = false;
|
||||
int i, j;
|
||||
|
||||
if (!caldata || !(ah->enabled_cals & TX_CL_CAL))
|
||||
return;
|
||||
|
||||
txclcal_done = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) &
|
||||
AR_PHY_AGC_CONTROL_CLC_SUCCESS);
|
||||
|
||||
if (caldata->done_txclcal_once) {
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (!(ah->txchainmask & (1 << i)))
|
||||
continue;
|
||||
for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
|
||||
REG_WRITE(ah, CL_TAB_ENTRY(cl_idx[i]),
|
||||
caldata->tx_clcal[i][j]);
|
||||
}
|
||||
} else if (is_reusable && txclcal_done) {
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (!(ah->txchainmask & (1 << i)))
|
||||
continue;
|
||||
for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
|
||||
caldata->tx_clcal[i][j] =
|
||||
REG_READ(ah, CL_TAB_ENTRY(cl_idx[i]));
|
||||
}
|
||||
caldata->done_txclcal_once = true;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ar9003_hw_init_cal(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_hw_cal_data *caldata = ah->caldata;
|
||||
bool txiqcal_done = false, txclcal_done = false;
|
||||
bool txiqcal_done = false;
|
||||
bool is_reusable = true, status = true;
|
||||
bool run_rtt_cal = false, run_agc_cal;
|
||||
bool run_rtt_cal = false, run_agc_cal, sep_iq_cal = false;
|
||||
bool rtt = !!(ah->caps.hw_caps & ATH9K_HW_CAP_RTT);
|
||||
u32 agc_ctrl = 0, agc_supp_cals = AR_PHY_AGC_CONTROL_OFFSET_CAL |
|
||||
AR_PHY_AGC_CONTROL_FLTR_CAL |
|
||||
AR_PHY_AGC_CONTROL_PKDET_CAL;
|
||||
int i, j;
|
||||
u32 cl_idx[AR9300_MAX_CHAINS] = { AR_PHY_CL_TAB_0,
|
||||
AR_PHY_CL_TAB_1,
|
||||
AR_PHY_CL_TAB_2 };
|
||||
|
||||
ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
|
||||
|
||||
if (rtt) {
|
||||
if (!ar9003_hw_rtt_restore(ah, chan))
|
||||
@ -1012,7 +1061,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
|
||||
}
|
||||
}
|
||||
|
||||
if (!(ah->enabled_cals & TX_IQ_CAL))
|
||||
if ((IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan)) ||
|
||||
!(ah->enabled_cals & TX_IQ_CAL))
|
||||
goto skip_tx_iqcal;
|
||||
|
||||
/* Do Tx IQ Calibration */
|
||||
@ -1032,21 +1082,22 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
|
||||
REG_CLR_BIT(ah, AR_PHY_TX_IQCAL_CONTROL_0,
|
||||
AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL);
|
||||
txiqcal_done = run_agc_cal = true;
|
||||
goto skip_tx_iqcal;
|
||||
} else if (caldata && !caldata->done_txiqcal_once)
|
||||
} else if (caldata && !caldata->done_txiqcal_once) {
|
||||
run_agc_cal = true;
|
||||
sep_iq_cal = true;
|
||||
}
|
||||
|
||||
skip_tx_iqcal:
|
||||
if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
|
||||
ar9003_mci_init_cal_req(ah, &is_reusable);
|
||||
|
||||
if (!(IS_CHAN_HALF_RATE(chan) || IS_CHAN_QUARTER_RATE(chan))) {
|
||||
if (sep_iq_cal) {
|
||||
txiqcal_done = ar9003_hw_tx_iq_cal_run(ah);
|
||||
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
|
||||
udelay(5);
|
||||
REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
|
||||
}
|
||||
|
||||
skip_tx_iqcal:
|
||||
if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
|
||||
/* Calibrate the AGC */
|
||||
REG_WRITE(ah, AR_PHY_AGC_CONTROL,
|
||||
@ -1057,14 +1108,8 @@ skip_tx_iqcal:
|
||||
status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
|
||||
AR_PHY_AGC_CONTROL_CAL,
|
||||
0, AH_WAIT_TIMEOUT);
|
||||
if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (!(ah->rxchainmask & (1 << i)))
|
||||
continue;
|
||||
ar9003_hw_manual_peak_cal(ah, i,
|
||||
IS_CHAN_2GHZ(chan));
|
||||
}
|
||||
}
|
||||
|
||||
ar9003_hw_do_manual_peak_cal(ah, chan);
|
||||
}
|
||||
|
||||
if (ath9k_hw_mci_is_enabled(ah) && IS_CHAN_2GHZ(chan) && run_agc_cal)
|
||||
@ -1089,31 +1134,7 @@ skip_tx_iqcal:
|
||||
else if (caldata && caldata->done_txiqcal_once)
|
||||
ar9003_hw_tx_iq_cal_reload(ah);
|
||||
|
||||
#define CL_TAB_ENTRY(reg_base) (reg_base + (4 * j))
|
||||
if (caldata && (ah->enabled_cals & TX_CL_CAL)) {
|
||||
txclcal_done = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) &
|
||||
AR_PHY_AGC_CONTROL_CLC_SUCCESS);
|
||||
if (caldata->done_txclcal_once) {
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (!(ah->txchainmask & (1 << i)))
|
||||
continue;
|
||||
for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
|
||||
REG_WRITE(ah, CL_TAB_ENTRY(cl_idx[i]),
|
||||
caldata->tx_clcal[i][j]);
|
||||
}
|
||||
} else if (is_reusable && txclcal_done) {
|
||||
for (i = 0; i < AR9300_MAX_CHAINS; i++) {
|
||||
if (!(ah->txchainmask & (1 << i)))
|
||||
continue;
|
||||
for (j = 0; j < MAX_CL_TAB_ENTRY; j++)
|
||||
caldata->tx_clcal[i][j] =
|
||||
REG_READ(ah,
|
||||
CL_TAB_ENTRY(cl_idx[i]));
|
||||
}
|
||||
caldata->done_txclcal_once = true;
|
||||
}
|
||||
}
|
||||
#undef CL_TAB_ENTRY
|
||||
ar9003_hw_cl_cal_post_proc(ah, is_reusable);
|
||||
|
||||
if (run_rtt_cal && caldata) {
|
||||
if (is_reusable) {
|
||||
@ -1131,20 +1152,10 @@ skip_tx_iqcal:
|
||||
|
||||
/* Initialize list pointers */
|
||||
ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
|
||||
ah->supp_cals = IQ_MISMATCH_CAL;
|
||||
|
||||
if (ah->supp_cals & IQ_MISMATCH_CAL) {
|
||||
INIT_CAL(&ah->iq_caldata);
|
||||
INSERT_CAL(ah, &ah->iq_caldata);
|
||||
ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
|
||||
}
|
||||
|
||||
if (ah->supp_cals & TEMP_COMP_CAL) {
|
||||
INIT_CAL(&ah->tempCompCalData);
|
||||
INSERT_CAL(ah, &ah->tempCompCalData);
|
||||
ath_dbg(common, CALIBRATE,
|
||||
"enabling Temperature Compensation Calibration\n");
|
||||
}
|
||||
INIT_CAL(&ah->iq_caldata);
|
||||
INSERT_CAL(ah, &ah->iq_caldata);
|
||||
ath_dbg(common, CALIBRATE, "enabling IQ Calibration\n");
|
||||
|
||||
/* Initialize current pointer to first element in list */
|
||||
ah->cal_list_curr = ah->cal_list;
|
||||
|
@ -4586,14 +4586,14 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ar9003_hw_power_control_override(struct ath_hw *ah,
|
||||
int frequency,
|
||||
int *correction,
|
||||
int *voltage, int *temperature)
|
||||
static void ar9003_hw_power_control_override(struct ath_hw *ah,
|
||||
int frequency,
|
||||
int *correction,
|
||||
int *voltage, int *temperature)
|
||||
{
|
||||
int tempSlope = 0;
|
||||
int temp_slope = 0, temp_slope1 = 0, temp_slope2 = 0;
|
||||
struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
|
||||
int f[8], t[8], i;
|
||||
int f[8], t[8], t1[3], t2[3], i;
|
||||
|
||||
REG_RMW(ah, AR_PHY_TPC_11_B0,
|
||||
(correction[0] << AR_PHY_TPC_OLPC_GAIN_DELTA_S),
|
||||
@ -4624,38 +4624,108 @@ static int ar9003_hw_power_control_override(struct ath_hw *ah,
|
||||
* enable temperature compensation
|
||||
* Need to use register names
|
||||
*/
|
||||
if (frequency < 4000)
|
||||
tempSlope = eep->modalHeader2G.tempSlope;
|
||||
else if ((eep->baseEepHeader.miscConfiguration & 0x20) != 0) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
t[i] = eep->base_ext1.tempslopextension[i];
|
||||
f[i] = FBIN2FREQ(eep->calFreqPier5G[i], 0);
|
||||
}
|
||||
tempSlope = ar9003_hw_power_interpolate((s32) frequency,
|
||||
f, t, 8);
|
||||
} else if (eep->base_ext2.tempSlopeLow != 0) {
|
||||
t[0] = eep->base_ext2.tempSlopeLow;
|
||||
f[0] = 5180;
|
||||
t[1] = eep->modalHeader5G.tempSlope;
|
||||
f[1] = 5500;
|
||||
t[2] = eep->base_ext2.tempSlopeHigh;
|
||||
f[2] = 5785;
|
||||
tempSlope = ar9003_hw_power_interpolate((s32) frequency,
|
||||
f, t, 3);
|
||||
} else
|
||||
tempSlope = eep->modalHeader5G.tempSlope;
|
||||
if (frequency < 4000) {
|
||||
temp_slope = eep->modalHeader2G.tempSlope;
|
||||
} else {
|
||||
if (AR_SREV_9550(ah)) {
|
||||
t[0] = eep->base_ext1.tempslopextension[2];
|
||||
t1[0] = eep->base_ext1.tempslopextension[3];
|
||||
t2[0] = eep->base_ext1.tempslopextension[4];
|
||||
f[0] = 5180;
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_TPC_19, AR_PHY_TPC_19_ALPHA_THERM, tempSlope);
|
||||
t[1] = eep->modalHeader5G.tempSlope;
|
||||
t1[1] = eep->base_ext1.tempslopextension[0];
|
||||
t2[1] = eep->base_ext1.tempslopextension[1];
|
||||
f[1] = 5500;
|
||||
|
||||
t[2] = eep->base_ext1.tempslopextension[5];
|
||||
t1[2] = eep->base_ext1.tempslopextension[6];
|
||||
t2[2] = eep->base_ext1.tempslopextension[7];
|
||||
f[2] = 5785;
|
||||
|
||||
temp_slope = ar9003_hw_power_interpolate(frequency,
|
||||
f, t, 3);
|
||||
temp_slope1 = ar9003_hw_power_interpolate(frequency,
|
||||
f, t1, 3);
|
||||
temp_slope2 = ar9003_hw_power_interpolate(frequency,
|
||||
f, t2, 3);
|
||||
|
||||
goto tempslope;
|
||||
}
|
||||
|
||||
if ((eep->baseEepHeader.miscConfiguration & 0x20) != 0) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
t[i] = eep->base_ext1.tempslopextension[i];
|
||||
f[i] = FBIN2FREQ(eep->calFreqPier5G[i], 0);
|
||||
}
|
||||
temp_slope = ar9003_hw_power_interpolate((s32) frequency,
|
||||
f, t, 8);
|
||||
} else if (eep->base_ext2.tempSlopeLow != 0) {
|
||||
t[0] = eep->base_ext2.tempSlopeLow;
|
||||
f[0] = 5180;
|
||||
t[1] = eep->modalHeader5G.tempSlope;
|
||||
f[1] = 5500;
|
||||
t[2] = eep->base_ext2.tempSlopeHigh;
|
||||
f[2] = 5785;
|
||||
temp_slope = ar9003_hw_power_interpolate((s32) frequency,
|
||||
f, t, 3);
|
||||
} else {
|
||||
temp_slope = eep->modalHeader5G.tempSlope;
|
||||
}
|
||||
}
|
||||
|
||||
tempslope:
|
||||
if (AR_SREV_9550(ah)) {
|
||||
/*
|
||||
* AR955x has tempSlope register for each chain.
|
||||
* Check whether temp_compensation feature is enabled or not.
|
||||
*/
|
||||
if (eep->baseEepHeader.featureEnable & 0x1) {
|
||||
if (frequency < 4000) {
|
||||
REG_RMW_FIELD(ah, AR_PHY_TPC_19,
|
||||
AR_PHY_TPC_19_ALPHA_THERM,
|
||||
eep->base_ext2.tempSlopeLow);
|
||||
REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1,
|
||||
AR_PHY_TPC_19_ALPHA_THERM,
|
||||
temp_slope);
|
||||
REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2,
|
||||
AR_PHY_TPC_19_ALPHA_THERM,
|
||||
eep->base_ext2.tempSlopeHigh);
|
||||
} else {
|
||||
REG_RMW_FIELD(ah, AR_PHY_TPC_19,
|
||||
AR_PHY_TPC_19_ALPHA_THERM,
|
||||
temp_slope);
|
||||
REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1,
|
||||
AR_PHY_TPC_19_ALPHA_THERM,
|
||||
temp_slope1);
|
||||
REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2,
|
||||
AR_PHY_TPC_19_ALPHA_THERM,
|
||||
temp_slope2);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If temp compensation is not enabled,
|
||||
* set all registers to 0.
|
||||
*/
|
||||
REG_RMW_FIELD(ah, AR_PHY_TPC_19,
|
||||
AR_PHY_TPC_19_ALPHA_THERM, 0);
|
||||
REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1,
|
||||
AR_PHY_TPC_19_ALPHA_THERM, 0);
|
||||
REG_RMW_FIELD(ah, AR_PHY_TPC_19_B2,
|
||||
AR_PHY_TPC_19_ALPHA_THERM, 0);
|
||||
}
|
||||
} else {
|
||||
REG_RMW_FIELD(ah, AR_PHY_TPC_19,
|
||||
AR_PHY_TPC_19_ALPHA_THERM, temp_slope);
|
||||
}
|
||||
|
||||
if (AR_SREV_9462_20(ah))
|
||||
REG_RMW_FIELD(ah, AR_PHY_TPC_19_B1,
|
||||
AR_PHY_TPC_19_B1_ALPHA_THERM, tempSlope);
|
||||
AR_PHY_TPC_19_B1_ALPHA_THERM, temp_slope);
|
||||
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_TPC_18, AR_PHY_TPC_18_THERM_CAL_VALUE,
|
||||
temperature[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Apply the recorded correction values. */
|
||||
|
@ -507,28 +507,59 @@ static void ar9003_tx_gain_table_mode4(struct ath_hw *ah)
|
||||
else if (AR_SREV_9580(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9580_1p0_mixed_ob_db_tx_gain_table);
|
||||
else
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_mixed_ob_db_tx_gain_table_2p2);
|
||||
}
|
||||
|
||||
static void ar9003_tx_gain_table_mode5(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9485_11(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9485Modes_green_ob_db_tx_gain_1_1);
|
||||
else if (AR_SREV_9340(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9340Modes_ub124_tx_gain_table_1p0);
|
||||
else if (AR_SREV_9580(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9580_1p0_type5_tx_gain_table);
|
||||
else if (AR_SREV_9300_22(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9300Modes_type5_tx_gain_table_2p2);
|
||||
}
|
||||
|
||||
static void ar9003_tx_gain_table_mode6(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9340(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9340Modes_low_ob_db_and_spur_tx_gain_table_1p0);
|
||||
else if (AR_SREV_9485_11(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9485Modes_green_spur_ob_db_tx_gain_1_1);
|
||||
else if (AR_SREV_9580(ah))
|
||||
INIT_INI_ARRAY(&ah->iniModesTxGain,
|
||||
ar9580_1p0_type6_tx_gain_table);
|
||||
}
|
||||
|
||||
typedef void (*ath_txgain_tab)(struct ath_hw *ah);
|
||||
|
||||
static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
|
||||
{
|
||||
switch (ar9003_hw_get_tx_gain_idx(ah)) {
|
||||
case 0:
|
||||
default:
|
||||
ar9003_tx_gain_table_mode0(ah);
|
||||
break;
|
||||
case 1:
|
||||
ar9003_tx_gain_table_mode1(ah);
|
||||
break;
|
||||
case 2:
|
||||
ar9003_tx_gain_table_mode2(ah);
|
||||
break;
|
||||
case 3:
|
||||
ar9003_tx_gain_table_mode3(ah);
|
||||
break;
|
||||
case 4:
|
||||
ar9003_tx_gain_table_mode4(ah);
|
||||
break;
|
||||
}
|
||||
static const ath_txgain_tab modes[] = {
|
||||
ar9003_tx_gain_table_mode0,
|
||||
ar9003_tx_gain_table_mode1,
|
||||
ar9003_tx_gain_table_mode2,
|
||||
ar9003_tx_gain_table_mode3,
|
||||
ar9003_tx_gain_table_mode4,
|
||||
ar9003_tx_gain_table_mode5,
|
||||
ar9003_tx_gain_table_mode6,
|
||||
};
|
||||
int idx = ar9003_hw_get_tx_gain_idx(ah);
|
||||
|
||||
if (idx >= ARRAY_SIZE(modes))
|
||||
idx = 0;
|
||||
|
||||
modes[idx](ah);
|
||||
}
|
||||
|
||||
static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
|
||||
@ -673,7 +704,7 @@ void ar9003_hw_attach_ops(struct ath_hw *ah)
|
||||
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
|
||||
struct ath_hw_ops *ops = ath9k_hw_ops(ah);
|
||||
|
||||
priv_ops->init_mode_regs = ar9003_hw_init_mode_regs;
|
||||
ar9003_hw_init_mode_regs(ah);
|
||||
priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
|
||||
|
||||
ops->config_pci_powersave = ar9003_hw_configpcipowersave;
|
||||
|
@ -68,7 +68,7 @@ static const int m2ThreshExt_off = 127;
|
||||
static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
{
|
||||
u16 bMode, fracMode = 0, aModeRefSel = 0;
|
||||
u32 freq, channelSel = 0, reg32 = 0;
|
||||
u32 freq, chan_frac, div, channelSel = 0, reg32 = 0;
|
||||
struct chan_centers centers;
|
||||
int loadSynthChannel;
|
||||
|
||||
@ -77,9 +77,6 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
|
||||
if (freq < 4800) { /* 2 GHz, fractional mode */
|
||||
if (AR_SREV_9330(ah)) {
|
||||
u32 chan_frac;
|
||||
u32 div;
|
||||
|
||||
if (ah->is_clk_25mhz)
|
||||
div = 75;
|
||||
else
|
||||
@ -89,34 +86,40 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
chan_frac = (((freq * 4) % div) * 0x20000) / div;
|
||||
channelSel = (channelSel << 17) | chan_frac;
|
||||
} else if (AR_SREV_9485(ah) || AR_SREV_9565(ah)) {
|
||||
u32 chan_frac;
|
||||
|
||||
/*
|
||||
* freq_ref = 40 / (refdiva >> amoderefsel); where refdiva=1 and amoderefsel=0
|
||||
* freq_ref = 40 / (refdiva >> amoderefsel);
|
||||
* where refdiva=1 and amoderefsel=0
|
||||
* ndiv = ((chan_mhz * 4) / 3) / freq_ref;
|
||||
* chansel = int(ndiv), chanfrac = (ndiv - chansel) * 0x20000
|
||||
*/
|
||||
channelSel = (freq * 4) / 120;
|
||||
chan_frac = (((freq * 4) % 120) * 0x20000) / 120;
|
||||
channelSel = (channelSel << 17) | chan_frac;
|
||||
} else if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) {
|
||||
} else if (AR_SREV_9340(ah)) {
|
||||
if (ah->is_clk_25mhz) {
|
||||
u32 chan_frac;
|
||||
|
||||
channelSel = (freq * 2) / 75;
|
||||
chan_frac = (((freq * 2) % 75) * 0x20000) / 75;
|
||||
channelSel = (channelSel << 17) | chan_frac;
|
||||
} else
|
||||
} else {
|
||||
channelSel = CHANSEL_2G(freq) >> 1;
|
||||
} else
|
||||
}
|
||||
} else if (AR_SREV_9550(ah)) {
|
||||
if (ah->is_clk_25mhz)
|
||||
div = 75;
|
||||
else
|
||||
div = 120;
|
||||
|
||||
channelSel = (freq * 4) / div;
|
||||
chan_frac = (((freq * 4) % div) * 0x20000) / div;
|
||||
channelSel = (channelSel << 17) | chan_frac;
|
||||
} else {
|
||||
channelSel = CHANSEL_2G(freq);
|
||||
}
|
||||
/* Set to 2G mode */
|
||||
bMode = 1;
|
||||
} else {
|
||||
if ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) &&
|
||||
ah->is_clk_25mhz) {
|
||||
u32 chan_frac;
|
||||
|
||||
channelSel = freq / 75;
|
||||
chan_frac = ((freq % 75) * 0x20000) / 75;
|
||||
channelSel = (channelSel << 17) | chan_frac;
|
||||
@ -586,32 +589,19 @@ static void ar9003_hw_init_bb(struct ath_hw *ah,
|
||||
ath9k_hw_synth_delay(ah, chan, synthDelay);
|
||||
}
|
||||
|
||||
static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
|
||||
void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
|
||||
{
|
||||
switch (rx) {
|
||||
case 0x5:
|
||||
if (ah->caps.tx_chainmask == 5 || ah->caps.rx_chainmask == 5)
|
||||
REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
|
||||
AR_PHY_SWAP_ALT_CHAIN);
|
||||
case 0x3:
|
||||
case 0x1:
|
||||
case 0x2:
|
||||
case 0x7:
|
||||
REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx);
|
||||
REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx);
|
||||
REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx);
|
||||
|
||||
if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7))
|
||||
REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
|
||||
else
|
||||
REG_WRITE(ah, AR_SELFGEN_MASK, tx);
|
||||
tx = 3;
|
||||
|
||||
if (tx == 0x5) {
|
||||
REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
|
||||
AR_PHY_SWAP_ALT_CHAIN);
|
||||
}
|
||||
REG_WRITE(ah, AR_SELFGEN_MASK, tx);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1450,6 +1440,67 @@ set_rfmode:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ar9003_hw_spectral_scan_config(struct ath_hw *ah,
|
||||
struct ath_spec_scan *param)
|
||||
{
|
||||
u8 count;
|
||||
|
||||
if (!param->enabled) {
|
||||
REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_ENABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
REG_SET_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_FFT_ENA);
|
||||
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN, AR_PHY_SPECTRAL_SCAN_ENABLE);
|
||||
|
||||
/* on AR93xx and newer, count = 0 will make the the chip send
|
||||
* spectral samples endlessly. Check if this really was intended,
|
||||
* and fix otherwise.
|
||||
*/
|
||||
count = param->count;
|
||||
if (param->endless)
|
||||
count = 0;
|
||||
else if (param->count == 0)
|
||||
count = 1;
|
||||
|
||||
if (param->short_repeat)
|
||||
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
|
||||
else
|
||||
REG_CLR_BIT(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT);
|
||||
|
||||
REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_COUNT, count);
|
||||
REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_PERIOD, param->period);
|
||||
REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_FFT_PERIOD, param->fft_period);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void ar9003_hw_spectral_scan_trigger(struct ath_hw *ah)
|
||||
{
|
||||
/* Activate spectral scan */
|
||||
REG_SET_BIT(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_ACTIVE);
|
||||
}
|
||||
|
||||
static void ar9003_hw_spectral_scan_wait(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
/* Poll for spectral scan complete */
|
||||
if (!ath9k_hw_wait(ah, AR_PHY_SPECTRAL_SCAN,
|
||||
AR_PHY_SPECTRAL_SCAN_ACTIVE,
|
||||
0, AH_WAIT_TIMEOUT)) {
|
||||
ath_err(common, "spectral scan wait failed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
|
||||
@ -1483,6 +1534,9 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
|
||||
ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get;
|
||||
ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set;
|
||||
ops->antctrl_shared_chain_lnadiv = ar9003_hw_antctrl_shared_chain_lnadiv;
|
||||
ops->spectral_scan_config = ar9003_hw_spectral_scan_config;
|
||||
ops->spectral_scan_trigger = ar9003_hw_spectral_scan_trigger;
|
||||
ops->spectral_scan_wait = ar9003_hw_spectral_scan_wait;
|
||||
|
||||
ar9003_hw_set_nf_limits(ah);
|
||||
ar9003_hw_set_radar_conf(ah);
|
||||
|
@ -1028,7 +1028,7 @@
|
||||
#define AR_PHY_TPC_5_B2 (AR_SM2_BASE + 0x208)
|
||||
#define AR_PHY_TPC_6_B2 (AR_SM2_BASE + 0x20c)
|
||||
#define AR_PHY_TPC_11_B2 (AR_SM2_BASE + 0x220)
|
||||
#define AR_PHY_PDADC_TAB_2 (AR_SM2_BASE + 0x240)
|
||||
#define AR_PHY_TPC_19_B2 (AR_SM2_BASE + 0x240)
|
||||
#define AR_PHY_TX_IQCAL_STATUS_B2 (AR_SM2_BASE + 0x48c)
|
||||
#define AR_PHY_TX_IQCAL_CORR_COEFF_B2(_i) (AR_SM2_BASE + 0x450 + ((_i) << 2))
|
||||
|
||||
|
@ -1172,6 +1172,106 @@ static const u32 ar9340Modes_mixed_ob_db_tx_gain_table_1p0[][5] = {
|
||||
{0x00016448, 0x24925666, 0x24925666, 0x8e481266, 0x8e481266},
|
||||
};
|
||||
|
||||
static const u32 ar9340Modes_low_ob_db_and_spur_tx_gain_table_1p0[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03eaac5a, 0x03eaac5a},
|
||||
{0x0000a2e0, 0x0000f800, 0x0000f800, 0x03f330ac, 0x03f330ac},
|
||||
{0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03fc3f00, 0x03fc3f00},
|
||||
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ffc000, 0x03ffc000},
|
||||
{0x0000a394, 0x00000444, 0x00000444, 0x00000404, 0x00000404},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
||||
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06000003, 0x06000003, 0x02000001, 0x02000001},
|
||||
{0x0000a508, 0x0a000020, 0x0a000020, 0x05000003, 0x05000003},
|
||||
{0x0000a50c, 0x10000023, 0x10000023, 0x0a000005, 0x0a000005},
|
||||
{0x0000a510, 0x16000220, 0x16000220, 0x0e000201, 0x0e000201},
|
||||
{0x0000a514, 0x1c000223, 0x1c000223, 0x11000203, 0x11000203},
|
||||
{0x0000a518, 0x21002220, 0x21002220, 0x14000401, 0x14000401},
|
||||
{0x0000a51c, 0x27002223, 0x27002223, 0x18000403, 0x18000403},
|
||||
{0x0000a520, 0x2b022220, 0x2b022220, 0x1b000602, 0x1b000602},
|
||||
{0x0000a524, 0x2f022222, 0x2f022222, 0x1f000802, 0x1f000802},
|
||||
{0x0000a528, 0x34022225, 0x34022225, 0x21000620, 0x21000620},
|
||||
{0x0000a52c, 0x3a02222a, 0x3a02222a, 0x25000820, 0x25000820},
|
||||
{0x0000a530, 0x3e02222c, 0x3e02222c, 0x29000822, 0x29000822},
|
||||
{0x0000a534, 0x4202242a, 0x4202242a, 0x2d000824, 0x2d000824},
|
||||
{0x0000a538, 0x4702244a, 0x4702244a, 0x30000828, 0x30000828},
|
||||
{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x3400082a, 0x3400082a},
|
||||
{0x0000a540, 0x4e02246c, 0x4e02246c, 0x38000849, 0x38000849},
|
||||
{0x0000a544, 0x5302266c, 0x5302266c, 0x3b000a2c, 0x3b000a2c},
|
||||
{0x0000a548, 0x5702286c, 0x5702286c, 0x3e000e2b, 0x3e000e2b},
|
||||
{0x0000a54c, 0x5c02486b, 0x5c02486b, 0x42000e2d, 0x42000e2d},
|
||||
{0x0000a550, 0x61024a6c, 0x61024a6c, 0x4500124a, 0x4500124a},
|
||||
{0x0000a554, 0x66026a6c, 0x66026a6c, 0x4900124c, 0x4900124c},
|
||||
{0x0000a558, 0x6b026e6c, 0x6b026e6c, 0x4c00126c, 0x4c00126c},
|
||||
{0x0000a55c, 0x7002708c, 0x7002708c, 0x4f00128c, 0x4f00128c},
|
||||
{0x0000a560, 0x7302b08a, 0x7302b08a, 0x52001290, 0x52001290},
|
||||
{0x0000a564, 0x7702b08c, 0x7702b08c, 0x56001292, 0x56001292},
|
||||
{0x0000a568, 0x7702b08c, 0x7702b08c, 0x56001292, 0x56001292},
|
||||
{0x0000a56c, 0x7702b08c, 0x7702b08c, 0x56001292, 0x56001292},
|
||||
{0x0000a570, 0x7702b08c, 0x7702b08c, 0x56001292, 0x56001292},
|
||||
{0x0000a574, 0x7702b08c, 0x7702b08c, 0x56001292, 0x56001292},
|
||||
{0x0000a578, 0x7702b08c, 0x7702b08c, 0x56001292, 0x56001292},
|
||||
{0x0000a57c, 0x7702b08c, 0x7702b08c, 0x56001292, 0x56001292},
|
||||
{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
|
||||
{0x0000a584, 0x06800003, 0x06800003, 0x02800001, 0x02800001},
|
||||
{0x0000a588, 0x0a800020, 0x0a800020, 0x05800003, 0x05800003},
|
||||
{0x0000a58c, 0x10800023, 0x10800023, 0x0a800005, 0x0a800005},
|
||||
{0x0000a590, 0x16800220, 0x16800220, 0x0e800201, 0x0e800201},
|
||||
{0x0000a594, 0x1c800223, 0x1c800223, 0x11800203, 0x11800203},
|
||||
{0x0000a598, 0x21820220, 0x21820220, 0x14800401, 0x14800401},
|
||||
{0x0000a59c, 0x27820223, 0x27820223, 0x18800403, 0x18800403},
|
||||
{0x0000a5a0, 0x2b822220, 0x2b822220, 0x1b800602, 0x1b800602},
|
||||
{0x0000a5a4, 0x2f822222, 0x2f822222, 0x1f800802, 0x1f800802},
|
||||
{0x0000a5a8, 0x34822225, 0x34822225, 0x21800620, 0x21800620},
|
||||
{0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x25800820, 0x25800820},
|
||||
{0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x29800822, 0x29800822},
|
||||
{0x0000a5b4, 0x4282242a, 0x4282242a, 0x2d800824, 0x2d800824},
|
||||
{0x0000a5b8, 0x4782244a, 0x4782244a, 0x30800828, 0x30800828},
|
||||
{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x3480082a, 0x3480082a},
|
||||
{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x38800849, 0x38800849},
|
||||
{0x0000a5c4, 0x5382266c, 0x5382266c, 0x3b800a2c, 0x3b800a2c},
|
||||
{0x0000a5c8, 0x5782286c, 0x5782286c, 0x3e800e2b, 0x3e800e2b},
|
||||
{0x0000a5cc, 0x5c84286b, 0x5c84286b, 0x42800e2d, 0x42800e2d},
|
||||
{0x0000a5d0, 0x61842a6c, 0x61842a6c, 0x4580124a, 0x4580124a},
|
||||
{0x0000a5d4, 0x66862a6c, 0x66862a6c, 0x4980124c, 0x4980124c},
|
||||
{0x0000a5d8, 0x6b862e6c, 0x6b862e6c, 0x4c80126c, 0x4c80126c},
|
||||
{0x0000a5dc, 0x7086308c, 0x7086308c, 0x4f80128c, 0x4f80128c},
|
||||
{0x0000a5e0, 0x738a308a, 0x738a308a, 0x52801290, 0x52801290},
|
||||
{0x0000a5e4, 0x778a308c, 0x778a308c, 0x56801292, 0x56801292},
|
||||
{0x0000a5e8, 0x778a308c, 0x778a308c, 0x56801292, 0x56801292},
|
||||
{0x0000a5ec, 0x778a308c, 0x778a308c, 0x56801292, 0x56801292},
|
||||
{0x0000a5f0, 0x778a308c, 0x778a308c, 0x56801292, 0x56801292},
|
||||
{0x0000a5f4, 0x778a308c, 0x778a308c, 0x56801292, 0x56801292},
|
||||
{0x0000a5f8, 0x778a308c, 0x778a308c, 0x56801292, 0x56801292},
|
||||
{0x0000a5fc, 0x778a308c, 0x778a308c, 0x56801292, 0x56801292},
|
||||
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a614, 0x01404000, 0x01404000, 0x01404501, 0x01404501},
|
||||
{0x0000a618, 0x01404501, 0x01404501, 0x01404501, 0x01404501},
|
||||
{0x0000a61c, 0x02008802, 0x02008802, 0x01404501, 0x01404501},
|
||||
{0x0000a620, 0x0300cc03, 0x0300cc03, 0x03c0cf02, 0x03c0cf02},
|
||||
{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03c0cf03, 0x03c0cf03},
|
||||
{0x0000a628, 0x0300cc03, 0x0300cc03, 0x04011004, 0x04011004},
|
||||
{0x0000a62c, 0x03810c03, 0x03810c03, 0x05419405, 0x05419405},
|
||||
{0x0000a630, 0x03810e04, 0x03810e04, 0x05419506, 0x05419506},
|
||||
{0x0000a634, 0x03810e04, 0x03810e04, 0x05419506, 0x05419506},
|
||||
{0x0000a638, 0x03810e04, 0x03810e04, 0x05419506, 0x05419506},
|
||||
{0x0000a63c, 0x03810e04, 0x03810e04, 0x05419506, 0x05419506},
|
||||
{0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03eaac5a, 0x03eaac5a},
|
||||
{0x0000b2e0, 0x0000f800, 0x0000f800, 0x03f330ac, 0x03f330ac},
|
||||
{0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03fc3f00, 0x03fc3f00},
|
||||
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ffc000, 0x03ffc000},
|
||||
{0x00016044, 0x022492db, 0x022492db, 0x022492db, 0x022492db},
|
||||
{0x00016048, 0x24925666, 0x24925666, 0x24925266, 0x24925266},
|
||||
{0x00016280, 0x01000015, 0x01000015, 0x01001015, 0x01001015},
|
||||
{0x00016288, 0xf0318000, 0xf0318000, 0xf0318000, 0xf0318000},
|
||||
{0x00016444, 0x022492db, 0x022492db, 0x022492db, 0x022492db},
|
||||
{0x00016448, 0x24925666, 0x24925666, 0x24925266, 0x24925266},
|
||||
};
|
||||
|
||||
static const u32 ar9340_1p0_mac_core[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00000008, 0x00000000},
|
||||
|
@ -260,6 +260,79 @@ static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
|
||||
{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
|
||||
};
|
||||
|
||||
static const u32 ar9485Modes_green_ob_db_tx_gain_1_1[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
|
||||
{0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
|
||||
{0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006},
|
||||
{0x0000a504, 0x05062002, 0x05062002, 0x03000201, 0x03000201},
|
||||
{0x0000a508, 0x0c002e00, 0x0c002e00, 0x06000203, 0x06000203},
|
||||
{0x0000a50c, 0x11062202, 0x11062202, 0x0a000401, 0x0a000401},
|
||||
{0x0000a510, 0x17022e00, 0x17022e00, 0x0e000403, 0x0e000403},
|
||||
{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x12000405, 0x12000405},
|
||||
{0x0000a518, 0x25020ec0, 0x25020ec0, 0x15000604, 0x15000604},
|
||||
{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x18000605, 0x18000605},
|
||||
{0x0000a520, 0x2f001f04, 0x2f001f04, 0x1c000a04, 0x1c000a04},
|
||||
{0x0000a524, 0x35001fc4, 0x35001fc4, 0x21000a06, 0x21000a06},
|
||||
{0x0000a528, 0x3c022f04, 0x3c022f04, 0x29000a24, 0x29000a24},
|
||||
{0x0000a52c, 0x41023e85, 0x41023e85, 0x2f000e21, 0x2f000e21},
|
||||
{0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000e20, 0x31000e20},
|
||||
{0x0000a534, 0x4d023f01, 0x4d023f01, 0x33000e20, 0x33000e20},
|
||||
{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
|
||||
{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
|
||||
{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
|
||||
{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
|
||||
{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
|
||||
{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
|
||||
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
|
||||
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
|
||||
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001ceb, 0x5a001ceb},
|
||||
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
|
||||
{0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b50c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b510, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b514, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b518, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b51c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b520, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b524, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b528, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b52c, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a},
|
||||
{0x0000b530, 0x0000003a, 0x0000003a, 0x0000003a, 0x0000003a},
|
||||
{0x0000b534, 0x0000004a, 0x0000004a, 0x0000004a, 0x0000004a},
|
||||
{0x0000b538, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b53c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b540, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b544, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b548, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b54c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b550, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b554, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b558, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b55c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b560, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b564, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b568, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b56c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b570, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b574, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b578, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b57c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
|
||||
{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
|
||||
};
|
||||
|
||||
static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
|
||||
@ -450,6 +523,79 @@ static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
|
||||
|
||||
#define ar9485_modes_lowest_ob_db_tx_gain_1_1 ar9485Modes_low_ob_db_tx_gain_1_1
|
||||
|
||||
static const u32 ar9485Modes_green_spur_ob_db_tx_gain_1_1[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
|
||||
{0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
|
||||
{0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006},
|
||||
{0x0000a504, 0x05062002, 0x05062002, 0x03000201, 0x03000201},
|
||||
{0x0000a508, 0x0c002e00, 0x0c002e00, 0x07000203, 0x07000203},
|
||||
{0x0000a50c, 0x11062202, 0x11062202, 0x0a000401, 0x0a000401},
|
||||
{0x0000a510, 0x17022e00, 0x17022e00, 0x0e000403, 0x0e000403},
|
||||
{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x12000405, 0x12000405},
|
||||
{0x0000a518, 0x25020ec0, 0x25020ec0, 0x14000406, 0x14000406},
|
||||
{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1800040a, 0x1800040a},
|
||||
{0x0000a520, 0x2f001f04, 0x2f001f04, 0x1c000460, 0x1c000460},
|
||||
{0x0000a524, 0x35001fc4, 0x35001fc4, 0x22000463, 0x22000463},
|
||||
{0x0000a528, 0x3c022f04, 0x3c022f04, 0x26000465, 0x26000465},
|
||||
{0x0000a52c, 0x41023e85, 0x41023e85, 0x2e0006e0, 0x2e0006e0},
|
||||
{0x0000a530, 0x48023ec6, 0x48023ec6, 0x310006e0, 0x310006e0},
|
||||
{0x0000a534, 0x4d023f01, 0x4d023f01, 0x330006e0, 0x330006e0},
|
||||
{0x0000a538, 0x53023f4b, 0x53023f4b, 0x3e0008e3, 0x3e0008e3},
|
||||
{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x410008e5, 0x410008e5},
|
||||
{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x430008e6, 0x430008e6},
|
||||
{0x0000a544, 0x6502feca, 0x6502feca, 0x4a0008ec, 0x4a0008ec},
|
||||
{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4e0008f1, 0x4e0008f1},
|
||||
{0x0000a54c, 0x7203feca, 0x7203feca, 0x520008f3, 0x520008f3},
|
||||
{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x54000eed, 0x54000eed},
|
||||
{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x58000ef1, 0x58000ef1},
|
||||
{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5c000ef3, 0x5c000ef3},
|
||||
{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x60000ef5, 0x60000ef5},
|
||||
{0x0000a560, 0x900fff0b, 0x900fff0b, 0x62000ef6, 0x62000ef6},
|
||||
{0x0000a564, 0x960fffcb, 0x960fffcb, 0x62000ef6, 0x62000ef6},
|
||||
{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6},
|
||||
{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6},
|
||||
{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6},
|
||||
{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6},
|
||||
{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6},
|
||||
{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x62000ef6, 0x62000ef6},
|
||||
{0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b50c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b510, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b514, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b518, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b51c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b520, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b524, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b528, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
|
||||
{0x0000b52c, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a},
|
||||
{0x0000b530, 0x0000003a, 0x0000003a, 0x0000003a, 0x0000003a},
|
||||
{0x0000b534, 0x0000004a, 0x0000004a, 0x0000004a, 0x0000004a},
|
||||
{0x0000b538, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b53c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b540, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b544, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b548, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b54c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b550, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b554, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b558, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b55c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b560, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b564, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b568, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b56c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b570, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b574, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b578, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x0000b57c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
|
||||
{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
|
||||
{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
|
||||
};
|
||||
|
||||
static const u32 ar9485_1_1[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x0000a580, 0x00000000},
|
||||
|
@ -23,16 +23,16 @@
|
||||
static const u32 ar955x_1p0_radio_postamble[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x00016098, 0xd2dd5554, 0xd2dd5554, 0xd28b3330, 0xd28b3330},
|
||||
{0x0001609c, 0x0a566f3a, 0x0a566f3a, 0x06345f2a, 0x06345f2a},
|
||||
{0x000160ac, 0xa4647c00, 0xa4647c00, 0xa4646800, 0xa4646800},
|
||||
{0x000160b0, 0x01885f52, 0x01885f52, 0x04accf3a, 0x04accf3a},
|
||||
{0x00016104, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001},
|
||||
{0x0001609c, 0x0a566f3a, 0x0a566f3a, 0x0a566f3a, 0x0a566f3a},
|
||||
{0x000160ac, 0xa4647c00, 0xa4647c00, 0x24647c00, 0x24647c00},
|
||||
{0x000160b0, 0x01885f52, 0x01885f52, 0x01885f52, 0x01885f52},
|
||||
{0x00016104, 0xb7a00000, 0xb7a00000, 0xb7a00001, 0xb7a00001},
|
||||
{0x0001610c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000},
|
||||
{0x00016140, 0x10804008, 0x10804008, 0x10804008, 0x10804008},
|
||||
{0x00016504, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001},
|
||||
{0x00016504, 0xb7a00000, 0xb7a00000, 0xb7a00001, 0xb7a00001},
|
||||
{0x0001650c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000},
|
||||
{0x00016540, 0x10804008, 0x10804008, 0x10804008, 0x10804008},
|
||||
{0x00016904, 0xb7a00001, 0xb7a00001, 0xb7a00001, 0xb7a00001},
|
||||
{0x00016904, 0xb7a00000, 0xb7a00000, 0xb7a00001, 0xb7a00001},
|
||||
{0x0001690c, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000},
|
||||
{0x00016940, 0x10804008, 0x10804008, 0x10804008, 0x10804008},
|
||||
};
|
||||
@ -69,15 +69,15 @@ static const u32 ar955x_1p0_baseband_postamble[][5] = {
|
||||
{0x0000a204, 0x005c0ec0, 0x005c0ec4, 0x005c0ec4, 0x005c0ec0},
|
||||
{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
|
||||
{0x0000a22c, 0x07e26a2f, 0x07e26a2f, 0x01026a2f, 0x01026a2f},
|
||||
{0x0000a230, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b},
|
||||
{0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
|
||||
{0x0000a234, 0x00000fff, 0x10000fff, 0x10000fff, 0x00000fff},
|
||||
{0x0000a238, 0xffb01018, 0xffb01018, 0xffb01018, 0xffb01018},
|
||||
{0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
|
||||
{0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
|
||||
{0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
|
||||
{0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
|
||||
{0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01010e0e, 0x01010e0e},
|
||||
{0x0000a260, 0x0a021501, 0x0a021501, 0x3a021501, 0x3a021501},
|
||||
{0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
|
||||
{0x0000a264, 0x00000e0e, 0x00000e0e, 0x01000e0e, 0x01000e0e},
|
||||
{0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
|
||||
{0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
|
||||
{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
|
||||
@ -125,7 +125,7 @@ static const u32 ar955x_1p0_radio_core[][2] = {
|
||||
{0x00016094, 0x00000000},
|
||||
{0x000160a0, 0x0a108ffe},
|
||||
{0x000160a4, 0x812fc370},
|
||||
{0x000160a8, 0x423c8000},
|
||||
{0x000160a8, 0x423c8100},
|
||||
{0x000160b4, 0x92480080},
|
||||
{0x000160c0, 0x006db6d0},
|
||||
{0x000160c4, 0x6db6db60},
|
||||
@ -134,7 +134,7 @@ static const u32 ar955x_1p0_radio_core[][2] = {
|
||||
{0x00016100, 0x11999601},
|
||||
{0x00016108, 0x00080010},
|
||||
{0x00016144, 0x02084080},
|
||||
{0x00016148, 0x000080c0},
|
||||
{0x00016148, 0x00008040},
|
||||
{0x00016280, 0x01800804},
|
||||
{0x00016284, 0x00038dc5},
|
||||
{0x00016288, 0x00000000},
|
||||
@ -178,7 +178,7 @@ static const u32 ar955x_1p0_radio_core[][2] = {
|
||||
{0x00016500, 0x11999601},
|
||||
{0x00016508, 0x00080010},
|
||||
{0x00016544, 0x02084080},
|
||||
{0x00016548, 0x000080c0},
|
||||
{0x00016548, 0x00008040},
|
||||
{0x00016780, 0x00000000},
|
||||
{0x00016784, 0x00000000},
|
||||
{0x00016788, 0x00400705},
|
||||
@ -218,7 +218,7 @@ static const u32 ar955x_1p0_radio_core[][2] = {
|
||||
{0x00016900, 0x11999601},
|
||||
{0x00016908, 0x00080010},
|
||||
{0x00016944, 0x02084080},
|
||||
{0x00016948, 0x000080c0},
|
||||
{0x00016948, 0x00008040},
|
||||
{0x00016b80, 0x00000000},
|
||||
{0x00016b84, 0x00000000},
|
||||
{0x00016b88, 0x00400705},
|
||||
@ -245,9 +245,9 @@ static const u32 ar955x_1p0_radio_core[][2] = {
|
||||
|
||||
static const u32 ar955x_1p0_modes_xpa_tx_gain_table[][9] = {
|
||||
/* Addr 5G_HT20_L 5G_HT40_L 5G_HT20_M 5G_HT40_M 5G_HT20_H 5G_HT40_H 2G_HT40 2G_HT20 */
|
||||
{0x0000a2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa},
|
||||
{0x0000a2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc},
|
||||
{0x0000a2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0},
|
||||
{0x0000a2dc, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xfffd5aaa, 0xfffd5aaa},
|
||||
{0x0000a2e0, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffe9ccc, 0xfffe9ccc},
|
||||
{0x0000a2e4, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffffe0f0, 0xffffe0f0},
|
||||
{0x0000a2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00},
|
||||
{0x0000a410, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050de, 0x000050da, 0x000050da},
|
||||
{0x0000a500, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000000, 0x00000000},
|
||||
@ -256,63 +256,63 @@ static const u32 ar955x_1p0_modes_xpa_tx_gain_table[][9] = {
|
||||
{0x0000a50c, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c00000b, 0x0c000006, 0x0c000006},
|
||||
{0x0000a510, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x1000000d, 0x0f00000a, 0x0f00000a},
|
||||
{0x0000a514, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x14000011, 0x1300000c, 0x1300000c},
|
||||
{0x0000a518, 0x19004008, 0x19004008, 0x19004008, 0x19004008, 0x18004008, 0x18004008, 0x1700000e, 0x1700000e},
|
||||
{0x0000a51c, 0x1d00400a, 0x1d00400a, 0x1d00400a, 0x1d00400a, 0x1c00400a, 0x1c00400a, 0x1b000064, 0x1b000064},
|
||||
{0x0000a520, 0x230020a2, 0x230020a2, 0x210020a2, 0x210020a2, 0x200020a2, 0x200020a2, 0x1f000242, 0x1f000242},
|
||||
{0x0000a524, 0x2500006e, 0x2500006e, 0x2500006e, 0x2500006e, 0x2400006e, 0x2400006e, 0x23000229, 0x23000229},
|
||||
{0x0000a528, 0x29022221, 0x29022221, 0x28022221, 0x28022221, 0x27022221, 0x27022221, 0x270002a2, 0x270002a2},
|
||||
{0x0000a52c, 0x2d00062a, 0x2d00062a, 0x2c00062a, 0x2c00062a, 0x2a00062a, 0x2a00062a, 0x2c001203, 0x2c001203},
|
||||
{0x0000a530, 0x340220a5, 0x340220a5, 0x320220a5, 0x320220a5, 0x2f0220a5, 0x2f0220a5, 0x30001803, 0x30001803},
|
||||
{0x0000a534, 0x380022c5, 0x380022c5, 0x350022c5, 0x350022c5, 0x320022c5, 0x320022c5, 0x33000881, 0x33000881},
|
||||
{0x0000a538, 0x3b002486, 0x3b002486, 0x39002486, 0x39002486, 0x36002486, 0x36002486, 0x38001809, 0x38001809},
|
||||
{0x0000a53c, 0x3f00248a, 0x3f00248a, 0x3d00248a, 0x3d00248a, 0x3a00248a, 0x3a00248a, 0x3a000814, 0x3a000814},
|
||||
{0x0000a540, 0x4202242c, 0x4202242c, 0x4102242c, 0x4102242c, 0x3f02242c, 0x3f02242c, 0x3f001a0c, 0x3f001a0c},
|
||||
{0x0000a544, 0x490044c6, 0x490044c6, 0x460044c6, 0x460044c6, 0x420044c6, 0x420044c6, 0x43001a0e, 0x43001a0e},
|
||||
{0x0000a548, 0x4d024485, 0x4d024485, 0x4a024485, 0x4a024485, 0x46024485, 0x46024485, 0x46001812, 0x46001812},
|
||||
{0x0000a54c, 0x51044483, 0x51044483, 0x4e044483, 0x4e044483, 0x4a044483, 0x4a044483, 0x49001884, 0x49001884},
|
||||
{0x0000a550, 0x5404a40c, 0x5404a40c, 0x5204a40c, 0x5204a40c, 0x4d04a40c, 0x4d04a40c, 0x4d001e84, 0x4d001e84},
|
||||
{0x0000a554, 0x57024632, 0x57024632, 0x55024632, 0x55024632, 0x52024632, 0x52024632, 0x50001e69, 0x50001e69},
|
||||
{0x0000a558, 0x5c00a634, 0x5c00a634, 0x5900a634, 0x5900a634, 0x5600a634, 0x5600a634, 0x550006f4, 0x550006f4},
|
||||
{0x0000a55c, 0x5f026832, 0x5f026832, 0x5d026832, 0x5d026832, 0x5a026832, 0x5a026832, 0x59000ad3, 0x59000ad3},
|
||||
{0x0000a560, 0x6602b012, 0x6602b012, 0x6202b012, 0x6202b012, 0x5d02b012, 0x5d02b012, 0x5e000ad5, 0x5e000ad5},
|
||||
{0x0000a564, 0x6e02d0e1, 0x6e02d0e1, 0x6802d0e1, 0x6802d0e1, 0x6002d0e1, 0x6002d0e1, 0x61001ced, 0x61001ced},
|
||||
{0x0000a568, 0x7202b4c4, 0x7202b4c4, 0x6c02b4c4, 0x6c02b4c4, 0x6502b4c4, 0x6502b4c4, 0x660018d4, 0x660018d4},
|
||||
{0x0000a56c, 0x75007894, 0x75007894, 0x70007894, 0x70007894, 0x6b007894, 0x6b007894, 0x660018d4, 0x660018d4},
|
||||
{0x0000a570, 0x7b025c74, 0x7b025c74, 0x75025c74, 0x75025c74, 0x70025c74, 0x70025c74, 0x660018d4, 0x660018d4},
|
||||
{0x0000a574, 0x8300bcb5, 0x8300bcb5, 0x7a00bcb5, 0x7a00bcb5, 0x7600bcb5, 0x7600bcb5, 0x660018d4, 0x660018d4},
|
||||
{0x0000a578, 0x8a04dc74, 0x8a04dc74, 0x7f04dc74, 0x7f04dc74, 0x7c04dc74, 0x7c04dc74, 0x660018d4, 0x660018d4},
|
||||
{0x0000a57c, 0x8a04dc74, 0x8a04dc74, 0x7f04dc74, 0x7f04dc74, 0x7c04dc74, 0x7c04dc74, 0x660018d4, 0x660018d4},
|
||||
{0x0000a518, 0x1700002b, 0x1700002b, 0x1700002b, 0x1700002b, 0x1600002b, 0x1600002b, 0x1700000e, 0x1700000e},
|
||||
{0x0000a51c, 0x1b00002d, 0x1b00002d, 0x1b00002d, 0x1b00002d, 0x1a00002d, 0x1a00002d, 0x1b000064, 0x1b000064},
|
||||
{0x0000a520, 0x20000031, 0x20000031, 0x1f000031, 0x1f000031, 0x1e000031, 0x1e000031, 0x1f000242, 0x1f000242},
|
||||
{0x0000a524, 0x24000051, 0x24000051, 0x23000051, 0x23000051, 0x23000051, 0x23000051, 0x23000229, 0x23000229},
|
||||
{0x0000a528, 0x27000071, 0x27000071, 0x27000071, 0x27000071, 0x26000071, 0x26000071, 0x270002a2, 0x270002a2},
|
||||
{0x0000a52c, 0x2b000092, 0x2b000092, 0x2b000092, 0x2b000092, 0x2b000092, 0x2b000092, 0x2c001203, 0x2c001203},
|
||||
{0x0000a530, 0x3000028c, 0x3000028c, 0x2f00028c, 0x2f00028c, 0x2e00028c, 0x2e00028c, 0x30001803, 0x30001803},
|
||||
{0x0000a534, 0x34000290, 0x34000290, 0x33000290, 0x33000290, 0x32000290, 0x32000290, 0x33000881, 0x33000881},
|
||||
{0x0000a538, 0x37000292, 0x37000292, 0x36000292, 0x36000292, 0x35000292, 0x35000292, 0x38001809, 0x38001809},
|
||||
{0x0000a53c, 0x3b02028d, 0x3b02028d, 0x3a02028d, 0x3a02028d, 0x3902028d, 0x3902028d, 0x3a000814, 0x3a000814},
|
||||
{0x0000a540, 0x3f020291, 0x3f020291, 0x3e020291, 0x3e020291, 0x3d020291, 0x3d020291, 0x3f001a0c, 0x3f001a0c},
|
||||
{0x0000a544, 0x44020490, 0x44020490, 0x43020490, 0x43020490, 0x42020490, 0x42020490, 0x43001a0e, 0x43001a0e},
|
||||
{0x0000a548, 0x48020492, 0x48020492, 0x47020492, 0x47020492, 0x46020492, 0x46020492, 0x46001812, 0x46001812},
|
||||
{0x0000a54c, 0x4c020692, 0x4c020692, 0x4b020692, 0x4b020692, 0x4a020692, 0x4a020692, 0x49001884, 0x49001884},
|
||||
{0x0000a550, 0x50020892, 0x50020892, 0x4f020892, 0x4f020892, 0x4e020892, 0x4e020892, 0x4d001e84, 0x4d001e84},
|
||||
{0x0000a554, 0x53040891, 0x53040891, 0x53040891, 0x53040891, 0x52040891, 0x52040891, 0x50001e69, 0x50001e69},
|
||||
{0x0000a558, 0x58040893, 0x58040893, 0x57040893, 0x57040893, 0x56040893, 0x56040893, 0x550006f4, 0x550006f4},
|
||||
{0x0000a55c, 0x5c0408b4, 0x5c0408b4, 0x5a0408b4, 0x5a0408b4, 0x5a0408b4, 0x5a0408b4, 0x59000ad3, 0x59000ad3},
|
||||
{0x0000a560, 0x610408b6, 0x610408b6, 0x5e0408b6, 0x5e0408b6, 0x5e0408b6, 0x5e0408b6, 0x5e000ad5, 0x5e000ad5},
|
||||
{0x0000a564, 0x670408f6, 0x670408f6, 0x620408f6, 0x620408f6, 0x620408f6, 0x620408f6, 0x61001ced, 0x61001ced},
|
||||
{0x0000a568, 0x6a040cf6, 0x6a040cf6, 0x66040cf6, 0x66040cf6, 0x66040cf6, 0x66040cf6, 0x660018d4, 0x660018d4},
|
||||
{0x0000a56c, 0x6d040d76, 0x6d040d76, 0x6a040d76, 0x6a040d76, 0x6a040d76, 0x6a040d76, 0x660018d4, 0x660018d4},
|
||||
{0x0000a570, 0x70060db6, 0x70060db6, 0x6e060db6, 0x6e060db6, 0x6e060db6, 0x6e060db6, 0x660018d4, 0x660018d4},
|
||||
{0x0000a574, 0x730a0df6, 0x730a0df6, 0x720a0df6, 0x720a0df6, 0x720a0df6, 0x720a0df6, 0x660018d4, 0x660018d4},
|
||||
{0x0000a578, 0x770a13f6, 0x770a13f6, 0x760a13f6, 0x760a13f6, 0x760a13f6, 0x760a13f6, 0x660018d4, 0x660018d4},
|
||||
{0x0000a57c, 0x770a13f6, 0x770a13f6, 0x760a13f6, 0x760a13f6, 0x760a13f6, 0x760a13f6, 0x660018d4, 0x660018d4},
|
||||
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x03804000, 0x03804000},
|
||||
{0x0000a610, 0x04c08c01, 0x04c08c01, 0x04808b01, 0x04808b01, 0x04808a01, 0x04808a01, 0x0300ca02, 0x0300ca02},
|
||||
{0x0000a614, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00000e04, 0x00000e04},
|
||||
{0x0000a618, 0x04010c01, 0x04010c01, 0x03c10b01, 0x03c10b01, 0x03810a01, 0x03810a01, 0x03014000, 0x03014000},
|
||||
{0x0000a61c, 0x03814e05, 0x03814e05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03414d05, 0x00000000, 0x00000000},
|
||||
{0x0000a620, 0x04010303, 0x04010303, 0x03c10303, 0x03c10303, 0x03810303, 0x03810303, 0x00000000, 0x00000000},
|
||||
{0x0000a624, 0x03814e05, 0x03814e05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03414d05, 0x03014000, 0x03014000},
|
||||
{0x0000a628, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x00c0c000, 0x03804c05, 0x03804c05},
|
||||
{0x0000a62c, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x00c0c303, 0x0701de06, 0x0701de06},
|
||||
{0x0000a630, 0x03418000, 0x03418000, 0x03018000, 0x03018000, 0x02c18000, 0x02c18000, 0x07819c07, 0x07819c07},
|
||||
{0x0000a634, 0x03815004, 0x03815004, 0x03414f04, 0x03414f04, 0x03414e04, 0x03414e04, 0x0701dc07, 0x0701dc07},
|
||||
{0x0000a638, 0x03005302, 0x03005302, 0x02c05202, 0x02c05202, 0x02805202, 0x02805202, 0x0701dc07, 0x0701dc07},
|
||||
{0x0000a63c, 0x04c09302, 0x04c09302, 0x04809202, 0x04809202, 0x04809202, 0x04809202, 0x0701dc07, 0x0701dc07},
|
||||
{0x0000b2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa},
|
||||
{0x0000b2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc},
|
||||
{0x0000b2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0},
|
||||
{0x0000a60c, 0x02c04b01, 0x02c04b01, 0x02c04b01, 0x02c04b01, 0x02c04b01, 0x02c04b01, 0x03804000, 0x03804000},
|
||||
{0x0000a610, 0x04008b01, 0x04008b01, 0x04008b01, 0x04008b01, 0x03c08b01, 0x03c08b01, 0x0300ca02, 0x0300ca02},
|
||||
{0x0000a614, 0x05811403, 0x05811403, 0x05411303, 0x05411303, 0x05411303, 0x05411303, 0x00000e04, 0x00000e04},
|
||||
{0x0000a618, 0x05811604, 0x05811604, 0x05411504, 0x05411504, 0x05411504, 0x05411504, 0x03014000, 0x03014000},
|
||||
{0x0000a61c, 0x05811604, 0x05811604, 0x05411504, 0x05411504, 0x05411504, 0x05411504, 0x00000000, 0x00000000},
|
||||
{0x0000a620, 0x05811604, 0x05811604, 0x05411504, 0x05411504, 0x05411504, 0x05411504, 0x00000000, 0x00000000},
|
||||
{0x0000a624, 0x05811604, 0x05811604, 0x05411504, 0x05411504, 0x05411504, 0x05411504, 0x03014000, 0x03014000},
|
||||
{0x0000a628, 0x05811604, 0x05811604, 0x05411504, 0x05411504, 0x05411504, 0x05411504, 0x03804c05, 0x03804c05},
|
||||
{0x0000a62c, 0x06815604, 0x06815604, 0x06415504, 0x06415504, 0x06015504, 0x06015504, 0x0701de06, 0x0701de06},
|
||||
{0x0000a630, 0x07819a05, 0x07819a05, 0x07419905, 0x07419905, 0x07019805, 0x07019805, 0x07819c07, 0x07819c07},
|
||||
{0x0000a634, 0x07819e06, 0x07819e06, 0x07419d06, 0x07419d06, 0x07019c06, 0x07019c06, 0x0701dc07, 0x0701dc07},
|
||||
{0x0000a638, 0x07819e06, 0x07819e06, 0x07419d06, 0x07419d06, 0x07019c06, 0x07019c06, 0x0701dc07, 0x0701dc07},
|
||||
{0x0000a63c, 0x07819e06, 0x07819e06, 0x07419d06, 0x07419d06, 0x07019c06, 0x07019c06, 0x0701dc07, 0x0701dc07},
|
||||
{0x0000b2dc, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xfffd5aaa, 0xfffd5aaa},
|
||||
{0x0000b2e0, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffe9ccc, 0xfffe9ccc},
|
||||
{0x0000b2e4, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffffe0f0, 0xffffe0f0},
|
||||
{0x0000b2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00},
|
||||
{0x0000c2dc, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xffffaaaa, 0xfffd5aaa, 0xfffd5aaa},
|
||||
{0x0000c2e0, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xffffcccc, 0xfffe9ccc, 0xfffe9ccc},
|
||||
{0x0000c2e4, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xfffff0f0, 0xffffe0f0, 0xffffe0f0},
|
||||
{0x0000c2dc, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xffff6aaa, 0xfffd5aaa, 0xfffd5aaa},
|
||||
{0x0000c2e0, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffdcccc, 0xfffe9ccc, 0xfffe9ccc},
|
||||
{0x0000c2e4, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffe3b0f0, 0xffffe0f0, 0xffffe0f0},
|
||||
{0x0000c2e8, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xffffff00, 0xfffcff00, 0xfffcff00},
|
||||
{0x00016044, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4},
|
||||
{0x00016048, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401},
|
||||
{0x00016048, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401},
|
||||
{0x00016280, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01801e84, 0x01808e84, 0x01808e84},
|
||||
{0x00016444, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4},
|
||||
{0x00016448, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401},
|
||||
{0x00016448, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401},
|
||||
{0x00016844, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x056db2d4, 0x010002d4, 0x010002d4},
|
||||
{0x00016848, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x62482401, 0x66482401, 0x66482401},
|
||||
{0x00016848, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401, 0x66482401},
|
||||
};
|
||||
|
||||
static const u32 ar955x_1p0_mac_core[][2] = {
|
||||
@ -846,7 +846,7 @@ static const u32 ar955x_1p0_baseband_core[][2] = {
|
||||
{0x0000a44c, 0x00000001},
|
||||
{0x0000a450, 0x00010000},
|
||||
{0x0000a458, 0x00000000},
|
||||
{0x0000a644, 0x3fad9d74},
|
||||
{0x0000a644, 0xbfad9d74},
|
||||
{0x0000a648, 0x0048060a},
|
||||
{0x0000a64c, 0x00003c37},
|
||||
{0x0000a670, 0x03020100},
|
||||
@ -1277,7 +1277,7 @@ static const u32 ar955x_1p0_modes_fast_clock[][3] = {
|
||||
{0x0000801c, 0x148ec02b, 0x148ec057},
|
||||
{0x00008318, 0x000044c0, 0x00008980},
|
||||
{0x00009e00, 0x0372131c, 0x0372131c},
|
||||
{0x0000a230, 0x0000000b, 0x00000016},
|
||||
{0x0000a230, 0x0000400b, 0x00004016},
|
||||
{0x0000a254, 0x00000898, 0x00001130},
|
||||
};
|
||||
|
||||
|
@ -685,6 +685,82 @@ static const u32 ar9580_1p0_mixed_ob_db_tx_gain_table[][5] = {
|
||||
|
||||
#define ar9580_1p0_high_ob_db_tx_gain_table ar9300Modes_high_ob_db_tx_gain_table_2p2
|
||||
|
||||
#define ar9580_1p0_type5_tx_gain_table ar9300Modes_type5_tx_gain_table_2p2
|
||||
|
||||
static const u32 ar9580_1p0_type6_tx_gain_table[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
||||
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
|
||||
{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
|
||||
{0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202},
|
||||
{0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400},
|
||||
{0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402},
|
||||
{0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404},
|
||||
{0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603},
|
||||
{0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02},
|
||||
{0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04},
|
||||
{0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20},
|
||||
{0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20},
|
||||
{0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22},
|
||||
{0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24},
|
||||
{0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640},
|
||||
{0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660},
|
||||
{0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861},
|
||||
{0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81},
|
||||
{0x0000a54c, 0x5e08442e, 0x5e08442e, 0x47001a83, 0x47001a83},
|
||||
{0x0000a550, 0x620a4431, 0x620a4431, 0x4a001c84, 0x4a001c84},
|
||||
{0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3},
|
||||
{0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5},
|
||||
{0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9},
|
||||
{0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb},
|
||||
{0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
|
||||
{0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
|
||||
{0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
|
||||
{0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000},
|
||||
{0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501},
|
||||
{0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501},
|
||||
{0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03},
|
||||
{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
|
||||
{0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04},
|
||||
{0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
{0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
|
||||
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
|
||||
{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
|
||||
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
};
|
||||
|
||||
static const u32 ar9580_1p0_soc_preamble[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x000040a4, 0x00a0c1c9},
|
||||
|
@ -109,14 +109,11 @@ struct ath_descdma {
|
||||
void *dd_desc;
|
||||
dma_addr_t dd_desc_paddr;
|
||||
u32 dd_desc_len;
|
||||
struct ath_buf *dd_bufptr;
|
||||
};
|
||||
|
||||
int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
struct list_head *head, const char *name,
|
||||
int nbuf, int ndesc, bool is_tx);
|
||||
void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
struct list_head *head);
|
||||
|
||||
/***********/
|
||||
/* RX / TX */
|
||||
@ -317,10 +314,8 @@ struct ath_rx {
|
||||
u32 *rxlink;
|
||||
u32 num_pkts;
|
||||
unsigned int rxfilter;
|
||||
spinlock_t rxbuflock;
|
||||
struct list_head rxbuf;
|
||||
struct ath_descdma rxdma;
|
||||
struct ath_buf *rx_bufptr;
|
||||
struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
|
||||
|
||||
struct sk_buff *frag;
|
||||
@ -328,7 +323,6 @@ struct ath_rx {
|
||||
|
||||
int ath_startrecv(struct ath_softc *sc);
|
||||
bool ath_stoprecv(struct ath_softc *sc);
|
||||
void ath_flushrecv(struct ath_softc *sc);
|
||||
u32 ath_calcrxfilter(struct ath_softc *sc);
|
||||
int ath_rx_init(struct ath_softc *sc, int nbufs);
|
||||
void ath_rx_cleanup(struct ath_softc *sc);
|
||||
@ -338,14 +332,12 @@ void ath_txq_lock(struct ath_softc *sc, struct ath_txq *txq);
|
||||
void ath_txq_unlock(struct ath_softc *sc, struct ath_txq *txq);
|
||||
void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq);
|
||||
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
|
||||
bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx);
|
||||
void ath_draintxq(struct ath_softc *sc,
|
||||
struct ath_txq *txq, bool retry_tx);
|
||||
bool ath_drain_all_txq(struct ath_softc *sc);
|
||||
void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq);
|
||||
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
|
||||
void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
|
||||
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
|
||||
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);
|
||||
@ -646,7 +638,6 @@ void ath_ant_comb_update(struct ath_softc *sc);
|
||||
enum sc_op_flags {
|
||||
SC_OP_INVALID,
|
||||
SC_OP_BEACONS,
|
||||
SC_OP_RXFLUSH,
|
||||
SC_OP_ANI_RUN,
|
||||
SC_OP_PRIM_STA_VIF,
|
||||
SC_OP_HW_RESET,
|
||||
@ -675,6 +666,23 @@ struct ath9k_vif_iter_data {
|
||||
int nadhocs; /* number of adhoc vifs */
|
||||
};
|
||||
|
||||
/* enum spectral_mode:
|
||||
*
|
||||
* @SPECTRAL_DISABLED: spectral mode is disabled
|
||||
* @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
|
||||
* something else.
|
||||
* @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
|
||||
* is performed manually.
|
||||
* @SPECTRAL_CHANSCAN: Like manual, but also triggered when changing channels
|
||||
* during a channel scan.
|
||||
*/
|
||||
enum spectral_mode {
|
||||
SPECTRAL_DISABLED = 0,
|
||||
SPECTRAL_BACKGROUND,
|
||||
SPECTRAL_MANUAL,
|
||||
SPECTRAL_CHANSCAN,
|
||||
};
|
||||
|
||||
struct ath_softc {
|
||||
struct ieee80211_hw *hw;
|
||||
struct device *dev;
|
||||
@ -743,6 +751,10 @@ struct ath_softc {
|
||||
u8 ant_tx, ant_rx;
|
||||
struct dfs_pattern_detector *dfs_detector;
|
||||
u32 wow_enabled;
|
||||
/* relay(fs) channel for spectral scan */
|
||||
struct rchan *rfs_chan_spec_scan;
|
||||
enum spectral_mode spectral_mode;
|
||||
int scanning;
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
atomic_t wow_got_bmiss_intr;
|
||||
@ -751,6 +763,133 @@ struct ath_softc {
|
||||
#endif
|
||||
};
|
||||
|
||||
#define SPECTRAL_SCAN_BITMASK 0x10
|
||||
/* Radar info packet format, used for DFS and spectral formats. */
|
||||
struct ath_radar_info {
|
||||
u8 pulse_length_pri;
|
||||
u8 pulse_length_ext;
|
||||
u8 pulse_bw_info;
|
||||
} __packed;
|
||||
|
||||
/* The HT20 spectral data has 4 bytes of additional information at it's end.
|
||||
*
|
||||
* [7:0]: all bins {max_magnitude[1:0], bitmap_weight[5:0]}
|
||||
* [7:0]: all bins max_magnitude[9:2]
|
||||
* [7:0]: all bins {max_index[5:0], max_magnitude[11:10]}
|
||||
* [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
|
||||
*/
|
||||
struct ath_ht20_mag_info {
|
||||
u8 all_bins[3];
|
||||
u8 max_exp;
|
||||
} __packed;
|
||||
|
||||
#define SPECTRAL_HT20_NUM_BINS 56
|
||||
|
||||
/* WARNING: don't actually use this struct! MAC may vary the amount of
|
||||
* data by -1/+2. This struct is for reference only.
|
||||
*/
|
||||
struct ath_ht20_fft_packet {
|
||||
u8 data[SPECTRAL_HT20_NUM_BINS];
|
||||
struct ath_ht20_mag_info mag_info;
|
||||
struct ath_radar_info radar_info;
|
||||
} __packed;
|
||||
|
||||
#define SPECTRAL_HT20_TOTAL_DATA_LEN (sizeof(struct ath_ht20_fft_packet))
|
||||
|
||||
/* Dynamic 20/40 mode:
|
||||
*
|
||||
* [7:0]: lower bins {max_magnitude[1:0], bitmap_weight[5:0]}
|
||||
* [7:0]: lower bins max_magnitude[9:2]
|
||||
* [7:0]: lower bins {max_index[5:0], max_magnitude[11:10]}
|
||||
* [7:0]: upper bins {max_magnitude[1:0], bitmap_weight[5:0]}
|
||||
* [7:0]: upper bins max_magnitude[9:2]
|
||||
* [7:0]: upper bins {max_index[5:0], max_magnitude[11:10]}
|
||||
* [3:0]: max_exp (shift amount to size max bin to 8-bit unsigned)
|
||||
*/
|
||||
struct ath_ht20_40_mag_info {
|
||||
u8 lower_bins[3];
|
||||
u8 upper_bins[3];
|
||||
u8 max_exp;
|
||||
} __packed;
|
||||
|
||||
#define SPECTRAL_HT20_40_NUM_BINS 128
|
||||
|
||||
/* WARNING: don't actually use this struct! MAC may vary the amount of
|
||||
* data. This struct is for reference only.
|
||||
*/
|
||||
struct ath_ht20_40_fft_packet {
|
||||
u8 data[SPECTRAL_HT20_40_NUM_BINS];
|
||||
struct ath_ht20_40_mag_info mag_info;
|
||||
struct ath_radar_info radar_info;
|
||||
} __packed;
|
||||
|
||||
|
||||
#define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet))
|
||||
|
||||
/* grabs the max magnitude from the all/upper/lower bins */
|
||||
static inline u16 spectral_max_magnitude(u8 *bins)
|
||||
{
|
||||
return (bins[0] & 0xc0) >> 6 |
|
||||
(bins[1] & 0xff) << 2 |
|
||||
(bins[2] & 0x03) << 10;
|
||||
}
|
||||
|
||||
/* return the max magnitude from the all/upper/lower bins */
|
||||
static inline u8 spectral_max_index(u8 *bins)
|
||||
{
|
||||
s8 m = (bins[2] & 0xfc) >> 2;
|
||||
|
||||
/* TODO: this still doesn't always report the right values ... */
|
||||
if (m > 32)
|
||||
m |= 0xe0;
|
||||
else
|
||||
m &= ~0xe0;
|
||||
|
||||
return m + 29;
|
||||
}
|
||||
|
||||
/* return the bitmap weight from the all/upper/lower bins */
|
||||
static inline u8 spectral_bitmap_weight(u8 *bins)
|
||||
{
|
||||
return bins[0] & 0x3f;
|
||||
}
|
||||
|
||||
/* FFT sample format given to userspace via debugfs.
|
||||
*
|
||||
* Please keep the type/length at the front position and change
|
||||
* other fields after adding another sample type
|
||||
*
|
||||
* TODO: this might need rework when switching to nl80211-based
|
||||
* interface.
|
||||
*/
|
||||
enum ath_fft_sample_type {
|
||||
ATH_FFT_SAMPLE_HT20 = 0,
|
||||
};
|
||||
|
||||
struct fft_sample_tlv {
|
||||
u8 type; /* see ath_fft_sample */
|
||||
u16 length;
|
||||
/* type dependent data follows */
|
||||
} __packed;
|
||||
|
||||
struct fft_sample_ht20 {
|
||||
struct fft_sample_tlv tlv;
|
||||
|
||||
u8 __alignment;
|
||||
|
||||
u16 freq;
|
||||
s8 rssi;
|
||||
s8 noise;
|
||||
|
||||
u16 max_magnitude;
|
||||
u8 max_index;
|
||||
u8 bitmap_weight;
|
||||
|
||||
u64 tsf;
|
||||
|
||||
u16 data[SPECTRAL_HT20_NUM_BINS];
|
||||
} __packed;
|
||||
|
||||
void ath9k_tasklet(unsigned long data);
|
||||
int ath_cabq_update(struct ath_softc *);
|
||||
|
||||
@ -773,6 +912,10 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
|
||||
void ath9k_reload_chainmask_settings(struct ath_softc *sc);
|
||||
|
||||
bool ath9k_uses_beacons(int type);
|
||||
void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw);
|
||||
int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
|
||||
enum spectral_mode spectral_mode);
|
||||
|
||||
|
||||
#ifdef CONFIG_ATH9K_PCI
|
||||
int ath_pci_init(void);
|
||||
|
@ -147,6 +147,7 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
|
||||
skb->len, DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(skb);
|
||||
bf->bf_buf_addr = 0;
|
||||
bf->bf_mpdu = NULL;
|
||||
}
|
||||
|
||||
skb = ieee80211_beacon_get(hw, vif);
|
||||
@ -198,7 +199,7 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
|
||||
if (sc->nvifs > 1) {
|
||||
ath_dbg(common, BEACON,
|
||||
"Flushing previous cabq traffic\n");
|
||||
ath_draintxq(sc, cabq, false);
|
||||
ath_draintxq(sc, cabq);
|
||||
}
|
||||
}
|
||||
|
||||
@ -359,7 +360,6 @@ void ath9k_beacon_tasklet(unsigned long data)
|
||||
return;
|
||||
|
||||
bf = ath9k_beacon_generate(sc->hw, vif);
|
||||
WARN_ON(!bf);
|
||||
|
||||
if (sc->beacon.bmisscnt != 0) {
|
||||
ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n",
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/relay.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "ath9k.h"
|
||||
@ -861,7 +862,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
|
||||
RXS_ERR("RX-LENGTH-ERR", rx_len_err);
|
||||
RXS_ERR("RX-OOM-ERR", rx_oom_err);
|
||||
RXS_ERR("RX-RATE-ERR", rx_rate_err);
|
||||
RXS_ERR("RX-DROP-RXFLUSH", rx_drop_rxflush);
|
||||
RXS_ERR("RX-TOO-MANY-FRAGS", rx_too_many_frags_err);
|
||||
|
||||
PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN);
|
||||
@ -966,6 +966,112 @@ static const struct file_operations fops_recv = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
char *mode = "";
|
||||
unsigned int len;
|
||||
|
||||
switch (sc->spectral_mode) {
|
||||
case SPECTRAL_DISABLED:
|
||||
mode = "disable";
|
||||
break;
|
||||
case SPECTRAL_BACKGROUND:
|
||||
mode = "background";
|
||||
break;
|
||||
case SPECTRAL_CHANSCAN:
|
||||
mode = "chanscan";
|
||||
break;
|
||||
case SPECTRAL_MANUAL:
|
||||
mode = "manual";
|
||||
break;
|
||||
}
|
||||
len = strlen(mode);
|
||||
return simple_read_from_buffer(user_buf, count, ppos, mode, len);
|
||||
}
|
||||
|
||||
static ssize_t write_file_spec_scan_ctl(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath_softc *sc = file->private_data;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
char buf[32];
|
||||
ssize_t len;
|
||||
|
||||
len = min(count, sizeof(buf) - 1);
|
||||
if (copy_from_user(buf, user_buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
buf[len] = '\0';
|
||||
|
||||
if (strncmp("trigger", buf, 7) == 0) {
|
||||
ath9k_spectral_scan_trigger(sc->hw);
|
||||
} else if (strncmp("background", buf, 9) == 0) {
|
||||
ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND);
|
||||
ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n");
|
||||
} else if (strncmp("chanscan", buf, 8) == 0) {
|
||||
ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN);
|
||||
ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n");
|
||||
} else if (strncmp("manual", buf, 6) == 0) {
|
||||
ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL);
|
||||
ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n");
|
||||
} else if (strncmp("disable", buf, 7) == 0) {
|
||||
ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED);
|
||||
ath_dbg(common, CONFIG, "spectral scan: disabled\n");
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_spec_scan_ctl = {
|
||||
.read = read_file_spec_scan_ctl,
|
||||
.write = write_file_spec_scan_ctl,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static struct dentry *create_buf_file_handler(const char *filename,
|
||||
struct dentry *parent,
|
||||
umode_t mode,
|
||||
struct rchan_buf *buf,
|
||||
int *is_global)
|
||||
{
|
||||
struct dentry *buf_file;
|
||||
|
||||
buf_file = debugfs_create_file(filename, mode, parent, buf,
|
||||
&relay_file_operations);
|
||||
*is_global = 1;
|
||||
return buf_file;
|
||||
}
|
||||
|
||||
static int remove_buf_file_handler(struct dentry *dentry)
|
||||
{
|
||||
debugfs_remove(dentry);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath_debug_send_fft_sample(struct ath_softc *sc,
|
||||
struct fft_sample_tlv *fft_sample_tlv)
|
||||
{
|
||||
if (!sc->rfs_chan_spec_scan)
|
||||
return;
|
||||
|
||||
relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv,
|
||||
fft_sample_tlv->length + sizeof(*fft_sample_tlv));
|
||||
}
|
||||
|
||||
static struct rchan_callbacks rfs_spec_scan_cb = {
|
||||
.create_buf_file = create_buf_file_handler,
|
||||
.remove_buf_file = remove_buf_file_handler,
|
||||
};
|
||||
|
||||
|
||||
static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
@ -1780,6 +1886,14 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
&fops_base_eeprom);
|
||||
debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||
&fops_modal_eeprom);
|
||||
sc->rfs_chan_spec_scan = relay_open("spectral_scan",
|
||||
sc->debug.debugfs_phy,
|
||||
262144, 4, &rfs_spec_scan_cb,
|
||||
NULL);
|
||||
debugfs_create_file("spectral_scan_ctl", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, sc,
|
||||
&fops_spec_scan_ctl);
|
||||
|
||||
#ifdef CONFIG_ATH9K_MAC_DEBUG
|
||||
debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||
&fops_samps);
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
struct ath_txq;
|
||||
struct ath_buf;
|
||||
struct fft_sample_tlv;
|
||||
|
||||
#ifdef CONFIG_ATH9K_DEBUGFS
|
||||
#define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++
|
||||
@ -216,7 +217,6 @@ struct ath_tx_stats {
|
||||
* @rx_oom_err: No. of frames dropped due to OOM issues.
|
||||
* @rx_rate_err: No. of frames dropped due to rate errors.
|
||||
* @rx_too_many_frags_err: Frames dropped due to too-many-frags received.
|
||||
* @rx_drop_rxflush: No. of frames dropped due to RX-FLUSH.
|
||||
* @rx_beacons: No. of beacons received.
|
||||
* @rx_frags: No. of rx-fragements received.
|
||||
*/
|
||||
@ -235,7 +235,6 @@ struct ath_rx_stats {
|
||||
u32 rx_oom_err;
|
||||
u32 rx_rate_err;
|
||||
u32 rx_too_many_frags_err;
|
||||
u32 rx_drop_rxflush;
|
||||
u32 rx_beacons;
|
||||
u32 rx_frags;
|
||||
};
|
||||
@ -323,6 +322,10 @@ void ath9k_sta_remove_debugfs(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct dentry *dir);
|
||||
|
||||
void ath_debug_send_fft_sample(struct ath_softc *sc,
|
||||
struct fft_sample_tlv *fft_sample);
|
||||
|
||||
#else
|
||||
|
||||
#define RX_STAT_INC(c) /* NOP */
|
||||
|
@ -280,14 +280,14 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath9k_reg_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
static void ath9k_reg_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct ath9k_htc_priv *priv = hw->priv;
|
||||
|
||||
return ath_reg_notifier_apply(wiphy, request,
|
||||
ath9k_hw_regulatory(priv->ah));
|
||||
ath_reg_notifier_apply(wiphy, request,
|
||||
ath9k_hw_regulatory(priv->ah));
|
||||
}
|
||||
|
||||
static unsigned int ath9k_regread(void *hw_priv, u32 reg_offset)
|
||||
|
@ -1628,7 +1628,9 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
|
||||
if (!ret)
|
||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP:
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid);
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
|
@ -344,6 +344,8 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
|
||||
endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv,
|
||||
skb, htc_hdr->endpoint_id,
|
||||
txok);
|
||||
} else {
|
||||
kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,22 +101,6 @@ static inline void ath9k_hw_spur_mitigate_freq(struct ath_hw *ah,
|
||||
ath9k_hw_private_ops(ah)->spur_mitigate_freq(ah, chan);
|
||||
}
|
||||
|
||||
static inline int ath9k_hw_rf_alloc_ext_banks(struct ath_hw *ah)
|
||||
{
|
||||
if (!ath9k_hw_private_ops(ah)->rf_alloc_ext_banks)
|
||||
return 0;
|
||||
|
||||
return ath9k_hw_private_ops(ah)->rf_alloc_ext_banks(ah);
|
||||
}
|
||||
|
||||
static inline void ath9k_hw_rf_free_ext_banks(struct ath_hw *ah)
|
||||
{
|
||||
if (!ath9k_hw_private_ops(ah)->rf_free_ext_banks)
|
||||
return;
|
||||
|
||||
ath9k_hw_private_ops(ah)->rf_free_ext_banks(ah);
|
||||
}
|
||||
|
||||
static inline bool ath9k_hw_set_rf_regs(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
u16 modesIndex)
|
||||
|
@ -54,11 +54,6 @@ static void ath9k_hw_init_cal_settings(struct ath_hw *ah)
|
||||
ath9k_hw_private_ops(ah)->init_cal_settings(ah);
|
||||
}
|
||||
|
||||
static void ath9k_hw_init_mode_regs(struct ath_hw *ah)
|
||||
{
|
||||
ath9k_hw_private_ops(ah)->init_mode_regs(ah);
|
||||
}
|
||||
|
||||
static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan)
|
||||
{
|
||||
@ -208,7 +203,7 @@ void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
udelay(hw_delay + BASE_ACTIVATE_DELAY);
|
||||
}
|
||||
|
||||
void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array,
|
||||
void ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array,
|
||||
int column, unsigned int *writecnt)
|
||||
{
|
||||
int r;
|
||||
@ -554,28 +549,19 @@ static int ath9k_hw_post_init(struct ath_hw *ah)
|
||||
ah->eep_ops->get_eeprom_ver(ah),
|
||||
ah->eep_ops->get_eeprom_rev(ah));
|
||||
|
||||
ecode = ath9k_hw_rf_alloc_ext_banks(ah);
|
||||
if (ecode) {
|
||||
ath_err(ath9k_hw_common(ah),
|
||||
"Failed allocating banks for external radio\n");
|
||||
ath9k_hw_rf_free_ext_banks(ah);
|
||||
return ecode;
|
||||
}
|
||||
|
||||
if (ah->config.enable_ani) {
|
||||
ath9k_hw_ani_setup(ah);
|
||||
if (ah->config.enable_ani)
|
||||
ath9k_hw_ani_init(ah);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath9k_hw_attach_ops(struct ath_hw *ah)
|
||||
static int ath9k_hw_attach_ops(struct ath_hw *ah)
|
||||
{
|
||||
if (AR_SREV_9300_20_OR_LATER(ah))
|
||||
ar9003_hw_attach_ops(ah);
|
||||
else
|
||||
ar9002_hw_attach_ops(ah);
|
||||
if (!AR_SREV_9300_20_OR_LATER(ah))
|
||||
return ar9002_hw_attach_ops(ah);
|
||||
|
||||
ar9003_hw_attach_ops(ah);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Called for all hardware families */
|
||||
@ -611,7 +597,9 @@ static int __ath9k_hw_init(struct ath_hw *ah)
|
||||
ath9k_hw_init_defaults(ah);
|
||||
ath9k_hw_init_config(ah);
|
||||
|
||||
ath9k_hw_attach_ops(ah);
|
||||
r = ath9k_hw_attach_ops(ah);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
|
||||
ath_err(common, "Couldn't wakeup chip\n");
|
||||
@ -675,8 +663,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;
|
||||
|
||||
ath9k_hw_init_mode_regs(ah);
|
||||
|
||||
if (!ah->is_pciexpress)
|
||||
ath9k_hw_disablepcie(ah);
|
||||
|
||||
@ -1153,12 +1139,9 @@ void ath9k_hw_deinit(struct ath_hw *ah)
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
|
||||
if (common->state < ATH_HW_INITIALIZED)
|
||||
goto free_hw;
|
||||
return;
|
||||
|
||||
ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
|
||||
|
||||
free_hw:
|
||||
ath9k_hw_rf_free_ext_banks(ah);
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_deinit);
|
||||
|
||||
@ -2576,12 +2559,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
||||
rx_chainmask >>= 1;
|
||||
}
|
||||
|
||||
if (AR_SREV_9300_20_OR_LATER(ah)) {
|
||||
ah->enabled_cals |= TX_IQ_CAL;
|
||||
if (AR_SREV_9485_OR_LATER(ah))
|
||||
ah->enabled_cals |= TX_IQ_ON_AGC_CAL;
|
||||
}
|
||||
|
||||
if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
|
||||
if (!(ah->ent_mode & AR_ENT_OTP_49GHZ_DISABLE))
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_MCI;
|
||||
@ -2590,7 +2567,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
|
||||
pCap->hw_caps |= ATH9K_HW_CAP_RTT;
|
||||
}
|
||||
|
||||
|
||||
if (AR_SREV_9280_20_OR_LATER(ah)) {
|
||||
pCap->hw_caps |= ATH9K_HW_WOW_DEVICE_CAPABLE |
|
||||
ATH9K_HW_WOW_PATTERN_MATCH_EXACT;
|
||||
|
@ -397,6 +397,7 @@ enum ath9k_int {
|
||||
#define MAX_RTT_TABLE_ENTRY 6
|
||||
#define MAX_IQCAL_MEASUREMENT 8
|
||||
#define MAX_CL_TAB_ENTRY 16
|
||||
#define CL_TAB_ENTRY(reg_base) (reg_base + (4 * j))
|
||||
|
||||
struct ath9k_hw_cal_data {
|
||||
u16 channel;
|
||||
@ -599,13 +600,10 @@ struct ath_hw_radar_conf {
|
||||
* @init_cal_settings: setup types of calibrations supported
|
||||
* @init_cal: starts actual calibration
|
||||
*
|
||||
* @init_mode_regs: Initializes mode registers
|
||||
* @init_mode_gain_regs: Initialize TX/RX gain registers
|
||||
*
|
||||
* @rf_set_freq: change frequency
|
||||
* @spur_mitigate_freq: spur mitigation
|
||||
* @rf_alloc_ext_banks:
|
||||
* @rf_free_ext_banks:
|
||||
* @set_rf_regs:
|
||||
* @compute_pll_control: compute the PLL control value to use for
|
||||
* AR_RTC_PLL_CONTROL for a given channel
|
||||
@ -620,7 +618,6 @@ struct ath_hw_private_ops {
|
||||
void (*init_cal_settings)(struct ath_hw *ah);
|
||||
bool (*init_cal)(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
|
||||
void (*init_mode_regs)(struct ath_hw *ah);
|
||||
void (*init_mode_gain_regs)(struct ath_hw *ah);
|
||||
void (*setup_calibration)(struct ath_hw *ah,
|
||||
struct ath9k_cal_list *currCal);
|
||||
@ -630,8 +627,6 @@ struct ath_hw_private_ops {
|
||||
struct ath9k_channel *chan);
|
||||
void (*spur_mitigate_freq)(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan);
|
||||
int (*rf_alloc_ext_banks)(struct ath_hw *ah);
|
||||
void (*rf_free_ext_banks)(struct ath_hw *ah);
|
||||
bool (*set_rf_regs)(struct ath_hw *ah,
|
||||
struct ath9k_channel *chan,
|
||||
u16 modesIndex);
|
||||
@ -660,6 +655,37 @@ struct ath_hw_private_ops {
|
||||
void (*ani_cache_ini_regs)(struct ath_hw *ah);
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ath_spec_scan - parameters for Atheros spectral scan
|
||||
*
|
||||
* @enabled: enable/disable spectral scan
|
||||
* @short_repeat: controls whether the chip is in spectral scan mode
|
||||
* for 4 usec (enabled) or 204 usec (disabled)
|
||||
* @count: number of scan results requested. There are special meanings
|
||||
* in some chip revisions:
|
||||
* AR92xx: highest bit set (>=128) for endless mode
|
||||
* (spectral scan won't stopped until explicitly disabled)
|
||||
* AR9300 and newer: 0 for endless mode
|
||||
* @endless: true if endless mode is intended. Otherwise, count value is
|
||||
* corrected to the next possible value.
|
||||
* @period: time duration between successive spectral scan entry points
|
||||
* (period*256*Tclk). Tclk = ath_common->clockrate
|
||||
* @fft_period: PHY passes FFT frames to MAC every (fft_period+1)*4uS
|
||||
*
|
||||
* Note: Tclk = 40MHz or 44MHz depending upon operating mode.
|
||||
* Typically it's 44MHz in 2/5GHz on later chips, but there's
|
||||
* a "fast clock" check for this in 5GHz.
|
||||
*
|
||||
*/
|
||||
struct ath_spec_scan {
|
||||
bool enabled;
|
||||
bool short_repeat;
|
||||
bool endless;
|
||||
u8 count;
|
||||
u8 period;
|
||||
u8 fft_period;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct ath_hw_ops - callbacks used by hardware code and driver code
|
||||
*
|
||||
@ -668,6 +694,10 @@ struct ath_hw_private_ops {
|
||||
*
|
||||
* @config_pci_powersave:
|
||||
* @calibrate: periodic calibration for NF, ANI, IQ, ADC gain, ADC-DC
|
||||
*
|
||||
* @spectral_scan_config: set parameters for spectral scan and enable/disable it
|
||||
* @spectral_scan_trigger: trigger a spectral scan run
|
||||
* @spectral_scan_wait: wait for a spectral scan run to finish
|
||||
*/
|
||||
struct ath_hw_ops {
|
||||
void (*config_pci_powersave)(struct ath_hw *ah,
|
||||
@ -688,6 +718,10 @@ struct ath_hw_ops {
|
||||
void (*antdiv_comb_conf_set)(struct ath_hw *ah,
|
||||
struct ath_hw_antcomb_conf *antconf);
|
||||
void (*antctrl_shared_chain_lnadiv)(struct ath_hw *hw, bool enable);
|
||||
void (*spectral_scan_config)(struct ath_hw *ah,
|
||||
struct ath_spec_scan *param);
|
||||
void (*spectral_scan_trigger)(struct ath_hw *ah);
|
||||
void (*spectral_scan_wait)(struct ath_hw *ah);
|
||||
};
|
||||
|
||||
struct ath_nf_limits {
|
||||
@ -710,6 +744,7 @@ enum ath_cal_list {
|
||||
struct ath_hw {
|
||||
struct ath_ops reg_ops;
|
||||
|
||||
struct device *dev;
|
||||
struct ieee80211_hw *hw;
|
||||
struct ath_common common;
|
||||
struct ath9k_hw_version hw_version;
|
||||
@ -771,7 +806,6 @@ struct ath_hw {
|
||||
struct ath9k_cal_list iq_caldata;
|
||||
struct ath9k_cal_list adcgain_caldata;
|
||||
struct ath9k_cal_list adcdc_caldata;
|
||||
struct ath9k_cal_list tempCompCalData;
|
||||
struct ath9k_cal_list *cal_list;
|
||||
struct ath9k_cal_list *cal_list_last;
|
||||
struct ath9k_cal_list *cal_list_curr;
|
||||
@ -830,10 +864,6 @@ struct ath_hw {
|
||||
/* ANI */
|
||||
u32 proc_phyerr;
|
||||
u32 aniperiod;
|
||||
int totalSizeDesired[5];
|
||||
int coarse_high[5];
|
||||
int coarse_low[5];
|
||||
int firpwr[5];
|
||||
enum ath9k_ani_cmd ani_function;
|
||||
u32 ani_skip_count;
|
||||
|
||||
@ -979,7 +1009,7 @@ void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
|
||||
void ath9k_hw_synth_delay(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||
int hw_delay);
|
||||
bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
|
||||
void ath9k_hw_write_array(struct ath_hw *ah, struct ar5416IniArray *array,
|
||||
void ath9k_hw_write_array(struct ath_hw *ah, const struct ar5416IniArray *array,
|
||||
int column, unsigned int *writecnt);
|
||||
u32 ath9k_hw_reverse_bits(u32 val, u32 n);
|
||||
u16 ath9k_hw_computetxtime(struct ath_hw *ah,
|
||||
@ -1066,16 +1096,17 @@ void ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain);
|
||||
int ar9003_paprd_init_table(struct ath_hw *ah);
|
||||
bool ar9003_paprd_is_done(struct ath_hw *ah);
|
||||
bool ar9003_is_paprd_enabled(struct ath_hw *ah);
|
||||
void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
|
||||
|
||||
/* Hardware family op attach helpers */
|
||||
void ar5008_hw_attach_phy_ops(struct ath_hw *ah);
|
||||
int ar5008_hw_attach_phy_ops(struct ath_hw *ah);
|
||||
void ar9002_hw_attach_phy_ops(struct ath_hw *ah);
|
||||
void ar9003_hw_attach_phy_ops(struct ath_hw *ah);
|
||||
|
||||
void ar9002_hw_attach_calib_ops(struct ath_hw *ah);
|
||||
void ar9003_hw_attach_calib_ops(struct ath_hw *ah);
|
||||
|
||||
void ar9002_hw_attach_ops(struct ath_hw *ah);
|
||||
int ar9002_hw_attach_ops(struct ath_hw *ah);
|
||||
void ar9003_hw_attach_ops(struct ath_hw *ah);
|
||||
|
||||
void ar9002_hw_load_ani_reg(struct ath_hw *ah, struct ath9k_channel *chan);
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/ath9k_platform.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/relay.h>
|
||||
|
||||
#include "ath9k.h"
|
||||
|
||||
@ -302,16 +303,15 @@ static void setup_ht_cap(struct ath_softc *sc,
|
||||
ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED;
|
||||
}
|
||||
|
||||
static int ath9k_reg_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
static void ath9k_reg_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
|
||||
int ret;
|
||||
|
||||
ret = ath_reg_notifier_apply(wiphy, request, reg);
|
||||
ath_reg_notifier_apply(wiphy, request, reg);
|
||||
|
||||
/* Set tx power */
|
||||
if (ah->curchan) {
|
||||
@ -321,8 +321,6 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,
|
||||
sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -337,7 +335,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
u8 *ds;
|
||||
struct ath_buf *bf;
|
||||
int i, bsize, error, desc_len;
|
||||
int i, bsize, desc_len;
|
||||
|
||||
ath_dbg(common, CONFIG, "%s DMA: %u buffers %u desc/buf\n",
|
||||
name, nbuf, ndesc);
|
||||
@ -353,8 +351,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
if ((desc_len % 4) != 0) {
|
||||
ath_err(common, "ath_desc not DWORD aligned\n");
|
||||
BUG_ON((desc_len % 4) != 0);
|
||||
error = -ENOMEM;
|
||||
goto fail;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dd->dd_desc_len = desc_len * nbuf * ndesc;
|
||||
@ -378,12 +375,11 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
}
|
||||
|
||||
/* allocate descriptors */
|
||||
dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
|
||||
&dd->dd_desc_paddr, GFP_KERNEL);
|
||||
if (dd->dd_desc == NULL) {
|
||||
error = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
dd->dd_desc = dmam_alloc_coherent(sc->dev, dd->dd_desc_len,
|
||||
&dd->dd_desc_paddr, GFP_KERNEL);
|
||||
if (!dd->dd_desc)
|
||||
return -ENOMEM;
|
||||
|
||||
ds = (u8 *) dd->dd_desc;
|
||||
ath_dbg(common, CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
|
||||
name, ds, (u32) dd->dd_desc_len,
|
||||
@ -391,12 +387,9 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
|
||||
/* allocate buffers */
|
||||
bsize = sizeof(struct ath_buf) * nbuf;
|
||||
bf = kzalloc(bsize, GFP_KERNEL);
|
||||
if (bf == NULL) {
|
||||
error = -ENOMEM;
|
||||
goto fail2;
|
||||
}
|
||||
dd->dd_bufptr = bf;
|
||||
bf = devm_kzalloc(sc->dev, bsize, GFP_KERNEL);
|
||||
if (!bf)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < nbuf; i++, bf++, ds += (desc_len * ndesc)) {
|
||||
bf->bf_desc = ds;
|
||||
@ -422,12 +415,6 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
|
||||
list_add_tail(&bf->list, head);
|
||||
}
|
||||
return 0;
|
||||
fail2:
|
||||
dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
|
||||
dd->dd_desc_paddr);
|
||||
fail:
|
||||
memset(dd, 0, sizeof(*dd));
|
||||
return error;
|
||||
}
|
||||
|
||||
static int ath9k_init_queues(struct ath_softc *sc)
|
||||
@ -457,11 +444,13 @@ static int ath9k_init_channels_rates(struct ath_softc *sc)
|
||||
ATH9K_NUM_CHANNELS);
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) {
|
||||
channels = kmemdup(ath9k_2ghz_chantable,
|
||||
channels = devm_kzalloc(sc->dev,
|
||||
sizeof(ath9k_2ghz_chantable), GFP_KERNEL);
|
||||
if (!channels)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(channels, ath9k_2ghz_chantable,
|
||||
sizeof(ath9k_2ghz_chantable));
|
||||
sc->sbands[IEEE80211_BAND_2GHZ].channels = channels;
|
||||
sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
|
||||
sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
|
||||
@ -472,14 +461,13 @@ static int ath9k_init_channels_rates(struct ath_softc *sc)
|
||||
}
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_5GHZ) {
|
||||
channels = kmemdup(ath9k_5ghz_chantable,
|
||||
channels = devm_kzalloc(sc->dev,
|
||||
sizeof(ath9k_5ghz_chantable), GFP_KERNEL);
|
||||
if (!channels) {
|
||||
if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
|
||||
kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
|
||||
if (!channels)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(channels, ath9k_5ghz_chantable,
|
||||
sizeof(ath9k_5ghz_chantable));
|
||||
sc->sbands[IEEE80211_BAND_5GHZ].channels = channels;
|
||||
sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
|
||||
sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
|
||||
@ -565,10 +553,11 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
int ret = 0, i;
|
||||
int csz = 0;
|
||||
|
||||
ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL);
|
||||
ah = devm_kzalloc(sc->dev, sizeof(struct ath_hw), GFP_KERNEL);
|
||||
if (!ah)
|
||||
return -ENOMEM;
|
||||
|
||||
ah->dev = sc->dev;
|
||||
ah->hw = sc->hw;
|
||||
ah->hw_version.devid = devid;
|
||||
ah->reg_ops.read = ath9k_ioread32;
|
||||
@ -636,7 +625,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
if (pdata && pdata->eeprom_name) {
|
||||
ret = ath9k_eeprom_request(sc, pdata->eeprom_name);
|
||||
if (ret)
|
||||
goto err_eeprom;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initializes the hardware for all supported chipsets */
|
||||
@ -676,10 +665,6 @@ err_queues:
|
||||
ath9k_hw_deinit(ah);
|
||||
err_hw:
|
||||
ath9k_eeprom_release(sc);
|
||||
err_eeprom:
|
||||
kfree(ah);
|
||||
sc->sc_ah = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -844,8 +829,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
|
||||
|
||||
/* Bring up device */
|
||||
error = ath9k_init_softc(devid, sc, bus_ops);
|
||||
if (error != 0)
|
||||
goto error_init;
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
ah = sc->sc_ah;
|
||||
common = ath9k_hw_common(ah);
|
||||
@ -855,19 +840,19 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
|
||||
error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
|
||||
ath9k_reg_notifier);
|
||||
if (error)
|
||||
goto error_regd;
|
||||
goto deinit;
|
||||
|
||||
reg = &common->regulatory;
|
||||
|
||||
/* Setup TX DMA */
|
||||
error = ath_tx_init(sc, ATH_TXBUF);
|
||||
if (error != 0)
|
||||
goto error_tx;
|
||||
goto deinit;
|
||||
|
||||
/* Setup RX DMA */
|
||||
error = ath_rx_init(sc, ATH_RXBUF);
|
||||
if (error != 0)
|
||||
goto error_rx;
|
||||
goto deinit;
|
||||
|
||||
ath9k_init_txpower_limits(sc);
|
||||
|
||||
@ -881,19 +866,19 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
|
||||
/* Register with mac80211 */
|
||||
error = ieee80211_register_hw(hw);
|
||||
if (error)
|
||||
goto error_register;
|
||||
goto rx_cleanup;
|
||||
|
||||
error = ath9k_init_debug(ah);
|
||||
if (error) {
|
||||
ath_err(common, "Unable to create debugfs files\n");
|
||||
goto error_world;
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
/* Handle world regulatory */
|
||||
if (!ath_is_world_regd(reg)) {
|
||||
error = regulatory_hint(hw->wiphy, reg->alpha2);
|
||||
if (error)
|
||||
goto error_world;
|
||||
goto unregister;
|
||||
}
|
||||
|
||||
ath_init_leds(sc);
|
||||
@ -901,17 +886,12 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
|
||||
|
||||
return 0;
|
||||
|
||||
error_world:
|
||||
unregister:
|
||||
ieee80211_unregister_hw(hw);
|
||||
error_register:
|
||||
rx_cleanup:
|
||||
ath_rx_cleanup(sc);
|
||||
error_rx:
|
||||
ath_tx_cleanup(sc);
|
||||
error_tx:
|
||||
/* Nothing */
|
||||
error_regd:
|
||||
deinit:
|
||||
ath9k_deinit_softc(sc);
|
||||
error_init:
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -923,12 +903,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
|
||||
kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);
|
||||
|
||||
if (sc->sbands[IEEE80211_BAND_5GHZ].channels)
|
||||
kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
|
||||
|
||||
ath9k_deinit_btcoex(sc);
|
||||
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
|
||||
@ -940,8 +914,11 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
|
||||
sc->dfs_detector->exit(sc->dfs_detector);
|
||||
|
||||
ath9k_eeprom_release(sc);
|
||||
kfree(sc->sc_ah);
|
||||
sc->sc_ah = NULL;
|
||||
|
||||
if (sc->rfs_chan_spec_scan) {
|
||||
relay_close(sc->rfs_chan_spec_scan);
|
||||
sc->rfs_chan_spec_scan = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ath9k_deinit_device(struct ath_softc *sc)
|
||||
@ -957,22 +934,9 @@ void ath9k_deinit_device(struct ath_softc *sc)
|
||||
|
||||
ieee80211_unregister_hw(hw);
|
||||
ath_rx_cleanup(sc);
|
||||
ath_tx_cleanup(sc);
|
||||
ath9k_deinit_softc(sc);
|
||||
}
|
||||
|
||||
void ath_descdma_cleanup(struct ath_softc *sc,
|
||||
struct ath_descdma *dd,
|
||||
struct list_head *head)
|
||||
{
|
||||
dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
|
||||
dd->dd_desc_paddr);
|
||||
|
||||
INIT_LIST_HEAD(head);
|
||||
kfree(dd->dd_bufptr);
|
||||
memset(dd, 0, sizeof(*dd));
|
||||
}
|
||||
|
||||
/************************/
|
||||
/* Module Hooks */
|
||||
/************************/
|
||||
|
@ -226,7 +226,8 @@ enum ath9k_phyerr {
|
||||
ATH9K_PHYERR_HT_LENGTH_ILLEGAL = 35,
|
||||
ATH9K_PHYERR_HT_RATE_ILLEGAL = 36,
|
||||
|
||||
ATH9K_PHYERR_MAX = 37,
|
||||
ATH9K_PHYERR_SPECTRAL = 38,
|
||||
ATH9K_PHYERR_MAX = 39,
|
||||
};
|
||||
|
||||
struct ath_desc {
|
||||
|
@ -182,7 +182,7 @@ static void ath_restart_work(struct ath_softc *sc)
|
||||
ath_start_ani(sc);
|
||||
}
|
||||
|
||||
static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
|
||||
static bool ath_prepare_reset(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
bool ret = true;
|
||||
@ -196,20 +196,12 @@ static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
|
||||
ath9k_debug_samp_bb_mac(sc);
|
||||
ath9k_hw_disable_interrupts(ah);
|
||||
|
||||
if (!ath_drain_all_txq(sc))
|
||||
ret = false;
|
||||
|
||||
if (!ath_stoprecv(sc))
|
||||
ret = false;
|
||||
|
||||
if (!ath_drain_all_txq(sc, retry_tx))
|
||||
ret = false;
|
||||
|
||||
if (!flush) {
|
||||
if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
|
||||
ath_rx_tasklet(sc, 1, true);
|
||||
ath_rx_tasklet(sc, 1, false);
|
||||
} else {
|
||||
ath_flushrecv(sc);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -255,18 +247,17 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
|
||||
bool retry_tx)
|
||||
static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath9k_hw_cal_data *caldata = NULL;
|
||||
bool fastcc = true;
|
||||
bool flush = false;
|
||||
int r;
|
||||
|
||||
__ath_cancel_work(sc);
|
||||
|
||||
tasklet_disable(&sc->intr_tq);
|
||||
spin_lock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
|
||||
@ -276,11 +267,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
|
||||
|
||||
if (!hchan) {
|
||||
fastcc = false;
|
||||
flush = true;
|
||||
hchan = ah->curchan;
|
||||
}
|
||||
|
||||
if (!ath_prepare_reset(sc, retry_tx, flush))
|
||||
if (!ath_prepare_reset(sc))
|
||||
fastcc = false;
|
||||
|
||||
ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n",
|
||||
@ -302,6 +292,8 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
|
||||
|
||||
out:
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
tasklet_enable(&sc->intr_tq);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -319,7 +311,7 @@ static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
|
||||
if (test_bit(SC_OP_INVALID, &sc->sc_flags))
|
||||
return -EIO;
|
||||
|
||||
r = ath_reset_internal(sc, hchan, false);
|
||||
r = ath_reset_internal(sc, hchan);
|
||||
|
||||
return r;
|
||||
}
|
||||
@ -549,23 +541,21 @@ chip_reset:
|
||||
#undef SCHED_INTR
|
||||
}
|
||||
|
||||
static int ath_reset(struct ath_softc *sc, bool retry_tx)
|
||||
static int ath_reset(struct ath_softc *sc)
|
||||
{
|
||||
int r;
|
||||
int i, r;
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
|
||||
r = ath_reset_internal(sc, NULL, retry_tx);
|
||||
r = ath_reset_internal(sc, NULL);
|
||||
|
||||
if (retry_tx) {
|
||||
int i;
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
if (ATH_TXQ_SETUP(sc, i)) {
|
||||
spin_lock_bh(&sc->tx.txq[i].axq_lock);
|
||||
ath_txq_schedule(sc, &sc->tx.txq[i]);
|
||||
spin_unlock_bh(&sc->tx.txq[i].axq_lock);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
if (!ATH_TXQ_SETUP(sc, i))
|
||||
continue;
|
||||
|
||||
spin_lock_bh(&sc->tx.txq[i].axq_lock);
|
||||
ath_txq_schedule(sc, &sc->tx.txq[i]);
|
||||
spin_unlock_bh(&sc->tx.txq[i].axq_lock);
|
||||
}
|
||||
|
||||
ath9k_ps_restore(sc);
|
||||
@ -586,7 +576,7 @@ void ath_reset_work(struct work_struct *work)
|
||||
{
|
||||
struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
|
||||
|
||||
ath_reset(sc, true);
|
||||
ath_reset(sc);
|
||||
}
|
||||
|
||||
/**********************/
|
||||
@ -804,7 +794,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
|
||||
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
|
||||
}
|
||||
|
||||
ath_prepare_reset(sc, false, true);
|
||||
ath_prepare_reset(sc);
|
||||
|
||||
if (sc->rx.frag) {
|
||||
dev_kfree_skb_any(sc->rx.frag);
|
||||
@ -1075,6 +1065,86 @@ static void ath9k_disable_ps(struct ath_softc *sc)
|
||||
ath_dbg(common, PS, "PowerSave disabled\n");
|
||||
}
|
||||
|
||||
void ath9k_spectral_scan_trigger(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 rxfilter;
|
||||
|
||||
if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
|
||||
ath_err(common, "spectrum analyzer not implemented on this hardware\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
rxfilter = ath9k_hw_getrxfilter(ah);
|
||||
ath9k_hw_setrxfilter(ah, rxfilter |
|
||||
ATH9K_RX_FILTER_PHYRADAR |
|
||||
ATH9K_RX_FILTER_PHYERR);
|
||||
|
||||
/* TODO: usually this should not be neccesary, but for some reason
|
||||
* (or in some mode?) the trigger must be called after the
|
||||
* configuration, otherwise the register will have its values reset
|
||||
* (on my ar9220 to value 0x01002310)
|
||||
*/
|
||||
ath9k_spectral_scan_config(hw, sc->spectral_mode);
|
||||
ath9k_hw_ops(ah)->spectral_scan_trigger(ah);
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
|
||||
enum spectral_mode spectral_mode)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_spec_scan param;
|
||||
|
||||
if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
|
||||
ath_err(common, "spectrum analyzer not implemented on this hardware\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* NOTE: this will generate a few samples ...
|
||||
*
|
||||
* TODO: review default parameters, and/or define an interface to set
|
||||
* them.
|
||||
*/
|
||||
param.enabled = 1;
|
||||
param.short_repeat = true;
|
||||
param.count = 8;
|
||||
param.endless = false;
|
||||
param.period = 0xFF;
|
||||
param.fft_period = 0xF;
|
||||
|
||||
switch (spectral_mode) {
|
||||
case SPECTRAL_DISABLED:
|
||||
param.enabled = 0;
|
||||
break;
|
||||
case SPECTRAL_BACKGROUND:
|
||||
/* send endless samples.
|
||||
* TODO: is this really useful for "background"?
|
||||
*/
|
||||
param.endless = 1;
|
||||
break;
|
||||
case SPECTRAL_CHANSCAN:
|
||||
break;
|
||||
case SPECTRAL_MANUAL:
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath9k_hw_ops(ah)->spectral_scan_config(ah, ¶m);
|
||||
ath9k_ps_restore(sc);
|
||||
|
||||
sc->spectral_mode = spectral_mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
@ -1188,6 +1258,11 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
*/
|
||||
if (old_pos >= 0)
|
||||
ath_update_survey_nf(sc, old_pos);
|
||||
|
||||
/* perform spectral scan if requested. */
|
||||
if (sc->scanning && sc->spectral_mode == SPECTRAL_CHANSCAN)
|
||||
ath9k_spectral_scan_trigger(hw);
|
||||
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
||||
@ -1610,7 +1685,9 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
|
||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
ath9k_ps_restore(sc);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP:
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath_tx_aggr_stop(sc, sta, tid);
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
@ -1729,11 +1806,11 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
|
||||
if (drop) {
|
||||
ath9k_ps_wakeup(sc);
|
||||
spin_lock_bh(&sc->sc_pcu_lock);
|
||||
drain_txq = ath_drain_all_txq(sc, false);
|
||||
drain_txq = ath_drain_all_txq(sc);
|
||||
spin_unlock_bh(&sc->sc_pcu_lock);
|
||||
|
||||
if (!drain_txq)
|
||||
ath_reset(sc, false);
|
||||
ath_reset(sc);
|
||||
|
||||
ath9k_ps_restore(sc);
|
||||
ieee80211_wake_queues(hw);
|
||||
@ -1833,6 +1910,9 @@ static u32 fill_chainmask(u32 cap, u32 new)
|
||||
|
||||
static bool validate_antenna_mask(struct ath_hw *ah, u32 val)
|
||||
{
|
||||
if (AR_SREV_9300_20_OR_LATER(ah))
|
||||
return true;
|
||||
|
||||
switch (val & 0x7) {
|
||||
case 0x1:
|
||||
case 0x3:
|
||||
@ -2238,6 +2318,19 @@ static void ath9k_set_wakeup(struct ieee80211_hw *hw, bool enabled)
|
||||
}
|
||||
|
||||
#endif
|
||||
static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
|
||||
sc->scanning = 1;
|
||||
}
|
||||
|
||||
static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct ath_softc *sc = hw->priv;
|
||||
|
||||
sc->scanning = 0;
|
||||
}
|
||||
|
||||
struct ieee80211_ops ath9k_ops = {
|
||||
.tx = ath9k_tx,
|
||||
@ -2284,4 +2377,6 @@ struct ieee80211_ops ath9k_ops = {
|
||||
.sta_add_debugfs = ath9k_sta_add_debugfs,
|
||||
.sta_remove_debugfs = ath9k_sta_remove_debugfs,
|
||||
#endif
|
||||
.sw_scan_start = ath9k_sw_scan_start,
|
||||
.sw_scan_complete = ath9k_sw_scan_complete,
|
||||
};
|
||||
|
@ -438,7 +438,7 @@ int ath_mci_setup(struct ath_softc *sc)
|
||||
struct ath_mci_buf *buf = &mci->sched_buf;
|
||||
int ret;
|
||||
|
||||
buf->bf_addr = dma_alloc_coherent(sc->dev,
|
||||
buf->bf_addr = dmam_alloc_coherent(sc->dev,
|
||||
ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE,
|
||||
&buf->bf_paddr, GFP_KERNEL);
|
||||
|
||||
@ -477,11 +477,6 @@ void ath_mci_cleanup(struct ath_softc *sc)
|
||||
struct ath_mci_coex *mci = &sc->mci_coex;
|
||||
struct ath_mci_buf *buf = &mci->sched_buf;
|
||||
|
||||
if (buf->bf_addr)
|
||||
dma_free_coherent(sc->dev,
|
||||
ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE,
|
||||
buf->bf_addr, buf->bf_paddr);
|
||||
|
||||
ar9003_mci_cleanup(ah);
|
||||
|
||||
ath_dbg(common, MCI, "MCI De-Initialized\n");
|
||||
|
@ -147,7 +147,6 @@ static const struct ath_bus_ops ath_pci_bus_ops = {
|
||||
|
||||
static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
void __iomem *mem;
|
||||
struct ath_softc *sc;
|
||||
struct ieee80211_hw *hw;
|
||||
u8 csz;
|
||||
@ -155,19 +154,19 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
int ret = 0;
|
||||
char hw_name[64];
|
||||
|
||||
if (pci_enable_device(pdev))
|
||||
if (pcim_enable_device(pdev))
|
||||
return -EIO;
|
||||
|
||||
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
|
||||
if (ret) {
|
||||
pr_err("32-bit DMA not available\n");
|
||||
goto err_dma;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
|
||||
if (ret) {
|
||||
pr_err("32-bit DMA consistent DMA enable failed\n");
|
||||
goto err_dma;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -203,25 +202,16 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
if ((val & 0x0000ff00) != 0)
|
||||
pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
|
||||
|
||||
ret = pci_request_region(pdev, 0, "ath9k");
|
||||
ret = pcim_iomap_regions(pdev, BIT(0), "ath9k");
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "PCI memory region reserve error\n");
|
||||
ret = -ENODEV;
|
||||
goto err_region;
|
||||
}
|
||||
|
||||
mem = pci_iomap(pdev, 0, 0);
|
||||
if (!mem) {
|
||||
pr_err("PCI memory map error\n") ;
|
||||
ret = -EIO;
|
||||
goto err_iomap;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
|
||||
if (!hw) {
|
||||
dev_err(&pdev->dev, "No memory for ieee80211_hw\n");
|
||||
ret = -ENOMEM;
|
||||
goto err_alloc_hw;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
SET_IEEE80211_DEV(hw, &pdev->dev);
|
||||
@ -230,7 +220,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
sc = hw->priv;
|
||||
sc->hw = hw;
|
||||
sc->dev = &pdev->dev;
|
||||
sc->mem = mem;
|
||||
sc->mem = pcim_iomap_table(pdev)[0];
|
||||
|
||||
/* Will be cleared in ath9k_start() */
|
||||
set_bit(SC_OP_INVALID, &sc->sc_flags);
|
||||
@ -251,7 +241,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
|
||||
ath9k_hw_name(sc->sc_ah, hw_name, sizeof(hw_name));
|
||||
wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
|
||||
hw_name, (unsigned long)mem, pdev->irq);
|
||||
hw_name, (unsigned long)sc->mem, pdev->irq);
|
||||
|
||||
return 0;
|
||||
|
||||
@ -259,14 +249,6 @@ err_init:
|
||||
free_irq(sc->irq, sc);
|
||||
err_irq:
|
||||
ieee80211_free_hw(hw);
|
||||
err_alloc_hw:
|
||||
pci_iounmap(pdev, mem);
|
||||
err_iomap:
|
||||
pci_release_region(pdev, 0);
|
||||
err_region:
|
||||
/* Nothing */
|
||||
err_dma:
|
||||
pci_disable_device(pdev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -274,17 +256,12 @@ static void ath_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
|
||||
struct ath_softc *sc = hw->priv;
|
||||
void __iomem *mem = sc->mem;
|
||||
|
||||
if (!is_ath9k_unloaded)
|
||||
sc->sc_ah->ah_flags |= AH_UNPLUGGED;
|
||||
ath9k_deinit_device(sc);
|
||||
free_irq(sc->irq, sc);
|
||||
ieee80211_free_hw(sc->hw);
|
||||
|
||||
pci_iounmap(pdev, mem);
|
||||
pci_disable_device(pdev);
|
||||
pci_release_region(pdev, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/relay.h>
|
||||
#include "ath9k.h"
|
||||
#include "ar9003_mac.h"
|
||||
|
||||
@ -180,11 +181,6 @@ static void ath_rx_edma_cleanup(struct ath_softc *sc)
|
||||
bf->bf_mpdu = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&sc->rx.rxbuf);
|
||||
|
||||
kfree(sc->rx.rx_bufptr);
|
||||
sc->rx.rx_bufptr = NULL;
|
||||
}
|
||||
|
||||
static void ath_rx_edma_init_queue(struct ath_rx_edma *rx_edma, int size)
|
||||
@ -211,12 +207,11 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs)
|
||||
ah->caps.rx_hp_qdepth);
|
||||
|
||||
size = sizeof(struct ath_buf) * nbufs;
|
||||
bf = kzalloc(size, GFP_KERNEL);
|
||||
bf = devm_kzalloc(sc->dev, size, GFP_KERNEL);
|
||||
if (!bf)
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&sc->rx.rxbuf);
|
||||
sc->rx.rx_bufptr = bf;
|
||||
|
||||
for (i = 0; i < nbufs; i++, bf++) {
|
||||
skb = ath_rxbuf_alloc(common, common->rx_bufsize, GFP_KERNEL);
|
||||
@ -254,8 +249,6 @@ rx_init_fail:
|
||||
|
||||
static void ath_edma_start_recv(struct ath_softc *sc)
|
||||
{
|
||||
spin_lock_bh(&sc->rx.rxbuflock);
|
||||
|
||||
ath9k_hw_rxena(sc->sc_ah);
|
||||
|
||||
ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP,
|
||||
@ -267,8 +260,6 @@ static void ath_edma_start_recv(struct ath_softc *sc)
|
||||
ath_opmode_init(sc);
|
||||
|
||||
ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
|
||||
|
||||
spin_unlock_bh(&sc->rx.rxbuflock);
|
||||
}
|
||||
|
||||
static void ath_edma_stop_recv(struct ath_softc *sc)
|
||||
@ -285,8 +276,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
|
||||
int error = 0;
|
||||
|
||||
spin_lock_init(&sc->sc_pcu_lock);
|
||||
spin_lock_init(&sc->rx.rxbuflock);
|
||||
clear_bit(SC_OP_RXFLUSH, &sc->sc_flags);
|
||||
|
||||
common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
|
||||
sc->sc_ah->caps.rx_status_len;
|
||||
@ -363,9 +352,6 @@ void ath_rx_cleanup(struct ath_softc *sc)
|
||||
bf->bf_mpdu = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (sc->rx.rxdma.dd_desc_len != 0)
|
||||
ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf);
|
||||
}
|
||||
}
|
||||
|
||||
@ -447,7 +433,6 @@ int ath_startrecv(struct ath_softc *sc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_lock_bh(&sc->rx.rxbuflock);
|
||||
if (list_empty(&sc->rx.rxbuf))
|
||||
goto start_recv;
|
||||
|
||||
@ -468,26 +453,31 @@ start_recv:
|
||||
ath_opmode_init(sc);
|
||||
ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
|
||||
|
||||
spin_unlock_bh(&sc->rx.rxbuflock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath_flushrecv(struct ath_softc *sc)
|
||||
{
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
|
||||
ath_rx_tasklet(sc, 1, true);
|
||||
ath_rx_tasklet(sc, 1, false);
|
||||
}
|
||||
|
||||
bool ath_stoprecv(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
bool stopped, reset = false;
|
||||
|
||||
spin_lock_bh(&sc->rx.rxbuflock);
|
||||
ath9k_hw_abortpcurecv(ah);
|
||||
ath9k_hw_setrxfilter(ah, 0);
|
||||
stopped = ath9k_hw_stopdmarecv(ah, &reset);
|
||||
|
||||
ath_flushrecv(sc);
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
|
||||
ath_edma_stop_recv(sc);
|
||||
else
|
||||
sc->rx.rxlink = NULL;
|
||||
spin_unlock_bh(&sc->rx.rxbuflock);
|
||||
|
||||
if (!(ah->ah_flags & AH_UNPLUGGED) &&
|
||||
unlikely(!stopped)) {
|
||||
@ -499,15 +489,6 @@ bool ath_stoprecv(struct ath_softc *sc)
|
||||
return stopped && !reset;
|
||||
}
|
||||
|
||||
void ath_flushrecv(struct ath_softc *sc)
|
||||
{
|
||||
set_bit(SC_OP_RXFLUSH, &sc->sc_flags);
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
|
||||
ath_rx_tasklet(sc, 1, true);
|
||||
ath_rx_tasklet(sc, 1, false);
|
||||
clear_bit(SC_OP_RXFLUSH, &sc->sc_flags);
|
||||
}
|
||||
|
||||
static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
|
||||
{
|
||||
/* Check whether the Beacon frame has DTIM indicating buffered bc/mc */
|
||||
@ -744,6 +725,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_del(&bf->list);
|
||||
if (!bf->bf_mpdu)
|
||||
return bf;
|
||||
|
||||
@ -1034,6 +1016,108 @@ static void ath9k_rx_skb_postprocess(struct ath_common *common,
|
||||
rxs->flag &= ~RX_FLAG_DECRYPTED;
|
||||
}
|
||||
|
||||
static s8 fix_rssi_inv_only(u8 rssi_val)
|
||||
{
|
||||
if (rssi_val == 128)
|
||||
rssi_val = 0;
|
||||
return (s8) rssi_val;
|
||||
}
|
||||
|
||||
|
||||
static void ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
|
||||
struct ath_rx_status *rs, u64 tsf)
|
||||
{
|
||||
#ifdef CONFIG_ATH_DEBUG
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
u8 bins[SPECTRAL_HT20_NUM_BINS];
|
||||
u8 *vdata = (u8 *)hdr;
|
||||
struct fft_sample_ht20 fft_sample;
|
||||
struct ath_radar_info *radar_info;
|
||||
struct ath_ht20_mag_info *mag_info;
|
||||
int len = rs->rs_datalen;
|
||||
int i, dc_pos;
|
||||
|
||||
/* AR9280 and before report via ATH9K_PHYERR_RADAR, AR93xx and newer
|
||||
* via ATH9K_PHYERR_SPECTRAL. Haven't seen ATH9K_PHYERR_FALSE_RADAR_EXT
|
||||
* yet, but this is supposed to be possible as well.
|
||||
*/
|
||||
if (rs->rs_phyerr != ATH9K_PHYERR_RADAR &&
|
||||
rs->rs_phyerr != ATH9K_PHYERR_FALSE_RADAR_EXT &&
|
||||
rs->rs_phyerr != ATH9K_PHYERR_SPECTRAL)
|
||||
return;
|
||||
|
||||
/* Variation in the data length is possible and will be fixed later.
|
||||
* Note that we only support HT20 for now.
|
||||
*
|
||||
* TODO: add HT20_40 support as well.
|
||||
*/
|
||||
if ((len > SPECTRAL_HT20_TOTAL_DATA_LEN + 2) ||
|
||||
(len < SPECTRAL_HT20_TOTAL_DATA_LEN - 1))
|
||||
return;
|
||||
|
||||
/* check if spectral scan bit is set. This does not have to be checked
|
||||
* if received through a SPECTRAL phy error, but shouldn't hurt.
|
||||
*/
|
||||
radar_info = ((struct ath_radar_info *)&vdata[len]) - 1;
|
||||
if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
|
||||
return;
|
||||
|
||||
fft_sample.tlv.type = ATH_FFT_SAMPLE_HT20;
|
||||
fft_sample.tlv.length = sizeof(fft_sample) - sizeof(fft_sample.tlv);
|
||||
|
||||
fft_sample.freq = ah->curchan->chan->center_freq;
|
||||
fft_sample.rssi = fix_rssi_inv_only(rs->rs_rssi_ctl0);
|
||||
fft_sample.noise = ah->noise;
|
||||
|
||||
switch (len - SPECTRAL_HT20_TOTAL_DATA_LEN) {
|
||||
case 0:
|
||||
/* length correct, nothing to do. */
|
||||
memcpy(bins, vdata, SPECTRAL_HT20_NUM_BINS);
|
||||
break;
|
||||
case -1:
|
||||
/* first byte missing, duplicate it. */
|
||||
memcpy(&bins[1], vdata, SPECTRAL_HT20_NUM_BINS - 1);
|
||||
bins[0] = vdata[0];
|
||||
break;
|
||||
case 2:
|
||||
/* MAC added 2 extra bytes at bin 30 and 32, remove them. */
|
||||
memcpy(bins, vdata, 30);
|
||||
bins[30] = vdata[31];
|
||||
memcpy(&bins[31], &vdata[33], SPECTRAL_HT20_NUM_BINS - 31);
|
||||
break;
|
||||
case 1:
|
||||
/* MAC added 2 extra bytes AND first byte is missing. */
|
||||
bins[0] = vdata[0];
|
||||
memcpy(&bins[0], vdata, 30);
|
||||
bins[31] = vdata[31];
|
||||
memcpy(&bins[32], &vdata[33], SPECTRAL_HT20_NUM_BINS - 32);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
/* DC value (value in the middle) is the blind spot of the spectral
|
||||
* sample and invalid, interpolate it.
|
||||
*/
|
||||
dc_pos = SPECTRAL_HT20_NUM_BINS / 2;
|
||||
bins[dc_pos] = (bins[dc_pos + 1] + bins[dc_pos - 1]) / 2;
|
||||
|
||||
/* mag data is at the end of the frame, in front of radar_info */
|
||||
mag_info = ((struct ath_ht20_mag_info *)radar_info) - 1;
|
||||
|
||||
/* Apply exponent and grab further auxiliary information. */
|
||||
for (i = 0; i < SPECTRAL_HT20_NUM_BINS; i++)
|
||||
fft_sample.data[i] = bins[i] << mag_info->max_exp;
|
||||
|
||||
fft_sample.max_magnitude = spectral_max_magnitude(mag_info->all_bins);
|
||||
fft_sample.max_index = spectral_max_index(mag_info->all_bins);
|
||||
fft_sample.bitmap_weight = spectral_bitmap_weight(mag_info->all_bins);
|
||||
fft_sample.tsf = tsf;
|
||||
|
||||
ath_debug_send_fft_sample(sc, &fft_sample.tlv);
|
||||
#endif
|
||||
}
|
||||
|
||||
int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
{
|
||||
struct ath_buf *bf;
|
||||
@ -1059,16 +1143,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
dma_type = DMA_FROM_DEVICE;
|
||||
|
||||
qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP;
|
||||
spin_lock_bh(&sc->rx.rxbuflock);
|
||||
|
||||
tsf = ath9k_hw_gettsf64(ah);
|
||||
tsf_lower = tsf & 0xffffffff;
|
||||
|
||||
do {
|
||||
bool decrypt_error = false;
|
||||
/* If handling rx interrupt and flush is in progress => exit */
|
||||
if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0))
|
||||
break;
|
||||
|
||||
memset(&rs, 0, sizeof(rs));
|
||||
if (edma)
|
||||
@ -1111,15 +1191,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
|
||||
ath_debug_stat_rx(sc, &rs);
|
||||
|
||||
/*
|
||||
* If we're asked to flush receive queue, directly
|
||||
* chain it back at the queue without processing it.
|
||||
*/
|
||||
if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags)) {
|
||||
RX_STAT_INC(rx_drop_rxflush);
|
||||
goto requeue_drop_frag;
|
||||
}
|
||||
|
||||
memset(rxs, 0, sizeof(struct ieee80211_rx_status));
|
||||
|
||||
rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
|
||||
@ -1131,6 +1202,9 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||
unlikely(tsf_lower - rs.rs_tstamp > 0x10000000))
|
||||
rxs->mactime += 0x100000000ULL;
|
||||
|
||||
if ((rs.rs_status & ATH9K_RXERR_PHY))
|
||||
ath_process_fft(sc, hdr, &rs, rxs->mactime);
|
||||
|
||||
retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
|
||||
rxs, &decrypt_error);
|
||||
if (retval)
|
||||
@ -1254,19 +1328,18 @@ requeue_drop_frag:
|
||||
sc->rx.frag = NULL;
|
||||
}
|
||||
requeue:
|
||||
list_add_tail(&bf->list, &sc->rx.rxbuf);
|
||||
if (flush)
|
||||
continue;
|
||||
|
||||
if (edma) {
|
||||
list_add_tail(&bf->list, &sc->rx.rxbuf);
|
||||
ath_rx_edma_buf_link(sc, qtype);
|
||||
} else {
|
||||
list_move_tail(&bf->list, &sc->rx.rxbuf);
|
||||
ath_rx_buf_link(sc, bf);
|
||||
if (!flush)
|
||||
ath9k_hw_rxena(ah);
|
||||
ath9k_hw_rxena(ah);
|
||||
}
|
||||
} while (1);
|
||||
|
||||
spin_unlock_bh(&sc->rx.rxbuflock);
|
||||
|
||||
if (!(ah->imask & ATH9K_INT_RXEOL)) {
|
||||
ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
|
||||
ath9k_hw_set_interrupts(ah);
|
||||
|
@ -789,6 +789,7 @@
|
||||
#define AR_SREV_REVISION_9271_11 1
|
||||
#define AR_SREV_VERSION_9300 0x1c0
|
||||
#define AR_SREV_REVISION_9300_20 2 /* 2.0 and 2.1 */
|
||||
#define AR_SREV_REVISION_9300_22 3
|
||||
#define AR_SREV_VERSION_9330 0x200
|
||||
#define AR_SREV_REVISION_9330_10 0
|
||||
#define AR_SREV_REVISION_9330_11 1
|
||||
@ -869,6 +870,9 @@
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9300))
|
||||
#define AR_SREV_9300_20_OR_LATER(_ah) \
|
||||
((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300)
|
||||
#define AR_SREV_9300_22(_ah) \
|
||||
(AR_SREV_9300(ah) && \
|
||||
((_ah)->hw_version.macRev == AR_SREV_REVISION_9300_22))
|
||||
|
||||
#define AR_SREV_9330(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9330))
|
||||
@ -884,9 +888,6 @@
|
||||
|
||||
#define AR_SREV_9485(_ah) \
|
||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
|
||||
#define AR_SREV_9485_10(_ah) \
|
||||
(AR_SREV_9485(_ah) && \
|
||||
((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_10))
|
||||
#define AR_SREV_9485_11(_ah) \
|
||||
(AR_SREV_9485(_ah) && \
|
||||
((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11))
|
||||
|
@ -378,7 +378,7 @@ static void ath_tx_count_frames(struct ath_softc *sc, struct ath_buf *bf,
|
||||
|
||||
static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct ath_buf *bf, struct list_head *bf_q,
|
||||
struct ath_tx_status *ts, int txok, bool retry)
|
||||
struct ath_tx_status *ts, int txok)
|
||||
{
|
||||
struct ath_node *an = NULL;
|
||||
struct sk_buff *skb;
|
||||
@ -490,7 +490,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
} else if (!isaggr && txok) {
|
||||
/* transmit completion */
|
||||
acked_cnt++;
|
||||
} else if ((tid->state & AGGR_CLEANUP) || !retry) {
|
||||
} else if (tid->state & AGGR_CLEANUP) {
|
||||
/*
|
||||
* cleanup in progress, just fail
|
||||
* the un-acked sub-frames
|
||||
@ -604,6 +604,37 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
|
||||
ath9k_queue_reset(sc, RESET_TYPE_TX_ERROR);
|
||||
}
|
||||
|
||||
static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu);
|
||||
return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
|
||||
}
|
||||
|
||||
static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct ath_tx_status *ts, struct ath_buf *bf,
|
||||
struct list_head *bf_head)
|
||||
{
|
||||
bool txok, flush;
|
||||
|
||||
txok = !(ts->ts_status & ATH9K_TXERR_MASK);
|
||||
flush = !!(ts->ts_status & ATH9K_TX_FLUSH);
|
||||
txq->axq_tx_inprogress = false;
|
||||
|
||||
txq->axq_depth--;
|
||||
if (bf_is_ampdu_not_probing(bf))
|
||||
txq->axq_ampdu_depth--;
|
||||
|
||||
if (!bf_isampdu(bf)) {
|
||||
if (!flush)
|
||||
ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
|
||||
ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok);
|
||||
} else
|
||||
ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok);
|
||||
|
||||
if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && !flush)
|
||||
ath_txq_schedule(sc, txq);
|
||||
}
|
||||
|
||||
static bool ath_lookup_legacy(struct ath_buf *bf)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
@ -1331,23 +1362,6 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid
|
||||
/* Queue Management */
|
||||
/********************/
|
||||
|
||||
static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
|
||||
struct ath_txq *txq)
|
||||
{
|
||||
struct ath_atx_ac *ac, *ac_tmp;
|
||||
struct ath_atx_tid *tid, *tid_tmp;
|
||||
|
||||
list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
|
||||
list_del(&ac->list);
|
||||
ac->sched = false;
|
||||
list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) {
|
||||
list_del(&tid->list);
|
||||
tid->sched = false;
|
||||
ath_tid_drain(sc, txq, tid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
@ -1470,14 +1484,8 @@ int ath_cabq_update(struct ath_softc *sc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool bf_is_ampdu_not_probing(struct ath_buf *bf)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(bf->bf_mpdu);
|
||||
return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE);
|
||||
}
|
||||
|
||||
static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct list_head *list, bool retry_tx)
|
||||
struct list_head *list)
|
||||
{
|
||||
struct ath_buf *bf, *lastbf;
|
||||
struct list_head bf_head;
|
||||
@ -1499,16 +1507,7 @@ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
|
||||
|
||||
lastbf = bf->bf_lastbf;
|
||||
list_cut_position(&bf_head, list, &lastbf->list);
|
||||
|
||||
txq->axq_depth--;
|
||||
if (bf_is_ampdu_not_probing(bf))
|
||||
txq->axq_ampdu_depth--;
|
||||
|
||||
if (bf_isampdu(bf))
|
||||
ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, 0,
|
||||
retry_tx);
|
||||
else
|
||||
ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0);
|
||||
ath_tx_process_buffer(sc, txq, &ts, bf, &bf_head);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1518,7 +1517,7 @@ static void ath_drain_txq_list(struct ath_softc *sc, struct ath_txq *txq,
|
||||
* This assumes output has been stopped and
|
||||
* we do not need to block ath_tx_tasklet.
|
||||
*/
|
||||
void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
|
||||
void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
{
|
||||
ath_txq_lock(sc, txq);
|
||||
|
||||
@ -1526,8 +1525,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
|
||||
int idx = txq->txq_tailidx;
|
||||
|
||||
while (!list_empty(&txq->txq_fifo[idx])) {
|
||||
ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx],
|
||||
retry_tx);
|
||||
ath_drain_txq_list(sc, txq, &txq->txq_fifo[idx]);
|
||||
|
||||
INCR(idx, ATH_TXFIFO_DEPTH);
|
||||
}
|
||||
@ -1536,16 +1534,12 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
|
||||
|
||||
txq->axq_link = NULL;
|
||||
txq->axq_tx_inprogress = false;
|
||||
ath_drain_txq_list(sc, txq, &txq->axq_q, retry_tx);
|
||||
|
||||
/* flush any pending frames if aggregation is enabled */
|
||||
if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) && !retry_tx)
|
||||
ath_txq_drain_pending_buffers(sc, txq);
|
||||
ath_drain_txq_list(sc, txq, &txq->axq_q);
|
||||
|
||||
ath_txq_unlock_complete(sc, txq);
|
||||
}
|
||||
|
||||
bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
|
||||
bool ath_drain_all_txq(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
@ -1581,7 +1575,7 @@ bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
|
||||
*/
|
||||
txq = &sc->tx.txq[i];
|
||||
txq->stopped = false;
|
||||
ath_draintxq(sc, txq, retry_tx);
|
||||
ath_draintxq(sc, txq);
|
||||
}
|
||||
|
||||
return !npend;
|
||||
@ -2175,28 +2169,6 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
|
||||
tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
|
||||
}
|
||||
|
||||
static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq,
|
||||
struct ath_tx_status *ts, struct ath_buf *bf,
|
||||
struct list_head *bf_head)
|
||||
{
|
||||
int txok;
|
||||
|
||||
txq->axq_depth--;
|
||||
txok = !(ts->ts_status & ATH9K_TXERR_MASK);
|
||||
txq->axq_tx_inprogress = false;
|
||||
if (bf_is_ampdu_not_probing(bf))
|
||||
txq->axq_ampdu_depth--;
|
||||
|
||||
if (!bf_isampdu(bf)) {
|
||||
ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok);
|
||||
ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok);
|
||||
} else
|
||||
ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok, true);
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
|
||||
ath_txq_schedule(sc, txq);
|
||||
}
|
||||
|
||||
static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
|
||||
{
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
@ -2361,8 +2333,8 @@ static int ath_txstatus_setup(struct ath_softc *sc, int size)
|
||||
u8 txs_len = sc->sc_ah->caps.txs_len;
|
||||
|
||||
dd->dd_desc_len = size * txs_len;
|
||||
dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len,
|
||||
&dd->dd_desc_paddr, GFP_KERNEL);
|
||||
dd->dd_desc = dmam_alloc_coherent(sc->dev, dd->dd_desc_len,
|
||||
&dd->dd_desc_paddr, GFP_KERNEL);
|
||||
if (!dd->dd_desc)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -2382,14 +2354,6 @@ static int ath_tx_edma_init(struct ath_softc *sc)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ath_tx_edma_cleanup(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_descdma *dd = &sc->txsdma;
|
||||
|
||||
dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc,
|
||||
dd->dd_desc_paddr);
|
||||
}
|
||||
|
||||
int ath_tx_init(struct ath_softc *sc, int nbufs)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
|
||||
@ -2402,7 +2366,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
|
||||
if (error != 0) {
|
||||
ath_err(common,
|
||||
"Failed to allocate tx descriptors: %d\n", error);
|
||||
goto err;
|
||||
return error;
|
||||
}
|
||||
|
||||
error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
|
||||
@ -2410,36 +2374,17 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
|
||||
if (error != 0) {
|
||||
ath_err(common,
|
||||
"Failed to allocate beacon descriptors: %d\n", error);
|
||||
goto err;
|
||||
return error;
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work);
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
|
||||
error = ath_tx_edma_init(sc);
|
||||
if (error)
|
||||
goto err;
|
||||
}
|
||||
|
||||
err:
|
||||
if (error != 0)
|
||||
ath_tx_cleanup(sc);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void ath_tx_cleanup(struct ath_softc *sc)
|
||||
{
|
||||
if (sc->beacon.bdma.dd_desc_len != 0)
|
||||
ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf);
|
||||
|
||||
if (sc->tx.txdma.dd_desc_len != 0)
|
||||
ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
|
||||
|
||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
|
||||
ath_tx_edma_cleanup(sc);
|
||||
}
|
||||
|
||||
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
|
||||
{
|
||||
struct ath_atx_tid *tid;
|
||||
|
@ -85,20 +85,14 @@ enum carl9170_device_state {
|
||||
CARL9170_STARTED,
|
||||
};
|
||||
|
||||
#define CARL9170_NUM_TID 16
|
||||
#define WME_BA_BMP_SIZE 64
|
||||
#define CARL9170_TX_USER_RATE_TRIES 3
|
||||
|
||||
#define WME_AC_BE 2
|
||||
#define WME_AC_BK 3
|
||||
#define WME_AC_VI 1
|
||||
#define WME_AC_VO 0
|
||||
|
||||
#define TID_TO_WME_AC(_tid) \
|
||||
((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
|
||||
(((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
|
||||
(((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
|
||||
WME_AC_VO)
|
||||
((((_tid) == 0) || ((_tid) == 3)) ? IEEE80211_AC_BE : \
|
||||
(((_tid) == 1) || ((_tid) == 2)) ? IEEE80211_AC_BK : \
|
||||
(((_tid) == 4) || ((_tid) == 5)) ? IEEE80211_AC_VI : \
|
||||
IEEE80211_AC_VO)
|
||||
|
||||
#define SEQ_DIFF(_start, _seq) \
|
||||
(((_start) - (_seq)) & 0x0fff)
|
||||
@ -290,6 +284,7 @@ struct ar9170 {
|
||||
unsigned int rx_size;
|
||||
unsigned int tx_seq_table;
|
||||
bool ba_filter;
|
||||
bool disable_offload_fw;
|
||||
} fw;
|
||||
|
||||
/* interface configuration combinations */
|
||||
@ -493,8 +488,8 @@ struct carl9170_sta_info {
|
||||
bool sleeping;
|
||||
atomic_t pending_frames;
|
||||
unsigned int ampdu_max_len;
|
||||
struct carl9170_sta_tid __rcu *agg[CARL9170_NUM_TID];
|
||||
struct carl9170_ba_stats stats[CARL9170_NUM_TID];
|
||||
struct carl9170_sta_tid __rcu *agg[IEEE80211_NUM_TIDS];
|
||||
struct carl9170_ba_stats stats[IEEE80211_NUM_TIDS];
|
||||
};
|
||||
|
||||
struct carl9170_tx_info {
|
||||
|
@ -215,6 +215,24 @@ static int carl9170_fw_tx_sequence(struct ar9170 *ar)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void carl9170_fw_set_if_combinations(struct ar9170 *ar,
|
||||
u16 if_comb_types)
|
||||
{
|
||||
if (ar->fw.vif_num < 2)
|
||||
return;
|
||||
|
||||
ar->if_comb_limits[0].max = ar->fw.vif_num;
|
||||
ar->if_comb_limits[0].types = if_comb_types;
|
||||
|
||||
ar->if_combs[0].num_different_channels = 1;
|
||||
ar->if_combs[0].max_interfaces = ar->fw.vif_num;
|
||||
ar->if_combs[0].limits = ar->if_comb_limits;
|
||||
ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits);
|
||||
|
||||
ar->hw->wiphy->iface_combinations = ar->if_combs;
|
||||
ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs);
|
||||
}
|
||||
|
||||
static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
|
||||
{
|
||||
const struct carl9170fw_otus_desc *otus_desc;
|
||||
@ -264,7 +282,7 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
|
||||
if (!SUPP(CARL9170FW_COMMAND_CAM)) {
|
||||
dev_info(&ar->udev->dev, "crypto offloading is disabled "
|
||||
"by firmware.\n");
|
||||
ar->disable_offload = true;
|
||||
ar->fw.disable_offload_fw = true;
|
||||
}
|
||||
|
||||
if (SUPP(CARL9170FW_PSM) && SUPP(CARL9170FW_FIXED_5GHZ_PSM))
|
||||
@ -345,20 +363,15 @@ static int carl9170_fw(struct ar9170 *ar, const __u8 *data, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
ar->if_comb_limits[0].max = ar->fw.vif_num;
|
||||
ar->if_comb_limits[0].types = if_comb_types;
|
||||
|
||||
ar->if_combs[0].num_different_channels = 1;
|
||||
ar->if_combs[0].max_interfaces = ar->fw.vif_num;
|
||||
ar->if_combs[0].limits = ar->if_comb_limits;
|
||||
ar->if_combs[0].n_limits = ARRAY_SIZE(ar->if_comb_limits);
|
||||
|
||||
ar->hw->wiphy->iface_combinations = ar->if_combs;
|
||||
ar->hw->wiphy->n_iface_combinations = ARRAY_SIZE(ar->if_combs);
|
||||
carl9170_fw_set_if_combinations(ar, if_comb_types);
|
||||
|
||||
ar->hw->wiphy->interface_modes |= if_comb_types;
|
||||
|
||||
ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
|
||||
ar->hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
|
||||
/* As IBSS Encryption is software-based, IBSS RSN is supported. */
|
||||
ar->hw->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
|
||||
WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_SUPPORTS_TDLS;
|
||||
|
||||
#undef SUPPORTED
|
||||
return carl9170_fw_tx_sequence(ar);
|
||||
|
@ -156,6 +156,14 @@ struct carl9170_psm {
|
||||
} __packed;
|
||||
#define CARL9170_PSM_SIZE 4
|
||||
|
||||
/*
|
||||
* Note: If a bit in rx_filter is set, then it
|
||||
* means that the particular frames which matches
|
||||
* the condition are FILTERED/REMOVED/DISCARDED!
|
||||
* (This is can be a bit confusing, especially
|
||||
* because someone people think it's the exact
|
||||
* opposite way, so watch out!)
|
||||
*/
|
||||
struct carl9170_rx_filter_cmd {
|
||||
__le32 rx_filter;
|
||||
} __packed;
|
||||
|
@ -384,7 +384,7 @@
|
||||
|
||||
#define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xd84)
|
||||
#define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xd88)
|
||||
#define AR9170_MAC_BCN_LENGTH_MAX 256
|
||||
#define AR9170_MAC_BCN_LENGTH_MAX (512 - 32)
|
||||
|
||||
#define AR9170_MAC_REG_BCN_STATUS (AR9170_MAC_REG_BASE + 0xd8c)
|
||||
|
||||
|
@ -358,8 +358,13 @@ static int carl9170_op_start(struct ieee80211_hw *hw)
|
||||
ar->ps.last_action = jiffies;
|
||||
ar->ps.last_slept = jiffies;
|
||||
ar->erp_mode = CARL9170_ERP_AUTO;
|
||||
ar->rx_software_decryption = false;
|
||||
ar->disable_offload = false;
|
||||
|
||||
/* Set "disable hw crypto offload" whenever the module parameter
|
||||
* nohwcrypt is true or if the firmware does not support it.
|
||||
*/
|
||||
ar->disable_offload = modparam_nohwcrypt |
|
||||
ar->fw.disable_offload_fw;
|
||||
ar->rx_software_decryption = ar->disable_offload;
|
||||
|
||||
for (i = 0; i < ar->hw->queues; i++) {
|
||||
ar->queue_stop_timeout[i] = jiffies;
|
||||
@ -565,12 +570,28 @@ static int carl9170_init_interface(struct ar9170 *ar,
|
||||
|
||||
memcpy(common->macaddr, vif->addr, ETH_ALEN);
|
||||
|
||||
if (modparam_nohwcrypt ||
|
||||
((vif->type != NL80211_IFTYPE_STATION) &&
|
||||
(vif->type != NL80211_IFTYPE_AP))) {
|
||||
ar->rx_software_decryption = true;
|
||||
ar->disable_offload = true;
|
||||
}
|
||||
/* We have to fall back to software crypto, whenever
|
||||
* the user choose to participates in an IBSS. HW
|
||||
* offload for IBSS RSN is not supported by this driver.
|
||||
*
|
||||
* NOTE: If the previous main interface has already
|
||||
* disabled hw crypto offload, we have to keep this
|
||||
* previous disable_offload setting as it was.
|
||||
* Altough ideally, we should notify mac80211 and tell
|
||||
* it to forget about any HW crypto offload for now.
|
||||
*/
|
||||
ar->disable_offload |= ((vif->type != NL80211_IFTYPE_STATION) &&
|
||||
(vif->type != NL80211_IFTYPE_AP));
|
||||
|
||||
/* While the driver supports HW offload in a single
|
||||
* P2P client configuration, it doesn't support HW
|
||||
* offload in the favourit, concurrent P2P GO+CLIENT
|
||||
* configuration. Hence, HW offload will always be
|
||||
* disabled for P2P.
|
||||
*/
|
||||
ar->disable_offload |= vif->p2p;
|
||||
|
||||
ar->rx_software_decryption = ar->disable_offload;
|
||||
|
||||
err = carl9170_set_operating_mode(ar);
|
||||
return err;
|
||||
@ -580,7 +601,7 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv;
|
||||
struct ieee80211_vif *main_vif;
|
||||
struct ieee80211_vif *main_vif, *old_main = NULL;
|
||||
struct ar9170 *ar = hw->priv;
|
||||
int vif_id = -1, err = 0;
|
||||
|
||||
@ -602,6 +623,15 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
|
||||
goto init;
|
||||
}
|
||||
|
||||
/* Because the AR9170 HW's MAC doesn't provide full support for
|
||||
* multiple, independent interfaces [of different operation modes].
|
||||
* We have to select ONE main interface [main mode of HW], but we
|
||||
* can have multiple slaves [AKA: entry in the ACK-table].
|
||||
*
|
||||
* The first (from HEAD/TOP) interface in the ar->vif_list is
|
||||
* always the main intf. All following intfs in this list
|
||||
* are considered to be slave intfs.
|
||||
*/
|
||||
main_vif = carl9170_get_main_vif(ar);
|
||||
|
||||
if (main_vif) {
|
||||
@ -610,6 +640,18 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
break;
|
||||
|
||||
/* P2P GO [master] use-case
|
||||
* Because the P2P GO station is selected dynamically
|
||||
* by all participating peers of a WIFI Direct network,
|
||||
* the driver has be able to change the main interface
|
||||
* operating mode on the fly.
|
||||
*/
|
||||
if (main_vif->p2p && vif->p2p &&
|
||||
vif->type == NL80211_IFTYPE_AP) {
|
||||
old_main = main_vif;
|
||||
break;
|
||||
}
|
||||
|
||||
err = -EBUSY;
|
||||
rcu_read_unlock();
|
||||
|
||||
@ -648,14 +690,41 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
|
||||
vif_priv->id = vif_id;
|
||||
vif_priv->enable_beacon = false;
|
||||
ar->vifs++;
|
||||
list_add_tail_rcu(&vif_priv->list, &ar->vif_list);
|
||||
if (old_main) {
|
||||
/* We end up in here, if the main interface is being replaced.
|
||||
* Put the new main interface at the HEAD of the list and the
|
||||
* previous inteface will automatically become second in line.
|
||||
*/
|
||||
list_add_rcu(&vif_priv->list, &ar->vif_list);
|
||||
} else {
|
||||
/* Add new inteface. If the list is empty, it will become the
|
||||
* main inteface, otherwise it will be slave.
|
||||
*/
|
||||
list_add_tail_rcu(&vif_priv->list, &ar->vif_list);
|
||||
}
|
||||
rcu_assign_pointer(ar->vif_priv[vif_id].vif, vif);
|
||||
|
||||
init:
|
||||
if (carl9170_get_main_vif(ar) == vif) {
|
||||
main_vif = carl9170_get_main_vif(ar);
|
||||
|
||||
if (main_vif == vif) {
|
||||
rcu_assign_pointer(ar->beacon_iter, vif_priv);
|
||||
rcu_read_unlock();
|
||||
|
||||
if (old_main) {
|
||||
struct carl9170_vif_info *old_main_priv =
|
||||
(void *) old_main->drv_priv;
|
||||
/* downgrade old main intf to slave intf.
|
||||
* NOTE: We are no longer under rcu_read_lock.
|
||||
* But we are still holding ar->mutex, so the
|
||||
* vif data [id, addr] is safe.
|
||||
*/
|
||||
err = carl9170_mod_virtual_mac(ar, old_main_priv->id,
|
||||
old_main->addr);
|
||||
if (err)
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
err = carl9170_init_interface(ar, vif);
|
||||
if (err)
|
||||
goto unlock;
|
||||
@ -1112,9 +1181,7 @@ static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
if (ar->disable_offload || !vif)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
* We have to fall back to software encryption, whenever
|
||||
* the user choose to participates in an IBSS or is connected
|
||||
/* Fall back to software encryption whenever the driver is connected
|
||||
* to more than one network.
|
||||
*
|
||||
* This is very unfortunate, because some machines cannot handle
|
||||
@ -1263,7 +1330,7 @@ static int carl9170_op_sta_add(struct ieee80211_hw *hw,
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < CARL9170_NUM_TID; i++)
|
||||
for (i = 0; i < ARRAY_SIZE(sta_info->agg); i++)
|
||||
RCU_INIT_POINTER(sta_info->agg[i], NULL);
|
||||
|
||||
sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor);
|
||||
@ -1287,7 +1354,7 @@ static int carl9170_op_sta_remove(struct ieee80211_hw *hw,
|
||||
sta_info->ht_sta = false;
|
||||
|
||||
rcu_read_lock();
|
||||
for (i = 0; i < CARL9170_NUM_TID; i++) {
|
||||
for (i = 0; i < ARRAY_SIZE(sta_info->agg); i++) {
|
||||
struct carl9170_sta_tid *tid_info;
|
||||
|
||||
tid_info = rcu_dereference(sta_info->agg[i]);
|
||||
@ -1394,7 +1461,9 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
|
||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
|
||||
case IEEE80211_AMPDU_TX_STOP:
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
rcu_read_lock();
|
||||
tid_info = rcu_dereference(sta_info->agg[tid]);
|
||||
if (tid_info) {
|
||||
@ -1805,10 +1874,6 @@ void *carl9170_alloc(size_t priv_size)
|
||||
for (i = 0; i < ARRAY_SIZE(ar->noise); i++)
|
||||
ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */
|
||||
|
||||
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
|
||||
/* As IBSS Encryption is software-based, IBSS RSN is supported. */
|
||||
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
||||
return ar;
|
||||
|
||||
err_nomem:
|
||||
@ -1916,13 +1981,13 @@ static int carl9170_parse_eeprom(struct ar9170 *ar)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int carl9170_reg_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
static void carl9170_reg_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct ar9170 *ar = hw->priv;
|
||||
|
||||
return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory);
|
||||
ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory);
|
||||
}
|
||||
|
||||
int carl9170_register(struct ar9170 *ar)
|
||||
|
@ -1520,36 +1520,93 @@ void carl9170_tx_scheduler(struct ar9170 *ar)
|
||||
carl9170_tx(ar);
|
||||
}
|
||||
|
||||
/* caller has to take rcu_read_lock */
|
||||
static struct carl9170_vif_info *carl9170_pick_beaconing_vif(struct ar9170 *ar)
|
||||
{
|
||||
struct carl9170_vif_info *cvif;
|
||||
int i = 1;
|
||||
|
||||
/* The AR9170 hardware has no fancy beacon queue or some
|
||||
* other scheduling mechanism. So, the driver has to make
|
||||
* due by setting the two beacon timers (pretbtt and tbtt)
|
||||
* once and then swapping the beacon address in the HW's
|
||||
* register file each time the pretbtt fires.
|
||||
*/
|
||||
|
||||
cvif = rcu_dereference(ar->beacon_iter);
|
||||
if (ar->vifs > 0 && cvif) {
|
||||
do {
|
||||
list_for_each_entry_continue_rcu(cvif, &ar->vif_list,
|
||||
list) {
|
||||
if (cvif->active && cvif->enable_beacon)
|
||||
goto out;
|
||||
}
|
||||
} while (ar->beacon_enabled && i--);
|
||||
}
|
||||
|
||||
out:
|
||||
rcu_assign_pointer(ar->beacon_iter, cvif);
|
||||
return cvif;
|
||||
}
|
||||
|
||||
static bool carl9170_tx_beacon_physet(struct ar9170 *ar, struct sk_buff *skb,
|
||||
u32 *ht1, u32 *plcp)
|
||||
{
|
||||
struct ieee80211_tx_info *txinfo;
|
||||
struct ieee80211_tx_rate *rate;
|
||||
unsigned int power, chains;
|
||||
bool ht_rate;
|
||||
|
||||
txinfo = IEEE80211_SKB_CB(skb);
|
||||
rate = &txinfo->control.rates[0];
|
||||
ht_rate = !!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS);
|
||||
carl9170_tx_rate_tpc_chains(ar, txinfo, rate, plcp, &power, &chains);
|
||||
|
||||
*ht1 = AR9170_MAC_BCN_HT1_TX_ANT0;
|
||||
if (chains == AR9170_TX_PHY_TXCHAIN_2)
|
||||
*ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1;
|
||||
SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, *ht1, 7);
|
||||
SET_VAL(AR9170_MAC_BCN_HT1_TPC, *ht1, power);
|
||||
SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, *ht1, chains);
|
||||
|
||||
if (ht_rate) {
|
||||
*ht1 |= AR9170_MAC_BCN_HT1_HT_EN;
|
||||
if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
|
||||
*plcp |= AR9170_MAC_BCN_HT2_SGI;
|
||||
|
||||
if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
|
||||
*ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED;
|
||||
*plcp |= AR9170_MAC_BCN_HT2_BW40;
|
||||
} else if (rate->flags & IEEE80211_TX_RC_DUP_DATA) {
|
||||
*ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP;
|
||||
*plcp |= AR9170_MAC_BCN_HT2_BW40;
|
||||
}
|
||||
|
||||
SET_VAL(AR9170_MAC_BCN_HT2_LEN, *plcp, skb->len + FCS_LEN);
|
||||
} else {
|
||||
if (*plcp <= AR9170_TX_PHY_RATE_CCK_11M)
|
||||
*plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
|
||||
else
|
||||
*plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010;
|
||||
}
|
||||
|
||||
return ht_rate;
|
||||
}
|
||||
|
||||
int carl9170_update_beacon(struct ar9170 *ar, const bool submit)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
struct carl9170_vif_info *cvif;
|
||||
struct ieee80211_tx_info *txinfo;
|
||||
struct ieee80211_tx_rate *rate;
|
||||
__le32 *data, *old = NULL;
|
||||
unsigned int plcp, power, chains;
|
||||
u32 word, ht1, off, addr, len;
|
||||
u32 word, ht1, plcp, off, addr, len;
|
||||
int i = 0, err = 0;
|
||||
bool ht_rate;
|
||||
|
||||
rcu_read_lock();
|
||||
cvif = rcu_dereference(ar->beacon_iter);
|
||||
retry:
|
||||
if (ar->vifs == 0 || !cvif)
|
||||
cvif = carl9170_pick_beaconing_vif(ar);
|
||||
if (!cvif)
|
||||
goto out_unlock;
|
||||
|
||||
list_for_each_entry_continue_rcu(cvif, &ar->vif_list, list) {
|
||||
if (cvif->active && cvif->enable_beacon)
|
||||
goto found;
|
||||
}
|
||||
|
||||
if (!ar->beacon_enabled || i++)
|
||||
goto out_unlock;
|
||||
|
||||
goto retry;
|
||||
|
||||
found:
|
||||
rcu_assign_pointer(ar->beacon_iter, cvif);
|
||||
|
||||
skb = ieee80211_beacon_get_tim(ar->hw, carl9170_get_vif(cvif),
|
||||
NULL, NULL);
|
||||
|
||||
@ -1558,7 +1615,6 @@ found:
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
txinfo = IEEE80211_SKB_CB(skb);
|
||||
spin_lock_bh(&ar->beacon_lock);
|
||||
data = (__le32 *)skb->data;
|
||||
if (cvif->beacon)
|
||||
@ -1588,43 +1644,14 @@ found:
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
ht1 = AR9170_MAC_BCN_HT1_TX_ANT0;
|
||||
rate = &txinfo->control.rates[0];
|
||||
carl9170_tx_rate_tpc_chains(ar, txinfo, rate, &plcp, &power, &chains);
|
||||
if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS)) {
|
||||
if (plcp <= AR9170_TX_PHY_RATE_CCK_11M)
|
||||
plcp |= ((skb->len + FCS_LEN) << (3 + 16)) + 0x0400;
|
||||
else
|
||||
plcp |= ((skb->len + FCS_LEN) << 16) + 0x0010;
|
||||
} else {
|
||||
ht1 |= AR9170_MAC_BCN_HT1_HT_EN;
|
||||
if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
|
||||
plcp |= AR9170_MAC_BCN_HT2_SGI;
|
||||
|
||||
if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
|
||||
ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_SHARED;
|
||||
plcp |= AR9170_MAC_BCN_HT2_BW40;
|
||||
}
|
||||
if (rate->flags & IEEE80211_TX_RC_DUP_DATA) {
|
||||
ht1 |= AR9170_MAC_BCN_HT1_BWC_40M_DUP;
|
||||
plcp |= AR9170_MAC_BCN_HT2_BW40;
|
||||
}
|
||||
|
||||
SET_VAL(AR9170_MAC_BCN_HT2_LEN, plcp, skb->len + FCS_LEN);
|
||||
}
|
||||
|
||||
SET_VAL(AR9170_MAC_BCN_HT1_PWR_CTRL, ht1, 7);
|
||||
SET_VAL(AR9170_MAC_BCN_HT1_TPC, ht1, power);
|
||||
SET_VAL(AR9170_MAC_BCN_HT1_CHAIN_MASK, ht1, chains);
|
||||
if (chains == AR9170_TX_PHY_TXCHAIN_2)
|
||||
ht1 |= AR9170_MAC_BCN_HT1_TX_ANT1;
|
||||
ht_rate = carl9170_tx_beacon_physet(ar, skb, &ht1, &plcp);
|
||||
|
||||
carl9170_async_regwrite_begin(ar);
|
||||
carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT1, ht1);
|
||||
if (!(txinfo->control.rates[0].flags & IEEE80211_TX_RC_MCS))
|
||||
carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp);
|
||||
else
|
||||
if (ht_rate)
|
||||
carl9170_async_regwrite(AR9170_MAC_REG_BCN_HT2, plcp);
|
||||
else
|
||||
carl9170_async_regwrite(AR9170_MAC_REG_BCN_PLCP, plcp);
|
||||
|
||||
for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) {
|
||||
/*
|
||||
|
@ -1,7 +1,7 @@
|
||||
#ifndef __CARL9170_SHARED_VERSION_H
|
||||
#define __CARL9170_SHARED_VERSION_H
|
||||
#define CARL9170FW_VERSION_YEAR 12
|
||||
#define CARL9170FW_VERSION_MONTH 7
|
||||
#define CARL9170FW_VERSION_DAY 7
|
||||
#define CARL9170FW_VERSION_GIT "1.9.6"
|
||||
#define CARL9170FW_VERSION_MONTH 12
|
||||
#define CARL9170FW_VERSION_DAY 15
|
||||
#define CARL9170FW_VERSION_GIT "1.9.7"
|
||||
#endif /* __CARL9170_SHARED_VERSION_H */
|
||||
|
@ -195,8 +195,6 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
|
||||
const struct ieee80211_reg_rule *reg_rule;
|
||||
struct ieee80211_channel *ch;
|
||||
unsigned int i;
|
||||
u32 bandwidth = 0;
|
||||
int r;
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
|
||||
@ -214,11 +212,8 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
|
||||
continue;
|
||||
|
||||
if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
|
||||
r = freq_reg_info(wiphy,
|
||||
ch->center_freq,
|
||||
bandwidth,
|
||||
®_rule);
|
||||
if (r)
|
||||
reg_rule = freq_reg_info(wiphy, ch->center_freq);
|
||||
if (IS_ERR(reg_rule))
|
||||
continue;
|
||||
/*
|
||||
* If 11d had a rule for this channel ensure
|
||||
@ -254,8 +249,6 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_channel *ch;
|
||||
const struct ieee80211_reg_rule *reg_rule;
|
||||
u32 bandwidth = 0;
|
||||
int r;
|
||||
|
||||
sband = wiphy->bands[IEEE80211_BAND_2GHZ];
|
||||
if (!sband)
|
||||
@ -283,16 +276,16 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
|
||||
*/
|
||||
|
||||
ch = &sband->channels[11]; /* CH 12 */
|
||||
r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule);
|
||||
if (!r) {
|
||||
reg_rule = freq_reg_info(wiphy, ch->center_freq);
|
||||
if (!IS_ERR(reg_rule)) {
|
||||
if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
|
||||
if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
||||
ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
|
||||
}
|
||||
|
||||
ch = &sband->channels[12]; /* CH 13 */
|
||||
r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule);
|
||||
if (!r) {
|
||||
reg_rule = freq_reg_info(wiphy, ch->center_freq);
|
||||
if (!IS_ERR(reg_rule)) {
|
||||
if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
|
||||
if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
|
||||
ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
|
||||
@ -363,9 +356,9 @@ static u16 ath_regd_find_country_by_name(char *alpha2)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ath_reg_notifier_apply(struct wiphy *wiphy,
|
||||
struct regulatory_request *request,
|
||||
struct ath_regulatory *reg)
|
||||
void ath_reg_notifier_apply(struct wiphy *wiphy,
|
||||
struct regulatory_request *request,
|
||||
struct ath_regulatory *reg)
|
||||
{
|
||||
struct ath_common *common = container_of(reg, struct ath_common,
|
||||
regulatory);
|
||||
@ -380,7 +373,7 @@ int ath_reg_notifier_apply(struct wiphy *wiphy,
|
||||
* any pending requests in the queue.
|
||||
*/
|
||||
if (!request)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
switch (request->initiator) {
|
||||
case NL80211_REGDOM_SET_BY_CORE:
|
||||
@ -416,8 +409,6 @@ int ath_reg_notifier_apply(struct wiphy *wiphy,
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath_reg_notifier_apply);
|
||||
|
||||
@ -507,8 +498,8 @@ ath_get_regpair(int regdmn)
|
||||
static int
|
||||
ath_regd_init_wiphy(struct ath_regulatory *reg,
|
||||
struct wiphy *wiphy,
|
||||
int (*reg_notifier)(struct wiphy *wiphy,
|
||||
struct regulatory_request *request))
|
||||
void (*reg_notifier)(struct wiphy *wiphy,
|
||||
struct regulatory_request *request))
|
||||
{
|
||||
const struct ieee80211_regdomain *regd;
|
||||
|
||||
@ -628,8 +619,8 @@ static int __ath_regd_init(struct ath_regulatory *reg)
|
||||
int
|
||||
ath_regd_init(struct ath_regulatory *reg,
|
||||
struct wiphy *wiphy,
|
||||
int (*reg_notifier)(struct wiphy *wiphy,
|
||||
struct regulatory_request *request))
|
||||
void (*reg_notifier)(struct wiphy *wiphy,
|
||||
struct regulatory_request *request))
|
||||
{
|
||||
struct ath_common *common = container_of(reg, struct ath_common,
|
||||
regulatory);
|
||||
|
@ -252,12 +252,12 @@ enum CountryCode {
|
||||
bool ath_is_world_regd(struct ath_regulatory *reg);
|
||||
bool ath_is_49ghz_allowed(u16 redomain);
|
||||
int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy,
|
||||
int (*reg_notifier)(struct wiphy *wiphy,
|
||||
struct regulatory_request *request));
|
||||
void (*reg_notifier)(struct wiphy *wiphy,
|
||||
struct regulatory_request *request));
|
||||
u32 ath_regd_get_band_ctl(struct ath_regulatory *reg,
|
||||
enum ieee80211_band band);
|
||||
int ath_reg_notifier_apply(struct wiphy *wiphy,
|
||||
struct regulatory_request *request,
|
||||
struct ath_regulatory *reg);
|
||||
void ath_reg_notifier_apply(struct wiphy *wiphy,
|
||||
struct regulatory_request *request,
|
||||
struct ath_regulatory *reg);
|
||||
|
||||
#endif
|
||||
|
@ -3226,8 +3226,6 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
|
||||
{
|
||||
struct nphy_gain_ctl_workaround_entry *e;
|
||||
u8 phy_idx;
|
||||
u8 tr_iso = ghz5 ? dev->dev->bus_sprom->fem.ghz5.tr_iso :
|
||||
dev->dev->bus_sprom->fem.ghz2.tr_iso;
|
||||
|
||||
if (!ghz5 && dev->phy.rev >= 6 && dev->phy.radio_rev == 11)
|
||||
return &nphy_gain_ctl_wa_phy6_radio11_ghz2;
|
||||
@ -3249,6 +3247,10 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
|
||||
!b43_channel_type_is_40mhz(dev->phy.channel_type))
|
||||
e->cliplo_gain = 0x2d;
|
||||
} else if (!ghz5 && dev->phy.rev >= 5) {
|
||||
static const int gain_data[] = {0x0062, 0x0064, 0x006a, 0x106a,
|
||||
0x106c, 0x1074, 0x107c, 0x207c};
|
||||
u8 tr_iso = dev->dev->bus_sprom->fem.ghz2.tr_iso;
|
||||
|
||||
if (ext_lna) {
|
||||
e->rfseq_init[0] &= ~0x4000;
|
||||
e->rfseq_init[1] &= ~0x4000;
|
||||
@ -3256,26 +3258,10 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
|
||||
e->rfseq_init[3] &= ~0x4000;
|
||||
e->init_gain &= ~0x4000;
|
||||
}
|
||||
switch (tr_iso) {
|
||||
case 0:
|
||||
e->cliplo_gain = 0x0062;
|
||||
case 1:
|
||||
e->cliplo_gain = 0x0064;
|
||||
case 2:
|
||||
e->cliplo_gain = 0x006a;
|
||||
case 3:
|
||||
e->cliplo_gain = 0x106a;
|
||||
case 4:
|
||||
e->cliplo_gain = 0x106c;
|
||||
case 5:
|
||||
e->cliplo_gain = 0x1074;
|
||||
case 6:
|
||||
e->cliplo_gain = 0x107c;
|
||||
case 7:
|
||||
e->cliplo_gain = 0x207c;
|
||||
default:
|
||||
e->cliplo_gain = 0x106a;
|
||||
}
|
||||
if (tr_iso > 7)
|
||||
tr_iso = 3;
|
||||
e->cliplo_gain = gain_data[tr_iso];
|
||||
|
||||
} else if (ghz5 && dev->phy.rev == 4 && ext_lna) {
|
||||
e->rfseq_init[0] &= ~0x4000;
|
||||
e->rfseq_init[1] &= ~0x4000;
|
||||
|
@ -15,8 +15,6 @@
|
||||
*/
|
||||
/* ****************** SDIO CARD Interface Functions **************************/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/export.h>
|
||||
|
@ -14,8 +14,6 @@
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/mmc/sdio.h>
|
||||
|
@ -39,6 +39,7 @@
|
||||
#define BRCMF_C_GET_BSSID 23
|
||||
#define BRCMF_C_GET_SSID 25
|
||||
#define BRCMF_C_SET_SSID 26
|
||||
#define BRCMF_C_TERMINATED 28
|
||||
#define BRCMF_C_GET_CHANNEL 29
|
||||
#define BRCMF_C_SET_CHANNEL 30
|
||||
#define BRCMF_C_GET_SRL 31
|
||||
@ -480,36 +481,14 @@ struct brcmf_pub {
|
||||
unsigned long drv_version; /* Version of dongle-resident driver */
|
||||
u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */
|
||||
|
||||
/* Additional stats for the bus level */
|
||||
|
||||
/* Multicast data packets sent to dongle */
|
||||
unsigned long tx_multicast;
|
||||
/* Packets flushed due to unscheduled sendup thread */
|
||||
unsigned long rx_flushed;
|
||||
/* Number of times dpc scheduled by watchdog timer */
|
||||
unsigned long wd_dpc_sched;
|
||||
|
||||
/* Number of flow control pkts recvd */
|
||||
unsigned long fc_packets;
|
||||
|
||||
/* Last error return */
|
||||
int bcmerror;
|
||||
|
||||
/* Last error from dongle */
|
||||
int dongle_error;
|
||||
|
||||
/* Suspend disable flag flag */
|
||||
int suspend_disable_flag; /* "1" to disable all extra powersaving
|
||||
during suspend */
|
||||
int in_suspend; /* flag set to 1 when early suspend called */
|
||||
int dtim_skip; /* dtim skip , default 0 means wake each dtim */
|
||||
|
||||
struct brcmf_if *iflist[BRCMF_MAX_IFS];
|
||||
|
||||
struct mutex proto_block;
|
||||
unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
|
||||
|
||||
u8 macvalue[ETH_ALEN];
|
||||
atomic_t pend_8021x_cnt;
|
||||
wait_queue_head_t pend_8021x_wait;
|
||||
|
||||
@ -519,11 +498,6 @@ struct brcmf_pub {
|
||||
#endif
|
||||
};
|
||||
|
||||
struct bcmevent_name {
|
||||
uint event;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct brcmf_if_event {
|
||||
u8 ifidx;
|
||||
u8 action;
|
||||
@ -557,13 +531,6 @@ struct brcmf_if {
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
};
|
||||
|
||||
static inline s32 brcmf_ndev_bssidx(struct net_device *ndev)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
return ifp->bssidx;
|
||||
}
|
||||
|
||||
extern const struct bcmevent_name bcmevent_names[];
|
||||
|
||||
extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
|
||||
|
||||
@ -576,6 +543,10 @@ extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx,
|
||||
extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
|
||||
void *buf, uint len);
|
||||
|
||||
/* Remove any protocol-specific data header. */
|
||||
extern int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
|
||||
struct sk_buff *rxp);
|
||||
|
||||
extern int brcmf_net_attach(struct brcmf_if *ifp);
|
||||
extern struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, int ifidx,
|
||||
s32 bssidx, char *name, u8 *mac_addr);
|
||||
|
@ -130,31 +130,18 @@ int brcmf_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint len)
|
||||
* interface functions from common layer
|
||||
*/
|
||||
|
||||
/* Remove any protocol-specific data header. */
|
||||
extern int brcmf_proto_hdrpull(struct device *dev, int *ifidx,
|
||||
struct sk_buff *rxp);
|
||||
|
||||
extern bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
|
||||
struct sk_buff *pkt, int prec);
|
||||
|
||||
/* Receive frame for delivery to OS. Callee disposes of rxp. */
|
||||
extern void brcmf_rx_frame(struct device *dev, u8 ifidx,
|
||||
struct sk_buff_head *rxlist);
|
||||
static inline void brcmf_rx_packet(struct device *dev, int ifidx,
|
||||
struct sk_buff *pkt)
|
||||
{
|
||||
struct sk_buff_head q;
|
||||
|
||||
skb_queue_head_init(&q);
|
||||
skb_queue_tail(&q, pkt);
|
||||
brcmf_rx_frame(dev, ifidx, &q);
|
||||
}
|
||||
extern void brcmf_rx_frames(struct device *dev, struct sk_buff_head *rxlist);
|
||||
|
||||
/* Indication from bus module regarding presence/insertion of dongle. */
|
||||
extern int brcmf_attach(uint bus_hdrlen, struct device *dev);
|
||||
/* Indication from bus module regarding removal/absence of dongle */
|
||||
extern void brcmf_detach(struct device *dev);
|
||||
|
||||
/* Indication from bus module that dongle should be reset */
|
||||
extern void brcmf_dev_reset(struct device *dev);
|
||||
/* Indication from bus module to change flow-control state */
|
||||
extern void brcmf_txflowblock(struct device *dev, bool state);
|
||||
|
||||
|
@ -19,8 +19,6 @@
|
||||
* For certain dcmd codes, the dongle interprets string data from the host.
|
||||
******************************************************************************/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
@ -94,8 +92,6 @@ struct brcmf_proto_bdc_header {
|
||||
|
||||
struct brcmf_proto {
|
||||
u16 reqid;
|
||||
u8 pending;
|
||||
u32 lastcmd;
|
||||
u8 bus_header[BUS_HEADER_LEN];
|
||||
struct brcmf_proto_cdc_dcmd msg;
|
||||
unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN];
|
||||
@ -107,7 +103,7 @@ static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr)
|
||||
int len = le32_to_cpu(prot->msg.len) +
|
||||
sizeof(struct brcmf_proto_cdc_dcmd);
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(CDC, "Enter\n");
|
||||
|
||||
/* NOTE : cdc->msg.len holds the desired length of the buffer to be
|
||||
* returned. Only up to CDC_MAX_MSG_SIZE of this buffer area
|
||||
@ -125,7 +121,7 @@ static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
|
||||
int ret;
|
||||
struct brcmf_proto *prot = drvr->prot;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(CDC, "Enter\n");
|
||||
len += sizeof(struct brcmf_proto_cdc_dcmd);
|
||||
do {
|
||||
ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&prot->msg,
|
||||
@ -147,20 +143,7 @@ brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
|
||||
int ret = 0, retries = 0;
|
||||
u32 id, flags;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len);
|
||||
|
||||
/* Respond "bcmerror" and "bcmerrorstr" with local cache */
|
||||
if (cmd == BRCMF_C_GET_VAR && buf) {
|
||||
if (!strcmp((char *)buf, "bcmerrorstr")) {
|
||||
strncpy((char *)buf, "bcm_error",
|
||||
BCME_STRLEN);
|
||||
goto done;
|
||||
} else if (!strcmp((char *)buf, "bcmerror")) {
|
||||
*(int *)buf = drvr->dongle_error;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len);
|
||||
|
||||
memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd));
|
||||
|
||||
@ -210,11 +193,8 @@ retry:
|
||||
}
|
||||
|
||||
/* Check the ERROR flag */
|
||||
if (flags & CDC_DCMD_ERROR) {
|
||||
if (flags & CDC_DCMD_ERROR)
|
||||
ret = le32_to_cpu(msg->status);
|
||||
/* Cache error from dongle */
|
||||
drvr->dongle_error = ret;
|
||||
}
|
||||
|
||||
done:
|
||||
return ret;
|
||||
@ -228,8 +208,7 @@ int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
|
||||
int ret = 0;
|
||||
u32 flags, id;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len);
|
||||
brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len);
|
||||
|
||||
memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd));
|
||||
|
||||
@ -262,11 +241,8 @@ int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
|
||||
}
|
||||
|
||||
/* Check the ERROR flag */
|
||||
if (flags & CDC_DCMD_ERROR) {
|
||||
if (flags & CDC_DCMD_ERROR)
|
||||
ret = le32_to_cpu(msg->status);
|
||||
/* Cache error from dongle */
|
||||
drvr->dongle_error = ret;
|
||||
}
|
||||
|
||||
done:
|
||||
return ret;
|
||||
@ -287,7 +263,7 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
|
||||
{
|
||||
struct brcmf_proto_bdc_header *h;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(CDC, "Enter\n");
|
||||
|
||||
/* Push BDC header used to convey priority for buses that don't */
|
||||
|
||||
@ -305,14 +281,12 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,
|
||||
BDC_SET_IF_IDX(h, ifidx);
|
||||
}
|
||||
|
||||
int brcmf_proto_hdrpull(struct device *dev, int *ifidx,
|
||||
int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,
|
||||
struct sk_buff *pktbuf)
|
||||
{
|
||||
struct brcmf_proto_bdc_header *h;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
brcmf_dbg(CDC, "Enter\n");
|
||||
|
||||
/* Pop BDC header used to convey priority for buses that don't */
|
||||
|
||||
@ -338,7 +312,7 @@ int brcmf_proto_hdrpull(struct device *dev, int *ifidx,
|
||||
}
|
||||
|
||||
if (h->flags & BDC_FLAG_SUM_GOOD) {
|
||||
brcmf_dbg(INFO, "%s: BDC packet received with good rx-csum, flags 0x%x\n",
|
||||
brcmf_dbg(CDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
|
||||
brcmf_ifname(drvr, *ifidx), h->flags);
|
||||
pkt_set_sum_good(pktbuf, true);
|
||||
}
|
||||
@ -348,6 +322,8 @@ int brcmf_proto_hdrpull(struct device *dev, int *ifidx,
|
||||
skb_pull(pktbuf, BDC_HEADER_LEN);
|
||||
skb_pull(pktbuf, h->data_offset << 2);
|
||||
|
||||
if (pktbuf->len == 0)
|
||||
return -ENODATA;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -14,8 +14,6 @@
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
@ -18,21 +18,26 @@
|
||||
#define _BRCMF_DBG_H_
|
||||
|
||||
/* message levels */
|
||||
#define BRCMF_TRACE_VAL 0x0002
|
||||
#define BRCMF_INFO_VAL 0x0004
|
||||
#define BRCMF_DATA_VAL 0x0008
|
||||
#define BRCMF_CTL_VAL 0x0010
|
||||
#define BRCMF_TIMER_VAL 0x0020
|
||||
#define BRCMF_HDRS_VAL 0x0040
|
||||
#define BRCMF_BYTES_VAL 0x0080
|
||||
#define BRCMF_INTR_VAL 0x0100
|
||||
#define BRCMF_GLOM_VAL 0x0200
|
||||
#define BRCMF_EVENT_VAL 0x0400
|
||||
#define BRCMF_BTA_VAL 0x0800
|
||||
#define BRCMF_FIL_VAL 0x1000
|
||||
#define BRCMF_USB_VAL 0x2000
|
||||
#define BRCMF_SCAN_VAL 0x4000
|
||||
#define BRCMF_CONN_VAL 0x8000
|
||||
#define BRCMF_TRACE_VAL 0x00000002
|
||||
#define BRCMF_INFO_VAL 0x00000004
|
||||
#define BRCMF_DATA_VAL 0x00000008
|
||||
#define BRCMF_CTL_VAL 0x00000010
|
||||
#define BRCMF_TIMER_VAL 0x00000020
|
||||
#define BRCMF_HDRS_VAL 0x00000040
|
||||
#define BRCMF_BYTES_VAL 0x00000080
|
||||
#define BRCMF_INTR_VAL 0x00000100
|
||||
#define BRCMF_GLOM_VAL 0x00000200
|
||||
#define BRCMF_EVENT_VAL 0x00000400
|
||||
#define BRCMF_BTA_VAL 0x00000800
|
||||
#define BRCMF_FIL_VAL 0x00001000
|
||||
#define BRCMF_USB_VAL 0x00002000
|
||||
#define BRCMF_SCAN_VAL 0x00004000
|
||||
#define BRCMF_CONN_VAL 0x00008000
|
||||
#define BRCMF_CDC_VAL 0x00010000
|
||||
|
||||
/* set default print format */
|
||||
#undef pr_fmt
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
/* Macro for error messages. net_ratelimit() is used when driver
|
||||
* debugging is not selected. When debugging the driver error
|
||||
|
@ -14,8 +14,6 @@
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/module.h>
|
||||
@ -162,28 +160,31 @@ static void brcmf_netdev_set_multicast_list(struct net_device *ndev)
|
||||
schedule_work(&ifp->multicast_work);
|
||||
}
|
||||
|
||||
static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
|
||||
struct net_device *ndev)
|
||||
{
|
||||
int ret;
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
struct ethhdr *eh;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
/* Reject if down */
|
||||
if (!drvr->bus_if->drvr_up ||
|
||||
(drvr->bus_if->state != BRCMF_BUS_DATA)) {
|
||||
brcmf_err("xmit rejected drvup=%d state=%d\n",
|
||||
drvr->bus_if->drvr_up,
|
||||
drvr->bus_if->state);
|
||||
/* Can the device send data? */
|
||||
if (drvr->bus_if->state != BRCMF_BUS_DATA) {
|
||||
brcmf_err("xmit rejected state=%d\n", drvr->bus_if->state);
|
||||
netif_stop_queue(ndev);
|
||||
return -ENODEV;
|
||||
dev_kfree_skb(skb);
|
||||
ret = -ENODEV;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!drvr->iflist[ifp->idx]) {
|
||||
brcmf_err("bad ifidx %d\n", ifp->idx);
|
||||
netif_stop_queue(ndev);
|
||||
return -ENODEV;
|
||||
dev_kfree_skb(skb);
|
||||
ret = -ENODEV;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Make sure there's enough room for any header */
|
||||
@ -204,17 +205,20 @@ static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
}
|
||||
}
|
||||
|
||||
/* Update multicast statistic */
|
||||
if (skb->len >= ETH_ALEN) {
|
||||
u8 *pktdata = (u8 *)(skb->data);
|
||||
struct ethhdr *eh = (struct ethhdr *)pktdata;
|
||||
|
||||
if (is_multicast_ether_addr(eh->h_dest))
|
||||
drvr->tx_multicast++;
|
||||
if (ntohs(eh->h_proto) == ETH_P_PAE)
|
||||
atomic_inc(&drvr->pend_8021x_cnt);
|
||||
/* validate length for ether packet */
|
||||
if (skb->len < sizeof(*eh)) {
|
||||
ret = -EINVAL;
|
||||
dev_kfree_skb(skb);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* handle ethernet header */
|
||||
eh = (struct ethhdr *)(skb->data);
|
||||
if (is_multicast_ether_addr(eh->h_dest))
|
||||
drvr->tx_multicast++;
|
||||
if (ntohs(eh->h_proto) == ETH_P_PAE)
|
||||
atomic_inc(&drvr->pend_8021x_cnt);
|
||||
|
||||
/* If the protocol uses a data header, apply it */
|
||||
brcmf_proto_hdrpush(drvr, ifp->idx, skb);
|
||||
|
||||
@ -228,7 +232,7 @@ done:
|
||||
drvr->bus_if->dstats.tx_packets++;
|
||||
|
||||
/* Return ok: we always eat the packet */
|
||||
return 0;
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
void brcmf_txflowblock(struct device *dev, bool state)
|
||||
@ -250,8 +254,7 @@ void brcmf_txflowblock(struct device *dev, bool state)
|
||||
}
|
||||
}
|
||||
|
||||
void brcmf_rx_frame(struct device *dev, u8 ifidx,
|
||||
struct sk_buff_head *skb_list)
|
||||
void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
|
||||
{
|
||||
unsigned char *eth;
|
||||
uint len;
|
||||
@ -259,12 +262,24 @@ void brcmf_rx_frame(struct device *dev, u8 ifidx,
|
||||
struct brcmf_if *ifp;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
u8 ifidx;
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
|
||||
skb_queue_walk_safe(skb_list, skb, pnext) {
|
||||
skb_unlink(skb, skb_list);
|
||||
|
||||
/* process and remove protocol-specific header
|
||||
*/
|
||||
ret = brcmf_proto_hdrpull(drvr, &ifidx, skb);
|
||||
if (ret < 0) {
|
||||
if (ret != -ENODATA)
|
||||
bus_if->dstats.rx_errors++;
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get the protocol, maintain skb around eth_type_trans()
|
||||
* The main reason for this hack is for the limitation of
|
||||
* Linux 2.4 where 'eth_type_trans' uses the
|
||||
@ -328,13 +343,13 @@ void brcmf_rx_frame(struct device *dev, u8 ifidx,
|
||||
|
||||
void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
|
||||
{
|
||||
uint ifidx;
|
||||
u8 ifidx;
|
||||
struct ethhdr *eh;
|
||||
u16 type;
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
|
||||
brcmf_proto_hdrpull(dev, &ifidx, txp);
|
||||
brcmf_proto_hdrpull(drvr, &ifidx, txp);
|
||||
|
||||
eh = (struct ethhdr *)(txp->data);
|
||||
type = ntohs(eh->h_proto);
|
||||
@ -452,7 +467,7 @@ static int brcmf_ethtool(struct brcmf_if *ifp, void __user *uaddr)
|
||||
sprintf(info.version, "%lu", drvr->drv_version);
|
||||
if (copy_to_user(uaddr, &info, sizeof(info)))
|
||||
return -EFAULT;
|
||||
brcmf_dbg(CTL, "given %*s, returning %s\n",
|
||||
brcmf_dbg(TRACE, "given %*s, returning %s\n",
|
||||
(int)sizeof(drvname), drvname, info.driver);
|
||||
break;
|
||||
|
||||
@ -572,14 +587,9 @@ static int brcmf_netdev_open(struct net_device *ndev)
|
||||
/* Get current TOE mode from dongle */
|
||||
if (brcmf_fil_iovar_int_get(ifp, "toe_ol", &toe_ol) >= 0
|
||||
&& (toe_ol & TOE_TX_CSUM_OL) != 0)
|
||||
drvr->iflist[ifp->idx]->ndev->features |=
|
||||
NETIF_F_IP_CSUM;
|
||||
ndev->features |= NETIF_F_IP_CSUM;
|
||||
else
|
||||
drvr->iflist[ifp->idx]->ndev->features &=
|
||||
~NETIF_F_IP_CSUM;
|
||||
|
||||
/* make sure RF is ready for work */
|
||||
brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
|
||||
ndev->features &= ~NETIF_F_IP_CSUM;
|
||||
|
||||
/* Allow transmit calls */
|
||||
netif_start_queue(ndev);
|
||||
@ -847,6 +857,17 @@ static void brcmf_bus_detach(struct brcmf_pub *drvr)
|
||||
}
|
||||
}
|
||||
|
||||
void brcmf_dev_reset(struct device *dev)
|
||||
{
|
||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||
struct brcmf_pub *drvr = bus_if->drvr;
|
||||
|
||||
if (drvr == NULL)
|
||||
return;
|
||||
|
||||
brcmf_fil_cmd_int_set(drvr->iflist[0], BRCMF_C_TERMINATED, 1);
|
||||
}
|
||||
|
||||
void brcmf_detach(struct device *dev)
|
||||
{
|
||||
int i;
|
||||
@ -868,9 +889,8 @@ void brcmf_detach(struct device *dev)
|
||||
|
||||
brcmf_bus_detach(drvr);
|
||||
|
||||
if (drvr->prot) {
|
||||
if (drvr->prot)
|
||||
brcmf_proto_detach(drvr);
|
||||
}
|
||||
|
||||
brcmf_debugfs_detach(drvr);
|
||||
bus_if->drvr = NULL;
|
||||
|
@ -14,8 +14,6 @@
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/kthread.h>
|
||||
@ -1169,7 +1167,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
||||
int errcode;
|
||||
u8 doff, sfdoff;
|
||||
|
||||
int ifidx = 0;
|
||||
bool usechain = bus->use_rxchain;
|
||||
|
||||
struct brcmf_sdio_read rd_new;
|
||||
@ -1388,13 +1385,6 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
||||
skb_unlink(pfirst, &bus->glom);
|
||||
brcmu_pkt_buf_free_skb(pfirst);
|
||||
continue;
|
||||
} else if (brcmf_proto_hdrpull(bus->sdiodev->dev,
|
||||
&ifidx, pfirst) != 0) {
|
||||
brcmf_err("rx protocol error\n");
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
skb_unlink(pfirst, &bus->glom);
|
||||
brcmu_pkt_buf_free_skb(pfirst);
|
||||
continue;
|
||||
}
|
||||
|
||||
brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
|
||||
@ -1407,7 +1397,7 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
||||
}
|
||||
/* sent any remaining packets up */
|
||||
if (bus->glom.qlen)
|
||||
brcmf_rx_frame(bus->sdiodev->dev, ifidx, &bus->glom);
|
||||
brcmf_rx_frames(bus->sdiodev->dev, &bus->glom);
|
||||
|
||||
bus->sdcnt.rxglomframes++;
|
||||
bus->sdcnt.rxglompkts += bus->glom.qlen;
|
||||
@ -1558,10 +1548,10 @@ static void brcmf_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen)
|
||||
static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
||||
{
|
||||
struct sk_buff *pkt; /* Packet for event or data frames */
|
||||
struct sk_buff_head pktlist; /* needed for bus interface */
|
||||
u16 pad; /* Number of pad bytes to read */
|
||||
uint rxleft = 0; /* Remaining number of frames allowed */
|
||||
int sdret; /* Return code from calls */
|
||||
int ifidx = 0;
|
||||
uint rxcount = 0; /* Total frames read */
|
||||
struct brcmf_sdio_read *rd = &bus->cur_read, rd_new;
|
||||
u8 head_read = 0;
|
||||
@ -1760,15 +1750,11 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
||||
if (pkt->len == 0) {
|
||||
brcmu_pkt_buf_free_skb(pkt);
|
||||
continue;
|
||||
} else if (brcmf_proto_hdrpull(bus->sdiodev->dev, &ifidx,
|
||||
pkt) != 0) {
|
||||
brcmf_err("rx protocol error\n");
|
||||
brcmu_pkt_buf_free_skb(pkt);
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
continue;
|
||||
}
|
||||
|
||||
brcmf_rx_packet(bus->sdiodev->dev, ifidx, pkt);
|
||||
skb_queue_head_init(&pktlist);
|
||||
skb_queue_tail(&pktlist, pkt);
|
||||
brcmf_rx_frames(bus->sdiodev->dev, &pktlist);
|
||||
}
|
||||
|
||||
rxcount = maxframes - rxleft;
|
||||
|
@ -15,8 +15,6 @@
|
||||
*/
|
||||
/* ***** SDIO interface chip backplane handle functions ***** */
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/mmc/card.h>
|
||||
|
@ -443,14 +443,15 @@ static void brcmf_usb_rx_complete(struct urb *urb)
|
||||
struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context;
|
||||
struct brcmf_usbdev_info *devinfo = req->devinfo;
|
||||
struct sk_buff *skb;
|
||||
int ifidx = 0;
|
||||
struct sk_buff_head skbq;
|
||||
|
||||
brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status);
|
||||
brcmf_usb_del_fromq(devinfo, req);
|
||||
skb = req->skb;
|
||||
req->skb = NULL;
|
||||
|
||||
if (urb->status == 0) {
|
||||
/* zero lenght packets indicate usb "failure". Do not refill */
|
||||
if (urb->status == 0 && urb->actual_length) {
|
||||
devinfo->bus_pub.bus->dstats.rx_packets++;
|
||||
} else {
|
||||
devinfo->bus_pub.bus->dstats.rx_errors++;
|
||||
@ -460,13 +461,10 @@ static void brcmf_usb_rx_complete(struct urb *urb)
|
||||
}
|
||||
|
||||
if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
|
||||
skb_queue_head_init(&skbq);
|
||||
skb_queue_tail(&skbq, skb);
|
||||
skb_put(skb, urb->actual_length);
|
||||
if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {
|
||||
brcmf_err("rx protocol error\n");
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
devinfo->bus_pub.bus->dstats.rx_errors++;
|
||||
} else
|
||||
brcmf_rx_packet(devinfo->dev, ifidx, skb);
|
||||
brcmf_rx_frames(devinfo->dev, &skbq);
|
||||
brcmf_usb_rx_refill(devinfo, req);
|
||||
} else {
|
||||
brcmu_pkt_buf_free_skb(skb);
|
||||
@ -1520,10 +1518,23 @@ static void brcmf_release_fw(struct list_head *q)
|
||||
}
|
||||
}
|
||||
|
||||
static int brcmf_usb_reset_device(struct device *dev, void *notused)
|
||||
{
|
||||
/* device past is the usb interface so we
|
||||
* need to use parent here.
|
||||
*/
|
||||
brcmf_dev_reset(dev->parent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void brcmf_usb_exit(void)
|
||||
{
|
||||
struct device_driver *drv = &brcmf_usbdrvr.drvwrap.driver;
|
||||
int ret;
|
||||
|
||||
brcmf_dbg(USB, "Enter\n");
|
||||
ret = driver_for_each_device(drv, NULL, NULL,
|
||||
brcmf_usb_reset_device);
|
||||
usb_deregister(&brcmf_usbdrvr);
|
||||
brcmf_release_fw(&fw_image_list);
|
||||
}
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
/* Toplevel file. Relies on dhd_linux.c to send commands to the dongle. */
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <net/cfg80211.h>
|
||||
@ -2011,67 +2009,6 @@ done:
|
||||
return err;
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev,
|
||||
const u8 *addr,
|
||||
const struct cfg80211_bitrate_mask *mask)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
struct brcm_rateset_le rateset_le;
|
||||
s32 rate;
|
||||
s32 val;
|
||||
s32 err_bg;
|
||||
s32 err_a;
|
||||
u32 legacy;
|
||||
s32 err = 0;
|
||||
|
||||
brcmf_dbg(TRACE, "Enter\n");
|
||||
if (!check_vif_up(ifp->vif))
|
||||
return -EIO;
|
||||
|
||||
/* addr param is always NULL. ignore it */
|
||||
/* Get current rateset */
|
||||
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CURR_RATESET,
|
||||
&rateset_le, sizeof(rateset_le));
|
||||
if (err) {
|
||||
brcmf_err("could not get current rateset (%d)\n", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
legacy = ffs(mask->control[IEEE80211_BAND_2GHZ].legacy & 0xFFFF);
|
||||
if (!legacy)
|
||||
legacy = ffs(mask->control[IEEE80211_BAND_5GHZ].legacy &
|
||||
0xFFFF);
|
||||
|
||||
val = wl_g_rates[legacy - 1].bitrate * 100000;
|
||||
|
||||
if (val < le32_to_cpu(rateset_le.count))
|
||||
/* Select rate by rateset index */
|
||||
rate = rateset_le.rates[val] & 0x7f;
|
||||
else
|
||||
/* Specified rate in bps */
|
||||
rate = val / 500000;
|
||||
|
||||
brcmf_dbg(CONN, "rate %d mbps\n", rate / 2);
|
||||
|
||||
/*
|
||||
*
|
||||
* Set rate override,
|
||||
* Since the is a/b/g-blind, both a/bg_rate are enforced.
|
||||
*/
|
||||
err_bg = brcmf_fil_iovar_int_set(ifp, "bg_rate", rate);
|
||||
err_a = brcmf_fil_iovar_int_set(ifp, "a_rate", rate);
|
||||
if (err_bg && err_a) {
|
||||
brcmf_err("could not set fixed rate (%d) (%d)\n", err_bg,
|
||||
err_a);
|
||||
err = err_bg | err_a;
|
||||
}
|
||||
|
||||
done:
|
||||
brcmf_dbg(TRACE, "Exit\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg,
|
||||
struct brcmf_bss_info_le *bi)
|
||||
{
|
||||
@ -3704,7 +3641,6 @@ static struct cfg80211_ops wl_cfg80211_ops = {
|
||||
.set_default_key = brcmf_cfg80211_config_default_key,
|
||||
.set_default_mgmt_key = brcmf_cfg80211_config_default_mgmt_key,
|
||||
.set_power_mgmt = brcmf_cfg80211_set_power_mgmt,
|
||||
.set_bitrate_mask = brcmf_cfg80211_set_bitrate_mask,
|
||||
.connect = brcmf_cfg80211_connect,
|
||||
.disconnect = brcmf_cfg80211_disconnect,
|
||||
.suspend = brcmf_cfg80211_suspend,
|
||||
@ -4330,9 +4266,8 @@ void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg)
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
|
||||
brcmf_dongle_roam(struct brcmf_if *ifp, u32 roamvar, u32 bcn_timeout)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
s32 err = 0;
|
||||
__le32 roamtrigger[2];
|
||||
__le32 roam_delta[2];
|
||||
@ -4383,10 +4318,9 @@ dongle_rom_out:
|
||||
}
|
||||
|
||||
static s32
|
||||
brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
|
||||
brcmf_dongle_scantime(struct brcmf_if *ifp, s32 scan_assoc_time,
|
||||
s32 scan_unassoc_time, s32 scan_passive_time)
|
||||
{
|
||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||
s32 err = 0;
|
||||
|
||||
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
|
||||
@ -4456,6 +4390,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
|
||||
{
|
||||
struct net_device *ndev;
|
||||
struct wireless_dev *wdev;
|
||||
struct brcmf_if *ifp;
|
||||
s32 power_mode;
|
||||
s32 err = 0;
|
||||
|
||||
@ -4464,35 +4399,34 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
|
||||
|
||||
ndev = cfg_to_ndev(cfg);
|
||||
wdev = ndev->ieee80211_ptr;
|
||||
ifp = netdev_priv(ndev);
|
||||
|
||||
brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME,
|
||||
WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
|
||||
/* make sure RF is ready for work */
|
||||
brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
|
||||
|
||||
brcmf_dongle_scantime(ifp, WL_SCAN_CHANNEL_TIME,
|
||||
WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
|
||||
|
||||
power_mode = cfg->pwr_save ? PM_FAST : PM_OFF;
|
||||
err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PM,
|
||||
power_mode);
|
||||
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, power_mode);
|
||||
if (err)
|
||||
goto default_conf_out;
|
||||
brcmf_dbg(INFO, "power save set to %s\n",
|
||||
(power_mode ? "enabled" : "disabled"));
|
||||
|
||||
err = brcmf_dongle_roam(ndev, (cfg->roam_on ? 0 : 1),
|
||||
WL_BEACON_TIMEOUT);
|
||||
err = brcmf_dongle_roam(ifp, (cfg->roam_on ? 0 : 1), WL_BEACON_TIMEOUT);
|
||||
if (err)
|
||||
goto default_conf_out;
|
||||
err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,
|
||||
NULL, NULL);
|
||||
if (err && err != -EINPROGRESS)
|
||||
if (err)
|
||||
goto default_conf_out;
|
||||
err = brcmf_dongle_probecap(cfg);
|
||||
if (err)
|
||||
goto default_conf_out;
|
||||
|
||||
/* -EINPROGRESS: Call commit handler */
|
||||
|
||||
default_conf_out:
|
||||
|
||||
cfg->dongle_up = true;
|
||||
default_conf_out:
|
||||
|
||||
return err;
|
||||
|
||||
@ -4501,8 +4435,6 @@ default_conf_out:
|
||||
static s32 __brcmf_cfg80211_up(struct brcmf_if *ifp)
|
||||
{
|
||||
set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state);
|
||||
if (ifp->idx)
|
||||
return 0;
|
||||
|
||||
return brcmf_config_dongle(ifp->drvr->config);
|
||||
}
|
||||
|
@ -961,7 +961,6 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
||||
/* if acked then clear bit and free packet */
|
||||
if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
|
||||
&& isset(bitmap, bindex)) {
|
||||
ini->tx_in_transit--;
|
||||
ini->txretry[index] = 0;
|
||||
|
||||
/*
|
||||
@ -990,7 +989,6 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
||||
if (retry && (ini->txretry[index] < (int)retry_limit)) {
|
||||
int ret;
|
||||
ini->txretry[index]++;
|
||||
ini->tx_in_transit--;
|
||||
ret = brcms_c_txfifo(wlc, queue, p);
|
||||
/*
|
||||
* We shouldn't be out of space in the DMA
|
||||
@ -1000,7 +998,6 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
||||
WARN_ONCE(ret, "queue %d out of txds\n", queue);
|
||||
} else {
|
||||
/* Retry timeout */
|
||||
ini->tx_in_transit--;
|
||||
ieee80211_tx_info_clear_status(tx_info);
|
||||
tx_info->status.ampdu_ack_len = 0;
|
||||
tx_info->status.ampdu_len = 1;
|
||||
@ -1009,8 +1006,8 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
|
||||
skb_pull(p, D11_PHY_HDR_LEN);
|
||||
skb_pull(p, D11_TXH_LEN);
|
||||
brcms_dbg_ht(wlc->hw->d11core,
|
||||
"BA Timeout, seq %d, in_transit %d\n",
|
||||
seq, ini->tx_in_transit);
|
||||
"BA Timeout, seq %d\n",
|
||||
seq);
|
||||
ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
|
||||
p);
|
||||
}
|
||||
|
@ -670,7 +670,7 @@ brcms_reg_apply_beaconing_flags(struct wiphy *wiphy,
|
||||
struct ieee80211_supported_band *sband;
|
||||
struct ieee80211_channel *ch;
|
||||
const struct ieee80211_reg_rule *rule;
|
||||
int band, i, ret;
|
||||
int band, i;
|
||||
|
||||
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
|
||||
sband = wiphy->bands[band];
|
||||
@ -685,9 +685,8 @@ brcms_reg_apply_beaconing_flags(struct wiphy *wiphy,
|
||||
continue;
|
||||
|
||||
if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
|
||||
ret = freq_reg_info(wiphy, ch->center_freq,
|
||||
0, &rule);
|
||||
if (ret)
|
||||
rule = freq_reg_info(wiphy, ch->center_freq);
|
||||
if (IS_ERR(rule))
|
||||
continue;
|
||||
|
||||
if (!(rule->flags & NL80211_RRF_NO_IBSS))
|
||||
@ -703,8 +702,8 @@ brcms_reg_apply_beaconing_flags(struct wiphy *wiphy,
|
||||
}
|
||||
}
|
||||
|
||||
static int brcms_reg_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
static void brcms_reg_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct brcms_info *wl = hw->priv;
|
||||
@ -745,8 +744,6 @@ static int brcms_reg_notifier(struct wiphy *wiphy,
|
||||
if (wlc->pub->_nbands > 1 || wlc->band->bandtype == BRCM_BAND_2G)
|
||||
wlc_phy_chanspec_ch14_widefilter_set(wlc->band->pi,
|
||||
brcms_c_japan_ccode(request->alpha2));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void brcms_c_regd_init(struct brcms_c_info *wlc)
|
||||
|
@ -362,8 +362,11 @@ brcms_ops_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
spin_lock_bh(&wl->lock);
|
||||
memcpy(wl->pub->cur_etheraddr, vif->addr, sizeof(vif->addr));
|
||||
wl->mute_tx = false;
|
||||
brcms_c_mute(wl->wlc, false);
|
||||
spin_unlock_bh(&wl->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -668,7 +671,9 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
|
||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
|
||||
case IEEE80211_AMPDU_TX_STOP:
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
spin_lock_bh(&wl->lock);
|
||||
brcms_c_ampdu_flush(wl->wlc, sta, tid);
|
||||
spin_unlock_bh(&wl->lock);
|
||||
@ -1407,9 +1412,10 @@ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic)
|
||||
#endif
|
||||
t->ms = ms;
|
||||
t->periodic = (bool) periodic;
|
||||
t->set = true;
|
||||
|
||||
atomic_inc(&t->wl->callbacks);
|
||||
if (!t->set) {
|
||||
t->set = true;
|
||||
atomic_inc(&t->wl->callbacks);
|
||||
}
|
||||
|
||||
ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms));
|
||||
}
|
||||
|
@ -2473,6 +2473,7 @@ static void brcms_b_tx_fifo_resume(struct brcms_hardware *wlc_hw,
|
||||
static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool mute_tx)
|
||||
{
|
||||
static const u8 null_ether_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
|
||||
u8 *ethaddr = wlc_hw->wlc->pub->cur_etheraddr;
|
||||
|
||||
if (mute_tx) {
|
||||
/* suspend tx fifos */
|
||||
@ -2482,8 +2483,7 @@ static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool mute_tx)
|
||||
brcms_b_tx_fifo_suspend(wlc_hw, TX_AC_VI_FIFO);
|
||||
|
||||
/* zero the address match register so we do not send ACKs */
|
||||
brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
|
||||
null_ether_addr);
|
||||
brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, null_ether_addr);
|
||||
} else {
|
||||
/* resume tx fifos */
|
||||
brcms_b_tx_fifo_resume(wlc_hw, TX_DATA_FIFO);
|
||||
@ -2492,8 +2492,7 @@ static void brcms_b_mute(struct brcms_hardware *wlc_hw, bool mute_tx)
|
||||
brcms_b_tx_fifo_resume(wlc_hw, TX_AC_VI_FIFO);
|
||||
|
||||
/* Restore address */
|
||||
brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET,
|
||||
wlc_hw->etheraddr);
|
||||
brcms_b_set_addrmatch(wlc_hw, RCM_MAC_OFFSET, ethaddr);
|
||||
}
|
||||
|
||||
wlc_phy_mute_upd(wlc_hw->band->pi, mute_tx, 0);
|
||||
@ -7633,7 +7632,7 @@ brcms_b_recv(struct brcms_hardware *wlc_hw, uint fifo, bool bound)
|
||||
|
||||
uint n = 0;
|
||||
uint bound_limit = bound ? RXBND : -1;
|
||||
bool morepending;
|
||||
bool morepending = false;
|
||||
|
||||
skb_queue_head_init(&recv_frames);
|
||||
|
||||
|
@ -36,7 +36,6 @@
|
||||
|
||||
/* structure to store per-tid state for the ampdu initiator */
|
||||
struct scb_ampdu_tid_ini {
|
||||
u8 tx_in_transit; /* number of pending mpdus in transit in driver */
|
||||
u8 tid; /* initiator tid for easy lookup */
|
||||
/* tx retry count; indexed by seq modulo */
|
||||
u8 txretry[AMPDU_TX_BA_MAX_WSIZE];
|
||||
|
@ -3474,6 +3474,7 @@ struct ieee80211_ops il3945_mac_ops = {
|
||||
.sta_add = il3945_mac_sta_add,
|
||||
.sta_remove = il_mac_sta_remove,
|
||||
.tx_last_beacon = il_mac_tx_last_beacon,
|
||||
.flush = il_mac_flush,
|
||||
};
|
||||
|
||||
static int
|
||||
@ -3548,7 +3549,8 @@ il3945_setup_mac(struct il_priv *il)
|
||||
hw->vif_data_size = sizeof(struct il_vif_priv);
|
||||
|
||||
/* Tell mac80211 our characteristics */
|
||||
hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SPECTRUM_MGMT;
|
||||
hw->flags = IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SPECTRUM_MGMT |
|
||||
IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
|
||||
|
||||
hw->wiphy->interface_modes =
|
||||
BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC);
|
||||
@ -3557,6 +3559,8 @@ il3945_setup_mac(struct il_priv *il)
|
||||
WIPHY_FLAG_CUSTOM_REGULATORY | WIPHY_FLAG_DISABLE_BEACON_HINTS |
|
||||
WIPHY_FLAG_IBSS_RSN;
|
||||
|
||||
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||
|
||||
hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945;
|
||||
/* we create the 802.11 header and a zero-length SSID element */
|
||||
hw->wiphy->max_scan_ie_len = IL3945_MAX_PROBE_REQUEST - 24 - 2;
|
||||
|
@ -5712,8 +5712,8 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length)
|
||||
hw->flags =
|
||||
IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION |
|
||||
IEEE80211_HW_NEED_DTIM_PERIOD | IEEE80211_HW_SPECTRUM_MGMT |
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS;
|
||||
|
||||
IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS |
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
|
||||
if (il->cfg->sku & IL_SKU_N)
|
||||
hw->flags |=
|
||||
IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
|
||||
@ -5968,7 +5968,9 @@ il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
D_HT("start Tx\n");
|
||||
ret = il4965_tx_agg_start(il, vif, sta, tid, ssn);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP:
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
D_HT("stop Tx\n");
|
||||
ret = il4965_tx_agg_stop(il, vif, sta, tid);
|
||||
if (test_bit(S_EXIT_PENDING, &il->status))
|
||||
@ -6306,6 +6308,7 @@ const struct ieee80211_ops il4965_mac_ops = {
|
||||
.sta_remove = il_mac_sta_remove,
|
||||
.channel_switch = il4965_mac_channel_switch,
|
||||
.tx_last_beacon = il_mac_tx_last_beacon,
|
||||
.flush = il_mac_flush,
|
||||
};
|
||||
|
||||
static int
|
||||
@ -6553,6 +6556,7 @@ il4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
il4965_prepare_card_hw(il);
|
||||
if (!il->hw_ready) {
|
||||
IL_WARN("Failed, HW not ready\n");
|
||||
err = -EIO;
|
||||
goto out_iounmap;
|
||||
}
|
||||
|
||||
|
@ -3958,17 +3958,21 @@ il_connection_init_rx_config(struct il_priv *il)
|
||||
|
||||
memset(&il->staging, 0, sizeof(il->staging));
|
||||
|
||||
if (!il->vif) {
|
||||
switch (il->iw_mode) {
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
il->staging.dev_type = RXON_DEV_TYPE_ESS;
|
||||
} else if (il->vif->type == NL80211_IFTYPE_STATION) {
|
||||
break;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
il->staging.dev_type = RXON_DEV_TYPE_ESS;
|
||||
il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
|
||||
} else if (il->vif->type == NL80211_IFTYPE_ADHOC) {
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
il->staging.dev_type = RXON_DEV_TYPE_IBSS;
|
||||
il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
|
||||
il->staging.filter_flags =
|
||||
RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
IL_ERR("Unsupported interface type %d\n", il->vif->type);
|
||||
return;
|
||||
}
|
||||
@ -4550,8 +4554,7 @@ out:
|
||||
EXPORT_SYMBOL(il_mac_add_interface);
|
||||
|
||||
static void
|
||||
il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif,
|
||||
bool mode_change)
|
||||
il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif)
|
||||
{
|
||||
lockdep_assert_held(&il->mutex);
|
||||
|
||||
@ -4560,9 +4563,7 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif,
|
||||
il_force_scan_end(il);
|
||||
}
|
||||
|
||||
if (!mode_change)
|
||||
il_set_mode(il);
|
||||
|
||||
il_set_mode(il);
|
||||
}
|
||||
|
||||
void
|
||||
@ -4575,8 +4576,8 @@ il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
|
||||
|
||||
WARN_ON(il->vif != vif);
|
||||
il->vif = NULL;
|
||||
|
||||
il_teardown_interface(il, vif, false);
|
||||
il->iw_mode = NL80211_IFTYPE_UNSPECIFIED;
|
||||
il_teardown_interface(il, vif);
|
||||
memset(il->bssid, 0, ETH_ALEN);
|
||||
|
||||
D_MAC80211("leave\n");
|
||||
@ -4685,18 +4686,10 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
}
|
||||
|
||||
/* success */
|
||||
il_teardown_interface(il, vif, true);
|
||||
vif->type = newtype;
|
||||
vif->p2p = false;
|
||||
err = il_set_mode(il);
|
||||
WARN_ON(err);
|
||||
/*
|
||||
* We've switched internally, but submitting to the
|
||||
* device may have failed for some reason. Mask this
|
||||
* error, because otherwise mac80211 will not switch
|
||||
* (and set the interface type back) and we'll be
|
||||
* out of sync with it.
|
||||
*/
|
||||
il->iw_mode = newtype;
|
||||
il_teardown_interface(il, vif);
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
@ -4707,6 +4700,42 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(il_mac_change_interface);
|
||||
|
||||
void
|
||||
il_mac_flush(struct ieee80211_hw *hw, bool drop)
|
||||
{
|
||||
struct il_priv *il = hw->priv;
|
||||
unsigned long timeout = jiffies + msecs_to_jiffies(500);
|
||||
int i;
|
||||
|
||||
mutex_lock(&il->mutex);
|
||||
D_MAC80211("enter\n");
|
||||
|
||||
if (il->txq == NULL)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < il->hw_params.max_txq_num; i++) {
|
||||
struct il_queue *q;
|
||||
|
||||
if (i == il->cmd_queue)
|
||||
continue;
|
||||
|
||||
q = &il->txq[i].q;
|
||||
if (q->read_ptr == q->write_ptr)
|
||||
continue;
|
||||
|
||||
if (time_after(jiffies, timeout)) {
|
||||
IL_ERR("Failed to flush queue %d\n", q->id);
|
||||
break;
|
||||
}
|
||||
|
||||
msleep(20);
|
||||
}
|
||||
out:
|
||||
D_MAC80211("leave\n");
|
||||
mutex_unlock(&il->mutex);
|
||||
}
|
||||
EXPORT_SYMBOL(il_mac_flush);
|
||||
|
||||
/*
|
||||
* On every watchdog tick we check (latest) time stamp. If it does not
|
||||
* change during timeout period and queue is not empty we reset firmware.
|
||||
|
@ -1723,6 +1723,7 @@ void il_mac_remove_interface(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif);
|
||||
int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
enum nl80211_iftype newtype, bool newp2p);
|
||||
void il_mac_flush(struct ieee80211_hw *hw, bool drop);
|
||||
int il_alloc_txq_mem(struct il_priv *il);
|
||||
void il_free_txq_mem(struct il_priv *il);
|
||||
|
||||
|
@ -3695,7 +3695,7 @@ struct iwl_bt_uart_msg {
|
||||
u8 frame5;
|
||||
u8 frame6;
|
||||
u8 frame7;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
struct iwl_bt_coex_profile_notif {
|
||||
struct iwl_bt_uart_msg last_bt_uart_msg;
|
||||
@ -3703,7 +3703,7 @@ struct iwl_bt_coex_profile_notif {
|
||||
u8 bt_traffic_load; /* 0 .. 3? */
|
||||
u8 bt_ci_compliance; /* 0 - not complied, 1 - complied */
|
||||
u8 reserved;
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
#define IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS 0
|
||||
#define IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_MSK 0x1
|
||||
@ -3752,7 +3752,7 @@ enum bt_coex_prio_table_priorities {
|
||||
|
||||
struct iwl_bt_coex_prio_table_cmd {
|
||||
u8 prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
#define IWL_BT_COEX_ENV_CLOSE 0
|
||||
#define IWL_BT_COEX_ENV_OPEN 1
|
||||
@ -3764,7 +3764,7 @@ struct iwl_bt_coex_prot_env_cmd {
|
||||
u8 action; /* 0 = closed, 1 = open */
|
||||
u8 type; /* 0 .. 15 */
|
||||
u8 reserved[2];
|
||||
} __attribute__((packed));
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* REPLY_D3_CONFIG
|
||||
|
@ -157,7 +157,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
|
||||
sram = priv->dbgfs_sram_offset & ~0x3;
|
||||
|
||||
/* read the first u32 from sram */
|
||||
val = iwl_read_targ_mem(priv->trans, sram);
|
||||
val = iwl_trans_read_mem32(priv->trans, sram);
|
||||
|
||||
for (; len; len--) {
|
||||
/* put the address at the start of every line */
|
||||
@ -176,7 +176,7 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
|
||||
if (++offset == 4) {
|
||||
sram += 4;
|
||||
offset = 0;
|
||||
val = iwl_read_targ_mem(priv->trans, sram);
|
||||
val = iwl_trans_read_mem32(priv->trans, sram);
|
||||
}
|
||||
|
||||
/* put in extra spaces and split lines for human readability */
|
||||
|
@ -69,7 +69,7 @@ static const struct ieee80211_tpt_blink iwl_blink[] = {
|
||||
/* Set led register off */
|
||||
void iwlagn_led_enable(struct iwl_priv *priv)
|
||||
{
|
||||
iwl_write32(priv->trans, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
|
||||
iwl_write32(priv->trans, CSR_LED_REG, CSR_LED_REG_TURN_ON);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -206,7 +206,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
|
||||
priv->trans->ops->wowlan_suspend &&
|
||||
priv->trans->ops->d3_suspend &&
|
||||
priv->trans->ops->d3_resume &&
|
||||
device_can_wakeup(priv->trans->dev)) {
|
||||
hw->wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
|
||||
WIPHY_WOWLAN_DISCONNECT |
|
||||
@ -426,7 +427,7 @@ static int iwlagn_mac_suspend(struct ieee80211_hw *hw,
|
||||
if (ret)
|
||||
goto error;
|
||||
|
||||
iwl_trans_wowlan_suspend(priv->trans);
|
||||
iwl_trans_d3_suspend(priv->trans);
|
||||
|
||||
goto out;
|
||||
|
||||
@ -459,11 +460,11 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
||||
base = priv->device_pointers.error_event_table;
|
||||
if (iwlagn_hw_valid_rtc_data_addr(base)) {
|
||||
spin_lock_irqsave(&priv->trans->reg_lock, flags);
|
||||
ret = iwl_grab_nic_access_silent(priv->trans);
|
||||
if (likely(ret == 0)) {
|
||||
if (iwl_trans_grab_nic_access(priv->trans, true)) {
|
||||
iwl_write32(priv->trans, HBUS_TARG_MEM_RADDR, base);
|
||||
status = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
|
||||
iwl_release_nic_access(priv->trans);
|
||||
iwl_trans_release_nic_access(priv->trans);
|
||||
ret = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->trans->reg_lock, flags);
|
||||
|
||||
@ -479,7 +480,7 @@ static int iwlagn_mac_resume(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
if (priv->wowlan_sram)
|
||||
_iwl_read_targ_mem_dwords(
|
||||
iwl_trans_read_mem(
|
||||
priv->trans, 0x800000,
|
||||
priv->wowlan_sram,
|
||||
img->sec[IWL_UCODE_SECTION_DATA].len / 4);
|
||||
@ -520,9 +521,6 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw,
|
||||
{
|
||||
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
|
||||
|
||||
IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
|
||||
ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
|
||||
|
||||
if (iwlagn_tx_skb(priv, control->sta, skb))
|
||||
ieee80211_free_txskb(hw, skb);
|
||||
}
|
||||
@ -679,7 +677,9 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
|
||||
IWL_DEBUG_HT(priv, "start Tx\n");
|
||||
ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP:
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
IWL_DEBUG_HT(priv, "stop Tx\n");
|
||||
ret = iwlagn_tx_agg_stop(priv, vif, sta, tid);
|
||||
if ((ret == 0) && (priv->agg_tids_count > 0)) {
|
||||
|
@ -354,7 +354,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
|
||||
|
||||
/* Make sure device is powered up for SRAM reads */
|
||||
spin_lock_irqsave(&priv->trans->reg_lock, reg_flags);
|
||||
if (unlikely(!iwl_grab_nic_access(priv->trans))) {
|
||||
if (!iwl_trans_grab_nic_access(priv->trans, false)) {
|
||||
spin_unlock_irqrestore(&priv->trans->reg_lock, reg_flags);
|
||||
return;
|
||||
}
|
||||
@ -388,7 +388,7 @@ static void iwl_print_cont_event_trace(struct iwl_priv *priv, u32 base,
|
||||
}
|
||||
}
|
||||
/* Allow device to power down */
|
||||
iwl_release_nic_access(priv->trans);
|
||||
iwl_trans_release_nic_access(priv->trans);
|
||||
spin_unlock_irqrestore(&priv->trans->reg_lock, reg_flags);
|
||||
}
|
||||
|
||||
@ -408,7 +408,8 @@ static void iwl_continuous_event_trace(struct iwl_priv *priv)
|
||||
|
||||
base = priv->device_pointers.log_event_table;
|
||||
if (iwlagn_hw_valid_rtc_data_addr(base)) {
|
||||
iwl_read_targ_mem_bytes(priv->trans, base, &read, sizeof(read));
|
||||
iwl_trans_read_mem_bytes(priv->trans, base,
|
||||
&read, sizeof(read));
|
||||
capacity = read.capacity;
|
||||
mode = read.mode;
|
||||
num_wraps = read.wrap_counter;
|
||||
@ -1627,7 +1628,7 @@ static void iwl_dump_nic_error_log(struct iwl_priv *priv)
|
||||
}
|
||||
|
||||
/*TODO: Update dbgfs with ISR error stats obtained below */
|
||||
iwl_read_targ_mem_bytes(trans, base, &table, sizeof(table));
|
||||
iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
|
||||
|
||||
if (ERROR_START_OFFSET <= table.valid * ERROR_ELEM_SIZE) {
|
||||
IWL_ERR(trans, "Start IWL Error Log Dump:\n");
|
||||
@ -1717,7 +1718,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
||||
|
||||
/* Make sure device is powered up for SRAM reads */
|
||||
spin_lock_irqsave(&trans->reg_lock, reg_flags);
|
||||
if (unlikely(!iwl_grab_nic_access(trans)))
|
||||
if (!iwl_trans_grab_nic_access(trans, false))
|
||||
goto out_unlock;
|
||||
|
||||
/* Set starting address; reads will auto-increment */
|
||||
@ -1756,7 +1757,7 @@ static int iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
|
||||
}
|
||||
|
||||
/* Allow device to power down */
|
||||
iwl_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
out_unlock:
|
||||
spin_unlock_irqrestore(&trans->reg_lock, reg_flags);
|
||||
return pos;
|
||||
@ -1835,10 +1836,10 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
|
||||
}
|
||||
|
||||
/* event log header */
|
||||
capacity = iwl_read_targ_mem(trans, base);
|
||||
mode = iwl_read_targ_mem(trans, base + (1 * sizeof(u32)));
|
||||
num_wraps = iwl_read_targ_mem(trans, base + (2 * sizeof(u32)));
|
||||
next_entry = iwl_read_targ_mem(trans, base + (3 * sizeof(u32)));
|
||||
capacity = iwl_trans_read_mem32(trans, base);
|
||||
mode = iwl_trans_read_mem32(trans, base + (1 * sizeof(u32)));
|
||||
num_wraps = iwl_trans_read_mem32(trans, base + (2 * sizeof(u32)));
|
||||
next_entry = iwl_trans_read_mem32(trans, base + (3 * sizeof(u32)));
|
||||
|
||||
if (capacity > logsize) {
|
||||
IWL_ERR(priv, "Log capacity %d is bogus, limit to %d "
|
||||
|
@ -186,8 +186,8 @@ static void iwl_tt_check_exit_ct_kill(unsigned long data)
|
||||
}
|
||||
iwl_read32(priv->trans, CSR_UCODE_DRV_GP1);
|
||||
spin_lock_irqsave(&priv->trans->reg_lock, flags);
|
||||
if (likely(iwl_grab_nic_access(priv->trans)))
|
||||
iwl_release_nic_access(priv->trans);
|
||||
if (iwl_trans_grab_nic_access(priv->trans, false))
|
||||
iwl_trans_release_nic_access(priv->trans);
|
||||
spin_unlock_irqrestore(&priv->trans->reg_lock, flags);
|
||||
|
||||
/* Reschedule the ct_kill timer to occur in
|
||||
|
@ -231,13 +231,11 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
|
||||
memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
|
||||
if (info->flags & IEEE80211_TX_CTL_AMPDU)
|
||||
tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
|
||||
IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
|
||||
break;
|
||||
|
||||
case WLAN_CIPHER_SUITE_TKIP:
|
||||
tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
|
||||
ieee80211_get_tkip_p2k(keyconf, skb_frag, tx_cmd->key);
|
||||
IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
|
||||
break;
|
||||
|
||||
case WLAN_CIPHER_SUITE_WEP104:
|
||||
@ -355,8 +353,6 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
|
||||
}
|
||||
}
|
||||
|
||||
IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
|
||||
|
||||
if (sta)
|
||||
sta_priv = (void *)sta->drv_priv;
|
||||
|
||||
@ -472,6 +468,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
|
||||
WARN_ON_ONCE(is_agg &&
|
||||
priv->queue_to_mac80211[txq_id] != info->hw_queue);
|
||||
|
||||
IWL_DEBUG_TX(priv, "TX to [%d|%d] Q:%d - seq: 0x%x\n", sta_id, tid,
|
||||
txq_id, seq_number);
|
||||
|
||||
if (iwl_trans_tx(priv->trans, skb, dev_cmd, txq_id))
|
||||
goto drop_unlock_sta;
|
||||
|
||||
@ -541,9 +540,9 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
spin_lock_bh(&priv->sta_lock);
|
||||
|
||||
tid_data = &priv->tid_data[sta_id][tid];
|
||||
txq_id = priv->tid_data[sta_id][tid].agg.txq_id;
|
||||
txq_id = tid_data->agg.txq_id;
|
||||
|
||||
switch (priv->tid_data[sta_id][tid].agg.state) {
|
||||
switch (tid_data->agg.state) {
|
||||
case IWL_EMPTYING_HW_QUEUE_ADDBA:
|
||||
/*
|
||||
* This can happen if the peer stops aggregation
|
||||
@ -563,9 +562,9 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
case IWL_AGG_ON:
|
||||
break;
|
||||
default:
|
||||
IWL_WARN(priv, "Stopping AGG while state not ON "
|
||||
"or starting for %d on %d (%d)\n", sta_id, tid,
|
||||
priv->tid_data[sta_id][tid].agg.state);
|
||||
IWL_WARN(priv,
|
||||
"Stopping AGG while state not ON or starting for %d on %d (%d)\n",
|
||||
sta_id, tid, tid_data->agg.state);
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
return 0;
|
||||
}
|
||||
@ -578,12 +577,11 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
"stopping AGG on STA/TID %d/%d but hwq %d not used\n",
|
||||
sta_id, tid, txq_id);
|
||||
} else if (tid_data->agg.ssn != tid_data->next_reclaimed) {
|
||||
IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, "
|
||||
"next_recl = %d\n",
|
||||
IWL_DEBUG_TX_QUEUES(priv,
|
||||
"Can't proceed: ssn %d, next_recl = %d\n",
|
||||
tid_data->agg.ssn,
|
||||
tid_data->next_reclaimed);
|
||||
priv->tid_data[sta_id][tid].agg.state =
|
||||
IWL_EMPTYING_HW_QUEUE_DELBA;
|
||||
tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_DELBA;
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
return 0;
|
||||
}
|
||||
@ -591,8 +589,8 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
|
||||
IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n",
|
||||
tid_data->agg.ssn);
|
||||
turn_off:
|
||||
agg_state = priv->tid_data[sta_id][tid].agg.state;
|
||||
priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
|
||||
agg_state = tid_data->agg.state;
|
||||
tid_data->agg.state = IWL_AGG_OFF;
|
||||
|
||||
spin_unlock_bh(&priv->sta_lock);
|
||||
|
||||
@ -954,12 +952,6 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv,
|
||||
if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
|
||||
AGG_TX_STATE_ABORT_MSK))
|
||||
continue;
|
||||
|
||||
IWL_DEBUG_TX_REPLY(priv, "status %s (0x%08x), "
|
||||
"try-count (0x%08x)\n",
|
||||
iwl_get_agg_tx_fail_reason(fstatus),
|
||||
fstatus & AGG_TX_STATUS_MSK,
|
||||
fstatus & AGG_TX_TRY_MSK);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1079,6 +1071,8 @@ static void iwlagn_set_tx_status(struct iwl_priv *priv,
|
||||
{
|
||||
u16 status = le16_to_cpu(tx_resp->status.status);
|
||||
|
||||
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
|
||||
|
||||
info->status.rates[0].count = tx_resp->failure_frame + 1;
|
||||
info->flags |= iwl_tx_status_to_mac80211(status);
|
||||
iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
|
||||
@ -1223,16 +1217,27 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
|
||||
next_reclaimed);
|
||||
}
|
||||
|
||||
WARN_ON(!is_agg && freed != 1);
|
||||
if (!is_agg && freed != 1)
|
||||
IWL_ERR(priv, "Q: %d, freed %d\n", txq_id, freed);
|
||||
|
||||
/*
|
||||
* An offchannel frame can be send only on the AUX queue, where
|
||||
* there is no aggregation (and reordering) so it only is single
|
||||
* skb is expected to be processed.
|
||||
*/
|
||||
WARN_ON(is_offchannel_skb && freed != 1);
|
||||
if (is_offchannel_skb && freed != 1)
|
||||
IWL_ERR(priv, "OFFCHANNEL SKB freed %d\n", freed);
|
||||
}
|
||||
|
||||
IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x)\n", txq_id,
|
||||
iwl_get_tx_fail_reason(status), status);
|
||||
|
||||
IWL_DEBUG_TX_REPLY(priv,
|
||||
"\t\t\t\tinitial_rate 0x%x retries %d, idx=%d ssn=%d seq_ctl=0x%x\n",
|
||||
le32_to_cpu(tx_resp->rate_n_flags),
|
||||
tx_resp->failure_frame, SEQ_TO_INDEX(sequence), ssn,
|
||||
le16_to_cpu(tx_resp->seq_ctl));
|
||||
|
||||
iwl_check_abort_status(priv, tx_resp->frame_count, status);
|
||||
spin_unlock(&priv->sta_lock);
|
||||
|
||||
|
@ -286,89 +286,6 @@ static int iwl_alive_notify(struct iwl_priv *priv)
|
||||
return iwl_send_calib_results(priv);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* iwl_verify_inst_sparse - verify runtime uCode image in card vs. host,
|
||||
* using sample data 100 bytes apart. If these sample points are good,
|
||||
* it's a pretty good bet that everything between them is good, too.
|
||||
*/
|
||||
static int iwl_verify_sec_sparse(struct iwl_priv *priv,
|
||||
const struct fw_desc *fw_desc)
|
||||
{
|
||||
__le32 *image = (__le32 *)fw_desc->data;
|
||||
u32 len = fw_desc->len;
|
||||
u32 val;
|
||||
u32 i;
|
||||
|
||||
IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
|
||||
|
||||
for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
|
||||
/* read data comes through single port, auto-incr addr */
|
||||
/* NOTE: Use the debugless read so we don't flood kernel log
|
||||
* if IWL_DL_IO is set */
|
||||
iwl_write_direct32(priv->trans, HBUS_TARG_MEM_RADDR,
|
||||
i + fw_desc->offset);
|
||||
val = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
|
||||
if (val != le32_to_cpu(*image))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_print_mismatch_sec(struct iwl_priv *priv,
|
||||
const struct fw_desc *fw_desc)
|
||||
{
|
||||
__le32 *image = (__le32 *)fw_desc->data;
|
||||
u32 len = fw_desc->len;
|
||||
u32 val;
|
||||
u32 offs;
|
||||
int errors = 0;
|
||||
|
||||
IWL_DEBUG_FW(priv, "ucode inst image size is %u\n", len);
|
||||
|
||||
iwl_write_direct32(priv->trans, HBUS_TARG_MEM_RADDR,
|
||||
fw_desc->offset);
|
||||
|
||||
for (offs = 0;
|
||||
offs < len && errors < 20;
|
||||
offs += sizeof(u32), image++) {
|
||||
/* read data comes through single port, auto-incr addr */
|
||||
val = iwl_read32(priv->trans, HBUS_TARG_MEM_RDAT);
|
||||
if (val != le32_to_cpu(*image)) {
|
||||
IWL_ERR(priv, "uCode INST section at "
|
||||
"offset 0x%x, is 0x%x, s/b 0x%x\n",
|
||||
offs, val, le32_to_cpu(*image));
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* iwl_verify_ucode - determine which instruction image is in SRAM,
|
||||
* and verify its contents
|
||||
*/
|
||||
static int iwl_verify_ucode(struct iwl_priv *priv,
|
||||
enum iwl_ucode_type ucode_type)
|
||||
{
|
||||
const struct fw_img *img = iwl_get_ucode_image(priv, ucode_type);
|
||||
|
||||
if (!img) {
|
||||
IWL_ERR(priv, "Invalid ucode requested (%d)\n", ucode_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!iwl_verify_sec_sparse(priv, &img->sec[IWL_UCODE_SECTION_INST])) {
|
||||
IWL_DEBUG_FW(priv, "uCode is good in inst SRAM\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
IWL_ERR(priv, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n");
|
||||
|
||||
iwl_print_mismatch_sec(priv, &img->sec[IWL_UCODE_SECTION_INST]);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
struct iwl_alive_data {
|
||||
bool valid;
|
||||
u8 subtype;
|
||||
@ -426,7 +343,7 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
|
||||
alive_cmd, ARRAY_SIZE(alive_cmd),
|
||||
iwl_alive_fn, &alive_data);
|
||||
|
||||
ret = iwl_trans_start_fw(priv->trans, fw);
|
||||
ret = iwl_trans_start_fw(priv->trans, fw, false);
|
||||
if (ret) {
|
||||
priv->cur_ucode = old_type;
|
||||
iwl_remove_notification(&priv->notif_wait, &alive_wait);
|
||||
@ -450,18 +367,7 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* This step takes a long time (60-80ms!!) and
|
||||
* WoWLAN image should be loaded quickly, so
|
||||
* skip it for WoWLAN.
|
||||
*/
|
||||
if (ucode_type != IWL_UCODE_WOWLAN) {
|
||||
ret = iwl_verify_ucode(priv, ucode_type);
|
||||
if (ret) {
|
||||
priv->cur_ucode = old_type;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* delay a bit to give rfkill time to run */
|
||||
msleep(5);
|
||||
}
|
||||
|
@ -381,8 +381,8 @@
|
||||
|
||||
/* LED */
|
||||
#define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF)
|
||||
#define CSR_LED_REG_TRUN_ON (0x78)
|
||||
#define CSR_LED_REG_TRUN_OFF (0x38)
|
||||
#define CSR_LED_REG_TURN_ON (0x60)
|
||||
#define CSR_LED_REG_TURN_OFF (0x20)
|
||||
|
||||
/* ANA_PLL */
|
||||
#define CSR50_ANA_PLL_CFG_VAL (0x00880300)
|
||||
|
@ -225,6 +225,8 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
|
||||
#define FH_RSCSR_CHNL0_RBDCB_WPTR_REG (FH_MEM_RSCSR_CHNL0 + 0x008)
|
||||
#define FH_RSCSR_CHNL0_WPTR (FH_RSCSR_CHNL0_RBDCB_WPTR_REG)
|
||||
|
||||
#define FW_RSCSR_CHNL0_RXDCB_RDPTR_REG (FH_MEM_RSCSR_CHNL0 + 0x00c)
|
||||
#define FH_RSCSR_CHNL0_RDPTR FW_RSCSR_CHNL0_RXDCB_RDPTR_REG
|
||||
|
||||
/**
|
||||
* Rx Config/Status Registers (RCSR)
|
||||
@ -257,6 +259,8 @@ static inline unsigned int FH_MEM_CBBC_QUEUE(unsigned int chnl)
|
||||
#define FH_MEM_RCSR_CHNL0 (FH_MEM_RCSR_LOWER_BOUND)
|
||||
|
||||
#define FH_MEM_RCSR_CHNL0_CONFIG_REG (FH_MEM_RCSR_CHNL0)
|
||||
#define FH_MEM_RCSR_CHNL0_RBDCB_WPTR (FH_MEM_RCSR_CHNL0 + 0x8)
|
||||
#define FH_MEM_RCSR_CHNL0_FLUSH_RB_REQ (FH_MEM_RCSR_CHNL0 + 0x10)
|
||||
|
||||
#define FH_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MSK (0x00000FF0) /* bits 4-11 */
|
||||
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MSK (0x00001000) /* bits 12 */
|
||||
|
@ -35,12 +35,12 @@
|
||||
|
||||
#define IWL_POLL_INTERVAL 10 /* microseconds */
|
||||
|
||||
static inline void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
iwl_write32(trans, reg, iwl_read32(trans, reg) | mask);
|
||||
}
|
||||
|
||||
static inline void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask)
|
||||
{
|
||||
iwl_write32(trans, reg, iwl_read32(trans, reg) & ~mask);
|
||||
}
|
||||
@ -99,86 +99,16 @@ int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_poll_bit);
|
||||
|
||||
int iwl_grab_nic_access_silent(struct iwl_trans *trans)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&trans->reg_lock);
|
||||
|
||||
/* this bit wakes up the NIC */
|
||||
__iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
|
||||
/*
|
||||
* These bits say the device is running, and should keep running for
|
||||
* at least a short while (at least as long as MAC_ACCESS_REQ stays 1),
|
||||
* but they do not indicate that embedded SRAM is restored yet;
|
||||
* 3945 and 4965 have volatile SRAM, and must save/restore contents
|
||||
* to/from host DRAM when sleeping/waking for power-saving.
|
||||
* Each direction takes approximately 1/4 millisecond; with this
|
||||
* overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a
|
||||
* series of register accesses are expected (e.g. reading Event Log),
|
||||
* to keep device from sleeping.
|
||||
*
|
||||
* CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that
|
||||
* SRAM is okay/restored. We don't check that here because this call
|
||||
* is just for hardware register access; but GP1 MAC_SLEEP check is a
|
||||
* good idea before accessing 3945/4965 SRAM (e.g. reading Event Log).
|
||||
*
|
||||
* 5000 series and later (including 1000 series) have non-volatile SRAM,
|
||||
* and do not save/restore SRAM when power cycling.
|
||||
*/
|
||||
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
|
||||
(CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
|
||||
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
|
||||
if (ret < 0) {
|
||||
iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_grab_nic_access_silent);
|
||||
|
||||
bool iwl_grab_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
int ret = iwl_grab_nic_access_silent(trans);
|
||||
if (unlikely(ret)) {
|
||||
u32 val = iwl_read32(trans, CSR_GP_CNTRL);
|
||||
WARN_ONCE(1, "Timeout waiting for hardware access "
|
||||
"(CSR_GP_CNTRL 0x%08x)\n", val);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_grab_nic_access);
|
||||
|
||||
void iwl_release_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
lockdep_assert_held(&trans->reg_lock);
|
||||
__iwl_clear_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
/*
|
||||
* Above we read the CSR_GP_CNTRL register, which will flush
|
||||
* any previous writes, but we need the write that clears the
|
||||
* MAC_ACCESS_REQ bit to be performed before any other writes
|
||||
* scheduled on different CPUs (after we drop reg_lock).
|
||||
*/
|
||||
mmiowb();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_release_nic_access);
|
||||
|
||||
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg)
|
||||
{
|
||||
u32 value;
|
||||
u32 value = 0x5a5a5a5a;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
iwl_grab_nic_access(trans);
|
||||
value = iwl_read32(trans, reg);
|
||||
iwl_release_nic_access(trans);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
value = iwl_read32(trans, reg);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
|
||||
return value;
|
||||
@ -190,9 +120,9 @@ void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (likely(iwl_grab_nic_access(trans))) {
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
iwl_write32(trans, reg, value);
|
||||
iwl_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
@ -230,12 +160,13 @@ static inline void __iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
|
||||
{
|
||||
unsigned long flags;
|
||||
u32 val;
|
||||
u32 val = 0x5a5a5a5a;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
iwl_grab_nic_access(trans);
|
||||
val = __iwl_read_prph(trans, ofs);
|
||||
iwl_release_nic_access(trans);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
val = __iwl_read_prph(trans, ofs);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
return val;
|
||||
}
|
||||
@ -246,9 +177,9 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (likely(iwl_grab_nic_access(trans))) {
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
__iwl_write_prph(trans, ofs, val);
|
||||
iwl_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
@ -259,10 +190,10 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (likely(iwl_grab_nic_access(trans))) {
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
__iwl_write_prph(trans, ofs,
|
||||
__iwl_read_prph(trans, ofs) | mask);
|
||||
iwl_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
@ -274,10 +205,10 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (likely(iwl_grab_nic_access(trans))) {
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
__iwl_write_prph(trans, ofs,
|
||||
(__iwl_read_prph(trans, ofs) & mask) | bits);
|
||||
iwl_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
@ -289,66 +220,11 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
|
||||
u32 val;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (likely(iwl_grab_nic_access(trans))) {
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
val = __iwl_read_prph(trans, ofs);
|
||||
__iwl_write_prph(trans, ofs, (val & ~mask));
|
||||
iwl_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_clear_bits_prph);
|
||||
|
||||
void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords)
|
||||
{
|
||||
unsigned long flags;
|
||||
int offs;
|
||||
u32 *vals = buf;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (likely(iwl_grab_nic_access(trans))) {
|
||||
iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr);
|
||||
for (offs = 0; offs < dwords; offs++)
|
||||
vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
|
||||
iwl_release_nic_access(trans);
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(_iwl_read_targ_mem_dwords);
|
||||
|
||||
u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
_iwl_read_targ_mem_dwords(trans, addr, &value, 1);
|
||||
|
||||
return value;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_read_targ_mem);
|
||||
|
||||
int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
|
||||
const void *buf, int dwords)
|
||||
{
|
||||
unsigned long flags;
|
||||
int offs, result = 0;
|
||||
const u32 *vals = buf;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (likely(iwl_grab_nic_access(trans))) {
|
||||
iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
|
||||
for (offs = 0; offs < dwords; offs++)
|
||||
iwl_write32(trans, HBUS_TARG_MEM_WDAT, vals[offs]);
|
||||
iwl_release_nic_access(trans);
|
||||
} else
|
||||
result = -EBUSY;
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
|
||||
return result;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(_iwl_write_targ_mem_dwords);
|
||||
|
||||
int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val)
|
||||
{
|
||||
return _iwl_write_targ_mem_dwords(trans, addr, &val, 1);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(iwl_write_targ_mem);
|
||||
|
@ -53,6 +53,8 @@ static inline u32 iwl_read32(struct iwl_trans *trans, u32 ofs)
|
||||
|
||||
void iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask);
|
||||
void iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask);
|
||||
void __iwl_set_bit(struct iwl_trans *trans, u32 reg, u32 mask);
|
||||
void __iwl_clear_bit(struct iwl_trans *trans, u32 reg, u32 mask);
|
||||
|
||||
void iwl_set_bits_mask(struct iwl_trans *trans, u32 reg, u32 mask, u32 value);
|
||||
|
||||
@ -61,10 +63,6 @@ int iwl_poll_bit(struct iwl_trans *trans, u32 addr,
|
||||
int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
|
||||
int timeout);
|
||||
|
||||
int iwl_grab_nic_access_silent(struct iwl_trans *trans);
|
||||
bool iwl_grab_nic_access(struct iwl_trans *trans);
|
||||
void iwl_release_nic_access(struct iwl_trans *trans);
|
||||
|
||||
u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg);
|
||||
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value);
|
||||
|
||||
@ -76,19 +74,4 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
|
||||
u32 bits, u32 mask);
|
||||
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
|
||||
|
||||
void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords);
|
||||
|
||||
#define iwl_read_targ_mem_bytes(trans, addr, buf, bufsize) \
|
||||
do { \
|
||||
BUILD_BUG_ON((bufsize) % sizeof(u32)); \
|
||||
_iwl_read_targ_mem_dwords(trans, addr, buf, \
|
||||
(bufsize) / sizeof(u32));\
|
||||
} while (0)
|
||||
|
||||
int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
|
||||
const void *buf, int dwords);
|
||||
|
||||
u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr);
|
||||
int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val);
|
||||
#endif
|
||||
|
@ -467,18 +467,20 @@ static int iwl_test_indirect_read(struct iwl_test *tst, u32 addr, u32 size)
|
||||
if (IWL_ABS_PRPH_START <= addr &&
|
||||
addr < IWL_ABS_PRPH_START + PRPH_END) {
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
iwl_grab_nic_access(trans);
|
||||
if (!iwl_trans_grab_nic_access(trans, false)) {
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
return -EIO;
|
||||
}
|
||||
iwl_write32(trans, HBUS_TARG_PRPH_RADDR,
|
||||
addr | (3 << 24));
|
||||
for (i = 0; i < size; i += 4)
|
||||
*(u32 *)(tst->mem.addr + i) =
|
||||
iwl_read32(trans, HBUS_TARG_PRPH_RDAT);
|
||||
iwl_release_nic_access(trans);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
} else { /* target memory (SRAM) */
|
||||
_iwl_read_targ_mem_dwords(trans, addr,
|
||||
tst->mem.addr,
|
||||
tst->mem.size / 4);
|
||||
iwl_trans_read_mem(trans, addr, tst->mem.addr,
|
||||
tst->mem.size / 4);
|
||||
}
|
||||
|
||||
tst->mem.nchunks =
|
||||
@ -501,28 +503,31 @@ static int iwl_test_indirect_write(struct iwl_test *tst, u32 addr,
|
||||
|
||||
if (IWL_ABS_PRPH_START <= addr &&
|
||||
addr < IWL_ABS_PRPH_START + PRPH_END) {
|
||||
/* Periphery writes can be 1-3 bytes long, or DWORDs */
|
||||
if (size < 4) {
|
||||
memcpy(&val, buf, size);
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
iwl_grab_nic_access(trans);
|
||||
iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
|
||||
(addr & 0x0000FFFF) |
|
||||
((size - 1) << 24));
|
||||
iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val);
|
||||
iwl_release_nic_access(trans);
|
||||
/* needed after consecutive writes w/o read */
|
||||
mmiowb();
|
||||
/* Periphery writes can be 1-3 bytes long, or DWORDs */
|
||||
if (size < 4) {
|
||||
memcpy(&val, buf, size);
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (!iwl_trans_grab_nic_access(trans, false)) {
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
} else {
|
||||
if (size % 4)
|
||||
return -EINVAL;
|
||||
for (i = 0; i < size; i += 4)
|
||||
iwl_write_prph(trans, addr+i,
|
||||
*(u32 *)(buf+i));
|
||||
return -EIO;
|
||||
}
|
||||
iwl_write32(trans, HBUS_TARG_PRPH_WADDR,
|
||||
(addr & 0x0000FFFF) |
|
||||
((size - 1) << 24));
|
||||
iwl_write32(trans, HBUS_TARG_PRPH_WDAT, val);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
/* needed after consecutive writes w/o read */
|
||||
mmiowb();
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
} else {
|
||||
if (size % 4)
|
||||
return -EINVAL;
|
||||
for (i = 0; i < size; i += 4)
|
||||
iwl_write_prph(trans, addr+i,
|
||||
*(u32 *)(buf+i));
|
||||
}
|
||||
} else if (iwl_test_valid_hw_addr(tst, addr)) {
|
||||
_iwl_write_targ_mem_dwords(trans, addr, buf, size / 4);
|
||||
iwl_trans_write_mem(trans, addr, buf, size / 4);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -307,6 +307,16 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r)
|
||||
#define IWL_MAX_TID_COUNT 8
|
||||
#define IWL_FRAME_LIMIT 64
|
||||
|
||||
/**
|
||||
* enum iwl_wowlan_status - WoWLAN image/device status
|
||||
* @IWL_D3_STATUS_ALIVE: firmware is still running after resume
|
||||
* @IWL_D3_STATUS_RESET: device was reset while suspended
|
||||
*/
|
||||
enum iwl_d3_status {
|
||||
IWL_D3_STATUS_ALIVE,
|
||||
IWL_D3_STATUS_RESET,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct iwl_trans_config - transport configuration
|
||||
*
|
||||
@ -321,6 +331,8 @@ static inline struct page *rxb_steal_page(struct iwl_rx_cmd_buffer *r)
|
||||
* @n_no_reclaim_cmds: # of commands in list
|
||||
* @rx_buf_size_8k: 8 kB RX buffer size needed for A-MSDUs,
|
||||
* if unset 4k will be the RX buffer size
|
||||
* @bc_table_dword: set to true if the BC table expects the byte count to be
|
||||
* in DWORD (as opposed to bytes)
|
||||
* @queue_watchdog_timeout: time (in ms) after which queues
|
||||
* are considered stuck and will trigger device restart
|
||||
* @command_names: array of command names, must be 256 entries
|
||||
@ -335,6 +347,7 @@ struct iwl_trans_config {
|
||||
int n_no_reclaim_cmds;
|
||||
|
||||
bool rx_buf_size_8k;
|
||||
bool bc_table_dword;
|
||||
unsigned int queue_watchdog_timeout;
|
||||
const char **command_names;
|
||||
};
|
||||
@ -360,9 +373,12 @@ struct iwl_trans;
|
||||
* May sleep
|
||||
* @stop_device:stops the whole device (embedded CPU put to reset)
|
||||
* May sleep
|
||||
* @wowlan_suspend: put the device into the correct mode for WoWLAN during
|
||||
* @d3_suspend: put the device into the correct mode for WoWLAN during
|
||||
* suspend. This is optional, if not implemented WoWLAN will not be
|
||||
* supported. This callback may sleep.
|
||||
* @d3_resume: resume the device after WoWLAN, enabling the opmode to
|
||||
* talk to the WoWLAN image to get its status. This is optional, if not
|
||||
* implemented WoWLAN will not be supported. This callback may sleep.
|
||||
* @send_cmd:send a host command. Must return -ERFKILL if RFkill is asserted.
|
||||
* If RFkill is asserted in the middle of a SYNC host command, it must
|
||||
* return -ERFKILL straight away.
|
||||
@ -387,20 +403,27 @@ struct iwl_trans;
|
||||
* @read32: read a u32 register at offset ofs from the BAR
|
||||
* @read_prph: read a DWORD from a periphery register
|
||||
* @write_prph: write a DWORD to a periphery register
|
||||
* @read_mem: read device's SRAM in DWORD
|
||||
* @write_mem: write device's SRAM in DWORD. If %buf is %NULL, then the memory
|
||||
* will be zeroed.
|
||||
* @configure: configure parameters required by the transport layer from
|
||||
* the op_mode. May be called several times before start_fw, can't be
|
||||
* called after that.
|
||||
* @set_pmi: set the power pmi state
|
||||
* @grab_nic_access: wake the NIC to be able to access non-HBUS regs
|
||||
* @release_nic_access: let the NIC go to sleep
|
||||
*/
|
||||
struct iwl_trans_ops {
|
||||
|
||||
int (*start_hw)(struct iwl_trans *iwl_trans);
|
||||
void (*stop_hw)(struct iwl_trans *iwl_trans, bool op_mode_leaving);
|
||||
int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw);
|
||||
int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw,
|
||||
bool run_in_rfkill);
|
||||
void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr);
|
||||
void (*stop_device)(struct iwl_trans *trans);
|
||||
|
||||
void (*wowlan_suspend)(struct iwl_trans *trans);
|
||||
void (*d3_suspend)(struct iwl_trans *trans);
|
||||
int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status);
|
||||
|
||||
int (*send_cmd)(struct iwl_trans *trans, struct iwl_host_cmd *cmd);
|
||||
|
||||
@ -424,9 +447,15 @@ struct iwl_trans_ops {
|
||||
u32 (*read32)(struct iwl_trans *trans, u32 ofs);
|
||||
u32 (*read_prph)(struct iwl_trans *trans, u32 ofs);
|
||||
void (*write_prph)(struct iwl_trans *trans, u32 ofs, u32 val);
|
||||
int (*read_mem)(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords);
|
||||
int (*write_mem)(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords);
|
||||
void (*configure)(struct iwl_trans *trans,
|
||||
const struct iwl_trans_config *trans_cfg);
|
||||
void (*set_pmi)(struct iwl_trans *trans, bool state);
|
||||
bool (*grab_nic_access)(struct iwl_trans *trans, bool silent);
|
||||
void (*release_nic_access)(struct iwl_trans *trans);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -528,13 +557,14 @@ static inline void iwl_trans_fw_alive(struct iwl_trans *trans, u32 scd_addr)
|
||||
}
|
||||
|
||||
static inline int iwl_trans_start_fw(struct iwl_trans *trans,
|
||||
const struct fw_img *fw)
|
||||
const struct fw_img *fw,
|
||||
bool run_in_rfkill)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
WARN_ON_ONCE(!trans->rx_mpdu_cmd);
|
||||
|
||||
return trans->ops->start_fw(trans, fw);
|
||||
return trans->ops->start_fw(trans, fw, run_in_rfkill);
|
||||
}
|
||||
|
||||
static inline void iwl_trans_stop_device(struct iwl_trans *trans)
|
||||
@ -546,10 +576,17 @@ static inline void iwl_trans_stop_device(struct iwl_trans *trans)
|
||||
trans->state = IWL_TRANS_NO_FW;
|
||||
}
|
||||
|
||||
static inline void iwl_trans_wowlan_suspend(struct iwl_trans *trans)
|
||||
static inline void iwl_trans_d3_suspend(struct iwl_trans *trans)
|
||||
{
|
||||
might_sleep();
|
||||
trans->ops->wowlan_suspend(trans);
|
||||
trans->ops->d3_suspend(trans);
|
||||
}
|
||||
|
||||
static inline int iwl_trans_d3_resume(struct iwl_trans *trans,
|
||||
enum iwl_d3_status *status)
|
||||
{
|
||||
might_sleep();
|
||||
return trans->ops->d3_resume(trans, status);
|
||||
}
|
||||
|
||||
static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
|
||||
@ -636,7 +673,7 @@ static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans)
|
||||
}
|
||||
|
||||
static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans,
|
||||
struct dentry *dir)
|
||||
struct dentry *dir)
|
||||
{
|
||||
return trans->ops->dbgfs_register(trans, dir);
|
||||
}
|
||||
@ -679,11 +716,57 @@ static inline void iwl_trans_write_prph(struct iwl_trans *trans, u32 ofs,
|
||||
return trans->ops->write_prph(trans, ofs, val);
|
||||
}
|
||||
|
||||
static inline int iwl_trans_read_mem(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords)
|
||||
{
|
||||
return trans->ops->read_mem(trans, addr, buf, dwords);
|
||||
}
|
||||
|
||||
#define iwl_trans_read_mem_bytes(trans, addr, buf, bufsize) \
|
||||
do { \
|
||||
if (__builtin_constant_p(bufsize)) \
|
||||
BUILD_BUG_ON((bufsize) % sizeof(u32)); \
|
||||
iwl_trans_read_mem(trans, addr, buf, (bufsize) / sizeof(u32));\
|
||||
} while (0)
|
||||
|
||||
static inline u32 iwl_trans_read_mem32(struct iwl_trans *trans, u32 addr)
|
||||
{
|
||||
u32 value;
|
||||
|
||||
if (WARN_ON(iwl_trans_read_mem(trans, addr, &value, 1)))
|
||||
return 0xa5a5a5a5;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static inline int iwl_trans_write_mem(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords)
|
||||
{
|
||||
return trans->ops->write_mem(trans, addr, buf, dwords);
|
||||
}
|
||||
|
||||
static inline u32 iwl_trans_write_mem32(struct iwl_trans *trans, u32 addr,
|
||||
u32 val)
|
||||
{
|
||||
return iwl_trans_write_mem(trans, addr, &val, 1);
|
||||
}
|
||||
|
||||
static inline void iwl_trans_set_pmi(struct iwl_trans *trans, bool state)
|
||||
{
|
||||
trans->ops->set_pmi(trans, state);
|
||||
}
|
||||
|
||||
#define iwl_trans_grab_nic_access(trans, silent) \
|
||||
__cond_lock(nic_access, \
|
||||
likely((trans)->ops->grab_nic_access(trans, silent)))
|
||||
|
||||
static inline void __releases(nic_access)
|
||||
iwl_trans_release_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
trans->ops->release_nic_access(trans);
|
||||
__release(nic_access);
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* driver (transport) register/unregister functions
|
||||
******************************************************/
|
||||
|
@ -222,8 +222,6 @@ struct iwl_txq {
|
||||
* @rx_replenish: work that will be called when buffers need to be allocated
|
||||
* @drv - pointer to iwl_drv
|
||||
* @trans: pointer to the generic transport area
|
||||
* @irq - the irq number for the device
|
||||
* @irq_requested: true when the irq has been requested
|
||||
* @scd_base_addr: scheduler sram base address in SRAM
|
||||
* @scd_bc_tbls: pointer to the byte count table of the scheduler
|
||||
* @kw: keep warm address
|
||||
@ -234,6 +232,7 @@ struct iwl_txq {
|
||||
* @status - transport specific status flags
|
||||
* @cmd_queue - command queue number
|
||||
* @rx_buf_size_8k: 8 kB RX buffer size
|
||||
* @bc_table_dword: true if the BC table expects DWORD (as opposed to bytes)
|
||||
* @rx_page_order: page order for receive buffer size
|
||||
* @wd_timeout: queue watchdog timeout (jiffies)
|
||||
*/
|
||||
@ -249,11 +248,9 @@ struct iwl_trans_pcie {
|
||||
int ict_index;
|
||||
u32 inta;
|
||||
bool use_ict;
|
||||
bool irq_requested;
|
||||
struct tasklet_struct irq_tasklet;
|
||||
struct isr_statistics isr_stats;
|
||||
|
||||
unsigned int irq;
|
||||
spinlock_t irq_lock;
|
||||
u32 inta_mask;
|
||||
u32 scd_base_addr;
|
||||
@ -279,6 +276,7 @@ struct iwl_trans_pcie {
|
||||
u8 no_reclaim_cmds[MAX_NO_RECLAIM_CMDS];
|
||||
|
||||
bool rx_buf_size_8k;
|
||||
bool bc_table_dword;
|
||||
u32 rx_page_order;
|
||||
|
||||
const char **command_names;
|
||||
@ -359,6 +357,8 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
|
||||
struct iwl_rx_cmd_buffer *rxb, int handler_status);
|
||||
void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
|
||||
struct sk_buff_head *skbs);
|
||||
void iwl_trans_pcie_tx_reset(struct iwl_trans *trans);
|
||||
|
||||
/*****************************************************
|
||||
* Error handling
|
||||
******************************************************/
|
||||
|
@ -436,7 +436,7 @@ static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
|
||||
err_rb_stts:
|
||||
dma_free_coherent(dev, sizeof(__le32) * RX_QUEUE_SIZE,
|
||||
rxq->bd, rxq->bd_dma);
|
||||
memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
|
||||
rxq->bd_dma = 0;
|
||||
rxq->bd = NULL;
|
||||
err_bd:
|
||||
return -ENOMEM;
|
||||
@ -455,6 +455,10 @@ static void iwl_pcie_rx_hw_init(struct iwl_trans *trans, struct iwl_rxq *rxq)
|
||||
|
||||
/* Stop Rx DMA */
|
||||
iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
|
||||
/* reset and flush pointers */
|
||||
iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_RBDCB_WPTR, 0);
|
||||
iwl_write_direct32(trans, FH_MEM_RCSR_CHNL0_FLUSH_RB_REQ, 0);
|
||||
iwl_write_direct32(trans, FH_RSCSR_CHNL0_RDPTR, 0);
|
||||
|
||||
/* Reset driver's Rx queue write index */
|
||||
iwl_write_direct32(trans, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
|
||||
@ -491,7 +495,6 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
struct iwl_rxq *rxq = &trans_pcie->rxq;
|
||||
|
||||
int i, err;
|
||||
unsigned long flags;
|
||||
|
||||
@ -518,6 +521,7 @@ int iwl_pcie_rx_init(struct iwl_trans *trans)
|
||||
rxq->read = rxq->write = 0;
|
||||
rxq->write_actual = 0;
|
||||
rxq->free_count = 0;
|
||||
memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts));
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
|
||||
iwl_pcie_rx_replenish(trans);
|
||||
@ -545,13 +549,15 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
|
||||
return;
|
||||
}
|
||||
|
||||
cancel_work_sync(&trans_pcie->rx_replenish);
|
||||
|
||||
spin_lock_irqsave(&rxq->lock, flags);
|
||||
iwl_pcie_rxq_free_rbs(trans);
|
||||
spin_unlock_irqrestore(&rxq->lock, flags);
|
||||
|
||||
dma_free_coherent(trans->dev, sizeof(__le32) * RX_QUEUE_SIZE,
|
||||
rxq->bd, rxq->bd_dma);
|
||||
memset(&rxq->bd_dma, 0, sizeof(rxq->bd_dma));
|
||||
rxq->bd_dma = 0;
|
||||
rxq->bd = NULL;
|
||||
|
||||
if (rxq->rb_stts)
|
||||
@ -560,7 +566,7 @@ void iwl_pcie_rx_free(struct iwl_trans *trans)
|
||||
rxq->rb_stts, rxq->rb_stts_dma);
|
||||
else
|
||||
IWL_DEBUG_INFO(trans, "Free rxq->rb_stts which is NULL\n");
|
||||
memset(&rxq->rb_stts_dma, 0, sizeof(rxq->rb_stts_dma));
|
||||
rxq->rb_stts_dma = 0;
|
||||
rxq->rb_stts = NULL;
|
||||
}
|
||||
|
||||
|
@ -75,21 +75,16 @@
|
||||
#include "iwl-agn-hw.h"
|
||||
#include "internal.h"
|
||||
|
||||
static void iwl_pcie_set_pwr_vmain(struct iwl_trans *trans)
|
||||
static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux)
|
||||
{
|
||||
/*
|
||||
* (for documentation purposes)
|
||||
* to set power to V_AUX, do:
|
||||
|
||||
if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
|
||||
iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
|
||||
~APMG_PS_CTRL_MSK_PWR_SRC);
|
||||
*/
|
||||
|
||||
iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
|
||||
~APMG_PS_CTRL_MSK_PWR_SRC);
|
||||
if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold))
|
||||
iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
|
||||
~APMG_PS_CTRL_MSK_PWR_SRC);
|
||||
else
|
||||
iwl_set_bits_mask_prph(trans, APMG_PS_CTRL_REG,
|
||||
APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
|
||||
~APMG_PS_CTRL_MSK_PWR_SRC);
|
||||
}
|
||||
|
||||
/* PCI registers */
|
||||
@ -259,7 +254,7 @@ static int iwl_pcie_nic_init(struct iwl_trans *trans)
|
||||
|
||||
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
|
||||
|
||||
iwl_pcie_set_pwr_vmain(trans);
|
||||
iwl_pcie_set_pwr(trans, false);
|
||||
|
||||
iwl_op_mode_nic_config(trans->op_mode);
|
||||
|
||||
@ -435,7 +430,7 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
|
||||
const struct fw_img *fw)
|
||||
const struct fw_img *fw, bool run_in_rfkill)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int ret;
|
||||
@ -454,7 +449,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
|
||||
/* If platform's RF_KILL switch is NOT set to KILL */
|
||||
hw_rfkill = iwl_is_rfkill_set(trans);
|
||||
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
|
||||
if (hw_rfkill)
|
||||
if (hw_rfkill && !run_in_rfkill)
|
||||
return -ERFKILL;
|
||||
|
||||
iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
|
||||
@ -534,12 +529,6 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
|
||||
|
||||
iwl_enable_rfkill_int(trans);
|
||||
|
||||
/* wait to make sure we flush pending tasklet*/
|
||||
synchronize_irq(trans_pcie->irq);
|
||||
tasklet_kill(&trans_pcie->irq_tasklet);
|
||||
|
||||
cancel_work_sync(&trans_pcie->rx_replenish);
|
||||
|
||||
/* stop and reset the on-board processor */
|
||||
iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
|
||||
|
||||
@ -551,46 +540,87 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
|
||||
clear_bit(STATUS_RFKILL, &trans_pcie->status);
|
||||
}
|
||||
|
||||
static void iwl_trans_pcie_wowlan_suspend(struct iwl_trans *trans)
|
||||
static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans)
|
||||
{
|
||||
/* let the ucode operate on its own */
|
||||
iwl_write32(trans, CSR_UCODE_DRV_GP1_SET,
|
||||
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
|
||||
|
||||
iwl_disable_interrupts(trans);
|
||||
iwl_pcie_disable_ict(trans);
|
||||
|
||||
iwl_clear_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
iwl_clear_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
/*
|
||||
* reset TX queues -- some of their registers reset during S3
|
||||
* so if we don't reset everything here the D3 image would try
|
||||
* to execute some invalid memory upon resume
|
||||
*/
|
||||
iwl_trans_pcie_tx_reset(trans);
|
||||
|
||||
iwl_pcie_set_pwr(trans, true);
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
|
||||
enum iwl_d3_status *status)
|
||||
{
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
iwl_pcie_set_pwr(trans, false);
|
||||
|
||||
val = iwl_read32(trans, CSR_RESET);
|
||||
if (val & CSR_RESET_REG_FLAG_NEVO_RESET) {
|
||||
*status = IWL_D3_STATUS_RESET;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Also enables interrupts - none will happen as the device doesn't
|
||||
* know we're waking it up, only when the opmode actually tells it
|
||||
* after this call.
|
||||
*/
|
||||
iwl_pcie_reset_ict(trans);
|
||||
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
|
||||
|
||||
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
|
||||
25000);
|
||||
if (ret) {
|
||||
IWL_ERR(trans, "Failed to resume the device (mac ready)\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
iwl_trans_pcie_tx_reset(trans);
|
||||
|
||||
ret = iwl_pcie_rx_init(trans);
|
||||
if (ret) {
|
||||
IWL_ERR(trans, "Failed to resume the device (RX reset)\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR,
|
||||
CSR_UCODE_DRV_GP1_BIT_D3_CFG_COMPLETE);
|
||||
|
||||
*status = IWL_D3_STATUS_ALIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int err;
|
||||
bool hw_rfkill;
|
||||
|
||||
trans_pcie->inta_mask = CSR_INI_SET_MASK;
|
||||
|
||||
if (!trans_pcie->irq_requested) {
|
||||
tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long))
|
||||
iwl_pcie_tasklet, (unsigned long)trans);
|
||||
|
||||
iwl_pcie_alloc_ict(trans);
|
||||
|
||||
err = request_irq(trans_pcie->irq, iwl_pcie_isr_ict,
|
||||
IRQF_SHARED, DRV_NAME, trans);
|
||||
if (err) {
|
||||
IWL_ERR(trans, "Error allocating IRQ %d\n",
|
||||
trans_pcie->irq);
|
||||
goto error;
|
||||
}
|
||||
|
||||
trans_pcie->irq_requested = true;
|
||||
}
|
||||
int err;
|
||||
|
||||
err = iwl_pcie_prepare_card_hw(trans);
|
||||
if (err) {
|
||||
IWL_ERR(trans, "Error while preparing HW: %d\n", err);
|
||||
goto err_free_irq;
|
||||
return err;
|
||||
}
|
||||
|
||||
iwl_pcie_apm_init(trans);
|
||||
@ -601,15 +631,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
|
||||
hw_rfkill = iwl_is_rfkill_set(trans);
|
||||
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
|
||||
|
||||
return err;
|
||||
|
||||
err_free_irq:
|
||||
trans_pcie->irq_requested = false;
|
||||
free_irq(trans_pcie->irq, trans);
|
||||
error:
|
||||
iwl_pcie_free_ict(trans);
|
||||
tasklet_kill(&trans_pcie->irq_tasklet);
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans,
|
||||
@ -703,19 +725,21 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
|
||||
msecs_to_jiffies(trans_cfg->queue_watchdog_timeout);
|
||||
|
||||
trans_pcie->command_names = trans_cfg->command_names;
|
||||
trans_pcie->bc_table_dword = trans_cfg->bc_table_dword;
|
||||
}
|
||||
|
||||
void iwl_trans_pcie_free(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
synchronize_irq(trans_pcie->pci_dev->irq);
|
||||
tasklet_kill(&trans_pcie->irq_tasklet);
|
||||
|
||||
iwl_pcie_tx_free(trans);
|
||||
iwl_pcie_rx_free(trans);
|
||||
|
||||
if (trans_pcie->irq_requested == true) {
|
||||
free_irq(trans_pcie->irq, trans);
|
||||
iwl_pcie_free_ict(trans);
|
||||
}
|
||||
free_irq(trans_pcie->pci_dev->irq, trans);
|
||||
iwl_pcie_free_ict(trans);
|
||||
|
||||
pci_disable_msi(trans_pcie->pci_dev);
|
||||
iounmap(trans_pcie->hw_base);
|
||||
@ -751,13 +775,112 @@ static int iwl_trans_pcie_resume(struct iwl_trans *trans)
|
||||
hw_rfkill = iwl_is_rfkill_set(trans);
|
||||
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
|
||||
|
||||
if (!hw_rfkill)
|
||||
iwl_enable_interrupts(trans);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent)
|
||||
{
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&trans->reg_lock);
|
||||
|
||||
/* this bit wakes up the NIC */
|
||||
__iwl_set_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
|
||||
/*
|
||||
* These bits say the device is running, and should keep running for
|
||||
* at least a short while (at least as long as MAC_ACCESS_REQ stays 1),
|
||||
* but they do not indicate that embedded SRAM is restored yet;
|
||||
* 3945 and 4965 have volatile SRAM, and must save/restore contents
|
||||
* to/from host DRAM when sleeping/waking for power-saving.
|
||||
* Each direction takes approximately 1/4 millisecond; with this
|
||||
* overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a
|
||||
* series of register accesses are expected (e.g. reading Event Log),
|
||||
* to keep device from sleeping.
|
||||
*
|
||||
* CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that
|
||||
* SRAM is okay/restored. We don't check that here because this call
|
||||
* is just for hardware register access; but GP1 MAC_SLEEP check is a
|
||||
* good idea before accessing 3945/4965 SRAM (e.g. reading Event Log).
|
||||
*
|
||||
* 5000 series and later (including 1000 series) have non-volatile SRAM,
|
||||
* and do not save/restore SRAM when power cycling.
|
||||
*/
|
||||
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
|
||||
(CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
|
||||
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
|
||||
if (unlikely(ret < 0)) {
|
||||
iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
|
||||
if (!silent) {
|
||||
u32 val = iwl_read32(trans, CSR_GP_CNTRL);
|
||||
WARN_ONCE(1,
|
||||
"Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n",
|
||||
val);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
lockdep_assert_held(&trans->reg_lock);
|
||||
__iwl_clear_bit(trans, CSR_GP_CNTRL,
|
||||
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
|
||||
/*
|
||||
* Above we read the CSR_GP_CNTRL register, which will flush
|
||||
* any previous writes, but we need the write that clears the
|
||||
* MAC_ACCESS_REQ bit to be performed before any other writes
|
||||
* scheduled on different CPUs (after we drop reg_lock).
|
||||
*/
|
||||
mmiowb();
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_read_mem(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords)
|
||||
{
|
||||
unsigned long flags;
|
||||
int offs, ret = 0;
|
||||
u32 *vals = buf;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
iwl_write32(trans, HBUS_TARG_MEM_RADDR, addr);
|
||||
for (offs = 0; offs < dwords; offs++)
|
||||
vals[offs] = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
} else {
|
||||
ret = -EBUSY;
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iwl_trans_pcie_write_mem(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords)
|
||||
{
|
||||
unsigned long flags;
|
||||
int offs, ret = 0;
|
||||
u32 *vals = buf;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
if (iwl_trans_grab_nic_access(trans, false)) {
|
||||
iwl_write32(trans, HBUS_TARG_MEM_WADDR, addr);
|
||||
for (offs = 0; offs < dwords; offs++)
|
||||
iwl_write32(trans, HBUS_TARG_MEM_WDAT,
|
||||
vals ? vals[offs] : 0);
|
||||
iwl_trans_release_nic_access(trans);
|
||||
} else {
|
||||
ret = -EBUSY;
|
||||
}
|
||||
spin_unlock_irqrestore(&trans->reg_lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define IWL_FLUSH_WAIT_MS 2000
|
||||
|
||||
static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans)
|
||||
@ -767,6 +890,8 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans)
|
||||
struct iwl_queue *q;
|
||||
int cnt;
|
||||
unsigned long now = jiffies;
|
||||
u32 scd_sram_addr;
|
||||
u8 buf[16];
|
||||
int ret = 0;
|
||||
|
||||
/* waiting for all the tx frames complete might take a while */
|
||||
@ -780,11 +905,50 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans)
|
||||
msleep(1);
|
||||
|
||||
if (q->read_ptr != q->write_ptr) {
|
||||
IWL_ERR(trans, "fail to flush all tx fifo queues\n");
|
||||
IWL_ERR(trans,
|
||||
"fail to flush all tx fifo queues Q %d\n", cnt);
|
||||
ret = -ETIMEDOUT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
return 0;
|
||||
|
||||
IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n",
|
||||
txq->q.read_ptr, txq->q.write_ptr);
|
||||
|
||||
scd_sram_addr = trans_pcie->scd_base_addr +
|
||||
SCD_TX_STTS_QUEUE_OFFSET(txq->q.id);
|
||||
iwl_trans_read_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf));
|
||||
|
||||
iwl_print_hex_error(trans, buf, sizeof(buf));
|
||||
|
||||
for (cnt = 0; cnt < FH_TCSR_CHNL_NUM; cnt++)
|
||||
IWL_ERR(trans, "FH TRBs(%d) = 0x%08x\n", cnt,
|
||||
iwl_read_direct32(trans, FH_TX_TRB_REG(cnt)));
|
||||
|
||||
for (cnt = 0; cnt < trans->cfg->base_params->num_of_queues; cnt++) {
|
||||
u32 status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(cnt));
|
||||
u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7;
|
||||
bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE));
|
||||
u32 tbl_dw =
|
||||
iwl_trans_read_mem32(trans, trans_pcie->scd_base_addr +
|
||||
SCD_TRANS_TBL_OFFSET_QUEUE(cnt));
|
||||
|
||||
if (cnt & 0x1)
|
||||
tbl_dw = (tbl_dw & 0xFFFF0000) >> 16;
|
||||
else
|
||||
tbl_dw = tbl_dw & 0x0000FFFF;
|
||||
|
||||
IWL_ERR(trans,
|
||||
"Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n",
|
||||
cnt, active ? "" : "in", fifo, tbl_dw,
|
||||
iwl_read_prph(trans,
|
||||
SCD_QUEUE_RDPTR(cnt)) & (txq->q.n_bd - 1),
|
||||
iwl_read_prph(trans, SCD_QUEUE_WRPTR(cnt)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1212,7 +1376,8 @@ static const struct iwl_trans_ops trans_ops_pcie = {
|
||||
.start_fw = iwl_trans_pcie_start_fw,
|
||||
.stop_device = iwl_trans_pcie_stop_device,
|
||||
|
||||
.wowlan_suspend = iwl_trans_pcie_wowlan_suspend,
|
||||
.d3_suspend = iwl_trans_pcie_d3_suspend,
|
||||
.d3_resume = iwl_trans_pcie_d3_resume,
|
||||
|
||||
.send_cmd = iwl_trans_pcie_send_hcmd,
|
||||
|
||||
@ -1235,8 +1400,12 @@ static const struct iwl_trans_ops trans_ops_pcie = {
|
||||
.read32 = iwl_trans_pcie_read32,
|
||||
.read_prph = iwl_trans_pcie_read_prph,
|
||||
.write_prph = iwl_trans_pcie_write_prph,
|
||||
.read_mem = iwl_trans_pcie_read_mem,
|
||||
.write_mem = iwl_trans_pcie_write_mem,
|
||||
.configure = iwl_trans_pcie_configure,
|
||||
.set_pmi = iwl_trans_pcie_set_pmi,
|
||||
.grab_nic_access = iwl_trans_pcie_grab_nic_access,
|
||||
.release_nic_access = iwl_trans_pcie_release_nic_access
|
||||
};
|
||||
|
||||
struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
@ -1318,7 +1487,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
}
|
||||
|
||||
trans->dev = &pdev->dev;
|
||||
trans_pcie->irq = pdev->irq;
|
||||
trans_pcie->pci_dev = pdev;
|
||||
trans->hw_rev = iwl_read32(trans, CSR_HW_REV);
|
||||
trans->hw_id = (pdev->device << 16) + pdev->subsystem_device;
|
||||
@ -1344,8 +1512,27 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
|
||||
if (!trans->dev_cmd_pool)
|
||||
goto out_pci_disable_msi;
|
||||
|
||||
trans_pcie->inta_mask = CSR_INI_SET_MASK;
|
||||
|
||||
tasklet_init(&trans_pcie->irq_tasklet, (void (*)(unsigned long))
|
||||
iwl_pcie_tasklet, (unsigned long)trans);
|
||||
|
||||
if (iwl_pcie_alloc_ict(trans))
|
||||
goto out_free_cmd_pool;
|
||||
|
||||
err = request_irq(pdev->irq, iwl_pcie_isr_ict,
|
||||
IRQF_SHARED, DRV_NAME, trans);
|
||||
if (err) {
|
||||
IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq);
|
||||
goto out_free_ict;
|
||||
}
|
||||
|
||||
return trans;
|
||||
|
||||
out_free_ict:
|
||||
iwl_pcie_free_ict(trans);
|
||||
out_free_cmd_pool:
|
||||
kmem_cache_destroy(trans->dev_cmd_pool);
|
||||
out_pci_disable_msi:
|
||||
pci_disable_msi(pdev);
|
||||
out_pci_release_regions:
|
||||
|
@ -160,7 +160,7 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
|
||||
IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n",
|
||||
txq->q.read_ptr, txq->q.write_ptr);
|
||||
|
||||
iwl_read_targ_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf));
|
||||
iwl_trans_read_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf));
|
||||
|
||||
iwl_print_hex_error(trans, buf, sizeof(buf));
|
||||
|
||||
@ -173,9 +173,9 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
|
||||
u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7;
|
||||
bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE));
|
||||
u32 tbl_dw =
|
||||
iwl_read_targ_mem(trans,
|
||||
trans_pcie->scd_base_addr +
|
||||
SCD_TRANS_TBL_OFFSET_QUEUE(i));
|
||||
iwl_trans_read_mem32(trans,
|
||||
trans_pcie->scd_base_addr +
|
||||
SCD_TRANS_TBL_OFFSET_QUEUE(i));
|
||||
|
||||
if (i & 0x1)
|
||||
tbl_dw = (tbl_dw & 0xFFFF0000) >> 16;
|
||||
@ -237,7 +237,10 @@ static void iwl_pcie_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
|
||||
break;
|
||||
}
|
||||
|
||||
bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12));
|
||||
if (trans_pcie->bc_table_dword)
|
||||
len = DIV_ROUND_UP(len, 4);
|
||||
|
||||
bc_ent = cpu_to_le16(len | (sta_id << 12));
|
||||
|
||||
scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
|
||||
|
||||
@ -306,6 +309,9 @@ void iwl_pcie_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq)
|
||||
return;
|
||||
}
|
||||
|
||||
IWL_DEBUG_TX(trans, "Q:%d WR: 0x%x\n", txq_id,
|
||||
txq->q.write_ptr);
|
||||
|
||||
iwl_write_direct32(trans, HBUS_TARG_WRPTR,
|
||||
txq->q.write_ptr | (txq_id << 8));
|
||||
|
||||
@ -612,7 +618,7 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
|
||||
if (txq->q.n_bd) {
|
||||
dma_free_coherent(dev, sizeof(struct iwl_tfd) *
|
||||
txq->q.n_bd, txq->tfds, txq->q.dma_addr);
|
||||
memset(&txq->q.dma_addr, 0, sizeof(txq->q.dma_addr));
|
||||
txq->q.dma_addr = 0;
|
||||
}
|
||||
|
||||
kfree(txq->entries);
|
||||
@ -638,9 +644,11 @@ static void iwl_pcie_txq_set_sched(struct iwl_trans *trans, u32 mask)
|
||||
void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
u32 a;
|
||||
int nq = trans->cfg->base_params->num_of_queues;
|
||||
int chan;
|
||||
u32 reg_val;
|
||||
int clear_dwords = (SCD_TRANS_TBL_OFFSET_QUEUE(nq) -
|
||||
SCD_CONTEXT_MEM_LOWER_BOUND) / sizeof(u32);
|
||||
|
||||
/* make sure all queue are not stopped/used */
|
||||
memset(trans_pcie->queue_stopped, 0, sizeof(trans_pcie->queue_stopped));
|
||||
@ -652,20 +660,10 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
|
||||
WARN_ON(scd_base_addr != 0 &&
|
||||
scd_base_addr != trans_pcie->scd_base_addr);
|
||||
|
||||
a = trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_LOWER_BOUND;
|
||||
/* reset conext data memory */
|
||||
for (; a < trans_pcie->scd_base_addr + SCD_CONTEXT_MEM_UPPER_BOUND;
|
||||
a += 4)
|
||||
iwl_write_targ_mem(trans, a, 0);
|
||||
/* reset tx status memory */
|
||||
for (; a < trans_pcie->scd_base_addr + SCD_TX_STTS_MEM_UPPER_BOUND;
|
||||
a += 4)
|
||||
iwl_write_targ_mem(trans, a, 0);
|
||||
for (; a < trans_pcie->scd_base_addr +
|
||||
SCD_TRANS_TBL_OFFSET_QUEUE(
|
||||
trans->cfg->base_params->num_of_queues);
|
||||
a += 4)
|
||||
iwl_write_targ_mem(trans, a, 0);
|
||||
/* reset context data, TX status and translation data */
|
||||
iwl_trans_write_mem(trans, trans_pcie->scd_base_addr +
|
||||
SCD_CONTEXT_MEM_LOWER_BOUND,
|
||||
NULL, clear_dwords);
|
||||
|
||||
iwl_write_prph(trans, SCD_DRAM_BASE_ADDR,
|
||||
trans_pcie->scd_bc_tbls.dma >> 10);
|
||||
@ -697,6 +695,29 @@ void iwl_pcie_tx_start(struct iwl_trans *trans, u32 scd_base_addr)
|
||||
APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
|
||||
}
|
||||
|
||||
void iwl_trans_pcie_tx_reset(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
int txq_id;
|
||||
|
||||
for (txq_id = 0; txq_id < trans->cfg->base_params->num_of_queues;
|
||||
txq_id++) {
|
||||
struct iwl_txq *txq = &trans_pcie->txq[txq_id];
|
||||
|
||||
iwl_write_direct32(trans, FH_MEM_CBBC_QUEUE(txq_id),
|
||||
txq->q.dma_addr >> 8);
|
||||
iwl_pcie_txq_unmap(trans, txq_id);
|
||||
txq->q.read_ptr = 0;
|
||||
txq->q.write_ptr = 0;
|
||||
}
|
||||
|
||||
/* Tell NIC where to find the "keep warm" buffer */
|
||||
iwl_write_direct32(trans, FH_KW_MEM_ADDR_REG,
|
||||
trans_pcie->kw.dma >> 4);
|
||||
|
||||
iwl_pcie_tx_start(trans, trans_pcie->scd_base_addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* iwl_pcie_tx_stop - Stop all Tx DMA channels
|
||||
*/
|
||||
@ -1002,14 +1023,14 @@ static int iwl_pcie_txq_set_ratid_map(struct iwl_trans *trans, u16 ra_tid,
|
||||
tbl_dw_addr = trans_pcie->scd_base_addr +
|
||||
SCD_TRANS_TBL_OFFSET_QUEUE(txq_id);
|
||||
|
||||
tbl_dw = iwl_read_targ_mem(trans, tbl_dw_addr);
|
||||
tbl_dw = iwl_trans_read_mem32(trans, tbl_dw_addr);
|
||||
|
||||
if (txq_id & 0x1)
|
||||
tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
|
||||
else
|
||||
tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
|
||||
|
||||
iwl_write_targ_mem(trans, tbl_dw_addr, tbl_dw);
|
||||
iwl_trans_write_mem32(trans, tbl_dw_addr, tbl_dw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1068,9 +1089,9 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
|
||||
iwl_write_prph(trans, SCD_QUEUE_RDPTR(txq_id), ssn);
|
||||
|
||||
/* Set up Tx window size and frame limit for this queue */
|
||||
iwl_write_targ_mem(trans, trans_pcie->scd_base_addr +
|
||||
iwl_trans_write_mem32(trans, trans_pcie->scd_base_addr +
|
||||
SCD_CONTEXT_QUEUE_OFFSET(txq_id), 0);
|
||||
iwl_write_targ_mem(trans, trans_pcie->scd_base_addr +
|
||||
iwl_trans_write_mem32(trans, trans_pcie->scd_base_addr +
|
||||
SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
|
||||
((frame_limit << SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) &
|
||||
SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) |
|
||||
@ -1101,8 +1122,8 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
|
||||
|
||||
iwl_pcie_txq_set_inactive(trans, txq_id);
|
||||
|
||||
_iwl_write_targ_mem_dwords(trans, stts_addr,
|
||||
zero_val, ARRAY_SIZE(zero_val));
|
||||
iwl_trans_write_mem(trans, stts_addr, (void *)zero_val,
|
||||
ARRAY_SIZE(zero_val));
|
||||
|
||||
iwl_pcie_txq_unmap(trans, txq_id);
|
||||
|
||||
@ -1642,10 +1663,6 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||
tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
|
||||
tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
|
||||
|
||||
IWL_DEBUG_TX(trans, "sequence nr = 0X%x\n",
|
||||
le16_to_cpu(dev_cmd->hdr.sequence));
|
||||
IWL_DEBUG_TX(trans, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
|
||||
|
||||
/* Set up entry for this TFD in Tx byte-count array */
|
||||
iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len));
|
||||
|
||||
|
@ -2132,6 +2132,21 @@ static void lbs_cfg_set_regulatory_hint(struct lbs_private *priv)
|
||||
lbs_deb_leave(LBS_DEB_CFG80211);
|
||||
}
|
||||
|
||||
static void lbs_reg_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct lbs_private *priv = wiphy_priv(wiphy);
|
||||
|
||||
lbs_deb_enter_args(LBS_DEB_CFG80211, "cfg80211 regulatory domain "
|
||||
"callback for domain %c%c\n", request->alpha2[0],
|
||||
request->alpha2[1]);
|
||||
|
||||
memcpy(priv->country_code, request->alpha2, sizeof(request->alpha2));
|
||||
if (lbs_iface_active(priv))
|
||||
lbs_set_11d_domain_info(priv);
|
||||
|
||||
lbs_deb_leave(LBS_DEB_CFG80211);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function get's called after lbs_setup_firmware() determined the
|
||||
@ -2184,24 +2199,6 @@ int lbs_cfg_register(struct lbs_private *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int lbs_reg_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request)
|
||||
{
|
||||
struct lbs_private *priv = wiphy_priv(wiphy);
|
||||
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]);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void lbs_scan_deinit(struct lbs_private *priv)
|
||||
{
|
||||
lbs_deb_enter(LBS_DEB_CFG80211);
|
||||
|
@ -10,9 +10,6 @@ struct wireless_dev *lbs_cfg_alloc(struct device *dev);
|
||||
int lbs_cfg_register(struct lbs_private *priv);
|
||||
void lbs_cfg_free(struct lbs_private *priv);
|
||||
|
||||
int lbs_reg_notifier(struct wiphy *wiphy,
|
||||
struct regulatory_request *request);
|
||||
|
||||
void lbs_send_disconnect_notification(struct lbs_private *priv);
|
||||
void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
|
||||
|
||||
|
@ -48,6 +48,10 @@ static int channels = 1;
|
||||
module_param(channels, int, 0444);
|
||||
MODULE_PARM_DESC(channels, "Number of concurrent channels");
|
||||
|
||||
static bool paged_rx = false;
|
||||
module_param(paged_rx, bool, 0644);
|
||||
MODULE_PARM_DESC(paged_rx, "Use paged SKBs for RX instead of linear ones");
|
||||
|
||||
/**
|
||||
* enum hwsim_regtest - the type of regulatory tests we offer
|
||||
*
|
||||
@ -333,11 +337,11 @@ struct mac80211_hwsim_data {
|
||||
int scan_chan_idx;
|
||||
|
||||
struct ieee80211_channel *channel;
|
||||
unsigned long beacon_int; /* in jiffies unit */
|
||||
u64 beacon_int /* beacon interval in us */;
|
||||
unsigned int rx_filter;
|
||||
bool started, idle, scanning;
|
||||
struct mutex mutex;
|
||||
struct timer_list beacon_timer;
|
||||
struct tasklet_hrtimer beacon_timer;
|
||||
enum ps_mode {
|
||||
PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL
|
||||
} ps;
|
||||
@ -357,7 +361,10 @@ struct mac80211_hwsim_data {
|
||||
int power_level;
|
||||
|
||||
/* difference between this hw's clock and the real clock, in usecs */
|
||||
u64 tsf_offset;
|
||||
s64 tsf_offset;
|
||||
s64 bcn_delta;
|
||||
/* absolute beacon transmission time. Used to cover up "tx" delay. */
|
||||
u64 abs_bcn_ts;
|
||||
};
|
||||
|
||||
|
||||
@ -405,15 +412,19 @@ static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb,
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
|
||||
static inline u64 mac80211_hwsim_get_tsf_raw(void)
|
||||
{
|
||||
return ktime_to_us(ktime_get_real());
|
||||
}
|
||||
|
||||
static __le64 __mac80211_hwsim_get_tsf(struct mac80211_hwsim_data *data)
|
||||
{
|
||||
struct timeval tv = ktime_to_timeval(ktime_get_real());
|
||||
u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
|
||||
u64 now = mac80211_hwsim_get_tsf_raw();
|
||||
return cpu_to_le64(now + data->tsf_offset);
|
||||
}
|
||||
|
||||
static u64 mac80211_hwsim_get_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct mac80211_hwsim_data *data = hw->priv;
|
||||
return le64_to_cpu(__mac80211_hwsim_get_tsf(data));
|
||||
@ -423,9 +434,13 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, u64 tsf)
|
||||
{
|
||||
struct mac80211_hwsim_data *data = hw->priv;
|
||||
struct timeval tv = ktime_to_timeval(ktime_get_real());
|
||||
u64 now = tv.tv_sec * USEC_PER_SEC + tv.tv_usec;
|
||||
data->tsf_offset = tsf - now;
|
||||
u64 now = mac80211_hwsim_get_tsf(hw, vif);
|
||||
u32 bcn_int = data->beacon_int;
|
||||
s64 delta = tsf - now;
|
||||
|
||||
data->tsf_offset += delta;
|
||||
/* adjust after beaconing with new timestamp at old TBTT */
|
||||
data->bcn_delta = do_div(delta, bcn_int);
|
||||
}
|
||||
|
||||
static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
|
||||
@ -696,7 +711,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_rx_status rx_status;
|
||||
struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info);
|
||||
u64 now;
|
||||
|
||||
memset(&rx_status, 0, sizeof(rx_status));
|
||||
rx_status.flag |= RX_FLAG_MACTIME_START;
|
||||
@ -722,11 +737,23 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
|
||||
secpath_reset(skb);
|
||||
nf_reset(skb);
|
||||
|
||||
/*
|
||||
* Get absolute mactime here so all HWs RX at the "same time", and
|
||||
* absolute TX time for beacon mactime so the timestamp matches.
|
||||
* Giving beacons a different mactime than non-beacons looks messy, but
|
||||
* it helps the Toffset be exact and a ~10us mactime discrepancy
|
||||
* probably doesn't really matter.
|
||||
*/
|
||||
if (ieee80211_is_beacon(hdr->frame_control) ||
|
||||
ieee80211_is_probe_resp(hdr->frame_control))
|
||||
now = data->abs_bcn_ts;
|
||||
else
|
||||
now = mac80211_hwsim_get_tsf_raw();
|
||||
|
||||
/* Copy skb to all enabled radios that are on the current frequency */
|
||||
spin_lock(&hwsim_radio_lock);
|
||||
list_for_each_entry(data2, &hwsim_radios, list) {
|
||||
struct sk_buff *nskb;
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
struct tx_iter_data tx_iter_data = {
|
||||
.receive = false,
|
||||
.channel = chan,
|
||||
@ -755,24 +782,30 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
|
||||
* reserve some space for our vendor and the normal
|
||||
* radiotap header, since we're copying anyway
|
||||
*/
|
||||
nskb = skb_copy_expand(skb, 64, 0, GFP_ATOMIC);
|
||||
if (nskb == NULL)
|
||||
continue;
|
||||
if (skb->len < PAGE_SIZE && paged_rx) {
|
||||
struct page *page = alloc_page(GFP_ATOMIC);
|
||||
|
||||
if (!page)
|
||||
continue;
|
||||
|
||||
nskb = dev_alloc_skb(128);
|
||||
if (!nskb) {
|
||||
__free_page(page);
|
||||
continue;
|
||||
}
|
||||
|
||||
memcpy(page_address(page), skb->data, skb->len);
|
||||
skb_add_rx_frag(nskb, 0, page, 0, skb->len, skb->len);
|
||||
} else {
|
||||
nskb = skb_copy(skb, GFP_ATOMIC);
|
||||
if (!nskb)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mac80211_hwsim_addr_match(data2, hdr->addr1))
|
||||
ack = true;
|
||||
|
||||
/* set bcn timestamp relative to receiver mactime */
|
||||
rx_status.mactime =
|
||||
le64_to_cpu(__mac80211_hwsim_get_tsf(data2));
|
||||
mgmt = (struct ieee80211_mgmt *) nskb->data;
|
||||
if (ieee80211_is_beacon(mgmt->frame_control) ||
|
||||
ieee80211_is_probe_resp(mgmt->frame_control))
|
||||
mgmt->u.beacon.timestamp = cpu_to_le64(
|
||||
rx_status.mactime +
|
||||
(data->tsf_offset - data2->tsf_offset) +
|
||||
24 * 8 * 10 / txrate->bitrate);
|
||||
|
||||
rx_status.mactime = now + data2->tsf_offset;
|
||||
#if 0
|
||||
/*
|
||||
* Don't enable this code by default as the OUI 00:00:00
|
||||
@ -896,7 +929,7 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct mac80211_hwsim_data *data = hw->priv;
|
||||
data->started = false;
|
||||
del_timer(&data->beacon_timer);
|
||||
tasklet_hrtimer_cancel(&data->beacon_timer);
|
||||
wiphy_debug(hw->wiphy, "%s\n", __func__);
|
||||
}
|
||||
|
||||
@ -962,7 +995,11 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
|
||||
static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
struct ieee80211_hw *hw = arg;
|
||||
struct mac80211_hwsim_data *data = arg;
|
||||
struct ieee80211_hw *hw = data->hw;
|
||||
struct ieee80211_tx_info *info;
|
||||
struct ieee80211_rate *txrate;
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
struct sk_buff *skb;
|
||||
|
||||
hwsim_check_magic(vif);
|
||||
@ -975,26 +1012,48 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
|
||||
skb = ieee80211_beacon_get(hw, vif);
|
||||
if (skb == NULL)
|
||||
return;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
txrate = ieee80211_get_tx_rate(hw, info);
|
||||
|
||||
mgmt = (struct ieee80211_mgmt *) skb->data;
|
||||
/* fake header transmission time */
|
||||
data->abs_bcn_ts = mac80211_hwsim_get_tsf_raw();
|
||||
mgmt->u.beacon.timestamp = cpu_to_le64(data->abs_bcn_ts +
|
||||
data->tsf_offset +
|
||||
24 * 8 * 10 / txrate->bitrate);
|
||||
|
||||
mac80211_hwsim_tx_frame(hw, skb,
|
||||
rcu_dereference(vif->chanctx_conf)->def.chan);
|
||||
}
|
||||
|
||||
|
||||
static void mac80211_hwsim_beacon(unsigned long arg)
|
||||
static enum hrtimer_restart
|
||||
mac80211_hwsim_beacon(struct hrtimer *timer)
|
||||
{
|
||||
struct ieee80211_hw *hw = (struct ieee80211_hw *) arg;
|
||||
struct mac80211_hwsim_data *data = hw->priv;
|
||||
struct mac80211_hwsim_data *data =
|
||||
container_of(timer, struct mac80211_hwsim_data,
|
||||
beacon_timer.timer);
|
||||
struct ieee80211_hw *hw = data->hw;
|
||||
u64 bcn_int = data->beacon_int;
|
||||
ktime_t next_bcn;
|
||||
|
||||
if (!data->started)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
ieee80211_iterate_active_interfaces_atomic(
|
||||
hw, IEEE80211_IFACE_ITER_NORMAL,
|
||||
mac80211_hwsim_beacon_tx, hw);
|
||||
mac80211_hwsim_beacon_tx, data);
|
||||
|
||||
data->beacon_timer.expires = jiffies + data->beacon_int;
|
||||
add_timer(&data->beacon_timer);
|
||||
/* beacon at new TBTT + beacon interval */
|
||||
if (data->bcn_delta) {
|
||||
bcn_int -= data->bcn_delta;
|
||||
data->bcn_delta = 0;
|
||||
}
|
||||
|
||||
next_bcn = ktime_add(hrtimer_get_expires(timer),
|
||||
ns_to_ktime(bcn_int * 1000));
|
||||
tasklet_hrtimer_start(&data->beacon_timer, next_bcn, HRTIMER_MODE_ABS);
|
||||
out:
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
static const char *hwsim_chantypes[] = {
|
||||
@ -1032,9 +1091,16 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
|
||||
|
||||
data->power_level = conf->power_level;
|
||||
if (!data->started || !data->beacon_int)
|
||||
del_timer(&data->beacon_timer);
|
||||
else
|
||||
mod_timer(&data->beacon_timer, jiffies + data->beacon_int);
|
||||
tasklet_hrtimer_cancel(&data->beacon_timer);
|
||||
else if (!hrtimer_is_queued(&data->beacon_timer.timer)) {
|
||||
u64 tsf = mac80211_hwsim_get_tsf(hw, NULL);
|
||||
u32 bcn_int = data->beacon_int;
|
||||
u64 until_tbtt = bcn_int - do_div(tsf, bcn_int);
|
||||
|
||||
tasklet_hrtimer_start(&data->beacon_timer,
|
||||
ns_to_ktime(until_tbtt * 1000),
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1084,12 +1150,26 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_INT) {
|
||||
wiphy_debug(hw->wiphy, " BCNINT: %d\n", info->beacon_int);
|
||||
data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000;
|
||||
if (WARN_ON(!data->beacon_int))
|
||||
data->beacon_int = 1;
|
||||
if (data->started)
|
||||
mod_timer(&data->beacon_timer,
|
||||
jiffies + data->beacon_int);
|
||||
data->beacon_int = info->beacon_int * 1024;
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED) {
|
||||
wiphy_debug(hw->wiphy, " BCN EN: %d\n", info->enable_beacon);
|
||||
if (data->started &&
|
||||
!hrtimer_is_queued(&data->beacon_timer.timer) &&
|
||||
info->enable_beacon) {
|
||||
u64 tsf, until_tbtt;
|
||||
u32 bcn_int;
|
||||
if (WARN_ON(!data->beacon_int))
|
||||
data->beacon_int = 1000 * 1024;
|
||||
tsf = mac80211_hwsim_get_tsf(hw, vif);
|
||||
bcn_int = data->beacon_int;
|
||||
until_tbtt = bcn_int - do_div(tsf, bcn_int);
|
||||
tasklet_hrtimer_start(&data->beacon_timer,
|
||||
ns_to_ktime(until_tbtt * 1000),
|
||||
HRTIMER_MODE_REL);
|
||||
} else if (!info->enable_beacon)
|
||||
tasklet_hrtimer_cancel(&data->beacon_timer);
|
||||
}
|
||||
|
||||
if (changed & BSS_CHANGED_ERP_CTS_PROT) {
|
||||
@ -1292,7 +1372,9 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
|
||||
case IEEE80211_AMPDU_TX_START:
|
||||
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_STOP:
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
|
||||
break;
|
||||
case IEEE80211_AMPDU_TX_OPERATIONAL:
|
||||
@ -2370,8 +2452,9 @@ static int __init init_mac80211_hwsim(void)
|
||||
data->debugfs, data,
|
||||
&hwsim_fops_group);
|
||||
|
||||
setup_timer(&data->beacon_timer, mac80211_hwsim_beacon,
|
||||
(unsigned long) hw);
|
||||
tasklet_hrtimer_init(&data->beacon_timer,
|
||||
mac80211_hwsim_beacon,
|
||||
CLOCK_REALTIME, HRTIMER_MODE_ABS);
|
||||
|
||||
list_add_tail(&data->list, &hwsim_radios);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user