aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2014-09-26 13:35:46 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-09-26 13:35:46 -0400
commit687b93082c0469fe9fe85583e6265a3d910cd89a (patch)
tree2069814b550be9e4cb194a658b2c3f91198efb3f /drivers/net/wireless/ath
parentd3d3e0017fcc2c3c8e5f6a229f4b65f8bcc15bae (diff)
parentb25f32cb02155d68c690255ba846796a1c248fd3 (diff)
Merge branch 'for-linville' of git://github.com/kvalo/ath
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath10k/Kconfig2
-rw-r--r--drivers/net/wireless/ath/ath10k/Makefile1
-rw-r--r--drivers/net/wireless/ath/ath10k/bmi.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c106
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h25
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c102
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h12
-rw-r--r--drivers/net/wireless/ath/ath10k/hif.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.c10
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c54
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h2
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c192
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c183
-rw-r--r--drivers/net/wireless/ath/ath10k/rx_desc.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/targaddrs.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/testmode.c382
-rw-r--r--drivers/net/wireless/ath/ath10k/testmode.h46
-rw-r--r--drivers/net/wireless/ath/ath10k/testmode_i.h70
-rw-r--r--drivers/net/wireless/ath/ath10k/trace.h105
-rw-r--r--drivers/net/wireless/ath/ath10k/txrx.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c103
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h33
28 files changed, 1017 insertions, 440 deletions
diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index 1053bb5f2cdc..72acb822bb11 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -24,7 +24,7 @@ config ATH10K_DEBUG
config ATH10K_DEBUGFS
bool "Atheros ath10k debugfs support"
- depends on ATH10K
+ depends on ATH10K && DEBUG_FS
select RELAY
---help---
Enabled debugfs support
diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile
index 2cfb63ca9327..8b1b1adb477a 100644
--- a/drivers/net/wireless/ath/ath10k/Makefile
+++ b/drivers/net/wireless/ath/ath10k/Makefile
@@ -11,6 +11,7 @@ ath10k_core-y += mac.o \
bmi.o
ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o
+ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o
obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o
diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h
index 111ab701465c..31a990635490 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.h
+++ b/drivers/net/wireless/ath/ath10k/bmi.h
@@ -177,7 +177,6 @@ struct bmi_target_info {
u32 type;
};
-
/* in msec */
#define BMI_COMMUNICATION_TIMEOUT_HZ (1*HZ)
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index 71eef233bd01..101cadb6e4ba 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -260,7 +260,6 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
ath10k_pci_write32(ar, ce_ctrl_addr + HOST_IS_ADDRESS, mask);
}
-
/*
* Guts of ath10k_ce_send, used by both ath10k_ce_send and
* ath10k_ce_sendlist_send.
@@ -385,7 +384,6 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe)
return delta;
}
-
int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe)
{
struct ath10k *ar = pipe->ar;
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index 82d1f23546b9..329b7340fa72 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -20,7 +20,6 @@
#include "hif.h"
-
/* Maximum number of Copy Engine's supported */
#define CE_COUNT_MAX 8
#define CE_HTT_H2T_MSG_SRC_NENTRIES 4096
@@ -37,7 +36,6 @@
struct ath10k_ce_pipe;
-
#define CE_DESC_FLAGS_GATHER (1 << 0)
#define CE_DESC_FLAGS_BYTE_SWAP (1 << 1)
#define CE_DESC_FLAGS_META_DATA_MASK 0xFFFC
@@ -189,10 +187,10 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
* Pops 1 completed send buffer from Source ring.
*/
int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
- void **per_transfer_contextp,
- u32 *bufferp,
- unsigned int *nbytesp,
- unsigned int *transfer_idp);
+ void **per_transfer_contextp,
+ u32 *bufferp,
+ unsigned int *nbytesp,
+ unsigned int *transfer_idp);
/*==================CE Engine Initialization=======================*/
@@ -202,7 +200,7 @@ int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
void (*recv_cb)(struct ath10k_ce_pipe *));
void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id);
int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
- const struct ce_attr *attr);
+ const struct ce_attr *attr);
void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id);
/*==================CE Engine Shutdown=======================*/
@@ -383,7 +381,6 @@ struct ce_attr {
#define DST_WATERMARK_HIGH_RESET 0
#define DST_WATERMARK_ADDRESS 0x0050
-
static inline u32 ath10k_ce_base_address(unsigned int ce_id)
{
return CE0_BASE_ADDRESS + (CE1_BASE_ADDRESS - CE0_BASE_ADDRESS) * ce_id;
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 651a6da8adf5..cee18c89d7f2 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -26,6 +26,7 @@
#include "bmi.h"
#include "debug.h"
#include "htt.h"
+#include "testmode.h"
unsigned int ath10k_debug_mask;
static bool uart_print;
@@ -257,21 +258,42 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
return 0;
}
-static int ath10k_download_fw(struct ath10k *ar)
+static int ath10k_download_fw(struct ath10k *ar, enum ath10k_firmware_mode mode)
{
- u32 address;
+ u32 address, data_len;
+ const char *mode_name;
+ const void *data;
int ret;
address = ar->hw_params.patch_load_addr;
- ret = ath10k_bmi_fast_download(ar, address, ar->firmware_data,
- ar->firmware_len);
+ switch (mode) {
+ case ATH10K_FIRMWARE_MODE_NORMAL:
+ data = ar->firmware_data;
+ data_len = ar->firmware_len;
+ mode_name = "normal";
+ break;
+ case ATH10K_FIRMWARE_MODE_UTF:
+ data = ar->testmode.utf->data;
+ data_len = ar->testmode.utf->size;
+ mode_name = "utf";
+ break;
+ default:
+ ath10k_err(ar, "unknown firmware mode: %d\n", mode);
+ return -EINVAL;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT,
+ "boot uploading firmware image %p len %d mode %s\n",
+ data, data_len, mode_name);
+
+ ret = ath10k_bmi_fast_download(ar, address, data, data_len);
if (ret) {
- ath10k_err(ar, "could not write fw (%d)\n", ret);
- goto exit;
+ ath10k_err(ar, "failed to download %s firmware: %d\n",
+ mode_name, ret);
+ return ret;
}
-exit:
return ret;
}
@@ -567,7 +589,8 @@ success:
return 0;
}
-static int ath10k_init_download_firmware(struct ath10k *ar)
+static int ath10k_init_download_firmware(struct ath10k *ar,
+ enum ath10k_firmware_mode mode)
{
int ret;
@@ -583,7 +606,7 @@ static int ath10k_init_download_firmware(struct ath10k *ar)
return ret;
}
- ret = ath10k_download_fw(ar);
+ ret = ath10k_download_fw(ar, mode);
if (ret) {
ath10k_err(ar, "failed to download firmware: %d\n", ret);
return ret;
@@ -685,12 +708,15 @@ static void ath10k_core_restart(struct work_struct *work)
case ATH10K_STATE_WEDGED:
ath10k_warn(ar, "device is wedged, will not restart\n");
break;
+ case ATH10K_STATE_UTF:
+ ath10k_warn(ar, "firmware restart in UTF mode not supported\n");
+ break;
}
mutex_unlock(&ar->conf_mutex);
}
-int ath10k_core_start(struct ath10k *ar)
+int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
{
int status;
@@ -703,7 +729,7 @@ int ath10k_core_start(struct ath10k *ar)
goto err;
}
- status = ath10k_init_download_firmware(ar);
+ status = ath10k_init_download_firmware(ar, mode);
if (status)
goto err;
@@ -760,10 +786,12 @@ int ath10k_core_start(struct ath10k *ar)
goto err_hif_stop;
}
- status = ath10k_htt_connect(&ar->htt);
- if (status) {
- ath10k_err(ar, "failed to connect htt (%d)\n", status);
- goto err_hif_stop;
+ if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+ status = ath10k_htt_connect(&ar->htt);
+ if (status) {
+ ath10k_err(ar, "failed to connect htt (%d)\n", status);
+ goto err_hif_stop;
+ }
}
status = ath10k_wmi_connect(ar);
@@ -778,11 +806,13 @@ int ath10k_core_start(struct ath10k *ar)
goto err_hif_stop;
}
- status = ath10k_wmi_wait_for_service_ready(ar);
- if (status <= 0) {
- ath10k_warn(ar, "wmi service ready event not received");
- status = -ETIMEDOUT;
- goto err_hif_stop;
+ if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+ status = ath10k_wmi_wait_for_service_ready(ar);
+ if (status <= 0) {
+ ath10k_warn(ar, "wmi service ready event not received");
+ status = -ETIMEDOUT;
+ goto err_hif_stop;
+ }
}
ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
@@ -802,10 +832,13 @@ int ath10k_core_start(struct ath10k *ar)
goto err_hif_stop;
}
- status = ath10k_htt_setup(&ar->htt);
- if (status) {
- ath10k_err(ar, "failed to setup htt: %d\n", status);
- goto err_hif_stop;
+ /* we don't care about HTT in UTF mode */
+ if (mode == ATH10K_FIRMWARE_MODE_NORMAL) {
+ status = ath10k_htt_setup(&ar->htt);
+ if (status) {
+ ath10k_err(ar, "failed to setup htt: %d\n", status);
+ goto err_hif_stop;
+ }
}
status = ath10k_debug_start(ar);
@@ -861,7 +894,8 @@ void ath10k_core_stop(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex);
/* try to suspend target */
- if (ar->state != ATH10K_STATE_RESTARTING)
+ if (ar->state != ATH10K_STATE_RESTARTING &&
+ ar->state != ATH10K_STATE_UTF)
ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);
ath10k_debug_stop(ar);
@@ -914,7 +948,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
mutex_lock(&ar->conf_mutex);
- ret = ath10k_core_start(ar);
+ ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
if (ret) {
ath10k_err(ar, "could not init core (%d)\n", ret);
ath10k_core_free_firmware_files(ar);
@@ -977,7 +1011,7 @@ static void ath10k_core_register_work(struct work_struct *work)
goto err_release_fw;
}
- status = ath10k_debug_create(ar);
+ status = ath10k_debug_register(ar);
if (status) {
ath10k_err(ar, "unable to initialize debugfs\n");
goto err_unregister_mac;
@@ -1041,9 +1075,11 @@ void ath10k_core_unregister(struct ath10k *ar)
* unhappy about callback failures. */
ath10k_mac_unregister(ar);
+ ath10k_testmode_destroy(ar);
+
ath10k_core_free_firmware_files(ar);
- ath10k_debug_destroy(ar);
+ ath10k_debug_unregister(ar);
}
EXPORT_SYMBOL(ath10k_core_unregister);
@@ -1051,6 +1087,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
const struct ath10k_hif_ops *hif_ops)
{
struct ath10k *ar;
+ int ret;
ar = ath10k_mac_create(priv_size);
if (!ar)
@@ -1076,7 +1113,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
ar->workqueue = create_singlethread_workqueue("ath10k_wq");
if (!ar->workqueue)
- goto err_wq;
+ goto err_free_mac;
mutex_init(&ar->conf_mutex);
spin_lock_init(&ar->data_lock);
@@ -1094,10 +1131,18 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
INIT_WORK(&ar->register_work, ath10k_core_register_work);
INIT_WORK(&ar->restart_work, ath10k_core_restart);
+ ret = ath10k_debug_create(ar);
+ if (ret)
+ goto err_free_wq;
+
return ar;
-err_wq:
+err_free_wq:
+ destroy_workqueue(ar->workqueue);
+
+err_free_mac:
ath10k_mac_destroy(ar);
+
return NULL;
}
EXPORT_SYMBOL(ath10k_core_create);
@@ -1107,6 +1152,7 @@ void ath10k_core_destroy(struct ath10k *ar)
flush_workqueue(ar->workqueue);
destroy_workqueue(ar->workqueue);
+ ath10k_debug_destroy(ar);
ath10k_mac_destroy(ar);
}
EXPORT_SYMBOL(ath10k_core_destroy);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 4ef476099225..fe531ea6926c 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -293,7 +293,7 @@ struct ath10k_debug {
struct dentry *debugfs_phy;
struct ath10k_target_stats target_stats;
- DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_BM_SIZE);
+ DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX);
struct completion event_stats_compl;
@@ -330,6 +330,17 @@ enum ath10k_state {
* prevents completion timeouts and makes the driver more responsive to
* userspace commands. This is also prevents recursive recovery. */
ATH10K_STATE_WEDGED,
+
+ /* factory tests */
+ ATH10K_STATE_UTF,
+};
+
+enum ath10k_firmware_mode {
+ /* the default mode, standard 802.11 functionality */
+ ATH10K_FIRMWARE_MODE_NORMAL,
+
+ /* factory tests etc */
+ ATH10K_FIRMWARE_MODE_UTF,
};
enum ath10k_fw_features {
@@ -472,7 +483,6 @@ struct ath10k {
struct cfg80211_chan_def chandef;
int free_vdev_map;
- bool promisc;
bool monitor;
int monitor_vdev_id;
bool monitor_started;
@@ -544,6 +554,15 @@ struct ath10k {
struct ath10k_spec_scan config;
} spectral;
+ struct {
+ /* protected by conf_mutex */
+ const struct firmware *utf;
+ DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);
+
+ /* protected by data_lock */
+ bool utf_monitor;
+ } testmode;
+
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
@@ -552,7 +571,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
const struct ath10k_hif_ops *hif_ops);
void ath10k_core_destroy(struct ath10k *ar);
-int ath10k_core_start(struct ath10k *ar);
+int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode);
int ath10k_wait_for_suspend(struct ath10k *ar, u32 suspend_opt);
void ath10k_core_stop(struct ath10k *ar);
int ath10k_core_register(struct ath10k *ar, u32 chip_id);
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index f3f0a80f8bab..3756feba3223 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -117,7 +117,7 @@ int ath10k_info(struct ath10k *ar, const char *fmt, ...)
va_start(args, fmt);
vaf.va = &args;
ret = dev_info(ar->dev, "%pV", &vaf);
- trace_ath10k_log_info(&vaf);
+ trace_ath10k_log_info(ar, &vaf);
va_end(args);
return ret;
@@ -134,11 +134,12 @@ void ath10k_print_driver_info(struct ath10k *ar)
ar->fw_api,
ar->htt.target_version_major,
ar->htt.target_version_minor);
- ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d\n",
+ ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
config_enabled(CONFIG_ATH10K_DEBUG),
config_enabled(CONFIG_ATH10K_DEBUGFS),
config_enabled(CONFIG_ATH10K_TRACING),
- config_enabled(CONFIG_ATH10K_DFS_CERTIFIED));
+ config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
+ config_enabled(CONFIG_NL80211_TESTMODE));
}
EXPORT_SYMBOL(ath10k_print_driver_info);
@@ -153,7 +154,7 @@ int ath10k_err(struct ath10k *ar, const char *fmt, ...)
va_start(args, fmt);
vaf.va = &args;
ret = dev_err(ar->dev, "%pV", &vaf);
- trace_ath10k_log_err(&vaf);
+ trace_ath10k_log_err(ar, &vaf);
va_end(args);
return ret;
@@ -170,7 +171,7 @@ int ath10k_warn(struct ath10k *ar, const char *fmt, ...)
va_start(args, fmt);
vaf.va = &args;
dev_warn_ratelimited(ar->dev, "%pV", &vaf);
- trace_ath10k_log_warn(&vaf);
+ trace_ath10k_log_warn(ar, &vaf);
va_end(args);
@@ -208,7 +209,7 @@ static ssize_t ath10k_read_wmi_services(struct file *file,
if (len > buf_len)
len = buf_len;
- for (i = 0; i < WMI_MAX_SERVICE; i++) {
+ for (i = 0; i < WMI_SERVICE_MAX; i++) {
enabled = test_bit(i, ar->debug.wmi_service_bitmap);
name = wmi_service_name(i);
@@ -564,16 +565,35 @@ static const struct file_operations fops_fw_stats = {
.llseek = default_llseek,
};
+/* This is a clean assert crash in firmware. */
+static int ath10k_debug_fw_assert(struct ath10k *ar)
+{
+ struct wmi_vdev_install_key_cmd *cmd;
+ struct sk_buff *skb;
+
+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd) + 16);
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct wmi_vdev_install_key_cmd *)skb->data;
+ memset(cmd, 0, sizeof(*cmd));
+
+ /* big enough number so that firmware asserts */
+ cmd->vdev_id = __cpu_to_le32(0x7ffe);
+
+ return ath10k_wmi_cmd_send(ar, skb,
+ ar->wmi.cmd->vdev_install_key_cmdid);
+}
+
static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
- const char buf[] = "To simulate firmware crash write one of the"
- " keywords to this file:\n `soft` - this will send"
- " WMI_FORCE_FW_HANG_ASSERT to firmware if FW"
- " supports that command.\n `hard` - this will send"
- " to firmware command with illegal parameters"
- " causing firmware crash.\n";
+ const char buf[] =
+ "To simulate firmware crash write one of the keywords to this file:\n"
+ "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
+ "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
+ "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n";
return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
}
@@ -621,7 +641,11 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
* firmware variants in order to force a firmware crash.
*/
ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
- ar->wmi.vdev_param->rts_threshold, 0);
+ ar->wmi.vdev_param->rts_threshold,
+ 0);
+ } else if (!strcmp(buf, "assert")) {
+ ath10k_info(ar, "simulating firmware assert crash\n");
+ ret = ath10k_debug_fw_assert(ar);
} else {
ret = -EINVAL;
goto exit;
@@ -840,8 +864,8 @@ static void ath10k_debug_htt_stats_dwork(struct work_struct *work)
}
static ssize_t ath10k_read_htt_stats_mask(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
char buf[32];
@@ -853,8 +877,8 @@ static ssize_t ath10k_read_htt_stats_mask(struct file *file,
}
static ssize_t ath10k_write_htt_stats_mask(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
unsigned long mask;
@@ -959,8 +983,8 @@ static const struct file_operations fops_htt_max_amsdu_ampdu = {
};
static ssize_t ath10k_read_fw_dbglog(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
unsigned int len;
@@ -1132,19 +1156,28 @@ static const struct file_operations fops_dfs_stats = {
int ath10k_debug_create(struct ath10k *ar)
{
- int ret;
-
ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
- if (!ar->debug.fw_crash_data) {
- ret = -ENOMEM;
- goto err;
- }
+ if (!ar->debug.fw_crash_data)
+ return -ENOMEM;
+ return 0;
+}
+
+void ath10k_debug_destroy(struct ath10k *ar)
+{
+ vfree(ar->debug.fw_crash_data);
+ ar->debug.fw_crash_data = NULL;
+}
+
+int ath10k_debug_register(struct ath10k *ar)
+{
ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
ar->hw->wiphy->debugfsdir);
- if (!ar->debug.debugfs_phy) {
- ret = -ENOMEM;
- goto err_free_fw_crash_data;
+ if (IS_ERR_OR_NULL(ar->debug.debugfs_phy)) {
+ if (IS_ERR(ar->debug.debugfs_phy))
+ return PTR_ERR(ar->debug.debugfs_phy);
+
+ return -ENOMEM;
}
INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
@@ -1192,17 +1225,10 @@ int ath10k_debug_create(struct ath10k *ar)
}
return 0;
-
-err_free_fw_crash_data:
- vfree(ar->debug.fw_crash_data);
-
-err:
- return ret;
}
-void ath10k_debug_destroy(struct ath10k *ar)
+void ath10k_debug_unregister(struct ath10k *ar)
{
- vfree(ar->debug.fw_crash_data);
cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
}
@@ -1223,7 +1249,7 @@ void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
if (ath10k_debug_mask & mask)
dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf);
- trace_ath10k_log_dbg(mask, &vaf);
+ trace_ath10k_log_dbg(ar, mask, &vaf);
va_end(args);
}
@@ -1242,7 +1268,7 @@ void ath10k_dbg_dump(struct ath10k *ar,
}
/* tracing code doesn't like null strings :/ */
- trace_ath10k_log_dbg_dump(msg ? msg : "", prefix ? prefix : "",
+ trace_ath10k_log_dbg_dump(ar, msg ? msg : "", prefix ? prefix : "",
buf, len);
}
EXPORT_SYMBOL(ath10k_dbg_dump);
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 56746539bea2..b3774f7f492c 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -34,6 +34,7 @@ enum ath10k_debug_mask {
ATH10K_DBG_DATA = 0x00000200,
ATH10K_DBG_BMI = 0x00000400,
ATH10K_DBG_REGULATORY = 0x00000800,
+ ATH10K_DBG_TESTMODE = 0x00001000,
ATH10K_DBG_ANY = 0xffffffff,
};
@@ -49,6 +50,8 @@ int ath10k_debug_start(struct ath10k *ar);
void ath10k_debug_stop(struct ath10k *ar);
int ath10k_debug_create(struct ath10k *ar);
void ath10k_debug_destroy(struct ath10k *ar);
+int ath10k_debug_register(struct ath10k *ar);
+void ath10k_debug_unregister(struct ath10k *ar);
void ath10k_debug_read_service_map(struct ath10k *ar,
void *service_map,
size_t map_size);
@@ -80,6 +83,15 @@ static inline void ath10k_debug_destroy(struct ath10k *ar)
{
}
+static inline int ath10k_debug_register(struct ath10k *ar)
+{
+ return 0;
+}
+
+static inline void ath10k_debug_unregister(struct ath10k *ar)
+{
+}
+
static inline void ath10k_debug_read_service_map(struct ath10k *ar,
void *service_map,
size_t map_size)
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index 2ac7beacddca..62323fea27e1 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -91,7 +91,6 @@ struct ath10k_hif_ops {
int (*resume)(struct ath10k *ar);
};
-
static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
struct ath10k_hif_sg_item *items,
int n_items)
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index fd9a251f0659..676bd4ed969b 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -45,10 +45,8 @@ static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar)
struct ath10k_skb_cb *skb_cb;
skb = dev_alloc_skb(ATH10K_HTC_CONTROL_BUFFER_SIZE);
- if (!skb) {
- ath10k_warn(ar, "Unable to allocate ctrl skb\n");
+ if (!skb)
return NULL;
- }
skb_reserve(skb, 20); /* FIXME: why 20 bytes? */
WARN_ONCE((unsigned long)skb->data & 3, "unaligned skb");
@@ -569,7 +567,7 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
ath10k_hif_send_complete_check(htc->ar, i, 1);
status = wait_for_completion_timeout(&htc->ctl_resp,
- ATH10K_HTC_WAIT_TIMEOUT_HZ);
+ ATH10K_HTC_WAIT_TIMEOUT_HZ);
if (status == 0)
status = -ETIMEDOUT;
@@ -806,10 +804,8 @@ struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size)
struct sk_buff *skb;
skb = dev_alloc_skb(size + sizeof(struct ath10k_htc_hdr));
- if (!skb) {
- ath10k_warn(ar, "could not allocate HTC tx skb\n");
+ if (!skb)
return NULL;
- }
skb_reserve(skb, sizeof(struct ath10k_htc_hdr));
diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h
index bf532f671189..527179c0edce 100644
--- a/drivers/net/wireless/ath/ath10k/htc.h
+++ b/drivers/net/wireless/ath/ath10k/htc.h
@@ -214,7 +214,6 @@ struct ath10k_htc_frame {
struct ath10k_htc_record trailer[0];
} __packed __aligned(4);
-
/*******************/
/* Host-side stuff */
/*******************/
diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c
index 87daae11f116..56cb4aceb383 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -101,7 +101,7 @@ int ath10k_htt_setup(struct ath10k_htt *htt)
return status;
status = wait_for_completion_timeout(&htt->target_version_received,
- HTT_TARGET_VERSION_TIMEOUT_HZ);
+ HTT_TARGET_VERSION_TIMEOUT_HZ);
if (status <= 0) {
ath10k_warn(ar, "htt version request timed out\n");
return -ETIMEDOUT;
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 6c93f3885ee5..3b44217a6c19 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -265,7 +265,6 @@ enum htt_mgmt_tx_status {
/*=== target -> host messages ===============================================*/
-
enum htt_t2h_msg_type {
HTT_T2H_MSG_TYPE_VERSION_CONF = 0x0,
HTT_T2H_MSG_TYPE_RX_IND = 0x1,
@@ -1032,6 +1031,7 @@ static inline struct htt_stats_conf_item *htt_stats_conf_next_item(
{
return (void *)item + sizeof(*item) + roundup(item->length, 4);
}
+
/*
* host -> target FRAG DESCRIPTOR/MSDU_EXT DESC bank
*
@@ -1148,7 +1148,6 @@ struct htt_resp {
};
} __packed;
-
/*** host side structures follow ***/
struct htt_tx_done {
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 30927b1d7109..60d40a04508b 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -42,7 +42,6 @@
/* when under memory pressure rx ring refill may fail and needs a retry */
#define HTT_RX_RING_REFILL_RETRY_MS 50
-
static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb);
static void ath10k_htt_txrx_compl_task(unsigned long ptr);
@@ -133,7 +132,7 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num)
dma_addr_t paddr;
int ret = 0, idx;
- idx = __le32_to_cpu(*(htt->rx_ring.alloc_idx.vaddr));
+ idx = __le32_to_cpu(*htt->rx_ring.alloc_idx.vaddr);
while (num > 0) {
skb = dev_alloc_skb(HTT_RX_BUF_SIZE + HTT_RX_DESC_ALIGN);
if (!skb) {
@@ -171,7 +170,7 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num)
}
fail:
- *(htt->rx_ring.alloc_idx.vaddr) = __cpu_to_le32(idx);
+ *htt->rx_ring.alloc_idx.vaddr = __cpu_to_le32(idx);
return ret;
}
@@ -223,6 +222,7 @@ static void ath10k_htt_rx_msdu_buff_replenish(struct ath10k_htt *htt)
static void ath10k_htt_rx_ring_refill_retry(unsigned long arg)
{
struct ath10k_htt *htt = (struct ath10k_htt *)arg;
+
ath10k_htt_rx_msdu_buff_replenish(htt);
}
@@ -314,7 +314,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
{
struct ath10k *ar = htt->ar;
int msdu_len, msdu_chaining = 0;
- struct sk_buff *msdu;
+ struct sk_buff *msdu, *next;
struct htt_rx_desc *rx_desc;
lockdep_assert_held(&htt->rx_ring.lock);
@@ -450,11 +450,11 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
if (last_msdu) {
msdu->next = NULL;
break;
- } else {
- struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt);
- msdu->next = next;
- msdu = next;
}
+
+ next = ath10k_htt_rx_netbuf_pop(htt);
+ msdu->next = next;
+ msdu = next;
}
*tail_msdu = msdu;
@@ -480,6 +480,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
static void ath10k_htt_rx_replenish_task(unsigned long ptr)
{
struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
+
ath10k_htt_rx_msdu_buff_replenish(htt);
}
@@ -488,6 +489,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
struct ath10k *ar = htt->ar;
dma_addr_t paddr;
void *vaddr;
+ size_t size;
struct timer_list *timer = &htt->rx_ring.refill_retry_timer;
htt->rx_ring.size = ath10k_htt_rx_ring_size(htt);
@@ -515,9 +517,9 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
if (!htt->rx_ring.netbufs_ring)
goto err_netbuf;
- vaddr = dma_alloc_coherent(htt->ar->dev,
- (htt->rx_ring.size * sizeof(htt->rx_ring.paddrs_ring)),
- &paddr, GFP_DMA);
+ size = htt->rx_ring.size * sizeof(htt->rx_ring.paddrs_ring);
+
+ vaddr = dma_alloc_coherent(htt->ar->dev, size, &paddr, GFP_DMA);
if (!vaddr)
goto err_dma_ring;
@@ -625,19 +627,21 @@ static struct ieee80211_hdr *ath10k_htt_rx_skb_get_hdr(struct sk_buff *skb)
rxd = (void *)skb->data - sizeof(*rxd);
fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
- RX_MSDU_START_INFO1_DECAP_FORMAT);
+ RX_MSDU_START_INFO1_DECAP_FORMAT);
if (fmt == RX_MSDU_DECAP_RAW)
return (void *)skb->data;
- else
- return (void *)skb->data - RX_HTT_HDR_STATUS_LEN;
+
+ return (void *)skb->data - RX_HTT_HDR_STATUS_LEN;
}
/* This function only applies for first msdu in an msdu chain */
static bool ath10k_htt_rx_hdr_is_amsdu(struct ieee80211_hdr *hdr)
{
+ u8 *qc;
+
if (ieee80211_is_data_qos(hdr->frame_control)) {
- u8 *qc = ieee80211_get_qos_ctl(hdr);
+ qc = ieee80211_get_qos_ctl(hdr);
if (qc[0] & 0x80)
return true;
}
@@ -914,7 +918,7 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
rxd = (void *)skb->data - sizeof(*rxd);
enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
- RX_MPDU_START_INFO0_ENCRYPT_TYPE);
+ RX_MPDU_START_INFO0_ENCRYPT_TYPE);
hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
hdr_len = ieee80211_hdrlen(hdr->frame_control);
@@ -950,8 +954,8 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
/* pull decapped header and copy SA & DA */
hdr = (struct ieee80211_hdr *)skb->data;
hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
- memcpy(da, ieee80211_get_DA(hdr), ETH_ALEN);
- memcpy(sa, ieee80211_get_SA(hdr), ETH_ALEN);
+ ether_addr_copy(da, ieee80211_get_DA(hdr));
+ ether_addr_copy(sa, ieee80211_get_SA(hdr));
skb_pull(skb, hdr_len);
/* push original 802.11 header */
@@ -968,8 +972,8 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
/* original 802.11 header has a different DA and in
* case of 4addr it may also have different SA
*/
- memcpy(ieee80211_get_DA(hdr), da, ETH_ALEN);
- memcpy(ieee80211_get_SA(hdr), sa, ETH_ALEN);
+ ether_addr_copy(ieee80211_get_DA(hdr), da);
+ ether_addr_copy(ieee80211_get_SA(hdr), sa);
break;
case RX_MSDU_DECAP_ETHERNET2_DIX:
/* strip ethernet header and insert decapped 802.11
@@ -1029,9 +1033,9 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt,
rxd = (void *)skb->data - sizeof(*rxd);
fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
- RX_MSDU_START_INFO1_DECAP_FORMAT);
+ RX_MSDU_START_INFO1_DECAP_FORMAT);
enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
- RX_MPDU_START_INFO0_ENCRYPT_TYPE);
+ RX_MPDU_START_INFO0_ENCRYPT_TYPE);
hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
hdr_len = ieee80211_hdrlen(hdr->frame_control);
@@ -1332,7 +1336,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
}
static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
- struct htt_rx_fragment_indication *frag)
+ struct htt_rx_fragment_indication *frag)
{
struct ath10k *ar = htt->ar;
struct sk_buff *msdu_head, *msdu_tail;
@@ -1378,7 +1382,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
tkip_mic_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
decrypt_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR);
fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
- RX_MSDU_START_INFO1_DECAP_FORMAT);
+ RX_MSDU_START_INFO1_DECAP_FORMAT);
if (fmt != RX_MSDU_DECAP_RAW) {
ath10k_warn(ar, "we dont support non-raw fragmented rx yet\n");
@@ -1654,7 +1658,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
/* FIX THIS */
break;
case HTT_T2H_MSG_TYPE_STATS_CONF:
- trace_ath10k_htt_stats(skb->data, skb->len);
+ trace_ath10k_htt_stats(ar, skb->data, skb->len);
break;
case HTT_T2H_MSG_TYPE_TX_INSPECT_IND:
/* Firmware can return tx frames if it's unable to fully
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index eaa73aa99c20..bd87a35201d8 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -154,7 +154,6 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
kfree(htt->pending_tx);
kfree(htt->used_msdu_ids);
dma_pool_destroy(htt->tx_pool);
- return;
}
void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
@@ -377,7 +376,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
int msdu_id = -1;
int res;
-
res = ath10k_htt_tx_inc_pending(htt);
if (res)
goto err;
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 13568b01de9f..3cf5702c1e7e 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -36,6 +36,8 @@
#define ATH10K_FW_API2_FILE "firmware-2.bin"
#define ATH10K_FW_API3_FILE "firmware-3.bin"
+#define ATH10K_FW_UTF_FILE "utf.bin"
+
/* includes also the null byte */
#define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K"
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 1f35bd1ef563..46709301a51e 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -26,6 +26,7 @@
#include "wmi.h"
#include "htt.h"
#include "txrx.h"
+#include "testmode.h"
/**********/
/* Crypto */
@@ -198,7 +199,7 @@ static int ath10k_clear_vdev_key(struct ath10k_vif *arvif,
list_for_each_entry(peer, &ar->peers, list) {
for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
if (peer->keys[i] == key) {
- memcpy(addr, peer->addr, ETH_ALEN);
+ ether_addr_copy(addr, peer->addr);
peer->keys[i] = NULL;
break;
}
@@ -224,7 +225,6 @@ static int ath10k_clear_vdev_key(struct ath10k_vif *arvif,
return first_errno;
}
-
/*********************/
/* General utilities */
/*********************/
@@ -493,19 +493,6 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
return 0;
}
-static bool ath10k_monitor_is_enabled(struct ath10k *ar)
-{
- lockdep_assert_held(&ar->conf_mutex);
-
- ath10k_dbg(ar, ATH10K_DBG_MAC,
- "mac monitor refs: promisc %d monitor %d cac %d\n",
- ar->promisc, ar->monitor,
- test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags));
-
- return ar->promisc || ar->monitor ||
- test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
-}
-
static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
{
struct cfg80211_chan_def *chandef = &ar->chandef;
@@ -649,16 +636,6 @@ static int ath10k_monitor_start(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex);
- if (!ath10k_monitor_is_enabled(ar)) {
- ath10k_warn(ar, "trying to start monitor with no references\n");
- return 0;
- }
-
- if (ar->monitor_started) {
- ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor already started\n");
- return 0;
- }
-
ret = ath10k_monitor_vdev_create(ar);
if (ret) {
ath10k_warn(ar, "failed to create monitor vdev: %d\n", ret);
@@ -678,34 +655,51 @@ static int ath10k_monitor_start(struct ath10k *ar)
return 0;
}
-static void ath10k_monitor_stop(struct ath10k *ar)
+static int ath10k_monitor_stop(struct ath10k *ar)
{
int ret;
lockdep_assert_held(&ar->conf_mutex);
- if (ath10k_monitor_is_enabled(ar)) {
- ath10k_dbg(ar, ATH10K_DBG_MAC,
- "mac monitor will be stopped later\n");
- return;
- }
-
- if (!ar->monitor_started) {
- ath10k_dbg(ar, ATH10K_DBG_MAC,
- "mac monitor probably failed to start earlier\n");
- return;
- }
-
ret = ath10k_monitor_vdev_stop(ar);
- if (ret)
+ if (ret) {
ath10k_warn(ar, "failed to stop monitor vdev: %d\n", ret);
+ return ret;
+ }
ret = ath10k_monitor_vdev_delete(ar);
- if (ret)
+ if (ret) {
ath10k_warn(ar, "failed to delete monitor vdev: %d\n", ret);
+ return ret;
+ }
ar->monitor_started = false;
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor stopped\n");
+
+ return 0;
+}
+
+static int ath10k_monitor_recalc(struct ath10k *ar)
+{
+ bool should_start;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ should_start = ar->monitor ||
+ ar->filter_flags & FIF_PROMISC_IN_BSS ||
+ test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
+
+ ath10k_dbg(ar, ATH10K_DBG_MAC,
+ "mac monitor recalc started? %d should? %d\n",
+ ar->monitor_started, should_start);
+
+ if (should_start == ar->monitor_started)
+ return 0;
+
+ if (should_start)
+ return ath10k_monitor_start(ar);
+
+ return ath10k_monitor_stop(ar);
}
static int ath10k_recalc_rtscts_prot(struct ath10k_vif *arvif)
@@ -736,7 +730,7 @@ static int ath10k_start_cac(struct ath10k *ar)
set_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
- ret = ath10k_monitor_start(ar);
+ ret = ath10k_monitor_recalc(ar);
if (ret) {
ath10k_warn(ar, "failed to start monitor (cac): %d\n", ret);
clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
@@ -901,7 +895,7 @@ static int ath10k_vdev_stop(struct ath10k_vif *arvif)
}
static void ath10k_control_beaconing(struct ath10k_vif *arvif,
- struct ieee80211_bss_conf *info)
+ struct ieee80211_bss_conf *info)
{
struct ath10k *ar = arvif->ar;
int ret = 0;
@@ -936,7 +930,7 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif,
return;
arvif->aid = 0;
- memcpy(arvif->bssid, info->bssid, ETH_ALEN);
+ ether_addr_copy(arvif->bssid, info->bssid);
ret = ath10k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
arvif->bssid);
@@ -1056,7 +1050,7 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
{
lockdep_assert_held(&ar->conf_mutex);
- memcpy(arg->addr, sta->addr, ETH_ALEN);
+ ether_addr_copy(arg->addr, sta->addr);
arg->vdev_id = arvif->vdev_id;
arg->peer_aid = sta->aid;
arg->peer_flags |= WMI_PEER_AUTH;
@@ -1111,9 +1105,9 @@ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
ies = rcu_dereference(bss->ies);
wpaie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
- WLAN_OUI_TYPE_MICROSOFT_WPA,
- ies->data,
- ies->len);
+ WLAN_OUI_TYPE_MICROSOFT_WPA,
+ ies->data,
+ ies->len);
rcu_read_unlock();
cfg80211_put_bss(ar->hw->wiphy, bss);
}
@@ -1163,6 +1157,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
{
const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
int i, n;
+ u32 stbc;
lockdep_assert_held(&ar->conf_mutex);
@@ -1199,7 +1194,6 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
}
if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) {
- u32 stbc;
stbc = ht_cap->cap & IEEE80211_HT_CAP_RX_STBC;
stbc = stbc >> IEEE80211_HT_CAP_RX_STBC_SHIFT;
stbc = stbc << WMI_RC_RX_STBC_FLAG_S;
@@ -1267,7 +1261,6 @@ static int ath10k_peer_assoc_qos_ap(struct ath10k *ar,
uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN |
WMI_AP_PS_UAPSD_AC0_TRIGGER_EN;
-
if (sta->max_sp < MAX_WMI_AP_PS_PEER_PARAM_MAX_SP)
max_sp = sta->max_sp;
@@ -1296,7 +1289,8 @@ static int ath10k_peer_assoc_qos_ap(struct ath10k *ar,
sta->listen_interval - mac80211 patch required.
Currently use 10 seconds */
ret = ath10k_wmi_set_ap_ps_param(ar, arvif->vdev_id, sta->addr,
- WMI_AP_PS_PEER_PARAM_AGEOUT_TIME, 10);
+ WMI_AP_PS_PEER_PARAM_AGEOUT_TIME,
+ 10);
if (ret) {
ath10k_warn(ar, "failed to set ap ps peer param ageout time for vdev %i: %d\n",
arvif->vdev_id, ret);
@@ -1320,7 +1314,6 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
arg->peer_flags |= WMI_PEER_VHT;
arg->peer_vht_caps = vht_cap->cap;
-
ampdu_factor = (vht_cap->cap &
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>
IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
@@ -1531,7 +1524,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
arvif->vdev_id, bss_conf->bssid, bss_conf->aid);
arvif->aid = bss_conf->aid;
- memcpy(arvif->bssid, bss_conf->bssid, ETH_ALEN);
+ ether_addr_copy(arvif->bssid, bss_conf->bssid);
ret = ath10k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid);
if (ret) {
@@ -1615,7 +1608,7 @@ static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
return ret;
}
- if (!sta->wme) {
+ if (!sta->wme && !reassoc) {
arvif->num_legacy_stations++;
ret = ath10k_recalc_rtscts_prot(arvif);
if (ret) {
@@ -1863,11 +1856,10 @@ static u8 ath10k_tx_h_get_tid(struct ieee80211_hdr *hdr)
return ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
}
-static u8 ath10k_tx_h_get_vdev_id(struct ath10k *ar,
- struct ieee80211_tx_info *info)
+static u8 ath10k_tx_h_get_vdev_id(struct ath10k *ar, struct ieee80211_vif *vif)
{
- if (info->control.vif)
- return ath10k_vif_to_arvif(info->control.vif)->vdev_id;
+ if (vif)
+ return ath10k_vif_to_arvif(vif)->vdev_id;
if (ar->monitor_started)
return ar->monitor_vdev_id;
@@ -2323,7 +2315,7 @@ static void ath10k_tx(struct ieee80211_hw *hw,
ATH10K_SKB_CB(skb)->htt.is_offchan = false;
ATH10K_SKB_CB(skb)->htt.tid = ath10k_tx_h_get_tid(hdr);
- ATH10K_SKB_CB(skb)->vdev_id = ath10k_tx_h_get_vdev_id(ar, info);
+ ATH10K_SKB_CB(skb)->vdev_id = ath10k_tx_h_get_vdev_id(ar, vif);
/* it makes no sense to process injected frames like that */
if (vif && vif->type != NL80211_IFTYPE_MONITOR) {
@@ -2369,12 +2361,14 @@ void ath10k_halt(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex);
- if (ath10k_monitor_is_enabled(ar)) {
- clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
- ar->promisc = false;
- ar->monitor = false;
+ clear_bit(ATH10K_CAC_RUNNING, &ar->dev_flags);
+ ar->filter_flags = 0;
+ ar->monitor = false;
+
+ if (ar->monitor_started)
ath10k_monitor_stop(ar);
- }
+
+ ar->monitor_started = false;
ath10k_scan_finish(ar);
ath10k_peer_cleanup_all(ar);
@@ -2485,6 +2479,9 @@ static int ath10k_start(struct ieee80211_hw *hw)
WARN_ON(1);
ret = -EINVAL;
goto err;
+ case ATH10K_STATE_UTF:
+ ret = -EBUSY;
+ goto err;
}
ret = ath10k_hif_power_up(ar);
@@ -2493,7 +2490,7 @@ static int ath10k_start(struct ieee80211_hw *hw)
goto err_off;
}
- ret = ath10k_core_start(ar);
+ ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
if (ret) {
ath10k_err(ar, "Could not init core: %d\n", ret);
goto err_power_down;
@@ -2629,7 +2626,7 @@ static void ath10k_config_chan(struct ath10k *ar)
/* First stop monitor interface. Some FW versions crash if there's a
* lone monitor interface. */
if (ar->monitor_started)
- ath10k_monitor_vdev_stop(ar);
+ ath10k_monitor_stop(ar);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (!arvif->is_started)
@@ -2677,8 +2674,7 @@ static void ath10k_config_chan(struct ath10k *ar)
}
}
- if (ath10k_monitor_is_enabled(ar))
- ath10k_monitor_vdev_start(ar, ar->monitor_vdev_id);
+ ath10k_monitor_recalc(ar);
}
static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
@@ -2733,19 +2729,10 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
ath10k_config_ps(ar);
if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
- if (conf->flags & IEEE80211_CONF_MONITOR && !ar->monitor) {
- ar->monitor = true;
- ret = ath10k_monitor_start(ar);
- if (ret) {
- ath10k_warn(ar, "failed to start monitor (config): %d\n",
- ret);
- ar->monitor = false;
- }
- } else if (!(conf->flags & IEEE80211_CONF_MONITOR) &&
- ar->monitor) {
- ar->monitor = false;
- ath10k_monitor_stop(ar);
- }
+ ar->monitor = conf->flags & IEEE80211_CONF_MONITOR;
+ ret = ath10k_monitor_recalc(ar);
+ if (ret)
+ ath10k_warn(ar, "failed to recalc monitor: %d\n", ret);
}
mutex_unlock(&ar->conf_mutex);
@@ -3009,18 +2996,9 @@ static void ath10k_configure_filter(struct ieee80211_hw *hw,
*total_flags &= SUPPORTED_FILTERS;
ar->filter_flags = *total_flags;
- if (ar->filter_flags & FIF_PROMISC_IN_BSS && !ar->promisc) {
- ar->promisc = true;
- ret = ath10k_monitor_start(ar);
- if (ret) {
- ath10k_warn(ar, "failed to start monitor (promisc): %d\n",
- ret);
- ar->promisc = false;
- }
- } else if (!(ar->filter_flags & FIF_PROMISC_IN_BSS) && ar->promisc) {
- ar->promisc = false;
- ath10k_monitor_stop(ar);
- }
+ ret = ath10k_monitor_recalc(ar);
+ if (ret)
+ ath10k_warn(ar, "failed to recalc montior: %d\n", ret);
mutex_unlock(&ar->conf_mutex);
}
@@ -3033,7 +3011,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
int ret = 0;
- u32 vdev_param, pdev_param;
+ u32 vdev_param, pdev_param, slottime, preamble;
mutex_lock(&ar->conf_mutex);
@@ -3112,7 +3090,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
* this is never erased as we it for crypto key
* clearing; this is FW requirement
*/
- memcpy(arvif->bssid, info->bssid, ETH_ALEN);
+ ether_addr_copy(arvif->bssid, info->bssid);
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac vdev %d start %pM\n",
@@ -3154,7 +3132,6 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_ERP_SLOT) {
- u32 slottime;
if (info->use_short_slot)
slottime = WMI_VDEV_SLOT_TIME_SHORT; /* 9us */
@@ -3173,7 +3150,6 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- u32 preamble;
if (info->use_short_preamble)
preamble = WMI_VDEV_PREAMBLE_SHORT;
else
@@ -3192,8 +3168,16 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_ASSOC) {
- if (info->assoc)
+ if (info->assoc) {
+ /* Workaround: Make sure monitor vdev is not running
+ * when associating to prevent some firmware revisions
+ * (e.g. 10.1 and 10.2) from crashing.
+ */
+ if (ar->monitor_started)
+ ath10k_monitor_stop(ar);
ath10k_bss_assoc(hw, vif, info);
+ ath10k_monitor_recalc(ar);
+ }
}
exit:
@@ -3580,7 +3564,7 @@ exit:
}
static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif,
- u16 ac, bool enable)
+ u16 ac, bool enable)
{
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
u32 value = 0;
@@ -4081,8 +4065,8 @@ ath10k_bitrate_mask_nss(const struct cfg80211_bitrate_mask *mask,
continue;
else if (mask->control[band].ht_mcs[i] == 0x00)
break;
- else
- return false;
+
+ return false;
}
ht_nss = i;
@@ -4093,8 +4077,8 @@ ath10k_bitrate_mask_nss(const struct cfg80211_bitrate_mask *mask,
continue;
else if (mask->control[band].vht_mcs[i] == 0x0000)
break;
- else
- return false;
+
+ return false;
}
vht_nss = i;
@@ -4472,6 +4456,9 @@ static const struct ieee80211_ops ath10k_ops = {
.sta_rc_update = ath10k_sta_rc_update,
.get_tsf = ath10k_get_tsf,
.ampdu_action = ath10k_ampdu_action,
+
+ CFG80211_TESTMODE_CMD(ath10k_tm_cmd)
+
#ifdef CONFIG_PM
.suspend = ath10k_suspend,
.resume = ath10k_resume,
@@ -4723,7 +4710,6 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
return ht_cap;
}
-
static void ath10k_get_arvif_iter(void *data, u8 *mac,
struct ieee80211_vif *vif)
{
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 056a35a77133..59e0ea83be50 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -64,9 +64,6 @@ static const struct pci_device_id ath10k_pci_id_table[] = {
{0}
};
-static int ath10k_pci_diag_read_access(struct ath10k *ar, u32 address,
- u32 *data);
-
static void ath10k_pci_buffer_cleanup(struct ath10k *ar);
static int ath10k_pci_cold_reset(struct ath10k *ar);
static int ath10k_pci_warm_reset(struct ath10k *ar);
@@ -343,8 +340,8 @@ static void ath10k_pci_disable_and_clear_legacy_irq(struct ath10k *ar)
/* IMPORTANT: this extra read transaction is required to
* flush the posted write buffer. */
- (void) ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
- PCIE_INTR_ENABLE_ADDRESS);
+ (void)ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+ PCIE_INTR_ENABLE_ADDRESS);
}
static void ath10k_pci_enable_legacy_irq(struct ath10k *ar)
@@ -355,8 +352,8 @@ static void ath10k_pci_enable_legacy_irq(struct ath10k *ar)
/* IMPORTANT: this extra read transaction is required to
* flush the posted write buffer. */
- (void) ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
- PCIE_INTR_ENABLE_ADDRESS);
+ (void)ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+ PCIE_INTR_ENABLE_ADDRESS);
}
static inline const char *ath10k_pci_get_irq_method(struct ath10k *ar)
@@ -365,10 +362,11 @@ static inline const char *ath10k_pci_get_irq_method(struct ath10k *ar)
if (ar_pci->num_msi_intrs > 1)
return "msi-x";
- else if (ar_pci->num_msi_intrs == 1)
+
+ if (ar_pci->num_msi_intrs == 1)
return "msi";
- else
- return "legacy";
+
+ return "legacy";
}
static int __ath10k_pci_rx_post_buf(struct ath10k_pci_pipe *pipe)
@@ -487,25 +485,6 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
void *data_buf = NULL;
int i;
- /*
- * This code cannot handle reads to non-memory space. Redirect to the
- * register read fn but preserve the multi word read capability of
- * this fn
- */
- if (address < DRAM_BASE_ADDRESS) {
- if (!IS_ALIGNED(address, 4) ||
- !IS_ALIGNED((unsigned long)data, 4))
- return -EIO;
-
- while ((nbytes >= 4) && ((ret = ath10k_pci_diag_read_access(
- ar, address, (u32 *)data)) == 0)) {
- nbytes -= sizeof(u32);
- address += sizeof(u32);
- data += sizeof(u32);
- }
- return ret;
- }
-
ce_diag = ar_pci->ce_diag;
/*
@@ -549,7 +528,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
address);
ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0,
- 0);
+ 0);
if (ret)
goto done;
@@ -569,7 +548,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
goto done;
}
- if (buf != (u32) address) {
+ if (buf != (u32)address) {
ret = -EIO;
goto done;
}
@@ -652,19 +631,7 @@ static int __ath10k_pci_diag_read_hi(struct ath10k *ar, void *dest,
}
#define ath10k_pci_diag_read_hi(ar, dest, src, len) \
- __ath10k_pci_diag_read_hi(ar, dest, HI_ITEM(src), len);
-
-/* Read 4-byte aligned data from Target memory or register */
-static int ath10k_pci_diag_read_access(struct ath10k *ar, u32 address,
- u32 *data)
-{
- /* Assume range doesn't cross this boundary */
- if (address >= DRAM_BASE_ADDRESS)
- return ath10k_pci_diag_read32(ar, address, data);
-
- *data = ath10k_pci_read32(ar, address);
- return 0;
-}
+ __ath10k_pci_diag_read_hi(ar, dest, HI_ITEM(src), len)
static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
const void *data, int nbytes)
@@ -729,7 +696,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
* Request CE to send caller-supplied data that
* was copied to bounce buffer to Target(!) address.
*/
- ret = ath10k_ce_send(ce_diag, NULL, (u32) ce_data,
+ ret = ath10k_ce_send(ce_diag, NULL, (u32)ce_data,
nbytes, 0, 0);
if (ret != 0)
goto done;
@@ -803,18 +770,6 @@ static int ath10k_pci_diag_write32(struct ath10k *ar, u32 address, u32 value)
return ath10k_pci_diag_write_mem(ar, address, &val, sizeof(val));
}
-/* Write 4B data to Target memory or register */
-static int ath10k_pci_diag_write_access(struct ath10k *ar, u32 address,
- u32 data)
-{
- /* Assume range doesn't cross this boundary */
- if (address >= DRAM_BASE_ADDRESS)
- return ath10k_pci_diag_write32(ar, address, data);
-
- ath10k_pci_write32(ar, address, data);
- return 0;
-}
-
static bool ath10k_pci_is_awake(struct ath10k *ar)
{
u32 val = ath10k_pci_reg_read32(ar, RTC_STATE_ADDRESS);
@@ -1152,7 +1107,7 @@ static int ath10k_pci_hif_map_service_to_pipe(struct ath10k *ar,
}
static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar,
- u8 *ul_pipe, u8 *dl_pipe)
+ u8 *ul_pipe, u8 *dl_pipe)
{
int ul_is_polled, dl_is_polled;
@@ -1172,16 +1127,8 @@ static void ath10k_pci_irq_disable(struct ath10k *ar)
int i;
ath10k_ce_disable_interrupts(ar);
-
- /* Regardless how many interrupts were assigned for MSI the first one
- * is always used for firmware indications (crashes). There's no way to
- * mask the irq in the device so call disable_irq(). Legacy (shared)
- * interrupts can be masked on the device though.
- */
- if (ar_pci->num_msi_intrs > 0)
- disable_irq(ar_pci->pdev->irq);
- else
- ath10k_pci_disable_and_clear_legacy_irq(ar);
+ ath10k_pci_disable_and_clear_legacy_irq(ar);
+ /* FIXME: How to mask all MSI interrupts? */
for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
synchronize_irq(ar_pci->pdev->irq + i);
@@ -1189,15 +1136,9 @@ static void ath10k_pci_irq_disable(struct ath10k *ar)
static void ath10k_pci_irq_enable(struct ath10k *ar)
{
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
-
ath10k_ce_enable_interrupts(ar);
-
- /* See comment in ath10k_pci_irq_disable() */
- if (ar_pci->num_msi_intrs > 0)
- enable_irq(ar_pci->pdev->irq);
- else
- ath10k_pci_enable_legacy_irq(ar);
+ ath10k_pci_enable_legacy_irq(ar);
+ /* FIXME: How to unmask all MSI interrupts? */
}
static int ath10k_pci_hif_start(struct ath10k *ar)
@@ -1311,14 +1252,21 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
{
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif stop\n");
- ath10k_pci_irq_disable(ar);
- ath10k_pci_flush(ar);
-
/* Most likely the device has HTT Rx ring configured. The only way to
* prevent the device from accessing (and possible corrupting) host
* memory is to reset the chip now.
+ *
+ * There's also no known way of masking MSI interrupts on the device.
+ * For ranged MSI the CE-related interrupts can be masked. However
+ * regardless how many MSI interrupts are assigned the first one
+ * is always used for firmware indications (crashes) and cannot be
+ * masked. To prevent the device from asserting the interrupt reset it
+ * before proceeding with cleanup.
*/
ath10k_pci_warm_reset(ar);
+
+ ath10k_pci_irq_disable(ar);
+ ath10k_pci_flush(ar);
}
static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
@@ -1472,28 +1420,12 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
*/
static int ath10k_pci_wake_target_cpu(struct ath10k *ar)
{
- int ret;
- u32 core_ctrl;
-
- ret = ath10k_pci_diag_read_access(ar, SOC_CORE_BASE_ADDRESS |
- CORE_CTRL_ADDRESS,
- &core_ctrl);
- if (ret) {
- ath10k_warn(ar, "failed to read core_ctrl: %d\n", ret);
- return ret;
- }
-
- /* A_INUM_FIRMWARE interrupt to Target CPU */
- core_ctrl |= CORE_CTRL_CPU_INTR_MASK;
+ u32 addr, val;
- ret = ath10k_pci_diag_write_access(ar, SOC_CORE_BASE_ADDRESS |
- CORE_CTRL_ADDRESS,
- core_ctrl);
- if (ret) {
- ath10k_warn(ar, "failed to set target CPU interrupt mask: %d\n",
- ret);
- return ret;
- }
+ 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);
return 0;
}
@@ -1516,8 +1448,8 @@ static int ath10k_pci_init_config(struct ath10k *ar)
host_interest_item_address(HI_ITEM(hi_interconnect_state));
/* Supply Target-side CE configuration */
- ret = ath10k_pci_diag_read_access(ar, interconnect_targ_addr,
- &pcie_state_targ_addr);
+ ret = ath10k_pci_diag_read32(ar, interconnect_targ_addr,
+ &pcie_state_targ_addr);
if (ret != 0) {
ath10k_err(ar, "Failed to get pcie state addr: %d\n", ret);
return ret;
@@ -1529,10 +1461,10 @@ static int ath10k_pci_init_config(struct ath10k *ar)
return ret;
}
- ret = ath10k_pci_diag_read_access(ar, pcie_state_targ_addr +
+ ret = ath10k_pci_diag_read32(ar, (pcie_state_targ_addr +
offsetof(struct pcie_state,
- pipe_cfg_addr),
- &pipe_cfg_targ_addr);
+ pipe_cfg_addr)),
+ &pipe_cfg_targ_addr);
if (ret != 0) {
ath10k_err(ar, "Failed to get pipe cfg addr: %d\n", ret);
return ret;
@@ -1545,18 +1477,18 @@ static int ath10k_pci_init_config(struct ath10k *ar)
}
ret = ath10k_pci_diag_write_mem(ar, pipe_cfg_targ_addr,
- target_ce_config_wlan,
- sizeof(target_ce_config_wlan));
+ target_ce_config_wlan,
+ sizeof(target_ce_config_wlan));
if (ret != 0) {
ath10k_err(ar, "Failed to write pipe cfg: %d\n", ret);
return ret;
}
- ret = ath10k_pci_diag_read_access(ar, pcie_state_targ_addr +
+ ret = ath10k_pci_diag_read32(ar, (pcie_state_targ_addr +
offsetof(struct pcie_state,
- svc_to_pipe_map),
- &svc_to_pipe_map);
+ svc_to_pipe_map)),
+ &svc_to_pipe_map);
if (ret != 0) {
ath10k_err(ar, "Failed to get svc/pipe map: %d\n", ret);
return ret;
@@ -1569,17 +1501,17 @@ static int ath10k_pci_init_config(struct ath10k *ar)
}
ret = ath10k_pci_diag_write_mem(ar, svc_to_pipe_map,
- target_service_to_ce_map_wlan,
- sizeof(target_service_to_ce_map_wlan));
+ target_service_to_ce_map_wlan,
+ sizeof(target_service_to_ce_map_wlan));
if (ret != 0) {
ath10k_err(ar, "Failed to write svc/pipe map: %d\n", ret);
return ret;
}
- ret = ath10k_pci_diag_read_access(ar, pcie_state_targ_addr +
+ ret = ath10k_pci_diag_read32(ar, (pcie_state_targ_addr +
offsetof(struct pcie_state,
- config_flags),
- &pcie_config_flags);
+ config_flags)),
+ &pcie_config_flags);
if (ret != 0) {
ath10k_err(ar, "Failed to get pcie config_flags: %d\n", ret);
return ret;
@@ -1587,9 +1519,10 @@ static int ath10k_pci_init_config(struct ath10k *ar)
pcie_config_flags &= ~PCIE_CONFIG_FLAG_ENABLE_L1;
- ret = ath10k_pci_diag_write_access(ar, pcie_state_targ_addr +
- offsetof(struct pcie_state, config_flags),
- pcie_config_flags);
+ ret = ath10k_pci_diag_write32(ar, (pcie_state_targ_addr +
+ offsetof(struct pcie_state,
+ config_flags)),
+ pcie_config_flags);
if (ret != 0) {
ath10k_err(ar, "Failed to write pcie config_flags: %d\n", ret);
return ret;
@@ -1598,7 +1531,7 @@ static int ath10k_pci_init_config(struct ath10k *ar)
/* configure early allocation */
ealloc_targ_addr = host_interest_item_address(HI_ITEM(hi_early_alloc));
- ret = ath10k_pci_diag_read_access(ar, ealloc_targ_addr, &ealloc_value);
+ ret = ath10k_pci_diag_read32(ar, ealloc_targ_addr, &ealloc_value);
if (ret != 0) {
ath10k_err(ar, "Faile to get early alloc val: %d\n", ret);
return ret;
@@ -1610,7 +1543,7 @@ static int ath10k_pci_init_config(struct ath10k *ar)
ealloc_value |= ((1 << HI_EARLY_ALLOC_IRAM_BANKS_SHIFT) &
HI_EARLY_ALLOC_IRAM_BANKS_MASK);
- ret = ath10k_pci_diag_write_access(ar, ealloc_targ_addr, ealloc_value);
+ ret = ath10k_pci_diag_write32(ar, ealloc_targ_addr, ealloc_value);
if (ret != 0) {
ath10k_err(ar, "Failed to set early alloc val: %d\n", ret);
return ret;
@@ -1619,7 +1552,7 @@ static int ath10k_pci_init_config(struct ath10k *ar)
/* Tell Target to proceed with initialization */
flag2_targ_addr = host_interest_item_address(HI_ITEM(hi_option_flag2));
- ret = ath10k_pci_diag_read_access(ar, flag2_targ_addr, &flag2_value);
+ ret = ath10k_pci_diag_read32(ar, flag2_targ_addr, &flag2_value);
if (ret != 0) {
ath10k_err(ar, "Failed to get option val: %d\n", ret);
return ret;
@@ -1627,7 +1560,7 @@ static int ath10k_pci_init_config(struct ath10k *ar)
flag2_value |= HI_OPTION_EARLY_CFG_DONE;
- ret = ath10k_pci_diag_write_access(ar, flag2_targ_addr, flag2_value);
+ ret = ath10k_pci_diag_write32(ar, flag2_targ_addr, flag2_value);
if (ret != 0) {
ath10k_err(ar, "Failed to set option val: %d\n", ret);
return ret;
@@ -1692,7 +1625,7 @@ static int ath10k_pci_ce_init(struct ath10k *ar)
continue;
}
- pipe_info->buf_sz = (size_t) (attr->src_sz_max);
+ pipe_info->buf_sz = (size_t)(attr->src_sz_max);
}
return 0;
@@ -2228,7 +2161,7 @@ static int ath10k_pci_init_irq(struct ath10k *ar)
if (ath10k_pci_irq_mode == ATH10K_PCI_IRQ_AUTO) {
ar_pci->num_msi_intrs = MSI_NUM_REQUEST;
ret = pci_enable_msi_range(ar_pci->pdev, ar_pci->num_msi_intrs,
- ar_pci->num_msi_intrs);
+ ar_pci->num_msi_intrs);
if (ret > 0)
return 0;
@@ -2554,6 +2487,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
err_free_irq:
ath10k_pci_free_irq(ar);
+ ath10k_pci_kill_tasklet(ar);
err_deinit_irq:
ath10k_pci_deinit_irq(ar);
@@ -2590,6 +2524,7 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
ath10k_core_unregister(ar);
ath10k_pci_free_irq(ar);
+ ath10k_pci_kill_tasklet(ar);
ath10k_pci_deinit_irq(ar);
ath10k_pci_ce_deinit(ar);
ath10k_pci_free_ce(ar);
diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h
index 1c584c4b019c..e1ffdd57a18c 100644
--- a/drivers/net/wireless/ath/ath10k/rx_desc.h
+++ b/drivers/net/wireless/ath/ath10k/rx_desc.h
@@ -839,7 +839,6 @@ struct rx_ppdu_start {
* Reserved: HW should fill with 0, FW should ignore.
*/
-
#define RX_PPDU_END_FLAGS_PHY_ERR (1 << 0)
#define RX_PPDU_END_FLAGS_RX_LOCATION (1 << 1)
#define RX_PPDU_END_FLAGS_TXBF_H_INFO (1 << 2)
diff --git a/drivers/net/wireless/ath/ath10k/targaddrs.h b/drivers/net/wireless/ath/ath10k/targaddrs.h
index be7ba1e78afe..9d0ae30f9ff1 100644
--- a/drivers/net/wireless/ath/ath10k/targaddrs.h
+++ b/drivers/net/wireless/ath/ath10k/targaddrs.h
@@ -284,7 +284,6 @@ Fw Mode/SubMode Mask
#define HI_OPTION_ALL_FW_SUBMODE_MASK 0xFF00
#define HI_OPTION_ALL_FW_SUBMODE_SHIFT 0x8
-
/* hi_option_flag2 options */
#define HI_OPTION_OFFLOAD_AMSDU 0x01
#define HI_OPTION_DFS_SUPPORT 0x02 /* Enable DFS support */
diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c
new file mode 100644
index 000000000000..483db9cb8c96
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/testmode.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2014 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "testmode.h"
+
+#include <net/netlink.h>
+#include <linux/firmware.h>
+
+#include "debug.h"
+#include "wmi.h"
+#include "hif.h"
+#include "hw.h"
+
+#include "testmode_i.h"
+
+static const struct nla_policy ath10k_tm_policy[ATH10K_TM_ATTR_MAX + 1] = {
+ [ATH10K_TM_ATTR_CMD] = { .type = NLA_U32 },
+ [ATH10K_TM_ATTR_DATA] = { .type = NLA_BINARY,
+ .len = ATH10K_TM_DATA_MAX_LEN },
+ [ATH10K_TM_ATTR_WMI_CMDID] = { .type = NLA_U32 },
+ [ATH10K_TM_ATTR_VERSION_MAJOR] = { .type = NLA_U32 },
+ [ATH10K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 },
+};
+
+/* Returns true if callee consumes the skb and the skb should be discarded.
+ * Returns false if skb is not used. Does not sleep.
+ */
+bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb)
+{
+ struct sk_buff *nl_skb;
+ bool consumed;
+ int ret;
+
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
+ "testmode event wmi cmd_id %d skb %p skb->len %d\n",
+ cmd_id, skb, skb->len);
+
+ ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
+
+ spin_lock_bh(&ar->data_lock);
+
+ if (!ar->testmode.utf_monitor) {
+ consumed = false;
+ goto out;
+ }
+
+ /* Only testmode.c should be handling events from utf firmware,
+ * otherwise all sort of problems will arise as mac80211 operations
+ * are not initialised.
+ */
+ consumed = true;
+
+ nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy,
+ 2 * sizeof(u32) + skb->len,
+ GFP_ATOMIC);
+ if (!nl_skb) {
+ ath10k_warn(ar,
+ "failed to allocate skb for testmode wmi event\n");
+ goto out;
+ }
+
+ ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_CMD, ATH10K_TM_CMD_WMI);
+ if (ret) {
+ ath10k_warn(ar,
+ "failed to to put testmode wmi event cmd attribute: %d\n",
+ ret);
+ kfree_skb(nl_skb);
+ goto out;
+ }
+
+ ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_WMI_CMDID, cmd_id);
+ if (ret) {
+ ath10k_warn(ar,
+ "failed to to put testmode wmi even cmd_id: %d\n",
+ ret);
+ kfree_skb(nl_skb);
+ goto out;
+ }
+
+ ret = nla_put(nl_skb, ATH10K_TM_ATTR_DATA, skb->len, skb->data);
+ if (ret) {
+ ath10k_warn(ar,
+ "failed to copy skb to testmode wmi event: %d\n",
+ ret);
+ kfree_skb(nl_skb);
+ goto out;
+ }
+
+ cfg80211_testmode_event(nl_skb, GFP_ATOMIC);
+
+out:
+ spin_unlock_bh(&ar->data_lock);
+
+ return consumed;
+}
+
+static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
+{
+ struct sk_buff *skb;
+ int ret;
+
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
+ "testmode cmd get version_major %d version_minor %d\n",
+ ATH10K_TESTMODE_VERSION_MAJOR,
+ ATH10K_TESTMODE_VERSION_MINOR);
+
+ skb = cfg80211_testmode_alloc_reply_skb(ar->hw->wiphy,
+ nla_total_size(sizeof(u32)));
+ if (!skb)
+ return -ENOMEM;
+
+ ret = nla_put_u32(skb, ATH10K_TM_ATTR_VERSION_MAJOR,
+ ATH10K_TESTMODE_VERSION_MAJOR);
+ if (ret) {
+ kfree_skb(skb);
+ return ret;
+ }
+
+ ret = nla_put_u32(skb, ATH10K_TM_ATTR_VERSION_MINOR,
+ ATH10K_TESTMODE_VERSION_MINOR);
+ if (ret) {
+ kfree_skb(skb);
+ return ret;
+ }
+
+ return cfg80211_testmode_reply(skb);
+}
+
+static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
+{
+ char filename[100];
+ int ret;
+
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n");
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state == ATH10K_STATE_UTF) {
+ ret = -EALREADY;
+ goto err;
+ }
+
+ /* start utf only when the driver is not in use */
+ if (ar->state != ATH10K_STATE_OFF) {
+ ret = -EBUSY;
+ goto err;
+ }
+
+ if (WARN_ON(ar->testmode.utf != NULL)) {
+ /* utf image is already downloaded, it shouldn't be */
+ ret = -EEXIST;
+ goto err;
+ }
+
+ snprintf(filename, sizeof(filename), "%s/%s",
+ ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
+
+ /* load utf firmware image */
+ ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
+ if (ret) {
+ ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
+ filename, ret);
+ goto err;
+ }
+
+ spin_lock_bh(&ar->data_lock);
+
+ ar->testmode.utf_monitor = true;
+
+ spin_unlock_bh(&ar->data_lock);
+
+ BUILD_BUG_ON(sizeof(ar->fw_features) !=
+ sizeof(ar->testmode.orig_fw_features));
+
+ memcpy(ar->testmode.orig_fw_features, ar->fw_features,
+ sizeof(ar->fw_features));
+
+ /* utf.bin firmware image does not advertise firmware features. Do
+ * an ugly hack where we force the firmware features so that wmi.c
+ * will use the correct WMI interface.
+ */
+ memset(ar->fw_features, 0, sizeof(ar->fw_features));
+ __set_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features);
+
+ ret = ath10k_hif_power_up(ar);
+ if (ret) {
+ ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret);
+ ar->state = ATH10K_STATE_OFF;
+ goto err_fw_features;
+ }
+
+ ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF);
+ if (ret) {
+ ath10k_err(ar, "failed to start core (testmode): %d\n", ret);
+ ar->state = ATH10K_STATE_OFF;
+ goto err_power_down;
+ }
+
+ ar->state = ATH10K_STATE_UTF;
+
+ ath10k_info(ar, "UTF firmware started\n");
+
+ mutex_unlock(&ar->conf_mutex);
+
+ return 0;
+
+err_power_down:
+ ath10k_hif_power_down(ar);
+
+err_fw_features:
+ /* return the original firmware features */
+ memcpy(ar->fw_features, ar->testmode.orig_fw_features,
+ sizeof(ar->fw_features));
+
+ release_firmware(ar->testmode.utf);
+ ar->testmode.utf = NULL;
+
+err:
+ mutex_unlock(&ar->conf_mutex);
+
+ return ret;
+}
+
+static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar)
+{
+ lockdep_assert_held(&ar->conf_mutex);
+
+ ath10k_core_stop(ar);
+ ath10k_hif_power_down(ar);
+
+ spin_lock_bh(&ar->data_lock);
+
+ ar->testmode.utf_monitor = false;
+
+ spin_unlock_bh(&ar->data_lock);
+
+ /* return the original firmware features */
+ memcpy(ar->fw_features, ar->testmode.orig_fw_features,
+ sizeof(ar->fw_features));
+
+ release_firmware(ar->testmode.utf);
+ ar->testmode.utf = NULL;
+
+ ar->state = ATH10K_STATE_OFF;
+}
+
+static int ath10k_tm_cmd_utf_stop(struct ath10k *ar, struct nlattr *tb[])
+{
+ int ret;
+
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf stop\n");
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state != ATH10K_STATE_UTF) {
+ ret = -ENETDOWN;
+ goto out;
+ }
+
+ __ath10k_tm_cmd_utf_stop(ar);
+
+ ret = 0;
+
+ ath10k_info(ar, "UTF firmware stopped\n");
+
+out:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
+static int ath10k_tm_cmd_wmi(struct ath10k *ar, struct nlattr *tb[])
+{
+ struct sk_buff *skb;
+ int ret, buf_len;
+ u32 cmd_id;
+ void *buf;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state != ATH10K_STATE_UTF) {
+ ret = -ENETDOWN;
+ goto out;
+ }
+
+ if (!tb[ATH10K_TM_ATTR_DATA]) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (!tb[ATH10K_TM_ATTR_WMI_CMDID]) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ buf = nla_data(tb[ATH10K_TM_ATTR_DATA]);
+ buf_len = nla_len(tb[ATH10K_TM_ATTR_DATA]);
+ cmd_id = nla_get_u32(tb[ATH10K_TM_ATTR_WMI_CMDID]);
+
+ ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
+ "testmode cmd wmi cmd_id %d buf %p buf_len %d\n",
+ cmd_id, buf, buf_len);
+
+ ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", buf, buf_len);
+
+ skb = ath10k_wmi_alloc_skb(ar, buf_len);
+ if (!skb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(skb->data, buf, buf_len);
+
+ ret = ath10k_wmi_cmd_send(ar, skb, cmd_id);
+ if (ret) {
+ ath10k_warn(ar, "failed to transmit wmi command (testmode): %d\n",
+ ret);
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
+int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ void *data, int len)
+{
+ struct ath10k *ar = hw->priv;
+ struct nlattr *tb[ATH10K_TM_ATTR_MAX + 1];
+ int ret;
+
+ ret = nla_parse(tb, ATH10K_TM_ATTR_MAX, data, len,
+ ath10k_tm_policy);
+ if (ret)
+ return ret;
+
+ if (!tb[ATH10K_TM_ATTR_CMD])
+ return -EINVAL;
+
+ switch (nla_get_u32(tb[ATH10K_TM_ATTR_CMD])) {
+ case ATH10K_TM_CMD_GET_VERSION:
+ return ath10k_tm_cmd_get_version(ar, tb);
+ case ATH10K_TM_CMD_UTF_START:
+ return ath10k_tm_cmd_utf_start(ar, tb);
+ case ATH10K_TM_CMD_UTF_STOP:
+ return ath10k_tm_cmd_utf_stop(ar, tb);
+ case ATH10K_TM_CMD_WMI:
+ return ath10k_tm_cmd_wmi(ar, tb);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+void ath10k_testmode_destroy(struct ath10k *ar)
+{
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state != ATH10K_STATE_UTF) {
+ /* utf firmware is not running, nothing to do */
+ goto out;
+ }
+
+ __ath10k_tm_cmd_utf_stop(ar);
+
+out:
+ mutex_unlock(&ar->conf_mutex);
+}
diff --git a/drivers/net/wireless/ath/ath10k/testmode.h b/drivers/net/wireless/ath/ath10k/testmode.h
new file mode 100644
index 000000000000..9cdd150815db
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/testmode.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2014 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "core.h"
+
+#ifdef CONFIG_NL80211_TESTMODE
+
+void ath10k_testmode_destroy(struct ath10k *ar);
+
+bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb);
+int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ void *data, int len);
+
+#else
+
+static inline void ath10k_testmode_destroy(struct ath10k *ar)
+{
+}
+
+static inline bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id,
+ struct sk_buff *skb)
+{
+ return false;
+}
+
+static inline int ath10k_tm_cmd(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ void *data, int len)
+{
+ return 0;
+}
+
+#endif
diff --git a/drivers/net/wireless/ath/ath10k/testmode_i.h b/drivers/net/wireless/ath/ath10k/testmode_i.h
new file mode 100644
index 000000000000..ba81bf66ce85
--- /dev/null
+++ b/drivers/net/wireless/ath/ath10k/testmode_i.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* "API" level of the ath10k testmode interface. Bump it after every
+ * incompatible interface change.
+ */
+#define ATH10K_TESTMODE_VERSION_MAJOR 1
+
+/* Bump this after every _compatible_ interface change, for example
+ * addition of a new command or an attribute.
+ */
+#define ATH10K_TESTMODE_VERSION_MINOR 0
+
+#define ATH10K_TM_DATA_MAX_LEN 5000
+
+enum ath10k_tm_attr {
+ __ATH10K_TM_ATTR_INVALID = 0,
+ ATH10K_TM_ATTR_CMD = 1,
+ ATH10K_TM_ATTR_DATA = 2,
+ ATH10K_TM_ATTR_WMI_CMDID = 3,
+ ATH10K_TM_ATTR_VERSION_MAJOR = 4,
+ ATH10K_TM_ATTR_VERSION_MINOR = 5,
+
+ /* keep last */
+ __ATH10K_TM_ATTR_AFTER_LAST,
+ ATH10K_TM_ATTR_MAX = __ATH10K_TM_ATTR_AFTER_LAST - 1,
+};
+
+/* All ath10k testmode interface commands specified in
+ * ATH10K_TM_ATTR_CMD
+ */
+enum ath10k_tm_cmd {
+ /* Returns the supported ath10k testmode interface version in
+ * ATH10K_TM_ATTR_VERSION. Always guaranteed to work. User space
+ * uses this to verify it's using the correct version of the
+ * testmode interface
+ */
+ ATH10K_TM_CMD_GET_VERSION = 0,
+
+ /* Boots the UTF firmware, the netdev interface must be down at the
+ * time.
+ */
+ ATH10K_TM_CMD_UTF_START = 1,
+
+ /* Shuts down the UTF firmware and puts the driver back into OFF
+ * state.
+ */
+ ATH10K_TM_CMD_UTF_STOP = 2,
+
+ /* The command used to transmit a WMI command to the firmware and
+ * the event to receive WMI events from the firmware. Without
+ * struct wmi_cmd_hdr header, only the WMI payload. Command id is
+ * provided with ATH10K_TM_ATTR_WMI_CMDID and payload in
+ * ATH10K_TM_ATTR_DATA.
+ */
+ ATH10K_TM_CMD_WMI = 3,
+};
diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h
index 4eb2ecbc06ef..574b75ab2609 100644
--- a/drivers/net/wireless/ath/ath10k/trace.h
+++ b/drivers/net/wireless/ath/ath10k/trace.h
@@ -18,6 +18,7 @@
#if !defined(_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
#include <linux/tracepoint.h>
+#include "core.h"
#define _TRACE_H_
@@ -39,59 +40,79 @@ static inline void trace_ ## name(proto) {}
#define ATH10K_MSG_MAX 200
DECLARE_EVENT_CLASS(ath10k_log_event,
- TP_PROTO(struct va_format *vaf),
- TP_ARGS(vaf),
+ TP_PROTO(struct ath10k *ar, struct va_format *vaf),
+ TP_ARGS(ar, vaf),
TP_STRUCT__entry(
+ __string(device, dev_name(ar->dev))
+ __string(driver, dev_driver_string(ar->dev))
__dynamic_array(char, msg, ATH10K_MSG_MAX)
),
TP_fast_assign(
+ __assign_str(device, dev_name(ar->dev));
+ __assign_str(driver, dev_driver_string(ar->dev));
WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
ATH10K_MSG_MAX,
vaf->fmt,
*vaf->va) >= ATH10K_MSG_MAX);
),
- TP_printk("%s", __get_str(msg))
+ TP_printk(
+ "%s %s %s",
+ __get_str(driver),
+ __get_str(device),
+ __get_str(msg)
+ )
);
DEFINE_EVENT(ath10k_log_event, ath10k_log_err,
- TP_PROTO(struct va_format *vaf),
- TP_ARGS(vaf)
+ TP_PROTO(struct ath10k *ar, struct va_format *vaf),
+ TP_ARGS(ar, vaf)
);
DEFINE_EVENT(ath10k_log_event, ath10k_log_warn,
- TP_PROTO(struct va_format *vaf),
- TP_ARGS(vaf)
+ TP_PROTO(struct ath10k *ar, struct va_format *vaf),
+ TP_ARGS(ar, vaf)
);
DEFINE_EVENT(ath10k_log_event, ath10k_log_info,
- TP_PROTO(struct va_format *vaf),
- TP_ARGS(vaf)
+ TP_PROTO(struct ath10k *ar, struct va_format *vaf),
+ TP_ARGS(ar, vaf)
);
TRACE_EVENT(ath10k_log_dbg,
- TP_PROTO(unsigned int level, struct va_format *vaf),
- TP_ARGS(level, vaf),
+ TP_PROTO(struct ath10k *ar, unsigned int level, struct va_format *vaf),
+ TP_ARGS(ar, level, vaf),
TP_STRUCT__entry(
+ __string(device, dev_name(ar->dev))
+ __string(driver, dev_driver_string(ar->dev))
__field(unsigned int, level)
__dynamic_array(char, msg, ATH10K_MSG_MAX)
),
TP_fast_assign(
+ __assign_str(device, dev_name(ar->dev));
+ __assign_str(driver, dev_driver_string(ar->dev));
__entry->level = level;
WARN_ON_ONCE(vsnprintf(__get_dynamic_array(msg),
ATH10K_MSG_MAX,
vaf->fmt,
*vaf->va) >= ATH10K_MSG_MAX);
),
- TP_printk("%s", __get_str(msg))
+ TP_printk(
+ "%s %s %s",
+ __get_str(driver),
+ __get_str(device),
+ __get_str(msg)
+ )
);
TRACE_EVENT(ath10k_log_dbg_dump,
- TP_PROTO(const char *msg, const char *prefix,
+ TP_PROTO(struct ath10k *ar, const char *msg, const char *prefix,
const void *buf, size_t buf_len),
- TP_ARGS(msg, prefix, buf, buf_len),
+ TP_ARGS(ar, msg, prefix, buf, buf_len),
TP_STRUCT__entry(
+ __string(device, dev_name(ar->dev))
+ __string(driver, dev_driver_string(ar->dev))
__string(msg, msg)
__string(prefix, prefix)
__field(size_t, buf_len)
@@ -99,6 +120,8 @@ TRACE_EVENT(ath10k_log_dbg_dump,
),
TP_fast_assign(
+ __assign_str(device, dev_name(ar->dev));
+ __assign_str(driver, dev_driver_string(ar->dev));
__assign_str(msg, msg);
__assign_str(prefix, prefix);
__entry->buf_len = buf_len;
@@ -106,16 +129,22 @@ TRACE_EVENT(ath10k_log_dbg_dump,
),
TP_printk(
- "%s/%s\n", __get_str(prefix), __get_str(msg)
+ "%s %s %s/%s\n",
+ __get_str(driver),
+ __get_str(device),
+ __get_str(prefix),
+ __get_str(msg)
)
);
TRACE_EVENT(ath10k_wmi_cmd,
- TP_PROTO(int id, void *buf, size_t buf_len, int ret),
+ TP_PROTO(struct ath10k *ar, int id, void *buf, size_t buf_len, int ret),
- TP_ARGS(id, buf, buf_len, ret),
+ TP_ARGS(ar, id, buf, buf_len, ret),
TP_STRUCT__entry(
+ __string(device, dev_name(ar->dev))
+ __string(driver, dev_driver_string(ar->dev))
__field(unsigned int, id)
__field(size_t, buf_len)
__dynamic_array(u8, buf, buf_len)
@@ -123,6 +152,8 @@ TRACE_EVENT(ath10k_wmi_cmd,
),
TP_fast_assign(
+ __assign_str(device, dev_name(ar->dev));
+ __assign_str(driver, dev_driver_string(ar->dev));
__entry->id = id;
__entry->buf_len = buf_len;
__entry->ret = ret;
@@ -130,7 +161,9 @@ TRACE_EVENT(ath10k_wmi_cmd,
),
TP_printk(
- "id %d len %zu ret %d",
+ "%s %s id %d len %zu ret %d",
+ __get_str(driver),
+ __get_str(device),
__entry->id,
__entry->buf_len,
__entry->ret
@@ -138,67 +171,85 @@ TRACE_EVENT(ath10k_wmi_cmd,
);
TRACE_EVENT(ath10k_wmi_event,
- TP_PROTO(int id, void *buf, size_t buf_len),
+ TP_PROTO(struct ath10k *ar, int id, void *buf, size_t buf_len),
- TP_ARGS(id, buf, buf_len),
+ TP_ARGS(ar, id, buf, buf_len),
TP_STRUCT__entry(
+ __string(device, dev_name(ar->dev))
+ __string(driver, dev_driver_string(ar->dev))
__field(unsigned int, id)
__field(size_t, buf_len)
__dynamic_array(u8, buf, buf_len)
),
TP_fast_assign(
+ __assign_str(device, dev_name(ar->dev));
+ __assign_str(driver, dev_driver_string(ar->dev));
__entry->id = id;
__entry->buf_len = buf_len;
memcpy(__get_dynamic_array(buf), buf, buf_len);
),
TP_printk(
- "id %d len %zu",
+ "%s %s id %d len %zu",
+ __get_str(driver),
+ __get_str(device),
__entry->id,
__entry->buf_len
)
);
TRACE_EVENT(ath10k_htt_stats,
- TP_PROTO(void *buf, size_t buf_len),
+ TP_PROTO(struct ath10k *ar, void *buf, size_t buf_len),
- TP_ARGS(buf, buf_len),
+ TP_ARGS(ar, buf, buf_len),
TP_STRUCT__entry(
+ __string(device, dev_name(ar->dev))
+ __string(driver, dev_driver_string(ar->dev))
__field(size_t, buf_len)
__dynamic_array(u8, buf, buf_len)
),
TP_fast_assign(
+ __assign_str(device, dev_name(ar->dev));
+ __assign_str(driver, dev_driver_string(ar->dev));
__entry->buf_len = buf_len;
memcpy(__get_dynamic_array(buf), buf, buf_len);
),
TP_printk(
- "len %zu",
+ "%s %s len %zu",
+ __get_str(driver),
+ __get_str(device),
__entry->buf_len
)
);
TRACE_EVENT(ath10k_wmi_dbglog,
- TP_PROTO(void *buf, size_t buf_len),
+ TP_PROTO(struct ath10k *ar, void *buf, size_t buf_len),
- TP_ARGS(buf, buf_len),
+ TP_ARGS(ar, buf, buf_len),
TP_STRUCT__entry(
+ __string(device, dev_name(ar->dev))
+ __string(driver, dev_driver_string(ar->dev))
__field(size_t, buf_len)
__dynamic_array(u8, buf, buf_len)
),
TP_fast_assign(
+ __assign_str(device, dev_name(ar->dev));
+ __assign_str(driver, dev_driver_string(ar->dev));
__entry->buf_len = buf_len;
memcpy(__get_dynamic_array(buf), buf, buf_len);
),
TP_printk(
- "len %zu",
+ "%s %s len %zu",
+ __get_str(driver),
+ __get_str(device),
__entry->buf_len
)
);
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 2eeec8a63d5c..a0cbc21d0d4b 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -178,7 +178,7 @@ void ath10k_peer_map_event(struct ath10k_htt *htt,
goto exit;
peer->vdev_id = ev->vdev_id;
- memcpy(peer->addr, ev->addr, ETH_ALEN);
+ ether_addr_copy(peer->addr, ev->addr);
list_add(&peer->list, &ar->peers);
wake_up(&ar->peer_mapping_wq);
}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index e500a3cc905e..2c42bd504b79 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -23,6 +23,7 @@
#include "debug.h"
#include "wmi.h"
#include "mac.h"
+#include "testmode.h"
/* MAIN WMI cmd track */
static struct wmi_cmd_map wmi_cmd_map = {
@@ -611,6 +612,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = {
int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
{
int ret;
+
ret = wait_for_completion_timeout(&ar->wmi.service_ready,
WMI_SERVICE_READY_TIMEOUT_HZ);
return ret;
@@ -619,12 +621,13 @@ int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar)
{
int ret;
+
ret = wait_for_completion_timeout(&ar->wmi.unified_ready,
WMI_UNIFIED_READY_TIMEOUT_HZ);
return ret;
}
-static struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len)
+struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len)
{
struct sk_buff *skb;
u32 round_len = roundup(len, 4);
@@ -666,7 +669,7 @@ static int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb,
memset(skb_cb, 0, sizeof(*skb_cb));
ret = ath10k_htc_send(&ar->htc, ar->wmi.eid, skb);
- trace_ath10k_wmi_cmd(cmd_id, skb->data, skb->len, ret);
+ trace_ath10k_wmi_cmd(ar, cmd_id, skb->data, skb->len, ret);
if (ret)
goto err_pull;
@@ -725,8 +728,7 @@ static void ath10k_wmi_op_ep_tx_credits(struct ath10k *ar)
wake_up(&ar->wmi.tx_credits_wq);
}
-static int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb,
- u32 cmd_id)
+int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
{
int ret = -EOPNOTSUPP;
@@ -792,7 +794,7 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb)
cmd->hdr.tx_power = 0;
cmd->hdr.buf_len = __cpu_to_le32(buf_len);
- memcpy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr), ETH_ALEN);
+ ether_addr_copy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr));
memcpy(cmd->buf, skb->data, skb->len);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n",
@@ -1288,7 +1290,7 @@ static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb)
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event debug mesg len %d\n",
skb->len);
- trace_ath10k_wmi_dbglog(skb->data, skb->len);
+ trace_ath10k_wmi_dbglog(ar, skb->data, skb->len);
return 0;
}
@@ -1384,6 +1386,8 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
struct ieee80211_tim_ie *tim;
u8 *ies, *ie;
u8 ie_len, pvm_len;
+ __le32 t;
+ u32 v;
/* if next SWBA has no tim_changed the tim_bitmap is garbage.
* we must copy the bitmap upon change and reuse it later */
@@ -1394,8 +1398,8 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
sizeof(bcn_info->tim_info.tim_bitmap));
for (i = 0; i < sizeof(arvif->u.ap.tim_bitmap); i++) {
- __le32 t = bcn_info->tim_info.tim_bitmap[i / 4];
- u32 v = __le32_to_cpu(t);
+ t = bcn_info->tim_info.tim_bitmap[i / 4];
+ v = __le32_to_cpu(t);
arvif->u.ap.tim_bitmap[i] = (v >> ((i % 4) * 8)) & 0xFF;
}
@@ -1511,7 +1515,6 @@ static u32 ath10k_p2p_calc_noa_ie_len(struct wmi_p2p_noa_info *noa)
u8 opp_ps_info = noa->ctwindow_oppps;
bool opps_enabled = !!(opp_ps_info & WMI_P2P_OPPPS_ENABLE_BIT);
-
if (!noa_descriptors && !opps_enabled)
return len;
@@ -1568,7 +1571,6 @@ cleanup:
kfree(old_data);
}
-
static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_host_swba_event *ev;
@@ -1859,9 +1861,10 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar,
}
}
-static void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
- struct wmi_single_phyerr_rx_event *event,
- u64 tsf)
+static void
+ath10k_wmi_event_spectral_scan(struct ath10k *ar,
+ struct wmi_single_phyerr_rx_event *event,
+ u64 tsf)
{
int buf_len, tlv_len, res, i = 0;
struct phyerr_tlv *tlv;
@@ -1989,7 +1992,7 @@ static void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb)
}
static void ath10k_wmi_event_profile_match(struct ath10k *ar,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_PROFILE_MATCH\n");
}
@@ -2040,13 +2043,13 @@ static void ath10k_wmi_event_wlan_profile_data(struct ath10k *ar,
}
static void ath10k_wmi_event_rtt_measurement_report(struct ath10k *ar,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_RTT_MEASUREMENT_REPORT_EVENTID\n");
}
static void ath10k_wmi_event_tsf_measurement_report(struct ath10k *ar,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TSF_MEASUREMENT_REPORT_EVENTID\n");
}
@@ -2082,7 +2085,7 @@ static void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar,
}
static void ath10k_wmi_event_gtk_offload_status(struct ath10k *ar,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_GTK_OFFLOAD_STATUS_EVENTID\n");
}
@@ -2106,7 +2109,7 @@ static void ath10k_wmi_event_addba_complete(struct ath10k *ar,
}
static void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar,
- struct sk_buff *skb)
+ struct sk_buff *skb)
{
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_INSTALL_KEY_COMPLETE_EVENTID\n");
}
@@ -2130,7 +2133,7 @@ static void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar,
}
static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
- u32 num_units, u32 unit_len)
+ u32 num_units, u32 unit_len)
{
dma_addr_t paddr;
u32 pool_size;
@@ -2164,7 +2167,7 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
struct sk_buff *skb)
{
struct wmi_service_ready_event *ev = (void *)skb->data;
- DECLARE_BITMAP(svc_bmap, WMI_SERVICE_BM_SIZE) = {};
+ DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {};
if (skb->len < sizeof(*ev)) {
ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
@@ -2241,7 +2244,7 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
int ret;
struct wmi_service_ready_event_10x *ev = (void *)skb->data;
- DECLARE_BITMAP(svc_bmap, WMI_SERVICE_BM_SIZE) = {};
+ DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {};
if (skb->len < sizeof(*ev)) {
ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
@@ -2347,7 +2350,7 @@ static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb)
if (WARN_ON(skb->len < sizeof(*ev)))
return -EINVAL;
- memcpy(ar->mac_addr, ev->mac_addr.addr, ETH_ALEN);
+ ether_addr_copy(ar->mac_addr, ev->mac_addr.addr);
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi event ready sw_version %u abi_version %u mac_addr %pM status %d skb->len %i ev-sz %zu\n",
@@ -2371,7 +2374,7 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb)
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
return;
- trace_ath10k_wmi_event(id, skb->data, skb->len);
+ trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
switch (id) {
case WMI_MGMT_RX_EVENTID:
@@ -2480,6 +2483,7 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
enum wmi_10x_event_id id;
+ bool consumed;
cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
@@ -2487,7 +2491,19 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
return;
- trace_ath10k_wmi_event(id, skb->data, skb->len);
+ trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
+
+ consumed = ath10k_tm_event_wmi(ar, id, skb);
+
+ /* Ready event must be handled normally also in UTF mode so that we
+ * know the UTF firmware has booted, others we are just bypass WMI
+ * events to testmode.
+ */
+ if (consumed && id != WMI_10X_READY_EVENTID) {
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi testmode consumed 0x%x\n", id);
+ goto out;
+ }
switch (id) {
case WMI_10X_MGMT_RX_EVENTID:
@@ -2575,11 +2591,15 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
case WMI_10X_READY_EVENTID:
ath10k_wmi_ready_event_rx(ar, skb);
break;
+ case WMI_10X_PDEV_UTF_EVENTID:
+ /* ignore utf events */
+ break;
default:
ath10k_warn(ar, "Unknown eventid: %d\n", id);
break;
}
+out:
dev_kfree_skb(skb);
}
@@ -2594,7 +2614,7 @@ static void ath10k_wmi_10_2_process_rx(struct ath10k *ar, struct sk_buff *skb)
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
return;
- trace_ath10k_wmi_event(id, skb->data, skb->len);
+ trace_ath10k_wmi_event(ar, id, skb->data, skb->len);
switch (id) {
case WMI_10_2_MGMT_RX_EVENTID:
@@ -3476,7 +3496,7 @@ int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id,
cmd->vdev_id = __cpu_to_le32(vdev_id);
cmd->vdev_type = __cpu_to_le32(type);
cmd->vdev_subtype = __cpu_to_le32(subtype);
- memcpy(cmd->vdev_macaddr.addr, macaddr, ETH_ALEN);
+ ether_addr_copy(cmd->vdev_macaddr.addr, macaddr);
ath10k_dbg(ar, ATH10K_DBG_WMI,
"WMI vdev create: id %d type %d subtype %d macaddr %pM\n",
@@ -3503,9 +3523,10 @@ int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id)
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_delete_cmdid);
}
-static int ath10k_wmi_vdev_start_restart(struct ath10k *ar,
- const struct wmi_vdev_start_request_arg *arg,
- u32 cmd_id)
+static int
+ath10k_wmi_vdev_start_restart(struct ath10k *ar,
+ const struct wmi_vdev_start_request_arg *arg,
+ u32 cmd_id)
{
struct wmi_vdev_start_request_cmd *cmd;
struct sk_buff *skb;
@@ -3569,8 +3590,8 @@ static int ath10k_wmi_vdev_start_restart(struct ath10k *ar,
cmd->chan.antenna_max = arg->channel.max_antenna_gain;
ath10k_dbg(ar, ATH10K_DBG_WMI,
- "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, "
- "ch_flags: 0x%0X, max_power: %d\n", cmdname, arg->vdev_id,
+ "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, ch_flags: 0x%0X, max_power: %d\n",
+ cmdname, arg->vdev_id,
flags, arg->channel.freq, arg->channel.mode,
cmd->chan.flags, arg->channel.max_power);
@@ -3586,7 +3607,7 @@ int ath10k_wmi_vdev_start(struct ath10k *ar,
}
int ath10k_wmi_vdev_restart(struct ath10k *ar,
- const struct wmi_vdev_start_request_arg *arg)
+ const struct wmi_vdev_start_request_arg *arg)
{
u32 cmd_id = ar->wmi.cmd->vdev_restart_request_cmdid;
@@ -3622,7 +3643,7 @@ int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
cmd = (struct wmi_vdev_up_cmd *)skb->data;
cmd->vdev_id = __cpu_to_le32(vdev_id);
cmd->vdev_assoc_id = __cpu_to_le32(aid);
- memcpy(&cmd->vdev_bssid.addr, bssid, ETH_ALEN);
+ ether_addr_copy(cmd->vdev_bssid.addr, bssid);
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi mgmt vdev up id 0x%x assoc id %d bssid %pM\n",
@@ -3703,7 +3724,7 @@ int ath10k_wmi_vdev_install_key(struct ath10k *ar,
cmd->key_rxmic_len = __cpu_to_le32(arg->key_rxmic_len);
if (arg->macaddr)
- memcpy(cmd->peer_macaddr.addr, arg->macaddr, ETH_ALEN);
+ ether_addr_copy(cmd->peer_macaddr.addr, arg->macaddr);
if (arg->key_data)
memcpy(cmd->key_data, arg->key_data, arg->key_len);
@@ -3782,7 +3803,7 @@ int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
cmd = (struct wmi_peer_create_cmd *)skb->data;
cmd->vdev_id = __cpu_to_le32(vdev_id);
- memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN);
+ ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi peer create vdev_id %d peer_addr %pM\n",
@@ -3802,7 +3823,7 @@ int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
cmd = (struct wmi_peer_delete_cmd *)skb->data;
cmd->vdev_id = __cpu_to_le32(vdev_id);
- memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN);
+ ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi peer delete vdev_id %d peer_addr %pM\n",
@@ -3823,7 +3844,7 @@ int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id,
cmd = (struct wmi_peer_flush_tids_cmd *)skb->data;
cmd->vdev_id = __cpu_to_le32(vdev_id);
cmd->peer_tid_bitmap = __cpu_to_le32(tid_bitmap);
- memcpy(cmd->peer_macaddr.addr, peer_addr, ETH_ALEN);
+ ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi peer flush vdev_id %d peer_addr %pM tids %08x\n",
@@ -3846,7 +3867,7 @@ int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id,
cmd->vdev_id = __cpu_to_le32(vdev_id);
cmd->param_id = __cpu_to_le32(param_id);
cmd->param_value = __cpu_to_le32(param_value);
- memcpy(&cmd->peer_macaddr.addr, peer_addr, ETH_ALEN);
+ ether_addr_copy(cmd->peer_macaddr.addr, peer_addr);
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi vdev %d peer 0x%pM set param %d value %d\n",
@@ -3917,7 +3938,7 @@ int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac,
cmd->vdev_id = __cpu_to_le32(vdev_id);
cmd->param_id = __cpu_to_le32(param_id);
cmd->param_value = __cpu_to_le32(value);
- memcpy(&cmd->peer_macaddr, mac, ETH_ALEN);
+ ether_addr_copy(cmd->peer_macaddr.addr, mac);
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi ap ps param vdev_id 0x%X param %d value %d mac_addr %pM\n",
@@ -4001,7 +4022,7 @@ ath10k_wmi_peer_assoc_fill(struct ath10k *ar, void *buf,
cmd->peer_vht_caps = __cpu_to_le32(arg->peer_vht_caps);
cmd->peer_phymode = __cpu_to_le32(arg->peer_phymode);
- memcpy(cmd->peer_macaddr.addr, arg->addr, ETH_ALEN);
+ ether_addr_copy(cmd->peer_macaddr.addr, arg->addr);
cmd->peer_legacy_rates.num_rates =
__cpu_to_le32(arg->peer_legacy_rates.num_rates);
@@ -4155,7 +4176,7 @@ static void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params,
}
int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
- const struct wmi_pdev_set_wmm_params_arg *arg)
+ const struct wmi_pdev_set_wmm_params_arg *arg)
{
struct wmi_pdev_set_wmm_params *cmd;
struct sk_buff *skb;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index e70836586756..86f5ebccfe79 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -109,6 +109,9 @@ enum wmi_service {
WMI_SERVICE_BURST,
WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT,
WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT,
+
+ /* keep last */
+ WMI_SERVICE_MAX,
};
enum wmi_10x_service {
@@ -219,8 +222,6 @@ static inline char *wmi_service_name(int service_id)
#undef SVCSTR
}
-#define WMI_MAX_SERVICE 64
-
#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id) \
(__le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
BIT((svc_id)%(sizeof(u32))))
@@ -347,9 +348,6 @@ static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out)
#undef SVCMAP
-#define WMI_SERVICE_BM_SIZE \
- ((WMI_MAX_SERVICE + sizeof(u32) - 1)/sizeof(u32))
-
/* 2 word representation of MAC addr */
struct wmi_mac_addr {
union {
@@ -1271,7 +1269,6 @@ enum wmi_channel_change_cause {
WMI_HT_CAP_RX_STBC | \
WMI_HT_CAP_LDPC)
-
/*
* WMI_VHT_CAP_* these maps to ieee 802.11ac vht capability information
* field. The fields not defined here are not supported, or reserved.
@@ -1405,7 +1402,7 @@ struct wmi_service_ready_event {
__le32 phy_capability;
/* Maximum number of frag table entries that SW will populate less 1 */
__le32 max_frag_entry;
- __le32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE];
+ __le32 wmi_service_bitmap[16];
__le32 num_rf_chains;
/*
* The following field is only valid for service type
@@ -1444,7 +1441,7 @@ struct wmi_service_ready_event_10x {
/* Maximum number of frag table entries that SW will populate less 1 */
__le32 max_frag_entry;
- __le32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE];
+ __le32 wmi_service_bitmap[16];
__le32 num_rf_chains;
/*
@@ -1473,7 +1470,6 @@ struct wmi_service_ready_event_10x {
struct wlan_host_mem_req mem_reqs[1];
} __packed;
-
#define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ)
#define WMI_UNIFIED_READY_TIMEOUT_HZ (5*HZ)
@@ -2127,7 +2123,6 @@ struct wmi_start_scan_cmd_10x {
*/
} __packed;
-
struct wmi_ssid_arg {
int len;
const u8 *ssid;
@@ -2188,7 +2183,6 @@ struct wmi_start_scan_arg {
/* WMI_SCAN_CLASS_MASK must be the same value as IEEE80211_SCAN_CLASS_MASK */
#define WMI_SCAN_CLASS_MASK 0xFF000000
-
enum wmi_stop_scan_type {
WMI_SCAN_STOP_ONE = 0x00000000, /* stop by scan_id */
WMI_SCAN_STOP_VDEV_ALL = 0x01000000, /* stop by vdev_id */
@@ -2373,7 +2367,6 @@ struct wmi_single_phyerr_rx_hdr {
__le32 nf_list_1;
__le32 nf_list_2;
-
/* Length of the frame */
__le32 buf_len;
} __packed;
@@ -2475,7 +2468,6 @@ struct phyerr_fft_report {
#define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_MASK 0x000000FF
#define SEARCH_FFT_REPORT_REG1_NUM_STR_BINS_IB_LSB 0
-
struct phyerr_tlv {
__le16 len;
u8 tag;
@@ -2506,7 +2498,6 @@ struct wmi_echo_cmd {
__le32 value;
} __packed;
-
struct wmi_pdev_set_regdomain_cmd {
__le32 reg_domain;
__le32 reg_domain_2G;
@@ -2555,7 +2546,6 @@ struct wmi_pdev_set_quiet_cmd {
__le32 enabled;
} __packed;
-
/*
* 802.11g protection mode.
*/
@@ -4293,7 +4283,6 @@ struct wmi_tbtt_offset_event {
__le32 tbttoffset_list[WMI_MAX_AP_VDEV];
} __packed;
-
struct wmi_peer_create_cmd {
__le32 vdev_id;
struct wmi_mac_addr peer_macaddr;
@@ -4739,6 +4728,10 @@ int ath10k_wmi_wait_for_service_ready(struct ath10k *ar);
int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar);
int ath10k_wmi_connect(struct ath10k *ar);
+
+struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
+int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
+
int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
const struct wmi_channel_arg *);
int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);
@@ -4774,11 +4767,11 @@ int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
u32 enable);
int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
- const u8 peer_addr[ETH_ALEN]);
+ const u8 peer_addr[ETH_ALEN]);
int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
- const u8 peer_addr[ETH_ALEN]);
+ const u8 peer_addr[ETH_ALEN]);
int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id,
- const u8 peer_addr[ETH_ALEN], u32 tid_bitmap);
+ const u8 peer_addr[ETH_ALEN], u32 tid_bitmap);
int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id,
const u8 *peer_addr,
enum wmi_peer_param param_id, u32 param_value);
@@ -4795,7 +4788,7 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar,
const struct wmi_scan_chan_list_arg *arg);
int ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif);
int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
- const struct wmi_pdev_set_wmm_params_arg *arg);
+ const struct wmi_pdev_set_wmm_params_arg *arg);
int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id);
int ath10k_wmi_force_fw_hang(struct ath10k *ar,
enum wmi_force_fw_hang_type type, u32 delay_ms);