* support bcm4359 which can operate in two bands concurrently
 * disable runtime pm for USB avoiding issues
 * use generic pm callback in PCIe driver
 * support wowlan wake indication reporting
 * add beamforming support
 * unified handling of firmware files
 
 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
 
 iwlwifi
 
 * BT coex improvements
 * D3 operation bugfixes
 * rate control improvements
 * firmware debugging infra improvements
 * ground work for multi Rx
 * various security fixes
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQEcBAABAgAGBQJWZcQtAAoJEG4XJFUm622bgcMH/1VRwtzAKpYVwAyAN0MtVLxe
 uANi0Pw1PmEAeEI3TxEBckEH0JYfpg+aAwX7S8scnQSvLP3FYeC5IcHG551vlh0s
 FlkGexcXqGrDqjt8mz8hxqqAmMH9YEVlzj2HJf6YFjNS4K84CEgpaSjaSG8S7Wc8
 hTSA5K+XxrnEeX41W7FYmeBFLejisg0gVTkS3ZCe4qYz4Gh1oamoA0pOdU+AYOMy
 0XBkCT8fqTVXWLHh9/+J7IZOYrjBl4rVaHofeygEAfSRNNfmmjZXX1R+FCQoJEZC
 IOEQ31T64G4A37t2N2RGOhiG+2vckdbPg2JsqJosI1L2OZSBbeGZsVW48w+5cgc=
 =GQDA
 -----END PGP SIGNATURE-----

Merge tag 'wireless-drivers-next-for-davem-2015-12-07' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Vallo says:

====================
brcfmac

* support bcm4359 which can operate in two bands concurrently
* disable runtime pm for USB avoiding issues
* use generic pm callback in PCIe driver
* support wowlan wake indication reporting
* add beamforming support
* unified handling of firmware files

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

iwlwifi

* BT coex improvements
* D3 operation bugfixes
* rate control improvements
* firmware debugging infra improvements
* ground work for multi Rx
* various security fixes
====================

Conflicts:
	drivers/net/wireless/ath/ath10k/pci.c

The conflict resolution at:

	http://article.gmane.org/gmane.linux.kernel.next/37391

by Stephen Rothwell was used.

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2015-12-08 12:39:15 -05:00
commit e370abd956
147 changed files with 3290 additions and 2066 deletions

View file

@ -2,6 +2,7 @@ config ATH10K
tristate "Atheros 802.11ac wireless cards support" tristate "Atheros 802.11ac wireless cards support"
depends on MAC80211 && HAS_DMA depends on MAC80211 && HAS_DMA
select ATH_COMMON select ATH_COMMON
select CRC32
---help--- ---help---
This module adds support for wireless adapters based on This module adds support for wireless adapters based on
Atheros IEEE 802.11ac family of chipsets. Atheros IEEE 802.11ac family of chipsets.

View file

@ -59,6 +59,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.otp_exe_param = 0, .otp_exe_param = 0,
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0, .max_probe_resp_desc_thres = 0,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
.fw = { .fw = {
.dir = QCA988X_HW_2_0_FW_DIR, .dir = QCA988X_HW_2_0_FW_DIR,
.fw = QCA988X_HW_2_0_FW_FILE, .fw = QCA988X_HW_2_0_FW_FILE,
@ -95,6 +96,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.otp_exe_param = 0, .otp_exe_param = 0,
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0, .max_probe_resp_desc_thres = 0,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
.fw = { .fw = {
.dir = QCA6174_HW_2_1_FW_DIR, .dir = QCA6174_HW_2_1_FW_DIR,
.fw = QCA6174_HW_2_1_FW_FILE, .fw = QCA6174_HW_2_1_FW_FILE,
@ -113,6 +115,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.otp_exe_param = 0, .otp_exe_param = 0,
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0, .max_probe_resp_desc_thres = 0,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
.fw = { .fw = {
.dir = QCA6174_HW_3_0_FW_DIR, .dir = QCA6174_HW_3_0_FW_DIR,
.fw = QCA6174_HW_3_0_FW_FILE, .fw = QCA6174_HW_3_0_FW_FILE,
@ -131,6 +134,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.otp_exe_param = 0, .otp_exe_param = 0,
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0, .max_probe_resp_desc_thres = 0,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
.fw = { .fw = {
/* uses same binaries as hw3.0 */ /* uses same binaries as hw3.0 */
.dir = QCA6174_HW_3_0_FW_DIR, .dir = QCA6174_HW_3_0_FW_DIR,
@ -151,6 +155,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.continuous_frag_desc = true, .continuous_frag_desc = true,
.channel_counters_freq_hz = 150000, .channel_counters_freq_hz = 150000,
.max_probe_resp_desc_thres = 24, .max_probe_resp_desc_thres = 24,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
.fw = { .fw = {
.dir = QCA99X0_HW_2_0_FW_DIR, .dir = QCA99X0_HW_2_0_FW_DIR,
.fw = QCA99X0_HW_2_0_FW_FILE, .fw = QCA99X0_HW_2_0_FW_FILE,
@ -211,6 +216,7 @@ static const char *const ath10k_core_fw_feature_str[] = {
[ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init", [ATH10K_FW_FEATURE_SUPPORTS_SKIP_CLOCK_INIT] = "skip-clock-init",
[ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode", [ATH10K_FW_FEATURE_RAW_MODE_SUPPORT] = "raw-mode",
[ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca", [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, static unsigned int ath10k_core_get_fw_feature_str(char *buf,
@ -887,7 +893,7 @@ out:
if (!ar->board_data || !ar->board_len) { if (!ar->board_data || !ar->board_len) {
ath10k_err(ar, ath10k_err(ar,
"failed to fetch board data for %s from %s/%s\n", "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; ret = -ENODATA;
goto err; goto err;
} }
@ -1790,9 +1796,11 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
goto err_power_down; goto err_power_down;
} }
ath10k_debug_print_hwfw_info(ar);
ret = ath10k_core_get_board_id_from_otp(ar); ret = ath10k_core_get_board_id_from_otp(ar);
if (ret && ret != -EOPNOTSUPP) { 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); ret);
return ret; return ret;
} }
@ -1803,6 +1811,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
goto err_free_firmware_files; goto err_free_firmware_files;
} }
ath10k_debug_print_board_info(ar);
ret = ath10k_core_init_firmware_features(ar); ret = ath10k_core_init_firmware_features(ar);
if (ret) { if (ret) {
ath10k_err(ar, "fatal problem with firmware features: %d\n", ath10k_err(ar, "fatal problem with firmware features: %d\n",
@ -1825,7 +1835,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
goto err_unlock; goto err_unlock;
} }
ath10k_print_driver_info(ar); ath10k_debug_print_boot_info(ar);
ath10k_core_stop(ar); ath10k_core_stop(ar);
mutex_unlock(&ar->conf_mutex); mutex_unlock(&ar->conf_mutex);

View file

@ -81,26 +81,20 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus)
return "unknown"; 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 { struct ath10k_skb_cb {
dma_addr_t paddr; dma_addr_t paddr;
u8 flags;
u8 eid; u8 eid;
u8 vdev_id; u16 msdu_id;
enum ath10k_hw_txrx_mode txmode; struct ieee80211_vif *vif;
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;
} __packed; } __packed;
struct ath10k_skb_rxcb { struct ath10k_skb_rxcb {
@ -151,6 +145,7 @@ struct ath10k_wmi {
struct wmi_vdev_param_map *vdev_param; struct wmi_vdev_param_map *vdev_param;
struct wmi_pdev_param_map *pdev_param; struct wmi_pdev_param_map *pdev_param;
const struct wmi_ops *ops; const struct wmi_ops *ops;
const struct wmi_peer_flags_map *peer_flags;
u32 num_mem_chunks; u32 num_mem_chunks;
u32 rx_decap_mode; u32 rx_decap_mode;
@ -512,6 +507,9 @@ enum ath10k_fw_features {
/* Firmware Supports Adaptive CCA*/ /* Firmware Supports Adaptive CCA*/
ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11, ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11,
/* Firmware supports management frame protection */
ATH10K_FW_FEATURE_MFP_SUPPORT = 12,
/* keep last */ /* keep last */
ATH10K_FW_FEATURE_COUNT, ATH10K_FW_FEATURE_COUNT,
}; };
@ -534,6 +532,9 @@ enum ath10k_dev_flags {
/* Disable HW crypto engine */ /* Disable HW crypto engine */
ATH10K_FLAG_HW_CRYPTO_DISABLED, ATH10K_FLAG_HW_CRYPTO_DISABLED,
/* Bluetooth coexistance enabled */
ATH10K_FLAG_BTCOEX,
}; };
enum ath10k_cal_mode { enum ath10k_cal_mode {
@ -662,6 +663,9 @@ struct ath10k {
*/ */
u32 max_probe_resp_desc_thres; 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 { struct ath10k_hw_params_fw {
const char *dir; const char *dir;
const char *fw; const char *fw;

View file

@ -19,6 +19,8 @@
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/utsname.h> #include <linux/utsname.h>
#include <linux/crc32.h>
#include <linux/firmware.h>
#include "core.h" #include "core.h"
#include "debug.h" #include "debug.h"
@ -122,28 +124,51 @@ void ath10k_info(struct ath10k *ar, const char *fmt, ...)
} }
EXPORT_SYMBOL(ath10k_info); 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 fw_features[128] = {};
char boardinfo[100];
ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features)); ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
if (ar->id.bmi_ids_valid) ath10k_info(ar, "%s target 0x%08x chip_id 0x%08x sub %04x:%04x",
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",
ar->hw_params.name, ar->hw_params.name,
ar->target_version, ar->target_version,
ar->chip_id, 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->hw->wiphy->fw_version,
ar->fw_api, 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, 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_major,
ar->htt.target_version_minor, ar->htt.target_version_minor,
ar->wmi.op_version, ar->wmi.op_version,
@ -151,14 +176,14 @@ void ath10k_print_driver_info(struct ath10k *ar)
ath10k_cal_mode_str(ar->cal_mode), ath10k_cal_mode_str(ar->cal_mode),
ar->max_num_stations, ar->max_num_stations,
test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags), test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
!test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &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), void ath10k_print_driver_info(struct ath10k *ar)
config_enabled(CONFIG_ATH10K_DEBUGFS), {
config_enabled(CONFIG_ATH10K_TRACING), ath10k_debug_print_hwfw_info(ar);
config_enabled(CONFIG_ATH10K_DFS_CERTIFIED), ath10k_debug_print_board_info(ar);
config_enabled(CONFIG_NL80211_TESTMODE)); ath10k_debug_print_boot_info(ar);
} }
EXPORT_SYMBOL(ath10k_print_driver_info); EXPORT_SYMBOL(ath10k_print_driver_info);
@ -2074,6 +2099,121 @@ static const struct file_operations fops_quiet_period = {
.open = simple_open .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) int ath10k_debug_create(struct ath10k *ar)
{ {
ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data)); 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, debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
&fops_wmi_services); &fops_wmi_services);
debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy, debugfs_create_file("simulate_fw_crash", S_IRUSR | S_IWUSR,
ar, &fops_simulate_fw_crash); ar->debug.debugfs_phy, ar, &fops_simulate_fw_crash);
debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy, debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_fw_crash_dump); 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, debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_chip_id); ar, &fops_chip_id);
debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy, debugfs_create_file("htt_stats_mask", S_IRUSR | S_IWUSR,
ar, &fops_htt_stats_mask); ar->debug.debugfs_phy, ar, &fops_htt_stats_mask);
debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR, debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar, ar->debug.debugfs_phy, ar,
&fops_htt_max_amsdu_ampdu); &fops_htt_max_amsdu_ampdu);
debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy, debugfs_create_file("fw_dbglog", S_IRUSR | S_IWUSR,
ar, &fops_fw_dbglog); ar->debug.debugfs_phy, ar, &fops_fw_dbglog);
debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy, debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_cal_data); ar, &fops_cal_data);
@ -2183,6 +2323,13 @@ int ath10k_debug_register(struct ath10k *ar)
debugfs_create_file("tpc_stats", S_IRUSR, debugfs_create_file("tpc_stats", S_IRUSR,
ar->debug.debugfs_phy, ar, &fops_tpc_stats); 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; return 0;
} }

View file

@ -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_info(struct ath10k *ar, const char *fmt, ...);
__printf(2, 3) void ath10k_err(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, ...); __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); void ath10k_print_driver_info(struct ath10k *ar);
#ifdef CONFIG_ATH10K_DEBUGFS #ifdef CONFIG_ATH10K_DEBUGFS

View file

@ -166,8 +166,13 @@ struct htt_data_tx_desc {
__le16 len; __le16 len;
__le16 id; __le16 id;
__le32 frags_paddr; __le32 frags_paddr;
__le16 peerid; union {
__le16 freq; __le32 peerid;
struct {
__le16 peerid;
__le16 freq;
} __packed offchan_tx;
} __packed;
u8 prefetch[0]; /* start of frame, for FW classification engine */ u8 prefetch[0]; /* start of frame, for FW classification engine */
} __packed; } __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); 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); void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id);
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *); int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *);
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 #endif

View file

@ -536,7 +536,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
size = htt->rx_ring.size * sizeof(htt->rx_ring.paddrs_ring); 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) if (!vaddr)
goto err_dma_ring; goto err_dma_ring;
@ -545,7 +545,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
vaddr = dma_alloc_coherent(htt->ar->dev, vaddr = dma_alloc_coherent(htt->ar->dev,
sizeof(*htt->rx_ring.alloc_idx.vaddr), sizeof(*htt->rx_ring.alloc_idx.vaddr),
&paddr, GFP_DMA); &paddr, GFP_KERNEL);
if (!vaddr) if (!vaddr)
goto err_dma_idx; goto err_dma_idx;
@ -674,7 +674,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
rate &= ~RX_PPDU_START_RATE_FLAG; rate &= ~RX_PPDU_START_RATE_FLAG;
sband = &ar->mac.sbands[status->band]; 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; break;
case HTT_RX_HT: case HTT_RX_HT:
case HTT_RX_HT_WITH_TXBF: 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 */ /* 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); hdr_len = ath10k_htt_rx_nwifi_hdrlen(ar, hdr);
ether_addr_copy(da, ieee80211_get_DA(hdr)); ether_addr_copy(da, ieee80211_get_DA(hdr));
ether_addr_copy(sa, ieee80211_get_SA(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); 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) static void ath10k_htt_txrx_compl_task(unsigned long ptr)
{ {
struct ath10k_htt *htt = (struct ath10k_htt *)ptr; struct ath10k_htt *htt = (struct ath10k_htt *)ptr;

View file

@ -111,7 +111,7 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf); size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf);
htt->txbuf.vaddr = dma_alloc_coherent(ar->dev, size, htt->txbuf.vaddr = dma_alloc_coherent(ar->dev, size,
&htt->txbuf.paddr, &htt->txbuf.paddr,
GFP_DMA); GFP_KERNEL);
if (!htt->txbuf.vaddr) { if (!htt->txbuf.vaddr) {
ath10k_err(ar, "failed to alloc tx buffer\n"); ath10k_err(ar, "failed to alloc tx buffer\n");
ret = -ENOMEM; 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); 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.vaddr = dma_alloc_coherent(ar->dev, size,
&htt->frag_desc.paddr, &htt->frag_desc.paddr,
GFP_DMA); GFP_KERNEL);
if (!htt->frag_desc.vaddr) { if (!htt->frag_desc.vaddr) {
ath10k_warn(ar, "failed to alloc fragment desc memory\n"); ath10k_warn(ar, "failed to alloc fragment desc memory\n");
ret = -ENOMEM; ret = -ENOMEM;
@ -439,6 +439,35 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
return 0; 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) int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
{ {
struct ath10k *ar = htt->ar; 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 sk_buff *txdesc = NULL;
struct htt_cmd *cmd; struct htt_cmd *cmd;
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); 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 len = 0;
int msdu_id = -1; int msdu_id = -1;
int res; int res;
@ -477,6 +506,13 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
msdu_id = res; 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); txdesc = ath10k_htc_alloc_skb(ar, len);
if (!txdesc) { if (!txdesc) {
res = -ENOMEM; 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, memcpy(cmd->mgmt_tx.hdr, msdu->data,
min_t(int, msdu->len, HTT_MGMT_FRM_HDR_DOWNLOAD_LEN)); 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); res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc);
if (res) if (res)
goto err_unmap_msdu; goto err_unmap_msdu;
@ -525,21 +559,27 @@ err:
return res; 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 ath10k *ar = htt->ar;
struct device *dev = ar->dev; struct device *dev = ar->dev;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; 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_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
struct ath10k_hif_sg_item sg_items[2]; struct ath10k_hif_sg_item sg_items[2];
struct ath10k_htt_txbuf *txbuf;
struct htt_data_tx_desc_frag *frags; struct htt_data_tx_desc_frag *frags;
u8 vdev_id = skb_cb->vdev_id; bool is_eth = (txmode == ATH10K_HW_TXRX_ETHERNET);
u8 tid = skb_cb->htt.tid; 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 prefetch_len;
int res; int res;
u8 flags0 = 0; u8 flags0 = 0;
u16 msdu_id, flags1 = 0; u16 msdu_id, flags1 = 0;
u16 freq = 0;
u32 frags_paddr = 0; u32 frags_paddr = 0;
u32 txbuf_paddr;
struct htt_msdu_ext_desc *ext_desc = NULL; struct htt_msdu_ext_desc *ext_desc = NULL;
bool limit_mgmt_desc = false; bool limit_mgmt_desc = false;
bool is_probe_resp = 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 = min(htt->prefetch_len, msdu->len);
prefetch_len = roundup(prefetch_len, 4); prefetch_len = roundup(prefetch_len, 4);
skb_cb->htt.txbuf = &htt->txbuf.vaddr[msdu_id]; txbuf = &htt->txbuf.vaddr[msdu_id];
skb_cb->htt.txbuf_paddr = htt->txbuf.paddr + txbuf_paddr = htt->txbuf.paddr +
(sizeof(struct ath10k_htt_txbuf) * msdu_id); (sizeof(struct ath10k_htt_txbuf) * msdu_id);
if ((ieee80211_is_action(hdr->frame_control) || if ((ieee80211_is_action(hdr->frame_control) ||
ieee80211_is_deauth(hdr->frame_control) || ieee80211_is_deauth(hdr->frame_control) ||
ieee80211_is_disassoc(hdr->frame_control)) && ieee80211_is_disassoc(hdr->frame_control)) &&
ieee80211_has_protected(hdr->frame_control)) { ieee80211_has_protected(hdr->frame_control)) {
skb_put(msdu, IEEE80211_CCMP_MIC_LEN); skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
} else if (!skb_cb->htt.nohwcrypt && } else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
skb_cb->txmode == ATH10K_HW_TXRX_RAW && txmode == ATH10K_HW_TXRX_RAW &&
ieee80211_has_protected(hdr->frame_control)) { ieee80211_has_protected(hdr->frame_control)) {
skb_put(msdu, IEEE80211_CCMP_MIC_LEN); 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; 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_RAW:
case ATH10K_HW_TXRX_NATIVE_WIFI: case ATH10K_HW_TXRX_NATIVE_WIFI:
flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT; 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 + frags_paddr = htt->frag_desc.paddr +
(sizeof(struct htt_msdu_ext_desc) * msdu_id); (sizeof(struct htt_msdu_ext_desc) * msdu_id);
} else { } else {
frags = skb_cb->htt.txbuf->frags; frags = txbuf->frags;
frags[0].dword_addr.paddr = frags[0].dword_addr.paddr =
__cpu_to_le32(skb_cb->paddr); __cpu_to_le32(skb_cb->paddr);
frags[0].dword_addr.len = __cpu_to_le32(msdu->len); frags[0].dword_addr.len = __cpu_to_le32(msdu->len);
frags[1].dword_addr.paddr = 0; frags[1].dword_addr.paddr = 0;
frags[1].dword_addr.len = 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; break;
case ATH10K_HW_TXRX_MGMT: case ATH10K_HW_TXRX_MGMT:
flags0 |= SM(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 * avoid extra memory allocations, compress data structures and thus
* improve performance. */ * improve performance. */
skb_cb->htt.txbuf->htc_hdr.eid = htt->eid; txbuf->htc_hdr.eid = htt->eid;
skb_cb->htt.txbuf->htc_hdr.len = __cpu_to_le16( txbuf->htc_hdr.len = __cpu_to_le16(sizeof(txbuf->cmd_hdr) +
sizeof(skb_cb->htt.txbuf->cmd_hdr) + sizeof(txbuf->cmd_tx) +
sizeof(skb_cb->htt.txbuf->cmd_tx) + prefetch_len);
prefetch_len); txbuf->htc_hdr.flags = 0;
skb_cb->htt.txbuf->htc_hdr.flags = 0;
if (skb_cb->htt.nohwcrypt) if (skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT)
flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
if (!skb_cb->is_protected)
flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT; flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID); 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; flags1 |= HTT_DATA_TX_DESC_FLAGS1_POSTPONED;
skb_cb->htt.txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM; txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
skb_cb->htt.txbuf->cmd_tx.flags0 = flags0; txbuf->cmd_tx.flags0 = flags0;
skb_cb->htt.txbuf->cmd_tx.flags1 = __cpu_to_le16(flags1); txbuf->cmd_tx.flags1 = __cpu_to_le16(flags1);
skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len); txbuf->cmd_tx.len = __cpu_to_le16(msdu->len);
skb_cb->htt.txbuf->cmd_tx.id = __cpu_to_le16(msdu_id); txbuf->cmd_tx.id = __cpu_to_le16(msdu_id);
skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr); txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr);
skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le16(HTT_INVALID_PEERID); if (ath10k_mac_tx_frm_has_freq(ar)) {
skb_cb->htt.txbuf->cmd_tx.freq = __cpu_to_le16(skb_cb->htt.freq); 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); trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid);
ath10k_dbg(ar, ATH10K_DBG_HTT, 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", "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, 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: ", ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ",
msdu->data, msdu->len); msdu->data, msdu->len);
trace_ath10k_tx_hdr(ar, 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_id = 0;
sg_items[0].transfer_context = NULL; sg_items[0].transfer_context = NULL;
sg_items[0].vaddr = &skb_cb->htt.txbuf->htc_hdr; sg_items[0].vaddr = &txbuf->htc_hdr;
sg_items[0].paddr = skb_cb->htt.txbuf_paddr + sg_items[0].paddr = txbuf_paddr +
sizeof(skb_cb->htt.txbuf->frags); sizeof(txbuf->frags);
sg_items[0].len = sizeof(skb_cb->htt.txbuf->htc_hdr) + sg_items[0].len = sizeof(txbuf->htc_hdr) +
sizeof(skb_cb->htt.txbuf->cmd_hdr) + sizeof(txbuf->cmd_hdr) +
sizeof(skb_cb->htt.txbuf->cmd_tx); sizeof(txbuf->cmd_tx);
sg_items[1].transfer_id = 0; sg_items[1].transfer_id = 0;
sg_items[1].transfer_context = NULL; sg_items[1].transfer_context = NULL;

View file

@ -286,6 +286,16 @@ struct ath10k_pktlog_hdr {
u8 payload[0]; u8 payload[0];
} __packed; } __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 { enum ath10k_hw_rate_ofdm {
ATH10K_HW_RATE_OFDM_48M = 0, ATH10K_HW_RATE_OFDM_48M = 0,
ATH10K_HW_RATE_OFDM_24M, ATH10K_HW_RATE_OFDM_24M,
@ -307,6 +317,11 @@ enum ath10k_hw_rate_cck {
ATH10K_HW_RATE_CCK_SP_2M, 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 */ /* Target specific defines for MAIN firmware */
#define TARGET_NUM_VDEVS 8 #define TARGET_NUM_VDEVS 8
#define TARGET_NUM_PEER_AST 2 #define TARGET_NUM_PEER_AST 2

View file

@ -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 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; const struct ieee80211_rate *rate;
int i; 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++) { for (i = 0; i < sband->n_bitrates; i++) {
rate = &sband->bitrates[i]; rate = &sband->bitrates[i];
if (ath10k_mac_bitrate_is_cck(rate->bitrate) != cck)
continue;
if (rate->hw_value == hw_rate) if (rate->hw_value == hw_rate)
return i; return i;
else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE && 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); ether_addr_copy(arg->addr, sta->addr);
arg->vdev_id = arvif->vdev_id; arg->vdev_id = arvif->vdev_id;
arg->peer_aid = aid; 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_listen_intval = ath10k_peer_assoc_h_listen_intval(ar, vif);
arg->peer_num_spatial_streams = 1; arg->peer_num_spatial_streams = 1;
arg->peer_caps = vif->bss_conf.assoc_capability; 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, static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct wmi_peer_assoc_complete_arg *arg) struct wmi_peer_assoc_complete_arg *arg)
{ {
struct ieee80211_bss_conf *info = &vif->bss_conf; 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? */ /* FIXME: base on RSN IE/WPA IE is a correct idea? */
if (rsnie || wpaie) { if (rsnie || wpaie) {
ath10k_dbg(ar, ATH10K_DBG_WMI, "%s: rsn ie found\n", __func__); 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) { if (wpaie) {
ath10k_dbg(ar, ATH10K_DBG_WMI, "%s: wpa ie found\n", __func__); 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)) ath10k_peer_assoc_h_vht_masked(vht_mcs_mask))
return; 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 + arg->peer_max_mpdu = (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
ht_cap->ampdu_factor)) - 1; 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; arg->peer_rate_caps |= WMI_RC_HT_FLAG;
if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING) 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) { 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; 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) { if (ht_cap->cap & IEEE80211_HT_CAP_TX_STBC) {
arg->peer_rate_caps |= WMI_RC_TX_STBC_FLAG; 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) { 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 >> IEEE80211_HT_CAP_RX_STBC_SHIFT;
stbc = stbc << WMI_RC_RX_STBC_FLAG_S; stbc = stbc << WMI_RC_RX_STBC_FLAG_S;
arg->peer_rate_caps |= stbc; 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]) 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)) if (ath10k_peer_assoc_h_vht_masked(vht_mcs_mask))
return; return;
arg->peer_flags |= WMI_PEER_VHT; arg->peer_flags |= ar->wmi.peer_flags->vht;
if (def.chan->band == IEEE80211_BAND_2GHZ) 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; arg->peer_vht_caps = vht_cap->cap;
@ -2341,7 +2350,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
ampdu_factor)) - 1); ampdu_factor)) - 1);
if (sta->bandwidth == IEEE80211_STA_RX_BW_80) 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 = arg->peer_vht_rates.rx_max_rate =
__le16_to_cpu(vht_cap->vht_mcs.rx_highest); __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) { switch (arvif->vdev_type) {
case WMI_VDEV_TYPE_AP: case WMI_VDEV_TYPE_AP:
if (sta->wme) if (sta->wme)
arg->peer_flags |= WMI_PEER_QOS; arg->peer_flags |= arvif->ar->wmi.peer_flags->qos;
if (sta->wme && sta->uapsd_queues) { 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; arg->peer_rate_caps |= WMI_RC_UAPSD_FLAG;
} }
break; break;
case WMI_VDEV_TYPE_STA: case WMI_VDEV_TYPE_STA:
if (vif->bss_conf.qos) if (vif->bss_conf.qos)
arg->peer_flags |= WMI_PEER_QOS; arg->peer_flags |= arvif->ar->wmi.peer_flags->qos;
break; break;
case WMI_VDEV_TYPE_IBSS: case WMI_VDEV_TYPE_IBSS:
if (sta->wme) if (sta->wme)
arg->peer_flags |= WMI_PEER_QOS; arg->peer_flags |= arvif->ar->wmi.peer_flags->qos;
break; break;
default: default:
break; break;
} }
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac peer %pM qos %d\n", 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) 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)); memset(arg, 0, sizeof(*arg));
ath10k_peer_assoc_h_basic(ar, vif, sta, 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_rates(ar, vif, sta, arg);
ath10k_peer_assoc_h_ht(ar, vif, sta, arg); ath10k_peer_assoc_h_ht(ar, vif, sta, arg);
ath10k_peer_assoc_h_vht(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); 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 static enum ath10k_hw_txrx_mode
ath10k_tx_h_get_txmode(struct ath10k *ar, struct ieee80211_vif *vif, ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
struct ieee80211_sta *sta, struct sk_buff *skb) struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct sk_buff *skb)
{ {
const struct ieee80211_hdr *hdr = (void *)skb->data; const struct ieee80211_hdr *hdr = (void *)skb->data;
__le16 fc = hdr->frame_control; __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, static bool ath10k_tx_h_use_hwcrypto(struct ieee80211_vif *vif,
struct sk_buff *skb) { struct sk_buff *skb)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(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 | const u32 mask = IEEE80211_TX_INTFL_DONT_ENCRYPT |
IEEE80211_TX_CTL_INJECTED; IEEE80211_TX_CTL_INJECTED;
if (!ieee80211_has_protected(hdr->frame_control))
return false;
if ((info->flags & mask) == mask) if ((info->flags & mask) == mask)
return false; return false;
if (vif) if (vif)
return !ath10k_vif_to_arvif(vif)->nohwcrypt; return !ath10k_vif_to_arvif(vif)->nohwcrypt;
return true; return true;
} }
@ -3224,7 +3218,7 @@ static void ath10k_tx_h_nwifi(struct ieee80211_hw *hw, struct sk_buff *skb)
*/ */
hdr = (void *)skb->data; hdr = (void *)skb->data;
if (ieee80211_is_qos_nullfunc(hdr->frame_control)) 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); 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 /* FIXME: Not really sure since when the behaviour changed. At some
* point new firmware stopped requiring creation of peer entries for * 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 * 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. * because that's when the `freq` was introduced to TX_FRM HTT command.
*/ */
return !(ar->htt.target_version_major >= 3 && return (ar->htt.target_version_major >= 3 &&
ar->htt.target_version_minor >= 4); 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) static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb)
@ -3314,24 +3309,24 @@ unlock:
return ret; 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; struct ath10k_htt *htt = &ar->htt;
int ret = 0; int ret = 0;
switch (cb->txmode) { switch (txmode) {
case ATH10K_HW_TXRX_RAW: case ATH10K_HW_TXRX_RAW:
case ATH10K_HW_TXRX_NATIVE_WIFI: case ATH10K_HW_TXRX_NATIVE_WIFI:
case ATH10K_HW_TXRX_ETHERNET: case ATH10K_HW_TXRX_ETHERNET:
ret = ath10k_htt_tx(htt, skb); ret = ath10k_htt_tx(htt, txmode, skb);
break; break;
case ATH10K_HW_TXRX_MGMT: case ATH10K_HW_TXRX_MGMT:
if (test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX, if (test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
ar->fw_features)) ar->fw_features))
ret = ath10k_mac_tx_wmi_mgmt(ar, skb); ret = ath10k_mac_tx_wmi_mgmt(ar, skb);
else if (ar->htt.target_version_major >= 3) else if (ar->htt.target_version_major >= 3)
ret = ath10k_htt_tx(htt, skb); ret = ath10k_htt_tx(htt, txmode, skb);
else else
ret = ath10k_htt_mgmt_tx(htt, skb); ret = ath10k_htt_mgmt_tx(htt, skb);
break; 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 *ar = container_of(work, struct ath10k, offchan_tx_work);
struct ath10k_peer *peer; struct ath10k_peer *peer;
struct ath10k_vif *arvif;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
struct ieee80211_vif *vif;
struct ieee80211_sta *sta;
struct sk_buff *skb; struct sk_buff *skb;
const u8 *peer_addr; const u8 *peer_addr;
enum ath10k_hw_txrx_mode txmode;
int vdev_id; int vdev_id;
int ret; int ret;
unsigned long time_left; unsigned long time_left;
@ -3388,9 +3387,9 @@ void ath10k_offchan_tx_work(struct work_struct *work)
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
peer_addr = ieee80211_get_DA(hdr); peer_addr = ieee80211_get_DA(hdr);
vdev_id = ATH10K_SKB_CB(skb)->vdev_id;
spin_lock_bh(&ar->data_lock); spin_lock_bh(&ar->data_lock);
vdev_id = ar->scan.vdev_id;
peer = ath10k_peer_find(ar, vdev_id, peer_addr); peer = ath10k_peer_find(ar, vdev_id, peer_addr);
spin_unlock_bh(&ar->data_lock); spin_unlock_bh(&ar->data_lock);
@ -3413,7 +3412,22 @@ void ath10k_offchan_tx_work(struct work_struct *work)
ar->offchan_tx_skb = skb; ar->offchan_tx_skb = skb;
spin_unlock_bh(&ar->data_lock); 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 = time_left =
wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ); 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: case ATH10K_SCAN_STARTING:
ar->scan.state = ATH10K_SCAN_IDLE; ar->scan.state = ATH10K_SCAN_IDLE;
ar->scan_channel = NULL; ar->scan_channel = NULL;
ar->scan.roc_freq = 0;
ath10k_offchan_tx_purge(ar); ath10k_offchan_tx_purge(ar);
cancel_delayed_work(&ar->scan.timeout); cancel_delayed_work(&ar->scan.timeout);
complete_all(&ar->scan.completed); complete_all(&ar->scan.completed);
@ -3631,25 +3646,32 @@ static void ath10k_tx(struct ieee80211_hw *hw,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ath10k *ar = hw->priv; 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_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif; struct ieee80211_vif *vif = info->control.vif;
struct ieee80211_sta *sta = control->sta; struct ieee80211_sta *sta = control->sta;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 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 */ /* We should disable CCK RATE due to P2P */
if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE) if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n"); ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
ATH10K_SKB_CB(skb)->htt.is_offchan = false; txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
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);
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_MGMT:
case ATH10K_HW_TXRX_NATIVE_WIFI: case ATH10K_HW_TXRX_NATIVE_WIFI:
ath10k_tx_h_nwifi(hw, skb); 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) { if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
spin_lock_bh(&ar->data_lock); if (!ath10k_mac_tx_frm_has_freq(ar)) {
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;
ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n", ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n",
skb); 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. */ /* 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; arvif->vdev_type = WMI_VDEV_TYPE_IBSS;
break; break;
case NL80211_IFTYPE_MESH_POINT: 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; ret = -EINVAL;
ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n"); ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n");
goto err; goto err;
@ -6907,35 +6923,39 @@ void ath10k_mac_destroy(struct ath10k *ar)
static const struct ieee80211_iface_limit ath10k_if_limits[] = { static const struct ieee80211_iface_limit ath10k_if_limits[] = {
{ {
.max = 8, .max = 8,
.types = BIT(NL80211_IFTYPE_STATION) .types = BIT(NL80211_IFTYPE_STATION)
| BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_CLIENT)
}, },
{ {
.max = 3, .max = 3,
.types = BIT(NL80211_IFTYPE_P2P_GO) .types = BIT(NL80211_IFTYPE_P2P_GO)
}, },
{ {
.max = 1, .max = 1,
.types = BIT(NL80211_IFTYPE_P2P_DEVICE) .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
}, },
{ {
.max = 7, .max = 7,
.types = BIT(NL80211_IFTYPE_AP) .types = BIT(NL80211_IFTYPE_AP)
#ifdef CONFIG_MAC80211_MESH #ifdef CONFIG_MAC80211_MESH
| BIT(NL80211_IFTYPE_MESH_POINT) | BIT(NL80211_IFTYPE_MESH_POINT)
#endif #endif
}, },
}; };
static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = { static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = {
{ {
.max = 8, .max = 8,
.types = BIT(NL80211_IFTYPE_AP) .types = BIT(NL80211_IFTYPE_AP)
#ifdef CONFIG_MAC80211_MESH #ifdef CONFIG_MAC80211_MESH
| BIT(NL80211_IFTYPE_MESH_POINT) | BIT(NL80211_IFTYPE_MESH_POINT)
#endif #endif
}, },
{
.max = 1,
.types = BIT(NL80211_IFTYPE_STATION)
},
}; };
static const struct ieee80211_iface_combination ath10k_if_comb[] = { static const struct ieee80211_iface_combination ath10k_if_comb[] = {

View file

@ -66,7 +66,7 @@ void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id,
enum wmi_tlv_tx_pause_action action); enum wmi_tlv_tx_pause_action action);
u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband, 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, u8 ath10k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
u32 bitrate); 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_tx_unlock(struct ath10k *ar, int reason);
void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, 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); 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) static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
{ {

View file

@ -108,6 +108,7 @@ 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_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_htt_rx_cb(struct ath10k_ce_pipe *ce_state);
static void ath10k_pci_htt_htc_rx_cb(struct ath10k_ce_pipe *ce_state); static void ath10k_pci_htt_htc_rx_cb(struct ath10k_ce_pipe *ce_state);
static void ath10k_pci_pktlog_rx_cb(struct ath10k_ce_pipe *ce_state);
static struct ce_attr host_ce_config_wlan[] = { static struct ce_attr host_ce_config_wlan[] = {
/* CE0: host->target HTC control and raw streams */ /* CE0: host->target HTC control and raw streams */
@ -186,6 +187,7 @@ static struct ce_attr host_ce_config_wlan[] = {
.src_nentries = 0, .src_nentries = 0,
.src_sz_max = 2048, .src_sz_max = 2048,
.dest_nentries = 128, .dest_nentries = 128,
.recv_cb = ath10k_pci_pktlog_rx_cb,
}, },
/* CE9 target autonomous qcache memcpy */ /* CE9 target autonomous qcache memcpy */
@ -1215,6 +1217,15 @@ static void ath10k_pci_htt_htc_rx_cb(struct ath10k_ce_pipe *ce_state)
ath10k_pci_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler); 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. */ /* 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) static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state)
{ {

View file

@ -187,7 +187,7 @@ int ath10k_thermal_register(struct ath10k *ar)
/* Do not register hwmon device when temperature reading is not /* Do not register hwmon device when temperature reading is not
* supported by firmware * 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; return 0;
/* Avoid linking error on devm_hwmon_device_register_with_groups, I /* Avoid linking error on devm_hwmon_device_register_with_groups, I

View file

@ -23,7 +23,12 @@
static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb) 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; return;
/* If the original wait_for_completion() timed out before /* 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 ieee80211_tx_info *info;
struct ath10k_skb_cb *skb_cb; struct ath10k_skb_cb *skb_cb;
struct sk_buff *msdu; struct sk_buff *msdu;
struct ieee80211_hdr *hdr;
__le16 fc;
bool limit_mgmt_desc = false; bool limit_mgmt_desc = false;
ath10k_dbg(ar, ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
@ -76,10 +79,9 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
return; return;
} }
hdr = (struct ieee80211_hdr *)msdu->data; skb_cb = ATH10K_SKB_CB(msdu);
fc = hdr->frame_control;
if (unlikely(ieee80211_is_mgmt(fc)) && if (unlikely(skb_cb->flags & ATH10K_SKB_F_MGMT) &&
ar->hw_params.max_probe_resp_desc_thres) ar->hw_params.max_probe_resp_desc_thres)
limit_mgmt_desc = true; limit_mgmt_desc = true;
@ -89,7 +91,6 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
wake_up(&htt->empty_tx_wq); wake_up(&htt->empty_tx_wq);
spin_unlock_bh(&htt->tx_lock); spin_unlock_bh(&htt->tx_lock);
skb_cb = ATH10K_SKB_CB(msdu);
dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
ath10k_report_offchan_tx(htt->ar, msdu); ath10k_report_offchan_tx(htt->ar, msdu);

View file

@ -3485,6 +3485,24 @@ static const struct wmi_ops wmi_tlv_ops = {
.fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill, .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 */ /* 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.vdev_param = &wmi_tlv_vdev_param_map;
ar->wmi.pdev_param = &wmi_tlv_pdev_param_map; ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
ar->wmi.ops = &wmi_tlv_ops; ar->wmi.ops = &wmi_tlv_ops;
ar->wmi.peer_flags = &wmi_tlv_peer_flags_map;
} }

View file

@ -527,6 +527,24 @@ enum wmi_tlv_vdev_param {
WMI_TLV_VDEV_PARAM_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE, 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 { enum wmi_tlv_tag {
WMI_TLV_TAG_LAST_RESERVED = 15, WMI_TLV_TAG_LAST_RESERVED = 15,

View file

@ -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, .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, void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
const struct wmi_channel_arg *arg) 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 *ar = arvif->ar;
struct ath10k_skb_cb *cb; struct ath10k_skb_cb *cb;
struct sk_buff *bcn; struct sk_buff *bcn;
bool dtim_zero;
bool deliver_cab;
int ret; int ret;
spin_lock_bh(&ar->data_lock); 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; arvif->beacon_state = ATH10K_BEACON_SENDING;
spin_unlock_bh(&ar->data_lock); 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, ret = ath10k_wmi_beacon_send_ref_nowait(arvif->ar,
arvif->vdev_id, arvif->vdev_id,
bcn->data, bcn->len, bcn->data, bcn->len,
cb->paddr, cb->paddr,
cb->bcn.dtim_zero, dtim_zero,
cb->bcn.deliver_cab); deliver_cab);
spin_lock_bh(&ar->data_lock); 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 * static struct sk_buff *
ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu) 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 wmi_mgmt_tx_cmd *cmd;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
struct sk_buff *skb; struct sk_buff *skb;
int len; int len;
u32 vdev_id;
u32 buf_len = msdu->len; u32 buf_len = msdu->len;
u16 fc; u16 fc;
hdr = (struct ieee80211_hdr *)msdu->data; hdr = (struct ieee80211_hdr *)msdu->data;
fc = le16_to_cpu(hdr->frame_control); 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))) if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
return ERR_PTR(-EINVAL); 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 = (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_rate = 0;
cmd->hdr.tx_power = 0; cmd->hdr.tx_power = 0;
cmd->hdr.buf_len = __cpu_to_le32(buf_len); 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, ath10k_dbg(ar, ATH10K_DBG_MGMT,
"event mgmt rx status %08x\n", rx_status); "event mgmt rx status %08x\n", rx_status);
if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) { if ((test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) ||
dev_kfree_skb(skb); (rx_status & (WMI_RX_STATUS_ERR_DECRYPT |
return 0; WMI_RX_STATUS_ERR_KEY_CACHE_MISS | WMI_RX_STATUS_ERR_CRC))) {
}
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) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
return 0; 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); memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len);
if (tim->dtim_count == 0) { 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) 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", 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: case WMI_10_4_UPDATE_STATS_EVENTID:
ath10k_wmi_event_update_stats(ar, skb); ath10k_wmi_event_update_stats(ar, skb);
break; break;
case WMI_10_4_PDEV_TEMPERATURE_EVENTID:
ath10k_wmi_event_temperature(ar, skb);
break;
default: default:
ath10k_warn(ar, "Unknown eventid: %d\n", id); ath10k_warn(ar, "Unknown eventid: %d\n", id);
break; 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; cmd = (struct wmi_init_cmd_10_2 *)buf->data;
features = WMI_10_2_RX_BATCH_MODE; 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; features |= WMI_10_2_COEX_GPIO;
cmd->resource_config.feature_mask = __cpu_to_le32(features); cmd->resource_config.feature_mask = __cpu_to_le32(features);
memcpy(&cmd->resource_config.common, &config, sizeof(config)); 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); 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 static int
ath10k_wmi_peer_assoc_check_arg(const struct wmi_peer_assoc_complete_arg *arg) 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; 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 * static struct sk_buff *
ath10k_wmi_10_2_op_gen_pdev_get_temperature(struct ath10k *ar) 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_delete = ath10k_wmi_op_gen_peer_delete,
.gen_peer_flush = ath10k_wmi_op_gen_peer_flush, .gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
.gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param, .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_psmode = ath10k_wmi_op_gen_set_psmode,
.gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps, .gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps,
.gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_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, .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill,
/* shared with 10.2 */ /* 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_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) 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.cmd = &wmi_10_4_cmd_map;
ar->wmi.vdev_param = &wmi_10_4_vdev_param_map; ar->wmi.vdev_param = &wmi_10_4_vdev_param_map;
ar->wmi.pdev_param = &wmi_10_4_pdev_param_map; ar->wmi.pdev_param = &wmi_10_4_pdev_param_map;
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
break; break;
case ATH10K_FW_WMI_OP_VERSION_10_2_4: case ATH10K_FW_WMI_OP_VERSION_10_2_4:
ar->wmi.cmd = &wmi_10_2_4_cmd_map; ar->wmi.cmd = &wmi_10_2_4_cmd_map;
ar->wmi.ops = &wmi_10_2_4_ops; ar->wmi.ops = &wmi_10_2_4_ops;
ar->wmi.vdev_param = &wmi_10_2_4_vdev_param_map; ar->wmi.vdev_param = &wmi_10_2_4_vdev_param_map;
ar->wmi.pdev_param = &wmi_10_2_4_pdev_param_map; ar->wmi.pdev_param = &wmi_10_2_4_pdev_param_map;
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
break; break;
case ATH10K_FW_WMI_OP_VERSION_10_2: case ATH10K_FW_WMI_OP_VERSION_10_2:
ar->wmi.cmd = &wmi_10_2_cmd_map; ar->wmi.cmd = &wmi_10_2_cmd_map;
ar->wmi.ops = &wmi_10_2_ops; ar->wmi.ops = &wmi_10_2_ops;
ar->wmi.vdev_param = &wmi_10x_vdev_param_map; ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
ar->wmi.pdev_param = &wmi_10x_pdev_param_map; ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
break; break;
case ATH10K_FW_WMI_OP_VERSION_10_1: case ATH10K_FW_WMI_OP_VERSION_10_1:
ar->wmi.cmd = &wmi_10x_cmd_map; ar->wmi.cmd = &wmi_10x_cmd_map;
ar->wmi.ops = &wmi_10_1_ops; ar->wmi.ops = &wmi_10_1_ops;
ar->wmi.vdev_param = &wmi_10x_vdev_param_map; ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
ar->wmi.pdev_param = &wmi_10x_pdev_param_map; ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
ar->wmi.peer_flags = &wmi_10x_peer_flags_map;
break; break;
case ATH10K_FW_WMI_OP_VERSION_MAIN: case ATH10K_FW_WMI_OP_VERSION_MAIN:
ar->wmi.cmd = &wmi_cmd_map; ar->wmi.cmd = &wmi_cmd_map;
ar->wmi.ops = &wmi_ops; ar->wmi.ops = &wmi_ops;
ar->wmi.vdev_param = &wmi_vdev_param_map; ar->wmi.vdev_param = &wmi_vdev_param_map;
ar->wmi.pdev_param = &wmi_pdev_param_map; ar->wmi.pdev_param = &wmi_pdev_param_map;
ar->wmi.peer_flags = &wmi_peer_flags_map;
break; break;
case ATH10K_FW_WMI_OP_VERSION_TLV: case ATH10K_FW_WMI_OP_VERSION_TLV:
ath10k_wmi_tlv_attach(ar); ath10k_wmi_tlv_attach(ar);

View file

@ -175,6 +175,8 @@ enum wmi_service {
WMI_SERVICE_AUX_SPECTRAL_INTF, WMI_SERVICE_AUX_SPECTRAL_INTF,
WMI_SERVICE_AUX_CHAN_LOAD_INTF, WMI_SERVICE_AUX_CHAN_LOAD_INTF,
WMI_SERVICE_BSS_CHANNEL_INFO_64, WMI_SERVICE_BSS_CHANNEL_INFO_64,
WMI_SERVICE_EXT_RES_CFG_SUPPORT,
WMI_SERVICE_MESH,
/* keep last */ /* keep last */
WMI_SERVICE_MAX, WMI_SERVICE_MAX,
@ -206,6 +208,11 @@ enum wmi_10x_service {
WMI_10X_SERVICE_SMART_ANTENNA_HW_SUPPORT, WMI_10X_SERVICE_SMART_ANTENNA_HW_SUPPORT,
WMI_10X_SERVICE_ATF, WMI_10X_SERVICE_ATF,
WMI_10X_SERVICE_COEX_GPIO, 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 { 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_SPECTRAL_INTF,
WMI_10_4_SERVICE_AUX_CHAN_LOAD_INTF, WMI_10_4_SERVICE_AUX_CHAN_LOAD_INTF,
WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64, 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) 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_SPECTRAL_INTF);
SVCSTR(WMI_SERVICE_AUX_CHAN_LOAD_INTF); SVCSTR(WMI_SERVICE_AUX_CHAN_LOAD_INTF);
SVCSTR(WMI_SERVICE_BSS_CHANNEL_INFO_64); SVCSTR(WMI_SERVICE_BSS_CHANNEL_INFO_64);
SVCSTR(WMI_SERVICE_EXT_RES_CFG_SUPPORT);
SVCSTR(WMI_SERVICE_MESH);
default: default:
return NULL; return NULL;
} }
@ -442,6 +453,16 @@ static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out,
WMI_SERVICE_ATF, len); WMI_SERVICE_ATF, len);
SVCMAP(WMI_10X_SERVICE_COEX_GPIO, SVCMAP(WMI_10X_SERVICE_COEX_GPIO,
WMI_SERVICE_COEX_GPIO, len); 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, 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); WMI_SERVICE_AUX_CHAN_LOAD_INTF, len);
SVCMAP(WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64, SVCMAP(WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64,
WMI_SERVICE_BSS_CHANNEL_INFO_64, len); 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 #undef SVCMAP
@ -1576,6 +1601,9 @@ enum wmi_10_4_cmd_id {
WMI_10_4_MU_CAL_START_CMDID, WMI_10_4_MU_CAL_START_CMDID,
WMI_10_4_SET_CCA_PARAMS_CMDID, WMI_10_4_SET_CCA_PARAMS_CMDID,
WMI_10_4_PDEV_BSS_CHAN_INFO_REQUEST_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, 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_TEMPERATURE_EVENTID,
WMI_10_4_PDEV_NFCAL_POWER_ALL_CHANNELS_EVENTID, WMI_10_4_PDEV_NFCAL_POWER_ALL_CHANNELS_EVENTID,
WMI_10_4_PDEV_BSS_CHAN_INFO_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, 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_WAPI_MBSSID_OFFSET,
WMI_10_4_PDEV_PARAM_ARP_SRCADDR, WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
WMI_10_4_PDEV_PARAM_ARP_DSTADDR, 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 { struct wmi_pdev_set_param_cmd {
@ -4239,6 +4274,8 @@ enum wmi_vdev_subtype {
WMI_VDEV_SUBTYPE_P2P_DEVICE = 1, WMI_VDEV_SUBTYPE_P2P_DEVICE = 1,
WMI_VDEV_SUBTYPE_P2P_CLIENT = 2, WMI_VDEV_SUBTYPE_P2P_CLIENT = 2,
WMI_VDEV_SUBTYPE_P2P_GO = 3, WMI_VDEV_SUBTYPE_P2P_GO = 3,
WMI_VDEV_SUBTYPE_PROXY_STA = 4,
WMI_VDEV_SUBTYPE_MESH = 5,
}; };
/* values for vdev_subtype */ /* values for vdev_subtype */
@ -5641,21 +5678,79 @@ struct wmi_peer_set_q_empty_callback_cmd {
__le32 callback_enable; __le32 callback_enable;
} __packed; } __packed;
#define WMI_PEER_AUTH 0x00000001 struct wmi_peer_flags_map {
#define WMI_PEER_QOS 0x00000002 u32 auth;
#define WMI_PEER_NEED_PTK_4_WAY 0x00000004 u32 qos;
#define WMI_PEER_NEED_GTK_2_WAY 0x00000010 u32 need_ptk_4_way;
#define WMI_PEER_APSD 0x00000800 u32 need_gtk_2_way;
#define WMI_PEER_HT 0x00001000 u32 apsd;
#define WMI_PEER_40MHZ 0x00002000 u32 ht;
#define WMI_PEER_STBC 0x00008000 u32 bw40;
#define WMI_PEER_LDPC 0x00010000 u32 stbc;
#define WMI_PEER_DYN_MIMOPS 0x00020000 u32 ldbc;
#define WMI_PEER_STATIC_MIMOPS 0x00040000 u32 dyn_mimops;
#define WMI_PEER_SPATIAL_MUX 0x00200000 u32 static_mimops;
#define WMI_PEER_VHT 0x02000000 u32 spatial_mux;
#define WMI_PEER_80MHZ 0x04000000 u32 vht;
#define WMI_PEER_VHT_2G 0x08000000 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. * Peer rate capabilities.
@ -5721,6 +5816,11 @@ struct wmi_10_2_peer_assoc_complete_cmd {
__le32 info0; /* WMI_PEER_ASSOC_INFO0_ */ __le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
} __packed; } __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 { struct wmi_peer_assoc_complete_arg {
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
u32 vdev_id; u32 vdev_id;

View file

@ -414,7 +414,7 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
return; return;
} }
if (epid >= ENDPOINT_MAX) { if (epid < 0 || epid >= ENDPOINT_MAX) {
if (pipe_id != USB_REG_IN_PIPE) if (pipe_id != USB_REG_IN_PIPE)
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
else else

View file

@ -345,6 +345,8 @@ enum wcn36xx_hal_host_msg_type {
WCN36XX_HAL_DHCP_START_IND = 189, WCN36XX_HAL_DHCP_START_IND = 189,
WCN36XX_HAL_DHCP_STOP_IND = 190, WCN36XX_HAL_DHCP_STOP_IND = 190,
WCN36XX_HAL_AVOID_FREQ_RANGE_IND = 233,
WCN36XX_HAL_MSG_MAX = WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE WCN36XX_HAL_MSG_MAX = WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE
}; };

View file

@ -302,6 +302,22 @@ static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
return 0; return 0;
} }
static int wcn36xx_smd_rsp_status_check_v2(struct wcn36xx *wcn, void *buf,
size_t len)
{
struct wcn36xx_fw_msg_status_rsp_v2 *rsp;
if (len < sizeof(struct wcn36xx_hal_msg_header) + sizeof(*rsp))
return wcn36xx_smd_rsp_status_check(buf, len);
rsp = buf + sizeof(struct wcn36xx_hal_msg_header);
if (WCN36XX_FW_MSG_RESULT_SUCCESS != rsp->status)
return rsp->status;
return 0;
}
int wcn36xx_smd_load_nv(struct wcn36xx *wcn) int wcn36xx_smd_load_nv(struct wcn36xx *wcn)
{ {
struct nv_data *nv_d; struct nv_data *nv_d;
@ -1582,7 +1598,8 @@ int wcn36xx_smd_remove_bsskey(struct wcn36xx *wcn,
wcn36xx_err("Sending hal_remove_bsskey failed\n"); wcn36xx_err("Sending hal_remove_bsskey failed\n");
goto out; goto out;
} }
ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf,
wcn->hal_rsp_len);
if (ret) { if (ret) {
wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret); wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
goto out; goto out;
@ -1951,7 +1968,8 @@ int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index)
wcn36xx_err("Sending hal_trigger_ba failed\n"); wcn36xx_err("Sending hal_trigger_ba failed\n");
goto out; goto out;
} }
ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); ret = wcn36xx_smd_rsp_status_check_v2(wcn, wcn->hal_buf,
wcn->hal_rsp_len);
if (ret) { if (ret) {
wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret); wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
goto out; goto out;
@ -2128,6 +2146,8 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
complete(&wcn->hal_rsp_compl); complete(&wcn->hal_rsp_compl);
break; break;
case WCN36XX_HAL_COEX_IND:
case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
case WCN36XX_HAL_OTA_TX_COMPL_IND: case WCN36XX_HAL_OTA_TX_COMPL_IND:
case WCN36XX_HAL_MISSED_BEACON_IND: case WCN36XX_HAL_MISSED_BEACON_IND:
case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: case WCN36XX_HAL_DELETE_STA_CONTEXT_IND:
@ -2174,6 +2194,9 @@ static void wcn36xx_ind_smd_work(struct work_struct *work)
msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg; msg_header = (struct wcn36xx_hal_msg_header *)hal_ind_msg->msg;
switch (msg_header->msg_type) { switch (msg_header->msg_type) {
case WCN36XX_HAL_COEX_IND:
case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
break;
case WCN36XX_HAL_OTA_TX_COMPL_IND: case WCN36XX_HAL_OTA_TX_COMPL_IND:
wcn36xx_smd_tx_compl_ind(wcn, wcn36xx_smd_tx_compl_ind(wcn,
hal_ind_msg->msg, hal_ind_msg->msg,

View file

@ -44,6 +44,15 @@ struct wcn36xx_fw_msg_status_rsp {
u32 status; u32 status;
} __packed; } __packed;
/* wcn3620 returns this for tigger_ba */
struct wcn36xx_fw_msg_status_rsp_v2 {
u8 bss_id[6];
u32 status __packed;
u16 count_following_candidates __packed;
/* candidate list follows */
};
struct wcn36xx_hal_ind_msg { struct wcn36xx_hal_ind_msg {
struct list_head list; struct list_head list;
u8 *msg; u8 *msg;

View file

@ -401,20 +401,26 @@ void wil_bcast_fini(struct wil6210_priv *wil)
static void wil_connect_worker(struct work_struct *work) 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, struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
connect_worker); connect_worker);
struct net_device *ndev = wil_to_ndev(wil); struct net_device *ndev = wil_to_ndev(wil);
int cid = wil->pending_connect_cid; mutex_lock(&wil->mutex);
int ringid = wil_find_free_vring(wil);
cid = wil->pending_connect_cid;
if (cid < 0) { if (cid < 0) {
wil_err(wil, "No connection pending\n"); 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); rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0);
wil->pending_connect_cid = -1; wil->pending_connect_cid = -1;
@ -424,6 +430,8 @@ static void wil_connect_worker(struct work_struct *work)
} else { } else {
wil_disconnect_cid(wil, cid, WLAN_REASON_UNSPECIFIED, true); wil_disconnect_cid(wil, cid, WLAN_REASON_UNSPECIFIED, true);
} }
out:
mutex_unlock(&wil->mutex);
} }
int wil_priv_init(struct wil6210_priv *wil) int wil_priv_init(struct wil6210_priv *wil)

View file

@ -160,6 +160,7 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
struct device *dev = wil_to_dev(wil); struct device *dev = wil_to_dev(wil);
size_t sz = vring->size * sizeof(vring->va[0]); size_t sz = vring->size * sizeof(vring->va[0]);
lockdep_assert_held(&wil->mutex);
if (tx) { if (tx) {
int vring_index = vring - wil->vring_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__, wil_dbg_misc(wil, "%s() max_mpdu_size %d\n", __func__,
cmd.vring_cfg.tx_sw_ring.max_mpdu_size); cmd.vring_cfg.tx_sw_ring.max_mpdu_size);
lockdep_assert_held(&wil->mutex);
if (vring->va) { if (vring->va) {
wil_err(wil, "Tx ring [%d] already allocated\n", id); 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__, wil_dbg_misc(wil, "%s() max_mpdu_size %d\n", __func__,
cmd.vring_cfg.tx_sw_ring.max_mpdu_size); cmd.vring_cfg.tx_sw_ring.max_mpdu_size);
lockdep_assert_held(&wil->mutex);
if (vring->va) { if (vring->va) {
wil_err(wil, "Tx ring [%d] already allocated\n", id); 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 *vring = &wil->vring_tx[id];
struct vring_tx_data *txdata = &wil->vring_tx_data[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) if (!vring->va)
return; return;

View file

@ -187,7 +187,8 @@ retry:
goto retry; goto retry;
if (id != bcdc->reqid) { if (id != bcdc->reqid) {
brcmf_err("%s: unexpected request id %d (expected %d)\n", brcmf_err("%s: unexpected request id %d (expected %d)\n",
brcmf_ifname(drvr, ifidx), id, bcdc->reqid); brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id,
bcdc->reqid);
ret = -EINVAL; ret = -EINVAL;
goto done; goto done;
} }
@ -234,7 +235,8 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
if (id != bcdc->reqid) { if (id != bcdc->reqid) {
brcmf_err("%s: unexpected request id %d (expected %d)\n", brcmf_err("%s: unexpected request id %d (expected %d)\n",
brcmf_ifname(drvr, ifidx), id, bcdc->reqid); brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id,
bcdc->reqid);
ret = -EINVAL; ret = -EINVAL;
goto done; goto done;
} }
@ -298,13 +300,13 @@ brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws,
if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) != if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) !=
BCDC_PROTO_VER) { BCDC_PROTO_VER) {
brcmf_err("%s: non-BCDC packet received, flags 0x%x\n", brcmf_err("%s: non-BCDC packet received, flags 0x%x\n",
brcmf_ifname(drvr, tmp_if->ifidx), h->flags); brcmf_ifname(tmp_if), h->flags);
return -EBADE; return -EBADE;
} }
if (h->flags & BCDC_FLAG_SUM_GOOD) { if (h->flags & BCDC_FLAG_SUM_GOOD) {
brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n", brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
brcmf_ifname(drvr, tmp_if->ifidx), h->flags); brcmf_ifname(tmp_if), h->flags);
pktbuf->ip_summed = CHECKSUM_UNNECESSARY; pktbuf->ip_summed = CHECKSUM_UNNECESSARY;
} }

View file

@ -137,7 +137,7 @@ struct brcmf_bus {
bool always_use_fws_queue; bool always_use_fws_queue;
bool wowl_supported; bool wowl_supported;
struct brcmf_bus_ops *ops; const struct brcmf_bus_ops *ops;
struct brcmf_bus_msgbuf *msgbuf; struct brcmf_bus_msgbuf *msgbuf;
}; };

View file

@ -776,7 +776,8 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
s32 ap = 0; s32 ap = 0;
s32 err = 0; s32 err = 0;
brcmf_dbg(TRACE, "Enter, idx=%d, type=%d\n", ifp->bssidx, type); brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, type=%d\n", ifp->bsscfgidx,
type);
/* WAR: There are a number of p2p interface related problems which /* WAR: There are a number of p2p interface related problems which
* need to be handled initially (before doing the validate). * need to be handled initially (before doing the validate).
@ -945,7 +946,7 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg,
static s32 static s32
brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
struct cfg80211_scan_request *request, u16 action) struct cfg80211_scan_request *request)
{ {
s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE + s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE +
offsetof(struct brcmf_escan_params_le, params_le); offsetof(struct brcmf_escan_params_le, params_le);
@ -959,7 +960,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
params_size += sizeof(u32) * ((request->n_channels + 1) / 2); params_size += sizeof(u32) * ((request->n_channels + 1) / 2);
/* Allocate space for populating ssids in struct */ /* Allocate space for populating ssids in struct */
params_size += sizeof(struct brcmf_ssid) * request->n_ssids; params_size += sizeof(struct brcmf_ssid_le) * request->n_ssids;
} }
params = kzalloc(params_size, GFP_KERNEL); params = kzalloc(params_size, GFP_KERNEL);
@ -970,7 +971,7 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN); BUG_ON(params_size + sizeof("escan") >= BRCMF_DCMD_MEDLEN);
brcmf_escan_prep(cfg, &params->params_le, request); brcmf_escan_prep(cfg, &params->params_le, request);
params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION); params->version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
params->action = cpu_to_le16(action); params->action = cpu_to_le16(WL_ESCAN_ACTION_START);
params->sync_id = cpu_to_le16(0x1234); params->sync_id = cpu_to_le16(0x1234);
err = brcmf_fil_iovar_data_set(ifp, "escan", params, params_size); err = brcmf_fil_iovar_data_set(ifp, "escan", params, params_size);
@ -1012,7 +1013,7 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy,
results->count = 0; results->count = 0;
results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE; results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE;
err = escan->run(cfg, ifp, request, WL_ESCAN_ACTION_START); err = escan->run(cfg, ifp, request);
if (err) if (err)
brcmf_scan_config_mpc(ifp, 1); brcmf_scan_config_mpc(ifp, 1);
return err; return err;
@ -1291,6 +1292,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
s32 wsec = 0; s32 wsec = 0;
s32 bcnprd; s32 bcnprd;
u16 chanspec; u16 chanspec;
u32 ssid_len;
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
if (!check_vif_up(ifp->vif)) if (!check_vif_up(ifp->vif))
@ -1368,17 +1370,15 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
memset(&join_params, 0, sizeof(struct brcmf_join_params)); memset(&join_params, 0, sizeof(struct brcmf_join_params));
/* SSID */ /* SSID */
profile->ssid.SSID_len = min_t(u32, params->ssid_len, 32); ssid_len = min_t(u32, params->ssid_len, IEEE80211_MAX_SSID_LEN);
memcpy(profile->ssid.SSID, params->ssid, profile->ssid.SSID_len); memcpy(join_params.ssid_le.SSID, params->ssid, ssid_len);
memcpy(join_params.ssid_le.SSID, params->ssid, profile->ssid.SSID_len); join_params.ssid_le.SSID_len = cpu_to_le32(ssid_len);
join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
join_params_size = sizeof(join_params.ssid_le); join_params_size = sizeof(join_params.ssid_le);
/* BSSID */ /* BSSID */
if (params->bssid) { if (params->bssid) {
memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN); memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);
join_params_size = sizeof(join_params.ssid_le) + join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE;
BRCMF_ASSOC_PARAMS_FIXED_SIZE;
memcpy(profile->bssid, params->bssid, ETH_ALEN); memcpy(profile->bssid, params->bssid, ETH_ALEN);
} else { } else {
eth_broadcast_addr(join_params.params_le.bssid); eth_broadcast_addr(join_params.params_le.bssid);
@ -1728,7 +1728,6 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
{ {
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct ieee80211_channel *chan = sme->channel; struct ieee80211_channel *chan = sme->channel;
struct brcmf_join_params join_params; struct brcmf_join_params join_params;
size_t join_params_size; size_t join_params_size;
@ -1739,6 +1738,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_ext_join_params_le *ext_join_params; struct brcmf_ext_join_params_le *ext_join_params;
u16 chanspec; u16 chanspec;
s32 err = 0; s32 err = 0;
u32 ssid_len;
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
if (!check_vif_up(ifp->vif)) if (!check_vif_up(ifp->vif))
@ -1824,15 +1824,6 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
goto done; goto done;
} }
profile->ssid.SSID_len = min_t(u32, (u32)sizeof(profile->ssid.SSID),
(u32)sme->ssid_len);
memcpy(&profile->ssid.SSID, sme->ssid, profile->ssid.SSID_len);
if (profile->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
profile->ssid.SSID[profile->ssid.SSID_len] = 0;
brcmf_dbg(CONN, "SSID \"%s\", len (%d)\n", profile->ssid.SSID,
profile->ssid.SSID_len);
}
/* Join with specific BSSID and cached SSID /* Join with specific BSSID and cached SSID
* If SSID is zero join based on BSSID only * If SSID is zero join based on BSSID only
*/ */
@ -1845,9 +1836,12 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
err = -ENOMEM; err = -ENOMEM;
goto done; goto done;
} }
ext_join_params->ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len); ssid_len = min_t(u32, sme->ssid_len, IEEE80211_MAX_SSID_LEN);
memcpy(&ext_join_params->ssid_le.SSID, sme->ssid, ext_join_params->ssid_le.SSID_len = cpu_to_le32(ssid_len);
profile->ssid.SSID_len); memcpy(&ext_join_params->ssid_le.SSID, sme->ssid, ssid_len);
if (ssid_len < IEEE80211_MAX_SSID_LEN)
brcmf_dbg(CONN, "SSID \"%s\", len (%d)\n",
ext_join_params->ssid_le.SSID, ssid_len);
/* Set up join scan parameters */ /* Set up join scan parameters */
ext_join_params->scan_le.scan_type = -1; ext_join_params->scan_le.scan_type = -1;
@ -1895,8 +1889,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
memset(&join_params, 0, sizeof(join_params)); memset(&join_params, 0, sizeof(join_params));
join_params_size = sizeof(join_params.ssid_le); join_params_size = sizeof(join_params.ssid_le);
memcpy(&join_params.ssid_le.SSID, sme->ssid, profile->ssid.SSID_len); memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid_len);
join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len); join_params.ssid_le.SSID_len = cpu_to_le32(ssid_len);
if (sme->bssid) if (sme->bssid)
memcpy(join_params.params_le.bssid, sme->bssid, ETH_ALEN); memcpy(join_params.params_le.bssid, sme->bssid, ETH_ALEN);
@ -2775,9 +2769,7 @@ CleanUp:
static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg, static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
struct brcmf_if *ifp) struct brcmf_if *ifp)
{ {
struct brcmf_cfg80211_profile *profile = ndev_to_prof(ifp->ndev);
struct brcmf_bss_info_le *bi; struct brcmf_bss_info_le *bi;
struct brcmf_ssid *ssid;
const struct brcmf_tlv *tim; const struct brcmf_tlv *tim;
u16 beacon_interval; u16 beacon_interval;
u8 dtim_period; u8 dtim_period;
@ -2789,8 +2781,6 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
if (brcmf_is_ibssmode(ifp->vif)) if (brcmf_is_ibssmode(ifp->vif))
return err; return err;
ssid = &profile->ssid;
*(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX); *(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
cfg->extra_buf, WL_EXTRA_BUF_MAX); cfg->extra_buf, WL_EXTRA_BUF_MAX);
@ -2921,7 +2911,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
status = e->status; status = e->status;
if (!test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { if (!test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
brcmf_err("scan not ready, bssidx=%d\n", ifp->bssidx); brcmf_err("scan not ready, bsscfgidx=%d\n", ifp->bsscfgidx);
return -EPERM; return -EPERM;
} }
@ -3061,6 +3051,67 @@ static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4],
return ret; return ret;
} }
#ifdef CONFIG_PM
static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp)
{
struct brcmf_wowl_wakeind_le wake_ind_le;
struct cfg80211_wowlan_wakeup wakeup_data;
struct cfg80211_wowlan_wakeup *wakeup;
u32 wakeind;
s32 err;
err = brcmf_fil_iovar_data_get(ifp, "wowl_wakeind", &wake_ind_le,
sizeof(wake_ind_le));
if (!err) {
brcmf_err("Get wowl_wakeind failed, err = %d\n", err);
return;
}
wakeind = le32_to_cpu(wake_ind_le.ucode_wakeind);
if (wakeind & (BRCMF_WOWL_MAGIC | BRCMF_WOWL_DIS | BRCMF_WOWL_BCN |
BRCMF_WOWL_RETR | BRCMF_WOWL_NET)) {
wakeup = &wakeup_data;
memset(&wakeup_data, 0, sizeof(wakeup_data));
wakeup_data.pattern_idx = -1;
if (wakeind & BRCMF_WOWL_MAGIC) {
brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_MAGIC\n");
wakeup_data.magic_pkt = true;
}
if (wakeind & BRCMF_WOWL_DIS) {
brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_DIS\n");
wakeup_data.disconnect = true;
}
if (wakeind & BRCMF_WOWL_BCN) {
brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_BCN\n");
wakeup_data.disconnect = true;
}
if (wakeind & BRCMF_WOWL_RETR) {
brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_RETR\n");
wakeup_data.disconnect = true;
}
if (wakeind & BRCMF_WOWL_NET) {
brcmf_dbg(INFO, "WOWL Wake indicator: BRCMF_WOWL_NET\n");
/* For now always map to pattern 0, no API to get
* correct information available at the moment.
*/
wakeup_data.pattern_idx = 0;
}
} else {
wakeup = NULL;
}
cfg80211_report_wowlan_wakeup(&ifp->vif->wdev, wakeup, GFP_KERNEL);
}
#else
static void brcmf_report_wowl_wakeind(struct wiphy *wiphy, struct brcmf_if *ifp)
{
}
#endif /* CONFIG_PM */
static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
{ {
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
@ -3070,11 +3121,12 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
brcmf_dbg(TRACE, "Enter\n"); brcmf_dbg(TRACE, "Enter\n");
if (cfg->wowl_enabled) { if (cfg->wowl_enabled) {
brcmf_report_wowl_wakeind(wiphy, ifp);
brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0);
brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0);
brcmf_configure_arp_offload(ifp, true); brcmf_configure_arp_offload(ifp, true);
brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM,
cfg->pre_wowl_pmmode); cfg->pre_wowl_pmmode);
brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0);
brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0);
cfg->wowl_enabled = false; cfg->wowl_enabled = false;
} }
return 0; return 0;
@ -3108,6 +3160,7 @@ static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg,
wowl->patterns[i].pkt_offset); wowl->patterns[i].pkt_offset);
} }
} }
brcmf_fil_iovar_data_set(ifp, "wowl_wakeind", "clear", strlen("clear"));
brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config); brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config);
brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1); brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1);
brcmf_bus_wowl_config(cfg->pub->bus_if, true); brcmf_bus_wowl_config(cfg->pub->bus_if, true);
@ -3877,7 +3930,8 @@ s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
ifp = vif->ifp; ifp = vif->ifp;
saved_ie = &vif->saved_ie; saved_ie = &vif->saved_ie;
brcmf_dbg(TRACE, "bssidx %d, pktflag : 0x%02X\n", ifp->bssidx, pktflag); brcmf_dbg(TRACE, "bsscfgidx %d, pktflag : 0x%02X\n", ifp->bsscfgidx,
pktflag);
iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
if (!iovar_ie_buf) if (!iovar_ie_buf)
return -ENOMEM; return -ENOMEM;
@ -4183,7 +4237,9 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
} }
} }
if (dev_role == NL80211_IFTYPE_AP) { if ((dev_role == NL80211_IFTYPE_AP) &&
((ifp->ifidx == 0) ||
!brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB))) {
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
if (err < 0) { if (err < 0) {
brcmf_err("BRCMF_C_DOWN error %d\n", err); brcmf_err("BRCMF_C_DOWN error %d\n", err);
@ -4239,7 +4295,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
brcmf_err("setting ssid failed %d\n", err); brcmf_err("setting ssid failed %d\n", err);
goto exit; goto exit;
} }
bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx); bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx);
bss_enable.enable = cpu_to_le32(1); bss_enable.enable = cpu_to_le32(1);
err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable, err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable,
sizeof(bss_enable)); sizeof(bss_enable));
@ -4306,7 +4362,7 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
if (err < 0) if (err < 0)
brcmf_err("BRCMF_C_UP error %d\n", err); brcmf_err("BRCMF_C_UP error %d\n", err);
} else { } else {
bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx); bss_enable.bsscfgidx = cpu_to_le32(ifp->bsscfgidx);
bss_enable.enable = cpu_to_le32(0); bss_enable.enable = cpu_to_le32(0);
err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable, err = brcmf_fil_iovar_data_set(ifp, "bss", &bss_enable,
sizeof(bss_enable)); sizeof(bss_enable));
@ -4700,7 +4756,6 @@ struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
vif->wdev.iftype = type; vif->wdev.iftype = type;
vif->pm_block = pm_block; vif->pm_block = pm_block;
vif->roam_off = -1;
brcmf_init_prof(&vif->profile); brcmf_init_prof(&vif->profile);
@ -5092,9 +5147,9 @@ static s32 brcmf_notify_vif_event(struct brcmf_if *ifp,
struct brcmf_cfg80211_vif_event *event = &cfg->vif_event; struct brcmf_cfg80211_vif_event *event = &cfg->vif_event;
struct brcmf_cfg80211_vif *vif; struct brcmf_cfg80211_vif *vif;
brcmf_dbg(TRACE, "Enter: action %u flags %u ifidx %u bsscfg %u\n", brcmf_dbg(TRACE, "Enter: action %u flags %u ifidx %u bsscfgidx %u\n",
ifevent->action, ifevent->flags, ifevent->ifidx, ifevent->action, ifevent->flags, ifevent->ifidx,
ifevent->bssidx); ifevent->bsscfgidx);
mutex_lock(&event->vif_event_lock); mutex_lock(&event->vif_event_lock);
event->action = ifevent->action; event->action = ifevent->action;
@ -5250,35 +5305,33 @@ static void init_vif_event(struct brcmf_cfg80211_vif_event *event)
mutex_init(&event->vif_event_lock); mutex_init(&event->vif_event_lock);
} }
static s32 static s32 brcmf_dongle_roam(struct brcmf_if *ifp)
brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout)
{ {
s32 err = 0; s32 err;
u32 bcn_timeout;
__le32 roamtrigger[2]; __le32 roamtrigger[2];
__le32 roam_delta[2]; __le32 roam_delta[2];
/* /* Configure beacon timeout value based upon roaming setting */
* Setup timeout if Beacons are lost and roam is if (brcmf_roamoff)
* off to report link down bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_OFF;
*/ else
if (brcmf_roamoff) { bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON;
err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout); err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);
if (err) { if (err) {
brcmf_err("bcn_timeout error (%d)\n", err); brcmf_err("bcn_timeout error (%d)\n", err);
goto dongle_rom_out; goto roam_setup_done;
}
} }
/* /* Enable/Disable built-in roaming to allow supplicant to take care of
* Enable/Disable built-in roaming to allow supplicant * roaming.
* to take care of roaming
*/ */
brcmf_dbg(INFO, "Internal Roaming = %s\n", brcmf_dbg(INFO, "Internal Roaming = %s\n",
brcmf_roamoff ? "Off" : "On"); brcmf_roamoff ? "Off" : "On");
err = brcmf_fil_iovar_int_set(ifp, "roam_off", !!(brcmf_roamoff)); err = brcmf_fil_iovar_int_set(ifp, "roam_off", !!(brcmf_roamoff));
if (err) { if (err) {
brcmf_err("roam_off error (%d)\n", err); brcmf_err("roam_off error (%d)\n", err);
goto dongle_rom_out; goto roam_setup_done;
} }
roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL); roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL);
@ -5287,7 +5340,7 @@ brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout)
(void *)roamtrigger, sizeof(roamtrigger)); (void *)roamtrigger, sizeof(roamtrigger));
if (err) { if (err) {
brcmf_err("WLC_SET_ROAM_TRIGGER error (%d)\n", err); brcmf_err("WLC_SET_ROAM_TRIGGER error (%d)\n", err);
goto dongle_rom_out; goto roam_setup_done;
} }
roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA); roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA);
@ -5296,10 +5349,10 @@ brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout)
(void *)roam_delta, sizeof(roam_delta)); (void *)roam_delta, sizeof(roam_delta));
if (err) { if (err) {
brcmf_err("WLC_SET_ROAM_DELTA error (%d)\n", err); brcmf_err("WLC_SET_ROAM_DELTA error (%d)\n", err);
goto dongle_rom_out; goto roam_setup_done;
} }
dongle_rom_out: roam_setup_done:
return err; return err;
} }
@ -5619,7 +5672,8 @@ static __le16 brcmf_get_mcs_map(u32 nchain, enum ieee80211_vht_mcs_support supp)
} }
static void brcmf_update_vht_cap(struct ieee80211_supported_band *band, static void brcmf_update_vht_cap(struct ieee80211_supported_band *band,
u32 bw_cap[2], u32 nchain) u32 bw_cap[2], u32 nchain, u32 txstreams,
u32 txbf_bfe_cap, u32 txbf_bfr_cap)
{ {
__le16 mcs_map; __le16 mcs_map;
@ -5638,6 +5692,25 @@ static void brcmf_update_vht_cap(struct ieee80211_supported_band *band,
mcs_map = brcmf_get_mcs_map(nchain, IEEE80211_VHT_MCS_SUPPORT_0_9); mcs_map = brcmf_get_mcs_map(nchain, IEEE80211_VHT_MCS_SUPPORT_0_9);
band->vht_cap.vht_mcs.rx_mcs_map = mcs_map; band->vht_cap.vht_mcs.rx_mcs_map = mcs_map;
band->vht_cap.vht_mcs.tx_mcs_map = mcs_map; band->vht_cap.vht_mcs.tx_mcs_map = mcs_map;
/* Beamforming support information */
if (txbf_bfe_cap & BRCMF_TXBF_SU_BFE_CAP)
band->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
if (txbf_bfe_cap & BRCMF_TXBF_MU_BFE_CAP)
band->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
if (txbf_bfr_cap & BRCMF_TXBF_SU_BFR_CAP)
band->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
if (txbf_bfr_cap & BRCMF_TXBF_MU_BFR_CAP)
band->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
if ((txbf_bfe_cap || txbf_bfr_cap) && (txstreams > 1)) {
band->vht_cap.cap |=
(2 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT);
band->vht_cap.cap |= ((txstreams - 1) <<
IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT);
band->vht_cap.cap |=
IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
}
} }
static int brcmf_setup_wiphybands(struct wiphy *wiphy) static int brcmf_setup_wiphybands(struct wiphy *wiphy)
@ -5652,6 +5725,9 @@ static int brcmf_setup_wiphybands(struct wiphy *wiphy)
int err; int err;
s32 i; s32 i;
struct ieee80211_supported_band *band; struct ieee80211_supported_band *band;
u32 txstreams = 0;
u32 txbf_bfe_cap = 0;
u32 txbf_bfr_cap = 0;
(void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode); (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode);
err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode); err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
@ -5680,6 +5756,14 @@ static int brcmf_setup_wiphybands(struct wiphy *wiphy)
return err; return err;
} }
if (vhtmode) {
(void)brcmf_fil_iovar_int_get(ifp, "txstreams", &txstreams);
(void)brcmf_fil_iovar_int_get(ifp, "txbf_bfe_cap",
&txbf_bfe_cap);
(void)brcmf_fil_iovar_int_get(ifp, "txbf_bfr_cap",
&txbf_bfr_cap);
}
wiphy = cfg_to_wiphy(cfg); wiphy = cfg_to_wiphy(cfg);
for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) { for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) {
band = wiphy->bands[i]; band = wiphy->bands[i];
@ -5689,7 +5773,8 @@ static int brcmf_setup_wiphybands(struct wiphy *wiphy)
if (nmode) if (nmode)
brcmf_update_ht_cap(band, bw_cap, nchain); brcmf_update_ht_cap(band, bw_cap, nchain);
if (vhtmode) if (vhtmode)
brcmf_update_vht_cap(band, bw_cap, nchain); brcmf_update_vht_cap(band, bw_cap, nchain, txstreams,
txbf_bfe_cap, txbf_bfr_cap);
} }
return 0; return 0;
@ -6014,7 +6099,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
brcmf_dbg(INFO, "power save set to %s\n", brcmf_dbg(INFO, "power save set to %s\n",
(power_mode ? "enabled" : "disabled")); (power_mode ? "enabled" : "disabled"));
err = brcmf_dongle_roam(ifp, WL_BEACON_TIMEOUT); err = brcmf_dongle_roam(ifp);
if (err) if (err)
goto default_conf_out; goto default_conf_out;
err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,

View file

@ -28,7 +28,6 @@
#define WL_EXTRA_BUF_MAX 2048 #define WL_EXTRA_BUF_MAX 2048
#define WL_ROAM_TRIGGER_LEVEL -75 #define WL_ROAM_TRIGGER_LEVEL -75
#define WL_ROAM_DELTA 20 #define WL_ROAM_DELTA 20
#define WL_BEACON_TIMEOUT 3
#define WL_SCAN_CHANNEL_TIME 40 #define WL_SCAN_CHANNEL_TIME 40
#define WL_SCAN_UNASSOC_TIME 40 #define WL_SCAN_UNASSOC_TIME 40
@ -77,6 +76,9 @@
#define BRCMF_MAX_DEFAULT_KEYS 4 #define BRCMF_MAX_DEFAULT_KEYS 4
/* beacon loss timeout defaults */
#define BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON 2
#define BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_OFF 4
/** /**
* enum brcmf_scan_status - scan engine status * enum brcmf_scan_status - scan engine status
@ -124,13 +126,11 @@ struct brcmf_cfg80211_security {
/** /**
* struct brcmf_cfg80211_profile - profile information. * struct brcmf_cfg80211_profile - profile information.
* *
* @ssid: ssid of associated/associating ap.
* @bssid: bssid of joined/joining ibss. * @bssid: bssid of joined/joining ibss.
* @sec: security information. * @sec: security information.
* @key: key information * @key: key information
*/ */
struct brcmf_cfg80211_profile { struct brcmf_cfg80211_profile {
struct brcmf_ssid ssid;
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
struct brcmf_cfg80211_security sec; struct brcmf_cfg80211_security sec;
struct brcmf_wsec_key key[BRCMF_MAX_DEFAULT_KEYS]; struct brcmf_wsec_key key[BRCMF_MAX_DEFAULT_KEYS];
@ -180,7 +180,6 @@ struct vif_saved_ie {
* @ifp: lower layer interface pointer * @ifp: lower layer interface pointer
* @wdev: wireless device. * @wdev: wireless device.
* @profile: profile information. * @profile: profile information.
* @roam_off: roaming state.
* @sme_state: SME state using enum brcmf_vif_status bits. * @sme_state: SME state using enum brcmf_vif_status bits.
* @pm_block: power-management blocked. * @pm_block: power-management blocked.
* @list: linked list. * @list: linked list.
@ -191,7 +190,6 @@ struct brcmf_cfg80211_vif {
struct brcmf_if *ifp; struct brcmf_if *ifp;
struct wireless_dev wdev; struct wireless_dev wdev;
struct brcmf_cfg80211_profile profile; struct brcmf_cfg80211_profile profile;
s32 roam_off;
unsigned long sme_state; unsigned long sme_state;
bool pm_block; bool pm_block;
struct vif_saved_ie saved_ie; struct vif_saved_ie saved_ie;
@ -233,7 +231,7 @@ struct escan_info {
struct wiphy *wiphy; struct wiphy *wiphy;
struct brcmf_if *ifp; struct brcmf_if *ifp;
s32 (*run)(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, s32 (*run)(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
struct cfg80211_scan_request *request, u16 action); struct cfg80211_scan_request *request);
}; };
/** /**

View file

@ -681,6 +681,7 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
case BRCM_CC_43569_CHIP_ID: case BRCM_CC_43569_CHIP_ID:
case BRCM_CC_43570_CHIP_ID: case BRCM_CC_43570_CHIP_ID:
case BRCM_CC_4358_CHIP_ID: case BRCM_CC_4358_CHIP_ID:
case BRCM_CC_4359_CHIP_ID:
case BRCM_CC_43602_CHIP_ID: case BRCM_CC_43602_CHIP_ID:
case BRCM_CC_4371_CHIP_ID: case BRCM_CC_4371_CHIP_ID:
return 0x180000; return 0x180000;

View file

@ -29,7 +29,6 @@
const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
#define BRCMF_DEFAULT_BCN_TIMEOUT 3
#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40 #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40
#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40 #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
@ -107,26 +106,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
goto done; goto done;
} }
/*
* Setup timeout if Beacons are lost and roam is off to report
* link down
*/
err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout",
BRCMF_DEFAULT_BCN_TIMEOUT);
if (err) {
brcmf_err("bcn_timeout error (%d)\n", err);
goto done;
}
/* Enable/Disable build-in roaming to allowed ext supplicant to take
* of romaing
*/
err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
if (err) {
brcmf_err("roam_off error (%d)\n", err);
goto done;
}
/* Setup join_pref to select target by RSSI(with boost on 5GHz) */ /* Setup join_pref to select target by RSSI(with boost on 5GHz) */
join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA; join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
join_pref_params[0].len = 2; join_pref_params[0].len = 2;
@ -174,6 +153,9 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
goto done; goto done;
} }
/* Enable tx beamforming, errors can be ignored (not supported) */
(void)brcmf_fil_iovar_int_set(ifp, "txbf", 1);
/* do bus specific preinit here */ /* do bus specific preinit here */
err = brcmf_bus_preinit(ifp->drvr->bus_if); err = brcmf_bus_preinit(ifp->drvr->bus_if);
done: done:

View file

@ -66,20 +66,13 @@ static int brcmf_p2p_enable;
module_param_named(p2pon, brcmf_p2p_enable, int, 0); module_param_named(p2pon, brcmf_p2p_enable, int, 0);
MODULE_PARM_DESC(p2pon, "enable legacy p2p management functionality"); MODULE_PARM_DESC(p2pon, "enable legacy p2p management functionality");
char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx) char *brcmf_ifname(struct brcmf_if *ifp)
{ {
if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { if (!ifp)
brcmf_err("ifidx %d out of range\n", ifidx);
return "<if_bad>";
}
if (drvr->iflist[ifidx] == NULL) {
brcmf_err("null i/f %d\n", ifidx);
return "<if_null>"; return "<if_null>";
}
if (drvr->iflist[ifidx]->ndev) if (ifp->ndev)
return drvr->iflist[ifidx]->ndev->name; return ifp->ndev->name;
return "<if_none>"; return "<if_none>";
} }
@ -87,7 +80,7 @@ char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx)
struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx) struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx)
{ {
struct brcmf_if *ifp; struct brcmf_if *ifp;
s32 bssidx; s32 bsscfgidx;
if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
brcmf_err("ifidx %d out of range\n", ifidx); brcmf_err("ifidx %d out of range\n", ifidx);
@ -95,9 +88,9 @@ struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx)
} }
ifp = NULL; ifp = NULL;
bssidx = drvr->if2bss[ifidx]; bsscfgidx = drvr->if2bss[ifidx];
if (bssidx >= 0) if (bsscfgidx >= 0)
ifp = drvr->iflist[bssidx]; ifp = drvr->iflist[bsscfgidx];
return ifp; return ifp;
} }
@ -115,7 +108,7 @@ static void _brcmf_set_multicast_list(struct work_struct *work)
ifp = container_of(work, struct brcmf_if, multicast_work); ifp = container_of(work, struct brcmf_if, multicast_work);
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
ndev = ifp->ndev; ndev = ifp->ndev;
@ -175,7 +168,7 @@ _brcmf_set_mac_address(struct work_struct *work)
ifp = container_of(work, struct brcmf_if, setmacaddr_work); ifp = container_of(work, struct brcmf_if, setmacaddr_work);
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr, err = brcmf_fil_iovar_data_set(ifp, "cur_etheraddr", ifp->mac_addr,
ETH_ALEN); ETH_ALEN);
@ -213,7 +206,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
struct brcmf_pub *drvr = ifp->drvr; struct brcmf_pub *drvr = ifp->drvr;
struct ethhdr *eh = (struct ethhdr *)(skb->data); struct ethhdr *eh = (struct ethhdr *)(skb->data);
brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx); brcmf_dbg(DATA, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
/* Can the device send data? */ /* Can the device send data? */
if (drvr->bus_if->state != BRCMF_BUS_UP) { if (drvr->bus_if->state != BRCMF_BUS_UP) {
@ -224,27 +217,19 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
goto done; goto done;
} }
if (!drvr->iflist[ifp->bssidx]) {
brcmf_err("bad ifidx %d\n", ifp->bssidx);
netif_stop_queue(ndev);
dev_kfree_skb(skb);
ret = -ENODEV;
goto done;
}
/* Make sure there's enough room for any header */ /* Make sure there's enough room for any header */
if (skb_headroom(skb) < drvr->hdrlen) { if (skb_headroom(skb) < drvr->hdrlen) {
struct sk_buff *skb2; struct sk_buff *skb2;
brcmf_dbg(INFO, "%s: insufficient headroom\n", brcmf_dbg(INFO, "%s: insufficient headroom\n",
brcmf_ifname(drvr, ifp->bssidx)); brcmf_ifname(ifp));
drvr->bus_if->tx_realloc++; drvr->bus_if->tx_realloc++;
skb2 = skb_realloc_headroom(skb, drvr->hdrlen); skb2 = skb_realloc_headroom(skb, drvr->hdrlen);
dev_kfree_skb(skb); dev_kfree_skb(skb);
skb = skb2; skb = skb2;
if (skb == NULL) { if (skb == NULL) {
brcmf_err("%s: skb_realloc_headroom failed\n", brcmf_err("%s: skb_realloc_headroom failed\n",
brcmf_ifname(drvr, ifp->bssidx)); brcmf_ifname(ifp));
ret = -ENOMEM; ret = -ENOMEM;
goto done; goto done;
} }
@ -282,8 +267,8 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp,
if (!ifp || !ifp->ndev) if (!ifp || !ifp->ndev)
return; return;
brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n", brcmf_dbg(TRACE, "enter: bsscfgidx=%d stop=0x%X reason=%d state=%d\n",
ifp->bssidx, ifp->netif_stop, reason, state); ifp->bsscfgidx, ifp->netif_stop, reason, state);
spin_lock_irqsave(&ifp->netif_stop_lock, flags); spin_lock_irqsave(&ifp->netif_stop_lock, flags);
if (state) { if (state) {
@ -602,7 +587,7 @@ static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *ndev)
{ {
struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_if *ifp = netdev_priv(ndev);
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
return &ifp->stats; return &ifp->stats;
} }
@ -631,7 +616,7 @@ static int brcmf_netdev_stop(struct net_device *ndev)
{ {
struct brcmf_if *ifp = netdev_priv(ndev); struct brcmf_if *ifp = netdev_priv(ndev);
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
brcmf_cfg80211_down(ndev); brcmf_cfg80211_down(ndev);
@ -647,7 +632,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
struct brcmf_bus *bus_if = drvr->bus_if; struct brcmf_bus *bus_if = drvr->bus_if;
u32 toe_ol; u32 toe_ol;
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx); brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
/* If bus is not ready, can't continue */ /* If bus is not ready, can't continue */
if (bus_if->state != BRCMF_BUS_UP) { if (bus_if->state != BRCMF_BUS_UP) {
@ -689,7 +674,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
struct net_device *ndev; struct net_device *ndev;
s32 err; s32 err;
brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx, brcmf_dbg(TRACE, "Enter, bsscfgidx=%d mac=%pM\n", ifp->bsscfgidx,
ifp->mac_addr); ifp->mac_addr);
ndev = ifp->ndev; ndev = ifp->ndev;
@ -721,7 +706,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
return 0; return 0;
fail: fail:
drvr->iflist[ifp->bssidx] = NULL; drvr->iflist[ifp->bsscfgidx] = NULL;
ndev->netdev_ops = NULL; ndev->netdev_ops = NULL;
free_netdev(ndev); free_netdev(ndev);
return -EBADE; return -EBADE;
@ -739,7 +724,8 @@ void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on)
{ {
struct net_device *ndev; struct net_device *ndev;
brcmf_dbg(TRACE, "Enter, idx=%d carrier=%d\n", ifp->bssidx, on); brcmf_dbg(TRACE, "Enter, bsscfgidx=%d carrier=%d\n", ifp->bsscfgidx,
on);
ndev = ifp->ndev; ndev = ifp->ndev;
brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_DISCONNECTED, !on); brcmf_txflowblock_if(ifp, BRCMF_NETIF_STOP_REASON_DISCONNECTED, !on);
@ -786,7 +772,7 @@ static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
{ {
struct net_device *ndev; struct net_device *ndev;
brcmf_dbg(TRACE, "Enter, idx=%d mac=%pM\n", ifp->bssidx, brcmf_dbg(TRACE, "Enter, bsscfgidx=%d mac=%pM\n", ifp->bsscfgidx,
ifp->mac_addr); ifp->mac_addr);
ndev = ifp->ndev; ndev = ifp->ndev;
@ -805,34 +791,35 @@ static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
return 0; return 0;
fail: fail:
ifp->drvr->iflist[ifp->bssidx] = NULL; ifp->drvr->iflist[ifp->bsscfgidx] = NULL;
ndev->netdev_ops = NULL; ndev->netdev_ops = NULL;
free_netdev(ndev); free_netdev(ndev);
return -EBADE; return -EBADE;
} }
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
bool is_p2pdev, char *name, u8 *mac_addr) bool is_p2pdev, char *name, u8 *mac_addr)
{ {
struct brcmf_if *ifp; struct brcmf_if *ifp;
struct net_device *ndev; struct net_device *ndev;
brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifidx); brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", bsscfgidx, ifidx);
ifp = drvr->iflist[bssidx]; ifp = drvr->iflist[bsscfgidx];
/* /*
* Delete the existing interface before overwriting it * Delete the existing interface before overwriting it
* in case we missed the BRCMF_E_IF_DEL event. * in case we missed the BRCMF_E_IF_DEL event.
*/ */
if (ifp) { if (ifp) {
brcmf_err("ERROR: netdev:%s already exists\n",
ifp->ndev->name);
if (ifidx) { if (ifidx) {
brcmf_err("ERROR: netdev:%s already exists\n",
ifp->ndev->name);
netif_stop_queue(ifp->ndev); netif_stop_queue(ifp->ndev);
brcmf_net_detach(ifp->ndev); brcmf_net_detach(ifp->ndev);
drvr->iflist[bssidx] = NULL; drvr->iflist[bsscfgidx] = NULL;
} else { } else {
brcmf_err("ignore IF event\n"); brcmf_dbg(INFO, "netdev:%s ignore IF event\n",
ifp->ndev->name);
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
} }
@ -854,15 +841,15 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
ndev->destructor = brcmf_cfg80211_free_netdev; ndev->destructor = brcmf_cfg80211_free_netdev;
ifp = netdev_priv(ndev); ifp = netdev_priv(ndev);
ifp->ndev = ndev; ifp->ndev = ndev;
/* store mapping ifidx to bssidx */ /* store mapping ifidx to bsscfgidx */
if (drvr->if2bss[ifidx] == BRCMF_BSSIDX_INVALID) if (drvr->if2bss[ifidx] == BRCMF_BSSIDX_INVALID)
drvr->if2bss[ifidx] = bssidx; drvr->if2bss[ifidx] = bsscfgidx;
} }
ifp->drvr = drvr; ifp->drvr = drvr;
drvr->iflist[bssidx] = ifp; drvr->iflist[bsscfgidx] = ifp;
ifp->ifidx = ifidx; ifp->ifidx = ifidx;
ifp->bssidx = bssidx; ifp->bsscfgidx = bsscfgidx;
init_waitqueue_head(&ifp->pend_8021x_wait); init_waitqueue_head(&ifp->pend_8021x_wait);
spin_lock_init(&ifp->netif_stop_lock); spin_lock_init(&ifp->netif_stop_lock);
@ -876,21 +863,22 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
return ifp; return ifp;
} }
static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx) static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx)
{ {
struct brcmf_if *ifp; struct brcmf_if *ifp;
ifp = drvr->iflist[bssidx]; ifp = drvr->iflist[bsscfgidx];
drvr->iflist[bssidx] = NULL; drvr->iflist[bsscfgidx] = NULL;
if (!ifp) { if (!ifp) {
brcmf_err("Null interface, idx=%d\n", bssidx); brcmf_err("Null interface, bsscfgidx=%d\n", bsscfgidx);
return; return;
} }
brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx); brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", bsscfgidx,
if (drvr->if2bss[ifp->ifidx] == bssidx) ifp->ifidx);
if (drvr->if2bss[ifp->ifidx] == bsscfgidx)
drvr->if2bss[ifp->ifidx] = BRCMF_BSSIDX_INVALID; drvr->if2bss[ifp->ifidx] = BRCMF_BSSIDX_INVALID;
if (ifp->ndev) { if (ifp->ndev) {
if (bssidx == 0) { if (bsscfgidx == 0) {
if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
rtnl_lock(); rtnl_lock();
brcmf_netdev_stop(ifp->ndev); brcmf_netdev_stop(ifp->ndev);
@ -920,12 +908,12 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
void brcmf_remove_interface(struct brcmf_if *ifp) void brcmf_remove_interface(struct brcmf_if *ifp)
{ {
if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bssidx] != ifp)) if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bsscfgidx] != ifp))
return; return;
brcmf_dbg(TRACE, "Enter, bssidx=%d, ifidx=%d\n", ifp->bssidx, brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", ifp->bsscfgidx,
ifp->ifidx); ifp->ifidx);
brcmf_fws_del_interface(ifp); brcmf_fws_del_interface(ifp);
brcmf_del_if(ifp->drvr, ifp->bssidx); brcmf_del_if(ifp->drvr, ifp->bsscfgidx);
} }
int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr) int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr)
@ -940,10 +928,10 @@ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr)
highest = 2; highest = 2;
for (ifidx = 0; ifidx < BRCMF_MAX_IFS; ifidx++) { for (ifidx = 0; ifidx < BRCMF_MAX_IFS; ifidx++) {
if (drvr->iflist[ifidx]) { if (drvr->iflist[ifidx]) {
if (drvr->iflist[ifidx]->bssidx == bsscfgidx) if (drvr->iflist[ifidx]->bsscfgidx == bsscfgidx)
bsscfgidx = highest + 1; bsscfgidx = highest + 1;
else if (drvr->iflist[ifidx]->bssidx > highest) else if (drvr->iflist[ifidx]->bsscfgidx > highest)
highest = drvr->iflist[ifidx]->bssidx; highest = drvr->iflist[ifidx]->bsscfgidx;
} else { } else {
available = true; available = true;
} }
@ -1095,6 +1083,8 @@ fail:
brcmf_net_detach(ifp->ndev); brcmf_net_detach(ifp->ndev);
if (p2p_ifp) if (p2p_ifp)
brcmf_net_detach(p2p_ifp->ndev); brcmf_net_detach(p2p_ifp->ndev);
drvr->iflist[0] = NULL;
drvr->iflist[1] = NULL;
return ret; return ret;
} }
return 0; return 0;

View file

@ -174,7 +174,7 @@ enum brcmf_netif_stop_reason {
* @multicast_work: worker object for multicast provisioning. * @multicast_work: worker object for multicast provisioning.
* @fws_desc: interface specific firmware-signalling descriptor. * @fws_desc: interface specific firmware-signalling descriptor.
* @ifidx: interface index in device firmware. * @ifidx: interface index in device firmware.
* @bssidx: index of bss associated with this interface. * @bsscfgidx: index of bss associated with this interface.
* @mac_addr: assigned mac address. * @mac_addr: assigned mac address.
* @netif_stop: bitmap indicates reason why netif queues are stopped. * @netif_stop: bitmap indicates reason why netif queues are stopped.
* @netif_stop_lock: spinlock for update netif_stop from multiple sources. * @netif_stop_lock: spinlock for update netif_stop from multiple sources.
@ -190,7 +190,7 @@ struct brcmf_if {
struct work_struct multicast_work; struct work_struct multicast_work;
struct brcmf_fws_mac_descriptor *fws_desc; struct brcmf_fws_mac_descriptor *fws_desc;
int ifidx; int ifidx;
s32 bssidx; s32 bsscfgidx;
u8 mac_addr[ETH_ALEN]; u8 mac_addr[ETH_ALEN];
u8 netif_stop; u8 netif_stop;
spinlock_t netif_stop_lock; spinlock_t netif_stop_lock;
@ -205,10 +205,10 @@ struct brcmf_skb_reorder_data {
int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp); int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
/* Return pointer to interface name */ /* Return pointer to interface name */
char *brcmf_ifname(struct brcmf_pub *drvr, int idx); char *brcmf_ifname(struct brcmf_if *ifp);
struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx); struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx);
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx,
bool is_p2pdev, char *name, u8 *mac_addr); bool is_p2pdev, char *name, u8 *mac_addr);
void brcmf_remove_interface(struct brcmf_if *ifp); void brcmf_remove_interface(struct brcmf_if *ifp);
int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr); int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);

View file

@ -49,7 +49,7 @@ static int brcmf_debug_psm_watchdog_notify(struct brcmf_if *ifp,
const struct brcmf_event_msg *evtmsg, const struct brcmf_event_msg *evtmsg,
void *data) void *data)
{ {
brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx); brcmf_dbg(TRACE, "enter: bsscfgidx=%d\n", ifp->bsscfgidx);
return brcmf_debug_create_memdump(ifp->drvr->bus_if, data, return brcmf_debug_create_memdump(ifp->drvr->bus_if, data,
evtmsg->datalen); evtmsg->datalen);

View file

@ -17,6 +17,8 @@
#ifndef BRCMFMAC_DEBUG_H #ifndef BRCMFMAC_DEBUG_H
#define BRCMFMAC_DEBUG_H #define BRCMFMAC_DEBUG_H
#include <linux/net.h> /* net_ratelimit() */
/* message levels */ /* message levels */
#define BRCMF_TRACE_VAL 0x00000002 #define BRCMF_TRACE_VAL 0x00000002
#define BRCMF_INFO_VAL 0x00000004 #define BRCMF_INFO_VAL 0x00000004

View file

@ -137,6 +137,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID) if (drvr->bus_if->chip != BRCM_CC_43362_CHIP_ID)
brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0); brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p"); brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_P2P, "p2p");
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_RSDB, "rsdb_mode");
if (brcmf_feature_disable) { if (brcmf_feature_disable) {
brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n", brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",

View file

@ -24,13 +24,16 @@
* PNO: preferred network offload. * PNO: preferred network offload.
* WOWL: Wake-On-WLAN. * WOWL: Wake-On-WLAN.
* P2P: peer-to-peer * P2P: peer-to-peer
* RSDB: Real Simultaneous Dual Band
*/ */
#define BRCMF_FEAT_LIST \ #define BRCMF_FEAT_LIST \
BRCMF_FEAT_DEF(MBSS) \ BRCMF_FEAT_DEF(MBSS) \
BRCMF_FEAT_DEF(MCHAN) \ BRCMF_FEAT_DEF(MCHAN) \
BRCMF_FEAT_DEF(PNO) \ BRCMF_FEAT_DEF(PNO) \
BRCMF_FEAT_DEF(WOWL) \ BRCMF_FEAT_DEF(WOWL) \
BRCMF_FEAT_DEF(P2P) BRCMF_FEAT_DEF(P2P) \
BRCMF_FEAT_DEF(RSDB)
/* /*
* Quirks: * Quirks:
* *

View file

@ -28,9 +28,9 @@
#define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */ #define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */
#define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */ #define BRCMF_FW_NVRAM_PCIEDEV_LEN 10 /* pcie/1/4/ + \0 */
char brcmf_firmware_path[BRCMF_FW_PATH_LEN]; static char brcmf_firmware_path[BRCMF_FW_NAME_LEN];
module_param_string(alternative_fw_path, brcmf_firmware_path, module_param_string(alternative_fw_path, brcmf_firmware_path,
BRCMF_FW_PATH_LEN, 0440); BRCMF_FW_NAME_LEN, 0440);
enum nvram_parser_state { enum nvram_parser_state {
IDLE, IDLE,
@ -449,8 +449,7 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
if (raw_nvram) if (raw_nvram)
bcm47xx_nvram_release_contents(data); bcm47xx_nvram_release_contents(data);
if (fw) release_firmware(fw);
release_firmware(fw);
if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL)) if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
goto fail; goto fail;
@ -540,3 +539,43 @@ int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
0); 0);
} }
int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev,
struct brcmf_firmware_mapping mapping_table[],
u32 table_size, char fw_name[BRCMF_FW_NAME_LEN],
char nvram_name[BRCMF_FW_NAME_LEN])
{
u32 i;
char end;
for (i = 0; i < table_size; i++) {
if (mapping_table[i].chipid == chip &&
mapping_table[i].revmask & BIT(chiprev))
break;
}
if (i == table_size) {
brcmf_err("Unknown chipid %d [%d]\n", chip, chiprev);
return -ENODEV;
}
/* check if firmware path is provided by module parameter */
if (brcmf_firmware_path[0] != '\0') {
strlcpy(fw_name, brcmf_firmware_path, BRCMF_FW_NAME_LEN);
if ((nvram_name) && (mapping_table[i].nvram))
strlcpy(nvram_name, brcmf_firmware_path,
BRCMF_FW_NAME_LEN);
end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
if (end != '/') {
strlcat(fw_name, "/", BRCMF_FW_NAME_LEN);
if ((nvram_name) && (mapping_table[i].nvram))
strlcat(nvram_name, "/", BRCMF_FW_NAME_LEN);
}
}
strlcat(fw_name, mapping_table[i].fw, BRCMF_FW_NAME_LEN);
if ((nvram_name) && (mapping_table[i].nvram))
strlcat(nvram_name, mapping_table[i].nvram, BRCMF_FW_NAME_LEN);
return 0;
}

View file

@ -21,11 +21,51 @@
#define BRCMF_FW_REQ_FLAGS 0x00F0 #define BRCMF_FW_REQ_FLAGS 0x00F0
#define BRCMF_FW_REQ_NV_OPTIONAL 0x0010 #define BRCMF_FW_REQ_NV_OPTIONAL 0x0010
#define BRCMF_FW_PATH_LEN 256 #define BRCMF_FW_NAME_LEN 320
#define BRCMF_FW_NAME_LEN 32
extern char brcmf_firmware_path[]; #define BRCMF_FW_DEFAULT_PATH "brcm/"
/**
* struct brcmf_firmware_mapping - Used to map chipid/revmask to firmware
* filename and nvram filename. Each bus type implementation should create
* a table of firmware mappings (using the macros defined below).
*
* @chipid: ID of chip.
* @revmask: bitmask of revisions, e.g. 0x10 means rev 4 only, 0xf means rev 0-3
* @fw: name of the firmware file.
* @nvram: name of nvram file.
*/
struct brcmf_firmware_mapping {
u32 chipid;
u32 revmask;
const char *fw;
const char *nvram;
};
#define BRCMF_FW_NVRAM_DEF(fw_nvram_name, fw, nvram) \
static const char BRCM_ ## fw_nvram_name ## _FIRMWARE_NAME[] = \
BRCMF_FW_DEFAULT_PATH fw; \
static const char BRCM_ ## fw_nvram_name ## _NVRAM_NAME[] = \
BRCMF_FW_DEFAULT_PATH nvram; \
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw); \
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH nvram)
#define BRCMF_FW_DEF(fw_name, fw) \
static const char BRCM_ ## fw_name ## _FIRMWARE_NAME[] = \
BRCMF_FW_DEFAULT_PATH fw; \
MODULE_FIRMWARE(BRCMF_FW_DEFAULT_PATH fw) \
#define BRCMF_FW_NVRAM_ENTRY(chipid, mask, name) \
{ chipid, mask, \
BRCM_ ## name ## _FIRMWARE_NAME, BRCM_ ## name ## _NVRAM_NAME }
#define BRCMF_FW_ENTRY(chipid, mask, name) \
{ chipid, mask, BRCM_ ## name ## _FIRMWARE_NAME, NULL }
int brcmf_fw_map_chip_to_name(u32 chip, u32 chiprev,
struct brcmf_firmware_mapping mapping_table[],
u32 table_size, char fw_name[BRCMF_FW_NAME_LEN],
char nvram_name[BRCMF_FW_NAME_LEN]);
void brcmf_fw_nvram_free(void *nvram); void brcmf_fw_nvram_free(void *nvram);
/* /*
* Request firmware(s) asynchronously. When the asynchronous request * Request firmware(s) asynchronously. When the asynchronous request

View file

@ -182,8 +182,8 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
bool is_p2pdev; bool is_p2pdev;
int err = 0; int err = 0;
brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n", brcmf_dbg(EVENT, "action: %u ifidx: %u bsscfgidx: %u flags: %u role: %u\n",
ifevent->action, ifevent->ifidx, ifevent->bssidx, ifevent->action, ifevent->ifidx, ifevent->bsscfgidx,
ifevent->flags, ifevent->role); ifevent->flags, ifevent->role);
/* The P2P Device interface event must not be ignored contrary to what /* The P2P Device interface event must not be ignored contrary to what
@ -204,12 +204,12 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
return; return;
} }
ifp = drvr->iflist[ifevent->bssidx]; ifp = drvr->iflist[ifevent->bsscfgidx];
if (ifevent->action == BRCMF_E_IF_ADD) { if (ifevent->action == BRCMF_E_IF_ADD) {
brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname, brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
emsg->addr); emsg->addr);
ifp = brcmf_add_if(drvr, ifevent->bssidx, ifevent->ifidx, ifp = brcmf_add_if(drvr, ifevent->bsscfgidx, ifevent->ifidx,
is_p2pdev, emsg->ifname, emsg->addr); is_p2pdev, emsg->ifname, emsg->addr);
if (IS_ERR(ifp)) if (IS_ERR(ifp))
return; return;

View file

@ -219,7 +219,7 @@ struct brcmf_if_event {
u8 ifidx; u8 ifidx;
u8 action; u8 action;
u8 flags; u8 flags;
u8 bssidx; u8 bsscfgidx;
u8 role; u8 role;
}; };

View file

@ -126,7 +126,8 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
brcmf_dbg(FIL, "Failed: %s (%d)\n", brcmf_dbg(FIL, "Failed: %s (%d)\n",
brcmf_fil_get_errstr((u32)(-err)), err); brcmf_fil_get_errstr((u32)(-err)), err);
return -EBADE;
return err;
} }
s32 s32
@ -293,22 +294,22 @@ brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data)
} }
static u32 static u32
brcmf_create_bsscfg(s32 bssidx, char *name, char *data, u32 datalen, char *buf, brcmf_create_bsscfg(s32 bsscfgidx, char *name, char *data, u32 datalen,
u32 buflen) char *buf, u32 buflen)
{ {
const s8 *prefix = "bsscfg:"; const s8 *prefix = "bsscfg:";
s8 *p; s8 *p;
u32 prefixlen; u32 prefixlen;
u32 namelen; u32 namelen;
u32 iolen; u32 iolen;
__le32 bssidx_le; __le32 bsscfgidx_le;
if (bssidx == 0) if (bsscfgidx == 0)
return brcmf_create_iovar(name, data, datalen, buf, buflen); return brcmf_create_iovar(name, data, datalen, buf, buflen);
prefixlen = strlen(prefix); prefixlen = strlen(prefix);
namelen = strlen(name) + 1; /* lengh of iovar name + null */ namelen = strlen(name) + 1; /* lengh of iovar name + null */
iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen; iolen = prefixlen + namelen + sizeof(bsscfgidx_le) + datalen;
if (buflen < iolen) { if (buflen < iolen) {
brcmf_err("buffer is too short\n"); brcmf_err("buffer is too short\n");
@ -326,9 +327,9 @@ brcmf_create_bsscfg(s32 bssidx, char *name, char *data, u32 datalen, char *buf,
p += namelen; p += namelen;
/* bss config index as first data */ /* bss config index as first data */
bssidx_le = cpu_to_le32(bssidx); bsscfgidx_le = cpu_to_le32(bsscfgidx);
memcpy(p, &bssidx_le, sizeof(bssidx_le)); memcpy(p, &bsscfgidx_le, sizeof(bsscfgidx_le));
p += sizeof(bssidx_le); p += sizeof(bsscfgidx_le);
/* parameter buffer follows */ /* parameter buffer follows */
if (datalen) if (datalen)
@ -347,12 +348,12 @@ brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name,
mutex_lock(&drvr->proto_block); mutex_lock(&drvr->proto_block);
brcmf_dbg(FIL, "ifidx=%d, bssidx=%d, name=%s, len=%d\n", ifp->ifidx, brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d\n", ifp->ifidx,
ifp->bssidx, name, len); ifp->bsscfgidx, name, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len, buflen = brcmf_create_bsscfg(ifp->bsscfgidx, name, data, len,
drvr->proto_buf, sizeof(drvr->proto_buf)); drvr->proto_buf, sizeof(drvr->proto_buf));
if (buflen) { if (buflen) {
err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf, err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
@ -376,7 +377,7 @@ brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name,
mutex_lock(&drvr->proto_block); mutex_lock(&drvr->proto_block);
buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len, buflen = brcmf_create_bsscfg(ifp->bsscfgidx, name, data, len,
drvr->proto_buf, sizeof(drvr->proto_buf)); drvr->proto_buf, sizeof(drvr->proto_buf));
if (buflen) { if (buflen) {
err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf, err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
@ -387,8 +388,8 @@ brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name,
err = -EPERM; err = -EPERM;
brcmf_err("Creating bsscfg failed\n"); brcmf_err("Creating bsscfg failed\n");
} }
brcmf_dbg(FIL, "ifidx=%d, bssidx=%d, name=%s, len=%d\n", ifp->ifidx, brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d\n", ifp->ifidx,
ifp->bssidx, name, len); ifp->bsscfgidx, name, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n"); min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");

View file

@ -121,6 +121,11 @@
#define BRCMF_MAX_ASSOCLIST 128 #define BRCMF_MAX_ASSOCLIST 128
#define BRCMF_TXBF_SU_BFE_CAP BIT(0)
#define BRCMF_TXBF_MU_BFE_CAP BIT(1)
#define BRCMF_TXBF_SU_BFR_CAP BIT(0)
#define BRCMF_TXBF_MU_BFR_CAP BIT(1)
/* join preference types for join_pref iovar */ /* join preference types for join_pref iovar */
enum brcmf_join_pref_types { enum brcmf_join_pref_types {
BRCMF_JOIN_PREF_RSSI = 1, BRCMF_JOIN_PREF_RSSI = 1,
@ -170,7 +175,7 @@ struct brcmf_fil_af_params_le {
}; };
struct brcmf_fil_bss_enable_le { struct brcmf_fil_bss_enable_le {
__le32 bsscfg_idx; __le32 bsscfgidx;
__le32 enable; __le32 enable;
}; };
@ -282,14 +287,9 @@ struct brcm_rateset_le {
u8 rates[BRCMF_MAXRATES_IN_SET]; u8 rates[BRCMF_MAXRATES_IN_SET];
}; };
struct brcmf_ssid {
u32 SSID_len;
unsigned char SSID[32];
};
struct brcmf_ssid_le { struct brcmf_ssid_le {
__le32 SSID_len; __le32 SSID_len;
unsigned char SSID[32]; unsigned char SSID[IEEE80211_MAX_SSID_LEN];
}; };
struct brcmf_scan_params_le { struct brcmf_scan_params_le {
@ -634,4 +634,16 @@ struct brcmf_assoclist_le {
u8 mac[BRCMF_MAX_ASSOCLIST][ETH_ALEN]; u8 mac[BRCMF_MAX_ASSOCLIST][ETH_ALEN];
}; };
/**
* struct brcmf_wowl_wakeind_le - Wakeup indicators
* Note: note both fields contain same information.
*
* @pci_wakeind: Whether PCI PMECSR PMEStatus bit was set.
* @ucode_wakeind: What wakeup-event indication was set by ucode
*/
struct brcmf_wowl_wakeind_le {
__le32 pci_wakeind;
__le32 ucode_wakeind;
};
#endif /* FWIL_TYPES_H_ */ #endif /* FWIL_TYPES_H_ */

View file

@ -719,7 +719,7 @@ static void brcmf_fws_macdesc_init(struct brcmf_fws_mac_descriptor *desc,
desc->state = BRCMF_FWS_STATE_OPEN; desc->state = BRCMF_FWS_STATE_OPEN;
desc->requested_credit = 0; desc->requested_credit = 0;
desc->requested_packet = 0; desc->requested_packet = 0;
/* depending on use may need ifp->bssidx instead */ /* depending on use may need ifp->bsscfgidx instead */
desc->interface_id = ifidx; desc->interface_id = ifidx;
desc->ac_bitmap = 0xff; /* update this when handling APSD */ desc->ac_bitmap = 0xff; /* update this when handling APSD */
if (addr) if (addr)
@ -1938,7 +1938,7 @@ void brcmf_fws_reset_interface(struct brcmf_if *ifp)
{ {
struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc; struct brcmf_fws_mac_descriptor *entry = ifp->fws_desc;
brcmf_dbg(TRACE, "enter: idx=%d\n", ifp->bssidx); brcmf_dbg(TRACE, "enter: bsscfgidx=%d\n", ifp->bsscfgidx);
if (!entry) if (!entry)
return; return;

View file

@ -625,11 +625,10 @@ exit:
* @num_chans: number of channels to scan. * @num_chans: number of channels to scan.
* @chanspecs: channel parameters for @num_chans channels. * @chanspecs: channel parameters for @num_chans channels.
* @search_state: P2P discover state to use. * @search_state: P2P discover state to use.
* @action: scan action to pass to firmware.
* @bss_type: type of P2P bss. * @bss_type: type of P2P bss.
*/ */
static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans, static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
u16 chanspecs[], s32 search_state, u16 action, u16 chanspecs[], s32 search_state,
enum p2p_bss_type bss_type) enum p2p_bss_type bss_type)
{ {
s32 ret = 0; s32 ret = 0;
@ -642,7 +641,6 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
struct brcmf_cfg80211_vif *vif; struct brcmf_cfg80211_vif *vif;
struct brcmf_p2p_scan_le *p2p_params; struct brcmf_p2p_scan_le *p2p_params;
struct brcmf_scan_params_le *sparams; struct brcmf_scan_params_le *sparams;
struct brcmf_ssid ssid;
memsize += num_chans * sizeof(__le16); memsize += num_chans * sizeof(__le16);
memblk = kzalloc(memsize, GFP_KERNEL); memblk = kzalloc(memsize, GFP_KERNEL);
@ -655,16 +653,16 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
ret = -EINVAL; ret = -EINVAL;
goto exit; goto exit;
} }
p2p_params = (struct brcmf_p2p_scan_le *)memblk;
sparams = &p2p_params->eparams.params_le;
switch (search_state) { switch (search_state) {
case WL_P2P_DISC_ST_SEARCH: case WL_P2P_DISC_ST_SEARCH:
/* /*
* If we in SEARCH STATE, we don't need to set SSID explictly * If we in SEARCH STATE, we don't need to set SSID explictly
* because dongle use P2P WILDCARD internally by default * because dongle use P2P WILDCARD internally by default, use
* null ssid, which it is already due to kzalloc.
*/ */
/* use null ssid */
ssid.SSID_len = 0;
memset(ssid.SSID, 0, sizeof(ssid.SSID));
break; break;
case WL_P2P_DISC_ST_SCAN: case WL_P2P_DISC_ST_SCAN:
/* /*
@ -673,8 +671,10 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
* P2P WILDCARD because we just do broadcast scan unless * P2P WILDCARD because we just do broadcast scan unless
* setting SSID. * setting SSID.
*/ */
ssid.SSID_len = BRCMF_P2P_WILDCARD_SSID_LEN; sparams->ssid_le.SSID_len =
memcpy(ssid.SSID, BRCMF_P2P_WILDCARD_SSID, ssid.SSID_len); cpu_to_le32(BRCMF_P2P_WILDCARD_SSID_LEN);
memcpy(sparams->ssid_le.SSID, BRCMF_P2P_WILDCARD_SSID,
BRCMF_P2P_WILDCARD_SSID_LEN);
break; break;
default: default:
brcmf_err(" invalid search state %d\n", search_state); brcmf_err(" invalid search state %d\n", search_state);
@ -687,11 +687,9 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
/* /*
* set p2p scan parameters. * set p2p scan parameters.
*/ */
p2p_params = (struct brcmf_p2p_scan_le *)memblk;
p2p_params->type = 'E'; p2p_params->type = 'E';
/* determine the scan engine parameters */ /* determine the scan engine parameters */
sparams = &p2p_params->eparams.params_le;
sparams->bss_type = DOT11_BSSTYPE_ANY; sparams->bss_type = DOT11_BSSTYPE_ANY;
if (p2p->cfg->active_scan) if (p2p->cfg->active_scan)
sparams->scan_type = 0; sparams->scan_type = 0;
@ -699,9 +697,6 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
sparams->scan_type = 1; sparams->scan_type = 1;
eth_broadcast_addr(sparams->bssid); eth_broadcast_addr(sparams->bssid);
if (ssid.SSID_len)
memcpy(sparams->ssid_le.SSID, ssid.SSID, ssid.SSID_len);
sparams->ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
sparams->home_time = cpu_to_le32(P2PAPI_SCAN_HOME_TIME_MS); sparams->home_time = cpu_to_le32(P2PAPI_SCAN_HOME_TIME_MS);
/* /*
@ -742,7 +737,7 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
/* set the escan specific parameters */ /* set the escan specific parameters */
p2p_params->eparams.version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION); p2p_params->eparams.version = cpu_to_le32(BRCMF_ESCAN_REQ_VERSION);
p2p_params->eparams.action = cpu_to_le16(action); p2p_params->eparams.action = cpu_to_le16(WL_ESCAN_ACTION_START);
p2p_params->eparams.sync_id = cpu_to_le16(0x1234); p2p_params->eparams.sync_id = cpu_to_le16(0x1234);
/* perform p2p scan on primary device */ /* perform p2p scan on primary device */
ret = brcmf_fil_bsscfg_data_set(vif->ifp, "p2p_scan", memblk, memsize); ret = brcmf_fil_bsscfg_data_set(vif->ifp, "p2p_scan", memblk, memsize);
@ -766,8 +761,7 @@ exit:
*/ */
static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg, static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
struct brcmf_if *ifp, struct brcmf_if *ifp,
struct cfg80211_scan_request *request, struct cfg80211_scan_request *request)
u16 action)
{ {
struct brcmf_p2p_info *p2p = &cfg->p2p; struct brcmf_p2p_info *p2p = &cfg->p2p;
s32 err = 0; s32 err = 0;
@ -827,7 +821,7 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
num_nodfs++; num_nodfs++;
} }
err = brcmf_p2p_escan(p2p, num_nodfs, chanspecs, search_state, err = brcmf_p2p_escan(p2p, num_nodfs, chanspecs, search_state,
action, P2PAPI_BSSCFG_DEVICE); P2PAPI_BSSCFG_DEVICE);
kfree(chanspecs); kfree(chanspecs);
} }
exit: exit:
@ -1096,8 +1090,7 @@ static s32 brcmf_p2p_act_frm_search(struct brcmf_p2p_info *p2p, u16 channel)
default_chan_list[2] = ch.chspec; default_chan_list[2] = ch.chspec;
} }
err = brcmf_p2p_escan(p2p, channel_cnt, default_chan_list, err = brcmf_p2p_escan(p2p, channel_cnt, default_chan_list,
WL_P2P_DISC_ST_SEARCH, WL_ESCAN_ACTION_START, WL_P2P_DISC_ST_SEARCH, P2PAPI_BSSCFG_DEVICE);
P2PAPI_BSSCFG_DEVICE);
kfree(default_chan_list); kfree(default_chan_list);
exit: exit:
return err; return err;
@ -2067,7 +2060,7 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
struct brcmf_if *p2p_ifp; struct brcmf_if *p2p_ifp;
struct brcmf_if *pri_ifp; struct brcmf_if *pri_ifp;
int err; int err;
u32 bssidx; u32 bsscfgidx;
if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif) if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
return ERR_PTR(-ENOSPC); return ERR_PTR(-ENOSPC);
@ -2113,13 +2106,13 @@ static struct wireless_dev *brcmf_p2p_create_p2pdev(struct brcmf_p2p_info *p2p,
memcpy(&p2p_vif->wdev.address, p2p->dev_addr, sizeof(p2p->dev_addr)); memcpy(&p2p_vif->wdev.address, p2p->dev_addr, sizeof(p2p->dev_addr));
/* verify bsscfg index for P2P discovery */ /* verify bsscfg index for P2P discovery */
err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx); err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bsscfgidx);
if (err < 0) { if (err < 0) {
brcmf_err("retrieving discover bsscfg index failed\n"); brcmf_err("retrieving discover bsscfg index failed\n");
goto fail; goto fail;
} }
WARN_ON(p2p_ifp->bssidx != bssidx); WARN_ON(p2p_ifp->bsscfgidx != bsscfgidx);
init_completion(&p2p->send_af_done); init_completion(&p2p->send_af_done);
INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler); INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);

View file

@ -112,7 +112,6 @@ struct afx_hdl {
* @int_addr: P2P interface address. * @int_addr: P2P interface address.
* @bss_idx: informate for P2P bss types. * @bss_idx: informate for P2P bss types.
* @listen_timer: timer for @WL_P2P_DISC_ST_LISTEN discover state. * @listen_timer: timer for @WL_P2P_DISC_ST_LISTEN discover state.
* @ssid: ssid for P2P GO.
* @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state. * @listen_channel: channel for @WL_P2P_DISC_ST_LISTEN discover state.
* @remain_on_channel: contains copy of struct used by cfg80211. * @remain_on_channel: contains copy of struct used by cfg80211.
* @remain_on_channel_cookie: cookie counter for remain on channel cmd * @remain_on_channel_cookie: cookie counter for remain on channel cmd
@ -133,7 +132,6 @@ struct brcmf_p2p_info {
u8 int_addr[ETH_ALEN]; u8 int_addr[ETH_ALEN];
struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX]; struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX];
struct timer_list listen_timer; struct timer_list listen_timer;
struct brcmf_ssid ssid;
u8 listen_channel; u8 listen_channel;
struct ieee80211_channel remain_on_channel; struct ieee80211_channel remain_on_channel;
u32 remain_on_channel_cookie; u32 remain_on_channel_cookie;

View file

@ -44,23 +44,29 @@ enum brcmf_pcie_state {
BRCMFMAC_PCIE_STATE_UP BRCMFMAC_PCIE_STATE_UP
}; };
BRCMF_FW_NVRAM_DEF(43602, "brcmfmac43602-pcie.bin", "brcmfmac43602-pcie.txt");
BRCMF_FW_NVRAM_DEF(4350, "brcmfmac4350-pcie.bin", "brcmfmac4350-pcie.txt");
BRCMF_FW_NVRAM_DEF(4356, "brcmfmac4356-pcie.bin", "brcmfmac4356-pcie.txt");
BRCMF_FW_NVRAM_DEF(43570, "brcmfmac43570-pcie.bin", "brcmfmac43570-pcie.txt");
BRCMF_FW_NVRAM_DEF(4358, "brcmfmac4358-pcie.bin", "brcmfmac4358-pcie.txt");
BRCMF_FW_NVRAM_DEF(4359, "brcmfmac4359-pcie.bin", "brcmfmac4359-pcie.txt");
BRCMF_FW_NVRAM_DEF(4365B, "brcmfmac4365b-pcie.bin", "brcmfmac4365b-pcie.txt");
BRCMF_FW_NVRAM_DEF(4366B, "brcmfmac4366b-pcie.bin", "brcmfmac4366b-pcie.txt");
BRCMF_FW_NVRAM_DEF(4371, "brcmfmac4371-pcie.bin", "brcmfmac4371-pcie.txt");
#define BRCMF_PCIE_43602_FW_NAME "brcm/brcmfmac43602-pcie.bin" static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
#define BRCMF_PCIE_43602_NVRAM_NAME "brcm/brcmfmac43602-pcie.txt" BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
#define BRCMF_PCIE_4350_FW_NAME "brcm/brcmfmac4350-pcie.bin" BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4350_CHIP_ID, 0xFFFFFFFF, 4350),
#define BRCMF_PCIE_4350_NVRAM_NAME "brcm/brcmfmac4350-pcie.txt" BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
#define BRCMF_PCIE_4356_FW_NAME "brcm/brcmfmac4356-pcie.bin" BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43567_CHIP_ID, 0xFFFFFFFF, 43570),
#define BRCMF_PCIE_4356_NVRAM_NAME "brcm/brcmfmac4356-pcie.txt" BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43570),
#define BRCMF_PCIE_43570_FW_NAME "brcm/brcmfmac43570-pcie.bin" BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43570_CHIP_ID, 0xFFFFFFFF, 43570),
#define BRCMF_PCIE_43570_NVRAM_NAME "brcm/brcmfmac43570-pcie.txt" BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358),
#define BRCMF_PCIE_4358_FW_NAME "brcm/brcmfmac4358-pcie.bin" BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359),
#define BRCMF_PCIE_4358_NVRAM_NAME "brcm/brcmfmac4358-pcie.txt" BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFFF, 4365B),
#define BRCMF_PCIE_4365_FW_NAME "brcm/brcmfmac4365b-pcie.bin" BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFFF, 4366B),
#define BRCMF_PCIE_4365_NVRAM_NAME "brcm/brcmfmac4365b-pcie.txt" BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
#define BRCMF_PCIE_4366_FW_NAME "brcm/brcmfmac4366b-pcie.bin" };
#define BRCMF_PCIE_4366_NVRAM_NAME "brcm/brcmfmac4366b-pcie.txt"
#define BRCMF_PCIE_4371_FW_NAME "brcm/brcmfmac4371-pcie.bin"
#define BRCMF_PCIE_4371_NVRAM_NAME "brcm/brcmfmac4371-pcie.txt"
#define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */ #define BRCMF_PCIE_FW_UP_TIMEOUT 2000 /* msec */
@ -200,24 +206,6 @@ enum brcmf_pcie_state {
#define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB 3 #define BRCMF_PCIE_LINK_STATUS_CTRL_ASPM_ENAB 3
MODULE_FIRMWARE(BRCMF_PCIE_43602_FW_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_43602_NVRAM_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4350_FW_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4350_NVRAM_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4356_FW_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4356_NVRAM_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_43570_FW_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_43570_NVRAM_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4358_FW_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4358_NVRAM_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4365_FW_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4365_NVRAM_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4366_FW_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4366_NVRAM_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4371_FW_NAME);
MODULE_FIRMWARE(BRCMF_PCIE_4371_NVRAM_NAME);
struct brcmf_pcie_console { struct brcmf_pcie_console {
u32 base_addr; u32 base_addr;
u32 buf_addr; u32 buf_addr;
@ -253,10 +241,9 @@ struct brcmf_pcie_core_info {
struct brcmf_pciedev_info { struct brcmf_pciedev_info {
enum brcmf_pcie_state state; enum brcmf_pcie_state state;
bool in_irq; bool in_irq;
bool irq_requested;
struct pci_dev *pdev; struct pci_dev *pdev;
char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; char fw_name[BRCMF_FW_NAME_LEN];
char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; char nvram_name[BRCMF_FW_NAME_LEN];
void __iomem *regs; void __iomem *regs;
void __iomem *tcm; void __iomem *tcm;
u32 tcm_size; u32 tcm_size;
@ -622,7 +609,9 @@ static int brcmf_pcie_exit_download_state(struct brcmf_pciedev_info *devinfo,
brcmf_chip_resetcore(core, 0, 0, 0); brcmf_chip_resetcore(core, 0, 0, 0);
} }
return !brcmf_chip_set_active(devinfo->ci, resetintr); if (!brcmf_chip_set_active(devinfo->ci, resetintr))
return -EINVAL;
return 0;
} }
@ -885,7 +874,6 @@ static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo)
brcmf_dbg(PCIE, "Enter\n"); brcmf_dbg(PCIE, "Enter\n");
/* is it a v1 or v2 implementation */ /* is it a v1 or v2 implementation */
devinfo->irq_requested = false;
pci_enable_msi(pdev); pci_enable_msi(pdev);
if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) { if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) {
if (request_threaded_irq(pdev->irq, if (request_threaded_irq(pdev->irq,
@ -908,7 +896,6 @@ static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo)
return -EIO; return -EIO;
} }
} }
devinfo->irq_requested = true;
devinfo->irq_allocated = true; devinfo->irq_allocated = true;
return 0; return 0;
} }
@ -926,9 +913,6 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
pdev = devinfo->pdev; pdev = devinfo->pdev;
brcmf_pcie_intr_disable(devinfo); brcmf_pcie_intr_disable(devinfo);
if (!devinfo->irq_requested)
return;
devinfo->irq_requested = false;
free_irq(pdev->irq, devinfo); free_irq(pdev->irq, devinfo);
pci_disable_msi(pdev); pci_disable_msi(pdev);
@ -1390,10 +1374,6 @@ static void brcmf_pcie_wowl_config(struct device *dev, bool enabled)
brcmf_dbg(PCIE, "Configuring WOWL, enabled=%d\n", enabled); brcmf_dbg(PCIE, "Configuring WOWL, enabled=%d\n", enabled);
devinfo->wowl_enabled = enabled; devinfo->wowl_enabled = enabled;
if (enabled)
device_set_wakeup_enable(&devinfo->pdev->dev, true);
else
device_set_wakeup_enable(&devinfo->pdev->dev, false);
} }
@ -1419,7 +1399,7 @@ static int brcmf_pcie_get_memdump(struct device *dev, void *data, size_t len)
} }
static struct brcmf_bus_ops brcmf_pcie_bus_ops = { static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
.txdata = brcmf_pcie_tx, .txdata = brcmf_pcie_tx,
.stop = brcmf_pcie_down, .stop = brcmf_pcie_down,
.txctl = brcmf_pcie_tx_ctlpkt, .txctl = brcmf_pcie_tx_ctlpkt,
@ -1484,80 +1464,6 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
} }
static int brcmf_pcie_get_fwnames(struct brcmf_pciedev_info *devinfo)
{
char *fw_name;
char *nvram_name;
uint fw_len, nv_len;
char end;
brcmf_dbg(PCIE, "Enter, chip 0x%04x chiprev %d\n", devinfo->ci->chip,
devinfo->ci->chiprev);
switch (devinfo->ci->chip) {
case BRCM_CC_43602_CHIP_ID:
fw_name = BRCMF_PCIE_43602_FW_NAME;
nvram_name = BRCMF_PCIE_43602_NVRAM_NAME;
break;
case BRCM_CC_4350_CHIP_ID:
fw_name = BRCMF_PCIE_4350_FW_NAME;
nvram_name = BRCMF_PCIE_4350_NVRAM_NAME;
break;
case BRCM_CC_4356_CHIP_ID:
fw_name = BRCMF_PCIE_4356_FW_NAME;
nvram_name = BRCMF_PCIE_4356_NVRAM_NAME;
break;
case BRCM_CC_43567_CHIP_ID:
case BRCM_CC_43569_CHIP_ID:
case BRCM_CC_43570_CHIP_ID:
fw_name = BRCMF_PCIE_43570_FW_NAME;
nvram_name = BRCMF_PCIE_43570_NVRAM_NAME;
break;
case BRCM_CC_4358_CHIP_ID:
fw_name = BRCMF_PCIE_4358_FW_NAME;
nvram_name = BRCMF_PCIE_4358_NVRAM_NAME;
break;
case BRCM_CC_4365_CHIP_ID:
fw_name = BRCMF_PCIE_4365_FW_NAME;
nvram_name = BRCMF_PCIE_4365_NVRAM_NAME;
break;
case BRCM_CC_4366_CHIP_ID:
fw_name = BRCMF_PCIE_4366_FW_NAME;
nvram_name = BRCMF_PCIE_4366_NVRAM_NAME;
break;
case BRCM_CC_4371_CHIP_ID:
fw_name = BRCMF_PCIE_4371_FW_NAME;
nvram_name = BRCMF_PCIE_4371_NVRAM_NAME;
break;
default:
brcmf_err("Unsupported chip 0x%04x\n", devinfo->ci->chip);
return -ENODEV;
}
fw_len = sizeof(devinfo->fw_name) - 1;
nv_len = sizeof(devinfo->nvram_name) - 1;
/* check if firmware path is provided by module parameter */
if (brcmf_firmware_path[0] != '\0') {
strncpy(devinfo->fw_name, brcmf_firmware_path, fw_len);
strncpy(devinfo->nvram_name, brcmf_firmware_path, nv_len);
fw_len -= strlen(devinfo->fw_name);
nv_len -= strlen(devinfo->nvram_name);
end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
if (end != '/') {
strncat(devinfo->fw_name, "/", fw_len);
strncat(devinfo->nvram_name, "/", nv_len);
fw_len--;
nv_len--;
}
}
strncat(devinfo->fw_name, fw_name, fw_len);
strncat(devinfo->nvram_name, nvram_name, nv_len);
return 0;
}
static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo, static int brcmf_pcie_download_fw_nvram(struct brcmf_pciedev_info *devinfo,
const struct firmware *fw, void *nvram, const struct firmware *fw, void *nvram,
u32 nvram_len) u32 nvram_len)
@ -1893,7 +1799,10 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot); bus->wowl_supported = pci_pme_capable(pdev, PCI_D3hot);
dev_set_drvdata(&pdev->dev, bus); dev_set_drvdata(&pdev->dev, bus);
ret = brcmf_pcie_get_fwnames(devinfo); ret = brcmf_fw_map_chip_to_name(devinfo->ci->chip, devinfo->ci->chiprev,
brcmf_pcie_fwnames,
ARRAY_SIZE(brcmf_pcie_fwnames),
devinfo->fw_name, devinfo->nvram_name);
if (ret) if (ret)
goto fail_bus; goto fail_bus;
@ -1959,15 +1868,14 @@ brcmf_pcie_remove(struct pci_dev *pdev)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int brcmf_pcie_suspend(struct pci_dev *pdev, pm_message_t state) static int brcmf_pcie_pm_enter_D3(struct device *dev)
{ {
struct brcmf_pciedev_info *devinfo; struct brcmf_pciedev_info *devinfo;
struct brcmf_bus *bus; struct brcmf_bus *bus;
int err;
brcmf_dbg(PCIE, "Enter, state=%d, pdev=%p\n", state.event, pdev); brcmf_err("Enter\n");
bus = dev_get_drvdata(&pdev->dev); bus = dev_get_drvdata(dev);
devinfo = bus->bus_priv.pcie->devinfo; devinfo = bus->bus_priv.pcie->devinfo;
brcmf_bus_change_state(bus, BRCMF_BUS_DOWN); brcmf_bus_change_state(bus, BRCMF_BUS_DOWN);
@ -1982,62 +1890,45 @@ static int brcmf_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
brcmf_err("Timeout on response for entering D3 substate\n"); brcmf_err("Timeout on response for entering D3 substate\n");
return -EIO; return -EIO;
} }
brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM_IN_USE);
err = pci_save_state(pdev); devinfo->state = BRCMFMAC_PCIE_STATE_DOWN;
if (err)
brcmf_err("pci_save_state failed, err=%d\n", err);
if ((err) || (!devinfo->wowl_enabled)) {
brcmf_chip_detach(devinfo->ci);
devinfo->ci = NULL;
brcmf_pcie_remove(pdev);
return 0;
}
return pci_prepare_to_sleep(pdev); return 0;
} }
static int brcmf_pcie_resume(struct pci_dev *pdev)
static int brcmf_pcie_pm_leave_D3(struct device *dev)
{ {
struct brcmf_pciedev_info *devinfo; struct brcmf_pciedev_info *devinfo;
struct brcmf_bus *bus; struct brcmf_bus *bus;
struct pci_dev *pdev;
int err; int err;
bus = dev_get_drvdata(&pdev->dev); brcmf_err("Enter\n");
brcmf_dbg(PCIE, "Enter, pdev=%p, bus=%p\n", pdev, bus);
err = pci_set_power_state(pdev, PCI_D0); bus = dev_get_drvdata(dev);
if (err) { devinfo = bus->bus_priv.pcie->devinfo;
brcmf_err("pci_set_power_state failed, err=%d\n", err); brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus);
goto cleanup;
}
pci_restore_state(pdev);
pci_enable_wake(pdev, PCI_D3hot, false);
pci_enable_wake(pdev, PCI_D3cold, false);
/* Check if device is still up and running, if so we are ready */ /* Check if device is still up and running, if so we are ready */
if (bus) { if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0) {
devinfo = bus->bus_priv.pcie->devinfo; brcmf_dbg(PCIE, "Try to wakeup device....\n");
if (brcmf_pcie_read_reg32(devinfo, if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM))
BRCMF_PCIE_PCIE2REG_INTMASK) != 0) { goto cleanup;
if (brcmf_pcie_send_mb_data(devinfo, brcmf_dbg(PCIE, "Hot resume, continue....\n");
BRCMF_H2D_HOST_D0_INFORM)) devinfo->state = BRCMFMAC_PCIE_STATE_UP;
goto cleanup; brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
brcmf_dbg(PCIE, "Hot resume, continue....\n"); brcmf_bus_change_state(bus, BRCMF_BUS_UP);
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2); brcmf_pcie_intr_enable(devinfo);
brcmf_bus_change_state(bus, BRCMF_BUS_UP); return 0;
brcmf_pcie_intr_enable(devinfo);
return 0;
}
} }
cleanup: cleanup:
if (bus) { brcmf_chip_detach(devinfo->ci);
devinfo = bus->bus_priv.pcie->devinfo; devinfo->ci = NULL;
brcmf_chip_detach(devinfo->ci); pdev = devinfo->pdev;
devinfo->ci = NULL; brcmf_pcie_remove(pdev);
brcmf_pcie_remove(pdev);
}
err = brcmf_pcie_probe(pdev, NULL); err = brcmf_pcie_probe(pdev, NULL);
if (err) if (err)
brcmf_err("probe after resume failed, err=%d\n", err); brcmf_err("probe after resume failed, err=%d\n", err);
@ -2046,6 +1937,14 @@ cleanup:
} }
static const struct dev_pm_ops brcmf_pciedrvr_pm = {
.suspend = brcmf_pcie_pm_enter_D3,
.resume = brcmf_pcie_pm_leave_D3,
.freeze = brcmf_pcie_pm_enter_D3,
.restore = brcmf_pcie_pm_leave_D3,
};
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
@ -2058,6 +1957,7 @@ static struct pci_device_id brcmf_pcie_devid_table[] = {
BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_4358_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_4358_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_4359_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID), BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID),
@ -2083,9 +1983,8 @@ static struct pci_driver brcmf_pciedrvr = {
.probe = brcmf_pcie_probe, .probe = brcmf_pcie_probe,
.remove = brcmf_pcie_remove, .remove = brcmf_pcie_remove,
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = brcmf_pcie_suspend, .driver.pm = &brcmf_pciedrvr_pm,
.resume = brcmf_pcie_resume #endif
#endif /* CONFIG_PM */
}; };

View file

@ -460,7 +460,6 @@ struct brcmf_sdio {
struct sk_buff *glomd; /* Packet containing glomming descriptor */ struct sk_buff *glomd; /* Packet containing glomming descriptor */
struct sk_buff_head glom; /* Packet list for glommed superframe */ struct sk_buff_head glom; /* Packet list for glommed superframe */
uint glomerr; /* Glom packet read errors */
u8 *rxbuf; /* Buffer for receiving control packets */ u8 *rxbuf; /* Buffer for receiving control packets */
uint rxblen; /* Allocated length of rxbuf */ uint rxblen; /* Allocated length of rxbuf */
@ -597,136 +596,41 @@ static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
{4, 0x1} {4, 0x1}
}; };
#define BCM43143_FIRMWARE_NAME "brcm/brcmfmac43143-sdio.bin" BRCMF_FW_NVRAM_DEF(43143, "brcmfmac43143-sdio.bin", "brcmfmac43143-sdio.txt");
#define BCM43143_NVRAM_NAME "brcm/brcmfmac43143-sdio.txt" BRCMF_FW_NVRAM_DEF(43241B0, "brcmfmac43241b0-sdio.bin",
#define BCM43241B0_FIRMWARE_NAME "brcm/brcmfmac43241b0-sdio.bin" "brcmfmac43241b0-sdio.txt");
#define BCM43241B0_NVRAM_NAME "brcm/brcmfmac43241b0-sdio.txt" BRCMF_FW_NVRAM_DEF(43241B4, "brcmfmac43241b4-sdio.bin",
#define BCM43241B4_FIRMWARE_NAME "brcm/brcmfmac43241b4-sdio.bin" "brcmfmac43241b4-sdio.txt");
#define BCM43241B4_NVRAM_NAME "brcm/brcmfmac43241b4-sdio.txt" BRCMF_FW_NVRAM_DEF(43241B5, "brcmfmac43241b5-sdio.bin",
#define BCM43241B5_FIRMWARE_NAME "brcm/brcmfmac43241b5-sdio.bin" "brcmfmac43241b5-sdio.txt");
#define BCM43241B5_NVRAM_NAME "brcm/brcmfmac43241b5-sdio.txt" BRCMF_FW_NVRAM_DEF(4329, "brcmfmac4329-sdio.bin", "brcmfmac4329-sdio.txt");
#define BCM4329_FIRMWARE_NAME "brcm/brcmfmac4329-sdio.bin" BRCMF_FW_NVRAM_DEF(4330, "brcmfmac4330-sdio.bin", "brcmfmac4330-sdio.txt");
#define BCM4329_NVRAM_NAME "brcm/brcmfmac4329-sdio.txt" BRCMF_FW_NVRAM_DEF(4334, "brcmfmac4334-sdio.bin", "brcmfmac4334-sdio.txt");
#define BCM4330_FIRMWARE_NAME "brcm/brcmfmac4330-sdio.bin" BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt");
#define BCM4330_NVRAM_NAME "brcm/brcmfmac4330-sdio.txt" BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt");
#define BCM4334_FIRMWARE_NAME "brcm/brcmfmac4334-sdio.bin" BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt");
#define BCM4334_NVRAM_NAME "brcm/brcmfmac4334-sdio.txt" BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt");
#define BCM43340_FIRMWARE_NAME "brcm/brcmfmac43340-sdio.bin" BRCMF_FW_NVRAM_DEF(43430, "brcmfmac43430-sdio.bin", "brcmfmac43430-sdio.txt");
#define BCM43340_NVRAM_NAME "brcm/brcmfmac43340-sdio.txt" BRCMF_FW_NVRAM_DEF(43455, "brcmfmac43455-sdio.bin", "brcmfmac43455-sdio.txt");
#define BCM4335_FIRMWARE_NAME "brcm/brcmfmac4335-sdio.bin" BRCMF_FW_NVRAM_DEF(4354, "brcmfmac4354-sdio.bin", "brcmfmac4354-sdio.txt");
#define BCM4335_NVRAM_NAME "brcm/brcmfmac4335-sdio.txt"
#define BCM43362_FIRMWARE_NAME "brcm/brcmfmac43362-sdio.bin"
#define BCM43362_NVRAM_NAME "brcm/brcmfmac43362-sdio.txt"
#define BCM4339_FIRMWARE_NAME "brcm/brcmfmac4339-sdio.bin"
#define BCM4339_NVRAM_NAME "brcm/brcmfmac4339-sdio.txt"
#define BCM43430_FIRMWARE_NAME "brcm/brcmfmac43430-sdio.bin"
#define BCM43430_NVRAM_NAME "brcm/brcmfmac43430-sdio.txt"
#define BCM43455_FIRMWARE_NAME "brcm/brcmfmac43455-sdio.bin"
#define BCM43455_NVRAM_NAME "brcm/brcmfmac43455-sdio.txt"
#define BCM4354_FIRMWARE_NAME "brcm/brcmfmac4354-sdio.bin"
#define BCM4354_NVRAM_NAME "brcm/brcmfmac4354-sdio.txt"
MODULE_FIRMWARE(BCM43143_FIRMWARE_NAME); static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
MODULE_FIRMWARE(BCM43143_NVRAM_NAME); BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
MODULE_FIRMWARE(BCM43241B0_FIRMWARE_NAME); BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0),
MODULE_FIRMWARE(BCM43241B0_NVRAM_NAME); BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4),
MODULE_FIRMWARE(BCM43241B4_FIRMWARE_NAME); BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0xFFFFFFC0, 43241B5),
MODULE_FIRMWARE(BCM43241B4_NVRAM_NAME); BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, 4329),
MODULE_FIRMWARE(BCM43241B5_FIRMWARE_NAME); BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330),
MODULE_FIRMWARE(BCM43241B5_NVRAM_NAME); BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334),
MODULE_FIRMWARE(BCM4329_FIRMWARE_NAME); BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340),
MODULE_FIRMWARE(BCM4329_NVRAM_NAME); BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335),
MODULE_FIRMWARE(BCM4330_FIRMWARE_NAME); BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362),
MODULE_FIRMWARE(BCM4330_NVRAM_NAME); BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339),
MODULE_FIRMWARE(BCM4334_FIRMWARE_NAME); BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFF, 43430),
MODULE_FIRMWARE(BCM4334_NVRAM_NAME); BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455),
MODULE_FIRMWARE(BCM43340_FIRMWARE_NAME); BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354)
MODULE_FIRMWARE(BCM43340_NVRAM_NAME);
MODULE_FIRMWARE(BCM4335_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM4335_NVRAM_NAME);
MODULE_FIRMWARE(BCM43362_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM43362_NVRAM_NAME);
MODULE_FIRMWARE(BCM4339_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM4339_NVRAM_NAME);
MODULE_FIRMWARE(BCM43430_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM43430_NVRAM_NAME);
MODULE_FIRMWARE(BCM43455_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM43455_NVRAM_NAME);
MODULE_FIRMWARE(BCM4354_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM4354_NVRAM_NAME);
struct brcmf_firmware_names {
u32 chipid;
u32 revmsk;
const char *bin;
const char *nv;
}; };
enum brcmf_firmware_type {
BRCMF_FIRMWARE_BIN,
BRCMF_FIRMWARE_NVRAM
};
#define BRCMF_FIRMWARE_NVRAM(name) \
name ## _FIRMWARE_NAME, name ## _NVRAM_NAME
static const struct brcmf_firmware_names brcmf_fwname_data[] = {
{ BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) },
{ BRCM_CC_43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) },
{ BRCM_CC_43241_CHIP_ID, 0x00000020, BRCMF_FIRMWARE_NVRAM(BCM43241B4) },
{ BRCM_CC_43241_CHIP_ID, 0xFFFFFFC0, BRCMF_FIRMWARE_NVRAM(BCM43241B5) },
{ BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) },
{ BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) },
{ BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) },
{ BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43340) },
{ BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
{ BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
{ BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) },
{ BRCM_CC_43430_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43430) },
{ BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, BRCMF_FIRMWARE_NVRAM(BCM43455) },
{ BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) }
};
static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
struct brcmf_sdio_dev *sdiodev)
{
int i;
char end;
for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) {
if (brcmf_fwname_data[i].chipid == ci->chip &&
brcmf_fwname_data[i].revmsk & BIT(ci->chiprev))
break;
}
if (i == ARRAY_SIZE(brcmf_fwname_data)) {
brcmf_err("Unknown chipid %d [%d]\n", ci->chip, ci->chiprev);
return -ENODEV;
}
/* check if firmware path is provided by module parameter */
if (brcmf_firmware_path[0] != '\0') {
strlcpy(sdiodev->fw_name, brcmf_firmware_path,
sizeof(sdiodev->fw_name));
strlcpy(sdiodev->nvram_name, brcmf_firmware_path,
sizeof(sdiodev->nvram_name));
end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
if (end != '/') {
strlcat(sdiodev->fw_name, "/",
sizeof(sdiodev->fw_name));
strlcat(sdiodev->nvram_name, "/",
sizeof(sdiodev->nvram_name));
}
}
strlcat(sdiodev->fw_name, brcmf_fwname_data[i].bin,
sizeof(sdiodev->fw_name));
strlcat(sdiodev->nvram_name, brcmf_fwname_data[i].nv,
sizeof(sdiodev->nvram_name));
return 0;
}
static void pkt_align(struct sk_buff *p, int len, int align) static void pkt_align(struct sk_buff *p, int len, int align)
{ {
uint datalign; uint datalign;
@ -1654,20 +1558,15 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)
sdio_release_host(bus->sdiodev->func[1]); sdio_release_host(bus->sdiodev->func[1]);
bus->sdcnt.f2rxdata++; bus->sdcnt.f2rxdata++;
/* On failure, kill the superframe, allow a couple retries */ /* On failure, kill the superframe */
if (errcode < 0) { if (errcode < 0) {
brcmf_err("glom read of %d bytes failed: %d\n", brcmf_err("glom read of %d bytes failed: %d\n",
dlen, errcode); dlen, errcode);
sdio_claim_host(bus->sdiodev->func[1]); sdio_claim_host(bus->sdiodev->func[1]);
if (bus->glomerr++ < 3) { brcmf_sdio_rxfail(bus, true, false);
brcmf_sdio_rxfail(bus, true, true); bus->sdcnt.rxglomfail++;
} else { brcmf_sdio_free_glom(bus);
bus->glomerr = 0;
brcmf_sdio_rxfail(bus, true, false);
bus->sdcnt.rxglomfail++;
brcmf_sdio_free_glom(bus);
}
sdio_release_host(bus->sdiodev->func[1]); sdio_release_host(bus->sdiodev->func[1]);
return 0; return 0;
} }
@ -1708,19 +1607,11 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)
} }
if (errcode) { if (errcode) {
/* Terminate frame on error, request /* Terminate frame on error */
a couple retries */
sdio_claim_host(bus->sdiodev->func[1]); sdio_claim_host(bus->sdiodev->func[1]);
if (bus->glomerr++ < 3) { brcmf_sdio_rxfail(bus, true, false);
/* Restore superframe header space */ bus->sdcnt.rxglomfail++;
skb_push(pfirst, sfdoff); brcmf_sdio_free_glom(bus);
brcmf_sdio_rxfail(bus, true, true);
} else {
bus->glomerr = 0;
brcmf_sdio_rxfail(bus, true, false);
bus->sdcnt.rxglomfail++;
brcmf_sdio_free_glom(bus);
}
sdio_release_host(bus->sdiodev->func[1]); sdio_release_host(bus->sdiodev->func[1]);
bus->cur_read.len = 0; bus->cur_read.len = 0;
return 0; return 0;
@ -4025,7 +3916,7 @@ brcmf_sdio_watchdog(unsigned long data)
} }
} }
static struct brcmf_bus_ops brcmf_sdio_bus_ops = { static const struct brcmf_bus_ops brcmf_sdio_bus_ops = {
.stop = brcmf_sdio_bus_stop, .stop = brcmf_sdio_bus_stop,
.preinit = brcmf_sdio_bus_preinit, .preinit = brcmf_sdio_bus_preinit,
.txdata = brcmf_sdio_bus_txdata, .txdata = brcmf_sdio_bus_txdata,
@ -4266,7 +4157,10 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
brcmf_sdio_debugfs_create(bus); brcmf_sdio_debugfs_create(bus);
brcmf_dbg(INFO, "completed!!\n"); brcmf_dbg(INFO, "completed!!\n");
ret = brcmf_sdio_get_fwnames(bus->ci, sdiodev); ret = brcmf_fw_map_chip_to_name(bus->ci->chip, bus->ci->chiprev,
brcmf_sdio_fwnames,
ARRAY_SIZE(brcmf_sdio_fwnames),
sdiodev->fw_name, sdiodev->nvram_name);
if (ret) if (ret)
goto fail; goto fail;

View file

@ -195,8 +195,8 @@ struct brcmf_sdio_dev {
uint max_segment_size; uint max_segment_size;
uint txglomsz; uint txglomsz;
struct sg_table sgtable; struct sg_table sgtable;
char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; char fw_name[BRCMF_FW_NAME_LEN];
char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; char nvram_name[BRCMF_FW_NAME_LEN];
bool wowl_enabled; bool wowl_enabled;
enum brcmf_sdiod_state state; enum brcmf_sdiod_state state;
struct brcmf_sdiod_freezer *freezer; struct brcmf_sdiod_freezer *freezer;

View file

@ -43,10 +43,20 @@
#define BRCMF_USB_CBCTL_READ 1 #define BRCMF_USB_CBCTL_READ 1
#define BRCMF_USB_MAX_PKT_SIZE 1600 #define BRCMF_USB_MAX_PKT_SIZE 1600
#define BRCMF_USB_43143_FW_NAME "brcm/brcmfmac43143.bin" BRCMF_FW_DEF(43143, "brcmfmac43143.bin");
#define BRCMF_USB_43236_FW_NAME "brcm/brcmfmac43236b.bin" BRCMF_FW_DEF(43236B, "brcmfmac43236b.bin");
#define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin" BRCMF_FW_DEF(43242A, "brcmfmac43242a.bin");
#define BRCMF_USB_43569_FW_NAME "brcm/brcmfmac43569.bin" BRCMF_FW_DEF(43569, "brcmfmac43569.bin");
static struct brcmf_firmware_mapping brcmf_usb_fwnames[] = {
BRCMF_FW_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
BRCMF_FW_ENTRY(BRCM_CC_43235_CHIP_ID, 0x00000008, 43236B),
BRCMF_FW_ENTRY(BRCM_CC_43236_CHIP_ID, 0x00000008, 43236B),
BRCMF_FW_ENTRY(BRCM_CC_43238_CHIP_ID, 0x00000008, 43236B),
BRCMF_FW_ENTRY(BRCM_CC_43242_CHIP_ID, 0xFFFFFFFF, 43242A),
BRCMF_FW_ENTRY(BRCM_CC_43566_CHIP_ID, 0xFFFFFFFF, 43569),
BRCMF_FW_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43569)
};
#define TRX_MAGIC 0x30524448 /* "HDR0" */ #define TRX_MAGIC 0x30524448 /* "HDR0" */
#define TRX_MAX_OFFSET 3 /* Max number of file offsets */ #define TRX_MAX_OFFSET 3 /* Max number of file offsets */
@ -139,6 +149,7 @@ struct brcmf_usbdev_info {
struct brcmf_usbreq *tx_reqs; struct brcmf_usbreq *tx_reqs;
struct brcmf_usbreq *rx_reqs; struct brcmf_usbreq *rx_reqs;
char fw_name[BRCMF_FW_NAME_LEN];
const u8 *image; /* buffer for combine fw and nvram */ const u8 *image; /* buffer for combine fw and nvram */
int image_len; int image_len;
@ -983,45 +994,15 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
return 0; return 0;
} }
static bool brcmf_usb_chip_support(int chipid, int chiprev)
{
switch(chipid) {
case BRCM_CC_43143_CHIP_ID:
return true;
case BRCM_CC_43235_CHIP_ID:
case BRCM_CC_43236_CHIP_ID:
case BRCM_CC_43238_CHIP_ID:
return (chiprev == 3);
case BRCM_CC_43242_CHIP_ID:
return true;
case BRCM_CC_43566_CHIP_ID:
case BRCM_CC_43569_CHIP_ID:
return true;
default:
break;
}
return false;
}
static int static int
brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo) brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
{ {
int devid, chiprev;
int err; int err;
brcmf_dbg(USB, "Enter\n"); brcmf_dbg(USB, "Enter\n");
if (devinfo == NULL) if (devinfo == NULL)
return -ENODEV; return -ENODEV;
devid = devinfo->bus_pub.devid;
chiprev = devinfo->bus_pub.chiprev;
if (!brcmf_usb_chip_support(devid, chiprev)) {
brcmf_err("unsupported chip %d rev %d\n",
devid, chiprev);
return -EINVAL;
}
if (!devinfo->image) { if (!devinfo->image) {
brcmf_err("No firmware!\n"); brcmf_err("No firmware!\n");
return -ENOENT; return -ENOENT;
@ -1071,25 +1052,6 @@ static int check_file(const u8 *headers)
return -1; return -1;
} }
static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo)
{
switch (devinfo->bus_pub.devid) {
case BRCM_CC_43143_CHIP_ID:
return BRCMF_USB_43143_FW_NAME;
case BRCM_CC_43235_CHIP_ID:
case BRCM_CC_43236_CHIP_ID:
case BRCM_CC_43238_CHIP_ID:
return BRCMF_USB_43236_FW_NAME;
case BRCM_CC_43242_CHIP_ID:
return BRCMF_USB_43242_FW_NAME;
case BRCM_CC_43566_CHIP_ID:
case BRCM_CC_43569_CHIP_ID:
return BRCMF_USB_43569_FW_NAME;
default:
return NULL;
}
}
static static
struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo, struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
@ -1163,7 +1125,7 @@ static void brcmf_usb_wowl_config(struct device *dev, bool enabled)
device_set_wakeup_enable(devinfo->dev, false); device_set_wakeup_enable(devinfo->dev, false);
} }
static struct brcmf_bus_ops brcmf_usb_bus_ops = { static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
.txdata = brcmf_usb_tx, .txdata = brcmf_usb_tx,
.stop = brcmf_usb_down, .stop = brcmf_usb_down,
.txctl = brcmf_usb_tx_ctlpkt, .txctl = brcmf_usb_tx_ctlpkt,
@ -1274,9 +1236,16 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
bus->chip = bus_pub->devid; bus->chip = bus_pub->devid;
bus->chiprev = bus_pub->chiprev; bus->chiprev = bus_pub->chiprev;
ret = brcmf_fw_map_chip_to_name(bus_pub->devid, bus_pub->chiprev,
brcmf_usb_fwnames,
ARRAY_SIZE(brcmf_usb_fwnames),
devinfo->fw_name, NULL);
if (ret)
goto fail;
/* request firmware here */ /* request firmware here */
ret = brcmf_fw_get_firmwares(dev, 0, brcmf_usb_get_fwname(devinfo), ret = brcmf_fw_get_firmwares(dev, 0, devinfo->fw_name, NULL,
NULL, brcmf_usb_probe_phase2); brcmf_usb_probe_phase2);
if (ret) { if (ret) {
brcmf_err("firmware request failed: %d\n", ret); brcmf_err("firmware request failed: %d\n", ret);
goto fail; goto fail;
@ -1472,8 +1441,7 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf)
brcmf_dbg(USB, "Enter\n"); brcmf_dbg(USB, "Enter\n");
return brcmf_fw_get_firmwares(&usb->dev, 0, return brcmf_fw_get_firmwares(&usb->dev, 0, devinfo->fw_name, NULL,
brcmf_usb_get_fwname(devinfo), NULL,
brcmf_usb_probe_phase2); brcmf_usb_probe_phase2);
} }
@ -1491,10 +1459,6 @@ static struct usb_device_id brcmf_usb_devid_table[] = {
}; };
MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table); MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table);
MODULE_FIRMWARE(BRCMF_USB_43143_FW_NAME);
MODULE_FIRMWARE(BRCMF_USB_43236_FW_NAME);
MODULE_FIRMWARE(BRCMF_USB_43242_FW_NAME);
MODULE_FIRMWARE(BRCMF_USB_43569_FW_NAME);
static struct usb_driver brcmf_usbdrvr = { static struct usb_driver brcmf_usbdrvr = {
.name = KBUILD_MODNAME, .name = KBUILD_MODNAME,
@ -1504,7 +1468,6 @@ static struct usb_driver brcmf_usbdrvr = {
.suspend = brcmf_usb_suspend, .suspend = brcmf_usb_suspend,
.resume = brcmf_usb_resume, .resume = brcmf_usb_resume,
.reset_resume = brcmf_usb_reset_resume, .reset_resume = brcmf_usb_reset_resume,
.supports_autosuspend = 1,
.disable_hub_initiated_lpm = 1, .disable_hub_initiated_lpm = 1,
}; };

View file

@ -47,6 +47,7 @@
#define BRCM_CC_43569_CHIP_ID 43569 #define BRCM_CC_43569_CHIP_ID 43569
#define BRCM_CC_43570_CHIP_ID 43570 #define BRCM_CC_43570_CHIP_ID 43570
#define BRCM_CC_4358_CHIP_ID 0x4358 #define BRCM_CC_4358_CHIP_ID 0x4358
#define BRCM_CC_4359_CHIP_ID 0x4359
#define BRCM_CC_43602_CHIP_ID 43602 #define BRCM_CC_43602_CHIP_ID 43602
#define BRCM_CC_4365_CHIP_ID 0x4365 #define BRCM_CC_4365_CHIP_ID 0x4365
#define BRCM_CC_4366_CHIP_ID 0x4366 #define BRCM_CC_4366_CHIP_ID 0x4366
@ -66,6 +67,7 @@
#define BRCM_PCIE_43567_DEVICE_ID 0x43d3 #define BRCM_PCIE_43567_DEVICE_ID 0x43d3
#define BRCM_PCIE_43570_DEVICE_ID 0x43d9 #define BRCM_PCIE_43570_DEVICE_ID 0x43d9
#define BRCM_PCIE_4358_DEVICE_ID 0x43e9 #define BRCM_PCIE_4358_DEVICE_ID 0x43e9
#define BRCM_PCIE_4359_DEVICE_ID 0x43ef
#define BRCM_PCIE_43602_DEVICE_ID 0x43ba #define BRCM_PCIE_43602_DEVICE_ID 0x43ba
#define BRCM_PCIE_43602_2G_DEVICE_ID 0x43bb #define BRCM_PCIE_43602_2G_DEVICE_ID 0x43bb
#define BRCM_PCIE_43602_5G_DEVICE_ID 0x43bc #define BRCM_PCIE_43602_5G_DEVICE_ID 0x43bc

View file

@ -5137,21 +5137,9 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) {
memset(APList_rid, 0, sizeof(*APList_rid)); memset(APList_rid, 0, sizeof(*APList_rid));
APList_rid->len = cpu_to_le16(sizeof(*APList_rid)); APList_rid->len = cpu_to_le16(sizeof(*APList_rid));
for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) { for (i = 0; i < 4 && data->writelen >= (i + 1) * 6 * 3; i++)
int j; mac_pton(data->wbuffer + i * 6 * 3, APList_rid->ap[i]);
for( j = 0; j < 6*3 && data->wbuffer[j+i*6*3]; j++ ) {
switch(j%3) {
case 0:
APList_rid->ap[i][j/3]=
hex_to_bin(data->wbuffer[j+i*6*3])<<4;
break;
case 1:
APList_rid->ap[i][j/3]|=
hex_to_bin(data->wbuffer[j+i*6*3]);
break;
}
}
}
disable_MAC(ai, 1); disable_MAC(ai, 1);
writeAPListRid(ai, APList_rid, 1); writeAPListRid(ai, APList_rid, 1);
enable_MAC(ai, 1); enable_MAC(ai, 1);

View file

@ -53,7 +53,7 @@ config IWLWIFI_LEDS
config IWLDVM config IWLDVM
tristate "Intel Wireless WiFi DVM Firmware support" tristate "Intel Wireless WiFi DVM Firmware support"
default IWLWIFI depends on m
help help
This is the driver that supports the DVM firmware. The list This is the driver that supports the DVM firmware. The list
of the devices that use this firmware is available here: of the devices that use this firmware is available here:

View file

@ -8,7 +8,7 @@ iwlwifi-objs += iwl-eeprom-read.o iwl-eeprom-parse.o
iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o iwlwifi-objs += iwl-phy-db.o iwl-nvm-parse.o
iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o iwlwifi-objs += pcie/drv.o pcie/rx.o pcie/tx.o pcie/trans.o
iwlwifi-$(CONFIG_IWLDVM) += iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o iwlwifi-$(CONFIG_IWLDVM) += iwl-1000.o iwl-2000.o iwl-5000.o iwl-6000.o
iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o iwl-8000.o iwlwifi-$(CONFIG_IWLMVM) += iwl-7000.o iwl-8000.o iwl-9000.o
iwlwifi-objs += iwl-trans.o iwlwifi-objs += iwl-trans.o
iwlwifi-objs += $(iwlwifi-m) iwlwifi-objs += $(iwlwifi-m)

View file

@ -25,7 +25,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE

View file

@ -25,7 +25,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE

View file

@ -25,7 +25,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE

View file

@ -19,7 +19,7 @@
* file called LICENSE. * file called LICENSE.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -19,7 +19,7 @@
* file called LICENSE. * file called LICENSE.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/
@ -134,8 +134,6 @@ static int iwl_led_cmd(struct iwl_priv *priv,
on = IWL_LED_SOLID; on = IWL_LED_SOLID;
} }
IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n",
priv->cfg->base_params->led_compensation);
led_cmd.on = iwl_blink_compensation(priv, on, led_cmd.on = iwl_blink_compensation(priv, on,
priv->cfg->base_params->led_compensation); priv->cfg->base_params->led_compensation);
led_cmd.off = iwl_blink_compensation(priv, off, led_cmd.off = iwl_blink_compensation(priv, off,

View file

@ -22,7 +22,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -1411,13 +1411,7 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
if (WARN_ON(ctx->vif != vif)) { WARN_ON(ctx->vif != vif);
struct iwl_rxon_context *tmp;
IWL_ERR(priv, "ctx->vif = %p, vif = %p\n", ctx->vif, vif);
for_each_context(priv, tmp)
IWL_ERR(priv, "\tID = %d:\tctx = %p\tctx->vif = %p\n",
tmp->ctxid, tmp, tmp->vif);
}
ctx->vif = NULL; ctx->vif = NULL;
iwl_teardown_interface(priv, vif, false); iwl_teardown_interface(priv, vif, false);

View file

@ -1227,7 +1227,21 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
trans_cfg.op_mode = op_mode; trans_cfg.op_mode = op_mode;
trans_cfg.no_reclaim_cmds = no_reclaim_cmds; trans_cfg.no_reclaim_cmds = no_reclaim_cmds;
trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds); trans_cfg.n_no_reclaim_cmds = ARRAY_SIZE(no_reclaim_cmds);
trans_cfg.rx_buf_size_8k = iwlwifi_mod_params.amsdu_size_8K;
switch (iwlwifi_mod_params.amsdu_size) {
case IWL_AMSDU_4K:
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
break;
case IWL_AMSDU_8K:
trans_cfg.rx_buf_size = IWL_AMSDU_8K;
break;
case IWL_AMSDU_12K:
default:
trans_cfg.rx_buf_size = IWL_AMSDU_4K;
pr_err("Unsupported amsdu_size: %d\n",
iwlwifi_mod_params.amsdu_size);
}
trans_cfg.cmd_q_wdg_timeout = IWL_WATCHDOG_DISABLED; trans_cfg.cmd_q_wdg_timeout = IWL_WATCHDOG_DISABLED;
trans_cfg.command_names = iwl_dvm_cmd_strings; trans_cfg.command_names = iwl_dvm_cmd_strings;

View file

@ -22,7 +22,7 @@
* file called LICENSE. * file called LICENSE.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/ *****************************************************************************/

View file

@ -22,7 +22,7 @@
* file called LICENSE. * file called LICENSE.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/ *****************************************************************************/
#ifndef __iwl_power_setting_h__ #ifndef __iwl_power_setting_h__

View file

@ -23,7 +23,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -19,7 +19,7 @@
* file called LICENSE. * file called LICENSE.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -19,7 +19,7 @@
* file called LICENSE. * file called LICENSE.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -19,7 +19,7 @@
* file called LICENSE. * file called LICENSE.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -19,7 +19,7 @@
* file called LICENSE. * file called LICENSE.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -7,6 +7,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as * it under the terms of version 2 of the GNU General Public License as
@ -33,6 +34,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -274,6 +276,17 @@ const struct iwl_cfg iwl3165_2ac_cfg = {
.dccm_len = IWL7265_DCCM_LEN, .dccm_len = IWL7265_DCCM_LEN,
}; };
const struct iwl_cfg iwl3168_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 3168",
.fw_name_pre = IWL7265D_FW_PRE,
IWL_DEVICE_7000,
.ht_params = &iwl7000_ht_params,
.nvm_ver = IWL3165_NVM_VERSION,
.nvm_calib_ver = IWL3165_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265_2ac_cfg = { const struct iwl_cfg iwl7265_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 7265", .name = "Intel(R) Dual Band Wireless AC 7265",
.fw_name_pre = IWL7265_FW_PRE, .fw_name_pre = IWL7265_FW_PRE,

View file

@ -154,7 +154,6 @@ static const struct iwl_tt_params iwl8000_tt_params = {
.base_params = &iwl8000_base_params, \ .base_params = &iwl8000_base_params, \
.led_mode = IWL_LED_RF_STATE, \ .led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000, \ .nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000, \
.d0i3 = true, \
.features = NETIF_F_RXCSUM, \ .features = NETIF_F_RXCSUM, \
.non_shared_ant = ANT_A, \ .non_shared_ant = ANT_A, \
.dccm_offset = IWL8260_DCCM_OFFSET, \ .dccm_offset = IWL8260_DCCM_OFFSET, \
@ -187,6 +186,16 @@ const struct iwl_cfg iwl8260_2ac_cfg = {
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
}; };
const struct iwl_cfg iwl8265_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 8265",
.fw_name_pre = IWL8000_FW_PRE,
IWL_DEVICE_8000,
.ht_params = &iwl8000_ht_params,
.nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
};
const struct iwl_cfg iwl4165_2ac_cfg = { const struct iwl_cfg iwl4165_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 4165", .name = "Intel(R) Dual Band Wireless AC 4165",
.fw_name_pre = IWL8000_FW_PRE, .fw_name_pre = IWL8000_FW_PRE,

View file

@ -0,0 +1,163 @@
/******************************************************************************
*
* This file is provided under a dual BSD/GPLv2 license. When using or
* redistributing this file, you may do so under either license.
*
* GPL LICENSE SUMMARY
*
* Copyright(c) 2015 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* BSD LICENSE
*
* Copyright(c) 2015 Intel Deutschland GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* * Neither the name Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
#include <linux/module.h>
#include <linux/stringify.h>
#include "iwl-config.h"
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
#define IWL9000_UCODE_API_MAX 16
/* Oldest version we won't warn about */
#define IWL9000_UCODE_API_OK 13
/* Lowest firmware API version supported */
#define IWL9000_UCODE_API_MIN 13
/* NVM versions */
#define IWL9000_NVM_VERSION 0x0a1d
#define IWL9000_TX_POWER_VERSION 0xffff /* meaningless */
/* Memory offsets and lengths */
#define IWL9000_DCCM_OFFSET 0x800000
#define IWL9000_DCCM_LEN 0x18000
#define IWL9000_DCCM2_OFFSET 0x880000
#define IWL9000_DCCM2_LEN 0x8000
#define IWL9000_SMEM_OFFSET 0x400000
#define IWL9000_SMEM_LEN 0x68000
#define IWL9000_FW_PRE "iwlwifi-9000-"
#define IWL9000_MODULE_FIRMWARE(api) \
IWL9000_FW_PRE "-" __stringify(api) ".ucode"
#define NVM_HW_SECTION_NUM_FAMILY_9000 10
static const struct iwl_base_params iwl9000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_9000,
.num_of_queues = IWLAGN_NUM_QUEUES,
.pll_cfg_val = 0,
.shadow_ram_support = true,
.led_compensation = 57,
.wd_timeout = IWL_LONG_WD_TIMEOUT,
.max_event_log_size = 512,
.shadow_reg_enable = true,
.pcie_l1_allowed = true,
};
static const struct iwl_ht_params iwl9000_ht_params = {
.stbc = true,
.ldpc = true,
.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
};
static const struct iwl_tt_params iwl9000_tt_params = {
.ct_kill_entry = 115,
.ct_kill_exit = 93,
.ct_kill_duration = 5,
.dynamic_smps_entry = 111,
.dynamic_smps_exit = 107,
.tx_protection_entry = 112,
.tx_protection_exit = 105,
.tx_backoff = {
{.temperature = 110, .backoff = 200},
{.temperature = 111, .backoff = 600},
{.temperature = 112, .backoff = 1200},
{.temperature = 113, .backoff = 2000},
{.temperature = 114, .backoff = 4000},
},
.support_ct_kill = true,
.support_dynamic_smps = true,
.support_tx_protection = true,
.support_tx_backoff = true,
};
#define IWL_DEVICE_9000 \
.ucode_api_max = IWL9000_UCODE_API_MAX, \
.ucode_api_ok = IWL9000_UCODE_API_OK, \
.ucode_api_min = IWL9000_UCODE_API_MIN, \
.device_family = IWL_DEVICE_FAMILY_8000, \
.max_inst_size = IWL60_RTC_INST_SIZE, \
.max_data_size = IWL60_RTC_DATA_SIZE, \
.base_params = &iwl9000_base_params, \
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_9000, \
.non_shared_ant = ANT_A, \
.dccm_offset = IWL9000_DCCM_OFFSET, \
.dccm_len = IWL9000_DCCM_LEN, \
.dccm2_offset = IWL9000_DCCM2_OFFSET, \
.dccm2_len = IWL9000_DCCM2_LEN, \
.smem_offset = IWL9000_SMEM_OFFSET, \
.smem_len = IWL9000_SMEM_LEN, \
.thermal_params = &iwl9000_tt_params, \
.apmg_not_supported = true
const struct iwl_cfg iwl9260_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 9260",
.fw_name_pre = IWL9000_FW_PRE,
IWL_DEVICE_9000,
.ht_params = &iwl9000_ht_params,
.nvm_ver = IWL9000_NVM_VERSION,
.nvm_calib_ver = IWL9000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
};
const struct iwl_cfg iwl5165_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 5165",
.fw_name_pre = IWL9000_FW_PRE,
IWL_DEVICE_9000,
.ht_params = &iwl9000_ht_params,
.nvm_ver = IWL9000_NVM_VERSION,
.nvm_calib_ver = IWL9000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
};
MODULE_FIRMWARE(IWL9000_MODULE_FIRMWARE(IWL9000_UCODE_API_OK));

View file

@ -25,7 +25,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE

View file

@ -254,6 +254,7 @@ struct iwl_tt_params {
#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ #define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */
#define OTP_LOW_IMAGE_SIZE_FAMILY_7000 (16 * 512 * sizeof(u16)) /* 16 KB */ #define OTP_LOW_IMAGE_SIZE_FAMILY_7000 (16 * 512 * sizeof(u16)) /* 16 KB */
#define OTP_LOW_IMAGE_SIZE_FAMILY_8000 (32 * 512 * sizeof(u16)) /* 32 KB */ #define OTP_LOW_IMAGE_SIZE_FAMILY_8000 (32 * 512 * sizeof(u16)) /* 32 KB */
#define OTP_LOW_IMAGE_SIZE_FAMILY_9000 OTP_LOW_IMAGE_SIZE_FAMILY_8000
struct iwl_eeprom_params { struct iwl_eeprom_params {
const u8 regulatory_bands[7]; const u8 regulatory_bands[7];
@ -295,7 +296,6 @@ struct iwl_pwr_tx_backoff {
* @high_temp: Is this NIC is designated to be in high temperature. * @high_temp: Is this NIC is designated to be in high temperature.
* @host_interrupt_operation_mode: device needs host interrupt operation * @host_interrupt_operation_mode: device needs host interrupt operation
* mode set * mode set
* @d0i3: device uses d0i3 instead of d3
* @nvm_hw_section_num: the ID of the HW NVM section * @nvm_hw_section_num: the ID of the HW NVM section
* @features: hw features, any combination of feature_whitelist * @features: hw features, any combination of feature_whitelist
* @pwr_tx_backoffs: translation table between power limits and backoffs * @pwr_tx_backoffs: translation table between power limits and backoffs
@ -342,7 +342,6 @@ struct iwl_cfg {
const bool internal_wimax_coex; const bool internal_wimax_coex;
const bool host_interrupt_operation_mode; const bool host_interrupt_operation_mode;
bool high_temp; bool high_temp;
bool d0i3;
u8 nvm_hw_section_num; u8 nvm_hw_section_num;
bool lp_xtal_workaround; bool lp_xtal_workaround;
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs; const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
@ -421,6 +420,7 @@ extern const struct iwl_cfg iwl3160_2ac_cfg;
extern const struct iwl_cfg iwl3160_2n_cfg; extern const struct iwl_cfg iwl3160_2n_cfg;
extern const struct iwl_cfg iwl3160_n_cfg; extern const struct iwl_cfg iwl3160_n_cfg;
extern const struct iwl_cfg iwl3165_2ac_cfg; extern const struct iwl_cfg iwl3165_2ac_cfg;
extern const struct iwl_cfg iwl3168_2ac_cfg;
extern const struct iwl_cfg iwl7265_2ac_cfg; extern const struct iwl_cfg iwl7265_2ac_cfg;
extern const struct iwl_cfg iwl7265_2n_cfg; extern const struct iwl_cfg iwl7265_2n_cfg;
extern const struct iwl_cfg iwl7265_n_cfg; extern const struct iwl_cfg iwl7265_n_cfg;
@ -429,9 +429,12 @@ extern const struct iwl_cfg iwl7265d_2n_cfg;
extern const struct iwl_cfg iwl7265d_n_cfg; extern const struct iwl_cfg iwl7265d_n_cfg;
extern const struct iwl_cfg iwl8260_2n_cfg; extern const struct iwl_cfg iwl8260_2n_cfg;
extern const struct iwl_cfg iwl8260_2ac_cfg; extern const struct iwl_cfg iwl8260_2ac_cfg;
extern const struct iwl_cfg iwl8265_2ac_cfg;
extern const struct iwl_cfg iwl4165_2ac_cfg; extern const struct iwl_cfg iwl4165_2ac_cfg;
extern const struct iwl_cfg iwl8260_2ac_sdio_cfg; extern const struct iwl_cfg iwl8260_2ac_sdio_cfg;
extern const struct iwl_cfg iwl4165_2ac_sdio_cfg; extern const struct iwl_cfg iwl4165_2ac_sdio_cfg;
extern const struct iwl_cfg iwl9260_2ac_cfg;
extern const struct iwl_cfg iwl5165_2ac_cfg;
#endif /* CONFIG_IWLMVM */ #endif /* CONFIG_IWLMVM */
#endif /* __IWL_CONFIG_H__ */ #endif /* __IWL_CONFIG_H__ */

View file

@ -163,7 +163,6 @@ do { \
#define IWL_DL_FW 0x00010000 #define IWL_DL_FW 0x00010000
#define IWL_DL_RF_KILL 0x00020000 #define IWL_DL_RF_KILL 0x00020000
#define IWL_DL_FW_ERRORS 0x00040000 #define IWL_DL_FW_ERRORS 0x00040000
#define IWL_DL_LED 0x00080000
/* 0x00F00000 - 0x00100000 */ /* 0x00F00000 - 0x00100000 */
#define IWL_DL_RATE 0x00100000 #define IWL_DL_RATE 0x00100000
#define IWL_DL_CALIB 0x00200000 #define IWL_DL_CALIB 0x00200000
@ -189,7 +188,6 @@ do { \
#define IWL_DEBUG_RX(p, f, a...) IWL_DEBUG(p, IWL_DL_RX, f, ## a) #define IWL_DEBUG_RX(p, f, a...) IWL_DEBUG(p, IWL_DL_RX, f, ## a)
#define IWL_DEBUG_TX(p, f, a...) IWL_DEBUG(p, IWL_DL_TX, f, ## a) #define IWL_DEBUG_TX(p, f, a...) IWL_DEBUG(p, IWL_DL_TX, f, ## a)
#define IWL_DEBUG_ISR(p, f, a...) IWL_DEBUG(p, IWL_DL_ISR, f, ## a) #define IWL_DEBUG_ISR(p, f, a...) IWL_DEBUG(p, IWL_DL_ISR, f, ## a)
#define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a)
#define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a) #define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a)
#define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) #define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a)
#define IWL_DEBUG_QUOTA(p, f, a...) IWL_DEBUG(p, IWL_DL_QUOTA, f, ## a) #define IWL_DEBUG_QUOTA(p, f, a...) IWL_DEBUG(p, IWL_DL_QUOTA, f, ## a)

View file

@ -19,7 +19,7 @@
* file called LICENSE. * file called LICENSE.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -19,7 +19,7 @@
* file called LICENSE. * file called LICENSE.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -19,7 +19,7 @@
* file called LICENSE. * file called LICENSE.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -19,7 +19,7 @@
* file called LICENSE. * file called LICENSE.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/

View file

@ -451,7 +451,9 @@ static int iwl_set_ucode_api_flags(struct iwl_drv *drv, const u8 *data,
int i; int i;
if (api_index >= DIV_ROUND_UP(NUM_IWL_UCODE_TLV_API, 32)) { if (api_index >= DIV_ROUND_UP(NUM_IWL_UCODE_TLV_API, 32)) {
IWL_ERR(drv, "api_index larger than supported by driver\n"); IWL_ERR(drv,
"api flags index %d larger than supported by driver\n",
api_index);
/* don't return an error so we can load FW that has more bits */ /* don't return an error so we can load FW that has more bits */
return 0; return 0;
} }
@ -473,7 +475,9 @@ static int iwl_set_ucode_capabilities(struct iwl_drv *drv, const u8 *data,
int i; int i;
if (api_index >= DIV_ROUND_UP(NUM_IWL_UCODE_TLV_CAPA, 32)) { if (api_index >= DIV_ROUND_UP(NUM_IWL_UCODE_TLV_CAPA, 32)) {
IWL_ERR(drv, "api_index larger than supported by driver\n"); IWL_ERR(drv,
"capa flags index %d larger than supported by driver\n",
api_index);
/* don't return an error so we can load FW that has more bits */ /* don't return an error so we can load FW that has more bits */
return 0; return 0;
} }
@ -1323,6 +1327,8 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
sizeof(struct iwl_fw_dbg_trigger_time_event); sizeof(struct iwl_fw_dbg_trigger_time_event);
trigger_tlv_sz[FW_DBG_TRIGGER_BA] = trigger_tlv_sz[FW_DBG_TRIGGER_BA] =
sizeof(struct iwl_fw_dbg_trigger_ba); sizeof(struct iwl_fw_dbg_trigger_ba);
trigger_tlv_sz[FW_DBG_TRIGGER_TDLS] =
sizeof(struct iwl_fw_dbg_trigger_tdls);
for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) { for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++) {
if (pieces->dbg_trigger_tlv[i]) { if (pieces->dbg_trigger_tlv[i]) {
@ -1539,6 +1545,7 @@ struct iwl_mod_params iwlwifi_mod_params = {
.bt_coex_active = true, .bt_coex_active = true,
.power_level = IWL_POWER_INDEX_1, .power_level = IWL_POWER_INDEX_1,
.d0i3_disable = true, .d0i3_disable = true,
.d0i3_entry_delay = 1000,
#ifndef CONFIG_IWLWIFI_UAPSD #ifndef CONFIG_IWLWIFI_UAPSD
.uapsd_disable = true, .uapsd_disable = true,
#endif /* CONFIG_IWLWIFI_UAPSD */ #endif /* CONFIG_IWLWIFI_UAPSD */
@ -1637,9 +1644,9 @@ MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
module_param_named(11n_disable, iwlwifi_mod_params.disable_11n, uint, S_IRUGO); module_param_named(11n_disable, iwlwifi_mod_params.disable_11n, uint, S_IRUGO);
MODULE_PARM_DESC(11n_disable, MODULE_PARM_DESC(11n_disable,
"disable 11n functionality, bitmap: 1: full, 2: disable agg TX, 4: disable agg RX, 8 enable agg TX"); "disable 11n functionality, bitmap: 1: full, 2: disable agg TX, 4: disable agg RX, 8 enable agg TX");
module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K, module_param_named(amsdu_size, iwlwifi_mod_params.amsdu_size,
int, S_IRUGO); int, S_IRUGO);
MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)"); MODULE_PARM_DESC(amsdu_size, "amsdu size 0:4K 1:8K 2:12K (default 0)");
module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, bool, S_IRUGO); module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, bool, S_IRUGO);
MODULE_PARM_DESC(fw_restart, "restart firmware in case of error (default true)"); MODULE_PARM_DESC(fw_restart, "restart firmware in case of error (default true)");
@ -1704,3 +1711,7 @@ MODULE_PARM_DESC(power_level,
module_param_named(fw_monitor, iwlwifi_mod_params.fw_monitor, bool, S_IRUGO); module_param_named(fw_monitor, iwlwifi_mod_params.fw_monitor, bool, S_IRUGO);
MODULE_PARM_DESC(fw_monitor, MODULE_PARM_DESC(fw_monitor,
"firmware monitor - to debug FW (default: false - needs lots of memory)"); "firmware monitor - to debug FW (default: false - needs lots of memory)");
module_param_named(d0i3_timeout, iwlwifi_mod_params.d0i3_entry_delay,
uint, S_IRUGO);
MODULE_PARM_DESC(d0i3_timeout, "Timeout to D0i3 entry when idle (ms)");

View file

@ -26,7 +26,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE
@ -766,7 +766,7 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
if (cfg->ht_params->ldpc) if (cfg->ht_params->ldpc)
ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING;
if (iwlwifi_mod_params.amsdu_size_8K) if (iwlwifi_mod_params.amsdu_size >= IWL_AMSDU_8K)
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
ht_info->ampdu_factor = cfg->max_ht_ampdu_exponent; ht_info->ampdu_factor = cfg->max_ht_ampdu_exponent;

View file

@ -26,7 +26,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE

View file

@ -25,7 +25,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE

View file

@ -25,7 +25,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE

View file

@ -25,7 +25,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE

View file

@ -26,7 +26,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE
@ -288,6 +288,9 @@ iwl_fw_error_next_data(struct iwl_fw_error_dump_data *data)
* @FW_DBG_TRIGGER_TIME_EVENT: trigger log collection upon time events related * @FW_DBG_TRIGGER_TIME_EVENT: trigger log collection upon time events related
* events. * events.
* @FW_DBG_TRIGGER_BA: trigger log collection upon BlockAck related events. * @FW_DBG_TRIGGER_BA: trigger log collection upon BlockAck related events.
* @FW_DBG_TX_LATENCY: trigger log collection when the tx latency goes above a
* threshold.
* @FW_DBG_TDLS: trigger log collection upon TDLS related events.
*/ */
enum iwl_fw_dbg_trigger { enum iwl_fw_dbg_trigger {
FW_DBG_TRIGGER_INVALID = 0, FW_DBG_TRIGGER_INVALID = 0,
@ -302,6 +305,8 @@ enum iwl_fw_dbg_trigger {
FW_DBG_TRIGGER_TXQ_TIMERS, FW_DBG_TRIGGER_TXQ_TIMERS,
FW_DBG_TRIGGER_TIME_EVENT, FW_DBG_TRIGGER_TIME_EVENT,
FW_DBG_TRIGGER_BA, FW_DBG_TRIGGER_BA,
FW_DBG_TRIGGER_TX_LATENCY,
FW_DBG_TRIGGER_TDLS,
/* must be last */ /* must be last */
FW_DBG_TRIGGER_MAX, FW_DBG_TRIGGER_MAX,

View file

@ -308,6 +308,7 @@ typedef unsigned int __bitwise__ iwl_ucode_tlv_capa_t;
* @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan * @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan
* @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement * @IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE: extended DTS measurement
* @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts * @IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS: supports short PM timeouts
* @IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT: supports bt-coex Multi-priority LUT
* *
* @NUM_IWL_UCODE_TLV_CAPA: number of bits used * @NUM_IWL_UCODE_TLV_CAPA: number of bits used
*/ */
@ -334,6 +335,7 @@ enum iwl_ucode_tlv_capa {
IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31,
IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64, IWL_UCODE_TLV_CAPA_EXTENDED_DTS_MEASURE = (__force iwl_ucode_tlv_capa_t)64,
IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65, IWL_UCODE_TLV_CAPA_SHORT_PM_TIMEOUTS = (__force iwl_ucode_tlv_capa_t)65,
IWL_UCODE_TLV_CAPA_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67,
NUM_IWL_UCODE_TLV_CAPA NUM_IWL_UCODE_TLV_CAPA
#ifdef __CHECKER__ #ifdef __CHECKER__
@ -722,6 +724,19 @@ struct iwl_fw_dbg_trigger_ba {
__le16 frame_timeout; __le16 frame_timeout;
} __packed; } __packed;
/**
* struct iwl_fw_dbg_trigger_tdls - configures trigger for TDLS events.
* @action_bitmap: the TDLS action to trigger the collection upon
* @peer_mode: trigger on specific peer or all
* @peer: the TDLS peer to trigger the collection on
*/
struct iwl_fw_dbg_trigger_tdls {
u8 action_bitmap;
u8 peer_mode;
u8 peer[ETH_ALEN];
u8 reserved[4];
} __packed;
/** /**
* struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration. * struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration.
* @id: conf id * @id: conf id

View file

@ -26,7 +26,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE
@ -305,18 +305,4 @@ iwl_fw_dbg_conf_usniffer(const struct iwl_fw *fw, u8 id)
return conf_tlv->usniffer; return conf_tlv->usniffer;
} }
#define iwl_fw_dbg_trigger_enabled(fw, id) ({ \
void *__dbg_trigger = (fw)->dbg_trigger_tlv[(id)]; \
unlikely(__dbg_trigger); \
})
static inline struct iwl_fw_dbg_trigger_tlv*
iwl_fw_dbg_get_trigger(const struct iwl_fw *fw, u8 id)
{
if (WARN_ON(id >= ARRAY_SIZE(fw->dbg_trigger_tlv)))
return NULL;
return fw->dbg_trigger_tlv[id];
}
#endif /* __iwl_fw_h__ */ #endif /* __iwl_fw_h__ */

View file

@ -1,6 +1,7 @@
/****************************************************************************** /******************************************************************************
* *
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2015 Intel Deutschland GmbH
* *
* Portions of this file are derived from the ipw3945 project. * Portions of this file are derived from the ipw3945 project.
* *
@ -117,18 +118,20 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
} }
IWL_EXPORT_SYMBOL(iwl_poll_direct_bit); IWL_EXPORT_SYMBOL(iwl_poll_direct_bit);
u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs) u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs)
{ {
u32 val = iwl_trans_read_prph(trans, ofs); u32 val = iwl_trans_read_prph(trans, ofs);
trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val); trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, val);
return val; return val;
} }
IWL_EXPORT_SYMBOL(iwl_read_prph_no_grab);
void __iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val) void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val)
{ {
trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val); trace_iwlwifi_dev_iowrite_prph32(trans->dev, ofs, val);
iwl_trans_write_prph(trans, ofs, val); iwl_trans_write_prph(trans, ofs, val);
} }
IWL_EXPORT_SYMBOL(iwl_write_prph_no_grab);
u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs) u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
{ {
@ -136,7 +139,7 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
u32 val = 0x5a5a5a5a; u32 val = 0x5a5a5a5a;
if (iwl_trans_grab_nic_access(trans, false, &flags)) { if (iwl_trans_grab_nic_access(trans, false, &flags)) {
val = __iwl_read_prph(trans, ofs); val = iwl_read_prph_no_grab(trans, ofs);
iwl_trans_release_nic_access(trans, &flags); iwl_trans_release_nic_access(trans, &flags);
} }
return val; return val;
@ -148,7 +151,7 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
unsigned long flags; unsigned long flags;
if (iwl_trans_grab_nic_access(trans, false, &flags)) { if (iwl_trans_grab_nic_access(trans, false, &flags)) {
__iwl_write_prph(trans, ofs, val); iwl_write_prph_no_grab(trans, ofs, val);
iwl_trans_release_nic_access(trans, &flags); iwl_trans_release_nic_access(trans, &flags);
} }
} }
@ -174,8 +177,9 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
unsigned long flags; unsigned long flags;
if (iwl_trans_grab_nic_access(trans, false, &flags)) { if (iwl_trans_grab_nic_access(trans, false, &flags)) {
__iwl_write_prph(trans, ofs, iwl_write_prph_no_grab(trans, ofs,
__iwl_read_prph(trans, ofs) | mask); iwl_read_prph_no_grab(trans, ofs) |
mask);
iwl_trans_release_nic_access(trans, &flags); iwl_trans_release_nic_access(trans, &flags);
} }
} }
@ -187,8 +191,9 @@ void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
unsigned long flags; unsigned long flags;
if (iwl_trans_grab_nic_access(trans, false, &flags)) { if (iwl_trans_grab_nic_access(trans, false, &flags)) {
__iwl_write_prph(trans, ofs, iwl_write_prph_no_grab(trans, ofs,
(__iwl_read_prph(trans, ofs) & mask) | bits); (iwl_read_prph_no_grab(trans, ofs) &
mask) | bits);
iwl_trans_release_nic_access(trans, &flags); iwl_trans_release_nic_access(trans, &flags);
} }
} }
@ -200,8 +205,8 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
u32 val; u32 val;
if (iwl_trans_grab_nic_access(trans, false, &flags)) { if (iwl_trans_grab_nic_access(trans, false, &flags)) {
val = __iwl_read_prph(trans, ofs); val = iwl_read_prph_no_grab(trans, ofs);
__iwl_write_prph(trans, ofs, (val & ~mask)); iwl_write_prph_no_grab(trans, ofs, (val & ~mask));
iwl_trans_release_nic_access(trans, &flags); iwl_trans_release_nic_access(trans, &flags);
} }
} }

View file

@ -21,7 +21,7 @@
* file called LICENSE. * file called LICENSE.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
*****************************************************************************/ *****************************************************************************/
@ -55,9 +55,9 @@ u32 iwl_read_direct32(struct iwl_trans *trans, u32 reg);
void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value); void iwl_write_direct32(struct iwl_trans *trans, u32 reg, u32 value);
u32 __iwl_read_prph(struct iwl_trans *trans, u32 ofs); u32 iwl_read_prph_no_grab(struct iwl_trans *trans, u32 ofs);
u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs); u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs);
void __iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val); void iwl_write_prph_no_grab(struct iwl_trans *trans, u32 ofs, u32 val);
void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val); void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val);
int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr, int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr,
u32 bits, u32 mask, int timeout); u32 bits, u32 mask, int timeout);

View file

@ -86,6 +86,12 @@ enum iwl_disable_11n {
IWL_ENABLE_HT_TXAGG = BIT(3), IWL_ENABLE_HT_TXAGG = BIT(3),
}; };
enum iwl_amsdu_size {
IWL_AMSDU_4K = 0,
IWL_AMSDU_8K = 1,
IWL_AMSDU_12K = 2,
};
/** /**
* struct iwl_mod_params * struct iwl_mod_params
* *
@ -94,7 +100,7 @@ enum iwl_disable_11n {
* @sw_crypto: using hardware encryption, default = 0 * @sw_crypto: using hardware encryption, default = 0
* @disable_11n: disable 11n capabilities, default = 0, * @disable_11n: disable 11n capabilities, default = 0,
* use IWL_[DIS,EN]ABLE_HT_* constants * use IWL_[DIS,EN]ABLE_HT_* constants
* @amsdu_size_8K: enable 8K amsdu size, default = 0 * @amsdu_size: enable 8K amsdu size, default = 4K. enum iwl_amsdu_size.
* @restart_fw: restart firmware, default = 1 * @restart_fw: restart firmware, default = 1
* @bt_coex_active: enable bt coex, default = true * @bt_coex_active: enable bt coex, default = true
* @led_mode: system default, default = 0 * @led_mode: system default, default = 0
@ -103,13 +109,15 @@ enum iwl_disable_11n {
* @debug_level: levels are IWL_DL_* * @debug_level: levels are IWL_DL_*
* @ant_coupling: antenna coupling in dB, default = 0 * @ant_coupling: antenna coupling in dB, default = 0
* @d0i3_disable: disable d0i3, default = 1, * @d0i3_disable: disable d0i3, default = 1,
* @d0i3_entry_delay: time to wait after no refs are taken before
* entering D0i3 (in msecs)
* @lar_disable: disable LAR (regulatory), default = 0 * @lar_disable: disable LAR (regulatory), default = 0
* @fw_monitor: allow to use firmware monitor * @fw_monitor: allow to use firmware monitor
*/ */
struct iwl_mod_params { struct iwl_mod_params {
int sw_crypto; int sw_crypto;
unsigned int disable_11n; unsigned int disable_11n;
int amsdu_size_8K; int amsdu_size;
bool restart_fw; bool restart_fw;
bool bt_coex_active; bool bt_coex_active;
int led_mode; int led_mode;
@ -122,6 +130,7 @@ struct iwl_mod_params {
char *nvm_file; char *nvm_file;
bool uapsd_disable; bool uapsd_disable;
bool d0i3_disable; bool d0i3_disable;
unsigned int d0i3_entry_delay;
bool lar_disable; bool lar_disable;
bool fw_monitor; bool fw_monitor;
}; };

View file

@ -26,7 +26,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE

View file

@ -26,7 +26,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE

View file

@ -26,7 +26,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE
@ -379,8 +379,19 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg,
else else
vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN; vht_cap->cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
if (iwlwifi_mod_params.amsdu_size_8K) switch (iwlwifi_mod_params.amsdu_size) {
case IWL_AMSDU_4K:
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
break;
case IWL_AMSDU_8K:
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991;
break;
case IWL_AMSDU_12K:
vht_cap->cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
break;
default:
break;
}
vht_cap->vht_mcs.rx_mcs_map = vht_cap->vht_mcs.rx_mcs_map =
cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | cpu_to_le16(IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 |
@ -580,15 +591,13 @@ static void iwl_set_hw_address_family_8000(struct device *dev,
IWL_ERR_DEV(dev, "mac address is not found\n"); IWL_ERR_DEV(dev, "mac address is not found\n");
} }
#define IWL_4165_DEVICE_ID 0x5501
struct iwl_nvm_data * struct iwl_nvm_data *
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
const __le16 *nvm_hw, const __le16 *nvm_sw, const __le16 *nvm_hw, const __le16 *nvm_sw,
const __le16 *nvm_calib, const __le16 *regulatory, const __le16 *nvm_calib, const __le16 *regulatory,
const __le16 *mac_override, const __le16 *phy_sku, const __le16 *mac_override, const __le16 *phy_sku,
u8 tx_chains, u8 rx_chains, bool lar_fw_supported, u8 tx_chains, u8 rx_chains, bool lar_fw_supported,
u32 mac_addr0, u32 mac_addr1, u32 hw_id) u32 mac_addr0, u32 mac_addr1)
{ {
struct iwl_nvm_data *data; struct iwl_nvm_data *data;
u32 sku; u32 sku;
@ -627,17 +636,6 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
(sku & NVM_SKU_CAP_11AC_ENABLE); (sku & NVM_SKU_CAP_11AC_ENABLE);
data->sku_cap_mimo_disabled = sku & NVM_SKU_CAP_MIMO_DISABLE; data->sku_cap_mimo_disabled = sku & NVM_SKU_CAP_MIMO_DISABLE;
/*
* OTP 0x52 bug work around
* define antenna 1x1 according to MIMO disabled
*/
if (hw_id == IWL_4165_DEVICE_ID && data->sku_cap_mimo_disabled) {
data->valid_tx_ant = ANT_B;
data->valid_rx_ant = ANT_B;
tx_chains = ANT_B;
rx_chains = ANT_B;
}
data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw); data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw);
if (cfg->device_family != IWL_DEVICE_FAMILY_8000) { if (cfg->device_family != IWL_DEVICE_FAMILY_8000) {

View file

@ -25,7 +25,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE
@ -79,7 +79,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
const __le16 *nvm_calib, const __le16 *regulatory, const __le16 *nvm_calib, const __le16 *regulatory,
const __le16 *mac_override, const __le16 *phy_sku, const __le16 *mac_override, const __le16 *phy_sku,
u8 tx_chains, u8 rx_chains, bool lar_fw_supported, u8 tx_chains, u8 rx_chains, bool lar_fw_supported,
u32 mac_addr0, u32 mac_addr1, u32 hw_id); u32 mac_addr0, u32 mac_addr1);
/** /**
* iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW * iwl_parse_mcc_info - parse MCC (mobile country code) info coming from FW

View file

@ -25,7 +25,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE

View file

@ -25,7 +25,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE

View file

@ -423,6 +423,22 @@ enum iwl_trans_status {
STATUS_TRANS_DEAD, STATUS_TRANS_DEAD,
}; };
static inline int
iwl_trans_get_rb_size_order(enum iwl_amsdu_size rb_size)
{
switch (rb_size) {
case IWL_AMSDU_4K:
return get_order(4 * 1024);
case IWL_AMSDU_8K:
return get_order(8 * 1024);
case IWL_AMSDU_12K:
return get_order(12 * 1024);
default:
WARN_ON(1);
return -1;
}
}
/** /**
* struct iwl_trans_config - transport configuration * struct iwl_trans_config - transport configuration
* *
@ -436,7 +452,7 @@ enum iwl_trans_status {
* list of such notifications to filter. Max length is * list of such notifications to filter. Max length is
* %MAX_NO_RECLAIM_CMDS. * %MAX_NO_RECLAIM_CMDS.
* @n_no_reclaim_cmds: # of commands in list * @n_no_reclaim_cmds: # of commands in list
* @rx_buf_size_8k: 8 kB RX buffer size needed for A-MSDUs, * @rx_buf_size: RX buffer size needed for A-MSDUs
* if unset 4k will be the RX buffer size * if unset 4k will be the RX buffer size
* @bc_table_dword: set to true if the BC table expects the byte count to be * @bc_table_dword: set to true if the BC table expects the byte count to be
* in DWORD (as opposed to bytes) * in DWORD (as opposed to bytes)
@ -456,7 +472,7 @@ struct iwl_trans_config {
const u8 *no_reclaim_cmds; const u8 *no_reclaim_cmds;
unsigned int n_no_reclaim_cmds; unsigned int n_no_reclaim_cmds;
bool rx_buf_size_8k; enum iwl_amsdu_size rx_buf_size;
bool bc_table_dword; bool bc_table_dword;
bool scd_set_active; bool scd_set_active;
bool wide_cmd_header; bool wide_cmd_header;
@ -526,8 +542,6 @@ struct iwl_trans_txq_scd_cfg {
* @wait_tx_queue_empty: wait until tx queues are empty. May sleep. * @wait_tx_queue_empty: wait until tx queues are empty. May sleep.
* @freeze_txq_timer: prevents the timer of the queue from firing until the * @freeze_txq_timer: prevents the timer of the queue from firing until the
* queue is set to awake. Must be atomic. * queue is set to awake. Must be atomic.
* @dbgfs_register: add the dbgfs files under this directory. Files will be
* automatically deleted.
* @write8: write a u8 to a register at offset ofs from the BAR * @write8: write a u8 to a register at offset ofs from the BAR
* @write32: write a u32 to a register at offset ofs from the BAR * @write32: write a u32 to a register at offset ofs from the BAR
* @read32: read a u32 register at offset ofs from the BAR * @read32: read a u32 register at offset ofs from the BAR
@ -583,7 +597,6 @@ struct iwl_trans_ops {
void (*txq_disable)(struct iwl_trans *trans, int queue, void (*txq_disable)(struct iwl_trans *trans, int queue,
bool configure_scd); bool configure_scd);
int (*dbgfs_register)(struct iwl_trans *trans, struct dentry* dir);
int (*wait_tx_queue_empty)(struct iwl_trans *trans, u32 txq_bm); int (*wait_tx_queue_empty)(struct iwl_trans *trans, u32 txq_bm);
void (*freeze_txq_timer)(struct iwl_trans *trans, unsigned long txqs, void (*freeze_txq_timer)(struct iwl_trans *trans, unsigned long txqs,
bool freeze); bool freeze);
@ -1006,12 +1019,6 @@ static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans,
return trans->ops->wait_tx_queue_empty(trans, txqs); return trans->ops->wait_tx_queue_empty(trans, txqs);
} }
static inline int iwl_trans_dbgfs_register(struct iwl_trans *trans,
struct dentry *dir)
{
return trans->ops->dbgfs_register(trans, dir);
}
static inline void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val) static inline void iwl_trans_write8(struct iwl_trans *trans, u32 ofs, u8 val)
{ {
trans->ops->write8(trans, ofs, val); trans->ops->write8(trans, ofs, val);

View file

@ -6,7 +6,7 @@ iwlmvm-y += power.o coex.o coex_legacy.o
iwlmvm-y += tt.o offloading.o tdls.o iwlmvm-y += tt.o offloading.o tdls.o
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o
iwlmvm-y += tof.o iwlmvm-y += tof.o fw-dbg.o
iwlmvm-$(CONFIG_PM_SLEEP) += d3.o iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../ ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../

View file

@ -25,7 +25,7 @@
* in the file called COPYING. * in the file called COPYING.
* *
* Contact Information: * Contact Information:
* Intel Linux Wireless <ilw@linux.intel.com> * Intel Linux Wireless <linuxwifi@intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
* *
* BSD LICENSE * BSD LICENSE

View file

@ -443,11 +443,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
if (iwl_mvm_bt_is_plcr_supported(mvm)) if (iwl_mvm_bt_is_plcr_supported(mvm))
bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_CORUN_ENABLED); bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_CORUN_ENABLED);
if (IWL_MVM_BT_COEX_MPLUT) { if (iwl_mvm_is_mplut_supported(mvm))
bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_MPLUT_ENABLED); bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_MPLUT_ENABLED);
bt_cmd.enabled_modules |=
cpu_to_le32(BT_COEX_MPLUT_BOOST_ENABLED);
}
bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_HIGH_BAND_RET); bt_cmd.enabled_modules |= cpu_to_le32(BT_COEX_HIGH_BAND_RET);
@ -904,6 +901,7 @@ u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *info, u8 ac) struct ieee80211_tx_info *info, u8 ac)
{ {
__le16 fc = hdr->frame_control; __le16 fc = hdr->frame_control;
bool mplut_enabled = iwl_mvm_is_mplut_supported(mvm);
if (info->band != IEEE80211_BAND_2GHZ) if (info->band != IEEE80211_BAND_2GHZ)
return 0; return 0;
@ -911,22 +909,27 @@ u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
if (unlikely(mvm->bt_tx_prio)) if (unlikely(mvm->bt_tx_prio))
return mvm->bt_tx_prio - 1; return mvm->bt_tx_prio - 1;
/* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */ if (likely(ieee80211_is_data(fc))) {
if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO || if (likely(ieee80211_is_data_qos(fc))) {
is_multicast_ether_addr(hdr->addr1) || switch (ac) {
ieee80211_is_ctl(fc) || ieee80211_is_mgmt(fc) || case IEEE80211_AC_BE:
ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc)) return mplut_enabled ? 1 : 0;
case IEEE80211_AC_VI:
return mplut_enabled ? 2 : 3;
case IEEE80211_AC_VO:
return 3;
default:
return 0;
}
} else if (is_multicast_ether_addr(hdr->addr1)) {
return 3;
} else
return 0;
} else if (ieee80211_is_mgmt(fc)) {
return ieee80211_is_disassoc(fc) ? 0 : 3;
} else if (ieee80211_is_ctl(fc)) {
/* ignore cfend and cfendack frames as we never send those */
return 3; return 3;
switch (ac) {
case IEEE80211_AC_BE:
return 1;
case IEEE80211_AC_VO:
return 3;
case IEEE80211_AC_VI:
return 2;
default:
break;
} }
return 0; return 0;

Some files were not shown because too many files have changed in this diff Show more