提交 a4b4a2b7 编写于 作者: D David S. Miller

Merge tag 'master-2014-10-02' of...

Merge tag 'master-2014-10-02' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next

John W. Linville says:

====================
pull request: wireless-next 2014-10-03

Please pull tihs batch of updates intended for the 3.18 stream!

For the iwlwifi bits, Emmanuel says:

"I have here a few things that depend on the latest mac80211's changes:
RRM, TPC, Quiet Period etc...  Eyal keeps improving our rate control
and we have a new device ID. This last patch should probably have
gone to wireless.git, but at that stage, I preferred to send it to
-next and CC stable."

For (most of) the Atheros bits, Kalle says:

"The only new feature is testmode support from me. Ben added a new method
to crash the firmware with an assert for debug purposes. As usual, we
have lots of smaller fixes from Michal. Matteo fixed a Kconfig
dependency with debugfs. I fixed some warnings recently added to
checkpatch."

For the NFC bits, Samuel says:

"We've had major updates for TI and ST Microelectronics drivers, and a
few NCI related changes.

For TI's trf7970a driver:

- Target mode support for trf7970a
- Suspend/resume support for trf7970a
- DT properties additions to handle different quirks
- A bunch of fixes for smartphone IOP related issues

For ST Microelectronics' ST21NFCA and ST21NFCB drivers:

- ISO15693 support for st21nfcb
- checkpatch and sparse related warning fixes
- Code cleanups and a few minor fixes

Finally, Marvell added ISO15693 support to the NCI stack, together with a
couple of NCI fixes."

For the Bluetooth bits, Johan says:

"This 3.18 pull request replaces the one I did on Monday ("bluetooth-next
2014-09-22", which hasn't been pulled yet). The additions since the last
request are:

 - SCO connection fix for devices not supporting eSCO
 - Cleanups regarding the SCO establishment logic
 - Remove unnecessary return value from logging functions
 - Header compression fix for 6lowpan
 - Cleanups to the ieee802154/mrf24j40 driver

Here's a copy from previous request that this one replaces:

'
Here are some more patches for 3.18. They include various fixes to the
btusb HCI driver, a fix for LE SMP, as well as adding Jukka to the
MAINTAINERS file for generic 6LoWPAN (as requested by Alexander Aring).

I've held on to this pull request a bit since we were waiting for a SCO
related fix to get sorted out first. However, since the merge window is
getting closer I decided not to wait for it. If we do get the fix sorted
out there'll probably be a second small pull request later this week.
'"

And,

"Unless 3.17 gets delayed this will probably be our last -next pull request for
3.18. We've got:

  - New Marvell hardware supportr
  - Multicast support for 6lowpan
  - Several of 6lowpan fixes & cleanups
  - Fix for a (false-positive) lockdep warning in L2CAP
  - Minor btusb cleanup"

On top of all that comes the usual sort of updates to ath5k, ath9k,
ath10k, brcmfmac, mwifiex, and wil6210.  This time around there are
also a number of rtlwifi updates to enable some new hardware and
to reconcile the in-kernel drivers with some newer releases of the
Realtek vendor drivers.  Also of note is some device tree work for
the bcma bus.

Please let me know if there are problems!
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
Driver for ARM AXI Bus with Broadcom Plugins (bcma)
Required properties:
- compatible : brcm,bus-axi
- reg : iomem address range of chipcommon core
The cores on the AXI bus are automatically detected by bcma with the
memory ranges they are using and they get registered afterwards.
The top-level axi bus may contain children representing attached cores
(devices). This is needed since some hardware details can't be auto
detected (e.g. IRQ numbers). Also some of the cores may be responsible
for extra things, e.g. ChipCommon providing access to the GPIO chip.
Example:
axi@18000000 {
compatible = "brcm,bus-axi";
reg = <0x18000000 0x1000>;
ranges = <0x00000000 0x18000000 0x00100000>;
#address-cells = <1>;
#size-cells = <1>;
chipcommon {
reg = <0x00000000 0x1000>;
gpio-controller;
#gpio-cells = <2>;
};
};
...@@ -26,7 +26,7 @@ Example (for ARM-based BeagleBoard xM with ST21NFCB on I2C2): ...@@ -26,7 +26,7 @@ Example (for ARM-based BeagleBoard xM with ST21NFCB on I2C2):
clock-frequency = <400000>; clock-frequency = <400000>;
interrupt-parent = <&gpio5>; interrupt-parent = <&gpio5>;
interrupts = <2 IRQ_TYPE_LEVEL_LOW>; interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
reset-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>; reset-gpios = <&gpio5 29 GPIO_ACTIVE_HIGH>;
}; };
......
...@@ -13,6 +13,11 @@ Optional SoC Specific Properties: ...@@ -13,6 +13,11 @@ Optional SoC Specific Properties:
- pinctrl-names: Contains only one value - "default". - pinctrl-names: Contains only one value - "default".
- pintctrl-0: Specifies the pin control groups used for this controller. - pintctrl-0: Specifies the pin control groups used for this controller.
- autosuspend-delay: Specify autosuspend delay in milliseconds. - autosuspend-delay: Specify autosuspend delay in milliseconds.
- vin-voltage-override: Specify voltage of VIN pin in microvolts.
- irq-status-read-quirk: Specify that the trf7970a being used has the
"IRQ Status Read" erratum.
- en2-rf-quirk: Specify that the trf7970a being used has the "EN2 RF"
erratum.
Example (for ARM-based BeagleBone with TRF7970A on SPI1): Example (for ARM-based BeagleBone with TRF7970A on SPI1):
...@@ -30,7 +35,10 @@ Example (for ARM-based BeagleBone with TRF7970A on SPI1): ...@@ -30,7 +35,10 @@ Example (for ARM-based BeagleBone with TRF7970A on SPI1):
ti,enable-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>, ti,enable-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>,
<&gpio2 5 GPIO_ACTIVE_LOW>; <&gpio2 5 GPIO_ACTIVE_LOW>;
vin-supply = <&ldo3_reg>; vin-supply = <&ldo3_reg>;
vin-voltage-override = <5000000>;
autosuspend-delay = <30000>; autosuspend-delay = <30000>;
irq-status-read-quirk;
en2-rf-quirk;
status = "okay"; status = "okay";
}; };
}; };
...@@ -152,6 +152,7 @@ F: drivers/scsi/53c700* ...@@ -152,6 +152,7 @@ F: drivers/scsi/53c700*
6LOWPAN GENERIC (BTLE/IEEE 802.15.4) 6LOWPAN GENERIC (BTLE/IEEE 802.15.4)
M: Alexander Aring <alex.aring@gmail.com> M: Alexander Aring <alex.aring@gmail.com>
M: Jukka Rissanen <jukka.rissanen@linux.intel.com>
L: linux-bluetooth@vger.kernel.org L: linux-bluetooth@vger.kernel.org
L: linux-wpan@vger.kernel.org L: linux-wpan@vger.kernel.org
S: Maintained S: Maintained
...@@ -1616,6 +1617,7 @@ L: wil6210@qca.qualcomm.com ...@@ -1616,6 +1617,7 @@ L: wil6210@qca.qualcomm.com
S: Supported S: Supported
W: http://wireless.kernel.org/en/users/Drivers/wil6210 W: http://wireless.kernel.org/en/users/Drivers/wil6210
F: drivers/net/wireless/ath/wil6210/ F: drivers/net/wireless/ath/wil6210/
F: include/uapi/linux/wil6210_uapi.h
CARL9170 LINUX COMMUNITY WIRELESS DRIVER CARL9170 LINUX COMMUNITY WIRELESS DRIVER
M: Christian Lamparter <chunkeey@googlemail.com> M: Christian Lamparter <chunkeey@googlemail.com>
...@@ -7494,13 +7496,12 @@ F: drivers/video/fbdev/aty/aty128fb.c ...@@ -7494,13 +7496,12 @@ F: drivers/video/fbdev/aty/aty128fb.c
RALINK RT2X00 WIRELESS LAN DRIVER RALINK RT2X00 WIRELESS LAN DRIVER
P: rt2x00 project P: rt2x00 project
M: Ivo van Doorn <IvDoorn@gmail.com> M: Stanislaw Gruszka <sgruszka@redhat.com>
M: Helmut Schaa <helmut.schaa@googlemail.com> M: Helmut Schaa <helmut.schaa@googlemail.com>
L: linux-wireless@vger.kernel.org L: linux-wireless@vger.kernel.org
L: users@rt2x00.serialmonkey.com (moderated for non-subscribers) L: users@rt2x00.serialmonkey.com (moderated for non-subscribers)
W: http://rt2x00.serialmonkey.com/ W: http://rt2x00.serialmonkey.com/
S: Maintained S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/ivd/rt2x00.git
F: drivers/net/wireless/rt2x00/ F: drivers/net/wireless/rt2x00/
RAMDISK RAM BLOCK DEVICE DRIVER RAMDISK RAM BLOCK DEVICE DRIVER
......
...@@ -88,6 +88,20 @@ extern int __init bcma_host_pci_init(void); ...@@ -88,6 +88,20 @@ extern int __init bcma_host_pci_init(void);
extern void __exit bcma_host_pci_exit(void); extern void __exit bcma_host_pci_exit(void);
#endif /* CONFIG_BCMA_HOST_PCI */ #endif /* CONFIG_BCMA_HOST_PCI */
/* host_soc.c */
#if defined(CONFIG_BCMA_HOST_SOC) && defined(CONFIG_OF)
extern int __init bcma_host_soc_register_driver(void);
extern void __exit bcma_host_soc_unregister_driver(void);
#else
static inline int __init bcma_host_soc_register_driver(void)
{
return 0;
}
static inline void __exit bcma_host_soc_unregister_driver(void)
{
}
#endif /* CONFIG_BCMA_HOST_SOC && CONFIG_OF */
/* driver_pci.c */ /* driver_pci.c */
u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address); u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address);
......
...@@ -76,7 +76,7 @@ static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio) ...@@ -76,7 +76,7 @@ static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio)
bcma_chipco_gpio_pullup(cc, 1 << gpio, 0); bcma_chipco_gpio_pullup(cc, 1 << gpio, 0);
} }
#if IS_BUILTIN(CONFIG_BCMA_HOST_SOC) #if IS_BUILTIN(CONFIG_BCM47XX)
static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
{ {
struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
...@@ -215,8 +215,12 @@ int bcma_gpio_init(struct bcma_drv_cc *cc) ...@@ -215,8 +215,12 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
chip->set = bcma_gpio_set_value; chip->set = bcma_gpio_set_value;
chip->direction_input = bcma_gpio_direction_input; chip->direction_input = bcma_gpio_direction_input;
chip->direction_output = bcma_gpio_direction_output; chip->direction_output = bcma_gpio_direction_output;
#if IS_BUILTIN(CONFIG_BCMA_HOST_SOC) #if IS_BUILTIN(CONFIG_BCM47XX)
chip->to_irq = bcma_gpio_to_irq; chip->to_irq = bcma_gpio_to_irq;
#endif
#if IS_BUILTIN(CONFIG_OF)
if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
chip->of_node = cc->core->dev.of_node;
#endif #endif
switch (cc->core->bus->chipinfo.id) { switch (cc->core->bus->chipinfo.id) {
case BCMA_CHIP_ID_BCM5357: case BCMA_CHIP_ID_BCM5357:
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
#include "bcma_private.h" #include "bcma_private.h"
#include "scan.h" #include "scan.h"
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/bcma/bcma.h> #include <linux/bcma/bcma.h>
#include <linux/bcma/bcma_soc.h> #include <linux/bcma/bcma_soc.h>
...@@ -176,6 +179,7 @@ int __init bcma_host_soc_register(struct bcma_soc *soc) ...@@ -176,6 +179,7 @@ int __init bcma_host_soc_register(struct bcma_soc *soc)
/* Host specific */ /* Host specific */
bus->hosttype = BCMA_HOSTTYPE_SOC; bus->hosttype = BCMA_HOSTTYPE_SOC;
bus->ops = &bcma_host_soc_ops; bus->ops = &bcma_host_soc_ops;
bus->host_pdev = NULL;
/* Initialize struct, detect chip */ /* Initialize struct, detect chip */
bcma_init_bus(bus); bcma_init_bus(bus);
...@@ -195,3 +199,80 @@ int __init bcma_host_soc_init(struct bcma_soc *soc) ...@@ -195,3 +199,80 @@ int __init bcma_host_soc_init(struct bcma_soc *soc)
return err; return err;
} }
#ifdef CONFIG_OF
static int bcma_host_soc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct bcma_bus *bus;
int err;
/* Alloc */
bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL);
if (!bus)
return -ENOMEM;
/* Map MMIO */
bus->mmio = of_iomap(np, 0);
if (!bus->mmio)
return -ENOMEM;
/* Host specific */
bus->hosttype = BCMA_HOSTTYPE_SOC;
bus->ops = &bcma_host_soc_ops;
bus->host_pdev = pdev;
/* Initialize struct, detect chip */
bcma_init_bus(bus);
/* Register */
err = bcma_bus_register(bus);
if (err)
goto err_unmap_mmio;
platform_set_drvdata(pdev, bus);
return err;
err_unmap_mmio:
iounmap(bus->mmio);
return err;
}
static int bcma_host_soc_remove(struct platform_device *pdev)
{
struct bcma_bus *bus = platform_get_drvdata(pdev);
bcma_bus_unregister(bus);
iounmap(bus->mmio);
platform_set_drvdata(pdev, NULL);
return 0;
}
static const struct of_device_id bcma_host_soc_of_match[] = {
{ .compatible = "brcm,bus-axi", },
{},
};
MODULE_DEVICE_TABLE(of, bcma_host_soc_of_match);
static struct platform_driver bcma_host_soc_driver = {
.driver = {
.name = "bcma-host-soc",
.of_match_table = bcma_host_soc_of_match,
},
.probe = bcma_host_soc_probe,
.remove = bcma_host_soc_remove,
};
int __init bcma_host_soc_register_driver(void)
{
return platform_driver_register(&bcma_host_soc_driver);
}
void __exit bcma_host_soc_unregister_driver(void)
{
platform_driver_unregister(&bcma_host_soc_driver);
}
#endif /* CONFIG_OF */
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/bcma/bcma.h> #include <linux/bcma/bcma.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/of_address.h>
MODULE_DESCRIPTION("Broadcom's specific AMBA driver"); MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -131,6 +132,43 @@ static bool bcma_is_core_needed_early(u16 core_id) ...@@ -131,6 +132,43 @@ static bool bcma_is_core_needed_early(u16 core_id)
return false; return false;
} }
#ifdef CONFIG_OF
static struct device_node *bcma_of_find_child_device(struct platform_device *parent,
struct bcma_device *core)
{
struct device_node *node;
u64 size;
const __be32 *reg;
if (!parent || !parent->dev.of_node)
return NULL;
for_each_child_of_node(parent->dev.of_node, node) {
reg = of_get_address(node, 0, &size, NULL);
if (!reg)
continue;
if (of_translate_address(node, reg) == core->addr)
return node;
}
return NULL;
}
static void bcma_of_fill_device(struct platform_device *parent,
struct bcma_device *core)
{
struct device_node *node;
node = bcma_of_find_child_device(parent, core);
if (node)
core->dev.of_node = node;
}
#else
static void bcma_of_fill_device(struct platform_device *parent,
struct bcma_device *core)
{
}
#endif /* CONFIG_OF */
static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core) static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core)
{ {
int err; int err;
...@@ -147,7 +185,13 @@ static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core) ...@@ -147,7 +185,13 @@ static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core)
break; break;
case BCMA_HOSTTYPE_SOC: case BCMA_HOSTTYPE_SOC:
core->dev.dma_mask = &core->dev.coherent_dma_mask; core->dev.dma_mask = &core->dev.coherent_dma_mask;
core->dma_dev = &core->dev; if (bus->host_pdev) {
core->dma_dev = &bus->host_pdev->dev;
core->dev.parent = &bus->host_pdev->dev;
bcma_of_fill_device(bus->host_pdev, core);
} else {
core->dma_dev = &core->dev;
}
break; break;
case BCMA_HOSTTYPE_SDIO: case BCMA_HOSTTYPE_SDIO:
break; break;
...@@ -528,6 +572,11 @@ static int __init bcma_modinit(void) ...@@ -528,6 +572,11 @@ static int __init bcma_modinit(void)
if (err) if (err)
return err; return err;
err = bcma_host_soc_register_driver();
if (err) {
pr_err("SoC host initialization failed\n");
err = 0;
}
#ifdef CONFIG_BCMA_HOST_PCI #ifdef CONFIG_BCMA_HOST_PCI
err = bcma_host_pci_init(); err = bcma_host_pci_init();
if (err) { if (err) {
...@@ -545,6 +594,7 @@ static void __exit bcma_modexit(void) ...@@ -545,6 +594,7 @@ static void __exit bcma_modexit(void)
#ifdef CONFIG_BCMA_HOST_PCI #ifdef CONFIG_BCMA_HOST_PCI
bcma_host_pci_exit(); bcma_host_pci_exit();
#endif #endif
bcma_host_soc_unregister_driver();
bus_unregister(&bcma_bus_type); bus_unregister(&bcma_bus_type);
} }
module_exit(bcma_modexit) module_exit(bcma_modexit)
...@@ -439,6 +439,7 @@ void bcma_init_bus(struct bcma_bus *bus) ...@@ -439,6 +439,7 @@ void bcma_init_bus(struct bcma_bus *bus)
{ {
s32 tmp; s32 tmp;
struct bcma_chipinfo *chipinfo = &(bus->chipinfo); struct bcma_chipinfo *chipinfo = &(bus->chipinfo);
char chip_id[8];
INIT_LIST_HEAD(&bus->cores); INIT_LIST_HEAD(&bus->cores);
bus->nr_cores = 0; bus->nr_cores = 0;
...@@ -449,8 +450,11 @@ void bcma_init_bus(struct bcma_bus *bus) ...@@ -449,8 +450,11 @@ void bcma_init_bus(struct bcma_bus *bus)
chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT;
chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT;
chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT;
bcma_info(bus, "Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n",
chipinfo->id, chipinfo->rev, chipinfo->pkg); snprintf(chip_id, ARRAY_SIZE(chip_id),
(chipinfo->id > 0x9999) ? "%d" : "0x%04X", chipinfo->id);
bcma_info(bus, "Found chip with id %s, rev 0x%02X and package 0x%02X\n",
chip_id, chipinfo->rev, chipinfo->pkg);
} }
int bcma_bus_scan(struct bcma_bus *bus) int bcma_bus_scan(struct bcma_bus *bus)
......
...@@ -201,7 +201,7 @@ config BT_MRVL ...@@ -201,7 +201,7 @@ config BT_MRVL
The core driver to support Marvell Bluetooth devices. The core driver to support Marvell Bluetooth devices.
This driver is required if you want to support This driver is required if you want to support
Marvell Bluetooth devices, such as 8688/8787/8797/8897. Marvell Bluetooth devices, such as 8688/8787/8797/8887/8897.
Say Y here to compile Marvell Bluetooth driver Say Y here to compile Marvell Bluetooth driver
into the kernel or say M to compile it as module. into the kernel or say M to compile it as module.
...@@ -214,7 +214,7 @@ config BT_MRVL_SDIO ...@@ -214,7 +214,7 @@ config BT_MRVL_SDIO
The driver for Marvell Bluetooth chipsets with SDIO interface. The driver for Marvell Bluetooth chipsets with SDIO interface.
This driver is required if you want to use Marvell Bluetooth This driver is required if you want to use Marvell Bluetooth
devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8897 devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8887/SD8897
chipsets are supported. chipsets are supported.
Say Y here to compile support for Marvell BT-over-SDIO driver Say Y here to compile support for Marvell BT-over-SDIO driver
......
...@@ -84,7 +84,27 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = { ...@@ -84,7 +84,27 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
.int_read_to_clear = false, .int_read_to_clear = false,
}; };
static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = { static const struct btmrvl_sdio_card_reg btmrvl_reg_8887 = {
.cfg = 0x00,
.host_int_mask = 0x08,
.host_intstatus = 0x0C,
.card_status = 0x5C,
.sq_read_base_addr_a0 = 0x6C,
.sq_read_base_addr_a1 = 0x6D,
.card_revision = 0xC8,
.card_fw_status0 = 0x88,
.card_fw_status1 = 0x89,
.card_rx_len = 0x8A,
.card_rx_unit = 0x8B,
.io_port_0 = 0xE4,
.io_port_1 = 0xE5,
.io_port_2 = 0xE6,
.int_read_to_clear = true,
.host_int_rsr = 0x04,
.card_misc_cfg = 0xD8,
};
static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = {
.cfg = 0x00, .cfg = 0x00,
.host_int_mask = 0x02, .host_int_mask = 0x02,
.host_intstatus = 0x03, .host_intstatus = 0x03,
...@@ -128,10 +148,18 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { ...@@ -128,10 +148,18 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
.sd_blksz_fw_dl = 256, .sd_blksz_fw_dl = 256,
}; };
static const struct btmrvl_sdio_device btmrvl_sdio_sd8887 = {
.helper = NULL,
.firmware = "mrvl/sd8887_uapsta.bin",
.reg = &btmrvl_reg_8887,
.support_pscan_win_report = true,
.sd_blksz_fw_dl = 256,
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
.helper = NULL, .helper = NULL,
.firmware = "mrvl/sd8897_uapsta.bin", .firmware = "mrvl/sd8897_uapsta.bin",
.reg = &btmrvl_reg_88xx, .reg = &btmrvl_reg_8897,
.support_pscan_win_report = true, .support_pscan_win_report = true,
.sd_blksz_fw_dl = 256, .sd_blksz_fw_dl = 256,
}; };
...@@ -149,6 +177,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = { ...@@ -149,6 +177,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = {
/* Marvell SD8797 Bluetooth device */ /* Marvell SD8797 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
.driver_data = (unsigned long) &btmrvl_sdio_sd8797 }, .driver_data = (unsigned long) &btmrvl_sdio_sd8797 },
/* Marvell SD8887 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9136),
.driver_data = (unsigned long)&btmrvl_sdio_sd8887 },
/* Marvell SD8897 Bluetooth device */ /* Marvell SD8897 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E),
.driver_data = (unsigned long) &btmrvl_sdio_sd8897 }, .driver_data = (unsigned long) &btmrvl_sdio_sd8897 },
...@@ -1280,4 +1311,5 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin"); ...@@ -1280,4 +1311,5 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
MODULE_FIRMWARE("mrvl/sd8688.bin"); MODULE_FIRMWARE("mrvl/sd8688.bin");
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8887_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
此差异已折叠。
...@@ -323,8 +323,8 @@ static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec, ...@@ -323,8 +323,8 @@ static int mrf24j40_read_rx_buf(struct mrf24j40 *devrec,
#ifdef DEBUG #ifdef DEBUG
print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ", print_hex_dump(KERN_DEBUG, "mrf24j40 rx: ",
DUMP_PREFIX_OFFSET, 16, 1, data, *len, 0); DUMP_PREFIX_OFFSET, 16, 1, data, *len, 0);
printk(KERN_DEBUG "mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n", pr_debug("mrf24j40 rx: lqi: %02hhx rssi: %02hhx\n",
lqi_rssi[0], lqi_rssi[1]); lqi_rssi[0], lqi_rssi[1]);
#endif #endif
out: out:
...@@ -385,7 +385,7 @@ static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb) ...@@ -385,7 +385,7 @@ static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
static int mrf24j40_ed(struct ieee802154_dev *dev, u8 *level) static int mrf24j40_ed(struct ieee802154_dev *dev, u8 *level)
{ {
/* TODO: */ /* TODO: */
printk(KERN_WARNING "mrf24j40: ed not implemented\n"); pr_warn("mrf24j40: ed not implemented\n");
*level = 0; *level = 0;
return 0; return 0;
} }
...@@ -412,6 +412,7 @@ static void mrf24j40_stop(struct ieee802154_dev *dev) ...@@ -412,6 +412,7 @@ static void mrf24j40_stop(struct ieee802154_dev *dev)
struct mrf24j40 *devrec = dev->priv; struct mrf24j40 *devrec = dev->priv;
u8 val; u8 val;
int ret; int ret;
dev_dbg(printdev(devrec), "stop\n"); dev_dbg(printdev(devrec), "stop\n");
ret = read_short_reg(devrec, REG_INTCON, &val); ret = read_short_reg(devrec, REG_INTCON, &val);
...@@ -419,8 +420,6 @@ static void mrf24j40_stop(struct ieee802154_dev *dev) ...@@ -419,8 +420,6 @@ static void mrf24j40_stop(struct ieee802154_dev *dev)
return; return;
val |= 0x1|0x8; /* Set TXNIE and RXIE. Disable Interrupts */ val |= 0x1|0x8; /* Set TXNIE and RXIE. Disable Interrupts */
write_short_reg(devrec, REG_INTCON, val); write_short_reg(devrec, REG_INTCON, val);
return;
} }
static int mrf24j40_set_channel(struct ieee802154_dev *dev, static int mrf24j40_set_channel(struct ieee802154_dev *dev,
...@@ -465,6 +464,7 @@ static int mrf24j40_filter(struct ieee802154_dev *dev, ...@@ -465,6 +464,7 @@ static int mrf24j40_filter(struct ieee802154_dev *dev,
if (changed & IEEE802515_AFILT_SADDR_CHANGED) { if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
/* Short Addr */ /* Short Addr */
u8 addrh, addrl; u8 addrh, addrl;
addrh = le16_to_cpu(filt->short_addr) >> 8 & 0xff; addrh = le16_to_cpu(filt->short_addr) >> 8 & 0xff;
addrl = le16_to_cpu(filt->short_addr) & 0xff; addrl = le16_to_cpu(filt->short_addr) & 0xff;
...@@ -483,16 +483,17 @@ static int mrf24j40_filter(struct ieee802154_dev *dev, ...@@ -483,16 +483,17 @@ static int mrf24j40_filter(struct ieee802154_dev *dev,
write_short_reg(devrec, REG_EADR0 + i, addr[i]); write_short_reg(devrec, REG_EADR0 + i, addr[i]);
#ifdef DEBUG #ifdef DEBUG
printk(KERN_DEBUG "Set long addr to: "); pr_debug("Set long addr to: ");
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
printk("%02hhx ", addr[7 - i]); pr_debug("%02hhx ", addr[7 - i]);
printk(KERN_DEBUG "\n"); pr_debug("\n");
#endif #endif
} }
if (changed & IEEE802515_AFILT_PANID_CHANGED) { if (changed & IEEE802515_AFILT_PANID_CHANGED) {
/* PAN ID */ /* PAN ID */
u8 panidl, panidh; u8 panidl, panidh;
panidh = le16_to_cpu(filt->pan_id) >> 8 & 0xff; panidh = le16_to_cpu(filt->pan_id) >> 8 & 0xff;
panidl = le16_to_cpu(filt->pan_id) & 0xff; panidl = le16_to_cpu(filt->pan_id) & 0xff;
write_short_reg(devrec, REG_PANIDH, panidh); write_short_reg(devrec, REG_PANIDH, panidh);
...@@ -701,7 +702,7 @@ static int mrf24j40_probe(struct spi_device *spi) ...@@ -701,7 +702,7 @@ static int mrf24j40_probe(struct spi_device *spi)
int ret = -ENOMEM; int ret = -ENOMEM;
struct mrf24j40 *devrec; struct mrf24j40 *devrec;
printk(KERN_INFO "mrf24j40: probe(). IRQ: %d\n", spi->irq); dev_info(&spi->dev, "probe(). IRQ: %d\n", spi->irq);
devrec = devm_kzalloc(&spi->dev, sizeof(struct mrf24j40), GFP_KERNEL); devrec = devm_kzalloc(&spi->dev, sizeof(struct mrf24j40), GFP_KERNEL);
if (!devrec) if (!devrec)
......
...@@ -25,6 +25,14 @@ config ATH_DEBUG ...@@ -25,6 +25,14 @@ config ATH_DEBUG
Say Y, if you want to debug atheros wireless drivers. Say Y, if you want to debug atheros wireless drivers.
Right now only ath9k makes use of this. Right now only ath9k makes use of this.
config ATH_TRACEPOINTS
bool "Atheros wireless tracing"
depends on ATH_DEBUG
depends on EVENT_TRACING
---help---
This option enables tracepoints for atheros wireless drivers.
Currently, ath9k makes use of this facility.
config ATH_REG_DYNAMIC_USER_REG_HINTS config ATH_REG_DYNAMIC_USER_REG_HINTS
bool "Atheros dynamic user regulatory hints" bool "Atheros dynamic user regulatory hints"
depends on CFG80211_CERTIFICATION_ONUS depends on CFG80211_CERTIFICATION_ONUS
......
...@@ -17,4 +17,8 @@ ath-objs := main.o \ ...@@ -17,4 +17,8 @@ ath-objs := main.o \
dfs_pri_detector.o dfs_pri_detector.o
ath-$(CONFIG_ATH_DEBUG) += debug.o ath-$(CONFIG_ATH_DEBUG) += debug.o
ath-$(CONFIG_ATH_TRACEPOINTS) += trace.o
ccflags-y += -D__CHECK_ENDIAN__ ccflags-y += -D__CHECK_ENDIAN__
CFLAGS_trace.o := -I$(src)
...@@ -268,6 +268,7 @@ enum ATH_DEBUG { ...@@ -268,6 +268,7 @@ enum ATH_DEBUG {
}; };
#define ATH_DBG_DEFAULT (ATH_DBG_FATAL) #define ATH_DBG_DEFAULT (ATH_DBG_FATAL)
#define ATH_DBG_MAX_LEN 512
#ifdef CONFIG_ATH_DEBUG #ifdef CONFIG_ATH_DEBUG
......
...@@ -24,7 +24,7 @@ config ATH10K_DEBUG ...@@ -24,7 +24,7 @@ config ATH10K_DEBUG
config ATH10K_DEBUGFS config ATH10K_DEBUGFS
bool "Atheros ath10k debugfs support" bool "Atheros ath10k debugfs support"
depends on ATH10K depends on ATH10K && DEBUG_FS
select RELAY select RELAY
---help--- ---help---
Enabled debugfs support Enabled debugfs support
......
...@@ -11,6 +11,7 @@ ath10k_core-y += mac.o \ ...@@ -11,6 +11,7 @@ ath10k_core-y += mac.o \
bmi.o bmi.o
ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o
ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o
obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o
......
...@@ -177,7 +177,6 @@ struct bmi_target_info { ...@@ -177,7 +177,6 @@ struct bmi_target_info {
u32 type; u32 type;
}; };
/* in msec */ /* in msec */
#define BMI_COMMUNICATION_TIMEOUT_HZ (1*HZ) #define BMI_COMMUNICATION_TIMEOUT_HZ (1*HZ)
......
...@@ -260,7 +260,6 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar, ...@@ -260,7 +260,6 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask); ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask);
} }
/* /*
* Guts of ath10k_ce_send, used by both ath10k_ce_send and * Guts of ath10k_ce_send, used by both ath10k_ce_send and
* ath10k_ce_sendlist_send. * ath10k_ce_sendlist_send.
...@@ -385,7 +384,6 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe) ...@@ -385,7 +384,6 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe)
return delta; return delta;
} }
int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe) int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe)
{ {
struct ath10k *ar = pipe->ar; struct ath10k *ar = pipe->ar;
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
#include "hif.h" #include "hif.h"
/* Maximum number of Copy Engine's supported */ /* Maximum number of Copy Engine's supported */
#define CE_COUNT_MAX 8 #define CE_COUNT_MAX 8
#define CE_HTT_H2T_MSG_SRC_NENTRIES 4096 #define CE_HTT_H2T_MSG_SRC_NENTRIES 4096
...@@ -37,7 +36,6 @@ ...@@ -37,7 +36,6 @@
struct ath10k_ce_pipe; struct ath10k_ce_pipe;
#define CE_DESC_FLAGS_GATHER (1 << 0) #define CE_DESC_FLAGS_GATHER (1 << 0)
#define CE_DESC_FLAGS_BYTE_SWAP (1 << 1) #define CE_DESC_FLAGS_BYTE_SWAP (1 << 1)
#define CE_DESC_FLAGS_META_DATA_MASK 0xFFFC #define CE_DESC_FLAGS_META_DATA_MASK 0xFFFC
...@@ -189,10 +187,10 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, ...@@ -189,10 +187,10 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
* Pops 1 completed send buffer from Source ring. * Pops 1 completed send buffer from Source ring.
*/ */
int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp, void **per_transfer_contextp,
u32 *bufferp, u32 *bufferp,
unsigned int *nbytesp, unsigned int *nbytesp,
unsigned int *transfer_idp); unsigned int *transfer_idp);
/*==================CE Engine Initialization=======================*/ /*==================CE Engine Initialization=======================*/
...@@ -202,7 +200,7 @@ int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, ...@@ -202,7 +200,7 @@ int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
void (*recv_cb)(struct ath10k_ce_pipe *)); void (*recv_cb)(struct ath10k_ce_pipe *));
void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id); void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id);
int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
const struct ce_attr *attr); const struct ce_attr *attr);
void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id); void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id);
/*==================CE Engine Shutdown=======================*/ /*==================CE Engine Shutdown=======================*/
...@@ -383,7 +381,6 @@ struct ce_attr { ...@@ -383,7 +381,6 @@ struct ce_attr {
#define DST_WATERMARK_HIGH_RESET 0 #define DST_WATERMARK_HIGH_RESET 0
#define DST_WATERMARK_ADDRESS 0x0050 #define DST_WATERMARK_ADDRESS 0x0050
static inline u32 ath10k_ce_base_address(unsigned int ce_id) static inline u32 ath10k_ce_base_address(unsigned int ce_id)
{ {
return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id; return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "bmi.h" #include "bmi.h"
#include "debug.h" #include "debug.h"
#include "htt.h" #include "htt.h"
#include "testmode.h"
unsigned int ath10k_debug_mask; unsigned int ath10k_debug_mask;
static bool uart_print; static bool uart_print;
...@@ -257,21 +258,42 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) ...@@ -257,21 +258,42 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
return 0; return 0;
} }
static int ath10k_download_fw(struct ath10k *ar) static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
{ {
u32 address; u32 address, data_len;
const char *mode_name;
const void *data;
int ret; int ret;
address = ar->hw_params.patch_load_addr; address = ar->hw_params.patch_load_addr;
ret = ath10k_bmi_fast_download(ar, address, ar->firmware_data, switch (mode) {
ar->firmware_len); case ATH10K_FIRMWARE_MODE_NORMAL:
data = ar->firmware_data;
data_len = ar->firmware_len;
mode_name = "normal";
break;
case ATH10K_FIRMWARE_MODE_UTF:
data = ar->testmode.utf->data;
data_len = ar->testmode.utf->size;
mode_name = "utf";
break;
default:
ath10k_err(ar, "unknown firmware mode: %d\n", mode);
return -EINVAL;
}
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot uploading firmware image %p len %d mode %s\n",
data, data_len, mode_name);
ret = ath10k_bmi_fast_download(ar, address, data, data_len);
if (ret) { if (ret) {
ath10k_err(ar, "could not write fw (%d)\n", ret); ath10k_err(ar, "failed to download %s firmware: %d\n",
goto exit; mode_name, ret);
return ret;
} }
exit:
return ret; return ret;
} }
...@@ -567,7 +589,8 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) ...@@ -567,7 +589,8 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
return 0; return 0;
} }
static int ath10k_init_download_firmware(struct ath10k *ar) static int ath10k_init_download_firmware(struct ath10k *ar,
enum ath10k_firmware_mode mode)
{ {
int ret; int ret;
...@@ -583,7 +606,7 @@ static int ath10k_init_download_firmware(struct ath10k *ar) ...@@ -583,7 +606,7 @@ static int ath10k_init_download_firmware(struct ath10k *ar)
return ret; return ret;
} }
ret = ath10k_download_fw(ar); ret = ath10k_download_fw(ar, mode);
if (ret) { if (ret) {
ath10k_err(ar, "failed to download firmware: %d\n", ret); ath10k_err(ar, "failed to download firmware: %d\n", ret);
return ret; return ret;
...@@ -685,12 +708,15 @@ static void ath10k_core_restart(struct work_struct *work) ...@@ -685,12 +708,15 @@ static void ath10k_core_restart(struct work_struct *work)
case ATH10K_STATE_WEDGED: case ATH10K_STATE_WEDGED:
ath10k_warn(ar, "device is wedged, will not restart\n"); ath10k_warn(ar, "device is wedged, will not restart\n");
break; break;
case ATH10K_STATE_UTF:
ath10k_warn(ar, "firmware restart in UTF mode not supported\n");
break;
} }
mutex_unlock(&ar->conf_mutex); mutex_unlock(&ar->conf_mutex);
} }
int ath10k_core_start(struct ath10k *ar) int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
{ {
int status; int status;
...@@ -703,7 +729,7 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -703,7 +729,7 @@ int ath10k_core_start(struct ath10k *ar)
goto err; goto err;
} }
status = ath10k_init_download_firmware(ar); status = ath10k_init_download_firmware(ar, mode);
if (status) if (status)
goto err; goto err;
...@@ -760,10 +786,12 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -760,10 +786,12 @@ int ath10k_core_start(struct ath10k *ar)
goto err_hif_stop; goto err_hif_stop;
} }
status = ath10k_htt_connect(&ar->htt); if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
if (status) { status = ath10k_htt_connect(&ar->htt);
ath10k_err(ar, "failed to connect htt (%d)\n", status); if (status) {
goto err_hif_stop; ath10k_err(ar, "failed to connect htt (%d)\n", status);
goto err_hif_stop;
}
} }
status = ath10k_wmi_connect(ar); status = ath10k_wmi_connect(ar);
...@@ -778,11 +806,13 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -778,11 +806,13 @@ int ath10k_core_start(struct ath10k *ar)
goto err_hif_stop; goto err_hif_stop;
} }
status = ath10k_wmi_wait_for_service_ready(ar); if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
if (status <= 0) { status = ath10k_wmi_wait_for_service_ready(ar);
ath10k_warn(ar, "wmi service ready event not received"); if (status <= 0) {
status = -ETIMEDOUT; ath10k_warn(ar, "wmi service ready event not received");
goto err_hif_stop; status = -ETIMEDOUT;
goto err_hif_stop;
}
} }
ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n", ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
...@@ -802,10 +832,13 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -802,10 +832,13 @@ int ath10k_core_start(struct ath10k *ar)
goto err_hif_stop; goto err_hif_stop;
} }
status = ath10k_htt_setup(&ar->htt); /* we don't care about HTT in UTF mode */
if (status) { if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
ath10k_err(ar, "failed to setup htt: %d\n", status); status = ath10k_htt_setup(&ar->htt);
goto err_hif_stop; if (status) {
ath10k_err(ar, "failed to setup htt: %d\n", status);
goto err_hif_stop;
}
} }
status = ath10k_debug_start(ar); status = ath10k_debug_start(ar);
...@@ -861,7 +894,8 @@ void ath10k_core_stop(struct ath10k *ar) ...@@ -861,7 +894,8 @@ void ath10k_core_stop(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
/* try to suspend target */ /* try to suspend target */
if (ar->state != ATH10K_STATE_RESTARTING) if (ar->state != ATH10K_STATE_RESTARTING &&
ar->state != ATH10K_STATE_UTF)
ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR); ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);
ath10k_debug_stop(ar); ath10k_debug_stop(ar);
...@@ -914,7 +948,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar) ...@@ -914,7 +948,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
mutex_lock(&ar->conf_mutex); mutex_lock(&ar->conf_mutex);
ret = ath10k_core_start(ar); ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
if (ret) { if (ret) {
ath10k_err(ar, "could not init core (%d)\n", ret); ath10k_err(ar, "could not init core (%d)\n", ret);
ath10k_core_free_firmware_files(ar); ath10k_core_free_firmware_files(ar);
...@@ -977,7 +1011,7 @@ static void ath10k_core_register_work(struct work_struct *work) ...@@ -977,7 +1011,7 @@ static void ath10k_core_register_work(struct work_struct *work)
goto err_release_fw; goto err_release_fw;
} }
status = ath10k_debug_create(ar); status = ath10k_debug_register(ar);
if (status) { if (status) {
ath10k_err(ar, "unable to initialize debugfs\n"); ath10k_err(ar, "unable to initialize debugfs\n");
goto err_unregister_mac; goto err_unregister_mac;
...@@ -1041,9 +1075,11 @@ void ath10k_core_unregister(struct ath10k *ar) ...@@ -1041,9 +1075,11 @@ void ath10k_core_unregister(struct ath10k *ar)
* unhappy about callback failures. */ * unhappy about callback failures. */
ath10k_mac_unregister(ar); ath10k_mac_unregister(ar);
ath10k_testmode_destroy(ar);
ath10k_core_free_firmware_files(ar); ath10k_core_free_firmware_files(ar);
ath10k_debug_destroy(ar); ath10k_debug_unregister(ar);
} }
EXPORT_SYMBOL(ath10k_core_unregister); EXPORT_SYMBOL(ath10k_core_unregister);
...@@ -1051,6 +1087,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ...@@ -1051,6 +1087,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
const struct ath10k_hif_ops *hif_ops) const struct ath10k_hif_ops *hif_ops)
{ {
struct ath10k *ar; struct ath10k *ar;
int ret;
ar = ath10k_mac_create(priv_size); ar = ath10k_mac_create(priv_size);
if (!ar) if (!ar)
...@@ -1076,7 +1113,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ...@@ -1076,7 +1113,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
ar->workqueue = create_singlethread_workqueue("ath10k_wq"); ar->workqueue = create_singlethread_workqueue("ath10k_wq");
if (!ar->workqueue) if (!ar->workqueue)
goto err_wq; goto err_free_mac;
mutex_init(&ar->conf_mutex); mutex_init(&ar->conf_mutex);
spin_lock_init(&ar->data_lock); spin_lock_init(&ar->data_lock);
...@@ -1094,10 +1131,18 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ...@@ -1094,10 +1131,18 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
INIT_WORK(&ar->register_work, ath10k_core_register_work); INIT_WORK(&ar->register_work, ath10k_core_register_work);
INIT_WORK(&ar->restart_work, ath10k_core_restart); INIT_WORK(&ar->restart_work, ath10k_core_restart);
ret = ath10k_debug_create(ar);
if (ret)
goto err_free_wq;
return ar; return ar;
err_wq: err_free_wq:
destroy_workqueue(ar->workqueue);
err_free_mac:
ath10k_mac_destroy(ar); ath10k_mac_destroy(ar);
return NULL; return NULL;
} }
EXPORT_SYMBOL(ath10k_core_create); EXPORT_SYMBOL(ath10k_core_create);
...@@ -1107,6 +1152,7 @@ void ath10k_core_destroy(struct ath10k *ar) ...@@ -1107,6 +1152,7 @@ void ath10k_core_destroy(struct ath10k *ar)
flush_workqueue(ar->workqueue); flush_workqueue(ar->workqueue);
destroy_workqueue(ar->workqueue); destroy_workqueue(ar->workqueue);
ath10k_debug_destroy(ar);
ath10k_mac_destroy(ar); ath10k_mac_destroy(ar);
} }
EXPORT_SYMBOL(ath10k_core_destroy); EXPORT_SYMBOL(ath10k_core_destroy);
......
...@@ -293,7 +293,7 @@ struct ath10k_debug { ...@@ -293,7 +293,7 @@ struct ath10k_debug {
struct dentry *debugfs_phy; struct dentry *debugfs_phy;
struct ath10k_target_stats target_stats; struct ath10k_target_stats target_stats;
DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_BM_SIZE); DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX);
struct completion event_stats_compl; struct completion event_stats_compl;
...@@ -330,6 +330,17 @@ enum ath10k_state { ...@@ -330,6 +330,17 @@ enum ath10k_state {
* prevents completion timeouts and makes the driver more responsive to * prevents completion timeouts and makes the driver more responsive to
* userspace commands. This is also prevents recursive recovery. */ * userspace commands. This is also prevents recursive recovery. */
ATH10K_STATE_WEDGED, ATH10K_STATE_WEDGED,
/* factory tests */
ATH10K_STATE_UTF,
};
enum ath10k_firmware_mode {
/* the default mode, standard 802.11 functionality */
ATH10K_FIRMWARE_MODE_NORMAL,
/* factory tests etc */
ATH10K_FIRMWARE_MODE_UTF,
}; };
enum ath10k_fw_features { enum ath10k_fw_features {
...@@ -472,7 +483,6 @@ struct ath10k { ...@@ -472,7 +483,6 @@ struct ath10k {
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
int free_vdev_map; int free_vdev_map;
bool promisc;
bool monitor; bool monitor;
int monitor_vdev_id; int monitor_vdev_id;
bool monitor_started; bool monitor_started;
...@@ -544,6 +554,15 @@ struct ath10k { ...@@ -544,6 +554,15 @@ struct ath10k {
struct ath10k_spec_scan config; struct ath10k_spec_scan config;
} spectral; } spectral;
struct {
/* protected by conf_mutex */
const struct firmware *utf;
DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);
/* protected by data_lock */
bool utf_monitor;
} testmode;
/* must be last */ /* must be last */
u8 drv_priv[0] __aligned(sizeof(void *)); u8 drv_priv[0] __aligned(sizeof(void *));
}; };
...@@ -552,7 +571,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ...@@ -552,7 +571,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
const struct ath10k_hif_ops *hif_ops); const struct ath10k_hif_ops *hif_ops);
void ath10k_core_destroy(struct ath10k *ar); void ath10k_core_destroy(struct ath10k *ar);
int ath10k_core_start(struct ath10k *ar); int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode);
int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt); int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
void ath10k_core_stop(struct ath10k *ar); void ath10k_core_stop(struct ath10k *ar);
int ath10k_core_register(struct ath10k *ar, u32 chip_id); int ath10k_core_register(struct ath10k *ar, u32 chip_id);
......
...@@ -117,7 +117,7 @@ int ath10k_info(struct ath10k *ar, const char *fmt, ...) ...@@ -117,7 +117,7 @@ int ath10k_info(struct ath10k *ar, const char *fmt, ...)
va_start(args, fmt); va_start(args, fmt);
vaf.va = &args; vaf.va = &args;
ret = dev_info(ar->dev, "%pV", &vaf); ret = dev_info(ar->dev, "%pV", &vaf);
trace_ath10k_log_info(&vaf); trace_ath10k_log_info(ar, &vaf);
va_end(args); va_end(args);
return ret; return ret;
...@@ -134,11 +134,12 @@ void ath10k_print_driver_info(struct ath10k *ar) ...@@ -134,11 +134,12 @@ void ath10k_print_driver_info(struct ath10k *ar)
ar->fw_api, ar->fw_api,
ar->htt.target_version_major, ar->htt.target_version_major,
ar->htt.target_version_minor); ar->htt.target_version_minor);
ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d\n", ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
config_enabled(CONFIG_ATH10K_DEBUG), config_enabled(CONFIG_ATH10K_DEBUG),
config_enabled(CONFIG_ATH10K_DEBUGFS), config_enabled(CONFIG_ATH10K_DEBUGFS),
config_enabled(CONFIG_ATH10K_TRACING), config_enabled(CONFIG_ATH10K_TRACING),
config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)); config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
config_enabled(CONFIG_NL80211_TESTMODE));
} }
EXPORT_SYMBOL(ath10k_print_driver_info); EXPORT_SYMBOL(ath10k_print_driver_info);
...@@ -153,7 +154,7 @@ int ath10k_err(struct ath10k *ar, const char *fmt, ...) ...@@ -153,7 +154,7 @@ int ath10k_err(struct ath10k *ar, const char *fmt, ...)
va_start(args, fmt); va_start(args, fmt);
vaf.va = &args; vaf.va = &args;
ret = dev_err(ar->dev, "%pV", &vaf); ret = dev_err(ar->dev, "%pV", &vaf);
trace_ath10k_log_err(&vaf); trace_ath10k_log_err(ar, &vaf);
va_end(args); va_end(args);
return ret; return ret;
...@@ -170,7 +171,7 @@ int ath10k_warn(struct ath10k *ar, const char *fmt, ...) ...@@ -170,7 +171,7 @@ int ath10k_warn(struct ath10k *ar, const char *fmt, ...)
va_start(args, fmt); va_start(args, fmt);
vaf.va = &args; vaf.va = &args;
dev_warn_ratelimited(ar->dev, "%pV", &vaf); dev_warn_ratelimited(ar->dev, "%pV", &vaf);
trace_ath10k_log_warn(&vaf); trace_ath10k_log_warn(ar, &vaf);
va_end(args); va_end(args);
...@@ -208,7 +209,7 @@ static ssize_t ath10k_read_wmi_services(struct file *file, ...@@ -208,7 +209,7 @@ static ssize_t ath10k_read_wmi_services(struct file *file,
if (len > buf_len) if (len > buf_len)
len = buf_len; len = buf_len;
for (i = 0; i < WMI_MAX_SERVICE; i++) { for (i = 0; i < WMI_SERVICE_MAX; i++) {
enabled = test_bit(i, ar->debug.wmi_service_bitmap); enabled = test_bit(i, ar->debug.wmi_service_bitmap);
name = wmi_service_name(i); name = wmi_service_name(i);
...@@ -564,16 +565,35 @@ static const struct file_operations fops_fw_stats = { ...@@ -564,16 +565,35 @@ static const struct file_operations fops_fw_stats = {
.llseek = default_llseek, .llseek = default_llseek,
}; };
/* This is a clean assert crash in firmware. */
static int ath10k_debug_fw_assert(struct ath10k *ar)
{
struct wmi_vdev_install_key_cmd *cmd;
struct sk_buff *skb;
skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
if (!skb)
return -ENOMEM;
cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
memset(cmd, 0, sizeof(*cmd));
/* big enough number so that firmware asserts */
cmd->vdev_id = __cpu_to_le32(0x7ffe);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->vdev_install_key_cmdid);
}
static ssize_t ath10k_read_simulate_fw_crash(struct file *file, static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
char __user *user_buf, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
const char buf[] = "To simulate firmware crash write one of the" const char buf[] =
" keywords to this file:\n `soft` - this will send" "To simulate firmware crash write one of the keywords to this file:\n"
" WMI_FORCE_FW_HANG_ASSERT to firmware if FW" "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
" supports that command.\n `hard` - this will send" "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
" to firmware command with illegal parameters" "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n";
" causing firmware crash.\n";
return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
} }
...@@ -621,7 +641,11 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file, ...@@ -621,7 +641,11 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
* firmware variants in order to force a firmware crash. * firmware variants in order to force a firmware crash.
*/ */
ret = ath10k_wmi_vdev_set_param(ar, 0x7fff, ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
ar->wmi.vdev_param->rts_threshold, 0); ar->wmi.vdev_param->rts_threshold,
0);
} else if (!strcmp(buf, "assert")) {
ath10k_info(ar, "simulating firmware assert crash\n");
ret = ath10k_debug_fw_assert(ar);
} else { } else {
ret = -EINVAL; ret = -EINVAL;
goto exit; goto exit;
...@@ -840,8 +864,8 @@ static void ath10k_debug_htt_stats_dwork(struct work_struct *work) ...@@ -840,8 +864,8 @@ static void ath10k_debug_htt_stats_dwork(struct work_struct *work)
} }
static ssize_t ath10k_read_htt_stats_mask(struct file *file, static ssize_t ath10k_read_htt_stats_mask(struct file *file,
char __user *user_buf, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct ath10k *ar = file->private_data; struct ath10k *ar = file->private_data;
char buf[32]; char buf[32];
...@@ -853,8 +877,8 @@ static ssize_t ath10k_read_htt_stats_mask(struct file *file, ...@@ -853,8 +877,8 @@ static ssize_t ath10k_read_htt_stats_mask(struct file *file,
} }
static ssize_t ath10k_write_htt_stats_mask(struct file *file, static ssize_t ath10k_write_htt_stats_mask(struct file *file,
const char __user *user_buf, const char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct ath10k *ar = file->private_data; struct ath10k *ar = file->private_data;
unsigned long mask; unsigned long mask;
...@@ -959,8 +983,8 @@ static const struct file_operations fops_htt_max_amsdu_ampdu = { ...@@ -959,8 +983,8 @@ static const struct file_operations fops_htt_max_amsdu_ampdu = {
}; };
static ssize_t ath10k_read_fw_dbglog(struct file *file, static ssize_t ath10k_read_fw_dbglog(struct file *file,
char __user *user_buf, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct ath10k *ar = file->private_data; struct ath10k *ar = file->private_data;
unsigned int len; unsigned int len;
...@@ -1132,19 +1156,28 @@ static const struct file_operations fops_dfs_stats = { ...@@ -1132,19 +1156,28 @@ static const struct file_operations fops_dfs_stats = {
int ath10k_debug_create(struct ath10k *ar) int ath10k_debug_create(struct ath10k *ar)
{ {
int ret;
ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data)); ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
if (!ar->debug.fw_crash_data) { if (!ar->debug.fw_crash_data)
ret = -ENOMEM; return -ENOMEM;
goto err;
}
return 0;
}
void ath10k_debug_destroy(struct ath10k *ar)
{
vfree(ar->debug.fw_crash_data);
ar->debug.fw_crash_data = NULL;
}
int ath10k_debug_register(struct ath10k *ar)
{
ar->debug.debugfs_phy = debugfs_create_dir("ath10k", ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
ar->hw->wiphy->debugfsdir); ar->hw->wiphy->debugfsdir);
if (!ar->debug.debugfs_phy) { if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
ret = -ENOMEM; if (IS_ERR(ar->debug.debugfs_phy))
goto err_free_fw_crash_data; return PTR_ERR(ar->debug.debugfs_phy);
return -ENOMEM;
} }
INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork, INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
...@@ -1192,17 +1225,10 @@ int ath10k_debug_create(struct ath10k *ar) ...@@ -1192,17 +1225,10 @@ int ath10k_debug_create(struct ath10k *ar)
} }
return 0; return 0;
err_free_fw_crash_data:
vfree(ar->debug.fw_crash_data);
err:
return ret;
} }
void ath10k_debug_destroy(struct ath10k *ar) void ath10k_debug_unregister(struct ath10k *ar)
{ {
vfree(ar->debug.fw_crash_data);
cancel_delayed_work_sync(&ar->debug.htt_stats_dwork); cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
} }
...@@ -1223,7 +1249,7 @@ void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask, ...@@ -1223,7 +1249,7 @@ void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
if (ath10k_debug_mask & mask) if (ath10k_debug_mask & mask)
dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf); dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf);
trace_ath10k_log_dbg(mask, &vaf); trace_ath10k_log_dbg(ar, mask, &vaf);
va_end(args); va_end(args);
} }
...@@ -1242,7 +1268,7 @@ void ath10k_dbg_dump(struct ath10k *ar, ...@@ -1242,7 +1268,7 @@ void ath10k_dbg_dump(struct ath10k *ar,
} }
/* tracing code doesn't like null strings :/ */ /* tracing code doesn't like null strings :/ */
trace_ath10k_log_dbg_dump(msg ? msg : "", prefix ? prefix : "", trace_ath10k_log_dbg_dump(ar, msg ? msg : "", prefix ? prefix : "",
buf, len); buf, len);
} }
EXPORT_SYMBOL(ath10k_dbg_dump); EXPORT_SYMBOL(ath10k_dbg_dump);
......
...@@ -34,6 +34,7 @@ enum ath10k_debug_mask { ...@@ -34,6 +34,7 @@ enum ath10k_debug_mask {
ATH10K_DBG_DATA = 0x00000200, ATH10K_DBG_DATA = 0x00000200,
ATH10K_DBG_BMI = 0x00000400, ATH10K_DBG_BMI = 0x00000400,
ATH10K_DBG_REGULATORY = 0x00000800, ATH10K_DBG_REGULATORY = 0x00000800,
ATH10K_DBG_TESTMODE = 0x00001000,
ATH10K_DBG_ANY = 0xffffffff, ATH10K_DBG_ANY = 0xffffffff,
}; };
...@@ -49,6 +50,8 @@ int ath10k_debug_start(struct ath10k *ar); ...@@ -49,6 +50,8 @@ int ath10k_debug_start(struct ath10k *ar);
void ath10k_debug_stop(struct ath10k *ar); void ath10k_debug_stop(struct ath10k *ar);
int ath10k_debug_create(struct ath10k *ar); int ath10k_debug_create(struct ath10k *ar);
void ath10k_debug_destroy(struct ath10k *ar); void ath10k_debug_destroy(struct ath10k *ar);
int ath10k_debug_register(struct ath10k *ar);
void ath10k_debug_unregister(struct ath10k *ar);
void ath10k_debug_read_service_map(struct ath10k *ar, void ath10k_debug_read_service_map(struct ath10k *ar,
void *service_map, void *service_map,
size_t map_size); size_t map_size);
...@@ -80,6 +83,15 @@ static inline void ath10k_debug_destroy(struct ath10k *ar) ...@@ -80,6 +83,15 @@ static inline void ath10k_debug_destroy(struct ath10k *ar)
{ {
} }
static inline int ath10k_debug_register(struct ath10k *ar)
{
return 0;
}
static inline void ath10k_debug_unregister(struct ath10k *ar)
{
}
static inline void ath10k_debug_read_service_map(struct ath10k *ar, static inline void ath10k_debug_read_service_map(struct ath10k *ar,
void *service_map, void *service_map,
size_t map_size) size_t map_size)
......
...@@ -91,7 +91,6 @@ struct ath10k_hif_ops { ...@@ -91,7 +91,6 @@ struct ath10k_hif_ops {
int (*resume)(struct ath10k *ar); int (*resume)(struct ath10k *ar);
}; };
static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id, static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
struct ath10k_hif_sg_item *items, struct ath10k_hif_sg_item *items,
int n_items) int n_items)
......
...@@ -45,10 +45,8 @@ static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar) ...@@ -45,10 +45,8 @@ static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar)
struct ath10k_skb_cb *skb_cb; struct ath10k_skb_cb *skb_cb;
skb = dev_alloc_skb(ATH10K_HTC_CONTROL_BUFFER_SIZE); skb = dev_alloc_skb(ATH10K_HTC_CONTROL_BUFFER_SIZE);
if (!skb) { if (!skb)
ath10k_warn(ar, "Unable to allocate ctrl skb\n");
return NULL; return NULL;
}
skb_reserve(skb, 20); /* FIXME: why 20 bytes? */ skb_reserve(skb, 20); /* FIXME: why 20 bytes? */
WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb"); WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb");
...@@ -569,7 +567,7 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) ...@@ -569,7 +567,7 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
ath10k_hif_send_complete_check(htc->ar, i, 1); ath10k_hif_send_complete_check(htc->ar, i, 1);
status = wait_for_completion_timeout(&htc->ctl_resp, status = wait_for_completion_timeout(&htc->ctl_resp,
ATH10K_HTC_WAIT_TIMEOUT_HZ); ATH10K_HTC_WAIT_TIMEOUT_HZ);
if (status == 0) if (status == 0)
status = -ETIMEDOUT; status = -ETIMEDOUT;
...@@ -806,10 +804,8 @@ struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size) ...@@ -806,10 +804,8 @@ struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size)
struct sk_buff *skb; struct sk_buff *skb;
skb = dev_alloc_skb(size + sizeof(struct ath10k_htc_hdr)); skb = dev_alloc_skb(size + sizeof(struct ath10k_htc_hdr));
if (!skb) { if (!skb)
ath10k_warn(ar, "could not allocate HTC tx skb\n");
return NULL; return NULL;
}
skb_reserve(skb, sizeof(struct ath10k_htc_hdr)); skb_reserve(skb, sizeof(struct ath10k_htc_hdr));
......
...@@ -214,7 +214,6 @@ struct ath10k_htc_frame { ...@@ -214,7 +214,6 @@ struct ath10k_htc_frame {
struct ath10k_htc_record trailer[0]; struct ath10k_htc_record trailer[0];
} __packed __aligned(4); } __packed __aligned(4);
/*******************/ /*******************/
/* Host-side stuff */ /* Host-side stuff */
/*******************/ /*******************/
......
...@@ -101,7 +101,7 @@ int ath10k_htt_setup(struct ath10k_htt *htt) ...@@ -101,7 +101,7 @@ int ath10k_htt_setup(struct ath10k_htt *htt)
return status; return status;
status = wait_for_completion_timeout(&htt->target_version_received, status = wait_for_completion_timeout(&htt->target_version_received,
HTT_TARGET_VERSION_TIMEOUT_HZ); HTT_TARGET_VERSION_TIMEOUT_HZ);
if (status <= 0) { if (status <= 0) {
ath10k_warn(ar, "htt version request timed out\n"); ath10k_warn(ar, "htt version request timed out\n");
return -ETIMEDOUT; return -ETIMEDOUT;
......
...@@ -265,7 +265,6 @@ enum htt_mgmt_tx_status { ...@@ -265,7 +265,6 @@ enum htt_mgmt_tx_status {
/*=== target -> host messages ===============================================*/ /*=== target -> host messages ===============================================*/
enum htt_t2h_msg_type { enum htt_t2h_msg_type {
HTT_T2H_MSG_TYPE_VERSION_CONF = 0x0, HTT_T2H_MSG_TYPE_VERSION_CONF = 0x0,
HTT_T2H_MSG_TYPE_RX_IND = 0x1, HTT_T2H_MSG_TYPE_RX_IND = 0x1,
...@@ -1032,6 +1031,7 @@ static inline struct htt_stats_conf_item *htt_stats_conf_next_item( ...@@ -1032,6 +1031,7 @@ static inline struct htt_stats_conf_item *htt_stats_conf_next_item(
{ {
return (void *)item + sizeof(*item) + roundup(item->length, 4); return (void *)item + sizeof(*item) + roundup(item->length, 4);
} }
/* /*
* host -> target FRAG DESCRIPTOR/MSDU_EXT DESC bank * host -> target FRAG DESCRIPTOR/MSDU_EXT DESC bank
* *
...@@ -1148,7 +1148,6 @@ struct htt_resp { ...@@ -1148,7 +1148,6 @@ struct htt_resp {
}; };
} __packed; } __packed;
/*** host side structures follow ***/ /*** host side structures follow ***/
struct htt_tx_done { struct htt_tx_done {
......
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
/* when under memory pressure rx ring refill may fail and needs a retry */ /* when under memory pressure rx ring refill may fail and needs a retry */
#define HTT_RX_RING_REFILL_RETRY_MS 50 #define HTT_RX_RING_REFILL_RETRY_MS 50
static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb); static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb);
static void ath10k_htt_txrx_compl_task(unsigned long ptr); static void ath10k_htt_txrx_compl_task(unsigned long ptr);
...@@ -133,7 +132,7 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num) ...@@ -133,7 +132,7 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num)
dma_addr_t paddr; dma_addr_t paddr;
int ret = 0, idx; int ret = 0, idx;
idx = __le32_to_cpu(*(htt->rx_ring.alloc_idx.vaddr)); idx = __le32_to_cpu(*htt->rx_ring.alloc_idx.vaddr);
while (num > 0) { while (num > 0) {
skb = dev_alloc_skb(HTT_RX_BUF_SIZE + HTT_RX_DESC_ALIGN); skb = dev_alloc_skb(HTT_RX_BUF_SIZE + HTT_RX_DESC_ALIGN);
if (!skb) { if (!skb) {
...@@ -171,7 +170,7 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num) ...@@ -171,7 +170,7 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num)
} }
fail: fail:
*(htt->rx_ring.alloc_idx.vaddr) = __cpu_to_le32(idx); *htt->rx_ring.alloc_idx.vaddr = __cpu_to_le32(idx);
return ret; return ret;
} }
...@@ -223,6 +222,7 @@ static void ath10k_htt_rx_msdu_buff_replenish(struct ath10k_htt *htt) ...@@ -223,6 +222,7 @@ static void ath10k_htt_rx_msdu_buff_replenish(struct ath10k_htt *htt)
static void ath10k_htt_rx_ring_refill_retry(unsigned long arg) static void ath10k_htt_rx_ring_refill_retry(unsigned long arg)
{ {
struct ath10k_htt *htt = (struct ath10k_htt *)arg; struct ath10k_htt *htt = (struct ath10k_htt *)arg;
ath10k_htt_rx_msdu_buff_replenish(htt); ath10k_htt_rx_msdu_buff_replenish(htt);
} }
...@@ -314,7 +314,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -314,7 +314,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
{ {
struct ath10k *ar = htt->ar; struct ath10k *ar = htt->ar;
int msdu_len, msdu_chaining = 0; int msdu_len, msdu_chaining = 0;
struct sk_buff *msdu; struct sk_buff *msdu, *next;
struct htt_rx_desc *rx_desc; struct htt_rx_desc *rx_desc;
lockdep_assert_held(&htt->rx_ring.lock); lockdep_assert_held(&htt->rx_ring.lock);
...@@ -450,11 +450,11 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -450,11 +450,11 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
if (last_msdu) { if (last_msdu) {
msdu->next = NULL; msdu->next = NULL;
break; break;
} else {
struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt);
msdu->next = next;
msdu = next;
} }
next = ath10k_htt_rx_netbuf_pop(htt);
msdu->next = next;
msdu = next;
} }
*tail_msdu = msdu; *tail_msdu = msdu;
...@@ -480,6 +480,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -480,6 +480,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
static void ath10k_htt_rx_replenish_task(unsigned long ptr) static void ath10k_htt_rx_replenish_task(unsigned long ptr)
{ {
struct ath10k_htt *htt = (struct ath10k_htt *)ptr; struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
ath10k_htt_rx_msdu_buff_replenish(htt); ath10k_htt_rx_msdu_buff_replenish(htt);
} }
...@@ -488,6 +489,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) ...@@ -488,6 +489,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
struct ath10k *ar = htt->ar; struct ath10k *ar = htt->ar;
dma_addr_t paddr; dma_addr_t paddr;
void *vaddr; void *vaddr;
size_t size;
struct timer_list *timer = &htt->rx_ring.refill_retry_timer; struct timer_list *timer = &htt->rx_ring.refill_retry_timer;
htt->rx_ring.size = ath10k_htt_rx_ring_size(htt); htt->rx_ring.size = ath10k_htt_rx_ring_size(htt);
...@@ -515,9 +517,9 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) ...@@ -515,9 +517,9 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
if (!htt->rx_ring.netbufs_ring) if (!htt->rx_ring.netbufs_ring)
goto err_netbuf; goto err_netbuf;
vaddr = dma_alloc_coherent(htt->ar->dev, size = htt->rx_ring.size * sizeof(htt->rx_ring.paddrs_ring);
(htt->rx_ring.size * sizeof(htt->rx_ring.paddrs_ring)),
&paddr, GFP_DMA); vaddr = dma_alloc_coherent(htt->ar->dev, size, &paddr, GFP_DMA);
if (!vaddr) if (!vaddr)
goto err_dma_ring; goto err_dma_ring;
...@@ -625,19 +627,21 @@ static struct ieee80211_hdr *ath10k_htt_rx_skb_get_hdr(struct sk_buff *skb) ...@@ -625,19 +627,21 @@ static struct ieee80211_hdr *ath10k_htt_rx_skb_get_hdr(struct sk_buff *skb)
rxd = (void *)skb->data - sizeof(*rxd); rxd = (void *)skb->data - sizeof(*rxd);
fmt = MS(__le32_to_cpu(rxd->msdu_start.info1), fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
RX_MSDU_START_INFO1_DECAP_FORMAT); RX_MSDU_START_INFO1_DECAP_FORMAT);
if (fmt == RX_MSDU_DECAP_RAW) if (fmt == RX_MSDU_DECAP_RAW)
return (void *)skb->data; return (void *)skb->data;
else
return (void *)skb->data - RX_HTT_HDR_STATUS_LEN; return (void *)skb->data - RX_HTT_HDR_STATUS_LEN;
} }
/* This function only applies for first msdu in an msdu chain */ /* This function only applies for first msdu in an msdu chain */
static bool ath10k_htt_rx_hdr_is_amsdu(struct ieee80211_hdr *hdr) static bool ath10k_htt_rx_hdr_is_amsdu(struct ieee80211_hdr *hdr)
{ {
u8 *qc;
if (ieee80211_is_data_qos(hdr->frame_control)) { if (ieee80211_is_data_qos(hdr->frame_control)) {
u8 *qc = ieee80211_get_qos_ctl(hdr); qc = ieee80211_get_qos_ctl(hdr);
if (qc[0] & 0x80) if (qc[0] & 0x80)
return true; return true;
} }
...@@ -914,7 +918,7 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, ...@@ -914,7 +918,7 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
rxd = (void *)skb->data - sizeof(*rxd); rxd = (void *)skb->data - sizeof(*rxd);
enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
RX_MPDU_START_INFO0_ENCRYPT_TYPE); RX_MPDU_START_INFO0_ENCRYPT_TYPE);
hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status; hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
hdr_len = ieee80211_hdrlen(hdr->frame_control); hdr_len = ieee80211_hdrlen(hdr->frame_control);
...@@ -950,8 +954,8 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, ...@@ -950,8 +954,8 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
/* pull decapped header and copy SA & DA */ /* pull decapped header and copy SA & DA */
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr); hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
memcpy(da, ieee80211_get_DA(hdr), ETH_ALEN); ether_addr_copy(da, ieee80211_get_DA(hdr));
memcpy(sa, ieee80211_get_SA(hdr), ETH_ALEN); ether_addr_copy(sa, ieee80211_get_SA(hdr));
skb_pull(skb, hdr_len); skb_pull(skb, hdr_len);
/* push original 802.11 header */ /* push original 802.11 header */
...@@ -968,8 +972,8 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, ...@@ -968,8 +972,8 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
/* original 802.11 header has a different DA and in /* original 802.11 header has a different DA and in
* case of 4addr it may also have different SA * case of 4addr it may also have different SA
*/ */
memcpy(ieee80211_get_DA(hdr), da, ETH_ALEN); ether_addr_copy(ieee80211_get_DA(hdr), da);
memcpy(ieee80211_get_SA(hdr), sa, ETH_ALEN); ether_addr_copy(ieee80211_get_SA(hdr), sa);
break; break;
case RX_MSDU_DECAP_ETHERNET2_DIX: case RX_MSDU_DECAP_ETHERNET2_DIX:
/* strip ethernet header and insert decapped 802.11 /* strip ethernet header and insert decapped 802.11
...@@ -1029,9 +1033,9 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt, ...@@ -1029,9 +1033,9 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt,
rxd = (void *)skb->data - sizeof(*rxd); rxd = (void *)skb->data - sizeof(*rxd);
fmt = MS(__le32_to_cpu(rxd->msdu_start.info1), fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
RX_MSDU_START_INFO1_DECAP_FORMAT); RX_MSDU_START_INFO1_DECAP_FORMAT);
enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
RX_MPDU_START_INFO0_ENCRYPT_TYPE); RX_MPDU_START_INFO0_ENCRYPT_TYPE);
hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status; hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
hdr_len = ieee80211_hdrlen(hdr->frame_control); hdr_len = ieee80211_hdrlen(hdr->frame_control);
...@@ -1332,7 +1336,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -1332,7 +1336,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
} }
static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
struct htt_rx_fragment_indication *frag) struct htt_rx_fragment_indication *frag)
{ {
struct ath10k *ar = htt->ar; struct ath10k *ar = htt->ar;
struct sk_buff *msdu_head, *msdu_tail; struct sk_buff *msdu_head, *msdu_tail;
...@@ -1378,7 +1382,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ...@@ -1378,7 +1382,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
tkip_mic_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR); tkip_mic_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
decrypt_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR); decrypt_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR);
fmt = MS(__le32_to_cpu(rxd->msdu_start.info1), fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
RX_MSDU_START_INFO1_DECAP_FORMAT); RX_MSDU_START_INFO1_DECAP_FORMAT);
if (fmt != RX_MSDU_DECAP_RAW) { if (fmt != RX_MSDU_DECAP_RAW) {
ath10k_warn(ar, "we dont support non-raw fragmented rx yet\n"); ath10k_warn(ar, "we dont support non-raw fragmented rx yet\n");
...@@ -1654,7 +1658,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) ...@@ -1654,7 +1658,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
/* FIX THIS */ /* FIX THIS */
break; break;
case HTT_T2H_MSG_TYPE_STATS_CONF: case HTT_T2H_MSG_TYPE_STATS_CONF:
trace_ath10k_htt_stats(skb->data, skb->len); trace_ath10k_htt_stats(ar, skb->data, skb->len);
break; break;
case HTT_T2H_MSG_TYPE_TX_INSPECT_IND: case HTT_T2H_MSG_TYPE_TX_INSPECT_IND:
/* Firmware can return tx frames if it's unable to fully /* Firmware can return tx frames if it's unable to fully
......
...@@ -154,7 +154,6 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt) ...@@ -154,7 +154,6 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
kfree(htt->pending_tx); kfree(htt->pending_tx);
kfree(htt->used_msdu_ids); kfree(htt->used_msdu_ids);
dma_pool_destroy(htt->tx_pool); dma_pool_destroy(htt->tx_pool);
return;
} }
void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
...@@ -377,7 +376,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -377,7 +376,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
int msdu_id = -1; int msdu_id = -1;
int res; int res;
res = ath10k_htt_tx_inc_pending(htt); res = ath10k_htt_tx_inc_pending(htt);
if (res) if (res)
goto err; goto err;
......
...@@ -36,6 +36,8 @@ ...@@ -36,6 +36,8 @@
#define ATH10K_FW_API2_FILE "firmware-2.bin" #define ATH10K_FW_API2_FILE "firmware-2.bin"
#define ATH10K_FW_API3_FILE "firmware-3.bin" #define ATH10K_FW_API3_FILE "firmware-3.bin"
#define ATH10K_FW_UTF_FILE "utf.bin"
/* includes also the null byte */ /* includes also the null byte */
#define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K" #define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K"
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "wmi.h" #include "wmi.h"
#include "htt.h" #include "htt.h"
#include "txrx.h" #include "txrx.h"
#include "testmode.h"
/**********/ /**********/
/* Crypto */ /* Crypto */
...@@ -198,7 +199,7 @@ static int ath10k_clear_vdev_key(struct ath10k_vif *arvif, ...@@ -198,7 +199,7 @@ static int ath10k_clear_vdev_key(struct ath10k_vif *arvif,
list_for_each_entry(peer, &ar->peers, list) { list_for_each_entry(peer, &ar->peers, list) {
for (i = 0; i < ARRAY_SIZE(peer->keys); i++) { for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
if (peer->keys[i] == key) { if (peer->keys[i] == key) {
memcpy(addr, peer->addr, ETH_ALEN); ether_addr_copy(addr, peer->addr);
peer->keys[i] = NULL; peer->keys[i] = NULL;
break; break;
} }
...@@ -224,7 +225,6 @@ static int ath10k_clear_vdev_key(struct ath10k_vif *arvif, ...@@ -224,7 +225,6 @@ static int ath10k_clear_vdev_key(struct ath10k_vif *arvif,
return first_errno; return first_errno;
} }
/*********************/ /*********************/
/* General utilities */ /* General utilities */
/*********************/ /*********************/
...@@ -493,19 +493,6 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar) ...@@ -493,19 +493,6 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
return 0; return 0;
} }
static bool ath10k_monitor_is_enabled(struct ath10k *ar)
{
lockdep_assert_held(&ar->conf_mutex);
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac monitor refs: promisc %d monitor %d cac %d\n",
ar->promisc, ar->monitor,
test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags));
return ar->promisc || ar->monitor ||
test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
}
static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
{ {
struct cfg80211_chan_def *chandef = &ar->chandef; struct cfg80211_chan_def *chandef = &ar->chandef;
...@@ -649,16 +636,6 @@ static int ath10k_monitor_start(struct ath10k *ar) ...@@ -649,16 +636,6 @@ static int ath10k_monitor_start(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
if (!ath10k_monitor_is_enabled(ar)) {
ath10k_warn(ar, "trying to start monitor with no references\n");
return 0;
}
if (ar->monitor_started) {
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor already started\n");
return 0;
}
ret = ath10k_monitor_vdev_create(ar); ret = ath10k_monitor_vdev_create(ar);
if (ret) { if (ret) {
ath10k_warn(ar, "failed to create monitor vdev: %d\n", ret); ath10k_warn(ar, "failed to create monitor vdev: %d\n", ret);
...@@ -678,34 +655,51 @@ static int ath10k_monitor_start(struct ath10k *ar) ...@@ -678,34 +655,51 @@ static int ath10k_monitor_start(struct ath10k *ar)
return 0; return 0;
} }
static void ath10k_monitor_stop(struct ath10k *ar) static int ath10k_monitor_stop(struct ath10k *ar)
{ {
int ret; int ret;
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
if (ath10k_monitor_is_enabled(ar)) {
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac monitor will be stopped later\n");
return;
}
if (!ar->monitor_started) {
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac monitor probably failed to start earlier\n");
return;
}
ret = ath10k_monitor_vdev_stop(ar); ret = ath10k_monitor_vdev_stop(ar);
if (ret) if (ret) {
ath10k_warn(ar, "failed to stop monitor vdev: %d\n", ret); ath10k_warn(ar, "failed to stop monitor vdev: %d\n", ret);
return ret;
}
ret = ath10k_monitor_vdev_delete(ar); ret = ath10k_monitor_vdev_delete(ar);
if (ret) if (ret) {
ath10k_warn(ar, "failed to delete monitor vdev: %d\n", ret); ath10k_warn(ar, "failed to delete monitor vdev: %d\n", ret);
return ret;
}
ar->monitor_started = false; ar->monitor_started = false;
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor stopped\n"); ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor stopped\n");
return 0;
}
static int ath10k_monitor_recalc(struct ath10k *ar)
{
bool should_start;
lockdep_assert_held(&ar->conf_mutex);
should_start = ar->monitor ||
ar->filter_flags & FIF_PROMISC_IN_BSS ||
test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac monitor recalc started? %d should? %d\n",
ar->monitor_started, should_start);
if (should_start == ar->monitor_started)
return 0;
if (should_start)
return ath10k_monitor_start(ar);
return ath10k_monitor_stop(ar);
} }
static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif) static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif)
...@@ -736,7 +730,7 @@ static int ath10k_start_cac(struct ath10k *ar) ...@@ -736,7 +730,7 @@ static int ath10k_start_cac(struct ath10k *ar)
set_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); set_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
ret = ath10k_monitor_start(ar); ret = ath10k_monitor_recalc(ar);
if (ret) { if (ret) {
ath10k_warn(ar, "failed to start monitor (cac): %d\n", ret); ath10k_warn(ar, "failed to start monitor (cac): %d\n", ret);
clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
...@@ -901,7 +895,7 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif) ...@@ -901,7 +895,7 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif)
} }
static void ath10k_control_beaconing(struct ath10k_vif *arvif, static void ath10k_control_beaconing(struct ath10k_vif *arvif,
struct ieee80211_bss_conf *info) struct ieee80211_bss_conf *info)
{ {
struct ath10k *ar = arvif->ar; struct ath10k *ar = arvif->ar;
int ret = 0; int ret = 0;
...@@ -936,7 +930,7 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif, ...@@ -936,7 +930,7 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif,
return; return;
arvif->aid = 0; arvif->aid = 0;
memcpy(arvif->bssid, info->bssid, ETH_ALEN); ether_addr_copy(arvif->bssid, info->bssid);
ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
arvif->bssid); arvif->bssid);
...@@ -1056,7 +1050,7 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar, ...@@ -1056,7 +1050,7 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
{ {
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
memcpy(arg->addr, sta->addr, ETH_ALEN); ether_addr_copy(arg->addr, sta->addr);
arg->vdev_id = arvif->vdev_id; arg->vdev_id = arvif->vdev_id;
arg->peer_aid = sta->aid; arg->peer_aid = sta->aid;
arg->peer_flags |= WMI_PEER_AUTH; arg->peer_flags |= WMI_PEER_AUTH;
...@@ -1111,9 +1105,9 @@ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar, ...@@ -1111,9 +1105,9 @@ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
ies = rcu_dereference(bss->ies); ies = rcu_dereference(bss->ies);
wpaie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, wpaie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
WLAN_OUI_TYPE_MICROSOFT_WPA, WLAN_OUI_TYPE_MICROSOFT_WPA,
ies->data, ies->data,
ies->len); ies->len);
rcu_read_unlock(); rcu_read_unlock();
cfg80211_put_bss(ar->hw->wiphy, bss); cfg80211_put_bss(ar->hw->wiphy, bss);
} }
...@@ -1163,6 +1157,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar, ...@@ -1163,6 +1157,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
{ {
const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
int i, n; int i, n;
u32 stbc;
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
...@@ -1199,7 +1194,6 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar, ...@@ -1199,7 +1194,6 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
} }
if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) { if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) {
u32 stbc;
stbc = ht_cap->cap & IEEE80211_HT_CAP_RX_STBC; stbc = ht_cap->cap & IEEE80211_HT_CAP_RX_STBC;
stbc = stbc >> IEEE80211_HT_CAP_RX_STBC_SHIFT; stbc = stbc >> IEEE80211_HT_CAP_RX_STBC_SHIFT;
stbc = stbc << WMI_RC_RX_STBC_FLAG_S; stbc = stbc << WMI_RC_RX_STBC_FLAG_S;
...@@ -1267,7 +1261,6 @@ static int ath10k_peer_assoc_qos_ap(struct ath10k *ar, ...@@ -1267,7 +1261,6 @@ static int ath10k_peer_assoc_qos_ap(struct ath10k *ar,
uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN | uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN |
WMI_AP_PS_UAPSD_AC0_TRIGGER_EN; WMI_AP_PS_UAPSD_AC0_TRIGGER_EN;
if (sta->max_sp < MAX_WMI_AP_PS_PEER_PARAM_MAX_SP) if (sta->max_sp < MAX_WMI_AP_PS_PEER_PARAM_MAX_SP)
max_sp = sta->max_sp; max_sp = sta->max_sp;
...@@ -1296,7 +1289,8 @@ static int ath10k_peer_assoc_qos_ap(struct ath10k *ar, ...@@ -1296,7 +1289,8 @@ static int ath10k_peer_assoc_qos_ap(struct ath10k *ar,
sta->listen_interval - mac80211 patch required. sta->listen_interval - mac80211 patch required.
Currently use 10 seconds */ Currently use 10 seconds */
ret = ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id, sta->addr, ret = ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id, sta->addr,
WMI_AP_PS_PEER_PARAM_AGEOUT_TIME, 10); WMI_AP_PS_PEER_PARAM_AGEOUT_TIME,
10);
if (ret) { if (ret) {
ath10k_warn(ar, "failed to set ap ps peer param ageout time for vdev %i: %d\n", ath10k_warn(ar, "failed to set ap ps peer param ageout time for vdev %i: %d\n",
arvif->vdev_id, ret); arvif->vdev_id, ret);
...@@ -1320,7 +1314,6 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, ...@@ -1320,7 +1314,6 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
arg->peer_flags |= WMI_PEER_VHT; arg->peer_flags |= WMI_PEER_VHT;
arg->peer_vht_caps = vht_cap->cap; arg->peer_vht_caps = vht_cap->cap;
ampdu_factor = (vht_cap->cap & ampdu_factor = (vht_cap->cap &
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >> IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
...@@ -1531,7 +1524,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, ...@@ -1531,7 +1524,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
arvif->vdev_id, bss_conf->bssid, bss_conf->aid); arvif->vdev_id, bss_conf->bssid, bss_conf->aid);
arvif->aid = bss_conf->aid; arvif->aid = bss_conf->aid;
memcpy(arvif->bssid, bss_conf->bssid, ETH_ALEN); ether_addr_copy(arvif->bssid, bss_conf->bssid);
ret = ath10k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid); ret = ath10k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid);
if (ret) { if (ret) {
...@@ -1615,7 +1608,7 @@ static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, ...@@ -1615,7 +1608,7 @@ static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
return ret; return ret;
} }
if (!sta->wme) { if (!sta->wme && !reassoc) {
arvif->num_legacy_stations++; arvif->num_legacy_stations++;
ret = ath10k_recalc_rtscts_prot(arvif); ret = ath10k_recalc_rtscts_prot(arvif);
if (ret) { if (ret) {
...@@ -1863,11 +1856,10 @@ static u8 ath10k_tx_h_get_tid(struct ieee80211_hdr *hdr) ...@@ -1863,11 +1856,10 @@ static u8 ath10k_tx_h_get_tid(struct ieee80211_hdr *hdr)
return ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; return ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
} }
static u8 ath10k_tx_h_get_vdev_id(struct ath10k *ar, static u8 ath10k_tx_h_get_vdev_id(struct ath10k *ar, struct ieee80211_vif *vif)
struct ieee80211_tx_info *info)
{ {
if (info->control.vif) if (vif)
return ath10k_vif_to_arvif(info->control.vif)->vdev_id; return ath10k_vif_to_arvif(vif)->vdev_id;
if (ar->monitor_started) if (ar->monitor_started)
return ar->monitor_vdev_id; return ar->monitor_vdev_id;
...@@ -2323,7 +2315,7 @@ static void ath10k_tx(struct ieee80211_hw *hw, ...@@ -2323,7 +2315,7 @@ static void ath10k_tx(struct ieee80211_hw *hw,
ATH10K_SKB_CB(skb)->htt.is_offchan = false; ATH10K_SKB_CB(skb)->htt.is_offchan = false;
ATH10K_SKB_CB(skb)->htt.tid = ath10k_tx_h_get_tid(hdr); ATH10K_SKB_CB(skb)->htt.tid = ath10k_tx_h_get_tid(hdr);
ATH10K_SKB_CB(skb)->vdev_id = ath10k_tx_h_get_vdev_id(ar, info); ATH10K_SKB_CB(skb)->vdev_id = ath10k_tx_h_get_vdev_id(ar, vif);
/* it makes no sense to process injected frames like that */ /* it makes no sense to process injected frames like that */
if (vif && vif->type != NL80211_IFTYPE_MONITOR) { if (vif && vif->type != NL80211_IFTYPE_MONITOR) {
...@@ -2369,12 +2361,14 @@ void ath10k_halt(struct ath10k *ar) ...@@ -2369,12 +2361,14 @@ void ath10k_halt(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
if (ath10k_monitor_is_enabled(ar)) { clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags); ar->filter_flags = 0;
ar->promisc = false; ar->monitor = false;
ar->monitor = false;
if (ar->monitor_started)
ath10k_monitor_stop(ar); ath10k_monitor_stop(ar);
}
ar->monitor_started = false;
ath10k_scan_finish(ar); ath10k_scan_finish(ar);
ath10k_peer_cleanup_all(ar); ath10k_peer_cleanup_all(ar);
...@@ -2485,6 +2479,9 @@ static int ath10k_start(struct ieee80211_hw *hw) ...@@ -2485,6 +2479,9 @@ static int ath10k_start(struct ieee80211_hw *hw)
WARN_ON(1); WARN_ON(1);
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
case ATH10K_STATE_UTF:
ret = -EBUSY;
goto err;
} }
ret = ath10k_hif_power_up(ar); ret = ath10k_hif_power_up(ar);
...@@ -2493,7 +2490,7 @@ static int ath10k_start(struct ieee80211_hw *hw) ...@@ -2493,7 +2490,7 @@ static int ath10k_start(struct ieee80211_hw *hw)
goto err_off; goto err_off;
} }
ret = ath10k_core_start(ar); ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
if (ret) { if (ret) {
ath10k_err(ar, "Could not init core: %d\n", ret); ath10k_err(ar, "Could not init core: %d\n", ret);
goto err_power_down; goto err_power_down;
...@@ -2629,7 +2626,7 @@ static void ath10k_config_chan(struct ath10k *ar) ...@@ -2629,7 +2626,7 @@ static void ath10k_config_chan(struct ath10k *ar)
/* First stop monitor interface. Some FW versions crash if there's a /* First stop monitor interface. Some FW versions crash if there's a
* lone monitor interface. */ * lone monitor interface. */
if (ar->monitor_started) if (ar->monitor_started)
ath10k_monitor_vdev_stop(ar); ath10k_monitor_stop(ar);
list_for_each_entry(arvif, &ar->arvifs, list) { list_for_each_entry(arvif, &ar->arvifs, list) {
if (!arvif->is_started) if (!arvif->is_started)
...@@ -2677,8 +2674,7 @@ static void ath10k_config_chan(struct ath10k *ar) ...@@ -2677,8 +2674,7 @@ static void ath10k_config_chan(struct ath10k *ar)
} }
} }
if (ath10k_monitor_is_enabled(ar)) ath10k_monitor_recalc(ar);
ath10k_monitor_vdev_start(ar, ar->monitor_vdev_id);
} }
static int ath10k_config(struct ieee80211_hw *hw, u32 changed) static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
...@@ -2733,19 +2729,10 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed) ...@@ -2733,19 +2729,10 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
ath10k_config_ps(ar); ath10k_config_ps(ar);
if (changed & IEEE80211_CONF_CHANGE_MONITOR) { if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
if (conf->flags & IEEE80211_CONF_MONITOR && !ar->monitor) { ar->monitor = conf->flags & IEEE80211_CONF_MONITOR;
ar->monitor = true; ret = ath10k_monitor_recalc(ar);
ret = ath10k_monitor_start(ar); if (ret)
if (ret) { ath10k_warn(ar, "failed to recalc monitor: %d\n", ret);
ath10k_warn(ar, "failed to start monitor (config): %d\n",
ret);
ar->monitor = false;
}
} else if (!(conf->flags & IEEE80211_CONF_MONITOR) &&
ar->monitor) {
ar->monitor = false;
ath10k_monitor_stop(ar);
}
} }
mutex_unlock(&ar->conf_mutex); mutex_unlock(&ar->conf_mutex);
...@@ -3009,18 +2996,9 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw, ...@@ -3009,18 +2996,9 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
*total_flags &= SUPPORTED_FILTERS; *total_flags &= SUPPORTED_FILTERS;
ar->filter_flags = *total_flags; ar->filter_flags = *total_flags;
if (ar->filter_flags & FIF_PROMISC_IN_BSS && !ar->promisc) { ret = ath10k_monitor_recalc(ar);
ar->promisc = true; if (ret)
ret = ath10k_monitor_start(ar); ath10k_warn(ar, "failed to recalc montior: %d\n", ret);
if (ret) {
ath10k_warn(ar, "failed to start monitor (promisc): %d\n",
ret);
ar->promisc = false;
}
} else if (!(ar->filter_flags & FIF_PROMISC_IN_BSS) && ar->promisc) {
ar->promisc = false;
ath10k_monitor_stop(ar);
}
mutex_unlock(&ar->conf_mutex); mutex_unlock(&ar->conf_mutex);
} }
...@@ -3033,7 +3011,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, ...@@ -3033,7 +3011,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
struct ath10k *ar = hw->priv; struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
int ret = 0; int ret = 0;
u32 vdev_param, pdev_param; u32 vdev_param, pdev_param, slottime, preamble;
mutex_lock(&ar->conf_mutex); mutex_lock(&ar->conf_mutex);
...@@ -3112,7 +3090,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, ...@@ -3112,7 +3090,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
* this is never erased as we it for crypto key * this is never erased as we it for crypto key
* clearing; this is FW requirement * clearing; this is FW requirement
*/ */
memcpy(arvif->bssid, info->bssid, ETH_ALEN); ether_addr_copy(arvif->bssid, info->bssid);
ath10k_dbg(ar, ATH10K_DBG_MAC, ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac vdev %d start %pM\n", "mac vdev %d start %pM\n",
...@@ -3154,7 +3132,6 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, ...@@ -3154,7 +3132,6 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
} }
if (changed & BSS_CHANGED_ERP_SLOT) { if (changed & BSS_CHANGED_ERP_SLOT) {
u32 slottime;
if (info->use_short_slot) if (info->use_short_slot)
slottime = WMI_VDEV_SLOT_TIME_SHORT; /* 9us */ slottime = WMI_VDEV_SLOT_TIME_SHORT; /* 9us */
...@@ -3173,7 +3150,6 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, ...@@ -3173,7 +3150,6 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
} }
if (changed & BSS_CHANGED_ERP_PREAMBLE) { if (changed & BSS_CHANGED_ERP_PREAMBLE) {
u32 preamble;
if (info->use_short_preamble) if (info->use_short_preamble)
preamble = WMI_VDEV_PREAMBLE_SHORT; preamble = WMI_VDEV_PREAMBLE_SHORT;
else else
...@@ -3192,8 +3168,16 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, ...@@ -3192,8 +3168,16 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
} }
if (changed & BSS_CHANGED_ASSOC) { if (changed & BSS_CHANGED_ASSOC) {
if (info->assoc) if (info->assoc) {
/* Workaround: Make sure monitor vdev is not running
* when associating to prevent some firmware revisions
* (e.g. 10.1 and 10.2) from crashing.
*/
if (ar->monitor_started)
ath10k_monitor_stop(ar);
ath10k_bss_assoc(hw, vif, info); ath10k_bss_assoc(hw, vif, info);
ath10k_monitor_recalc(ar);
}
} }
exit: exit:
...@@ -3580,7 +3564,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, ...@@ -3580,7 +3564,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
} }
static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif, static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif,
u16 ac, bool enable) u16 ac, bool enable)
{ {
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
u32 value = 0; u32 value = 0;
...@@ -4081,8 +4065,8 @@ ath10k_bitrate_mask_nss(const struct cfg80211_bitrate_mask *mask, ...@@ -4081,8 +4065,8 @@ ath10k_bitrate_mask_nss(const struct cfg80211_bitrate_mask *mask,
continue; continue;
else if (mask->control[band].ht_mcs[i] == 0x00) else if (mask->control[band].ht_mcs[i] == 0x00)
break; break;
else
return false; return false;
} }
ht_nss = i; ht_nss = i;
...@@ -4093,8 +4077,8 @@ ath10k_bitrate_mask_nss(const struct cfg80211_bitrate_mask *mask, ...@@ -4093,8 +4077,8 @@ ath10k_bitrate_mask_nss(const struct cfg80211_bitrate_mask *mask,
continue; continue;
else if (mask->control[band].vht_mcs[i] == 0x0000) else if (mask->control[band].vht_mcs[i] == 0x0000)
break; break;
else
return false; return false;
} }
vht_nss = i; vht_nss = i;
...@@ -4472,6 +4456,9 @@ static const struct ieee80211_ops ath10k_ops = { ...@@ -4472,6 +4456,9 @@ static const struct ieee80211_ops ath10k_ops = {
.sta_rc_update = ath10k_sta_rc_update, .sta_rc_update = ath10k_sta_rc_update,
.get_tsf = ath10k_get_tsf, .get_tsf = ath10k_get_tsf,
.ampdu_action = ath10k_ampdu_action, .ampdu_action = ath10k_ampdu_action,
CFG80211_TESTMODE_CMD(ath10k_tm_cmd)
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = ath10k_suspend, .suspend = ath10k_suspend,
.resume = ath10k_resume, .resume = ath10k_resume,
...@@ -4723,7 +4710,6 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) ...@@ -4723,7 +4710,6 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
return ht_cap; return ht_cap;
} }
static void ath10k_get_arvif_iter(void *data, u8 *mac, static void ath10k_get_arvif_iter(void *data, u8 *mac,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
......
...@@ -64,9 +64,6 @@ static const struct pci_device_id ath10k_pci_id_table[] = { ...@@ -64,9 +64,6 @@ static const struct pci_device_id ath10k_pci_id_table[] = {
{0} {0}
}; };
static int ath10k_pci_diag_read_access(struct ath10k *ar, u32 address,
u32 *data);
static void ath10k_pci_buffer_cleanup(struct ath10k *ar); static void ath10k_pci_buffer_cleanup(struct ath10k *ar);
static int ath10k_pci_cold_reset(struct ath10k *ar); static int ath10k_pci_cold_reset(struct ath10k *ar);
static int ath10k_pci_warm_reset(struct ath10k *ar); static int ath10k_pci_warm_reset(struct ath10k *ar);
...@@ -343,8 +340,8 @@ static void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar) ...@@ -343,8 +340,8 @@ static void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar)
/* IMPORTANT: this extra read transaction is required to /* IMPORTANT: this extra read transaction is required to
* flush the posted write buffer. */ * flush the posted write buffer. */
(void) ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + (void)ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
PCIE_INTR_ENABLE_ADDRESS); PCIE_INTR_ENABLE_ADDRESS);
} }
static void ath10k_pci_enable_legacy_irq(struct ath10k *ar) static void ath10k_pci_enable_legacy_irq(struct ath10k *ar)
...@@ -355,8 +352,8 @@ static void ath10k_pci_enable_legacy_irq(struct ath10k *ar) ...@@ -355,8 +352,8 @@ static void ath10k_pci_enable_legacy_irq(struct ath10k *ar)
/* IMPORTANT: this extra read transaction is required to /* IMPORTANT: this extra read transaction is required to
* flush the posted write buffer. */ * flush the posted write buffer. */
(void) ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + (void)ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
PCIE_INTR_ENABLE_ADDRESS); PCIE_INTR_ENABLE_ADDRESS);
} }
static inline const char *ath10k_pci_get_irq_method(struct ath10k *ar) static inline const char *ath10k_pci_get_irq_method(struct ath10k *ar)
...@@ -365,10 +362,11 @@ static inline const char *ath10k_pci_get_irq_method(struct ath10k *ar) ...@@ -365,10 +362,11 @@ static inline const char *ath10k_pci_get_irq_method(struct ath10k *ar)
if (ar_pci->num_msi_intrs > 1) if (ar_pci->num_msi_intrs > 1)
return "msi-x"; return "msi-x";
else if (ar_pci->num_msi_intrs == 1)
if (ar_pci->num_msi_intrs == 1)
return "msi"; return "msi";
else
return "legacy"; return "legacy";
} }
static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe) static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe)
...@@ -487,25 +485,6 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, ...@@ -487,25 +485,6 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
void *data_buf = NULL; void *data_buf = NULL;
int i; int i;
/*
* This code cannot handle reads to non-memory space. Redirect to the
* register read fn but preserve the multi word read capability of
* this fn
*/
if (address < DRAM_BASE_ADDRESS) {
if (!IS_ALIGNED(address, 4) ||
!IS_ALIGNED((unsigned long)data, 4))
return -EIO;
while ((nbytes >= 4) && ((ret = ath10k_pci_diag_read_access(
ar, address, (u32 *)data)) == 0)) {
nbytes -= sizeof(u32);
address += sizeof(u32);
data += sizeof(u32);
}
return ret;
}
ce_diag = ar_pci->ce_diag; ce_diag = ar_pci->ce_diag;
/* /*
...@@ -549,7 +528,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, ...@@ -549,7 +528,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
address); address);
ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0, ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0,
0); 0);
if (ret) if (ret)
goto done; goto done;
...@@ -569,7 +548,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, ...@@ -569,7 +548,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
goto done; goto done;
} }
if (buf != (u32) address) { if (buf != (u32)address) {
ret = -EIO; ret = -EIO;
goto done; goto done;
} }
...@@ -652,19 +631,7 @@ static int __ath10k_pci_diag_read_hi(struct ath10k *ar, void *dest, ...@@ -652,19 +631,7 @@ static int __ath10k_pci_diag_read_hi(struct ath10k *ar, void *dest,
} }
#define ath10k_pci_diag_read_hi(ar, dest, src, len) \ #define ath10k_pci_diag_read_hi(ar, dest, src, len) \
__ath10k_pci_diag_read_hi(ar, dest, HI_ITEM(src), len); __ath10k_pci_diag_read_hi(ar, dest, HI_ITEM(src), len)
/* Read 4-byte aligned data from Target memory or register */
static int ath10k_pci_diag_read_access(struct ath10k *ar, u32 address,
u32 *data)
{
/* Assume range doesn't cross this boundary */
if (address >= DRAM_BASE_ADDRESS)
return ath10k_pci_diag_read32(ar, address, data);
*data = ath10k_pci_read32(ar, address);
return 0;
}
static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
const void *data, int nbytes) const void *data, int nbytes)
...@@ -729,7 +696,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, ...@@ -729,7 +696,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
* Request CE to send caller-supplied data that * Request CE to send caller-supplied data that
* was copied to bounce buffer to Target(!) address. * was copied to bounce buffer to Target(!) address.
*/ */
ret = ath10k_ce_send(ce_diag, NULL, (u32) ce_data, ret = ath10k_ce_send(ce_diag, NULL, (u32)ce_data,
nbytes, 0, 0); nbytes, 0, 0);
if (ret != 0) if (ret != 0)
goto done; goto done;
...@@ -803,18 +770,6 @@ static int ath10k_pci_diag_write32(struct ath10k *ar, u32 address, u32 value) ...@@ -803,18 +770,6 @@ static int ath10k_pci_diag_write32(struct ath10k *ar, u32 address, u32 value)
return ath10k_pci_diag_write_mem(ar, address, &val, sizeof(val)); return ath10k_pci_diag_write_mem(ar, address, &val, sizeof(val));
} }
/* Write 4B data to Target memory or register */
static int ath10k_pci_diag_write_access(struct ath10k *ar, u32 address,
u32 data)
{
/* Assume range doesn't cross this boundary */
if (address >= DRAM_BASE_ADDRESS)
return ath10k_pci_diag_write32(ar, address, data);
ath10k_pci_write32(ar, address, data);
return 0;
}
static bool ath10k_pci_is_awake(struct ath10k *ar) static bool ath10k_pci_is_awake(struct ath10k *ar)
{ {
u32 val = ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS); u32 val = ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS);
...@@ -1152,7 +1107,7 @@ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar, ...@@ -1152,7 +1107,7 @@ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar,
} }
static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar,
u8 *ul_pipe, u8 *dl_pipe) u8 *ul_pipe, u8 *dl_pipe)
{ {
int ul_is_polled, dl_is_polled; int ul_is_polled, dl_is_polled;
...@@ -1172,16 +1127,8 @@ static void ath10k_pci_irq_disable(struct ath10k *ar) ...@@ -1172,16 +1127,8 @@ static void ath10k_pci_irq_disable(struct ath10k *ar)
int i; int i;
ath10k_ce_disable_interrupts(ar); ath10k_ce_disable_interrupts(ar);
ath10k_pci_disable_and_clear_legacy_irq(ar);
/* Regardless how many interrupts were assigned for MSI the first one /* FIXME: How to mask all MSI interrupts? */
* is always used for firmware indications (crashes). There's no way to
* mask the irq in the device so call disable_irq(). Legacy (shared)
* interrupts can be masked on the device though.
*/
if (ar_pci->num_msi_intrs > 0)
disable_irq(ar_pci->pdev->irq);
else
ath10k_pci_disable_and_clear_legacy_irq(ar);
for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++) for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
synchronize_irq(ar_pci->pdev->irq + i); synchronize_irq(ar_pci->pdev->irq + i);
...@@ -1189,15 +1136,9 @@ static void ath10k_pci_irq_disable(struct ath10k *ar) ...@@ -1189,15 +1136,9 @@ static void ath10k_pci_irq_disable(struct ath10k *ar)
static void ath10k_pci_irq_enable(struct ath10k *ar) static void ath10k_pci_irq_enable(struct ath10k *ar)
{ {
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
ath10k_ce_enable_interrupts(ar); ath10k_ce_enable_interrupts(ar);
ath10k_pci_enable_legacy_irq(ar);
/* See comment in ath10k_pci_irq_disable() */ /* FIXME: How to unmask all MSI interrupts? */
if (ar_pci->num_msi_intrs > 0)
enable_irq(ar_pci->pdev->irq);
else
ath10k_pci_enable_legacy_irq(ar);
} }
static int ath10k_pci_hif_start(struct ath10k *ar) static int ath10k_pci_hif_start(struct ath10k *ar)
...@@ -1311,14 +1252,21 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) ...@@ -1311,14 +1252,21 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
{ {
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif stop\n"); ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif stop\n");
ath10k_pci_irq_disable(ar);
ath10k_pci_flush(ar);
/* Most likely the device has HTT Rx ring configured. The only way to /* Most likely the device has HTT Rx ring configured. The only way to
* prevent the device from accessing (and possible corrupting) host * prevent the device from accessing (and possible corrupting) host
* memory is to reset the chip now. * memory is to reset the chip now.
*
* There's also no known way of masking MSI interrupts on the device.
* For ranged MSI the CE-related interrupts can be masked. However
* regardless how many MSI interrupts are assigned the first one
* is always used for firmware indications (crashes) and cannot be
* masked. To prevent the device from asserting the interrupt reset it
* before proceeding with cleanup.
*/ */
ath10k_pci_warm_reset(ar); ath10k_pci_warm_reset(ar);
ath10k_pci_irq_disable(ar);
ath10k_pci_flush(ar);
} }
static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
...@@ -1472,28 +1420,12 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, ...@@ -1472,28 +1420,12 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
*/ */
static int ath10k_pci_wake_target_cpu(struct ath10k *ar) static int ath10k_pci_wake_target_cpu(struct ath10k *ar)
{ {
int ret; u32 addr, val;
u32 core_ctrl;
ret = ath10k_pci_diag_read_access(ar, SOC_CORE_BASE_ADDRESS |
CORE_CTRL_ADDRESS,
&core_ctrl);
if (ret) {
ath10k_warn(ar, "failed to read core_ctrl: %d\n", ret);
return ret;
}
/* A_INUM_FIRMWARE interrupt to Target CPU */
core_ctrl |= CORE_CTRL_CPU_INTR_MASK;
ret = ath10k_pci_diag_write_access(ar, SOC_CORE_BASE_ADDRESS | addr = SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS;
CORE_CTRL_ADDRESS, val = ath10k_pci_read32(ar, addr);
core_ctrl); val |= CORE_CTRL_CPU_INTR_MASK;
if (ret) { ath10k_pci_write32(ar, addr, val);
ath10k_warn(ar, "failed to set target CPU interrupt mask: %d\n",
ret);
return ret;
}
return 0; return 0;
} }
...@@ -1516,8 +1448,8 @@ static int ath10k_pci_init_config(struct ath10k *ar) ...@@ -1516,8 +1448,8 @@ static int ath10k_pci_init_config(struct ath10k *ar)
host_interest_item_address(HI_ITEM(hi_interconnect_state)); host_interest_item_address(HI_ITEM(hi_interconnect_state));
/* Supply Target-side CE configuration */ /* Supply Target-side CE configuration */
ret = ath10k_pci_diag_read_access(ar, interconnect_targ_addr, ret = ath10k_pci_diag_read32(ar, interconnect_targ_addr,
&pcie_state_targ_addr); &pcie_state_targ_addr);
if (ret != 0) { if (ret != 0) {
ath10k_err(ar, "Failed to get pcie state addr: %d\n", ret); ath10k_err(ar, "Failed to get pcie state addr: %d\n", ret);
return ret; return ret;
...@@ -1529,10 +1461,10 @@ static int ath10k_pci_init_config(struct ath10k *ar) ...@@ -1529,10 +1461,10 @@ static int ath10k_pci_init_config(struct ath10k *ar)
return ret; return ret;
} }
ret = ath10k_pci_diag_read_access(ar, pcie_state_targ_addr + ret = ath10k_pci_diag_read32(ar, (pcie_state_targ_addr +
offsetof(struct pcie_state, offsetof(struct pcie_state,
pipe_cfg_addr), pipe_cfg_addr)),
&pipe_cfg_targ_addr); &pipe_cfg_targ_addr);
if (ret != 0) { if (ret != 0) {
ath10k_err(ar, "Failed to get pipe cfg addr: %d\n", ret); ath10k_err(ar, "Failed to get pipe cfg addr: %d\n", ret);
return ret; return ret;
...@@ -1545,18 +1477,18 @@ static int ath10k_pci_init_config(struct ath10k *ar) ...@@ -1545,18 +1477,18 @@ static int ath10k_pci_init_config(struct ath10k *ar)
} }
ret = ath10k_pci_diag_write_mem(ar, pipe_cfg_targ_addr, ret = ath10k_pci_diag_write_mem(ar, pipe_cfg_targ_addr,
target_ce_config_wlan, target_ce_config_wlan,
sizeof(target_ce_config_wlan)); sizeof(target_ce_config_wlan));
if (ret != 0) { if (ret != 0) {
ath10k_err(ar, "Failed to write pipe cfg: %d\n", ret); ath10k_err(ar, "Failed to write pipe cfg: %d\n", ret);
return ret; return ret;
} }
ret = ath10k_pci_diag_read_access(ar, pcie_state_targ_addr + ret = ath10k_pci_diag_read32(ar, (pcie_state_targ_addr +
offsetof(struct pcie_state, offsetof(struct pcie_state,
svc_to_pipe_map), svc_to_pipe_map)),
&svc_to_pipe_map); &svc_to_pipe_map);
if (ret != 0) { if (ret != 0) {
ath10k_err(ar, "Failed to get svc/pipe map: %d\n", ret); ath10k_err(ar, "Failed to get svc/pipe map: %d\n", ret);
return ret; return ret;
...@@ -1569,17 +1501,17 @@ static int ath10k_pci_init_config(struct ath10k *ar) ...@@ -1569,17 +1501,17 @@ static int ath10k_pci_init_config(struct ath10k *ar)
} }
ret = ath10k_pci_diag_write_mem(ar, svc_to_pipe_map, ret = ath10k_pci_diag_write_mem(ar, svc_to_pipe_map,
target_service_to_ce_map_wlan, target_service_to_ce_map_wlan,
sizeof(target_service_to_ce_map_wlan)); sizeof(target_service_to_ce_map_wlan));
if (ret != 0) { if (ret != 0) {
ath10k_err(ar, "Failed to write svc/pipe map: %d\n", ret); ath10k_err(ar, "Failed to write svc/pipe map: %d\n", ret);
return ret; return ret;
} }
ret = ath10k_pci_diag_read_access(ar, pcie_state_targ_addr + ret = ath10k_pci_diag_read32(ar, (pcie_state_targ_addr +
offsetof(struct pcie_state, offsetof(struct pcie_state,
config_flags), config_flags)),
&pcie_config_flags); &pcie_config_flags);
if (ret != 0) { if (ret != 0) {
ath10k_err(ar, "Failed to get pcie config_flags: %d\n", ret); ath10k_err(ar, "Failed to get pcie config_flags: %d\n", ret);
return ret; return ret;
...@@ -1587,9 +1519,10 @@ static int ath10k_pci_init_config(struct ath10k *ar) ...@@ -1587,9 +1519,10 @@ static int ath10k_pci_init_config(struct ath10k *ar)
pcie_config_flags &= ~PCIE_CONFIG_FLAG_ENABLE_L1; pcie_config_flags &= ~PCIE_CONFIG_FLAG_ENABLE_L1;
ret = ath10k_pci_diag_write_access(ar, pcie_state_targ_addr + ret = ath10k_pci_diag_write32(ar, (pcie_state_targ_addr +
offsetof(struct pcie_state, config_flags), offsetof(struct pcie_state,
pcie_config_flags); config_flags)),
pcie_config_flags);
if (ret != 0) { if (ret != 0) {
ath10k_err(ar, "Failed to write pcie config_flags: %d\n", ret); ath10k_err(ar, "Failed to write pcie config_flags: %d\n", ret);
return ret; return ret;
...@@ -1598,7 +1531,7 @@ static int ath10k_pci_init_config(struct ath10k *ar) ...@@ -1598,7 +1531,7 @@ static int ath10k_pci_init_config(struct ath10k *ar)
/* configure early allocation */ /* configure early allocation */
ealloc_targ_addr = host_interest_item_address(HI_ITEM(hi_early_alloc)); ealloc_targ_addr = host_interest_item_address(HI_ITEM(hi_early_alloc));
ret = ath10k_pci_diag_read_access(ar, ealloc_targ_addr, &ealloc_value); ret = ath10k_pci_diag_read32(ar, ealloc_targ_addr, &ealloc_value);
if (ret != 0) { if (ret != 0) {
ath10k_err(ar, "Faile to get early alloc val: %d\n", ret); ath10k_err(ar, "Faile to get early alloc val: %d\n", ret);
return ret; return ret;
...@@ -1610,7 +1543,7 @@ static int ath10k_pci_init_config(struct ath10k *ar) ...@@ -1610,7 +1543,7 @@ static int ath10k_pci_init_config(struct ath10k *ar)
ealloc_value |= ((1 << HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) & ealloc_value |= ((1 << HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) &
HI_EARLY_ALLOC_IRAM_BANKS_MASK); HI_EARLY_ALLOC_IRAM_BANKS_MASK);
ret = ath10k_pci_diag_write_access(ar, ealloc_targ_addr, ealloc_value); ret = ath10k_pci_diag_write32(ar, ealloc_targ_addr, ealloc_value);
if (ret != 0) { if (ret != 0) {
ath10k_err(ar, "Failed to set early alloc val: %d\n", ret); ath10k_err(ar, "Failed to set early alloc val: %d\n", ret);
return ret; return ret;
...@@ -1619,7 +1552,7 @@ static int ath10k_pci_init_config(struct ath10k *ar) ...@@ -1619,7 +1552,7 @@ static int ath10k_pci_init_config(struct ath10k *ar)
/* Tell Target to proceed with initialization */ /* Tell Target to proceed with initialization */
flag2_targ_addr = host_interest_item_address(HI_ITEM(hi_option_flag2)); flag2_targ_addr = host_interest_item_address(HI_ITEM(hi_option_flag2));
ret = ath10k_pci_diag_read_access(ar, flag2_targ_addr, &flag2_value); ret = ath10k_pci_diag_read32(ar, flag2_targ_addr, &flag2_value);
if (ret != 0) { if (ret != 0) {
ath10k_err(ar, "Failed to get option val: %d\n", ret); ath10k_err(ar, "Failed to get option val: %d\n", ret);
return ret; return ret;
...@@ -1627,7 +1560,7 @@ static int ath10k_pci_init_config(struct ath10k *ar) ...@@ -1627,7 +1560,7 @@ static int ath10k_pci_init_config(struct ath10k *ar)
flag2_value |= HI_OPTION_EARLY_CFG_DONE; flag2_value |= HI_OPTION_EARLY_CFG_DONE;
ret = ath10k_pci_diag_write_access(ar, flag2_targ_addr, flag2_value); ret = ath10k_pci_diag_write32(ar, flag2_targ_addr, flag2_value);
if (ret != 0) { if (ret != 0) {
ath10k_err(ar, "Failed to set option val: %d\n", ret); ath10k_err(ar, "Failed to set option val: %d\n", ret);
return ret; return ret;
...@@ -1692,7 +1625,7 @@ static int ath10k_pci_ce_init(struct ath10k *ar) ...@@ -1692,7 +1625,7 @@ static int ath10k_pci_ce_init(struct ath10k *ar)
continue; continue;
} }
pipe_info->buf_sz = (size_t) (attr->src_sz_max); pipe_info->buf_sz = (size_t)(attr->src_sz_max);
} }
return 0; return 0;
...@@ -2228,7 +2161,7 @@ static int ath10k_pci_init_irq(struct ath10k *ar) ...@@ -2228,7 +2161,7 @@ static int ath10k_pci_init_irq(struct ath10k *ar)
if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO) { if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO) {
ar_pci->num_msi_intrs = MSI_NUM_REQUEST; ar_pci->num_msi_intrs = MSI_NUM_REQUEST;
ret = pci_enable_msi_range(ar_pci->pdev, ar_pci->num_msi_intrs, ret = pci_enable_msi_range(ar_pci->pdev, ar_pci->num_msi_intrs,
ar_pci->num_msi_intrs); ar_pci->num_msi_intrs);
if (ret > 0) if (ret > 0)
return 0; return 0;
...@@ -2554,6 +2487,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ...@@ -2554,6 +2487,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
err_free_irq: err_free_irq:
ath10k_pci_free_irq(ar); ath10k_pci_free_irq(ar);
ath10k_pci_kill_tasklet(ar);
err_deinit_irq: err_deinit_irq:
ath10k_pci_deinit_irq(ar); ath10k_pci_deinit_irq(ar);
...@@ -2590,6 +2524,7 @@ static void ath10k_pci_remove(struct pci_dev *pdev) ...@@ -2590,6 +2524,7 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
ath10k_core_unregister(ar); ath10k_core_unregister(ar);
ath10k_pci_free_irq(ar); ath10k_pci_free_irq(ar);
ath10k_pci_kill_tasklet(ar);
ath10k_pci_deinit_irq(ar); ath10k_pci_deinit_irq(ar);
ath10k_pci_ce_deinit(ar); ath10k_pci_ce_deinit(ar);
ath10k_pci_free_ce(ar); ath10k_pci_free_ce(ar);
......
...@@ -839,7 +839,6 @@ struct rx_ppdu_start { ...@@ -839,7 +839,6 @@ struct rx_ppdu_start {
* Reserved: HW should fill with 0, FW should ignore. * Reserved: HW should fill with 0, FW should ignore.
*/ */
#define RX_PPDU_END_FLAGS_PHY_ERR (1 << 0) #define RX_PPDU_END_FLAGS_PHY_ERR (1 << 0)
#define RX_PPDU_END_FLAGS_RX_LOCATION (1 << 1) #define RX_PPDU_END_FLAGS_RX_LOCATION (1 << 1)
#define RX_PPDU_END_FLAGS_TXBF_H_INFO (1 << 2) #define RX_PPDU_END_FLAGS_TXBF_H_INFO (1 << 2)
......
...@@ -284,7 +284,6 @@ Fw Mode/SubMode Mask ...@@ -284,7 +284,6 @@ Fw Mode/SubMode Mask
#define HI_OPTION_ALL_FW_SUBMODE_MASK 0xFF00 #define HI_OPTION_ALL_FW_SUBMODE_MASK 0xFF00
#define HI_OPTION_ALL_FW_SUBMODE_SHIFT 0x8 #define HI_OPTION_ALL_FW_SUBMODE_SHIFT 0x8
/* hi_option_flag2 options */ /* hi_option_flag2 options */
#define HI_OPTION_OFFLOAD_AMSDU 0x01 #define HI_OPTION_OFFLOAD_AMSDU 0x01
#define HI_OPTION_DFS_SUPPORT 0x02 /* Enable DFS support */ #define HI_OPTION_DFS_SUPPORT 0x02 /* Enable DFS support */
......
/*
* Copyright (c) 2014 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "testmode.h"
#include <net/netlink.h>
#include <linux/firmware.h>
#include "debug.h"
#include "wmi.h"
#include "hif.h"
#include "hw.h"
#include "testmode_i.h"
static const struct nla_policy ath10k_tm_policy[ATH10K_TM_ATTR_MAX + 1] = {
[ATH10K_TM_ATTR_CMD] = { .type = NLA_U32 },
[ATH10K_TM_ATTR_DATA] = { .type = NLA_BINARY,
.len = ATH10K_TM_DATA_MAX_LEN },
[ATH10K_TM_ATTR_WMI_CMDID] = { .type = NLA_U32 },
[ATH10K_TM_ATTR_VERSION_MAJOR] = { .type = NLA_U32 },
[ATH10K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 },
};
/* Returns true if callee consumes the skb and the skb should be discarded.
* Returns false if skb is not used. Does not sleep.
*/
bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb)
{
struct sk_buff *nl_skb;
bool consumed;
int ret;
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
"testmode event wmi cmd_id %d skb %p skb->len %d\n",
cmd_id, skb, skb->len);
ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
spin_lock_bh(&ar->data_lock);
if (!ar->testmode.utf_monitor) {
consumed = false;
goto out;
}
/* Only testmode.c should be handling events from utf firmware,
* otherwise all sort of problems will arise as mac80211 operations
* are not initialised.
*/
consumed = true;
nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy,
2 * sizeof(u32) + skb->len,
GFP_ATOMIC);
if (!nl_skb) {
ath10k_warn(ar,
"failed to allocate skb for testmode wmi event\n");
goto out;
}
ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_CMD, ATH10K_TM_CMD_WMI);
if (ret) {
ath10k_warn(ar,
"failed to to put testmode wmi event cmd attribute: %d\n",
ret);
kfree_skb(nl_skb);
goto out;
}
ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_WMI_CMDID, cmd_id);
if (ret) {
ath10k_warn(ar,
"failed to to put testmode wmi even cmd_id: %d\n",
ret);
kfree_skb(nl_skb);
goto out;
}
ret = nla_put(nl_skb, ATH10K_TM_ATTR_DATA, skb->len, skb->data);
if (ret) {
ath10k_warn(ar,
"failed to copy skb to testmode wmi event: %d\n",
ret);
kfree_skb(nl_skb);
goto out;
}
cfg80211_testmode_event(nl_skb, GFP_ATOMIC);
out:
spin_unlock_bh(&ar->data_lock);
return consumed;
}
static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
{
struct sk_buff *skb;
int ret;
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
"testmode cmd get version_major %d version_minor %d\n",
ATH10K_TESTMODE_VERSION_MAJOR,
ATH10K_TESTMODE_VERSION_MINOR);
skb = cfg80211_testmode_alloc_reply_skb(ar->hw->wiphy,
nla_total_size(sizeof(u32)));
if (!skb)
return -ENOMEM;
ret = nla_put_u32(skb, ATH10K_TM_ATTR_VERSION_MAJOR,
ATH10K_TESTMODE_VERSION_MAJOR);
if (ret) {
kfree_skb(skb);
return ret;
}
ret = nla_put_u32(skb, ATH10K_TM_ATTR_VERSION_MINOR,
ATH10K_TESTMODE_VERSION_MINOR);
if (ret) {
kfree_skb(skb);
return ret;
}
return cfg80211_testmode_reply(skb);
}
static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
{
char filename[100];
int ret;
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n");
mutex_lock(&ar->conf_mutex);
if (ar->state == ATH10K_STATE_UTF) {
ret = -EALREADY;
goto err;
}
/* start utf only when the driver is not in use */
if (ar->state != ATH10K_STATE_OFF) {
ret = -EBUSY;
goto err;
}
if (WARN_ON(ar->testmode.utf != NULL)) {
/* utf image is already downloaded, it shouldn't be */
ret = -EEXIST;
goto err;
}
snprintf(filename, sizeof(filename), "%s/%s",
ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
/* load utf firmware image */
ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
if (ret) {
ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
filename, ret);
goto err;
}
spin_lock_bh(&ar->data_lock);
ar->testmode.utf_monitor = true;
spin_unlock_bh(&ar->data_lock);
BUILD_BUG_ON(sizeof(ar->fw_features) !=
sizeof(ar->testmode.orig_fw_features));
memcpy(ar->testmode.orig_fw_features, ar->fw_features,
sizeof(ar->fw_features));
/* utf.bin firmware image does not advertise firmware features. Do
* an ugly hack where we force the firmware features so that wmi.c
* will use the correct WMI interface.
*/
memset(ar->fw_features, 0, sizeof(ar->fw_features));
__set_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features);
ret = ath10k_hif_power_up(ar);
if (ret) {
ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret);
ar->state = ATH10K_STATE_OFF;
goto err_fw_features;
}
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF);
if (ret) {
ath10k_err(ar, "failed to start core (testmode): %d\n", ret);
ar->state = ATH10K_STATE_OFF;
goto err_power_down;
}
ar->state = ATH10K_STATE_UTF;
ath10k_info(ar, "UTF firmware started\n");
mutex_unlock(&ar->conf_mutex);
return 0;
err_power_down:
ath10k_hif_power_down(ar);
err_fw_features:
/* return the original firmware features */
memcpy(ar->fw_features, ar->testmode.orig_fw_features,
sizeof(ar->fw_features));
release_firmware(ar->testmode.utf);
ar->testmode.utf = NULL;
err:
mutex_unlock(&ar->conf_mutex);
return ret;
}
static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar)
{
lockdep_assert_held(&ar->conf_mutex);
ath10k_core_stop(ar);
ath10k_hif_power_down(ar);
spin_lock_bh(&ar->data_lock);
ar->testmode.utf_monitor = false;
spin_unlock_bh(&ar->data_lock);
/* return the original firmware features */
memcpy(ar->fw_features, ar->testmode.orig_fw_features,
sizeof(ar->fw_features));
release_firmware(ar->testmode.utf);
ar->testmode.utf = NULL;
ar->state = ATH10K_STATE_OFF;
}
static int ath10k_tm_cmd_utf_stop(struct ath10k *ar, struct nlattr *tb[])
{
int ret;
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf stop\n");
mutex_lock(&ar->conf_mutex);
if (ar->state != ATH10K_STATE_UTF) {
ret = -ENETDOWN;
goto out;
}
__ath10k_tm_cmd_utf_stop(ar);
ret = 0;
ath10k_info(ar, "UTF firmware stopped\n");
out:
mutex_unlock(&ar->conf_mutex);
return ret;
}
static int ath10k_tm_cmd_wmi(struct ath10k *ar, struct nlattr *tb[])
{
struct sk_buff *skb;
int ret, buf_len;
u32 cmd_id;
void *buf;
mutex_lock(&ar->conf_mutex);
if (ar->state != ATH10K_STATE_UTF) {
ret = -ENETDOWN;
goto out;
}
if (!tb[ATH10K_TM_ATTR_DATA]) {
ret = -EINVAL;
goto out;
}
if (!tb[ATH10K_TM_ATTR_WMI_CMDID]) {
ret = -EINVAL;
goto out;
}
buf = nla_data(tb[ATH10K_TM_ATTR_DATA]);
buf_len = nla_len(tb[ATH10K_TM_ATTR_DATA]);
cmd_id = nla_get_u32(tb[ATH10K_TM_ATTR_WMI_CMDID]);
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
"testmode cmd wmi cmd_id %d buf %p buf_len %d\n",
cmd_id, buf, buf_len);
ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", buf, buf_len);
skb = ath10k_wmi_alloc_skb(ar, buf_len);
if (!skb) {
ret = -ENOMEM;
goto out;
}
memcpy(skb->data, buf, buf_len);
ret = ath10k_wmi_cmd_send(ar, skb, cmd_id);
if (ret) {
ath10k_warn(ar, "failed to transmit wmi command (testmode): %d\n",
ret);
goto out;
}
ret = 0;
out:
mutex_unlock(&ar->conf_mutex);
return ret;
}
int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void *data, int len)
{
struct ath10k *ar = hw->priv;
struct nlattr *tb[ATH10K_TM_ATTR_MAX + 1];
int ret;
ret = nla_parse(tb, ATH10K_TM_ATTR_MAX, data, len,
ath10k_tm_policy);
if (ret)
return ret;
if (!tb[ATH10K_TM_ATTR_CMD])
return -EINVAL;
switch (nla_get_u32(tb[ATH10K_TM_ATTR_CMD])) {
case ATH10K_TM_CMD_GET_VERSION:
return ath10k_tm_cmd_get_version(ar, tb);
case ATH10K_TM_CMD_UTF_START:
return ath10k_tm_cmd_utf_start(ar, tb);
case ATH10K_TM_CMD_UTF_STOP:
return ath10k_tm_cmd_utf_stop(ar, tb);
case ATH10K_TM_CMD_WMI:
return ath10k_tm_cmd_wmi(ar, tb);
default:
return -EOPNOTSUPP;
}
}
void ath10k_testmode_destroy(struct ath10k *ar)
{
mutex_lock(&ar->conf_mutex);
if (ar->state != ATH10K_STATE_UTF) {
/* utf firmware is not running, nothing to do */
goto out;
}
__ath10k_tm_cmd_utf_stop(ar);
out:
mutex_unlock(&ar->conf_mutex);
}
/*
* Copyright (c) 2014 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "core.h"
#ifdef CONFIG_NL80211_TESTMODE
void ath10k_testmode_destroy(struct ath10k *ar);
bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb);
int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void *data, int len);
#else
static inline void ath10k_testmode_destroy(struct ath10k *ar)
{
}
static inline bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id,
struct sk_buff *skb)
{
return false;
}
static inline int ath10k_tm_cmd(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
void *data, int len)
{
return 0;
}
#endif
/*
* Copyright (c) 2014 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* "API" level of the ath10k testmode interface. Bump it after every
* incompatible interface change.
*/
#define ATH10K_TESTMODE_VERSION_MAJOR 1
/* Bump this after every _compatible_ interface change, for example
* addition of a new command or an attribute.
*/
#define ATH10K_TESTMODE_VERSION_MINOR 0
#define ATH10K_TM_DATA_MAX_LEN 5000
enum ath10k_tm_attr {
__ATH10K_TM_ATTR_INVALID = 0,
ATH10K_TM_ATTR_CMD = 1,
ATH10K_TM_ATTR_DATA = 2,
ATH10K_TM_ATTR_WMI_CMDID = 3,
ATH10K_TM_ATTR_VERSION_MAJOR = 4,
ATH10K_TM_ATTR_VERSION_MINOR = 5,
/* keep last */
__ATH10K_TM_ATTR_AFTER_LAST,
ATH10K_TM_ATTR_MAX = __ATH10K_TM_ATTR_AFTER_LAST - 1,
};
/* All ath10k testmode interface commands specified in
* ATH10K_TM_ATTR_CMD
*/
enum ath10k_tm_cmd {
/* Returns the supported ath10k testmode interface version in
* ATH10K_TM_ATTR_VERSION. Always guaranteed to work. User space
* uses this to verify it's using the correct version of the
* testmode interface
*/
ATH10K_TM_CMD_GET_VERSION = 0,
/* Boots the UTF firmware, the netdev interface must be down at the
* time.
*/
ATH10K_TM_CMD_UTF_START = 1,
/* Shuts down the UTF firmware and puts the driver back into OFF
* state.
*/
ATH10K_TM_CMD_UTF_STOP = 2,
/* The command used to transmit a WMI command to the firmware and
* the event to receive WMI events from the firmware. Without
* struct wmi_cmd_hdr header, only the WMI payload. Command id is
* provided with ATH10K_TM_ATTR_WMI_CMDID and payload in
* ATH10K_TM_ATTR_DATA.
*/
ATH10K_TM_CMD_WMI = 3,
};
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#if !defined(_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) #if !defined(_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
#include <linux/tracepoint.h> #include <linux/tracepoint.h>
#include "core.h"
#define _TRACE_H_ #define _TRACE_H_
...@@ -39,59 +40,79 @@ static inline void trace_ ## name(proto) {} ...@@ -39,59 +40,79 @@ static inline void trace_ ## name(proto) {}
#define ATH10K_MSG_MAX 200 #define ATH10K_MSG_MAX 200
DECLARE_EVENT_CLASS(ath10k_log_event, DECLARE_EVENT_CLASS(ath10k_log_event,
TP_PROTO(struct va_format *vaf), TP_PROTO(struct ath10k *ar, struct va_format *vaf),
TP_ARGS(vaf), TP_ARGS(ar, vaf),
TP_STRUCT__entry( TP_STRUCT__entry(
__string(device, dev_name(ar->dev))
__string(driver, dev_driver_string(ar->dev))
__dynamic_array(char, msg, ATH10K_MSG_MAX) __dynamic_array(char, msg, ATH10K_MSG_MAX)
), ),
TP_fast_assign( TP_fast_assign(
__assign_str(device, dev_name(ar->dev));
__assign_str(driver, dev_driver_string(ar->dev));
WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
ATH10K_MSG_MAX, ATH10K_MSG_MAX,
vaf->fmt, vaf->fmt,
*vaf->va) >= ATH10K_MSG_MAX); *vaf->va) >= ATH10K_MSG_MAX);
), ),
TP_printk("%s", __get_str(msg)) TP_printk(
"%s %s %s",
__get_str(driver),
__get_str(device),
__get_str(msg)
)
); );
DEFINE_EVENT(ath10k_log_event, ath10k_log_err, DEFINE_EVENT(ath10k_log_event, ath10k_log_err,
TP_PROTO(struct va_format *vaf), TP_PROTO(struct ath10k *ar, struct va_format *vaf),
TP_ARGS(vaf) TP_ARGS(ar, vaf)
); );
DEFINE_EVENT(ath10k_log_event, ath10k_log_warn, DEFINE_EVENT(ath10k_log_event, ath10k_log_warn,
TP_PROTO(struct va_format *vaf), TP_PROTO(struct ath10k *ar, struct va_format *vaf),
TP_ARGS(vaf) TP_ARGS(ar, vaf)
); );
DEFINE_EVENT(ath10k_log_event, ath10k_log_info, DEFINE_EVENT(ath10k_log_event, ath10k_log_info,
TP_PROTO(struct va_format *vaf), TP_PROTO(struct ath10k *ar, struct va_format *vaf),
TP_ARGS(vaf) TP_ARGS(ar, vaf)
); );
TRACE_EVENT(ath10k_log_dbg, TRACE_EVENT(ath10k_log_dbg,
TP_PROTO(unsigned int level, struct va_format *vaf), TP_PROTO(struct ath10k *ar, unsigned int level, struct va_format *vaf),
TP_ARGS(level, vaf), TP_ARGS(ar, level, vaf),
TP_STRUCT__entry( TP_STRUCT__entry(
__string(device, dev_name(ar->dev))
__string(driver, dev_driver_string(ar->dev))
__field(unsigned int, level) __field(unsigned int, level)
__dynamic_array(char, msg, ATH10K_MSG_MAX) __dynamic_array(char, msg, ATH10K_MSG_MAX)
), ),
TP_fast_assign( TP_fast_assign(
__assign_str(device, dev_name(ar->dev));
__assign_str(driver, dev_driver_string(ar->dev));
__entry->level = level; __entry->level = level;
WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg), WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
ATH10K_MSG_MAX, ATH10K_MSG_MAX,
vaf->fmt, vaf->fmt,
*vaf->va) >= ATH10K_MSG_MAX); *vaf->va) >= ATH10K_MSG_MAX);
), ),
TP_printk("%s", __get_str(msg)) TP_printk(
"%s %s %s",
__get_str(driver),
__get_str(device),
__get_str(msg)
)
); );
TRACE_EVENT(ath10k_log_dbg_dump, TRACE_EVENT(ath10k_log_dbg_dump,
TP_PROTO(const char *msg, const char *prefix, TP_PROTO(struct ath10k *ar, const char *msg, const char *prefix,
const void *buf, size_t buf_len), const void *buf, size_t buf_len),
TP_ARGS(msg, prefix, buf, buf_len), TP_ARGS(ar, msg, prefix, buf, buf_len),
TP_STRUCT__entry( TP_STRUCT__entry(
__string(device, dev_name(ar->dev))
__string(driver, dev_driver_string(ar->dev))
__string(msg, msg) __string(msg, msg)
__string(prefix, prefix) __string(prefix, prefix)
__field(size_t, buf_len) __field(size_t, buf_len)
...@@ -99,6 +120,8 @@ TRACE_EVENT(ath10k_log_dbg_dump, ...@@ -99,6 +120,8 @@ TRACE_EVENT(ath10k_log_dbg_dump,
), ),
TP_fast_assign( TP_fast_assign(
__assign_str(device, dev_name(ar->dev));
__assign_str(driver, dev_driver_string(ar->dev));
__assign_str(msg, msg); __assign_str(msg, msg);
__assign_str(prefix, prefix); __assign_str(prefix, prefix);
__entry->buf_len = buf_len; __entry->buf_len = buf_len;
...@@ -106,16 +129,22 @@ TRACE_EVENT(ath10k_log_dbg_dump, ...@@ -106,16 +129,22 @@ TRACE_EVENT(ath10k_log_dbg_dump,
), ),
TP_printk( TP_printk(
"%s/%s\n", __get_str(prefix), __get_str(msg) "%s %s %s/%s\n",
__get_str(driver),
__get_str(device),
__get_str(prefix),
__get_str(msg)
) )
); );
TRACE_EVENT(ath10k_wmi_cmd, TRACE_EVENT(ath10k_wmi_cmd,
TP_PROTO(int id, void *buf, size_t buf_len, int ret), TP_PROTO(struct ath10k *ar, int id, void *buf, size_t buf_len, int ret),
TP_ARGS(id, buf, buf_len, ret), TP_ARGS(ar, id, buf, buf_len, ret),
TP_STRUCT__entry( TP_STRUCT__entry(
__string(device, dev_name(ar->dev))
__string(driver, dev_driver_string(ar->dev))
__field(unsigned int, id) __field(unsigned int, id)
__field(size_t, buf_len) __field(size_t, buf_len)
__dynamic_array(u8, buf, buf_len) __dynamic_array(u8, buf, buf_len)
...@@ -123,6 +152,8 @@ TRACE_EVENT(ath10k_wmi_cmd, ...@@ -123,6 +152,8 @@ TRACE_EVENT(ath10k_wmi_cmd,
), ),
TP_fast_assign( TP_fast_assign(
__assign_str(device, dev_name(ar->dev));
__assign_str(driver, dev_driver_string(ar->dev));
__entry->id = id; __entry->id = id;
__entry->buf_len = buf_len; __entry->buf_len = buf_len;
__entry->ret = ret; __entry->ret = ret;
...@@ -130,7 +161,9 @@ TRACE_EVENT(ath10k_wmi_cmd, ...@@ -130,7 +161,9 @@ TRACE_EVENT(ath10k_wmi_cmd,
), ),
TP_printk( TP_printk(
"id %d len %zu ret %d", "%s %s id %d len %zu ret %d",
__get_str(driver),
__get_str(device),
__entry->id, __entry->id,
__entry->buf_len, __entry->buf_len,
__entry->ret __entry->ret
...@@ -138,67 +171,85 @@ TRACE_EVENT(ath10k_wmi_cmd, ...@@ -138,67 +171,85 @@ TRACE_EVENT(ath10k_wmi_cmd,
); );
TRACE_EVENT(ath10k_wmi_event, TRACE_EVENT(ath10k_wmi_event,
TP_PROTO(int id, void *buf, size_t buf_len), TP_PROTO(struct ath10k *ar, int id, void *buf, size_t buf_len),
TP_ARGS(id, buf, buf_len), TP_ARGS(ar, id, buf, buf_len),
TP_STRUCT__entry( TP_STRUCT__entry(
__string(device, dev_name(ar->dev))
__string(driver, dev_driver_string(ar->dev))
__field(unsigned int, id) __field(unsigned int, id)
__field(size_t, buf_len) __field(size_t, buf_len)
__dynamic_array(u8, buf, buf_len) __dynamic_array(u8, buf, buf_len)
), ),
TP_fast_assign( TP_fast_assign(
__assign_str(device, dev_name(ar->dev));
__assign_str(driver, dev_driver_string(ar->dev));
__entry->id = id; __entry->id = id;
__entry->buf_len = buf_len; __entry->buf_len = buf_len;
memcpy(__get_dynamic_array(buf), buf, buf_len); memcpy(__get_dynamic_array(buf), buf, buf_len);
), ),
TP_printk( TP_printk(
"id %d len %zu", "%s %s id %d len %zu",
__get_str(driver),
__get_str(device),
__entry->id, __entry->id,
__entry->buf_len __entry->buf_len
) )
); );
TRACE_EVENT(ath10k_htt_stats, TRACE_EVENT(ath10k_htt_stats,
TP_PROTO(void *buf, size_t buf_len), TP_PROTO(struct ath10k *ar, void *buf, size_t buf_len),
TP_ARGS(buf, buf_len), TP_ARGS(ar, buf, buf_len),
TP_STRUCT__entry( TP_STRUCT__entry(
__string(device, dev_name(ar->dev))
__string(driver, dev_driver_string(ar->dev))
__field(size_t, buf_len) __field(size_t, buf_len)
__dynamic_array(u8, buf, buf_len) __dynamic_array(u8, buf, buf_len)
), ),
TP_fast_assign( TP_fast_assign(
__assign_str(device, dev_name(ar->dev));
__assign_str(driver, dev_driver_string(ar->dev));
__entry->buf_len = buf_len; __entry->buf_len = buf_len;
memcpy(__get_dynamic_array(buf), buf, buf_len); memcpy(__get_dynamic_array(buf), buf, buf_len);
), ),
TP_printk( TP_printk(
"len %zu", "%s %s len %zu",
__get_str(driver),
__get_str(device),
__entry->buf_len __entry->buf_len
) )
); );
TRACE_EVENT(ath10k_wmi_dbglog, TRACE_EVENT(ath10k_wmi_dbglog,
TP_PROTO(void *buf, size_t buf_len), TP_PROTO(struct ath10k *ar, void *buf, size_t buf_len),
TP_ARGS(buf, buf_len), TP_ARGS(ar, buf, buf_len),
TP_STRUCT__entry( TP_STRUCT__entry(
__string(device, dev_name(ar->dev))
__string(driver, dev_driver_string(ar->dev))
__field(size_t, buf_len) __field(size_t, buf_len)
__dynamic_array(u8, buf, buf_len) __dynamic_array(u8, buf, buf_len)
), ),
TP_fast_assign( TP_fast_assign(
__assign_str(device, dev_name(ar->dev));
__assign_str(driver, dev_driver_string(ar->dev));
__entry->buf_len = buf_len; __entry->buf_len = buf_len;
memcpy(__get_dynamic_array(buf), buf, buf_len); memcpy(__get_dynamic_array(buf), buf, buf_len);
), ),
TP_printk( TP_printk(
"len %zu", "%s %s len %zu",
__get_str(driver),
__get_str(device),
__entry->buf_len __entry->buf_len
) )
); );
......
...@@ -178,7 +178,7 @@ void ath10k_peer_map_event(struct ath10k_htt *htt, ...@@ -178,7 +178,7 @@ void ath10k_peer_map_event(struct ath10k_htt *htt,
goto exit; goto exit;
peer->vdev_id = ev->vdev_id; peer->vdev_id = ev->vdev_id;
memcpy(peer->addr, ev->addr, ETH_ALEN); ether_addr_copy(peer->addr, ev->addr);
list_add(&peer->list, &ar->peers); list_add(&peer->list, &ar->peers);
wake_up(&ar->peer_mapping_wq); wake_up(&ar->peer_mapping_wq);
} }
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "debug.h" #include "debug.h"
#include "wmi.h" #include "wmi.h"
#include "mac.h" #include "mac.h"
#include "testmode.h"
/* MAIN WMI cmd track */ /* MAIN WMI cmd track */
static struct wmi_cmd_map wmi_cmd_map = { static struct wmi_cmd_map wmi_cmd_map = {
...@@ -611,6 +612,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = { ...@@ -611,6 +612,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = {
int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
{ {
int ret; int ret;
ret = wait_for_completion_timeout(&ar->wmi.service_ready, ret = wait_for_completion_timeout(&ar->wmi.service_ready,
WMI_SERVICE_READY_TIMEOUT_HZ); WMI_SERVICE_READY_TIMEOUT_HZ);
return ret; return ret;
...@@ -619,12 +621,13 @@ int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) ...@@ -619,12 +621,13 @@ int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar) int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar)
{ {
int ret; int ret;
ret = wait_for_completion_timeout(&ar->wmi.unified_ready, ret = wait_for_completion_timeout(&ar->wmi.unified_ready,
WMI_UNIFIED_READY_TIMEOUT_HZ); WMI_UNIFIED_READY_TIMEOUT_HZ);
return ret; return ret;
} }
static struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len) struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len)
{ {
struct sk_buff *skb; struct sk_buff *skb;
u32 round_len = roundup(len, 4); u32 round_len = roundup(len, 4);
...@@ -666,7 +669,7 @@ static int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb, ...@@ -666,7 +669,7 @@ static int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb,
memset(skb_cb, 0, sizeof(*skb_cb)); memset(skb_cb, 0, sizeof(*skb_cb));
ret = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb); ret = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb);
trace_ath10k_wmi_cmd(cmd_id, skb->data, skb->len, ret); trace_ath10k_wmi_cmd(ar, cmd_id, skb->data, skb->len, ret);
if (ret) if (ret)
goto err_pull; goto err_pull;
...@@ -725,8 +728,7 @@ static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar) ...@@ -725,8 +728,7 @@ static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar)
wake_up(&ar->wmi.tx_credits_wq); wake_up(&ar->wmi.tx_credits_wq);
} }
static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
u32 cmd_id)
{ {
int ret = -EOPNOTSUPP; int ret = -EOPNOTSUPP;
...@@ -792,7 +794,7 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb) ...@@ -792,7 +794,7 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb)
cmd->hdr.tx_power = 0; cmd->hdr.tx_power = 0;
cmd->hdr.buf_len = __cpu_to_le32(buf_len); cmd->hdr.buf_len = __cpu_to_le32(buf_len);
memcpy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr), ETH_ALEN); ether_addr_copy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr));
memcpy(cmd->buf, skb->data, skb->len); memcpy(cmd->buf, skb->data, skb->len);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n", ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n",
...@@ -1288,7 +1290,7 @@ static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb) ...@@ -1288,7 +1290,7 @@ static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb)
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event debug mesg len %d\n", ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event debug mesg len %d\n",
skb->len); skb->len);
trace_ath10k_wmi_dbglog(skb->data, skb->len); trace_ath10k_wmi_dbglog(ar, skb->data, skb->len);
return 0; return 0;
} }
...@@ -1384,6 +1386,8 @@ static void ath10k_wmi_update_tim(struct ath10k *ar, ...@@ -1384,6 +1386,8 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
struct ieee80211_tim_ie *tim; struct ieee80211_tim_ie *tim;
u8 *ies, *ie; u8 *ies, *ie;
u8 ie_len, pvm_len; u8 ie_len, pvm_len;
__le32 t;
u32 v;
/* if next SWBA has no tim_changed the tim_bitmap is garbage. /* if next SWBA has no tim_changed the tim_bitmap is garbage.
* we must copy the bitmap upon change and reuse it later */ * we must copy the bitmap upon change and reuse it later */
...@@ -1394,8 +1398,8 @@ static void ath10k_wmi_update_tim(struct ath10k *ar, ...@@ -1394,8 +1398,8 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
sizeof(bcn_info->tim_info.tim_bitmap)); sizeof(bcn_info->tim_info.tim_bitmap));
for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++) { for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++) {
__le32 t = bcn_info->tim_info.tim_bitmap[i / 4]; t = bcn_info->tim_info.tim_bitmap[i / 4];
u32 v = __le32_to_cpu(t); v = __le32_to_cpu(t);
arvif->u.ap.tim_bitmap[i] = (v >> ((i % 4) * 8)) & 0xFF; arvif->u.ap.tim_bitmap[i] = (v >> ((i % 4) * 8)) & 0xFF;
} }
...@@ -1511,7 +1515,6 @@ static u32 ath10k_p2p_calc_noa_ie_len(struct wmi_p2p_noa_info *noa) ...@@ -1511,7 +1515,6 @@ static u32 ath10k_p2p_calc_noa_ie_len(struct wmi_p2p_noa_info *noa)
u8 opp_ps_info = noa->ctwindow_oppps; u8 opp_ps_info = noa->ctwindow_oppps;
bool opps_enabled = !!(opp_ps_info & WMI_P2P_OPPPS_ENABLE_BIT); bool opps_enabled = !!(opp_ps_info & WMI_P2P_OPPPS_ENABLE_BIT);
if (!noa_descriptors && !opps_enabled) if (!noa_descriptors && !opps_enabled)
return len; return len;
...@@ -1568,7 +1571,6 @@ static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif, ...@@ -1568,7 +1571,6 @@ static void ath10k_wmi_update_noa(struct ath10k *ar, struct ath10k_vif *arvif,
kfree(old_data); kfree(old_data);
} }
static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
{ {
struct wmi_host_swba_event *ev; struct wmi_host_swba_event *ev;
...@@ -1859,9 +1861,10 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar, ...@@ -1859,9 +1861,10 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar,
} }
} }
static void ath10k_wmi_event_spectral_scan(struct ath10k *ar, static void
struct wmi_single_phyerr_rx_event *event, ath10k_wmi_event_spectral_scan(struct ath10k *ar,
u64 tsf) struct wmi_single_phyerr_rx_event *event,
u64 tsf)
{ {
int buf_len, tlv_len, res, i = 0; int buf_len, tlv_len, res, i = 0;
struct phyerr_tlv *tlv; struct phyerr_tlv *tlv;
...@@ -1989,7 +1992,7 @@ static void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb) ...@@ -1989,7 +1992,7 @@ static void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb)
} }
static void ath10k_wmi_event_profile_match(struct ath10k *ar, static void ath10k_wmi_event_profile_match(struct ath10k *ar,
struct sk_buff *skb) struct sk_buff *skb)
{ {
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PROFILE_MATCH\n"); ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PROFILE_MATCH\n");
} }
...@@ -2040,13 +2043,13 @@ static void ath10k_wmi_event_wlan_profile_data(struct ath10k *ar, ...@@ -2040,13 +2043,13 @@ static void ath10k_wmi_event_wlan_profile_data(struct ath10k *ar,
} }
static void ath10k_wmi_event_rtt_measurement_report(struct ath10k *ar, static void ath10k_wmi_event_rtt_measurement_report(struct ath10k *ar,
struct sk_buff *skb) struct sk_buff *skb)
{ {
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_RTT_MEASUREMENT_REPORT_EVENTID\n"); ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_RTT_MEASUREMENT_REPORT_EVENTID\n");
} }
static void ath10k_wmi_event_tsf_measurement_report(struct ath10k *ar, static void ath10k_wmi_event_tsf_measurement_report(struct ath10k *ar,
struct sk_buff *skb) struct sk_buff *skb)
{ {
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TSF_MEASUREMENT_REPORT_EVENTID\n"); ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TSF_MEASUREMENT_REPORT_EVENTID\n");
} }
...@@ -2082,7 +2085,7 @@ static void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, ...@@ -2082,7 +2085,7 @@ static void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar,
} }
static void ath10k_wmi_event_gtk_offload_status(struct ath10k *ar, static void ath10k_wmi_event_gtk_offload_status(struct ath10k *ar,
struct sk_buff *skb) struct sk_buff *skb)
{ {
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_GTK_OFFLOAD_STATUS_EVENTID\n"); ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_GTK_OFFLOAD_STATUS_EVENTID\n");
} }
...@@ -2106,7 +2109,7 @@ static void ath10k_wmi_event_addba_complete(struct ath10k *ar, ...@@ -2106,7 +2109,7 @@ static void ath10k_wmi_event_addba_complete(struct ath10k *ar,
} }
static void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar, static void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar,
struct sk_buff *skb) struct sk_buff *skb)
{ {
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n"); ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n");
} }
...@@ -2130,7 +2133,7 @@ static void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar, ...@@ -2130,7 +2133,7 @@ static void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar,
} }
static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id, static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
u32 num_units, u32 unit_len) u32 num_units, u32 unit_len)
{ {
dma_addr_t paddr; dma_addr_t paddr;
u32 pool_size; u32 pool_size;
...@@ -2164,7 +2167,7 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, ...@@ -2164,7 +2167,7 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct wmi_service_ready_event *ev = (void *)skb->data; struct wmi_service_ready_event *ev = (void *)skb->data;
DECLARE_BITMAP(svc_bmap, WMI_SERVICE_BM_SIZE) = {}; DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {};
if (skb->len < sizeof(*ev)) { if (skb->len < sizeof(*ev)) {
ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n", ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
...@@ -2241,7 +2244,7 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar, ...@@ -2241,7 +2244,7 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i; u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
int ret; int ret;
struct wmi_service_ready_event_10x *ev = (void *)skb->data; struct wmi_service_ready_event_10x *ev = (void *)skb->data;
DECLARE_BITMAP(svc_bmap, WMI_SERVICE_BM_SIZE) = {}; DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {};
if (skb->len < sizeof(*ev)) { if (skb->len < sizeof(*ev)) {
ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n", ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
...@@ -2347,7 +2350,7 @@ static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2347,7 +2350,7 @@ static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb)
if (WARN_ON(skb->len < sizeof(*ev))) if (WARN_ON(skb->len < sizeof(*ev)))
return -EINVAL; return -EINVAL;
memcpy(ar->mac_addr, ev->mac_addr.addr, ETH_ALEN); ether_addr_copy(ar->mac_addr, ev->mac_addr.addr);
ath10k_dbg(ar, ATH10K_DBG_WMI, ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi event ready sw_version %u abi_version %u mac_addr %pM status %d skb->len %i ev-sz %zu\n", "wmi event ready sw_version %u abi_version %u mac_addr %pM status %d skb->len %i ev-sz %zu\n",
...@@ -2371,7 +2374,7 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2371,7 +2374,7 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb)
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
return; return;
trace_ath10k_wmi_event(id, skb->data, skb->len); trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
switch (id) { switch (id) {
case WMI_MGMT_RX_EVENTID: case WMI_MGMT_RX_EVENTID:
...@@ -2480,6 +2483,7 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2480,6 +2483,7 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
{ {
struct wmi_cmd_hdr *cmd_hdr; struct wmi_cmd_hdr *cmd_hdr;
enum wmi_10x_event_id id; enum wmi_10x_event_id id;
bool consumed;
cmd_hdr = (struct wmi_cmd_hdr *)skb->data; cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
...@@ -2487,7 +2491,19 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2487,7 +2491,19 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
return; return;
trace_ath10k_wmi_event(id, skb->data, skb->len); trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
consumed = ath10k_tm_event_wmi(ar, id, skb);
/* Ready event must be handled normally also in UTF mode so that we
* know the UTF firmware has booted, others we are just bypass WMI
* events to testmode.
*/
if (consumed && id != WMI_10X_READY_EVENTID) {
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi testmode consumed 0x%x\n", id);
goto out;
}
switch (id) { switch (id) {
case WMI_10X_MGMT_RX_EVENTID: case WMI_10X_MGMT_RX_EVENTID:
...@@ -2575,11 +2591,15 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2575,11 +2591,15 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
case WMI_10X_READY_EVENTID: case WMI_10X_READY_EVENTID:
ath10k_wmi_ready_event_rx(ar, skb); ath10k_wmi_ready_event_rx(ar, skb);
break; break;
case WMI_10X_PDEV_UTF_EVENTID:
/* ignore utf events */
break;
default: default:
ath10k_warn(ar, "Unknown eventid: %d\n", id); ath10k_warn(ar, "Unknown eventid: %d\n", id);
break; break;
} }
out:
dev_kfree_skb(skb); dev_kfree_skb(skb);
} }
...@@ -2594,7 +2614,7 @@ static void ath10k_wmi_10_2_process_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2594,7 +2614,7 @@ static void ath10k_wmi_10_2_process_rx(struct ath10k *ar, struct sk_buff *skb)
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL) if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
return; return;
trace_ath10k_wmi_event(id, skb->data, skb->len); trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
switch (id) { switch (id) {
case WMI_10_2_MGMT_RX_EVENTID: case WMI_10_2_MGMT_RX_EVENTID:
...@@ -3476,7 +3496,7 @@ int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id, ...@@ -3476,7 +3496,7 @@ int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id,
cmd->vdev_id = __cpu_to_le32(vdev_id); cmd->vdev_id = __cpu_to_le32(vdev_id);
cmd->vdev_type = __cpu_to_le32(type); cmd->vdev_type = __cpu_to_le32(type);
cmd->vdev_subtype = __cpu_to_le32(subtype); cmd->vdev_subtype = __cpu_to_le32(subtype);
memcpy(cmd->vdev_macaddr.addr, macaddr, ETH_ALEN); ether_addr_copy(cmd->vdev_macaddr.addr, macaddr);
ath10k_dbg(ar, ATH10K_DBG_WMI, ath10k_dbg(ar, ATH10K_DBG_WMI,
"WMI vdev create: id %d type %d subtype %d macaddr %pM\n", "WMI vdev create: id %d type %d subtype %d macaddr %pM\n",
...@@ -3503,9 +3523,10 @@ int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id) ...@@ -3503,9 +3523,10 @@ int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id)
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_delete_cmdid); return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_delete_cmdid);
} }
static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, static int
const struct wmi_vdev_start_request_arg *arg, ath10k_wmi_vdev_start_restart(struct ath10k *ar,
u32 cmd_id) const struct wmi_vdev_start_request_arg *arg,
u32 cmd_id)
{ {
struct wmi_vdev_start_request_cmd *cmd; struct wmi_vdev_start_request_cmd *cmd;
struct sk_buff *skb; struct sk_buff *skb;
...@@ -3569,8 +3590,8 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar, ...@@ -3569,8 +3590,8 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar,
cmd->chan.antenna_max = arg->channel.max_antenna_gain; cmd->chan.antenna_max = arg->channel.max_antenna_gain;
ath10k_dbg(ar, ATH10K_DBG_WMI, ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, " "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, ch_flags: 0x%0X, max_power: %d\n",
"ch_flags: 0x%0X, max_power: %d\n", cmdname, arg->vdev_id, cmdname, arg->vdev_id,
flags, arg->channel.freq, arg->channel.mode, flags, arg->channel.freq, arg->channel.mode,
cmd->chan.flags, arg->channel.max_power); cmd->chan.flags, arg->channel.max_power);
...@@ -3586,7 +3607,7 @@ int ath10k_wmi_vdev_start(struct ath10k *ar, ...@@ -3586,7 +3607,7 @@ int ath10k_wmi_vdev_start(struct ath10k *ar,
} }
int ath10k_wmi_vdev_restart(struct ath10k *ar, int ath10k_wmi_vdev_restart(struct ath10k *ar,
const struct wmi_vdev_start_request_arg *arg) const struct wmi_vdev_start_request_arg *arg)
{ {
u32 cmd_id = ar->wmi.cmd->vdev_restart_request_cmdid; u32 cmd_id = ar->wmi.cmd->vdev_restart_request_cmdid;
...@@ -3622,7 +3643,7 @@ int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid) ...@@ -3622,7 +3643,7 @@ int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
cmd = (struct wmi_vdev_up_cmd *)skb->data; cmd = (struct wmi_vdev_up_cmd *)skb->data;
cmd->vdev_id = __cpu_to_le32(vdev_id); cmd->vdev_id = __cpu_to_le32(vdev_id);
cmd->vdev_assoc_id = __cpu_to_le32(aid); cmd->vdev_assoc_id = __cpu_to_le32(aid);
memcpy(&cmd->vdev_bssid.addr, bssid, ETH_ALEN); ether_addr_copy(cmd->vdev_bssid.addr, bssid);
ath10k_dbg(ar, ATH10K_DBG_WMI, ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi mgmt vdev up id 0x%x assoc id %d bssid %pM\n", "wmi mgmt vdev up id 0x%x assoc id %d bssid %pM\n",
...@@ -3703,7 +3724,7 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar, ...@@ -3703,7 +3724,7 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar,
cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len); cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len);
if (arg->macaddr) if (arg->macaddr)
memcpy(cmd->peer_macaddr.addr, arg->macaddr, ETH_ALEN); ether_addr_copy(cmd->peer_macaddr.addr, arg->macaddr);
if (arg->key_data) if (arg->key_data)
memcpy(cmd->key_data, arg->key_data, arg->key_len); memcpy(cmd->key_data, arg->key_data, arg->key_len);
...@@ -3782,7 +3803,7 @@ int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, ...@@ -3782,7 +3803,7 @@ int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
cmd = (struct wmi_peer_create_cmd *)skb->data; cmd = (struct wmi_peer_create_cmd *)skb->data;
cmd->vdev_id = __cpu_to_le32(vdev_id); cmd->vdev_id = __cpu_to_le32(vdev_id);
memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
ath10k_dbg(ar, ATH10K_DBG_WMI, ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi peer create vdev_id %d peer_addr %pM\n", "wmi peer create vdev_id %d peer_addr %pM\n",
...@@ -3802,7 +3823,7 @@ int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id, ...@@ -3802,7 +3823,7 @@ int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
cmd = (struct wmi_peer_delete_cmd *)skb->data; cmd = (struct wmi_peer_delete_cmd *)skb->data;
cmd->vdev_id = __cpu_to_le32(vdev_id); cmd->vdev_id = __cpu_to_le32(vdev_id);
memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
ath10k_dbg(ar, ATH10K_DBG_WMI, ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi peer delete vdev_id %d peer_addr %pM\n", "wmi peer delete vdev_id %d peer_addr %pM\n",
...@@ -3823,7 +3844,7 @@ int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id, ...@@ -3823,7 +3844,7 @@ int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id,
cmd = (struct wmi_peer_flush_tids_cmd *)skb->data; cmd = (struct wmi_peer_flush_tids_cmd *)skb->data;
cmd->vdev_id = __cpu_to_le32(vdev_id); cmd->vdev_id = __cpu_to_le32(vdev_id);
cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap); cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap);
memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
ath10k_dbg(ar, ATH10K_DBG_WMI, ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi peer flush vdev_id %d peer_addr %pM tids %08x\n", "wmi peer flush vdev_id %d peer_addr %pM tids %08x\n",
...@@ -3846,7 +3867,7 @@ int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, ...@@ -3846,7 +3867,7 @@ int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id,
cmd->vdev_id = __cpu_to_le32(vdev_id); cmd->vdev_id = __cpu_to_le32(vdev_id);
cmd->param_id = __cpu_to_le32(param_id); cmd->param_id = __cpu_to_le32(param_id);
cmd->param_value = __cpu_to_le32(param_value); cmd->param_value = __cpu_to_le32(param_value);
memcpy(&cmd->peer_macaddr.addr, peer_addr, ETH_ALEN); ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
ath10k_dbg(ar, ATH10K_DBG_WMI, ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi vdev %d peer 0x%pM set param %d value %d\n", "wmi vdev %d peer 0x%pM set param %d value %d\n",
...@@ -3917,7 +3938,7 @@ int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac, ...@@ -3917,7 +3938,7 @@ int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac,
cmd->vdev_id = __cpu_to_le32(vdev_id); cmd->vdev_id = __cpu_to_le32(vdev_id);
cmd->param_id = __cpu_to_le32(param_id); cmd->param_id = __cpu_to_le32(param_id);
cmd->param_value = __cpu_to_le32(value); cmd->param_value = __cpu_to_le32(value);
memcpy(&cmd->peer_macaddr, mac, ETH_ALEN); ether_addr_copy(cmd->peer_macaddr.addr, mac);
ath10k_dbg(ar, ATH10K_DBG_WMI, ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi ap ps param vdev_id 0x%X param %d value %d mac_addr %pM\n", "wmi ap ps param vdev_id 0x%X param %d value %d mac_addr %pM\n",
...@@ -4001,7 +4022,7 @@ ath10k_wmi_peer_assoc_fill(struct ath10k *ar, void *buf, ...@@ -4001,7 +4022,7 @@ ath10k_wmi_peer_assoc_fill(struct ath10k *ar, void *buf,
cmd->peer_vht_caps = __cpu_to_le32(arg->peer_vht_caps); cmd->peer_vht_caps = __cpu_to_le32(arg->peer_vht_caps);
cmd->peer_phymode = __cpu_to_le32(arg->peer_phymode); cmd->peer_phymode = __cpu_to_le32(arg->peer_phymode);
memcpy(cmd->peer_macaddr.addr, arg->addr, ETH_ALEN); ether_addr_copy(cmd->peer_macaddr.addr, arg->addr);
cmd->peer_legacy_rates.num_rates = cmd->peer_legacy_rates.num_rates =
__cpu_to_le32(arg->peer_legacy_rates.num_rates); __cpu_to_le32(arg->peer_legacy_rates.num_rates);
...@@ -4155,7 +4176,7 @@ static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params, ...@@ -4155,7 +4176,7 @@ static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params,
} }
int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
const struct wmi_pdev_set_wmm_params_arg *arg) const struct wmi_pdev_set_wmm_params_arg *arg)
{ {
struct wmi_pdev_set_wmm_params *cmd; struct wmi_pdev_set_wmm_params *cmd;
struct sk_buff *skb; struct sk_buff *skb;
......
...@@ -109,6 +109,9 @@ enum wmi_service { ...@@ -109,6 +109,9 @@ enum wmi_service {
WMI_SERVICE_BURST, WMI_SERVICE_BURST,
WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT, WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT,
WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT, WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT,
/* keep last */
WMI_SERVICE_MAX,
}; };
enum wmi_10x_service { enum wmi_10x_service {
...@@ -219,8 +222,6 @@ static inline char *wmi_service_name(int service_id) ...@@ -219,8 +222,6 @@ static inline char *wmi_service_name(int service_id)
#undef SVCSTR #undef SVCSTR
} }
#define WMI_MAX_SERVICE 64
#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id) \ #define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id) \
(__le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \ (__le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
BIT((svc_id)%(sizeof(u32)))) BIT((svc_id)%(sizeof(u32))))
...@@ -347,9 +348,6 @@ static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out) ...@@ -347,9 +348,6 @@ static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out)
#undef SVCMAP #undef SVCMAP
#define WMI_SERVICE_BM_SIZE \
((WMI_MAX_SERVICE + sizeof(u32) - 1)/sizeof(u32))
/* 2 word representation of MAC addr */ /* 2 word representation of MAC addr */
struct wmi_mac_addr { struct wmi_mac_addr {
union { union {
...@@ -1271,7 +1269,6 @@ enum wmi_channel_change_cause { ...@@ -1271,7 +1269,6 @@ enum wmi_channel_change_cause {
WMI_HT_CAP_RX_STBC | \ WMI_HT_CAP_RX_STBC | \
WMI_HT_CAP_LDPC) WMI_HT_CAP_LDPC)
/* /*
* WMI_VHT_CAP_* these maps to ieee 802.11ac vht capability information * WMI_VHT_CAP_* these maps to ieee 802.11ac vht capability information
* field. The fields not defined here are not supported, or reserved. * field. The fields not defined here are not supported, or reserved.
...@@ -1405,7 +1402,7 @@ struct wmi_service_ready_event { ...@@ -1405,7 +1402,7 @@ struct wmi_service_ready_event {
__le32 phy_capability; __le32 phy_capability;
/* Maximum number of frag table entries that SW will populate less 1 */ /* Maximum number of frag table entries that SW will populate less 1 */
__le32 max_frag_entry; __le32 max_frag_entry;
__le32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; __le32 wmi_service_bitmap[16];
__le32 num_rf_chains; __le32 num_rf_chains;
/* /*
* The following field is only valid for service type * The following field is only valid for service type
...@@ -1444,7 +1441,7 @@ struct wmi_service_ready_event_10x { ...@@ -1444,7 +1441,7 @@ struct wmi_service_ready_event_10x {
/* Maximum number of frag table entries that SW will populate less 1 */ /* Maximum number of frag table entries that SW will populate less 1 */
__le32 max_frag_entry; __le32 max_frag_entry;
__le32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; __le32 wmi_service_bitmap[16];
__le32 num_rf_chains; __le32 num_rf_chains;
/* /*
...@@ -1473,7 +1470,6 @@ struct wmi_service_ready_event_10x { ...@@ -1473,7 +1470,6 @@ struct wmi_service_ready_event_10x {
struct wlan_host_mem_req mem_reqs[1]; struct wlan_host_mem_req mem_reqs[1];
} __packed; } __packed;
#define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ) #define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ)
#define WMI_UNIFIED_READY_TIMEOUT_HZ (5*HZ) #define WMI_UNIFIED_READY_TIMEOUT_HZ (5*HZ)
...@@ -2127,7 +2123,6 @@ struct wmi_start_scan_cmd_10x { ...@@ -2127,7 +2123,6 @@ struct wmi_start_scan_cmd_10x {
*/ */
} __packed; } __packed;
struct wmi_ssid_arg { struct wmi_ssid_arg {
int len; int len;
const u8 *ssid; const u8 *ssid;
...@@ -2188,7 +2183,6 @@ struct wmi_start_scan_arg { ...@@ -2188,7 +2183,6 @@ struct wmi_start_scan_arg {
/* WMI_SCAN_CLASS_MASK must be the same value as IEEE80211_SCAN_CLASS_MASK */ /* WMI_SCAN_CLASS_MASK must be the same value as IEEE80211_SCAN_CLASS_MASK */
#define WMI_SCAN_CLASS_MASK 0xFF000000 #define WMI_SCAN_CLASS_MASK 0xFF000000
enum wmi_stop_scan_type { enum wmi_stop_scan_type {
WMI_SCAN_STOP_ONE = 0x00000000, /* stop by scan_id */ WMI_SCAN_STOP_ONE = 0x00000000, /* stop by scan_id */
WMI_SCAN_STOP_VDEV_ALL = 0x01000000, /* stop by vdev_id */ WMI_SCAN_STOP_VDEV_ALL = 0x01000000, /* stop by vdev_id */
...@@ -2373,7 +2367,6 @@ struct wmi_single_phyerr_rx_hdr { ...@@ -2373,7 +2367,6 @@ struct wmi_single_phyerr_rx_hdr {
__le32 nf_list_1; __le32 nf_list_1;
__le32 nf_list_2; __le32 nf_list_2;
/* Length of the frame */ /* Length of the frame */
__le32 buf_len; __le32 buf_len;
} __packed; } __packed;
...@@ -2475,7 +2468,6 @@ struct phyerr_fft_report { ...@@ -2475,7 +2468,6 @@ struct phyerr_fft_report {
#define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_MASK 0x000000FF #define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_MASK 0x000000FF
#define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_LSB 0 #define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_LSB 0
struct phyerr_tlv { struct phyerr_tlv {
__le16 len; __le16 len;
u8 tag; u8 tag;
...@@ -2506,7 +2498,6 @@ struct wmi_echo_cmd { ...@@ -2506,7 +2498,6 @@ struct wmi_echo_cmd {
__le32 value; __le32 value;
} __packed; } __packed;
struct wmi_pdev_set_regdomain_cmd { struct wmi_pdev_set_regdomain_cmd {
__le32 reg_domain; __le32 reg_domain;
__le32 reg_domain_2G; __le32 reg_domain_2G;
...@@ -2555,7 +2546,6 @@ struct wmi_pdev_set_quiet_cmd { ...@@ -2555,7 +2546,6 @@ struct wmi_pdev_set_quiet_cmd {
__le32 enabled; __le32 enabled;
} __packed; } __packed;
/* /*
* 802.11g protection mode. * 802.11g protection mode.
*/ */
...@@ -4293,7 +4283,6 @@ struct wmi_tbtt_offset_event { ...@@ -4293,7 +4283,6 @@ struct wmi_tbtt_offset_event {
__le32 tbttoffset_list[WMI_MAX_AP_VDEV]; __le32 tbttoffset_list[WMI_MAX_AP_VDEV];
} __packed; } __packed;
struct wmi_peer_create_cmd { struct wmi_peer_create_cmd {
__le32 vdev_id; __le32 vdev_id;
struct wmi_mac_addr peer_macaddr; struct wmi_mac_addr peer_macaddr;
...@@ -4739,6 +4728,10 @@ int ath10k_wmi_wait_for_service_ready(struct ath10k *ar); ...@@ -4739,6 +4728,10 @@ int ath10k_wmi_wait_for_service_ready(struct ath10k *ar);
int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar); int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar);
int ath10k_wmi_connect(struct ath10k *ar); int ath10k_wmi_connect(struct ath10k *ar);
struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
int ath10k_wmi_pdev_set_channel(struct ath10k *ar, int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
const struct wmi_channel_arg *); const struct wmi_channel_arg *);
int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt); int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);
...@@ -4774,11 +4767,11 @@ int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar, ...@@ -4774,11 +4767,11 @@ int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger, int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
u32 enable); u32 enable);
int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id, int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN]); const u8 peer_addr[ETH_ALEN]);
int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id, int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN]); const u8 peer_addr[ETH_ALEN]);
int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id, int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN], u32 tid_bitmap); const u8 peer_addr[ETH_ALEN], u32 tid_bitmap);
int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id,
const u8 *peer_addr, const u8 *peer_addr,
enum wmi_peer_param param_id, u32 param_value); enum wmi_peer_param param_id, u32 param_value);
...@@ -4795,7 +4788,7 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar, ...@@ -4795,7 +4788,7 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar,
const struct wmi_scan_chan_list_arg *arg); const struct wmi_scan_chan_list_arg *arg);
int ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif); int ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif);
int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar, int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
const struct wmi_pdev_set_wmm_params_arg *arg); const struct wmi_pdev_set_wmm_params_arg *arg);
int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id); int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id);
int ath10k_wmi_force_fw_hang(struct ath10k *ar, int ath10k_wmi_force_fw_hang(struct ath10k *ar,
enum wmi_force_fw_hang_type type, u32 delay_ms); enum wmi_force_fw_hang_type type, u32 delay_ms);
......
config ATH5K config ATH5K
tristate "Atheros 5xxx wireless cards support" tristate "Atheros 5xxx wireless cards support"
depends on (PCI || ATHEROS_AR231X) && MAC80211 depends on PCI && MAC80211
select ATH_COMMON select ATH_COMMON
select MAC80211_LEDS select MAC80211_LEDS
select LEDS_CLASS select LEDS_CLASS
select NEW_LEDS select NEW_LEDS
select AVERAGE select AVERAGE
select ATH5K_AHB if (ATHEROS_AR231X && !PCI) select ATH5K_PCI
select ATH5K_PCI if (!ATHEROS_AR231X && PCI)
---help--- ---help---
This module adds support for wireless adapters based on This module adds support for wireless adapters based on
Atheros 5xxx chipset. Atheros 5xxx chipset.
...@@ -52,16 +51,9 @@ config ATH5K_TRACER ...@@ -52,16 +51,9 @@ config ATH5K_TRACER
If unsure, say N. If unsure, say N.
config ATH5K_AHB
bool "Atheros 5xxx AHB bus support"
depends on (ATHEROS_AR231X && !PCI)
---help---
This adds support for WiSoC type chipsets of the 5xxx Atheros
family.
config ATH5K_PCI config ATH5K_PCI
bool "Atheros 5xxx PCI bus support" bool "Atheros 5xxx PCI bus support"
depends on (!ATHEROS_AR231X && PCI) depends on PCI
---help--- ---help---
This adds support for PCI type chipsets of the 5xxx Atheros This adds support for PCI type chipsets of the 5xxx Atheros
family. family.
......
...@@ -17,6 +17,5 @@ ath5k-y += ani.o ...@@ -17,6 +17,5 @@ ath5k-y += ani.o
ath5k-y += sysfs.o ath5k-y += sysfs.o
ath5k-y += mac80211-ops.o ath5k-y += mac80211-ops.o
ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o
ath5k-$(CONFIG_ATH5K_AHB) += ahb.o
ath5k-$(CONFIG_ATH5K_PCI) += pci.o ath5k-$(CONFIG_ATH5K_PCI) += pci.o
obj-$(CONFIG_ATH5K) += ath5k.o obj-$(CONFIG_ATH5K) += ath5k.o
/*
* Copyright (c) 2008-2009 Atheros Communications Inc.
* Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
* Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/nl80211.h>
#include <linux/platform_device.h>
#include <linux/etherdevice.h>
#include <linux/export.h>
#include <ar231x_platform.h>
#include "ath5k.h"
#include "debug.h"
#include "base.h"
#include "reg.h"
/* return bus cachesize in 4B word units */
static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
{
*csz = L1_CACHE_BYTES >> 2;
}
static bool
ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
{
struct ath5k_hw *ah = common->priv;
struct platform_device *pdev = to_platform_device(ah->dev);
struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
u16 *eeprom, *eeprom_end;
eeprom = (u16 *) bcfg->radio;
eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ;
eeprom += off;
if (eeprom > eeprom_end)
return false;
*data = *eeprom;
return true;
}
int ath5k_hw_read_srev(struct ath5k_hw *ah)
{
struct platform_device *pdev = to_platform_device(ah->dev);
struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
ah->ah_mac_srev = bcfg->devid;
return 0;
}
static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
{
struct platform_device *pdev = to_platform_device(ah->dev);
struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
u8 *cfg_mac;
if (to_platform_device(ah->dev)->id == 0)
cfg_mac = bcfg->config->wlan0_mac;
else
cfg_mac = bcfg->config->wlan1_mac;
memcpy(mac, cfg_mac, ETH_ALEN);
return 0;
}
static const struct ath_bus_ops ath_ahb_bus_ops = {
.ath_bus_type = ATH_AHB,
.read_cachesize = ath5k_ahb_read_cachesize,
.eeprom_read = ath5k_ahb_eeprom_read,
.eeprom_read_mac = ath5k_ahb_eeprom_read_mac,
};
/*Initialization*/
static int ath_ahb_probe(struct platform_device *pdev)
{
struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
struct ath5k_hw *ah;
struct ieee80211_hw *hw;
struct resource *res;
void __iomem *mem;
int irq;
int ret = 0;
u32 reg;
if (!dev_get_platdata(&pdev->dev)) {
dev_err(&pdev->dev, "no platform data specified\n");
ret = -EINVAL;
goto err_out;
}
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;
}
mem = ioremap_nocache(res->start, resource_size(res));
if (mem == NULL) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -ENOMEM;
goto err_out;
}
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;
}
irq = res->start;
hw = ieee80211_alloc_hw(sizeof(struct ath5k_hw), &ath5k_hw_ops);
if (hw == NULL) {
dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
ret = -ENOMEM;
goto err_iounmap;
}
ah = hw->priv;
ah->hw = hw;
ah->dev = &pdev->dev;
ah->iobase = mem;
ah->irq = irq;
ah->devid = bcfg->devid;
if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
/* Enable WMAC AHB arbitration */
reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
reg |= AR5K_AR2315_AHB_ARB_CTL_WLAN;
iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
/* Enable global WMAC swapping */
reg = ioread32((void __iomem *) AR5K_AR2315_BYTESWAP);
reg |= AR5K_AR2315_BYTESWAP_WMAC;
iowrite32(reg, (void __iomem *) AR5K_AR2315_BYTESWAP);
} else {
/* Enable WMAC DMA access (assuming 5312 or 231x*/
/* TODO: check other platforms */
reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
if (to_platform_device(ah->dev)->id == 0)
reg |= AR5K_AR5312_ENABLE_WLAN0;
else
reg |= AR5K_AR5312_ENABLE_WLAN1;
iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
/*
* On a dual-band AR5312, the multiband radio is only
* used as pass-through. Disable 2 GHz support in the
* driver for it
*/
if (to_platform_device(ah->dev)->id == 0 &&
(bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) ==
(BD_WLAN1 | BD_WLAN0))
ah->ah_capabilities.cap_needs_2GHz_ovr = true;
else
ah->ah_capabilities.cap_needs_2GHz_ovr = false;
}
ret = ath5k_init_ah(ah, &ath_ahb_bus_ops);
if (ret != 0) {
dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
ret = -ENODEV;
goto err_free_hw;
}
platform_set_drvdata(pdev, hw);
return 0;
err_free_hw:
ieee80211_free_hw(hw);
err_iounmap:
iounmap(mem);
err_out:
return ret;
}
static int ath_ahb_remove(struct platform_device *pdev)
{
struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
struct ieee80211_hw *hw = platform_get_drvdata(pdev);
struct ath5k_hw *ah;
u32 reg;
if (!hw)
return 0;
ah = hw->priv;
if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
/* Disable WMAC AHB arbitration */
reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
reg &= ~AR5K_AR2315_AHB_ARB_CTL_WLAN;
iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
} else {
/*Stop DMA access */
reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
if (to_platform_device(ah->dev)->id == 0)
reg &= ~AR5K_AR5312_ENABLE_WLAN0;
else
reg &= ~AR5K_AR5312_ENABLE_WLAN1;
iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
}
ath5k_deinit_ah(ah);
iounmap(ah->iobase);
ieee80211_free_hw(hw);
return 0;
}
static struct platform_driver ath_ahb_driver = {
.probe = ath_ahb_probe,
.remove = ath_ahb_remove,
.driver = {
.name = "ar231x-wmac",
.owner = THIS_MODULE,
},
};
module_platform_driver(ath_ahb_driver);
...@@ -1647,32 +1647,6 @@ static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah) ...@@ -1647,32 +1647,6 @@ static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah)
return &(ath5k_hw_common(ah)->regulatory); return &(ath5k_hw_common(ah)->regulatory);
} }
#ifdef CONFIG_ATHEROS_AR231X
#define AR5K_AR2315_PCI_BASE ((void __iomem *)0xb0100000)
static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg)
{
/* On AR2315 and AR2317 the PCI clock domain registers
* are outside of the WMAC register space */
if (unlikely((reg >= 0x4000) && (reg < 0x5000) &&
(ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))
return AR5K_AR2315_PCI_BASE + reg;
return ah->iobase + reg;
}
static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
{
return ioread32(ath5k_ahb_reg(ah, reg));
}
static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
{
iowrite32(val, ath5k_ahb_reg(ah, reg));
}
#else
static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
{ {
return ioread32(ah->iobase + reg); return ioread32(ah->iobase + reg);
...@@ -1683,8 +1657,6 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) ...@@ -1683,8 +1657,6 @@ static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
iowrite32(val, ah->iobase + reg); iowrite32(val, ah->iobase + reg);
} }
#endif
static inline enum ath_bus_type ath5k_get_bus_type(struct ath5k_hw *ah) static inline enum ath_bus_type ath5k_get_bus_type(struct ath5k_hw *ah)
{ {
return ath5k_hw_common(ah)->bus_ops->ath_bus_type; return ath5k_hw_common(ah)->bus_ops->ath_bus_type;
......
...@@ -99,15 +99,6 @@ static int ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan, ...@@ -99,15 +99,6 @@ static int ath5k_reset(struct ath5k_hw *ah, struct ieee80211_channel *chan,
/* Known SREVs */ /* Known SREVs */
static const struct ath5k_srev_name srev_names[] = { static const struct ath5k_srev_name srev_names[] = {
#ifdef CONFIG_ATHEROS_AR231X
{ "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R2 },
{ "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R7 },
{ "2313", AR5K_VERSION_MAC, AR5K_SREV_AR2313_R8 },
{ "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R6 },
{ "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R7 },
{ "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R1 },
{ "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R2 },
#else
{ "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 },
{ "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 },
{ "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A },
...@@ -126,7 +117,6 @@ static const struct ath5k_srev_name srev_names[] = { ...@@ -126,7 +117,6 @@ static const struct ath5k_srev_name srev_names[] = {
{ "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 }, { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 },
{ "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 }, { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 },
{ "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 }, { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 },
#endif
{ "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN }, { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN },
{ "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 },
{ "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 },
...@@ -142,10 +132,6 @@ static const struct ath5k_srev_name srev_names[] = { ...@@ -142,10 +132,6 @@ static const struct ath5k_srev_name srev_names[] = {
{ "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 }, { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 },
{ "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 }, { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 },
{ "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
#ifdef CONFIG_ATHEROS_AR231X
{ "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 },
{ "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 },
#endif
{ "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN },
}; };
......
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/vmalloc.h>
#include "debug.h" #include "debug.h"
#include "ath5k.h" #include "ath5k.h"
#include "reg.h" #include "reg.h"
......
...@@ -163,20 +163,14 @@ int ath5k_init_leds(struct ath5k_hw *ah) ...@@ -163,20 +163,14 @@ int ath5k_init_leds(struct ath5k_hw *ah)
{ {
int ret = 0; int ret = 0;
struct ieee80211_hw *hw = ah->hw; struct ieee80211_hw *hw = ah->hw;
#ifndef CONFIG_ATHEROS_AR231X
struct pci_dev *pdev = ah->pdev; struct pci_dev *pdev = ah->pdev;
#endif
char name[ATH5K_LED_MAX_NAME_LEN + 1]; char name[ATH5K_LED_MAX_NAME_LEN + 1];
const struct pci_device_id *match; const struct pci_device_id *match;
if (!ah->pdev) if (!ah->pdev)
return 0; return 0;
#ifdef CONFIG_ATHEROS_AR231X
match = NULL;
#else
match = pci_match_id(&ath5k_led_devices[0], pdev); match = pci_match_id(&ath5k_led_devices[0], pdev);
#endif
if (match) { if (match) {
__set_bit(ATH_STAT_LEDSOFT, ah->status); __set_bit(ATH_STAT_LEDSOFT, ah->status);
ah->led_pin = ATH_PIN(match->driver_data); ah->led_pin = ATH_PIN(match->driver_data);
......
...@@ -1004,9 +1004,11 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, ...@@ -1004,9 +1004,11 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
case ATH9K_ANI_FIRSTEP_LEVEL:{ case ATH9K_ANI_FIRSTEP_LEVEL:{
u32 level = param; u32 level = param;
value = level; value = level * 2;
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
AR_PHY_FIND_SIG_FIRSTEP, value); AR_PHY_FIND_SIG_FIRSTEP, value);
REG_RMW_FIELD(ah, AR_PHY_FIND_SIG_LOW,
AR_PHY_FIND_SIG_FIRSTEP_LOW, value);
if (level != aniState->firstepLevel) { if (level != aniState->firstepLevel) {
ath_dbg(common, ANI, ath_dbg(common, ANI,
...@@ -1040,9 +1042,8 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah, ...@@ -1040,9 +1042,8 @@ static bool ar5008_hw_ani_control_new(struct ath_hw *ah,
REG_RMW_FIELD(ah, AR_PHY_TIMING5, REG_RMW_FIELD(ah, AR_PHY_TIMING5,
AR_PHY_TIMING5_CYCPWR_THR1, value); AR_PHY_TIMING5_CYCPWR_THR1, value);
if (IS_CHAN_HT40(ah->curchan)) REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, AR_PHY_EXT_TIMING5_CYCPWR_THR1, value - 1);
AR_PHY_EXT_TIMING5_CYCPWR_THR1, value);
if (level != aniState->spurImmunityLevel) { if (level != aniState->spurImmunityLevel) {
ath_dbg(common, ANI, ath_dbg(common, ANI,
......
...@@ -381,16 +381,27 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, ...@@ -381,16 +381,27 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
ts->evm1 = ads->AR_TxEVM1; ts->evm1 = ads->AR_TxEVM1;
ts->evm2 = ads->AR_TxEVM2; ts->evm2 = ads->AR_TxEVM2;
status = ACCESS_ONCE(ads->ds_ctl4);
ts->duration[0] = MS(status, AR_PacketDur0);
ts->duration[1] = MS(status, AR_PacketDur1);
status = ACCESS_ONCE(ads->ds_ctl5);
ts->duration[2] = MS(status, AR_PacketDur2);
ts->duration[3] = MS(status, AR_PacketDur3);
return 0; return 0;
} }
static int ar9002_hw_get_duration(struct ath_hw *ah, const void *ds, int index)
{
struct ar5416_desc *ads = AR5416DESC(ds);
switch (index) {
case 0:
return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur0);
case 1:
return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur1);
case 2:
return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur2);
case 3:
return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur3);
default:
return -1;
}
}
void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
u32 size, u32 flags) u32 size, u32 flags)
{ {
...@@ -413,4 +424,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah) ...@@ -413,4 +424,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah)
ops->get_isr = ar9002_hw_get_isr; ops->get_isr = ar9002_hw_get_isr;
ops->set_txdesc = ar9002_set_txdesc; ops->set_txdesc = ar9002_set_txdesc;
ops->proc_txdesc = ar9002_hw_proc_txdesc; ops->proc_txdesc = ar9002_hw_proc_txdesc;
ops->get_duration = ar9002_hw_get_duration;
} }
...@@ -355,11 +355,9 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, ...@@ -355,11 +355,9 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts) struct ath_tx_status *ts)
{ {
struct ar9003_txs *ads; struct ar9003_txs *ads;
struct ar9003_txc *adc;
u32 status; u32 status;
ads = &ah->ts_ring[ah->ts_tail]; ads = &ah->ts_ring[ah->ts_tail];
adc = (struct ar9003_txc *)ads;
status = ACCESS_ONCE(ads->status8); status = ACCESS_ONCE(ads->status8);
if ((status & AR_TxDone) == 0) if ((status & AR_TxDone) == 0)
...@@ -428,18 +426,29 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, ...@@ -428,18 +426,29 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds,
ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11);
ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12); ts->ts_rssi_ext2 = MS(status, AR_TxRSSIAnt12);
status = ACCESS_ONCE(adc->ctl15);
ts->duration[0] = MS(status, AR_PacketDur0);
ts->duration[1] = MS(status, AR_PacketDur1);
status = ACCESS_ONCE(adc->ctl16);
ts->duration[2] = MS(status, AR_PacketDur2);
ts->duration[3] = MS(status, AR_PacketDur3);
memset(ads, 0, sizeof(*ads)); memset(ads, 0, sizeof(*ads));
return 0; return 0;
} }
static int ar9003_hw_get_duration(struct ath_hw *ah, const void *ds, int index)
{
const struct ar9003_txc *adc = ds;
switch (index) {
case 0:
return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur0);
case 1:
return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur1);
case 2:
return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur2);
case 3:
return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur3);
default:
return 0;
}
}
void ar9003_hw_attach_mac_ops(struct ath_hw *hw) void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
{ {
struct ath_hw_ops *ops = ath9k_hw_ops(hw); struct ath_hw_ops *ops = ath9k_hw_ops(hw);
...@@ -449,6 +458,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) ...@@ -449,6 +458,7 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw)
ops->get_isr = ar9003_hw_get_isr; ops->get_isr = ar9003_hw_get_isr;
ops->set_txdesc = ar9003_set_txdesc; ops->set_txdesc = ar9003_set_txdesc;
ops->proc_txdesc = ar9003_hw_proc_txdesc; ops->proc_txdesc = ar9003_hw_proc_txdesc;
ops->get_duration = ar9003_hw_get_duration;
} }
void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size)
......
...@@ -517,6 +517,23 @@ static void ar9003_hw_spur_mitigate(struct ath_hw *ah, ...@@ -517,6 +517,23 @@ static void ar9003_hw_spur_mitigate(struct ath_hw *ah,
ar9003_hw_spur_mitigate_ofdm(ah, chan); ar9003_hw_spur_mitigate_ofdm(ah, chan);
} }
static u32 ar9003_hw_compute_pll_control_soc(struct ath_hw *ah,
struct ath9k_channel *chan)
{
u32 pll;
pll = SM(0x5, AR_RTC_9300_SOC_PLL_REFDIV);
if (chan && IS_CHAN_HALF_RATE(chan))
pll |= SM(0x1, AR_RTC_9300_SOC_PLL_CLKSEL);
else if (chan && IS_CHAN_QUARTER_RATE(chan))
pll |= SM(0x2, AR_RTC_9300_SOC_PLL_CLKSEL);
pll |= SM(0x2c, AR_RTC_9300_SOC_PLL_DIV_INT);
return pll;
}
static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah, static u32 ar9003_hw_compute_pll_control(struct ath_hw *ah,
struct ath9k_channel *chan) struct ath9k_channel *chan)
{ {
...@@ -1781,7 +1798,12 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) ...@@ -1781,7 +1798,12 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->rf_set_freq = ar9003_hw_set_channel; priv_ops->rf_set_freq = ar9003_hw_set_channel;
priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate; priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate;
priv_ops->compute_pll_control = ar9003_hw_compute_pll_control;
if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah))
priv_ops->compute_pll_control = ar9003_hw_compute_pll_control_soc;
else
priv_ops->compute_pll_control = ar9003_hw_compute_pll_control;
priv_ops->set_channel_regs = ar9003_hw_set_channel_regs; priv_ops->set_channel_regs = ar9003_hw_set_channel_regs;
priv_ops->init_bb = ar9003_hw_init_bb; priv_ops->init_bb = ar9003_hw_init_bb;
priv_ops->process_ini = ar9003_hw_process_ini; priv_ops->process_ini = ar9003_hw_process_ini;
......
...@@ -354,6 +354,7 @@ struct ath_chanctx { ...@@ -354,6 +354,7 @@ struct ath_chanctx {
bool switch_after_beacon; bool switch_after_beacon;
short nvifs; short nvifs;
short nvifs_assigned;
unsigned int rxfilter; unsigned int rxfilter;
}; };
...@@ -454,7 +455,8 @@ void ath9k_p2p_bss_info_changed(struct ath_softc *sc, ...@@ -454,7 +455,8 @@ void ath9k_p2p_bss_info_changed(struct ath_softc *sc,
void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *avp, void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *avp,
struct sk_buff *skb); struct sk_buff *skb);
void ath9k_p2p_ps_timer(void *priv); void ath9k_p2p_ps_timer(void *priv);
void ath9k_chanctx_wake_queues(struct ath_softc *sc); void ath9k_chanctx_wake_queues(struct ath_softc *sc, struct ath_chanctx *ctx);
void ath9k_chanctx_stop_queues(struct ath_softc *sc, struct ath_chanctx *ctx);
void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx); void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx);
void ath_chanctx_beacon_recv_ev(struct ath_softc *sc, void ath_chanctx_beacon_recv_ev(struct ath_softc *sc,
...@@ -524,7 +526,12 @@ static inline void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *av ...@@ -524,7 +526,12 @@ static inline void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *av
static inline void ath9k_p2p_ps_timer(struct ath_softc *sc) static inline void ath9k_p2p_ps_timer(struct ath_softc *sc)
{ {
} }
static inline void ath9k_chanctx_wake_queues(struct ath_softc *sc) static inline void ath9k_chanctx_wake_queues(struct ath_softc *sc,
struct ath_chanctx *ctx)
{
}
static inline void ath9k_chanctx_stop_queues(struct ath_softc *sc,
struct ath_chanctx *ctx)
{ {
} }
static inline void ath_chanctx_check_active(struct ath_softc *sc, static inline void ath_chanctx_check_active(struct ath_softc *sc,
...@@ -585,6 +592,11 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, ...@@ -585,6 +592,11 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
struct ath_vif { struct ath_vif {
struct list_head list; struct list_head list;
/* BSS info */
u8 bssid[ETH_ALEN];
u16 aid;
bool assoc;
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
struct ath_node mcast_node; struct ath_node mcast_node;
int av_bslot; int av_bslot;
......
...@@ -211,7 +211,7 @@ void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx) ...@@ -211,7 +211,7 @@ void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx)
switch (vif->type) { switch (vif->type) {
case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
if (vif->bss_conf.assoc) if (avp->assoc)
active = true; active = true;
break; break;
default: default:
...@@ -761,6 +761,13 @@ void ath_offchannel_next(struct ath_softc *sc) ...@@ -761,6 +761,13 @@ void ath_offchannel_next(struct ath_softc *sc)
void ath_roc_complete(struct ath_softc *sc, bool abort) void ath_roc_complete(struct ath_softc *sc, bool abort)
{ {
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
if (abort)
ath_dbg(common, CHAN_CTX, "RoC aborted\n");
else
ath_dbg(common, CHAN_CTX, "RoC expired\n");
sc->offchannel.roc_vif = NULL; sc->offchannel.roc_vif = NULL;
sc->offchannel.roc_chan = NULL; sc->offchannel.roc_chan = NULL;
if (!abort) if (!abort)
...@@ -917,7 +924,7 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp, ...@@ -917,7 +924,7 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
switch (vif->type) { switch (vif->type) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
if (!vif->bss_conf.assoc) if (!avp->assoc)
return false; return false;
skb = ieee80211_nullfunc_get(sc->hw, vif); skb = ieee80211_nullfunc_get(sc->hw, vif);
...@@ -1037,9 +1044,11 @@ static void ath_offchannel_channel_change(struct ath_softc *sc) ...@@ -1037,9 +1044,11 @@ static void ath_offchannel_channel_change(struct ath_softc *sc)
void ath_chanctx_set_next(struct ath_softc *sc, bool force) void ath_chanctx_set_next(struct ath_softc *sc, bool force)
{ {
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_chanctx *old_ctx;
struct timespec ts; struct timespec ts;
bool measure_time = false; bool measure_time = false;
bool send_ps = false; bool send_ps = false;
bool queues_stopped = false;
spin_lock_bh(&sc->chan_lock); spin_lock_bh(&sc->chan_lock);
if (!sc->next_chan) { if (!sc->next_chan) {
...@@ -1069,6 +1078,10 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force) ...@@ -1069,6 +1078,10 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
getrawmonotonic(&ts); getrawmonotonic(&ts);
measure_time = true; measure_time = true;
} }
ath9k_chanctx_stop_queues(sc, sc->cur_chan);
queues_stopped = true;
__ath9k_flush(sc->hw, ~0, true); __ath9k_flush(sc->hw, ~0, true);
if (ath_chanctx_send_ps_frame(sc, true)) if (ath_chanctx_send_ps_frame(sc, true))
...@@ -1082,6 +1095,7 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force) ...@@ -1082,6 +1095,7 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
sc->cur_chan->tsf_val = ath9k_hw_gettsf64(sc->sc_ah); sc->cur_chan->tsf_val = ath9k_hw_gettsf64(sc->sc_ah);
} }
} }
old_ctx = sc->cur_chan;
sc->cur_chan = sc->next_chan; sc->cur_chan = sc->next_chan;
sc->cur_chan->stopped = false; sc->cur_chan->stopped = false;
sc->next_chan = NULL; sc->next_chan = NULL;
...@@ -1104,7 +1118,16 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force) ...@@ -1104,7 +1118,16 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
if (measure_time) if (measure_time)
sc->sched.channel_switch_time = sc->sched.channel_switch_time =
ath9k_hw_get_tsf_offset(&ts, NULL); ath9k_hw_get_tsf_offset(&ts, NULL);
/*
* A reset will ensure that all queues are woken up,
* so there is no need to awaken them again.
*/
goto out;
} }
if (queues_stopped)
ath9k_chanctx_wake_queues(sc, old_ctx);
out:
if (send_ps) if (send_ps)
ath_chanctx_send_ps_frame(sc, false); ath_chanctx_send_ps_frame(sc, false);
...@@ -1170,18 +1193,37 @@ bool ath9k_is_chanctx_enabled(void) ...@@ -1170,18 +1193,37 @@ bool ath9k_is_chanctx_enabled(void)
/* Queue management */ /* Queue management */
/********************/ /********************/
void ath9k_chanctx_wake_queues(struct ath_softc *sc) void ath9k_chanctx_stop_queues(struct ath_softc *sc, struct ath_chanctx *ctx)
{
struct ath_hw *ah = sc->sc_ah;
int i;
if (ctx == &sc->offchannel.chan) {
ieee80211_stop_queue(sc->hw,
sc->hw->offchannel_tx_hw_queue);
} else {
for (i = 0; i < IEEE80211_NUM_ACS; i++)
ieee80211_stop_queue(sc->hw,
ctx->hw_queue_base + i);
}
if (ah->opmode == NL80211_IFTYPE_AP)
ieee80211_stop_queue(sc->hw, sc->hw->queues - 2);
}
void ath9k_chanctx_wake_queues(struct ath_softc *sc, struct ath_chanctx *ctx)
{ {
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
int i; int i;
if (sc->cur_chan == &sc->offchannel.chan) { if (ctx == &sc->offchannel.chan) {
ieee80211_wake_queue(sc->hw, ieee80211_wake_queue(sc->hw,
sc->hw->offchannel_tx_hw_queue); sc->hw->offchannel_tx_hw_queue);
} else { } else {
for (i = 0; i < IEEE80211_NUM_ACS; i++) for (i = 0; i < IEEE80211_NUM_ACS; i++)
ieee80211_wake_queue(sc->hw, ieee80211_wake_queue(sc->hw,
sc->cur_chan->hw_queue_base + i); ctx->hw_queue_base + i);
} }
if (ah->opmode == NL80211_IFTYPE_AP) if (ah->opmode == NL80211_IFTYPE_AP)
...@@ -1339,7 +1381,7 @@ void ath9k_p2p_ps_timer(void *priv) ...@@ -1339,7 +1381,7 @@ void ath9k_p2p_ps_timer(void *priv)
rcu_read_lock(); rcu_read_lock();
vif = avp->vif; vif = avp->vif;
sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); sta = ieee80211_find_sta(vif, avp->bssid);
if (!sta) if (!sta)
goto out; goto out;
......
...@@ -202,7 +202,7 @@ void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb, ...@@ -202,7 +202,7 @@ void ath_dynack_sample_tx_ts(struct ath_hw *ah, struct sk_buff *skb,
ridx = ts->ts_rateindex; ridx = ts->ts_rateindex;
da->st_rbf.ts[da->st_rbf.t_rb].tstamp = ts->ts_tstamp; da->st_rbf.ts[da->st_rbf.t_rb].tstamp = ts->ts_tstamp;
da->st_rbf.ts[da->st_rbf.t_rb].dur = ts->duration[ts->ts_rateindex]; da->st_rbf.ts[da->st_rbf.t_rb].dur = ts->duration;
ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_dest, hdr->addr1); ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_dest, hdr->addr1);
ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_src, hdr->addr2); ether_addr_copy(da->st_rbf.addr[da->st_rbf.t_rb].h_src, hdr->addr2);
......
...@@ -67,6 +67,12 @@ static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds, ...@@ -67,6 +67,12 @@ static inline int ath9k_hw_txprocdesc(struct ath_hw *ah, void *ds,
return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts); return ath9k_hw_ops(ah)->proc_txdesc(ah, ds, ts);
} }
static inline int ath9k_hw_get_duration(struct ath_hw *ah, const void *ds,
int index)
{
return ath9k_hw_ops(ah)->get_duration(ah, ds, index);
}
static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah,
struct ath_hw_antcomb_conf *antconf) struct ath_hw_antcomb_conf *antconf)
{ {
......
此差异已折叠。
...@@ -691,6 +691,7 @@ struct ath_hw_ops { ...@@ -691,6 +691,7 @@ struct ath_hw_ops {
struct ath_tx_info *i); struct ath_tx_info *i);
int (*proc_txdesc)(struct ath_hw *ah, void *ds, int (*proc_txdesc)(struct ath_hw *ah, void *ds,
struct ath_tx_status *ts); struct ath_tx_status *ts);
int (*get_duration)(struct ath_hw *ah, const void *ds, int index);
void (*antdiv_comb_conf_get)(struct ath_hw *ah, void (*antdiv_comb_conf_get)(struct ath_hw *ah,
struct ath_hw_antcomb_conf *antconf); struct ath_hw_antcomb_conf *antconf);
void (*antdiv_comb_conf_set)(struct ath_hw *ah, void (*antdiv_comb_conf_set)(struct ath_hw *ah,
......
...@@ -121,7 +121,7 @@ struct ath_tx_status { ...@@ -121,7 +121,7 @@ struct ath_tx_status {
u32 evm0; u32 evm0;
u32 evm1; u32 evm1;
u32 evm2; u32 evm2;
u32 duration[4]; u32 duration;
}; };
struct ath_rx_status { struct ath_rx_status {
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/module.h> #include <linux/module.h>
#include "ath.h" #include "ath.h"
#include "trace.h"
MODULE_AUTHOR("Atheros Communications"); MODULE_AUTHOR("Atheros Communications");
MODULE_DESCRIPTION("Shared library for Atheros wireless LAN cards."); MODULE_DESCRIPTION("Shared library for Atheros wireless LAN cards.");
...@@ -84,6 +85,8 @@ void ath_printk(const char *level, const struct ath_common* common, ...@@ -84,6 +85,8 @@ void ath_printk(const char *level, const struct ath_common* common,
else else
printk("%sath: %pV", level, &vaf); printk("%sath: %pV", level, &vaf);
trace_ath_log(common->hw->wiphy, &vaf);
va_end(args); va_end(args);
} }
EXPORT_SYMBOL(ath_printk); EXPORT_SYMBOL(ath_printk);
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册