mirror of
https://github.com/Dasharo/linux.git
synced 2026-03-06 15:25:10 -08:00
Merge tag 'wireless-drivers-next-for-davem-2016-03-09' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Kalle Valo says: ==================== wireless-drivers patches for 4.6 Major changes: ath10k * dt: add bindings for ipq4019 wifi block * start adding support for qca4019 chip ath9k * add device ID for Toshiba WLM-20U2/GN-1080 * allow more than one interface on DFS channels bcma * move flash detection code to ChipCommon core driver brcmfmac * IPv6 Neighbor discovery offload * driver settings that can be populated from different sources * country code setting in firmware * length checks to validate firmware events * new way to determine device memory size needed for BCM4366 * various offloads during Wake on Wireless LAN (WoWLAN) * full Management Frame Protection (MFP) support iwlwifi * add support for thermal device / cooling device * improvements in scheduled scan without profiles * new firmware support (-21.ucode) * add MSIX support for 9000 devices * enable MU-MIMO and take care of firmware restart * add support for large SKBs in mvm to reach A-MSDU * add support for filtering frames from a BA session * start implementing the new Rx path for 9000 devices * enable the new Radio Resource Management (RRM) nl80211 feature flag * add a new module paramater to disable VHT * build infrastructure for Dynamic Queue Allocation ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -1,17 +1,46 @@
|
||||
* Qualcomm Atheros ath10k wireless devices
|
||||
|
||||
For ath10k devices the calibration data can be provided through Device
|
||||
Tree. The node is a child node of the PCI controller.
|
||||
|
||||
Required properties:
|
||||
-compatible : Should be "qcom,ath10k"
|
||||
- compatible: Should be one of the following:
|
||||
* "qcom,ath10k"
|
||||
* "qcom,ipq4019-wifi"
|
||||
|
||||
PCI based devices uses compatible string "qcom,ath10k" and takes only
|
||||
calibration data via "qcom,ath10k-calibration-data". Rest of the properties
|
||||
are not applicable for PCI based devices.
|
||||
|
||||
AHB based devices (i.e. ipq4019) uses compatible string "qcom,ipq4019-wifi"
|
||||
and also uses most of the properties defined in this doc.
|
||||
|
||||
Optional properties:
|
||||
- reg: Address and length of the register set for the device.
|
||||
- resets: Must contain an entry for each entry in reset-names.
|
||||
See ../reset/reseti.txt for details.
|
||||
- reset-names: Must include the list of following reset names,
|
||||
"wifi_cpu_init"
|
||||
"wifi_radio_srif"
|
||||
"wifi_radio_warm"
|
||||
"wifi_radio_cold"
|
||||
"wifi_core_warm"
|
||||
"wifi_core_cold"
|
||||
- clocks: List of clock specifiers, must contain an entry for each required
|
||||
entry in clock-names.
|
||||
- clock-names: Should contain the clock names "wifi_wcss_cmd", "wifi_wcss_ref",
|
||||
"wifi_wcss_rtc".
|
||||
- interrupts: List of interrupt lines. Must contain an entry
|
||||
for each entry in the interrupt-names property.
|
||||
- interrupt-names: Must include the entries for MSI interrupt
|
||||
names ("msi0" to "msi15") and legacy interrupt
|
||||
name ("legacy"),
|
||||
- qcom,msi_addr: MSI interrupt address.
|
||||
- qcom,msi_base: Base value to add before writing MSI data into
|
||||
MSI address register.
|
||||
- qcom,ath10k-calibration-data : calibration data as an array, the
|
||||
length can vary between hw versions
|
||||
|
||||
Example (to supply the calibration data alone):
|
||||
|
||||
Example:
|
||||
In this example, the node is defined as child node of the PCI controller.
|
||||
|
||||
pci {
|
||||
pcie@0 {
|
||||
@@ -28,3 +57,53 @@ pci {
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example (to supply ipq4019 SoC wifi block details):
|
||||
|
||||
wifi0: wifi@a000000 {
|
||||
compatible = "qcom,ipq4019-wifi";
|
||||
reg = <0xa000000 0x200000>;
|
||||
resets = <&gcc WIFI0_CPU_INIT_RESET>,
|
||||
<&gcc WIFI0_RADIO_SRIF_RESET>,
|
||||
<&gcc WIFI0_RADIO_WARM_RESET>,
|
||||
<&gcc WIFI0_RADIO_COLD_RESET>,
|
||||
<&gcc WIFI0_CORE_WARM_RESET>,
|
||||
<&gcc WIFI0_CORE_COLD_RESET>;
|
||||
reset-names = "wifi_cpu_init",
|
||||
"wifi_radio_srif",
|
||||
"wifi_radio_warm",
|
||||
"wifi_radio_cold",
|
||||
"wifi_core_warm",
|
||||
"wifi_core_cold";
|
||||
clocks = <&gcc GCC_WCSS2G_CLK>,
|
||||
<&gcc GCC_WCSS2G_REF_CLK>,
|
||||
<&gcc GCC_WCSS2G_RTC_CLK>;
|
||||
clock-names = "wifi_wcss_cmd",
|
||||
"wifi_wcss_ref",
|
||||
"wifi_wcss_rtc";
|
||||
interrupts = <0 0x20 0x1>,
|
||||
<0 0x21 0x1>,
|
||||
<0 0x22 0x1>,
|
||||
<0 0x23 0x1>,
|
||||
<0 0x24 0x1>,
|
||||
<0 0x25 0x1>,
|
||||
<0 0x26 0x1>,
|
||||
<0 0x27 0x1>,
|
||||
<0 0x28 0x1>,
|
||||
<0 0x29 0x1>,
|
||||
<0 0x2a 0x1>,
|
||||
<0 0x2b 0x1>,
|
||||
<0 0x2c 0x1>,
|
||||
<0 0x2d 0x1>,
|
||||
<0 0x2e 0x1>,
|
||||
<0 0x2f 0x1>,
|
||||
<0 0xa8 0x0>;
|
||||
interrupt-names = "msi0", "msi1", "msi2", "msi3",
|
||||
"msi4", "msi5", "msi6", "msi7",
|
||||
"msi8", "msi9", "msi10", "msi11",
|
||||
"msi12", "msi13", "msi14", "msi15",
|
||||
"legacy";
|
||||
qcom,msi_addr = <0x0b006040>;
|
||||
qcom,msi_base = <0x40>;
|
||||
qcom,ath10k-calibration-data = [ 01 02 03 ... ];
|
||||
};
|
||||
|
||||
@@ -70,6 +70,11 @@ config BCMA_DRIVER_MIPS
|
||||
|
||||
If unsure, say N
|
||||
|
||||
config BCMA_PFLASH
|
||||
bool
|
||||
depends on BCMA_DRIVER_MIPS
|
||||
default y
|
||||
|
||||
config BCMA_SFLASH
|
||||
bool
|
||||
depends on BCMA_DRIVER_MIPS
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
bcma-y += main.o scan.o core.o sprom.o
|
||||
bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
|
||||
bcma-y += driver_chipcommon_b.o
|
||||
bcma-$(CONFIG_BCMA_PFLASH) += driver_chipcommon_pflash.o
|
||||
bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o
|
||||
bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o
|
||||
bcma-$(CONFIG_BCMA_DRIVER_PCI) += driver_pci.o
|
||||
|
||||
@@ -47,9 +47,6 @@ int bcma_sprom_get(struct bcma_bus *bus);
|
||||
void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc);
|
||||
void bcma_core_chipcommon_init(struct bcma_drv_cc *cc);
|
||||
void bcma_chipco_bcm4331_ext_pa_lines_ctl(struct bcma_drv_cc *cc, bool enable);
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
extern struct platform_device bcma_pflash_dev;
|
||||
#endif /* CONFIG_BCMA_DRIVER_MIPS */
|
||||
|
||||
/* driver_chipcommon_b.c */
|
||||
int bcma_core_chipcommon_b_init(struct bcma_drv_cc_b *ccb);
|
||||
@@ -61,6 +58,21 @@ void bcma_pmu_init(struct bcma_drv_cc *cc);
|
||||
u32 bcma_pmu_get_alp_clock(struct bcma_drv_cc *cc);
|
||||
u32 bcma_pmu_get_cpu_clock(struct bcma_drv_cc *cc);
|
||||
|
||||
/**************************************************
|
||||
* driver_chipcommon_sflash.c
|
||||
**************************************************/
|
||||
|
||||
#ifdef CONFIG_BCMA_PFLASH
|
||||
extern struct platform_device bcma_pflash_dev;
|
||||
int bcma_pflash_init(struct bcma_drv_cc *cc);
|
||||
#else
|
||||
static inline int bcma_pflash_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
bcma_err(cc->core->bus, "Parallel flash not supported\n");
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BCMA_PFLASH */
|
||||
|
||||
#ifdef CONFIG_BCMA_SFLASH
|
||||
/* driver_chipcommon_sflash.c */
|
||||
int bcma_sflash_init(struct bcma_drv_cc *cc);
|
||||
|
||||
@@ -115,6 +115,33 @@ int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bcma_core_chipcommon_flash_detect(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
|
||||
switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
|
||||
case BCMA_CC_FLASHT_STSER:
|
||||
case BCMA_CC_FLASHT_ATSER:
|
||||
bcma_debug(bus, "Found serial flash\n");
|
||||
bcma_sflash_init(cc);
|
||||
break;
|
||||
case BCMA_CC_FLASHT_PARA:
|
||||
bcma_debug(bus, "Found parallel flash\n");
|
||||
bcma_pflash_init(cc);
|
||||
break;
|
||||
default:
|
||||
bcma_err(bus, "Flash type not supported\n");
|
||||
}
|
||||
|
||||
if (cc->core->id.rev == 38 ||
|
||||
bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
|
||||
if (cc->capabilities & BCMA_CC_CAP_NFLASH) {
|
||||
bcma_debug(bus, "Found NAND flash\n");
|
||||
bcma_nflash_init(cc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_bus *bus = cc->core->bus;
|
||||
@@ -136,6 +163,9 @@ void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
|
||||
if (IS_BUILTIN(CONFIG_BCM47XX) && bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
bcma_chipco_serial_init(cc);
|
||||
|
||||
if (bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
bcma_core_chipcommon_flash_detect(cc);
|
||||
|
||||
cc->early_setup_done = true;
|
||||
}
|
||||
|
||||
|
||||
49
drivers/bcma/driver_chipcommon_pflash.c
Normal file
49
drivers/bcma/driver_chipcommon_pflash.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Broadcom specific AMBA
|
||||
* ChipCommon parallel flash
|
||||
*
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include "bcma_private.h"
|
||||
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
static const char * const part_probes[] = { "bcm47xxpart", NULL };
|
||||
|
||||
static struct physmap_flash_data bcma_pflash_data = {
|
||||
.part_probe_types = part_probes,
|
||||
};
|
||||
|
||||
static struct resource bcma_pflash_resource = {
|
||||
.name = "bcma_pflash",
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
struct platform_device bcma_pflash_dev = {
|
||||
.name = "physmap-flash",
|
||||
.dev = {
|
||||
.platform_data = &bcma_pflash_data,
|
||||
},
|
||||
.resource = &bcma_pflash_resource,
|
||||
.num_resources = 1,
|
||||
};
|
||||
|
||||
int bcma_pflash_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct bcma_pflash *pflash = &cc->pflash;
|
||||
|
||||
pflash->present = true;
|
||||
|
||||
if (!(bcma_read32(cc->core, BCMA_CC_FLASH_CFG) & BCMA_CC_FLASH_CFG_DS))
|
||||
bcma_pflash_data.width = 1;
|
||||
else
|
||||
bcma_pflash_data.width = 2;
|
||||
|
||||
bcma_pflash_resource.start = BCMA_SOC_FLASH2;
|
||||
bcma_pflash_resource.end = BCMA_SOC_FLASH2 + BCMA_SOC_FLASH2_SZ;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
#include <linux/mtd/physmap.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/serial.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/serial_reg.h>
|
||||
@@ -32,26 +30,6 @@ enum bcma_boot_dev {
|
||||
BCMA_BOOT_DEV_NAND,
|
||||
};
|
||||
|
||||
static const char * const part_probes[] = { "bcm47xxpart", NULL };
|
||||
|
||||
static struct physmap_flash_data bcma_pflash_data = {
|
||||
.part_probe_types = part_probes,
|
||||
};
|
||||
|
||||
static struct resource bcma_pflash_resource = {
|
||||
.name = "bcma_pflash",
|
||||
.flags = IORESOURCE_MEM,
|
||||
};
|
||||
|
||||
struct platform_device bcma_pflash_dev = {
|
||||
.name = "physmap-flash",
|
||||
.dev = {
|
||||
.platform_data = &bcma_pflash_data,
|
||||
},
|
||||
.resource = &bcma_pflash_resource,
|
||||
.num_resources = 1,
|
||||
};
|
||||
|
||||
/* The 47162a0 hangs when reading MIPS DMP registers registers */
|
||||
static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
|
||||
{
|
||||
@@ -272,48 +250,11 @@ static enum bcma_boot_dev bcma_boot_dev(struct bcma_bus *bus)
|
||||
return BCMA_BOOT_DEV_SERIAL;
|
||||
}
|
||||
|
||||
static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
|
||||
static void bcma_core_mips_nvram_init(struct bcma_drv_mips *mcore)
|
||||
{
|
||||
struct bcma_bus *bus = mcore->core->bus;
|
||||
struct bcma_drv_cc *cc = &bus->drv_cc;
|
||||
struct bcma_pflash *pflash = &cc->pflash;
|
||||
enum bcma_boot_dev boot_dev;
|
||||
|
||||
switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
|
||||
case BCMA_CC_FLASHT_STSER:
|
||||
case BCMA_CC_FLASHT_ATSER:
|
||||
bcma_debug(bus, "Found serial flash\n");
|
||||
bcma_sflash_init(cc);
|
||||
break;
|
||||
case BCMA_CC_FLASHT_PARA:
|
||||
bcma_debug(bus, "Found parallel flash\n");
|
||||
pflash->present = true;
|
||||
pflash->window = BCMA_SOC_FLASH2;
|
||||
pflash->window_size = BCMA_SOC_FLASH2_SZ;
|
||||
|
||||
if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) &
|
||||
BCMA_CC_FLASH_CFG_DS) == 0)
|
||||
pflash->buswidth = 1;
|
||||
else
|
||||
pflash->buswidth = 2;
|
||||
|
||||
bcma_pflash_data.width = pflash->buswidth;
|
||||
bcma_pflash_resource.start = pflash->window;
|
||||
bcma_pflash_resource.end = pflash->window + pflash->window_size;
|
||||
|
||||
break;
|
||||
default:
|
||||
bcma_err(bus, "Flash type not supported\n");
|
||||
}
|
||||
|
||||
if (cc->core->id.rev == 38 ||
|
||||
bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
|
||||
if (cc->capabilities & BCMA_CC_CAP_NFLASH) {
|
||||
bcma_debug(bus, "Found NAND flash\n");
|
||||
bcma_nflash_init(cc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine flash type this SoC boots from */
|
||||
boot_dev = bcma_boot_dev(bus);
|
||||
switch (boot_dev) {
|
||||
@@ -340,7 +281,7 @@ void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
|
||||
if (mcore->early_setup_done)
|
||||
return;
|
||||
|
||||
bcma_core_mips_flash_detect(mcore);
|
||||
bcma_core_mips_nvram_init(mcore);
|
||||
|
||||
mcore->early_setup_done = true;
|
||||
}
|
||||
|
||||
@@ -350,7 +350,7 @@ static int bcma_register_devices(struct bcma_bus *bus)
|
||||
bcma_register_core(bus, core);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BCMA_DRIVER_MIPS
|
||||
#ifdef CONFIG_BCMA_PFLASH
|
||||
if (bus->drv_cc.pflash.present) {
|
||||
err = platform_device_register(&bcma_pflash_dev);
|
||||
if (err)
|
||||
|
||||
@@ -15,6 +15,12 @@ config ATH10K_PCI
|
||||
---help---
|
||||
This module adds support for PCIE bus
|
||||
|
||||
config ATH10K_AHB
|
||||
bool "Atheros ath10k AHB support"
|
||||
depends on ATH10K_PCI && OF && RESET_CONTROLLER
|
||||
---help---
|
||||
This module adds support for AHB bus
|
||||
|
||||
config ATH10K_DEBUG
|
||||
bool "Atheros ath10k debugging"
|
||||
depends on ATH10K
|
||||
|
||||
@@ -25,5 +25,7 @@ obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o
|
||||
ath10k_pci-y += pci.o \
|
||||
ce.o
|
||||
|
||||
ath10k_pci-$(CONFIG_ATH10K_AHB) += ahb.o
|
||||
|
||||
# for tracing framework to find trace.h
|
||||
CFLAGS_trace.o := -I$(src)
|
||||
|
||||
933
drivers/net/wireless/ath/ath10k/ahb.c
Normal file
933
drivers/net/wireless/ath/ath10k/ahb.c
Normal file
File diff suppressed because it is too large
Load Diff
87
drivers/net/wireless/ath/ath10k/ahb.h
Normal file
87
drivers/net/wireless/ath/ath10k/ahb.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Qualcomm Atheros, Inc. All rights reserved.
|
||||
* Copyright (c) 2015 The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _AHB_H_
|
||||
#define _AHB_H_
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
struct ath10k_ahb {
|
||||
struct platform_device *pdev;
|
||||
void __iomem *mem;
|
||||
unsigned long mem_len;
|
||||
void __iomem *gcc_mem;
|
||||
void __iomem *tcsr_mem;
|
||||
|
||||
int irq;
|
||||
|
||||
struct clk *cmd_clk;
|
||||
struct clk *ref_clk;
|
||||
struct clk *rtc_clk;
|
||||
|
||||
struct reset_control *core_cold_rst;
|
||||
struct reset_control *radio_cold_rst;
|
||||
struct reset_control *radio_warm_rst;
|
||||
struct reset_control *radio_srif_rst;
|
||||
struct reset_control *cpu_init_rst;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ATH10K_AHB
|
||||
|
||||
#define ATH10K_GCC_REG_BASE 0x1800000
|
||||
#define ATH10K_GCC_REG_SIZE 0x60000
|
||||
|
||||
#define ATH10K_TCSR_REG_BASE 0x1900000
|
||||
#define ATH10K_TCSR_REG_SIZE 0x80000
|
||||
|
||||
#define ATH10K_AHB_GCC_FEPLL_PLL_DIV 0x2f020
|
||||
#define ATH10K_AHB_WIFI_SCRATCH_5_REG 0x4f014
|
||||
|
||||
#define ATH10K_AHB_WLAN_CORE_ID_REG 0x82030
|
||||
|
||||
#define ATH10K_AHB_TCSR_WIFI0_GLB_CFG 0x49000
|
||||
#define ATH10K_AHB_TCSR_WIFI1_GLB_CFG 0x49004
|
||||
#define TCSR_WIFIX_GLB_CFG_DISABLE_CORE_CLK BIT(25)
|
||||
|
||||
#define ATH10K_AHB_TCSR_WCSS0_HALTREQ 0x52000
|
||||
#define ATH10K_AHB_TCSR_WCSS1_HALTREQ 0x52010
|
||||
#define ATH10K_AHB_TCSR_WCSS0_HALTACK 0x52004
|
||||
#define ATH10K_AHB_TCSR_WCSS1_HALTACK 0x52014
|
||||
|
||||
#define ATH10K_AHB_AXI_BUS_HALT_TIMEOUT 10 /* msec */
|
||||
#define AHB_AXI_BUS_HALT_REQ 1
|
||||
#define AHB_AXI_BUS_HALT_ACK 1
|
||||
|
||||
#define ATH10K_AHB_CORE_CTRL_CPU_INTR_MASK 1
|
||||
|
||||
int ath10k_ahb_init(void);
|
||||
void ath10k_ahb_exit(void);
|
||||
|
||||
#else /* CONFIG_ATH10K_AHB */
|
||||
|
||||
static inline int ath10k_ahb_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath10k_ahb_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ATH10K_AHB */
|
||||
|
||||
#endif /* _AHB_H_ */
|
||||
@@ -156,6 +156,11 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.channel_counters_freq_hz = 150000,
|
||||
.max_probe_resp_desc_thres = 24,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
|
||||
.num_msdu_desc = 1424,
|
||||
.qcache_active_peers = 50,
|
||||
.tx_chain_mask = 0xf,
|
||||
.rx_chain_mask = 0xf,
|
||||
.max_spatial_stream = 4,
|
||||
.fw = {
|
||||
.dir = QCA99X0_HW_2_0_FW_DIR,
|
||||
.fw = QCA99X0_HW_2_0_FW_FILE,
|
||||
@@ -201,6 +206,31 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
},
|
||||
{
|
||||
.id = QCA4019_HW_1_0_DEV_VERSION,
|
||||
.dev_id = 0,
|
||||
.name = "qca4019 hw1.0",
|
||||
.patch_load_addr = QCA4019_HW_1_0_PATCH_LOAD_ADDR,
|
||||
.uart_pin = 7,
|
||||
.otp_exe_param = 0x0010000,
|
||||
.continuous_frag_desc = true,
|
||||
.channel_counters_freq_hz = 125000,
|
||||
.max_probe_resp_desc_thres = 24,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
|
||||
.num_msdu_desc = 2500,
|
||||
.qcache_active_peers = 35,
|
||||
.tx_chain_mask = 0x3,
|
||||
.rx_chain_mask = 0x3,
|
||||
.max_spatial_stream = 2,
|
||||
.fw = {
|
||||
.dir = QCA4019_HW_1_0_FW_DIR,
|
||||
.fw = QCA4019_HW_1_0_FW_FILE,
|
||||
.otp = QCA4019_HW_1_0_OTP_FILE,
|
||||
.board = QCA4019_HW_1_0_BOARD_DATA_FILE,
|
||||
.board_size = QCA4019_BOARD_DATA_SZ,
|
||||
.board_ext_size = QCA4019_BOARD_EXT_DATA_SZ,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const char *const ath10k_core_fw_feature_str[] = {
|
||||
@@ -217,6 +247,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
|
||||
[ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode",
|
||||
[ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca",
|
||||
[ATH10K_FW_FEATURE_MFP_SUPPORT] = "mfp",
|
||||
[ATH10K_FW_FEATURE_PEER_FLOW_CONTROL] = "peer-flow-ctrl",
|
||||
};
|
||||
|
||||
static unsigned int ath10k_core_get_fw_feature_str(char *buf,
|
||||
@@ -1478,8 +1509,13 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
|
||||
case ATH10K_FW_WMI_OP_VERSION_10_1:
|
||||
case ATH10K_FW_WMI_OP_VERSION_10_2:
|
||||
case ATH10K_FW_WMI_OP_VERSION_10_2_4:
|
||||
ar->max_num_peers = TARGET_10X_NUM_PEERS;
|
||||
ar->max_num_stations = TARGET_10X_NUM_STATIONS;
|
||||
if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) {
|
||||
ar->max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS;
|
||||
ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS;
|
||||
} else {
|
||||
ar->max_num_peers = TARGET_10X_NUM_PEERS;
|
||||
ar->max_num_stations = TARGET_10X_NUM_STATIONS;
|
||||
}
|
||||
ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;
|
||||
ar->htt.max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
|
||||
ar->fw_stats_req_mask = WMI_STAT_PEER;
|
||||
@@ -1502,9 +1538,9 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
|
||||
ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS;
|
||||
ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS;
|
||||
ar->num_tids = TARGET_10_4_TGT_NUM_TIDS;
|
||||
ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC;
|
||||
ar->htt.max_num_pending_tx = ar->hw_params.num_msdu_desc;
|
||||
ar->fw_stats_req_mask = WMI_STAT_PEER;
|
||||
ar->max_spatial_stream = WMI_10_4_MAX_SPATIAL_STREAM;
|
||||
ar->max_spatial_stream = ar->hw_params.max_spatial_stream;
|
||||
break;
|
||||
case ATH10K_FW_WMI_OP_VERSION_UNSET:
|
||||
case ATH10K_FW_WMI_OP_VERSION_MAX:
|
||||
@@ -1979,6 +2015,10 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
||||
ar->regs = &qca99x0_regs;
|
||||
ar->hw_values = &qca99x0_values;
|
||||
break;
|
||||
case ATH10K_HW_QCA4019:
|
||||
ar->regs = &qca4019_regs;
|
||||
ar->hw_values = &qca4019_values;
|
||||
break;
|
||||
default:
|
||||
ath10k_err(ar, "unsupported core hardware revision %d\n",
|
||||
hw_rev);
|
||||
|
||||
@@ -69,6 +69,7 @@ struct ath10k;
|
||||
|
||||
enum ath10k_bus {
|
||||
ATH10K_BUS_PCI,
|
||||
ATH10K_BUS_AHB,
|
||||
};
|
||||
|
||||
static inline const char *ath10k_bus_str(enum ath10k_bus bus)
|
||||
@@ -76,6 +77,8 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus)
|
||||
switch (bus) {
|
||||
case ATH10K_BUS_PCI:
|
||||
return "pci";
|
||||
case ATH10K_BUS_AHB:
|
||||
return "ahb";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
@@ -159,6 +162,7 @@ struct ath10k_fw_stats_peer {
|
||||
u32 peer_rssi;
|
||||
u32 peer_tx_rate;
|
||||
u32 peer_rx_rate; /* 10x only */
|
||||
u32 rx_duration;
|
||||
};
|
||||
|
||||
struct ath10k_fw_stats_vdev {
|
||||
@@ -315,6 +319,7 @@ struct ath10k_sta {
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
/* protected by conf_mutex */
|
||||
bool aggr_mode;
|
||||
u64 rx_duration;
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -510,6 +515,15 @@ enum ath10k_fw_features {
|
||||
/* Firmware supports management frame protection */
|
||||
ATH10K_FW_FEATURE_MFP_SUPPORT = 12,
|
||||
|
||||
/* Firmware supports pull-push model where host shares it's software
|
||||
* queue state with firmware and firmware generates fetch requests
|
||||
* telling host which queues to dequeue tx from.
|
||||
*
|
||||
* Primary function of this is improved MU-MIMO performance with
|
||||
* multiple clients.
|
||||
*/
|
||||
ATH10K_FW_FEATURE_PEER_FLOW_CONTROL = 13,
|
||||
|
||||
/* keep last */
|
||||
ATH10K_FW_FEATURE_COUNT,
|
||||
};
|
||||
@@ -666,6 +680,12 @@ struct ath10k {
|
||||
/* The padding bytes's location is different on various chips */
|
||||
enum ath10k_hw_4addr_pad hw_4addr_pad;
|
||||
|
||||
u32 num_msdu_desc;
|
||||
u32 qcache_active_peers;
|
||||
u32 tx_chain_mask;
|
||||
u32 rx_chain_mask;
|
||||
u32 max_spatial_stream;
|
||||
|
||||
struct ath10k_hw_params_fw {
|
||||
const char *dir;
|
||||
const char *fw;
|
||||
|
||||
@@ -276,7 +276,7 @@ static const struct file_operations fops_wmi_services = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head)
|
||||
static void ath10k_fw_stats_pdevs_free(struct list_head *head)
|
||||
{
|
||||
struct ath10k_fw_stats_pdev *i, *tmp;
|
||||
|
||||
@@ -286,7 +286,7 @@ static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head)
|
||||
}
|
||||
}
|
||||
|
||||
static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head)
|
||||
static void ath10k_fw_stats_vdevs_free(struct list_head *head)
|
||||
{
|
||||
struct ath10k_fw_stats_vdev *i, *tmp;
|
||||
|
||||
@@ -296,7 +296,7 @@ static void ath10k_debug_fw_stats_vdevs_free(struct list_head *head)
|
||||
}
|
||||
}
|
||||
|
||||
static void ath10k_debug_fw_stats_peers_free(struct list_head *head)
|
||||
static void ath10k_fw_stats_peers_free(struct list_head *head)
|
||||
{
|
||||
struct ath10k_fw_stats_peer *i, *tmp;
|
||||
|
||||
@@ -310,16 +310,16 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
|
||||
{
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ar->debug.fw_stats_done = false;
|
||||
ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
|
||||
ath10k_debug_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
|
||||
ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers);
|
||||
ath10k_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
|
||||
ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
|
||||
ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct ath10k_fw_stats stats = {};
|
||||
bool is_start, is_started, is_end;
|
||||
bool is_start, is_started, is_end, peer_stats_svc;
|
||||
size_t num_peers;
|
||||
size_t num_vdevs;
|
||||
int ret;
|
||||
@@ -347,8 +347,14 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
|
||||
* delivered which is treated as end-of-data and is itself discarded
|
||||
*/
|
||||
|
||||
peer_stats_svc = test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map);
|
||||
if (peer_stats_svc)
|
||||
ath10k_sta_update_rx_duration(ar, &stats.peers);
|
||||
|
||||
if (ar->debug.fw_stats_done) {
|
||||
ath10k_warn(ar, "received unsolicited stats update event\n");
|
||||
if (!peer_stats_svc)
|
||||
ath10k_warn(ar, "received unsolicited stats update event\n");
|
||||
|
||||
goto free;
|
||||
}
|
||||
|
||||
@@ -372,11 +378,13 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
|
||||
/* Although this is unlikely impose a sane limit to
|
||||
* prevent firmware from DoS-ing the host.
|
||||
*/
|
||||
ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
|
||||
ath10k_warn(ar, "dropping fw peer stats\n");
|
||||
goto free;
|
||||
}
|
||||
|
||||
if (num_vdevs >= BITS_PER_LONG) {
|
||||
ath10k_fw_stats_vdevs_free(&ar->debug.fw_stats.vdevs);
|
||||
ath10k_warn(ar, "dropping fw vdev stats\n");
|
||||
goto free;
|
||||
}
|
||||
@@ -391,9 +399,9 @@ free:
|
||||
/* In some cases lists have been spliced and cleared. Free up
|
||||
* resources if that is not the case.
|
||||
*/
|
||||
ath10k_debug_fw_stats_pdevs_free(&stats.pdevs);
|
||||
ath10k_debug_fw_stats_vdevs_free(&stats.vdevs);
|
||||
ath10k_debug_fw_stats_peers_free(&stats.peers);
|
||||
ath10k_fw_stats_pdevs_free(&stats.pdevs);
|
||||
ath10k_fw_stats_vdevs_free(&stats.vdevs);
|
||||
ath10k_fw_stats_peers_free(&stats.peers);
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
@@ -2106,6 +2114,7 @@ static ssize_t ath10k_write_btcoex(struct file *file,
|
||||
struct ath10k *ar = file->private_data;
|
||||
char buf[32];
|
||||
size_t buf_size;
|
||||
int ret = 0;
|
||||
bool val;
|
||||
|
||||
buf_size = min(count, (sizeof(buf) - 1));
|
||||
@@ -2119,6 +2128,12 @@ static ssize_t ath10k_write_btcoex(struct file *file,
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON &&
|
||||
ar->state != ATH10K_STATE_RESTARTED) {
|
||||
ret = -ENETDOWN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val))
|
||||
goto exit;
|
||||
|
||||
@@ -2127,17 +2142,15 @@ static ssize_t ath10k_write_btcoex(struct file *file,
|
||||
else
|
||||
clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON)
|
||||
goto exit;
|
||||
|
||||
ath10k_info(ar, "restarting firmware due to btcoex change");
|
||||
|
||||
queue_work(ar->workqueue, &ar->restart_work);
|
||||
ret = count;
|
||||
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return count;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,
|
||||
@@ -2176,9 +2189,6 @@ static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (len > buf_len)
|
||||
len = buf_len;
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"firmware-N.bin\t\t%08x\n",
|
||||
crc32_le(0, ar->firmware->data, ar->firmware->size));
|
||||
|
||||
@@ -37,6 +37,7 @@ enum ath10k_debug_mask {
|
||||
ATH10K_DBG_TESTMODE = 0x00001000,
|
||||
ATH10K_DBG_WMI_PRINT = 0x00002000,
|
||||
ATH10K_DBG_PCI_PS = 0x00004000,
|
||||
ATH10K_DBG_AHB = 0x00008000,
|
||||
ATH10K_DBG_ANY = 0xffffffff,
|
||||
};
|
||||
|
||||
@@ -153,6 +154,12 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
|
||||
#ifdef CONFIG_MAC80211_DEBUGFS
|
||||
void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct dentry *dir);
|
||||
void ath10k_sta_update_rx_duration(struct ath10k *ar, struct list_head *peer);
|
||||
#else
|
||||
static inline void ath10k_sta_update_rx_duration(struct ath10k *ar,
|
||||
struct list_head *peer)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_MAC80211_DEBUGFS */
|
||||
|
||||
#ifdef CONFIG_ATH10K_DEBUG
|
||||
|
||||
@@ -18,6 +18,23 @@
|
||||
#include "wmi-ops.h"
|
||||
#include "debug.h"
|
||||
|
||||
void ath10k_sta_update_rx_duration(struct ath10k *ar, struct list_head *head)
|
||||
{ struct ieee80211_sta *sta;
|
||||
struct ath10k_fw_stats_peer *peer;
|
||||
struct ath10k_sta *arsta;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry(peer, head, list) {
|
||||
sta = ieee80211_find_sta_by_ifaddr(ar->hw, peer->peer_macaddr,
|
||||
NULL);
|
||||
if (!sta)
|
||||
continue;
|
||||
arsta = (struct ath10k_sta *)sta->drv_priv;
|
||||
arsta->rx_duration += (u64)peer->rx_duration;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static ssize_t ath10k_dbg_sta_read_aggr_mode(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
@@ -232,6 +249,28 @@ static const struct file_operations fops_delba = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath10k_dbg_sta_read_rx_duration(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ieee80211_sta *sta = file->private_data;
|
||||
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
|
||||
char buf[100];
|
||||
int len = 0;
|
||||
|
||||
len = scnprintf(buf, sizeof(buf),
|
||||
"%llu usecs\n", arsta->rx_duration);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_rx_duration = {
|
||||
.read = ath10k_dbg_sta_read_rx_duration,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct dentry *dir)
|
||||
{
|
||||
@@ -240,4 +279,6 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
debugfs_create_file("addba", S_IWUSR, dir, sta, &fops_addba);
|
||||
debugfs_create_file("addba_resp", S_IWUSR, dir, sta, &fops_addba_resp);
|
||||
debugfs_create_file("delba", S_IWUSR, dir, sta, &fops_delba);
|
||||
debugfs_create_file("rx_duration", S_IRUGO, dir, sta,
|
||||
&fops_rx_duration);
|
||||
}
|
||||
|
||||
@@ -131,12 +131,12 @@ static const enum htt_t2h_msg_type htt_10_4_t2h_msg_types[] = {
|
||||
[HTT_10_4_T2H_MSG_TYPE_AGGR_CONF] = HTT_T2H_MSG_TYPE_AGGR_CONF,
|
||||
[HTT_10_4_T2H_MSG_TYPE_TX_FETCH_IND] =
|
||||
HTT_T2H_MSG_TYPE_TX_FETCH_IND,
|
||||
[HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONF] =
|
||||
HTT_T2H_MSG_TYPE_TX_FETCH_CONF,
|
||||
[HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONFIRM] =
|
||||
HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM,
|
||||
[HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD] =
|
||||
HTT_T2H_MSG_TYPE_STATS_NOUPLOAD,
|
||||
[HTT_10_4_T2H_MSG_TYPE_TX_LOW_LATENCY_IND] =
|
||||
HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND,
|
||||
[HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND] =
|
||||
HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND,
|
||||
};
|
||||
|
||||
int ath10k_htt_connect(struct ath10k_htt *htt)
|
||||
|
||||
@@ -52,6 +52,7 @@ enum htt_h2t_msg_type { /* host-to-target */
|
||||
/* This command is used for sending management frames in HTT < 3.0.
|
||||
* HTT >= 3.0 uses TX_FRM for everything. */
|
||||
HTT_H2T_MSG_TYPE_MGMT_TX = 7,
|
||||
HTT_H2T_MSG_TYPE_TX_FETCH_RESP = 11,
|
||||
|
||||
HTT_H2T_NUM_MSGS /* keep this last */
|
||||
};
|
||||
@@ -413,10 +414,10 @@ enum htt_10_4_t2h_msg_type {
|
||||
HTT_10_4_T2H_MSG_TYPE_EN_STATS = 0x14,
|
||||
HTT_10_4_T2H_MSG_TYPE_AGGR_CONF = 0x15,
|
||||
HTT_10_4_T2H_MSG_TYPE_TX_FETCH_IND = 0x16,
|
||||
HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONF = 0x17,
|
||||
HTT_10_4_T2H_MSG_TYPE_TX_FETCH_CONFIRM = 0x17,
|
||||
HTT_10_4_T2H_MSG_TYPE_STATS_NOUPLOAD = 0x18,
|
||||
/* 0x19 to 0x2f are reserved */
|
||||
HTT_10_4_T2H_MSG_TYPE_TX_LOW_LATENCY_IND = 0x30,
|
||||
HTT_10_4_T2H_MSG_TYPE_TX_MODE_SWITCH_IND = 0x30,
|
||||
/* keep this last */
|
||||
HTT_10_4_T2H_NUM_MSGS
|
||||
};
|
||||
@@ -449,8 +450,8 @@ enum htt_t2h_msg_type {
|
||||
HTT_T2H_MSG_TYPE_TEST,
|
||||
HTT_T2H_MSG_TYPE_EN_STATS,
|
||||
HTT_T2H_MSG_TYPE_TX_FETCH_IND,
|
||||
HTT_T2H_MSG_TYPE_TX_FETCH_CONF,
|
||||
HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND,
|
||||
HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM,
|
||||
HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND,
|
||||
/* keep this last */
|
||||
HTT_T2H_NUM_MSGS
|
||||
};
|
||||
@@ -1306,9 +1307,43 @@ struct htt_frag_desc_bank_id {
|
||||
* so we use a conservatively safe value for now */
|
||||
#define HTT_FRAG_DESC_BANK_MAX 4
|
||||
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_MASK 0x03
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_LSB 0
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_SWAP (1 << 2)
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_MASK 0x03
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_PDEV_ID_LSB 0
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_SWAP BIT(2)
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_VALID BIT(3)
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE_MASK BIT(4)
|
||||
#define HTT_FRAG_DESC_BANK_CFG_INFO_Q_STATE_DEPTH_TYPE_LSB 4
|
||||
|
||||
enum htt_q_depth_type {
|
||||
HTT_Q_DEPTH_TYPE_BYTES = 0,
|
||||
HTT_Q_DEPTH_TYPE_MSDUS = 1,
|
||||
};
|
||||
|
||||
#define HTT_TX_Q_STATE_NUM_PEERS (TARGET_10_4_NUM_QCACHE_PEERS_MAX + \
|
||||
TARGET_10_4_NUM_VDEVS)
|
||||
#define HTT_TX_Q_STATE_NUM_TIDS 8
|
||||
#define HTT_TX_Q_STATE_ENTRY_SIZE 1
|
||||
#define HTT_TX_Q_STATE_ENTRY_MULTIPLIER 0
|
||||
|
||||
/**
|
||||
* htt_q_state_conf - part of htt_frag_desc_bank_cfg for host q state config
|
||||
*
|
||||
* Defines host q state format and behavior. See htt_q_state.
|
||||
*
|
||||
* @record_size: Defines the size of each host q entry in bytes. In practice
|
||||
* however firmware (at least 10.4.3-00191) ignores this host
|
||||
* configuration value and uses hardcoded value of 1.
|
||||
* @record_multiplier: This is valid only when q depth type is MSDUs. It
|
||||
* defines the exponent for the power of 2 multiplication.
|
||||
*/
|
||||
struct htt_q_state_conf {
|
||||
__le32 paddr;
|
||||
__le16 num_peers;
|
||||
__le16 num_tids;
|
||||
u8 record_size;
|
||||
u8 record_multiplier;
|
||||
u8 pad[2];
|
||||
} __packed;
|
||||
|
||||
struct htt_frag_desc_bank_cfg {
|
||||
u8 info; /* HTT_FRAG_DESC_BANK_CFG_INFO_ */
|
||||
@@ -1316,6 +1351,114 @@ struct htt_frag_desc_bank_cfg {
|
||||
u8 desc_size;
|
||||
__le32 bank_base_addrs[HTT_FRAG_DESC_BANK_MAX];
|
||||
struct htt_frag_desc_bank_id bank_id[HTT_FRAG_DESC_BANK_MAX];
|
||||
struct htt_q_state_conf q_state;
|
||||
} __packed;
|
||||
|
||||
#define HTT_TX_Q_STATE_ENTRY_COEFFICIENT 128
|
||||
#define HTT_TX_Q_STATE_ENTRY_FACTOR_MASK 0x3f
|
||||
#define HTT_TX_Q_STATE_ENTRY_FACTOR_LSB 0
|
||||
#define HTT_TX_Q_STATE_ENTRY_EXP_MASK 0xc0
|
||||
#define HTT_TX_Q_STATE_ENTRY_EXP_LSB 6
|
||||
|
||||
/**
|
||||
* htt_q_state - shared between host and firmware via DMA
|
||||
*
|
||||
* This structure is used for the host to expose it's software queue state to
|
||||
* firmware so that its rate control can schedule fetch requests for optimized
|
||||
* performance. This is most notably used for MU-MIMO aggregation when multiple
|
||||
* MU clients are connected.
|
||||
*
|
||||
* @count: Each element defines the host queue depth. When q depth type was
|
||||
* configured as HTT_Q_DEPTH_TYPE_BYTES then each entry is defined as:
|
||||
* FACTOR * 128 * 8^EXP (see HTT_TX_Q_STATE_ENTRY_FACTOR_MASK and
|
||||
* HTT_TX_Q_STATE_ENTRY_EXP_MASK). When q depth type was configured as
|
||||
* HTT_Q_DEPTH_TYPE_MSDUS the number of packets is scaled by 2 **
|
||||
* record_multiplier (see htt_q_state_conf).
|
||||
* @map: Used by firmware to quickly check which host queues are not empty. It
|
||||
* is a bitmap simply saying.
|
||||
* @seq: Used by firmware to quickly check if the host queues were updated
|
||||
* since it last checked.
|
||||
*
|
||||
* FIXME: Is the q_state map[] size calculation really correct?
|
||||
*/
|
||||
struct htt_q_state {
|
||||
u8 count[HTT_TX_Q_STATE_NUM_TIDS][HTT_TX_Q_STATE_NUM_PEERS];
|
||||
u32 map[HTT_TX_Q_STATE_NUM_TIDS][(HTT_TX_Q_STATE_NUM_PEERS + 31) / 32];
|
||||
__le32 seq;
|
||||
} __packed;
|
||||
|
||||
#define HTT_TX_FETCH_RECORD_INFO_PEER_ID_MASK 0x0fff
|
||||
#define HTT_TX_FETCH_RECORD_INFO_PEER_ID_LSB 0
|
||||
#define HTT_TX_FETCH_RECORD_INFO_TID_MASK 0xf000
|
||||
#define HTT_TX_FETCH_RECORD_INFO_TID_LSB 12
|
||||
|
||||
struct htt_tx_fetch_record {
|
||||
__le16 info; /* HTT_TX_FETCH_IND_RECORD_INFO_ */
|
||||
__le16 num_msdus;
|
||||
__le32 num_bytes;
|
||||
} __packed;
|
||||
|
||||
struct htt_tx_fetch_ind {
|
||||
u8 pad0;
|
||||
__le16 fetch_seq_num;
|
||||
__le32 token;
|
||||
__le16 num_resp_ids;
|
||||
__le16 num_records;
|
||||
struct htt_tx_fetch_record records[0];
|
||||
__le32 resp_ids[0]; /* ath10k_htt_get_tx_fetch_ind_resp_ids() */
|
||||
} __packed;
|
||||
|
||||
static inline void *
|
||||
ath10k_htt_get_tx_fetch_ind_resp_ids(struct htt_tx_fetch_ind *ind)
|
||||
{
|
||||
return (void *)&ind->records[le16_to_cpu(ind->num_records)];
|
||||
}
|
||||
|
||||
struct htt_tx_fetch_resp {
|
||||
u8 pad0;
|
||||
__le16 resp_id;
|
||||
__le16 fetch_seq_num;
|
||||
__le16 num_records;
|
||||
__le32 token;
|
||||
struct htt_tx_fetch_record records[0];
|
||||
} __packed;
|
||||
|
||||
struct htt_tx_fetch_confirm {
|
||||
u8 pad0;
|
||||
__le16 num_resp_ids;
|
||||
__le32 resp_ids[0];
|
||||
} __packed;
|
||||
|
||||
enum htt_tx_mode_switch_mode {
|
||||
HTT_TX_MODE_SWITCH_PUSH = 0,
|
||||
HTT_TX_MODE_SWITCH_PUSH_PULL = 1,
|
||||
};
|
||||
|
||||
#define HTT_TX_MODE_SWITCH_IND_INFO0_ENABLE BIT(0)
|
||||
#define HTT_TX_MODE_SWITCH_IND_INFO0_NUM_RECORDS_MASK 0xfffe
|
||||
#define HTT_TX_MODE_SWITCH_IND_INFO0_NUM_RECORDS_LSB 1
|
||||
|
||||
#define HTT_TX_MODE_SWITCH_IND_INFO1_MODE_MASK 0x0003
|
||||
#define HTT_TX_MODE_SWITCH_IND_INFO1_MODE_LSB 0
|
||||
#define HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD_MASK 0xfffc
|
||||
#define HTT_TX_MODE_SWITCH_IND_INFO1_THRESHOLD_LSB 2
|
||||
|
||||
#define HTT_TX_MODE_SWITCH_RECORD_INFO0_PEER_ID_MASK 0x0fff
|
||||
#define HTT_TX_MODE_SWITCH_RECORD_INFO0_PEER_ID_LSB 0
|
||||
#define HTT_TX_MODE_SWITCH_RECORD_INFO0_TID_MASK 0xf000
|
||||
#define HTT_TX_MODE_SWITCH_RECORD_INFO0_TID_LSB 12
|
||||
|
||||
struct htt_tx_mode_switch_record {
|
||||
__le16 info0; /* HTT_TX_MODE_SWITCH_RECORD_INFO0_ */
|
||||
__le16 num_max_msdus;
|
||||
} __packed;
|
||||
|
||||
struct htt_tx_mode_switch_ind {
|
||||
u8 pad0;
|
||||
__le16 info0; /* HTT_TX_MODE_SWITCH_IND_INFO0_ */
|
||||
__le16 info1; /* HTT_TX_MODE_SWITCH_IND_INFO1_ */
|
||||
u8 pad1[2];
|
||||
struct htt_tx_mode_switch_record records[0];
|
||||
} __packed;
|
||||
|
||||
union htt_rx_pn_t {
|
||||
@@ -1340,6 +1483,7 @@ struct htt_cmd {
|
||||
struct htt_oob_sync_req oob_sync_req;
|
||||
struct htt_aggr_conf aggr_conf;
|
||||
struct htt_frag_desc_bank_cfg frag_desc_bank_cfg;
|
||||
struct htt_tx_fetch_resp tx_fetch_resp;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
@@ -1364,6 +1508,9 @@ struct htt_resp {
|
||||
struct htt_rx_pn_ind rx_pn_ind;
|
||||
struct htt_rx_offload_ind rx_offload_ind;
|
||||
struct htt_rx_in_ord_ind rx_in_ord_ind;
|
||||
struct htt_tx_fetch_ind tx_fetch_ind;
|
||||
struct htt_tx_fetch_confirm tx_fetch_confirm;
|
||||
struct htt_tx_mode_switch_ind tx_mode_switch_ind;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
@@ -1518,6 +1665,14 @@ struct ath10k_htt {
|
||||
dma_addr_t paddr;
|
||||
struct ath10k_htt_txbuf *vaddr;
|
||||
} txbuf;
|
||||
|
||||
struct {
|
||||
struct htt_q_state *vaddr;
|
||||
dma_addr_t paddr;
|
||||
u16 num_peers;
|
||||
u16 num_tids;
|
||||
enum htt_q_depth_type type;
|
||||
} tx_q_state;
|
||||
};
|
||||
|
||||
#define RX_HTT_HDR_STATUS_LEN 64
|
||||
|
||||
@@ -2011,9 +2011,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
break;
|
||||
}
|
||||
case HTT_T2H_MSG_TYPE_RX_IND:
|
||||
spin_lock_bh(&htt->rx_ring.lock);
|
||||
__skb_queue_tail(&htt->rx_compl_q, skb);
|
||||
spin_unlock_bh(&htt->rx_ring.lock);
|
||||
skb_queue_tail(&htt->rx_compl_q, skb);
|
||||
tasklet_schedule(&htt->txrx_compl_task);
|
||||
return;
|
||||
case HTT_T2H_MSG_TYPE_PEER_MAP: {
|
||||
@@ -2111,9 +2109,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
break;
|
||||
}
|
||||
case HTT_T2H_MSG_TYPE_RX_IN_ORD_PADDR_IND: {
|
||||
spin_lock_bh(&htt->rx_ring.lock);
|
||||
__skb_queue_tail(&htt->rx_in_ord_compl_q, skb);
|
||||
spin_unlock_bh(&htt->rx_ring.lock);
|
||||
skb_queue_tail(&htt->rx_in_ord_compl_q, skb);
|
||||
tasklet_schedule(&htt->txrx_compl_task);
|
||||
return;
|
||||
}
|
||||
@@ -2123,10 +2119,12 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
break;
|
||||
case HTT_T2H_MSG_TYPE_AGGR_CONF:
|
||||
break;
|
||||
case HTT_T2H_MSG_TYPE_EN_STATS:
|
||||
case HTT_T2H_MSG_TYPE_TX_FETCH_IND:
|
||||
case HTT_T2H_MSG_TYPE_TX_FETCH_CONF:
|
||||
case HTT_T2H_MSG_TYPE_TX_LOW_LATENCY_IND:
|
||||
case HTT_T2H_MSG_TYPE_TX_FETCH_CONFIRM:
|
||||
case HTT_T2H_MSG_TYPE_TX_MODE_SWITCH_IND:
|
||||
/* TODO: Implement pull-push logic */
|
||||
break;
|
||||
case HTT_T2H_MSG_TYPE_EN_STATS:
|
||||
default:
|
||||
ath10k_warn(ar, "htt event (%d) not handled\n",
|
||||
resp->hdr.msg_type);
|
||||
@@ -2143,11 +2141,7 @@ EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler);
|
||||
void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ath10k_pktlog_10_4_hdr *hdr =
|
||||
(struct ath10k_pktlog_10_4_hdr *)skb->data;
|
||||
|
||||
trace_ath10k_htt_pktlog(ar, hdr->payload,
|
||||
sizeof(*hdr) + __le16_to_cpu(hdr->size));
|
||||
trace_ath10k_htt_pktlog(ar, skb->data, skb->len);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_htt_rx_pktlog_completion_handler);
|
||||
@@ -2156,24 +2150,46 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr)
|
||||
{
|
||||
struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct sk_buff_head tx_q;
|
||||
struct sk_buff_head rx_q;
|
||||
struct sk_buff_head rx_ind_q;
|
||||
struct htt_resp *resp;
|
||||
struct sk_buff *skb;
|
||||
unsigned long flags;
|
||||
|
||||
while ((skb = skb_dequeue(&htt->tx_compl_q))) {
|
||||
__skb_queue_head_init(&tx_q);
|
||||
__skb_queue_head_init(&rx_q);
|
||||
__skb_queue_head_init(&rx_ind_q);
|
||||
|
||||
spin_lock_irqsave(&htt->tx_compl_q.lock, flags);
|
||||
skb_queue_splice_init(&htt->tx_compl_q, &tx_q);
|
||||
spin_unlock_irqrestore(&htt->tx_compl_q.lock, flags);
|
||||
|
||||
spin_lock_irqsave(&htt->rx_compl_q.lock, flags);
|
||||
skb_queue_splice_init(&htt->rx_compl_q, &rx_q);
|
||||
spin_unlock_irqrestore(&htt->rx_compl_q.lock, flags);
|
||||
|
||||
spin_lock_irqsave(&htt->rx_in_ord_compl_q.lock, flags);
|
||||
skb_queue_splice_init(&htt->rx_in_ord_compl_q, &rx_ind_q);
|
||||
spin_unlock_irqrestore(&htt->rx_in_ord_compl_q.lock, flags);
|
||||
|
||||
while ((skb = __skb_dequeue(&tx_q))) {
|
||||
ath10k_htt_rx_frm_tx_compl(htt->ar, skb);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
spin_lock_bh(&htt->rx_ring.lock);
|
||||
while ((skb = __skb_dequeue(&htt->rx_compl_q))) {
|
||||
while ((skb = __skb_dequeue(&rx_q))) {
|
||||
resp = (struct htt_resp *)skb->data;
|
||||
spin_lock_bh(&htt->rx_ring.lock);
|
||||
ath10k_htt_rx_handler(htt, &resp->rx_ind);
|
||||
spin_unlock_bh(&htt->rx_ring.lock);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
while ((skb = __skb_dequeue(&htt->rx_in_ord_compl_q))) {
|
||||
while ((skb = __skb_dequeue(&rx_ind_q))) {
|
||||
spin_lock_bh(&htt->rx_ring.lock);
|
||||
ath10k_htt_rx_in_ord_ind(ar, skb);
|
||||
spin_unlock_bh(&htt->rx_ring.lock);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
spin_unlock_bh(&htt->rx_ring.lock);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user