Commit 687b9308 authored by John W. Linville's avatar John W. Linville

Merge branch 'for-linville' of git://github.com/kvalo/ath

parents d3d3e001 b25f32cb
......@@ -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
......
......@@ -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
......
......@@ -177,7 +177,6 @@ struct bmi_target_info {
u32 type;
};
/* in msec */
#define BMI_COMMUNICATION_TIMEOUT_HZ (1*HZ)
......
......@@ -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;
......
......@@ -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;
......
......@@ -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 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
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);
......
......@@ -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);
......
......@@ -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);
......
......@@ -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)
......
......@@ -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)
......
......@@ -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));
......
......@@ -214,7 +214,6 @@ struct ath10k_htc_frame {
struct ath10k_htc_record trailer[0];
} __packed __aligned(4);
/*******************/
/* Host-side stuff */
/*******************/
......
......@@ -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;
......
......@@ -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 {
......
......@@ -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
......
......@@ -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;
......
......@@ -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"
......
This diff is collapsed.
This diff is collapsed.
......@@ -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)
......
......@@ -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 */
......
/*
* Copyright (c) 2014 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "testmode.h"
#include <net/netlink.h>
#include <linux/firmware.h>
#include "debug.h"
#include "wmi.h"
#include "hif.h"
#include "hw.h"
#include "testmode_i.h"
static const struct nla_policy ath10k_tm_policy[ATH10K_TM_ATTR_MAX + 1] = {
[ATH10K_TM_ATTR_CMD] = { .type = NLA_U32 },
[ATH10K_TM_ATTR_DATA] = { .type = NLA_BINARY,
.len = ATH10K_TM_DATA_MAX_LEN },
[ATH10K_TM_ATTR_WMI_CMDID] = { .type = NLA_U32 },
[ATH10K_TM_ATTR_VERSION_MAJOR] = { .type = NLA_U32 },
[ATH10K_TM_ATTR_VERSION_MINOR] = { .type = NLA_U32 },
};
/* Returns true if callee consumes the skb and the skb should be discarded.
* Returns false if skb is not used. Does not sleep.
*/
bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb)
{
struct sk_buff *nl_skb;
bool consumed;
int ret;
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
"testmode event wmi cmd_id %d skb %p skb->len %d\n",
cmd_id, skb, skb->len);
ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", skb->data, skb->len);
spin_lock_bh(&ar->data_lock);
if (!ar->testmode.utf_monitor) {
consumed = false;
goto out;
}
/* Only testmode.c should be handling events from utf firmware,
* otherwise all sort of problems will arise as mac80211 operations
* are not initialised.
*/
consumed = true;
nl_skb = cfg80211_testmode_alloc_event_skb(ar->hw->wiphy,
2 * sizeof(u32) + skb->len,
GFP_ATOMIC);
if (!nl_skb) {
ath10k_warn(ar,
"failed to allocate skb for testmode wmi event\n");
goto out;
}
ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_CMD, ATH10K_TM_CMD_WMI);
if (ret) {
ath10k_warn(ar,
"failed to to put testmode wmi event cmd attribute: %d\n",
ret);
kfree_skb(nl_skb);
goto out;
}
ret = nla_put_u32(nl_skb, ATH10K_TM_ATTR_WMI_CMDID, cmd_id);
if (ret) {
ath10k_warn(ar,
"failed to to put testmode wmi even cmd_id: %d\n",
ret);
kfree_skb(nl_skb);
goto out;
}
ret = nla_put(nl_skb, ATH10K_TM_ATTR_DATA, skb->len, skb->data);
if (ret) {
ath10k_warn(ar,
"failed to copy skb to testmode wmi event: %d\n",
ret);
kfree_skb(nl_skb);
goto out;
}
cfg80211_testmode_event(nl_skb, GFP_ATOMIC);
out:
spin_unlock_bh(&ar->data_lock);
return consumed;
}
static int ath10k_tm_cmd_get_version(struct ath10k *ar, struct nlattr *tb[])
{
struct sk_buff *skb;
int ret;
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
"testmode cmd get version_major %d version_minor %d\n",
ATH10K_TESTMODE_VERSION_MAJOR,
ATH10K_TESTMODE_VERSION_MINOR);
skb = cfg80211_testmode_alloc_reply_skb(ar->hw->wiphy,
nla_total_size(sizeof(u32)));
if (!skb)
return -ENOMEM;
ret = nla_put_u32(skb, ATH10K_TM_ATTR_VERSION_MAJOR,
ATH10K_TESTMODE_VERSION_MAJOR);
if (ret) {
kfree_skb(skb);
return ret;
}
ret = nla_put_u32(skb, ATH10K_TM_ATTR_VERSION_MINOR,
ATH10K_TESTMODE_VERSION_MINOR);
if (ret) {
kfree_skb(skb);
return ret;
}
return cfg80211_testmode_reply(skb);
}
static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
{
char filename[100];
int ret;
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf start\n");
mutex_lock(&ar->conf_mutex);
if (ar->state == ATH10K_STATE_UTF) {
ret = -EALREADY;
goto err;
}
/* start utf only when the driver is not in use */
if (ar->state != ATH10K_STATE_OFF) {
ret = -EBUSY;
goto err;
}
if (WARN_ON(ar->testmode.utf != NULL)) {
/* utf image is already downloaded, it shouldn't be */
ret = -EEXIST;
goto err;
}
snprintf(filename, sizeof(filename), "%s/%s",
ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE);
/* load utf firmware image */
ret = request_firmware(&ar->testmode.utf, filename, ar->dev);
if (ret) {
ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n",
filename, ret);
goto err;
}
spin_lock_bh(&ar->data_lock);
ar->testmode.utf_monitor = true;
spin_unlock_bh(&ar->data_lock);
BUILD_BUG_ON(sizeof(ar->fw_features) !=
sizeof(ar->testmode.orig_fw_features));
memcpy(ar->testmode.orig_fw_features, ar->fw_features,
sizeof(ar->fw_features));
/* utf.bin firmware image does not advertise firmware features. Do
* an ugly hack where we force the firmware features so that wmi.c
* will use the correct WMI interface.
*/
memset(ar->fw_features, 0, sizeof(ar->fw_features));
__set_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features);
ret = ath10k_hif_power_up(ar);
if (ret) {
ath10k_err(ar, "failed to power up hif (testmode): %d\n", ret);
ar->state = ATH10K_STATE_OFF;
goto err_fw_features;
}
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_UTF);
if (ret) {
ath10k_err(ar, "failed to start core (testmode): %d\n", ret);
ar->state = ATH10K_STATE_OFF;
goto err_power_down;
}
ar->state = ATH10K_STATE_UTF;
ath10k_info(ar, "UTF firmware started\n");
mutex_unlock(&ar->conf_mutex);
return 0;
err_power_down:
ath10k_hif_power_down(ar);
err_fw_features:
/* return the original firmware features */
memcpy(ar->fw_features, ar->testmode.orig_fw_features,
sizeof(ar->fw_features));
release_firmware(ar->testmode.utf);
ar->testmode.utf = NULL;
err:
mutex_unlock(&ar->conf_mutex);
return ret;
}
static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar)
{
lockdep_assert_held(&ar->conf_mutex);
ath10k_core_stop(ar);
ath10k_hif_power_down(ar);
spin_lock_bh(&ar->data_lock);
ar->testmode.utf_monitor = false;
spin_unlock_bh(&ar->data_lock);
/* return the original firmware features */
memcpy(ar->fw_features, ar->testmode.orig_fw_features,
sizeof(ar->fw_features));
release_firmware(ar->testmode.utf);
ar->testmode.utf = NULL;
ar->state = ATH10K_STATE_OFF;
}
static int ath10k_tm_cmd_utf_stop(struct ath10k *ar, struct nlattr *tb[])
{
int ret;
ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode cmd utf stop\n");
mutex_lock(&ar->conf_mutex);
if (ar->state != ATH10K_STATE_UTF) {
ret = -ENETDOWN;
goto out;
}
__ath10k_tm_cmd_utf_stop(ar);
ret = 0;
ath10k_info(ar, "UTF firmware stopped\n");
out:
mutex_unlock(&ar->conf_mutex);
return ret;
}
static int ath10k_tm_cmd_wmi(struct ath10k *ar, struct nlattr *tb[])
{
struct sk_buff *skb;
int ret, buf_len;
u32 cmd_id;
void *buf;
mutex_lock(&ar->conf_mutex);
if (ar->state != ATH10K_STATE_UTF) {
ret = -ENETDOWN;
goto out;
}
if (!tb[ATH10K_TM_ATTR_DATA]) {
ret = -EINVAL;
goto out;
}
if (!tb[ATH10K_TM_ATTR_WMI_CMDID]) {
ret = -EINVAL;
goto out;
}
buf = nla_data(tb[ATH10K_TM_ATTR_DATA]);
buf_len = nla_len(tb[ATH10K_TM_ATTR_DATA]);
cmd_id = nla_get_u32(tb[ATH10K_TM_ATTR_WMI_CMDID]);
ath10k_dbg(ar, ATH10K_DBG_TESTMODE,
"testmode cmd wmi cmd_id %d buf %p buf_len %d\n",
cmd_id, buf, buf_len);
ath10k_dbg_dump(ar, ATH10K_DBG_TESTMODE, NULL, "", buf, buf_len);
skb = ath10k_wmi_alloc_skb(ar, buf_len);
if (!skb) {
ret = -ENOMEM;
goto out;
}
memcpy(skb->data, buf, buf_len);
ret = ath10k_wmi_cmd_send(ar, skb, cmd_id);
if (ret) {
ath10k_warn(ar, "failed to transmit wmi command (testmode): %d\n",
ret);
goto out;
}
ret = 0;
out:
mutex_unlock(&ar->conf_mutex);
return ret;
}
int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void *data, int len)
{
struct ath10k *ar = hw->priv;
struct nlattr *tb[ATH10K_TM_ATTR_MAX + 1];
int ret;
ret = nla_parse(tb, ATH10K_TM_ATTR_MAX, data, len,
ath10k_tm_policy);
if (ret)
return ret;
if (!tb[ATH10K_TM_ATTR_CMD])
return -EINVAL;
switch (nla_get_u32(tb[ATH10K_TM_ATTR_CMD])) {
case ATH10K_TM_CMD_GET_VERSION:
return ath10k_tm_cmd_get_version(ar, tb);
case ATH10K_TM_CMD_UTF_START:
return ath10k_tm_cmd_utf_start(ar, tb);
case ATH10K_TM_CMD_UTF_STOP:
return ath10k_tm_cmd_utf_stop(ar, tb);
case ATH10K_TM_CMD_WMI:
return ath10k_tm_cmd_wmi(ar, tb);
default:
return -EOPNOTSUPP;
}
}
void ath10k_testmode_destroy(struct ath10k *ar)
{
mutex_lock(&ar->conf_mutex);
if (ar->state != ATH10K_STATE_UTF) {
/* utf firmware is not running, nothing to do */
goto out;
}
__ath10k_tm_cmd_utf_stop(ar);
out:
mutex_unlock(&ar->conf_mutex);
}
/*
* Copyright (c) 2014 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "core.h"
#ifdef CONFIG_NL80211_TESTMODE
void ath10k_testmode_destroy(struct ath10k *ar);
bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id, struct sk_buff *skb);
int ath10k_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
void *data, int len);
#else
static inline void ath10k_testmode_destroy(struct ath10k *ar)
{
}
static inline bool ath10k_tm_event_wmi(struct ath10k *ar, u32 cmd_id,
struct sk_buff *skb)
{
return false;
}
static inline int ath10k_tm_cmd(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
void *data, int len)
{
return 0;
}
#endif
/*
* Copyright (c) 2014 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* "API" level of the ath10k testmode interface. Bump it after every
* incompatible interface change.
*/
#define ATH10K_TESTMODE_VERSION_MAJOR 1
/* Bump this after every _compatible_ interface change, for example
* addition of a new command or an attribute.
*/
#define ATH10K_TESTMODE_VERSION_MINOR 0
#define ATH10K_TM_DATA_MAX_LEN 5000
enum ath10k_tm_attr {
__ATH10K_TM_ATTR_INVALID = 0,
ATH10K_TM_ATTR_CMD = 1,
ATH10K_TM_ATTR_DATA = 2,
ATH10K_TM_ATTR_WMI_CMDID = 3,
ATH10K_TM_ATTR_VERSION_MAJOR = 4,
ATH10K_TM_ATTR_VERSION_MINOR = 5,
/* keep last */
__ATH10K_TM_ATTR_AFTER_LAST,
ATH10K_TM_ATTR_MAX = __ATH10K_TM_ATTR_AFTER_LAST - 1,
};
/* All ath10k testmode interface commands specified in
* ATH10K_TM_ATTR_CMD
*/
enum ath10k_tm_cmd {
/* Returns the supported ath10k testmode interface version in
* ATH10K_TM_ATTR_VERSION. Always guaranteed to work. User space
* uses this to verify it's using the correct version of the
* testmode interface
*/
ATH10K_TM_CMD_GET_VERSION = 0,
/* Boots the UTF firmware, the netdev interface must be down at the
* time.
*/
ATH10K_TM_CMD_UTF_START = 1,
/* Shuts down the UTF firmware and puts the driver back into OFF
* state.
*/
ATH10K_TM_CMD_UTF_STOP = 2,
/* The command used to transmit a WMI command to the firmware and
* the event to receive WMI events from the firmware. Without
* struct wmi_cmd_hdr header, only the WMI payload. Command id is
* provided with ATH10K_TM_ATTR_WMI_CMDID and payload in
* ATH10K_TM_ATTR_DATA.
*/
ATH10K_TM_CMD_WMI = 3,
};
......@@ -18,6 +18,7 @@
#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
)
);
......
......@@ -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);
}
......
This diff is collapsed.
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment