提交 e370abd9 编写于 作者: D David S. Miller

Merge tag 'wireless-drivers-next-for-davem-2015-12-07' of...

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: NDavid S. Miller <davem@davemloft.net>
无相关合并请求
......@@ -2,6 +2,7 @@ config ATH10K
tristate "Atheros 802.11ac wireless cards support"
depends on MAC80211 && HAS_DMA
select ATH_COMMON
select CRC32
---help---
This module adds support for wireless adapters based on
Atheros IEEE 802.11ac family of chipsets.
......
......@@ -59,6 +59,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.otp_exe_param = 0,
.channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
.fw = {
.dir = QCA988X_HW_2_0_FW_DIR,
.fw = QCA988X_HW_2_0_FW_FILE,
......@@ -95,6 +96,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.otp_exe_param = 0,
.channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
.fw = {
.dir = QCA6174_HW_2_1_FW_DIR,
.fw = QCA6174_HW_2_1_FW_FILE,
......@@ -113,6 +115,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.otp_exe_param = 0,
.channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
.fw = {
.dir = QCA6174_HW_3_0_FW_DIR,
.fw = QCA6174_HW_3_0_FW_FILE,
......@@ -131,6 +134,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.otp_exe_param = 0,
.channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
.fw = {
/* uses same binaries as hw3.0 */
.dir = QCA6174_HW_3_0_FW_DIR,
......@@ -151,6 +155,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.continuous_frag_desc = true,
.channel_counters_freq_hz = 150000,
.max_probe_resp_desc_thres = 24,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
.fw = {
.dir = QCA99X0_HW_2_0_FW_DIR,
.fw = QCA99X0_HW_2_0_FW_FILE,
......@@ -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_RAW_MODE_SUPPORT] = "raw-mode",
[ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA] = "adaptive-cca",
[ATH10K_FW_FEATURE_MFP_SUPPORT] = "mfp",
};
static unsigned int ath10k_core_get_fw_feature_str(char *buf,
......@@ -887,7 +893,7 @@ static int ath10k_core_fetch_board_data_api_n(struct ath10k *ar,
if (!ar->board_data || !ar->board_len) {
ath10k_err(ar,
"failed to fetch board data for %s from %s/%s\n",
ar->hw_params.fw.dir, boardname, filename);
boardname, ar->hw_params.fw.dir, filename);
ret = -ENODATA;
goto err;
}
......@@ -1790,9 +1796,11 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
goto err_power_down;
}
ath10k_debug_print_hwfw_info(ar);
ret = ath10k_core_get_board_id_from_otp(ar);
if (ret && ret != -EOPNOTSUPP) {
ath10k_err(ar, "failed to get board id from otp for qca99x0: %d\n",
ath10k_err(ar, "failed to get board id from otp: %d\n",
ret);
return ret;
}
......@@ -1803,6 +1811,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
goto err_free_firmware_files;
}
ath10k_debug_print_board_info(ar);
ret = ath10k_core_init_firmware_features(ar);
if (ret) {
ath10k_err(ar, "fatal problem with firmware features: %d\n",
......@@ -1825,7 +1835,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
goto err_unlock;
}
ath10k_print_driver_info(ar);
ath10k_debug_print_boot_info(ar);
ath10k_core_stop(ar);
mutex_unlock(&ar->conf_mutex);
......
......@@ -81,26 +81,20 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus)
return "unknown";
}
enum ath10k_skb_flags {
ATH10K_SKB_F_NO_HWCRYPT = BIT(0),
ATH10K_SKB_F_DTIM_ZERO = BIT(1),
ATH10K_SKB_F_DELIVER_CAB = BIT(2),
ATH10K_SKB_F_MGMT = BIT(3),
ATH10K_SKB_F_QOS = BIT(4),
};
struct ath10k_skb_cb {
dma_addr_t paddr;
u8 flags;
u8 eid;
u8 vdev_id;
enum ath10k_hw_txrx_mode txmode;
bool is_protected;
struct {
u8 tid;
u16 freq;
bool is_offchan;
bool nohwcrypt;
struct ath10k_htt_txbuf *txbuf;
u32 txbuf_paddr;
} __packed htt;
struct {
bool dtim_zero;
bool deliver_cab;
} bcn;
u16 msdu_id;
struct ieee80211_vif *vif;
} __packed;
struct ath10k_skb_rxcb {
......@@ -151,6 +145,7 @@ struct ath10k_wmi {
struct wmi_vdev_param_map *vdev_param;
struct wmi_pdev_param_map *pdev_param;
const struct wmi_ops *ops;
const struct wmi_peer_flags_map *peer_flags;
u32 num_mem_chunks;
u32 rx_decap_mode;
......@@ -512,6 +507,9 @@ enum ath10k_fw_features {
/* Firmware Supports Adaptive CCA*/
ATH10K_FW_FEATURE_SUPPORTS_ADAPTIVE_CCA = 11,
/* Firmware supports management frame protection */
ATH10K_FW_FEATURE_MFP_SUPPORT = 12,
/* keep last */
ATH10K_FW_FEATURE_COUNT,
};
......@@ -534,6 +532,9 @@ enum ath10k_dev_flags {
/* Disable HW crypto engine */
ATH10K_FLAG_HW_CRYPTO_DISABLED,
/* Bluetooth coexistance enabled */
ATH10K_FLAG_BTCOEX,
};
enum ath10k_cal_mode {
......@@ -662,6 +663,9 @@ struct ath10k {
*/
u32 max_probe_resp_desc_thres;
/* The padding bytes's location is different on various chips */
enum ath10k_hw_4addr_pad hw_4addr_pad;
struct ath10k_hw_params_fw {
const char *dir;
const char *fw;
......
......@@ -19,6 +19,8 @@
#include <linux/debugfs.h>
#include <linux/vmalloc.h>
#include <linux/utsname.h>
#include <linux/crc32.h>
#include <linux/firmware.h>
#include "core.h"
#include "debug.h"
......@@ -122,28 +124,51 @@ void ath10k_info(struct ath10k *ar, const char *fmt, ...)
}
EXPORT_SYMBOL(ath10k_info);
void ath10k_print_driver_info(struct ath10k *ar)
void ath10k_debug_print_hwfw_info(struct ath10k *ar)
{
char fw_features[128] = {};
char boardinfo[100];
ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
if (ar->id.bmi_ids_valid)
scnprintf(boardinfo, sizeof(boardinfo), "bmi %d:%d",
ar->id.bmi_chip_id, ar->id.bmi_board_id);
else
scnprintf(boardinfo, sizeof(boardinfo), "sub %04x:%04x",
ar->id.subsystem_vendor, ar->id.subsystem_device);
ath10k_info(ar, "%s (0x%08x, 0x%08x %s) fw %s fwapi %d bdapi %d htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d features %s\n",
ath10k_info(ar, "%s target 0x%08x chip_id 0x%08x sub %04x:%04x",
ar->hw_params.name,
ar->target_version,
ar->chip_id,
boardinfo,
ar->id.subsystem_vendor, ar->id.subsystem_device);
ath10k_info(ar, "kconfig debug %d debugfs %d tracing %d dfs %d testmode %d\n",
config_enabled(CONFIG_ATH10K_DEBUG),
config_enabled(CONFIG_ATH10K_DEBUGFS),
config_enabled(CONFIG_ATH10K_TRACING),
config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
config_enabled(CONFIG_NL80211_TESTMODE));
ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n",
ar->hw->wiphy->fw_version,
ar->fw_api,
fw_features,
crc32_le(0, ar->firmware->data, ar->firmware->size));
}
void ath10k_debug_print_board_info(struct ath10k *ar)
{
char boardinfo[100];
if (ar->id.bmi_ids_valid)
scnprintf(boardinfo, sizeof(boardinfo), "%d:%d",
ar->id.bmi_chip_id, ar->id.bmi_board_id);
else
scnprintf(boardinfo, sizeof(boardinfo), "N/A");
ath10k_info(ar, "board_file api %d bmi_id %s crc32 %08x",
ar->bd_api,
boardinfo,
crc32_le(0, ar->board->data, ar->board->size));
}
void ath10k_debug_print_boot_info(struct ath10k *ar)
{
ath10k_info(ar, "htt-ver %d.%d wmi-op %d htt-op %d cal %s max-sta %d raw %d hwcrypto %d\n",
ar->htt.target_version_major,
ar->htt.target_version_minor,
ar->wmi.op_version,
......@@ -151,14 +176,14 @@ void ath10k_print_driver_info(struct ath10k *ar)
ath10k_cal_mode_str(ar->cal_mode),
ar->max_num_stations,
test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags),
!test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags),
fw_features);
ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
config_enabled(CONFIG_ATH10K_DEBUG),
config_enabled(CONFIG_ATH10K_DEBUGFS),
config_enabled(CONFIG_ATH10K_TRACING),
config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
config_enabled(CONFIG_NL80211_TESTMODE));
!test_bit(ATH10K_FLAG_HW_CRYPTO_DISABLED, &ar->dev_flags));
}
void ath10k_print_driver_info(struct ath10k *ar)
{
ath10k_debug_print_hwfw_info(ar);
ath10k_debug_print_board_info(ar);
ath10k_debug_print_boot_info(ar);
}
EXPORT_SYMBOL(ath10k_print_driver_info);
......@@ -2074,6 +2099,121 @@ static const struct file_operations fops_quiet_period = {
.open = simple_open
};
static ssize_t ath10k_write_btcoex(struct file *file,
const char __user *ubuf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
char buf[32];
size_t buf_size;
bool val;
buf_size = min(count, (sizeof(buf) - 1));
if (copy_from_user(buf, ubuf, buf_size))
return -EFAULT;
buf[buf_size] = '\0';
if (strtobool(buf, &val) != 0)
return -EINVAL;
mutex_lock(&ar->conf_mutex);
if (!(test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) ^ val))
goto exit;
if (val)
set_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
else
clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
if (ar->state != ATH10K_STATE_ON)
goto exit;
ath10k_info(ar, "restarting firmware due to btcoex change");
queue_work(ar->workqueue, &ar->restart_work);
exit:
mutex_unlock(&ar->conf_mutex);
return count;
}
static ssize_t ath10k_read_btcoex(struct file *file, char __user *ubuf,
size_t count, loff_t *ppos)
{
char buf[32];
struct ath10k *ar = file->private_data;
int len = 0;
mutex_lock(&ar->conf_mutex);
len = scnprintf(buf, sizeof(buf) - len, "%d\n",
test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags));
mutex_unlock(&ar->conf_mutex);
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
}
static const struct file_operations fops_btcoex = {
.read = ath10k_read_btcoex,
.write = ath10k_write_btcoex,
.open = simple_open
};
static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
unsigned int len = 0, buf_len = 4096;
ssize_t ret_cnt;
char *buf;
buf = kzalloc(buf_len, GFP_KERNEL);
if (!buf)
return -ENOMEM;
mutex_lock(&ar->conf_mutex);
if (len > buf_len)
len = buf_len;
len += scnprintf(buf + len, buf_len - len,
"firmware-N.bin\t\t%08x\n",
crc32_le(0, ar->firmware->data, ar->firmware->size));
len += scnprintf(buf + len, buf_len - len,
"athwlan\t\t\t%08x\n",
crc32_le(0, ar->firmware_data, ar->firmware_len));
len += scnprintf(buf + len, buf_len - len,
"otp\t\t\t%08x\n",
crc32_le(0, ar->otp_data, ar->otp_len));
len += scnprintf(buf + len, buf_len - len,
"codeswap\t\t%08x\n",
crc32_le(0, ar->swap.firmware_codeswap_data,
ar->swap.firmware_codeswap_len));
len += scnprintf(buf + len, buf_len - len,
"board-N.bin\t\t%08x\n",
crc32_le(0, ar->board->data, ar->board->size));
len += scnprintf(buf + len, buf_len - len,
"board\t\t\t%08x\n",
crc32_le(0, ar->board_data, ar->board_len));
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
mutex_unlock(&ar->conf_mutex);
kfree(buf);
return ret_cnt;
}
static const struct file_operations fops_fw_checksums = {
.read = ath10k_debug_fw_checksums_read,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
int ath10k_debug_create(struct ath10k *ar)
{
ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
......@@ -2123,8 +2263,8 @@ int ath10k_debug_register(struct ath10k *ar)
debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
&fops_wmi_services);
debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_simulate_fw_crash);
debugfs_create_file("simulate_fw_crash", S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar, &fops_simulate_fw_crash);
debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_fw_crash_dump);
......@@ -2141,15 +2281,15 @@ int ath10k_debug_register(struct ath10k *ar)
debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_chip_id);
debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_htt_stats_mask);
debugfs_create_file("htt_stats_mask", S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar, &fops_htt_stats_mask);
debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar,
&fops_htt_max_amsdu_ampdu);
debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_fw_dbglog);
debugfs_create_file("fw_dbglog", S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar, &fops_fw_dbglog);
debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_cal_data);
......@@ -2183,6 +2323,13 @@ int ath10k_debug_register(struct ath10k *ar)
debugfs_create_file("tpc_stats", S_IRUSR,
ar->debug.debugfs_phy, ar, &fops_tpc_stats);
if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
debugfs_create_file("btcoex", S_IRUGO | S_IWUSR,
ar->debug.debugfs_phy, ar, &fops_btcoex);
debugfs_create_file("fw_checksums", S_IRUSR,
ar->debug.debugfs_phy, ar, &fops_fw_checksums);
return 0;
}
......
......@@ -63,6 +63,10 @@ extern unsigned int ath10k_debug_mask;
__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
__printf(2, 3) void ath10k_err(struct ath10k *ar, const char *fmt, ...);
__printf(2, 3) void ath10k_warn(struct ath10k *ar, const char *fmt, ...);
void ath10k_debug_print_hwfw_info(struct ath10k *ar);
void ath10k_debug_print_board_info(struct ath10k *ar);
void ath10k_debug_print_boot_info(struct ath10k *ar);
void ath10k_print_driver_info(struct ath10k *ar);
#ifdef CONFIG_ATH10K_DEBUGFS
......
......@@ -166,8 +166,13 @@ struct htt_data_tx_desc {
__le16 len;
__le16 id;
__le32 frags_paddr;
__le16 peerid;
__le16 freq;
union {
__le32 peerid;
struct {
__le16 peerid;
__le16 freq;
} __packed offchan_tx;
} __packed;
u8 prefetch[0]; /* start of frame, for FW classification engine */
} __packed;
......@@ -1597,6 +1602,10 @@ void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc);
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb);
void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id);
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *);
int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *);
int ath10k_htt_tx(struct ath10k_htt *htt,
enum ath10k_hw_txrx_mode txmode,
struct sk_buff *msdu);
void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
struct sk_buff *skb);
#endif
......@@ -536,7 +536,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
size = htt->rx_ring.size * sizeof(htt->rx_ring.paddrs_ring);
vaddr = dma_alloc_coherent(htt->ar->dev, size, &paddr, GFP_DMA);
vaddr = dma_alloc_coherent(htt->ar->dev, size, &paddr, GFP_KERNEL);
if (!vaddr)
goto err_dma_ring;
......@@ -545,7 +545,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
vaddr = dma_alloc_coherent(htt->ar->dev,
sizeof(*htt->rx_ring.alloc_idx.vaddr),
&paddr, GFP_DMA);
&paddr, GFP_KERNEL);
if (!vaddr)
goto err_dma_idx;
......@@ -674,7 +674,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
rate &= ~RX_PPDU_START_RATE_FLAG;
sband = &ar->mac.sbands[status->band];
status->rate_idx = ath10k_mac_hw_rate_to_idx(sband, rate);
status->rate_idx = ath10k_mac_hw_rate_to_idx(sband, rate, cck);
break;
case HTT_RX_HT:
case HTT_RX_HT_WITH_TXBF:
......@@ -1114,7 +1114,20 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
*/
/* pull decapped header and copy SA & DA */
hdr = (struct ieee80211_hdr *)msdu->data;
if ((ar->hw_params.hw_4addr_pad == ATH10K_HW_4ADDR_PAD_BEFORE) &&
ieee80211_has_a4(((struct ieee80211_hdr *)first_hdr)->frame_control)) {
/* The QCA99X0 4 address mode pad 2 bytes at the
* beginning of MSDU
*/
hdr = (struct ieee80211_hdr *)(msdu->data + 2);
/* The skb length need be extended 2 as the 2 bytes at the tail
* be excluded due to the padding
*/
skb_put(msdu, 2);
} else {
hdr = (struct ieee80211_hdr *)(msdu->data);
}
hdr_len = ath10k_htt_rx_nwifi_hdrlen(ar, hdr);
ether_addr_copy(da, ieee80211_get_DA(hdr));
ether_addr_copy(sa, ieee80211_get_SA(hdr));
......@@ -2127,6 +2140,18 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
}
EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler);
void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
struct sk_buff *skb)
{
struct ath10k_pktlog_10_4_hdr *hdr =
(struct ath10k_pktlog_10_4_hdr *)skb->data;
trace_ath10k_htt_pktlog(ar, hdr->payload,
sizeof(*hdr) + __le16_to_cpu(hdr->size));
dev_kfree_skb_any(skb);
}
EXPORT_SYMBOL(ath10k_htt_rx_pktlog_completion_handler);
static void ath10k_htt_txrx_compl_task(unsigned long ptr)
{
struct ath10k_htt *htt = (struct ath10k_htt *)ptr;
......
......@@ -111,7 +111,7 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
size = htt->max_num_pending_tx * sizeof(struct ath10k_htt_txbuf);
htt->txbuf.vaddr = dma_alloc_coherent(ar->dev, size,
&htt->txbuf.paddr,
GFP_DMA);
GFP_KERNEL);
if (!htt->txbuf.vaddr) {
ath10k_err(ar, "failed to alloc tx buffer\n");
ret = -ENOMEM;
......@@ -124,7 +124,7 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
size = htt->max_num_pending_tx * sizeof(struct htt_msdu_ext_desc);
htt->frag_desc.vaddr = dma_alloc_coherent(ar->dev, size,
&htt->frag_desc.paddr,
GFP_DMA);
GFP_KERNEL);
if (!htt->frag_desc.vaddr) {
ath10k_warn(ar, "failed to alloc fragment desc memory\n");
ret = -ENOMEM;
......@@ -439,6 +439,35 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
return 0;
}
static u8 ath10k_htt_tx_get_vdev_id(struct ath10k *ar, struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
struct ath10k_vif *arvif = (void *)cb->vif->drv_priv;
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
return ar->scan.vdev_id;
else if (cb->vif)
return arvif->vdev_id;
else if (ar->monitor_started)
return ar->monitor_vdev_id;
else
return 0;
}
static u8 ath10k_htt_tx_get_tid(struct sk_buff *skb, bool is_eth)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
if (!is_eth && ieee80211_is_mgmt(hdr->frame_control))
return HTT_DATA_TX_EXT_TID_MGMT;
else if (cb->flags & ATH10K_SKB_F_QOS)
return skb->priority % IEEE80211_QOS_CTL_TID_MASK;
else
return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
}
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
{
struct ath10k *ar = htt->ar;
......@@ -446,7 +475,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
struct sk_buff *txdesc = NULL;
struct htt_cmd *cmd;
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
u8 vdev_id = skb_cb->vdev_id;
u8 vdev_id = ath10k_htt_tx_get_vdev_id(ar, msdu);
int len = 0;
int msdu_id = -1;
int res;
......@@ -477,6 +506,13 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
msdu_id = res;
if ((ieee80211_is_action(hdr->frame_control) ||
ieee80211_is_deauth(hdr->frame_control) ||
ieee80211_is_disassoc(hdr->frame_control)) &&
ieee80211_has_protected(hdr->frame_control)) {
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
}
txdesc = ath10k_htc_alloc_skb(ar, len);
if (!txdesc) {
res = -ENOMEM;
......@@ -503,8 +539,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
memcpy(cmd->mgmt_tx.hdr, msdu->data,
min_t(int, msdu->len, HTT_MGMT_FRM_HDR_DOWNLOAD_LEN));
skb_cb->htt.txbuf = NULL;
res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc);
if (res)
goto err_unmap_msdu;
......@@ -525,21 +559,27 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
return res;
}
int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
struct sk_buff *msdu)
{
struct ath10k *ar = htt->ar;
struct device *dev = ar->dev;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu);
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
struct ath10k_hif_sg_item sg_items[2];
struct ath10k_htt_txbuf *txbuf;
struct htt_data_tx_desc_frag *frags;
u8 vdev_id = skb_cb->vdev_id;
u8 tid = skb_cb->htt.tid;
bool is_eth = (txmode == ATH10K_HW_TXRX_ETHERNET);
u8 vdev_id = ath10k_htt_tx_get_vdev_id(ar, msdu);
u8 tid = ath10k_htt_tx_get_tid(msdu, is_eth);
int prefetch_len;
int res;
u8 flags0 = 0;
u16 msdu_id, flags1 = 0;
u16 freq = 0;
u32 frags_paddr = 0;
u32 txbuf_paddr;
struct htt_msdu_ext_desc *ext_desc = NULL;
bool limit_mgmt_desc = false;
bool is_probe_resp = false;
......@@ -567,17 +607,17 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
prefetch_len = min(htt->prefetch_len, msdu->len);
prefetch_len = roundup(prefetch_len, 4);
skb_cb->htt.txbuf = &htt->txbuf.vaddr[msdu_id];
skb_cb->htt.txbuf_paddr = htt->txbuf.paddr +
(sizeof(struct ath10k_htt_txbuf) * msdu_id);
txbuf = &htt->txbuf.vaddr[msdu_id];
txbuf_paddr = htt->txbuf.paddr +
(sizeof(struct ath10k_htt_txbuf) * msdu_id);
if ((ieee80211_is_action(hdr->frame_control) ||
ieee80211_is_deauth(hdr->frame_control) ||
ieee80211_is_disassoc(hdr->frame_control)) &&
ieee80211_has_protected(hdr->frame_control)) {
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
} else if (!skb_cb->htt.nohwcrypt &&
skb_cb->txmode == ATH10K_HW_TXRX_RAW &&
} else if (!(skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT) &&
txmode == ATH10K_HW_TXRX_RAW &&
ieee80211_has_protected(hdr->frame_control)) {
skb_put(msdu, IEEE80211_CCMP_MIC_LEN);
}
......@@ -590,7 +630,10 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
goto err_free_msdu_id;
}
switch (skb_cb->txmode) {
if (unlikely(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN))
freq = ar->scan.roc_freq;
switch (txmode) {
case ATH10K_HW_TXRX_RAW:
case ATH10K_HW_TXRX_NATIVE_WIFI:
flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
......@@ -610,16 +653,16 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
frags_paddr = htt->frag_desc.paddr +
(sizeof(struct htt_msdu_ext_desc) * msdu_id);
} else {
frags = skb_cb->htt.txbuf->frags;
frags = txbuf->frags;
frags[0].dword_addr.paddr =
__cpu_to_le32(skb_cb->paddr);
frags[0].dword_addr.len = __cpu_to_le32(msdu->len);
frags[1].dword_addr.paddr = 0;
frags[1].dword_addr.len = 0;
frags_paddr = skb_cb->htt.txbuf_paddr;
frags_paddr = txbuf_paddr;
}
flags0 |= SM(skb_cb->txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
flags0 |= SM(txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
break;
case ATH10K_HW_TXRX_MGMT:
flags0 |= SM(ATH10K_HW_TXRX_MGMT,
......@@ -646,17 +689,13 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
* avoid extra memory allocations, compress data structures and thus
* improve performance. */
skb_cb->htt.txbuf->htc_hdr.eid = htt->eid;
skb_cb->htt.txbuf->htc_hdr.len = __cpu_to_le16(
sizeof(skb_cb->htt.txbuf->cmd_hdr) +
sizeof(skb_cb->htt.txbuf->cmd_tx) +
prefetch_len);
skb_cb->htt.txbuf->htc_hdr.flags = 0;
if (skb_cb->htt.nohwcrypt)
flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
txbuf->htc_hdr.eid = htt->eid;
txbuf->htc_hdr.len = __cpu_to_le16(sizeof(txbuf->cmd_hdr) +
sizeof(txbuf->cmd_tx) +
prefetch_len);
txbuf->htc_hdr.flags = 0;
if (!skb_cb->is_protected)
if (skb_cb->flags & ATH10K_SKB_F_NO_HWCRYPT)
flags0 |= HTT_DATA_TX_DESC_FLAGS0_NO_ENCRYPT;
flags1 |= SM((u16)vdev_id, HTT_DATA_TX_DESC_FLAGS1_VDEV_ID);
......@@ -675,20 +714,27 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
*/
flags1 |= HTT_DATA_TX_DESC_FLAGS1_POSTPONED;
skb_cb->htt.txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
skb_cb->htt.txbuf->cmd_tx.flags0 = flags0;
skb_cb->htt.txbuf->cmd_tx.flags1 = __cpu_to_le16(flags1);
skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len);
skb_cb->htt.txbuf->cmd_tx.id = __cpu_to_le16(msdu_id);
skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr);
skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le16(HTT_INVALID_PEERID);
skb_cb->htt.txbuf->cmd_tx.freq = __cpu_to_le16(skb_cb->htt.freq);
txbuf->cmd_hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FRM;
txbuf->cmd_tx.flags0 = flags0;
txbuf->cmd_tx.flags1 = __cpu_to_le16(flags1);
txbuf->cmd_tx.len = __cpu_to_le16(msdu->len);
txbuf->cmd_tx.id = __cpu_to_le16(msdu_id);
txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr);
if (ath10k_mac_tx_frm_has_freq(ar)) {
txbuf->cmd_tx.offchan_tx.peerid =
__cpu_to_le16(HTT_INVALID_PEERID);
txbuf->cmd_tx.offchan_tx.freq =
__cpu_to_le16(freq);
} else {
txbuf->cmd_tx.peerid =
__cpu_to_le32(HTT_INVALID_PEERID);
}
trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid);
ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu freq %hu\n",
flags0, flags1, msdu->len, msdu_id, frags_paddr,
(u32)skb_cb->paddr, vdev_id, tid, skb_cb->htt.freq);
(u32)skb_cb->paddr, vdev_id, tid, freq);
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ",
msdu->data, msdu->len);
trace_ath10k_tx_hdr(ar, msdu->data, msdu->len);
......@@ -696,12 +742,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
sg_items[0].transfer_id = 0;
sg_items[0].transfer_context = NULL;
sg_items[0].vaddr = &skb_cb->htt.txbuf->htc_hdr;
sg_items[0].paddr = skb_cb->htt.txbuf_paddr +
sizeof(skb_cb->htt.txbuf->frags);
sg_items[0].len = sizeof(skb_cb->htt.txbuf->htc_hdr) +
sizeof(skb_cb->htt.txbuf->cmd_hdr) +
sizeof(skb_cb->htt.txbuf->cmd_tx);
sg_items[0].vaddr = &txbuf->htc_hdr;
sg_items[0].paddr = txbuf_paddr +
sizeof(txbuf->frags);
sg_items[0].len = sizeof(txbuf->htc_hdr) +
sizeof(txbuf->cmd_hdr) +
sizeof(txbuf->cmd_tx);
sg_items[1].transfer_id = 0;
sg_items[1].transfer_context = NULL;
......
......@@ -286,6 +286,16 @@ struct ath10k_pktlog_hdr {
u8 payload[0];
} __packed;
struct ath10k_pktlog_10_4_hdr {
__le16 flags;
__le16 missed_cnt;
__le16 log_type;
__le16 size;
__le32 timestamp;
__le32 type_specific_data;
u8 payload[0];
} __packed;
enum ath10k_hw_rate_ofdm {
ATH10K_HW_RATE_OFDM_48M = 0,
ATH10K_HW_RATE_OFDM_24M,
......@@ -307,6 +317,11 @@ enum ath10k_hw_rate_cck {
ATH10K_HW_RATE_CCK_SP_2M,
};
enum ath10k_hw_4addr_pad {
ATH10K_HW_4ADDR_PAD_AFTER,
ATH10K_HW_4ADDR_PAD_BEFORE,
};
/* Target specific defines for MAIN firmware */
#define TARGET_NUM_VDEVS 8
#define TARGET_NUM_PEER_AST 2
......
......@@ -90,7 +90,7 @@ static u8 ath10k_mac_bitrate_to_rate(int bitrate)
}
u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
u8 hw_rate)
u8 hw_rate, bool cck)
{
const struct ieee80211_rate *rate;
int i;
......@@ -98,6 +98,9 @@ u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
for (i = 0; i < sband->n_bitrates; i++) {
rate = &sband->bitrates[i];
if (ath10k_mac_bitrate_is_cck(rate->bitrate) != cck)
continue;
if (rate->hw_value == hw_rate)
return i;
else if (rate->flags & IEEE80211_RATE_SHORT_PREAMBLE &&
......@@ -1960,7 +1963,7 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
ether_addr_copy(arg->addr, sta->addr);
arg->vdev_id = arvif->vdev_id;
arg->peer_aid = aid;
arg->peer_flags |= WMI_PEER_AUTH;
arg->peer_flags |= arvif->ar->wmi.peer_flags->auth;
arg->peer_listen_intval = ath10k_peer_assoc_h_listen_intval(ar, vif);
arg->peer_num_spatial_streams = 1;
arg->peer_caps = vif->bss_conf.assoc_capability;
......@@ -1968,6 +1971,7 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct wmi_peer_assoc_complete_arg *arg)
{
struct ieee80211_bss_conf *info = &vif->bss_conf;
......@@ -2002,12 +2006,17 @@ static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
/* FIXME: base on RSN IE/WPA IE is a correct idea? */
if (rsnie || wpaie) {
ath10k_dbg(ar, ATH10K_DBG_WMI, "%s: rsn ie found\n", __func__);
arg->peer_flags |= WMI_PEER_NEED_PTK_4_WAY;
arg->peer_flags |= ar->wmi.peer_flags->need_ptk_4_way;
}
if (wpaie) {
ath10k_dbg(ar, ATH10K_DBG_WMI, "%s: wpa ie found\n", __func__);
arg->peer_flags |= WMI_PEER_NEED_GTK_2_WAY;
arg->peer_flags |= ar->wmi.peer_flags->need_gtk_2_way;
}
if (sta->mfp &&
test_bit(ATH10K_FW_FEATURE_MFP_SUPPORT, ar->fw_features)) {
arg->peer_flags |= ar->wmi.peer_flags->pmf;
}
}
......@@ -2104,7 +2113,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
ath10k_peer_assoc_h_vht_masked(vht_mcs_mask))
return;
arg->peer_flags |= WMI_PEER_HT;
arg->peer_flags |= ar->wmi.peer_flags->ht;
arg->peer_max_mpdu = (1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
ht_cap->ampdu_factor)) - 1;
......@@ -2115,10 +2124,10 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
arg->peer_rate_caps |= WMI_RC_HT_FLAG;
if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)
arg->peer_flags |= WMI_PEER_LDPC;
arg->peer_flags |= ar->wmi.peer_flags->ldbc;
if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) {
arg->peer_flags |= WMI_PEER_40MHZ;
arg->peer_flags |= ar->wmi.peer_flags->bw40;
arg->peer_rate_caps |= WMI_RC_CW40_FLAG;
}
......@@ -2132,7 +2141,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
if (ht_cap->cap & IEEE80211_HT_CAP_TX_STBC) {
arg->peer_rate_caps |= WMI_RC_TX_STBC_FLAG;
arg->peer_flags |= WMI_PEER_STBC;
arg->peer_flags |= ar->wmi.peer_flags->stbc;
}
if (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC) {
......@@ -2140,7 +2149,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
stbc = stbc >> IEEE80211_HT_CAP_RX_STBC_SHIFT;
stbc = stbc << WMI_RC_RX_STBC_FLAG_S;
arg->peer_rate_caps |= stbc;
arg->peer_flags |= WMI_PEER_STBC;
arg->peer_flags |= ar->wmi.peer_flags->stbc;
}
if (ht_cap->mcs.rx_mask[1] && ht_cap->mcs.rx_mask[2])
......@@ -2321,10 +2330,10 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
if (ath10k_peer_assoc_h_vht_masked(vht_mcs_mask))
return;
arg->peer_flags |= WMI_PEER_VHT;
arg->peer_flags |= ar->wmi.peer_flags->vht;
if (def.chan->band == IEEE80211_BAND_2GHZ)
arg->peer_flags |= WMI_PEER_VHT_2G;
arg->peer_flags |= ar->wmi.peer_flags->vht_2g;
arg->peer_vht_caps = vht_cap->cap;
......@@ -2341,7 +2350,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
ampdu_factor)) - 1);
if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
arg->peer_flags |= WMI_PEER_80MHZ;
arg->peer_flags |= ar->wmi.peer_flags->bw80;
arg->peer_vht_rates.rx_max_rate =
__le16_to_cpu(vht_cap->vht_mcs.rx_highest);
......@@ -2366,27 +2375,28 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
switch (arvif->vdev_type) {
case WMI_VDEV_TYPE_AP:
if (sta->wme)
arg->peer_flags |= WMI_PEER_QOS;
arg->peer_flags |= arvif->ar->wmi.peer_flags->qos;
if (sta->wme && sta->uapsd_queues) {
arg->peer_flags |= WMI_PEER_APSD;
arg->peer_flags |= arvif->ar->wmi.peer_flags->apsd;
arg->peer_rate_caps |= WMI_RC_UAPSD_FLAG;
}
break;
case WMI_VDEV_TYPE_STA:
if (vif->bss_conf.qos)
arg->peer_flags |= WMI_PEER_QOS;
arg->peer_flags |= arvif->ar->wmi.peer_flags->qos;
break;
case WMI_VDEV_TYPE_IBSS:
if (sta->wme)
arg->peer_flags |= WMI_PEER_QOS;
arg->peer_flags |= arvif->ar->wmi.peer_flags->qos;
break;
default:
break;
}
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac peer %pM qos %d\n",
sta->addr, !!(arg->peer_flags & WMI_PEER_QOS));
sta->addr, !!(arg->peer_flags &
arvif->ar->wmi.peer_flags->qos));
}
static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
......@@ -2479,7 +2489,7 @@ static int ath10k_peer_assoc_prepare(struct ath10k *ar,
memset(arg, 0, sizeof(*arg));
ath10k_peer_assoc_h_basic(ar, vif, sta, arg);
ath10k_peer_assoc_h_crypto(ar, vif, arg);
ath10k_peer_assoc_h_crypto(ar, vif, sta, arg);
ath10k_peer_assoc_h_rates(ar, vif, sta, arg);
ath10k_peer_assoc_h_ht(ar, vif, sta, arg);
ath10k_peer_assoc_h_vht(ar, vif, sta, arg);
......@@ -3112,35 +3122,11 @@ void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id,
spin_unlock_bh(&ar->htt.tx_lock);
}
static u8 ath10k_tx_h_get_tid(struct ieee80211_hdr *hdr)
{
if (ieee80211_is_mgmt(hdr->frame_control))
return HTT_DATA_TX_EXT_TID_MGMT;
if (!ieee80211_is_data_qos(hdr->frame_control))
return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
if (!is_unicast_ether_addr(ieee80211_get_DA(hdr)))
return HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
return ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;
}
static u8 ath10k_tx_h_get_vdev_id(struct ath10k *ar, struct ieee80211_vif *vif)
{
if (vif)
return ath10k_vif_to_arvif(vif)->vdev_id;
if (ar->monitor_started)
return ar->monitor_vdev_id;
ath10k_warn(ar, "failed to resolve vdev id\n");
return 0;
}
static enum ath10k_hw_txrx_mode
ath10k_tx_h_get_txmode(struct ath10k *ar, struct ieee80211_vif *vif,
struct ieee80211_sta *sta, struct sk_buff *skb)
ath10k_mac_tx_h_get_txmode(struct ath10k *ar,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct sk_buff *skb)
{
const struct ieee80211_hdr *hdr = (void *)skb->data;
__le16 fc = hdr->frame_control;
......@@ -3190,14 +3176,22 @@ ath10k_tx_h_get_txmode(struct ath10k *ar, struct ieee80211_vif *vif,
}
static bool ath10k_tx_h_use_hwcrypto(struct ieee80211_vif *vif,
struct sk_buff *skb) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct sk_buff *skb)
{
const struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
const struct ieee80211_hdr *hdr = (void *)skb->data;
const u32 mask = IEEE80211_TX_INTFL_DONT_ENCRYPT |
IEEE80211_TX_CTL_INJECTED;
if (!ieee80211_has_protected(hdr->frame_control))
return false;
if ((info->flags & mask) == mask)
return false;
if (vif)
return !ath10k_vif_to_arvif(vif)->nohwcrypt;
return true;
}
......@@ -3224,7 +3218,7 @@ static void ath10k_tx_h_nwifi(struct ieee80211_hw *hw, struct sk_buff *skb)
*/
hdr = (void *)skb->data;
if (ieee80211_is_qos_nullfunc(hdr->frame_control))
cb->htt.tid = HTT_DATA_TX_EXT_TID_NON_QOS_MCAST_BCAST;
cb->flags &= ~ATH10K_SKB_F_QOS;
hdr->frame_control &= ~__cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
}
......@@ -3280,7 +3274,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar,
}
}
static bool ath10k_mac_need_offchan_tx_work(struct ath10k *ar)
bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar)
{
/* FIXME: Not really sure since when the behaviour changed. At some
* point new firmware stopped requiring creation of peer entries for
......@@ -3288,8 +3282,9 @@ static bool ath10k_mac_need_offchan_tx_work(struct ath10k *ar)
* tx credit replenishment and reliability). Assuming it's at least 3.4
* because that's when the `freq` was introduced to TX_FRM HTT command.
*/
return !(ar->htt.target_version_major >= 3 &&
ar->htt.target_version_minor >= 4);
return (ar->htt.target_version_major >= 3 &&
ar->htt.target_version_minor >= 4 &&
ar->htt.op_version == ATH10K_FW_HTT_OP_VERSION_TLV);
}
static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb)
......@@ -3314,24 +3309,24 @@ static int ath10k_mac_tx_wmi_mgmt(struct ath10k *ar, struct sk_buff *skb)
return ret;
}
static void ath10k_mac_tx(struct ath10k *ar, struct sk_buff *skb)
static void ath10k_mac_tx(struct ath10k *ar, enum ath10k_hw_txrx_mode txmode,
struct sk_buff *skb)
{
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
struct ath10k_htt *htt = &ar->htt;
int ret = 0;
switch (cb->txmode) {
switch (txmode) {
case ATH10K_HW_TXRX_RAW:
case ATH10K_HW_TXRX_NATIVE_WIFI:
case ATH10K_HW_TXRX_ETHERNET:
ret = ath10k_htt_tx(htt, skb);
ret = ath10k_htt_tx(htt, txmode, skb);
break;
case ATH10K_HW_TXRX_MGMT:
if (test_bit(ATH10K_FW_FEATURE_HAS_WMI_MGMT_TX,
ar->fw_features))
ret = ath10k_mac_tx_wmi_mgmt(ar, skb);
else if (ar->htt.target_version_major >= 3)
ret = ath10k_htt_tx(htt, skb);
ret = ath10k_htt_tx(htt, txmode, skb);
else
ret = ath10k_htt_mgmt_tx(htt, skb);
break;
......@@ -3361,9 +3356,13 @@ void ath10k_offchan_tx_work(struct work_struct *work)
{
struct ath10k *ar = container_of(work, struct ath10k, offchan_tx_work);
struct ath10k_peer *peer;
struct ath10k_vif *arvif;
struct ieee80211_hdr *hdr;
struct ieee80211_vif *vif;
struct ieee80211_sta *sta;
struct sk_buff *skb;
const u8 *peer_addr;
enum ath10k_hw_txrx_mode txmode;
int vdev_id;
int ret;
unsigned long time_left;
......@@ -3388,9 +3387,9 @@ void ath10k_offchan_tx_work(struct work_struct *work)
hdr = (struct ieee80211_hdr *)skb->data;
peer_addr = ieee80211_get_DA(hdr);
vdev_id = ATH10K_SKB_CB(skb)->vdev_id;
spin_lock_bh(&ar->data_lock);
vdev_id = ar->scan.vdev_id;
peer = ath10k_peer_find(ar, vdev_id, peer_addr);
spin_unlock_bh(&ar->data_lock);
......@@ -3413,7 +3412,22 @@ void ath10k_offchan_tx_work(struct work_struct *work)
ar->offchan_tx_skb = skb;
spin_unlock_bh(&ar->data_lock);
ath10k_mac_tx(ar, skb);
/* It's safe to access vif and sta - conf_mutex guarantees that
* sta_state() and remove_interface() are locked exclusively
* out wrt to this offchannel worker.
*/
arvif = ath10k_get_arvif(ar, vdev_id);
if (arvif) {
vif = arvif->vif;
sta = ieee80211_find_sta(vif, peer_addr);
} else {
vif = NULL;
sta = NULL;
}
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
ath10k_mac_tx(ar, txmode, skb);
time_left =
wait_for_completion_timeout(&ar->offchan_tx_completed, 3 * HZ);
......@@ -3488,6 +3502,7 @@ void __ath10k_scan_finish(struct ath10k *ar)
case ATH10K_SCAN_STARTING:
ar->scan.state = ATH10K_SCAN_IDLE;
ar->scan_channel = NULL;
ar->scan.roc_freq = 0;
ath10k_offchan_tx_purge(ar);
cancel_delayed_work(&ar->scan.timeout);
complete_all(&ar->scan.completed);
......@@ -3631,25 +3646,32 @@ static void ath10k_tx(struct ieee80211_hw *hw,
struct sk_buff *skb)
{
struct ath10k *ar = hw->priv;
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
struct ieee80211_sta *sta = control->sta;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
__le16 fc = hdr->frame_control;
enum ath10k_hw_txrx_mode txmode;
/* We should disable CCK RATE due to P2P */
if (info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
ath10k_dbg(ar, ATH10K_DBG_MAC, "IEEE80211_TX_CTL_NO_CCK_RATE\n");
ATH10K_SKB_CB(skb)->htt.is_offchan = false;
ATH10K_SKB_CB(skb)->htt.freq = 0;
ATH10K_SKB_CB(skb)->htt.tid = ath10k_tx_h_get_tid(hdr);
ATH10K_SKB_CB(skb)->htt.nohwcrypt = !ath10k_tx_h_use_hwcrypto(vif, skb);
ATH10K_SKB_CB(skb)->vdev_id = ath10k_tx_h_get_vdev_id(ar, vif);
ATH10K_SKB_CB(skb)->txmode = ath10k_tx_h_get_txmode(ar, vif, sta, skb);
ATH10K_SKB_CB(skb)->is_protected = ieee80211_has_protected(fc);
txmode = ath10k_mac_tx_h_get_txmode(ar, vif, sta, skb);
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;
switch (ATH10K_SKB_CB(skb)->txmode) {
if (ieee80211_is_data_qos(hdr->frame_control))
skb_cb->flags |= ATH10K_SKB_F_QOS;
skb_cb->vif = vif;
switch (txmode) {
case ATH10K_HW_TXRX_MGMT:
case ATH10K_HW_TXRX_NATIVE_WIFI:
ath10k_tx_h_nwifi(hw, skb);
......@@ -3668,15 +3690,7 @@ static void ath10k_tx(struct ieee80211_hw *hw,
}
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
spin_lock_bh(&ar->data_lock);
ATH10K_SKB_CB(skb)->htt.freq = ar->scan.roc_freq;
ATH10K_SKB_CB(skb)->vdev_id = ar->scan.vdev_id;
spin_unlock_bh(&ar->data_lock);
if (ath10k_mac_need_offchan_tx_work(ar)) {
ATH10K_SKB_CB(skb)->htt.freq = 0;
ATH10K_SKB_CB(skb)->htt.is_offchan = true;
if (!ath10k_mac_tx_frm_has_freq(ar)) {
ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n",
skb);
......@@ -3686,7 +3700,7 @@ static void ath10k_tx(struct ieee80211_hw *hw,
}
}
ath10k_mac_tx(ar, skb);
ath10k_mac_tx(ar, txmode, skb);
}
/* Must not be called with conf_mutex held as workers can use that also. */
......@@ -4350,7 +4364,9 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
arvif->vdev_type = WMI_VDEV_TYPE_IBSS;
break;
case NL80211_IFTYPE_MESH_POINT:
if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
if (test_bit(WMI_SERVICE_MESH, ar->wmi.svc_map)) {
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH;
} else if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) {
ret = -EINVAL;
ath10k_warn(ar, "must load driver with rawmode=1 to add mesh interfaces\n");
goto err;
......@@ -6907,35 +6923,39 @@ void ath10k_mac_destroy(struct ath10k *ar)
static const struct ieee80211_iface_limit ath10k_if_limits[] = {
{
.max = 8,
.types = BIT(NL80211_IFTYPE_STATION)
| BIT(NL80211_IFTYPE_P2P_CLIENT)
.max = 8,
.types = BIT(NL80211_IFTYPE_STATION)
| BIT(NL80211_IFTYPE_P2P_CLIENT)
},
{
.max = 3,
.types = BIT(NL80211_IFTYPE_P2P_GO)
.max = 3,
.types = BIT(NL80211_IFTYPE_P2P_GO)
},
{
.max = 1,
.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
.max = 1,
.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
},
{
.max = 7,
.types = BIT(NL80211_IFTYPE_AP)
.max = 7,
.types = BIT(NL80211_IFTYPE_AP)
#ifdef CONFIG_MAC80211_MESH
| BIT(NL80211_IFTYPE_MESH_POINT)
| BIT(NL80211_IFTYPE_MESH_POINT)
#endif
},
};
static const struct ieee80211_iface_limit ath10k_10x_if_limits[] = {
{
.max = 8,
.types = BIT(NL80211_IFTYPE_AP)
.max = 8,
.types = BIT(NL80211_IFTYPE_AP)
#ifdef CONFIG_MAC80211_MESH
| BIT(NL80211_IFTYPE_MESH_POINT)
| BIT(NL80211_IFTYPE_MESH_POINT)
#endif
},
{
.max = 1,
.types = BIT(NL80211_IFTYPE_STATION)
},
};
static const struct ieee80211_iface_combination ath10k_if_comb[] = {
......
......@@ -66,7 +66,7 @@ void ath10k_mac_handle_tx_pause_vdev(struct ath10k *ar, u32 vdev_id,
enum wmi_tlv_tx_pause_action action);
u8 ath10k_mac_hw_rate_to_idx(const struct ieee80211_supported_band *sband,
u8 hw_rate);
u8 hw_rate, bool cck);
u8 ath10k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
u32 bitrate);
......@@ -74,6 +74,7 @@ void ath10k_mac_tx_lock(struct ath10k *ar, int reason);
void ath10k_mac_tx_unlock(struct ath10k *ar, int reason);
void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, int reason);
void ath10k_mac_vif_tx_unlock(struct ath10k_vif *arvif, int reason);
bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar);
static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
{
......
......@@ -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_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[] = {
/* CE0: host->target HTC control and raw streams */
......@@ -186,6 +187,7 @@ static struct ce_attr host_ce_config_wlan[] = {
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 128,
.recv_cb = ath10k_pci_pktlog_rx_cb,
},
/* CE9 target autonomous qcache memcpy */
......@@ -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);
}
/* Called by lower (CE) layer when data is received from the Target.
* Only 10.4 firmware uses separate CE to transfer pktlog data.
*/
static void ath10k_pci_pktlog_rx_cb(struct ath10k_ce_pipe *ce_state)
{
ath10k_pci_process_rx_cb(ce_state,
ath10k_htt_rx_pktlog_completion_handler);
}
/* Called by lower (CE) layer when a send to HTT Target completes. */
static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state)
{
......
......@@ -187,7 +187,7 @@ int ath10k_thermal_register(struct ath10k *ar)
/* Do not register hwmon device when temperature reading is not
* supported by firmware
*/
if (ar->wmi.op_version != ATH10K_FW_WMI_OP_VERSION_10_2_4)
if (!(ar->wmi.ops->gen_pdev_get_temperature))
return 0;
/* Avoid linking error on devm_hwmon_device_register_with_groups, I
......
......@@ -23,7 +23,12 @@
static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb)
{
if (!ATH10K_SKB_CB(skb)->htt.is_offchan)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
if (likely(!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)))
return;
if (ath10k_mac_tx_frm_has_freq(ar))
return;
/* If the original wait_for_completion() timed out before
......@@ -52,8 +57,6 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
struct ieee80211_tx_info *info;
struct ath10k_skb_cb *skb_cb;
struct sk_buff *msdu;
struct ieee80211_hdr *hdr;
__le16 fc;
bool limit_mgmt_desc = false;
ath10k_dbg(ar, ATH10K_DBG_HTT,
......@@ -76,10 +79,9 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
return;
}
hdr = (struct ieee80211_hdr *)msdu->data;
fc = hdr->frame_control;
skb_cb = ATH10K_SKB_CB(msdu);
if (unlikely(ieee80211_is_mgmt(fc)) &&
if (unlikely(skb_cb->flags & ATH10K_SKB_F_MGMT) &&
ar->hw_params.max_probe_resp_desc_thres)
limit_mgmt_desc = true;
......@@ -89,7 +91,6 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
wake_up(&htt->empty_tx_wq);
spin_unlock_bh(&htt->tx_lock);
skb_cb = ATH10K_SKB_CB(msdu);
dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
ath10k_report_offchan_tx(htt->ar, msdu);
......
......@@ -3485,6 +3485,24 @@ static const struct wmi_ops wmi_tlv_ops = {
.fw_stats_fill = ath10k_wmi_main_op_fw_stats_fill,
};
static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
.auth = WMI_TLV_PEER_AUTH,
.qos = WMI_TLV_PEER_QOS,
.need_ptk_4_way = WMI_TLV_PEER_NEED_PTK_4_WAY,
.need_gtk_2_way = WMI_TLV_PEER_NEED_GTK_2_WAY,
.apsd = WMI_TLV_PEER_APSD,
.ht = WMI_TLV_PEER_HT,
.bw40 = WMI_TLV_PEER_40MHZ,
.stbc = WMI_TLV_PEER_STBC,
.ldbc = WMI_TLV_PEER_LDPC,
.dyn_mimops = WMI_TLV_PEER_DYN_MIMOPS,
.static_mimops = WMI_TLV_PEER_STATIC_MIMOPS,
.spatial_mux = WMI_TLV_PEER_SPATIAL_MUX,
.vht = WMI_TLV_PEER_VHT,
.bw80 = WMI_TLV_PEER_80MHZ,
.pmf = WMI_TLV_PEER_PMF,
};
/************/
/* TLV init */
/************/
......@@ -3495,4 +3513,5 @@ void ath10k_wmi_tlv_attach(struct ath10k *ar)
ar->wmi.vdev_param = &wmi_tlv_vdev_param_map;
ar->wmi.pdev_param = &wmi_tlv_pdev_param_map;
ar->wmi.ops = &wmi_tlv_ops;
ar->wmi.peer_flags = &wmi_tlv_peer_flags_map;
}
......@@ -527,6 +527,24 @@ enum wmi_tlv_vdev_param {
WMI_TLV_VDEV_PARAM_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE,
};
enum wmi_tlv_peer_flags {
WMI_TLV_PEER_AUTH = 0x00000001,
WMI_TLV_PEER_QOS = 0x00000002,
WMI_TLV_PEER_NEED_PTK_4_WAY = 0x00000004,
WMI_TLV_PEER_NEED_GTK_2_WAY = 0x00000010,
WMI_TLV_PEER_APSD = 0x00000800,
WMI_TLV_PEER_HT = 0x00001000,
WMI_TLV_PEER_40MHZ = 0x00002000,
WMI_TLV_PEER_STBC = 0x00008000,
WMI_TLV_PEER_LDPC = 0x00010000,
WMI_TLV_PEER_DYN_MIMOPS = 0x00020000,
WMI_TLV_PEER_STATIC_MIMOPS = 0x00040000,
WMI_TLV_PEER_SPATIAL_MUX = 0x00200000,
WMI_TLV_PEER_VHT = 0x02000000,
WMI_TLV_PEER_80MHZ = 0x04000000,
WMI_TLV_PEER_PMF = 0x08000000,
};
enum wmi_tlv_tag {
WMI_TLV_TAG_LAST_RESERVED = 15,
......
......@@ -1546,6 +1546,61 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
.arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
};
static const struct wmi_peer_flags_map wmi_peer_flags_map = {
.auth = WMI_PEER_AUTH,
.qos = WMI_PEER_QOS,
.need_ptk_4_way = WMI_PEER_NEED_PTK_4_WAY,
.need_gtk_2_way = WMI_PEER_NEED_GTK_2_WAY,
.apsd = WMI_PEER_APSD,
.ht = WMI_PEER_HT,
.bw40 = WMI_PEER_40MHZ,
.stbc = WMI_PEER_STBC,
.ldbc = WMI_PEER_LDPC,
.dyn_mimops = WMI_PEER_DYN_MIMOPS,
.static_mimops = WMI_PEER_STATIC_MIMOPS,
.spatial_mux = WMI_PEER_SPATIAL_MUX,
.vht = WMI_PEER_VHT,
.bw80 = WMI_PEER_80MHZ,
.vht_2g = WMI_PEER_VHT_2G,
.pmf = WMI_PEER_PMF,
};
static const struct wmi_peer_flags_map wmi_10x_peer_flags_map = {
.auth = WMI_10X_PEER_AUTH,
.qos = WMI_10X_PEER_QOS,
.need_ptk_4_way = WMI_10X_PEER_NEED_PTK_4_WAY,
.need_gtk_2_way = WMI_10X_PEER_NEED_GTK_2_WAY,
.apsd = WMI_10X_PEER_APSD,
.ht = WMI_10X_PEER_HT,
.bw40 = WMI_10X_PEER_40MHZ,
.stbc = WMI_10X_PEER_STBC,
.ldbc = WMI_10X_PEER_LDPC,
.dyn_mimops = WMI_10X_PEER_DYN_MIMOPS,
.static_mimops = WMI_10X_PEER_STATIC_MIMOPS,
.spatial_mux = WMI_10X_PEER_SPATIAL_MUX,
.vht = WMI_10X_PEER_VHT,
.bw80 = WMI_10X_PEER_80MHZ,
};
static const struct wmi_peer_flags_map wmi_10_2_peer_flags_map = {
.auth = WMI_10_2_PEER_AUTH,
.qos = WMI_10_2_PEER_QOS,
.need_ptk_4_way = WMI_10_2_PEER_NEED_PTK_4_WAY,
.need_gtk_2_way = WMI_10_2_PEER_NEED_GTK_2_WAY,
.apsd = WMI_10_2_PEER_APSD,
.ht = WMI_10_2_PEER_HT,
.bw40 = WMI_10_2_PEER_40MHZ,
.stbc = WMI_10_2_PEER_STBC,
.ldbc = WMI_10_2_PEER_LDPC,
.dyn_mimops = WMI_10_2_PEER_DYN_MIMOPS,
.static_mimops = WMI_10_2_PEER_STATIC_MIMOPS,
.spatial_mux = WMI_10_2_PEER_SPATIAL_MUX,
.vht = WMI_10_2_PEER_VHT,
.bw80 = WMI_10_2_PEER_80MHZ,
.vht_2g = WMI_10_2_PEER_VHT_2G,
.pmf = WMI_10_2_PEER_PMF,
};
void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
const struct wmi_channel_arg *arg)
{
......@@ -1660,6 +1715,8 @@ static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
struct ath10k *ar = arvif->ar;
struct ath10k_skb_cb *cb;
struct sk_buff *bcn;
bool dtim_zero;
bool deliver_cab;
int ret;
spin_lock_bh(&ar->data_lock);
......@@ -1679,12 +1736,14 @@ static void ath10k_wmi_tx_beacon_nowait(struct ath10k_vif *arvif)
arvif->beacon_state = ATH10K_BEACON_SENDING;
spin_unlock_bh(&ar->data_lock);
dtim_zero = !!(cb->flags & ATH10K_SKB_F_DTIM_ZERO);
deliver_cab = !!(cb->flags & ATH10K_SKB_F_DELIVER_CAB);
ret = ath10k_wmi_beacon_send_ref_nowait(arvif->ar,
arvif->vdev_id,
bcn->data, bcn->len,
cb->paddr,
cb->bcn.dtim_zero,
cb->bcn.deliver_cab);
dtim_zero,
deliver_cab);
spin_lock_bh(&ar->data_lock);
......@@ -1755,16 +1814,24 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id)
static struct sk_buff *
ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
{
struct ath10k_skb_cb *cb = ATH10K_SKB_CB(msdu);
struct ath10k_vif *arvif = (void *)cb->vif->drv_priv;
struct wmi_mgmt_tx_cmd *cmd;
struct ieee80211_hdr *hdr;
struct sk_buff *skb;
int len;
u32 vdev_id;
u32 buf_len = msdu->len;
u16 fc;
hdr = (struct ieee80211_hdr *)msdu->data;
fc = le16_to_cpu(hdr->frame_control);
if (cb->vif)
vdev_id = arvif->vdev_id;
else
vdev_id = 0;
if (WARN_ON_ONCE(!ieee80211_is_mgmt(hdr->frame_control)))
return ERR_PTR(-EINVAL);
......@@ -1786,7 +1853,7 @@ ath10k_wmi_op_gen_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
cmd = (struct wmi_mgmt_tx_cmd *)skb->data;
cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(msdu)->vdev_id);
cmd->hdr.vdev_id = __cpu_to_le32(vdev_id);
cmd->hdr.tx_rate = 0;
cmd->hdr.tx_power = 0;
cmd->hdr.buf_len = __cpu_to_le32(buf_len);
......@@ -2204,22 +2271,9 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
ath10k_dbg(ar, ATH10K_DBG_MGMT,
"event mgmt rx status %08x\n", rx_status);
if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) {
dev_kfree_skb(skb);
return 0;
}
if (rx_status & WMI_RX_STATUS_ERR_DECRYPT) {
dev_kfree_skb(skb);
return 0;
}
if (rx_status & WMI_RX_STATUS_ERR_KEY_CACHE_MISS) {
dev_kfree_skb(skb);
return 0;
}
if (rx_status & WMI_RX_STATUS_ERR_CRC) {
if ((test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) ||
(rx_status & (WMI_RX_STATUS_ERR_DECRYPT |
WMI_RX_STATUS_ERR_KEY_CACHE_MISS | WMI_RX_STATUS_ERR_CRC))) {
dev_kfree_skb(skb);
return 0;
}
......@@ -3115,10 +3169,10 @@ static void ath10k_wmi_update_tim(struct ath10k *ar,
memcpy(tim->virtual_map, arvif->u.ap.tim_bitmap, pvm_len);
if (tim->dtim_count == 0) {
ATH10K_SKB_CB(bcn)->bcn.dtim_zero = true;
ATH10K_SKB_CB(bcn)->flags |= ATH10K_SKB_F_DTIM_ZERO;
if (__le32_to_cpu(tim_info->tim_mcast) == 1)
ATH10K_SKB_CB(bcn)->bcn.deliver_cab = true;
ATH10K_SKB_CB(bcn)->flags |= ATH10K_SKB_F_DELIVER_CAB;
}
ath10k_dbg(ar, ATH10K_DBG_MGMT, "dtim %d/%d mcast %d pvmlen %d\n",
......@@ -5061,6 +5115,9 @@ static void ath10k_wmi_10_4_op_rx(struct ath10k *ar, struct sk_buff *skb)
case WMI_10_4_UPDATE_STATS_EVENTID:
ath10k_wmi_event_update_stats(ar, skb);
break;
case WMI_10_4_PDEV_TEMPERATURE_EVENTID:
ath10k_wmi_event_temperature(ar, skb);
break;
default:
ath10k_warn(ar, "Unknown eventid: %d\n", id);
break;
......@@ -5431,8 +5488,11 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
cmd = (struct wmi_init_cmd_10_2 *)buf->data;
features = WMI_10_2_RX_BATCH_MODE;
if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
if (test_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags) &&
test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
features |= WMI_10_2_COEX_GPIO;
cmd->resource_config.feature_mask = __cpu_to_le32(features);
memcpy(&cmd->resource_config.common, &config, sizeof(config));
......@@ -6328,6 +6388,16 @@ ath10k_wmi_peer_assoc_fill_10_2(struct ath10k *ar, void *buf,
cmd->info0 = __cpu_to_le32(info0);
}
static void
ath10k_wmi_peer_assoc_fill_10_4(struct ath10k *ar, void *buf,
const struct wmi_peer_assoc_complete_arg *arg)
{
struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf;
ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg);
cmd->peer_bw_rxnss_override = 0;
}
static int
ath10k_wmi_peer_assoc_check_arg(const struct wmi_peer_assoc_complete_arg *arg)
{
......@@ -6416,6 +6486,31 @@ ath10k_wmi_10_2_op_gen_peer_assoc(struct ath10k *ar,
return skb;
}
static struct sk_buff *
ath10k_wmi_10_4_op_gen_peer_assoc(struct ath10k *ar,
const struct wmi_peer_assoc_complete_arg *arg)
{
size_t len = sizeof(struct wmi_10_4_peer_assoc_complete_cmd);
struct sk_buff *skb;
int ret;
ret = ath10k_wmi_peer_assoc_check_arg(arg);
if (ret)
return ERR_PTR(ret);
skb = ath10k_wmi_alloc_skb(ar, len);
if (!skb)
return ERR_PTR(-ENOMEM);
ath10k_wmi_peer_assoc_fill_10_4(ar, skb->data, arg);
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi peer assoc vdev %d addr %pM (%s)\n",
arg->vdev_id, arg->addr,
arg->peer_reassoc ? "reassociate" : "new");
return skb;
}
static struct sk_buff *
ath10k_wmi_10_2_op_gen_pdev_get_temperature(struct ath10k *ar)
{
......@@ -7536,6 +7631,7 @@ static const struct wmi_ops wmi_10_4_ops = {
.gen_peer_delete = ath10k_wmi_op_gen_peer_delete,
.gen_peer_flush = ath10k_wmi_op_gen_peer_flush,
.gen_peer_set_param = ath10k_wmi_op_gen_peer_set_param,
.gen_peer_assoc = ath10k_wmi_10_4_op_gen_peer_assoc,
.gen_set_psmode = ath10k_wmi_op_gen_set_psmode,
.gen_set_sta_ps = ath10k_wmi_op_gen_set_sta_ps,
.gen_set_ap_ps = ath10k_wmi_op_gen_set_ap_ps,
......@@ -7555,8 +7651,8 @@ static const struct wmi_ops wmi_10_4_ops = {
.fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill,
/* shared with 10.2 */
.gen_peer_assoc = ath10k_wmi_10_2_op_gen_peer_assoc,
.gen_request_stats = ath10k_wmi_op_gen_request_stats,
.gen_pdev_get_temperature = ath10k_wmi_10_2_op_gen_pdev_get_temperature,
};
int ath10k_wmi_attach(struct ath10k *ar)
......@@ -7567,30 +7663,35 @@ int ath10k_wmi_attach(struct ath10k *ar)
ar->wmi.cmd = &wmi_10_4_cmd_map;
ar->wmi.vdev_param = &wmi_10_4_vdev_param_map;
ar->wmi.pdev_param = &wmi_10_4_pdev_param_map;
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
break;
case ATH10K_FW_WMI_OP_VERSION_10_2_4:
ar->wmi.cmd = &wmi_10_2_4_cmd_map;
ar->wmi.ops = &wmi_10_2_4_ops;
ar->wmi.vdev_param = &wmi_10_2_4_vdev_param_map;
ar->wmi.pdev_param = &wmi_10_2_4_pdev_param_map;
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
break;
case ATH10K_FW_WMI_OP_VERSION_10_2:
ar->wmi.cmd = &wmi_10_2_cmd_map;
ar->wmi.ops = &wmi_10_2_ops;
ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
ar->wmi.peer_flags = &wmi_10_2_peer_flags_map;
break;
case ATH10K_FW_WMI_OP_VERSION_10_1:
ar->wmi.cmd = &wmi_10x_cmd_map;
ar->wmi.ops = &wmi_10_1_ops;
ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
ar->wmi.peer_flags = &wmi_10x_peer_flags_map;
break;
case ATH10K_FW_WMI_OP_VERSION_MAIN:
ar->wmi.cmd = &wmi_cmd_map;
ar->wmi.ops = &wmi_ops;
ar->wmi.vdev_param = &wmi_vdev_param_map;
ar->wmi.pdev_param = &wmi_pdev_param_map;
ar->wmi.peer_flags = &wmi_peer_flags_map;
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
ath10k_wmi_tlv_attach(ar);
......
......@@ -175,6 +175,8 @@ enum wmi_service {
WMI_SERVICE_AUX_SPECTRAL_INTF,
WMI_SERVICE_AUX_CHAN_LOAD_INTF,
WMI_SERVICE_BSS_CHANNEL_INFO_64,
WMI_SERVICE_EXT_RES_CFG_SUPPORT,
WMI_SERVICE_MESH,
/* keep last */
WMI_SERVICE_MAX,
......@@ -206,6 +208,11 @@ enum wmi_10x_service {
WMI_10X_SERVICE_SMART_ANTENNA_HW_SUPPORT,
WMI_10X_SERVICE_ATF,
WMI_10X_SERVICE_COEX_GPIO,
WMI_10X_SERVICE_AUX_SPECTRAL_INTF,
WMI_10X_SERVICE_AUX_CHAN_LOAD_INTF,
WMI_10X_SERVICE_BSS_CHANNEL_INFO_64,
WMI_10X_SERVICE_MESH,
WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT,
};
enum wmi_main_service {
......@@ -286,6 +293,8 @@ enum wmi_10_4_service {
WMI_10_4_SERVICE_AUX_SPECTRAL_INTF,
WMI_10_4_SERVICE_AUX_CHAN_LOAD_INTF,
WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64,
WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT,
WMI_10_4_SERVICE_MESH,
};
static inline char *wmi_service_name(int service_id)
......@@ -375,6 +384,8 @@ static inline char *wmi_service_name(int service_id)
SVCSTR(WMI_SERVICE_AUX_SPECTRAL_INTF);
SVCSTR(WMI_SERVICE_AUX_CHAN_LOAD_INTF);
SVCSTR(WMI_SERVICE_BSS_CHANNEL_INFO_64);
SVCSTR(WMI_SERVICE_EXT_RES_CFG_SUPPORT);
SVCSTR(WMI_SERVICE_MESH);
default:
return NULL;
}
......@@ -442,6 +453,16 @@ static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out,
WMI_SERVICE_ATF, len);
SVCMAP(WMI_10X_SERVICE_COEX_GPIO,
WMI_SERVICE_COEX_GPIO, len);
SVCMAP(WMI_10X_SERVICE_AUX_SPECTRAL_INTF,
WMI_SERVICE_AUX_SPECTRAL_INTF, len);
SVCMAP(WMI_10X_SERVICE_AUX_CHAN_LOAD_INTF,
WMI_SERVICE_AUX_CHAN_LOAD_INTF, len);
SVCMAP(WMI_10X_SERVICE_BSS_CHANNEL_INFO_64,
WMI_SERVICE_BSS_CHANNEL_INFO_64, len);
SVCMAP(WMI_10X_SERVICE_MESH,
WMI_SERVICE_MESH, len);
SVCMAP(WMI_10X_SERVICE_EXT_RES_CFG_SUPPORT,
WMI_SERVICE_EXT_RES_CFG_SUPPORT, len);
}
static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out,
......@@ -600,6 +621,10 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
WMI_SERVICE_AUX_CHAN_LOAD_INTF, len);
SVCMAP(WMI_10_4_SERVICE_BSS_CHANNEL_INFO_64,
WMI_SERVICE_BSS_CHANNEL_INFO_64, len);
SVCMAP(WMI_10_4_SERVICE_EXT_RES_CFG_SUPPORT,
WMI_SERVICE_EXT_RES_CFG_SUPPORT, len);
SVCMAP(WMI_10_4_SERVICE_MESH,
WMI_SERVICE_MESH, len);
}
#undef SVCMAP
......@@ -1576,6 +1601,9 @@ enum wmi_10_4_cmd_id {
WMI_10_4_MU_CAL_START_CMDID,
WMI_10_4_SET_CCA_PARAMS_CMDID,
WMI_10_4_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
WMI_10_4_EXT_RESOURCE_CFG_CMDID,
WMI_10_4_VDEV_SET_IE_CMDID,
WMI_10_4_SET_LTEU_CONFIG_CMDID,
WMI_10_4_PDEV_UTF_CMDID = WMI_10_4_END_CMDID - 1,
};
......@@ -1638,6 +1666,7 @@ enum wmi_10_4_event_id {
WMI_10_4_PDEV_TEMPERATURE_EVENTID,
WMI_10_4_PDEV_NFCAL_POWER_ALL_CHANNELS_EVENTID,
WMI_10_4_PDEV_BSS_CHAN_INFO_EVENTID,
WMI_10_4_MU_REPORT_EVENTID,
WMI_10_4_PDEV_UTF_EVENTID = WMI_10_4_END_EVENTID - 1,
};
......@@ -3650,6 +3679,12 @@ enum wmi_10_4_pdev_param {
WMI_10_4_PDEV_PARAM_WAPI_MBSSID_OFFSET,
WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
WMI_10_4_PDEV_PARAM_TXPOWER_DECR_DB,
WMI_10_4_PDEV_PARAM_RX_BATCHMODE,
WMI_10_4_PDEV_PARAM_PACKET_AGGR_DELAY,
WMI_10_4_PDEV_PARAM_ATF_OBSS_NOISE_SCH,
WMI_10_4_PDEV_PARAM_ATF_OBSS_NOISE_SCALING_FACTOR,
WMI_10_4_PDEV_PARAM_CUST_TXPOWER_SCALE,
};
struct wmi_pdev_set_param_cmd {
......@@ -4239,6 +4274,8 @@ enum wmi_vdev_subtype {
WMI_VDEV_SUBTYPE_P2P_DEVICE = 1,
WMI_VDEV_SUBTYPE_P2P_CLIENT = 2,
WMI_VDEV_SUBTYPE_P2P_GO = 3,
WMI_VDEV_SUBTYPE_PROXY_STA = 4,
WMI_VDEV_SUBTYPE_MESH = 5,
};
/* values for vdev_subtype */
......@@ -5641,21 +5678,79 @@ struct wmi_peer_set_q_empty_callback_cmd {
__le32 callback_enable;
} __packed;
#define WMI_PEER_AUTH 0x00000001
#define WMI_PEER_QOS 0x00000002
#define WMI_PEER_NEED_PTK_4_WAY 0x00000004
#define WMI_PEER_NEED_GTK_2_WAY 0x00000010
#define WMI_PEER_APSD 0x00000800
#define WMI_PEER_HT 0x00001000
#define WMI_PEER_40MHZ 0x00002000
#define WMI_PEER_STBC 0x00008000
#define WMI_PEER_LDPC 0x00010000
#define WMI_PEER_DYN_MIMOPS 0x00020000
#define WMI_PEER_STATIC_MIMOPS 0x00040000
#define WMI_PEER_SPATIAL_MUX 0x00200000
#define WMI_PEER_VHT 0x02000000
#define WMI_PEER_80MHZ 0x04000000
#define WMI_PEER_VHT_2G 0x08000000
struct wmi_peer_flags_map {
u32 auth;
u32 qos;
u32 need_ptk_4_way;
u32 need_gtk_2_way;
u32 apsd;
u32 ht;
u32 bw40;
u32 stbc;
u32 ldbc;
u32 dyn_mimops;
u32 static_mimops;
u32 spatial_mux;
u32 vht;
u32 bw80;
u32 vht_2g;
u32 pmf;
};
enum wmi_peer_flags {
WMI_PEER_AUTH = 0x00000001,
WMI_PEER_QOS = 0x00000002,
WMI_PEER_NEED_PTK_4_WAY = 0x00000004,
WMI_PEER_NEED_GTK_2_WAY = 0x00000010,
WMI_PEER_APSD = 0x00000800,
WMI_PEER_HT = 0x00001000,
WMI_PEER_40MHZ = 0x00002000,
WMI_PEER_STBC = 0x00008000,
WMI_PEER_LDPC = 0x00010000,
WMI_PEER_DYN_MIMOPS = 0x00020000,
WMI_PEER_STATIC_MIMOPS = 0x00040000,
WMI_PEER_SPATIAL_MUX = 0x00200000,
WMI_PEER_VHT = 0x02000000,
WMI_PEER_80MHZ = 0x04000000,
WMI_PEER_VHT_2G = 0x08000000,
WMI_PEER_PMF = 0x10000000,
};
enum wmi_10x_peer_flags {
WMI_10X_PEER_AUTH = 0x00000001,
WMI_10X_PEER_QOS = 0x00000002,
WMI_10X_PEER_NEED_PTK_4_WAY = 0x00000004,
WMI_10X_PEER_NEED_GTK_2_WAY = 0x00000010,
WMI_10X_PEER_APSD = 0x00000800,
WMI_10X_PEER_HT = 0x00001000,
WMI_10X_PEER_40MHZ = 0x00002000,
WMI_10X_PEER_STBC = 0x00008000,
WMI_10X_PEER_LDPC = 0x00010000,
WMI_10X_PEER_DYN_MIMOPS = 0x00020000,
WMI_10X_PEER_STATIC_MIMOPS = 0x00040000,
WMI_10X_PEER_SPATIAL_MUX = 0x00200000,
WMI_10X_PEER_VHT = 0x02000000,
WMI_10X_PEER_80MHZ = 0x04000000,
};
enum wmi_10_2_peer_flags {
WMI_10_2_PEER_AUTH = 0x00000001,
WMI_10_2_PEER_QOS = 0x00000002,
WMI_10_2_PEER_NEED_PTK_4_WAY = 0x00000004,
WMI_10_2_PEER_NEED_GTK_2_WAY = 0x00000010,
WMI_10_2_PEER_APSD = 0x00000800,
WMI_10_2_PEER_HT = 0x00001000,
WMI_10_2_PEER_40MHZ = 0x00002000,
WMI_10_2_PEER_STBC = 0x00008000,
WMI_10_2_PEER_LDPC = 0x00010000,
WMI_10_2_PEER_DYN_MIMOPS = 0x00020000,
WMI_10_2_PEER_STATIC_MIMOPS = 0x00040000,
WMI_10_2_PEER_SPATIAL_MUX = 0x00200000,
WMI_10_2_PEER_VHT = 0x02000000,
WMI_10_2_PEER_80MHZ = 0x04000000,
WMI_10_2_PEER_VHT_2G = 0x08000000,
WMI_10_2_PEER_PMF = 0x10000000,
};
/*
* Peer rate capabilities.
......@@ -5721,6 +5816,11 @@ struct wmi_10_2_peer_assoc_complete_cmd {
__le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
} __packed;
struct wmi_10_4_peer_assoc_complete_cmd {
struct wmi_10_2_peer_assoc_complete_cmd cmd;
__le32 peer_bw_rxnss_override;
} __packed;
struct wmi_peer_assoc_complete_arg {
u8 addr[ETH_ALEN];
u32 vdev_id;
......
......@@ -414,7 +414,7 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
return;
}
if (epid >= ENDPOINT_MAX) {
if (epid < 0 || epid >= ENDPOINT_MAX) {
if (pipe_id != USB_REG_IN_PIPE)
dev_kfree_skb_any(skb);
else
......
......@@ -345,6 +345,8 @@ enum wcn36xx_hal_host_msg_type {
WCN36XX_HAL_DHCP_START_IND = 189,
WCN36XX_HAL_DHCP_STOP_IND = 190,
WCN36XX_HAL_AVOID_FREQ_RANGE_IND = 233,
WCN36XX_HAL_MSG_MAX = WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE
};
......
......@@ -302,6 +302,22 @@ static int wcn36xx_smd_rsp_status_check(void *buf, size_t len)
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)
{
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");
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) {
wcn36xx_err("hal_remove_bsskey response failed err=%d\n", ret);
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");
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) {
wcn36xx_err("hal_trigger_ba response failed err=%d\n", ret);
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);
break;
case WCN36XX_HAL_COEX_IND:
case WCN36XX_HAL_AVOID_FREQ_RANGE_IND:
case WCN36XX_HAL_OTA_TX_COMPL_IND:
case WCN36XX_HAL_MISSED_BEACON_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;
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:
wcn36xx_smd_tx_compl_ind(wcn,
hal_ind_msg->msg,
......
......@@ -44,6 +44,15 @@ struct wcn36xx_fw_msg_status_rsp {
u32 status;
} __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 list_head list;
u8 *msg;
......
......@@ -401,20 +401,26 @@ void wil_bcast_fini(struct wil6210_priv *wil)
static void wil_connect_worker(struct work_struct *work)
{
int rc;
int rc, cid, ringid;
struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
connect_worker);
struct net_device *ndev = wil_to_ndev(wil);
int cid = wil->pending_connect_cid;
int ringid = wil_find_free_vring(wil);
mutex_lock(&wil->mutex);
cid = wil->pending_connect_cid;
if (cid < 0) {
wil_err(wil, "No connection pending\n");
return;
goto out;
}
ringid = wil_find_free_vring(wil);
if (ringid < 0) {
wil_err(wil, "No free vring found\n");
goto out;
}
wil_dbg_wmi(wil, "Configure for connection CID %d\n", cid);
wil_dbg_wmi(wil, "Configure for connection CID %d vring %d\n",
cid, ringid);
rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0);
wil->pending_connect_cid = -1;
......@@ -424,6 +430,8 @@ static void wil_connect_worker(struct work_struct *work)
} else {
wil_disconnect_cid(wil, cid, WLAN_REASON_UNSPECIFIED, true);
}
out:
mutex_unlock(&wil->mutex);
}
int wil_priv_init(struct wil6210_priv *wil)
......
......@@ -160,6 +160,7 @@ static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
struct device *dev = wil_to_dev(wil);
size_t sz = vring->size * sizeof(vring->va[0]);
lockdep_assert_held(&wil->mutex);
if (tx) {
int vring_index = vring - wil->vring_tx;
......@@ -749,6 +750,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
wil_dbg_misc(wil, "%s() max_mpdu_size %d\n", __func__,
cmd.vring_cfg.tx_sw_ring.max_mpdu_size);
lockdep_assert_held(&wil->mutex);
if (vring->va) {
wil_err(wil, "Tx ring [%d] already allocated\n", id);
......@@ -821,6 +823,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
wil_dbg_misc(wil, "%s() max_mpdu_size %d\n", __func__,
cmd.vring_cfg.tx_sw_ring.max_mpdu_size);
lockdep_assert_held(&wil->mutex);
if (vring->va) {
wil_err(wil, "Tx ring [%d] already allocated\n", id);
......@@ -872,7 +875,7 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
struct vring *vring = &wil->vring_tx[id];
struct vring_tx_data *txdata = &wil->vring_tx_data[id];
WARN_ON(!mutex_is_locked(&wil->mutex));
lockdep_assert_held(&wil->mutex);
if (!vring->va)
return;
......
......@@ -187,7 +187,8 @@ brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
goto retry;
if (id != bcdc->reqid) {
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;
goto done;
}
......@@ -234,7 +235,8 @@ brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
if (id != bcdc->reqid) {
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;
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) !=
BCDC_PROTO_VER) {
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;
}
if (h->flags & BCDC_FLAG_SUM_GOOD) {
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;
}
......
......@@ -137,7 +137,7 @@ struct brcmf_bus {
bool always_use_fws_queue;
bool wowl_supported;
struct brcmf_bus_ops *ops;
const struct brcmf_bus_ops *ops;
struct brcmf_bus_msgbuf *msgbuf;
};
......
......@@ -776,7 +776,8 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev,
s32 ap = 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
* 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
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 +
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);
/* 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);
......@@ -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);
brcmf_escan_prep(cfg, &params->params_le, request);
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);
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->buflen = WL_ESCAN_RESULTS_FIXED_SIZE;
err = escan->run(cfg, ifp, request, WL_ESCAN_ACTION_START);
err = escan->run(cfg, ifp, request);
if (err)
brcmf_scan_config_mpc(ifp, 1);
return err;
......@@ -1291,6 +1292,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
s32 wsec = 0;
s32 bcnprd;
u16 chanspec;
u32 ssid_len;
brcmf_dbg(TRACE, "Enter\n");
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));
/* SSID */
profile->ssid.SSID_len = min_t(u32, params->ssid_len, 32);
memcpy(profile->ssid.SSID, params->ssid, profile->ssid.SSID_len);
memcpy(join_params.ssid_le.SSID, params->ssid, profile->ssid.SSID_len);
join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
ssid_len = min_t(u32, params->ssid_len, IEEE80211_MAX_SSID_LEN);
memcpy(join_params.ssid_le.SSID, params->ssid, ssid_len);
join_params.ssid_le.SSID_len = cpu_to_le32(ssid_len);
join_params_size = sizeof(join_params.ssid_le);
/* BSSID */
if (params->bssid) {
memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN);
join_params_size = sizeof(join_params.ssid_le) +
BRCMF_ASSOC_PARAMS_FIXED_SIZE;
join_params_size += BRCMF_ASSOC_PARAMS_FIXED_SIZE;
memcpy(profile->bssid, params->bssid, ETH_ALEN);
} else {
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_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct ieee80211_channel *chan = sme->channel;
struct brcmf_join_params join_params;
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;
u16 chanspec;
s32 err = 0;
u32 ssid_len;
brcmf_dbg(TRACE, "Enter\n");
if (!check_vif_up(ifp->vif))
......@@ -1824,15 +1824,6 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
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
* 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;
goto done;
}
ext_join_params->ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
memcpy(&ext_join_params->ssid_le.SSID, sme->ssid,
profile->ssid.SSID_len);
ssid_len = min_t(u32, sme->ssid_len, IEEE80211_MAX_SSID_LEN);
ext_join_params->ssid_le.SSID_len = cpu_to_le32(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 */
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));
join_params_size = sizeof(join_params.ssid_le);
memcpy(&join_params.ssid_le.SSID, sme->ssid, profile->ssid.SSID_len);
join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len);
memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid_len);
join_params.ssid_le.SSID_len = cpu_to_le32(ssid_len);
if (sme->bssid)
memcpy(join_params.params_le.bssid, sme->bssid, ETH_ALEN);
......@@ -2775,9 +2769,7 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
struct brcmf_if *ifp)
{
struct brcmf_cfg80211_profile *profile = ndev_to_prof(ifp->ndev);
struct brcmf_bss_info_le *bi;
struct brcmf_ssid *ssid;
const struct brcmf_tlv *tim;
u16 beacon_interval;
u8 dtim_period;
......@@ -2789,8 +2781,6 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg,
if (brcmf_is_ibssmode(ifp->vif))
return err;
ssid = &profile->ssid;
*(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO,
cfg->extra_buf, WL_EXTRA_BUF_MAX);
......@@ -2921,7 +2911,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp,
status = e->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;
}
......@@ -3061,6 +3051,67 @@ static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4],
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)
{
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");
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_fil_cmd_int_set(ifp, BRCMF_C_SET_PM,
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;
}
return 0;
......@@ -3108,6 +3160,7 @@ static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg,
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_activate", 1);
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;
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);
if (!iovar_ie_buf)
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);
if (err < 0) {
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);
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);
err = brcmf_fil_iovar_data_set(ifp, "bss", &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)
brcmf_err("BRCMF_C_UP error %d\n", err);
} 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);
err = brcmf_fil_iovar_data_set(ifp, "bss", &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->pm_block = pm_block;
vif->roam_off = -1;
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 *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->bssidx);
ifevent->bsscfgidx);
mutex_lock(&event->vif_event_lock);
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);
}
static s32
brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout)
static s32 brcmf_dongle_roam(struct brcmf_if *ifp)
{
s32 err = 0;
s32 err;
u32 bcn_timeout;
__le32 roamtrigger[2];
__le32 roam_delta[2];
/*
* Setup timeout if Beacons are lost and roam is
* off to report link down
*/
if (brcmf_roamoff) {
err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);
if (err) {
brcmf_err("bcn_timeout error (%d)\n", err);
goto dongle_rom_out;
}
/* Configure beacon timeout value based upon roaming setting */
if (brcmf_roamoff)
bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_OFF;
else
bcn_timeout = BRCMF_DEFAULT_BCN_TIMEOUT_ROAM_ON;
err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout);
if (err) {
brcmf_err("bcn_timeout error (%d)\n", err);
goto roam_setup_done;
}
/*
* Enable/Disable built-in roaming to allow supplicant
* to take care of roaming
/* Enable/Disable built-in roaming to allow supplicant to take care of
* roaming.
*/
brcmf_dbg(INFO, "Internal Roaming = %s\n",
brcmf_roamoff ? "Off" : "On");
err = brcmf_fil_iovar_int_set(ifp, "roam_off", !!(brcmf_roamoff));
if (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);
......@@ -5287,7 +5340,7 @@ brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout)
(void *)roamtrigger, sizeof(roamtrigger));
if (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);
......@@ -5296,10 +5349,10 @@ brcmf_dongle_roam(struct brcmf_if *ifp, u32 bcn_timeout)
(void *)roam_delta, sizeof(roam_delta));
if (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;
}
......@@ -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,
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;
......@@ -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);
band->vht_cap.vht_mcs.rx_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)
......@@ -5652,6 +5725,9 @@ static int brcmf_setup_wiphybands(struct wiphy *wiphy)
int err;
s32 i;
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);
err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
......@@ -5680,6 +5756,14 @@ static int brcmf_setup_wiphybands(struct wiphy *wiphy)
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);
for (i = 0; i < ARRAY_SIZE(wiphy->bands); i++) {
band = wiphy->bands[i];
......@@ -5689,7 +5773,8 @@ static int brcmf_setup_wiphybands(struct wiphy *wiphy)
if (nmode)
brcmf_update_ht_cap(band, bw_cap, nchain);
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;
......@@ -6014,7 +6099,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
brcmf_dbg(INFO, "power save set to %s\n",
(power_mode ? "enabled" : "disabled"));
err = brcmf_dongle_roam(ifp, WL_BEACON_TIMEOUT);
err = brcmf_dongle_roam(ifp);
if (err)
goto default_conf_out;
err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype,
......
......@@ -28,7 +28,6 @@
#define WL_EXTRA_BUF_MAX 2048
#define WL_ROAM_TRIGGER_LEVEL -75
#define WL_ROAM_DELTA 20
#define WL_BEACON_TIMEOUT 3
#define WL_SCAN_CHANNEL_TIME 40
#define WL_SCAN_UNASSOC_TIME 40
......@@ -77,6 +76,9 @@
#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
......@@ -124,13 +126,11 @@ struct brcmf_cfg80211_security {
/**
* struct brcmf_cfg80211_profile - profile information.
*
* @ssid: ssid of associated/associating ap.
* @bssid: bssid of joined/joining ibss.
* @sec: security information.
* @key: key information
*/
struct brcmf_cfg80211_profile {
struct brcmf_ssid ssid;
u8 bssid[ETH_ALEN];
struct brcmf_cfg80211_security sec;
struct brcmf_wsec_key key[BRCMF_MAX_DEFAULT_KEYS];
......@@ -180,7 +180,6 @@ struct vif_saved_ie {
* @ifp: lower layer interface pointer
* @wdev: wireless device.
* @profile: profile information.
* @roam_off: roaming state.
* @sme_state: SME state using enum brcmf_vif_status bits.
* @pm_block: power-management blocked.
* @list: linked list.
......@@ -191,7 +190,6 @@ struct brcmf_cfg80211_vif {
struct brcmf_if *ifp;
struct wireless_dev wdev;
struct brcmf_cfg80211_profile profile;
s32 roam_off;
unsigned long sme_state;
bool pm_block;
struct vif_saved_ie saved_ie;
......@@ -233,7 +231,7 @@ struct escan_info {
struct wiphy *wiphy;
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);
};
/**
......
......@@ -681,6 +681,7 @@ static u32 brcmf_chip_tcm_rambase(struct brcmf_chip_priv *ci)
case BRCM_CC_43569_CHIP_ID:
case BRCM_CC_43570_CHIP_ID:
case BRCM_CC_4358_CHIP_ID:
case BRCM_CC_4359_CHIP_ID:
case BRCM_CC_43602_CHIP_ID:
case BRCM_CC_4371_CHIP_ID:
return 0x180000;
......
......@@ -29,7 +29,6 @@
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_UNASSOC_TIME 40
......@@ -107,26 +106,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
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) */
join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
join_pref_params[0].len = 2;
......@@ -174,6 +153,9 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
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 */
err = brcmf_bus_preinit(ifp->drvr->bus_if);
done:
......
......@@ -66,20 +66,13 @@ static int brcmf_p2p_enable;
module_param_named(p2pon, brcmf_p2p_enable, int, 0);
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) {
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);
if (!ifp)
return "<if_null>";
}
if (drvr->iflist[ifidx]->ndev)
return drvr->iflist[ifidx]->ndev->name;
if (ifp->ndev)
return ifp->ndev->name;
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 *ifp;
s32 bssidx;
s32 bsscfgidx;
if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) {
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;
bssidx = drvr->if2bss[ifidx];
if (bssidx >= 0)
ifp = drvr->iflist[bssidx];
bsscfgidx = drvr->if2bss[ifidx];
if (bsscfgidx >= 0)
ifp = drvr->iflist[bsscfgidx];
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);
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
ndev = ifp->ndev;
......@@ -175,7 +168,7 @@ _brcmf_set_mac_address(struct work_struct *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,
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 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? */
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;
}
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 */
if (skb_headroom(skb) < drvr->hdrlen) {
struct sk_buff *skb2;
brcmf_dbg(INFO, "%s: insufficient headroom\n",
brcmf_ifname(drvr, ifp->bssidx));
brcmf_ifname(ifp));
drvr->bus_if->tx_realloc++;
skb2 = skb_realloc_headroom(skb, drvr->hdrlen);
dev_kfree_skb(skb);
skb = skb2;
if (skb == NULL) {
brcmf_err("%s: skb_realloc_headroom failed\n",
brcmf_ifname(drvr, ifp->bssidx));
brcmf_ifname(ifp));
ret = -ENOMEM;
goto done;
}
......@@ -282,8 +267,8 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp,
if (!ifp || !ifp->ndev)
return;
brcmf_dbg(TRACE, "enter: idx=%d stop=0x%X reason=%d state=%d\n",
ifp->bssidx, ifp->netif_stop, reason, state);
brcmf_dbg(TRACE, "enter: bsscfgidx=%d stop=0x%X reason=%d state=%d\n",
ifp->bsscfgidx, ifp->netif_stop, reason, state);
spin_lock_irqsave(&ifp->netif_stop_lock, flags);
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);
brcmf_dbg(TRACE, "Enter, idx=%d\n", ifp->bssidx);
brcmf_dbg(TRACE, "Enter, bsscfgidx=%d\n", ifp->bsscfgidx);
return &ifp->stats;
}
......@@ -631,7 +616,7 @@ static int brcmf_netdev_stop(struct net_device *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);
......@@ -647,7 +632,7 @@ static int brcmf_netdev_open(struct net_device *ndev)
struct brcmf_bus *bus_if = drvr->bus_if;
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_if->state != BRCMF_BUS_UP) {
......@@ -689,7 +674,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
struct net_device *ndev;
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);
ndev = ifp->ndev;
......@@ -721,7 +706,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked)
return 0;
fail:
drvr->iflist[ifp->bssidx] = NULL;
drvr->iflist[ifp->bsscfgidx] = NULL;
ndev->netdev_ops = NULL;
free_netdev(ndev);
return -EBADE;
......@@ -739,7 +724,8 @@ void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on)
{
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;
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;
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);
ndev = ifp->ndev;
......@@ -805,34 +791,35 @@ static int brcmf_net_p2p_attach(struct brcmf_if *ifp)
return 0;
fail:
ifp->drvr->iflist[ifp->bssidx] = NULL;
ifp->drvr->iflist[ifp->bsscfgidx] = NULL;
ndev->netdev_ops = NULL;
free_netdev(ndev);
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)
{
struct brcmf_if *ifp;
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
* in case we missed the BRCMF_E_IF_DEL event.
*/
if (ifp) {
brcmf_err("ERROR: netdev:%s already exists\n",
ifp->ndev->name);
if (ifidx) {
brcmf_err("ERROR: netdev:%s already exists\n",
ifp->ndev->name);
netif_stop_queue(ifp->ndev);
brcmf_net_detach(ifp->ndev);
drvr->iflist[bssidx] = NULL;
drvr->iflist[bsscfgidx] = NULL;
} else {
brcmf_err("ignore IF event\n");
brcmf_dbg(INFO, "netdev:%s ignore IF event\n",
ifp->ndev->name);
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;
ifp = netdev_priv(ndev);
ifp->ndev = ndev;
/* store mapping ifidx to bssidx */
/* store mapping ifidx to bsscfgidx */
if (drvr->if2bss[ifidx] == BRCMF_BSSIDX_INVALID)
drvr->if2bss[ifidx] = bssidx;
drvr->if2bss[ifidx] = bsscfgidx;
}
ifp->drvr = drvr;
drvr->iflist[bssidx] = ifp;
drvr->iflist[bsscfgidx] = ifp;
ifp->ifidx = ifidx;
ifp->bssidx = bssidx;
ifp->bsscfgidx = bsscfgidx;
init_waitqueue_head(&ifp->pend_8021x_wait);
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;
}
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;
ifp = drvr->iflist[bssidx];
drvr->iflist[bssidx] = NULL;
ifp = drvr->iflist[bsscfgidx];
drvr->iflist[bsscfgidx] = NULL;
if (!ifp) {
brcmf_err("Null interface, idx=%d\n", bssidx);
brcmf_err("Null interface, bsscfgidx=%d\n", bsscfgidx);
return;
}
brcmf_dbg(TRACE, "Enter, idx=%d, ifidx=%d\n", bssidx, ifp->ifidx);
if (drvr->if2bss[ifp->ifidx] == bssidx)
brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", bsscfgidx,
ifp->ifidx);
if (drvr->if2bss[ifp->ifidx] == bsscfgidx)
drvr->if2bss[ifp->ifidx] = BRCMF_BSSIDX_INVALID;
if (ifp->ndev) {
if (bssidx == 0) {
if (bsscfgidx == 0) {
if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) {
rtnl_lock();
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)
{
if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bssidx] != ifp))
if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bsscfgidx] != ifp))
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);
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)
......@@ -940,10 +928,10 @@ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr)
highest = 2;
for (ifidx = 0; ifidx < BRCMF_MAX_IFS; ifidx++) {
if (drvr->iflist[ifidx]) {
if (drvr->iflist[ifidx]->bssidx == bsscfgidx)
if (drvr->iflist[ifidx]->bsscfgidx == bsscfgidx)
bsscfgidx = highest + 1;
else if (drvr->iflist[ifidx]->bssidx > highest)
highest = drvr->iflist[ifidx]->bssidx;
else if (drvr->iflist[ifidx]->bsscfgidx > highest)
highest = drvr->iflist[ifidx]->bsscfgidx;
} else {
available = true;
}
......@@ -1095,6 +1083,8 @@ int brcmf_bus_start(struct device *dev)
brcmf_net_detach(ifp->ndev);
if (p2p_ifp)
brcmf_net_detach(p2p_ifp->ndev);
drvr->iflist[0] = NULL;
drvr->iflist[1] = NULL;
return ret;
}
return 0;
......
......@@ -174,7 +174,7 @@ enum brcmf_netif_stop_reason {
* @multicast_work: worker object for multicast provisioning.
* @fws_desc: interface specific firmware-signalling descriptor.
* @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.
* @netif_stop: bitmap indicates reason why netif queues are stopped.
* @netif_stop_lock: spinlock for update netif_stop from multiple sources.
......@@ -190,7 +190,7 @@ struct brcmf_if {
struct work_struct multicast_work;
struct brcmf_fws_mac_descriptor *fws_desc;
int ifidx;
s32 bssidx;
s32 bsscfgidx;
u8 mac_addr[ETH_ALEN];
u8 netif_stop;
spinlock_t netif_stop_lock;
......@@ -205,10 +205,10 @@ struct brcmf_skb_reorder_data {
int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
/* 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);
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);
void brcmf_remove_interface(struct brcmf_if *ifp);
int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
......
......@@ -49,7 +49,7 @@ static int brcmf_debug_psm_watchdog_notify(struct brcmf_if *ifp,
const struct brcmf_event_msg *evtmsg,
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,
evtmsg->datalen);
......
......@@ -17,6 +17,8 @@
#ifndef BRCMFMAC_DEBUG_H
#define BRCMFMAC_DEBUG_H
#include <linux/net.h> /* net_ratelimit() */
/* message levels */
#define BRCMF_TRACE_VAL 0x00000002
#define BRCMF_INFO_VAL 0x00000004
......
......@@ -137,6 +137,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
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_get(ifp, BRCMF_FEAT_P2P, "p2p");
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_RSDB, "rsdb_mode");
if (brcmf_feature_disable) {
brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",
......
......@@ -24,13 +24,16 @@
* PNO: preferred network offload.
* WOWL: Wake-On-WLAN.
* P2P: peer-to-peer
* RSDB: Real Simultaneous Dual Band
*/
#define BRCMF_FEAT_LIST \
BRCMF_FEAT_DEF(MBSS) \
BRCMF_FEAT_DEF(MCHAN) \
BRCMF_FEAT_DEF(PNO) \
BRCMF_FEAT_DEF(WOWL) \
BRCMF_FEAT_DEF(P2P)
BRCMF_FEAT_DEF(P2P) \
BRCMF_FEAT_DEF(RSDB)
/*
* Quirks:
*
......
......@@ -28,9 +28,9 @@
#define BRCMF_FW_NVRAM_DEVPATH_LEN 19 /* devpath0=pcie/1/4/ */
#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,
BRCMF_FW_PATH_LEN, 0440);
BRCMF_FW_NAME_LEN, 0440);
enum nvram_parser_state {
IDLE,
......@@ -449,8 +449,7 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
if (raw_nvram)
bcm47xx_nvram_release_contents(data);
if (fw)
release_firmware(fw);
release_firmware(fw);
if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
goto fail;
......@@ -540,3 +539,43 @@ int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
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;
}
......@@ -21,11 +21,51 @@
#define BRCMF_FW_REQ_FLAGS 0x00F0
#define BRCMF_FW_REQ_NV_OPTIONAL 0x0010
#define BRCMF_FW_PATH_LEN 256
#define BRCMF_FW_NAME_LEN 32
#define BRCMF_FW_NAME_LEN 320
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);
/*
* Request firmware(s) asynchronously. When the asynchronous request
......
......@@ -182,8 +182,8 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr,
bool is_p2pdev;
int err = 0;
brcmf_dbg(EVENT, "action: %u idx: %u bsscfg: %u flags: %u role: %u\n",
ifevent->action, ifevent->ifidx, ifevent->bssidx,
brcmf_dbg(EVENT, "action: %u ifidx: %u bsscfgidx: %u flags: %u role: %u\n",
ifevent->action, ifevent->ifidx, ifevent->bsscfgidx,
ifevent->flags, ifevent->role);
/* 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;
}
ifp = drvr->iflist[ifevent->bssidx];
ifp = drvr->iflist[ifevent->bsscfgidx];
if (ifevent->action == BRCMF_E_IF_ADD) {
brcmf_dbg(EVENT, "adding %s (%pM)\n", emsg->ifname,
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);
if (IS_ERR(ifp))
return;
......
......@@ -219,7 +219,7 @@ struct brcmf_if_event {
u8 ifidx;
u8 action;
u8 flags;
u8 bssidx;
u8 bsscfgidx;
u8 role;
};
......
......@@ -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_fil_get_errstr((u32)(-err)), err);
return -EBADE;
return err;
}
s32
......@@ -293,22 +294,22 @@ brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data)
}
static u32
brcmf_create_bsscfg(s32 bssidx, char *name, char *data, u32 datalen, char *buf,
u32 buflen)
brcmf_create_bsscfg(s32 bsscfgidx, char *name, char *data, u32 datalen,
char *buf, u32 buflen)
{
const s8 *prefix = "bsscfg:";
s8 *p;
u32 prefixlen;
u32 namelen;
u32 iolen;
__le32 bssidx_le;
__le32 bsscfgidx_le;
if (bssidx == 0)
if (bsscfgidx == 0)
return brcmf_create_iovar(name, data, datalen, buf, buflen);
prefixlen = strlen(prefix);
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) {
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;
/* bss config index as first data */
bssidx_le = cpu_to_le32(bssidx);
memcpy(p, &bssidx_le, sizeof(bssidx_le));
p += sizeof(bssidx_le);
bsscfgidx_le = cpu_to_le32(bsscfgidx);
memcpy(p, &bsscfgidx_le, sizeof(bsscfgidx_le));
p += sizeof(bsscfgidx_le);
/* parameter buffer follows */
if (datalen)
......@@ -347,12 +348,12 @@ brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name,
mutex_lock(&drvr->proto_block);
brcmf_dbg(FIL, "ifidx=%d, bssidx=%d, name=%s, len=%d\n", ifp->ifidx,
ifp->bssidx, name, len);
brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d\n", ifp->ifidx,
ifp->bsscfgidx, name, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
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));
if (buflen) {
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);
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));
if (buflen) {
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;
brcmf_err("Creating bsscfg failed\n");
}
brcmf_dbg(FIL, "ifidx=%d, bssidx=%d, name=%s, len=%d\n", ifp->ifidx,
ifp->bssidx, name, len);
brcmf_dbg(FIL, "ifidx=%d, bsscfgidx=%d, name=%s, len=%d\n", ifp->ifidx,
ifp->bsscfgidx, name, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
......
......@@ -121,6 +121,11 @@
#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 */
enum brcmf_join_pref_types {
BRCMF_JOIN_PREF_RSSI = 1,
......@@ -170,7 +175,7 @@ struct brcmf_fil_af_params_le {
};
struct brcmf_fil_bss_enable_le {
__le32 bsscfg_idx;
__le32 bsscfgidx;
__le32 enable;
};
......@@ -282,14 +287,9 @@ struct brcm_rateset_le {
u8 rates[BRCMF_MAXRATES_IN_SET];
};
struct brcmf_ssid {
u32 SSID_len;
unsigned char SSID[32];
};
struct brcmf_ssid_le {
__le32 SSID_len;
unsigned char SSID[32];
unsigned char SSID[IEEE80211_MAX_SSID_LEN];
};
struct brcmf_scan_params_le {
......@@ -634,4 +634,16 @@ struct brcmf_assoclist_le {
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_ */
......@@ -719,7 +719,7 @@ static void brcmf_fws_macdesc_init(struct brcmf_fws_mac_descriptor *desc,
desc->state = BRCMF_FWS_STATE_OPEN;
desc->requested_credit = 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->ac_bitmap = 0xff; /* update this when handling APSD */
if (addr)
......@@ -1938,7 +1938,7 @@ void brcmf_fws_reset_interface(struct brcmf_if *ifp)
{
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)
return;
......
......@@ -625,11 +625,10 @@ static int brcmf_p2p_enable_discovery(struct brcmf_p2p_info *p2p)
* @num_chans: number of channels to scan.
* @chanspecs: channel parameters for @num_chans channels.
* @search_state: P2P discover state to use.
* @action: scan action to pass to firmware.
* @bss_type: type of P2P bss.
*/
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)
{
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_p2p_scan_le *p2p_params;
struct brcmf_scan_params_le *sparams;
struct brcmf_ssid ssid;
memsize += num_chans * sizeof(__le16);
memblk = kzalloc(memsize, GFP_KERNEL);
......@@ -655,16 +653,16 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
ret = -EINVAL;
goto exit;
}
p2p_params = (struct brcmf_p2p_scan_le *)memblk;
sparams = &p2p_params->eparams.params_le;
switch (search_state) {
case WL_P2P_DISC_ST_SEARCH:
/*
* 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;
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
* setting SSID.
*/
ssid.SSID_len = BRCMF_P2P_WILDCARD_SSID_LEN;
memcpy(ssid.SSID, BRCMF_P2P_WILDCARD_SSID, ssid.SSID_len);
sparams->ssid_le.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;
default:
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.
*/
p2p_params = (struct brcmf_p2p_scan_le *)memblk;
p2p_params->type = 'E';
/* determine the scan engine parameters */
sparams = &p2p_params->eparams.params_le;
sparams->bss_type = DOT11_BSSTYPE_ANY;
if (p2p->cfg->active_scan)
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;
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);
/*
......@@ -742,7 +737,7 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
/* set the escan specific parameters */
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);
/* perform p2p scan on primary device */
ret = brcmf_fil_bsscfg_data_set(vif->ifp, "p2p_scan", memblk, memsize);
......@@ -766,8 +761,7 @@ static s32 brcmf_p2p_escan(struct brcmf_p2p_info *p2p, u32 num_chans,
*/
static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
struct brcmf_if *ifp,
struct cfg80211_scan_request *request,
u16 action)
struct cfg80211_scan_request *request)
{
struct brcmf_p2p_info *p2p = &cfg->p2p;
s32 err = 0;
......@@ -827,7 +821,7 @@ static s32 brcmf_p2p_run_escan(struct brcmf_cfg80211_info *cfg,
num_nodfs++;
}
err = brcmf_p2p_escan(p2p, num_nodfs, chanspecs, search_state,
action, P2PAPI_BSSCFG_DEVICE);
P2PAPI_BSSCFG_DEVICE);
kfree(chanspecs);
}
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;
}
err = brcmf_p2p_escan(p2p, channel_cnt, default_chan_list,
WL_P2P_DISC_ST_SEARCH, WL_ESCAN_ACTION_START,
P2PAPI_BSSCFG_DEVICE);
WL_P2P_DISC_ST_SEARCH, P2PAPI_BSSCFG_DEVICE);
kfree(default_chan_list);
exit:
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 *pri_ifp;
int err;
u32 bssidx;
u32 bsscfgidx;
if (p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
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));
/* 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) {
brcmf_err("retrieving discover bsscfg index failed\n");
goto fail;
}
WARN_ON(p2p_ifp->bssidx != bssidx);
WARN_ON(p2p_ifp->bsscfgidx != bsscfgidx);
init_completion(&p2p->send_af_done);
INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
......
......@@ -112,7 +112,6 @@ struct afx_hdl {
* @int_addr: P2P interface address.
* @bss_idx: informate for P2P bss types.
* @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.
* @remain_on_channel: contains copy of struct used by cfg80211.
* @remain_on_channel_cookie: cookie counter for remain on channel cmd
......@@ -133,7 +132,6 @@ struct brcmf_p2p_info {
u8 int_addr[ETH_ALEN];
struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX];
struct timer_list listen_timer;
struct brcmf_ssid ssid;
u8 listen_channel;
struct ieee80211_channel remain_on_channel;
u32 remain_on_channel_cookie;
......
......@@ -44,23 +44,29 @@ enum brcmf_pcie_state {
BRCMFMAC_PCIE_STATE_UP
};
#define BRCMF_PCIE_43602_FW_NAME "brcm/brcmfmac43602-pcie.bin"
#define BRCMF_PCIE_43602_NVRAM_NAME "brcm/brcmfmac43602-pcie.txt"
#define BRCMF_PCIE_4350_FW_NAME "brcm/brcmfmac4350-pcie.bin"
#define BRCMF_PCIE_4350_NVRAM_NAME "brcm/brcmfmac4350-pcie.txt"
#define BRCMF_PCIE_4356_FW_NAME "brcm/brcmfmac4356-pcie.bin"
#define BRCMF_PCIE_4356_NVRAM_NAME "brcm/brcmfmac4356-pcie.txt"
#define BRCMF_PCIE_43570_FW_NAME "brcm/brcmfmac43570-pcie.bin"
#define BRCMF_PCIE_43570_NVRAM_NAME "brcm/brcmfmac43570-pcie.txt"
#define BRCMF_PCIE_4358_FW_NAME "brcm/brcmfmac4358-pcie.bin"
#define BRCMF_PCIE_4358_NVRAM_NAME "brcm/brcmfmac4358-pcie.txt"
#define BRCMF_PCIE_4365_FW_NAME "brcm/brcmfmac4365b-pcie.bin"
#define BRCMF_PCIE_4365_NVRAM_NAME "brcm/brcmfmac4365b-pcie.txt"
#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"
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");
static struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43602_CHIP_ID, 0xFFFFFFFF, 43602),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4350_CHIP_ID, 0xFFFFFFFF, 4350),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4356_CHIP_ID, 0xFFFFFFFF, 4356),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43567_CHIP_ID, 0xFFFFFFFF, 43570),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43569_CHIP_ID, 0xFFFFFFFF, 43570),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43570_CHIP_ID, 0xFFFFFFFF, 43570),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4358_CHIP_ID, 0xFFFFFFFF, 4358),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4359_CHIP_ID, 0xFFFFFFFF, 4359),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4365_CHIP_ID, 0xFFFFFFFF, 4365B),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4366_CHIP_ID, 0xFFFFFFFF, 4366B),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4371_CHIP_ID, 0xFFFFFFFF, 4371),
};
#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
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 {
u32 base_addr;
u32 buf_addr;
......@@ -253,10 +241,9 @@ struct brcmf_pcie_core_info {
struct brcmf_pciedev_info {
enum brcmf_pcie_state state;
bool in_irq;
bool irq_requested;
struct pci_dev *pdev;
char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
char fw_name[BRCMF_FW_NAME_LEN];
char nvram_name[BRCMF_FW_NAME_LEN];
void __iomem *regs;
void __iomem *tcm;
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);
}
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");
/* is it a v1 or v2 implementation */
devinfo->irq_requested = false;
pci_enable_msi(pdev);
if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) {
if (request_threaded_irq(pdev->irq,
......@@ -908,7 +896,6 @@ static int brcmf_pcie_request_irq(struct brcmf_pciedev_info *devinfo)
return -EIO;
}
}
devinfo->irq_requested = true;
devinfo->irq_allocated = true;
return 0;
}
......@@ -926,9 +913,6 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
pdev = devinfo->pdev;
brcmf_pcie_intr_disable(devinfo);
if (!devinfo->irq_requested)
return;
devinfo->irq_requested = false;
free_irq(pdev->irq, devinfo);
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);
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,
.stop = brcmf_pcie_down,
.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,
const struct firmware *fw, void *nvram,
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);
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)
goto fail_bus;
......@@ -1959,15 +1868,14 @@ brcmf_pcie_remove(struct pci_dev *pdev)
#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_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;
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");
return -EIO;
}
brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM_IN_USE);
err = pci_save_state(pdev);
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;
}
devinfo->state = BRCMFMAC_PCIE_STATE_DOWN;
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_bus *bus;
struct pci_dev *pdev;
int err;
bus = dev_get_drvdata(&pdev->dev);
brcmf_dbg(PCIE, "Enter, pdev=%p, bus=%p\n", pdev, bus);
brcmf_err("Enter\n");
err = pci_set_power_state(pdev, PCI_D0);
if (err) {
brcmf_err("pci_set_power_state failed, err=%d\n", err);
goto cleanup;
}
pci_restore_state(pdev);
pci_enable_wake(pdev, PCI_D3hot, false);
pci_enable_wake(pdev, PCI_D3cold, false);
bus = dev_get_drvdata(dev);
devinfo = bus->bus_priv.pcie->devinfo;
brcmf_dbg(PCIE, "Enter, dev=%p, bus=%p\n", dev, bus);
/* Check if device is still up and running, if so we are ready */
if (bus) {
devinfo = bus->bus_priv.pcie->devinfo;
if (brcmf_pcie_read_reg32(devinfo,
BRCMF_PCIE_PCIE2REG_INTMASK) != 0) {
if (brcmf_pcie_send_mb_data(devinfo,
BRCMF_H2D_HOST_D0_INFORM))
goto cleanup;
brcmf_dbg(PCIE, "Hot resume, continue....\n");
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
brcmf_bus_change_state(bus, BRCMF_BUS_UP);
brcmf_pcie_intr_enable(devinfo);
return 0;
}
if (brcmf_pcie_read_reg32(devinfo, BRCMF_PCIE_PCIE2REG_INTMASK) != 0) {
brcmf_dbg(PCIE, "Try to wakeup device....\n");
if (brcmf_pcie_send_mb_data(devinfo, BRCMF_H2D_HOST_D0_INFORM))
goto cleanup;
brcmf_dbg(PCIE, "Hot resume, continue....\n");
devinfo->state = BRCMFMAC_PCIE_STATE_UP;
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
brcmf_bus_change_state(bus, BRCMF_BUS_UP);
brcmf_pcie_intr_enable(devinfo);
return 0;
}
cleanup:
if (bus) {
devinfo = bus->bus_priv.pcie->devinfo;
brcmf_chip_detach(devinfo->ci);
devinfo->ci = NULL;
brcmf_pcie_remove(pdev);
}
brcmf_chip_detach(devinfo->ci);
devinfo->ci = NULL;
pdev = devinfo->pdev;
brcmf_pcie_remove(pdev);
err = brcmf_pcie_probe(pdev, NULL);
if (err)
brcmf_err("probe after resume failed, err=%d\n", err);
......@@ -2046,6 +1937,14 @@ static int brcmf_pcie_resume(struct pci_dev *pdev)
}
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 */
......@@ -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_43570_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_2G_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,
.remove = brcmf_pcie_remove,
#ifdef CONFIG_PM
.suspend = brcmf_pcie_suspend,
.resume = brcmf_pcie_resume
#endif /* CONFIG_PM */
.driver.pm = &brcmf_pciedrvr_pm,
#endif
};
......
......@@ -460,7 +460,6 @@ struct brcmf_sdio {
struct sk_buff *glomd; /* Packet containing glomming descriptor */
struct sk_buff_head glom; /* Packet list for glommed superframe */
uint glomerr; /* Glom packet read errors */
u8 *rxbuf; /* Buffer for receiving control packets */
uint rxblen; /* Allocated length of rxbuf */
......@@ -597,136 +596,41 @@ static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
{4, 0x1}
};
#define BCM43143_FIRMWARE_NAME "brcm/brcmfmac43143-sdio.bin"
#define BCM43143_NVRAM_NAME "brcm/brcmfmac43143-sdio.txt"
#define BCM43241B0_FIRMWARE_NAME "brcm/brcmfmac43241b0-sdio.bin"
#define BCM43241B0_NVRAM_NAME "brcm/brcmfmac43241b0-sdio.txt"
#define BCM43241B4_FIRMWARE_NAME "brcm/brcmfmac43241b4-sdio.bin"
#define BCM43241B4_NVRAM_NAME "brcm/brcmfmac43241b4-sdio.txt"
#define BCM43241B5_FIRMWARE_NAME "brcm/brcmfmac43241b5-sdio.bin"
#define BCM43241B5_NVRAM_NAME "brcm/brcmfmac43241b5-sdio.txt"
#define BCM4329_FIRMWARE_NAME "brcm/brcmfmac4329-sdio.bin"
#define BCM4329_NVRAM_NAME "brcm/brcmfmac4329-sdio.txt"
#define BCM4330_FIRMWARE_NAME "brcm/brcmfmac4330-sdio.bin"
#define BCM4330_NVRAM_NAME "brcm/brcmfmac4330-sdio.txt"
#define BCM4334_FIRMWARE_NAME "brcm/brcmfmac4334-sdio.bin"
#define BCM4334_NVRAM_NAME "brcm/brcmfmac4334-sdio.txt"
#define BCM43340_FIRMWARE_NAME "brcm/brcmfmac43340-sdio.bin"
#define BCM43340_NVRAM_NAME "brcm/brcmfmac43340-sdio.txt"
#define BCM4335_FIRMWARE_NAME "brcm/brcmfmac4335-sdio.bin"
#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);
MODULE_FIRMWARE(BCM43143_NVRAM_NAME);
MODULE_FIRMWARE(BCM43241B0_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM43241B0_NVRAM_NAME);
MODULE_FIRMWARE(BCM43241B4_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM43241B4_NVRAM_NAME);
MODULE_FIRMWARE(BCM43241B5_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM43241B5_NVRAM_NAME);
MODULE_FIRMWARE(BCM4329_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM4329_NVRAM_NAME);
MODULE_FIRMWARE(BCM4330_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM4330_NVRAM_NAME);
MODULE_FIRMWARE(BCM4334_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM4334_NVRAM_NAME);
MODULE_FIRMWARE(BCM43340_FIRMWARE_NAME);
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;
BRCMF_FW_NVRAM_DEF(43143, "brcmfmac43143-sdio.bin", "brcmfmac43143-sdio.txt");
BRCMF_FW_NVRAM_DEF(43241B0, "brcmfmac43241b0-sdio.bin",
"brcmfmac43241b0-sdio.txt");
BRCMF_FW_NVRAM_DEF(43241B4, "brcmfmac43241b4-sdio.bin",
"brcmfmac43241b4-sdio.txt");
BRCMF_FW_NVRAM_DEF(43241B5, "brcmfmac43241b5-sdio.bin",
"brcmfmac43241b5-sdio.txt");
BRCMF_FW_NVRAM_DEF(4329, "brcmfmac4329-sdio.bin", "brcmfmac4329-sdio.txt");
BRCMF_FW_NVRAM_DEF(4330, "brcmfmac4330-sdio.bin", "brcmfmac4330-sdio.txt");
BRCMF_FW_NVRAM_DEF(4334, "brcmfmac4334-sdio.bin", "brcmfmac4334-sdio.txt");
BRCMF_FW_NVRAM_DEF(43340, "brcmfmac43340-sdio.bin", "brcmfmac43340-sdio.txt");
BRCMF_FW_NVRAM_DEF(4335, "brcmfmac4335-sdio.bin", "brcmfmac4335-sdio.txt");
BRCMF_FW_NVRAM_DEF(43362, "brcmfmac43362-sdio.bin", "brcmfmac43362-sdio.txt");
BRCMF_FW_NVRAM_DEF(4339, "brcmfmac4339-sdio.bin", "brcmfmac4339-sdio.txt");
BRCMF_FW_NVRAM_DEF(43430, "brcmfmac43430-sdio.bin", "brcmfmac43430-sdio.txt");
BRCMF_FW_NVRAM_DEF(43455, "brcmfmac43455-sdio.bin", "brcmfmac43455-sdio.txt");
BRCMF_FW_NVRAM_DEF(4354, "brcmfmac4354-sdio.bin", "brcmfmac4354-sdio.txt");
static struct brcmf_firmware_mapping brcmf_sdio_fwnames[] = {
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, 43143),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0x0000001F, 43241B0),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0x00000020, 43241B4),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43241_CHIP_ID, 0xFFFFFFC0, 43241B5),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, 4329),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, 4330),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, 4334),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, 43340),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, 4335),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, 43362),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, 4339),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_43430_CHIP_ID, 0xFFFFFFFF, 43430),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4345_CHIP_ID, 0xFFFFFFC0, 43455),
BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, 4354)
};
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)
{
uint datalign;
......@@ -1654,20 +1558,15 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)
sdio_release_host(bus->sdiodev->func[1]);
bus->sdcnt.f2rxdata++;
/* On failure, kill the superframe, allow a couple retries */
/* On failure, kill the superframe */
if (errcode < 0) {
brcmf_err("glom read of %d bytes failed: %d\n",
dlen, errcode);
sdio_claim_host(bus->sdiodev->func[1]);
if (bus->glomerr++ < 3) {
brcmf_sdio_rxfail(bus, true, true);
} else {
bus->glomerr = 0;
brcmf_sdio_rxfail(bus, true, false);
bus->sdcnt.rxglomfail++;
brcmf_sdio_free_glom(bus);
}
brcmf_sdio_rxfail(bus, true, false);
bus->sdcnt.rxglomfail++;
brcmf_sdio_free_glom(bus);
sdio_release_host(bus->sdiodev->func[1]);
return 0;
}
......@@ -1708,19 +1607,11 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)
}
if (errcode) {
/* Terminate frame on error, request
a couple retries */
/* Terminate frame on error */
sdio_claim_host(bus->sdiodev->func[1]);
if (bus->glomerr++ < 3) {
/* Restore superframe header space */
skb_push(pfirst, sfdoff);
brcmf_sdio_rxfail(bus, true, true);
} else {
bus->glomerr = 0;
brcmf_sdio_rxfail(bus, true, false);
bus->sdcnt.rxglomfail++;
brcmf_sdio_free_glom(bus);
}
brcmf_sdio_rxfail(bus, true, false);
bus->sdcnt.rxglomfail++;
brcmf_sdio_free_glom(bus);
sdio_release_host(bus->sdiodev->func[1]);
bus->cur_read.len = 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,
.preinit = brcmf_sdio_bus_preinit,
.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_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)
goto fail;
......
......@@ -195,8 +195,8 @@ struct brcmf_sdio_dev {
uint max_segment_size;
uint txglomsz;
struct sg_table sgtable;
char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
char fw_name[BRCMF_FW_NAME_LEN];
char nvram_name[BRCMF_FW_NAME_LEN];
bool wowl_enabled;
enum brcmf_sdiod_state state;
struct brcmf_sdiod_freezer *freezer;
......
......@@ -43,10 +43,20 @@
#define BRCMF_USB_CBCTL_READ 1
#define BRCMF_USB_MAX_PKT_SIZE 1600
#define BRCMF_USB_43143_FW_NAME "brcm/brcmfmac43143.bin"
#define BRCMF_USB_43236_FW_NAME "brcm/brcmfmac43236b.bin"
#define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin"
#define BRCMF_USB_43569_FW_NAME "brcm/brcmfmac43569.bin"
BRCMF_FW_DEF(43143, "brcmfmac43143.bin");
BRCMF_FW_DEF(43236B, "brcmfmac43236b.bin");
BRCMF_FW_DEF(43242A, "brcmfmac43242a.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_MAX_OFFSET 3 /* Max number of file offsets */
......@@ -139,6 +149,7 @@ struct brcmf_usbdev_info {
struct brcmf_usbreq *tx_reqs;
struct brcmf_usbreq *rx_reqs;
char fw_name[BRCMF_FW_NAME_LEN];
const u8 *image; /* buffer for combine fw and nvram */
int image_len;
......@@ -983,45 +994,15 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
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
brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
{
int devid, chiprev;
int err;
brcmf_dbg(USB, "Enter\n");
if (devinfo == NULL)
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) {
brcmf_err("No firmware!\n");
return -ENOENT;
......@@ -1071,25 +1052,6 @@ static int check_file(const u8 *headers)
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
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);
}
static struct brcmf_bus_ops brcmf_usb_bus_ops = {
static const struct brcmf_bus_ops brcmf_usb_bus_ops = {
.txdata = brcmf_usb_tx,
.stop = brcmf_usb_down,
.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->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 */
ret = brcmf_fw_get_firmwares(dev, 0, brcmf_usb_get_fwname(devinfo),
NULL, brcmf_usb_probe_phase2);
ret = brcmf_fw_get_firmwares(dev, 0, devinfo->fw_name, NULL,
brcmf_usb_probe_phase2);
if (ret) {
brcmf_err("firmware request failed: %d\n", ret);
goto fail;
......@@ -1472,8 +1441,7 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf)
brcmf_dbg(USB, "Enter\n");
return brcmf_fw_get_firmwares(&usb->dev, 0,
brcmf_usb_get_fwname(devinfo), NULL,
return brcmf_fw_get_firmwares(&usb->dev, 0, devinfo->fw_name, NULL,
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_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 = {
.name = KBUILD_MODNAME,
......@@ -1504,7 +1468,6 @@ static struct usb_driver brcmf_usbdrvr = {
.suspend = brcmf_usb_suspend,
.resume = brcmf_usb_resume,
.reset_resume = brcmf_usb_reset_resume,
.supports_autosuspend = 1,
.disable_hub_initiated_lpm = 1,
};
......
......@@ -47,6 +47,7 @@
#define BRCM_CC_43569_CHIP_ID 43569
#define BRCM_CC_43570_CHIP_ID 43570
#define BRCM_CC_4358_CHIP_ID 0x4358
#define BRCM_CC_4359_CHIP_ID 0x4359
#define BRCM_CC_43602_CHIP_ID 43602
#define BRCM_CC_4365_CHIP_ID 0x4365
#define BRCM_CC_4366_CHIP_ID 0x4366
......@@ -66,6 +67,7 @@
#define BRCM_PCIE_43567_DEVICE_ID 0x43d3
#define BRCM_PCIE_43570_DEVICE_ID 0x43d9
#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_2G_DEVICE_ID 0x43bb
#define BRCM_PCIE_43602_5G_DEVICE_ID 0x43bc
......
......@@ -5137,21 +5137,9 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) {
memset(APList_rid, 0, sizeof(*APList_rid));
APList_rid->len = cpu_to_le16(sizeof(*APList_rid));
for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) {
int j;
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;
}
}
}
for (i = 0; i < 4 && data->writelen >= (i + 1) * 6 * 3; i++)
mac_pton(data->wbuffer + i * 6 * 3, APList_rid->ap[i]);
disable_MAC(ai, 1);
writeAPListRid(ai, APList_rid, 1);
enable_MAC(ai, 1);
......
......@@ -53,7 +53,7 @@ config IWLWIFI_LEDS
config IWLDVM
tristate "Intel Wireless WiFi DVM Firmware support"
default IWLWIFI
depends on m
help
This is the driver that supports the DVM firmware. The list
of the devices that use this firmware is available here:
......
......@@ -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 += 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_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 += $(iwlwifi-m)
......
......@@ -25,7 +25,7 @@
* in the file called COPYING.
*
* 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
*
* BSD LICENSE
......
......@@ -25,7 +25,7 @@
* in the file called COPYING.
*
* 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
*
* BSD LICENSE
......
......@@ -25,7 +25,7 @@
* in the file called COPYING.
*
* 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
*
* BSD LICENSE
......
......@@ -19,7 +19,7 @@
* file called LICENSE.
*
* 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
*
*****************************************************************************/
......
......@@ -19,7 +19,7 @@
* file called LICENSE.
*
* 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
*
*****************************************************************************/
......@@ -134,8 +134,6 @@ static int iwl_led_cmd(struct iwl_priv *priv,
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,
priv->cfg->base_params->led_compensation);
led_cmd.off = iwl_blink_compensation(priv, off,
......
......@@ -22,7 +22,7 @@
* in the file called COPYING.
*
* 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
*
*****************************************************************************/
......
......@@ -1411,13 +1411,7 @@ static void iwlagn_mac_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&priv->mutex);
if (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);
}
WARN_ON(ctx->vif != vif);
ctx->vif = NULL;
iwl_teardown_interface(priv, vif, false);
......
......@@ -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.no_reclaim_cmds = 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.command_names = iwl_dvm_cmd_strings;
......
......@@ -22,7 +22,7 @@
* file called LICENSE.
*
* 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
*****************************************************************************/
......
......@@ -22,7 +22,7 @@
* file called LICENSE.
*
* 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
*****************************************************************************/
#ifndef __iwl_power_setting_h__
......
......@@ -23,7 +23,7 @@
* in the file called COPYING.
*
* 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
*
*****************************************************************************/
......
......@@ -19,7 +19,7 @@
* file called LICENSE.
*
* 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
*
*****************************************************************************/
......
......@@ -19,7 +19,7 @@
* file called LICENSE.
*
* 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
*
*****************************************************************************/
......
......@@ -19,7 +19,7 @@
* file called LICENSE.
*
* 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
*
*****************************************************************************/
......
......@@ -19,7 +19,7 @@
* file called LICENSE.
*
* 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
*
*****************************************************************************/
......
......@@ -7,6 +7,7 @@
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* 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
* 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) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH
* All rights reserved.
*
* 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,
};
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 = {
.name = "Intel(R) Dual Band Wireless AC 7265",
.fw_name_pre = IWL7265_FW_PRE,
......
......@@ -154,7 +154,6 @@ static const struct iwl_tt_params iwl8000_tt_params = {
.base_params = &iwl8000_base_params, \
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000, \
.d0i3 = true, \
.features = NETIF_F_RXCSUM, \
.non_shared_ant = ANT_A, \
.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,
};
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 = {
.name = "Intel(R) Dual Band Wireless AC 4165",
.fw_name_pre = IWL8000_FW_PRE,
......
/******************************************************************************
*
* 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));
......@@ -25,7 +25,7 @@
* in the file called COPYING.
*
* 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
*
* BSD LICENSE
......
......@@ -254,6 +254,7 @@ struct iwl_tt_params {
#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_8000 (32 * 512 * sizeof(u16)) /* 32 KB */
#define OTP_LOW_IMAGE_SIZE_FAMILY_9000 OTP_LOW_IMAGE_SIZE_FAMILY_8000
struct iwl_eeprom_params {
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.
* @host_interrupt_operation_mode: device needs host interrupt operation
* mode set
* @d0i3: device uses d0i3 instead of d3
* @nvm_hw_section_num: the ID of the HW NVM section
* @features: hw features, any combination of feature_whitelist
* @pwr_tx_backoffs: translation table between power limits and backoffs
......@@ -342,7 +342,6 @@ struct iwl_cfg {
const bool internal_wimax_coex;
const bool host_interrupt_operation_mode;
bool high_temp;
bool d0i3;
u8 nvm_hw_section_num;
bool lp_xtal_workaround;
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_n_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_2n_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 iwl8260_2n_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 iwl8260_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 /* __IWL_CONFIG_H__ */
......@@ -163,7 +163,6 @@ do { \
#define IWL_DL_FW 0x00010000
#define IWL_DL_RF_KILL 0x00020000
#define IWL_DL_FW_ERRORS 0x00040000
#define IWL_DL_LED 0x00080000
/* 0x00F00000 - 0x00100000 */
#define IWL_DL_RATE 0x00100000
#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_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_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_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)
......
......@@ -19,7 +19,7 @@
* file called LICENSE.
*
* 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
*
*****************************************************************************/
......
......@@ -19,7 +19,7 @@
* file called LICENSE.
*
* 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
*
*****************************************************************************/
......
......@@ -19,7 +19,7 @@
* file called LICENSE.
*
* 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
*
*****************************************************************************/
......
......@@ -19,7 +19,7 @@
* file called LICENSE.
*
* 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
*
*****************************************************************************/
......
......@@ -451,7 +451,9 @@ static int iwl_set_ucode_api_flags(struct iwl_drv *drv, const u8 *data,
int i;
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 */
return 0;
}
......@@ -473,7 +475,9 @@ static int iwl_set_ucode_capabilities(struct iwl_drv *drv, const u8 *data,
int i;
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 */
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);
trigger_tlv_sz[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++) {
if (pieces->dbg_trigger_tlv[i]) {
......@@ -1539,6 +1545,7 @@ struct iwl_mod_params iwlwifi_mod_params = {
.bt_coex_active = true,
.power_level = IWL_POWER_INDEX_1,
.d0i3_disable = true,
.d0i3_entry_delay = 1000,
#ifndef CONFIG_IWLWIFI_UAPSD
.uapsd_disable = true,
#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_PARM_DESC(11n_disable,
"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);
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_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_PARM_DESC(fw_monitor,
"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)");
......@@ -26,7 +26,7 @@
* in the file called COPYING.
*
* 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
*
* BSD LICENSE
......@@ -766,7 +766,7 @@ void iwl_init_ht_hw_capab(const struct iwl_cfg *cfg,
if (cfg->ht_params->ldpc)
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->ampdu_factor = cfg->max_ht_ampdu_exponent;
......
......@@ -26,7 +26,7 @@
* in the file called COPYING.
*
* 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
*
* BSD LICENSE
......
......@@ -25,7 +25,7 @@
* in the file called COPYING.
*
* 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
*
* BSD LICENSE
......
......@@ -25,7 +25,7 @@
* in the file called COPYING.
*
* 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
*
* BSD LICENSE
......
......@@ -25,7 +25,7 @@
* in the file called COPYING.
*
* 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
*
* BSD LICENSE
......
......@@ -26,7 +26,7 @@
* in the file called COPYING.
*
* 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
*
* 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
* 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 {
FW_DBG_TRIGGER_INVALID = 0,
......@@ -302,6 +305,8 @@ enum iwl_fw_dbg_trigger {
FW_DBG_TRIGGER_TXQ_TIMERS,
FW_DBG_TRIGGER_TIME_EVENT,
FW_DBG_TRIGGER_BA,
FW_DBG_TRIGGER_TX_LATENCY,
FW_DBG_TRIGGER_TDLS,
/* must be last */
FW_DBG_TRIGGER_MAX,
......
......@@ -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_EXTENDED_DTS_MEASURE: extended DTS measurement
* @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
*/
......@@ -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_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_BT_MPLUT_SUPPORT = (__force iwl_ucode_tlv_capa_t)67,
NUM_IWL_UCODE_TLV_CAPA
#ifdef __CHECKER__
......@@ -722,6 +724,19 @@ struct iwl_fw_dbg_trigger_ba {
__le16 frame_timeout;
} __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.
* @id: conf id
......
......@@ -26,7 +26,7 @@
* in the file called COPYING.
*
* 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
*
* BSD LICENSE
......@@ -305,18 +305,4 @@ iwl_fw_dbg_conf_usniffer(const struct iwl_fw *fw, u8 id)
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__ */
/******************************************************************************
*
* 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.
*
......@@ -117,18 +118,20 @@ int iwl_poll_direct_bit(struct iwl_trans *trans, u32 addr, u32 mask,
}
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);
trace_iwlwifi_dev_ioread_prph32(trans->dev, ofs, 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);
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)
{
......@@ -136,7 +139,7 @@ u32 iwl_read_prph(struct iwl_trans *trans, u32 ofs)
u32 val = 0x5a5a5a5a;
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);
}
return val;
......@@ -148,7 +151,7 @@ void iwl_write_prph(struct iwl_trans *trans, u32 ofs, u32 val)
unsigned long 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);
}
}
......@@ -174,8 +177,9 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
unsigned long flags;
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
__iwl_write_prph(trans, ofs,
__iwl_read_prph(trans, ofs) | mask);
iwl_write_prph_no_grab(trans, ofs,
iwl_read_prph_no_grab(trans, ofs) |
mask);
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;
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
__iwl_write_prph(trans, ofs,
(__iwl_read_prph(trans, ofs) & mask) | bits);
iwl_write_prph_no_grab(trans, ofs,
(iwl_read_prph_no_grab(trans, ofs) &
mask) | bits);
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;
if (iwl_trans_grab_nic_access(trans, false, &flags)) {
val = __iwl_read_prph(trans, ofs);
__iwl_write_prph(trans, ofs, (val & ~mask));
val = iwl_read_prph_no_grab(trans, ofs);
iwl_write_prph_no_grab(trans, ofs, (val & ~mask));
iwl_trans_release_nic_access(trans, &flags);
}
}
......
......@@ -21,7 +21,7 @@
* file called LICENSE.
*
* 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
*
*****************************************************************************/
......@@ -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);
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);
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);
int iwl_poll_prph_bit(struct iwl_trans *trans, u32 addr,
u32 bits, u32 mask, int timeout);
......
......@@ -86,6 +86,12 @@ enum iwl_disable_11n {
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
*
......@@ -94,7 +100,7 @@ enum iwl_disable_11n {
* @sw_crypto: using hardware encryption, default = 0
* @disable_11n: disable 11n capabilities, default = 0,
* 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
* @bt_coex_active: enable bt coex, default = true
* @led_mode: system default, default = 0
......@@ -103,13 +109,15 @@ enum iwl_disable_11n {
* @debug_level: levels are IWL_DL_*
* @ant_coupling: antenna coupling in dB, default = 0
* @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
* @fw_monitor: allow to use firmware monitor
*/
struct iwl_mod_params {
int sw_crypto;
unsigned int disable_11n;
int amsdu_size_8K;
int amsdu_size;
bool restart_fw;
bool bt_coex_active;
int led_mode;
......@@ -122,6 +130,7 @@ struct iwl_mod_params {
char *nvm_file;
bool uapsd_disable;
bool d0i3_disable;
unsigned int d0i3_entry_delay;
bool lar_disable;
bool fw_monitor;
};
......
......@@ -26,7 +26,7 @@
* in the file called COPYING.
*
* 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
*
* BSD LICENSE
......
......@@ -26,7 +26,7 @@
* in the file called COPYING.
*
* 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
*
* BSD LICENSE
......
......@@ -25,7 +25,7 @@
* in the file called COPYING.
*
* 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
*
* BSD LICENSE
......
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部