diff options
author | David S. Miller <davem@davemloft.net> | 2018-06-03 11:03:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-06-03 11:03:10 -0400 |
commit | f624434a0ec96ac338f10f3f7f5a2ef287dd597e (patch) | |
tree | c6d9643f7887f192460a2e6c34e9f219337a169a /drivers/net/wireless/ath | |
parent | 8051ac7643e8d0f1dd7272042d66c0518e718347 (diff) | |
parent | 76606886c9f433bb46ed9c8910cabce780b23f36 (diff) |
Merge tag 'wireless-drivers-next-for-davem-2018-05-31' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next
Kalle Valo says:
====================
wireless-drivers-next patches for 4.18
Hopefully the last pull request to 4.18 before the merge window.
Nothing major here, we have smaller new features and of course a lots
of fixes.
Major changes:
ath10k
* add memory dump support for QCA9888 and QCA99X0
* add support to configure channel dwell time
* support new DFS host confirmation feature in the firmware
ath
* update various regulatory mappings
wcn36xx
* various fixes to improve reliability
* add Factory Test Mode support
brmfmac
* add debugfs file for reading firmware capabilities
mwifiex
* support sysfs initiated device coredump
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/wireless/ath')
43 files changed, 1604 insertions, 367 deletions
diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 35d10490f6c3..fa39ffffd34d 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -180,14 +180,11 @@ static void ath10k_ahb_clock_disable(struct ath10k *ar) { struct ath10k_ahb *ar_ahb = ath10k_ahb_priv(ar); - if (!IS_ERR_OR_NULL(ar_ahb->cmd_clk)) - clk_disable_unprepare(ar_ahb->cmd_clk); + clk_disable_unprepare(ar_ahb->cmd_clk); - if (!IS_ERR_OR_NULL(ar_ahb->ref_clk)) - clk_disable_unprepare(ar_ahb->ref_clk); + clk_disable_unprepare(ar_ahb->ref_clk); - if (!IS_ERR_OR_NULL(ar_ahb->rtc_clk)) - clk_disable_unprepare(ar_ahb->rtc_clk); + clk_disable_unprepare(ar_ahb->rtc_clk); } static int ath10k_ahb_rst_ctrl_init(struct ath10k *ar) diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index e4ac8f2831fd..951dbdd1c9eb 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -44,6 +44,7 @@ #define WO(_f) ((_f##_OFFSET) >> 2) #define ATH10K_SCAN_ID 0 +#define ATH10K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD 10 /* msec */ #define WMI_READY_TIMEOUT (5 * HZ) #define ATH10K_FLUSH_TIMEOUT_HZ (5 * HZ) #define ATH10K_CONNECTION_LOSS_HZ (3 * HZ) @@ -175,6 +176,7 @@ struct ath10k_wmi { struct completion service_ready; struct completion unified_ready; struct completion barrier; + struct completion radar_confirm; wait_queue_head_t tx_credits_wq; DECLARE_BITMAP(svc_map, WMI_SERVICE_MAX); struct wmi_cmd_map *cmd; @@ -377,6 +379,21 @@ struct ath10k_dfs_stats { u32 radar_detected; }; +enum ath10k_radar_confirmation_state { + ATH10K_RADAR_CONFIRMATION_IDLE = 0, + ATH10K_RADAR_CONFIRMATION_INPROGRESS, + ATH10K_RADAR_CONFIRMATION_STOPPED, +}; + +struct ath10k_radar_found_info { + u32 pri_min; + u32 pri_max; + u32 width_min; + u32 width_max; + u32 sidx_min; + u32 sidx_max; +}; + #define ATH10K_MAX_NUM_PEER_IDS (1 << 11) /* htt rx_desc limit */ struct ath10k_peer { @@ -1109,6 +1126,11 @@ struct ath10k { u32 sta_tid_stats_mask; + /* protected by data_lock */ + enum ath10k_radar_confirmation_state radar_conf_state; + struct ath10k_radar_found_info last_radar_info; + struct work_struct radar_confirmation_work; + /* must be last */ u8 drv_priv[0] __aligned(sizeof(void *)); }; diff --git a/drivers/net/wireless/ath/ath10k/coredump.c b/drivers/net/wireless/ath/ath10k/coredump.c index f90cec0ebb1c..4d28063052fe 100644 --- a/drivers/net/wireless/ath/ath10k/coredump.c +++ b/drivers/net/wireless/ath/ath10k/coredump.c @@ -701,6 +701,89 @@ static const struct ath10k_mem_region qca988x_hw20_mem_regions[] = { }, }; +static const struct ath10k_mem_region qca99x0_hw20_mem_regions[] = { + { + .type = ATH10K_MEM_REGION_TYPE_DRAM, + .start = 0x400000, + .len = 0x60000, + .name = "DRAM", + .section_table = { + .sections = NULL, + .size = 0, + }, + }, + { + .type = ATH10K_MEM_REGION_TYPE_REG, + .start = 0x98000, + .len = 0x50000, + .name = "IRAM", + .section_table = { + .sections = NULL, + .size = 0, + }, + }, + { + .type = ATH10K_MEM_REGION_TYPE_IOSRAM, + .start = 0xC0000, + .len = 0x40000, + .name = "SRAM", + .section_table = { + .sections = NULL, + .size = 0, + }, + }, + { + .type = ATH10K_MEM_REGION_TYPE_IOREG, + .start = 0x30000, + .len = 0x7000, + .name = "APB REG 1", + .section_table = { + .sections = NULL, + .size = 0, + }, + }, + { + .type = ATH10K_MEM_REGION_TYPE_IOREG, + .start = 0x3f000, + .len = 0x3000, + .name = "APB REG 2", + .section_table = { + .sections = NULL, + .size = 0, + }, + }, + { + .type = ATH10K_MEM_REGION_TYPE_IOREG, + .start = 0x43000, + .len = 0x3000, + .name = "WIFI REG", + .section_table = { + .sections = NULL, + .size = 0, + }, + }, + { + .type = ATH10K_MEM_REGION_TYPE_IOREG, + .start = 0x4A000, + .len = 0x5000, + .name = "CE REG", + .section_table = { + .sections = NULL, + .size = 0, + }, + }, + { + .type = ATH10K_MEM_REGION_TYPE_IOREG, + .start = 0x80000, + .len = 0x6000, + .name = "SOC REG", + .section_table = { + .sections = NULL, + .size = 0, + }, + }, +}; + static const struct ath10k_mem_region qca9984_hw10_mem_regions[] = { { .type = ATH10K_MEM_REGION_TYPE_DRAM, @@ -848,6 +931,21 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = { .size = ARRAY_SIZE(qca9984_hw10_mem_regions), }, }, + { + .hw_id = QCA9888_HW_2_0_DEV_VERSION, + .region_table = { + .regions = qca9984_hw10_mem_regions, + .size = ARRAY_SIZE(qca9984_hw10_mem_regions), + }, + }, + { + .hw_id = QCA99X0_HW_2_0_DEV_VERSION, + .region_table = { + .regions = qca99x0_hw20_mem_regions, + .size = ARRAY_SIZE(qca99x0_hw20_mem_regions), + }, + }, + }; static u32 ath10k_coredump_get_ramdump_size(struct ath10k *ar) diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index bac832ce1873..0d98c93a3aba 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -987,13 +987,13 @@ static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file, { struct ath10k *ar = file->private_data; int res; - char buf[64]; + char buf[64] = {0}; unsigned int amsdu, ampdu; - simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); - - /* make sure that buf is null terminated */ - buf[sizeof(buf) - 1] = 0; + res = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, + user_buf, count); + if (res <= 0) + return res; res = sscanf(buf, "%u %u", &amsdu, &du); @@ -1043,14 +1043,14 @@ static ssize_t ath10k_write_fw_dbglog(struct file *file, { struct ath10k *ar = file->private_data; int ret; - char buf[96]; + char buf[96] = {0}; unsigned int log_level; u64 mask; - simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); - - /* make sure that buf is null terminated */ - buf[sizeof(buf) - 1] = 0; + ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, + user_buf, count); + if (ret <= 0) + return ret; ret = sscanf(buf, "%llx %u", &mask, &log_level); @@ -1519,7 +1519,13 @@ static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats, *len += scnprintf(buf + *len, buf_len - *len, "********************************\n"); *len += scnprintf(buf + *len, buf_len - *len, - "No. Preamble Rate_code tpc_value1 tpc_value2 tpc_value3\n"); + "No. Preamble Rate_code "); + + for (i = 0; i < WMI_TPC_TX_N_CHAIN; i++) + *len += scnprintf(buf + *len, buf_len - *len, + "tpc_value%d ", i); + + *len += scnprintf(buf + *len, buf_len - *len, "\n"); for (i = 0; i < tpc_stats->rate_max; i++) { *len += scnprintf(buf + *len, buf_len - *len, diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index 8f688f136c22..a63c97e2c50c 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c @@ -254,12 +254,12 @@ static ssize_t ath10k_dbg_sta_write_addba(struct file *file, struct ath10k *ar = arsta->arvif->ar; u32 tid, buf_size; int ret; - char buf[64]; + char buf[64] = {0}; - simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); - - /* make sure that buf is null terminated */ - buf[sizeof(buf) - 1] = '\0'; + ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, + user_buf, count); + if (ret <= 0) + return ret; ret = sscanf(buf, "%u %u", &tid, &buf_size); if (ret != 2) @@ -305,12 +305,12 @@ static ssize_t ath10k_dbg_sta_write_addba_resp(struct file *file, struct ath10k *ar = arsta->arvif->ar; u32 tid, status; int ret; - char buf[64]; - - simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); + char buf[64] = {0}; - /* make sure that buf is null terminated */ - buf[sizeof(buf) - 1] = '\0'; + ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, + user_buf, count); + if (ret <= 0) + return ret; ret = sscanf(buf, "%u %u", &tid, &status); if (ret != 2) @@ -355,12 +355,12 @@ static ssize_t ath10k_dbg_sta_write_delba(struct file *file, struct ath10k *ar = arsta->arvif->ar; u32 tid, initiator, reason; int ret; - char buf[64]; - - simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count); + char buf[64] = {0}; - /* make sure that buf is null terminated */ - buf[sizeof(buf) - 1] = '\0'; + ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, + user_buf, count); + if (ret <= 0) + return ret; ret = sscanf(buf, "%u %u %u", &tid, &initiator, &reason); if (ret != 3) diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index b8bdabe73073..23467e9fefeb 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -85,11 +85,11 @@ enum qca9377_chip_id_rev { QCA9377_HW_1_1_CHIP_ID_REV = 0x1, }; -#define QCA6174_HW_2_1_FW_DIR "ath10k/QCA6174/hw2.1" +#define QCA6174_HW_2_1_FW_DIR ATH10K_FW_DIR "/QCA6174/hw2.1" #define QCA6174_HW_2_1_BOARD_DATA_FILE "board.bin" #define QCA6174_HW_2_1_PATCH_LOAD_ADDR 0x1234 -#define QCA6174_HW_3_0_FW_DIR "ath10k/QCA6174/hw3.0" +#define QCA6174_HW_3_0_FW_DIR ATH10K_FW_DIR "/QCA6174/hw3.0" #define QCA6174_HW_3_0_BOARD_DATA_FILE "board.bin" #define QCA6174_HW_3_0_PATCH_LOAD_ADDR 0x1234 diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 3d7119ad7c7a..e9c2fb318c03 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -3217,6 +3217,15 @@ static void ath10k_reg_notifier(struct wiphy *wiphy, ar->hw->wiphy->bands[NL80211_BAND_5GHZ]); } +static void ath10k_stop_radar_confirmation(struct ath10k *ar) +{ + spin_lock_bh(&ar->data_lock); + ar->radar_conf_state = ATH10K_RADAR_CONFIRMATION_STOPPED; + spin_unlock_bh(&ar->data_lock); + + cancel_work_sync(&ar->radar_confirmation_work); +} + /***************/ /* TX handlers */ /***************/ @@ -4290,7 +4299,7 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw, while (ath10k_mac_tx_can_push(hw, f_txq) && max--) { ret = ath10k_mac_tx_push_txq(hw, f_txq); - if (ret) + if (ret < 0) break; } if (ret != -ENOENT) @@ -4333,6 +4342,7 @@ void ath10k_halt(struct ath10k *ar) ath10k_scan_finish(ar); ath10k_peer_cleanup_all(ar); + ath10k_stop_radar_confirmation(ar); ath10k_core_stop(ar); ath10k_hif_power_down(ar); @@ -4758,6 +4768,8 @@ static int ath10k_start(struct ieee80211_hw *hw) ath10k_spectral_start(ar); ath10k_thermal_set_throttling(ar); + ar->radar_conf_state = ATH10K_RADAR_CONFIRMATION_IDLE; + mutex_unlock(&ar->conf_mutex); return 0; @@ -5675,6 +5687,7 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw, struct wmi_start_scan_arg arg; int ret = 0; int i; + u32 scan_timeout; mutex_lock(&ar->conf_mutex); @@ -5736,6 +5749,22 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw, arg.channels[i] = req->channels[i]->center_freq; } + /* if duration is set, default dwell times will be overwritten */ + if (req->duration) { + arg.dwell_time_active = req->duration; + arg.dwell_time_passive = req->duration; + arg.burst_duration_ms = req->duration; + + scan_timeout = min_t(u32, arg.max_rest_time * + (arg.n_channels - 1) + (req->duration + + ATH10K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) * + arg.n_channels, arg.max_scan_time + 200); + + } else { + /* Add a 200ms margin to account for event/command processing */ + scan_timeout = arg.max_scan_time + 200; + } + ret = ath10k_start_scan(ar, &arg); if (ret) { ath10k_warn(ar, "failed to start hw scan: %d\n", ret); @@ -5744,10 +5773,8 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw, spin_unlock_bh(&ar->data_lock); } - /* Add a 200ms margin to account for event/command processing */ ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout, - msecs_to_jiffies(arg.max_scan_time + - 200)); + msecs_to_jiffies(scan_timeout)); exit: mutex_unlock(&ar->conf_mutex); @@ -8364,6 +8391,8 @@ int ath10k_mac_register(struct ath10k *ar) } wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS); + wiphy_ext_feature_set(ar->hw->wiphy, + NL80211_EXT_FEATURE_SET_SCAN_DWELL); /* * on LL hardware queues are managed entirely by the FW diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h index 545deb6d7af1..ea4075d456fa 100644 --- a/drivers/net/wireless/ath/ath10k/rx_desc.h +++ b/drivers/net/wireless/ath/ath10k/rx_desc.h @@ -18,39 +18,41 @@ #ifndef _RX_DESC_H_ #define _RX_DESC_H_ +#include <linux/bitops.h> + enum rx_attention_flags { - RX_ATTENTION_FLAGS_FIRST_MPDU = 1 << 0, - RX_ATTENTION_FLAGS_LAST_MPDU = 1 << 1, - RX_ATTENTION_FLAGS_MCAST_BCAST = 1 << 2, - RX_ATTENTION_FLAGS_PEER_IDX_INVALID = 1 << 3, - RX_ATTENTION_FLAGS_PEER_IDX_TIMEOUT = 1 << 4, - RX_ATTENTION_FLAGS_POWER_MGMT = 1 << 5, - RX_ATTENTION_FLAGS_NON_QOS = 1 << 6, - RX_ATTENTION_FLAGS_NULL_DATA = 1 << 7, - RX_ATTENTION_FLAGS_MGMT_TYPE = 1 << 8, - RX_ATTENTION_FLAGS_CTRL_TYPE = 1 << 9, - RX_ATTENTION_FLAGS_MORE_DATA = 1 << 10, - RX_ATTENTION_FLAGS_EOSP = 1 << 11, - RX_ATTENTION_FLAGS_U_APSD_TRIGGER = 1 << 12, - RX_ATTENTION_FLAGS_FRAGMENT = 1 << 13, - RX_ATTENTION_FLAGS_ORDER = 1 << 14, - RX_ATTENTION_FLAGS_CLASSIFICATION = 1 << 15, - RX_ATTENTION_FLAGS_OVERFLOW_ERR = 1 << 16, - RX_ATTENTION_FLAGS_MSDU_LENGTH_ERR = 1 << 17, - RX_ATTENTION_FLAGS_TCP_UDP_CHKSUM_FAIL = 1 << 18, - RX_ATTENTION_FLAGS_IP_CHKSUM_FAIL = 1 << 19, - RX_ATTENTION_FLAGS_SA_IDX_INVALID = 1 << 20, - RX_ATTENTION_FLAGS_DA_IDX_INVALID = 1 << 21, - RX_ATTENTION_FLAGS_SA_IDX_TIMEOUT = 1 << 22, - RX_ATTENTION_FLAGS_DA_IDX_TIMEOUT = 1 << 23, - RX_ATTENTION_FLAGS_ENCRYPT_REQUIRED = 1 << 24, - RX_ATTENTION_FLAGS_DIRECTED = 1 << 25, - RX_ATTENTION_FLAGS_BUFFER_FRAGMENT = 1 << 26, - RX_ATTENTION_FLAGS_MPDU_LENGTH_ERR = 1 << 27, - RX_ATTENTION_FLAGS_TKIP_MIC_ERR = 1 << 28, - RX_ATTENTION_FLAGS_DECRYPT_ERR = 1 << 29, - RX_ATTENTION_FLAGS_FCS_ERR = 1 << 30, - RX_ATTENTION_FLAGS_MSDU_DONE = 1 << 31, + RX_ATTENTION_FLAGS_FIRST_MPDU = BIT(0), + RX_ATTENTION_FLAGS_LAST_MPDU = BIT(1), + RX_ATTENTION_FLAGS_MCAST_BCAST = BIT(2), + RX_ATTENTION_FLAGS_PEER_IDX_INVALID = BIT(3), + RX_ATTENTION_FLAGS_PEER_IDX_TIMEOUT = BIT(4), + RX_ATTENTION_FLAGS_POWER_MGMT = BIT(5), + RX_ATTENTION_FLAGS_NON_QOS = BIT(6), + RX_ATTENTION_FLAGS_NULL_DATA = BIT(7), + RX_ATTENTION_FLAGS_MGMT_TYPE = BIT(8), + RX_ATTENTION_FLAGS_CTRL_TYPE = BIT(9), + RX_ATTENTION_FLAGS_MORE_DATA = BIT(10), + RX_ATTENTION_FLAGS_EOSP = BIT(11), + RX_ATTENTION_FLAGS_U_APSD_TRIGGER = BIT(12), + RX_ATTENTION_FLAGS_FRAGMENT = BIT(13), + RX_ATTENTION_FLAGS_ORDER = BIT(14), + RX_ATTENTION_FLAGS_CLASSIFICATION = BIT(15), + RX_ATTENTION_FLAGS_OVERFLOW_ERR = BIT(16), + RX_ATTENTION_FLAGS_MSDU_LENGTH_ERR = BIT(17), + RX_ATTENTION_FLAGS_TCP_UDP_CHKSUM_FAIL = BIT(18), + RX_ATTENTION_FLAGS_IP_CHKSUM_FAIL = BIT(19), + RX_ATTENTION_FLAGS_SA_IDX_INVALID = BIT(20), + RX_ATTENTION_FLAGS_DA_IDX_INVALID = BIT(21), + RX_ATTENTION_FLAGS_SA_IDX_TIMEOUT = BIT(22), + RX_ATTENTION_FLAGS_DA_IDX_TIMEOUT = BIT(23), + RX_ATTENTION_FLAGS_ENCRYPT_REQUIRED = BIT(24), + RX_ATTENTION_FLAGS_DIRECTED = BIT(25), + RX_ATTENTION_FLAGS_BUFFER_FRAGMENT = BIT(26), + RX_ATTENTION_FLAGS_MPDU_LENGTH_ERR = BIT(27), + RX_ATTENTION_FLAGS_TKIP_MIC_ERR = BIT(28), + RX_ATTENTION_FLAGS_DECRYPT_ERR = BIT(29), + RX_ATTENTION_FLAGS_FCS_ERR = BIT(30), + RX_ATTENTION_FLAGS_MSDU_DONE = BIT(31), }; struct rx_attention { @@ -254,15 +256,15 @@ enum htt_rx_mpdu_encrypt_type { #define RX_MPDU_START_INFO0_SEQ_NUM_LSB 16 #define RX_MPDU_START_INFO0_ENCRYPT_TYPE_MASK 0xf0000000 #define RX_MPDU_START_INFO0_ENCRYPT_TYPE_LSB 28 -#define RX_MPDU_START_INFO0_FROM_DS (1 << 11) -#define RX_MPDU_START_INFO0_TO_DS (1 << 12) -#define RX_MPDU_START_INFO0_ENCRYPTED (1 << 13) -#define RX_MPDU_START_INFO0_RETRY (1 << 14) -#define RX_MPDU_START_INFO0_TXBF_H_INFO (1 << 15) +#define RX_MPDU_START_INFO0_FROM_DS BIT(11) +#define RX_MPDU_START_INFO0_TO_DS BIT(12) +#define RX_MPDU_START_INFO0_ENCRYPTED BIT(13) +#define RX_MPDU_START_INFO0_RETRY BIT(14) +#define RX_MPDU_START_INFO0_TXBF_H_INFO BIT(15) #define RX_MPDU_START_INFO1_TID_MASK 0xf0000000 #define RX_MPDU_START_INFO1_TID_LSB 28 -#define RX_MPDU_START_INFO1_DIRECTED (1 << 16) +#define RX_MPDU_START_INFO1_DIRECTED BIT(16) struct rx_mpdu_start { __le32 info0; @@ -357,13 +359,13 @@ struct rx_mpdu_start { #define RX_MPDU_END_INFO0_RESERVED_0_LSB 0 #define RX_MPDU_END_INFO0_POST_DELIM_CNT_MASK 0x0fff0000 #define RX_MPDU_END_INFO0_POST_DELIM_CNT_LSB 16 -#define RX_MPDU_END_INFO0_OVERFLOW_ERR (1 << 13) -#define RX_MPDU_END_INFO0_LAST_MPDU (1 << 14) -#define RX_MPDU_END_INFO0_POST_DELIM_ERR (1 << 15) -#define RX_MPDU_END_INFO0_MPDU_LENGTH_ERR (1 << 28) -#define RX_MPDU_END_INFO0_TKIP_MIC_ERR (1 << 29) -#define RX_MPDU_END_INFO0_DECRYPT_ERR (1 << 30) -#define RX_MPDU_END_INFO0_FCS_ERR (1 << 31) +#define RX_MPDU_END_INFO0_OVERFLOW_ERR BIT(13) +#define RX_MPDU_END_INFO0_LAST_MPDU BIT(14) +#define RX_MPDU_END_INFO0_POST_DELIM_ERR BIT(15) +#define RX_MPDU_END_INFO0_MPDU_LENGTH_ERR BIT(28) +#define RX_MPDU_END_INFO0_TKIP_MIC_ERR BIT(29) +#define RX_MPDU_END_INFO0_DECRYPT_ERR BIT(30) +#define RX_MPDU_END_INFO0_FCS_ERR BIT(31) struct rx_mpdu_end { __le32 info0; @@ -422,12 +424,12 @@ struct rx_mpdu_end { #define RX_MSDU_START_INFO1_DECAP_FORMAT_LSB 8 #define RX_MSDU_START_INFO1_SA_IDX_MASK 0x07ff0000 #define RX_MSDU_START_INFO1_SA_IDX_LSB 16 -#define RX_MSDU_START_INFO1_IPV4_PROTO (1 << 10) -#define RX_MSDU_START_INFO1_IPV6_PROTO (1 << 11) -#define RX_MSDU_START_INFO1_TCP_PROTO (1 << 12) -#define RX_MSDU_START_INFO1_UDP_PROTO (1 << 13) -#define RX_MSDU_START_INFO1_IP_FRAG (1 << 14) -#define RX_MSDU_START_INFO1_TCP_ONLY_ACK (1 << 15) +#define RX_MSDU_START_INFO1_IPV4_PROTO BIT(10) +#define RX_MSDU_START_INFO1_IPV6_PROTO BIT(11) +#define RX_MSDU_START_INFO1_TCP_PROTO BIT(12) +#define RX_MSDU_START_INFO1_UDP_PROTO BIT(13) +#define RX_MSDU_START_INFO1_IP_FRAG BIT(14) +#define RX_MSDU_START_INFO1_TCP_ONLY_ACK BIT(15) #define RX_MSDU_START_INFO2_DA_IDX_MASK 0x000007ff #define RX_MSDU_START_INFO2_DA_IDX_LSB 0 @@ -568,10 +570,10 @@ struct rx_msdu_start { #define RX_MSDU_END_INFO0_REPORTED_MPDU_LENGTH_MASK 0x00003fff #define RX_MSDU_END_INFO0_REPORTED_MPDU_LENGTH_LSB 0 -#define RX_MSDU_END_INFO0_FIRST_MSDU (1 << 14) -#define RX_MSDU_END_INFO0_LAST_MSDU (1 << 15) -#define RX_MSDU_END_INFO0_PRE_DELIM_ERR (1 << 30) -#define RX_MSDU_END_INFO0_RESERVED_3B (1 << 31) +#define RX_MSDU_END_INFO0_FIRST_MSDU BIT(14) +#define RX_MSDU_END_INFO0_LAST_MSDU BIT(15) +#define RX_MSDU_END_INFO0_PRE_DELIM_ERR BIT(30) +#define RX_MSDU_END_INFO0_RESERVED_3B BIT(31) struct rx_msdu_end_common { __le16 ip_hdr_cksum; @@ -691,7 +693,7 @@ struct rx_msdu_end { #define HTT_RX_PPDU_START_PREAMBLE_VHT 0x0C #define HTT_RX_PPDU_START_PREAMBLE_VHT_WITH_TXBF 0x0D -#define RX_PPDU_START_INFO0_IS_GREENFIELD (1 << 0) +#define RX_PPDU_START_INFO0_IS_GREENFIELD BIT(0) #define RX_PPDU_START_INFO1_L_SIG_RATE_MASK 0x0000000f #define RX_PPDU_START_INFO1_L_SIG_RATE_LSB 0 @@ -701,15 +703,15 @@ struct rx_msdu_end { #define RX_PPDU_START_INFO1_L_SIG_TAIL_LSB 18 #define RX_PPDU_START_INFO1_PREAMBLE_TYPE_MASK 0xff000000 #define RX_PPDU_START_INFO1_PREAMBLE_TYPE_LSB 24 -#define RX_PPDU_START_INFO1_L_SIG_RATE_SELECT (1 << 4) -#define RX_PPDU_START_INFO1_L_SIG_PARITY (1 << 17) +#define RX_PPDU_START_INFO1_L_SIG_RATE_SELECT BIT(4) +#define RX_PPDU_START_INFO1_L_SIG_PARITY BIT(17) #define RX_PPDU_START_INFO2_HT_SIG_VHT_SIG_A_1_MASK 0x00ffffff #define RX_PPDU_START_INFO2_HT_SIG_VHT_SIG_A_1_LSB 0 #define RX_PPDU_START_INFO3_HT_SIG_VHT_SIG_A_2_MASK 0x00ffffff #define RX_PPDU_START_INFO3_HT_SIG_VHT_SIG_A_2_LSB 0 -#define RX_PPDU_START_INFO3_TXBF_H_INFO (1 << 24) +#define RX_PPDU_START_INFO3_TXBF_H_INFO BIT(24) #define RX_PPDU_START_INFO4_VHT_SIG_B_MASK 0x1fffffff #define RX_PPDU_START_INFO4_VHT_SIG_B_LSB 0 @@ -898,14 +900,14 @@ 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) +#define RX_PPDU_END_FLAGS_PHY_ERR BIT(0) +#define RX_PPDU_END_FLAGS_RX_LOCATION BIT(1) +#define RX_PPDU_END_FLAGS_TXBF_H_INFO BIT(2) #define RX_PPDU_END_INFO0_RX_ANTENNA_MASK 0x00ffffff #define RX_PPDU_END_INFO0_RX_ANTENNA_LSB 0 -#define RX_PPDU_END_INFO0_FLAGS_TX_HT_VHT_ACK (1 << 24) -#define RX_PPDU_END_INFO0_BB_CAPTURED_CHANNEL (1 << 25) +#define RX_PPDU_END_INFO0_FLAGS_TX_HT_VHT_ACK BIT(24) +#define RX_PPDU_END_INFO0_BB_CAPTURED_CHANNEL BIT(25) #define RX_PPDU_END_INFO1_PEER_IDX_MASK 0x1ffc #define RX_PPDU_END_INFO1_PEER_IDX_LSB 2 @@ -1265,9 +1267,9 @@ struct rx_ppdu_end { * to 0. */ -#define FW_RX_DESC_INFO0_DISCARD (1 << 0) -#define FW_RX_DESC_INFO0_FORWARD (1 << 1) -#define FW_RX_DESC_INFO0_INSPECT (1 << 5) +#define FW_RX_DESC_INFO0_DISCARD BIT(0) +#define FW_RX_DESC_INFO0_FORWARD BIT(1) +#define FW_RX_DESC_INFO0_INSPECT BIT(5) #define FW_RX_DESC_INFO0_EXT_MASK 0xC0 #define FW_RX_DESC_INFO0_EXT_LSB 6 diff --git a/drivers/net/wireless/ath/ath10k/sdio.c b/drivers/net/wireless/ath/ath10k/sdio.c index 2d04c54a4153..d612ce8c9cff 100644 --- a/drivers/net/wireless/ath/ath10k/sdio.c +++ b/drivers/net/wireless/ath/ath10k/sdio.c @@ -2011,7 +2011,7 @@ static int ath10k_sdio_probe(struct sdio_func *func, ret = -ENODEV; ath10k_err(ar, "unsupported device id %u (0x%x)\n", dev_id_base, id->device); - goto err_core_destroy; + goto err_free_wq; } ar->id.vendor = id->vendor; diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index 47a4d2a5bd4c..a3a7042fe13a 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -1385,7 +1385,6 @@ static struct platform_driver ath10k_snoc_driver = { .remove = ath10k_snoc_remove, .driver = { .name = "ath10k_snoc", - .owner = THIS_MODULE, .of_match_table = ath10k_snoc_dt_match, }, }; diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h index e37d16b31afe..5ecce04005d2 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-ops.h +++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h @@ -55,6 +55,8 @@ struct wmi_ops { struct wmi_wow_ev_arg *arg); int (*pull_echo_ev)(struct ath10k *ar, struct sk_buff *skb, struct wmi_echo_ev_arg *arg); + int (*pull_dfs_status_ev)(struct ath10k *ar, struct sk_buff *skb, + struct wmi_dfs_status_ev_arg *arg); int (*pull_svc_avail)(struct ath10k *ar, struct sk_buff *skb, struct wmi_svc_avail_ev_arg *arg); @@ -188,6 +190,9 @@ struct wmi_ops { const struct wmi_tdls_peer_update_cmd_arg *arg, const struct wmi_tdls_peer_capab_arg *cap, const struct wmi_channel_arg *chan); + struct sk_buff *(*gen_radar_found) + (struct ath10k *ar, + const struct ath10k_radar_found_info *arg); struct sk_buff *(*gen_adaptive_qcs)(struct ath10k *ar, bool enable); struct sk_buff *(*gen_pdev_get_tpc_config)(struct ath10k *ar, u32 param); @@ -395,6 +400,16 @@ ath10k_wmi_pull_echo_ev(struct ath10k *ar, struct sk_buff *skb, return ar->wmi.ops->pull_echo_ev(ar, skb, arg); } +static inline int +ath10k_wmi_pull_dfs_status(struct ath10k *ar, struct sk_buff *skb, + struct wmi_dfs_status_ev_arg *arg) +{ + if (!ar->wmi.ops->pull_dfs_status_ev) + return -EOPNOTSUPP; + + return ar->wmi.ops->pull_dfs_status_ev(ar, skb, arg); +} + static inline enum wmi_txbf_conf ath10k_wmi_get_txbf_conf_scheme(struct ath10k *ar) { @@ -1511,4 +1526,21 @@ ath10k_wmi_pdev_get_tpc_table_cmdid(struct ath10k *ar, u32 param) ar->wmi.cmd->pdev_get_tpc_table_cmdid); } +static inline int +ath10k_wmi_report_radar_found(struct ath10k *ar, + const struct ath10k_radar_found_info *arg) +{ + struct sk_buff *skb; + + if (!ar->wmi.ops->gen_radar_found) + return -EOPNOTSUPP; + + skb = ar->wmi.ops->gen_radar_found(ar, arg); + if (IS_ERR(skb)) + return PTR_ERR(skb); + + return ath10k_wmi_cmd_send(ar, skb, + ar->wmi.cmd->radar_found_cmdid); +} + #endif diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 01f4eb201330..2e34a1fc5ba6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -3136,6 +3136,37 @@ ath10k_wmi_tlv_op_gen_tdls_peer_update(struct ath10k *ar, } static struct sk_buff * +ath10k_wmi_tlv_op_gen_pdev_set_quiet_mode(struct ath10k *ar, u32 period, + u32 duration, u32 next_offset, + u32 enabled) +{ + struct wmi_tlv_set_quiet_cmd *cmd; + struct wmi_tlv *tlv; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(ar, sizeof(*tlv) + sizeof(*cmd)); + if (!skb) + return ERR_PTR(-ENOMEM); + + tlv = (void *)skb->data; + tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_PDEV_SET_QUIET_CMD); + tlv->len = __cpu_to_le16(sizeof(*cmd)); + cmd = (void *)tlv->value; + + /* vdev_id is not in use, set to 0 */ + cmd->vdev_id = __cpu_to_le32(0); + cmd->period = __cpu_to_le32(period); + cmd->duration = __cpu_to_le32(duration); + cmd->next_start = __cpu_to_le32(next_offset); + cmd->enabled = __cpu_to_le32(enabled); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi tlv quiet param: period %u duration %u enabled %d\n", + period, duration, enabled); + return skb; +} + +static struct sk_buff * ath10k_wmi_tlv_op_gen_wow_enable(struct ath10k *ar) { struct wmi_tlv_wow_enable_cmd *cmd; @@ -3854,7 +3885,7 @@ static const struct wmi_ops wmi_tlv_ops = { .gen_dbglog_cfg = ath10k_wmi_tlv_op_gen_dbglog_cfg, .gen_pktlog_enable = ath10k_wmi_tlv_op_gen_pktlog_enable, .gen_pktlog_disable = ath10k_wmi_tlv_op_gen_pktlog_disable, - /* .gen_pdev_set_quiet_mode not implemented */ + .gen_pdev_set_quiet_mode = ath10k_wmi_tlv_op_gen_pdev_set_quiet_mode, .gen_pdev_get_temperature = ath10k_wmi_tlv_op_gen_pdev_get_temperature, /* .gen_addba_clear_resp not implemented */ /* .gen_addba_send not implemented */ diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index 954c50bb3f66..3e1e340cd834 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -1,6 +1,7 @@ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. + * Copyright (c) 2018, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -1952,6 +1953,21 @@ struct wmi_tlv_wow_add_del_event_cmd { __le32 event_bitmap; } __packed; +/* Command to set/unset chip in quiet mode */ +struct wmi_tlv_set_quiet_cmd { + __le32 vdev_id; + + /* in TUs */ + __le32 period; + + /* in TUs */ + __le32 duration; + + /* offset in TUs */ + __le32 next_start; + __le32 enabled; +} __packed; + struct wmi_tlv_wow_enable_cmd { __le32 enable; } __packed; diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index df2e92a6c9bd..f97ab795cf2e 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -34,6 +34,7 @@ #define ATH10K_WMI_BARRIER_ECHO_ID 0xBA991E9 #define ATH10K_WMI_BARRIER_TIMEOUT_HZ (3 * HZ) +#define ATH10K_WMI_DFS_CONF_TIMEOUT_HZ (HZ / 6) /* MAIN WMI cmd track */ static struct wmi_cmd_map wmi_cmd_map = { @@ -199,6 +200,7 @@ static struct wmi_cmd_map wmi_cmd_map = { .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED, .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED, .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED, + .radar_found_cmdid = WMI_CMD_UNSUPPORTED, }; /* 10.X WMI cmd track */ @@ -367,6 +369,7 @@ static struct wmi_cmd_map wmi_10x_cmd_map = { .set_cca_params_cmdid = WMI_CMD_UNSUPPORTED, .pdev_bss_chan_info_request_cmdid = WMI_CMD_UNSUPPORTED, .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED, + .radar_found_cmdid = WMI_CMD_UNSUPPORTED, }; /* 10.2.4 WMI cmd track */ @@ -535,6 +538,7 @@ static struct wmi_cmd_map wmi_10_2_4_cmd_map = { .pdev_bss_chan_info_request_cmdid = WMI_10_2_PDEV_BSS_CHAN_INFO_REQUEST_CMDID, .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED, + .radar_found_cmdid = WMI_CMD_UNSUPPORTED, }; /* 10.4 WMI cmd track */ @@ -745,6 +749,7 @@ static struct wmi_cmd_map wmi_10_4_cmd_map = { .tdls_set_state_cmdid = WMI_10_4_TDLS_SET_STATE_CMDID, .tdls_peer_update_cmdid = WMI_10_4_TDLS_PEER_UPDATE_CMDID, .tdls_set_offchan_mode_cmdid = WMI_10_4_TDLS_SET_OFFCHAN_MODE_CMDID, + .radar_found_cmdid = WMI_10_4_RADAR_FOUND_CMDID, }; /* MAIN WMI VDEV param map */ @@ -1490,6 +1495,7 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = { .pdev_get_ani_ofdm_config_cmdid = WMI_CMD_UNSUPPORTED, .pdev_reserve_ast_entry_cmdid = WMI_CMD_UNSUPPORTED, .pdev_get_tpc_table_cmdid = WMI_CMD_UNSUPPORTED, + .radar_found_cmdid = WMI_CMD_UNSUPPORTED, }; static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = { @@ -2318,7 +2324,6 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) u32 phy_mode; u32 snr; u32 rate; - u32 buf_len; u16 fc; int ret; @@ -2330,7 +2335,6 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) } channel = __le32_to_cpu(arg.channel); - buf_len = __le32_to_cpu(arg.buf_len); rx_status = __le32_to_cpu(arg.status); snr = __le32_to_cpu(arg.snr); phy_mode = __le32_to_cpu(arg.phy_mode); @@ -2740,14 +2744,13 @@ static int ath10k_wmi_main_op_pull_fw_stats(struct ath10k *ar, struct ath10k_fw_stats *stats) { const struct wmi_stats_event *ev = (void *)skb->data; - u32 num_pdev_stats, num_vdev_stats, num_peer_stats; + u32 num_pdev_stats, num_peer_stats; int i; if (!skb_pull(skb, sizeof(*ev))) return -EPROTO; num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); - num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); num_peer_stats = __le32_to_cpu(ev->num_peer_stats); for (i = 0; i < num_pdev_stats; i++) { @@ -2795,14 +2798,13 @@ static int ath10k_wmi_10x_op_pull_fw_stats(struct ath10k *ar, struct ath10k_fw_stats *stats) { const struct wmi_stats_event *ev = (void *)skb->data; - u32 num_pdev_stats, num_vdev_stats, num_peer_stats; + u32 num_pdev_stats, num_peer_stats; int i; if (!skb_pull(skb, sizeof(*ev))) return -EPROTO; num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); - num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); num_peer_stats = __le32_to_cpu(ev->num_peer_stats); for (i = 0; i < num_pdev_stats; i++) { @@ -2856,7 +2858,6 @@ static int ath10k_wmi_10_2_op_pull_fw_stats(struct ath10k *ar, const struct wmi_10_2_stats_event *ev = (void *)skb->data; u32 num_pdev_stats; u32 num_pdev_ext_stats; - u32 num_vdev_stats; u32 num_peer_stats; int i; @@ -2865,7 +2866,6 @@ static int ath10k_wmi_10_2_op_pull_fw_stats(struct ath10k *ar, num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats); - num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); num_peer_stats = __le32_to_cpu(ev->num_peer_stats); for (i = 0; i < num_pdev_stats; i++) { @@ -2935,7 +2935,6 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, const struct wmi_10_2_stats_event *ev = (void *)skb->data; u32 num_pdev_stats; u32 num_pdev_ext_stats; - u32 num_vdev_stats; u32 num_peer_stats; int i; @@ -2944,7 +2943,6 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats); - num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); num_peer_stats = __le32_to_cpu(ev->num_peer_stats); for (i = 0; i < num_pdev_stats; i++) { @@ -3691,6 +3689,68 @@ void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, struct sk_buff *skb) ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_TBTTOFFSET_UPDATE_EVENTID\n"); } +static void ath10k_radar_detected(struct ath10k *ar) +{ + ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs radar detected\n"); + ATH10K_DFS_STAT_INC(ar, radar_detected); + + /* Control radar events reporting in debugfs file + * dfs_block_radar_events + */ + if (ar->dfs_block_radar_events) + ath10k_info(ar, "DFS Radar detected, but ignored as requested\n"); + else + ieee80211_radar_detected(ar->hw); +} + +static void ath10k_radar_confirmation_work(struct work_struct *work) +{ + struct ath10k *ar = container_of(work, struct ath10k, + radar_confirmation_work); + struct ath10k_radar_found_info radar_info; + int ret, time_left; + + reinit_completion(&ar->wmi.radar_confirm); + + spin_lock_bh(&ar->data_lock); + memcpy(&radar_info, &ar->last_radar_info, sizeof(radar_info)); + spin_unlock_bh(&ar->data_lock); + + ret = ath10k_wmi_report_radar_found(ar, &radar_info); + if (ret) { + ath10k_warn(ar, "failed to send radar found %d\n", ret); + goto wait_complete; + } + + time_left = wait_for_completion_timeout(&ar->wmi.radar_confirm, + ATH10K_WMI_DFS_CONF_TIMEOUT_HZ); + if (time_left) { + /* DFS Confirmation status event received and + * necessary action completed. + */ + goto wait_complete; + } else { + /* DFS Confirmation event not received from FW.Considering this + * as real radar. + */ + ath10k_dbg(ar, ATH10K_DBG_REGULATORY, + "dfs confirmation not received from fw, considering as radar\n"); + goto radar_detected; + } + +radar_detected: + ath10k_radar_detected(ar); + + /* Reset state to allow sending confirmation on consecutive radar + * detections, unless radar confirmation is disabled/stopped. + */ +wait_complete: + spin_lock_bh(&ar->data_lock); + if (ar->radar_conf_state != ATH10K_RADAR_CONFIRMATION_STOPPED) + ar->radar_conf_state = ATH10K_RADAR_CONFIRMATION_IDLE; + spin_unlock_bh(&ar->data_lock); +} + static void ath10k_dfs_radar_report(struct ath10k *ar, struct wmi_phyerr_ev_arg *phyerr, const struct phyerr_radar_report *rr, @@ -3699,8 +3759,10 @@ static void ath10k_dfs_radar_report(struct ath10k *ar, u32 reg0, reg1, tsf32l; struct ieee80211_channel *ch; struct pulse_event pe; + struct radar_detector_specs rs; u64 tsf64; u8 rssi, width; + struct ath10k_radar_found_info *radar_info; reg0 = __le32_to_cpu(rr->reg0); reg1 = __le32_to_cpu(rr->reg1); @@ -3765,25 +3827,46 @@ static void ath10k_dfs_radar_report(struct ath10k *ar, ATH10K_DFS_STAT_INC(ar, pulses_detected); - if (!ar->dfs_detector->add_pulse(ar->dfs_detector, &pe)) { + if (!ar->dfs_detector->add_pulse(ar->dfs_detector, &pe, &rs)) { ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs no pulse pattern detected, yet\n"); return; } -radar_detected: - ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs radar detected\n"); - ATH10K_DFS_STAT_INC(ar, radar_detected); + if ((test_bit(WMI_SERVICE_HOST_DFS_CHECK_SUPPORT, ar->wmi.svc_map)) && + ar->dfs_detector->region == NL80211_DFS_FCC) { + /* Consecutive radar indications need not be + * sent to the firmware until we get confirmation + * for the previous detected radar. + */ + spin_lock_bh(&ar->data_lock); + if (ar->radar_conf_state != ATH10K_RADAR_CONFIRMATION_IDLE) { + spin_unlock_bh(&ar->data_lock); + return; + } + ar->radar_conf_state = ATH10K_RADAR_CONFIRMATION_INPROGRESS; + radar_info = &ar->last_radar_info; - /* Control radar events reporting in debugfs file - * dfs_block_radar_events - */ - if (ar->dfs_block_radar_events) { - ath10k_info(ar, "DFS Radar detected, but ignored as requested\n"); + radar_info->pri_min = rs.pri_min; + radar_info->pri_max = rs.pri_max; + radar_info->width_min = rs.width_min; + radar_info->width_max = rs.width_max; + /*TODO Find sidx_min and sidx_max */ + radar_info->sidx_min = MS(reg0, RADAR_REPORT_REG0_PULSE_SIDX); + radar_info->sidx_max = MS(reg0, RADAR_REPORT_REG0_PULSE_SIDX); + + ath10k_dbg(ar, ATH10K_DBG_REGULATORY, + "sending wmi radar found cmd pri_min %d pri_max %d width_min %d width_max %d sidx_min %d sidx_max %d\n", + radar_info->pri_min, radar_info->pri_max, + radar_info->width_min, radar_info->width_max, + radar_info->sidx_min, radar_info->sidx_max); + ieee80211_queue_work(ar->hw, &ar->radar_confirmation_work); + spin_unlock_bh(&ar->data_lock); return; } - ieee80211_radar_detected(ar->hw); +radar_detected: + ath10k_radar_detected(ar); } static int ath10k_dfs_fft_report(struct ath10k *ar, @@ -4133,6 +4216,47 @@ void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) } } +static int +ath10k_wmi_10_4_op_pull_dfs_status_ev(struct ath10k *ar, struct sk_buff *skb, + struct wmi_dfs_status_ev_arg *arg) +{ + struct wmi_dfs_status_ev_arg *ev = (void *)skb->data; + + if (skb->len < sizeof(*ev)) + return -EPROTO; + + arg->status = ev->status; + + return 0; +} + +static void +ath10k_wmi_event_dfs_status_check(struct ath10k *ar, struct sk_buff *skb) +{ + struct wmi_dfs_status_ev_arg status_arg = {}; + int ret; + + ret = ath10k_wmi_pull_dfs_status(ar, skb, &status_arg); + + if (ret) { + ath10k_warn(ar, "failed to parse dfs status event: %d\n", ret); + return; + } + + ath10k_dbg(ar, ATH10K_DBG_REGULATORY, + "dfs status event received from fw: %d\n", + status_arg.status); + + /* Even in case of radar detection failure we follow the same + * behaviour as if radar is detected i.e to switch to a different + * channel. + */ + if (status_arg.status == WMI_HW_RADAR_DETECTED || + status_arg.status == WMI_RADAR_DETECTION_FAIL) + ath10k_radar_detected(ar); + complete(&ar->wmi.radar_confirm); +} + void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb) { struct wmi_roam_ev_arg arg = {}; @@ -4484,6 +4608,12 @@ void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) num_tx_chain = __le32_to_cpu(ev->num_tx_chain); + if (num_tx_chain > WMI_TPC_TX_N_CHAIN) { + ath10k_warn(ar, "number of tx chain is %d greater than TPC configured tx chain %d\n", + num_tx_chain, WMI_TPC_TX_N_CHAIN); + return; + } + ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table, num_tx_chain); @@ -5280,7 +5410,7 @@ void ath10k_wmi_event_service_available(struct ath10k *ar, struct sk_buff *skb) ret = ath10k_wmi_pull_svc_avail(ar, skb, &arg); if (ret) { - ath10k_warn(ar, "failed to parse servive available event: %d\n", + ath10k_warn(ar, "failed to parse service available event: %d\n", ret); } @@ -5878,6 +6008,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb) case WMI_10_4_PDEV_TPC_TABLE_EVENTID: ath10k_wmi_event_tpc_final_table(ar, skb); break; + case WMI_10_4_DFS_STATUS_CHECK_EVENTID: + ath10k_wmi_event_dfs_status_check(ar, skb); + break; default: ath10k_warn(ar, "Unknown eventid: %d\n", id); break; @@ -8464,6 +8597,32 @@ ath10k_wmi_10_4_gen_tdls_peer_update(struct ath10k *ar, } static struct sk_buff * +ath10k_wmi_10_4_gen_radar_found(struct ath10k *ar, + const struct ath10k_radar_found_info *arg) +{ + struct wmi_radar_found_info *cmd; + struct sk_buff *skb; + + skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); + if (!skb) + return ERR_PTR(-ENOMEM); + + cmd = (struct wmi_radar_found_info *)skb->data; + cmd->pri_min = __cpu_to_le32(arg->pri_min); + cmd->pri_max = __cpu_to_le32(arg->pri_max); + cmd->width_min = __cpu_to_le32(arg->width_min); + cmd->width_max = __cpu_to_le32(arg->width_max); + cmd->sidx_min = __cpu_to_le32(arg->sidx_min); + cmd->sidx_max = __cpu_to_le32(arg->sidx_max); + + ath10k_dbg(ar, ATH10K_DBG_WMI, + "wmi radar found pri_min %d pri_max %d width_min %d width_max %d sidx_min %d sidx_max %d\n", + arg->pri_min, arg->pri_max, arg->width_min, + arg->width_max, arg->sidx_min, arg->sidx_max); + return skb; +} + +static struct sk_buff * ath10k_wmi_op_gen_echo(struct ath10k *ar, u32 value) { struct wmi_echo_cmd *cmd; @@ -8800,6 +8959,7 @@ static const struct wmi_ops wmi_10_4_ops = { .pull_svc_rdy = ath10k_wmi_main_op_pull_svc_rdy_ev, .pull_rdy = ath10k_wmi_op_pull_rdy_ev, .pull_roam_ev = ath10k_wmi_op_pull_roam_ev, + .pull_dfs_status_ev = ath10k_wmi_10_4_op_pull_dfs_status_ev, .get_txbf_conf_scheme = ath10k_wmi_10_4_txbf_conf_scheme, .gen_pdev_suspend = ath10k_wmi_op_gen_pdev_suspend, @@ -8846,6 +9006,7 @@ static const struct wmi_ops wmi_10_4_ops = { .gen_tdls_peer_update = ath10k_wmi_10_4_gen_tdls_peer_update, .gen_pdev_get_tpc_table_cmdid = ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid, + .gen_radar_found = ath10k_wmi_10_4_gen_radar_found, /* shared with 10.2 */ .pull_echo_ev = ath10k_wmi_op_pull_echo_ev, @@ -8908,8 +9069,11 @@ int ath10k_wmi_attach(struct ath10k *ar) init_completion(&ar->wmi.service_ready); init_completion(&ar->wmi.unified_ready); init_completion(&ar->wmi.barrier); + init_completion(&ar->wmi.radar_confirm); INIT_WORK(&ar->svc_rdy_work, ath10k_wmi_event_service_ready_work); + INIT_WORK(&ar->radar_confirmation_work, + ath10k_radar_confirmation_work); return 0; } diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 16a39244a34f..b48db54e9865 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -969,6 +969,7 @@ struct wmi_cmd_map { u32 vdev_sifs_trigger_time_cmdid; u32 pdev_wds_entry_list_cmdid; u32 tdls_set_offchan_mode_cmdid; + u32 radar_found_cmdid; }; /* @@ -1803,6 +1804,11 @@ enum wmi_10_4_cmd_id { WMI_10_4_TDLS_SET_STATE_CMDID, WMI_10_4_TDLS_PEER_UPDATE_CMDID, WMI_10_4_TDLS_SET_OFFCHAN_MODE_CMDID, + WMI_10_4_PDEV_SEND_FD_CMDID, + WMI_10_4_ENABLE_FILS_CMDID, + WMI_10_4_PDEV_SET_BRIDGE_MACADDR_CMDID, + WMI_10_4_ATF_GROUP_WMM_AC_CONFIG_REQUEST_CMDID, + WMI_10_4_RADAR_FOUND_CMDID, WMI_10_4_PDEV_UTF_CMDID = WMI_10_4_END_CMDID - 1, }; @@ -1878,6 +1884,9 @@ enum wmi_10_4_event_id { WMI_10_4_PDEV_TPC_TABLE_EVENTID, WMI_10_4_PDEV_WDS_ENTRY_LIST_EVENTID, WMI_10_4_TDLS_PEER_EVENTID, + WMI_10_4_HOST_SWFDA_EVENTID, + WMI_10_4_ESP_ESTIMATE_EVENTID, + WMI_10_4_DFS_STATUS_CHECK_EVENTID, WMI_10_4_PDEV_UTF_EVENTID = WMI_10_4_END_EVENTID - 1, }; @@ -3398,6 +3407,25 @@ struct wmi_10_4_phyerr_event { u8 buf[0]; } __packed; +struct wmi_radar_found_info { + __le32 pri_min; + __le32 pri_max; + __le32 width_min; + __le32 width_max; + __le32 sidx_min; + __le32 sidx_max; +} __packed; + +enum wmi_radar_confirmation_status { + /* Detected radar was due to SW pulses */ + WMI_SW_RADAR_DETECTED = 0, + + WMI_RADAR_DETECTION_FAIL = 1, + + /* Real radar detected */ + WMI_HW_RADAR_DETECTED = 2, +}; + #define PHYERR_TLV_SIG 0xBB #define PHYERR_TLV_TAG_SEARCH_FFT_REPORT 0xFB #define PHYERR_TLV_TAG_RADAR_PULSE_SUMMARY 0xF8 @@ -4026,9 +4054,9 @@ struct wmi_pdev_get_tpc_config_cmd { } __packed; #define WMI_TPC_CONFIG_PARAM 1 -#define WMI_TPC_RATE_MAX 160 #define WMI_TPC_FINAL_RATE_MAX 240 #define WMI_TPC_TX_N_CHAIN 4 +#define WMI_TPC_RATE_MAX (WMI_TPC_TX_N_CHAIN * 65) #define WMI_TPC_PREAM_TABLE_MAX 10 #define WMI_TPC_FLAG 3 #define WMI_TPC_BUF_SIZE 10 @@ -6631,6 +6659,10 @@ struct wmi_phyerr_hdr_arg { const void *phyerrs; }; +struct wmi_dfs_status_ev_arg { + u32 status; +}; + struct wmi_svc_rdy_ev_arg { __le32 min_tx_power; __le32 max_tx_power; diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index e23d450babd2..0d30e762c090 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -914,7 +914,7 @@ void ath6kl_tx_data_cleanup(struct ath6kl *ar); struct ath6kl_cookie *ath6kl_alloc_cookie(struct ath6kl *ar); void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie); -int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev); +netdev_tx_t ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev); struct aggr_info *aggr_init(struct ath6kl_vif *vif); void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info, diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 8da9506f8c2b..618d12ed4b40 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -353,7 +353,7 @@ fail_ctrl_tx: return status; } -int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) +netdev_tx_t ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) { struct ath6kl *ar = ath6kl_priv(dev); struct ath6kl_cookie *cookie = NULL; diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c index c8844f55574c..acb9602aa464 100644 --- a/drivers/net/wireless/ath/ath9k/dfs.c +++ b/drivers/net/wireless/ath/ath9k/dfs.c @@ -277,7 +277,7 @@ ath9k_dfs_process_radar_pulse(struct ath_softc *sc, struct pulse_event *pe) DFS_STAT_INC(sc, pulses_processed); if (pd == NULL) return; - if (!pd->add_pulse(pd, pe)) + if (!pd->add_pulse(pd, pe, NULL)) return; DFS_STAT_INC(sc, radar_detected); ieee80211_radar_detected(sc->hw); diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c index 448b83eea810..d52b31b45df7 100644 --- a/drivers/net/wireless/ath/dfs_pattern_detector.c +++ b/drivers/net/wireless/ath/dfs_pattern_detector.c @@ -268,7 +268,8 @@ static void dpd_exit(struct dfs_pattern_detector *dpd) } static bool -dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event) +dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event, + struct radar_detector_specs *rs) { u32 i; struct channel_detector *cd; @@ -294,6 +295,8 @@ dpd_add_pulse(struct dfs_pattern_detector *dpd, struct pulse_event *event) struct pri_detector *pd = cd->detectors[i]; struct pri_sequence *ps = pd->add_pulse(pd, event); if (ps != NULL) { + if (rs != NULL) + memcpy(rs, pd->rs, sizeof(*rs)); ath_dbg(dpd->common, DFS, "DFS: radar found on freq=%d: id=%d, pri=%d, " "count=%d, count_false=%d\n", diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.h b/drivers/net/wireless/ath/dfs_pattern_detector.h index 92be3530e9b5..18db6f4f3568 100644 --- a/drivers/net/wireless/ath/dfs_pattern_detector.h +++ b/drivers/net/wireless/ath/dfs_pattern_detector.h @@ -97,7 +97,8 @@ struct dfs_pattern_detector { bool (*set_dfs_domain)(struct dfs_pattern_detector *dpd, enum nl80211_dfs_regions region); bool (*add_pulse)(struct dfs_pattern_detector *dpd, - struct pulse_event *pe); + struct pulse_event *pe, + struct radar_detector_specs *rs); struct ath_dfs_pool_stats (*get_stats)(struct dfs_pattern_detector *dpd); enum nl80211_dfs_regions region; diff --git a/drivers/net/wireless/ath/dfs_pri_detector.h b/drivers/net/wireless/ath/dfs_pri_detector.h index 79f0fff4d1e6..86339f2b4d3a 100644 --- a/drivers/net/wireless/ath/dfs_pri_detector.h +++ b/drivers/net/wireless/ath/dfs_pri_detector.h @@ -62,8 +62,9 @@ struct pri_detector { (*add_pulse)(struct pri_detector *de, struct pulse_event *e); void (*reset) (struct pri_detector *de, u64 ts); -/* private: internal use only */ const struct radar_detector_specs *rs; + +/* private: internal use only */ u64 last_ts; struct list_head sequences; struct list_head pulses; diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index 5d80be213fac..d73e45e26547 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -68,12 +68,14 @@ enum CountryCode { CTRY_AUSTRALIA = 36, CTRY_AUSTRIA = 40, CTRY_AZERBAIJAN = 31, + CTRY_BAHAMAS = 44, CTRY_BAHRAIN = 48, CTRY_BANGLADESH = 50, CTRY_BARBADOS = 52, CTRY_BELARUS = 112, CTRY_BELGIUM = 56, CTRY_BELIZE = 84, + CTRY_BERMUDA = 60, CTRY_BOLIVIA = 68, CTRY_BOSNIA_HERZ = 70, CTRY_BRAZIL = 76, @@ -136,8 +138,10 @@ enum CountryCode { CTRY_MACEDONIA = 807, CTRY_MALAYSIA = 458, CTRY_MALTA = 470, + CTRY_MAURITIUS = 480, CTRY_MEXICO = 484, CTRY_MONACO = 492, + CTRY_MONTENEGRO = 499, CTRY_MOROCCO = 504, CTRY_NEPAL = 524, CTRY_NETHERLANDS = 528, @@ -159,6 +163,7 @@ enum CountryCode { CTRY_ROMANIA = 642, CTRY_RUSSIA = 643, CTRY_SAUDI_ARABIA = 682, + CTRY_SERBIA = 688, CTRY_SERBIA_MONTENEGRO = 891, CTRY_SINGAPORE = 702, CTRY_SLOVAKIA = 703, @@ -170,11 +175,13 @@ enum CountryCode { CTRY_SWITZERLAND = 756, CTRY_SYRIA = 760, CTRY_TAIWAN = 158, + CTRY_TANZANIA = 834, CTRY_THAILAND = 764, CTRY_TRINIDAD_Y_TOBAGO = 780, CTRY_TUNISIA = 788, CTRY_TURKEY = 792, CTRY_UAE = 784, + CTRY_UGANDA = 800, CTRY_UKRAINE = 804, CTRY_UNITED_KINGDOM = 826, CTRY_UNITED_STATES = 840, diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h index bdd2b4d61f2f..4021e37a225a 100644 --- a/drivers/net/wireless/ath/regd_common.h +++ b/drivers/net/wireless/ath/regd_common.h @@ -35,6 +35,7 @@ enum EnumRd { FRANCE_RES = 0x31, FCC3_FCCA = 0x3A, FCC3_WORLD = 0x3B, + FCC3_ETSIC = 0x3F, ETSI1_WORLD = 0x37, ETSI3_ETSIA = 0x32, @@ -44,6 +45,8 @@ enum EnumRd { ETSI4_ETSIC = 0x38, ETSI5_WORLD = 0x39, ETSI6_WORLD = 0x34, + ETSI8_WORLD = 0x3D, + ETSI9_WORLD = 0x3E, ETSI_RESERVED = 0x33, MKK1_MKKA = 0x40, @@ -59,6 +62,7 @@ enum EnumRd { MKK1_MKKA1 = 0x4A, MKK1_MKKA2 = 0x4B, MKK1_MKKC = 0x4C, + APL2_FCCA = 0x4D, APL3_FCCA = 0x50, APL1_WORLD = 0x52, @@ -67,6 +71,7 @@ enum EnumRd { APL1_ETSIC = 0x55, APL2_ETSIC = 0x56, APL5_WORLD = 0x58, + APL13_WORLD = 0x5A, APL6_WORLD = 0x5B, APL7_FCCA = 0x5C, APL8_WORLD = 0x5D, @@ -168,6 +173,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { {FCC2_ETSIC, CTL_FCC, CTL_ETSI}, {FCC3_FCCA, CTL_FCC, CTL_FCC}, {FCC3_WORLD, CTL_FCC, CTL_ETSI}, + {FCC3_ETSIC, CTL_FCC, CTL_ETSI}, {FCC4_FCCA, CTL_FCC, CTL_FCC}, {FCC5_FCCA, CTL_FCC, CTL_FCC}, {FCC6_FCCA, CTL_FCC, CTL_FCC}, @@ -179,6 +185,8 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { {ETSI4_WORLD, CTL_ETSI, CTL_ETSI}, {ETSI5_WORLD, CTL_ETSI, CTL_ETSI}, {ETSI6_WORLD, CTL_ETSI, CTL_ETSI}, + {ETSI8_WORLD, CTL_ETSI, CTL_ETSI}, + {ETSI9_WORLD, CTL_ETSI, CTL_ETSI}, /* XXX: For ETSI3_ETSIA, Was NO_CTL meant for the 2 GHz band ? */ {ETSI3_ETSIA, CTL_ETSI, CTL_ETSI}, @@ -188,9 +196,11 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { {FCC1_FCCA, CTL_FCC, CTL_FCC}, {APL1_WORLD, CTL_FCC, CTL_ETSI}, {APL2_WORLD, CTL_FCC, CTL_ETSI}, + {APL2_FCCA, CTL_FCC, CTL_FCC}, {APL3_WORLD, CTL_FCC, CTL_ETSI}, {APL4_WORLD, CTL_FCC, CTL_ETSI}, {APL5_WORLD, CTL_FCC, CTL_ETSI}, + {APL13_WORLD, CTL_ETSI, CTL_ETSI}, {APL6_WORLD, CTL_ETSI, CTL_ETSI}, {APL8_WORLD, CTL_ETSI, CTL_ETSI}, {APL9_WORLD, CTL_ETSI, CTL_ETSI}, @@ -289,37 +299,39 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { static struct country_code_to_enum_rd allCountries[] = { {CTRY_DEBUG, NO_ENUMRD, "DB"}, {CTRY_DEFAULT, FCC1_FCCA, "CO"}, - {CTRY_ALBANIA, NULL1_WORLD, "AL"}, - {CTRY_ALGERIA, NULL1_WORLD, "DZ"}, + {CTRY_ALBANIA, ETSI1_WORLD, "AL"}, + {CTRY_ALGERIA, APL13_WORLD, "DZ"}, {CTRY_ARGENTINA, FCC3_WORLD, "AR"}, {CTRY_ARMENIA, ETSI4_WORLD, "AM"}, {CTRY_ARUBA, ETSI1_WORLD, "AW"}, - {CTRY_AUSTRALIA, FCC2_WORLD, "AU"}, + {CTRY_AUSTRALIA, FCC3_WORLD, "AU"}, {CTRY_AUSTRALIA2, FCC6_WORLD, "AU"}, {CTRY_AUSTRIA, ETSI1_WORLD, "AT"}, {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"}, + {CTRY_BAHAMAS, FCC3_WORLD, "BS"}, {CTRY_BAHRAIN, APL6_WORLD, "BH"}, - {CTRY_BANGLADESH, NULL1_WORLD, "BD"}, + {CTRY_BANGLADESH, APL1_WORLD, "BD"}, {CTRY_BARBADOS, FCC2_WORLD, "BB"}, {CTRY_BELARUS, ETSI1_WORLD, "BY"}, {CTRY_BELGIUM, ETSI1_WORLD, "BE"}, {CTRY_BELGIUM2, ETSI4_WORLD, "BL"}, {CTRY_BELIZE, APL1_ETSIC, "BZ"}, + {CTRY_BERMUDA, FCC3_FCCA, "BM"}, {CTRY_BOLIVIA, APL1_ETSIC, "BO"}, {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA"}, {CTRY_BRAZIL, FCC3_WORLD, "BR"}, - {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"}, - {CTRY_BULGARIA, ETSI6_WORLD, "BG"}, + {CTRY_BRUNEI_DARUSSALAM, APL6_WORLD, "BN"}, + {CTRY_BULGARIA, ETSI1_WORLD, "BG"}, {CTRY_CAMBODIA, ETSI1_WORLD, "KH"}, {CTRY_CANADA, FCC3_FCCA, "CA"}, {CTRY_CANADA2, FCC6_FCCA, "CA"}, {CTRY_CHILE, APL6_WORLD, "CL"}, {CTRY_CHINA, APL1_WORLD, "CN"}, - {CTRY_COLOMBIA, FCC1_FCCA, "CO"}, + {CTRY_COLOMBIA, FCC3_WORLD, "CO"}, {CTRY_COSTA_RICA, FCC1_WORLD, "CR"}, {CTRY_CROATIA, ETSI1_WORLD, "HR"}, {CTRY_CYPRUS, ETSI1_WORLD, "CY"}, - {CTRY_CZECH, ETSI3_WORLD, "CZ"}, + {CTRY_CZECH, ETSI1_WORLD, "CZ"}, {CTRY_DENMARK, ETSI1_WORLD, "DK"}, {CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO"}, {CTRY_ECUADOR, FCC1_WORLD, "EC"}, @@ -336,7 +348,7 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_GUAM, FCC1_FCCA, "GU"}, {CTRY_GUATEMALA, FCC1_FCCA, "GT"}, {CTRY_HAITI, ETSI1_WORLD, "HT"}, - {CTRY_HONDURAS, NULL1_WORLD, "HN"}, + {CTRY_HONDURAS, FCC3_WORLD, "HN"}, {CTRY_HONG_KONG, FCC3_WORLD, "HK"}, {CTRY_HUNGARY, ETSI1_WORLD, "HU"}, {CTRY_ICELAND, ETSI1_WORLD, "IS"}, @@ -344,7 +356,7 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_INDONESIA, NULL1_WORLD, "ID"}, {CTRY_IRAN, APL1_WORLD, "IR"}, {CTRY_IRELAND, ETSI1_WORLD, "IE"}, - {CTRY_ISRAEL, NULL1_WORLD, "IL"}, + {CTRY_ISRAEL, ETSI3_WORLD, "IL"}, {CTRY_ITALY, ETSI1_WORLD, "IT"}, {CTRY_JAMAICA, FCC3_WORLD, "JM"}, @@ -409,6 +421,7 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_JORDAN, ETSI2_WORLD, "JO"}, {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ"}, + {CTRY_KENYA, APL1_WORLD, "KE"}, {CTRY_KOREA_NORTH, APL9_WORLD, "KP"}, {CTRY_KOREA_ROC, APL9_WORLD, "KR"}, {CTRY_KOREA_ROC2, APL2_WORLD, "K2"}, @@ -420,32 +433,37 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_LITHUANIA, ETSI1_WORLD, "LT"}, {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU"}, {CTRY_MACAU, FCC2_WORLD, "MO"}, - {CTRY_MACEDONIA, NULL1_WORLD, "MK"}, - {CTRY_MALAYSIA, APL8_WORLD, "MY"}, + {CTRY_MACEDONIA, ETSI1_WORLD, "MK"}, + {CTRY_MALAYSIA, FCC1_WORLD, "MY"}, {CTRY_MALTA, ETSI1_WORLD, "MT"}, + {CTRY_MAURITIUS, ETSI1_WORLD, "MU"}, {CTRY_MEXICO, FCC1_FCCA, "MX"}, {CTRY_MONACO, ETSI4_WORLD, "MC"}, + {CTRY_MONTENEGRO, ETSI1_WORLD, "ME"}, {CTRY_MOROCCO, APL4_WORLD, "MA"}, {CTRY_NEPAL, APL1_WORLD, "NP"}, {CTRY_NETHERLANDS, ETSI1_WORLD, "NL"}, {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"}, - {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"}, + {CTRY_NEW_ZEALAND, FCC3_ETSIC, "NZ"}, + {CTRY_NICARAGUA, FCC3_FCCA, "NI"}, {CTRY_NORWAY, ETSI1_WORLD, "NO"}, {CTRY_OMAN, FCC3_WORLD, "OM"}, {CTRY_PAKISTAN, NULL1_WORLD, "PK"}, {CTRY_PANAMA, FCC1_FCCA, "PA"}, {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"}, - {CTRY_PERU, APL1_WORLD, "PE"}, - {CTRY_PHILIPPINES, APL1_WORLD, "PH"}, + {CTRY_PARAGUAY, FCC3_WORLD, "PY"}, + {CTRY_PERU, FCC3_WORLD, "PE"}, + {CTRY_PHILIPPINES, FCC3_WORLD, "PH"}, {CTRY_POLAND, ETSI1_WORLD, "PL"}, {CTRY_PORTUGAL, ETSI1_WORLD, "PT"}, {CTRY_PUERTO_RICO, FCC1_FCCA, "PR"}, {CTRY_QATAR, APL1_WORLD, "QA"}, - {CTRY_ROMANIA, NULL1_WORLD, "RO"}, - {CTRY_RUSSIA, NULL1_WORLD, "RU"}, + {CTRY_ROMANIA, ETSI1_WORLD, "RO"}, + {CTRY_RUSSIA, ETSI8_WORLD, "RU"}, {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"}, + {CTRY_SERBIA, ETSI1_WORLD, "RS"}, {CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS"}, - {CTRY_SINGAPORE, APL6_WORLD, "SG"}, + {CTRY_SINGAPORE, FCC3_WORLD, "SG"}, {CTRY_SLOVAKIA, ETSI1_WORLD, "SK"}, {CTRY_SLOVENIA, ETSI1_WORLD, "SI"}, {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA"}, @@ -455,11 +473,13 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_SWITZERLAND, ETSI1_WORLD, "CH"}, {CTRY_SYRIA, NULL1_WORLD, "SY"}, {CTRY_TAIWAN, APL3_FCCA, "TW"}, + {CTRY_TANZANIA, APL1_WORLD, "TZ"}, {CTRY_THAILAND, FCC3_WORLD, "TH"}, {CTRY_TRINIDAD_Y_TOBAGO, FCC3_WORLD, "TT"}, {CTRY_TUNISIA, ETSI3_WORLD, "TN"}, {CTRY_TURKEY, ETSI3_WORLD, "TR"}, - {CTRY_UKRAINE, NULL1_WORLD, "UA"}, + {CTRY_UGANDA, FCC3_WORLD, "UG"}, + {CTRY_UKRAINE, ETSI9_WORLD, "UA"}, {CTRY_UAE, NULL1_WORLD, "AE"}, {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"}, {CTRY_UNITED_STATES, FCC3_FCCA, "US"}, @@ -472,7 +492,7 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_VENEZUELA, APL2_ETSIC, "VE"}, {CTRY_VIET_NAM, NULL1_WORLD, "VN"}, {CTRY_YEMEN, NULL1_WORLD, "YE"}, - {CTRY_ZIMBABWE, NULL1_WORLD, "ZW"}, + {CTRY_ZIMBABWE, ETSI1_WORLD, "ZW"}, }; #endif diff --git a/drivers/net/wireless/ath/wcn36xx/Makefile b/drivers/net/wireless/ath/wcn36xx/Makefile index 3b09435104eb..582049f65735 100644 --- a/drivers/net/wireless/ath/wcn36xx/Makefile +++ b/drivers/net/wireless/ath/wcn36xx/Makefile @@ -6,3 +6,5 @@ wcn36xx-y += main.o \ smd.o \ pmc.o \ debug.o + +wcn36xx-$(CONFIG_NL80211_TESTMODE) += testmode.o diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index bd2b946a65c9..06cfe8d311f3 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -370,7 +370,9 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch) do { if (READ_ONCE(ctl->desc->ctrl) & WCN36xx_DXE_CTRL_VLD) break; - if (ctl->skb) { + + if (ctl->skb && + READ_ONCE(ctl->desc->ctrl) & WCN36xx_DXE_CTRL_EOP) { dma_unmap_single(wcn->dev, ctl->desc->src_addr_l, ctl->skb->len, DMA_TO_DEVICE); info = IEEE80211_SKB_CB(ctl->skb); @@ -430,8 +432,12 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) WCN36XX_INT_MASK_CHAN_TX_H); } - wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high\n"); - reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch); + wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready high, reason %08x\n", + int_reason); + + if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK | + WCN36XX_CH_STAT_INT_ED_MASK)) + reap_tx_dxes(wcn, &wcn->dxe_tx_h_ch); } if (int_src & WCN36XX_INT_MASK_CHAN_TX_L) { @@ -465,8 +471,12 @@ static irqreturn_t wcn36xx_irq_tx_complete(int irq, void *dev) WCN36XX_INT_MASK_CHAN_TX_L); } - wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low\n"); - reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch); + wcn36xx_dbg(WCN36XX_DBG_DXE, "dxe tx ready low, reason %08x\n", + int_reason); + + if (int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK | + WCN36XX_CH_STAT_INT_ED_MASK)) + reap_tx_dxes(wcn, &wcn->dxe_tx_l_ch); } return IRQ_HANDLED; @@ -476,9 +486,8 @@ static irqreturn_t wcn36xx_irq_rx_ready(int irq, void *dev) { struct wcn36xx *wcn = (struct wcn36xx *)dev; - disable_irq_nosync(wcn->rx_irq); wcn36xx_dxe_rx_frame(wcn); - enable_irq(wcn->rx_irq); + return IRQ_HANDLED; } @@ -512,23 +521,49 @@ out_err: } static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, - struct wcn36xx_dxe_ch *ch) + struct wcn36xx_dxe_ch *ch, + u32 ctrl, + u32 en_mask, + u32 int_mask, + u32 status_reg) { - struct wcn36xx_dxe_ctl *ctl = ch->head_blk_ctl; - struct wcn36xx_dxe_desc *dxe = ctl->desc; + struct wcn36xx_dxe_desc *dxe; + struct wcn36xx_dxe_ctl *ctl; dma_addr_t dma_addr; struct sk_buff *skb; - int ret = 0, int_mask; - u32 value; + u32 int_reason; + int ret; - if (ch->ch_type == WCN36XX_DXE_CH_RX_L) { - value = WCN36XX_DXE_CTRL_RX_L; - int_mask = WCN36XX_DXE_INT_CH1_MASK; - } else { - value = WCN36XX_DXE_CTRL_RX_H; - int_mask = WCN36XX_DXE_INT_CH3_MASK; + wcn36xx_dxe_read_register(wcn, status_reg, &int_reason); + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, int_mask); + + if (int_reason & WCN36XX_CH_STAT_INT_ERR_MASK) { + wcn36xx_dxe_write_register(wcn, + WCN36XX_DXE_0_INT_ERR_CLR, + int_mask); + + wcn36xx_err("DXE IRQ reported error on RX channel\n"); } + if (int_reason & WCN36XX_CH_STAT_INT_DONE_MASK) + wcn36xx_dxe_write_register(wcn, + WCN36XX_DXE_0_INT_DONE_CLR, + int_mask); + + if (int_reason & WCN36XX_CH_STAT_INT_ED_MASK) + wcn36xx_dxe_write_register(wcn, + WCN36XX_DXE_0_INT_ED_CLR, + int_mask); + + if (!(int_reason & (WCN36XX_CH_STAT_INT_DONE_MASK | + WCN36XX_CH_STAT_INT_ED_MASK))) + return 0; + + spin_lock(&ch->lock); + + ctl = ch->head_blk_ctl; + dxe = ctl->desc; + while (!(READ_ONCE(dxe->ctrl) & WCN36xx_DXE_CTRL_VLD)) { skb = ctl->skb; dma_addr = dxe->dst_addr_l; @@ -542,13 +577,16 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn, wcn36xx_rx_skb(wcn, skb); } /* else keep old skb not submitted and use it for rx DMA */ - dxe->ctrl = value; + dxe->ctrl = ctrl; ctl = ctl->next; dxe = ctl->desc; } - wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, int_mask); + wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, en_mask); ch->head_blk_ctl = ctl; + + spin_unlock(&ch->lock); + return 0; } @@ -559,19 +597,20 @@ void wcn36xx_dxe_rx_frame(struct wcn36xx *wcn) wcn36xx_dxe_read_register(wcn, WCN36XX_DXE_INT_SRC_RAW_REG, &int_src); /* RX_LOW_PRI */ - if (int_src & WCN36XX_DXE_INT_CH1_MASK) { - wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, - WCN36XX_DXE_INT_CH1_MASK); - wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_l_ch)); - } + if (int_src & WCN36XX_DXE_INT_CH1_MASK) + wcn36xx_rx_handle_packets(wcn, &wcn->dxe_rx_l_ch, + WCN36XX_DXE_CTRL_RX_L, + WCN36XX_DXE_INT_CH1_MASK, + WCN36XX_INT_MASK_CHAN_RX_L, + WCN36XX_DXE_CH_STATUS_REG_ADDR_RX_L); /* RX_HIGH_PRI */ - if (int_src & WCN36XX_DXE_INT_CH3_MASK) { - /* Clean up all the INT within this channel */ - wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_0_INT_CLR, - WCN36XX_DXE_INT_CH3_MASK); - wcn36xx_rx_handle_packets(wcn, &(wcn->dxe_rx_h_ch)); - } + if (int_src & WCN36XX_DXE_INT_CH3_MASK) + wcn36xx_rx_handle_packets(wcn, &wcn->dxe_rx_h_ch, + WCN36XX_DXE_CTRL_RX_H, + WCN36XX_DXE_INT_CH3_MASK, + WCN36XX_INT_MASK_CHAN_RX_H, + WCN36XX_DXE_CH_STATUS_REG_ADDR_RX_H); if (!int_src) wcn36xx_warn("No DXE interrupt pending\n"); @@ -642,8 +681,8 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, struct sk_buff *skb, bool is_low) { - struct wcn36xx_dxe_ctl *ctl = NULL; - struct wcn36xx_dxe_desc *desc = NULL; + struct wcn36xx_dxe_desc *desc_bd, *desc_skb; + struct wcn36xx_dxe_ctl *ctl_bd, *ctl_skb; struct wcn36xx_dxe_ch *ch = NULL; unsigned long flags; int ret; @@ -651,74 +690,75 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, ch = is_low ? &wcn->dxe_tx_l_ch : &wcn->dxe_tx_h_ch; spin_lock_irqsave(&ch->lock, flags); - ctl = ch->head_blk_ctl; + ctl_bd = ch->head_blk_ctl; + ctl_skb = ctl_bd->next; /* * If skb is not null that means that we reached the tail of the ring * hence ring is full. Stop queues to let mac80211 back off until ring * has an empty slot again. */ - if (NULL != ctl->next->skb) { + if (NULL != ctl_skb->skb) { ieee80211_stop_queues(wcn->hw); wcn->queues_stopped = true; spin_unlock_irqrestore(&ch->lock, flags); return -EBUSY; } - ctl->skb = NULL; - desc = ctl->desc; + if (unlikely(ctl_skb->bd_cpu_addr)) { + wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n"); + ret = -EINVAL; + goto unlock; + } + + desc_bd = ctl_bd->desc; + desc_skb = ctl_skb->desc; + + ctl_bd->skb = NULL; /* write buffer descriptor */ - memcpy(ctl->bd_cpu_addr, bd, sizeof(*bd)); + memcpy(ctl_bd->bd_cpu_addr, bd, sizeof(*bd)); /* Set source address of the BD we send */ - desc->src_addr_l = ctl->bd_phy_addr; - - desc->dst_addr_l = ch->dxe_wq; - desc->fr_len = sizeof(struct wcn36xx_tx_bd); - desc->ctrl = ch->ctrl_bd; + desc_bd->src_addr_l = ctl_bd->bd_phy_addr; + desc_bd->dst_addr_l = ch->dxe_wq; + desc_bd->fr_len = sizeof(struct wcn36xx_tx_bd); wcn36xx_dbg(WCN36XX_DBG_DXE, "DXE TX\n"); wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC1 >>> ", - (char *)desc, sizeof(*desc)); + (char *)desc_bd, sizeof(*desc_bd)); wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, - "BD >>> ", (char *)ctl->bd_cpu_addr, + "BD >>> ", (char *)ctl_bd->bd_cpu_addr, sizeof(struct wcn36xx_tx_bd)); - /* Set source address of the SKB we send */ - ctl = ctl->next; - desc = ctl->desc; - if (ctl->bd_cpu_addr) { - wcn36xx_err("bd_cpu_addr cannot be NULL for skb DXE\n"); - ret = -EINVAL; - goto unlock; - } - - desc->src_addr_l = dma_map_single(wcn->dev, - skb->data, - skb->len, - DMA_TO_DEVICE); - if (dma_mapping_error(wcn->dev, desc->src_addr_l)) { + desc_skb->src_addr_l = dma_map_single(wcn->dev, + skb->data, + skb->len, + DMA_TO_DEVICE); + if (dma_mapping_error(wcn->dev, desc_skb->src_addr_l)) { dev_err(wcn->dev, "unable to DMA map src_addr_l\n"); ret = -ENOMEM; goto unlock; } - ctl->skb = skb; - desc->dst_addr_l = ch->dxe_wq; - desc->fr_len = ctl->skb->len; - - /* set dxe descriptor to VALID */ - desc->ctrl = ch->ctrl_skb; + ctl_skb->skb = skb; + desc_skb->dst_addr_l = ch->dxe_wq; + desc_skb->fr_len = ctl_skb->skb->len; wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "DESC2 >>> ", - (char *)desc, sizeof(*desc)); + (char *)desc_skb, sizeof(*desc_skb)); wcn36xx_dbg_dump(WCN36XX_DBG_DXE_DUMP, "SKB >>> ", - (char *)ctl->skb->data, ctl->skb->len); + (char *)ctl_skb->skb->data, ctl_skb->skb->len); /* Move the head of the ring to the next empty descriptor */ - ch->head_blk_ctl = ctl->next; + ch->head_blk_ctl = ctl_skb->next; + + /* Commit all previous writes and set descriptors to VALID */ + wmb(); + desc_skb->ctrl = ch->ctrl_skb; + wmb(); + desc_bd->ctrl = ch->ctrl_bd; /* * When connected and trying to send data frame chip can be in sleep diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index 2aed6c233508..8abda2760e04 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -2236,6 +2236,22 @@ struct wcn36xx_hal_switch_channel_rsp_msg { } __packed; +struct wcn36xx_hal_process_ptt_msg_req_msg { + struct wcn36xx_hal_msg_header header; + + /* Actual FTM Command body */ + u8 ptt_msg[0]; +} __packed; + +struct wcn36xx_hal_process_ptt_msg_rsp_msg { + struct wcn36xx_hal_msg_header header; + + /* FTM Command response status */ + u32 ptt_msg_resp_status; + /* Actual FTM Command body */ + u8 ptt_msg[0]; +} __packed; + struct update_edca_params_req_msg { struct wcn36xx_hal_msg_header header; diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index e3b91b3b38ef..aeb5e6e806be 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -26,6 +26,7 @@ #include <linux/soc/qcom/smem_state.h> #include <linux/soc/qcom/wcnss_ctrl.h> #include "wcn36xx.h" +#include "testmode.h" unsigned int wcn36xx_dbg_mask; module_param_named(debug_mask, wcn36xx_dbg_mask, uint, 0644); @@ -798,6 +799,8 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, if (!is_zero_ether_addr(bss_conf->bssid)) { vif_priv->is_joining = true; vif_priv->bss_index = WCN36XX_HAL_BSS_INVALID_IDX; + wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr, + WCN36XX_HAL_LINK_PREASSOC_STATE); wcn36xx_smd_join(wcn, bss_conf->bssid, vif->addr, WCN36XX_HW_CHANNEL(wcn)); wcn36xx_smd_config_bss(wcn, vif, NULL, @@ -805,6 +808,8 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw, } else { vif_priv->is_joining = false; wcn36xx_smd_delete_bss(wcn, vif); + wcn36xx_smd_set_link_st(wcn, bss_conf->bssid, vif->addr, + WCN36XX_HAL_LINK_IDLE_STATE); vif_priv->encrypt_type = WCN36XX_HAL_ED_NONE; } } @@ -1142,6 +1147,8 @@ static const struct ieee80211_ops wcn36xx_ops = { .sta_add = wcn36xx_sta_add, .sta_remove = wcn36xx_sta_remove, .ampdu_action = wcn36xx_ampdu_action, + + CFG80211_TESTMODE_CMD(wcn36xx_tm_cmd) }; static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) @@ -1309,6 +1316,12 @@ static int wcn36xx_probe(struct platform_device *pdev) mutex_init(&wcn->hal_mutex); mutex_init(&wcn->scan_lock); + ret = dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32)); + if (ret < 0) { + wcn36xx_err("failed to set DMA mask: %d\n", ret); + goto out_wq; + } + INIT_WORK(&wcn->scan_work, wcn36xx_hw_scan_worker); wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process, hw); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index ea74f2b92df5..b4dadf75d565 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -252,23 +252,29 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len) { int ret = 0; unsigned long start; + struct wcn36xx_hal_msg_header *hdr = + (struct wcn36xx_hal_msg_header *)wcn->hal_buf; + u16 req_type = hdr->msg_type; + wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "HAL >>> ", wcn->hal_buf, len); init_completion(&wcn->hal_rsp_compl); start = jiffies; ret = rpmsg_send(wcn->smd_channel, wcn->hal_buf, len); if (ret) { - wcn36xx_err("HAL TX failed\n"); + wcn36xx_err("HAL TX failed for req %d\n", req_type); goto out; } if (wait_for_completion_timeout(&wcn->hal_rsp_compl, msecs_to_jiffies(HAL_MSG_TIMEOUT)) <= 0) { - wcn36xx_err("Timeout! No SMD response in %dms\n", - HAL_MSG_TIMEOUT); + wcn36xx_err("Timeout! No SMD response to req %d in %dms\n", + req_type, HAL_MSG_TIMEOUT); ret = -ETIME; goto out; } - wcn36xx_dbg(WCN36XX_DBG_SMD, "SMD command completed in %dms", + wcn36xx_dbg(WCN36XX_DBG_SMD, + "SMD command (req %d, rsp %d) completed in %dms\n", + req_type, hdr->msg_type, jiffies_to_msecs(jiffies - start)); out: return ret; @@ -292,12 +298,26 @@ static void init_hal_msg(struct wcn36xx_hal_msg_header *hdr, msg_body.header.len = sizeof(msg_body); \ } while (0) \ +#define INIT_HAL_PTT_MSG(p_msg_body, ppt_msg_len) \ + do { \ + memset(p_msg_body, 0, sizeof(*p_msg_body) + ppt_msg_len); \ + p_msg_body->header.msg_type = WCN36XX_HAL_PROCESS_PTT_REQ; \ + p_msg_body->header.msg_version = WCN36XX_HAL_MSG_VERSION0; \ + p_msg_body->header.len = sizeof(*p_msg_body) + ppt_msg_len; \ + } while (0) + #define PREPARE_HAL_BUF(send_buf, msg_body) \ do { \ memset(send_buf, 0, msg_body.header.len); \ memcpy(send_buf, &msg_body, sizeof(msg_body)); \ } while (0) \ +#define PREPARE_HAL_PTT_MSG_BUF(send_buf, p_msg_body) \ + do { \ + memset(send_buf, 0, p_msg_body->header.len); \ + memcpy(send_buf, p_msg_body, p_msg_body->header.len); \ + } while (0) + static int wcn36xx_smd_rsp_status_check(void *buf, size_t len) { struct wcn36xx_fw_msg_status_rsp *rsp; @@ -754,6 +774,71 @@ out: return ret; } +static int wcn36xx_smd_process_ptt_msg_rsp(void *buf, size_t len, + void **p_ptt_rsp_msg) +{ + struct wcn36xx_hal_process_ptt_msg_rsp_msg *rsp; + int ret; + + ret = wcn36xx_smd_rsp_status_check(buf, len); + if (ret) + return ret; + + rsp = (struct wcn36xx_hal_process_ptt_msg_rsp_msg *)buf; + + wcn36xx_dbg(WCN36XX_DBG_HAL, "process ptt msg responded with length %d\n", + rsp->header.len); + wcn36xx_dbg_dump(WCN36XX_DBG_HAL_DUMP, "HAL_PTT_MSG_RSP:", rsp->ptt_msg, + rsp->header.len - sizeof(rsp->ptt_msg_resp_status)); + + if (rsp->header.len > 0) { + *p_ptt_rsp_msg = kmalloc(rsp->header.len, GFP_ATOMIC); + if (!*p_ptt_rsp_msg) + return -ENOMEM; + memcpy(*p_ptt_rsp_msg, rsp->ptt_msg, rsp->header.len); + } + return ret; +} + +int wcn36xx_smd_process_ptt_msg(struct wcn36xx *wcn, + struct ieee80211_vif *vif, void *ptt_msg, size_t len, + void **ptt_rsp_msg) +{ + struct wcn36xx_hal_process_ptt_msg_req_msg *p_msg_body; + int ret; + + mutex_lock(&wcn->hal_mutex); + p_msg_body = kmalloc( + sizeof(struct wcn36xx_hal_process_ptt_msg_req_msg) + len, + GFP_ATOMIC); + if (!p_msg_body) { + ret = -ENOMEM; + goto out_nomem; + } + INIT_HAL_PTT_MSG(p_msg_body, len); + + memcpy(&p_msg_body->ptt_msg, ptt_msg, len); + + PREPARE_HAL_PTT_MSG_BUF(wcn->hal_buf, p_msg_body); + + ret = wcn36xx_smd_send_and_wait(wcn, p_msg_body->header.len); + if (ret) { + wcn36xx_err("Sending hal_process_ptt_msg failed\n"); + goto out; + } + ret = wcn36xx_smd_process_ptt_msg_rsp(wcn->hal_buf, wcn->hal_rsp_len, + ptt_rsp_msg); + if (ret) { + wcn36xx_err("process_ptt_msg response failed err=%d\n", ret); + goto out; + } +out: + kfree(p_msg_body); +out_nomem: + mutex_unlock(&wcn->hal_mutex); + return ret; +} + static int wcn36xx_smd_update_scan_params_rsp(void *buf, size_t len) { struct wcn36xx_hal_update_scan_params_resp *rsp; @@ -2390,6 +2475,7 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev, case WCN36XX_HAL_JOIN_RSP: case WCN36XX_HAL_UPDATE_SCAN_PARAM_RSP: case WCN36XX_HAL_CH_SWITCH_RSP: + case WCN36XX_HAL_PROCESS_PTT_RSP: case WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_RSP: case WCN36XX_HAL_8023_MULTICAST_LIST_RSP: case WCN36XX_HAL_START_SCAN_OFFLOAD_RSP: @@ -2430,6 +2516,7 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev, return 0; } + static void wcn36xx_ind_smd_work(struct work_struct *work) { struct wcn36xx *wcn = @@ -2494,24 +2581,24 @@ static void wcn36xx_ind_smd_work(struct work_struct *work) } int wcn36xx_smd_open(struct wcn36xx *wcn) { - int ret = 0; wcn->hal_ind_wq = create_freezable_workqueue("wcn36xx_smd_ind"); - if (!wcn->hal_ind_wq) { - wcn36xx_err("failed to allocate wq\n"); - ret = -ENOMEM; - goto out; - } + if (!wcn->hal_ind_wq) + return -ENOMEM; + INIT_WORK(&wcn->hal_ind_work, wcn36xx_ind_smd_work); INIT_LIST_HEAD(&wcn->hal_ind_queue); spin_lock_init(&wcn->hal_ind_lock); return 0; - -out: - return ret; } void wcn36xx_smd_close(struct wcn36xx *wcn) { + struct wcn36xx_hal_ind_msg *msg, *tmp; + + cancel_work_sync(&wcn->hal_ind_work); destroy_workqueue(wcn->hal_ind_wq); + + list_for_each_entry_safe(msg, tmp, &wcn->hal_ind_queue, list) + kfree(msg); } diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h index 61bb8d43138c..ff15df8ab56f 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.h +++ b/drivers/net/wireless/ath/wcn36xx/smd.h @@ -86,6 +86,10 @@ int wcn36xx_smd_send_beacon(struct wcn36xx *wcn, struct ieee80211_vif *vif, u16 p2p_off); int wcn36xx_smd_switch_channel(struct wcn36xx *wcn, struct ieee80211_vif *vif, int ch); +int wcn36xx_smd_process_ptt_msg(struct wcn36xx *wcn, + struct ieee80211_vif *vif, + void *ptt_msg, size_t len, + void **ptt_rsp_msg); int wcn36xx_smd_update_proberesp_tmpl(struct wcn36xx *wcn, struct ieee80211_vif *vif, struct sk_buff *skb); diff --git a/drivers/net/wireless/ath/wcn36xx/testmode.c b/drivers/net/wireless/ath/wcn36xx/testmode.c new file mode 100644 index 000000000000..1279064a3b71 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/testmode.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <net/netlink.h> +#include <linux/firmware.h> +#include <net/cfg80211.h> +#include "wcn36xx.h" + +#include "testmode.h" +#include "testmode_i.h" +#include "hal.h" +#include "smd.h" + +static const struct nla_policy wcn36xx_tm_policy[WCN36XX_TM_ATTR_MAX + 1] = { + [WCN36XX_TM_ATTR_CMD] = { .type = NLA_U16 }, + [WCN36XX_TM_ATTR_DATA] = { .type = NLA_BINARY, + .len = WCN36XX_TM_DATA_MAX_LEN }, +}; + +struct build_release_number { + u16 drv_major; + u16 drv_minor; + u16 drv_patch; + u16 drv_build; + u16 ptt_max; + u16 ptt_min; + u16 fw_ver; +} __packed; + +static int wcn36xx_tm_cmd_ptt(struct wcn36xx *wcn, struct ieee80211_vif *vif, + struct nlattr *tb[]) +{ + int ret = 0, buf_len; + void *buf; + struct ftm_rsp_msg *msg, *rsp = NULL; + struct sk_buff *skb; + + if (!tb[WCN36XX_TM_ATTR_DATA]) + return -EINVAL; + + buf = nla_data(tb[WCN36XX_TM_ATTR_DATA]); + buf_len = nla_len(tb[WCN36XX_TM_ATTR_DATA]); + msg = (struct ftm_rsp_msg *)buf; + + wcn36xx_dbg(WCN36XX_DBG_TESTMODE, + "testmode cmd wmi msg_id 0x%04X msg_len %d buf %pK buf_len %d\n", + msg->msg_id, msg->msg_body_length, + buf, buf_len); + + wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP, "REQ ", buf, buf_len); + + if (msg->msg_id == MSG_GET_BUILD_RELEASE_NUMBER) { + struct build_release_number *body = + (struct build_release_number *) + msg->msg_response; + + body->drv_major = wcn->fw_major; + body->drv_minor = wcn->fw_minor; + body->drv_patch = wcn->fw_version; + body->drv_build = wcn->fw_revision; + body->ptt_max = 10; + body->ptt_min = 0; + + rsp = msg; + rsp->resp_status = 0; + } else { + wcn36xx_dbg(WCN36XX_DBG_TESTMODE, + "PPT Request >> HAL size %d\n", + msg->msg_body_length); + + msg->resp_status = wcn36xx_smd_process_ptt_msg(wcn, vif, msg, + msg->msg_body_length, (void *)(&rsp)); + + wcn36xx_dbg(WCN36XX_DBG_TESTMODE, + "Response status = %d\n", + msg->resp_status); + if (rsp) + wcn36xx_dbg(WCN36XX_DBG_TESTMODE, + "PPT Response << HAL size %d\n", + rsp->msg_body_length); + } + + if (!rsp) { + rsp = msg; + wcn36xx_warn("No response! Echoing request with response status %d\n", + rsp->resp_status); + } + wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP, "RSP ", + rsp, rsp->msg_body_length); + + skb = cfg80211_testmode_alloc_reply_skb(wcn->hw->wiphy, + nla_total_size(msg->msg_body_length)); + if (!skb) { + ret = -ENOMEM; + goto out; + } + + ret = nla_put(skb, WCN36XX_TM_ATTR_DATA, rsp->msg_body_length, rsp); + if (ret) { + kfree_skb(skb); + goto out; + } + + ret = cfg80211_testmode_reply(skb); + +out: + if (rsp != msg) + kfree(rsp); + + return ret; +} + +int wcn36xx_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + void *data, int len) +{ + struct wcn36xx *wcn = hw->priv; + struct nlattr *tb[WCN36XX_TM_ATTR_MAX + 1]; + int ret = 0; + unsigned short attr; + + wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP, "Data:", data, len); + ret = nla_parse(tb, WCN36XX_TM_ATTR_MAX, data, len, + wcn36xx_tm_policy, NULL); + if (ret) + return ret; + + if (!tb[WCN36XX_TM_ATTR_CMD]) + return -EINVAL; + + attr = nla_get_u16(tb[WCN36XX_TM_ATTR_CMD]); + + if (attr != WCN36XX_TM_CMD_PTT) + return -EOPNOTSUPP; + + return wcn36xx_tm_cmd_ptt(wcn, vif, tb); +} diff --git a/drivers/net/wireless/ath/wcn36xx/testmode.h b/drivers/net/wireless/ath/wcn36xx/testmode.h new file mode 100644 index 000000000000..4c6cfdb46580 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/testmode.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "wcn36xx.h" + +struct ftm_rsp_msg { + u16 msg_id; + u16 msg_body_length; + u32 resp_status; + u8 msg_response[0]; +} __packed; + +/* The request buffer of FTM which contains a byte of command and the request */ +struct ftm_payload { + u16 ftm_cmd_type; + struct ftm_rsp_msg ftm_cmd_msg; +} __packed; + +#define MSG_GET_BUILD_RELEASE_NUMBER 0x32A2 + +#ifdef CONFIG_NL80211_TESTMODE +int wcn36xx_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + void *data, int len); + +#else +static inline int wcn36xx_tm_cmd(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + void *data, int len) +{ + return 0; +} + +#endif diff --git a/drivers/net/wireless/ath/wcn36xx/testmode_i.h b/drivers/net/wireless/ath/wcn36xx/testmode_i.h new file mode 100644 index 000000000000..8a1477ffd5a0 --- /dev/null +++ b/drivers/net/wireless/ath/wcn36xx/testmode_i.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#define WCN36XX_TM_DATA_MAX_LEN 5000 + +enum wcn36xx_tm_attr { + __WCN36XX_TM_ATTR_INVALID = 0, + WCN36XX_TM_ATTR_CMD = 1, + WCN36XX_TM_ATTR_DATA = 2, + + /* keep last */ + __WCN36XX_TM_ATTR_AFTER_LAST, + WCN36XX_TM_ATTR_MAX = __WCN36XX_TM_ATTR_AFTER_LAST - 1, +}; + +#define WCN36XX_TM_CMD_PTT 3 diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 9343989d1169..11e74015c79a 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -50,6 +50,8 @@ enum wcn36xx_debug_mask { WCN36XX_DBG_BEACON_DUMP = 0x00001000, WCN36XX_DBG_PMC = 0x00002000, WCN36XX_DBG_PMC_DUMP = 0x00004000, + WCN36XX_DBG_TESTMODE = 0x00008000, + WCN36XX_DBG_TESTMODE_DUMP = 0x00010000, WCN36XX_DBG_ANY = 0xffffffff, }; diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig index b448926b0c0f..3548e8d5e18e 100644 --- a/drivers/net/wireless/ath/wil6210/Kconfig +++ b/drivers/net/wireless/ath/wil6210/Kconfig @@ -33,7 +33,7 @@ config WIL6210_TRACING bool "wil6210 tracing support" depends on WIL6210 depends on EVENT_TRACING - default y + default n ---help--- Say Y here to enable tracepoints for the wil6210 driver using the kernel tracing infrastructure. Select this diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index cdbb393863f3..78946f28d0c7 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -276,6 +276,8 @@ int wil_cid_fill_sinfo(struct wil6210_vif *vif, int cid, struct wil_net_stats *stats = &wil->sta[cid].stats; int rc; + memset(&reply, 0, sizeof(reply)); + rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_NOTIFY_REQ_DONE_EVENTID, &reply, sizeof(reply), 20); if (rc) @@ -1081,17 +1083,11 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, u64 *cookie) { const u8 *buf = params->buf; - size_t len = params->len, total; + size_t len = params->len; struct wil6210_priv *wil = wiphy_to_wil(wiphy); struct wil6210_vif *vif = wdev_to_vif(wil, wdev); int rc; - bool tx_status = false; - struct ieee80211_mgmt *mgmt_frame = (void *)buf; - struct wmi_sw_tx_req_cmd *cmd; - struct { - struct wmi_cmd_hdr wmi; - struct wmi_sw_tx_complete_event evt; - } __packed evt; + bool tx_status; /* Note, currently we do not support the "wait" parameter, user-space * must call remain_on_channel before mgmt_tx or listen on a channel @@ -1100,34 +1096,9 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, * different from currently "listened" channel and fail if it is. */ - wil_dbg_misc(wil, "mgmt_tx mid %d\n", vif->mid); - wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf, - len, true); - - if (len < sizeof(struct ieee80211_hdr_3addr)) - return -EINVAL; - - total = sizeof(*cmd) + len; - if (total < len) - return -EINVAL; - - cmd = kmalloc(total, GFP_KERNEL); - if (!cmd) { - rc = -ENOMEM; - goto out; - } - - memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN); - cmd->len = cpu_to_le16(len); - memcpy(cmd->payload, buf, len); - - rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, vif->mid, cmd, total, - WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000); - if (rc == 0) - tx_status = !evt.evt.status; + rc = wmi_mgmt_tx(vif, buf, len); + tx_status = (rc == 0); - kfree(cmd); - out: cfg80211_mgmt_tx_status(wdev, cookie ? *cookie : 0, buf, len, tx_status, GFP_KERNEL); return rc; @@ -2277,7 +2248,9 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy, struct { struct wmi_cmd_hdr wmi; struct wmi_get_rf_sector_params_done_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR}, + }; struct sk_buff *msg; struct nlattr *nl_cfgs, *nl_cfg; u32 i; @@ -2323,7 +2296,6 @@ static int wil_rf_sector_get_cfg(struct wiphy *wiphy, cmd.sector_idx = cpu_to_le16(sector_index); cmd.sector_type = sector_type; cmd.rf_modules_vec = rf_modules_vec & 0xFF; - memset(&reply, 0, sizeof(reply)); rc = wmi_call(wil, WMI_GET_RF_SECTOR_PARAMS_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_GET_RF_SECTOR_PARAMS_DONE_EVENTID, &reply, sizeof(reply), @@ -2398,7 +2370,9 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy, struct { struct wmi_cmd_hdr wmi; struct wmi_set_rf_sector_params_done_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR}, + }; struct nlattr *nl_cfg; struct wmi_rf_sector_info *si; @@ -2481,7 +2455,6 @@ static int wil_rf_sector_set_cfg(struct wiphy *wiphy, } cmd.rf_modules_vec = rf_modules_vec & 0xFF; - memset(&reply, 0, sizeof(reply)); rc = wmi_call(wil, WMI_SET_RF_SECTOR_PARAMS_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_SET_RF_SECTOR_PARAMS_DONE_EVENTID, &reply, sizeof(reply), @@ -2505,7 +2478,9 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, struct { struct wmi_cmd_hdr wmi; struct wmi_get_selected_rf_sector_index_done_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR}, + }; struct sk_buff *msg; if (!test_bit(WMI_FW_CAPABILITY_RF_SECTORS, wil->fw_capabilities)) @@ -2545,7 +2520,6 @@ static int wil_rf_sector_get_selected(struct wiphy *wiphy, memset(&cmd, 0, sizeof(cmd)); cmd.cid = (u8)cid; cmd.sector_type = sector_type; - memset(&reply, 0, sizeof(reply)); rc = wmi_call(wil, WMI_GET_SELECTED_RF_SECTOR_INDEX_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_GET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID, @@ -2586,14 +2560,15 @@ static int wil_rf_sector_wmi_set_selected(struct wil6210_priv *wil, struct { struct wmi_cmd_hdr wmi; struct wmi_set_selected_rf_sector_index_done_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_RF_SECTOR_STATUS_NOT_SUPPORTED_ERROR}, + }; int rc; memset(&cmd, 0, sizeof(cmd)); cmd.sector_idx = cpu_to_le16(sector_index); cmd.sector_type = sector_type; cmd.cid = (u8)cid; - memset(&reply, 0, sizeof(reply)); rc = wmi_call(wil, WMI_SET_SELECTED_RF_SECTOR_INDEX_CMDID, mid, &cmd, sizeof(cmd), WMI_SET_SELECTED_RF_SECTOR_INDEX_DONE_EVENTID, diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 11e46e44381e..ebfdff4d328c 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1078,6 +1078,8 @@ static int wil_bf_debugfs_show(struct seq_file *s, void *data) struct wmi_notify_req_done_event evt; } __packed reply; + memset(&reply, 0, sizeof(reply)); + for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { u32 status; @@ -1383,8 +1385,7 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r) u16 index = ((r->head_seq_num - r->ssn) & 0xfff) % r->buf_size; unsigned long long drop_dup = r->drop_dup, drop_old = r->drop_old; - seq_printf(s, "([%2d] %3d TU) 0x%03x [", r->buf_size, r->timeout, - r->head_seq_num); + seq_printf(s, "([%2d]) 0x%03x [", r->buf_size, r->head_seq_num); for (i = 0; i < r->buf_size; i++) { if (i == index) seq_printf(s, "%c", r->reorder_buf[i] ? 'O' : '|'); diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 82aec6b06d09..e7006c2428a0 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -342,6 +342,8 @@ void wil_disconnect_worker(struct work_struct *work) /* already disconnected */ return; + memset(&reply, 0, sizeof(reply)); + rc = wmi_call(wil, WMI_DISCONNECT_CMDID, vif->mid, NULL, 0, WMI_DISCONNECT_EVENTID, &reply, sizeof(reply), WIL6210_DISCONNECT_TO_MS); diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 05e9408e7ea3..eb6c14ed65a4 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -457,16 +457,16 @@ void wil_vif_remove(struct wil6210_priv *wil, u8 mid) return; } + mutex_lock(&wil->mutex); + wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); + mutex_unlock(&wil->mutex); + ndev = vif_to_ndev(vif); /* during unregister_netdevice cfg80211_leave may perform operations * such as stop AP, disconnect, so we only clear the VIF afterwards */ unregister_netdevice(ndev); - mutex_lock(&wil->mutex); - wil6210_disconnect(vif, NULL, WLAN_REASON_DEAUTH_LEAVING, false); - mutex_unlock(&wil->mutex); - if (any_active && vif->mid != 0) wmi_port_delete(wil, vif->mid); diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index 14dcb0698dee..76f8084c1fd8 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c @@ -206,7 +206,6 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) /* put the frame in the reordering buffer */ r->reorder_buf[index] = skb; - r->reorder_time[index] = jiffies; r->stored_mpdu_num++; wil_reorder_release(ndev, r); @@ -252,11 +251,8 @@ struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil, r->reorder_buf = kcalloc(size, sizeof(struct sk_buff *), GFP_KERNEL); - r->reorder_time = - kcalloc(size, sizeof(unsigned long), GFP_KERNEL); - if (!r->reorder_buf || !r->reorder_time) { + if (!r->reorder_buf) { kfree(r->reorder_buf); - kfree(r->reorder_time); kfree(r); return NULL; } @@ -286,7 +282,6 @@ void wil_tid_ampdu_rx_free(struct wil6210_priv *wil, kfree_skb(r->reorder_buf[i]); kfree(r->reorder_buf); - kfree(r->reorder_time); kfree(r); } diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index b60b9fcaaebd..b9a9fa828961 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -652,8 +652,8 @@ static int wil_rx_refill(struct wil6210_priv *wil, int count) v->swtail = next_tail) { rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom); if (unlikely(rc)) { - wil_err(wil, "Error %d in wil_rx_refill[%d]\n", - rc, v->swtail); + wil_err_ratelimited(wil, "Error %d in rx refill[%d]\n", + rc, v->swtail); break; } } @@ -963,7 +963,9 @@ int wil_vring_init_tx(struct wil6210_vif *vif, int id, int size, struct { struct wmi_cmd_hdr wmi; struct wmi_vring_cfg_done_event cmd; - } __packed reply; + } __packed reply = { + .cmd = {.status = WMI_FW_STATUS_FAILURE}, + }; struct vring *vring = &wil->vring_tx[id]; struct vring_tx_data *txdata = &wil->vring_tx_data[id]; @@ -1045,7 +1047,9 @@ int wil_vring_init_bcast(struct wil6210_vif *vif, int id, int size) struct { struct wmi_cmd_hdr wmi; struct wmi_vring_cfg_done_event cmd; - } __packed reply; + } __packed reply = { + .cmd = {.status = WMI_FW_STATUS_FAILURE}, + }; struct vring *vring = &wil->vring_tx[id]; struct vring_tx_data *txdata = &wil->vring_tx_data[id]; diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index f9c5155025bc..b623510c6f6c 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -493,38 +493,28 @@ struct pci_dev; * struct tid_ampdu_rx - TID aggregation information (Rx). * * @reorder_buf: buffer to reorder incoming aggregated MPDUs - * @reorder_time: jiffies when skb was added - * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) - * @reorder_timer: releases expired frames from the reorder buffer. * @last_rx: jiffies of last rx activity * @head_seq_num: head sequence number in reordering buffer. * @stored_mpdu_num: number of MPDUs in reordering buffer * @ssn: Starting Sequence Number expected to be aggregated. * @buf_size: buffer size for incoming A-MPDUs - * @timeout: reset timer value (in TUs). * @ssn_last_drop: SSN of the last dropped frame * @total: total number of processed incoming frames * @drop_dup: duplicate frames dropped for this reorder buffer * @drop_old: old frames dropped for this reorder buffer - * @dialog_token: dialog token for aggregation session * @first_time: true when this buffer used 1-st time */ struct wil_tid_ampdu_rx { struct sk_buff **reorder_buf; - unsigned long *reorder_time; - struct timer_list session_timer; - struct timer_list reorder_timer; unsigned long last_rx; u16 head_seq_num; u16 stored_mpdu_num; u16 ssn; u16 buf_size; - u16 timeout; u16 ssn_last_drop; unsigned long long total; /* frames processed */ unsigned long long drop_dup; unsigned long long drop_old; - u8 dialog_token; bool first_time; /* is it 1-st time this buffer used? */ }; @@ -986,7 +976,7 @@ int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, int wmi_send(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len); void wmi_recv_cmd(struct wil6210_priv *wil); int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len, - u16 reply_id, void *reply, u8 reply_size, int to_msec); + u16 reply_id, void *reply, u16 reply_size, int to_msec); void wmi_event_worker(struct work_struct *work); void wmi_event_flush(struct wil6210_priv *wil); int wmi_set_ssid(struct wil6210_vif *vif, u8 ssid_len, const void *ssid); @@ -1150,5 +1140,6 @@ void wil6210_clear_halp(struct wil6210_priv *wil); int wmi_start_sched_scan(struct wil6210_priv *wil, struct cfg80211_sched_scan_request *request); int wmi_stop_sched_scan(struct wil6210_priv *wil); +int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len); #endif /* __WIL6210_H__ */ diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 90de9a916241..5d991243cdb5 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1423,7 +1423,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) } int wmi_call(struct wil6210_priv *wil, u16 cmdid, u8 mid, void *buf, u16 len, - u16 reply_id, void *reply, u8 reply_size, int to_msec) + u16 reply_id, void *reply, u16 reply_size, int to_msec) { int rc; unsigned long remain; @@ -1516,7 +1516,9 @@ int wmi_led_cfg(struct wil6210_priv *wil, bool enable) struct { struct wmi_cmd_hdr wmi; struct wmi_led_cfg_done_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = cpu_to_le32(WMI_FW_STATUS_FAILURE)}, + }; if (led_id == WIL_LED_INVALID_ID) goto out; @@ -1561,13 +1563,17 @@ int wmi_pcp_start(struct wil6210_vif *vif, .pcp_max_assoc_sta = max_assoc_sta, .hidden_ssid = hidden_ssid, .is_go = is_go, - .disable_ap_sme = disable_ap_sme, + .ap_sme_offload_mode = disable_ap_sme ? + WMI_AP_SME_OFFLOAD_PARTIAL : + WMI_AP_SME_OFFLOAD_FULL, .abft_len = wil->abft_len, }; struct { struct wmi_cmd_hdr wmi; struct wmi_pcp_started_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; if (!vif->privacy) cmd.disable_sec = 1; @@ -1581,7 +1587,7 @@ int wmi_pcp_start(struct wil6210_vif *vif, } if (disable_ap_sme && - !test_bit(WMI_FW_CAPABILITY_DISABLE_AP_SME, + !test_bit(WMI_FW_CAPABILITY_AP_SME_OFFLOAD_PARTIAL, wil->fw_capabilities)) { wil_err(wil, "disable_ap_sme not supported by FW\n"); return -EOPNOTSUPP; @@ -1644,6 +1650,8 @@ int wmi_get_ssid(struct wil6210_vif *vif, u8 *ssid_len, void *ssid) } __packed reply; int len; /* reply.cmd.ssid_len in CPU order */ + memset(&reply, 0, sizeof(reply)); + rc = wmi_call(wil, WMI_GET_SSID_CMDID, vif->mid, NULL, 0, WMI_GET_SSID_EVENTID, &reply, sizeof(reply), 20); if (rc) @@ -1679,6 +1687,8 @@ int wmi_get_channel(struct wil6210_priv *wil, int *channel) struct wmi_set_pcp_channel_cmd cmd; } __packed reply; + memset(&reply, 0, sizeof(reply)); + rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, vif->mid, NULL, 0, WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20); if (rc) @@ -1704,7 +1714,9 @@ int wmi_p2p_cfg(struct wil6210_vif *vif, int channel, int bi) struct { struct wmi_cmd_hdr wmi; struct wmi_p2p_cfg_done_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; wil_dbg_wmi(wil, "sending WMI_P2P_CFG_CMDID\n"); @@ -1725,7 +1737,9 @@ int wmi_start_listen(struct wil6210_vif *vif) struct { struct wmi_cmd_hdr wmi; struct wmi_listen_started_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; wil_dbg_wmi(wil, "sending WMI_START_LISTEN_CMDID\n"); @@ -1747,7 +1761,9 @@ int wmi_start_search(struct wil6210_vif *vif) struct { struct wmi_cmd_hdr wmi; struct wmi_search_started_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; wil_dbg_wmi(wil, "sending WMI_START_SEARCH_CMDID\n"); @@ -1873,7 +1889,9 @@ int wmi_rxon(struct wil6210_priv *wil, bool on) struct { struct wmi_cmd_hdr wmi; struct wmi_listen_started_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; wil_info(wil, "(%s)\n", on ? "on" : "off"); @@ -1915,6 +1933,8 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) } __packed evt; int rc; + memset(&evt, 0, sizeof(evt)); + if (wdev->iftype == NL80211_IFTYPE_MONITOR) { struct ieee80211_channel *ch = wil->monitor_chandef.chan; @@ -1944,14 +1964,14 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) if (rc) return rc; + if (le32_to_cpu(evt.evt.status) != WMI_CFG_RX_CHAIN_SUCCESS) + rc = -EINVAL; + vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr); wil_dbg_misc(wil, "Rx init: status %d tail 0x%08x\n", le32_to_cpu(evt.evt.status), vring->hwtail); - if (le32_to_cpu(evt.evt.status) != WMI_CFG_RX_CHAIN_SUCCESS) - rc = -EINVAL; - return rc; } @@ -1969,6 +1989,8 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) struct wmi_temp_sense_done_event evt; } __packed reply; + memset(&reply, 0, sizeof(reply)); + rc = wmi_call(wil, WMI_TEMP_SENSE_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_TEMP_SENSE_DONE_EVENTID, &reply, sizeof(reply), 100); if (rc) @@ -2001,6 +2023,7 @@ int wmi_disconnect_sta(struct wil6210_vif *vif, const u8 *mac, wil_dbg_wmi(wil, "disconnect_sta: (%pM, reason %d)\n", mac, reason); + memset(&reply, 0, sizeof(reply)); vif->locally_generated_disc = true; if (del_sta) { ether_addr_copy(del_sta_cmd.dst_mac, mac); @@ -2099,7 +2122,9 @@ int wmi_addba_rx_resp(struct wil6210_priv *wil, struct { struct wmi_cmd_hdr wmi; struct wmi_rcp_addba_resp_sent_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = cpu_to_le16(WMI_FW_STATUS_FAILURE)}, + }; wil_dbg_wmi(wil, "ADDBA response for MID %d CID %d TID %d size %d timeout %d status %d AMSDU%s\n", @@ -2132,13 +2157,13 @@ int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, struct { struct wmi_cmd_hdr wmi; struct wmi_ps_dev_profile_cfg_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR)}, + }; u32 status; wil_dbg_wmi(wil, "Setting ps dev profile %d\n", ps_profile); - reply.evt.status = cpu_to_le32(WMI_PS_CFG_CMD_STATUS_ERROR); - rc = wmi_call(wil, WMI_PS_DEV_PROFILE_CFG_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_PS_DEV_PROFILE_CFG_EVENTID, &reply, sizeof(reply), @@ -2167,15 +2192,15 @@ int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short) struct { struct wmi_cmd_hdr wmi; struct wmi_set_mgmt_retry_limit_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; wil_dbg_wmi(wil, "Setting mgmt retry short %d\n", retry_short); if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities)) return -ENOTSUPP; - reply.evt.status = WMI_FW_STATUS_FAILURE; - rc = wmi_call(wil, WMI_SET_MGMT_RETRY_LIMIT_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_SET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply), @@ -2206,7 +2231,7 @@ int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short) if (!test_bit(WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT, wil->fw_capabilities)) return -ENOTSUPP; - reply.evt.mgmt_retry_limit = 0; + memset(&reply, 0, sizeof(reply)); rc = wmi_call(wil, WMI_GET_MGMT_RETRY_LIMIT_CMDID, vif->mid, NULL, 0, WMI_GET_MGMT_RETRY_LIMIT_EVENTID, &reply, sizeof(reply), 100); @@ -2289,14 +2314,15 @@ int wmi_suspend(struct wil6210_priv *wil) struct { struct wmi_cmd_hdr wmi; struct wmi_traffic_suspend_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE}, + }; + u32 suspend_to = WIL_WAIT_FOR_SUSPEND_RESUME_COMP; wil->suspend_resp_rcvd = false; wil->suspend_resp_comp = false; - reply.evt.status = WMI_TRAFFIC_SUSPEND_REJECTED_LINK_NOT_IDLE; - rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_TRAFFIC_SUSPEND_EVENTID, &reply, sizeof(reply), @@ -2372,10 +2398,11 @@ int wmi_resume(struct wil6210_priv *wil) struct { struct wmi_cmd_hdr wmi; struct wmi_traffic_resume_event evt; - } __packed reply; - - reply.evt.status = WMI_TRAFFIC_RESUME_FAILED; - reply.evt.resume_triggers = WMI_RESUME_TRIGGER_UNKNOWN; + } __packed reply = { + .evt = {.status = WMI_TRAFFIC_RESUME_FAILED, + .resume_triggers = + cpu_to_le32(WMI_RESUME_TRIGGER_UNKNOWN)}, + }; rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, vif->mid, NULL, 0, WMI_TRAFFIC_RESUME_EVENTID, &reply, sizeof(reply), @@ -2401,7 +2428,9 @@ int wmi_port_allocate(struct wil6210_priv *wil, u8 mid, struct { struct wmi_cmd_hdr wmi; struct wmi_port_allocated_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; wil_dbg_misc(wil, "port allocate, mid %d iftype %d, mac %pM\n", mid, iftype, mac); @@ -2426,8 +2455,6 @@ int wmi_port_allocate(struct wil6210_priv *wil, u8 mid, return -EINVAL; } - reply.evt.status = WMI_FW_STATUS_FAILURE; - rc = wmi_call(wil, WMI_PORT_ALLOCATE_CMDID, mid, &cmd, sizeof(cmd), WMI_PORT_ALLOCATED_EVENTID, &reply, @@ -2454,12 +2481,12 @@ int wmi_port_delete(struct wil6210_priv *wil, u8 mid) struct { struct wmi_cmd_hdr wmi; struct wmi_port_deleted_event evt; - } __packed reply; + } __packed reply = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; wil_dbg_misc(wil, "port delete, mid %d\n", mid); - reply.evt.status = WMI_FW_STATUS_FAILURE; - rc = wmi_call(wil, WMI_PORT_DELETE_CMDID, mid, &cmd, sizeof(cmd), WMI_PORT_DELETED_EVENTID, &reply, @@ -2716,7 +2743,9 @@ int wmi_start_sched_scan(struct wil6210_priv *wil, struct { struct wmi_cmd_hdr wmi; struct wmi_start_sched_scan_event evt; - } __packed reply; + } __packed reply = { + .evt = {.result = WMI_PNO_REJECT}, + }; if (!test_bit(WMI_FW_CAPABILITY_PNO, wil->fw_capabilities)) return -ENOTSUPP; @@ -2732,8 +2761,6 @@ int wmi_start_sched_scan(struct wil6210_priv *wil, wmi_sched_scan_set_plans(wil, &cmd, request->scan_plans, request->n_scan_plans); - reply.evt.result = WMI_PNO_REJECT; - rc = wmi_call(wil, WMI_START_SCHED_SCAN_CMDID, vif->mid, &cmd, sizeof(cmd), WMI_START_SCHED_SCAN_EVENTID, &reply, sizeof(reply), @@ -2757,13 +2784,13 @@ int wmi_stop_sched_scan(struct wil6210_priv *wil) struct { struct wmi_cmd_hdr wmi; struct wmi_stop_sched_scan_event evt; - } __packed reply; + } __packed reply = { + .evt = {.result = WMI_PNO_REJECT}, + }; if (!test_bit(WMI_FW_CAPABILITY_PNO, wil->fw_capabilities)) return -ENOTSUPP; - reply.evt.result = WMI_PNO_REJECT; - rc = wmi_call(wil, WMI_STOP_SCHED_SCAN_CMDID, vif->mid, NULL, 0, WMI_STOP_SCHED_SCAN_EVENTID, &reply, sizeof(reply), WIL_WMI_CALL_GENERAL_TO_MS); @@ -2778,3 +2805,50 @@ int wmi_stop_sched_scan(struct wil6210_priv *wil) return 0; } + +int wmi_mgmt_tx(struct wil6210_vif *vif, const u8 *buf, size_t len) +{ + size_t total; + struct wil6210_priv *wil = vif_to_wil(vif); + struct ieee80211_mgmt *mgmt_frame = (void *)buf; + struct wmi_sw_tx_req_cmd *cmd; + struct { + struct wmi_cmd_hdr wmi; + struct wmi_sw_tx_complete_event evt; + } __packed evt = { + .evt = {.status = WMI_FW_STATUS_FAILURE}, + }; + int rc; + + wil_dbg_misc(wil, "mgmt_tx mid %d\n", vif->mid); + wil_hex_dump_misc("mgmt tx frame ", DUMP_PREFIX_OFFSET, 16, 1, buf, + len, true); + + if (len < sizeof(struct ieee80211_hdr_3addr)) + return -EINVAL; + + total = sizeof(*cmd) + len; + if (total < len) { + wil_err(wil, "mgmt_tx invalid len %zu\n", len); + return -EINVAL; + } + + cmd = kmalloc(total, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + memcpy(cmd->dst_mac, mgmt_frame->da, WMI_MAC_LEN); + cmd->len = cpu_to_le16(len); + memcpy(cmd->payload, buf, len); + + rc = wmi_call(wil, WMI_SW_TX_REQ_CMDID, vif->mid, cmd, total, + WMI_SW_TX_COMPLETE_EVENTID, &evt, sizeof(evt), 2000); + if (!rc && evt.evt.status != WMI_FW_STATUS_SUCCESS) { + wil_err(wil, "mgmt_tx failed with status %d\n", evt.evt.status); + rc = -EINVAL; + } + + kfree(cmd); + + return rc; +} diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index d3e75f0ff245..dc503d903786 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2018, The Linux Foundation. All rights reserved. * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * Copyright (c) 2006-2012 Wilocity * @@ -29,8 +30,6 @@ #ifndef __WILOCITY_WMI_H__ #define __WILOCITY_WMI_H__ -/* General */ -#define WMI_MAX_ASSOC_STA (8) #define WMI_DEFAULT_ASSOC_STA (1) #define WMI_MAC_LEN (6) #define WMI_PROX_RANGE_NUM (3) @@ -41,6 +40,19 @@ #define WMI_RF_ETYPE_LENGTH (3) #define WMI_RF_RX2TX_LENGTH (3) #define WMI_RF_ETYPE_VAL_PER_RANGE (5) +/* DTYPE configuration array size + * must always be kept equal to (WMI_RF_DTYPE_LENGTH+1) + */ +#define WMI_RF_DTYPE_CONF_LENGTH (4) +/* ETYPE configuration array size + * must always be kept equal to + * (WMI_RF_ETYPE_LENGTH+WMI_RF_ETYPE_VAL_PER_RANGE) + */ +#define WMI_RF_ETYPE_CONF_LENGTH (8) +/* RX2TX configuration array size + * must always be kept equal to (WMI_RF_RX2TX_LENGTH+1) + */ +#define WMI_RF_RX2TX_CONF_LENGTH (4) /* Mailbox interface * used for commands and events @@ -61,7 +73,7 @@ enum wmi_fw_capability { WMI_FW_CAPABILITY_PS_CONFIG = 1, WMI_FW_CAPABILITY_RF_SECTORS = 2, WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT = 3, - WMI_FW_CAPABILITY_DISABLE_AP_SME = 4, + WMI_FW_CAPABILITY_AP_SME_OFFLOAD_PARTIAL = 4, WMI_FW_CAPABILITY_WMI_ONLY = 5, WMI_FW_CAPABILITY_THERMAL_THROTTLING = 7, WMI_FW_CAPABILITY_D3_SUSPEND = 8, @@ -73,6 +85,7 @@ enum wmi_fw_capability { WMI_FW_CAPABILITY_LO_POWER_CALIB_FROM_OTP = 14, WMI_FW_CAPABILITY_PNO = 15, WMI_FW_CAPABILITY_REF_CLOCK_CONTROL = 18, + WMI_FW_CAPABILITY_AP_SME_OFFLOAD_NONE = 19, WMI_FW_CAPABILITY_MAX, }; @@ -164,12 +177,14 @@ enum wmi_command_id { WMI_SET_ACTIVE_SILENT_RSSI_TABLE_CMDID = 0x85C, WMI_RF_PWR_ON_DELAY_CMDID = 0x85D, WMI_SET_HIGH_POWER_TABLE_PARAMS_CMDID = 0x85E, + WMI_FIXED_SCHEDULING_UL_CONFIG_CMDID = 0x85F, /* Performance monitoring commands */ WMI_BF_CTRL_CMDID = 0x862, WMI_NOTIFY_REQ_CMDID = 0x863, WMI_GET_STATUS_CMDID = 0x864, WMI_GET_RF_STATUS_CMDID = 0x866, WMI_GET_BASEBAND_TYPE_CMDID = 0x867, + WMI_VRING_SWITCH_TIMING_CONFIG_CMDID = 0x868, WMI_UNIT_TEST_CMDID = 0x900, WMI_FLASH_READ_CMDID = 0x902, WMI_FLASH_WRITE_CMDID = 0x903, @@ -202,6 +217,7 @@ enum wmi_command_id { WMI_GET_THERMAL_THROTTLING_CFG_CMDID = 0x941, /* Read Power Save profile type */ WMI_PS_DEV_PROFILE_CFG_READ_CMDID = 0x942, + WMI_TSF_SYNC_CMDID = 0x973, WMI_TOF_SESSION_START_CMDID = 0x991, WMI_TOF_GET_CAPABILITIES_CMDID = 0x992, WMI_TOF_SET_LCR_CMDID = 0x993, @@ -218,11 +234,16 @@ enum wmi_command_id { WMI_PRIO_TX_SECTORS_ORDER_CMDID = 0x9A5, WMI_PRIO_TX_SECTORS_NUMBER_CMDID = 0x9A6, WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_CMDID = 0x9A7, + WMI_BF_CONTROL_CMDID = 0x9AA, WMI_SCHEDULING_SCHEME_CMDID = 0xA01, WMI_FIXED_SCHEDULING_CONFIG_CMDID = 0xA02, WMI_ENABLE_FIXED_SCHEDULING_CMDID = 0xA03, WMI_SET_MULTI_DIRECTED_OMNIS_CONFIG_CMDID = 0xA04, WMI_SET_LONG_RANGE_CONFIG_CMDID = 0xA05, + WMI_GET_ASSOC_LIST_CMDID = 0xA06, + WMI_GET_CCA_INDICATIONS_CMDID = 0xA07, + WMI_SET_CCA_INDICATIONS_BI_AVG_NUM_CMDID = 0xA08, + WMI_INTERNAL_FW_IOCTL_CMDID = 0xA0B, WMI_SET_MAC_ADDRESS_CMDID = 0xF003, WMI_ABORT_SCAN_CMDID = 0xF007, WMI_SET_PROMISCUOUS_MODE_CMDID = 0xF041, @@ -484,6 +505,18 @@ enum wmi_rf_mgmt_type { WMI_RF_MGMT_GET_STATUS = 0x02, }; +/* WMI_BF_CONTROL_CMDID */ +enum wmi_bf_triggers { + WMI_BF_TRIGGER_RS_MCS1_TH_FAILURE = 0x01, + WMI_BF_TRIGGER_RS_MCS1_NO_BACK_FAILURE = 0x02, + WMI_BF_TRIGGER_MAX_CTS_FAILURE_IN_TXOP = 0x04, + WMI_BF_TRIGGER_MAX_BACK_FAILURE = 0x08, + WMI_BF_TRIGGER_FW = 0x10, + WMI_BF_TRIGGER_MAX_CTS_FAILURE_IN_KEEP_ALIVE = 0x20, + WMI_BF_TRIGGER_AOA = 0x40, + WMI_BF_TRIGGER_MAX_CTS_FAILURE_IN_UPM = 0x80, +}; + /* WMI_RF_MGMT_CMDID */ struct wmi_rf_mgmt_cmd { __le32 rf_mgmt_type; @@ -519,7 +552,9 @@ struct wmi_bcon_ctrl_cmd { u8 disable_sec; u8 hidden_ssid; u8 is_go; - u8 reserved[2]; + /* A-BFT length override if non-0 */ + u8 abft_len; + u8 reserved; } __packed; /* WMI_PORT_ALLOCATE_CMDID */ @@ -585,6 +620,16 @@ struct wmi_power_mgmt_cfg_cmd { } __packed; /* WMI_PCP_START_CMDID */ +enum wmi_ap_sme_offload_mode { + /* Full AP SME in FW */ + WMI_AP_SME_OFFLOAD_FULL = 0x00, + /* Probe AP SME in FW */ + WMI_AP_SME_OFFLOAD_PARTIAL = 0x01, + /* AP SME in host */ + WMI_AP_SME_OFFLOAD_NONE = 0x02, +}; + +/* WMI_PCP_START_CMDID */ struct wmi_pcp_start_cmd { __le16 bcon_interval; u8 pcp_max_assoc_sta; @@ -593,7 +638,8 @@ struct wmi_pcp_start_cmd { u8 reserved0[5]; /* A-BFT length override if non-0 */ u8 abft_len; - u8 disable_ap_sme; + /* enum wmi_ap_sme_offload_mode_e */ + u8 ap_sme_offload_mode; u8 network_type; u8 channel; u8 disable_sec_offload; @@ -607,6 +653,17 @@ struct wmi_sw_tx_req_cmd { u8 payload[0]; } __packed; +/* WMI_VRING_SWITCH_TIMING_CONFIG_CMDID */ +struct wmi_vring_switch_timing_config_cmd { + /* Set vring timing configuration: + * + * defined interval for vring switch + */ + __le32 interval_usec; + /* vring inactivity threshold */ + __le32 idle_th_usec; +} __packed; + struct wmi_sw_ring_cfg { __le64 ring_mem_base; __le16 ring_size; @@ -642,6 +699,7 @@ enum wmi_vring_cfg_schd_params_priority { WMI_SCH_PRIO_HIGH = 0x01, }; +#define CIDXTID_EXTENDED_CID_TID (0xFF) #define CIDXTID_CID_POS (0) #define CIDXTID_CID_LEN (4) #define CIDXTID_CID_MSK (0xF) @@ -662,6 +720,9 @@ struct wmi_vring_cfg { struct wmi_sw_ring_cfg tx_sw_ring; /* 0-23 vrings */ u8 ringid; + /* Used for cid less than 8. For higher cid set + * CIDXTID_EXTENDED_CID_TID here and use cid and tid members instead + */ u8 cidxtid; u8 encap_trans_type; /* 802.3 DS cfg */ @@ -671,6 +732,11 @@ struct wmi_vring_cfg { u8 to_resolution; u8 agg_max_wsize; struct wmi_vring_cfg_schd schd_params; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 cid; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 tid; + u8 reserved[2]; } __packed; enum wmi_vring_cfg_cmd_action { @@ -868,23 +934,42 @@ struct wmi_cfg_rx_chain_cmd { /* WMI_RCP_ADDBA_RESP_CMDID */ struct wmi_rcp_addba_resp_cmd { + /* Used for cid less than 8. For higher cid set + * CIDXTID_EXTENDED_CID_TID here and use cid and tid members instead + */ u8 cidxtid; u8 dialog_token; __le16 status_code; /* ieee80211_ba_parameterset field to send */ __le16 ba_param_set; __le16 ba_timeout; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 cid; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 tid; + u8 reserved[2]; } __packed; /* WMI_RCP_DELBA_CMDID */ struct wmi_rcp_delba_cmd { + /* Used for cid less than 8. For higher cid set + * CIDXTID_EXTENDED_CID_TID here and use cid and tid members instead + */ u8 cidxtid; u8 reserved; __le16 reason; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 cid; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 tid; + u8 reserved2[2]; } __packed; /* WMI_RCP_ADDBA_REQ_CMDID */ struct wmi_rcp_addba_req_cmd { + /* Used for cid less than 8. For higher cid set + * CIDXTID_EXTENDED_CID_TID here and use cid and tid members instead + */ u8 cidxtid; u8 dialog_token; /* ieee80211_ba_parameterset field as it received */ @@ -892,6 +977,11 @@ struct wmi_rcp_addba_req_cmd { __le16 ba_timeout; /* ieee80211_ba_seqstrl field as it received */ __le16 ba_seq_ctrl; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 cid; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 tid; + u8 reserved[2]; } __packed; /* WMI_SET_MAC_ADDRESS_CMDID */ @@ -902,15 +992,20 @@ struct wmi_set_mac_address_cmd { /* WMI_ECHO_CMDID * Check FW is alive - * WMI_DEEP_ECHO_CMDID - * Check FW and ucode are alive * Returned event: WMI_ECHO_RSP_EVENTID - * same event for both commands */ struct wmi_echo_cmd { __le32 value; } __packed; +/* WMI_DEEP_ECHO_CMDID + * Check FW and ucode are alive + * Returned event: WMI_ECHO_RSP_EVENTID + */ +struct wmi_deep_echo_cmd { + __le32 value; +} __packed; + /* WMI_RF_PWR_ON_DELAY_CMDID * set FW time parameters used through RF resetting * RF reset consists of bringing its power down for a period of time, then @@ -928,7 +1023,7 @@ struct wmi_rf_pwr_on_delay_cmd { __le16 up_delay_usec; } __packed; -/* \WMI_SET_HIGH_POWER_TABLE_PARAMS_CMDID +/* WMI_SET_HIGH_POWER_TABLE_PARAMS_CMDID * This API controls the Tx and Rx gain over temperature. * It controls the Tx D-type, Rx D-type and Rx E-type amplifiers. * It also controls the Tx gain index, by controlling the Rx to Tx gain index @@ -942,25 +1037,46 @@ struct wmi_set_high_power_table_params_cmd { u8 tx_dtype_temp[WMI_RF_DTYPE_LENGTH]; u8 reserved0; /* Tx D-type values to be used for each temperature range */ - __le32 tx_dtype_conf[WMI_RF_DTYPE_LENGTH + 1]; + __le32 tx_dtype_conf[WMI_RF_DTYPE_CONF_LENGTH]; + /* Temperature range for Tx E-type parameters */ + u8 tx_etype_temp[WMI_RF_ETYPE_LENGTH]; + u8 reserved1; + /* Tx E-type values to be used for each temperature range. + * The last 4 values of any range are the first 4 values of the next + * range and so on + */ + __le32 tx_etype_conf[WMI_RF_ETYPE_CONF_LENGTH]; /* Temperature range for Rx D-type parameters */ u8 rx_dtype_temp[WMI_RF_DTYPE_LENGTH]; - u8 reserved1; + u8 reserved2; /* Rx D-type values to be used for each temperature range */ - __le32 rx_dtype_conf[WMI_RF_DTYPE_LENGTH + 1]; + __le32 rx_dtype_conf[WMI_RF_DTYPE_CONF_LENGTH]; /* Temperature range for Rx E-type parameters */ u8 rx_etype_temp[WMI_RF_ETYPE_LENGTH]; - u8 reserved2; + u8 reserved3; /* Rx E-type values to be used for each temperature range. * The last 4 values of any range are the first 4 values of the next * range and so on */ - __le32 rx_etype_conf[WMI_RF_ETYPE_VAL_PER_RANGE + WMI_RF_ETYPE_LENGTH]; + __le32 rx_etype_conf[WMI_RF_ETYPE_CONF_LENGTH]; /* Temperature range for rx_2_tx_offs parameters */ u8 rx_2_tx_temp[WMI_RF_RX2TX_LENGTH]; - u8 reserved3; + u8 reserved4; /* Rx to Tx gain index offset */ - s8 rx_2_tx_offs[WMI_RF_RX2TX_LENGTH + 1]; + s8 rx_2_tx_offs[WMI_RF_RX2TX_CONF_LENGTH]; +} __packed; + +/* WMI_FIXED_SCHEDULING_UL_CONFIG_CMDID + * This API sets rd parameter per mcs. + * Relevant only in Fixed Scheduling mode. + * Returned event: WMI_FIXED_SCHEDULING_UL_CONFIG_EVENTID + */ +struct wmi_fixed_scheduling_ul_config_cmd { + /* Use mcs -1 to set for every mcs */ + s8 mcs; + /* Number of frames with rd bit set in a single virtual slot */ + u8 rd_count_per_slot; + u8 reserved[2]; } __packed; /* CMD: WMI_RF_XPM_READ_CMDID */ @@ -1267,6 +1383,93 @@ struct wmi_set_long_range_config_complete_event { u8 reserved[3]; } __packed; +/* payload max size is 236 bytes: max event buffer size (256) - WMI headers + * (16) - prev struct field size (4) + */ +#define WMI_MAX_IOCTL_PAYLOAD_SIZE (236) +#define WMI_MAX_IOCTL_REPLY_PAYLOAD_SIZE (236) +#define WMI_MAX_INTERNAL_EVENT_PAYLOAD_SIZE (236) + +enum wmi_internal_fw_ioctl_code { + WMI_INTERNAL_FW_CODE_NONE = 0x0, + WMI_INTERNAL_FW_CODE_QCOM = 0x1, +}; + +/* WMI_INTERNAL_FW_IOCTL_CMDID */ +struct wmi_internal_fw_ioctl_cmd { + /* enum wmi_internal_fw_ioctl_code */ + __le16 code; + __le16 length; + /* payload max size is WMI_MAX_IOCTL_PAYLOAD_SIZE + * Must be the last member of the struct + */ + __le32 payload[0]; +} __packed; + +/* WMI_INTERNAL_FW_IOCTL_EVENTID */ +struct wmi_internal_fw_ioctl_event { + /* wmi_fw_status */ + u8 status; + u8 reserved; + __le16 length; + /* payload max size is WMI_MAX_IOCTL_REPLY_PAYLOAD_SIZE + * Must be the last member of the struct + */ + __le32 payload[0]; +} __packed; + +/* WMI_INTERNAL_FW_EVENT_EVENTID */ +struct wmi_internal_fw_event_event { + __le16 id; + __le16 length; + /* payload max size is WMI_MAX_INTERNAL_EVENT_PAYLOAD_SIZE + * Must be the last member of the struct + */ + __le32 payload[0]; +} __packed; + +/* WMI_BF_CONTROL_CMDID */ +struct wmi_bf_control_cmd { + /* wmi_bf_triggers */ + __le32 triggers; + u8 cid; + /* DISABLED = 0, ENABLED = 1 , DRY_RUN = 2 */ + u8 txss_mode; + /* DISABLED = 0, ENABLED = 1, DRY_RUN = 2 */ + u8 brp_mode; + /* Max cts threshold (correspond to + * WMI_BF_TRIGGER_MAX_CTS_FAILURE_IN_TXOP) + */ + u8 bf_trigger_max_cts_failure_thr; + /* Max cts threshold in dense (correspond to + * WMI_BF_TRIGGER_MAX_CTS_FAILURE_IN_TXOP) + */ + u8 bf_trigger_max_cts_failure_dense_thr; + /* Max b-ack threshold (correspond to + * WMI_BF_TRIGGER_MAX_BACK_FAILURE) + */ + u8 bf_trigger_max_back_failure_thr; + /* Max b-ack threshold in dense (correspond to + * WMI_BF_TRIGGER_MAX_BACK_FAILURE) + */ + u8 bf_trigger_max_back_failure_dense_thr; + u8 reserved0; + /* Wrong sectors threshold */ + __le32 wrong_sector_bis_thr; + /* BOOL to enable/disable long term trigger */ + u8 long_term_enable; + /* 1 = Update long term thresholds from the long_term_mbps_th_tbl and + * long_term_trig_timeout_per_mcs arrays, 0 = Ignore + */ + u8 long_term_update_thr; + /* Long term throughput threshold [Mbps] */ + u8 long_term_mbps_th_tbl[WMI_NUM_MCS]; + u8 reserved1; + /* Long term timeout threshold table [msec] */ + __le16 long_term_trig_timeout_per_mcs[WMI_NUM_MCS]; + u8 reserved2[2]; +} __packed; + /* WMI Events * List of Events (target to host) */ @@ -1325,6 +1528,7 @@ enum wmi_event_id { WMI_SET_SILENT_RSSI_TABLE_DONE_EVENTID = 0x185C, WMI_RF_PWR_ON_DELAY_RSP_EVENTID = 0x185D, WMI_SET_HIGH_POWER_TABLE_PARAMS_EVENTID = 0x185E, + WMI_FIXED_SCHEDULING_UL_CONFIG_EVENTID = 0x185F, /* Performance monitoring events */ WMI_DATA_PORT_OPEN_EVENTID = 0x1860, WMI_WBE_LINK_DOWN_EVENTID = 0x1861, @@ -1334,6 +1538,7 @@ enum wmi_event_id { WMI_VRING_EN_EVENTID = 0x1865, WMI_GET_RF_STATUS_EVENTID = 0x1866, WMI_GET_BASEBAND_TYPE_EVENTID = 0x1867, + WMI_VRING_SWITCH_TIMING_CONFIG_EVENTID = 0x1868, WMI_UNIT_TEST_EVENTID = 0x1900, WMI_FLASH_READ_DONE_EVENTID = 0x1902, WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, @@ -1363,6 +1568,7 @@ enum wmi_event_id { WMI_GET_THERMAL_THROTTLING_CFG_EVENTID = 0x1941, /* return the Power Save profile */ WMI_PS_DEV_PROFILE_CFG_READ_EVENTID = 0x1942, + WMI_TSF_SYNC_STATUS_EVENTID = 0x1973, WMI_TOF_SESSION_END_EVENTID = 0x1991, WMI_TOF_GET_CAPABILITIES_EVENTID = 0x1992, WMI_TOF_SET_LCR_EVENTID = 0x1993, @@ -1380,17 +1586,24 @@ enum wmi_event_id { WMI_PRIO_TX_SECTORS_ORDER_EVENTID = 0x19A5, WMI_PRIO_TX_SECTORS_NUMBER_EVENTID = 0x19A6, WMI_PRIO_TX_SECTORS_SET_DEFAULT_CFG_EVENTID = 0x19A7, + WMI_BF_CONTROL_EVENTID = 0x19AA, WMI_SCHEDULING_SCHEME_EVENTID = 0x1A01, WMI_FIXED_SCHEDULING_CONFIG_COMPLETE_EVENTID = 0x1A02, WMI_ENABLE_FIXED_SCHEDULING_COMPLETE_EVENTID = 0x1A03, WMI_SET_MULTI_DIRECTED_OMNIS_CONFIG_EVENTID = 0x1A04, WMI_SET_LONG_RANGE_CONFIG_COMPLETE_EVENTID = 0x1A05, + WMI_GET_ASSOC_LIST_RES_EVENTID = 0x1A06, + WMI_GET_CCA_INDICATIONS_EVENTID = 0x1A07, + WMI_SET_CCA_INDICATIONS_BI_AVG_NUM_EVENTID = 0x1A08, + WMI_INTERNAL_FW_EVENT_EVENTID = 0x1A0A, + WMI_INTERNAL_FW_IOCTL_EVENTID = 0x1A0B, WMI_SET_CHANNEL_EVENTID = 0x9000, WMI_ASSOC_REQ_EVENTID = 0x9001, WMI_EAPOL_RX_EVENTID = 0x9002, WMI_MAC_ADDR_RESP_EVENTID = 0x9003, WMI_FW_VER_EVENTID = 0x9004, WMI_ACS_PASSIVE_SCAN_COMPLETE_EVENTID = 0x9005, + WMI_INTERNAL_FW_SET_CHANNEL = 0x9006, WMI_COMMAND_NOT_SUPPORTED_EVENTID = 0xFFFF, }; @@ -1462,12 +1675,16 @@ enum rf_type { RF_UNKNOWN = 0x00, RF_MARLON = 0x01, RF_SPARROW = 0x02, + RF_TALYNA1 = 0x03, + RF_TALYNA2 = 0x04, }; /* WMI_GET_RF_STATUS_EVENTID */ enum board_file_rf_type { BF_RF_MARLON = 0x00, BF_RF_SPARROW = 0x01, + BF_RF_TALYNA1 = 0x02, + BF_RF_TALYNA2 = 0x03, }; /* WMI_GET_RF_STATUS_EVENTID */ @@ -1507,6 +1724,7 @@ enum baseband_type { BASEBAND_SPARROW_M_C0 = 0x06, BASEBAND_SPARROW_M_D0 = 0x07, BASEBAND_TALYN_M_A0 = 0x08, + BASEBAND_TALYN_M_B0 = 0x09, }; /* WMI_GET_BASEBAND_TYPE_EVENTID */ @@ -1551,7 +1769,11 @@ struct wmi_ready_event { u8 numof_additional_mids; /* rfc read calibration result. 5..15 */ u8 rfc_read_calib_result; - u8 reserved[3]; + /* Max associated STAs supported by FW in AP mode (default 0 means 8 + * STA) + */ + u8 max_assoc_sta; + u8 reserved[2]; } __packed; /* WMI_NOTIFY_REQ_DONE_EVENTID */ @@ -1666,13 +1888,13 @@ enum wmi_pno_result { }; struct wmi_start_sched_scan_event { - /* pno_result */ + /* wmi_pno_result */ u8 result; u8 reserved[3]; } __packed; struct wmi_stop_sched_scan_event { - /* pno_result */ + /* wmi_pno_result */ u8 result; u8 reserved[3]; } __packed; @@ -1739,9 +1961,17 @@ struct wmi_ba_status_event { /* WMI_DELBA_EVENTID */ struct wmi_delba_event { + /* Used for cid less than 8. For higher cid set + * CIDXTID_EXTENDED_CID_TID here and use cid and tid members instead + */ u8 cidxtid; u8 from_initiator; __le16 reason; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 cid; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 tid; + u8 reserved[2]; } __packed; /* WMI_VRING_CFG_DONE_EVENTID */ @@ -1754,13 +1984,24 @@ struct wmi_vring_cfg_done_event { /* WMI_RCP_ADDBA_RESP_SENT_EVENTID */ struct wmi_rcp_addba_resp_sent_event { + /* Used for cid less than 8. For higher cid set + * CIDXTID_EXTENDED_CID_TID here and use cid and tid members instead + */ u8 cidxtid; u8 reserved; __le16 status; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 cid; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 tid; + u8 reserved2[2]; } __packed; /* WMI_RCP_ADDBA_REQ_EVENTID */ struct wmi_rcp_addba_req_event { + /* Used for cid less than 8. For higher cid set + * CIDXTID_EXTENDED_CID_TID here and use cid and tid members instead + */ u8 cidxtid; u8 dialog_token; /* ieee80211_ba_parameterset as it received */ @@ -1768,6 +2009,11 @@ struct wmi_rcp_addba_req_event { __le16 ba_timeout; /* ieee80211_ba_seqstrl field as it received */ __le16 ba_seq_ctrl; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 cid; + /* Used when cidxtid = CIDXTID_EXTENDED_CID_TID */ + u8 tid; + u8 reserved[2]; } __packed; /* WMI_CFG_RX_CHAIN_DONE_EVENTID */ @@ -1942,6 +2188,13 @@ struct wmi_set_high_power_table_params_event { u8 reserved[3]; } __packed; +/* WMI_FIXED_SCHEDULING_UL_CONFIG_EVENTID */ +struct wmi_fixed_scheduling_ul_config_event { + /* wmi_fw_status */ + u8 status; + u8 reserved[3]; +} __packed; + /* WMI_TEMP_SENSE_DONE_EVENTID * * Measure MAC and radio temperatures @@ -2290,6 +2543,8 @@ struct wmi_link_maintain_cfg { __le32 bad_beacons_num_threshold; /* SNR limit for bad_beacons_detector */ __le32 bad_beacons_snr_threshold_db; + /* timeout for disassoc response frame in uSec */ + __le32 disconnect_timeout; } __packed; /* WMI_LINK_MAINTAIN_CFG_WRITE_CMDID */ @@ -2519,6 +2774,7 @@ enum wmi_tof_session_end_status { WMI_TOF_SESSION_END_FAIL = 0x01, WMI_TOF_SESSION_END_PARAMS_ERROR = 0x02, WMI_TOF_SESSION_END_ABORTED = 0x03, + WMI_TOF_SESSION_END_BUSY = 0x04, }; /* WMI_TOF_SESSION_END_EVENTID */ @@ -2925,7 +3181,40 @@ struct wmi_set_silent_rssi_table_done_event { __le32 table; } __packed; -/* \WMI_COMMAND_NOT_SUPPORTED_EVENTID */ +/* WMI_VRING_SWITCH_TIMING_CONFIG_EVENTID */ +struct wmi_vring_switch_timing_config_event { + /* enum wmi_fw_status */ + u8 status; + u8 reserved[3]; +} __packed; + +/* WMI_GET_ASSOC_LIST_RES_EVENTID */ +struct wmi_assoc_sta_info { + u8 mac[WMI_MAC_LEN]; + u8 omni_index_address; + u8 reserved; +} __packed; + +#define WMI_GET_ASSOC_LIST_SIZE (8) + +/* WMI_GET_ASSOC_LIST_RES_EVENTID + * Returns up to MAX_ASSOC_STA_LIST_SIZE associated STAs + */ +struct wmi_get_assoc_list_res_event { + struct wmi_assoc_sta_info assoc_sta_list[WMI_GET_ASSOC_LIST_SIZE]; + /* STA count */ + u8 count; + u8 reserved[3]; +} __packed; + +/* WMI_BF_CONTROL_EVENTID */ +struct wmi_bf_control_event { + /* wmi_fw_status */ + u8 status; + u8 reserved[3]; +} __packed; + +/* WMI_COMMAND_NOT_SUPPORTED_EVENTID */ struct wmi_command_not_supported_event { /* device id */ u8 mid; @@ -2936,4 +3225,62 @@ struct wmi_command_not_supported_event { __le16 reserved1; } __packed; +/* WMI_TSF_SYNC_CMDID */ +struct wmi_tsf_sync_cmd { + /* The time interval to send announce frame in one BI */ + u8 interval_ms; + /* The mcs to send announce frame */ + u8 mcs; + u8 reserved[6]; +} __packed; + +/* WMI_TSF_SYNC_STATUS_EVENTID */ +enum wmi_tsf_sync_status { + WMI_TSF_SYNC_SUCCESS = 0x00, + WMI_TSF_SYNC_FAILED = 0x01, + WMI_TSF_SYNC_REJECTED = 0x02, +}; + +/* WMI_TSF_SYNC_STATUS_EVENTID */ +struct wmi_tsf_sync_status_event { + /* enum wmi_tsf_sync_status */ + u8 status; + u8 reserved[3]; +} __packed; + +/* WMI_GET_CCA_INDICATIONS_EVENTID */ +struct wmi_get_cca_indications_event { + /* wmi_fw_status */ + u8 status; + /* CCA-Energy Detect in percentage over last BI (0..100) */ + u8 cca_ed_percent; + /* Averaged CCA-Energy Detect in percent over number of BIs (0..100) */ + u8 cca_ed_avg_percent; + /* NAV percent over last BI (0..100) */ + u8 nav_percent; + /* Averaged NAV percent over number of BIs (0..100) */ + u8 nav_avg_percent; + u8 reserved[3]; +} __packed; + +/* WMI_SET_CCA_INDICATIONS_BI_AVG_NUM_CMDID */ +struct wmi_set_cca_indications_bi_avg_num_cmd { + /* set the number of bis to average cca_ed (0..255) */ + u8 bi_number; + u8 reserved[3]; +} __packed; + +/* WMI_SET_CCA_INDICATIONS_BI_AVG_NUM_EVENTID */ +struct wmi_set_cca_indications_bi_avg_num_event { + /* wmi_fw_status */ + u8 status; + u8 reserved[3]; +} __packed; + +/* WMI_INTERNAL_FW_SET_CHANNEL */ +struct wmi_internal_fw_set_channel_event { + u8 channel_num; + u8 reserved[3]; +} __packed; + #endif /* __WILOCITY_WMI_H__ */ |