mirror of https://gitee.com/openkylin/linux.git
Merge ath-next from ath.git
Major changes: ath10k * support Manegement Frame Protection (MFP) * add thermal throttling support for 10.4 firmware * add support for pktlog in QCA99X0 * add debugfs file to enable Bluetooth coexistence feature * use firmware's native mesh interface type instead of raw mode
This commit is contained in:
commit
f1b4b51184
|
@ -2,6 +2,7 @@ config ATH10K
|
|||
tristate "Atheros 802.11ac wireless cards support"
|
||||
depends on MAC80211 && HAS_DMA
|
||||
select ATH_COMMON
|
||||
select CRC32
|
||||
---help---
|
||||
This module adds support for wireless adapters based on
|
||||
Atheros IEEE 802.11ac family of chipsets.
|
||||
|
|
|
@ -58,6 +58,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.otp_exe_param = 0,
|
||||
.channel_counters_freq_hz = 88000,
|
||||
.max_probe_resp_desc_thres = 0,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
|
||||
.fw = {
|
||||
.dir = QCA988X_HW_2_0_FW_DIR,
|
||||
.fw = QCA988X_HW_2_0_FW_FILE,
|
||||
|
@ -75,6 +76,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.otp_exe_param = 0,
|
||||
.channel_counters_freq_hz = 88000,
|
||||
.max_probe_resp_desc_thres = 0,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
|
||||
.fw = {
|
||||
.dir = QCA6174_HW_2_1_FW_DIR,
|
||||
.fw = QCA6174_HW_2_1_FW_FILE,
|
||||
|
@ -92,6 +94,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.otp_exe_param = 0,
|
||||
.channel_counters_freq_hz = 88000,
|
||||
.max_probe_resp_desc_thres = 0,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
|
||||
.fw = {
|
||||
.dir = QCA6174_HW_3_0_FW_DIR,
|
||||
.fw = QCA6174_HW_3_0_FW_FILE,
|
||||
|
@ -109,6 +112,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.otp_exe_param = 0,
|
||||
.channel_counters_freq_hz = 88000,
|
||||
.max_probe_resp_desc_thres = 0,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
|
||||
.fw = {
|
||||
/* uses same binaries as hw3.0 */
|
||||
.dir = QCA6174_HW_3_0_FW_DIR,
|
||||
|
@ -128,6 +132,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
|||
.continuous_frag_desc = true,
|
||||
.channel_counters_freq_hz = 150000,
|
||||
.max_probe_resp_desc_thres = 24,
|
||||
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
|
||||
.fw = {
|
||||
.dir = QCA99X0_HW_2_0_FW_DIR,
|
||||
.fw = QCA99X0_HW_2_0_FW_FILE,
|
||||
|
@ -167,6 +172,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
|
|||
[ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init",
|
||||
[ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode",
|
||||
[ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca",
|
||||
[ATH10K_FW_FEATURE_MFP_SUPPORT] = "mfp",
|
||||
};
|
||||
|
||||
static unsigned int ath10k_core_get_fw_feature_str(char *buf,
|
||||
|
@ -843,7 +849,7 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
|
|||
if (!ar->board_data || !ar->board_len) {
|
||||
ath10k_err(ar,
|
||||
"failed to fetch board data for %s from %s/%s\n",
|
||||
ar->hw_params.fw.dir, boardname, filename);
|
||||
boardname, ar->hw_params.fw.dir, filename);
|
||||
ret = -ENODATA;
|
||||
goto err;
|
||||
}
|
||||
|
@ -1745,9 +1751,11 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
|
|||
goto err_power_down;
|
||||
}
|
||||
|
||||
ath10k_debug_print_hwfw_info(ar);
|
||||
|
||||
ret = ath10k_core_get_board_id_from_otp(ar);
|
||||
if (ret && ret != -EOPNOTSUPP) {
|
||||
ath10k_err(ar, "failed to get board id from otp for qca99x0: %d\n",
|
||||
ath10k_err(ar, "failed to get board id from otp: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1758,6 +1766,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
|
|||
goto err_free_firmware_files;
|
||||
}
|
||||
|
||||
ath10k_debug_print_board_info(ar);
|
||||
|
||||
ret = ath10k_core_init_firmware_features(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "fatal problem with firmware features: %d\n",
|
||||
|
@ -1780,7 +1790,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
|
|||
goto err_unlock;
|
||||
}
|
||||
|
||||
ath10k_print_driver_info(ar);
|
||||
ath10k_debug_print_boot_info(ar);
|
||||
ath10k_core_stop(ar);
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
|
|
@ -81,26 +81,20 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus)
|
|||
return "unknown";
|
||||
}
|
||||
|
||||
enum ath10k_skb_flags {
|
||||
ATH10K_SKB_F_NO_HWCRYPT = BIT(0),
|
||||
ATH10K_SKB_F_DTIM_ZERO = BIT(1),
|
||||
ATH10K_SKB_F_DELIVER_CAB = BIT(2),
|
||||
ATH10K_SKB_F_MGMT = BIT(3),
|
||||
ATH10K_SKB_F_QOS = BIT(4),
|
||||
};
|
||||
|
||||
struct ath10k_skb_cb {
|
||||
dma_addr_t paddr;
|
||||
u8 flags;
|
||||
u8 eid;
|
||||
u8 vdev_id;
|
||||
enum ath10k_hw_txrx_mode txmode;
|
||||
bool is_protected;
|
||||
|
||||
struct {
|
||||
u8 tid;
|
||||
u16 freq;
|
||||
bool is_offchan;
|
||||
bool nohwcrypt;
|
||||
struct ath10k_htt_txbuf *txbuf;
|
||||
u32 txbuf_paddr;
|
||||
} __packed htt;
|
||||
|
||||
struct {
|
||||
bool dtim_zero;
|
||||
bool deliver_cab;
|
||||
} bcn;
|
||||
u16 msdu_id;
|
||||
struct ieee80211_vif *vif;
|
||||
} __packed;
|
||||
|
||||
struct ath10k_skb_rxcb {
|
||||
|
@ -151,6 +145,7 @@ struct ath10k_wmi {
|
|||
struct wmi_vdev_param_map *vdev_param;
|
||||
struct wmi_pdev_param_map *pdev_param;
|
||||
const struct wmi_ops *ops;
|
||||
const struct wmi_peer_flags_map *peer_flags;
|
||||
|
||||
u32 num_mem_chunks;
|
||||
u32 rx_decap_mode;
|
||||
|
@ -512,6 +507,9 @@ enum ath10k_fw_features {
|
|||
/* Firmware Supports Adaptive CCA*/
|
||||
ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11,
|
||||
|
||||
/* Firmware supports management frame protection */
|
||||
ATH10K_FW_FEATURE_MFP_SUPPORT = 12,
|
||||
|
||||
/* keep last */
|
||||
ATH10K_FW_FEATURE_COUNT,
|
||||
};
|
||||
|
@ -534,6 +532,9 @@ enum ath10k_dev_flags {
|
|||
|
||||
/* Disable HW crypto engine */
|
||||
ATH10K_FLAG_HW_CRYPTO_DISABLED,
|
||||
|
||||
/* Bluetooth coexistance enabled */
|
||||
ATH10K_FLAG_BTCOEX,
|
||||
};
|
||||
|
||||
enum ath10k_cal_mode {
|
||||
|
@ -661,6 +662,9 @@ struct ath10k {
|
|||
*/
|
||||
u32 max_probe_resp_desc_thres;
|
||||
|
||||
/* The padding bytes's location is different on various chips */
|
||||
enum ath10k_hw_4addr_pad hw_4addr_pad;
|
||||
|
||||
struct ath10k_hw_params_fw {
|
||||
const char *dir;
|
||||
const char *fw;
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <linux/debugfs.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/utsname.h>
|
||||
#include <linux/crc32.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
|
@ -122,28 +124,51 @@ void ath10k_info(struct ath10k *ar, const char *fmt, ...)
|
|||
}
|
||||
EXPORT_SYMBOL(ath10k_info);
|
||||
|
||||
void ath10k_print_driver_info(struct ath10k *ar)
|
||||
void ath10k_debug_print_hwfw_info(struct ath10k *ar)
|
||||
{
|
||||
char fw_features[128] = {};
|
||||
char boardinfo[100];
|
||||
|
||||
ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
|
||||
|
||||
if (ar->id.bmi_ids_valid)
|
||||
scnprintf(boardinfo, sizeof(boardinfo), "bmi %d:%d",
|
||||
ar->id.bmi_chip_id, ar->id.bmi_board_id);
|
||||
else
|
||||
scnprintf(boardinfo, sizeof(boardinfo), "sub %04x:%04x",
|
||||
ar->id.subsystem_vendor, ar->id.subsystem_device);
|
||||
|
||||
ath10k_info(ar, "%s (0x%08x, 0x%08x %s) fw %s fwapi %d bdapi %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n",
|
||||
ath10k_info(ar, "%s target 0x%08x chip_id 0x%08x sub %04x:%04x",
|
||||
ar->hw_params.name,
|
||||
ar->target_version,
|
||||
ar->chip_id,
|
||||
boardinfo,
|
||||
ar->id.subsystem_vendor, ar->id.subsystem_device);
|
||||
|
||||
ath10k_info(ar, "kconfig debug %d debugfs %d tracing %d dfs %d testmode %d\n",
|
||||
config_enabled(CONFIG_ATH10K_DEBUG),
|
||||
config_enabled(CONFIG_ATH10K_DEBUGFS),
|
||||
config_enabled(CONFIG_ATH10K_TRACING),
|
||||
config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
|
||||
config_enabled(CONFIG_NL80211_TESTMODE));
|
||||
|
||||
ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n",
|
||||
ar->hw->wiphy->fw_version,
|
||||
ar->fw_api,
|
||||
fw_features,
|
||||
crc32_le(0, ar->firmware->data, ar->firmware->size));
|
||||
}
|
||||
|
||||
void ath10k_debug_print_board_info(struct ath10k *ar)
|
||||
{
|
||||
char boardinfo[100];
|
||||
|
||||
if (ar->id.bmi_ids_valid)
|
||||
scnprintf(boardinfo, sizeof(boardinfo), "%d:%d",
|
||||
ar->id.bmi_chip_id, ar->id.bmi_board_id);
|
||||
else
|
||||
scnprintf(boardinfo, sizeof(boardinfo), "N/A");
|
||||
|
||||
ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x",
|
||||
ar->bd_api,
|
||||
boardinfo,
|
||||
crc32_le(0, ar->board->data, ar->board->size));
|
||||
}
|
||||
|
||||
void ath10k_debug_print_boot_info(struct ath10k *ar)
|
||||
{
|
||||
ath10k_info(ar, "htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d\n",
|
||||
ar->htt.target_version_major,
|
||||
ar->htt.target_version_minor,
|
||||
ar->wmi.op_version,
|
||||
|
@ -151,14 +176,14 @@ void ath10k_print_driver_info(struct ath10k *ar)
|
|||
ath10k_cal_mode_str(ar->cal_mode),
|
||||
ar->max_num_stations,
|
||||
test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
|
||||
!test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags),
|
||||
fw_features);
|
||||
ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
|
||||
config_enabled(CONFIG_ATH10K_DEBUG),
|
||||
config_enabled(CONFIG_ATH10K_DEBUGFS),
|
||||
config_enabled(CONFIG_ATH10K_TRACING),
|
||||
config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
|
||||
config_enabled(CONFIG_NL80211_TESTMODE));
|
||||
!test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags));
|
||||
}
|
||||
|
||||
void ath10k_print_driver_info(struct ath10k *ar)
|
||||
{
|
||||
ath10k_debug_print_hwfw_info(ar);
|
||||
ath10k_debug_print_board_info(ar);
|
||||
ath10k_debug_print_boot_info(ar);
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_print_driver_info);
|
||||
|
||||
|
@ -2074,6 +2099,121 @@ static const struct file_operations fops_quiet_period = {
|
|||
.open = simple_open
|
||||
};
|
||||
|
||||
static ssize_t ath10k_write_btcoex(struct file *file,
|
||||
const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
char buf[32];
|
||||
size_t buf_size;
|
||||
bool val;
|
||||
|
||||
buf_size = min(count, (sizeof(buf) - 1));
|
||||
if (copy_from_user(buf, ubuf, buf_size))
|
||||
return -EFAULT;
|
||||
|
||||
buf[buf_size] = '\0';
|
||||
|
||||
if (strtobool(buf, &val) != 0)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val))
|
||||
goto exit;
|
||||
|
||||
if (val)
|
||||
set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
|
||||
else
|
||||
clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON)
|
||||
goto exit;
|
||||
|
||||
ath10k_info(ar, "restarting firmware due to btcoex change");
|
||||
|
||||
queue_work(ar->workqueue, &ar->restart_work);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char buf[32];
|
||||
struct ath10k *ar = file->private_data;
|
||||
int len = 0;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
len = scnprintf(buf, sizeof(buf) - len, "%d\n",
|
||||
test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags));
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static const struct file_operations fops_btcoex = {
|
||||
.read = ath10k_read_btcoex,
|
||||
.write = ath10k_write_btcoex,
|
||||
.open = simple_open
|
||||
};
|
||||
|
||||
static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
unsigned int len = 0, buf_len = 4096;
|
||||
ssize_t ret_cnt;
|
||||
char *buf;
|
||||
|
||||
buf = kzalloc(buf_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (len > buf_len)
|
||||
len = buf_len;
|
||||
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"firmware-N.bin\t\t%08x\n",
|
||||
crc32_le(0, ar->firmware->data, ar->firmware->size));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"athwlan\t\t\t%08x\n",
|
||||
crc32_le(0, ar->firmware_data, ar->firmware_len));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"otp\t\t\t%08x\n",
|
||||
crc32_le(0, ar->otp_data, ar->otp_len));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"codeswap\t\t%08x\n",
|
||||
crc32_le(0, ar->swap.firmware_codeswap_data,
|
||||
ar->swap.firmware_codeswap_len));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"board-N.bin\t\t%08x\n",
|
||||
crc32_le(0, ar->board->data, ar->board->size));
|
||||
len += scnprintf(buf + len, buf_len - len,
|
||||
"board\t\t\t%08x\n",
|
||||
crc32_le(0, ar->board_data, ar->board_len));
|
||||
|
||||
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
kfree(buf);
|
||||
return ret_cnt;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_fw_checksums = {
|
||||
.read = ath10k_debug_fw_checksums_read,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
int ath10k_debug_create(struct ath10k *ar)
|
||||
{
|
||||
ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
|
||||
|
@ -2123,8 +2263,8 @@ int ath10k_debug_register(struct ath10k *ar)
|
|||
debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
|
||||
&fops_wmi_services);
|
||||
|
||||
debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_simulate_fw_crash);
|
||||
debugfs_create_file("simulate_fw_crash", S_IRUSR | S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_simulate_fw_crash);
|
||||
|
||||
debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_fw_crash_dump);
|
||||
|
@ -2141,15 +2281,15 @@ int ath10k_debug_register(struct ath10k *ar)
|
|||
debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_chip_id);
|
||||
|
||||
debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_htt_stats_mask);
|
||||
debugfs_create_file("htt_stats_mask", S_IRUSR | S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_htt_stats_mask);
|
||||
|
||||
debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar,
|
||||
&fops_htt_max_amsdu_ampdu);
|
||||
|
||||
debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_fw_dbglog);
|
||||
debugfs_create_file("fw_dbglog", S_IRUSR | S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_fw_dbglog);
|
||||
|
||||
debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_cal_data);
|
||||
|
@ -2183,6 +2323,13 @@ int ath10k_debug_register(struct ath10k *ar)
|
|||
debugfs_create_file("tpc_stats", S_IRUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_tpc_stats);
|
||||
|
||||
if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
|
||||
debugfs_create_file("btcoex", S_IRUGO | S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_btcoex);
|
||||
|
||||
debugfs_create_file("fw_checksums", S_IRUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_fw_checksums);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,10 @@ extern unsigned int ath10k_debug_mask;
|
|||
__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
|
||||
__printf(2, 3) void ath10k_err(struct ath10k *ar, const char *fmt, ...);
|
||||
__printf(2, 3) void ath10k_warn(struct ath10k *ar, const char *fmt, ...);
|
||||
|
||||
void ath10k_debug_print_hwfw_info(struct ath10k *ar);
|
||||
void ath10k_debug_print_board_info(struct ath10k *ar);
|
||||
void ath10k_debug_print_boot_info(struct ath10k *ar);
|
||||
void ath10k_print_driver_info(struct ath10k *ar);
|
||||
|
||||
#ifdef CONFIG_ATH10K_DEBUGFS
|
||||
|
|
|
@ -166,8 +166,13 @@ struct htt_data_tx_desc {
|
|||
__le16 len;
|
||||
__le16 id;
|
||||
__le32 frags_paddr;
|
||||
__le16 peerid;
|
||||
__le16 freq;
|
||||
union {
|
||||
__le32 peerid;
|
||||
struct {
|
||||
__le16 peerid;
|
||||
__le16 freq;
|
||||
} __packed offchan_tx;
|
||||
} __packed;
|
||||
u8 prefetch[0]; /* start of frame, for FW classification engine */
|
||||
} __packed;
|
||||
|
||||
|
@ -1597,6 +1602,10 @@ void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc);
|
|||
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb);
|
||||
void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id);
|
||||
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *);
|
||||
int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *);
|
||||
int ath10k_htt_tx(struct ath10k_htt *htt,
|
||||
enum ath10k_hw_txrx_mode txmode,
|
||||
struct sk_buff *msdu);
|
||||
void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
|
||||
struct sk_buff *skb);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -536,7 +536,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
|
|||
|
||||
size = htt->rx_ring.size * sizeof(htt->rx_ring.paddrs_ring);
|
||||
|
||||
vaddr = dma_alloc_coherent(htt->ar->dev, size, &paddr, GFP_DMA);
|
||||
vaddr = dma_alloc_coherent(htt->ar->dev, size, &paddr, GFP_KERNEL);
|
||||
if (!vaddr)
|
||||
goto err_dma_ring;
|
||||
|
||||
|
@ -545,7 +545,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
|
|||
|
||||
vaddr = dma_alloc_coherent(htt->ar->dev,
|
||||
sizeof(*htt->rx_ring.alloc_idx.vaddr),
|
||||
&paddr, GFP_DMA);
|
||||
&paddr, GFP_KERNEL);
|
||||
if (!vaddr)
|
||||
goto err_dma_idx;
|
||||
|
||||
|
@ -674,7 +674,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
|
|||
rate &= ~RX_PPDU_START_RATE_FLAG;
|
||||
|
||||
sband = &ar->mac.sbands[status->band];
|
||||
status->rate_idx = ath10k_mac_hw_rate_to_idx(sband, rate);
|
||||
status->rate_idx = ath10k_mac_hw_rate_to_idx(sband, rate, cck);
|
||||
break;
|
||||
case HTT_RX_HT:
|
||||
case HTT_RX_HT_WITH_TXBF:
|
||||
|
@ -1114,7 +1114,20 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
|
|||
*/
|
||||
|
||||
/* pull decapped header and copy SA & DA */
|
||||
hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
if ((ar->hw_params.hw_4addr_pad == ATH10K_HW_4ADDR_PAD_BEFORE) &&
|
||||
ieee80211_has_a4(((struct ieee80211_hdr *)first_hdr)->frame_control)) {
|
||||
/* The QCA99X0 4 address mode pad 2 bytes at the
|
||||
* beginning of MSDU
|
||||
*/
|
||||
hdr = (struct ieee80211_hdr *)(msdu->data + 2);
|
||||
/* The skb length need be extended 2 as the 2 bytes at the tail
|
||||
* be excluded due to the padding
|
||||
*/
|
||||
skb_put(msdu, 2);
|
||||
} else {
|
||||
hdr = (struct ieee80211_hdr *)(msdu->data);
|
||||
}
|
||||
|
||||
hdr_len = ath10k_htt_rx_nwifi_hdrlen(ar, hdr);
|
||||
ether_addr_copy(da, ieee80211_get_DA(hdr));
|
||||
ether_addr_copy(sa, ieee80211_get_SA(hdr));
|
||||
|
@ -2127,6 +2140,18 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
|||
}
|
||||
EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler);
|
||||
|
||||
void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ath10k_pktlog_10_4_hdr *hdr =
|
||||
(struct ath10k_pktlog_10_4_hdr *)skb->data;
|
||||
|
||||
trace_ath10k_htt_pktlog(ar, hdr->payload,
|
||||
sizeof(*hdr) + __le16_to_cpu(hdr->size));
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_htt_rx_pktlog_completion_handler);
|
||||
|
||||
static void ath10k_htt_txrx_compl_task(unsigned long ptr)
|
||||
{
|
||||
struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
|
||||
|
|
|
@ -111,7 +111,7 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
|
|||
size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf);
|
||||
htt->txbuf.vaddr = dma_alloc_coherent(ar->dev, size,
|
||||
&htt->txbuf.paddr,
|
||||
GFP_DMA);
|
||||
GFP_KERNEL);
|
||||
if (!htt->txbuf.vaddr) {
|
||||
ath10k_err(ar, "failed to alloc tx buffer\n");
|
||||
ret = -ENOMEM;
|
||||
|
@ -124,7 +124,7 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
|
|||
size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc);
|
||||
htt->frag_desc.vaddr = dma_alloc_coherent(ar->dev, size,
|
||||
&htt->frag_desc.paddr,
|
||||
GFP_DMA);
|
||||
GFP_KERNEL);
|
||||
if (!htt->frag_desc.vaddr) {
|
||||
ath10k_warn(ar, "failed to alloc fragment desc memory\n");
|
||||
ret = -ENOMEM;
|
||||
|
@ -439,6 +439,35 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static u8 ath10k_htt_tx_get_vdev_id(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
|
||||
struct ath10k_vif *arvif = (void *)cb->vif->drv_priv;
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
|
||||
return ar->scan.vdev_id;
|
||||
else if (cb->vif)
|
||||
return arvif->vdev_id;
|
||||
else if (ar->monitor_started)
|
||||
return ar->monitor_vdev_id;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 ath10k_htt_tx_get_tid(struct sk_buff *skb, bool is_eth)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
|
||||
|
||||
if (!is_eth && ieee80211_is_mgmt(hdr->frame_control))
|
||||
return HTT_DATA_TX_EXT_TID_MGMT;
|
||||
else if (cb->flags & ATH10K_SKB_F_QOS)
|
||||
return skb->priority % IEEE80211_QOS_CTL_TID_MASK;
|
||||
else
|
||||
return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
|
||||
}
|
||||
|
||||
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
|
@ -446,7 +475,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
struct sk_buff *txdesc = NULL;
|
||||
struct htt_cmd *cmd;
|
||||
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
|
||||
u8 vdev_id = skb_cb->vdev_id;
|
||||
u8 vdev_id = ath10k_htt_tx_get_vdev_id(ar, msdu);
|
||||
int len = 0;
|
||||
int msdu_id = -1;
|
||||
int res;
|
||||
|
@ -477,6 +506,13 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
|
||||
msdu_id = res;
|
||||
|
||||
if ((ieee80211_is_action(hdr->frame_control) ||
|
||||
ieee80211_is_deauth(hdr->frame_control) ||
|
||||
ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||
ieee80211_has_protected(hdr->frame_control)) {
|
||||
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
}
|
||||
|
||||
txdesc = ath10k_htc_alloc_skb(ar, len);
|
||||
if (!txdesc) {
|
||||
res = -ENOMEM;
|
||||
|
@ -503,8 +539,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
memcpy(cmd->mgmt_tx.hdr, msdu->data,
|
||||
min_t(int, msdu->len, HTT_MGMT_FRM_HDR_DOWNLOAD_LEN));
|
||||
|
||||
skb_cb->htt.txbuf = NULL;
|
||||
|
||||
res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc);
|
||||
if (res)
|
||||
goto err_unmap_msdu;
|
||||
|
@ -525,21 +559,27 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
return res;
|
||||
}
|
||||
|
||||
int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
||||
int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
|
||||
struct sk_buff *msdu)
|
||||
{
|
||||
struct ath10k *ar = htt->ar;
|
||||
struct device *dev = ar->dev;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu);
|
||||
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
|
||||
struct ath10k_hif_sg_item sg_items[2];
|
||||
struct ath10k_htt_txbuf *txbuf;
|
||||
struct htt_data_tx_desc_frag *frags;
|
||||
u8 vdev_id = skb_cb->vdev_id;
|
||||
u8 tid = skb_cb->htt.tid;
|
||||
bool is_eth = (txmode == ATH10K_HW_TXRX_ETHERNET);
|
||||
u8 vdev_id = ath10k_htt_tx_get_vdev_id(ar, msdu);
|
||||
u8 tid = ath10k_htt_tx_get_tid(msdu, is_eth);
|
||||
int prefetch_len;
|
||||
int res;
|
||||
u8 flags0 = 0;
|
||||
u16 msdu_id, flags1 = 0;
|
||||
u16 freq = 0;
|
||||
u32 frags_paddr = 0;
|
||||
u32 txbuf_paddr;
|
||||
struct htt_msdu_ext_desc *ext_desc = NULL;
|
||||
bool limit_mgmt_desc = false;
|
||||
bool is_probe_resp = false;
|
||||
|
@ -567,17 +607,17 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
prefetch_len = min(htt->prefetch_len, msdu->len);
|
||||
prefetch_len = roundup(prefetch_len, 4);
|
||||
|
||||
skb_cb->htt.txbuf = &htt->txbuf.vaddr[msdu_id];
|
||||
skb_cb->htt.txbuf_paddr = htt->txbuf.paddr +
|
||||
(sizeof(struct ath10k_htt_txbuf) * msdu_id);
|
||||
txbuf = &htt->txbuf.vaddr[msdu_id];
|
||||
txbuf_paddr = htt->txbuf.paddr +
|
||||
(sizeof(struct ath10k_htt_txbuf) * msdu_id);
|
||||
|
||||
if ((ieee80211_is_action(hdr->frame_control) ||
|
||||
ieee80211_is_deauth(hdr->frame_control) ||
|
||||
ieee80211_is_disassoc(hdr->frame_control)) &&
|
||||
ieee80211_has_protected(hdr->frame_control)) {
|
||||
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
} else if (!skb_cb->htt.nohwcrypt &&
|
||||
skb_cb->txmode == ATH10K_HW_TXRX_RAW &&
|
||||
} else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
|
||||
txmode == ATH10K_HW_TXRX_RAW &&
|
||||
ieee80211_has_protected(hdr->frame_control)) {
|
||||
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
|
||||
}
|
||||
|
@ -590,7 +630,10 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
goto err_free_msdu_id;
|
||||
}
|
||||
|
||||
switch (skb_cb->txmode) {
|
||||
if (unlikely(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN))
|
||||
freq = ar->scan.roc_freq;
|
||||
|
||||
switch (txmode) {
|
||||
case ATH10K_HW_TXRX_RAW:
|
||||
case ATH10K_HW_TXRX_NATIVE_WIFI:
|
||||
flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
|
||||
|
@ -610,16 +653,16 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
frags_paddr = htt->frag_desc.paddr +
|
||||
(sizeof(struct htt_msdu_ext_desc) * msdu_id);
|
||||
} else {
|
||||
frags = skb_cb->htt.txbuf->frags;
|
||||
frags = txbuf->frags;
|
||||
frags[0].dword_addr.paddr =
|
||||
__cpu_to_le32(skb_cb->paddr);
|
||||
frags[0].dword_addr.len = __cpu_to_le32(msdu->len);
|
||||
frags[1].dword_addr.paddr = 0;
|
||||
frags[1].dword_addr.len = 0;
|
||||
|
||||
frags_paddr = skb_cb->htt.txbuf_paddr;
|
||||
frags_paddr = txbuf_paddr;
|
||||
}
|
||||
flags0 |= SM(skb_cb->txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
|
||||
flags0 |= SM(txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
|
||||
break;
|
||||
case ATH10K_HW_TXRX_MGMT:
|
||||
flags0 |= SM(ATH10K_HW_TXRX_MGMT,
|
||||
|
@ -646,17 +689,13 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
* avoid extra memory allocations, compress data structures and thus
|
||||
* improve performance. */
|
||||
|
||||
skb_cb->htt.txbuf->htc_hdr.eid = htt->eid;
|
||||
skb_cb->htt.txbuf->htc_hdr.len = __cpu_to_le16(
|
||||
sizeof(skb_cb->htt.txbuf->cmd_hdr) +
|
||||
sizeof(skb_cb->htt.txbuf->cmd_tx) +
|
||||
prefetch_len);
|
||||
skb_cb->htt.txbuf->htc_hdr.flags = 0;
|
||||
txbuf->htc_hdr.eid = htt->eid;
|
||||
txbuf->htc_hdr.len = __cpu_to_le16(sizeof(txbuf->cmd_hdr) +
|
||||
sizeof(txbuf->cmd_tx) +
|
||||
prefetch_len);
|
||||
txbuf->htc_hdr.flags = 0;
|
||||
|
||||
if (skb_cb->htt.nohwcrypt)
|
||||
flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
|
||||
|
||||
if (!skb_cb->is_protected)
|
||||
if (skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT)
|
||||
flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
|
||||
|
||||
flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID);
|
||||
|
@ -675,20 +714,27 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
*/
|
||||
flags1 |= HTT_DATA_TX_DESC_FLAGS1_POSTPONED;
|
||||
|
||||
skb_cb->htt.txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
|
||||
skb_cb->htt.txbuf->cmd_tx.flags0 = flags0;
|
||||
skb_cb->htt.txbuf->cmd_tx.flags1 = __cpu_to_le16(flags1);
|
||||
skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len);
|
||||
skb_cb->htt.txbuf->cmd_tx.id = __cpu_to_le16(msdu_id);
|
||||
skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr);
|
||||
skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le16(HTT_INVALID_PEERID);
|
||||
skb_cb->htt.txbuf->cmd_tx.freq = __cpu_to_le16(skb_cb->htt.freq);
|
||||
txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
|
||||
txbuf->cmd_tx.flags0 = flags0;
|
||||
txbuf->cmd_tx.flags1 = __cpu_to_le16(flags1);
|
||||
txbuf->cmd_tx.len = __cpu_to_le16(msdu->len);
|
||||
txbuf->cmd_tx.id = __cpu_to_le16(msdu_id);
|
||||
txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr);
|
||||
if (ath10k_mac_tx_frm_has_freq(ar)) {
|
||||
txbuf->cmd_tx.offchan_tx.peerid =
|
||||
__cpu_to_le16(HTT_INVALID_PEERID);
|
||||
txbuf->cmd_tx.offchan_tx.freq =
|
||||
__cpu_to_le16(freq);
|
||||
} else {
|
||||
txbuf->cmd_tx.peerid =
|
||||
__cpu_to_le32(HTT_INVALID_PEERID);
|
||||
}
|
||||
|
||||
trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid);
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT,
|
||||
"htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu freq %hu\n",
|
||||
flags0, flags1, msdu->len, msdu_id, frags_paddr,
|
||||
(u32)skb_cb->paddr, vdev_id, tid, skb_cb->htt.freq);
|
||||
(u32)skb_cb->paddr, vdev_id, tid, freq);
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ",
|
||||
msdu->data, msdu->len);
|
||||
trace_ath10k_tx_hdr(ar, msdu->data, msdu->len);
|
||||
|
@ -696,12 +742,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
|
||||
sg_items[0].transfer_id = 0;
|
||||
sg_items[0].transfer_context = NULL;
|
||||
sg_items[0].vaddr = &skb_cb->htt.txbuf->htc_hdr;
|
||||
sg_items[0].paddr = skb_cb->htt.txbuf_paddr +
|
||||
sizeof(skb_cb->htt.txbuf->frags);
|
||||
sg_items[0].len = sizeof(skb_cb->htt.txbuf->htc_hdr) +
|
||||
sizeof(skb_cb->htt.txbuf->cmd_hdr) +
|
||||
sizeof(skb_cb->htt.txbuf->cmd_tx);
|
||||
sg_items[0].vaddr = &txbuf->htc_hdr;
|
||||
sg_items[0].paddr = txbuf_paddr +
|
||||
sizeof(txbuf->frags);
|
||||
sg_items[0].len = sizeof(txbuf->htc_hdr) +
|
||||
sizeof(txbuf->cmd_hdr) +
|
||||
sizeof(txbuf->cmd_tx);
|
||||
|
||||
sg_items[1].transfer_id = 0;
|
||||
sg_items[1].transfer_context = NULL;
|
||||
|
|
|
@ -273,6 +273,16 @@ struct ath10k_pktlog_hdr {
|
|||
u8 payload[0];
|
||||
} __packed;
|
||||
|
||||
struct ath10k_pktlog_10_4_hdr {
|
||||
__le16 flags;
|
||||
__le16 missed_cnt;
|
||||
__le16 log_type;
|
||||
__le16 size;
|
||||
__le32 timestamp;
|
||||
__le32 type_specific_data;
|
||||
u8 payload[0];
|
||||
} __packed;
|
||||
|
||||
enum ath10k_hw_rate_ofdm {
|
||||
ATH10K_HW_RATE_OFDM_48M = 0,
|
||||
ATH10K_HW_RATE_OFDM_24M,
|
||||
|
@ -294,6 +304,11 @@ enum ath10k_hw_rate_cck {
|
|||
ATH10K_HW_RATE_CCK_SP_2M,
|
||||
};
|
||||
|
||||
enum ath10k_hw_4addr_pad {
|
||||
ATH10K_HW_4ADDR_PAD_AFTER,
|
||||
ATH10K_HW_4ADDR_PAD_BEFORE,
|
||||
};
|
||||
|
||||
/* Target specific defines for MAIN firmware */
|
||||
#define TARGET_NUM_VDEVS 8
|
||||
#define TARGET_NUM_PEER_AST 2
|
||||
|
|
|
@ -90,7 +90,7 @@ static u8 ath10k_mac_bitrate_to_rate(int bitrate)
|
|||
}
|
||||
|
||||
u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
|
||||
u8 hw_rate)
|
||||
u8 hw_rate, bool cck)
|
||||
{
|
||||
const struct ieee80211_rate *rate;
|
||||
int i;
|
||||
|
@ -98,6 +98,9 @@ u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
|
|||
for (i = 0; i < sband->n_bitrates; i++) {
|
||||
rate = &sband->bitrates[i];
|
||||
|
||||
if (ath10k_mac_bitrate_is_cck(rate->bitrate) != cck)
|
||||
continue;
|
||||
|
||||
if (rate->hw_value == hw_rate)
|
||||
return i;
|
||||
else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE &&
|
||||
|
@ -1960,7 +1963,7 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
|
|||
ether_addr_copy(arg->addr, sta->addr);
|
||||
arg->vdev_id = arvif->vdev_id;
|
||||
arg->peer_aid = aid;
|
||||
arg->peer_flags |= WMI_PEER_AUTH;
|
||||
arg->peer_flags |= arvif->ar->wmi.peer_flags->auth;
|
||||
arg->peer_listen_intval = ath10k_peer_assoc_h_listen_intval(ar, vif);
|
||||
arg->peer_num_spatial_streams = 1;
|
||||
arg->peer_caps = vif->bss_conf.assoc_capability;
|
||||
|
@ -1968,6 +1971,7 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
|
|||
|
||||
static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct wmi_peer_assoc_complete_arg *arg)
|
||||
{
|
||||
struct ieee80211_bss_conf *info = &vif->bss_conf;
|
||||
|
@ -2002,12 +2006,17 @@ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
|
|||
/* FIXME: base on RSN IE/WPA IE is a correct idea? */
|
||||
if (rsnie || wpaie) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "%s: rsn ie found\n", __func__);
|
||||
arg->peer_flags |= WMI_PEER_NEED_PTK_4_WAY;
|
||||
arg->peer_flags |= ar->wmi.peer_flags->need_ptk_4_way;
|
||||
}
|
||||
|
||||
if (wpaie) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI, "%s: wpa ie found\n", __func__);
|
||||
arg->peer_flags |= WMI_PEER_NEED_GTK_2_WAY;
|
||||
arg->peer_flags |= ar->wmi.peer_flags->need_gtk_2_way;
|
||||
}
|
||||
|
||||
if (sta->mfp &&
|
||||
test_bit(ATH10K_FW_FEATURE_MFP_SUPPORT, ar->fw_features)) {
|
||||
arg->peer_flags |= ar->wmi.peer_flags->pmf;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2104,7 +2113,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
|
|||
ath10k_peer_assoc_h_vht_masked(vht_mcs_mask))
|
||||
return;
|
||||
|
||||
arg->peer_flags |= WMI_PEER_HT;
|
||||
arg->peer_flags |= ar->wmi.peer_flags->ht;
|
||||
arg->peer_max_mpdu = (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
|
||||
ht_cap->ampdu_factor)) - 1;
|
||||
|
||||
|
@ -2115,10 +2124,10 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
|
|||
arg->peer_rate_caps |= WMI_RC_HT_FLAG;
|
||||
|
||||
if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)
|
||||
arg->peer_flags |= WMI_PEER_LDPC;
|
||||
arg->peer_flags |= ar->wmi.peer_flags->ldbc;
|
||||
|
||||
if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) {
|
||||
arg->peer_flags |= WMI_PEER_40MHZ;
|
||||
arg->peer_flags |= ar->wmi.peer_flags->bw40;
|
||||
arg->peer_rate_caps |= WMI_RC_CW40_FLAG;
|
||||
}
|
||||
|
||||
|
@ -2132,7 +2141,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
|
|||
|
||||
if (ht_cap->cap & IEEE80211_HT_CAP_TX_STBC) {
|
||||
arg->peer_rate_caps |= WMI_RC_TX_STBC_FLAG;
|
||||
arg->peer_flags |= WMI_PEER_STBC;
|
||||
arg->peer_flags |= ar->wmi.peer_flags->stbc;
|
||||
}
|
||||
|
||||
if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) {
|
||||
|
@ -2140,7 +2149,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
|
|||
stbc = stbc >> IEEE80211_HT_CAP_RX_STBC_SHIFT;
|
||||
stbc = stbc << WMI_RC_RX_STBC_FLAG_S;
|
||||
arg->peer_rate_caps |= stbc;
|
||||
arg->peer_flags |= WMI_PEER_STBC;
|
||||
arg->peer_flags |= ar->wmi.peer_flags->stbc;
|
||||
}
|
||||
|
||||
if (ht_cap->mcs.rx_mask[1] && ht_cap->mcs.rx_mask[2])
|
||||
|
@ -2321,10 +2330,10 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
|
|||
if (ath10k_peer_assoc_h_vht_masked(vht_mcs_mask))
|
||||
return;
|
||||
|
||||
arg->peer_flags |= WMI_PEER_VHT;
|
||||
arg->peer_flags |= ar->wmi.peer_flags->vht;
|
||||
|
||||
if (def.chan->band == IEEE80211_BAND_2GHZ)
|
||||
arg->peer_flags |= WMI_PEER_VHT_2G;
|
||||
arg->peer_flags |= ar->wmi.peer_flags->vht_2g;
|
||||
|
||||
arg->peer_vht_caps = vht_cap->cap;
|
||||
|
||||
|
@ -2341,7 +2350,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
|
|||
ampdu_factor)) - 1);
|
||||
|
||||
if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
|
||||
arg->peer_flags |= WMI_PEER_80MHZ;
|
||||
arg->peer_flags |= ar->wmi.peer_flags->bw80;
|
||||
|
||||
arg->peer_vht_rates.rx_max_rate =
|
||||
__le16_to_cpu(vht_cap->vht_mcs.rx_highest);
|
||||
|
@ -2366,27 +2375,28 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
|
|||
switch (arvif->vdev_type) {
|
||||
case WMI_VDEV_TYPE_AP:
|
||||
if (sta->wme)
|
||||
arg->peer_flags |= WMI_PEER_QOS;
|
||||
arg->peer_flags |= arvif->ar->wmi.peer_flags->qos;
|
||||
|
||||
if (sta->wme && sta->uapsd_queues) {
|
||||
arg->peer_flags |= WMI_PEER_APSD;
|
||||
arg->peer_flags |= arvif->ar->wmi.peer_flags->apsd;
|
||||
arg->peer_rate_caps |= WMI_RC_UAPSD_FLAG;
|
||||
}
|
||||
break;
|
||||
case WMI_VDEV_TYPE_STA:
|
||||
if (vif->bss_conf.qos)
|
||||
arg->peer_flags |= WMI_PEER_QOS;
|
||||
arg->peer_flags |= arvif->ar->wmi.peer_flags->qos;
|
||||
break;
|
||||
case WMI_VDEV_TYPE_IBSS:
|
||||
if (sta->wme)
|
||||
arg->peer_flags |= WMI_PEER_QOS;
|
||||
arg->peer_flags |= arvif->ar->wmi.peer_flags->qos;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac peer %pM qos %d\n",
|
||||
sta->addr, !!(arg->peer_flags & WMI_PEER_QOS));
|
||||
sta->addr, !!(arg->peer_flags &
|
||||
arvif->ar->wmi.peer_flags->qos));
|
||||
}
|
||||
|
||||
static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
|
||||
|
@ -2479,7 +2489,7 @@ static int ath10k_peer_assoc_prepare(struct ath10k *ar,
|
|||
memset(arg, 0, sizeof(*arg));
|
||||
|
||||
ath10k_peer_assoc_h_basic(ar, vif, sta, arg);
|
||||
ath10k_peer_assoc_h_crypto(ar, vif, arg);
|
||||
ath10k_peer_assoc_h_crypto(ar, vif, sta, arg);
|
||||
ath10k_peer_assoc_h_rates(ar, vif, sta, arg);
|
||||
ath10k_peer_assoc_h_ht(ar, vif, sta, arg);
|
||||
ath10k_peer_assoc_h_vht(ar, vif, sta, arg);
|
||||
|
@ -3112,35 +3122,11 @@ void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id,
|
|||
spin_unlock_bh(&ar->htt.tx_lock);
|
||||
}
|
||||
|
||||
static u8 ath10k_tx_h_get_tid(struct ieee80211_hdr *hdr)
|
||||
{
|
||||
if (ieee80211_is_mgmt(hdr->frame_control))
|
||||
return HTT_DATA_TX_EXT_TID_MGMT;
|
||||
|
||||
if (!ieee80211_is_data_qos(hdr->frame_control))
|
||||
return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
|
||||
|
||||
if (!is_unicast_ether_addr(ieee80211_get_DA(hdr)))
|
||||
return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
|
||||
|
||||
return ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
|
||||
}
|
||||
|
||||
static u8 ath10k_tx_h_get_vdev_id(struct ath10k *ar, struct ieee80211_vif *vif)
|
||||
{
|
||||
if (vif)
|
||||
return ath10k_vif_to_arvif(vif)->vdev_id;
|
||||
|
||||
if (ar->monitor_started)
|
||||
return ar->monitor_vdev_id;
|
||||
|
||||
ath10k_warn(ar, "failed to resolve vdev id\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum ath10k_hw_txrx_mode
|
||||
ath10k_tx_h_get_txmode(struct ath10k *ar, struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta, struct sk_buff *skb)
|
||||
ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
|
@ -3190,14 +3176,22 @@ ath10k_tx_h_get_txmode(struct ath10k *ar, struct ieee80211_vif *vif,
|
|||
}
|
||||
|
||||
static bool ath10k_tx_h_use_hwcrypto(struct ieee80211_vif *vif,
|
||||
struct sk_buff *skb) {
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
const struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
const struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
const u32 mask = IEEE80211_TX_INTFL_DONT_ENCRYPT |
|
||||
IEEE80211_TX_CTL_INJECTED;
|
||||
|
||||
if (!ieee80211_has_protected(hdr->frame_control))
|
||||
return false;
|
||||
|
||||
if ((info->flags & mask) == mask)
|
||||
return false;
|
||||
|
||||
if (vif)
|
||||
return !ath10k_vif_to_arvif(vif)->nohwcrypt;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -3224,7 +3218,7 @@ static void ath10k_tx_h_nwifi(struct ieee80211_hw *hw, struct sk_buff *skb)
|
|||
*/
|
||||
hdr = (void *)skb->data;
|
||||
if (ieee80211_is_qos_nullfunc(hdr->frame_control))
|
||||
cb->htt.tid = HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
|
||||
cb->flags &= ~ATH10K_SKB_F_QOS;
|
||||
|
||||
hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
|
||||
}
|
||||
|
@ -3280,7 +3274,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
|
|||
}
|
||||
}
|
||||
|
||||
static bool ath10k_mac_need_offchan_tx_work(struct ath10k *ar)
|
||||
bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar)
|
||||
{
|
||||
/* FIXME: Not really sure since when the behaviour changed. At some
|
||||
* point new firmware stopped requiring creation of peer entries for
|
||||
|
@ -3288,8 +3282,9 @@ static bool ath10k_mac_need_offchan_tx_work(struct ath10k *ar)
|
|||
* tx credit replenishment and reliability). Assuming it's at least 3.4
|
||||
* because that's when the `freq` was introduced to TX_FRM HTT command.
|
||||
*/
|
||||
return !(ar->htt.target_version_major >= 3 &&
|
||||
ar->htt.target_version_minor >= 4);
|
||||
return (ar->htt.target_version_major >= 3 &&
|
||||
ar->htt.target_version_minor >= 4 &&
|
||||
ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_TLV);
|
||||
}
|
||||
|
||||
static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb)
|
||||
|
@ -3314,24 +3309,24 @@ static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void ath10k_mac_tx(struct ath10k *ar, struct sk_buff *skb)
|
||||
static void ath10k_mac_tx(struct ath10k *ar, enum ath10k_hw_txrx_mode txmode,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
|
||||
struct ath10k_htt *htt = &ar->htt;
|
||||
int ret = 0;
|
||||
|
||||
switch (cb->txmode) {
|
||||
switch (txmode) {
|
||||
case ATH10K_HW_TXRX_RAW:
|
||||
case ATH10K_HW_TXRX_NATIVE_WIFI:
|
||||
case ATH10K_HW_TXRX_ETHERNET:
|
||||
ret = ath10k_htt_tx(htt, skb);
|
||||
ret = ath10k_htt_tx(htt, txmode, skb);
|
||||
break;
|
||||
case ATH10K_HW_TXRX_MGMT:
|
||||
if (test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
|
||||
ar->fw_features))
|
||||
ret = ath10k_mac_tx_wmi_mgmt(ar, skb);
|
||||
else if (ar->htt.target_version_major >= 3)
|
||||
ret = ath10k_htt_tx(htt, skb);
|
||||
ret = ath10k_htt_tx(htt, txmode, skb);
|
||||
else
|
||||
ret = ath10k_htt_mgmt_tx(htt, skb);
|
||||
break;
|
||||
|
@ -3361,9 +3356,13 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
|||
{
|
||||
struct ath10k *ar = container_of(work, struct ath10k, offchan_tx_work);
|
||||
struct ath10k_peer *peer;
|
||||
struct ath10k_vif *arvif;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct ieee80211_vif *vif;
|
||||
struct ieee80211_sta *sta;
|
||||
struct sk_buff *skb;
|
||||
const u8 *peer_addr;
|
||||
enum ath10k_hw_txrx_mode txmode;
|
||||
int vdev_id;
|
||||
int ret;
|
||||
unsigned long time_left;
|
||||
|
@ -3388,9 +3387,9 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
|||
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
peer_addr = ieee80211_get_DA(hdr);
|
||||
vdev_id = ATH10K_SKB_CB(skb)->vdev_id;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
vdev_id = ar->scan.vdev_id;
|
||||
peer = ath10k_peer_find(ar, vdev_id, peer_addr);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
|
@ -3413,7 +3412,22 @@ void ath10k_offchan_tx_work(struct work_struct *work)
|
|||
ar->offchan_tx_skb = skb;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ath10k_mac_tx(ar, skb);
|
||||
/* It's safe to access vif and sta - conf_mutex guarantees that
|
||||
* sta_state() and remove_interface() are locked exclusively
|
||||
* out wrt to this offchannel worker.
|
||||
*/
|
||||
arvif = ath10k_get_arvif(ar, vdev_id);
|
||||
if (arvif) {
|
||||
vif = arvif->vif;
|
||||
sta = ieee80211_find_sta(vif, peer_addr);
|
||||
} else {
|
||||
vif = NULL;
|
||||
sta = NULL;
|
||||
}
|
||||
|
||||
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
|
||||
|
||||
ath10k_mac_tx(ar, txmode, skb);
|
||||
|
||||
time_left =
|
||||
wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ);
|
||||
|
@ -3488,6 +3502,7 @@ void __ath10k_scan_finish(struct ath10k *ar)
|
|||
case ATH10K_SCAN_STARTING:
|
||||
ar->scan.state = ATH10K_SCAN_IDLE;
|
||||
ar->scan_channel = NULL;
|
||||
ar->scan.roc_freq = 0;
|
||||
ath10k_offchan_tx_purge(ar);
|
||||
cancel_delayed_work(&ar->scan.timeout);
|
||||
complete_all(&ar->scan.completed);
|
||||
|
@ -3631,25 +3646,32 @@ static void ath10k_tx(struct ieee80211_hw *hw,
|
|||
struct sk_buff *skb)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_vif *vif = info->control.vif;
|
||||
struct ieee80211_sta *sta = control->sta;
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
__le16 fc = hdr->frame_control;
|
||||
enum ath10k_hw_txrx_mode txmode;
|
||||
|
||||
/* We should disable CCK RATE due to P2P */
|
||||
if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
|
||||
|
||||
ATH10K_SKB_CB(skb)->htt.is_offchan = false;
|
||||
ATH10K_SKB_CB(skb)->htt.freq = 0;
|
||||
ATH10K_SKB_CB(skb)->htt.tid = ath10k_tx_h_get_tid(hdr);
|
||||
ATH10K_SKB_CB(skb)->htt.nohwcrypt = !ath10k_tx_h_use_hwcrypto(vif, skb);
|
||||
ATH10K_SKB_CB(skb)->vdev_id = ath10k_tx_h_get_vdev_id(ar, vif);
|
||||
ATH10K_SKB_CB(skb)->txmode = ath10k_tx_h_get_txmode(ar, vif, sta, skb);
|
||||
ATH10K_SKB_CB(skb)->is_protected = ieee80211_has_protected(fc);
|
||||
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
|
||||
|
||||
switch (ATH10K_SKB_CB(skb)->txmode) {
|
||||
skb_cb->flags = 0;
|
||||
if (!ath10k_tx_h_use_hwcrypto(vif, skb))
|
||||
skb_cb->flags |= ATH10K_SKB_F_NO_HWCRYPT;
|
||||
|
||||
if (ieee80211_is_mgmt(hdr->frame_control))
|
||||
skb_cb->flags |= ATH10K_SKB_F_MGMT;
|
||||
|
||||
if (ieee80211_is_data_qos(hdr->frame_control))
|
||||
skb_cb->flags |= ATH10K_SKB_F_QOS;
|
||||
|
||||
skb_cb->vif = vif;
|
||||
|
||||
switch (txmode) {
|
||||
case ATH10K_HW_TXRX_MGMT:
|
||||
case ATH10K_HW_TXRX_NATIVE_WIFI:
|
||||
ath10k_tx_h_nwifi(hw, skb);
|
||||
|
@ -3668,15 +3690,7 @@ static void ath10k_tx(struct ieee80211_hw *hw,
|
|||
}
|
||||
|
||||
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
ATH10K_SKB_CB(skb)->htt.freq = ar->scan.roc_freq;
|
||||
ATH10K_SKB_CB(skb)->vdev_id = ar->scan.vdev_id;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
if (ath10k_mac_need_offchan_tx_work(ar)) {
|
||||
ATH10K_SKB_CB(skb)->htt.freq = 0;
|
||||
ATH10K_SKB_CB(skb)->htt.is_offchan = true;
|
||||
|
||||
if (!ath10k_mac_tx_frm_has_freq(ar)) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n",
|
||||
skb);
|
||||
|
||||
|
@ -3686,7 +3700,7 @@ static void ath10k_tx(struct ieee80211_hw *hw,
|
|||
}
|
||||
}
|
||||
|
||||
ath10k_mac_tx(ar, skb);
|
||||
ath10k_mac_tx(ar, txmode, skb);
|
||||
}
|
||||
|
||||
/* Must not be called with conf_mutex held as workers can use that also. */
|
||||
|
@ -4350,7 +4364,9 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
|||
arvif->vdev_type = WMI_VDEV_TYPE_IBSS;
|
||||
break;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
|
||||
if (test_bit(WMI_SERVICE_MESH, ar->wmi.svc_map)) {
|
||||
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH;
|
||||
} else if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
|
||||
ret = -EINVAL;
|
||||
ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n");
|
||||
goto err;
|
||||
|
@ -6907,35 +6923,39 @@ void ath10k_mac_destroy(struct ath10k *ar)
|
|||
|
||||
static const struct ieee80211_iface_limit ath10k_if_limits[] = {
|
||||
{
|
||||
.max = 8,
|
||||
.types = BIT(NL80211_IFTYPE_STATION)
|
||||
| BIT(NL80211_IFTYPE_P2P_CLIENT)
|
||||
.max = 8,
|
||||
.types = BIT(NL80211_IFTYPE_STATION)
|
||||
| BIT(NL80211_IFTYPE_P2P_CLIENT)
|
||||
},
|
||||
{
|
||||
.max = 3,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_GO)
|
||||
.max = 3,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_GO)
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
|
||||
},
|
||||
{
|
||||
.max = 7,
|
||||
.types = BIT(NL80211_IFTYPE_AP)
|
||||
.max = 7,
|
||||
.types = BIT(NL80211_IFTYPE_AP)
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
| BIT(NL80211_IFTYPE_MESH_POINT)
|
||||
| BIT(NL80211_IFTYPE_MESH_POINT)
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = {
|
||||
{
|
||||
.max = 8,
|
||||
.types = BIT(NL80211_IFTYPE_AP)
|
||||
.max = 8,
|
||||
.types = BIT(NL80211_IFTYPE_AP)
|
||||
#ifdef CONFIG_MAC80211_MESH
|
||||
| BIT(NL80211_IFTYPE_MESH_POINT)
|
||||
| BIT(NL80211_IFTYPE_MESH_POINT)
|
||||
#endif
|
||||
},
|
||||
{
|
||||
.max = 1,
|
||||
.types = BIT(NL80211_IFTYPE_STATION)
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ieee80211_iface_combination ath10k_if_comb[] = {
|
||||
|
|
|
@ -66,7 +66,7 @@ void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id,
|
|||
enum wmi_tlv_tx_pause_action action);
|
||||
|
||||
u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
|
||||
u8 hw_rate);
|
||||
u8 hw_rate, bool cck);
|
||||
u8 ath10k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
|
||||
u32 bitrate);
|
||||
|
||||
|
@ -74,6 +74,7 @@ void ath10k_mac_tx_lock(struct ath10k *ar, int reason);
|
|||
void ath10k_mac_tx_unlock(struct ath10k *ar, int reason);
|
||||
void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, int reason);
|
||||
void ath10k_mac_vif_tx_unlock(struct ath10k_vif *arvif, int reason);
|
||||
bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar);
|
||||
|
||||
static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
|
||||
{
|
||||
|
|
|
@ -111,6 +111,7 @@ static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state);
|
|||
static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state);
|
||||
static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state);
|
||||
static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state);
|
||||
static void ath10k_pci_pktlog_rx_cb(struct ath10k_ce_pipe *ce_state);
|
||||
|
||||
static const struct ce_attr host_ce_config_wlan[] = {
|
||||
/* CE0: host->target HTC control and raw streams */
|
||||
|
@ -189,6 +190,7 @@ static const struct ce_attr host_ce_config_wlan[] = {
|
|||
.src_nentries = 0,
|
||||
.src_sz_max = 2048,
|
||||
.dest_nentries = 128,
|
||||
.recv_cb = ath10k_pci_pktlog_rx_cb,
|
||||
},
|
||||
|
||||
/* CE9 target autonomous qcache memcpy */
|
||||
|
@ -1208,6 +1210,15 @@ static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state)
|
|||
ath10k_pci_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler);
|
||||
}
|
||||
|
||||
/* Called by lower (CE) layer when data is received from the Target.
|
||||
* Only 10.4 firmware uses separate CE to transfer pktlog data.
|
||||
*/
|
||||
static void ath10k_pci_pktlog_rx_cb(struct ath10k_ce_pipe *ce_state)
|
||||
{
|
||||
ath10k_pci_process_rx_cb(ce_state,
|
||||
ath10k_htt_rx_pktlog_completion_handler);
|
||||
}
|
||||
|
||||
/* Called by lower (CE) layer when a send to HTT Target completes. */
|
||||
static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state)
|
||||
{
|
||||
|
|
|
@ -187,7 +187,7 @@ int ath10k_thermal_register(struct ath10k *ar)
|
|||
/* Do not register hwmon device when temperature reading is not
|
||||
* supported by firmware
|
||||
*/
|
||||
if (ar->wmi.op_version != ATH10K_FW_WMI_OP_VERSION_10_2_4)
|
||||
if (!(ar->wmi.ops->gen_pdev_get_temperature))
|
||||
return 0;
|
||||
|
||||
/* Avoid linking error on devm_hwmon_device_register_with_groups, I
|
||||
|
|
|
@ -23,7 +23,12 @@
|
|||
|
||||
static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
if (!ATH10K_SKB_CB(skb)->htt.is_offchan)
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
|
||||
if (likely(!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)))
|
||||
return;
|
||||
|
||||
if (ath10k_mac_tx_frm_has_freq(ar))
|
||||
return;
|
||||
|
||||
/* If the original wait_for_completion() timed out before
|
||||
|
@ -52,8 +57,6 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
|||
struct ieee80211_tx_info *info;
|
||||
struct ath10k_skb_cb *skb_cb;
|
||||
struct sk_buff *msdu;
|
||||
struct ieee80211_hdr *hdr;
|
||||
__le16 fc;
|
||||
bool limit_mgmt_desc = false;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT,
|
||||
|
@ -76,10 +79,9 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
|||
return;
|
||||
}
|
||||
|
||||
hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
fc = hdr->frame_control;
|
||||
skb_cb = ATH10K_SKB_CB(msdu);
|
||||
|
||||
if (unlikely(ieee80211_is_mgmt(fc)) &&
|
||||
if (unlikely(skb_cb->flags & ATH10K_SKB_F_MGMT) &&
|
||||
ar->hw_params.max_probe_resp_desc_thres)
|
||||
limit_mgmt_desc = true;
|
||||
|
||||
|
@ -89,7 +91,6 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
|||
wake_up(&htt->empty_tx_wq);
|
||||
spin_unlock_bh(&htt->tx_lock);
|
||||
|
||||
skb_cb = ATH10K_SKB_CB(msdu);
|
||||
dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
|
||||
|
||||
ath10k_report_offchan_tx(htt->ar, msdu);
|
||||
|
|
|
@ -3485,6 +3485,24 @@ static const struct wmi_ops wmi_tlv_ops = {
|
|||
.fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
|
||||
};
|
||||
|
||||
static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
|
||||
.auth = WMI_TLV_PEER_AUTH,
|
||||
.qos = WMI_TLV_PEER_QOS,
|
||||
.need_ptk_4_way = WMI_TLV_PEER_NEED_PTK_4_WAY,
|
||||
.need_gtk_2_way = WMI_TLV_PEER_NEED_GTK_2_WAY,
|
||||
.apsd = WMI_TLV_PEER_APSD,
|
||||
.ht = WMI_TLV_PEER_HT,
|
||||
.bw40 = WMI_TLV_PEER_40MHZ,
|
||||
.stbc = WMI_TLV_PEER_STBC,
|
||||
.ldbc = WMI_TLV_PEER_LDPC,
|
||||
.dyn_mimops = WMI_TLV_PEER_DYN_MIMOPS,
|
||||
.static_mimops = WMI_TLV_PEER_STATIC_MIMOPS,
|
||||
.spatial_mux = WMI_TLV_PEER_SPATIAL_MUX,
|
||||
.vht = WMI_TLV_PEER_VHT,
|
||||
.bw80 = WMI_TLV_PEER_80MHZ,
|
||||
.pmf = WMI_TLV_PEER_PMF,
|
||||
};
|
||||
|
||||
/************/
|
||||
/* TLV init */
|
||||
/************/
|
||||
|
@ -3495,4 +3513,5 @@ void ath10k_wmi_tlv_attach(struct ath10k *ar)
|
|||
ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
|
||||
ar->wmi.ops = &wmi_tlv_ops;
|
||||
ar->wmi.peer_flags = &wmi_tlv_peer_flags_map;
|
||||
}
|
||||
|
|
|
@ -527,6 +527,24 @@ enum wmi_tlv_vdev_param {
|
|||
WMI_TLV_VDEV_PARAM_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE,
|
||||
};
|
||||
|
||||
enum wmi_tlv_peer_flags {
|
||||
WMI_TLV_PEER_AUTH = 0x00000001,
|
||||
WMI_TLV_PEER_QOS = 0x00000002,
|
||||
WMI_TLV_PEER_NEED_PTK_4_WAY = 0x00000004,
|
||||
WMI_TLV_PEER_NEED_GTK_2_WAY = 0x00000010,
|
||||
WMI_TLV_PEER_APSD = 0x00000800,
|
||||
WMI_TLV_PEER_HT = 0x00001000,
|
||||
WMI_TLV_PEER_40MHZ = 0x00002000,
|
||||
WMI_TLV_PEER_STBC = 0x00008000,
|
||||
WMI_TLV_PEER_LDPC = 0x00010000,
|
||||
WMI_TLV_PEER_DYN_MIMOPS = 0x00020000,
|
||||
WMI_TLV_PEER_STATIC_MIMOPS = 0x00040000,
|
||||
WMI_TLV_PEER_SPATIAL_MUX = 0x00200000,
|
||||
WMI_TLV_PEER_VHT = 0x02000000,
|
||||
WMI_TLV_PEER_80MHZ = 0x04000000,
|
||||
WMI_TLV_PEER_PMF = 0x08000000,
|
||||
};
|
||||
|
||||
enum wmi_tlv_tag {
|
||||
WMI_TLV_TAG_LAST_RESERVED = 15,
|
||||
|
||||
|
|
|
@ -1546,6 +1546,61 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
|
|||
.arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
|
||||
};
|
||||
|
||||
static const struct wmi_peer_flags_map wmi_peer_flags_map = {
|
||||
.auth = WMI_PEER_AUTH,
|
||||
.qos = WMI_PEER_QOS,
|
||||
.need_ptk_4_way = WMI_PEER_NEED_PTK_4_WAY,
|
||||
.need_gtk_2_way = WMI_PEER_NEED_GTK_2_WAY,
|
||||
.apsd = WMI_PEER_APSD,
|
||||
.ht = WMI_PEER_HT,
|
||||
.bw40 = WMI_PEER_40MHZ,
|
||||
.stbc = WMI_PEER_STBC,
|
||||
.ldbc = WMI_PEER_LDPC,
|
||||
.dyn_mimops = WMI_PEER_DYN_MIMOPS,
|
||||
.static_mimops = WMI_PEER_STATIC_MIMOPS,
|
||||
.spatial_mux = WMI_PEER_SPATIAL_MUX,
|
||||
.vht = WMI_PEER_VHT,
|
||||
.bw80 = WMI_PEER_80MHZ,
|
||||
.vht_2g = WMI_PEER_VHT_2G,
|
||||
.pmf = WMI_PEER_PMF,
|
||||
};
|
||||
|
||||
static const struct wmi_peer_flags_map wmi_10x_peer_flags_map = {
|
||||
.auth = WMI_10X_PEER_AUTH,
|
||||
.qos = WMI_10X_PEER_QOS,
|
||||
.need_ptk_4_way = WMI_10X_PEER_NEED_PTK_4_WAY,
|
||||
.need_gtk_2_way = WMI_10X_PEER_NEED_GTK_2_WAY,
|
||||
.apsd = WMI_10X_PEER_APSD,
|
||||
.ht = WMI_10X_PEER_HT,
|
||||
.bw40 = WMI_10X_PEER_40MHZ,
|
||||
.stbc = WMI_10X_PEER_STBC,
|
||||
.ldbc = WMI_10X_PEER_LDPC,
|
||||
.dyn_mimops = WMI_10X_PEER_DYN_MIMOPS,
|
||||
.static_mimops = WMI_10X_PEER_STATIC_MIMOPS,
|
||||
.spatial_mux = WMI_10X_PEER_SPATIAL_MUX,
|
||||
.vht = WMI_10X_PEER_VHT,
|
||||
.bw80 = WMI_10X_PEER_80MHZ,
|
||||
};
|
||||
|
||||
static const struct wmi_peer_flags_map wmi_10_2_peer_flags_map = {
|
||||
.auth = WMI_10_2_PEER_AUTH,
|
||||
.qos = WMI_10_2_PEER_QOS,
|
||||
.need_ptk_4_way = WMI_10_2_PEER_NEED_PTK_4_WAY,
|
||||
.need_gtk_2_way = WMI_10_2_PEER_NEED_GTK_2_WAY,
|
||||
.apsd = WMI_10_2_PEER_APSD,
|
||||
.ht = WMI_10_2_PEER_HT,
|
||||
.bw40 = WMI_10_2_PEER_40MHZ,
|
||||
.stbc = WMI_10_2_PEER_STBC,
|
||||
.ldbc = WMI_10_2_PEER_LDPC,
|
||||
.dyn_mimops = WMI_10_2_PEER_DYN_MIMOPS,
|
||||
.static_mimops = WMI_10_2_PEER_STATIC_MIMOPS,
|
||||
.spatial_mux = WMI_10_2_PEER_SPATIAL_MUX,
|
||||
.vht = WMI_10_2_PEER_VHT,
|
||||
.bw80 = WMI_10_2_PEER_80MHZ,
|
||||
.vht_2g = WMI_10_2_PEER_VHT_2G,
|
||||
.pmf = WMI_10_2_PEER_PMF,
|
||||
};
|
||||
|
||||
void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
|
||||
const struct wmi_channel_arg *arg)
|
||||
{
|
||||
|
@ -1660,6 +1715,8 @@ static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
|
|||
struct ath10k *ar = arvif->ar;
|
||||
struct ath10k_skb_cb *cb;
|
||||
struct sk_buff *bcn;
|
||||
bool dtim_zero;
|
||||
bool deliver_cab;
|
||||
int ret;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
@ -1679,12 +1736,14 @@ static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
|
|||
arvif->beacon_state = ATH10K_BEACON_SENDING;
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
dtim_zero = !!(cb->flags & ATH10K_SKB_F_DTIM_ZERO);
|
||||
deliver_cab = !!(cb->flags & ATH10K_SKB_F_DELIVER_CAB);
|
||||
ret = ath10k_wmi_beacon_send_ref_nowait(arvif->ar,
|
||||
arvif->vdev_id,
|
||||
bcn->data, bcn->len,
|
||||
cb->paddr,
|
||||
cb->bcn.dtim_zero,
|
||||
cb->bcn.deliver_cab);
|
||||
dtim_zero,
|
||||
deliver_cab);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
|
@ -1755,16 +1814,24 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
|
|||
static struct sk_buff *
|
||||
ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
|
||||
{
|
||||
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
|
||||
struct ath10k_vif *arvif = (void *)cb->vif->drv_priv;
|
||||
struct wmi_mgmt_tx_cmd *cmd;
|
||||
struct ieee80211_hdr *hdr;
|
||||
struct sk_buff *skb;
|
||||
int len;
|
||||
u32 vdev_id;
|
||||
u32 buf_len = msdu->len;
|
||||
u16 fc;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)msdu->data;
|
||||
fc = le16_to_cpu(hdr->frame_control);
|
||||
|
||||
if (cb->vif)
|
||||
vdev_id = arvif->vdev_id;
|
||||
else
|
||||
vdev_id = 0;
|
||||
|
||||
if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
|
@ -1786,7 +1853,7 @@ ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
|
|||
|
||||
cmd = (struct wmi_mgmt_tx_cmd *)skb->data;
|
||||
|
||||
cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(msdu)->vdev_id);
|
||||
cmd->hdr.vdev_id = __cpu_to_le32(vdev_id);
|
||||
cmd->hdr.tx_rate = 0;
|
||||
cmd->hdr.tx_power = 0;
|
||||
cmd->hdr.buf_len = __cpu_to_le32(buf_len);
|
||||
|
@ -2204,22 +2271,9 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
ath10k_dbg(ar, ATH10K_DBG_MGMT,
|
||||
"event mgmt rx status %08x\n", rx_status);
|
||||
|
||||
if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) {
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rx_status & WMI_RX_STATUS_ERR_DECRYPT) {
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rx_status & WMI_RX_STATUS_ERR_KEY_CACHE_MISS) {
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rx_status & WMI_RX_STATUS_ERR_CRC) {
|
||||
if ((test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) ||
|
||||
(rx_status & (WMI_RX_STATUS_ERR_DECRYPT |
|
||||
WMI_RX_STATUS_ERR_KEY_CACHE_MISS | WMI_RX_STATUS_ERR_CRC))) {
|
||||
dev_kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
@ -3115,10 +3169,10 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
|
|||
memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len);
|
||||
|
||||
if (tim->dtim_count == 0) {
|
||||
ATH10K_SKB_CB(bcn)->bcn.dtim_zero = true;
|
||||
ATH10K_SKB_CB(bcn)->flags |= ATH10K_SKB_F_DTIM_ZERO;
|
||||
|
||||
if (__le32_to_cpu(tim_info->tim_mcast) == 1)
|
||||
ATH10K_SKB_CB(bcn)->bcn.deliver_cab = true;
|
||||
ATH10K_SKB_CB(bcn)->flags |= ATH10K_SKB_F_DELIVER_CAB;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n",
|
||||
|
@ -5061,6 +5115,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
|
|||
case WMI_10_4_UPDATE_STATS_EVENTID:
|
||||
ath10k_wmi_event_update_stats(ar, skb);
|
||||
break;
|
||||
case WMI_10_4_PDEV_TEMPERATURE_EVENTID:
|
||||
ath10k_wmi_event_temperature(ar, skb);
|
||||
break;
|
||||
default:
|
||||
ath10k_warn(ar, "Unknown eventid: %d\n", id);
|
||||
break;
|
||||
|
@ -5431,8 +5488,11 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
|
|||
cmd = (struct wmi_init_cmd_10_2 *)buf->data;
|
||||
|
||||
features = WMI_10_2_RX_BATCH_MODE;
|
||||
if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
|
||||
|
||||
if (test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) &&
|
||||
test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
|
||||
features |= WMI_10_2_COEX_GPIO;
|
||||
|
||||
cmd->resource_config.feature_mask = __cpu_to_le32(features);
|
||||
|
||||
memcpy(&cmd->resource_config.common, &config, sizeof(config));
|
||||
|
@ -6328,6 +6388,16 @@ ath10k_wmi_peer_assoc_fill_10_2(struct ath10k *ar, void *buf,
|
|||
cmd->info0 = __cpu_to_le32(info0);
|
||||
}
|
||||
|
||||
static void
|
||||
ath10k_wmi_peer_assoc_fill_10_4(struct ath10k *ar, void *buf,
|
||||
const struct wmi_peer_assoc_complete_arg *arg)
|
||||
{
|
||||
struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf;
|
||||
|
||||
ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg);
|
||||
cmd->peer_bw_rxnss_override = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ath10k_wmi_peer_assoc_check_arg(const struct wmi_peer_assoc_complete_arg *arg)
|
||||
{
|
||||
|
@ -6416,6 +6486,31 @@ ath10k_wmi_10_2_op_gen_peer_assoc(struct ath10k *ar,
|
|||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_10_4_op_gen_peer_assoc(struct ath10k *ar,
|
||||
const struct wmi_peer_assoc_complete_arg *arg)
|
||||
{
|
||||
size_t len = sizeof(struct wmi_10_4_peer_assoc_complete_cmd);
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
ret = ath10k_wmi_peer_assoc_check_arg(arg);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
skb = ath10k_wmi_alloc_skb(ar, len);
|
||||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ath10k_wmi_peer_assoc_fill_10_4(ar, skb->data, arg);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi peer assoc vdev %d addr %pM (%s)\n",
|
||||
arg->vdev_id, arg->addr,
|
||||
arg->peer_reassoc ? "reassociate" : "new");
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_10_2_op_gen_pdev_get_temperature(struct ath10k *ar)
|
||||
{
|
||||
|
@ -7536,6 +7631,7 @@ static const struct wmi_ops wmi_10_4_ops = {
|
|||
.gen_peer_delete = ath10k_wmi_op_gen_peer_delete,
|
||||
.gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
|
||||
.gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param,
|
||||
.gen_peer_assoc = ath10k_wmi_10_4_op_gen_peer_assoc,
|
||||
.gen_set_psmode = ath10k_wmi_op_gen_set_psmode,
|
||||
.gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps,
|
||||
.gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps,
|
||||
|
@ -7555,8 +7651,8 @@ static const struct wmi_ops wmi_10_4_ops = {
|
|||
.fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill,
|
||||
|
||||
/* shared with 10.2 */
|
||||
.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
|
||||
.gen_request_stats = ath10k_wmi_op_gen_request_stats,
|
||||
.gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature,
|
||||
};
|
||||
|
||||
int ath10k_wmi_attach(struct ath10k *ar)
|
||||
|
@ -7567,30 +7663,35 @@ int ath10k_wmi_attach(struct ath10k *ar)
|
|||
ar->wmi.cmd = &wmi_10_4_cmd_map;
|
||||
ar->wmi.vdev_param = &wmi_10_4_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_10_4_pdev_param_map;
|
||||
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
|
||||
break;
|
||||
case ATH10K_FW_WMI_OP_VERSION_10_2_4:
|
||||
ar->wmi.cmd = &wmi_10_2_4_cmd_map;
|
||||
ar->wmi.ops = &wmi_10_2_4_ops;
|
||||
ar->wmi.vdev_param = &wmi_10_2_4_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_10_2_4_pdev_param_map;
|
||||
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
|
||||
break;
|
||||
case ATH10K_FW_WMI_OP_VERSION_10_2:
|
||||
ar->wmi.cmd = &wmi_10_2_cmd_map;
|
||||
ar->wmi.ops = &wmi_10_2_ops;
|
||||
ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
|
||||
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
|
||||
break;
|
||||
case ATH10K_FW_WMI_OP_VERSION_10_1:
|
||||
ar->wmi.cmd = &wmi_10x_cmd_map;
|
||||
ar->wmi.ops = &wmi_10_1_ops;
|
||||
ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
|
||||
ar->wmi.peer_flags = &wmi_10x_peer_flags_map;
|
||||
break;
|
||||
case ATH10K_FW_WMI_OP_VERSION_MAIN:
|
||||
ar->wmi.cmd = &wmi_cmd_map;
|
||||
ar->wmi.ops = &wmi_ops;
|
||||
ar->wmi.vdev_param = &wmi_vdev_param_map;
|
||||
ar->wmi.pdev_param = &wmi_pdev_param_map;
|
||||
ar->wmi.peer_flags = &wmi_peer_flags_map;
|
||||
break;
|
||||
case ATH10K_FW_WMI_OP_VERSION_TLV:
|
||||
ath10k_wmi_tlv_attach(ar);
|
||||
|
|
|
@ -175,6 +175,8 @@ enum wmi_service {
|
|||
WMI_SERVICE_AUX_SPECTRAL_INTF,
|
||||
WMI_SERVICE_AUX_CHAN_LOAD_INTF,
|
||||
WMI_SERVICE_BSS_CHANNEL_INFO_64,
|
||||
WMI_SERVICE_EXT_RES_CFG_SUPPORT,
|
||||
WMI_SERVICE_MESH,
|
||||
|
||||
/* keep last */
|
||||
WMI_SERVICE_MAX,
|
||||
|
@ -206,6 +208,11 @@ enum wmi_10x_service {
|
|||
WMI_10X_SERVICE_SMART_ANTENNA_HW_SUPPORT,
|
||||
WMI_10X_SERVICE_ATF,
|
||||
WMI_10X_SERVICE_COEX_GPIO,
|
||||
WMI_10X_SERVICE_AUX_SPECTRAL_INTF,
|
||||
WMI_10X_SERVICE_AUX_CHAN_LOAD_INTF,
|
||||
WMI_10X_SERVICE_BSS_CHANNEL_INFO_64,
|
||||
WMI_10X_SERVICE_MESH,
|
||||
WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT,
|
||||
};
|
||||
|
||||
enum wmi_main_service {
|
||||
|
@ -286,6 +293,8 @@ enum wmi_10_4_service {
|
|||
WMI_10_4_SERVICE_AUX_SPECTRAL_INTF,
|
||||
WMI_10_4_SERVICE_AUX_CHAN_LOAD_INTF,
|
||||
WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64,
|
||||
WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT,
|
||||
WMI_10_4_SERVICE_MESH,
|
||||
};
|
||||
|
||||
static inline char *wmi_service_name(int service_id)
|
||||
|
@ -375,6 +384,8 @@ static inline char *wmi_service_name(int service_id)
|
|||
SVCSTR(WMI_SERVICE_AUX_SPECTRAL_INTF);
|
||||
SVCSTR(WMI_SERVICE_AUX_CHAN_LOAD_INTF);
|
||||
SVCSTR(WMI_SERVICE_BSS_CHANNEL_INFO_64);
|
||||
SVCSTR(WMI_SERVICE_EXT_RES_CFG_SUPPORT);
|
||||
SVCSTR(WMI_SERVICE_MESH);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -442,6 +453,16 @@ static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out,
|
|||
WMI_SERVICE_ATF, len);
|
||||
SVCMAP(WMI_10X_SERVICE_COEX_GPIO,
|
||||
WMI_SERVICE_COEX_GPIO, len);
|
||||
SVCMAP(WMI_10X_SERVICE_AUX_SPECTRAL_INTF,
|
||||
WMI_SERVICE_AUX_SPECTRAL_INTF, len);
|
||||
SVCMAP(WMI_10X_SERVICE_AUX_CHAN_LOAD_INTF,
|
||||
WMI_SERVICE_AUX_CHAN_LOAD_INTF, len);
|
||||
SVCMAP(WMI_10X_SERVICE_BSS_CHANNEL_INFO_64,
|
||||
WMI_SERVICE_BSS_CHANNEL_INFO_64, len);
|
||||
SVCMAP(WMI_10X_SERVICE_MESH,
|
||||
WMI_SERVICE_MESH, len);
|
||||
SVCMAP(WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT,
|
||||
WMI_SERVICE_EXT_RES_CFG_SUPPORT, len);
|
||||
}
|
||||
|
||||
static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out,
|
||||
|
@ -600,6 +621,10 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
|
|||
WMI_SERVICE_AUX_CHAN_LOAD_INTF, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64,
|
||||
WMI_SERVICE_BSS_CHANNEL_INFO_64, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT,
|
||||
WMI_SERVICE_EXT_RES_CFG_SUPPORT, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_MESH,
|
||||
WMI_SERVICE_MESH, len);
|
||||
}
|
||||
|
||||
#undef SVCMAP
|
||||
|
@ -1576,6 +1601,9 @@ enum wmi_10_4_cmd_id {
|
|||
WMI_10_4_MU_CAL_START_CMDID,
|
||||
WMI_10_4_SET_CCA_PARAMS_CMDID,
|
||||
WMI_10_4_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
|
||||
WMI_10_4_EXT_RESOURCE_CFG_CMDID,
|
||||
WMI_10_4_VDEV_SET_IE_CMDID,
|
||||
WMI_10_4_SET_LTEU_CONFIG_CMDID,
|
||||
WMI_10_4_PDEV_UTF_CMDID = WMI_10_4_END_CMDID - 1,
|
||||
};
|
||||
|
||||
|
@ -1638,6 +1666,7 @@ enum wmi_10_4_event_id {
|
|||
WMI_10_4_PDEV_TEMPERATURE_EVENTID,
|
||||
WMI_10_4_PDEV_NFCAL_POWER_ALL_CHANNELS_EVENTID,
|
||||
WMI_10_4_PDEV_BSS_CHAN_INFO_EVENTID,
|
||||
WMI_10_4_MU_REPORT_EVENTID,
|
||||
WMI_10_4_PDEV_UTF_EVENTID = WMI_10_4_END_EVENTID - 1,
|
||||
};
|
||||
|
||||
|
@ -3650,6 +3679,12 @@ enum wmi_10_4_pdev_param {
|
|||
WMI_10_4_PDEV_PARAM_WAPI_MBSSID_OFFSET,
|
||||
WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
|
||||
WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
|
||||
WMI_10_4_PDEV_PARAM_TXPOWER_DECR_DB,
|
||||
WMI_10_4_PDEV_PARAM_RX_BATCHMODE,
|
||||
WMI_10_4_PDEV_PARAM_PACKET_AGGR_DELAY,
|
||||
WMI_10_4_PDEV_PARAM_ATF_OBSS_NOISE_SCH,
|
||||
WMI_10_4_PDEV_PARAM_ATF_OBSS_NOISE_SCALING_FACTOR,
|
||||
WMI_10_4_PDEV_PARAM_CUST_TXPOWER_SCALE,
|
||||
};
|
||||
|
||||
struct wmi_pdev_set_param_cmd {
|
||||
|
@ -4239,6 +4274,8 @@ enum wmi_vdev_subtype {
|
|||
WMI_VDEV_SUBTYPE_P2P_DEVICE = 1,
|
||||
WMI_VDEV_SUBTYPE_P2P_CLIENT = 2,
|
||||
WMI_VDEV_SUBTYPE_P2P_GO = 3,
|
||||
WMI_VDEV_SUBTYPE_PROXY_STA = 4,
|
||||
WMI_VDEV_SUBTYPE_MESH = 5,
|
||||
};
|
||||
|
||||
/* values for vdev_subtype */
|
||||
|
@ -5641,21 +5678,79 @@ struct wmi_peer_set_q_empty_callback_cmd {
|
|||
__le32 callback_enable;
|
||||
} __packed;
|
||||
|
||||
#define WMI_PEER_AUTH 0x00000001
|
||||
#define WMI_PEER_QOS 0x00000002
|
||||
#define WMI_PEER_NEED_PTK_4_WAY 0x00000004
|
||||
#define WMI_PEER_NEED_GTK_2_WAY 0x00000010
|
||||
#define WMI_PEER_APSD 0x00000800
|
||||
#define WMI_PEER_HT 0x00001000
|
||||
#define WMI_PEER_40MHZ 0x00002000
|
||||
#define WMI_PEER_STBC 0x00008000
|
||||
#define WMI_PEER_LDPC 0x00010000
|
||||
#define WMI_PEER_DYN_MIMOPS 0x00020000
|
||||
#define WMI_PEER_STATIC_MIMOPS 0x00040000
|
||||
#define WMI_PEER_SPATIAL_MUX 0x00200000
|
||||
#define WMI_PEER_VHT 0x02000000
|
||||
#define WMI_PEER_80MHZ 0x04000000
|
||||
#define WMI_PEER_VHT_2G 0x08000000
|
||||
struct wmi_peer_flags_map {
|
||||
u32 auth;
|
||||
u32 qos;
|
||||
u32 need_ptk_4_way;
|
||||
u32 need_gtk_2_way;
|
||||
u32 apsd;
|
||||
u32 ht;
|
||||
u32 bw40;
|
||||
u32 stbc;
|
||||
u32 ldbc;
|
||||
u32 dyn_mimops;
|
||||
u32 static_mimops;
|
||||
u32 spatial_mux;
|
||||
u32 vht;
|
||||
u32 bw80;
|
||||
u32 vht_2g;
|
||||
u32 pmf;
|
||||
};
|
||||
|
||||
enum wmi_peer_flags {
|
||||
WMI_PEER_AUTH = 0x00000001,
|
||||
WMI_PEER_QOS = 0x00000002,
|
||||
WMI_PEER_NEED_PTK_4_WAY = 0x00000004,
|
||||
WMI_PEER_NEED_GTK_2_WAY = 0x00000010,
|
||||
WMI_PEER_APSD = 0x00000800,
|
||||
WMI_PEER_HT = 0x00001000,
|
||||
WMI_PEER_40MHZ = 0x00002000,
|
||||
WMI_PEER_STBC = 0x00008000,
|
||||
WMI_PEER_LDPC = 0x00010000,
|
||||
WMI_PEER_DYN_MIMOPS = 0x00020000,
|
||||
WMI_PEER_STATIC_MIMOPS = 0x00040000,
|
||||
WMI_PEER_SPATIAL_MUX = 0x00200000,
|
||||
WMI_PEER_VHT = 0x02000000,
|
||||
WMI_PEER_80MHZ = 0x04000000,
|
||||
WMI_PEER_VHT_2G = 0x08000000,
|
||||
WMI_PEER_PMF = 0x10000000,
|
||||
};
|
||||
|
||||
enum wmi_10x_peer_flags {
|
||||
WMI_10X_PEER_AUTH = 0x00000001,
|
||||
WMI_10X_PEER_QOS = 0x00000002,
|
||||
WMI_10X_PEER_NEED_PTK_4_WAY = 0x00000004,
|
||||
WMI_10X_PEER_NEED_GTK_2_WAY = 0x00000010,
|
||||
WMI_10X_PEER_APSD = 0x00000800,
|
||||
WMI_10X_PEER_HT = 0x00001000,
|
||||
WMI_10X_PEER_40MHZ = 0x00002000,
|
||||
WMI_10X_PEER_STBC = 0x00008000,
|
||||
WMI_10X_PEER_LDPC = 0x00010000,
|
||||
WMI_10X_PEER_DYN_MIMOPS = 0x00020000,
|
||||
WMI_10X_PEER_STATIC_MIMOPS = 0x00040000,
|
||||
WMI_10X_PEER_SPATIAL_MUX = 0x00200000,
|
||||
WMI_10X_PEER_VHT = 0x02000000,
|
||||
WMI_10X_PEER_80MHZ = 0x04000000,
|
||||
};
|
||||
|
||||
enum wmi_10_2_peer_flags {
|
||||
WMI_10_2_PEER_AUTH = 0x00000001,
|
||||
WMI_10_2_PEER_QOS = 0x00000002,
|
||||
WMI_10_2_PEER_NEED_PTK_4_WAY = 0x00000004,
|
||||
WMI_10_2_PEER_NEED_GTK_2_WAY = 0x00000010,
|
||||
WMI_10_2_PEER_APSD = 0x00000800,
|
||||
WMI_10_2_PEER_HT = 0x00001000,
|
||||
WMI_10_2_PEER_40MHZ = 0x00002000,
|
||||
WMI_10_2_PEER_STBC = 0x00008000,
|
||||
WMI_10_2_PEER_LDPC = 0x00010000,
|
||||
WMI_10_2_PEER_DYN_MIMOPS = 0x00020000,
|
||||
WMI_10_2_PEER_STATIC_MIMOPS = 0x00040000,
|
||||
WMI_10_2_PEER_SPATIAL_MUX = 0x00200000,
|
||||
WMI_10_2_PEER_VHT = 0x02000000,
|
||||
WMI_10_2_PEER_80MHZ = 0x04000000,
|
||||
WMI_10_2_PEER_VHT_2G = 0x08000000,
|
||||
WMI_10_2_PEER_PMF = 0x10000000,
|
||||
};
|
||||
|
||||
/*
|
||||
* Peer rate capabilities.
|
||||
|
@ -5721,6 +5816,11 @@ struct wmi_10_2_peer_assoc_complete_cmd {
|
|||
__le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
|
||||
} __packed;
|
||||
|
||||
struct wmi_10_4_peer_assoc_complete_cmd {
|
||||
struct wmi_10_2_peer_assoc_complete_cmd cmd;
|
||||
__le32 peer_bw_rxnss_override;
|
||||
} __packed;
|
||||
|
||||
struct wmi_peer_assoc_complete_arg {
|
||||
u8 addr[ETH_ALEN];
|
||||
u32 vdev_id;
|
||||
|
|
|
@ -401,20 +401,26 @@ void wil_bcast_fini(struct wil6210_priv *wil)
|
|||
|
||||
static void wil_connect_worker(struct work_struct *work)
|
||||
{
|
||||
int rc;
|
||||
int rc, cid, ringid;
|
||||
struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
|
||||
connect_worker);
|
||||
struct net_device *ndev = wil_to_ndev(wil);
|
||||
|
||||
int cid = wil->pending_connect_cid;
|
||||
int ringid = wil_find_free_vring(wil);
|
||||
mutex_lock(&wil->mutex);
|
||||
|
||||
cid = wil->pending_connect_cid;
|
||||
if (cid < 0) {
|
||||
wil_err(wil, "No connection pending\n");
|
||||
return;
|
||||
goto out;
|
||||
}
|
||||
ringid = wil_find_free_vring(wil);
|
||||
if (ringid < 0) {
|
||||
wil_err(wil, "No free vring found\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
wil_dbg_wmi(wil, "Configure for connection CID %d\n", cid);
|
||||
wil_dbg_wmi(wil, "Configure for connection CID %d vring %d\n",
|
||||
cid, ringid);
|
||||
|
||||
rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0);
|
||||
wil->pending_connect_cid = -1;
|
||||
|
@ -424,6 +430,8 @@ static void wil_connect_worker(struct work_struct *work)
|
|||
} else {
|
||||
wil_disconnect_cid(wil, cid, WLAN_REASON_UNSPECIFIED, true);
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&wil->mutex);
|
||||
}
|
||||
|
||||
int wil_priv_init(struct wil6210_priv *wil)
|
||||
|
|
|
@ -160,6 +160,7 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
|
|||
struct device *dev = wil_to_dev(wil);
|
||||
size_t sz = vring->size * sizeof(vring->va[0]);
|
||||
|
||||
lockdep_assert_held(&wil->mutex);
|
||||
if (tx) {
|
||||
int vring_index = vring - wil->vring_tx;
|
||||
|
||||
|
@ -749,6 +750,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
|
|||
|
||||
wil_dbg_misc(wil, "%s() max_mpdu_size %d\n", __func__,
|
||||
cmd.vring_cfg.tx_sw_ring.max_mpdu_size);
|
||||
lockdep_assert_held(&wil->mutex);
|
||||
|
||||
if (vring->va) {
|
||||
wil_err(wil, "Tx ring [%d] already allocated\n", id);
|
||||
|
@ -821,6 +823,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
|
|||
|
||||
wil_dbg_misc(wil, "%s() max_mpdu_size %d\n", __func__,
|
||||
cmd.vring_cfg.tx_sw_ring.max_mpdu_size);
|
||||
lockdep_assert_held(&wil->mutex);
|
||||
|
||||
if (vring->va) {
|
||||
wil_err(wil, "Tx ring [%d] already allocated\n", id);
|
||||
|
@ -872,7 +875,7 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
|
|||
struct vring *vring = &wil->vring_tx[id];
|
||||
struct vring_tx_data *txdata = &wil->vring_tx_data[id];
|
||||
|
||||
WARN_ON(!mutex_is_locked(&wil->mutex));
|
||||
lockdep_assert_held(&wil->mutex);
|
||||
|
||||
if (!vring->va)
|
||||
return;
|
||||
|
|
Loading…
Reference in New Issue