You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'wireless-drivers-next-for-davem-2015-08-19' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Kalle Valo says: ==================== Major changes: ath10k: * add support for qca99x0 family of devices * improve performance of tx_lock * add support for raw mode (802.11 frame format) and software crypto engine enabled via a module parameter ath9k: * add fast-xmit support wil6210: * implement TSO support * support bootloader v1 and onwards iwlwifi: * Deprecate -10.ucode * Clean ups towards multiple Rx queues * Add support for longer CMD IDs. This will be required by new firmwares since we are getting close to the u8 limit. * bugfixes for the D0i3 power state * Add basic support for FTM * polish the Miracast operation * fix a few power consumption issues * scan cleanup * fixes for D0i3 system state * add paging for devices that support it * add again the new RBD allocation model * add more options to the firmware debug system * add support for frag SKBs in Tx ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -92,7 +92,7 @@ config BCMA_DRIVER_GMAC_CMN
|
||||
config BCMA_DRIVER_GPIO
|
||||
bool "BCMA GPIO driver"
|
||||
depends on BCMA && GPIOLIB
|
||||
select IRQ_DOMAIN if BCMA_HOST_SOC
|
||||
select GPIOLIB_IRQCHIP if BCMA_HOST_SOC
|
||||
help
|
||||
Driver to provide access to the GPIO pins of the bcma bus.
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ int __init bcma_bus_early_register(struct bcma_bus *bus);
|
||||
int bcma_bus_suspend(struct bcma_bus *bus);
|
||||
int bcma_bus_resume(struct bcma_bus *bus);
|
||||
#endif
|
||||
struct device *bcma_bus_get_host_dev(struct bcma_bus *bus);
|
||||
|
||||
/* scan.c */
|
||||
void bcma_detect_chip(struct bcma_bus *bus);
|
||||
|
||||
+30
-62
@@ -8,10 +8,8 @@
|
||||
* Licensed under the GNU/GPL. See COPYING for details.
|
||||
*/
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
|
||||
@@ -79,19 +77,11 @@ static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio)
|
||||
}
|
||||
|
||||
#if IS_BUILTIN(CONFIG_BCM47XX) || IS_BUILTIN(CONFIG_ARCH_BCM_5301X)
|
||||
static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
|
||||
{
|
||||
struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip);
|
||||
|
||||
if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
return irq_find_mapping(cc->irq_domain, gpio);
|
||||
else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void bcma_gpio_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct bcma_drv_cc *cc = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct bcma_drv_cc *cc = bcma_gpio_get_cc(gc);
|
||||
int gpio = irqd_to_hwirq(d);
|
||||
u32 val = bcma_chipco_gpio_in(cc, BIT(gpio));
|
||||
|
||||
@@ -101,7 +91,8 @@ static void bcma_gpio_irq_unmask(struct irq_data *d)
|
||||
|
||||
static void bcma_gpio_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct bcma_drv_cc *cc = irq_data_get_irq_chip_data(d);
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct bcma_drv_cc *cc = bcma_gpio_get_cc(gc);
|
||||
int gpio = irqd_to_hwirq(d);
|
||||
|
||||
bcma_chipco_gpio_intmask(cc, BIT(gpio), 0);
|
||||
@@ -116,6 +107,7 @@ static struct irq_chip bcma_gpio_irq_chip = {
|
||||
static irqreturn_t bcma_gpio_irq_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct bcma_drv_cc *cc = dev_id;
|
||||
struct gpio_chip *gc = &cc->gpio;
|
||||
u32 val = bcma_cc_read32(cc, BCMA_CC_GPIOIN);
|
||||
u32 mask = bcma_cc_read32(cc, BCMA_CC_GPIOIRQ);
|
||||
u32 pol = bcma_cc_read32(cc, BCMA_CC_GPIOPOL);
|
||||
@@ -125,81 +117,58 @@ static irqreturn_t bcma_gpio_irq_handler(int irq, void *dev_id)
|
||||
if (!irqs)
|
||||
return IRQ_NONE;
|
||||
|
||||
for_each_set_bit(gpio, &irqs, cc->gpio.ngpio)
|
||||
generic_handle_irq(bcma_gpio_to_irq(&cc->gpio, gpio));
|
||||
for_each_set_bit(gpio, &irqs, gc->ngpio)
|
||||
generic_handle_irq(irq_find_mapping(gc->irqdomain, gpio));
|
||||
bcma_chipco_gpio_polarity(cc, irqs, val & irqs);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int bcma_gpio_irq_domain_init(struct bcma_drv_cc *cc)
|
||||
static int bcma_gpio_irq_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct gpio_chip *chip = &cc->gpio;
|
||||
int gpio, hwirq, err;
|
||||
int hwirq, err;
|
||||
|
||||
if (cc->core->bus->hosttype != BCMA_HOSTTYPE_SOC)
|
||||
return 0;
|
||||
|
||||
cc->irq_domain = irq_domain_add_linear(NULL, chip->ngpio,
|
||||
&irq_domain_simple_ops, cc);
|
||||
if (!cc->irq_domain) {
|
||||
err = -ENODEV;
|
||||
goto err_irq_domain;
|
||||
}
|
||||
for (gpio = 0; gpio < chip->ngpio; gpio++) {
|
||||
int irq = irq_create_mapping(cc->irq_domain, gpio);
|
||||
|
||||
irq_set_chip_data(irq, cc);
|
||||
irq_set_chip_and_handler(irq, &bcma_gpio_irq_chip,
|
||||
handle_simple_irq);
|
||||
}
|
||||
|
||||
hwirq = bcma_core_irq(cc->core, 0);
|
||||
err = request_irq(hwirq, bcma_gpio_irq_handler, IRQF_SHARED, "gpio",
|
||||
cc);
|
||||
if (err)
|
||||
goto err_req_irq;
|
||||
return err;
|
||||
|
||||
bcma_chipco_gpio_intmask(cc, ~0, 0);
|
||||
bcma_cc_set32(cc, BCMA_CC_IRQMASK, BCMA_CC_IRQ_GPIO);
|
||||
|
||||
return 0;
|
||||
|
||||
err_req_irq:
|
||||
for (gpio = 0; gpio < chip->ngpio; gpio++) {
|
||||
int irq = irq_find_mapping(cc->irq_domain, gpio);
|
||||
|
||||
irq_dispose_mapping(irq);
|
||||
err = gpiochip_irqchip_add(chip,
|
||||
&bcma_gpio_irq_chip,
|
||||
0,
|
||||
handle_simple_irq,
|
||||
IRQ_TYPE_NONE);
|
||||
if (err) {
|
||||
free_irq(hwirq, cc);
|
||||
return err;
|
||||
}
|
||||
irq_domain_remove(cc->irq_domain);
|
||||
err_irq_domain:
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bcma_gpio_irq_domain_exit(struct bcma_drv_cc *cc)
|
||||
static void bcma_gpio_irq_exit(struct bcma_drv_cc *cc)
|
||||
{
|
||||
struct gpio_chip *chip = &cc->gpio;
|
||||
int gpio;
|
||||
|
||||
if (cc->core->bus->hosttype != BCMA_HOSTTYPE_SOC)
|
||||
return;
|
||||
|
||||
bcma_cc_mask32(cc, BCMA_CC_IRQMASK, ~BCMA_CC_IRQ_GPIO);
|
||||
free_irq(bcma_core_irq(cc->core, 0), cc);
|
||||
for (gpio = 0; gpio < chip->ngpio; gpio++) {
|
||||
int irq = irq_find_mapping(cc->irq_domain, gpio);
|
||||
|
||||
irq_dispose_mapping(irq);
|
||||
}
|
||||
irq_domain_remove(cc->irq_domain);
|
||||
}
|
||||
#else
|
||||
static int bcma_gpio_irq_domain_init(struct bcma_drv_cc *cc)
|
||||
static int bcma_gpio_irq_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bcma_gpio_irq_domain_exit(struct bcma_drv_cc *cc)
|
||||
static void bcma_gpio_irq_exit(struct bcma_drv_cc *cc)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
@@ -218,9 +187,8 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
|
||||
chip->set = bcma_gpio_set_value;
|
||||
chip->direction_input = bcma_gpio_direction_input;
|
||||
chip->direction_output = bcma_gpio_direction_output;
|
||||
#if IS_BUILTIN(CONFIG_BCM47XX) || IS_BUILTIN(CONFIG_ARCH_BCM_5301X)
|
||||
chip->to_irq = bcma_gpio_to_irq;
|
||||
#endif
|
||||
chip->owner = THIS_MODULE;
|
||||
chip->dev = bcma_bus_get_host_dev(bus);
|
||||
#if IS_BUILTIN(CONFIG_OF)
|
||||
if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC)
|
||||
chip->of_node = cc->core->dev.of_node;
|
||||
@@ -248,13 +216,13 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
|
||||
else
|
||||
chip->base = -1;
|
||||
|
||||
err = bcma_gpio_irq_domain_init(cc);
|
||||
err = gpiochip_add(chip);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = gpiochip_add(chip);
|
||||
err = bcma_gpio_irq_init(cc);
|
||||
if (err) {
|
||||
bcma_gpio_irq_domain_exit(cc);
|
||||
gpiochip_remove(chip);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -263,7 +231,7 @@ int bcma_gpio_init(struct bcma_drv_cc *cc)
|
||||
|
||||
int bcma_gpio_unregister(struct bcma_drv_cc *cc)
|
||||
{
|
||||
bcma_gpio_irq_domain_exit(cc);
|
||||
bcma_gpio_irq_exit(cc);
|
||||
gpiochip_remove(&cc->gpio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+27
-3
@@ -7,7 +7,9 @@
|
||||
|
||||
#include "bcma_private.h"
|
||||
#include <linux/module.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/bcma/bcma.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of_address.h>
|
||||
@@ -269,6 +271,28 @@ void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core)
|
||||
}
|
||||
}
|
||||
|
||||
struct device *bcma_bus_get_host_dev(struct bcma_bus *bus)
|
||||
{
|
||||
switch (bus->hosttype) {
|
||||
case BCMA_HOSTTYPE_PCI:
|
||||
if (bus->host_pci)
|
||||
return &bus->host_pci->dev;
|
||||
else
|
||||
return NULL;
|
||||
case BCMA_HOSTTYPE_SOC:
|
||||
if (bus->host_pdev)
|
||||
return &bus->host_pdev->dev;
|
||||
else
|
||||
return NULL;
|
||||
case BCMA_HOSTTYPE_SDIO:
|
||||
if (bus->host_sdio)
|
||||
return &bus->host_sdio->dev;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void bcma_init_bus(struct bcma_bus *bus)
|
||||
{
|
||||
mutex_lock(&bcma_buses_mutex);
|
||||
@@ -388,6 +412,7 @@ int bcma_bus_register(struct bcma_bus *bus)
|
||||
{
|
||||
int err;
|
||||
struct bcma_device *core;
|
||||
struct device *dev;
|
||||
|
||||
/* Scan for devices (cores) */
|
||||
err = bcma_bus_scan(bus);
|
||||
@@ -410,13 +435,12 @@ int bcma_bus_register(struct bcma_bus *bus)
|
||||
bcma_core_pci_early_init(&bus->drv_pci[0]);
|
||||
}
|
||||
|
||||
dev = bcma_bus_get_host_dev(bus);
|
||||
/* TODO: remove check for IS_BUILTIN(CONFIG_BCMA) check when
|
||||
* of_default_bus_match_table is exported or in some other way
|
||||
* accessible. This is just a temporary workaround.
|
||||
*/
|
||||
if (IS_BUILTIN(CONFIG_BCMA) && bus->host_pdev) {
|
||||
struct device *dev = &bus->host_pdev->dev;
|
||||
|
||||
if (IS_BUILTIN(CONFIG_BCMA) && dev) {
|
||||
of_platform_populate(dev->of_node, of_default_bus_match_table,
|
||||
NULL, dev);
|
||||
}
|
||||
|
||||
@@ -31,16 +31,19 @@
|
||||
#include "wmi-ops.h"
|
||||
|
||||
unsigned int ath10k_debug_mask;
|
||||
static unsigned int ath10k_cryptmode_param;
|
||||
static bool uart_print;
|
||||
static bool skip_otp;
|
||||
|
||||
module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
|
||||
module_param_named(cryptmode, ath10k_cryptmode_param, uint, 0644);
|
||||
module_param(uart_print, bool, 0644);
|
||||
module_param(skip_otp, bool, 0644);
|
||||
|
||||
MODULE_PARM_DESC(debug_mask, "Debugging mask");
|
||||
MODULE_PARM_DESC(uart_print, "Uart target debugging");
|
||||
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
|
||||
MODULE_PARM_DESC(cryptmode, "Crypto mode: 0-hardware, 1-software");
|
||||
|
||||
static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
{
|
||||
@@ -1073,6 +1076,46 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_NATIVE_WIFI;
|
||||
switch (ath10k_cryptmode_param) {
|
||||
case ATH10K_CRYPT_MODE_HW:
|
||||
clear_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);
|
||||
clear_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags);
|
||||
break;
|
||||
case ATH10K_CRYPT_MODE_SW:
|
||||
if (!test_bit(ATH10K_FW_FEATURE_RAW_MODE_SUPPORT,
|
||||
ar->fw_features)) {
|
||||
ath10k_err(ar, "cryptmode > 0 requires raw mode support from firmware");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
set_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags);
|
||||
set_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags);
|
||||
break;
|
||||
default:
|
||||
ath10k_info(ar, "invalid cryptmode: %d\n",
|
||||
ath10k_cryptmode_param);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ar->htt.max_num_amsdu = ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT;
|
||||
ar->htt.max_num_ampdu = ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT;
|
||||
|
||||
if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
|
||||
ar->wmi.rx_decap_mode = ATH10K_HW_TXRX_RAW;
|
||||
|
||||
/* Workaround:
|
||||
*
|
||||
* Firmware A-MSDU aggregation breaks with RAW Tx encap mode
|
||||
* and causes enormous performance issues (malformed frames,
|
||||
* etc).
|
||||
*
|
||||
* Disabling A-MSDU makes RAW mode stable with heavy traffic
|
||||
* albeit a bit slower compared to regular operation.
|
||||
*/
|
||||
ar->htt.max_num_amsdu = 1;
|
||||
}
|
||||
|
||||
/* Backwards compatibility for firmwares without
|
||||
* ATH10K_FW_IE_WMI_OP_VERSION.
|
||||
*/
|
||||
@@ -1606,6 +1649,10 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
||||
if (!ar->workqueue)
|
||||
goto err_free_mac;
|
||||
|
||||
ar->workqueue_aux = create_singlethread_workqueue("ath10k_aux_wq");
|
||||
if (!ar->workqueue_aux)
|
||||
goto err_free_wq;
|
||||
|
||||
mutex_init(&ar->conf_mutex);
|
||||
spin_lock_init(&ar->data_lock);
|
||||
|
||||
@@ -1626,10 +1673,12 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
||||
|
||||
ret = ath10k_debug_create(ar);
|
||||
if (ret)
|
||||
goto err_free_wq;
|
||||
goto err_free_aux_wq;
|
||||
|
||||
return ar;
|
||||
|
||||
err_free_aux_wq:
|
||||
destroy_workqueue(ar->workqueue_aux);
|
||||
err_free_wq:
|
||||
destroy_workqueue(ar->workqueue);
|
||||
|
||||
@@ -1645,6 +1694,9 @@ void ath10k_core_destroy(struct ath10k *ar)
|
||||
flush_workqueue(ar->workqueue);
|
||||
destroy_workqueue(ar->workqueue);
|
||||
|
||||
flush_workqueue(ar->workqueue_aux);
|
||||
destroy_workqueue(ar->workqueue_aux);
|
||||
|
||||
ath10k_debug_destroy(ar);
|
||||
ath10k_mac_destroy(ar);
|
||||
}
|
||||
|
||||
@@ -92,6 +92,7 @@ struct ath10k_skb_cb {
|
||||
u8 tid;
|
||||
u16 freq;
|
||||
bool is_offchan;
|
||||
bool nohwcrypt;
|
||||
struct ath10k_htt_txbuf *txbuf;
|
||||
u32 txbuf_paddr;
|
||||
} __packed htt;
|
||||
@@ -152,6 +153,7 @@ struct ath10k_wmi {
|
||||
const struct wmi_ops *ops;
|
||||
|
||||
u32 num_mem_chunks;
|
||||
u32 rx_decap_mode;
|
||||
struct ath10k_mem_chunk mem_chunks[WMI_MAX_MEM_REQS];
|
||||
};
|
||||
|
||||
@@ -341,6 +343,7 @@ struct ath10k_vif {
|
||||
} u;
|
||||
|
||||
bool use_cts_prot;
|
||||
bool nohwcrypt;
|
||||
int num_legacy_stations;
|
||||
int txpower;
|
||||
struct wmi_wmm_params_all_arg wmm_params;
|
||||
@@ -382,9 +385,6 @@ struct ath10k_debug {
|
||||
u32 reg_addr;
|
||||
u32 nf_cal_period;
|
||||
|
||||
u8 htt_max_amsdu;
|
||||
u8 htt_max_ampdu;
|
||||
|
||||
struct ath10k_fw_crash_data *fw_crash_data;
|
||||
};
|
||||
|
||||
@@ -453,16 +453,21 @@ enum ath10k_fw_features {
|
||||
ATH10K_FW_FEATURE_WOWLAN_SUPPORT = 6,
|
||||
|
||||
/* Don't trust error code from otp.bin */
|
||||
ATH10K_FW_FEATURE_IGNORE_OTP_RESULT,
|
||||
ATH10K_FW_FEATURE_IGNORE_OTP_RESULT = 7,
|
||||
|
||||
/* Some firmware revisions pad 4th hw address to 4 byte boundary making
|
||||
* it 8 bytes long in Native Wifi Rx decap.
|
||||
*/
|
||||
ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING,
|
||||
ATH10K_FW_FEATURE_NO_NWIFI_DECAP_4ADDR_PADDING = 8,
|
||||
|
||||
/* Firmware supports bypassing PLL setting on init. */
|
||||
ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT = 9,
|
||||
|
||||
/* Raw mode support. If supported, FW supports receiving and trasmitting
|
||||
* frames in raw mode.
|
||||
*/
|
||||
ATH10K_FW_FEATURE_RAW_MODE_SUPPORT = 10,
|
||||
|
||||
/* keep last */
|
||||
ATH10K_FW_FEATURE_COUNT,
|
||||
};
|
||||
@@ -476,6 +481,15 @@ enum ath10k_dev_flags {
|
||||
* waiters should immediately cancel instead of waiting for a time out.
|
||||
*/
|
||||
ATH10K_FLAG_CRASH_FLUSH,
|
||||
|
||||
/* Use Raw mode instead of native WiFi Tx/Rx encap mode.
|
||||
* Raw mode supports both hardware and software crypto. Native WiFi only
|
||||
* supports hardware crypto.
|
||||
*/
|
||||
ATH10K_FLAG_RAW_MODE,
|
||||
|
||||
/* Disable HW crypto engine */
|
||||
ATH10K_FLAG_HW_CRYPTO_DISABLED,
|
||||
};
|
||||
|
||||
enum ath10k_cal_mode {
|
||||
@@ -484,6 +498,13 @@ enum ath10k_cal_mode {
|
||||
ATH10K_CAL_MODE_DT,
|
||||
};
|
||||
|
||||
enum ath10k_crypt_mode {
|
||||
/* Only use hardware crypto engine */
|
||||
ATH10K_CRYPT_MODE_HW,
|
||||
/* Only use software crypto engine */
|
||||
ATH10K_CRYPT_MODE_SW,
|
||||
};
|
||||
|
||||
static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
@@ -673,6 +694,8 @@ struct ath10k {
|
||||
struct completion vdev_setup_done;
|
||||
|
||||
struct workqueue_struct *workqueue;
|
||||
/* Auxiliary workqueue */
|
||||
struct workqueue_struct *workqueue_aux;
|
||||
|
||||
/* prevents concurrent FW reconfiguration */
|
||||
struct mutex conf_mutex;
|
||||
@@ -695,6 +718,9 @@ struct ath10k {
|
||||
int num_active_peers;
|
||||
int num_tids;
|
||||
|
||||
struct work_struct svc_rdy_work;
|
||||
struct sk_buff *svc_rdy_skb;
|
||||
|
||||
struct work_struct offchan_tx_work;
|
||||
struct sk_buff_head offchan_tx_queue;
|
||||
struct completion offchan_tx_completed;
|
||||
|
||||
@@ -124,11 +124,11 @@ EXPORT_SYMBOL(ath10k_info);
|
||||
|
||||
void ath10k_print_driver_info(struct ath10k *ar)
|
||||
{
|
||||
char fw_features[128];
|
||||
char fw_features[128] = {};
|
||||
|
||||
ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
|
||||
|
||||
ath10k_info(ar, "%s (0x%08x, 0x%08x%s%s%s) fw %s api %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d features %s\n",
|
||||
ath10k_info(ar, "%s (0x%08x, 0x%08x%s%s%s) fw %s api %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n",
|
||||
ar->hw_params.name,
|
||||
ar->target_version,
|
||||
ar->chip_id,
|
||||
@@ -144,6 +144,8 @@ void ath10k_print_driver_info(struct ath10k *ar)
|
||||
ar->htt.op_version,
|
||||
ath10k_cal_mode_str(ar->cal_mode),
|
||||
ar->max_num_stations,
|
||||
test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
|
||||
!test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags),
|
||||
fw_features);
|
||||
ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
|
||||
config_enabled(CONFIG_ATH10K_DEBUG),
|
||||
@@ -1363,12 +1365,8 @@ static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->debug.htt_max_amsdu)
|
||||
amsdu = ar->debug.htt_max_amsdu;
|
||||
|
||||
if (ar->debug.htt_max_ampdu)
|
||||
ampdu = ar->debug.htt_max_ampdu;
|
||||
|
||||
amsdu = ar->htt.max_num_amsdu;
|
||||
ampdu = ar->htt.max_num_ampdu;
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
|
||||
@@ -1402,8 +1400,8 @@ static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
|
||||
goto out;
|
||||
|
||||
res = count;
|
||||
ar->debug.htt_max_amsdu = amsdu;
|
||||
ar->debug.htt_max_ampdu = ampdu;
|
||||
ar->htt.max_num_amsdu = amsdu;
|
||||
ar->htt.max_num_ampdu = ampdu;
|
||||
|
||||
out:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
@@ -1905,9 +1903,6 @@ void ath10k_debug_stop(struct ath10k *ar)
|
||||
if (ar->debug.htt_stats_mask != 0)
|
||||
cancel_delayed_work(&ar->debug.htt_stats_dwork);
|
||||
|
||||
ar->debug.htt_max_amsdu = 0;
|
||||
ar->debug.htt_max_ampdu = 0;
|
||||
|
||||
ath10k_wmi_pdev_pktlog_disable(ar);
|
||||
}
|
||||
|
||||
|
||||
@@ -246,12 +246,31 @@ int ath10k_htt_setup(struct ath10k_htt *htt)
|
||||
}
|
||||
|
||||
status = ath10k_htt_verify_version(htt);
|
||||
if (status)
|
||||
if (status) {
|
||||
ath10k_warn(ar, "failed to verify htt version: %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = ath10k_htt_send_frag_desc_bank_cfg(htt);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return ath10k_htt_send_rx_ring_cfg_ll(htt);
|
||||
status = ath10k_htt_send_rx_ring_cfg_ll(htt);
|
||||
if (status) {
|
||||
ath10k_warn(ar, "failed to setup rx ring: %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = ath10k_htt_h2t_aggr_cfg_msg(htt,
|
||||
htt->max_num_ampdu,
|
||||
htt->max_num_amsdu);
|
||||
if (status) {
|
||||
ath10k_warn(ar, "failed to setup amsdu/ampdu limit: %d\n",
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -83,15 +83,39 @@ struct htt_ver_req {
|
||||
* around the mask + shift defs.
|
||||
*/
|
||||
struct htt_data_tx_desc_frag {
|
||||
__le32 paddr;
|
||||
__le32 len;
|
||||
union {
|
||||
struct double_word_addr {
|
||||
__le32 paddr;
|
||||
__le32 len;
|
||||
} __packed dword_addr;
|
||||
struct triple_word_addr {
|
||||
__le32 paddr_lo;
|
||||
__le16 paddr_hi;
|
||||
__le16 len_16;
|
||||
} __packed tword_addr;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
struct htt_msdu_ext_desc {
|
||||
__le32 tso_flag[4];
|
||||
__le32 tso_flag[3];
|
||||
__le16 ip_identification;
|
||||
u8 flags;
|
||||
u8 reserved;
|
||||
struct htt_data_tx_desc_frag frags[6];
|
||||
};
|
||||
|
||||
#define HTT_MSDU_EXT_DESC_FLAG_IPV4_CSUM_ENABLE BIT(0)
|
||||
#define HTT_MSDU_EXT_DESC_FLAG_UDP_IPV4_CSUM_ENABLE BIT(1)
|
||||
#define HTT_MSDU_EXT_DESC_FLAG_UDP_IPV6_CSUM_ENABLE BIT(2)
|
||||
#define HTT_MSDU_EXT_DESC_FLAG_TCP_IPV4_CSUM_ENABLE BIT(3)
|
||||
#define HTT_MSDU_EXT_DESC_FLAG_TCP_IPV6_CSUM_ENABLE BIT(4)
|
||||
|
||||
#define HTT_MSDU_CHECKSUM_ENABLE (HTT_MSDU_EXT_DESC_FLAG_IPV4_CSUM_ENABLE \
|
||||
| HTT_MSDU_EXT_DESC_FLAG_UDP_IPV4_CSUM_ENABLE \
|
||||
| HTT_MSDU_EXT_DESC_FLAG_UDP_IPV6_CSUM_ENABLE \
|
||||
| HTT_MSDU_EXT_DESC_FLAG_TCP_IPV4_CSUM_ENABLE \
|
||||
| HTT_MSDU_EXT_DESC_FLAG_TCP_IPV6_CSUM_ENABLE)
|
||||
|
||||
enum htt_data_tx_desc_flags0 {
|
||||
HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT = 1 << 0,
|
||||
HTT_DATA_TX_DESC_FLAGS0_NO_AGGR = 1 << 1,
|
||||
@@ -260,6 +284,9 @@ struct htt_aggr_conf {
|
||||
} __packed;
|
||||
|
||||
#define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32
|
||||
struct htt_mgmt_tx_desc_qca99x0 {
|
||||
__le32 rate;
|
||||
} __packed;
|
||||
|
||||
struct htt_mgmt_tx_desc {
|
||||
u8 pad[sizeof(u32) - sizeof(struct htt_cmd_hdr)];
|
||||
@@ -268,6 +295,9 @@ struct htt_mgmt_tx_desc {
|
||||
__le32 len;
|
||||
__le32 vdev_id;
|
||||
u8 hdr[HTT_MGMT_FRM_HDR_DOWNLOAD_LEN];
|
||||
union {
|
||||
struct htt_mgmt_tx_desc_qca99x0 qca99x0;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
enum htt_mgmt_tx_status {
|
||||
@@ -1366,6 +1396,8 @@ struct ath10k_htt {
|
||||
u8 target_version_minor;
|
||||
struct completion target_version_received;
|
||||
enum ath10k_fw_htt_op_version op_version;
|
||||
u8 max_num_amsdu;
|
||||
u8 max_num_ampdu;
|
||||
|
||||
const enum htt_t2h_msg_type *t2h_msg_types;
|
||||
u32 t2h_msg_types_max;
|
||||
@@ -1528,6 +1560,12 @@ struct htt_rx_desc {
|
||||
#define HTT_LOG2_MAX_CACHE_LINE_SIZE 7 /* 2^7 = 128 */
|
||||
#define HTT_MAX_CACHE_LINE_SIZE_MASK ((1 << HTT_LOG2_MAX_CACHE_LINE_SIZE) - 1)
|
||||
|
||||
/* These values are default in most firmware revisions and apparently are a
|
||||
* sweet spot performance wise.
|
||||
*/
|
||||
#define ATH10K_HTT_MAX_NUM_AMSDU_DEFAULT 3
|
||||
#define ATH10K_HTT_MAX_NUM_AMPDU_DEFAULT 64
|
||||
|
||||
int ath10k_htt_connect(struct ath10k_htt *htt);
|
||||
int ath10k_htt_init(struct ath10k *ar);
|
||||
int ath10k_htt_setup(struct ath10k_htt *htt);
|
||||
|
||||
@@ -368,7 +368,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
|
||||
msdu_len_invalid = !!(__le32_to_cpu(rx_desc->attention.flags)
|
||||
& (RX_ATTENTION_FLAGS_MPDU_LENGTH_ERR |
|
||||
RX_ATTENTION_FLAGS_MSDU_LENGTH_ERR));
|
||||
msdu_len = MS(__le32_to_cpu(rx_desc->msdu_start.info0),
|
||||
msdu_len = MS(__le32_to_cpu(rx_desc->msdu_start.common.info0),
|
||||
RX_MSDU_START_INFO0_MSDU_LENGTH);
|
||||
msdu_chained = rx_desc->frag_info.ring2_more_count;
|
||||
|
||||
@@ -394,7 +394,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
|
||||
msdu_chaining = 1;
|
||||
}
|
||||
|
||||
last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) &
|
||||
last_msdu = __le32_to_cpu(rx_desc->msdu_end.common.info0) &
|
||||
RX_MSDU_END_INFO0_LAST_MSDU;
|
||||
|
||||
trace_ath10k_htt_rx_desc(ar, &rx_desc->attention,
|
||||
@@ -740,7 +740,7 @@ ath10k_htt_rx_h_peer_channel(struct ath10k *ar, struct htt_rx_desc *rxd)
|
||||
__cpu_to_le32(RX_ATTENTION_FLAGS_PEER_IDX_INVALID))
|
||||
return NULL;
|
||||
|
||||
if (!(rxd->msdu_end.info0 &
|
||||
if (!(rxd->msdu_end.common.info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU)))
|
||||
return NULL;
|
||||
|
||||
@@ -991,9 +991,9 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
|
||||
bool is_last;
|
||||
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
is_first = !!(rxd->msdu_end.info0 &
|
||||
is_first = !!(rxd->msdu_end.common.info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
|
||||
is_last = !!(rxd->msdu_end.info0 &
|
||||
is_last = !!(rxd->msdu_end.common.info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
|
||||
|
||||
/* Delivered decapped frame:
|
||||
@@ -1017,9 +1017,8 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
|
||||
skb_trim(msdu, msdu->len - FCS_LEN);
|
||||
|
||||
/* In most cases this will be true for sniffed frames. It makes sense
|
||||
* to deliver them as-is without stripping the crypto param. This would
|
||||
* also make sense for software based decryption (which is not
|
||||
* implemented in ath10k).
|
||||
* to deliver them as-is without stripping the crypto param. This is
|
||||
* necessary for software based decryption.
|
||||
*
|
||||
* If there's no error then the frame is decrypted. At least that is
|
||||
* the case for frames that come in via fragmented rx indication.
|
||||
@@ -1104,9 +1103,9 @@ static void *ath10k_htt_rx_h_find_rfc1042(struct ath10k *ar,
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
hdr = (void *)rxd->rx_hdr_status;
|
||||
|
||||
is_first = !!(rxd->msdu_end.info0 &
|
||||
is_first = !!(rxd->msdu_end.common.info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
|
||||
is_last = !!(rxd->msdu_end.info0 &
|
||||
is_last = !!(rxd->msdu_end.common.info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
|
||||
is_amsdu = !(is_first && is_last);
|
||||
|
||||
@@ -1214,7 +1213,7 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar,
|
||||
*/
|
||||
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
decap = MS(__le32_to_cpu(rxd->msdu_start.info1),
|
||||
decap = MS(__le32_to_cpu(rxd->msdu_start.common.info1),
|
||||
RX_MSDU_START_INFO1_DECAP_FORMAT);
|
||||
|
||||
switch (decap) {
|
||||
@@ -1244,7 +1243,7 @@ static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb)
|
||||
|
||||
rxd = (void *)skb->data - sizeof(*rxd);
|
||||
flags = __le32_to_cpu(rxd->attention.flags);
|
||||
info = __le32_to_cpu(rxd->msdu_start.info1);
|
||||
info = __le32_to_cpu(rxd->msdu_start.common.info1);
|
||||
|
||||
is_ip4 = !!(info & RX_MSDU_START_INFO1_IPV4_PROTO);
|
||||
is_ip6 = !!(info & RX_MSDU_START_INFO1_IPV6_PROTO);
|
||||
@@ -1437,7 +1436,7 @@ static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
|
||||
|
||||
first = skb_peek(amsdu);
|
||||
rxd = (void *)first->data - sizeof(*rxd);
|
||||
decap = MS(__le32_to_cpu(rxd->msdu_start.info1),
|
||||
decap = MS(__le32_to_cpu(rxd->msdu_start.common.info1),
|
||||
RX_MSDU_START_INFO1_DECAP_FORMAT);
|
||||
|
||||
if (!chained)
|
||||
@@ -1631,8 +1630,6 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar,
|
||||
__le16 msdu_id;
|
||||
int i;
|
||||
|
||||
lockdep_assert_held(&htt->tx_lock);
|
||||
|
||||
switch (status) {
|
||||
case HTT_DATA_TX_STATUS_NO_ACK:
|
||||
tx_done.no_ack = true;
|
||||
@@ -1757,14 +1754,14 @@ static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list,
|
||||
__skb_queue_tail(amsdu, msdu);
|
||||
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
if (rxd->msdu_end.info0 &
|
||||
if (rxd->msdu_end.common.info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU))
|
||||
break;
|
||||
}
|
||||
|
||||
msdu = skb_peek_tail(amsdu);
|
||||
rxd = (void *)msdu->data - sizeof(*rxd);
|
||||
if (!(rxd->msdu_end.info0 &
|
||||
if (!(rxd->msdu_end.common.info0 &
|
||||
__cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU))) {
|
||||
skb_queue_splice_init(amsdu, list);
|
||||
return -EAGAIN;
|
||||
@@ -1998,15 +1995,11 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
ath10k_txrx_tx_unref(htt, &tx_done);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
break;
|
||||
}
|
||||
case HTT_T2H_MSG_TYPE_TX_COMPL_IND:
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
__skb_queue_tail(&htt->tx_compl_q, skb);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
skb_queue_tail(&htt->tx_compl_q, skb);
|
||||
tasklet_schedule(&htt->txrx_compl_task);
|
||||
return;
|
||||
case HTT_T2H_MSG_TYPE_SEC_IND: {
|
||||
@@ -2072,6 +2065,8 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
break;
|
||||
case HTT_T2H_MSG_TYPE_CHAN_CHANGE:
|
||||
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:
|
||||
@@ -2095,12 +2090,10 @@ static void ath10k_htt_txrx_compl_task(unsigned long ptr)
|
||||
struct htt_resp *resp;
|
||||
struct sk_buff *skb;
|
||||
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
while ((skb = __skb_dequeue(&htt->tx_compl_q))) {
|
||||
while ((skb = skb_dequeue(&htt->tx_compl_q))) {
|
||||
ath10k_htt_rx_frm_tx_compl(htt->ar, skb);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
|
||||
spin_lock_bh(&htt->rx_ring.lock);
|
||||
while ((skb = __skb_dequeue(&htt->rx_compl_q))) {
|
||||
|
||||
@@ -63,7 +63,8 @@ int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb)
|
||||
|
||||
lockdep_assert_held(&htt->tx_lock);
|
||||
|
||||
ret = idr_alloc(&htt->pending_tx, skb, 0, 0x10000, GFP_ATOMIC);
|
||||
ret = idr_alloc(&htt->pending_tx, skb, 0,
|
||||
htt->max_num_pending_tx, GFP_ATOMIC);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx alloc msdu_id %d\n", ret);
|
||||
|
||||
@@ -133,9 +134,7 @@ static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx)
|
||||
tx_done.discard = 1;
|
||||
tx_done.msdu_id = msdu_id;
|
||||
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
ath10k_txrx_tx_unref(htt, &tx_done);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -259,6 +258,7 @@ int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt)
|
||||
cmd->frag_desc_bank_cfg.desc_size = sizeof(struct htt_msdu_ext_desc);
|
||||
cmd->frag_desc_bank_cfg.bank_base_addrs[0] =
|
||||
__cpu_to_le32(htt->frag_desc.paddr);
|
||||
cmd->frag_desc_bank_cfg.bank_id[0].bank_min_id = 0;
|
||||
cmd->frag_desc_bank_cfg.bank_id[0].bank_max_id =
|
||||
__cpu_to_le16(htt->max_num_pending_tx - 1);
|
||||
|
||||
@@ -427,12 +427,11 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
||||
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
if (res < 0) {
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
goto err_tx_dec;
|
||||
}
|
||||
msdu_id = res;
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
|
||||
txdesc = ath10k_htc_alloc_skb(ar, len);
|
||||
if (!txdesc) {
|
||||
@@ -448,6 +447,8 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
||||
|
||||
skb_put(txdesc, len);
|
||||
cmd = (struct htt_cmd *)txdesc->data;
|
||||
memset(cmd, 0, len);
|
||||
|
||||
cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_MGMT_TX;
|
||||
cmd->mgmt_tx.msdu_paddr = __cpu_to_le32(ATH10K_SKB_CB(msdu)->paddr);
|
||||
cmd->mgmt_tx.len = __cpu_to_le32(msdu->len);
|
||||
@@ -494,6 +495,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
||||
u16 msdu_id, flags1 = 0;
|
||||
dma_addr_t paddr = 0;
|
||||
u32 frags_paddr = 0;
|
||||
struct htt_msdu_ext_desc *ext_desc = NULL;
|
||||
|
||||
res = ath10k_htt_tx_inc_pending(htt);
|
||||
if (res)
|
||||
@@ -501,12 +503,11 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
||||
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
if (res < 0) {
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
goto err_tx_dec;
|
||||
}
|
||||
msdu_id = res;
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
|
||||
prefetch_len = min(htt->prefetch_len, msdu->len);
|
||||
prefetch_len = roundup(prefetch_len, 4);
|
||||
@@ -522,8 +523,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
||||
if ((ieee80211_is_action(hdr->frame_control) ||
|
||||
ieee80211_is_deauth(hdr->frame_control) ||
|
||||
ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||
ieee80211_has_protected(hdr->frame_control))
|
||||
ieee80211_has_protected(hdr->frame_control)) {
|
||||
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
} else if (!skb_cb->htt.nohwcrypt &&
|
||||
skb_cb->txmode == ATH10K_HW_TXRX_RAW) {
|
||||
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
}
|
||||
|
||||
skb_cb->paddr = dma_map_single(dev, msdu->data, msdu->len,
|
||||
DMA_TO_DEVICE);
|
||||
@@ -537,16 +542,30 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
||||
flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
|
||||
/* pass through */
|
||||
case ATH10K_HW_TXRX_ETHERNET:
|
||||
frags = skb_cb->htt.txbuf->frags;
|
||||
if (ar->hw_params.continuous_frag_desc) {
|
||||
memset(&htt->frag_desc.vaddr[msdu_id], 0,
|
||||
sizeof(struct htt_msdu_ext_desc));
|
||||
frags = (struct htt_data_tx_desc_frag *)
|
||||
&htt->frag_desc.vaddr[msdu_id].frags;
|
||||
ext_desc = &htt->frag_desc.vaddr[msdu_id];
|
||||
frags[0].tword_addr.paddr_lo =
|
||||
__cpu_to_le32(skb_cb->paddr);
|
||||
frags[0].tword_addr.paddr_hi = 0;
|
||||
frags[0].tword_addr.len_16 = __cpu_to_le16(msdu->len);
|
||||
|
||||
frags[0].paddr = __cpu_to_le32(skb_cb->paddr);
|
||||
frags[0].len = __cpu_to_le32(msdu->len);
|
||||
frags[1].paddr = 0;
|
||||
frags[1].len = 0;
|
||||
frags_paddr = htt->frag_desc.paddr +
|
||||
(sizeof(struct htt_msdu_ext_desc) * msdu_id);
|
||||
} else {
|
||||
frags = skb_cb->htt.txbuf->frags;
|
||||
frags[0].dword_addr.paddr =
|
||||
__cpu_to_le32(skb_cb->paddr);
|
||||
frags[0].dword_addr.len = __cpu_to_le32(msdu->len);
|
||||
frags[1].dword_addr.paddr = 0;
|
||||
frags[1].dword_addr.len = 0;
|
||||
|
||||
frags_paddr = skb_cb->htt.txbuf_paddr;
|
||||
}
|
||||
flags0 |= SM(skb_cb->txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
|
||||
|
||||
frags_paddr = skb_cb->htt.txbuf_paddr;
|
||||
break;
|
||||
case ATH10K_HW_TXRX_MGMT:
|
||||
flags0 |= SM(ATH10K_HW_TXRX_MGMT,
|
||||
@@ -580,14 +599,20 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
||||
prefetch_len);
|
||||
skb_cb->htt.txbuf->htc_hdr.flags = 0;
|
||||
|
||||
if (skb_cb->htt.nohwcrypt)
|
||||
flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
|
||||
|
||||
if (!skb_cb->is_protected)
|
||||
flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
|
||||
|
||||
flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID);
|
||||
flags1 |= SM((u16)tid, HTT_DATA_TX_DESC_FLAGS1_EXT_TID);
|
||||
if (msdu->ip_summed == CHECKSUM_PARTIAL) {
|
||||
if (msdu->ip_summed == CHECKSUM_PARTIAL &&
|
||||
!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
|
||||
flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L3_OFFLOAD;
|
||||
flags1 |= HTT_DATA_TX_DESC_FLAGS1_CKSUM_L4_OFFLOAD;
|
||||
if (ar->hw_params.continuous_frag_desc)
|
||||
ext_desc->flags |= HTT_MSDU_CHECKSUM_ENABLE;
|
||||
}
|
||||
|
||||
/* Prevent firmware from sending up tx inspection requests. There's
|
||||
|
||||
@@ -217,14 +217,16 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
|
||||
#define QCA_REV_99X0(ar) ((ar)->hw_rev == ATH10K_HW_QCA99X0)
|
||||
|
||||
/* Known pecularities:
|
||||
* - current FW doesn't support raw rx mode (last tested v599)
|
||||
* - current FW dumps upon raw tx mode (last tested v599)
|
||||
* - raw appears in nwifi decap, raw and nwifi appear in ethernet decap
|
||||
* - raw have FCS, nwifi doesn't
|
||||
* - ethernet frames have 802.11 header decapped and parts (base hdr, cipher
|
||||
* param, llc/snap) are aligned to 4byte boundaries each */
|
||||
enum ath10k_hw_txrx_mode {
|
||||
ATH10K_HW_TXRX_RAW = 0,
|
||||
|
||||
/* Native Wifi decap mode is used to align IP frames to 4-byte
|
||||
* boundaries and avoid a very expensive re-alignment in mac80211.
|
||||
*/
|
||||
ATH10K_HW_TXRX_NATIVE_WIFI = 1,
|
||||
ATH10K_HW_TXRX_ETHERNET = 2,
|
||||
|
||||
@@ -286,10 +288,6 @@ enum ath10k_hw_rate_cck {
|
||||
#define TARGET_RX_TIMEOUT_LO_PRI 100
|
||||
#define TARGET_RX_TIMEOUT_HI_PRI 40
|
||||
|
||||
/* Native Wifi decap mode is used to align IP frames to 4-byte boundaries and
|
||||
* avoid a very expensive re-alignment in mac80211. */
|
||||
#define TARGET_RX_DECAP_MODE ATH10K_HW_TXRX_NATIVE_WIFI
|
||||
|
||||
#define TARGET_SCAN_MAX_PENDING_REQS 4
|
||||
#define TARGET_BMISS_OFFLOAD_MAX_VDEV 3
|
||||
#define TARGET_ROAM_OFFLOAD_MAX_VDEV 3
|
||||
@@ -324,7 +322,6 @@ enum ath10k_hw_rate_cck {
|
||||
#define TARGET_10X_RX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2))
|
||||
#define TARGET_10X_RX_TIMEOUT_LO_PRI 100
|
||||
#define TARGET_10X_RX_TIMEOUT_HI_PRI 40
|
||||
#define TARGET_10X_RX_DECAP_MODE ATH10K_HW_TXRX_NATIVE_WIFI
|
||||
#define TARGET_10X_SCAN_MAX_PENDING_REQS 4
|
||||
#define TARGET_10X_BMISS_OFFLOAD_MAX_VDEV 2
|
||||
#define TARGET_10X_ROAM_OFFLOAD_MAX_VDEV 2
|
||||
@@ -363,10 +360,7 @@ enum ath10k_hw_rate_cck {
|
||||
(TARGET_10_4_NUM_VDEVS))
|
||||
#define TARGET_10_4_ACTIVE_PEERS 0
|
||||
|
||||
/* TODO: increase qcache max client limit to 512 after
|
||||
* testing with 512 client.
|
||||
*/
|
||||
#define TARGET_10_4_NUM_QCACHE_PEERS_MAX 256
|
||||
#define TARGET_10_4_NUM_QCACHE_PEERS_MAX 512
|
||||
#define TARGET_10_4_QCACHE_ACTIVE_PEERS 50
|
||||
#define TARGET_10_4_NUM_OFFLOAD_PEERS 0
|
||||
#define TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS 0
|
||||
|
||||
@@ -197,6 +197,10 @@ static int ath10k_send_key(struct ath10k_vif *arvif,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
|
||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
|
||||
}
|
||||
|
||||
if (cmd == DISABLE_KEY) {
|
||||
arg.key_cipher = WMI_CIPHER_NONE;
|
||||
arg.key_data = NULL;
|
||||
@@ -218,6 +222,9 @@ static int ath10k_install_key(struct ath10k_vif *arvif,
|
||||
|
||||
reinit_completion(&ar->install_key_done);
|
||||
|
||||
if (arvif->nohwcrypt)
|
||||
return 1;
|
||||
|
||||
ret = ath10k_send_key(arvif, key, cmd, macaddr, flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -256,7 +263,7 @@ static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif,
|
||||
|
||||
ret = ath10k_install_key(arvif, arvif->wep_keys[i], SET_KEY,
|
||||
addr, flags);
|
||||
if (ret)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
flags = 0;
|
||||
@@ -264,7 +271,7 @@ static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif,
|
||||
|
||||
ret = ath10k_install_key(arvif, arvif->wep_keys[i], SET_KEY,
|
||||
addr, flags);
|
||||
if (ret)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
@@ -322,10 +329,10 @@ static int ath10k_clear_peer_keys(struct ath10k_vif *arvif,
|
||||
/* key flags are not required to delete the key */
|
||||
ret = ath10k_install_key(arvif, peer->keys[i],
|
||||
DISABLE_KEY, addr, flags);
|
||||
if (ret && first_errno == 0)
|
||||
if (ret < 0 && first_errno == 0)
|
||||
first_errno = ret;
|
||||
|
||||
if (ret)
|
||||
if (ret < 0)
|
||||
ath10k_warn(ar, "failed to remove peer wep key %d: %d\n",
|
||||
i, ret);
|
||||
|
||||
@@ -398,7 +405,7 @@ static int ath10k_clear_vdev_key(struct ath10k_vif *arvif,
|
||||
break;
|
||||
/* key flags are not required to delete the key */
|
||||
ret = ath10k_install_key(arvif, key, DISABLE_KEY, addr, flags);
|
||||
if (ret && first_errno == 0)
|
||||
if (ret < 0 && first_errno == 0)
|
||||
first_errno = ret;
|
||||
|
||||
if (ret)
|
||||
@@ -591,11 +598,19 @@ ath10k_mac_get_any_chandef_iter(struct ieee80211_hw *hw,
|
||||
static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr,
|
||||
enum wmi_peer_type peer_type)
|
||||
{
|
||||
struct ath10k_vif *arvif;
|
||||
int num_peers = 0;
|
||||
int ret;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
if (ar->num_peers >= ar->max_num_peers)
|
||||
num_peers = ar->num_peers;
|
||||
|
||||
/* Each vdev consumes a peer entry as well */
|
||||
list_for_each_entry(arvif, &ar->arvifs, list)
|
||||
num_peers++;
|
||||
|
||||
if (num_peers >= ar->max_num_peers)
|
||||
return -ENOBUFS;
|
||||
|
||||
ret = ath10k_wmi_peer_create(ar, vdev_id, addr, peer_type);
|
||||
@@ -671,20 +686,6 @@ static int ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value)
|
||||
return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, value);
|
||||
}
|
||||
|
||||
static int ath10k_mac_set_frag(struct ath10k_vif *arvif, u32 value)
|
||||
{
|
||||
struct ath10k *ar = arvif->ar;
|
||||
u32 vdev_param;
|
||||
|
||||
if (value != 0xFFFFFFFF)
|
||||
value = clamp_t(u32, arvif->ar->hw->wiphy->frag_threshold,
|
||||
ATH10K_FRAGMT_THRESHOLD_MIN,
|
||||
ATH10K_FRAGMT_THRESHOLD_MAX);
|
||||
|
||||
vdev_param = ar->wmi.vdev_param->fragmentation_threshold;
|
||||
return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, value);
|
||||
}
|
||||
|
||||
static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr)
|
||||
{
|
||||
int ret;
|
||||
@@ -836,7 +837,7 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
|
||||
static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
|
||||
{
|
||||
struct cfg80211_chan_def *chandef = NULL;
|
||||
struct ieee80211_channel *channel = chandef->chan;
|
||||
struct ieee80211_channel *channel = NULL;
|
||||
struct wmi_vdev_start_request_arg arg = {};
|
||||
int ret = 0;
|
||||
|
||||
@@ -2502,6 +2503,9 @@ static int ath10k_mac_vif_recalc_txbf(struct ath10k *ar,
|
||||
u32 param;
|
||||
u32 value;
|
||||
|
||||
if (ath10k_wmi_get_txbf_conf_scheme(ar) != WMI_TXBF_CONF_AFTER_ASSOC)
|
||||
return 0;
|
||||
|
||||
if (!(ar->vht_cap_info &
|
||||
(IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
||||
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE |
|
||||
@@ -3149,13 +3153,30 @@ ath10k_tx_h_get_txmode(struct ath10k *ar, struct ieee80211_vif *vif,
|
||||
* Some wmi-tlv firmwares for qca6174 have broken Tx key selection for
|
||||
* NativeWifi txmode - it selects AP key instead of peer key. It seems
|
||||
* to work with Ethernet txmode so use it.
|
||||
*
|
||||
* FIXME: Check if raw mode works with TDLS.
|
||||
*/
|
||||
if (ieee80211_is_data_present(fc) && sta && sta->tdls)
|
||||
return ATH10K_HW_TXRX_ETHERNET;
|
||||
|
||||
if (test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
|
||||
return ATH10K_HW_TXRX_RAW;
|
||||
|
||||
return ATH10K_HW_TXRX_NATIVE_WIFI;
|
||||
}
|
||||
|
||||
static bool ath10k_tx_h_use_hwcrypto(struct ieee80211_vif *vif,
|
||||
struct sk_buff *skb) {
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
const u32 mask = IEEE80211_TX_INTFL_DONT_ENCRYPT |
|
||||
IEEE80211_TX_CTL_INJECTED;
|
||||
if ((info->flags & mask) == mask)
|
||||
return false;
|
||||
if (vif)
|
||||
return !ath10k_vif_to_arvif(vif)->nohwcrypt;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* HTT Tx uses Native Wifi tx mode which expects 802.11 frames without QoS
|
||||
* Control in the header.
|
||||
*/
|
||||
@@ -3322,6 +3343,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
||||
int vdev_id;
|
||||
int ret;
|
||||
unsigned long time_left;
|
||||
bool tmp_peer_created = false;
|
||||
|
||||
/* FW requirement: We must create a peer before FW will send out
|
||||
* an offchannel frame. Otherwise the frame will be stuck and
|
||||
@@ -3359,6 +3381,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to create peer %pM on vdev %d: %d\n",
|
||||
peer_addr, vdev_id, ret);
|
||||
tmp_peer_created = (ret == 0);
|
||||
}
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
@@ -3374,7 +3397,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
||||
ath10k_warn(ar, "timed out waiting for offchannel skb %p\n",
|
||||
skb);
|
||||
|
||||
if (!peer) {
|
||||
if (!peer && tmp_peer_created) {
|
||||
ret = ath10k_peer_delete(ar, vdev_id, peer_addr);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to delete peer %pM on vdev %d: %d\n",
|
||||
@@ -3600,6 +3623,7 @@ static void ath10k_tx(struct ieee80211_hw *hw,
|
||||
ATH10K_SKB_CB(skb)->htt.is_offchan = false;
|
||||
ATH10K_SKB_CB(skb)->htt.freq = 0;
|
||||
ATH10K_SKB_CB(skb)->htt.tid = ath10k_tx_h_get_tid(hdr);
|
||||
ATH10K_SKB_CB(skb)->htt.nohwcrypt = !ath10k_tx_h_use_hwcrypto(vif, skb);
|
||||
ATH10K_SKB_CB(skb)->vdev_id = ath10k_tx_h_get_vdev_id(ar, vif);
|
||||
ATH10K_SKB_CB(skb)->txmode = ath10k_tx_h_get_txmode(ar, vif, sta, skb);
|
||||
ATH10K_SKB_CB(skb)->is_protected = ieee80211_has_protected(fc);
|
||||
@@ -3615,12 +3639,11 @@ static void ath10k_tx(struct ieee80211_hw *hw,
|
||||
ath10k_tx_h_8023(skb);
|
||||
break;
|
||||
case ATH10K_HW_TXRX_RAW:
|
||||
/* FIXME: Packet injection isn't implemented. It should be
|
||||
* doable with firmware 10.2 on qca988x.
|
||||
*/
|
||||
WARN_ON_ONCE(1);
|
||||
ieee80211_free_txskb(hw, skb);
|
||||
return;
|
||||
if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
|
||||
WARN_ON_ONCE(1);
|
||||
ieee80211_free_txskb(hw, skb);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
|
||||
@@ -4019,6 +4042,43 @@ static u32 get_nss_from_chainmask(u16 chain_mask)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ath10k_mac_set_txbf_conf(struct ath10k_vif *arvif)
|
||||
{
|
||||
u32 value = 0;
|
||||
struct ath10k *ar = arvif->ar;
|
||||
|
||||
if (ath10k_wmi_get_txbf_conf_scheme(ar) != WMI_TXBF_CONF_BEFORE_ASSOC)
|
||||
return 0;
|
||||
|
||||
if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
|
||||
IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE))
|
||||
value |= SM((ar->num_rf_chains - 1), WMI_TXBF_STS_CAP_OFFSET);
|
||||
|
||||
if (ar->vht_cap_info & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
|
||||
IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE))
|
||||
value |= SM((ar->num_rf_chains - 1), WMI_BF_SOUND_DIM_OFFSET);
|
||||
|
||||
if (!value)
|
||||
return 0;
|
||||
|
||||
if (ar->vht_cap_info & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE)
|
||||
value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFER;
|
||||
|
||||
if (ar->vht_cap_info & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)
|
||||
value |= (WMI_VDEV_PARAM_TXBF_MU_TX_BFER |
|
||||
WMI_VDEV_PARAM_TXBF_SU_TX_BFER);
|
||||
|
||||
if (ar->vht_cap_info & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE)
|
||||
value |= WMI_VDEV_PARAM_TXBF_SU_TX_BFEE;
|
||||
|
||||
if (ar->vht_cap_info & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)
|
||||
value |= (WMI_VDEV_PARAM_TXBF_MU_TX_BFEE |
|
||||
WMI_VDEV_PARAM_TXBF_SU_TX_BFEE);
|
||||
|
||||
return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
|
||||
ar->wmi.vdev_param->txbf, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE,
|
||||
@@ -4060,6 +4120,11 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
||||
sizeof(arvif->bitrate_mask.control[i].vht_mcs));
|
||||
}
|
||||
|
||||
if (ar->num_peers >= ar->max_num_peers) {
|
||||
ath10k_warn(ar, "refusing vdev creation due to insufficient peer entry resources in firmware\n");
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
if (ar->free_vdev_map == 0) {
|
||||
ath10k_warn(ar, "Free vdev map is empty, no more interfaces allowed.\n");
|
||||
ret = -EBUSY;
|
||||
@@ -4139,6 +4204,14 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags))
|
||||
arvif->nohwcrypt = true;
|
||||
|
||||
if (arvif->nohwcrypt &&
|
||||
!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
|
||||
ath10k_warn(ar, "cryptmode module param needed for sw crypto\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d bcnmode %s\n",
|
||||
arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
|
||||
@@ -4237,16 +4310,16 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
||||
}
|
||||
}
|
||||
|
||||
ret = ath10k_mac_set_rts(arvif, ar->hw->wiphy->rts_threshold);
|
||||
ret = ath10k_mac_set_txbf_conf(arvif);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set rts threshold for vdev %d: %d\n",
|
||||
ath10k_warn(ar, "failed to set txbf for vdev %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
goto err_peer_delete;
|
||||
}
|
||||
|
||||
ret = ath10k_mac_set_frag(arvif, ar->hw->wiphy->frag_threshold);
|
||||
ret = ath10k_mac_set_rts(arvif, ar->hw->wiphy->rts_threshold);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set frag threshold for vdev %d: %d\n",
|
||||
ath10k_warn(ar, "failed to set rts threshold for vdev %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
goto err_peer_delete;
|
||||
}
|
||||
@@ -4728,6 +4801,9 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
|
||||
return 1;
|
||||
|
||||
if (arvif->nohwcrypt)
|
||||
return 1;
|
||||
|
||||
if (key->keyidx > WMI_MAX_KEY_INDEX)
|
||||
return -ENOSPC;
|
||||
|
||||
@@ -4797,6 +4873,7 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
|
||||
ret = ath10k_install_key(arvif, key, cmd, peer_addr, flags);
|
||||
if (ret) {
|
||||
WARN_ON(ret > 0);
|
||||
ath10k_warn(ar, "failed to install key for vdev %i peer %pM: %d\n",
|
||||
arvif->vdev_id, peer_addr, ret);
|
||||
goto exit;
|
||||
@@ -4812,13 +4889,16 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
|
||||
ret = ath10k_install_key(arvif, key, cmd, peer_addr, flags2);
|
||||
if (ret) {
|
||||
WARN_ON(ret > 0);
|
||||
ath10k_warn(ar, "failed to install (ucast) key for vdev %i peer %pM: %d\n",
|
||||
arvif->vdev_id, peer_addr, ret);
|
||||
ret2 = ath10k_install_key(arvif, key, DISABLE_KEY,
|
||||
peer_addr, flags);
|
||||
if (ret2)
|
||||
if (ret2) {
|
||||
WARN_ON(ret2 > 0);
|
||||
ath10k_warn(ar, "failed to disable (mcast) key for vdev %i peer %pM: %d\n",
|
||||
arvif->vdev_id, peer_addr, ret2);
|
||||
}
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
@@ -5545,6 +5625,21 @@ static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
|
||||
{
|
||||
/* Even though there's a WMI enum for fragmentation threshold no known
|
||||
* firmware actually implements it. Moreover it is not possible to rely
|
||||
* frame fragmentation to mac80211 because firmware clears the "more
|
||||
* fragments" bit in frame control making it impossible for remote
|
||||
* devices to reassemble frames.
|
||||
*
|
||||
* Hence implement a dummy callback just to say fragmentation isn't
|
||||
* supported. This effectively prevents mac80211 from doing frame
|
||||
* fragmentation in software.
|
||||
*/
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
u32 queues, bool drop)
|
||||
{
|
||||
@@ -6387,6 +6482,7 @@ static const struct ieee80211_ops ath10k_ops = {
|
||||
.remain_on_channel = ath10k_remain_on_channel,
|
||||
.cancel_remain_on_channel = ath10k_cancel_remain_on_channel,
|
||||
.set_rts_threshold = ath10k_set_rts_threshold,
|
||||
.set_frag_threshold = ath10k_mac_op_set_frag_threshold,
|
||||
.flush = ath10k_flush,
|
||||
.tx_last_beacon = ath10k_tx_last_beacon,
|
||||
.set_antenna = ath10k_set_antenna,
|
||||
@@ -6892,7 +6988,6 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
ieee80211_hw_set(ar->hw, HAS_RATE_CONTROL);
|
||||
ieee80211_hw_set(ar->hw, AP_LINK_PS);
|
||||
ieee80211_hw_set(ar->hw, SPECTRUM_MGMT);
|
||||
ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
|
||||
ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT);
|
||||
ieee80211_hw_set(ar->hw, CONNECTION_MONITOR);
|
||||
ieee80211_hw_set(ar->hw, SUPPORTS_PER_STA_GTK);
|
||||
@@ -6900,6 +6995,9 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
ieee80211_hw_set(ar->hw, CHANCTX_STA_CSA);
|
||||
ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
|
||||
|
||||
if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
|
||||
ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
|
||||
|
||||
ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS;
|
||||
ar->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
|
||||
|
||||
@@ -7003,7 +7101,8 @@ int ath10k_mac_register(struct ath10k *ar)
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
ar->hw->netdev_features = NETIF_F_HW_CSUM;
|
||||
if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
|
||||
ar->hw->netdev_features = NETIF_F_HW_CSUM;
|
||||
|
||||
if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
|
||||
/* Init ath dfs pattern detector */
|
||||
|
||||
@@ -64,6 +64,7 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)");
|
||||
static const struct pci_device_id ath10k_pci_id_table[] = {
|
||||
{ PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA6174_2_1_DEVICE_ID) }, /* PCI-E QCA6174 V2.1 */
|
||||
{ PCI_VDEVICE(ATHEROS, QCA99X0_2_0_DEVICE_ID) }, /* PCI-E QCA99X0 V2 */
|
||||
{0}
|
||||
};
|
||||
|
||||
@@ -78,6 +79,7 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = {
|
||||
{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_0_CHIP_ID_REV },
|
||||
{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_1_CHIP_ID_REV },
|
||||
{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_2_CHIP_ID_REV },
|
||||
{ QCA99X0_2_0_DEVICE_ID, QCA99X0_HW_2_0_CHIP_ID_REV },
|
||||
};
|
||||
|
||||
static void ath10k_pci_buffer_cleanup(struct ath10k *ar);
|
||||
@@ -2761,7 +2763,6 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar)
|
||||
|
||||
static int ath10k_pci_cold_reset(struct ath10k *ar)
|
||||
{
|
||||
int i;
|
||||
u32 val;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n");
|
||||
@@ -2777,23 +2778,18 @@ static int ath10k_pci_cold_reset(struct ath10k *ar)
|
||||
val |= 1;
|
||||
ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val);
|
||||
|
||||
for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) {
|
||||
if (ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) &
|
||||
RTC_STATE_COLD_RESET_MASK)
|
||||
break;
|
||||
msleep(1);
|
||||
}
|
||||
/* After writing into SOC_GLOBAL_RESET to put device into
|
||||
* reset and pulling out of reset pcie may not be stable
|
||||
* for any immediate pcie register access and cause bus error,
|
||||
* add delay before any pcie access request to fix this issue.
|
||||
*/
|
||||
msleep(20);
|
||||
|
||||
/* Pull Target, including PCIe, out of RESET. */
|
||||
val &= ~1;
|
||||
ath10k_pci_reg_write32(ar, SOC_GLOBAL_RESET_ADDRESS, val);
|
||||
|
||||
for (i = 0; i < ATH_PCI_RESET_WAIT_MAX; i++) {
|
||||
if (!(ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS) &
|
||||
RTC_STATE_COLD_RESET_MASK))
|
||||
break;
|
||||
msleep(1);
|
||||
}
|
||||
msleep(20);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset complete\n");
|
||||
|
||||
|
||||
@@ -422,6 +422,12 @@ struct rx_mpdu_end {
|
||||
#define RX_MSDU_START_INFO1_IP_FRAG (1 << 14)
|
||||
#define RX_MSDU_START_INFO1_TCP_ONLY_ACK (1 << 15)
|
||||
|
||||
#define RX_MSDU_START_INFO2_DA_IDX_MASK 0x000007ff
|
||||
#define RX_MSDU_START_INFO2_DA_IDX_LSB 0
|
||||
#define RX_MSDU_START_INFO2_IP_PROTO_FIELD_MASK 0x00ff0000
|
||||
#define RX_MSDU_START_INFO2_IP_PROTO_FIELD_LSB 16
|
||||
#define RX_MSDU_START_INFO2_DA_BCAST_MCAST BIT(11)
|
||||
|
||||
/* The decapped header (rx_hdr_status) contains the following:
|
||||
* a) 802.11 header
|
||||
* [padding to 4 bytes]
|
||||
@@ -449,12 +455,23 @@ enum rx_msdu_decap_format {
|
||||
RX_MSDU_DECAP_8023_SNAP_LLC = 3
|
||||
};
|
||||
|
||||
struct rx_msdu_start {
|
||||
struct rx_msdu_start_common {
|
||||
__le32 info0; /* %RX_MSDU_START_INFO0_ */
|
||||
__le32 flow_id_crc;
|
||||
__le32 info1; /* %RX_MSDU_START_INFO1_ */
|
||||
} __packed;
|
||||
|
||||
struct rx_msdu_start_qca99x0 {
|
||||
__le32 info2; /* %RX_MSDU_START_INFO2_ */
|
||||
} __packed;
|
||||
|
||||
struct rx_msdu_start {
|
||||
struct rx_msdu_start_common common;
|
||||
union {
|
||||
struct rx_msdu_start_qca99x0 qca99x0;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
* msdu_length
|
||||
* MSDU length in bytes after decapsulation. This field is
|
||||
@@ -540,7 +557,7 @@ struct rx_msdu_start {
|
||||
#define RX_MSDU_END_INFO0_PRE_DELIM_ERR (1 << 30)
|
||||
#define RX_MSDU_END_INFO0_RESERVED_3B (1 << 31)
|
||||
|
||||
struct rx_msdu_end {
|
||||
struct rx_msdu_end_common {
|
||||
__le16 ip_hdr_cksum;
|
||||
__le16 tcp_hdr_cksum;
|
||||
u8 key_id_octet;
|
||||
@@ -549,6 +566,36 @@ struct rx_msdu_end {
|
||||
__le32 info0;
|
||||
} __packed;
|
||||
|
||||
#define RX_MSDU_END_INFO1_TCP_FLAG_MASK 0x000001ff
|
||||
#define RX_MSDU_END_INFO1_TCP_FLAG_LSB 0
|
||||
#define RX_MSDU_END_INFO1_L3_HDR_PAD_MASK 0x00001c00
|
||||
#define RX_MSDU_END_INFO1_L3_HDR_PAD_LSB 10
|
||||
#define RX_MSDU_END_INFO1_WINDOW_SIZE_MASK 0xffff0000
|
||||
#define RX_MSDU_END_INFO1_WINDOW_SIZE_LSB 16
|
||||
#define RX_MSDU_END_INFO1_IRO_ELIGIBLE BIT(9)
|
||||
|
||||
#define RX_MSDU_END_INFO2_DA_OFFSET_MASK 0x0000003f
|
||||
#define RX_MSDU_END_INFO2_DA_OFFSET_LSB 0
|
||||
#define RX_MSDU_END_INFO2_SA_OFFSET_MASK 0x00000fc0
|
||||
#define RX_MSDU_END_INFO2_SA_OFFSET_LSB 6
|
||||
#define RX_MSDU_END_INFO2_TYPE_OFFSET_MASK 0x0003f000
|
||||
#define RX_MSDU_END_INFO2_TYPE_OFFSET_LSB 12
|
||||
|
||||
struct rx_msdu_end_qca99x0 {
|
||||
__le32 ipv6_crc;
|
||||
__le32 tcp_seq_no;
|
||||
__le32 tcp_ack_no;
|
||||
__le32 info1;
|
||||
__le32 info2;
|
||||
} __packed;
|
||||
|
||||
struct rx_msdu_end {
|
||||
struct rx_msdu_end_common common;
|
||||
union {
|
||||
struct rx_msdu_end_qca99x0 qca99x0;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
/*
|
||||
*ip_hdr_chksum
|
||||
* This can include the IP header checksum or the pseudo header
|
||||
@@ -870,7 +917,11 @@ struct rx_ppdu_start {
|
||||
#define RX_PPDU_END_INFO0_FLAGS_TX_HT_VHT_ACK (1 << 24)
|
||||
#define RX_PPDU_END_INFO0_BB_CAPTURED_CHANNEL (1 << 25)
|
||||
|
||||
#define RX_PPDU_END_INFO1_PPDU_DONE (1 << 15)
|
||||
#define RX_PPDU_END_INFO1_PEER_IDX_MASK 0x1ffc
|
||||
#define RX_PPDU_END_INFO1_PEER_IDX_LSB 2
|
||||
#define RX_PPDU_END_INFO1_BB_DATA BIT(0)
|
||||
#define RX_PPDU_END_INFO1_PEER_IDX_VALID BIT(1)
|
||||
#define RX_PPDU_END_INFO1_PPDU_DONE BIT(15)
|
||||
|
||||
struct rx_ppdu_end_common {
|
||||
__le32 evm_p0;
|
||||
@@ -891,13 +942,13 @@ struct rx_ppdu_end_common {
|
||||
__le32 evm_p15;
|
||||
__le32 tsf_timestamp;
|
||||
__le32 wb_timestamp;
|
||||
} __packed;
|
||||
|
||||
struct rx_ppdu_end_qca988x {
|
||||
u8 locationing_timestamp;
|
||||
u8 phy_err_code;
|
||||
__le16 flags; /* %RX_PPDU_END_FLAGS_ */
|
||||
__le32 info0; /* %RX_PPDU_END_INFO0_ */
|
||||
} __packed;
|
||||
|
||||
struct rx_ppdu_end_qca988x {
|
||||
__le16 bb_length;
|
||||
__le16 info1; /* %RX_PPDU_END_INFO1_ */
|
||||
} __packed;
|
||||
@@ -909,16 +960,126 @@ struct rx_ppdu_end_qca988x {
|
||||
#define RX_PPDU_END_RTT_NORMAL_MODE BIT(31)
|
||||
|
||||
struct rx_ppdu_end_qca6174 {
|
||||
u8 locationing_timestamp;
|
||||
u8 phy_err_code;
|
||||
__le16 flags; /* %RX_PPDU_END_FLAGS_ */
|
||||
__le32 info0; /* %RX_PPDU_END_INFO0_ */
|
||||
__le32 rtt; /* %RX_PPDU_END_RTT_ */
|
||||
__le16 bb_length;
|
||||
__le16 info1; /* %RX_PPDU_END_INFO1_ */
|
||||
} __packed;
|
||||
|
||||
#define RX_PKT_END_INFO0_RX_SUCCESS BIT(0)
|
||||
#define RX_PKT_END_INFO0_ERR_TX_INTERRUPT_RX BIT(3)
|
||||
#define RX_PKT_END_INFO0_ERR_OFDM_POWER_DROP BIT(4)
|
||||
#define RX_PKT_END_INFO0_ERR_OFDM_RESTART BIT(5)
|
||||
#define RX_PKT_END_INFO0_ERR_CCK_POWER_DROP BIT(6)
|
||||
#define RX_PKT_END_INFO0_ERR_CCK_RESTART BIT(7)
|
||||
|
||||
#define RX_LOCATION_INFO_RTT_CORR_VAL_MASK 0x0001ffff
|
||||
#define RX_LOCATION_INFO_RTT_CORR_VAL_LSB 0
|
||||
#define RX_LOCATION_INFO_FAC_STATUS_MASK 0x000c0000
|
||||
#define RX_LOCATION_INFO_FAC_STATUS_LSB 18
|
||||
#define RX_LOCATION_INFO_PKT_BW_MASK 0x00700000
|
||||
#define RX_LOCATION_INFO_PKT_BW_LSB 20
|
||||
#define RX_LOCATION_INFO_RTT_TX_FRAME_PHASE_MASK 0x01800000
|
||||
#define RX_LOCATION_INFO_RTT_TX_FRAME_PHASE_LSB 23
|
||||
#define RX_LOCATION_INFO_CIR_STATUS BIT(17)
|
||||
#define RX_LOCATION_INFO_RTT_MAC_PHY_PHASE BIT(25)
|
||||
#define RX_LOCATION_INFO_RTT_TX_DATA_START_X BIT(26)
|
||||
#define RX_LOCATION_INFO_HW_IFFT_MODE BIT(30)
|
||||
#define RX_LOCATION_INFO_RX_LOCATION_VALID BIT(31)
|
||||
|
||||
struct rx_pkt_end {
|
||||
__le32 info0; /* %RX_PKT_END_INFO0_ */
|
||||
__le32 phy_timestamp_1;
|
||||
__le32 phy_timestamp_2;
|
||||
__le32 rx_location_info; /* %RX_LOCATION_INFO_ */
|
||||
} __packed;
|
||||
|
||||
enum rx_phy_ppdu_end_info0 {
|
||||
RX_PHY_PPDU_END_INFO0_ERR_RADAR = BIT(2),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_RX_ABORT = BIT(3),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_RX_NAP = BIT(4),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_OFDM_TIMING = BIT(5),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_OFDM_PARITY = BIT(6),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_OFDM_RATE = BIT(7),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_OFDM_LENGTH = BIT(8),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_OFDM_RESTART = BIT(9),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_OFDM_SERVICE = BIT(10),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_OFDM_POWER_DROP = BIT(11),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_CCK_BLOCKER = BIT(12),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_CCK_TIMING = BIT(13),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_CCK_HEADER_CRC = BIT(14),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_CCK_RATE = BIT(15),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_CCK_LENGTH = BIT(16),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_CCK_RESTART = BIT(17),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_CCK_SERVICE = BIT(18),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_CCK_POWER_DROP = BIT(19),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_HT_CRC = BIT(20),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_HT_LENGTH = BIT(21),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_HT_RATE = BIT(22),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_HT_ZLF = BIT(23),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_FALSE_RADAR_EXT = BIT(24),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_GREEN_FIELD = BIT(25),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_SPECTRAL_SCAN = BIT(26),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_RX_DYN_BW = BIT(27),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_LEG_HT_MISMATCH = BIT(28),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_VHT_CRC = BIT(29),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_VHT_SIGA = BIT(30),
|
||||
RX_PHY_PPDU_END_INFO0_ERR_VHT_LSIG = BIT(31),
|
||||
};
|
||||
|
||||
enum rx_phy_ppdu_end_info1 {
|
||||
RX_PHY_PPDU_END_INFO1_ERR_VHT_NDP = BIT(0),
|
||||
RX_PHY_PPDU_END_INFO1_ERR_VHT_NSYM = BIT(1),
|
||||
RX_PHY_PPDU_END_INFO1_ERR_VHT_RX_EXT_SYM = BIT(2),
|
||||
RX_PHY_PPDU_END_INFO1_ERR_VHT_RX_SKIP_ID0 = BIT(3),
|
||||
RX_PHY_PPDU_END_INFO1_ERR_VHT_RX_SKIP_ID1_62 = BIT(4),
|
||||
RX_PHY_PPDU_END_INFO1_ERR_VHT_RX_SKIP_ID63 = BIT(5),
|
||||
RX_PHY_PPDU_END_INFO1_ERR_OFDM_LDPC_DECODER = BIT(6),
|
||||
RX_PHY_PPDU_END_INFO1_ERR_DEFER_NAP = BIT(7),
|
||||
RX_PHY_PPDU_END_INFO1_ERR_FDOMAIN_TIMEOUT = BIT(8),
|
||||
RX_PHY_PPDU_END_INFO1_ERR_LSIG_REL_CHECK = BIT(9),
|
||||
RX_PHY_PPDU_END_INFO1_ERR_BT_COLLISION = BIT(10),
|
||||
RX_PHY_PPDU_END_INFO1_ERR_MU_FEEDBACK = BIT(11),
|
||||
RX_PHY_PPDU_END_INFO1_ERR_TX_INTERRUPT_RX = BIT(12),
|
||||
RX_PHY_PPDU_END_INFO1_ERR_RX_CBF = BIT(13),
|
||||
};
|
||||
|
||||
struct rx_phy_ppdu_end {
|
||||
__le32 info0; /* %RX_PHY_PPDU_END_INFO0_ */
|
||||
__le32 info1; /* %RX_PHY_PPDU_END_INFO1_ */
|
||||
} __packed;
|
||||
|
||||
#define RX_PPDU_END_RX_TIMING_OFFSET_MASK 0x00000fff
|
||||
#define RX_PPDU_END_RX_TIMING_OFFSET_LSB 0
|
||||
|
||||
#define RX_PPDU_END_RX_INFO_RX_ANTENNA_MASK 0x00ffffff
|
||||
#define RX_PPDU_END_RX_INFO_RX_ANTENNA_LSB 0
|
||||
#define RX_PPDU_END_RX_INFO_TX_HT_VHT_ACK BIT(24)
|
||||
#define RX_PPDU_END_RX_INFO_RX_PKT_END_VALID BIT(25)
|
||||
#define RX_PPDU_END_RX_INFO_RX_PHY_PPDU_END_VALID BIT(26)
|
||||
#define RX_PPDU_END_RX_INFO_RX_TIMING_OFFSET_VALID BIT(27)
|
||||
#define RX_PPDU_END_RX_INFO_BB_CAPTURED_CHANNEL BIT(28)
|
||||
#define RX_PPDU_END_RX_INFO_UNSUPPORTED_MU_NC BIT(29)
|
||||
#define RX_PPDU_END_RX_INFO_OTP_TXBF_DISABLE BIT(30)
|
||||
|
||||
struct rx_ppdu_end_qca99x0 {
|
||||
struct rx_pkt_end rx_pkt_end;
|
||||
struct rx_phy_ppdu_end rx_phy_ppdu_end;
|
||||
__le32 rx_timing_offset; /* %RX_PPDU_END_RX_TIMING_OFFSET_ */
|
||||
__le32 rx_info; /* %RX_PPDU_END_RX_INFO_ */
|
||||
__le16 bb_length;
|
||||
__le16 info1; /* %RX_PPDU_END_INFO1_ */
|
||||
} __packed;
|
||||
|
||||
struct rx_ppdu_end {
|
||||
struct rx_ppdu_end_common common;
|
||||
union {
|
||||
struct rx_ppdu_end_qca988x qca988x;
|
||||
struct rx_ppdu_end_qca6174 qca6174;
|
||||
struct rx_ppdu_end_qca99x0 qca99x0;
|
||||
} __packed;
|
||||
} __packed;
|
||||
|
||||
|
||||
@@ -53,8 +53,6 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
struct ath10k_skb_cb *skb_cb;
|
||||
struct sk_buff *msdu;
|
||||
|
||||
lockdep_assert_held(&htt->tx_lock);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT,
|
||||
"htt tx completion msdu_id %u discard %d no_ack %d success %d\n",
|
||||
tx_done->msdu_id, !!tx_done->discard,
|
||||
@@ -66,12 +64,19 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_bh(&htt->tx_lock);
|
||||
msdu = idr_find(&htt->pending_tx, tx_done->msdu_id);
|
||||
if (!msdu) {
|
||||
ath10k_warn(ar, "received tx completion for invalid msdu_id: %d\n",
|
||||
tx_done->msdu_id);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
return;
|
||||
}
|
||||
ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
|
||||
__ath10k_htt_tx_dec_pending(htt);
|
||||
if (htt->num_pending_tx == 0)
|
||||
wake_up(&htt->empty_tx_wq);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
|
||||
skb_cb = ATH10K_SKB_CB(msdu);
|
||||
|
||||
@@ -90,7 +95,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
|
||||
if (tx_done->discard) {
|
||||
ieee80211_free_txskb(htt->ar->hw, msdu);
|
||||
goto exit;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
|
||||
@@ -104,12 +109,6 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
|
||||
ieee80211_tx_status(htt->ar->hw, msdu);
|
||||
/* we do not own the msdu anymore */
|
||||
|
||||
exit:
|
||||
ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
|
||||
__ath10k_htt_tx_dec_pending(htt);
|
||||
if (htt->num_pending_tx == 0)
|
||||
wake_up(&htt->empty_tx_wq);
|
||||
}
|
||||
|
||||
struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
|
||||
|
||||
@@ -49,6 +49,7 @@ struct wmi_ops {
|
||||
struct wmi_roam_ev_arg *arg);
|
||||
int (*pull_wow_event)(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_wow_ev_arg *arg);
|
||||
enum wmi_txbf_conf (*get_txbf_conf_scheme)(struct ath10k *ar);
|
||||
|
||||
struct sk_buff *(*gen_pdev_suspend)(struct ath10k *ar, u32 suspend_opt);
|
||||
struct sk_buff *(*gen_pdev_resume)(struct ath10k *ar);
|
||||
@@ -319,6 +320,15 @@ ath10k_wmi_pull_wow_event(struct ath10k *ar, struct sk_buff *skb,
|
||||
return ar->wmi.ops->pull_wow_event(ar, skb, arg);
|
||||
}
|
||||
|
||||
static inline enum wmi_txbf_conf
|
||||
ath10k_wmi_get_txbf_conf_scheme(struct ath10k *ar)
|
||||
{
|
||||
if (!ar->wmi.ops->get_txbf_conf_scheme)
|
||||
return WMI_TXBF_CONF_UNSUPPORTED;
|
||||
|
||||
return ar->wmi.ops->get_txbf_conf_scheme(ar);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
|
||||
{
|
||||
|
||||
@@ -519,7 +519,7 @@ static void ath10k_wmi_tlv_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
break;
|
||||
case WMI_TLV_SERVICE_READY_EVENTID:
|
||||
ath10k_wmi_event_service_ready(ar, skb);
|
||||
break;
|
||||
return;
|
||||
case WMI_TLV_READY_EVENTID:
|
||||
ath10k_wmi_event_ready(ar, skb);
|
||||
break;
|
||||
@@ -1279,6 +1279,11 @@ ath10k_wmi_tlv_op_gen_pdev_set_rd(struct ath10k *ar,
|
||||
return skb;
|
||||
}
|
||||
|
||||
static enum wmi_txbf_conf ath10k_wmi_tlv_txbf_conf_scheme(struct ath10k *ar)
|
||||
{
|
||||
return WMI_TXBF_CONF_AFTER_ASSOC;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_tlv_op_gen_pdev_set_param(struct ath10k *ar, u32 param_id,
|
||||
u32 param_value)
|
||||
@@ -1373,7 +1378,7 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar)
|
||||
cfg->rx_timeout_pri[1] = __cpu_to_le32(0x64);
|
||||
cfg->rx_timeout_pri[2] = __cpu_to_le32(0x64);
|
||||
cfg->rx_timeout_pri[3] = __cpu_to_le32(0x28);
|
||||
cfg->rx_decap_mode = __cpu_to_le32(1);
|
||||
cfg->rx_decap_mode = __cpu_to_le32(ar->wmi.rx_decap_mode);
|
||||
cfg->scan_max_pending_reqs = __cpu_to_le32(4);
|
||||
cfg->bmiss_offload_max_vdev = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
|
||||
cfg->roam_offload_max_vdev = __cpu_to_le32(TARGET_TLV_NUM_VDEVS);
|
||||
@@ -3408,6 +3413,7 @@ static const struct wmi_ops wmi_tlv_ops = {
|
||||
.pull_fw_stats = ath10k_wmi_tlv_op_pull_fw_stats,
|
||||
.pull_roam_ev = ath10k_wmi_tlv_op_pull_roam_ev,
|
||||
.pull_wow_event = ath10k_wmi_tlv_op_pull_wow_ev,
|
||||
.get_txbf_conf_scheme = ath10k_wmi_tlv_txbf_conf_scheme,
|
||||
|
||||
.gen_pdev_suspend = ath10k_wmi_tlv_op_gen_pdev_suspend,
|
||||
.gen_pdev_resume = ath10k_wmi_tlv_op_gen_pdev_resume,
|
||||
|
||||
@@ -3122,6 +3122,11 @@ static int ath10k_wmi_10_4_op_pull_swba_ev(struct ath10k *ar,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum wmi_txbf_conf ath10k_wmi_10_4_txbf_conf_scheme(struct ath10k *ar)
|
||||
{
|
||||
return WMI_TXBF_CONF_BEFORE_ASSOC;
|
||||
}
|
||||
|
||||
void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct wmi_swba_ev_arg arg = {};
|
||||
@@ -3498,7 +3503,7 @@ void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
|
||||
fftr, fftr_len,
|
||||
tsf);
|
||||
if (res < 0) {
|
||||
ath10k_warn(ar, "failed to process fft report: %d\n",
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "failed to process fft report: %d\n",
|
||||
res);
|
||||
return;
|
||||
}
|
||||
@@ -3789,7 +3794,7 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
|
||||
ar->wmi.mem_chunks[idx].vaddr = dma_alloc_coherent(ar->dev,
|
||||
pool_size,
|
||||
&paddr,
|
||||
GFP_ATOMIC);
|
||||
GFP_KERNEL);
|
||||
if (!ar->wmi.mem_chunks[idx].vaddr) {
|
||||
ath10k_warn(ar, "failed to allocate memory chunk\n");
|
||||
return -ENOMEM;
|
||||
@@ -3878,12 +3883,19 @@ ath10k_wmi_10x_op_pull_svc_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb)
|
||||
static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
|
||||
{
|
||||
struct ath10k *ar = container_of(work, struct ath10k, svc_rdy_work);
|
||||
struct sk_buff *skb = ar->svc_rdy_skb;
|
||||
struct wmi_svc_rdy_ev_arg arg = {};
|
||||
u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
|
||||
int ret;
|
||||
|
||||
if (!skb) {
|
||||
ath10k_warn(ar, "invalid service ready event skb\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = ath10k_wmi_pull_svc_rdy(ar, skb, &arg);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to parse service ready: %d\n", ret);
|
||||
@@ -4003,9 +4015,17 @@ void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb)
|
||||
__le32_to_cpu(arg.eeprom_rd),
|
||||
__le32_to_cpu(arg.num_mem_reqs));
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
ar->svc_rdy_skb = NULL;
|
||||
complete(&ar->wmi.service_ready);
|
||||
}
|
||||
|
||||
void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
ar->svc_rdy_skb = skb;
|
||||
queue_work(ar->workqueue_aux, &ar->svc_rdy_work);
|
||||
}
|
||||
|
||||
static int ath10k_wmi_op_pull_rdy_ev(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct wmi_rdy_ev_arg *arg)
|
||||
{
|
||||
@@ -4177,7 +4197,7 @@ static void ath10k_wmi_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
break;
|
||||
case WMI_SERVICE_READY_EVENTID:
|
||||
ath10k_wmi_event_service_ready(ar, skb);
|
||||
break;
|
||||
return;
|
||||
case WMI_READY_EVENTID:
|
||||
ath10k_wmi_event_ready(ar, skb);
|
||||
break;
|
||||
@@ -4298,7 +4318,7 @@ static void ath10k_wmi_10_1_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
break;
|
||||
case WMI_10X_SERVICE_READY_EVENTID:
|
||||
ath10k_wmi_event_service_ready(ar, skb);
|
||||
break;
|
||||
return;
|
||||
case WMI_10X_READY_EVENTID:
|
||||
ath10k_wmi_event_ready(ar, skb);
|
||||
break;
|
||||
@@ -4409,7 +4429,7 @@ static void ath10k_wmi_10_2_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
break;
|
||||
case WMI_10_2_SERVICE_READY_EVENTID:
|
||||
ath10k_wmi_event_service_ready(ar, skb);
|
||||
break;
|
||||
return;
|
||||
case WMI_10_2_READY_EVENTID:
|
||||
ath10k_wmi_event_ready(ar, skb);
|
||||
break;
|
||||
@@ -4461,7 +4481,7 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
||||
break;
|
||||
case WMI_10_4_SERVICE_READY_EVENTID:
|
||||
ath10k_wmi_event_service_ready(ar, skb);
|
||||
break;
|
||||
return;
|
||||
case WMI_10_4_SCAN_EVENTID:
|
||||
ath10k_wmi_event_scan(ar, skb);
|
||||
break;
|
||||
@@ -4688,8 +4708,7 @@ static struct sk_buff *ath10k_wmi_op_gen_init(struct ath10k *ar)
|
||||
config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_RX_TIMEOUT_LO_PRI);
|
||||
config.rx_timeout_pri_be = __cpu_to_le32(TARGET_RX_TIMEOUT_LO_PRI);
|
||||
config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_RX_TIMEOUT_HI_PRI);
|
||||
config.rx_decap_mode = __cpu_to_le32(TARGET_RX_DECAP_MODE);
|
||||
|
||||
config.rx_decap_mode = __cpu_to_le32(ar->wmi.rx_decap_mode);
|
||||
config.scan_max_pending_reqs =
|
||||
__cpu_to_le32(TARGET_SCAN_MAX_PENDING_REQS);
|
||||
|
||||
@@ -4757,8 +4776,7 @@ static struct sk_buff *ath10k_wmi_10_1_op_gen_init(struct ath10k *ar)
|
||||
config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
|
||||
config.rx_timeout_pri_be = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
|
||||
config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_HI_PRI);
|
||||
config.rx_decap_mode = __cpu_to_le32(TARGET_10X_RX_DECAP_MODE);
|
||||
|
||||
config.rx_decap_mode = __cpu_to_le32(ar->wmi.rx_decap_mode);
|
||||
config.scan_max_pending_reqs =
|
||||
__cpu_to_le32(TARGET_10X_SCAN_MAX_PENDING_REQS);
|
||||
|
||||
@@ -4823,7 +4841,7 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
|
||||
config.rx_timeout_pri_vi = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
|
||||
config.rx_timeout_pri_be = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_LO_PRI);
|
||||
config.rx_timeout_pri_bk = __cpu_to_le32(TARGET_10X_RX_TIMEOUT_HI_PRI);
|
||||
config.rx_decap_mode = __cpu_to_le32(TARGET_10X_RX_DECAP_MODE);
|
||||
config.rx_decap_mode = __cpu_to_le32(ar->wmi.rx_decap_mode);
|
||||
|
||||
config.scan_max_pending_reqs =
|
||||
__cpu_to_le32(TARGET_10X_SCAN_MAX_PENDING_REQS);
|
||||
@@ -6431,6 +6449,7 @@ static const struct wmi_ops wmi_10_4_ops = {
|
||||
.pull_swba = ath10k_wmi_10_4_op_pull_swba_ev,
|
||||
.pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev,
|
||||
.pull_rdy = ath10k_wmi_op_pull_rdy_ev,
|
||||
.get_txbf_conf_scheme = ath10k_wmi_10_4_txbf_conf_scheme,
|
||||
|
||||
.gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend,
|
||||
.gen_pdev_resume = ath10k_wmi_op_gen_pdev_resume,
|
||||
@@ -6514,6 +6533,8 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
||||
init_completion(&ar->wmi.service_ready);
|
||||
init_completion(&ar->wmi.unified_ready);
|
||||
|
||||
INIT_WORK(&ar->svc_rdy_work, ath10k_wmi_event_service_ready_work);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -6521,6 +6542,11 @@ void ath10k_wmi_detach(struct ath10k *ar)
|
||||
{
|
||||
int i;
|
||||
|
||||
cancel_work_sync(&ar->svc_rdy_work);
|
||||
|
||||
if (ar->svc_rdy_skb)
|
||||
dev_kfree_skb(ar->svc_rdy_skb);
|
||||
|
||||
/* free the host memory chunks requested by firmware */
|
||||
for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
|
||||
dma_free_coherent(ar->dev,
|
||||
|
||||
@@ -4628,6 +4628,11 @@ enum wmi_10_4_vdev_param {
|
||||
#define WMI_VDEV_PARAM_TXBF_SU_TX_BFER BIT(2)
|
||||
#define WMI_VDEV_PARAM_TXBF_MU_TX_BFER BIT(3)
|
||||
|
||||
#define WMI_TXBF_STS_CAP_OFFSET_LSB 4
|
||||
#define WMI_TXBF_STS_CAP_OFFSET_MASK 0xf0
|
||||
#define WMI_BF_SOUND_DIM_OFFSET_LSB 8
|
||||
#define WMI_BF_SOUND_DIM_OFFSET_MASK 0xf00
|
||||
|
||||
/* slot time long */
|
||||
#define WMI_VDEV_SLOT_TIME_LONG 0x1
|
||||
/* slot time short */
|
||||
@@ -6008,6 +6013,12 @@ struct wmi_tdls_peer_capab_arg {
|
||||
u32 pref_offchan_bw;
|
||||
};
|
||||
|
||||
enum wmi_txbf_conf {
|
||||
WMI_TXBF_CONF_UNSUPPORTED,
|
||||
WMI_TXBF_CONF_BEFORE_ASSOC,
|
||||
WMI_TXBF_CONF_AFTER_ASSOC,
|
||||
};
|
||||
|
||||
struct ath10k;
|
||||
struct ath10k_vif;
|
||||
struct ath10k_fw_stats_pdev;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user