summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath10k
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath10k')
-rw-r--r--drivers/net/wireless/ath/ath10k/Kconfig1
-rw-r--r--drivers/net/wireless/ath/ath10k/ahb.c23
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.c54
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.h4
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c93
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h19
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c115
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h8
-rw-r--r--drivers/net/wireless/ath/ath10k/debugfs_sta.c65
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.c35
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h6
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c16
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h9
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c216
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.h7
-rw-r--r--drivers/net/wireless/ath/ath10k/p2p.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c68
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.h10
-rw-r--r--drivers/net/wireless/ath/ath10k/spectral.c7
-rw-r--r--drivers/net/wireless/ath/ath10k/testmode.c5
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c13
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c13
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h32
26 files changed, 589 insertions, 238 deletions
diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index db1ca629cbd6..b4241cf9b7ed 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -3,6 +3,7 @@ config ATH10K
depends on MAC80211 && HAS_DMA
select ATH_COMMON
select CRC32
+ select WANT_DEV_COREDUMP
---help---
This module adds support for wireless adapters based on
Atheros IEEE 802.11ac family of chipsets.
diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c
index 766c63bf05c4..45226dbee5ce 100644
--- a/drivers/net/wireless/ath/ath10k/ahb.c
+++ b/drivers/net/wireless/ath/ath10k/ahb.c
@@ -33,6 +33,9 @@ static const struct of_device_id ath10k_ahb_of_match[] = {
MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match);
+#define QCA4019_SRAM_ADDR 0x000C0000
+#define QCA4019_SRAM_LEN 0x00040000 /* 256 kb */
+
static inline struct ath10k_ahb *ath10k_ahb_priv(struct ath10k *ar)
{
return &((struct ath10k_pci *)ar->drv_priv)->ahb[0];
@@ -699,6 +702,25 @@ out:
return ret;
}
+static u32 ath10k_ahb_qca4019_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
+{
+ u32 val = 0, region = addr & 0xfffff;
+
+ val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS);
+
+ if (region >= QCA4019_SRAM_ADDR && region <=
+ (QCA4019_SRAM_ADDR + QCA4019_SRAM_LEN)) {
+ /* SRAM contents for QCA4019 can be directly accessed and
+ * no conversions are required
+ */
+ val |= region;
+ } else {
+ val |= 0x100000 | region;
+ }
+
+ return val;
+}
+
static const struct ath10k_hif_ops ath10k_ahb_hif_ops = {
.tx_sg = ath10k_pci_hif_tx_sg,
.diag_read = ath10k_pci_hif_diag_read,
@@ -766,6 +788,7 @@ static int ath10k_ahb_probe(struct platform_device *pdev)
ar_pci->mem_len = ar_ahb->mem_len;
ar_pci->ar = ar;
ar_pci->bus_ops = &ath10k_ahb_bus_ops;
+ ar_pci->targ_cpu_to_ce_addr = ath10k_ahb_qca4019_targ_cpu_to_ce_addr;
ret = ath10k_pci_setup_resource(ar);
if (ret) {
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index 0b4d79659884..4045657e0a6e 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -958,10 +958,10 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id,
* coherent DMA are unsupported
*/
dest_ring->base_addr_owner_space_unaligned =
- dma_alloc_coherent(ar->dev,
- (nentries * sizeof(struct ce_desc) +
- CE_DESC_RING_ALIGN),
- &base_addr, GFP_KERNEL);
+ dma_zalloc_coherent(ar->dev,
+ (nentries * sizeof(struct ce_desc) +
+ CE_DESC_RING_ALIGN),
+ &base_addr, GFP_KERNEL);
if (!dest_ring->base_addr_owner_space_unaligned) {
kfree(dest_ring);
return ERR_PTR(-ENOMEM);
@@ -969,13 +969,6 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id,
dest_ring->base_addr_ce_space_unaligned = base_addr;
- /*
- * Correctly initialize memory to 0 to prevent garbage
- * data crashing system when download firmware
- */
- memset(dest_ring->base_addr_owner_space_unaligned, 0,
- nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN);
-
dest_ring->base_addr_owner_space = PTR_ALIGN(
dest_ring->base_addr_owner_space_unaligned,
CE_DESC_RING_ALIGN);
@@ -1130,3 +1123,42 @@ void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id)
ce_state->src_ring = NULL;
ce_state->dest_ring = NULL;
}
+
+void ath10k_ce_dump_registers(struct ath10k *ar,
+ struct ath10k_fw_crash_data *crash_data)
+{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ struct ath10k_ce_crash_data ce;
+ u32 addr, id;
+
+ lockdep_assert_held(&ar->data_lock);
+
+ ath10k_err(ar, "Copy Engine register dump:\n");
+
+ spin_lock_bh(&ar_pci->ce_lock);
+ for (id = 0; id < CE_COUNT; id++) {
+ addr = ath10k_ce_base_address(ar, id);
+ ce.base_addr = cpu_to_le32(addr);
+
+ ce.src_wr_idx =
+ cpu_to_le32(ath10k_ce_src_ring_write_index_get(ar, addr));
+ ce.src_r_idx =
+ cpu_to_le32(ath10k_ce_src_ring_read_index_get(ar, addr));
+ ce.dst_wr_idx =
+ cpu_to_le32(ath10k_ce_dest_ring_write_index_get(ar, addr));
+ ce.dst_r_idx =
+ cpu_to_le32(ath10k_ce_dest_ring_read_index_get(ar, addr));
+
+ if (crash_data)
+ crash_data->ce_crash_data[id] = ce;
+
+ ath10k_err(ar, "[%02d]: 0x%08x %3u %3u %3u %3u", id,
+ le32_to_cpu(ce.base_addr),
+ le32_to_cpu(ce.src_wr_idx),
+ le32_to_cpu(ce.src_r_idx),
+ le32_to_cpu(ce.dst_wr_idx),
+ le32_to_cpu(ce.dst_r_idx));
+ }
+
+ spin_unlock_bh(&ar_pci->ce_lock);
+}
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index dfc098606bee..e76a98242b98 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -20,8 +20,6 @@
#include "hif.h"
-/* Maximum number of Copy Engine's supported */
-#define CE_COUNT_MAX 12
#define CE_HTT_H2T_MSG_SRC_NENTRIES 8192
/* Descriptor rings must be aligned to this boundary */
@@ -228,6 +226,8 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar);
void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id);
int ath10k_ce_disable_interrupts(struct ath10k *ar);
void ath10k_ce_enable_interrupts(struct ath10k *ar);
+void ath10k_ce_dump_registers(struct ath10k *ar,
+ struct ath10k_fw_crash_data *crash_data);
/* ce_attr.flags values */
/* Use NonSnooping PCIe accesses? */
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 749e381edd38..dd902b43f8f7 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -349,7 +349,7 @@ void ath10k_core_get_fw_features_str(struct ath10k *ar,
char *buf,
size_t buf_len)
{
- unsigned int len = 0;
+ size_t len = 0;
int i;
for (i = 0; i < ATH10K_FW_FEATURE_COUNT; i++) {
@@ -454,7 +454,10 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar,
dir = ".";
snprintf(filename, sizeof(filename), "%s/%s", dir, file);
- ret = request_firmware(&fw, filename, ar->dev);
+ ret = request_firmware_direct(&fw, filename, ar->dev);
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot fw request '%s': %d\n",
+ filename, ret);
+
if (ret)
return ERR_PTR(ret);
@@ -694,8 +697,12 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
"boot get otp board id result 0x%08x board_id %d chip_id %d\n",
result, board_id, chip_id);
- if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0)
+ if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0 ||
+ (board_id == 0)) {
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "board id does not exist in otp, ignore it\n");
return -EOPNOTSUPP;
+ }
ar->id.bmi_ids_valid = true;
ar->id.bmi_board_id = board_id;
@@ -1091,7 +1098,8 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar)
ar->bd_api = 1;
ret = ath10k_core_fetch_board_data_api_1(ar);
if (ret) {
- ath10k_err(ar, "failed to fetch board data\n");
+ ath10k_err(ar, "failed to fetch board-2.bin or board.bin from %s\n",
+ ar->hw_params.fw.dir);
return ret;
}
@@ -1112,12 +1120,8 @@ int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name,
/* first fetch the firmware file (firmware-*.bin) */
fw_file->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,
name);
- if (IS_ERR(fw_file->firmware)) {
- ath10k_err(ar, "could not fetch firmware file '%s/%s': %ld\n",
- ar->hw_params.fw.dir, name,
- PTR_ERR(fw_file->firmware));
+ if (IS_ERR(fw_file->firmware))
return PTR_ERR(fw_file->firmware);
- }
data = fw_file->firmware->data;
len = fw_file->firmware->size;
@@ -1281,44 +1285,39 @@ err:
return ret;
}
+static void ath10k_core_get_fw_name(struct ath10k *ar, char *fw_name,
+ size_t fw_name_len, int fw_api)
+{
+ scnprintf(fw_name, fw_name_len, "%s-%d.bin", ATH10K_FW_FILE_BASE, fw_api);
+}
+
static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
{
- int ret;
+ int ret, i;
+ char fw_name[100];
/* calibration file is optional, don't check for any errors */
ath10k_fetch_cal_file(ar);
- ar->fw_api = 5;
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
+ for (i = ATH10K_FW_API_MAX; i >= ATH10K_FW_API_MIN; i--) {
+ ar->fw_api = i;
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n",
+ ar->fw_api);
- ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API5_FILE,
- &ar->normal_mode_fw.fw_file);
- if (ret == 0)
- goto success;
-
- ar->fw_api = 4;
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
-
- ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API4_FILE,
- &ar->normal_mode_fw.fw_file);
- if (ret == 0)
- goto success;
+ ath10k_core_get_fw_name(ar, fw_name, sizeof(fw_name), ar->fw_api);
+ ret = ath10k_core_fetch_firmware_api_n(ar, fw_name,
+ &ar->normal_mode_fw.fw_file);
+ if (!ret)
+ goto success;
+ }
- ar->fw_api = 3;
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
+ /* we end up here if we couldn't fetch any firmware */
- ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE,
- &ar->normal_mode_fw.fw_file);
- if (ret == 0)
- goto success;
-
- ar->fw_api = 2;
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
+ ath10k_err(ar, "Failed to find firmware-N.bin (N between %d and %d) from %s: %d",
+ ATH10K_FW_API_MIN, ATH10K_FW_API_MAX, ar->hw_params.fw.dir,
+ ret);
- ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE,
- &ar->normal_mode_fw.fw_file);
- if (ret)
- return ret;
+ return ret;
success:
ath10k_dbg(ar, ATH10K_DBG_BOOT, "using fw api %d\n", ar->fw_api);
@@ -1510,6 +1509,7 @@ static int ath10k_init_hw_params(struct ath10k *ar)
static void ath10k_core_restart(struct work_struct *work)
{
struct ath10k *ar = container_of(work, struct ath10k, restart_work);
+ int ret;
set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
@@ -1561,6 +1561,11 @@ static void ath10k_core_restart(struct work_struct *work)
}
mutex_unlock(&ar->conf_mutex);
+
+ ret = ath10k_debug_fw_devcoredump(ar);
+ if (ret)
+ ath10k_warn(ar, "failed to send firmware crash dump via devcoredump: %d",
+ ret);
}
static void ath10k_core_set_coverage_class_work(struct work_struct *work)
@@ -1913,7 +1918,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
ar->hw->wiphy->fw_version);
- if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map)) {
+ if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map) &&
+ mode == ATH10K_FIRMWARE_MODE_NORMAL) {
val = 0;
if (ath10k_peer_stats_enabled(ar))
val = WMI_10_4_PEER_STATS;
@@ -1966,10 +1972,13 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
* possible to implicitly make it correct by creating a dummy vdev and
* then deleting it.
*/
- status = ath10k_core_reset_rx_filter(ar);
- if (status) {
- ath10k_err(ar, "failed to reset rx filter: %d\n", status);
- goto err_hif_stop;
+ if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+ status = ath10k_core_reset_rx_filter(ar);
+ if (status) {
+ ath10k_err(ar,
+ "failed to reset rx filter: %d\n", status);
+ goto err_hif_stop;
+ }
}
/* If firmware indicates Full Rx Reorder support it must be used in a
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 09ff8b8a6441..757242ef52ac 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -46,7 +46,7 @@
#define WMI_READY_TIMEOUT (5 * HZ)
#define ATH10K_FLUSH_TIMEOUT_HZ (5 * HZ)
#define ATH10K_CONNECTION_LOSS_HZ (3 * HZ)
-#define ATH10K_NUM_CHANS 39
+#define ATH10K_NUM_CHANS 40
/* Antenna noise floor */
#define ATH10K_DEFAULT_NOISE_FLOOR -95
@@ -314,6 +314,7 @@ struct ath10k_peer {
struct ieee80211_vif *vif;
struct ieee80211_sta *sta;
+ bool removed;
int vdev_id;
u8 addr[ETH_ALEN];
DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS);
@@ -419,6 +420,21 @@ struct ath10k_vif_iter {
struct ath10k_vif *arvif;
};
+/* Copy Engine register dump, protected by ce-lock */
+struct ath10k_ce_crash_data {
+ __le32 base_addr;
+ __le32 src_wr_idx;
+ __le32 src_r_idx;
+ __le32 dst_wr_idx;
+ __le32 dst_r_idx;
+};
+
+struct ath10k_ce_crash_hdr {
+ __le32 ce_count;
+ __le32 reserved[3]; /* for future use */
+ struct ath10k_ce_crash_data entries[];
+};
+
/* used for crash-dump storage, protected by data-lock */
struct ath10k_fw_crash_data {
bool crashed_since_read;
@@ -426,6 +442,7 @@ struct ath10k_fw_crash_data {
uuid_le uuid;
struct timespec timestamp;
__le32 registers[REG_DUMP_COUNT_QCA988X];
+ struct ath10k_ce_crash_data ce_crash_data[CE_COUNT_MAX];
};
struct ath10k_debug {
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 82a4c67f3672..fb0ade3adb07 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -21,6 +21,7 @@
#include <linux/utsname.h>
#include <linux/crc32.h>
#include <linux/firmware.h>
+#include <linux/devcoredump.h>
#include "core.h"
#include "debug.h"
@@ -40,6 +41,7 @@
*/
enum ath10k_fw_crash_dump_type {
ATH10K_FW_CRASH_DUMP_REGISTERS = 0,
+ ATH10K_FW_CRASH_DUMP_CE_DATA = 1,
ATH10K_FW_CRASH_DUMP_MAX,
};
@@ -235,7 +237,7 @@ static ssize_t ath10k_read_wmi_services(struct file *file,
{
struct ath10k *ar = file->private_data;
char *buf;
- unsigned int len = 0, buf_len = 4096;
+ size_t len = 0, buf_len = 4096;
const char *name;
ssize_t ret_cnt;
bool enabled;
@@ -399,6 +401,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
* prevent firmware from DoS-ing the host.
*/
ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers);
+ ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd);
ath10k_warn(ar, "dropping fw peer stats\n");
goto free;
}
@@ -409,10 +412,12 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
goto free;
}
+ if (!list_empty(&stats.peers))
+ list_splice_tail_init(&stats.peers_extd,
+ &ar->debug.fw_stats.peers_extd);
+
list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs);
- list_splice_tail_init(&stats.peers_extd,
- &ar->debug.fw_stats.peers_extd);
}
complete(&ar->debug.fw_stats_complete);
@@ -524,7 +529,7 @@ static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
const char *buf = file->private_data;
- unsigned int len = strlen(buf);
+ size_t len = strlen(buf);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -542,17 +547,16 @@ static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
- int ret, len, buf_len;
+ int ret;
+ size_t len = 0, buf_len = 500;
char *buf;
- buf_len = 500;
buf = kmalloc(buf_len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
spin_lock_bh(&ar->data_lock);
- len = 0;
len += scnprintf(buf + len, buf_len - len,
"fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);
len += scnprintf(buf + len, buf_len - len,
@@ -691,7 +695,7 @@ static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
- unsigned int len;
+ size_t len;
char buf[50];
len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id);
@@ -721,17 +725,21 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
}
EXPORT_SYMBOL(ath10k_debug_get_new_fw_crash_data);
-static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
+static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar,
+ bool mark_read)
{
struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
+ struct ath10k_ce_crash_hdr *ce_hdr;
struct ath10k_dump_file_data *dump_data;
struct ath10k_tlv_dump_data *dump_tlv;
- int hdr_len = sizeof(*dump_data);
- unsigned int len, sofar = 0;
+ size_t hdr_len = sizeof(*dump_data);
+ size_t len, sofar = 0;
unsigned char *buf;
len = hdr_len;
len += sizeof(*dump_tlv) + sizeof(crash_data->registers);
+ len += sizeof(*dump_tlv) + sizeof(*ce_hdr) +
+ CE_COUNT * sizeof(ce_hdr->entries[0]);
sofar += hdr_len;
@@ -790,19 +798,66 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
sizeof(crash_data->registers));
sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers);
- ar->debug.fw_crash_data->crashed_since_read = false;
+ dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
+ dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_CE_DATA);
+ dump_tlv->tlv_len = cpu_to_le32(sizeof(*ce_hdr) +
+ CE_COUNT * sizeof(ce_hdr->entries[0]));
+ ce_hdr = (struct ath10k_ce_crash_hdr *)(dump_tlv->tlv_data);
+ ce_hdr->ce_count = cpu_to_le32(CE_COUNT);
+ memset(ce_hdr->reserved, 0, sizeof(ce_hdr->reserved));
+ memcpy(ce_hdr->entries, crash_data->ce_crash_data,
+ CE_COUNT * sizeof(ce_hdr->entries[0]));
+ sofar += sizeof(*dump_tlv) + sizeof(*ce_hdr) +
+ CE_COUNT * sizeof(ce_hdr->entries[0]);
+
+ ar->debug.fw_crash_data->crashed_since_read = !mark_read;
spin_unlock_bh(&ar->data_lock);
return dump_data;
}
+int ath10k_debug_fw_devcoredump(struct ath10k *ar)
+{
+ struct ath10k_dump_file_data *dump;
+ void *dump_ptr;
+ u32 dump_len;
+
+ /* To keep the dump file available also for debugfs don't mark the
+ * file read, only debugfs should do that.
+ */
+ dump = ath10k_build_dump_file(ar, false);
+ if (!dump) {
+ ath10k_warn(ar, "no crash dump data found for devcoredump");
+ return -ENODATA;
+ }
+
+ /* Make a copy of the dump file for dev_coredumpv() as during the
+ * transition period we need to own the original file. Once
+ * fw_crash_dump debugfs file is removed no need to have a copy
+ * anymore.
+ */
+ dump_len = le32_to_cpu(dump->len);
+ dump_ptr = vzalloc(dump_len);
+
+ if (!dump_ptr)
+ return -ENOMEM;
+
+ memcpy(dump_ptr, dump, dump_len);
+
+ dev_coredumpv(ar->dev, dump_ptr, dump_len, GFP_KERNEL);
+
+ return 0;
+}
+
static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file)
{
struct ath10k *ar = inode->i_private;
struct ath10k_dump_file_data *dump;
- dump = ath10k_build_dump_file(ar);
+ ath10k_warn(ar, "fw_crash_dump debugfs file is deprecated, please use /sys/class/devcoredump instead.");
+
+ dump = ath10k_build_dump_file(ar, true);
if (!dump)
return -ENODATA;
@@ -844,7 +899,7 @@ static ssize_t ath10k_reg_addr_read(struct file *file,
{
struct ath10k *ar = file->private_data;
u8 buf[32];
- unsigned int len = 0;
+ size_t len = 0;
u32 reg_addr;
mutex_lock(&ar->conf_mutex);
@@ -892,7 +947,7 @@ static ssize_t ath10k_reg_value_read(struct file *file,
{
struct ath10k *ar = file->private_data;
u8 buf[48];
- unsigned int len;
+ size_t len;
u32 reg_addr, reg_val;
int ret;
@@ -1115,7 +1170,7 @@ static ssize_t ath10k_read_htt_stats_mask(struct file *file,
{
struct ath10k *ar = file->private_data;
char buf[32];
- unsigned int len;
+ size_t len;
len = scnprintf(buf, sizeof(buf), "%lu\n", ar->debug.htt_stats_mask);
@@ -1169,7 +1224,7 @@ static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
struct ath10k *ar = file->private_data;
char buf[64];
u8 amsdu, ampdu;
- unsigned int len;
+ size_t len;
mutex_lock(&ar->conf_mutex);
@@ -1229,7 +1284,7 @@ static ssize_t ath10k_read_fw_dbglog(struct file *file,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
- unsigned int len;
+ size_t len;
char buf[96];
len = scnprintf(buf, sizeof(buf), "0x%16llx %u\n",
@@ -1555,11 +1610,10 @@ static ssize_t ath10k_read_ani_enable(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
- int len = 0;
+ size_t len;
char buf[32];
- len = scnprintf(buf, sizeof(buf) - len, "%d\n",
- ar->ani_enabled);
+ len = scnprintf(buf, sizeof(buf), "%d\n", ar->ani_enabled);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -1584,11 +1638,10 @@ static ssize_t ath10k_read_nf_cal_period(struct file *file,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
- unsigned int len;
+ size_t len;
char buf[32];
- len = scnprintf(buf, sizeof(buf), "%d\n",
- ar->debug.nf_cal_period);
+ len = scnprintf(buf, sizeof(buf), "%d\n", ar->debug.nf_cal_period);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -1684,9 +1737,10 @@ void ath10k_debug_tpc_stats_process(struct ath10k *ar,
}
static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats,
- unsigned int j, char *buf, unsigned int *len)
+ unsigned int j, char *buf, size_t *len)
{
- unsigned int i, buf_len;
+ int i;
+ size_t buf_len;
static const char table_str[][5] = { "CDD",
"STBC",
"TXBF" };
@@ -1726,7 +1780,8 @@ static void ath10k_tpc_stats_fill(struct ath10k *ar,
struct ath10k_tpc_stats *tpc_stats,
char *buf)
{
- unsigned int len, j, buf_len;
+ int j;
+ size_t len, buf_len;
len = 0;
buf_len = ATH10K_TPC_CONFIG_BUF_SIZE;
@@ -1860,7 +1915,7 @@ static ssize_t ath10k_tpc_stats_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
const char *buf = file->private_data;
- unsigned int len = strlen(buf);
+ size_t len = strlen(buf);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -2284,7 +2339,7 @@ static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
- unsigned int len = 0, buf_len = 4096;
+ size_t len = 0, buf_len = 4096;
ssize_t ret_cnt;
char *buf;
@@ -2500,7 +2555,7 @@ void ath10k_dbg_dump(struct ath10k *ar,
const void *buf, size_t len)
{
char linebuf[256];
- unsigned int linebuflen;
+ size_t linebuflen;
const void *ptr;
if (ath10k_debug_mask & mask) {
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 335512b11ca2..2368f47314ae 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -84,6 +84,9 @@ struct ath10k_fw_crash_data *
ath10k_debug_get_new_fw_crash_data(struct ath10k *ar);
void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len);
+
+int ath10k_debug_fw_devcoredump(struct ath10k *ar);
+
#define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
@@ -166,6 +169,11 @@ static inline u32 ath10k_debug_get_fw_dbglog_level(struct ath10k *ar)
return 0;
}
+static inline int ath10k_debug_fw_devcoredump(struct ath10k *ar)
+{
+ return 0;
+}
+
#define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
#define ath10k_debug_get_et_strings NULL
diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
index fce6f8137d33..7353e7ea88f1 100644
--- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c
+++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c
@@ -306,6 +306,69 @@ static const struct file_operations fops_delba = {
.llseek = default_llseek,
};
+static ssize_t ath10k_dbg_sta_read_peer_debug_trigger(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;
+ struct ath10k *ar = arsta->arvif->ar;
+ char buf[8];
+ int len = 0;
+
+ mutex_lock(&ar->conf_mutex);
+ len = scnprintf(buf, sizeof(buf) - len,
+ "Write 1 to once trigger the debug logs\n");
+ mutex_unlock(&ar->conf_mutex);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t
+ath10k_dbg_sta_write_peer_debug_trigger(struct file *file,
+ const 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;
+ struct ath10k *ar = arsta->arvif->ar;
+ u8 peer_debug_trigger;
+ int ret;
+
+ if (kstrtou8_from_user(user_buf, count, 0, &peer_debug_trigger))
+ return -EINVAL;
+
+ if (peer_debug_trigger != 1)
+ return -EINVAL;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state != ATH10K_STATE_ON) {
+ ret = -ENETDOWN;
+ goto out;
+ }
+
+ ret = ath10k_wmi_peer_set_param(ar, arsta->arvif->vdev_id, sta->addr,
+ WMI_PEER_DEBUG, peer_debug_trigger);
+ if (ret) {
+ ath10k_warn(ar, "failed to set param to trigger peer tid logs for station ret: %d\n",
+ ret);
+ goto out;
+ }
+out:
+ mutex_unlock(&ar->conf_mutex);
+ return count;
+}
+
+static const struct file_operations fops_peer_debug_trigger = {
+ .open = simple_open,
+ .read = ath10k_dbg_sta_read_peer_debug_trigger,
+ .write = ath10k_dbg_sta_write_peer_debug_trigger,
+ .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)
{
@@ -314,4 +377,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("peer_debug_trigger", 0600, dir, sta,
+ &fops_peer_debug_trigger);
}
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 175aae38c375..9f6a915f91bf 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -474,33 +474,16 @@ static void ath10k_htc_reset_endpoint_states(struct ath10k_htc *htc)
}
}
-static void ath10k_htc_setup_target_buffer_assignments(struct ath10k_htc *htc)
-{
- struct ath10k_htc_svc_tx_credits *entry;
-
- entry = &htc->service_tx_alloc[0];
-
- /*
- * for PCIE allocate all credists/HTC buffers to WMI.
- * no buffers are used/required for data. data always
- * remains on host.
- */
- entry++;
- entry->service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL;
- entry->credit_allocation = htc->total_transmit_credits;
-}
-
static u8 ath10k_htc_get_credit_allocation(struct ath10k_htc *htc,
u16 service_id)
{
u8 allocation = 0;
- int i;
- for (i = 0; i < ATH10K_HTC_EP_COUNT; i++) {
- if (htc->service_tx_alloc[i].service_id == service_id)
- allocation =
- htc->service_tx_alloc[i].credit_allocation;
- }
+ /* The WMI control service is the only service with flow control.
+ * Let it have all transmit credits.
+ */
+ if (service_id == ATH10K_HTC_SVC_ID_WMI_CONTROL)
+ allocation = htc->total_transmit_credits;
return allocation;
}
@@ -574,8 +557,6 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
return -ECOMM;
}
- ath10k_htc_setup_target_buffer_assignments(htc);
-
/* setup our pseudo HTC control endpoint connection */
memset(&conn_req, 0, sizeof(conn_req));
memset(&conn_resp, 0, sizeof(conn_resp));
@@ -726,12 +707,6 @@ setup:
ep->max_tx_queue_depth = conn_req->max_send_queue_depth;
ep->max_ep_message_len = __le16_to_cpu(resp_msg->max_msg_size);
ep->tx_credits = tx_alloc;
- ep->tx_credit_size = htc->target_credit_size;
- ep->tx_credits_per_max_message = ep->max_ep_message_len /
- htc->target_credit_size;
-
- if (ep->max_ep_message_len % htc->target_credit_size)
- ep->tx_credits_per_max_message++;
/* copy all the callbacks */
ep->ep_ops = conn_req->ep_ops;
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index 0c55cd92a951..6ababa345e2b 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -314,8 +314,6 @@ struct ath10k_htc_ep {
u8 seq_no; /* for debugging */
int tx_credits;
- int tx_credit_size;
- int tx_credits_per_max_message;
bool tx_credit_flow_enabled;
};
@@ -339,7 +337,6 @@ struct ath10k_htc {
struct completion ctl_resp;
int total_transmit_credits;
- struct ath10k_htc_svc_tx_credits service_tx_alloc[ATH10K_HTC_EP_COUNT];
int target_credit_size;
};
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 44b25cf00553..90c2f72666b8 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1636,7 +1636,7 @@ struct ath10k_htt {
int size;
/* size - 1 */
- unsigned size_mask;
+ unsigned int size_mask;
/* how many rx buffers to keep in the ring */
int fill_level;
@@ -1657,7 +1657,7 @@ struct ath10k_htt {
/* where HTT SW has processed bufs filled by rx MAC DMA */
struct {
- unsigned msdu_payld;
+ unsigned int msdu_payld;
} sw_rd_idx;
/*
@@ -1820,7 +1820,7 @@ int ath10k_htt_tx_mgmt_inc_pending(struct ath10k_htt *htt, bool is_mgmt,
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb);
void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id);
-int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *);
+int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu);
int ath10k_htt_tx(struct ath10k_htt *htt,
enum ath10k_hw_txrx_mode txmode,
struct sk_buff *msdu);
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 86d082cf4eef..02a3fc81fbe3 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -702,6 +702,10 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
/* 80MHZ */
case 2:
status->vht_flag |= RX_VHT_FLAG_80MHZ;
+ break;
+ case 3:
+ status->vht_flag |= RX_VHT_FLAG_160MHZ;
+ break;
}
status->flag |= RX_FLAG_VHT;
@@ -926,7 +930,7 @@ static void ath10k_process_rx(struct ath10k *ar,
*status = *rx_status;
ath10k_dbg(ar, ATH10K_DBG_DATA,
- "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n",
+ "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n",
skb,
skb->len,
ieee80211_get_SA(hdr),
@@ -940,6 +944,7 @@ static void ath10k_process_rx(struct ath10k *ar,
status->flag & RX_FLAG_VHT ? "vht" : "",
status->flag & RX_FLAG_40MHZ ? "40" : "",
status->vht_flag & RX_VHT_FLAG_80MHZ ? "80" : "",
+ status->vht_flag & RX_VHT_FLAG_160MHZ ? "160" : "",
status->flag & RX_FLAG_SHORT_GI ? "sgi " : "",
status->rate_idx,
status->vht_nss,
@@ -2231,6 +2236,8 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
return;
}
+ memset(&arsta->txrate, 0, sizeof(arsta->txrate));
+
if (txrate.flags == WMI_RATE_PREAMBLE_CCK ||
txrate.flags == WMI_RATE_PREAMBLE_OFDM) {
rate = ATH10K_HW_LEGACY_RATE(peer_stats->ratecode);
@@ -2245,7 +2252,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
rate *= 10;
if (rate == 60 && txrate.flags == WMI_RATE_PREAMBLE_CCK)
rate = rate - 5;
- arsta->txrate.legacy = rate * 10;
+ arsta->txrate.legacy = rate;
} else if (txrate.flags == WMI_RATE_PREAMBLE_HT) {
arsta->txrate.flags = RATE_INFO_FLAGS_MCS;
arsta->txrate.mcs = txrate.mcs;
@@ -2451,8 +2458,7 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
u32 phymode = __le32_to_cpu(resp->chan_change.phymode);
u32 freq = __le32_to_cpu(resp->chan_change.freq);
- ar->tgt_oper_chan =
- __ieee80211_get_channel(ar->hw->wiphy, freq);
+ ar->tgt_oper_chan = ieee80211_get_channel(ar->hw->wiphy, freq);
ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt chan change freq %u phymode %s\n",
freq, ath10k_wmi_phymode_str(phymode));
@@ -2486,7 +2492,7 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
skb->data, skb->len);
break;
- };
+ }
return true;
}
EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler);
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 27e49db4287a..86b427f5e2bc 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -239,6 +239,7 @@ static void ath10k_htt_tx_free_cont_txbuf(struct ath10k_htt *htt)
size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf);
dma_free_coherent(ar->dev, size, htt->txbuf.vaddr, htt->txbuf.paddr);
+ htt->txbuf.vaddr = NULL;
}
static int ath10k_htt_tx_alloc_cont_txbuf(struct ath10k_htt *htt)
@@ -268,6 +269,7 @@ static void ath10k_htt_tx_free_cont_frag_desc(struct ath10k_htt *htt)
size,
htt->frag_desc.vaddr,
htt->frag_desc.paddr);
+ htt->frag_desc.vaddr = NULL;
}
static int ath10k_htt_tx_alloc_cont_frag_desc(struct ath10k_htt *htt)
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 883547f3347c..f0fda0f2b3b4 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -128,6 +128,10 @@ enum qca9377_chip_id_rev {
#define QCA4019_HW_1_0_BOARD_DATA_FILE "board.bin"
#define QCA4019_HW_1_0_PATCH_LOAD_ADDR 0x1234
+#define ATH10K_FW_FILE_BASE "firmware"
+#define ATH10K_FW_API_MAX 5
+#define ATH10K_FW_API_MIN 2
+
#define ATH10K_FW_API2_FILE "firmware-2.bin"
#define ATH10K_FW_API3_FILE "firmware-3.bin"
@@ -512,7 +516,7 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
/* Target specific defines for WMI-TLV firmware */
#define TARGET_TLV_NUM_VDEVS 4
#define TARGET_TLV_NUM_STATIONS 32
-#define TARGET_TLV_NUM_PEERS 35
+#define TARGET_TLV_NUM_PEERS 33
#define TARGET_TLV_NUM_TDLS_VDEVS 1
#define TARGET_TLV_NUM_TIDS ((TARGET_TLV_NUM_PEERS) * 2)
#define TARGET_TLV_NUM_MSDU_DESC (1024 + 32)
@@ -578,6 +582,9 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw,
#define TARGET_10_4_IPHDR_PAD_CONFIG 1
#define TARGET_10_4_QWRAP_CONFIG 0
+/* Maximum number of Copy Engine's supported */
+#define CE_COUNT_MAX 12
+
/* Number of Copy Engines supported */
#define CE_COUNT ar->hw_values->ce_count
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index aa545a1dbdc7..3029f257a19a 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -569,10 +569,14 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef)
case NL80211_CHAN_WIDTH_80:
phymode = MODE_11AC_VHT80;
break;
+ case NL80211_CHAN_WIDTH_160:
+ phymode = MODE_11AC_VHT160;
+ break;
+ case NL80211_CHAN_WIDTH_80P80:
+ phymode = MODE_11AC_VHT80_80;
+ break;
case NL80211_CHAN_WIDTH_5:
case NL80211_CHAN_WIDTH_10:
- case NL80211_CHAN_WIDTH_80P80:
- case NL80211_CHAN_WIDTH_160:
phymode = MODE_UNKNOWN;
break;
}
@@ -971,6 +975,7 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
arg.vdev_id = vdev_id;
arg.channel.freq = channel->center_freq;
arg.channel.band_center_freq1 = chandef->center_freq1;
+ arg.channel.band_center_freq2 = chandef->center_freq2;
/* TODO setup this dynamically, what in case we
don't have any vifs? */
@@ -1227,6 +1232,36 @@ static int ath10k_monitor_recalc(struct ath10k *ar)
return ath10k_monitor_stop(ar);
}
+static bool ath10k_mac_can_set_cts_prot(struct ath10k_vif *arvif)
+{
+ struct ath10k *ar = arvif->ar;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ if (!arvif->is_started) {
+ ath10k_dbg(ar, ATH10K_DBG_MAC, "defer cts setup, vdev is not ready yet\n");
+ return false;
+ }
+
+ return true;
+}
+
+static int ath10k_mac_set_cts_prot(struct ath10k_vif *arvif)
+{
+ struct ath10k *ar = arvif->ar;
+ u32 vdev_param;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ vdev_param = ar->wmi.vdev_param->protection_mode;
+
+ ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d cts_protection %d\n",
+ arvif->vdev_id, arvif->use_cts_prot);
+
+ return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
+ arvif->use_cts_prot ? 1 : 0);
+}
+
static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
@@ -1245,6 +1280,9 @@ static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif)
rts_cts |= SM(WMI_RTSCTS_FOR_SECOND_RATESERIES,
WMI_RTSCTS_PROFILE);
+ ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d recalc rts/cts prot %d\n",
+ arvif->vdev_id, rts_cts);
+
return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
rts_cts);
}
@@ -1384,6 +1422,7 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif,
arg.channel.freq = chandef->chan->center_freq;
arg.channel.band_center_freq1 = chandef->center_freq1;
+ arg.channel.band_center_freq2 = chandef->center_freq2;
arg.channel.mode = chan_to_phymode(chandef);
arg.channel.min_power = 0;
@@ -1954,7 +1993,7 @@ static void ath10k_mac_handle_beacon_iter(void *data, u8 *mac,
{
struct sk_buff *skb = data;
struct ieee80211_mgmt *mgmt = (void *)skb->data;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
if (vif->type != NL80211_IFTYPE_STATION)
return;
@@ -1977,7 +2016,7 @@ static void ath10k_mac_handle_beacon_miss_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
u32 *vdev_id = data;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k *ar = arvif->ar;
struct ieee80211_hw *hw = ar->hw;
@@ -2044,7 +2083,7 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
struct ieee80211_sta *sta,
struct wmi_peer_assoc_complete_arg *arg)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
u32 aid;
lockdep_assert_held(&ar->conf_mutex);
@@ -2120,7 +2159,7 @@ static void ath10k_peer_assoc_h_rates(struct ath10k *ar,
struct ieee80211_sta *sta,
struct wmi_peer_assoc_complete_arg *arg)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates;
struct cfg80211_chan_def def;
const struct ieee80211_supported_band *sband;
@@ -2183,7 +2222,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
struct wmi_peer_assoc_complete_arg *arg)
{
const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct cfg80211_chan_def def;
enum nl80211_band band;
const u8 *ht_mcs_mask;
@@ -2407,7 +2446,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
struct wmi_peer_assoc_complete_arg *arg)
{
const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct cfg80211_chan_def def;
enum nl80211_band band;
const u16 *vht_mcs_mask;
@@ -2447,6 +2486,9 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
arg->peer_flags |= ar->wmi.peer_flags->bw80;
+ if (sta->bandwidth == IEEE80211_STA_RX_BW_160)
+ arg->peer_flags |= ar->wmi.peer_flags->bw160;
+
arg->peer_vht_rates.rx_max_rate =
__le16_to_cpu(vht_cap->vht_mcs.rx_highest);
arg->peer_vht_rates.rx_mcs_set =
@@ -2465,7 +2507,7 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
struct ieee80211_sta *sta,
struct wmi_peer_assoc_complete_arg *arg)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
switch (arvif->vdev_type) {
case WMI_VDEV_TYPE_AP:
@@ -2500,12 +2542,39 @@ static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
ATH10K_MAC_FIRST_OFDM_RATE_IDX;
}
+static enum wmi_phy_mode ath10k_mac_get_phymode_vht(struct ath10k *ar,
+ struct ieee80211_sta *sta)
+{
+ if (sta->bandwidth == IEEE80211_STA_RX_BW_160) {
+ switch (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
+ case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
+ return MODE_11AC_VHT160;
+ case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
+ return MODE_11AC_VHT80_80;
+ default:
+ /* not sure if this is a valid case? */
+ return MODE_11AC_VHT160;
+ }
+ }
+
+ if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
+ return MODE_11AC_VHT80;
+
+ if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
+ return MODE_11AC_VHT40;
+
+ if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
+ return MODE_11AC_VHT20;
+
+ return MODE_UNKNOWN;
+}
+
static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct wmi_peer_assoc_complete_arg *arg)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct cfg80211_chan_def def;
enum nl80211_band band;
const u8 *ht_mcs_mask;
@@ -2546,12 +2615,7 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
*/
if (sta->vht_cap.vht_supported &&
!ath10k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
- if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
- phymode = MODE_11AC_VHT80;
- else if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
- phymode = MODE_11AC_VHT40;
- else if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
- phymode = MODE_11AC_VHT20;
+ phymode = ath10k_mac_get_phymode_vht(ar, sta);
} else if (sta->ht_cap.ht_supported &&
!ath10k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
if (sta->bandwidth >= IEEE80211_STA_RX_BW_40)
@@ -2625,7 +2689,7 @@ static int ath10k_mac_vif_recalc_txbf(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta_vht_cap vht_cap)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
int ret;
u32 param;
u32 value;
@@ -2692,7 +2756,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *bss_conf)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ieee80211_sta_ht_cap ht_cap;
struct ieee80211_sta_vht_cap vht_cap;
struct wmi_peer_assoc_complete_arg peer_arg;
@@ -2785,7 +2849,7 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ieee80211_sta_vht_cap vht_cap = {};
int ret;
@@ -2818,7 +2882,7 @@ static int ath10k_station_assoc(struct ath10k *ar,
struct ieee80211_sta *sta,
bool reassoc)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct wmi_peer_assoc_complete_arg peer_arg;
int ret = 0;
@@ -2885,7 +2949,7 @@ static int ath10k_station_disassoc(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
int ret = 0;
lockdep_assert_held(&ar->conf_mutex);
@@ -3111,7 +3175,7 @@ static void ath10k_mac_tx_unlock_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
struct ath10k *ar = data;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
if (arvif->tx_paused)
return;
@@ -3198,7 +3262,7 @@ struct ath10k_mac_tx_pause {
static void ath10k_mac_handle_tx_pause_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_mac_tx_pause *arg = data;
if (arvif->vdev_id != arg->vdev_id)
@@ -3294,7 +3358,7 @@ static bool ath10k_tx_h_use_hwcrypto(struct ieee80211_vif *vif,
return false;
if (vif)
- return !ath10k_vif_to_arvif(vif)->nohwcrypt;
+ return !((struct ath10k_vif *)vif->drv_priv)->nohwcrypt;
return true;
}
@@ -3359,7 +3423,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
/* This is case only for P2P_GO */
if (vif->type != NL80211_IFTYPE_AP || !vif->p2p)
@@ -3495,7 +3559,6 @@ static int ath10k_mac_tx_submit(struct ath10k *ar,
*/
static int ath10k_mac_tx(struct ath10k *ar,
struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
enum ath10k_hw_txrx_mode txmode,
enum ath10k_mac_tx_path txpath,
struct sk_buff *skb)
@@ -3637,7 +3700,7 @@ void ath10k_offchan_tx_work(struct work_struct *work)
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
txpath = ath10k_mac_tx_h_get_txpath(ar, skb, txmode);
- ret = ath10k_mac_tx(ar, vif, sta, txmode, txpath, skb);
+ ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
if (ret) {
ath10k_warn(ar, "failed to transmit offchannel frame: %d\n",
ret);
@@ -3742,6 +3805,9 @@ struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar,
if (!peer)
return NULL;
+ if (peer->removed)
+ return NULL;
+
if (peer->sta)
return peer->sta->txq[tid];
else if (peer->vif)
@@ -3824,7 +3890,7 @@ int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
spin_unlock_bh(&ar->htt.tx_lock);
}
- ret = ath10k_mac_tx(ar, vif, sta, txmode, txpath, skb);
+ ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
if (unlikely(ret)) {
ath10k_warn(ar, "failed to push frame: %d\n", ret);
@@ -4105,7 +4171,7 @@ static void ath10k_mac_op_tx(struct ieee80211_hw *hw,
spin_unlock_bh(&ar->htt.tx_lock);
}
- ret = ath10k_mac_tx(ar, vif, sta, txmode, txpath, skb);
+ ret = ath10k_mac_tx(ar, vif, txmode, txpath, skb);
if (ret) {
ath10k_warn(ar, "failed to transmit frame: %d\n", ret);
if (is_htt) {
@@ -4279,6 +4345,13 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
vht_cap.cap |= val;
}
+ /* Currently the firmware seems to be buggy, don't enable 80+80
+ * mode until that's resolved.
+ */
+ if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SHORT_GI_160) &&
+ !(ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
+ vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+
mcs_map = 0;
for (i = 0; i < 8; i++) {
if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
@@ -4669,7 +4742,8 @@ static int ath10k_mac_txpower_recalc(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex);
list_for_each_entry(arvif, &ar->arvifs, list) {
- WARN_ON(arvif->txpower < 0);
+ if (arvif->txpower <= 0)
+ continue;
if (txpower == -1)
txpower = arvif->txpower;
@@ -4677,8 +4751,8 @@ static int ath10k_mac_txpower_recalc(struct ath10k *ar)
txpower = min(txpower, arvif->txpower);
}
- if (WARN_ON(txpower == -1))
- return -EINVAL;
+ if (txpower == -1)
+ return 0;
ret = ath10k_mac_txpower_setup(ar, txpower);
if (ret) {
@@ -4775,7 +4849,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_peer *peer;
enum wmi_sta_powersave_param param;
int ret = 0;
@@ -5111,7 +5185,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_peer *peer;
int ret;
int i;
@@ -5194,6 +5268,10 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
ath10k_warn(ar, "failed to recalc monitor: %d\n", ret);
}
+ ret = ath10k_mac_txpower_recalc(ar);
+ if (ret)
+ ath10k_warn(ar, "failed to recalc tx power: %d\n", ret);
+
spin_lock_bh(&ar->htt.tx_lock);
ath10k_mac_vif_tx_unlock_all(arvif);
spin_unlock_bh(&ar->htt.tx_lock);
@@ -5242,7 +5320,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
u32 changed)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
int ret = 0;
u32 vdev_param, pdev_param, slottime, preamble;
@@ -5328,20 +5406,18 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_ERP_CTS_PROT) {
arvif->use_cts_prot = info->use_cts_prot;
- ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d cts_prot %d\n",
- arvif->vdev_id, info->use_cts_prot);
ret = ath10k_recalc_rtscts_prot(arvif);
if (ret)
ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n",
arvif->vdev_id, ret);
- vdev_param = ar->wmi.vdev_param->protection_mode;
- ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
- info->use_cts_prot ? 1 : 0);
- if (ret)
- ath10k_warn(ar, "failed to set protection mode %d on vdev %i: %d\n",
- info->use_cts_prot, arvif->vdev_id, ret);
+ if (ath10k_mac_can_set_cts_prot(arvif)) {
+ ret = ath10k_mac_set_cts_prot(arvif);
+ if (ret)
+ ath10k_warn(ar, "failed to set cts protection for vdev %d: %d\n",
+ arvif->vdev_id, ret);
+ }
}
if (changed & BSS_CHANGED_ERP_SLOT) {
@@ -5436,7 +5512,7 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_scan_request *hw_req)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct cfg80211_scan_request *req = &hw_req->req;
struct wmi_start_scan_arg arg;
int ret = 0;
@@ -5568,7 +5644,7 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_key_conf *key)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_peer *peer;
const u8 *peer_addr;
bool is_wep = key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
@@ -5707,7 +5783,7 @@ static void ath10k_set_default_unicast_key(struct ieee80211_hw *hw,
int keyidx)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
int ret;
mutex_lock(&arvif->ar->conf_mutex);
@@ -5888,7 +5964,7 @@ static int ath10k_mac_tdls_vif_stations_count(struct ieee80211_hw *hw,
static void ath10k_mac_tdls_vifs_count_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
int *num_tdls_vifs = data;
if (vif->type != NL80211_IFTYPE_STATION)
@@ -5916,7 +5992,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
enum ieee80211_sta_state new_state)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
struct ath10k_peer *peer;
int ret = 0;
@@ -6151,7 +6227,7 @@ exit:
static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif,
u16 ac, bool enable)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct wmi_sta_uapsd_auto_trig_arg arg = {};
u32 prio = 0, acc = 0;
u32 value = 0;
@@ -6259,7 +6335,7 @@ static int ath10k_conf_tx(struct ieee80211_hw *hw,
const struct ieee80211_tx_queue_params *params)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct wmi_wmm_params_arg *p = NULL;
int ret;
@@ -6333,7 +6409,7 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw,
enum ieee80211_roc_type type)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct wmi_start_scan_arg arg;
int ret = 0;
u32 scan_time_msec;
@@ -6833,7 +6909,7 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
const struct cfg80211_bitrate_mask *mask)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct cfg80211_chan_def def;
struct ath10k *ar = arvif->ar;
enum nl80211_band band;
@@ -6934,6 +7010,9 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
bw = WMI_PEER_CHWIDTH_80MHZ;
break;
case IEEE80211_STA_RX_BW_160:
+ bw = WMI_PEER_CHWIDTH_160MHZ;
+ break;
+ default:
ath10k_warn(ar, "Invalid bandwidth %d in rc update for %pM\n",
sta->bandwidth, sta->addr);
bw = WMI_PEER_CHWIDTH_20MHZ;
@@ -6981,7 +7060,7 @@ static void ath10k_offset_tsf(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, s64 tsf_offset)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
u32 offset, vdev_param;
int ret;
@@ -7006,7 +7085,7 @@ static int ath10k_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_ampdu_params *params)
{
struct ath10k *ar = hw->priv;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ieee80211_sta *sta = params->sta;
enum ieee80211_ampdu_mlme_action action = params->action;
u16 tid = params->tid;
@@ -7104,7 +7183,7 @@ ath10k_mac_update_vif_chan(struct ath10k *ar,
ath10k_monitor_stop(ar);
for (i = 0; i < n_vifs; i++) {
- arvif = ath10k_vif_to_arvif(vifs[i].vif);
+ arvif = (void *)vifs[i].vif->drv_priv;
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n",
@@ -7137,7 +7216,7 @@ ath10k_mac_update_vif_chan(struct ath10k *ar,
spin_unlock_bh(&ar->data_lock);
for (i = 0; i < n_vifs; i++) {
- arvif = ath10k_vif_to_arvif(vifs[i].vif);
+ arvif = (void *)vifs[i].vif->drv_priv;
if (WARN_ON(!arvif->is_started))
continue;
@@ -7364,6 +7443,13 @@ ath10k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
arvif->is_up = true;
}
+ if (ath10k_mac_can_set_cts_prot(arvif)) {
+ ret = ath10k_mac_set_cts_prot(arvif);
+ if (ret)
+ ath10k_warn(ar, "failed to set cts protection for vdev %d: %d\n",
+ arvif->vdev_id, ret);
+ }
+
mutex_unlock(&ar->conf_mutex);
return 0;
@@ -7434,6 +7520,20 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw,
return 0;
}
+static void ath10k_mac_op_sta_pre_rcu_remove(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta)
+{
+ struct ath10k *ar;
+ struct ath10k_peer *peer;
+
+ ar = hw->priv;
+
+ list_for_each_entry(peer, &ar->peers, list)
+ if (peer->sta == sta)
+ peer->removed = true;
+}
+
static const struct ieee80211_ops ath10k_ops = {
.tx = ath10k_mac_op_tx,
.wake_tx_queue = ath10k_mac_op_wake_tx_queue,
@@ -7474,6 +7574,7 @@ static const struct ieee80211_ops ath10k_ops = {
.assign_vif_chanctx = ath10k_mac_op_assign_vif_chanctx,
.unassign_vif_chanctx = ath10k_mac_op_unassign_vif_chanctx,
.switch_vif_chanctx = ath10k_mac_op_switch_vif_chanctx,
+ .sta_pre_rcu_remove = ath10k_mac_op_sta_pre_rcu_remove,
CFG80211_TESTMODE_CMD(ath10k_tm_cmd)
@@ -7548,6 +7649,7 @@ static const struct ieee80211_channel ath10k_5ghz_channels[] = {
CHAN5G(157, 5785, 0),
CHAN5G(161, 5805, 0),
CHAN5G(165, 5825, 0),
+ CHAN5G(169, 5845, 0),
};
struct ath10k *ath10k_mac_create(size_t priv_size)
@@ -7771,7 +7873,7 @@ static void ath10k_get_arvif_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
struct ath10k_vif_iter *arvif_iter = data;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
if (arvif->vdev_id == arvif_iter->vdev_id)
arvif_iter->arvif = arvif;
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h
index 1bd29ecfcdcc..553747bc19ed 100644
--- a/drivers/net/wireless/ath/ath10k/mac.h
+++ b/drivers/net/wireless/ath/ath10k/mac.h
@@ -83,17 +83,12 @@ struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar,
u8 tid);
int ath10k_mac_ext_resource_config(struct ath10k *ar, u32 val);
-static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
-{
- return (struct ath10k_vif *)vif->drv_priv;
-}
-
static inline void ath10k_tx_h_seq_no(struct ieee80211_vif *vif,
struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
if (arvif->tx_seq_no == 0)
diff --git a/drivers/net/wireless/ath/ath10k/p2p.c b/drivers/net/wireless/ath/ath10k/p2p.c
index c0b6ffaf3ec1..7e621ee194e3 100644
--- a/drivers/net/wireless/ath/ath10k/p2p.c
+++ b/drivers/net/wireless/ath/ath10k/p2p.c
@@ -132,7 +132,7 @@ struct ath10k_p2p_noa_arg {
static void ath10k_p2p_noa_update_vdev_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
struct ath10k_p2p_noa_arg *arg = data;
if (arvif->vdev_id != arg->vdev_id)
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index b541a1c74488..6094372307aa 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -840,31 +840,35 @@ void ath10k_pci_rx_replenish_retry(unsigned long ptr)
ath10k_pci_rx_post(ar);
}
-static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
+static u32 ath10k_pci_qca988x_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
{
- u32 val = 0;
+ u32 val = 0, region = addr & 0xfffff;
- switch (ar->hw_rev) {
- case ATH10K_HW_QCA988X:
- case ATH10K_HW_QCA9887:
- case ATH10K_HW_QCA6174:
- case ATH10K_HW_QCA9377:
- val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
- CORE_CTRL_ADDRESS) &
- 0x7ff) << 21;
- break;
- case ATH10K_HW_QCA9888:
- case ATH10K_HW_QCA99X0:
- case ATH10K_HW_QCA9984:
- case ATH10K_HW_QCA4019:
- val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS);
- break;
- }
+ val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS)
+ & 0x7ff) << 21;
+ val |= 0x100000 | region;
+ return val;
+}
- val |= 0x100000 | (addr & 0xfffff);
+static u32 ath10k_pci_qca99x0_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
+{
+ u32 val = 0, region = addr & 0xfffff;
+
+ val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS);
+ val |= 0x100000 | region;
return val;
}
+static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr)
+{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+ if (WARN_ON_ONCE(!ar_pci->targ_cpu_to_ce_addr))
+ return -ENOTSUPP;
+
+ return ar_pci->targ_cpu_to_ce_addr(ar, addr);
+}
+
/*
* Diagnostic read/write access is provided for startup/config/debug usage.
* Caller must guarantee proper alignment, when applicable, and single user
@@ -896,7 +900,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
*/
alloc_nbytes = min_t(unsigned int, nbytes, DIAG_TRANSFER_LIMIT);
- data_buf = (unsigned char *)dma_alloc_coherent(ar->dev,
+ data_buf = (unsigned char *)dma_zalloc_coherent(ar->dev,
alloc_nbytes,
&ce_data_base,
GFP_ATOMIC);
@@ -905,7 +909,6 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
ret = -ENOMEM;
goto done;
}
- memset(data_buf, 0, alloc_nbytes);
remaining_bytes = nbytes;
ce_data = ce_data_base;
@@ -1474,6 +1477,7 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar)
ath10k_err(ar, "firmware crashed! (uuid %s)\n", uuid);
ath10k_print_driver_info(ar);
ath10k_pci_dump_registers(ar, crash_data);
+ ath10k_ce_dump_registers(ar, crash_data);
spin_unlock_bh(&ar->data_lock);
@@ -1590,7 +1594,7 @@ void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
/* TODO: Find appropriate register configuration for QCA99X0
* to mask irq/MSI.
*/
- break;
+ break;
}
}
@@ -1647,6 +1651,8 @@ static int ath10k_pci_hif_start(struct ath10k *ar)
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif start\n");
+ napi_enable(&ar->napi);
+
ath10k_pci_irq_enable(ar);
ath10k_pci_rx_post(ar);
@@ -1937,7 +1943,7 @@ static int ath10k_pci_wake_target_cpu(struct ath10k *ar)
{
u32 addr, val;
- addr = SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS;
+ addr = SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS;
val = ath10k_pci_read32(ar, addr);
val |= CORE_CTRL_CPU_INTR_MASK;
ath10k_pci_write32(ar, addr, val);
@@ -1973,7 +1979,7 @@ static int ath10k_pci_get_num_banks(struct ath10k *ar)
}
break;
case QCA9377_1_0_DEVICE_ID:
- return 2;
+ return 4;
}
ath10k_warn(ar, "unknown number of banks, assuming 1\n");
@@ -2531,7 +2537,6 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
ath10k_err(ar, "could not wake up target CPU: %d\n", ret);
goto err_ce;
}
- napi_enable(&ar->napi);
return 0;
@@ -2799,7 +2804,7 @@ static int ath10k_pci_napi_poll(struct napi_struct *ctx, int budget)
done = ath10k_htt_txrx_compl_task(ar, budget);
if (done < budget) {
- napi_complete(ctx);
+ napi_complete_done(ctx, done);
/* In case of MSI, it is possible that interrupts are received
* while NAPI poll is inprogress. So pending interrupts that are
* received after processing all copy engine pipes by NAPI poll
@@ -3132,7 +3137,7 @@ int ath10k_pci_setup_resource(struct ath10k *ar)
setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry,
(unsigned long)ar);
- if (QCA_REV_6174(ar))
+ if (QCA_REV_6174(ar) || QCA_REV_9377(ar))
ath10k_pci_override_ce_config(ar);
ret = ath10k_pci_alloc_pipes(ar);
@@ -3170,6 +3175,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
bool pci_ps;
int (*pci_soft_reset)(struct ath10k *ar);
int (*pci_hard_reset)(struct ath10k *ar);
+ u32 (*targ_cpu_to_ce_addr)(struct ath10k *ar, u32 addr);
switch (pci_dev->device) {
case QCA988X_2_0_DEVICE_ID:
@@ -3177,12 +3183,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
pci_ps = false;
pci_soft_reset = ath10k_pci_warm_reset;
pci_hard_reset = ath10k_pci_qca988x_chip_reset;
+ targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr;
break;
case QCA9887_1_0_DEVICE_ID:
hw_rev = ATH10K_HW_QCA9887;
pci_ps = false;
pci_soft_reset = ath10k_pci_warm_reset;
pci_hard_reset = ath10k_pci_qca988x_chip_reset;
+ targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr;
break;
case QCA6164_2_1_DEVICE_ID:
case QCA6174_2_1_DEVICE_ID:
@@ -3190,30 +3198,35 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
pci_ps = true;
pci_soft_reset = ath10k_pci_warm_reset;
pci_hard_reset = ath10k_pci_qca6174_chip_reset;
+ targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr;
break;
case QCA99X0_2_0_DEVICE_ID:
hw_rev = ATH10K_HW_QCA99X0;
pci_ps = false;
pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset;
pci_hard_reset = ath10k_pci_qca99x0_chip_reset;
+ targ_cpu_to_ce_addr = ath10k_pci_qca99x0_targ_cpu_to_ce_addr;
break;
case QCA9984_1_0_DEVICE_ID:
hw_rev = ATH10K_HW_QCA9984;
pci_ps = false;
pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset;
pci_hard_reset = ath10k_pci_qca99x0_chip_reset;
+ targ_cpu_to_ce_addr = ath10k_pci_qca99x0_targ_cpu_to_ce_addr;
break;
case QCA9888_2_0_DEVICE_ID:
hw_rev = ATH10K_HW_QCA9888;
pci_ps = false;
pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset;
pci_hard_reset = ath10k_pci_qca99x0_chip_reset;
+ targ_cpu_to_ce_addr = ath10k_pci_qca99x0_targ_cpu_to_ce_addr;
break;
case QCA9377_1_0_DEVICE_ID:
hw_rev = ATH10K_HW_QCA9377;
pci_ps = true;
pci_soft_reset = NULL;
pci_hard_reset = ath10k_pci_qca6174_chip_reset;
+ targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr;
break;
default:
WARN_ON(1);
@@ -3240,6 +3253,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
ar_pci->bus_ops = &ath10k_pci_bus_ops;
ar_pci->pci_soft_reset = pci_soft_reset;
ar_pci->pci_hard_reset = pci_hard_reset;
+ ar_pci->targ_cpu_to_ce_addr = targ_cpu_to_ce_addr;
ar->id.vendor = pdev->vendor;
ar->id.device = pdev->device;
diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h
index 9854ad56b2de..c1e08ad63940 100644
--- a/drivers/net/wireless/ath/ath10k/pci.h
+++ b/drivers/net/wireless/ath/ath10k/pci.h
@@ -25,11 +25,6 @@
#include "ahb.h"
/*
- * maximum number of bytes that can be handled atomically by DiagRead/DiagWrite
- */
-#define DIAG_TRANSFER_LIMIT 2048
-
-/*
* maximum number of bytes that can be
* handled atomically by DiagRead/DiagWrite
*/
@@ -238,6 +233,11 @@ struct ath10k_pci {
/* Chip specific pci full reset function */
int (*pci_hard_reset)(struct ath10k *ar);
+ /* chip specific methods for converting target CPU virtual address
+ * space to CE address space
+ */
+ u32 (*targ_cpu_to_ce_addr)(struct ath10k *ar, u32 addr);
+
/* Keep this entry in the last, memory for struct ath10k_ahb is
* allocated (ahb support enabled case) in the continuation of
* this struct.
diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
index 2ffc1fe4923b..c061d6958bd1 100644
--- a/drivers/net/wireless/ath/ath10k/spectral.c
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -278,7 +278,7 @@ static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
{
struct ath10k *ar = file->private_data;
char *mode = "";
- unsigned int len;
+ size_t len;
enum ath10k_spectral_mode spectral_mode;
mutex_lock(&ar->conf_mutex);
@@ -370,7 +370,7 @@ static ssize_t read_file_spectral_count(struct file *file,
{
struct ath10k *ar = file->private_data;
char buf[32];
- unsigned int len;
+ size_t len;
u8 spectral_count;
mutex_lock(&ar->conf_mutex);
@@ -422,7 +422,8 @@ static ssize_t read_file_spectral_bins(struct file *file,
{
struct ath10k *ar = file->private_data;
char buf[32];
- unsigned int len, bins, fft_size, bin_scale;
+ unsigned int bins, fft_size, bin_scale;
+ size_t len;
mutex_lock(&ar->conf_mutex);
diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c
index ed85f938e3c0..8bb36c18a749 100644
--- a/drivers/net/wireless/ath/ath10k/testmode.c
+++ b/drivers/net/wireless/ath/ath10k/testmode.c
@@ -150,7 +150,10 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar,
ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
/* load utf firmware image */
- ret = request_firmware(&fw_file->firmware, filename, ar->dev);
+ ret = request_firmware_direct(&fw_file->firmware, filename, ar->dev);
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode fw request '%s': %d\n",
+ filename, ret);
+
if (ret) {
ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
filename, ret);
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index f304f6632c4f..f9188027a6f6 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -1105,8 +1105,10 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
struct ath10k_fw_stats_pdev *dst;
src = data;
- if (data_len < sizeof(*src))
+ if (data_len < sizeof(*src)) {
+ kfree(tb);
return -EPROTO;
+ }
data += sizeof(*src);
data_len -= sizeof(*src);
@@ -1126,8 +1128,10 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
struct ath10k_fw_stats_vdev *dst;
src = data;
- if (data_len < sizeof(*src))
+ if (data_len < sizeof(*src)) {
+ kfree(tb);
return -EPROTO;
+ }
data += sizeof(*src);
data_len -= sizeof(*src);
@@ -1145,8 +1149,10 @@ static int ath10k_wmi_tlv_op_pull_fw_stats(struct ath10k *ar,
struct ath10k_fw_stats_peer *dst;
src = data;
- if (data_len < sizeof(*src))
+ if (data_len < sizeof(*src)) {
+ kfree(tb);
return -EPROTO;
+ }
data += sizeof(*src);
data_len -= sizeof(*src);
@@ -3631,6 +3637,7 @@ static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
.vht = WMI_TLV_PEER_VHT,
.bw80 = WMI_TLV_PEER_80MHZ,
.pmf = WMI_TLV_PEER_PMF,
+ .bw160 = WMI_TLV_PEER_160MHZ,
};
/************/
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index b8aa6000573c..22cf011e839a 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -543,6 +543,7 @@ enum wmi_tlv_peer_flags {
WMI_TLV_PEER_VHT = 0x02000000,
WMI_TLV_PEER_80MHZ = 0x04000000,
WMI_TLV_PEER_PMF = 0x08000000,
+ WMI_TLV_PEER_160MHZ = 0x20000000,
};
enum wmi_tlv_tag {
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 50d6ee6afe26..2f1743e60fa1 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -28,6 +28,7 @@
#include "wmi-ops.h"
#include "p2p.h"
#include "hw.h"
+#include "hif.h"
#define ATH10K_WMI_BARRIER_ECHO_ID 0xBA991E9
#define ATH10K_WMI_BARRIER_TIMEOUT_HZ (3 * HZ)
@@ -1574,6 +1575,7 @@ static const struct wmi_peer_flags_map wmi_peer_flags_map = {
.bw80 = WMI_PEER_80MHZ,
.vht_2g = WMI_PEER_VHT_2G,
.pmf = WMI_PEER_PMF,
+ .bw160 = WMI_PEER_160MHZ,
};
static const struct wmi_peer_flags_map wmi_10x_peer_flags_map = {
@@ -1591,6 +1593,7 @@ static const struct wmi_peer_flags_map wmi_10x_peer_flags_map = {
.spatial_mux = WMI_10X_PEER_SPATIAL_MUX,
.vht = WMI_10X_PEER_VHT,
.bw80 = WMI_10X_PEER_80MHZ,
+ .bw160 = WMI_10X_PEER_160MHZ,
};
static const struct wmi_peer_flags_map wmi_10_2_peer_flags_map = {
@@ -1610,6 +1613,7 @@ static const struct wmi_peer_flags_map wmi_10_2_peer_flags_map = {
.bw80 = WMI_10_2_PEER_80MHZ,
.vht_2g = WMI_10_2_PEER_VHT_2G,
.pmf = WMI_10_2_PEER_PMF,
+ .bw160 = WMI_10_2_PEER_160MHZ,
};
void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
@@ -1634,7 +1638,10 @@ void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
ch->mhz = __cpu_to_le32(arg->freq);
ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1);
- ch->band_center_freq2 = 0;
+ if (arg->mode == MODE_11AC_VHT80_80)
+ ch->band_center_freq2 = __cpu_to_le32(arg->band_center_freq2);
+ else
+ ch->band_center_freq2 = 0;
ch->min_power = arg->min_power;
ch->max_power = arg->max_power;
ch->reg_power = arg->max_reg_power;
@@ -1772,7 +1779,7 @@ unlock:
static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
+ struct ath10k_vif *arvif = (void *)vif->drv_priv;
ath10k_wmi_tx_beacon_nowait(arvif);
}
@@ -2319,7 +2326,7 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
*/
if (channel >= 1 && channel <= 14) {
status->band = NL80211_BAND_2GHZ;
- } else if (channel >= 36 && channel <= 165) {
+ } else if (channel >= 36 && channel <= 169) {
status->band = NL80211_BAND_5GHZ;
} else {
/* Shouldn't happen unless list of advertised channels to
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 5d3dff95b2e5..386aa51435f1 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -75,7 +75,7 @@ struct wmi_cmd_hdr {
/*
* There is no signed version of __le32, so for a temporary solution come
- * up with our own version. The idea is from fs/ntfs/types.h.
+ * up with our own version. The idea is from fs/ntfs/endian.h.
*
* Use a_ prefix so that it doesn't conflict if we get proper support to
* linux/types.h.
@@ -1728,8 +1728,10 @@ enum wmi_phy_mode {
MODE_11AC_VHT20_2G = 11,
MODE_11AC_VHT40_2G = 12,
MODE_11AC_VHT80_2G = 13,
- MODE_UNKNOWN = 14,
- MODE_MAX = 14
+ MODE_11AC_VHT80_80 = 14,
+ MODE_11AC_VHT160 = 15,
+ MODE_UNKNOWN = 16,
+ MODE_MAX = 16
};
static inline const char *ath10k_wmi_phymode_str(enum wmi_phy_mode mode)
@@ -1757,6 +1759,10 @@ static inline const char *ath10k_wmi_phymode_str(enum wmi_phy_mode mode)
return "11ac-vht40";
case MODE_11AC_VHT80:
return "11ac-vht80";
+ case MODE_11AC_VHT160:
+ return "11ac-vht160";
+ case MODE_11AC_VHT80_80:
+ return "11ac-vht80+80";
case MODE_11AC_VHT20_2G:
return "11ac-vht20-2g";
case MODE_11AC_VHT40_2G:
@@ -1811,6 +1817,7 @@ struct wmi_channel {
struct wmi_channel_arg {
u32 freq;
u32 band_center_freq1;
+ u32 band_center_freq2;
bool passive;
bool allow_ibss;
bool allow_ht;
@@ -1875,9 +1882,18 @@ enum wmi_channel_change_cause {
#define WMI_VHT_CAP_MAX_MPDU_LEN_MASK 0x00000003
#define WMI_VHT_CAP_RX_LDPC 0x00000010
#define WMI_VHT_CAP_SGI_80MHZ 0x00000020
+#define WMI_VHT_CAP_SGI_160MHZ 0x00000040
#define WMI_VHT_CAP_TX_STBC 0x00000080
#define WMI_VHT_CAP_RX_STBC_MASK 0x00000300
#define WMI_VHT_CAP_RX_STBC_MASK_SHIFT 8
+#define WMI_VHT_CAP_SU_BFER 0x00000800
+#define WMI_VHT_CAP_SU_BFEE 0x00001000
+#define WMI_VHT_CAP_MAX_CS_ANT_MASK 0x0000E000
+#define WMI_VHT_CAP_MAX_CS_ANT_MASK_SHIFT 13
+#define WMI_VHT_CAP_MAX_SND_DIM_MASK 0x00070000
+#define WMI_VHT_CAP_MAX_SND_DIM_MASK_SHIFT 16
+#define WMI_VHT_CAP_MU_BFER 0x00080000
+#define WMI_VHT_CAP_MU_BFEE 0x00100000
#define WMI_VHT_CAP_MAX_AMPDU_LEN_EXP 0x03800000
#define WMI_VHT_CAP_MAX_AMPDU_LEN_EXP_SHIFT 23
#define WMI_VHT_CAP_RX_FIXED_ANT 0x10000000
@@ -1926,6 +1942,8 @@ enum {
REGDMN_MODE_11AC_VHT40PLUS = 0x40000, /* 5Ghz, VHT40 + channels */
REGDMN_MODE_11AC_VHT40MINUS = 0x80000, /* 5Ghz VHT40 - channels */
REGDMN_MODE_11AC_VHT80 = 0x100000, /* 5Ghz, VHT80 channels */
+ REGDMN_MODE_11AC_VHT160 = 0x200000, /* 5Ghz, VHT160 channels */
+ REGDMN_MODE_11AC_VHT80_80 = 0x400000, /* 5Ghz, VHT80+80 channels */
REGDMN_MODE_ALL = 0xffffffff
};
@@ -5783,6 +5801,7 @@ enum wmi_peer_chwidth {
WMI_PEER_CHWIDTH_20MHZ = 0,
WMI_PEER_CHWIDTH_40MHZ = 1,
WMI_PEER_CHWIDTH_80MHZ = 2,
+ WMI_PEER_CHWIDTH_160MHZ = 3,
};
enum wmi_peer_param {
@@ -5792,6 +5811,7 @@ enum wmi_peer_param {
WMI_PEER_CHAN_WIDTH = 0x4,
WMI_PEER_NSS = 0x5,
WMI_PEER_USE_4ADDR = 0x6,
+ WMI_PEER_DEBUG = 0xa,
WMI_PEER_DUMMY_VAR = 0xff, /* dummy parameter for STA PS workaround */
};
@@ -5873,6 +5893,7 @@ struct wmi_peer_flags_map {
u32 bw80;
u32 vht_2g;
u32 pmf;
+ u32 bw160;
};
enum wmi_peer_flags {
@@ -5892,6 +5913,7 @@ enum wmi_peer_flags {
WMI_PEER_80MHZ = 0x04000000,
WMI_PEER_VHT_2G = 0x08000000,
WMI_PEER_PMF = 0x10000000,
+ WMI_PEER_160MHZ = 0x20000000
};
enum wmi_10x_peer_flags {
@@ -5909,6 +5931,7 @@ enum wmi_10x_peer_flags {
WMI_10X_PEER_SPATIAL_MUX = 0x00200000,
WMI_10X_PEER_VHT = 0x02000000,
WMI_10X_PEER_80MHZ = 0x04000000,
+ WMI_10X_PEER_160MHZ = 0x20000000
};
enum wmi_10_2_peer_flags {
@@ -5928,6 +5951,7 @@ enum wmi_10_2_peer_flags {
WMI_10_2_PEER_80MHZ = 0x04000000,
WMI_10_2_PEER_VHT_2G = 0x08000000,
WMI_10_2_PEER_PMF = 0x10000000,
+ WMI_10_2_PEER_160MHZ = 0x20000000
};
/*
@@ -6581,7 +6605,7 @@ struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb,
u32 cmd_id);
-void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *);
+void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *arg);
void ath10k_wmi_pull_pdev_stats_base(const struct wmi_pdev_stats_base *src,
struct ath10k_fw_stats_pdev *dst);