summaryrefslogtreecommitdiff
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/ath10k/Kconfig1
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c65
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h39
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c199
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h4
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h15
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c33
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c130
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h32
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c212
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c102
-rw-r--r--drivers/net/wireless/ath/ath10k/thermal.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/txrx.c15
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c19
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.h18
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c208
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h130
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c2
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c4
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_mbox.c5
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c16
-rw-r--r--drivers/net/wireless/ath/ath9k/Kconfig11
-rw-r--r--drivers/net/wireless/ath/ath9k/Makefile1
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h23
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/channel.c56
-rw-r--r--drivers/net/wireless/ath/ath9k/common-beacon.c22
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.c74
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c76
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_9287.c68
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c61
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_hst.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c11
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/rng.c107
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c23
-rw-r--r--drivers/net/wireless/ath/wcn36xx/dxe.c43
-rw-r--r--drivers/net/wireless/ath/wcn36xx/hal.h2
-rw-r--r--drivers/net/wireless/ath/wcn36xx/smd.c27
-rw-r--r--drivers/net/wireless/ath/wcn36xx/smd.h9
-rw-r--r--drivers/net/wireless/ath/wil6210/interrupt.c8
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c24
-rw-r--r--drivers/net/wireless/ath/wil6210/pcie_bus.c30
-rw-r--r--drivers/net/wireless/ath/wil6210/rx_reorder.c12
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c5
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h1
-rw-r--r--drivers/net/wireless/ath/wil6210/wil_crash_dump.c3
-rw-r--r--drivers/net/wireless/ath/wil6210/wil_platform.c3
-rw-r--r--drivers/net/wireless/ath/wil6210/wil_platform.h38
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c10
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c12
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c569
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h121
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c96
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h56
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c246
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h15
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c80
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h9
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c51
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h46
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c8
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c31
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h1
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h165
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c20
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c3
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c39
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c245
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c204
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c93
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h23
-rw-r--r--drivers/net/wireless/cisco/airo.c18
-rw-r--r--drivers/net/wireless/intel/ipw2x00/ipw2100.c11
-rw-r--r--drivers/net/wireless/intel/iwlegacy/4965-mac.c2
-rw-r--r--drivers/net/wireless/intel/iwlegacy/common.c14
-rw-r--r--drivers/net/wireless/intersil/hostap/hostap_cs.c6
-rw-r--r--drivers/net/wireless/intersil/prism54/isl_ioctl.c2
-rw-r--r--drivers/net/wireless/intersil/prism54/islpci_dev.c4
-rw-r--r--drivers/net/wireless/intersil/prism54/islpci_eth.c5
-rw-r--r--drivers/net/wireless/intersil/prism54/islpci_mgt.c4
-rw-r--r--drivers/net/wireless/intersil/prism54/oid_mgt.c10
-rw-r--r--drivers/net/wireless/marvell/libertas/cfg.c3
-rw-r--r--drivers/net/wireless/marvell/libertas/if_sdio.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/11n_aggr.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c10
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c62
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfp.c6
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cmdevt.c4
-rw-r--r--drivers/net/wireless/marvell/mwifiex/debugfs.c30
-rw-r--r--drivers/net/wireless/marvell/mwifiex/decl.h6
-rw-r--r--drivers/net/wireless/marvell/mwifiex/fw.h13
-rw-r--r--drivers/net/wireless/marvell/mwifiex/ie.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/init.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/join.c20
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/main.h50
-rw-r--r--drivers/net/wireless/marvell/mwifiex/pcie.c65
-rw-r--r--drivers/net/wireless/marvell/mwifiex/pcie.h10
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sdio.c15
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_ioctl.c85
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_rx.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/uap_cmd.c6
-rw-r--r--drivers/net/wireless/marvell/mwifiex/uap_txrx.c3
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2500usb.c5
-rw-r--r--drivers/net/wireless/ralink/rt2x00/rt2x00pci.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c23
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c21
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c22
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c23
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c21
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/core.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pci.c11
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c7
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c6
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c9
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c8
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c11
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/usb.c2
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mgmt.c5
-rw-r--r--drivers/net/wireless/st/cw1200/sta.c6
-rw-r--r--drivers/net/wireless/ti/wl12xx/conf.h233
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c116
-rw-r--r--drivers/net/wireless/ti/wl18xx/conf.h90
-rw-r--r--drivers/net/wireless/ti/wl18xx/event.c2
-rw-r--r--drivers/net/wireless/ti/wl18xx/event.h1
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c147
-rw-r--r--drivers/net/wireless/ti/wlcore/acx.c4
-rw-r--r--drivers/net/wireless/ti/wlcore/acx.h2
-rw-r--r--drivers/net/wireless/ti/wlcore/cmd.h1
-rw-r--r--drivers/net/wireless/ti/wlcore/conf.h237
-rw-r--r--drivers/net/wireless/ti/wlcore/debugfs.c60
-rw-r--r--drivers/net/wireless/ti/wlcore/event.c82
-rw-r--r--drivers/net/wireless/ti/wlcore/event.h9
-rw-r--r--drivers/net/wireless/ti/wlcore/io.c11
-rw-r--r--drivers/net/wireless/ti/wlcore/io.h14
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c96
-rw-r--r--drivers/net/wireless/ti/wlcore/rx.c1
-rw-r--r--drivers/net/wireless/ti/wlcore/spi.c10
-rw-r--r--drivers/net/wireless/ti/wlcore/sysfs.c26
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h3
161 files changed, 3737 insertions, 2263 deletions
diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index 72acb822bb11..03aa35f999a1 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -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.
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index aa9bd92ac4ed..b41eb3f4ee56 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -51,6 +51,7 @@ MODULE_PARM_DESC(rawmode, "Use raw 802.11 frame datapath");
static const struct ath10k_hw_params ath10k_hw_params_list[] = {
{
.id = QCA988X_HW_2_0_VERSION,
+ .dev_id = QCA988X_2_0_DEVICE_ID,
.name = "qca988x hw2.0",
.patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
@@ -58,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,
@@ -69,12 +71,32 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
},
{
.id = QCA6174_HW_2_1_VERSION,
+ .dev_id = QCA6164_2_1_DEVICE_ID,
+ .name = "qca6164 hw2.1",
+ .patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,
+ .uart_pin = 6,
+ .otp_exe_param = 0,
+ .channel_counters_freq_hz = 88000,
+ .max_probe_resp_desc_thres = 0,
+ .fw = {
+ .dir = QCA6174_HW_2_1_FW_DIR,
+ .fw = QCA6174_HW_2_1_FW_FILE,
+ .otp = QCA6174_HW_2_1_OTP_FILE,
+ .board = QCA6174_HW_2_1_BOARD_DATA_FILE,
+ .board_size = QCA6174_BOARD_DATA_SZ,
+ .board_ext_size = QCA6174_BOARD_EXT_DATA_SZ,
+ },
+ },
+ {
+ .id = QCA6174_HW_2_1_VERSION,
+ .dev_id = QCA6174_2_1_DEVICE_ID,
.name = "qca6174 hw2.1",
.patch_load_addr = QCA6174_HW_2_1_PATCH_LOAD_ADDR,
.uart_pin = 6,
.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,
@@ -86,12 +108,14 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
},
{
.id = QCA6174_HW_3_0_VERSION,
+ .dev_id = QCA6174_2_1_DEVICE_ID,
.name = "qca6174 hw3.0",
.patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
.uart_pin = 6,
.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,
@@ -103,12 +127,14 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
},
{
.id = QCA6174_HW_3_2_VERSION,
+ .dev_id = QCA6174_2_1_DEVICE_ID,
.name = "qca6174 hw3.2",
.patch_load_addr = QCA6174_HW_3_0_PATCH_LOAD_ADDR,
.uart_pin = 6,
.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,
@@ -121,6 +147,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
},
{
.id = QCA99X0_HW_2_0_DEV_VERSION,
+ .dev_id = QCA99X0_2_0_DEVICE_ID,
.name = "qca99x0 hw2.0",
.patch_load_addr = QCA99X0_HW_2_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
@@ -128,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,
@@ -139,10 +167,31 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
},
{
.id = QCA9377_HW_1_0_DEV_VERSION,
+ .dev_id = QCA9377_1_0_DEVICE_ID,
.name = "qca9377 hw1.0",
.patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
- .uart_pin = 7,
+ .uart_pin = 6,
.otp_exe_param = 0,
+ .channel_counters_freq_hz = 88000,
+ .max_probe_resp_desc_thres = 0,
+ .fw = {
+ .dir = QCA9377_HW_1_0_FW_DIR,
+ .fw = QCA9377_HW_1_0_FW_FILE,
+ .otp = QCA9377_HW_1_0_OTP_FILE,
+ .board = QCA9377_HW_1_0_BOARD_DATA_FILE,
+ .board_size = QCA9377_BOARD_DATA_SZ,
+ .board_ext_size = QCA9377_BOARD_EXT_DATA_SZ,
+ },
+ },
+ {
+ .id = QCA9377_HW_1_1_DEV_VERSION,
+ .dev_id = QCA9377_1_0_DEVICE_ID,
+ .name = "qca9377 hw1.1",
+ .patch_load_addr = QCA9377_HW_1_0_PATCH_LOAD_ADDR,
+ .uart_pin = 6,
+ .otp_exe_param = 0,
+ .channel_counters_freq_hz = 88000,
+ .max_probe_resp_desc_thres = 0,
.fw = {
.dir = QCA9377_HW_1_0_FW_DIR,
.fw = QCA9377_HW_1_0_FW_FILE,
@@ -167,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,
@@ -843,7 +893,7 @@ out:
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;
}
@@ -1263,7 +1313,8 @@ static int ath10k_init_hw_params(struct ath10k *ar)
for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) {
hw_params = &ath10k_hw_params_list[i];
- if (hw_params->id == ar->target_version)
+ if (hw_params->id == ar->target_version &&
+ hw_params->dev_id == ar->dev_id)
break;
}
@@ -1745,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;
}
@@ -1758,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",
@@ -1780,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);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 018c64f4fd25..7840cf3ef7a6 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -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 {
@@ -636,6 +637,7 @@ struct ath10k {
struct ath10k_hw_params {
u32 id;
+ u16 dev_id;
const char *name;
u32 patch_load_addr;
int uart_pin;
@@ -661,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;
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index 6cc1aa3449c8..2bdf5408b0d9 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -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);
@@ -1114,7 +1139,7 @@ static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
{
struct ath10k *ar = file->private_data;
char buf[64];
- u8 amsdu = 3, ampdu = 64;
+ u8 amsdu, ampdu;
unsigned int len;
mutex_lock(&ar->conf_mutex);
@@ -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;
}
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index 7de780c4ec8d..814719cf4f22 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -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
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 2bad50e520b5..47ca048feaf0 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -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
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 6060dda4e910..91afa3ae414c 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -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;
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 16823970dbfd..b3adadb5f824 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -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 @@ err:
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;
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 39966a05c1cc..0678831e8671 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -22,6 +22,12 @@
#define ATH10K_FW_DIR "ath10k"
+#define QCA988X_2_0_DEVICE_ID (0x003c)
+#define QCA6164_2_1_DEVICE_ID (0x0041)
+#define QCA6174_2_1_DEVICE_ID (0x003e)
+#define QCA99X0_2_0_DEVICE_ID (0x0040)
+#define QCA9377_1_0_DEVICE_ID (0x0042)
+
/* QCA988X 1.0 definitions (unsupported) */
#define QCA988X_HW_1_0_CHIP_ID_REV 0x0
@@ -42,6 +48,10 @@
#define QCA6174_HW_3_0_VERSION 0x05020000
#define QCA6174_HW_3_2_VERSION 0x05030000
+/* QCA9377 target BMI version signatures */
+#define QCA9377_HW_1_0_DEV_VERSION 0x05020000
+#define QCA9377_HW_1_1_DEV_VERSION 0x05020001
+
enum qca6174_pci_rev {
QCA6174_PCI_REV_1_1 = 0x11,
QCA6174_PCI_REV_1_3 = 0x13,
@@ -60,6 +70,11 @@ enum qca6174_chip_id_rev {
QCA6174_HW_3_2_CHIP_ID_REV = 10,
};
+enum qca9377_chip_id_rev {
+ QCA9377_HW_1_0_CHIP_ID_REV = 0x0,
+ QCA9377_HW_1_1_CHIP_ID_REV = 0x1,
+};
+
#define QCA6174_HW_2_1_FW_DIR "ath10k/QCA6174/hw2.1"
#define QCA6174_HW_2_1_FW_FILE "firmware.bin"
#define QCA6174_HW_2_1_OTP_FILE "otp.bin"
@@ -85,8 +100,6 @@ enum qca6174_chip_id_rev {
#define QCA99X0_HW_2_0_PATCH_LOAD_ADDR 0x1234
/* QCA9377 1.0 definitions */
-#define QCA9377_HW_1_0_DEV_VERSION 0x05020001
-#define QCA9377_HW_1_0_CHIP_ID_REV 0x1
#define QCA9377_HW_1_0_FW_DIR ATH10K_FW_DIR "/QCA9377/hw1.0"
#define QCA9377_HW_1_0_FW_FILE "firmware.bin"
#define QCA9377_HW_1_0_OTP_FILE "otp.bin"
@@ -273,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,
@@ -294,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
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index a7411fe90cc4..6146a293601a 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -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 &&
@@ -247,7 +250,8 @@ static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif,
lockdep_assert_held(&ar->conf_mutex);
if (WARN_ON(arvif->vif->type != NL80211_IFTYPE_AP &&
- arvif->vif->type != NL80211_IFTYPE_ADHOC))
+ arvif->vif->type != NL80211_IFTYPE_ADHOC &&
+ arvif->vif->type != NL80211_IFTYPE_MESH_POINT))
return -EINVAL;
spin_lock_bh(&ar->data_lock);
@@ -1960,7 +1964,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 +1972,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 +2007,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 +2114,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 +2125,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 +2142,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 +2150,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 +2331,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 +2351,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 +2376,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 +2490,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 +3123,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 +3177,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 +3219,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 +3275,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 +3283,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 +3310,24 @@ unlock:
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 +3357,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 +3388,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 +3413,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 +3503,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 +3647,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 +3691,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 +3701,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. */
@@ -3845,7 +3860,8 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
- ht_cap.cap |= WLAN_HT_CAP_SM_PS_STATIC << IEEE80211_HT_CAP_SM_PS_SHIFT;
+ ht_cap.cap |=
+ WLAN_HT_CAP_SM_PS_DISABLED << IEEE80211_HT_CAP_SM_PS_SHIFT;
if (ar->ht_cap_info & WMI_HT_CAP_HT20_SGI)
ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
@@ -4225,7 +4241,7 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
static u32 get_nss_from_chainmask(u16 chain_mask)
{
- if ((chain_mask & 0x15) == 0x15)
+ if ((chain_mask & 0xf) == 0xf)
return 4;
else if ((chain_mask & 0x7) == 0x7)
return 3;
@@ -4350,7 +4366,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 +6925,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[] = {
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h
index e3cefe4c7cfd..53091588090d 100644
--- a/drivers/net/wireless/ath/ath10k/mac.h
+++ b/drivers/net/wireless/ath/ath10k/mac.h
@@ -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)
{
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 3fca200b986c..ee925c618535 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -57,12 +57,6 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)");
#define ATH10K_PCI_TARGET_WAIT 3000
#define ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS 3
-#define QCA988X_2_0_DEVICE_ID (0x003c)
-#define QCA6164_2_1_DEVICE_ID (0x0041)
-#define QCA6174_2_1_DEVICE_ID (0x003e)
-#define QCA99X0_2_0_DEVICE_ID (0x0040)
-#define QCA9377_1_0_DEVICE_ID (0x0042)
-
static const struct pci_device_id ath10k_pci_id_table[] = {
{ PCI_VDEVICE(ATHEROS, QCA988X_2_0_DEVICE_ID) }, /* PCI-E QCA988X V2 */
{ PCI_VDEVICE(ATHEROS, QCA6164_2_1_DEVICE_ID) }, /* PCI-E QCA6164 V2.1 */
@@ -92,7 +86,9 @@ static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = {
{ QCA6174_2_1_DEVICE_ID, QCA6174_HW_3_2_CHIP_ID_REV },
{ QCA99X0_2_0_DEVICE_ID, QCA99X0_HW_2_0_CHIP_ID_REV },
+
{ QCA9377_1_0_DEVICE_ID, QCA9377_HW_1_0_CHIP_ID_REV },
+ { QCA9377_1_0_DEVICE_ID, QCA9377_HW_1_1_CHIP_ID_REV },
};
static void ath10k_pci_buffer_cleanup(struct ath10k *ar);
@@ -111,8 +107,10 @@ static void ath10k_pci_htc_tx_cb(struct ath10k_ce_pipe *ce_state);
static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state);
static void ath10k_pci_htt_tx_cb(struct ath10k_ce_pipe *ce_state);
static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state);
+static void ath10k_pci_htt_htc_rx_cb(struct ath10k_ce_pipe *ce_state);
+static void ath10k_pci_pktlog_rx_cb(struct ath10k_ce_pipe *ce_state);
-static const struct ce_attr host_ce_config_wlan[] = {
+static struct ce_attr host_ce_config_wlan[] = {
/* CE0: host->target HTC control and raw streams */
{
.flags = CE_ATTR_FLAGS,
@@ -128,7 +126,7 @@ static const struct ce_attr host_ce_config_wlan[] = {
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 512,
- .recv_cb = ath10k_pci_htc_rx_cb,
+ .recv_cb = ath10k_pci_htt_htc_rx_cb,
},
/* CE2: target->host WMI */
@@ -189,6 +187,7 @@ static const struct ce_attr host_ce_config_wlan[] = {
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 128,
+ .recv_cb = ath10k_pci_pktlog_rx_cb,
},
/* CE9 target autonomous qcache memcpy */
@@ -217,7 +216,7 @@ static const struct ce_attr host_ce_config_wlan[] = {
};
/* Target firmware's Copy Engine configuration. */
-static const struct ce_pipe_config target_ce_config_wlan[] = {
+static struct ce_pipe_config target_ce_config_wlan[] = {
/* CE0: host->target HTC control and raw streams */
{
.pipenum = __cpu_to_le32(0),
@@ -330,7 +329,7 @@ static const struct ce_pipe_config target_ce_config_wlan[] = {
* This table is derived from the CE_PCI TABLE, above.
* It is passed to the Target at startup for use by firmware.
*/
-static const struct service_to_pipe target_service_to_ce_map_wlan[] = {
+static struct service_to_pipe target_service_to_ce_map_wlan[] = {
{
__cpu_to_le32(ATH10K_HTC_SVC_ID_WMI_DATA_VO),
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
@@ -488,6 +487,9 @@ static int ath10k_pci_force_wake(struct ath10k *ar)
unsigned long flags;
int ret = 0;
+ if (ar_pci->pci_ps)
+ return ret;
+
spin_lock_irqsave(&ar_pci->ps_lock, flags);
if (!ar_pci->ps_awake) {
@@ -1208,6 +1210,25 @@ static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state)
ath10k_pci_process_rx_cb(ce_state, ath10k_htc_rx_completion_handler);
}
+static void ath10k_pci_htt_htc_rx_cb(struct ath10k_ce_pipe *ce_state)
+{
+ /* CE4 polling needs to be done whenever CE pipe which transports
+ * HTT Rx (target->host) is processed.
+ */
+ ath10k_ce_per_engine_service(ce_state->ar, 4);
+
+ 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)
{
@@ -2027,6 +2048,29 @@ static int ath10k_pci_init_config(struct ath10k *ar)
return 0;
}
+static void ath10k_pci_override_ce_config(struct ath10k *ar)
+{
+ struct ce_attr *attr;
+ struct ce_pipe_config *config;
+
+ /* For QCA6174 we're overriding the Copy Engine 5 configuration,
+ * since it is currently used for other feature.
+ */
+
+ /* Override Host's Copy Engine 5 configuration */
+ attr = &host_ce_config_wlan[5];
+ attr->src_sz_max = 0;
+ attr->dest_nentries = 0;
+
+ /* Override Target firmware's Copy Engine configuration */
+ config = &target_ce_config_wlan[5];
+ config->pipedir = __cpu_to_le32(PIPEDIR_OUT);
+ config->nbytes_max = __cpu_to_le32(2048);
+
+ /* Map from service/endpoint to Copy Engine */
+ target_service_to_ce_map_wlan[15].pipenum = __cpu_to_le32(1);
+}
+
static int ath10k_pci_alloc_pipes(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -2439,12 +2483,10 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
u32 val;
int ret = 0;
- if (ar_pci->pci_ps == 0) {
- ret = ath10k_pci_force_wake(ar);
- if (ret) {
- ath10k_err(ar, "failed to wake up target: %d\n", ret);
- return ret;
- }
+ ret = ath10k_pci_force_wake(ar);
+ if (ret) {
+ ath10k_err(ar, "failed to wake up target: %d\n", ret);
+ return ret;
}
/* Suspend/Resume resets the PCI configuration space, so we have to
@@ -2551,13 +2593,10 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg)
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ret;
- if (ar_pci->pci_ps == 0) {
- ret = ath10k_pci_force_wake(ar);
- if (ret) {
- ath10k_warn(ar, "failed to wake device up on irq: %d\n",
- ret);
- return IRQ_NONE;
- }
+ ret = ath10k_pci_force_wake(ar);
+ if (ret) {
+ ath10k_warn(ar, "failed to wake device up on irq: %d\n", ret);
+ return IRQ_NONE;
}
if (ar_pci->num_msi_intrs == 0) {
@@ -3020,6 +3059,9 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
goto err_core_destroy;
}
+ if (QCA_REV_6174(ar))
+ ath10k_pci_override_ce_config(ar);
+
ret = ath10k_pci_alloc_pipes(ar);
if (ret) {
ath10k_err(ar, "failed to allocate copy engine pipes: %d\n",
@@ -3027,17 +3069,15 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
goto err_sleep;
}
+ ret = ath10k_pci_force_wake(ar);
+ if (ret) {
+ ath10k_warn(ar, "failed to wake up device : %d\n", ret);
+ goto err_free_pipes;
+ }
+
ath10k_pci_ce_deinit(ar);
ath10k_pci_irq_disable(ar);
- if (ar_pci->pci_ps == 0) {
- ret = ath10k_pci_force_wake(ar);
- if (ret) {
- ath10k_warn(ar, "failed to wake up device : %d\n", ret);
- goto err_free_pipes;
- }
- }
-
ret = ath10k_pci_init_irq(ar);
if (ret) {
ath10k_err(ar, "failed to init irqs: %d\n", ret);
diff --git a/drivers/net/wireless/ath/ath10k/thermal.c b/drivers/net/wireless/ath/ath10k/thermal.c
index 60fe562e3041..444b52c7e4f3 100644
--- a/drivers/net/wireless/ath/ath10k/thermal.c
+++ b/drivers/net/wireless/ath/ath10k/thermal.c
@@ -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
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 6d1105ab4592..fbfb608e48ab 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -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);
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 6fbd17b69469..3b3a27b859f3 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -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;
}
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index ad655c44afdb..dd678590531a 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -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,
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 7569db0f69b5..a7c3d299639b 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -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",
@@ -4258,34 +4312,58 @@ void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar, struct sk_buff *skb)
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_RESUME_REQ_EVENTID\n");
}
-static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
- u32 num_units, u32 unit_len)
+static int ath10k_wmi_alloc_chunk(struct ath10k *ar, u32 req_id,
+ u32 num_units, u32 unit_len)
{
dma_addr_t paddr;
- u32 pool_size;
+ u32 pool_size = 0;
int idx = ar->wmi.num_mem_chunks;
+ void *vaddr = NULL;
- pool_size = num_units * round_up(unit_len, 4);
+ if (ar->wmi.num_mem_chunks == ARRAY_SIZE(ar->wmi.mem_chunks))
+ return -ENOMEM;
- if (!pool_size)
- return -EINVAL;
+ while (!vaddr && num_units) {
+ pool_size = num_units * round_up(unit_len, 4);
+ if (!pool_size)
+ return -EINVAL;
- ar->wmi.mem_chunks[idx].vaddr = dma_alloc_coherent(ar->dev,
- pool_size,
- &paddr,
- GFP_KERNEL);
- if (!ar->wmi.mem_chunks[idx].vaddr) {
- ath10k_warn(ar, "failed to allocate memory chunk\n");
- return -ENOMEM;
+ vaddr = kzalloc(pool_size, GFP_KERNEL | __GFP_NOWARN);
+ if (!vaddr)
+ num_units /= 2;
}
- memset(ar->wmi.mem_chunks[idx].vaddr, 0, pool_size);
+ if (!num_units)
+ return -ENOMEM;
+ paddr = dma_map_single(ar->dev, vaddr, pool_size, DMA_TO_DEVICE);
+ if (dma_mapping_error(ar->dev, paddr)) {
+ kfree(vaddr);
+ return -ENOMEM;
+ }
+
+ ar->wmi.mem_chunks[idx].vaddr = vaddr;
ar->wmi.mem_chunks[idx].paddr = paddr;
ar->wmi.mem_chunks[idx].len = pool_size;
ar->wmi.mem_chunks[idx].req_id = req_id;
ar->wmi.num_mem_chunks++;
+ return num_units;
+}
+
+static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id,
+ u32 num_units, u32 unit_len)
+{
+ int ret;
+
+ while (num_units) {
+ ret = ath10k_wmi_alloc_chunk(ar, req_id, num_units, unit_len);
+ if (ret < 0)
+ return ret;
+
+ num_units -= ret;
+ }
+
return 0;
}
@@ -5061,6 +5139,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 +5512,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 +6412,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)
{
@@ -6417,6 +6511,31 @@ ath10k_wmi_10_2_op_gen_peer_assoc(struct ath10k *ar,
}
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)
{
struct sk_buff *skb;
@@ -7536,6 +7655,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 +7675,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 +7687,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);
@@ -7616,10 +7741,11 @@ void ath10k_wmi_free_host_mem(struct ath10k *ar)
/* free the host memory chunks requested by firmware */
for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
- dma_free_coherent(ar->dev,
- ar->wmi.mem_chunks[i].len,
- ar->wmi.mem_chunks[i].vaddr,
- ar->wmi.mem_chunks[i].paddr);
+ dma_unmap_single(ar->dev,
+ ar->wmi.mem_chunks[i].paddr,
+ ar->wmi.mem_chunks[i].len,
+ DMA_TO_DEVICE);
+ kfree(ar->wmi.mem_chunks[i].vaddr);
}
ar->wmi.num_mem_chunks = 0;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 72a4ef709577..d85ad7855d20 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -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;
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 342563a3706f..3d946d8b2db2 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -767,7 +767,7 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf,
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
flags |= AR5K_TXDESC_NOACK;
- rc_flags = info->control.rates[0].flags;
+ rc_flags = bf->rates[0].flags;
hw_rate = ath5k_get_rate_hw_value(ah->hw, info, bf, 0);
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 81ac8c59f0ec..7f3f94fbf157 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -3930,8 +3930,8 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff;
- ar->hw.tx_ant = 2;
- ar->hw.rx_ant = 2;
+ ar->hw.tx_ant = 0x3; /* mask, 2 antenna */
+ ar->hw.rx_ant = 0x3;
} else {
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c
index fffb65b3e652..65c31da43c47 100644
--- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c
+++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c
@@ -2222,8 +2222,9 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
}
if (status) {
- ath6kl_err("failed to get pending recv messages: %d\n",
- status);
+ if (status != -ECANCELED)
+ ath6kl_err("failed to get pending recv messages: %d\n",
+ status);
/* cleanup any packets in sync completion queue */
list_for_each_entry_safe(packets, tmp_pkt, &comp_pktq, list) {
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 6ae0734f86e0..da557dc742e6 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -954,8 +954,10 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
snprintf(filename, sizeof(filename), "%s/%s", ar->hw.fw.dir, name);
ret = request_firmware(&fw, filename, ar->dev);
- if (ret)
+ if (ret) {
+ ath6kl_err("Failed request firmware, rv: %d\n", ret);
return ret;
+ }
data = fw->data;
len = fw->size;
@@ -964,11 +966,15 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
magic_len = strlen(ATH6KL_FIRMWARE_MAGIC) + 1;
if (len < magic_len) {
+ ath6kl_err("Magic length is invalid, len: %zd magic_len: %zd\n",
+ len, magic_len);
ret = -EINVAL;
goto out;
}
if (memcmp(data, ATH6KL_FIRMWARE_MAGIC, magic_len) != 0) {
+ ath6kl_err("Magic is invalid, magic_len: %zd\n",
+ magic_len);
ret = -EINVAL;
goto out;
}
@@ -987,7 +993,12 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
len -= sizeof(*hdr);
data += sizeof(*hdr);
+ ath6kl_dbg(ATH6KL_DBG_BOOT, "ie-id: %d len: %zd (0x%zx)\n",
+ ie_id, ie_len, ie_len);
+
if (len < ie_len) {
+ ath6kl_err("IE len is invalid, len: %zd ie_len: %zd ie-id: %d\n",
+ len, ie_len, ie_id);
ret = -EINVAL;
goto out;
}
@@ -1008,6 +1019,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL);
if (ar->fw_otp == NULL) {
+ ath6kl_err("fw_otp cannot be allocated\n");
ret = -ENOMEM;
goto out;
}
@@ -1025,6 +1037,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
ar->fw = vmalloc(ie_len);
if (ar->fw == NULL) {
+ ath6kl_err("fw storage cannot be allocated, len: %zd\n", ie_len);
ret = -ENOMEM;
goto out;
}
@@ -1039,6 +1052,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL);
if (ar->fw_patch == NULL) {
+ ath6kl_err("fw_patch storage cannot be allocated, len: %zd\n", ie_len);
ret = -ENOMEM;
goto out;
}
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index fee0cadb0f5e..40fa915d6f35 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -176,3 +176,14 @@ config ATH9K_HTC_DEBUGFS
depends on ATH9K_HTC && DEBUG_FS
---help---
Say Y, if you need access to ath9k_htc's statistics.
+
+config ATH9K_HWRNG
+ bool "Random number generator support"
+ depends on ATH9K && (HW_RANDOM = y || HW_RANDOM = ATH9K)
+ default y
+ ---help---
+ This option incorporates the ADC register output as a source of
+ randomness into Linux entropy pool (/dev/urandom and /dev/random)
+
+ Say Y, feeds the entropy directly from the WiFi driver to the input
+ pool.
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index ecda613c2d54..76f9dc37500b 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -15,6 +15,7 @@ ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o
ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o
ath9k-$(CONFIG_ATH9K_TX99) += tx99.o
ath9k-$(CONFIG_ATH9K_WOW) += wow.o
+ath9k-$(CONFIG_ATH9K_HWRNG) += rng.o
ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index b42f4a963ef4..5294595da5a7 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -23,6 +23,7 @@
#include <linux/leds.h>
#include <linux/completion.h>
#include <linux/time.h>
+#include <linux/hw_random.h>
#include "common.h"
#include "debug.h"
@@ -981,6 +982,7 @@ struct ath_softc {
struct ath_offchannel offchannel;
struct ath_chanctx *next_chan;
struct completion go_beacon;
+ struct timespec last_event_time;
#endif
unsigned long driver_data;
@@ -1040,6 +1042,11 @@ struct ath_softc {
u32 wow_intr_before_sleep;
bool force_wow;
#endif
+
+#ifdef CONFIG_ATH9K_HWRNG
+ u32 rng_last;
+ struct task_struct *rng_task;
+#endif
};
/********/
@@ -1062,6 +1069,22 @@ static inline int ath9k_tx99_send(struct ath_softc *sc,
}
#endif /* CONFIG_ATH9K_TX99 */
+/***************************/
+/* Random Number Generator */
+/***************************/
+#ifdef CONFIG_ATH9K_HWRNG
+void ath9k_rng_start(struct ath_softc *sc);
+void ath9k_rng_stop(struct ath_softc *sc);
+#else
+static inline void ath9k_rng_start(struct ath_softc *sc)
+{
+}
+
+static inline void ath9k_rng_stop(struct ath_softc *sc)
+{
+}
+#endif
+
static inline void ath_read_cachesize(struct ath_common *common, int *csz)
{
common->bus_ops->read_cachesize(common, csz);
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index f50a6bc5d06e..5cf0cd7cb2d1 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -148,7 +148,8 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw,
ath_assign_seq(common, skb);
- if (vif->p2p)
+ /* Always assign NOA attr when MCC enabled */
+ if (ath9k_is_chanctx_enabled())
ath9k_beacon_add_noa(sc, avp, skb);
bf->bf_buf_addr = dma_map_single(sc->dev, skb->data,
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index 90f5773a1a61..50e614b915f1 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -226,6 +226,20 @@ static const char *chanctx_state_string(enum ath_chanctx_state state)
}
}
+static const u32 chanctx_event_delta(struct ath_softc *sc)
+{
+ u64 ms;
+ struct timespec ts, *old;
+
+ getrawmonotonic(&ts);
+ old = &sc->last_event_time;
+ ms = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
+ ms -= old->tv_sec * 1000 + old->tv_nsec / 1000000;
+ sc->last_event_time = ts;
+
+ return (u32)ms;
+}
+
void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -356,14 +370,16 @@ static void ath_chanctx_setup_timer(struct ath_softc *sc, u32 tsf_time)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
+ unsigned long timeout;
ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, tsf_time, 1000000);
tsf_time -= ath9k_hw_gettsf32(ah);
- tsf_time = msecs_to_jiffies(tsf_time / 1000) + 1;
- mod_timer(&sc->sched.timer, jiffies + tsf_time);
+ timeout = msecs_to_jiffies(tsf_time / 1000) + 1;
+ mod_timer(&sc->sched.timer, jiffies + timeout);
ath_dbg(common, CHAN_CTX,
- "Setup chanctx timer with timeout: %d ms\n", jiffies_to_msecs(tsf_time));
+ "Setup chanctx timer with timeout: %d (%d) ms\n",
+ tsf_time / 1000, jiffies_to_msecs(timeout));
}
static void ath_chanctx_handle_bmiss(struct ath_softc *sc,
@@ -403,7 +419,7 @@ static void ath_chanctx_offchannel_noa(struct ath_softc *sc,
avp->offchannel_duration = sc->sched.offchannel_duration;
ath_dbg(common, CHAN_CTX,
- "offchannel noa_duration: %d, noa_start: %d, noa_index: %d\n",
+ "offchannel noa_duration: %d, noa_start: %u, noa_index: %d\n",
avp->offchannel_duration,
avp->offchannel_start,
avp->noa_index);
@@ -443,7 +459,7 @@ static void ath_chanctx_set_periodic_noa(struct ath_softc *sc,
avp->periodic_noa = true;
ath_dbg(common, CHAN_CTX,
- "noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n",
+ "noa_duration: %d, noa_start: %u, noa_index: %d, periodic: %d\n",
avp->noa_duration,
avp->noa_start,
avp->noa_index,
@@ -464,7 +480,7 @@ static void ath_chanctx_set_oneshot_noa(struct ath_softc *sc,
avp->noa_duration = duration + sc->sched.channel_switch_time;
ath_dbg(common, CHAN_CTX,
- "oneshot noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n",
+ "oneshot noa_duration: %d, noa_start: %u, noa_index: %d, periodic: %d\n",
avp->noa_duration,
avp->noa_start,
avp->noa_index,
@@ -487,10 +503,11 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
spin_lock_bh(&sc->chan_lock);
- ath_dbg(common, CHAN_CTX, "cur_chan: %d MHz, event: %s, state: %s\n",
+ ath_dbg(common, CHAN_CTX, "cur_chan: %d MHz, event: %s, state: %s, delta: %u ms\n",
sc->cur_chan->chandef.center_freq1,
chanctx_event_string(ev),
- chanctx_state_string(sc->sched.state));
+ chanctx_state_string(sc->sched.state),
+ chanctx_event_delta(sc));
switch (ev) {
case ATH_CHANCTX_EVENT_BEACON_PREPARE:
@@ -1099,6 +1116,7 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
nullfunc->frame_control |=
cpu_to_le16(IEEE80211_FCTL_PM);
+ skb->priority = 7;
skb_set_queue_mapping(skb, IEEE80211_AC_VO);
if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) {
dev_kfree_skb_any(skb);
@@ -1401,8 +1419,9 @@ void ath9k_chanctx_wake_queues(struct ath_softc *sc, struct ath_chanctx *ctx)
static void ath9k_update_p2p_ps_timer(struct ath_softc *sc, struct ath_vif *avp)
{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_hw *ah = sc->sc_ah;
- s32 tsf, target_tsf;
+ u32 tsf, target_tsf;
if (!avp || !avp->noa.has_next_tsf)
return;
@@ -1414,11 +1433,17 @@ static void ath9k_update_p2p_ps_timer(struct ath_softc *sc, struct ath_vif *avp)
target_tsf = avp->noa.next_tsf;
if (!avp->noa.absent)
target_tsf -= ATH_P2P_PS_STOP_TIME;
+ else
+ target_tsf += ATH_P2P_PS_STOP_TIME;
if (target_tsf - tsf < ATH_P2P_PS_STOP_TIME)
target_tsf = tsf + ATH_P2P_PS_STOP_TIME;
- ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, (u32) target_tsf, 1000000);
+ ath_dbg(common, CHAN_CTX, "%s absent %d tsf 0x%08X next_tsf 0x%08X (%dms)\n",
+ __func__, avp->noa.absent, tsf, target_tsf,
+ (target_tsf - tsf) / 1000);
+
+ ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, target_tsf, 1000000);
}
static void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
@@ -1433,6 +1458,10 @@ static void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
return;
sc->p2p_ps_vif = avp;
+
+ if (sc->ps_flags & PS_BEACON_SYNC)
+ return;
+
tsf = ath9k_hw_gettsf32(sc->sc_ah);
ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
ath9k_update_p2p_ps_timer(sc, avp);
@@ -1495,6 +1524,8 @@ void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *avp,
noa->index = avp->noa_index;
noa->oppps_ctwindow = ath9k_get_ctwin(sc, avp);
+ if (noa->oppps_ctwindow)
+ noa->oppps_ctwindow |= BIT(7);
if (avp->noa_duration) {
if (avp->periodic_noa) {
@@ -1536,6 +1567,8 @@ void ath9k_p2p_ps_timer(void *priv)
tsf = ath9k_hw_gettsf32(sc->sc_ah);
if (!avp->noa.absent)
tsf += ATH_P2P_PS_STOP_TIME;
+ else
+ tsf -= ATH_P2P_PS_STOP_TIME;
if (!avp->noa.has_next_tsf ||
avp->noa.next_tsf - tsf > BIT(31))
@@ -1571,8 +1604,7 @@ void ath9k_p2p_bss_info_changed(struct ath_softc *sc,
spin_lock_bh(&sc->sc_pcu_lock);
spin_lock_irqsave(&sc->sc_pm_lock, flags);
- if (!(sc->ps_flags & PS_BEACON_SYNC))
- ath9k_update_p2p_ps(sc, vif);
+ ath9k_update_p2p_ps(sc, vif);
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
spin_unlock_bh(&sc->sc_pcu_lock);
}
diff --git a/drivers/net/wireless/ath/ath9k/common-beacon.c b/drivers/net/wireless/ath/ath9k/common-beacon.c
index 6ad44470d0f2..01d6d3205a65 100644
--- a/drivers/net/wireless/ath/ath9k/common-beacon.c
+++ b/drivers/net/wireless/ath/ath9k/common-beacon.c
@@ -18,30 +18,16 @@
#define FUDGE 2
-/* Calculate the modulo of a 64 bit TSF snapshot with a TU divisor */
-static u32 ath9k_mod_tsf64_tu(u64 tsf, u32 div_tu)
-{
- u32 tsf_mod, tsf_hi, tsf_lo, mod_hi, mod_lo;
-
- tsf_mod = tsf & (BIT(10) - 1);
- tsf_hi = tsf >> 32;
- tsf_lo = ((u32) tsf) >> 10;
-
- mod_hi = tsf_hi % div_tu;
- mod_lo = ((mod_hi << 22) + tsf_lo) % div_tu;
-
- return (mod_lo << 10) | tsf_mod;
-}
-
static u32 ath9k_get_next_tbtt(struct ath_hw *ah, u64 tsf,
unsigned int interval)
{
- unsigned int offset;
+ unsigned int offset, divisor;
tsf += TU_TO_USEC(FUDGE + ah->config.sw_beacon_response_time);
- offset = ath9k_mod_tsf64_tu(tsf, interval);
+ divisor = TU_TO_USEC(interval);
+ div_u64_rem(tsf, divisor, &offset);
- return (u32) tsf + TU_TO_USEC(interval) - offset;
+ return (u32) tsf + divisor - offset;
}
/*
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c
index cc81482c934d..a7afdeee698c 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom.c
@@ -138,6 +138,80 @@ bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
return ret;
}
+int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size)
+{
+ u16 magic;
+ u16 *eepdata;
+ int i;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
+ ath_err(common, "Reading Magic # failed\n");
+ return -EIO;
+ }
+
+ if (magic == AR5416_EEPROM_MAGIC) {
+ *swap_needed = false;
+ } else if (swab16(magic) == AR5416_EEPROM_MAGIC) {
+ if (ah->ah_flags & AH_NO_EEP_SWAP) {
+ ath_info(common,
+ "Ignoring endianness difference in EEPROM magic bytes.\n");
+
+ *swap_needed = false;
+ } else {
+ *swap_needed = true;
+ }
+ } else {
+ ath_err(common,
+ "Invalid EEPROM Magic (0x%04x).\n", magic);
+ return -EINVAL;
+ }
+
+ eepdata = (u16 *)(&ah->eeprom);
+
+ if (*swap_needed) {
+ ath_dbg(common, EEPROM,
+ "EEPROM Endianness is not native.. Changing.\n");
+
+ for (i = 0; i < size; i++)
+ eepdata[i] = swab16(eepdata[i]);
+ }
+
+ return 0;
+}
+
+bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size)
+{
+ u32 i, sum = 0;
+ u16 *eepdata = (u16 *)(&ah->eeprom);
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ for (i = 0; i < size; i++)
+ sum ^= eepdata[i];
+
+ if (sum != 0xffff) {
+ ath_err(common, "Bad EEPROM checksum 0x%x\n", sum);
+ return false;
+ }
+
+ return true;
+}
+
+bool ath9k_hw_nvram_check_version(struct ath_hw *ah, int version, int minrev)
+{
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (ah->eep_ops->get_eeprom_ver(ah) != version ||
+ ah->eep_ops->get_eeprom_rev(ah) < minrev) {
+ ath_err(common, "Bad EEPROM VER 0x%04x or REV 0x%04x\n",
+ ah->eep_ops->get_eeprom_ver(ah),
+ ah->eep_ops->get_eeprom_rev(ah));
+ return false;
+ }
+
+ return true;
+}
+
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
u8 *pVpdList, u16 numIntercepts,
u8 *pRetVpdList)
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index 40d4f62d0f16..4465c6566f20 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -664,6 +664,9 @@ int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
u16 *indexL, u16 *indexR);
bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data);
+int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size);
+bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size);
+bool ath9k_hw_nvram_check_version(struct ath_hw *ah, int version, int minrev);
void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
int eep_start_loc, int size);
void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 4773da6dc6f2..5da0826bf1be 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -177,74 +177,30 @@ static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
}
#endif
-
-#undef SIZE_EEPROM_4K
-
static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
{
-#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
- struct ath_common *common = ath9k_hw_common(ah);
struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
- u16 *eepdata, temp, magic, magic2;
- u32 sum = 0, el;
- bool need_swap = false;
- int i, addr;
+ u32 el;
+ bool need_swap;
+ int i, err;
-
- if (!ath9k_hw_use_flash(ah)) {
- if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
- &magic)) {
- ath_err(common, "Reading Magic # failed\n");
- return false;
- }
-
- ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
-
- if (magic != AR5416_EEPROM_MAGIC) {
- magic2 = swab16(magic);
-
- if (magic2 == AR5416_EEPROM_MAGIC) {
- need_swap = true;
- eepdata = (u16 *) (&ah->eeprom);
-
- for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
- temp = swab16(*eepdata);
- *eepdata = temp;
- eepdata++;
- }
- } else {
- ath_err(common,
- "Invalid EEPROM Magic. Endianness mismatch.\n");
- return -EINVAL;
- }
- }
- }
-
- ath_dbg(common, EEPROM, "need_swap = %s\n",
- need_swap ? "True" : "False");
+ err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_4K);
+ if (err)
+ return err;
if (need_swap)
- el = swab16(ah->eeprom.map4k.baseEepHeader.length);
- else
- el = ah->eeprom.map4k.baseEepHeader.length;
-
- if (el > sizeof(struct ar5416_eeprom_4k))
- el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
+ el = swab16(eep->baseEepHeader.length);
else
- el = el / sizeof(u16);
+ el = eep->baseEepHeader.length;
- eepdata = (u16 *)(&ah->eeprom);
-
- for (i = 0; i < el; i++)
- sum ^= *eepdata++;
+ el = min(el / sizeof(u16), SIZE_EEPROM_4K);
+ if (!ath9k_hw_nvram_validate_checksum(ah, el))
+ return -EINVAL;
if (need_swap) {
u32 integer;
u16 word;
- ath_dbg(common, EEPROM,
- "EEPROM Endianness is not native.. Changing\n");
-
word = swab16(eep->baseEepHeader.length);
eep->baseEepHeader.length = word;
@@ -283,17 +239,15 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
}
}
- if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
- ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
- ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
- sum, ah->eep_ops->get_eeprom_ver(ah));
+ if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER,
+ AR5416_EEP_NO_BACK_VER))
return -EINVAL;
- }
return 0;
-#undef EEPROM_4K_SIZE
}
+#undef SIZE_EEPROM_4K
+
static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
enum eeprom_param param)
{
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index 6ca33dfde1fd..1a019a39eda1 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -177,59 +177,24 @@ static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
{
- u32 sum = 0, el, integer;
- u16 temp, word, magic, magic2, *eepdata;
- int i, addr;
- bool need_swap = false;
+ u32 el, integer;
+ u16 word;
+ int i, err;
+ bool need_swap;
struct ar9287_eeprom *eep = &ah->eeprom.map9287;
- struct ath_common *common = ath9k_hw_common(ah);
-
- if (!ath9k_hw_use_flash(ah)) {
- if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
- &magic)) {
- ath_err(common, "Reading Magic # failed\n");
- return false;
- }
-
- ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
-
- if (magic != AR5416_EEPROM_MAGIC) {
- magic2 = swab16(magic);
-
- if (magic2 == AR5416_EEPROM_MAGIC) {
- need_swap = true;
- eepdata = (u16 *)(&ah->eeprom);
-
- for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
- temp = swab16(*eepdata);
- *eepdata = temp;
- eepdata++;
- }
- } else {
- ath_err(common,
- "Invalid EEPROM Magic. Endianness mismatch.\n");
- return -EINVAL;
- }
- }
- }
- ath_dbg(common, EEPROM, "need_swap = %s\n",
- need_swap ? "True" : "False");
+ err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_AR9287);
+ if (err)
+ return err;
if (need_swap)
- el = swab16(ah->eeprom.map9287.baseEepHeader.length);
- else
- el = ah->eeprom.map9287.baseEepHeader.length;
-
- if (el > sizeof(struct ar9287_eeprom))
- el = sizeof(struct ar9287_eeprom) / sizeof(u16);
+ el = swab16(eep->baseEepHeader.length);
else
- el = el / sizeof(u16);
-
- eepdata = (u16 *)(&ah->eeprom);
+ el = eep->baseEepHeader.length;
- for (i = 0; i < el; i++)
- sum ^= *eepdata++;
+ el = min(el / sizeof(u16), SIZE_EEPROM_AR9287);
+ if (!ath9k_hw_nvram_validate_checksum(ah, el))
+ return -EINVAL;
if (need_swap) {
word = swab16(eep->baseEepHeader.length);
@@ -270,16 +235,15 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
}
}
- if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER
- || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
- ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
- sum, ah->eep_ops->get_eeprom_ver(ah));
+ if (!ath9k_hw_nvram_check_version(ah, AR9287_EEP_VER,
+ AR5416_EEP_NO_BACK_VER))
return -EINVAL;
- }
return 0;
}
+#undef SIZE_EEPROM_AR9287
+
static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah,
enum eeprom_param param)
{
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 056f516bf017..959682f7909c 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -126,8 +126,6 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
return __ath9k_hw_def_fill_eeprom(ah);
}
-#undef SIZE_EEPROM_DEF
-
#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,
struct modal_eep_header *modal_hdr)
@@ -257,59 +255,31 @@ static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
}
#endif
-
static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
{
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
struct ath_common *common = ath9k_hw_common(ah);
- u16 *eepdata, temp, magic;
- u32 sum = 0, el;
- bool need_swap = false;
- int i, addr, size;
-
- if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
- ath_err(common, "Reading Magic # failed\n");
- return false;
- }
-
- if (swab16(magic) == AR5416_EEPROM_MAGIC &&
- !(ah->ah_flags & AH_NO_EEP_SWAP)) {
- size = sizeof(struct ar5416_eeprom_def);
- need_swap = true;
- eepdata = (u16 *) (&ah->eeprom);
-
- for (addr = 0; addr < size / sizeof(u16); addr++) {
- temp = swab16(*eepdata);
- *eepdata = temp;
- eepdata++;
- }
- }
+ u32 el;
+ bool need_swap;
+ int i, err;
- ath_dbg(common, EEPROM, "need_swap = %s\n",
- need_swap ? "True" : "False");
+ err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_DEF);
+ if (err)
+ return err;
if (need_swap)
- el = swab16(ah->eeprom.def.baseEepHeader.length);
+ el = swab16(eep->baseEepHeader.length);
else
- el = ah->eeprom.def.baseEepHeader.length;
+ el = eep->baseEepHeader.length;
- if (el > sizeof(struct ar5416_eeprom_def))
- el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
- else
- el = el / sizeof(u16);
-
- eepdata = (u16 *)(&ah->eeprom);
-
- for (i = 0; i < el; i++)
- sum ^= *eepdata++;
+ el = min(el / sizeof(u16), SIZE_EEPROM_DEF);
+ if (!ath9k_hw_nvram_validate_checksum(ah, el))
+ return -EINVAL;
if (need_swap) {
u32 integer, j;
u16 word;
- ath_dbg(common, EEPROM,
- "EEPROM Endianness is not native.. Changing.\n");
-
word = swab16(eep->baseEepHeader.length);
eep->baseEepHeader.length = word;
@@ -356,12 +326,9 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
}
}
- if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER ||
- ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) {
- ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
- sum, ah->eep_ops->get_eeprom_ver(ah));
+ if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER,
+ AR5416_EEP_NO_BACK_VER))
return -EINVAL;
- }
/* Enable fixup for AR_AN_TOP2 if necessary */
if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
@@ -376,6 +343,8 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
return 0;
}
+#undef SIZE_EEPROM_DEF
+
static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
enum eeprom_param param)
{
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index a680a970b7f7..fe1fd1a5ae15 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -834,7 +834,7 @@ void ath9k_htc_ani_work(struct work_struct *work)
if (longcal || shortcal)
common->ani.caldone =
ath9k_hw_calibrate(ah, ah->curchan,
- ah->rxchainmask, longcal);
+ ah->rxchainmask, longcal) > 0;
ath9k_htc_ps_restore(priv);
}
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index 2294709ee8b0..fd85f996c554 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -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
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 41382f89abe1..257f46ed4a04 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2299,10 +2299,10 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah,
else
nextTbtt = bs->bs_nexttbtt;
- ath_dbg(common, BEACON, "next DTIM %d\n", bs->bs_nextdtim);
- ath_dbg(common, BEACON, "next beacon %d\n", nextTbtt);
- ath_dbg(common, BEACON, "beacon period %d\n", beaconintval);
- ath_dbg(common, BEACON, "DTIM period %d\n", dtimperiod);
+ ath_dbg(common, BEACON, "next DTIM %u\n", bs->bs_nextdtim);
+ ath_dbg(common, BEACON, "next beacon %u\n", nextTbtt);
+ ath_dbg(common, BEACON, "beacon period %u\n", beaconintval);
+ ath_dbg(common, BEACON, "DTIM period %u\n", dtimperiod);
ENABLE_REGWRITE_BUFFER(ah);
@@ -2761,9 +2761,6 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits)
ENABLE_REGWRITE_BUFFER(ah);
- if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
- bits |= ATH9K_RX_FILTER_CONTROL_WRAPPER;
-
REG_WRITE(ah, AR_RX_FILTER, bits);
phybits = 0;
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 2e2b92ba96b8..ab7a1ac37849 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -828,6 +828,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
ieee80211_hw_set(hw, RX_INCLUDES_FCS);
ieee80211_hw_set(hw, HOST_BROADCAST_PS_BUFFERING);
ieee80211_hw_set(hw, SUPPORT_FAST_XMIT);
+ ieee80211_hw_set(hw, SUPPORTS_CLONED_SKBS);
if (ath9k_ps_enable)
ieee80211_hw_set(hw, SUPPORTS_PS);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index d184e682e636..c1b33fdcca08 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -739,6 +739,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
ath9k_ps_restore(sc);
+ ath9k_rng_start(sc);
+
return 0;
}
@@ -828,6 +830,8 @@ static void ath9k_stop(struct ieee80211_hw *hw)
ath9k_deinit_channel_context(sc);
+ ath9k_rng_stop(sc);
+
mutex_lock(&sc->mutex);
ath_cancel_work(sc);
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 994daf6c6297..32160fca876a 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -424,6 +424,9 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
AR_SREV_9561(sc->sc_ah))
rfilt |= ATH9K_RX_FILTER_4ADDRESS;
+ if (AR_SREV_9462(sc->sc_ah) || AR_SREV_9565(sc->sc_ah))
+ rfilt |= ATH9K_RX_FILTER_CONTROL_WRAPPER;
+
if (ath9k_is_chanctx_enabled() &&
test_bit(ATH_OP_SCANNING, &common->op_flags))
rfilt |= ATH9K_RX_FILTER_BEACON;
diff --git a/drivers/net/wireless/ath/ath9k/rng.c b/drivers/net/wireless/ath/ath9k/rng.c
new file mode 100644
index 000000000000..c9cb2aad7b6f
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/rng.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2015 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/hw_random.h>
+#include <linux/kthread.h>
+
+#include "ath9k.h"
+#include "hw.h"
+#include "ar9003_phy.h"
+
+#define ATH9K_RNG_BUF_SIZE 320
+#define ATH9K_RNG_ENTROPY(x) (((x) * 8 * 320) >> 10) /* quality: 320/1024 */
+
+static int ath9k_rng_data_read(struct ath_softc *sc, u32 *buf, u32 buf_size)
+{
+ int i, j;
+ u32 v1, v2, rng_last = sc->rng_last;
+ struct ath_hw *ah = sc->sc_ah;
+
+ ath9k_ps_wakeup(sc);
+
+ REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1);
+ REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5);
+ REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0);
+
+ for (i = 0, j = 0; i < buf_size; i++) {
+ v1 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff;
+ v2 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff;
+
+ /* wait for data ready */
+ if (v1 && v2 && rng_last != v1 && v1 != v2 && v1 != 0xffff &&
+ v2 != 0xffff)
+ buf[j++] = (v1 << 16) | v2;
+
+ rng_last = v2;
+ }
+
+ ath9k_ps_restore(sc);
+
+ sc->rng_last = rng_last;
+
+ return j << 2;
+}
+
+static int ath9k_rng_kthread(void *data)
+{
+ int bytes_read;
+ struct ath_softc *sc = data;
+ u32 *rng_buf;
+
+ rng_buf = kmalloc_array(ATH9K_RNG_BUF_SIZE, sizeof(u32), GFP_KERNEL);
+ if (!rng_buf)
+ goto out;
+
+ while (!kthread_should_stop()) {
+ bytes_read = ath9k_rng_data_read(sc, rng_buf,
+ ATH9K_RNG_BUF_SIZE);
+ if (unlikely(!bytes_read)) {
+ msleep_interruptible(10);
+ continue;
+ }
+
+ /* sleep until entropy bits under write_wakeup_threshold */
+ add_hwgenerator_randomness((void *)rng_buf, bytes_read,
+ ATH9K_RNG_ENTROPY(bytes_read));
+ }
+
+ kfree(rng_buf);
+out:
+ sc->rng_task = NULL;
+
+ return 0;
+}
+
+void ath9k_rng_start(struct ath_softc *sc)
+{
+ struct ath_hw *ah = sc->sc_ah;
+
+ if (sc->rng_task)
+ return;
+
+ if (!AR_SREV_9300_20_OR_LATER(ah))
+ return;
+
+ sc->rng_task = kthread_run(ath9k_rng_kthread, sc, "ath9k-hwrng");
+ if (IS_ERR(sc->rng_task))
+ sc->rng_task = NULL;
+}
+
+void ath9k_rng_stop(struct ath_softc *sc)
+{
+ if (sc->rng_task)
+ kthread_stop(sc->rng_task);
+}
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 3e3dac3d7060..fe795fc5288c 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1473,11 +1473,14 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
u16 tid, u16 *ssn)
{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_atx_tid *txtid;
struct ath_txq *txq;
struct ath_node *an;
u8 density;
+ ath_dbg(common, XMIT, "%s called\n", __func__);
+
an = (struct ath_node *)sta->drv_priv;
txtid = ATH_AN_2_TID(an, tid);
txq = txtid->txq;
@@ -1512,10 +1515,13 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_node *an = (struct ath_node *)sta->drv_priv;
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
struct ath_txq *txq = txtid->txq;
+ ath_dbg(common, XMIT, "%s called\n", __func__);
+
ath_txq_lock(sc, txq);
txtid->active = false;
ath_tx_flush_tid(sc, txtid);
@@ -1526,11 +1532,14 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
struct ath_node *an)
{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_atx_tid *tid;
struct ath_txq *txq;
bool buffered;
int tidno;
+ ath_dbg(common, XMIT, "%s called\n", __func__);
+
for (tidno = 0, tid = &an->tid[tidno];
tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
@@ -1555,10 +1564,13 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc,
void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_atx_tid *tid;
struct ath_txq *txq;
int tidno;
+ ath_dbg(common, XMIT, "%s called\n", __func__);
+
for (tidno = 0, tid = &an->tid[tidno];
tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
@@ -1579,10 +1591,13 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta,
u16 tidno)
{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_atx_tid *tid;
struct ath_node *an;
struct ath_txq *txq;
+ ath_dbg(common, XMIT, "%s called\n", __func__);
+
an = (struct ath_node *)sta->drv_priv;
tid = ATH_AN_2_TID(an, tidno);
txq = tid->txq;
@@ -2316,6 +2331,12 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
queue = ieee80211_is_data_present(hdr->frame_control);
+ /* If chanctx, queue all null frames while NOA could be there */
+ if (ath9k_is_chanctx_enabled() &&
+ ieee80211_is_nullfunc(hdr->frame_control) &&
+ !txctl->force_channel)
+ queue = true;
+
/* Force queueing of all frames that belong to a virtual interface on
* a different channel context, to ensure that they are sent on the
* correct channel.
@@ -2894,7 +2915,7 @@ int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb,
if (skb_headroom(skb) < padsize) {
ath_dbg(common, XMIT,
"tx99 padding failed\n");
- return -EINVAL;
+ return -EINVAL;
}
skb_push(skb, padsize);
diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c
index f8dfa05b290a..8643801f31b6 100644
--- a/drivers/net/wireless/ath/wcn36xx/dxe.c
+++ b/drivers/net/wireless/ath/wcn36xx/dxe.c
@@ -474,36 +474,37 @@ static int wcn36xx_rx_handle_packets(struct wcn36xx *wcn,
struct wcn36xx_dxe_desc *dxe = ctl->desc;
dma_addr_t dma_addr;
struct sk_buff *skb;
+ int ret = 0, int_mask;
+ u32 value;
+
+ if (ch->ch_type == WCN36XX_DXE_CH_RX_L) {
+ value = WCN36XX_DXE_CTRL_RX_L;
+ int_mask = WCN36XX_DXE_INT_CH1_MASK;
+ } else {
+ value = WCN36XX_DXE_CTRL_RX_H;
+ int_mask = WCN36XX_DXE_INT_CH3_MASK;
+ }
while (!(dxe->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)) {
skb = ctl->skb;
dma_addr = dxe->dst_addr_l;
- wcn36xx_dxe_fill_skb(wcn->dev, ctl);
-
- switch (ch->ch_type) {
- case WCN36XX_DXE_CH_RX_L:
- dxe->ctrl = WCN36XX_DXE_CTRL_RX_L;
- wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR,
- WCN36XX_DXE_INT_CH1_MASK);
- break;
- case WCN36XX_DXE_CH_RX_H:
- dxe->ctrl = WCN36XX_DXE_CTRL_RX_H;
- wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR,
- WCN36XX_DXE_INT_CH3_MASK);
- break;
- default:
- wcn36xx_warn("Unknown channel\n");
- }
-
- dma_unmap_single(wcn->dev, dma_addr, WCN36XX_PKT_SIZE,
- DMA_FROM_DEVICE);
- wcn36xx_rx_skb(wcn, skb);
+ ret = wcn36xx_dxe_fill_skb(wcn->dev, ctl);
+ if (0 == ret) {
+ /* new skb allocation ok. Use the new one and queue
+ * the old one to network system.
+ */
+ dma_unmap_single(wcn->dev, dma_addr, WCN36XX_PKT_SIZE,
+ DMA_FROM_DEVICE);
+ wcn36xx_rx_skb(wcn, skb);
+ } /* else keep old skb not submitted and use it for rx DMA */
+
+ dxe->ctrl = value;
ctl = ctl->next;
dxe = ctl->desc;
}
+ wcn36xx_dxe_write_register(wcn, WCN36XX_DXE_ENCH_ADDR, int_mask);
ch->head_blk_ctl = ctl;
-
return 0;
}
diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h
index a1f1127d7808..b947de0fb2e5 100644
--- a/drivers/net/wireless/ath/wcn36xx/hal.h
+++ b/drivers/net/wireless/ath/wcn36xx/hal.h
@@ -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
};
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index c9263e1c75d4..74f56a81ad9a 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -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,
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h
index 008d03423dbf..8361f9e3995b 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.h
+++ b/drivers/net/wireless/ath/wcn36xx/smd.h
@@ -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;
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index 50c136e843c4..4f2ffa5c6e17 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -394,9 +394,13 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
wil_fw_core_dump(wil);
wil_notify_fw_error(wil);
isr &= ~ISR_MISC_FW_ERROR;
- wil_fw_error_recovery(wil);
+ if (wil->platform_ops.notify_crash) {
+ wil_err(wil, "notify platform driver about FW crash");
+ wil->platform_ops.notify_crash(wil->platform_handle);
+ } else {
+ wil_fw_error_recovery(wil);
+ }
}
-
if (isr & ISR_MISC_MBOX_EVT) {
wil_dbg_irq(wil, "MBOX event\n");
wmi_recv_cmd(wil);
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index bb69a5949aea..b39f0bfc591e 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -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)
@@ -773,8 +781,10 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
wil_bcast_fini(wil);
- /* prevent NAPI from being scheduled */
+ /* prevent NAPI from being scheduled and prevent wmi commands */
+ mutex_lock(&wil->wmi_mutex);
bitmap_zero(wil->status, wil_status_last);
+ mutex_unlock(&wil->wmi_mutex);
if (wil->scan_request) {
wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
@@ -977,7 +987,7 @@ int __wil_down(struct wil6210_priv *wil)
}
mutex_lock(&wil->mutex);
- if (!iter)
+ if (iter < 0)
wil_err(wil, "timeout waiting for idle FW/HW\n");
wil_reset(wil, false);
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index 1a3142c332e1..e36f2a0c8cb6 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
+ * Copyright (c) 2012-2015 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -125,11 +125,37 @@ static int wil_if_pcie_disable(struct wil6210_priv *wil)
return 0;
}
+static int wil_platform_rop_ramdump(void *wil_handle, void *buf, uint32_t size)
+{
+ struct wil6210_priv *wil = wil_handle;
+
+ if (!wil)
+ return -EINVAL;
+
+ return wil_fw_copy_crash_dump(wil, buf, size);
+}
+
+static int wil_platform_rop_fw_recovery(void *wil_handle)
+{
+ struct wil6210_priv *wil = wil_handle;
+
+ if (!wil)
+ return -EINVAL;
+
+ wil_fw_error_recovery(wil);
+
+ return 0;
+}
+
static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct wil6210_priv *wil;
struct device *dev = &pdev->dev;
int rc;
+ const struct wil_platform_rops rops = {
+ .ramdump = wil_platform_rop_ramdump,
+ .fw_recovery = wil_platform_rop_fw_recovery,
+ };
/* check HW */
dev_info(&pdev->dev, WIL_NAME
@@ -154,7 +180,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* rollback to if_free */
wil->platform_handle =
- wil_platform_init(&pdev->dev, &wil->platform_ops);
+ wil_platform_init(&pdev->dev, &wil->platform_ops, &rops, wil);
if (!wil->platform_handle) {
rc = -ENODEV;
wil_err(wil, "wil_platform_init failed\n");
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c
index e3d1be82f314..32031e7a11d5 100644
--- a/drivers/net/wireless/ath/wil6210/rx_reorder.c
+++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c
@@ -261,9 +261,19 @@ struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil,
void wil_tid_ampdu_rx_free(struct wil6210_priv *wil,
struct wil_tid_ampdu_rx *r)
{
+ int i;
+
if (!r)
return;
- wil_release_reorder_frames(wil, r, r->head_seq_num + r->buf_size);
+
+ /* Do not pass remaining frames to the network stack - it may be
+ * not expecting to get any more Rx. Rx from here may lead to
+ * kernel OOPS since some per-socket accounting info was already
+ * released.
+ */
+ for (i = 0; i < r->buf_size; i++)
+ kfree_skb(r->reorder_buf[i]);
+
kfree(r->reorder_buf);
kfree(r->reorder_time);
kfree(r);
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 3bc9bc0efbac..7887e6cfd817 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -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;
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index ade5f3b8274b..235e205ce2bc 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -828,6 +828,7 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime);
int wil_suspend(struct wil6210_priv *wil, bool is_runtime);
int wil_resume(struct wil6210_priv *wil, bool is_runtime);
+int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size);
void wil_fw_core_dump(struct wil6210_priv *wil);
#endif /* __WIL6210_H__ */
diff --git a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
index 7e70934990ae..b57d280946e0 100644
--- a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
+++ b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c
@@ -51,8 +51,7 @@ static int wil_fw_get_crash_dump_bounds(struct wil6210_priv *wil,
return 0;
}
-static int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest,
- u32 size)
+int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size)
{
int i;
const struct fw_map *map;
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.c b/drivers/net/wireless/ath/wil6210/wil_platform.c
index 2e831bf20117..4eed05bddb60 100644
--- a/drivers/net/wireless/ath/wil6210/wil_platform.c
+++ b/drivers/net/wireless/ath/wil6210/wil_platform.c
@@ -33,7 +33,8 @@ void wil_platform_modexit(void)
* It returns a handle which is used with the rest of the API
*
*/
-void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops)
+void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops,
+ const struct wil_platform_rops *rops, void *wil_handle)
{
void *handle = ops; /* to return some non-NULL for 'void' impl. */
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.h b/drivers/net/wireless/ath/wil6210/wil_platform.h
index d7fa19b7886d..9a949d910343 100644
--- a/drivers/net/wireless/ath/wil6210/wil_platform.h
+++ b/drivers/net/wireless/ath/wil6210/wil_platform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 Qualcomm Atheros, Inc.
+ * Copyright (c) 2014-2015 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -20,16 +20,48 @@
struct device;
/**
- * struct wil_platform_ops - wil platform module callbacks
+ * struct wil_platform_ops - wil platform module calls from this
+ * driver to platform driver
*/
struct wil_platform_ops {
int (*bus_request)(void *handle, uint32_t kbps /* KBytes/Sec */);
int (*suspend)(void *handle);
int (*resume)(void *handle);
void (*uninit)(void *handle);
+ int (*notify_crash)(void *handle);
};
-void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops);
+/**
+ * struct wil_platform_rops - wil platform module callbacks from
+ * platform driver to this driver
+ * @ramdump: store a ramdump from the wil firmware. The platform
+ * driver may add additional data to the ramdump to
+ * generate the final crash dump.
+ * @fw_recovery: start a firmware recovery process. Called as
+ * part of a crash recovery process which may include other
+ * related platform subsystems.
+ */
+struct wil_platform_rops {
+ int (*ramdump)(void *wil_handle, void *buf, uint32_t size);
+ int (*fw_recovery)(void *wil_handle);
+};
+
+/**
+ * wil_platform_init - initialize the platform driver
+ *
+ * @dev - pointer to the wil6210 device
+ * @ops - structure with platform driver operations. Platform
+ * driver will fill this structure with function pointers.
+ * @rops - structure with callbacks from platform driver to
+ * this driver. The platform driver copies the structure to
+ * its own storage. Can be NULL if this driver does not
+ * support crash recovery.
+ * @wil_handle - context for this driver that will be passed
+ * when platform driver invokes one of the callbacks in
+ * rops. May be NULL if rops is NULL.
+ */
+void *wil_platform_init(struct device *dev, struct wil_platform_ops *ops,
+ const struct wil_platform_rops *rops, void *wil_handle);
int __init wil_platform_modinit(void);
void wil_platform_modexit(void);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 6ed26baca0e5..e3ea74cdd4aa 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -228,6 +228,10 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
wil_dbg_wmi(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head);
/* wait till FW finish with previous command */
for (retry = 5; retry > 0; retry--) {
+ if (!test_bit(wil_status_fwready, wil->status)) {
+ wil_err(wil, "WMI: cannot send command while FW not ready\n");
+ return -EAGAIN;
+ }
r->tail = wil_r(wil, RGF_MBOX +
offsetof(struct wil6210_mbox_ctl, tx.tail));
if (next_head != r->tail)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
index 288c84e7c56b..6af658e443e4 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
@@ -187,7 +187,8 @@ retry:
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;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 410a6645d316..53637399bb99 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -47,6 +47,8 @@
#include "debug.h"
#include "sdio.h"
#include "of.h"
+#include "core.h"
+#include "common.h"
#define SDIOH_API_ACCESS_RETRY_LIMIT 2
@@ -57,7 +59,6 @@
/* Maximum milliseconds to wait for F2 to come up */
#define SDIO_WAIT_F2RDY 3000
-#define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */
#define BRCMF_DEFAULT_RXGLOM_SIZE 32 /* max rx frames in glom chain */
struct brcmf_sdiod_freezer {
@@ -68,10 +69,6 @@ struct brcmf_sdiod_freezer {
struct completion resumed;
};
-static int brcmf_sdiod_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE;
-module_param_named(txglomsz, brcmf_sdiod_txglomsz, int, 0);
-MODULE_PARM_DESC(txglomsz, "maximum tx packet chain size [SDIO]");
-
static irqreturn_t brcmf_sdiod_oob_irqhandler(int irq, void *dev_id)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev_id);
@@ -890,7 +887,8 @@ static void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev)
if (!sdiodev->sg_support)
return;
- nents = max_t(uint, BRCMF_DEFAULT_RXGLOM_SIZE, brcmf_sdiod_txglomsz);
+ nents = max_t(uint, BRCMF_DEFAULT_RXGLOM_SIZE,
+ sdiodev->bus_if->drvr->settings->sdiod_txglomsz);
nents += (nents >> 4) + 1;
WARN_ON(nents > sdiodev->max_segment_count);
@@ -902,7 +900,7 @@ static void brcmf_sdiod_sgtable_alloc(struct brcmf_sdio_dev *sdiodev)
sdiodev->sg_support = false;
}
- sdiodev->txglomsz = brcmf_sdiod_txglomsz;
+ sdiodev->txglomsz = sdiodev->bus_if->drvr->settings->sdiod_txglomsz;
}
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
index 230cad788ace..36093f93bfbe 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -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;
};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index deb5f78dcacc..6a7759fcbd86 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -91,6 +91,10 @@
#define BRCMF_SCAN_JOIN_PASSIVE_DWELL_TIME_MS 400
#define BRCMF_SCAN_JOIN_PROBE_INTERVAL_MS 20
+#define BRCMF_SCAN_CHANNEL_TIME 40
+#define BRCMF_SCAN_UNASSOC_TIME 40
+#define BRCMF_SCAN_PASSIVE_TIME 120
+
#define BRCMF_ASSOC_PARAMS_FIXED_SIZE \
(sizeof(struct brcmf_assoc_params_le) - sizeof(u16))
@@ -232,10 +236,6 @@ struct parsed_vndr_ies {
struct parsed_vndr_ie_info ie_info[VNDR_IE_PARSE_LIMIT];
};
-static int brcmf_roamoff;
-module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR);
-MODULE_PARM_DESC(roamoff, "do not use internal roaming engine");
-
static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
struct cfg80211_chan_def *ch)
@@ -392,15 +392,23 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,
{
int iftype_num[NUM_NL80211_IFTYPES];
struct brcmf_cfg80211_vif *pos;
+ bool check_combos = false;
+ int ret = 0;
memset(&iftype_num[0], 0, sizeof(iftype_num));
list_for_each_entry(pos, &cfg->vif_list, list)
- if (pos == vif)
+ if (pos == vif) {
iftype_num[new_type]++;
- else
+ } else {
+ /* concurrent interfaces so need check combinations */
+ check_combos = true;
iftype_num[pos->wdev.iftype]++;
+ }
- return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
+ if (check_combos)
+ ret = cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
+
+ return ret;
}
static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg,
@@ -776,7 +784,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 +954,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 +968,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 +979,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 +1021,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;
@@ -1026,11 +1035,11 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
struct brcmf_if *ifp = vif->ifp;
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct cfg80211_ssid *ssids;
- struct brcmf_cfg80211_scan_req *sr = &cfg->scan_req_int;
u32 passive_scan;
bool escan_req;
bool spec_scan;
s32 err;
+ struct brcmf_ssid_le ssid_le;
u32 SSID_len;
brcmf_dbg(SCAN, "START ESCAN\n");
@@ -1083,13 +1092,13 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
} else {
brcmf_dbg(SCAN, "ssid \"%s\", ssid_len (%d)\n",
ssids->ssid, ssids->ssid_len);
- memset(&sr->ssid_le, 0, sizeof(sr->ssid_le));
- SSID_len = min_t(u8, sizeof(sr->ssid_le.SSID), ssids->ssid_len);
- sr->ssid_le.SSID_len = cpu_to_le32(0);
+ memset(&ssid_le, 0, sizeof(ssid_le));
+ SSID_len = min_t(u8, sizeof(ssid_le.SSID), ssids->ssid_len);
+ ssid_le.SSID_len = cpu_to_le32(0);
spec_scan = false;
if (SSID_len) {
- memcpy(sr->ssid_le.SSID, ssids->ssid, SSID_len);
- sr->ssid_le.SSID_len = cpu_to_le32(SSID_len);
+ memcpy(ssid_le.SSID, ssids->ssid, SSID_len);
+ ssid_le.SSID_len = cpu_to_le32(SSID_len);
spec_scan = true;
} else
brcmf_dbg(SCAN, "Broadcast scan\n");
@@ -1102,12 +1111,12 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct brcmf_cfg80211_vif *vif,
goto scan_out;
}
brcmf_scan_config_mpc(ifp, 0);
- err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN,
- &sr->ssid_le, sizeof(sr->ssid_le));
+ err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, &ssid_le,
+ sizeof(ssid_le));
if (err) {
if (err == -EBUSY)
brcmf_dbg(INFO, "BUSY: scan for \"%s\" canceled\n",
- sr->ssid_le.SSID);
+ ssid_le.SSID);
else
brcmf_err("WLC_SCAN error (%d)\n", err);
@@ -1260,17 +1269,17 @@ static void brcmf_link_down(struct brcmf_cfg80211_vif *vif, u16 reason)
brcmf_dbg(TRACE, "Enter\n");
- if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state)) {
+ if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state)) {
brcmf_dbg(INFO, "Call WLC_DISASSOC to stop excess roaming\n ");
err = brcmf_fil_cmd_data_set(vif->ifp,
BRCMF_C_DISASSOC, NULL, 0);
if (err) {
brcmf_err("WLC_DISASSOC failed (%d)\n", err);
}
- clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state);
- cfg80211_disconnected(vif->wdev.netdev, reason, NULL, 0,
- true, GFP_KERNEL);
-
+ if ((vif->wdev.iftype == NL80211_IFTYPE_STATION) ||
+ (vif->wdev.iftype == NL80211_IFTYPE_P2P_CLIENT))
+ cfg80211_disconnected(vif->wdev.netdev, reason, NULL, 0,
+ true, GFP_KERNEL);
}
clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
@@ -1291,6 +1300,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 +1378,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);
@@ -1436,8 +1444,13 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev)
struct brcmf_if *ifp = netdev_priv(ndev);
brcmf_dbg(TRACE, "Enter\n");
- if (!check_vif_up(ifp->vif))
- return -EIO;
+ if (!check_vif_up(ifp->vif)) {
+ /* When driver is being unloaded, it can end up here. If an
+ * error is returned then later on a debug trace in the wireless
+ * core module will be printed. To avoid this 0 is returned.
+ */
+ return 0;
+ }
brcmf_link_down(ifp->vif, WLAN_REASON_DEAUTH_LEAVING);
@@ -1728,7 +1741,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 +1751,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 +1837,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 +1849,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 +1902,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);
@@ -2423,6 +2430,54 @@ static void brcmf_fill_bss_param(struct brcmf_if *ifp, struct station_info *si)
}
static s32
+brcmf_cfg80211_get_station_ibss(struct brcmf_if *ifp,
+ struct station_info *sinfo)
+{
+ struct brcmf_scb_val_le scbval;
+ struct brcmf_pktcnt_le pktcnt;
+ s32 err;
+ u32 rate;
+ u32 rssi;
+
+ /* Get the current tx rate */
+ err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate);
+ if (err < 0) {
+ brcmf_err("BRCMF_C_GET_RATE error (%d)\n", err);
+ return err;
+ }
+ sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE);
+ sinfo->txrate.legacy = rate * 5;
+
+ memset(&scbval, 0, sizeof(scbval));
+ err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI, &scbval,
+ sizeof(scbval));
+ if (err) {
+ brcmf_err("BRCMF_C_GET_RSSI error (%d)\n", err);
+ return err;
+ }
+ rssi = le32_to_cpu(scbval.val);
+ sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
+ sinfo->signal = rssi;
+
+ err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_GET_PKTCNTS, &pktcnt,
+ sizeof(pktcnt));
+ if (err) {
+ brcmf_err("BRCMF_C_GET_GET_PKTCNTS error (%d)\n", err);
+ return err;
+ }
+ sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS) |
+ BIT(NL80211_STA_INFO_RX_DROP_MISC) |
+ BIT(NL80211_STA_INFO_TX_PACKETS) |
+ BIT(NL80211_STA_INFO_TX_FAILED);
+ sinfo->rx_packets = le32_to_cpu(pktcnt.rx_good_pkt);
+ sinfo->rx_dropped_misc = le32_to_cpu(pktcnt.rx_bad_pkt);
+ sinfo->tx_packets = le32_to_cpu(pktcnt.tx_good_pkt);
+ sinfo->tx_failed = le32_to_cpu(pktcnt.tx_bad_pkt);
+
+ return 0;
+}
+
+static s32
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
const u8 *mac, struct station_info *sinfo)
{
@@ -2439,6 +2494,9 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
if (!check_vif_up(ifp->vif))
return -EIO;
+ if (brcmf_is_ibssmode(ifp->vif))
+ return brcmf_cfg80211_get_station_ibss(ifp, sinfo);
+
memset(&sta_info_le, 0, sizeof(sta_info_le));
memcpy(&sta_info_le, mac, ETH_ALEN);
err = brcmf_fil_iovar_data_get(ifp, "tdls_sta_info",
@@ -2691,8 +2749,8 @@ static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg)
return err;
}
-static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
- struct net_device *ndev, const u8 *bssid)
+static s32 brcmf_inform_ibss(struct brcmf_cfg80211_info *cfg,
+ struct net_device *ndev, const u8 *bssid)
{
struct wiphy *wiphy = cfg_to_wiphy(cfg);
struct ieee80211_channel *notify_channel;
@@ -2737,6 +2795,7 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg,
band = wiphy->bands[IEEE80211_BAND_5GHZ];
freq = ieee80211_channel_to_frequency(ch.chnum, band->band);
+ cfg->channel = freq;
notify_channel = ieee80211_get_channel(wiphy, freq);
notify_capability = le16_to_cpu(bi->capability);
@@ -2775,9 +2834,7 @@ CleanUp:
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 +2846,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 +2976,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 +3116,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 +3186,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 +3225,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);
@@ -3166,26 +3284,22 @@ exit:
}
static __used s32
-brcmf_update_pmklist(struct net_device *ndev,
- struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
+brcmf_update_pmklist(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp)
{
- int i, j;
- u32 pmkid_len;
+ struct brcmf_pmk_list_le *pmk_list;
+ int i;
+ u32 npmk;
+ s32 err;
- pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
+ pmk_list = &cfg->pmk_list;
+ npmk = le32_to_cpu(pmk_list->npmk);
- brcmf_dbg(CONN, "No of elements %d\n", pmkid_len);
- for (i = 0; i < pmkid_len; i++) {
- brcmf_dbg(CONN, "PMKID[%d]: %pM =\n", i,
- &pmk_list->pmkids.pmkid[i].BSSID);
- for (j = 0; j < WLAN_PMKID_LEN; j++)
- brcmf_dbg(CONN, "%02x\n",
- pmk_list->pmkids.pmkid[i].PMKID[j]);
- }
+ brcmf_dbg(CONN, "No of elements %d\n", npmk);
+ for (i = 0; i < npmk; i++)
+ brcmf_dbg(CONN, "PMK[%d]: %pM\n", i, &pmk_list->pmk[i].bssid);
- if (!err)
- brcmf_fil_iovar_data_set(netdev_priv(ndev), "pmkid_info",
- (char *)pmk_list, sizeof(*pmk_list));
+ err = brcmf_fil_iovar_data_set(ifp, "pmkid_info", pmk_list,
+ sizeof(*pmk_list));
return err;
}
@@ -3196,34 +3310,37 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
- struct pmkid_list *pmkids = &cfg->pmk_list->pmkids;
- s32 err = 0;
- u32 pmkid_len, i;
+ struct brcmf_pmksa *pmk = &cfg->pmk_list.pmk[0];
+ s32 err;
+ u32 npmk, i;
brcmf_dbg(TRACE, "Enter\n");
if (!check_vif_up(ifp->vif))
return -EIO;
- pmkid_len = le32_to_cpu(pmkids->npmkid);
- for (i = 0; i < pmkid_len; i++)
- if (!memcmp(pmksa->bssid, pmkids->pmkid[i].BSSID, ETH_ALEN))
+ npmk = le32_to_cpu(cfg->pmk_list.npmk);
+ for (i = 0; i < npmk; i++)
+ if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN))
break;
- if (i < WL_NUM_PMKIDS_MAX) {
- memcpy(pmkids->pmkid[i].BSSID, pmksa->bssid, ETH_ALEN);
- memcpy(pmkids->pmkid[i].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
- if (i == pmkid_len) {
- pmkid_len++;
- pmkids->npmkid = cpu_to_le32(pmkid_len);
+ if (i < BRCMF_MAXPMKID) {
+ memcpy(pmk[i].bssid, pmksa->bssid, ETH_ALEN);
+ memcpy(pmk[i].pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
+ if (i == npmk) {
+ npmk++;
+ cfg->pmk_list.npmk = cpu_to_le32(npmk);
}
- } else
- err = -EINVAL;
+ } else {
+ brcmf_err("Too many PMKSA entries cached %d\n", npmk);
+ return -EINVAL;
+ }
- brcmf_dbg(CONN, "set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
- pmkids->pmkid[pmkid_len].BSSID);
- for (i = 0; i < WLAN_PMKID_LEN; i++)
- brcmf_dbg(CONN, "%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]);
+ brcmf_dbg(CONN, "set_pmksa - PMK bssid: %pM =\n", pmk[npmk].bssid);
+ for (i = 0; i < WLAN_PMKID_LEN; i += 4)
+ brcmf_dbg(CONN, "%02x %02x %02x %02x\n", pmk[npmk].pmkid[i],
+ pmk[npmk].pmkid[i + 1], pmk[npmk].pmkid[i + 2],
+ pmk[npmk].pmkid[i + 3]);
- err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
+ err = brcmf_update_pmklist(cfg, ifp);
brcmf_dbg(TRACE, "Exit\n");
return err;
@@ -3231,50 +3348,39 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
static s32
brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
- struct cfg80211_pmksa *pmksa)
+ struct cfg80211_pmksa *pmksa)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
- struct pmkid_list pmkid;
- s32 err = 0;
- u32 pmkid_len, i;
+ struct brcmf_pmksa *pmk = &cfg->pmk_list.pmk[0];
+ s32 err;
+ u32 npmk, i;
brcmf_dbg(TRACE, "Enter\n");
if (!check_vif_up(ifp->vif))
return -EIO;
- memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
- memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
+ brcmf_dbg(CONN, "del_pmksa - PMK bssid = %pM\n", &pmksa->bssid);
- brcmf_dbg(CONN, "del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
- &pmkid.pmkid[0].BSSID);
- for (i = 0; i < WLAN_PMKID_LEN; i++)
- brcmf_dbg(CONN, "%02x\n", pmkid.pmkid[0].PMKID[i]);
-
- pmkid_len = le32_to_cpu(cfg->pmk_list->pmkids.npmkid);
- for (i = 0; i < pmkid_len; i++)
- if (!memcmp
- (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
- ETH_ALEN))
+ npmk = le32_to_cpu(cfg->pmk_list.npmk);
+ for (i = 0; i < npmk; i++)
+ if (!memcmp(&pmksa->bssid, &pmk[i].bssid, ETH_ALEN))
break;
- if ((pmkid_len > 0)
- && (i < pmkid_len)) {
- memset(&cfg->pmk_list->pmkids.pmkid[i], 0,
- sizeof(struct pmkid));
- for (; i < (pmkid_len - 1); i++) {
- memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID,
- &cfg->pmk_list->pmkids.pmkid[i + 1].BSSID,
- ETH_ALEN);
- memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID,
- &cfg->pmk_list->pmkids.pmkid[i + 1].PMKID,
+ if ((npmk > 0) && (i < npmk)) {
+ for (; i < (npmk - 1); i++) {
+ memcpy(&pmk[i].bssid, &pmk[i + 1].bssid, ETH_ALEN);
+ memcpy(&pmk[i].pmkid, &pmk[i + 1].pmkid,
WLAN_PMKID_LEN);
}
- cfg->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1);
- } else
- err = -EINVAL;
+ memset(&pmk[i], 0, sizeof(*pmk));
+ cfg->pmk_list.npmk = cpu_to_le32(npmk - 1);
+ } else {
+ brcmf_err("Cache entry not found\n");
+ return -EINVAL;
+ }
- err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
+ err = brcmf_update_pmklist(cfg, ifp);
brcmf_dbg(TRACE, "Exit\n");
return err;
@@ -3286,14 +3392,14 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
- s32 err = 0;
+ s32 err;
brcmf_dbg(TRACE, "Enter\n");
if (!check_vif_up(ifp->vif))
return -EIO;
- memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
- err = brcmf_update_pmklist(ndev, cfg->pmk_list, err);
+ memset(&cfg->pmk_list, 0, sizeof(cfg->pmk_list));
+ err = brcmf_update_pmklist(cfg, ifp);
brcmf_dbg(TRACE, "Exit\n");
return err;
@@ -3439,9 +3545,14 @@ static int brcmf_dev_pno_clean(struct net_device *ndev)
return ret;
}
-static int brcmf_dev_pno_config(struct net_device *ndev)
+static int brcmf_dev_pno_config(struct brcmf_if *ifp,
+ struct cfg80211_sched_scan_request *request)
{
struct brcmf_pno_param_le pfn_param;
+ struct brcmf_pno_macaddr_le pfn_mac;
+ s32 err;
+ u8 *mac_mask;
+ int i;
memset(&pfn_param, 0, sizeof(pfn_param));
pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION);
@@ -3454,8 +3565,37 @@ static int brcmf_dev_pno_config(struct net_device *ndev)
/* set up pno scan fr */
pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME);
- return brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfn_set",
- &pfn_param, sizeof(pfn_param));
+ err = brcmf_fil_iovar_data_set(ifp, "pfn_set", &pfn_param,
+ sizeof(pfn_param));
+ if (err) {
+ brcmf_err("pfn_set failed, err=%d\n", err);
+ return err;
+ }
+
+ /* Find out if mac randomization should be turned on */
+ if (!(request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR))
+ return 0;
+
+ pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
+ pfn_mac.flags = BRCMF_PFN_MAC_OUI_ONLY | BRCMF_PFN_SET_MAC_UNASSOC;
+
+ memcpy(pfn_mac.mac, request->mac_addr, ETH_ALEN);
+ mac_mask = request->mac_addr_mask;
+ for (i = 0; i < ETH_ALEN; i++) {
+ pfn_mac.mac[i] &= mac_mask[i];
+ pfn_mac.mac[i] |= get_random_int() & ~(mac_mask[i]);
+ }
+ /* Clear multi bit */
+ pfn_mac.mac[0] &= 0xFE;
+ /* Set locally administered */
+ pfn_mac.mac[0] |= 0x02;
+
+ err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac,
+ sizeof(pfn_mac));
+ if (err)
+ brcmf_err("pfn_macaddr failed, err=%d\n", err);
+
+ return err;
}
static int
@@ -3509,11 +3649,8 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
}
/* configure pno */
- ret = brcmf_dev_pno_config(ndev);
- if (ret < 0) {
- brcmf_err("PNO setup failed!! ret=%d\n", ret);
+ if (brcmf_dev_pno_config(ifp, request))
return -EINVAL;
- }
/* configure each match set */
for (i = 0; i < request->n_match_sets; i++) {
@@ -3877,7 +4014,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 +4321,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 +4379,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 +4446,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 +4840,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);
@@ -5016,9 +5155,9 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
} else if (brcmf_is_linkup(e)) {
brcmf_dbg(CONN, "Linkup\n");
if (brcmf_is_ibssmode(ifp->vif)) {
+ brcmf_inform_ibss(cfg, ndev, e->addr);
chan = ieee80211_get_channel(cfg->wiphy, cfg->channel);
memcpy(profile->bssid, e->addr, ETH_ALEN);
- wl_inform_ibss(cfg, ndev, e->addr);
cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL);
clear_bit(BRCMF_VIF_STATUS_CONNECTING,
&ifp->vif->sme_state);
@@ -5092,9 +5231,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;
@@ -5144,7 +5283,6 @@ static void brcmf_init_conf(struct brcmf_cfg80211_conf *conf)
conf->rts_threshold = (u32)-1;
conf->retry_short = (u32)-1;
conf->retry_long = (u32)-1;
- conf->tx_power = -1;
}
static void brcmf_register_event_handlers(struct brcmf_cfg80211_info *cfg)
@@ -5191,8 +5329,6 @@ static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg)
cfg->escan_ioctl_buf = NULL;
kfree(cfg->extra_buf);
cfg->extra_buf = NULL;
- kfree(cfg->pmk_list);
- cfg->pmk_list = NULL;
}
static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg)
@@ -5206,9 +5342,6 @@ static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg)
cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
if (!cfg->extra_buf)
goto init_priv_mem_out;
- cfg->pmk_list = kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
- if (!cfg->pmk_list)
- goto init_priv_mem_out;
return 0;
@@ -5250,35 +5383,34 @@ 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 (ifp->drvr->settings->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));
+ ifp->drvr->settings->roamoff ? "Off" : "On");
+ err = brcmf_fil_iovar_int_set(ifp, "roam_off",
+ ifp->drvr->settings->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 +5419,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,45 +5428,35 @@ 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;
}
static s32
-brcmf_dongle_scantime(struct brcmf_if *ifp, s32 scan_assoc_time,
- s32 scan_unassoc_time, s32 scan_passive_time)
+brcmf_dongle_scantime(struct brcmf_if *ifp)
{
s32 err = 0;
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
- scan_assoc_time);
+ BRCMF_SCAN_CHANNEL_TIME);
if (err) {
- if (err == -EOPNOTSUPP)
- brcmf_dbg(INFO, "Scan assoc time is not supported\n");
- else
- brcmf_err("Scan assoc time error (%d)\n", err);
+ brcmf_err("Scan assoc time error (%d)\n", err);
goto dongle_scantime_out;
}
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
- scan_unassoc_time);
+ BRCMF_SCAN_UNASSOC_TIME);
if (err) {
- if (err == -EOPNOTSUPP)
- brcmf_dbg(INFO, "Scan unassoc time is not supported\n");
- else
- brcmf_err("Scan unassoc time error (%d)\n", err);
+ brcmf_err("Scan unassoc time error (%d)\n", err);
goto dongle_scantime_out;
}
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME,
- scan_passive_time);
+ BRCMF_SCAN_PASSIVE_TIME);
if (err) {
- if (err == -EOPNOTSUPP)
- brcmf_dbg(INFO, "Scan passive time is not supported\n");
- else
- brcmf_err("Scan passive time error (%d)\n", err);
+ brcmf_err("Scan passive time error (%d)\n", err);
goto dongle_scantime_out;
}
@@ -5619,7 +5741,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 +5761,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 +5794,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 +5825,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 +5842,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;
@@ -5893,7 +6047,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
wiphy->max_scan_ie_len = BRCMF_SCAN_IE_LEN_MAX;
- wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
+ wiphy->max_num_pmkids = BRCMF_MAXPMKID;
err = brcmf_setup_ifmodes(wiphy, ifp);
if (err)
@@ -5922,9 +6076,10 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
WIPHY_FLAG_OFFCHAN_TX |
- WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
- WIPHY_FLAG_SUPPORTS_TDLS;
- if (!brcmf_roamoff)
+ WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_TDLS))
+ wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
+ if (!ifp->drvr->settings->roamoff)
wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
wiphy->mgmt_stypes = brcmf_txrx_stypes;
wiphy->max_remain_on_channel_duration = 5000;
@@ -6004,8 +6159,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
/* make sure RF is ready for work */
brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
- brcmf_dongle_scantime(ifp, WL_SCAN_CHANNEL_TIME,
- WL_SCAN_UNASSOC_TIME, WL_SCAN_PASSIVE_TIME);
+ brcmf_dongle_scantime(ifp);
power_mode = cfg->pwr_save ? PM_FAST : PM_OFF;
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, power_mode);
@@ -6014,7 +6168,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,
@@ -6316,13 +6470,15 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
goto wiphy_unreg_out;
}
- err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
- if (err) {
- brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
- wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
- } else {
- brcmf_fweh_register(cfg->pub, BRCMF_E_TDLS_PEER_EVENT,
- brcmf_notify_tdls_peer_event);
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_TDLS)) {
+ err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
+ if (err) {
+ brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
+ wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
+ } else {
+ brcmf_fweh_register(cfg->pub, BRCMF_E_TDLS_PEER_EVENT,
+ brcmf_notify_tdls_peer_event);
+ }
}
/* (re-) activate FWEH event handling */
@@ -6332,6 +6488,15 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
goto wiphy_unreg_out;
}
+ /* Fill in some of the advertised nl80211 supported features */
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_SCAN_RANDOM_MAC)) {
+ wiphy->features |= NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
+#ifdef CONFIG_PM
+ if (wiphy->wowlan->flags & WIPHY_WOWLAN_NET_DETECT)
+ wiphy->features |= NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
+#endif
+ }
+
return cfg;
wiphy_unreg_out:
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
index 6a878c8f883f..c17b6d584fe0 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
@@ -21,18 +21,12 @@
#include <brcmu_d11.h>
#define WL_NUM_SCAN_MAX 10
-#define WL_NUM_PMKIDS_MAX MAXPMKID
#define WL_TLV_INFO_MAX 1024
#define WL_BSS_INFO_MAX 2048
#define WL_ASSOC_INFO_MAX 512 /* assoc related fil max buf */
#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
-#define WL_SCAN_PASSIVE_TIME 120
#define WL_ESCAN_BUF_SIZE (1024 * 64)
#define WL_ESCAN_TIMER_INTERVAL_MS 10000 /* E-Scan timeout */
@@ -77,6 +71,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
@@ -97,19 +94,6 @@ struct brcmf_cfg80211_conf {
u32 rts_threshold;
u32 retry_short;
u32 retry_long;
- s32 tx_power;
- struct ieee80211_channel channel;
-};
-
-/* basic structure of scan request */
-struct brcmf_cfg80211_scan_req {
- struct brcmf_ssid_le ssid_le;
-};
-
-/* basic structure of information element */
-struct brcmf_cfg80211_ie {
- u16 offset;
- u8 buf[WL_TLV_INFO_MAX];
};
/* security information with currently associated ap */
@@ -124,13 +108,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 +162,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 +172,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;
@@ -215,12 +195,6 @@ struct brcmf_cfg80211_assoc_ielen_le {
__le32 resp_len;
};
-/* wpa2 pmk list */
-struct brcmf_cfg80211_pmk_list {
- struct pmkid_list pmkids;
- struct pmkid foo[MAXPMKID - 1];
-};
-
/* dongle escan state */
enum wl_escan_state {
WL_ESCAN_STATE_IDLE,
@@ -233,88 +207,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 brcmf_pno_param_le - PNO scan configuration parameters
- *
- * @version: PNO parameters version.
- * @scan_freq: scan frequency.
- * @lost_network_timeout: #sec. to declare discovered network as lost.
- * @flags: Bit field to control features of PFN such as sort criteria auto
- * enable switch and background scan.
- * @rssi_margin: Margin to avoid jitter for choosing a PFN based on RSSI sort
- * criteria.
- * @bestn: number of best networks in each scan.
- * @mscan: number of scans recorded.
- * @repeat: minimum number of scan intervals before scan frequency changes
- * in adaptive scan.
- * @exp: exponent of 2 for maximum scan interval.
- * @slow_freq: slow scan period.
- */
-struct brcmf_pno_param_le {
- __le32 version;
- __le32 scan_freq;
- __le32 lost_network_timeout;
- __le16 flags;
- __le16 rssi_margin;
- u8 bestn;
- u8 mscan;
- u8 repeat;
- u8 exp;
- __le32 slow_freq;
-};
-
-/**
- * struct brcmf_pno_net_param_le - scan parameters per preferred network.
- *
- * @ssid: ssid name and its length.
- * @flags: bit2: hidden.
- * @infra: BSS vs IBSS.
- * @auth: Open vs Closed.
- * @wpa_auth: WPA type.
- * @wsec: wsec value.
- */
-struct brcmf_pno_net_param_le {
- struct brcmf_ssid_le ssid;
- __le32 flags;
- __le32 infra;
- __le32 auth;
- __le32 wpa_auth;
- __le32 wsec;
-};
-
-/**
- * struct brcmf_pno_net_info_le - information per found network.
- *
- * @bssid: BSS network identifier.
- * @channel: channel number only.
- * @SSID_len: length of ssid.
- * @SSID: ssid characters.
- * @RSSI: receive signal strength (in dBm).
- * @timestamp: age in seconds.
- */
-struct brcmf_pno_net_info_le {
- u8 bssid[ETH_ALEN];
- u8 channel;
- u8 SSID_len;
- u8 SSID[32];
- __le16 RSSI;
- __le16 timestamp;
-};
-
-/**
- * struct brcmf_pno_scanresults_le - result returned in PNO NET FOUND event.
- *
- * @version: PNO version identifier.
- * @status: indicates completion status of PNO scan.
- * @count: amount of brcmf_pno_net_info_le entries appended.
- */
-struct brcmf_pno_scanresults_le {
- __le32 version;
- __le32 status;
- __le32 count;
+ struct cfg80211_scan_request *request);
};
/**
@@ -343,9 +236,7 @@ struct brcmf_cfg80211_vif_event {
* @scan_request: cfg80211 scan request object.
* @usr_sync: mainly for dongle up/down synchronization.
* @bss_list: bss_list holding scanned ap information.
- * @scan_req_int: internal scan request object.
* @bss_info: bss information for cfg80211 layer.
- * @ie: information element object for internal purpose.
* @conn_info: association info.
* @pmk_list: wpa2 pmk list.
* @scan_status: scan activity on the dongle.
@@ -378,11 +269,9 @@ struct brcmf_cfg80211_info {
struct brcmf_btcoex_info *btcoex;
struct cfg80211_scan_request *scan_request;
struct mutex usr_sync;
- struct brcmf_cfg80211_scan_req scan_req_int;
struct wl_cfg80211_bss_info *bss_info;
- struct brcmf_cfg80211_ie ie;
struct brcmf_cfg80211_connect_info conn_info;
- struct brcmf_cfg80211_pmk_list *pmk_list;
+ struct brcmf_pmk_list_le pmk_list;
unsigned long scan_status;
struct brcmf_pub *pub;
u32 channel;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
index f04833db2fd0..82e4382eb177 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c
@@ -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;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index fe54844c75e0..4265b50faa98 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -29,13 +29,53 @@
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
/* boost value for RSSI_DELTA in preferred join selection */
#define BRCMF_JOIN_PREF_RSSI_BOOST 8
+#define BRCMF_DEFAULT_TXGLOM_SIZE 32 /* max tx frames in glom chain */
+
+static int brcmf_sdiod_txglomsz = BRCMF_DEFAULT_TXGLOM_SIZE;
+module_param_named(txglomsz, brcmf_sdiod_txglomsz, int, 0);
+MODULE_PARM_DESC(txglomsz, "Maximum tx packet chain size [SDIO]");
+
+/* Debug level configuration. See debug.h for bits, sysfs modifiable */
+int brcmf_msg_level;
+module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR);
+MODULE_PARM_DESC(debug, "Level of debug output");
+
+static int brcmf_p2p_enable;
+module_param_named(p2pon, brcmf_p2p_enable, int, 0);
+MODULE_PARM_DESC(p2pon, "Enable legacy p2p management functionality");
+
+static int brcmf_feature_disable;
+module_param_named(feature_disable, brcmf_feature_disable, int, 0);
+MODULE_PARM_DESC(feature_disable, "Disable features");
+
+static char brcmf_firmware_path[BRCMF_FW_ALTPATH_LEN];
+module_param_string(alternative_fw_path, brcmf_firmware_path,
+ BRCMF_FW_ALTPATH_LEN, S_IRUSR);
+MODULE_PARM_DESC(alternative_fw_path, "Alternative firmware path");
+
+static int brcmf_fcmode;
+module_param_named(fcmode, brcmf_fcmode, int, 0);
+MODULE_PARM_DESC(fcmode, "Mode of firmware signalled flow control");
+
+static int brcmf_roamoff;
+module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR);
+MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine");
+
+#ifdef DEBUG
+/* always succeed brcmf_bus_start() */
+static int brcmf_ignore_probe_fail;
+module_param_named(ignore_probe_fail, brcmf_ignore_probe_fail, int, 0);
+MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging");
+#endif
+
+struct brcmf_mp_global_t brcmf_mp_global;
+
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
{
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
@@ -107,26 +147,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 +194,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:
@@ -196,3 +219,34 @@ void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...)
va_end(args);
}
#endif
+
+void brcmf_mp_attach(void)
+{
+ strlcpy(brcmf_mp_global.firmware_path, brcmf_firmware_path,
+ BRCMF_FW_ALTPATH_LEN);
+}
+
+int brcmf_mp_device_attach(struct brcmf_pub *drvr)
+{
+ drvr->settings = kzalloc(sizeof(*drvr->settings), GFP_ATOMIC);
+ if (!drvr->settings) {
+ brcmf_err("Failed to alloca storage space for settings\n");
+ return -ENOMEM;
+ }
+
+ drvr->settings->sdiod_txglomsz = brcmf_sdiod_txglomsz;
+ drvr->settings->p2p_enable = !!brcmf_p2p_enable;
+ drvr->settings->feature_disable = brcmf_feature_disable;
+ drvr->settings->fcmode = brcmf_fcmode;
+ drvr->settings->roamoff = !!brcmf_roamoff;
+#ifdef DEBUG
+ drvr->settings->ignore_probe_fail = !!brcmf_ignore_probe_fail;
+#endif
+ return 0;
+}
+
+void brcmf_mp_device_detach(struct brcmf_pub *drvr)
+{
+ kfree(drvr->settings);
+}
+
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
index 21c7488b4732..3b0a63b98e99 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.h
@@ -17,6 +17,62 @@
extern const u8 ALLFFMAC[ETH_ALEN];
+#define BRCMF_FW_ALTPATH_LEN 256
+
+/* Definitions for the module global and device specific settings are defined
+ * here. Two structs are used for them. brcmf_mp_global_t and brcmf_mp_device.
+ * The mp_global is instantiated once in a global struct and gets initialized
+ * by the common_attach function which should be called before any other
+ * (module) initiliazation takes place. The device specific settings is part
+ * of the drvr struct and should be initialized on every brcmf_attach.
+ */
+
+/**
+ * struct brcmf_mp_global_t - Global module paramaters.
+ *
+ * @firmware_path: Alternative firmware path.
+ */
+struct brcmf_mp_global_t {
+ char firmware_path[BRCMF_FW_ALTPATH_LEN];
+};
+
+extern struct brcmf_mp_global_t brcmf_mp_global;
+
+/**
+ * struct brcmf_mp_device - Device module paramaters.
+ *
+ * @sdiod_txglomsz: SDIO txglom size.
+ * @joinboost_5g_rssi: 5g rssi booost for preferred join selection.
+ * @p2p_enable: Legacy P2P0 enable (old wpa_supplicant).
+ * @feature_disable: Feature_disable bitmask.
+ * @fcmode: FWS flow control.
+ * @roamoff: Firmware roaming off?
+ */
+struct brcmf_mp_device {
+ int sdiod_txglomsz;
+ int joinboost_5g_rssi;
+ bool p2p_enable;
+ int feature_disable;
+ int fcmode;
+ bool roamoff;
+ bool ignore_probe_fail;
+};
+
+void brcmf_mp_attach(void);
+int brcmf_mp_device_attach(struct brcmf_pub *drvr);
+void brcmf_mp_device_detach(struct brcmf_pub *drvr);
+#ifdef DEBUG
+static inline bool brcmf_ignoring_probe_fail(struct brcmf_pub *drvr)
+{
+ return drvr->settings->ignore_probe_fail;
+}
+#else
+static inline bool brcmf_ignoring_probe_fail(struct brcmf_pub *drvr)
+{
+ return false;
+}
+#endif
+
/* Sets dongle media info (drv_version, mac address). */
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index b5ab98ee1445..7c75b1acdf00 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -17,6 +17,7 @@
#include <linux/kernel.h>
#include <linux/etherdevice.h>
#include <linux/module.h>
+#include <linux/inetdevice.h>
#include <net/cfg80211.h>
#include <net/rtnetlink.h>
#include <brcmu_utils.h>
@@ -56,30 +57,13 @@ MODULE_LICENSE("Dual BSD/GPL");
#define BRCMF_BSSIDX_INVALID -1
-/* Error bits */
-int brcmf_msg_level;
-module_param_named(debug, brcmf_msg_level, int, S_IRUSR | S_IWUSR);
-MODULE_PARM_DESC(debug, "level of debug output");
-
-/* P2P0 enable */
-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 +71,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 +79,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 +99,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 +159,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 +197,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 +208,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 +258,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 +578,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,10 +607,12 @@ 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);
+ brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear", NULL, 0);
+
brcmf_net_setcarrier(ifp, false);
return 0;
@@ -647,7 +625,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 +667,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 +699,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 +717,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 +765,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,39 +784,40 @@ 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);
}
}
- if (!brcmf_p2p_enable && is_p2pdev) {
+ if (!drvr->settings->p2p_enable && is_p2pdev) {
/* this is P2P_DEVICE interface */
brcmf_dbg(INFO, "allocate non-netdev interface\n");
ifp = kzalloc(sizeof(*ifp), GFP_KERNEL);
@@ -854,15 +834,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 +856,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 +901,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 +921,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;
}
@@ -952,6 +933,98 @@ int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr)
return available ? bsscfgidx : -ENOMEM;
}
+#ifdef CONFIG_INET
+#define ARPOL_MAX_ENTRIES 8
+static int brcmf_inetaddr_changed(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct brcmf_pub *drvr = container_of(nb, struct brcmf_pub,
+ inetaddr_notifier);
+ struct in_ifaddr *ifa = data;
+ struct net_device *ndev = ifa->ifa_dev->dev;
+ struct brcmf_if *ifp;
+ int idx, i, ret;
+ u32 val;
+ __be32 addr_table[ARPOL_MAX_ENTRIES] = {0};
+
+ /* Find out if the notification is meant for us */
+ for (idx = 0; idx < BRCMF_MAX_IFS; idx++) {
+ ifp = drvr->iflist[idx];
+ if (ifp && ifp->ndev == ndev)
+ break;
+ if (idx == BRCMF_MAX_IFS - 1)
+ return NOTIFY_DONE;
+ }
+
+ /* check if arp offload is supported */
+ ret = brcmf_fil_iovar_int_get(ifp, "arpoe", &val);
+ if (ret)
+ return NOTIFY_OK;
+
+ /* old version only support primary index */
+ ret = brcmf_fil_iovar_int_get(ifp, "arp_version", &val);
+ if (ret)
+ val = 1;
+ if (val == 1)
+ ifp = drvr->iflist[0];
+
+ /* retrieve the table from firmware */
+ ret = brcmf_fil_iovar_data_get(ifp, "arp_hostip", addr_table,
+ sizeof(addr_table));
+ if (ret) {
+ brcmf_err("fail to get arp ip table err:%d\n", ret);
+ return NOTIFY_OK;
+ }
+
+ for (i = 0; i < ARPOL_MAX_ENTRIES; i++)
+ if (ifa->ifa_address == addr_table[i])
+ break;
+
+ switch (action) {
+ case NETDEV_UP:
+ if (i == ARPOL_MAX_ENTRIES) {
+ brcmf_dbg(TRACE, "add %pI4 to arp table\n",
+ &ifa->ifa_address);
+ /* set it directly */
+ ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip",
+ &ifa->ifa_address, sizeof(ifa->ifa_address));
+ if (ret)
+ brcmf_err("add arp ip err %d\n", ret);
+ }
+ break;
+ case NETDEV_DOWN:
+ if (i < ARPOL_MAX_ENTRIES) {
+ addr_table[i] = 0;
+ brcmf_dbg(TRACE, "remove %pI4 from arp table\n",
+ &ifa->ifa_address);
+ /* clear the table in firmware */
+ ret = brcmf_fil_iovar_data_set(ifp, "arp_hostip_clear",
+ NULL, 0);
+ if (ret) {
+ brcmf_err("fail to clear arp ip table err:%d\n",
+ ret);
+ return NOTIFY_OK;
+ }
+ for (i = 0; i < ARPOL_MAX_ENTRIES; i++) {
+ if (addr_table[i] != 0) {
+ brcmf_fil_iovar_data_set(ifp,
+ "arp_hostip", &addr_table[i],
+ sizeof(addr_table[i]));
+ if (ret)
+ brcmf_err("add arp ip err %d\n",
+ ret);
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+#endif
+
int brcmf_attach(struct device *dev)
{
struct brcmf_pub *drvr = NULL;
@@ -975,6 +1048,10 @@ int brcmf_attach(struct device *dev)
drvr->bus_if = dev_get_drvdata(dev);
drvr->bus_if->drvr = drvr;
+ /* Initialize device specific settings */
+ if (brcmf_mp_device_attach(drvr))
+ goto fail;
+
/* attach debug facilities */
brcmf_debug_attach(drvr);
@@ -1067,7 +1144,7 @@ int brcmf_bus_start(struct device *dev)
brcmf_fws_add_interface(ifp);
drvr->config = brcmf_cfg80211_attach(drvr, bus_if->dev,
- brcmf_p2p_enable);
+ drvr->settings->p2p_enable);
if (drvr->config == NULL) {
ret = -ENOMEM;
goto fail;
@@ -1075,11 +1152,20 @@ int brcmf_bus_start(struct device *dev)
ret = brcmf_net_attach(ifp, false);
- if ((!ret) && (brcmf_p2p_enable)) {
+ if ((!ret) && (drvr->settings->p2p_enable)) {
p2p_ifp = drvr->iflist[1];
if (p2p_ifp)
ret = brcmf_net_p2p_attach(p2p_ifp);
}
+
+ if (ret)
+ goto fail;
+
+#ifdef CONFIG_INET
+ drvr->inetaddr_notifier.notifier_call = brcmf_inetaddr_changed;
+ ret = register_inetaddr_notifier(&drvr->inetaddr_notifier);
+#endif
+
fail:
if (ret < 0) {
brcmf_err("failed: %d\n", ret);
@@ -1095,6 +1181,10 @@ fail:
brcmf_net_detach(ifp->ndev);
if (p2p_ifp)
brcmf_net_detach(p2p_ifp->ndev);
+ drvr->iflist[0] = NULL;
+ drvr->iflist[1] = NULL;
+ if (brcmf_ignoring_probe_fail(drvr))
+ ret = 0;
return ret;
}
return 0;
@@ -1143,6 +1233,10 @@ void brcmf_detach(struct device *dev)
if (drvr == NULL)
return;
+#ifdef CONFIG_INET
+ unregister_inetaddr_notifier(&drvr->inetaddr_notifier);
+#endif
+
/* stop firmware event handling */
brcmf_fweh_detach(drvr);
if (drvr->config)
@@ -1162,6 +1256,8 @@ void brcmf_detach(struct device *dev)
brcmf_proto_detach(drvr);
+ brcmf_mp_device_detach(drvr);
+
brcmf_debug_detach(drvr);
bus_if->drvr = NULL;
kfree(drvr);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
index 2f9101b2ad34..8f39435f976f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
@@ -69,8 +69,8 @@ struct brcmf_ampdu_rx_reorder {
/* Forward decls for struct brcmf_pub (see below) */
struct brcmf_proto; /* device communication protocol info */
-struct brcmf_cfg80211_dev; /* cfg80211 device info */
-struct brcmf_fws_info; /* firmware signalling info */
+struct brcmf_fws_info; /* firmware signalling info */
+struct brcmf_mp_device; /* module paramateres, device specific */
/*
* struct brcmf_rev_info
@@ -141,6 +141,9 @@ struct brcmf_pub {
#ifdef DEBUG
struct dentry *dbgfs_dir;
#endif
+
+ struct notifier_block inetaddr_notifier;
+ struct brcmf_mp_device *settings;
};
/* forward declarations */
@@ -174,7 +177,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 +193,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 +208,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);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
index 1299dccc78b4..e64557c35553 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.c
@@ -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);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
index d0d9676f7f9d..6687812770cc 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/debug.h
@@ -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
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
index 44bb30636690..1ffa95f1b8d2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -18,18 +18,16 @@
#include <linux/module.h>
#include <brcm_hw_ids.h>
+#include <brcmu_wifi.h>
#include "core.h"
#include "bus.h"
#include "debug.h"
#include "fwil.h"
+#include "fwil_types.h"
#include "feature.h"
+#include "common.h"
-/* Module param feature_disable (global for all devices) */
-static int brcmf_feature_disable;
-module_param_named(feature_disable, brcmf_feature_disable, int, 0);
-MODULE_PARM_DESC(feature_disable, "Disable features");
-
/*
* expand feature list to array of feature strings.
*/
@@ -40,6 +38,17 @@ static const char *brcmf_feat_names[] = {
};
#undef BRCMF_FEAT_DEF
+struct brcmf_feat_fwcap {
+ enum brcmf_feat_id feature;
+ const char * const fwcap_id;
+};
+
+static const struct brcmf_feat_fwcap brcmf_fwcap_map[] = {
+ { BRCMF_FEAT_MBSS, "mbss" },
+ { BRCMF_FEAT_MCHAN, "mchan" },
+ { BRCMF_FEAT_P2P, "p2p" },
+};
+
#ifdef DEBUG
/*
* expand quirk list to array of quirk strings.
@@ -104,44 +113,53 @@ static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp,
}
}
-/**
- * brcmf_feat_iovar_int_set() - determine feature through iovar set.
- *
- * @ifp: interface to query.
- * @id: feature id.
- * @name: iovar name.
- */
-static void brcmf_feat_iovar_int_set(struct brcmf_if *ifp,
- enum brcmf_feat_id id, char *name, u32 val)
+static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp)
{
- int err;
-
- err = brcmf_fil_iovar_int_set(ifp, name, val);
- if (err == 0) {
- brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
- ifp->drvr->feat_flags |= BIT(id);
- } else {
- brcmf_dbg(TRACE, "%s feature check failed: %d\n",
- brcmf_feat_names[id], err);
+ char caps[256];
+ enum brcmf_feat_id id;
+ int i;
+
+ brcmf_fil_iovar_data_get(ifp, "cap", caps, sizeof(caps));
+ brcmf_dbg(INFO, "[ %s]\n", caps);
+
+ for (i = 0; i < ARRAY_SIZE(brcmf_fwcap_map); i++) {
+ if (strnstr(caps, brcmf_fwcap_map[i].fwcap_id, sizeof(caps))) {
+ id = brcmf_fwcap_map[i].feature;
+ brcmf_dbg(INFO, "enabling feature: %s\n",
+ brcmf_feat_names[id]);
+ ifp->drvr->feat_flags |= BIT(id);
+ }
}
}
void brcmf_feat_attach(struct brcmf_pub *drvr)
{
struct brcmf_if *ifp = brcmf_get_ifp(drvr, 0);
+ struct brcmf_pno_macaddr_le pfn_mac;
+ s32 err;
+
+ brcmf_feat_firmware_capabilities(ifp);
- brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_PNO, "pfn");
if (drvr->bus_if->wowl_supported)
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
- 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");
-
- if (brcmf_feature_disable) {
+ /* MBSS does not work for 43362 */
+ if (drvr->bus_if->chip == BRCM_CC_43362_CHIP_ID)
+ ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_MBSS);
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_RSDB, "rsdb_mode");
+ brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_TDLS, "tdls_enable");
+
+ pfn_mac.version = BRCMF_PFN_MACADDR_CFG_VER;
+ err = brcmf_fil_iovar_data_get(ifp, "pfn_macaddr", &pfn_mac,
+ sizeof(pfn_mac));
+ if (!err)
+ ifp->drvr->feat_flags |= BIT(BRCMF_FEAT_SCAN_RANDOM_MAC);
+
+ if (drvr->settings->feature_disable) {
brcmf_dbg(INFO, "Features: 0x%02x, disable: 0x%02x\n",
- ifp->drvr->feat_flags, brcmf_feature_disable);
- ifp->drvr->feat_flags &= ~brcmf_feature_disable;
+ ifp->drvr->feat_flags,
+ drvr->settings->feature_disable);
+ ifp->drvr->feat_flags &= ~drvr->settings->feature_disable;
}
/* set chip related quirks */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
index 6b381f799f22..2e2479d41337 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
@@ -24,13 +24,20 @@
* PNO: preferred network offload.
* WOWL: Wake-On-WLAN.
* P2P: peer-to-peer
+ * RSDB: Real Simultaneous Dual Band
+ * TDLS: Tunneled Direct Link Setup
+ * SCAN_RANDOM_MAC: Random MAC during (net detect) scheduled scan.
*/
#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) \
+ BRCMF_FEAT_DEF(TDLS) \
+ BRCMF_FEAT_DEF(SCAN_RANDOM_MAC)
+
/*
* Quirks:
*
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
index 4248f3c80e78..1365c12b78fc 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
@@ -23,15 +23,13 @@
#include "debug.h"
#include "firmware.h"
+#include "core.h"
+#include "common.h"
#define BRCMF_FW_MAX_NVRAM_SIZE 64000
#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];
-module_param_string(alternative_fw_path, brcmf_firmware_path,
- BRCMF_FW_PATH_LEN, 0440);
-
enum nvram_parser_state {
IDLE,
KEY,
@@ -449,8 +447,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 +537,45 @@ 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_mp_global.firmware_path[0] != '\0') {
+ strlcpy(fw_name, brcmf_mp_global.firmware_path,
+ BRCMF_FW_NAME_LEN);
+ if ((nvram_name) && (mapping_table[i].nvram))
+ strlcpy(nvram_name, brcmf_mp_global.firmware_path,
+ BRCMF_FW_NAME_LEN);
+
+ end = brcmf_mp_global.firmware_path[
+ strlen(brcmf_mp_global.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;
+}
+
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
index 604dd48ab4e0..ef06f57a7a0e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.h
@@ -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
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
index 3878b6f6cfce..7b26fb1b437c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
@@ -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;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
index d9a942842382..5e39e2a9e388 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
@@ -219,7 +219,7 @@ struct brcmf_if_event {
u8 ifidx;
u8 action;
u8 flags;
- u8 bssidx;
+ u8 bsscfgidx;
u8 role;
};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
index dcfa0bb149ce..f6a2df94dba7 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.c
@@ -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");
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
index b20fc0f82a48..6b72df17744e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
@@ -70,6 +70,7 @@
#define BRCMF_C_SET_WSEC 134
#define BRCMF_C_GET_PHY_NOISE 135
#define BRCMF_C_GET_BSS_INFO 136
+#define BRCMF_C_GET_GET_PKTCNTS 137
#define BRCMF_C_GET_BANDLIST 140
#define BRCMF_C_SET_SCB_TIMEOUT 158
#define BRCMF_C_GET_ASSOCLIST 159
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
index daa427b46712..bf2df49d7098 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -121,6 +121,17 @@
#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)
+
+#define BRCMF_MAXPMKID 16 /* max # PMKID cache entries */
+
+#define BRCMF_PFN_MACADDR_CFG_VER 1
+#define BRCMF_PFN_MAC_OUI_ONLY BIT(0)
+#define BRCMF_PFN_SET_MAC_UNASSOC BIT(1)
+
/* join preference types for join_pref iovar */
enum brcmf_join_pref_types {
BRCMF_JOIN_PREF_RSSI = 1,
@@ -170,7 +181,7 @@ struct brcmf_fil_af_params_le {
};
struct brcmf_fil_bss_enable_le {
- __le32 bsscfg_idx;
+ __le32 bsscfgidx;
__le32 enable;
};
@@ -282,14 +293,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 +640,149 @@ 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;
+};
+
+/**
+ * struct brcmf_pmksa - PMK Security Association
+ *
+ * @bssid: The AP's BSSID.
+ * @pmkid: he PMK material itself.
+ */
+struct brcmf_pmksa {
+ u8 bssid[ETH_ALEN];
+ u8 pmkid[WLAN_PMKID_LEN];
+};
+
+/**
+ * struct brcmf_pmk_list_le - List of pmksa's.
+ *
+ * @npmk: Number of pmksa's.
+ * @pmk: PMK SA information.
+ */
+struct brcmf_pmk_list_le {
+ __le32 npmk;
+ struct brcmf_pmksa pmk[BRCMF_MAXPMKID];
+};
+
+/**
+ * struct brcmf_pno_param_le - PNO scan configuration parameters
+ *
+ * @version: PNO parameters version.
+ * @scan_freq: scan frequency.
+ * @lost_network_timeout: #sec. to declare discovered network as lost.
+ * @flags: Bit field to control features of PFN such as sort criteria auto
+ * enable switch and background scan.
+ * @rssi_margin: Margin to avoid jitter for choosing a PFN based on RSSI sort
+ * criteria.
+ * @bestn: number of best networks in each scan.
+ * @mscan: number of scans recorded.
+ * @repeat: minimum number of scan intervals before scan frequency changes
+ * in adaptive scan.
+ * @exp: exponent of 2 for maximum scan interval.
+ * @slow_freq: slow scan period.
+ */
+struct brcmf_pno_param_le {
+ __le32 version;
+ __le32 scan_freq;
+ __le32 lost_network_timeout;
+ __le16 flags;
+ __le16 rssi_margin;
+ u8 bestn;
+ u8 mscan;
+ u8 repeat;
+ u8 exp;
+ __le32 slow_freq;
+};
+
+/**
+ * struct brcmf_pno_net_param_le - scan parameters per preferred network.
+ *
+ * @ssid: ssid name and its length.
+ * @flags: bit2: hidden.
+ * @infra: BSS vs IBSS.
+ * @auth: Open vs Closed.
+ * @wpa_auth: WPA type.
+ * @wsec: wsec value.
+ */
+struct brcmf_pno_net_param_le {
+ struct brcmf_ssid_le ssid;
+ __le32 flags;
+ __le32 infra;
+ __le32 auth;
+ __le32 wpa_auth;
+ __le32 wsec;
+};
+
+/**
+ * struct brcmf_pno_net_info_le - information per found network.
+ *
+ * @bssid: BSS network identifier.
+ * @channel: channel number only.
+ * @SSID_len: length of ssid.
+ * @SSID: ssid characters.
+ * @RSSI: receive signal strength (in dBm).
+ * @timestamp: age in seconds.
+ */
+struct brcmf_pno_net_info_le {
+ u8 bssid[ETH_ALEN];
+ u8 channel;
+ u8 SSID_len;
+ u8 SSID[32];
+ __le16 RSSI;
+ __le16 timestamp;
+};
+
+/**
+ * struct brcmf_pno_scanresults_le - result returned in PNO NET FOUND event.
+ *
+ * @version: PNO version identifier.
+ * @status: indicates completion status of PNO scan.
+ * @count: amount of brcmf_pno_net_info_le entries appended.
+ */
+struct brcmf_pno_scanresults_le {
+ __le32 version;
+ __le32 status;
+ __le32 count;
+};
+
+/**
+ * struct brcmf_pno_macaddr_le - to configure PNO macaddr randomization.
+ *
+ * @version: PNO version identifier.
+ * @flags: Flags defining how mac addrss should be used.
+ * @mac: MAC address.
+ */
+struct brcmf_pno_macaddr_le {
+ u8 version;
+ u8 flags;
+ u8 mac[ETH_ALEN];
+};
+
+/**
+ * struct brcmf_pktcnt_le - packet counters.
+ *
+ * @rx_good_pkt: packets (MSDUs & MMPDUs) received from this station
+ * @rx_bad_pkt: failed rx packets
+ * @tx_good_pkt: packets (MSDUs & MMPDUs) transmitted to this station
+ * @tx_bad_pkt: failed tx packets
+ * @rx_ocast_good_pkt: unicast packets destined for others
+ */
+struct brcmf_pktcnt_le {
+ __le32 rx_good_pkt;
+ __le32 rx_bad_pkt;
+ __le32 tx_good_pkt;
+ __le32 tx_bad_pkt;
+ __le32 rx_ocast_good_pkt;
+};
+
#endif /* FWIL_TYPES_H_ */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
index 086cac3f86d6..f82c9ab5480b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
@@ -36,6 +36,7 @@
#include "p2p.h"
#include "cfg80211.h"
#include "proto.h"
+#include "common.h"
/**
* DOC: Firmware Signalling
@@ -521,10 +522,6 @@ static const int brcmf_fws_prio2fifo[] = {
BRCMF_FWS_FIFO_AC_VO
};
-static int fcmode;
-module_param(fcmode, int, S_IRUSR);
-MODULE_PARM_DESC(fcmode, "mode of firmware signalled flow control");
-
#define BRCMF_FWS_TLV_DEF(name, id, len) \
case BRCMF_FWS_TYPE_ ## name: \
return len;
@@ -719,7 +716,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)
@@ -1609,10 +1606,11 @@ static int brcmf_fws_notify_bcmc_credit_support(struct brcmf_if *ifp,
{
struct brcmf_fws_info *fws = ifp->drvr->fws;
- brcmf_fws_lock(fws);
- if (fws)
+ if (fws) {
+ brcmf_fws_lock(fws);
fws->bcmc_credit_check = true;
- brcmf_fws_unlock(fws);
+ brcmf_fws_unlock(fws);
+ }
return 0;
}
@@ -1938,7 +1936,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;
@@ -2133,10 +2131,10 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
/* set linkage back */
fws->drvr = drvr;
- fws->fcmode = fcmode;
+ fws->fcmode = drvr->settings->fcmode;
if ((drvr->bus_if->always_use_fws_queue == false) &&
- (fcmode == BRCMF_FWS_FCMODE_NONE)) {
+ (fws->fcmode == BRCMF_FWS_FCMODE_NONE)) {
fws->avoid_queueing = true;
brcmf_dbg(INFO, "FWS queueing will be avoided\n");
return 0;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index 44e618f9d890..5df91386e13a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -473,8 +473,7 @@ static int brcmf_msgbuf_ioctl_resp_wait(struct brcmf_msgbuf *msgbuf)
static void brcmf_msgbuf_ioctl_resp_wake(struct brcmf_msgbuf *msgbuf)
{
msgbuf->ctl_completed = true;
- if (waitqueue_active(&msgbuf->ioctl_resp_wait))
- wake_up(&msgbuf->ioctl_resp_wait);
+ wake_up(&msgbuf->ioctl_resp_wait);
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
index d224b3dd72ed..b23dcbcd505e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
@@ -625,11 +625,10 @@ exit:
* @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 @@ exit:
*/
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);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h
index 5d49059021a9..a3bd18c2360b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.h
@@ -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;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 83d804221715..3d2d790d3ad6 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -44,23 +44,31 @@ 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(4350C, "brcmfmac4350c2-pcie.bin", "brcmfmac4350c2-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, 0x000000FF, 4350C),
+ BRCMF_FW_NVRAM_ENTRY(BRCM_CC_4350_CHIP_ID, 0xFFFFFF00, 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 +208,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 +243,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 +611,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 +876,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 +898,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 +915,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 +1376,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 +1401,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 +1466,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 +1801,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 +1870,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_dbg(PCIE, "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 +1892,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_dbg(PCIE, "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 +1939,14 @@ cleanup:
}
+static const struct dev_pm_ops brcmf_pciedrvr_pm = {
+ .suspend = brcmf_pcie_pm_enter_D3,
+ .resume = brcmf_pcie_pm_leave_D3,
+ .freeze = brcmf_pcie_pm_enter_D3,
+ .restore = brcmf_pcie_pm_leave_D3,
+};
+
+
#endif /* CONFIG_PM */
@@ -2058,6 +1959,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 +1985,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
};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index 7e74ac3ad815..ceb2a754308e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -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;
@@ -1787,8 +1678,7 @@ static int brcmf_sdio_dcmd_resp_wait(struct brcmf_sdio *bus, uint *condition,
static int brcmf_sdio_dcmd_resp_wake(struct brcmf_sdio *bus)
{
- if (waitqueue_active(&bus->dcmd_resp_wait))
- wake_up_interruptible(&bus->dcmd_resp_wait);
+ wake_up_interruptible(&bus->dcmd_resp_wait);
return 0;
}
@@ -2112,8 +2002,7 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
static void
brcmf_sdio_wait_event_wakeup(struct brcmf_sdio *bus)
{
- if (waitqueue_active(&bus->ctrl_wait))
- wake_up_interruptible(&bus->ctrl_wait);
+ wake_up_interruptible(&bus->ctrl_wait);
return;
}
@@ -4025,7 +3914,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 +4155,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;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
index 7328478b2d7b..d86ecf26f31a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h
@@ -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;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
index 689e64d004bc..66c26a92b29c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -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;
@@ -185,8 +196,7 @@ static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo)
static void brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo)
{
- if (waitqueue_active(&devinfo->ioctl_resp_wait))
- wake_up(&devinfo->ioctl_resp_wait);
+ wake_up(&devinfo->ioctl_resp_wait);
}
static void
@@ -983,45 +993,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 +1051,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 +1124,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 +1235,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 +1440,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);
}
@@ -1485,16 +1452,13 @@ static struct usb_device_id brcmf_usb_devid_table[] = {
BRCMF_USB_DEVICE(BRCM_USB_43236_DEVICE_ID),
BRCMF_USB_DEVICE(BRCM_USB_43242_DEVICE_ID),
BRCMF_USB_DEVICE(BRCM_USB_43569_DEVICE_ID),
+ { USB_DEVICE(BRCM_USB_VENDOR_ID_LG, BRCM_USB_43242_LG_DEVICE_ID) },
/* special entry for device with firmware loaded and running */
BRCMF_USB_DEVICE(BRCM_USB_BCMFW_DEVICE_ID),
{ /* end: all zeroes */ }
};
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,
};
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c
index 635ae034c7e5..38bd5890bd53 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/channel.c
@@ -177,8 +177,8 @@ static bool brcms_c_country_valid(const char *ccode)
* only allow ascii alpha uppercase for the first 2
* chars.
*/
- if (!((0x80 & ccode[0]) == 0 && ccode[0] >= 0x41 && ccode[0] <= 0x5A &&
- (0x80 & ccode[1]) == 0 && ccode[1] >= 0x41 && ccode[1] <= 0x5A))
+ if (!((ccode[0] & 0x80) == 0 && ccode[0] >= 0x41 && ccode[0] <= 0x5A &&
+ (ccode[1] & 0x80) == 0 && ccode[1] >= 0x41 && ccode[1] <= 0x5A))
return false;
/*
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
index aa06ea231db3..699f2c2782ee 100644
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcm_hw_ids.h
@@ -21,6 +21,7 @@
#include <linux/mmc/sdio_ids.h>
#define BRCM_USB_VENDOR_ID_BROADCOM 0x0a5c
+#define BRCM_USB_VENDOR_ID_LG 0x043e
#define BRCM_PCIE_VENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM
/* Chipcommon Core Chip IDs */
@@ -47,6 +48,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
@@ -56,6 +58,7 @@
#define BRCM_USB_43143_DEVICE_ID 0xbd1e
#define BRCM_USB_43236_DEVICE_ID 0xbd17
#define BRCM_USB_43242_DEVICE_ID 0xbd1f
+#define BRCM_USB_43242_LG_DEVICE_ID 0x3101
#define BRCM_USB_43569_DEVICE_ID 0xbd27
#define BRCM_USB_BCMFW_DEVICE_ID 0x0bdc
@@ -66,6 +69,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
diff --git a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h
index 76b5d3a86294..3f68dd5ecd11 100644
--- a/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h
+++ b/drivers/net/wireless/broadcom/brcm80211/include/brcmu_wifi.h
@@ -237,9 +237,6 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec)
#define WPA2_AUTH_RESERVED4 0x0400
#define WPA2_AUTH_RESERVED5 0x0800
-/* pmkid */
-#define MAXPMKID 16
-
#define DOT11_DEFAULT_RTS_LEN 2347
#define DOT11_DEFAULT_FRAG_LEN 2346
@@ -251,24 +248,4 @@ static inline bool ac_bitmap_tst(u8 bitmap, int prec)
#define HT_CAP_RX_STBC_NO 0x0
#define HT_CAP_RX_STBC_ONE_STREAM 0x1
-struct pmkid {
- u8 BSSID[ETH_ALEN];
- u8 PMKID[WLAN_PMKID_LEN];
-};
-
-struct pmkid_list {
- __le32 npmkid;
- struct pmkid pmkid[1];
-};
-
-struct pmkid_cand {
- u8 BSSID[ETH_ALEN];
- u8 preauth;
-};
-
-struct pmkid_cand_list {
- u32 npmkid_cand;
- struct pmkid_cand pmkid_cand[1];
-};
-
#endif /* _BRCMU_WIFI_H_ */
diff --git a/drivers/net/wireless/cisco/airo.c b/drivers/net/wireless/cisco/airo.c
index 17c40f06f13e..d2353f6e5214 100644
--- a/drivers/net/wireless/cisco/airo.c
+++ b/drivers/net/wireless/cisco/airo.c
@@ -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);
diff --git a/drivers/net/wireless/intel/ipw2x00/ipw2100.c b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
index 36818c7f30b9..f93a7f71c047 100644
--- a/drivers/net/wireless/intel/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/intel/ipw2x00/ipw2100.c
@@ -2311,8 +2311,10 @@ static int ipw2100_alloc_skb(struct ipw2100_priv *priv,
packet->dma_addr = pci_map_single(priv->pci_dev, packet->skb->data,
sizeof(struct ipw2100_rx),
PCI_DMA_FROMDEVICE);
- /* NOTE: pci_map_single does not return an error code, and 0 is a valid
- * dma_addr */
+ if (pci_dma_mapping_error(priv->pci_dev, packet->dma_addr)) {
+ dev_kfree_skb(packet->skb);
+ return -ENOMEM;
+ }
return 0;
}
@@ -3183,6 +3185,11 @@ static void ipw2100_tx_send_data(struct ipw2100_priv *priv)
LIBIPW_3ADDR_LEN,
tbd->buf_length,
PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(priv->pci_dev,
+ tbd->host_addr)) {
+ IPW_DEBUG_TX("dma mapping error\n");
+ break;
+ }
IPW_DEBUG_TX("data frag tbd TX%d P=%08x L=%d\n",
txq->next, tbd->host_addr,
diff --git a/drivers/net/wireless/intel/iwlegacy/4965-mac.c b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
index 6656215a13a9..fd38aa0763e4 100644
--- a/drivers/net/wireless/intel/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/intel/iwlegacy/4965-mac.c
@@ -6416,7 +6416,7 @@ il4965_hw_detect(struct il_priv *il)
D_INFO("HW Revision ID = 0x%X\n", il->rev_id);
}
-static struct il_sensitivity_ranges il4965_sensitivity = {
+static const struct il_sensitivity_ranges il4965_sensitivity = {
.min_nrg_cck = 97,
.max_nrg_cck = 0, /* not used, set to 0 */
diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c
index 887114582583..eb5cb603bc52 100644
--- a/drivers/net/wireless/intel/iwlegacy/common.c
+++ b/drivers/net/wireless/intel/iwlegacy/common.c
@@ -1865,14 +1865,14 @@ il_send_add_sta(struct il_priv *il, struct il_addsta_cmd *sta, u8 flags)
cmd.len = il->ops->build_addsta_hcmd(sta, data);
ret = il_send_cmd(il, &cmd);
-
- if (ret || (flags & CMD_ASYNC))
+ if (ret)
return ret;
+ if (flags & CMD_ASYNC)
+ return 0;
+
+ pkt = (struct il_rx_pkt *)cmd.reply_page;
+ ret = il_process_add_sta_resp(il, sta, pkt, true);
- if (ret == 0) {
- pkt = (struct il_rx_pkt *)cmd.reply_page;
- ret = il_process_add_sta_resp(il, sta, pkt, true);
- }
il_free_pages(il, cmd.reply_page);
return ret;
@@ -3602,7 +3602,7 @@ il_is_ht40_tx_allowed(struct il_priv *il, struct ieee80211_sta_ht_cap *ht_cap)
}
EXPORT_SYMBOL(il_is_ht40_tx_allowed);
-static u16
+static u16 noinline
il_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
{
u16 new_val;
diff --git a/drivers/net/wireless/intersil/hostap/hostap_cs.c b/drivers/net/wireless/intersil/hostap/hostap_cs.c
index 50033aa7c7d5..74f63b7bf7b4 100644
--- a/drivers/net/wireless/intersil/hostap/hostap_cs.c
+++ b/drivers/net/wireless/intersil/hostap/hostap_cs.c
@@ -473,7 +473,7 @@ static int prism2_config(struct pcmcia_device *link)
struct net_device *dev;
struct hostap_interface *iface;
local_info_t *local;
- int ret = 1;
+ int ret;
struct hostap_cs_priv *hw_priv;
unsigned long flags;
@@ -502,8 +502,10 @@ static int prism2_config(struct pcmcia_device *link)
/* Need to allocate net_device before requesting IRQ handler */
dev = prism2_init_local_data(&prism2_pccard_funcs, 0,
&link->dev);
- if (dev == NULL)
+ if (!dev) {
+ ret = -ENOMEM;
goto failed;
+ }
link->priv = dev;
iface = netdev_priv(dev);
diff --git a/drivers/net/wireless/intersil/prism54/isl_ioctl.c b/drivers/net/wireless/intersil/prism54/isl_ioctl.c
index ecbb0546cf3e..48e8a978a832 100644
--- a/drivers/net/wireless/intersil/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/intersil/prism54/isl_ioctl.c
@@ -2036,7 +2036,7 @@ format_event(islpci_private *priv, char *dest, const char *str,
mlme->address,
(error ? (mlme->code ? " : REJECTED " : " : ACCEPTED ")
: ""), mlme->code);
- BUG_ON(n > IW_CUSTOM_MAX);
+ WARN_ON(n >= IW_CUSTOM_MAX);
*length = n;
}
diff --git a/drivers/net/wireless/intersil/prism54/islpci_dev.c b/drivers/net/wireless/intersil/prism54/islpci_dev.c
index 931cf440ff18..84a42012aeae 100644
--- a/drivers/net/wireless/intersil/prism54/islpci_dev.c
+++ b/drivers/net/wireless/intersil/prism54/islpci_dev.c
@@ -707,7 +707,9 @@ islpci_alloc_memory(islpci_private *priv)
pci_map_single(priv->pdev, (void *) skb->data,
MAX_FRAGMENT_SIZE_RX + 2,
PCI_DMA_FROMDEVICE);
- if (!priv->pci_map_rx_address[counter]) {
+ if (pci_dma_mapping_error(priv->pdev,
+ priv->pci_map_rx_address[counter])) {
+ priv->pci_map_rx_address[counter] = 0;
/* error mapping the buffer to device
accessible memory address */
printk(KERN_ERR "failed to map skb DMA'able\n");
diff --git a/drivers/net/wireless/intersil/prism54/islpci_eth.c b/drivers/net/wireless/intersil/prism54/islpci_eth.c
index 674658f2e6ef..d83f6332019e 100644
--- a/drivers/net/wireless/intersil/prism54/islpci_eth.c
+++ b/drivers/net/wireless/intersil/prism54/islpci_eth.c
@@ -190,7 +190,7 @@ islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev)
pci_map_address = pci_map_single(priv->pdev,
(void *) skb->data, skb->len,
PCI_DMA_TODEVICE);
- if (unlikely(pci_map_address == 0)) {
+ if (pci_dma_mapping_error(priv->pdev, pci_map_address)) {
printk(KERN_WARNING "%s: cannot map buffer to PCI\n",
ndev->name);
goto drop_free;
@@ -448,7 +448,8 @@ islpci_eth_receive(islpci_private *priv)
pci_map_single(priv->pdev, (void *) skb->data,
MAX_FRAGMENT_SIZE_RX + 2,
PCI_DMA_FROMDEVICE);
- if (unlikely(!priv->pci_map_rx_address[index])) {
+ if (pci_dma_mapping_error(priv->pdev,
+ priv->pci_map_rx_address[index])) {
/* error mapping the buffer to device accessible memory address */
DEBUG(SHOW_ERROR_MESSAGES,
"Error mapping DMA address\n");
diff --git a/drivers/net/wireless/intersil/prism54/islpci_mgt.c b/drivers/net/wireless/intersil/prism54/islpci_mgt.c
index 0de14dfa68cc..53d7a1705e8e 100644
--- a/drivers/net/wireless/intersil/prism54/islpci_mgt.c
+++ b/drivers/net/wireless/intersil/prism54/islpci_mgt.c
@@ -130,7 +130,7 @@ islpci_mgmt_rx_fill(struct net_device *ndev)
buf->pci_addr = pci_map_single(priv->pdev, buf->mem,
MGMT_FRAME_SIZE,
PCI_DMA_FROMDEVICE);
- if (!buf->pci_addr) {
+ if (pci_dma_mapping_error(priv->pdev, buf->pci_addr)) {
printk(KERN_WARNING
"Failed to make memory DMA'able.\n");
return -ENOMEM;
@@ -217,7 +217,7 @@ islpci_mgt_transmit(struct net_device *ndev, int operation, unsigned long oid,
err = -ENOMEM;
buf.pci_addr = pci_map_single(priv->pdev, buf.mem, frag_len,
PCI_DMA_TODEVICE);
- if (!buf.pci_addr) {
+ if (pci_dma_mapping_error(priv->pdev, buf.pci_addr)) {
printk(KERN_WARNING "%s: cannot map PCI memory for mgmt\n",
ndev->name);
goto error_free;
diff --git a/drivers/net/wireless/intersil/prism54/oid_mgt.c b/drivers/net/wireless/intersil/prism54/oid_mgt.c
index 3a8d2dbcfecd..6528ed5b9b1d 100644
--- a/drivers/net/wireless/intersil/prism54/oid_mgt.c
+++ b/drivers/net/wireless/intersil/prism54/oid_mgt.c
@@ -424,7 +424,7 @@ mgt_set_request(islpci_private *priv, enum oid_num_t n, int extra, void *data)
void *cache, *_data = data;
u32 oid;
- BUG_ON(OID_NUM_LAST <= n);
+ BUG_ON(n >= OID_NUM_LAST);
BUG_ON(extra > isl_oid[n].range);
if (!priv->mib)
@@ -485,7 +485,7 @@ mgt_set_varlen(islpci_private *priv, enum oid_num_t n, void *data, int extra_len
int dlen;
u32 oid;
- BUG_ON(OID_NUM_LAST <= n);
+ BUG_ON(n >= OID_NUM_LAST);
dlen = isl_oid[n].size;
oid = isl_oid[n].oid;
@@ -524,7 +524,7 @@ mgt_get_request(islpci_private *priv, enum oid_num_t n, int extra, void *data,
void *cache, *_res = NULL;
u32 oid;
- BUG_ON(OID_NUM_LAST <= n);
+ BUG_ON(n >= OID_NUM_LAST);
BUG_ON(extra > isl_oid[n].range);
res->ptr = NULL;
@@ -626,7 +626,7 @@ mgt_commit_list(islpci_private *priv, enum oid_num_t *l, int n)
void
mgt_set(islpci_private *priv, enum oid_num_t n, void *data)
{
- BUG_ON(OID_NUM_LAST <= n);
+ BUG_ON(n >= OID_NUM_LAST);
BUG_ON(priv->mib[n] == NULL);
memcpy(priv->mib[n], data, isl_oid[n].size);
@@ -636,7 +636,7 @@ mgt_set(islpci_private *priv, enum oid_num_t n, void *data)
void
mgt_get(islpci_private *priv, enum oid_num_t n, void *res)
{
- BUG_ON(OID_NUM_LAST <= n);
+ BUG_ON(n >= OID_NUM_LAST);
BUG_ON(priv->mib[n] == NULL);
BUG_ON(res == NULL);
diff --git a/drivers/net/wireless/marvell/libertas/cfg.c b/drivers/net/wireless/marvell/libertas/cfg.c
index 8317afd065b4..86955c416b30 100644
--- a/drivers/net/wireless/marvell/libertas/cfg.c
+++ b/drivers/net/wireless/marvell/libertas/cfg.c
@@ -1108,7 +1108,7 @@ static int lbs_associate(struct lbs_private *priv,
size_t len, resp_ie_len;
int status;
int ret;
- u8 *pos = &(cmd->iebuf[0]);
+ u8 *pos;
u8 *tmp;
lbs_deb_enter(LBS_DEB_CFG80211);
@@ -1117,6 +1117,7 @@ static int lbs_associate(struct lbs_private *priv,
ret = -ENOMEM;
goto done;
}
+ pos = &cmd->iebuf[0];
/*
* cmd 50 00
diff --git a/drivers/net/wireless/marvell/libertas/if_sdio.c b/drivers/net/wireless/marvell/libertas/if_sdio.c
index 33ceda296c9c..68fd3a9779bd 100644
--- a/drivers/net/wireless/marvell/libertas/if_sdio.c
+++ b/drivers/net/wireless/marvell/libertas/if_sdio.c
@@ -228,7 +228,7 @@ static int if_sdio_handle_cmd(struct if_sdio_card *card,
memcpy(priv->resp_buf[i], buffer, size);
lbs_notify_command_response(priv, i);
- spin_unlock_irqrestore(&card->priv->driver_lock, flags);
+ spin_unlock_irqrestore(&priv->driver_lock, flags);
ret = 0;
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
index aa498e0d2204..1efef3b8273d 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_aggr.c
@@ -203,8 +203,6 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
skb_aggr->priority = skb_src->priority;
skb_aggr->tstamp = skb_src->tstamp;
- skb_aggr->tstamp = ktime_get_real();
-
do {
/* Check if AMSDU can accommodate this MSDU */
if (skb_tailroom(skb_aggr) < (skb_src->len + LLC_SNAP_LEN))
diff --git a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
index b3970a8c9e48..09578c6cde59 100644
--- a/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
@@ -48,7 +48,17 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,
priv->wdev.iftype, 0, false);
while (!skb_queue_empty(&list)) {
+ struct rx_packet_hdr *rx_hdr;
+
rx_skb = __skb_dequeue(&list);
+ rx_hdr = (struct rx_packet_hdr *)rx_skb->data;
+ if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
+ ntohs(rx_hdr->eth803_hdr.h_proto) == ETH_P_TDLS) {
+ mwifiex_process_tdls_action_frame(priv,
+ (u8 *)rx_hdr,
+ skb->len);
+ }
+
ret = mwifiex_recv_packet(priv, rx_skb);
if (ret == -1)
mwifiex_dbg(priv->adapter, ERROR,
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index 4073116e6e9f..e7adef72c05f 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -26,12 +26,10 @@ module_param(reg_alpha2, charp, 0);
static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = {
{
- .max = 2, .types = BIT(NL80211_IFTYPE_STATION) |
+ .max = 3, .types = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_P2P_GO) |
- BIT(NL80211_IFTYPE_P2P_CLIENT),
- },
- {
- .max = 1, .types = BIT(NL80211_IFTYPE_AP),
+ BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_AP),
},
};
@@ -827,18 +825,26 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv,
switch (type) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
+ priv->bss_num = mwifiex_get_unused_bss_num(adapter,
+ MWIFIEX_BSS_TYPE_STA);
priv->bss_role = MWIFIEX_BSS_ROLE_STA;
priv->bss_type = MWIFIEX_BSS_TYPE_STA;
break;
case NL80211_IFTYPE_P2P_CLIENT:
+ priv->bss_num = mwifiex_get_unused_bss_num(adapter,
+ MWIFIEX_BSS_TYPE_P2P);
priv->bss_role = MWIFIEX_BSS_ROLE_STA;
priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
break;
case NL80211_IFTYPE_P2P_GO:
+ priv->bss_num = mwifiex_get_unused_bss_num(adapter,
+ MWIFIEX_BSS_TYPE_P2P);
priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
priv->bss_type = MWIFIEX_BSS_TYPE_P2P;
break;
case NL80211_IFTYPE_AP:
+ priv->bss_num = mwifiex_get_unused_bss_num(adapter,
+ MWIFIEX_BSS_TYPE_UAP);
priv->bss_type = MWIFIEX_BSS_TYPE_UAP;
priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
break;
@@ -1533,6 +1539,7 @@ static const u32 mwifiex_cipher_suites[] = {
WLAN_CIPHER_SUITE_WEP104,
WLAN_CIPHER_SUITE_TKIP,
WLAN_CIPHER_SUITE_CCMP,
+ WLAN_CIPHER_SUITE_SMS4,
WLAN_CIPHER_SUITE_AES_CMAC,
};
@@ -1701,6 +1708,11 @@ mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
u8 deauth_mac[ETH_ALEN];
unsigned long flags;
+ if (!priv->bss_started && priv->wdev.cac_started) {
+ mwifiex_dbg(priv->adapter, INFO, "%s: abort CAC!\n", __func__);
+ mwifiex_abort_cac(priv);
+ }
+
if (list_empty(&priv->sta_list) || !priv->bss_started)
return 0;
@@ -2608,7 +2620,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
return ERR_PTR(-EINVAL);
}
- priv = mwifiex_get_unused_priv(adapter);
+ priv = mwifiex_get_unused_priv_by_bss_type(
+ adapter, MWIFIEX_BSS_TYPE_STA);
if (!priv) {
mwifiex_dbg(adapter, ERROR,
"could not get free private struct\n");
@@ -2627,7 +2640,6 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II;
priv->bss_priority = 0;
priv->bss_role = MWIFIEX_BSS_ROLE_STA;
- priv->bss_num = adapter->curr_iface_comb.sta_intf;
break;
case NL80211_IFTYPE_AP:
@@ -2638,7 +2650,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
return ERR_PTR(-EINVAL);
}
- priv = mwifiex_get_unused_priv(adapter);
+ priv = mwifiex_get_unused_priv_by_bss_type(
+ adapter, MWIFIEX_BSS_TYPE_UAP);
if (!priv) {
mwifiex_dbg(adapter, ERROR,
"could not get free private struct\n");
@@ -2653,7 +2666,6 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->bss_priority = 0;
priv->bss_role = MWIFIEX_BSS_ROLE_UAP;
priv->bss_started = 0;
- priv->bss_num = adapter->curr_iface_comb.uap_intf;
priv->bss_mode = type;
break;
@@ -2665,7 +2677,8 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
return ERR_PTR(-EINVAL);
}
- priv = mwifiex_get_unused_priv(adapter);
+ priv = mwifiex_get_unused_priv_by_bss_type(
+ adapter, MWIFIEX_BSS_TYPE_P2P);
if (!priv) {
mwifiex_dbg(adapter, ERROR,
"could not get free private struct\n");
@@ -2689,7 +2702,6 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
priv->bss_priority = MWIFIEX_BSS_ROLE_STA;
priv->bss_role = MWIFIEX_BSS_ROLE_STA;
priv->bss_started = 0;
- priv->bss_num = adapter->curr_iface_comb.p2p_intf;
if (mwifiex_cfg80211_init_p2p_client(priv)) {
memset(&priv->wdev, 0, sizeof(priv->wdev));
@@ -2914,6 +2926,12 @@ mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq,
dont_care_byte = true;
}
+ /* wildcard bytes record as the offset
+ * before the valid byte
+ */
+ if (!valid_byte_cnt && !dont_care_byte)
+ pat->pkt_offset++;
+
if (valid_byte_cnt > max_byte_seq)
return false;
}
@@ -3141,8 +3159,8 @@ static int mwifiex_cfg80211_suspend(struct wiphy *wiphy,
memset(&hs_cfg, 0, sizeof(hs_cfg));
hs_cfg.is_invoke_hostcmd = false;
hs_cfg.conditions = HS_CFG_COND_MAC_EVENT;
- hs_cfg.gpio = HS_CFG_GPIO_DEF;
- hs_cfg.gap = HS_CFG_GAP_DEF;
+ hs_cfg.gpio = adapter->hs_cfg.gpio;
+ hs_cfg.gap = adapter->hs_cfg.gap;
ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET,
MWIFIEX_SYNC_CMD, &hs_cfg);
if (ret) {
@@ -3802,6 +3820,10 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
wiphy->cipher_suites = mwifiex_cipher_suites;
wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites);
+ if (adapter->region_code)
+ wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS |
+ REGULATORY_COUNTRY_IE_IGNORE;
+
ether_addr_copy(wiphy->perm_addr, adapter->perm_addr);
wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
@@ -3862,11 +3884,15 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
"driver hint alpha2: %2.2s\n", reg_alpha2);
regulatory_hint(wiphy, reg_alpha2);
} else {
- country_code = mwifiex_11d_code_2_region(adapter->region_code);
- if (country_code)
- mwifiex_dbg(adapter, WARN,
- "ignoring F/W country code %2.2s\n",
- country_code);
+ if (adapter->region_code == 0x00) {
+ mwifiex_dbg(adapter, WARN, "Ignore world regulatory domain\n");
+ } else {
+ country_code =
+ mwifiex_11d_code_2_region(adapter->region_code);
+ if (country_code &&
+ regulatory_hint(wiphy, country_code))
+ mwifiex_dbg(priv->adapter, ERROR, "regulatory_hint() failed\n");
+ }
}
mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB,
diff --git a/drivers/net/wireless/marvell/mwifiex/cfp.c b/drivers/net/wireless/marvell/mwifiex/cfp.c
index 3ddb8ec676ed..09fae27140f7 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfp.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfp.c
@@ -66,8 +66,8 @@ static u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c,
0x12, 0x16, 0x18, 0x24, 0x30, 0x48,
0x60, 0x6c, 0 };
-u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x10, 0x20, 0x30,
- 0x32, 0x40, 0x41, 0xff };
+u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x00, 0x10, 0x20, 0x30,
+ 0x31, 0x32, 0x40, 0x41, 0x50 };
static u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 };
@@ -168,7 +168,7 @@ struct region_code_mapping {
static struct region_code_mapping region_code_mapping_t[] = {
{ 0x10, "US " }, /* US FCC */
{ 0x20, "CA " }, /* IC Canada */
- { 0x30, "EU " }, /* ETSI */
+ { 0x30, "FR " }, /* France */
{ 0x31, "ES " }, /* Spain */
{ 0x32, "FR " }, /* France */
{ 0x40, "JP " }, /* Japan */
diff --git a/drivers/net/wireless/marvell/mwifiex/cmdevt.c b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
index 45ae38e32621..cb25aa7e90db 100644
--- a/drivers/net/wireless/marvell/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/marvell/mwifiex/cmdevt.c
@@ -1637,9 +1637,9 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv,
if (adapter->region_code == region_code_index[i])
break;
- /* If it's unidentified region code, use the default (USA) */
+ /* If it's unidentified region code, use the default (world) */
if (i >= MWIFIEX_MAX_REGION_CODE) {
- adapter->region_code = 0x10;
+ adapter->region_code = 0x00;
mwifiex_dbg(adapter, WARN,
"cmd: unknown region code, use default (USA)\n");
}
diff --git a/drivers/net/wireless/marvell/mwifiex/debugfs.c b/drivers/net/wireless/marvell/mwifiex/debugfs.c
index 9824d8dd2b44..5e5562909d9f 100644
--- a/drivers/net/wireless/marvell/mwifiex/debugfs.c
+++ b/drivers/net/wireless/marvell/mwifiex/debugfs.c
@@ -906,6 +906,34 @@ mwifiex_timeshare_coex_write(struct file *file, const char __user *ubuf,
return count;
}
+static ssize_t
+mwifiex_reset_write(struct file *file,
+ const char __user *ubuf, size_t count, loff_t *ppos)
+{
+ struct mwifiex_private *priv = file->private_data;
+ struct mwifiex_adapter *adapter = priv->adapter;
+ char cmd;
+ bool result;
+
+ if (copy_from_user(&cmd, ubuf, sizeof(cmd)))
+ return -EFAULT;
+
+ if (strtobool(&cmd, &result))
+ return -EINVAL;
+
+ if (!result)
+ return -EINVAL;
+
+ if (adapter->if_ops.card_reset) {
+ dev_info(adapter->dev, "Resetting per request\n");
+ adapter->hw_status = MWIFIEX_HW_STATUS_RESET;
+ mwifiex_cancel_all_pending_cmd(adapter);
+ adapter->if_ops.card_reset(adapter);
+ }
+
+ return count;
+}
+
#define MWIFIEX_DFS_ADD_FILE(name) do { \
if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir, \
priv, &mwifiex_dfs_##name##_fops)) \
@@ -943,6 +971,7 @@ MWIFIEX_DFS_FILE_OPS(hscfg);
MWIFIEX_DFS_FILE_OPS(histogram);
MWIFIEX_DFS_FILE_OPS(debug_mask);
MWIFIEX_DFS_FILE_OPS(timeshare_coex);
+MWIFIEX_DFS_FILE_WRITE_OPS(reset);
/*
* This function creates the debug FS directory structure and the files.
@@ -970,6 +999,7 @@ mwifiex_dev_debugfs_init(struct mwifiex_private *priv)
MWIFIEX_DFS_ADD_FILE(histogram);
MWIFIEX_DFS_ADD_FILE(debug_mask);
MWIFIEX_DFS_ADD_FILE(timeshare_coex);
+ MWIFIEX_DFS_ADD_FILE(reset);
}
/*
diff --git a/drivers/net/wireless/marvell/mwifiex/decl.h b/drivers/net/wireless/marvell/mwifiex/decl.h
index 098e1f14dc9a..d9c15cd36f12 100644
--- a/drivers/net/wireless/marvell/mwifiex/decl.h
+++ b/drivers/net/wireless/marvell/mwifiex/decl.h
@@ -111,9 +111,9 @@
/* Rate index for OFDM 0 */
#define MWIFIEX_RATE_INDEX_OFDM0 4
-#define MWIFIEX_MAX_STA_NUM 1
-#define MWIFIEX_MAX_UAP_NUM 1
-#define MWIFIEX_MAX_P2P_NUM 1
+#define MWIFIEX_MAX_STA_NUM 3
+#define MWIFIEX_MAX_UAP_NUM 3
+#define MWIFIEX_MAX_P2P_NUM 3
#define MWIFIEX_A_BAND_START_FREQ 5000
diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h
index 1e1e81a0a8d4..ced7af2be29a 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -537,7 +537,7 @@ enum P2P_MODES {
#define EVENT_GET_BSS_TYPE(event_cause) \
(((event_cause) >> 24) & 0x00ff)
-#define MWIFIEX_MAX_PATTERN_LEN 20
+#define MWIFIEX_MAX_PATTERN_LEN 40
#define MWIFIEX_MAX_OFFSET_LEN 100
#define STACK_NBYTES 100
#define TYPE_DNUM 1
@@ -1092,9 +1092,15 @@ struct host_cmd_ds_802_11_ad_hoc_start {
u8 data_rate[HOSTCMD_SUPPORTED_RATES];
} __packed;
-struct host_cmd_ds_802_11_ad_hoc_result {
+struct host_cmd_ds_802_11_ad_hoc_start_result {
u8 pad[3];
u8 bssid[ETH_ALEN];
+ u8 pad2[2];
+ u8 result;
+} __packed;
+
+struct host_cmd_ds_802_11_ad_hoc_join_result {
+ u8 result;
} __packed;
struct adhoc_bss_desc {
@@ -2124,7 +2130,8 @@ struct host_cmd_ds_command {
struct host_cmd_ds_802_11_associate_rsp associate_rsp;
struct host_cmd_ds_802_11_deauthenticate deauth;
struct host_cmd_ds_802_11_ad_hoc_start adhoc_start;
- struct host_cmd_ds_802_11_ad_hoc_result adhoc_result;
+ struct host_cmd_ds_802_11_ad_hoc_start_result start_result;
+ struct host_cmd_ds_802_11_ad_hoc_join_result join_result;
struct host_cmd_ds_802_11_ad_hoc_join adhoc_join;
struct host_cmd_ds_802_11d_domain_info domain_info;
struct host_cmd_ds_802_11d_domain_info_rsp domain_info_resp;
diff --git a/drivers/net/wireless/marvell/mwifiex/ie.c b/drivers/net/wireless/marvell/mwifiex/ie.c
index abf52d25b981..c488c3068abc 100644
--- a/drivers/net/wireless/marvell/mwifiex/ie.c
+++ b/drivers/net/wireless/marvell/mwifiex/ie.c
@@ -140,7 +140,7 @@ mwifiex_update_autoindex_ies(struct mwifiex_private *priv,
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
return mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
HostCmd_ACT_GEN_SET,
- UAP_CUSTOM_IE_I, ie_list, false);
+ UAP_CUSTOM_IE_I, ie_list, true);
return 0;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/init.c b/drivers/net/wireless/marvell/mwifiex/init.c
index de74a7773fb6..6f7876ec31b7 100644
--- a/drivers/net/wireless/marvell/mwifiex/init.c
+++ b/drivers/net/wireless/marvell/mwifiex/init.c
@@ -95,7 +95,7 @@ int mwifiex_init_priv(struct mwifiex_private *priv)
priv->curr_pkt_filter = HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON |
HostCmd_ACT_MAC_ETHERNETII_ENABLE;
- priv->beacon_period = 100; /* beacon interval */ ;
+ priv->beacon_period = 100; /* beacon interval */
priv->attempted_bss_desc = NULL;
memset(&priv->curr_bss_params, 0, sizeof(priv->curr_bss_params));
priv->listen_interval = MWIFIEX_DEFAULT_LISTEN_INTERVAL;
diff --git a/drivers/net/wireless/marvell/mwifiex/join.c b/drivers/net/wireless/marvell/mwifiex/join.c
index 3cda1f956f0b..cc09a81dbf6a 100644
--- a/drivers/net/wireless/marvell/mwifiex/join.c
+++ b/drivers/net/wireless/marvell/mwifiex/join.c
@@ -1247,20 +1247,26 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
{
int ret = 0;
struct mwifiex_adapter *adapter = priv->adapter;
- struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result;
+ struct host_cmd_ds_802_11_ad_hoc_start_result *start_result =
+ &resp->params.start_result;
+ struct host_cmd_ds_802_11_ad_hoc_join_result *join_result =
+ &resp->params.join_result;
struct mwifiex_bssdescriptor *bss_desc;
- u16 reason_code;
+ u16 cmd = le16_to_cpu(resp->command);
+ u8 result;
- adhoc_result = &resp->params.adhoc_result;
+ if (cmd == HostCmd_CMD_802_11_AD_HOC_START)
+ result = start_result->result;
+ else
+ result = join_result->result;
bss_desc = priv->attempted_bss_desc;
/* Join result code 0 --> SUCCESS */
- reason_code = le16_to_cpu(resp->result);
- if (reason_code) {
+ if (result) {
mwifiex_dbg(priv->adapter, ERROR, "ADHOC_RESP: failed\n");
if (priv->media_connected)
- mwifiex_reset_connect_state(priv, reason_code);
+ mwifiex_reset_connect_state(priv, result);
memset(&priv->curr_bss_params.bss_descriptor,
0x00, sizeof(struct mwifiex_bssdescriptor));
@@ -1278,7 +1284,7 @@ int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv,
/* Update the created network descriptor with the new BSSID */
memcpy(bss_desc->mac_address,
- adhoc_result->bssid, ETH_ALEN);
+ start_result->bssid, ETH_ALEN);
priv->adhoc_state = ADHOC_STARTED;
} else {
diff --git a/drivers/net/wireless/marvell/mwifiex/main.c b/drivers/net/wireless/marvell/mwifiex/main.c
index 969ca1e1f3e9..79c16de8743e 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.c
+++ b/drivers/net/wireless/marvell/mwifiex/main.c
@@ -763,7 +763,7 @@ mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
spin_lock_irqsave(&priv->ack_status_lock, flags);
id = idr_alloc(&priv->ack_status_frames, orig_skb,
- 1, 0xff, GFP_ATOMIC);
+ 1, 0x10, GFP_ATOMIC);
spin_unlock_irqrestore(&priv->ack_status_lock, flags);
if (id >= 0) {
diff --git a/drivers/net/wireless/marvell/mwifiex/main.h b/drivers/net/wireless/marvell/mwifiex/main.h
index 3959f1c97f4e..2f7f478ce04b 100644
--- a/drivers/net/wireless/marvell/mwifiex/main.h
+++ b/drivers/net/wireless/marvell/mwifiex/main.h
@@ -84,7 +84,7 @@ enum {
#define MWIFIEX_KEY_BUFFER_SIZE 16
#define MWIFIEX_DEFAULT_LISTEN_INTERVAL 10
-#define MWIFIEX_MAX_REGION_CODE 7
+#define MWIFIEX_MAX_REGION_CODE 9
#define DEFAULT_BCN_AVG_FACTOR 8
#define DEFAULT_DATA_AVG_FACTOR 8
@@ -564,14 +564,14 @@ struct mwifiex_private {
struct mwifiex_wep_key wep_key[NUM_WEP_KEYS];
u16 wep_key_curr_index;
u8 wpa_ie[256];
- u8 wpa_ie_len;
+ u16 wpa_ie_len;
u8 wpa_is_gtk_set;
struct host_cmd_ds_802_11_key_material aes_key;
struct host_cmd_ds_802_11_key_material_v2 aes_key_v2;
u8 wapi_ie[256];
- u8 wapi_ie_len;
+ u16 wapi_ie_len;
u8 *wps_ie;
- u8 wps_ie_len;
+ u16 wps_ie_len;
u8 wmm_required;
u8 wmm_enabled;
u8 wmm_qosinfo;
@@ -1273,20 +1273,46 @@ mwifiex_get_priv(struct mwifiex_adapter *adapter,
}
/*
+ * This function checks available bss_num when adding new interface or
+ * changing interface type.
+ */
+static inline u8
+mwifiex_get_unused_bss_num(struct mwifiex_adapter *adapter, u8 bss_type)
+{
+ u8 i, j;
+ int index[MWIFIEX_MAX_BSS_NUM];
+
+ memset(index, 0, sizeof(index));
+ for (i = 0; i < adapter->priv_num; i++)
+ if (adapter->priv[i]) {
+ if (adapter->priv[i]->bss_type == bss_type &&
+ !(adapter->priv[i]->bss_mode ==
+ NL80211_IFTYPE_UNSPECIFIED)) {
+ index[adapter->priv[i]->bss_num] = 1;
+ }
+ }
+ for (j = 0; j < MWIFIEX_MAX_BSS_NUM; j++)
+ if (!index[j])
+ return j;
+ return -1;
+}
+
+/*
* This function returns the first available unused private structure pointer.
*/
static inline struct mwifiex_private *
-mwifiex_get_unused_priv(struct mwifiex_adapter *adapter)
+mwifiex_get_unused_priv_by_bss_type(struct mwifiex_adapter *adapter,
+ u8 bss_type)
{
- int i;
+ u8 i;
- for (i = 0; i < adapter->priv_num; i++) {
- if (adapter->priv[i]) {
- if (adapter->priv[i]->bss_mode ==
- NL80211_IFTYPE_UNSPECIFIED)
- break;
+ for (i = 0; i < adapter->priv_num; i++)
+ if (adapter->priv[i]->bss_mode ==
+ NL80211_IFTYPE_UNSPECIFIED) {
+ adapter->priv[i]->bss_num =
+ mwifiex_get_unused_bss_num(adapter, bss_type);
+ break;
}
- }
return ((i < adapter->priv_num) ? adapter->priv[i] : NULL);
}
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c
index 21192b6f9c64..6d0dc40e20e5 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.c
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.c
@@ -2129,14 +2129,14 @@ static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context)
struct mwifiex_adapter *adapter;
if (!pdev) {
- pr_debug("info: %s: pdev is NULL\n", (u8 *)pdev);
+ pr_err("info: %s: pdev is NULL\n", __func__);
goto exit;
}
card = pci_get_drvdata(pdev);
if (!card || !card->adapter) {
- pr_debug("info: %s: card=%p adapter=%p\n", __func__, card,
- card ? card->adapter : NULL);
+ pr_err("info: %s: card=%p adapter=%p\n", __func__, card,
+ card ? card->adapter : NULL);
goto exit;
}
adapter = card->adapter;
@@ -2473,50 +2473,44 @@ static int mwifiex_pcie_init(struct mwifiex_adapter *adapter)
pci_set_master(pdev);
- mwifiex_dbg(adapter, INFO,
- "try set_consistent_dma_mask(32)\n");
+ pr_notice("try set_consistent_dma_mask(32)\n");
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (ret) {
- mwifiex_dbg(adapter, ERROR,
- "set_dma_mask(32) failed\n");
+ pr_err("set_dma_mask(32) failed\n");
goto err_set_dma_mask;
}
ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
if (ret) {
- mwifiex_dbg(adapter, ERROR,
- "set_consistent_dma_mask(64) failed\n");
+ pr_err("set_consistent_dma_mask(64) failed\n");
goto err_set_dma_mask;
}
ret = pci_request_region(pdev, 0, DRV_NAME);
if (ret) {
- mwifiex_dbg(adapter, ERROR,
- "req_reg(0) error\n");
+ pr_err("req_reg(0) error\n");
goto err_req_region0;
}
card->pci_mmap = pci_iomap(pdev, 0, 0);
if (!card->pci_mmap) {
- mwifiex_dbg(adapter, ERROR, "iomap(0) error\n");
+ pr_err("iomap(0) error\n");
ret = -EIO;
goto err_iomap0;
}
ret = pci_request_region(pdev, 2, DRV_NAME);
if (ret) {
- mwifiex_dbg(adapter, ERROR, "req_reg(2) error\n");
+ pr_err("req_reg(2) error\n");
goto err_req_region2;
}
card->pci_mmap1 = pci_iomap(pdev, 2, 0);
if (!card->pci_mmap1) {
- mwifiex_dbg(adapter, ERROR,
- "iomap(2) error\n");
+ pr_err("iomap(2) error\n");
ret = -EIO;
goto err_iomap2;
}
- mwifiex_dbg(adapter, INFO,
- "PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
- card->pci_mmap, card->pci_mmap1);
+ pr_notice("PCI memory map Virt0: %p PCI memory map Virt2: %p\n",
+ card->pci_mmap, card->pci_mmap1);
card->cmdrsp_buf = NULL;
ret = mwifiex_pcie_create_txbd_ring(adapter);
@@ -2599,6 +2593,30 @@ static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
kfree(card);
}
+static int mwifiex_pcie_request_irq(struct mwifiex_adapter *adapter)
+{
+ int ret;
+ struct pcie_service_card *card = adapter->card;
+ struct pci_dev *pdev = card->dev;
+
+ if (pci_enable_msi(pdev) != 0)
+ pci_disable_msi(pdev);
+ else
+ card->msi_enable = 1;
+
+ mwifiex_dbg(adapter, INFO, "msi_enable = %d\n", card->msi_enable);
+
+ ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED,
+ "MRVL_PCIE", pdev);
+ if (ret) {
+ pr_err("request_irq failed: ret=%d\n", ret);
+ adapter->card = NULL;
+ return -1;
+ }
+
+ return 0;
+}
+
/*
* This function registers the PCIE device.
*
@@ -2606,23 +2624,16 @@ static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter)
*/
static int mwifiex_register_dev(struct mwifiex_adapter *adapter)
{
- int ret;
struct pcie_service_card *card = adapter->card;
struct pci_dev *pdev = card->dev;
/* save adapter pointer in card */
card->adapter = adapter;
+ adapter->dev = &pdev->dev;
- ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED,
- "MRVL_PCIE", pdev);
- if (ret) {
- mwifiex_dbg(adapter, ERROR,
- "request_irq failed: ret=%d\n", ret);
- adapter->card = NULL;
+ if (mwifiex_pcie_request_irq(adapter))
return -1;
- }
- adapter->dev = &pdev->dev;
adapter->tx_buf_size = card->pcie.tx_buf_size;
adapter->mem_type_mapping_tbl = mem_type_mapping_tbl;
adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl);
diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.h b/drivers/net/wireless/marvell/mwifiex/pcie.h
index 48e549c3b285..6fc28737b576 100644
--- a/drivers/net/wireless/marvell/mwifiex/pcie.h
+++ b/drivers/net/wireless/marvell/mwifiex/pcie.h
@@ -210,17 +210,17 @@ static const struct mwifiex_pcie_card_reg mwifiex_reg_8997 = {
.cmdrsp_addr_lo = PCIE_SCRATCH_4_REG,
.cmdrsp_addr_hi = PCIE_SCRATCH_5_REG,
.tx_rdptr = 0xC1A4,
- .tx_wrptr = 0xC1A8,
- .rx_rdptr = 0xC1A8,
+ .tx_wrptr = 0xC174,
+ .rx_rdptr = 0xC174,
.rx_wrptr = 0xC1A4,
.evt_rdptr = PCIE_SCRATCH_10_REG,
.evt_wrptr = PCIE_SCRATCH_11_REG,
.drv_rdy = PCIE_SCRATCH_12_REG,
.tx_start_ptr = 16,
.tx_mask = 0x0FFF0000,
- .tx_wrap_mask = 0x01FF0000,
+ .tx_wrap_mask = 0x1FFF0000,
.rx_mask = 0x00000FFF,
- .rx_wrap_mask = 0x000001FF,
+ .rx_wrap_mask = 0x00001FFF,
.tx_rollover_ind = BIT(28),
.rx_rollover_ind = BIT(12),
.evt_rollover_ind = MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND,
@@ -326,6 +326,7 @@ struct pcie_service_card {
dma_addr_t sleep_cookie_pbase;
void __iomem *pci_mmap;
void __iomem *pci_mmap1;
+ int msi_enable;
};
static inline int
@@ -342,6 +343,7 @@ mwifiex_pcie_txbd_empty(struct pcie_service_card *card, u32 rdptr)
return 1;
break;
case PCIE_DEVICE_ID_MARVELL_88W8897:
+ case PCIE_DEVICE_ID_MARVELL_88W8997:
if (((card->txbd_wrptr & reg->tx_mask) ==
(rdptr & reg->tx_mask)) &&
((card->txbd_wrptr & reg->tx_rollover_ind) ==
diff --git a/drivers/net/wireless/marvell/mwifiex/sdio.c b/drivers/net/wireless/marvell/mwifiex/sdio.c
index 78a8474e1a3d..4c8cae682c89 100644
--- a/drivers/net/wireless/marvell/mwifiex/sdio.c
+++ b/drivers/net/wireless/marvell/mwifiex/sdio.c
@@ -796,8 +796,8 @@ mwifiex_sdio_interrupt(struct sdio_func *func)
card = sdio_get_drvdata(func);
if (!card || !card->adapter) {
- pr_debug("int: func=%p card=%p adapter=%p\n",
- func, card, card ? card->adapter : NULL);
+ pr_err("int: func=%p card=%p adapter=%p\n",
+ func, card, card ? card->adapter : NULL);
return;
}
adapter = card->adapter;
@@ -2053,8 +2053,19 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter)
/* Allocate skb pointer buffers */
card->mpa_rx.skb_arr = kzalloc((sizeof(void *)) *
card->mp_agg_pkt_limit, GFP_KERNEL);
+ if (!card->mpa_rx.skb_arr) {
+ kfree(card->mp_regs);
+ return -ENOMEM;
+ }
+
card->mpa_rx.len_arr = kzalloc(sizeof(*card->mpa_rx.len_arr) *
card->mp_agg_pkt_limit, GFP_KERNEL);
+ if (!card->mpa_rx.len_arr) {
+ kfree(card->mp_regs);
+ kfree(card->mpa_rx.skb_arr);
+ return -ENOMEM;
+ }
+
ret = mwifiex_alloc_sdio_mpa_buffers(adapter,
card->mp_tx_agg_buf_size,
card->mp_rx_agg_buf_size);
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
index a6c8a4f7bfe9..6a4fc5d183cf 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
@@ -272,7 +272,8 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
priv->scan_block = false;
if (bss) {
- mwifiex_process_country_ie(priv, bss);
+ if (adapter->region_code == 0x00)
+ mwifiex_process_country_ie(priv, bss);
/* Allocate and fill new bss descriptor */
bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
@@ -758,7 +759,7 @@ static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv,
return -1;
}
memcpy(priv->wpa_ie, ie_data_ptr, ie_len);
- priv->wpa_ie_len = (u8) ie_len;
+ priv->wpa_ie_len = ie_len;
mwifiex_dbg(priv->adapter, CMD,
"cmd: Set Wpa_ie_len=%d IE=%#x\n",
priv->wpa_ie_len, priv->wpa_ie[0]);
@@ -923,9 +924,8 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv,
if (encrypt_key->key_disable) {
memset(&priv->wep_key[index], 0,
sizeof(struct mwifiex_wep_key));
- if (wep_key->key_length)
- goto done;
- }
+ goto done;
+ }
if (adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2)
enc_key = encrypt_key;
@@ -1293,6 +1293,8 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
struct ieee_types_vendor_header *pvendor_ie;
const u8 wpa_oui[] = { 0x00, 0x50, 0xf2, 0x01 };
const u8 wps_oui[] = { 0x00, 0x50, 0xf2, 0x04 };
+ u16 unparsed_len = ie_len;
+ int find_wpa_ie = 0;
/* If the passed length is zero, reset the buffer */
if (!ie_len) {
@@ -1304,40 +1306,69 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
return -1;
}
pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
- /* Test to see if it is a WPA IE, if not, then it is a gen IE */
- if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
- (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||
- (pvendor_ie->element_id == WLAN_EID_RSN)) {
- /* IE is a WPA/WPA2 IE so call set_wpa function */
- ret = mwifiex_set_wpa_ie_helper(priv, ie_data_ptr, ie_len);
- priv->wps.session_enable = false;
+ while (pvendor_ie) {
+ if (pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) {
+ /* Test to see if it is a WPA IE, if not, then it is a
+ * gen IE
+ */
+ if (!memcmp(pvendor_ie->oui, wpa_oui,
+ sizeof(wpa_oui))) {
+ find_wpa_ie = 1;
+ break;
+ }
- return ret;
- } else if (pvendor_ie->element_id == WLAN_EID_BSS_AC_ACCESS_DELAY) {
+ /* Test to see if it is a WPS IE, if so, enable
+ * wps session flag
+ */
+ if (!memcmp(pvendor_ie->oui, wps_oui,
+ sizeof(wps_oui))) {
+ priv->wps.session_enable = true;
+ mwifiex_dbg(priv->adapter, MSG,
+ "info: WPS Session Enabled.\n");
+ ret = mwifiex_set_wps_ie(priv,
+ (u8 *)pvendor_ie,
+ unparsed_len);
+ }
+ }
+
+ if (pvendor_ie->element_id == WLAN_EID_RSN) {
+ find_wpa_ie = 1;
+ break;
+ }
+
+ if (pvendor_ie->element_id == WLAN_EID_BSS_AC_ACCESS_DELAY) {
/* IE is a WAPI IE so call set_wapi function */
- ret = mwifiex_set_wapi_ie(priv, ie_data_ptr, ie_len);
+ ret = mwifiex_set_wapi_ie(priv, (u8 *)pvendor_ie,
+ unparsed_len);
+ return ret;
+ }
+ unparsed_len -= (pvendor_ie->len +
+ sizeof(struct ieee_types_header));
+
+ if (unparsed_len <= sizeof(struct ieee_types_header))
+ pvendor_ie = NULL;
+ else
+ pvendor_ie = (struct ieee_types_vendor_header *)
+ (((u8 *)pvendor_ie) + pvendor_ie->len +
+ sizeof(struct ieee_types_header));
+ }
+
+ if (find_wpa_ie) {
+ /* IE is a WPA/WPA2 IE so call set_wpa function */
+ ret = mwifiex_set_wpa_ie_helper(priv, (u8 *)pvendor_ie,
+ unparsed_len);
+ priv->wps.session_enable = false;
return ret;
}
+
/*
* Verify that the passed length is not larger than the
* available space remaining in the buffer
*/
if (ie_len < (sizeof(priv->gen_ie_buf) - priv->gen_ie_buf_len)) {
- /* Test to see if it is a WPS IE, if so, enable
- * wps session flag
- */
- pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
- if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
- (!memcmp(pvendor_ie->oui, wps_oui, sizeof(wps_oui)))) {
- priv->wps.session_enable = true;
- mwifiex_dbg(priv->adapter, INFO,
- "info: WPS Session Enabled.\n");
- ret = mwifiex_set_wps_ie(priv, ie_data_ptr, ie_len);
- }
-
/* Append the passed data to the end of the
genIeBuffer */
memcpy(priv->gen_ie_buf + priv->gen_ie_buf_len, ie_data_ptr,
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_rx.c b/drivers/net/wireless/marvell/mwifiex/sta_rx.c
index d4d4cb1ce95b..00fcbda09349 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_rx.c
@@ -215,7 +215,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
if (rx_pkt_type == PKT_TYPE_MGMT) {
ret = mwifiex_process_mgmt_packet(priv, skb);
if (ret)
- mwifiex_dbg(adapter, ERROR, "Rx of mgmt packet failed");
+ mwifiex_dbg(adapter, DATA, "Rx of mgmt packet failed");
dev_kfree_skb_any(skb);
return ret;
}
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
index 759a6ada5b0f..e791166d90c4 100644
--- a/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_cmd.c
@@ -848,9 +848,9 @@ int mwifiex_config_start_uap(struct mwifiex_private *priv,
if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG,
HostCmd_ACT_GEN_SET,
- UAP_BSS_PARAMS_I, bss_cfg, false)) {
+ UAP_BSS_PARAMS_I, bss_cfg, true)) {
mwifiex_dbg(priv->adapter, ERROR,
- "Failed to set the SSID\n");
+ "Failed to set AP configuration\n");
return -1;
}
@@ -865,7 +865,7 @@ int mwifiex_config_start_uap(struct mwifiex_private *priv,
}
if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START,
- HostCmd_ACT_GEN_SET, 0, NULL, false)) {
+ HostCmd_ACT_GEN_SET, 0, NULL, true)) {
mwifiex_dbg(priv->adapter, ERROR,
"Failed to start the BSS\n");
return -1;
diff --git a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
index 74d5d7238633..52f7981a8afc 100644
--- a/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/marvell/mwifiex/uap_txrx.c
@@ -310,8 +310,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
if (rx_pkt_type == PKT_TYPE_MGMT) {
ret = mwifiex_process_mgmt_packet(priv, skb);
if (ret)
- mwifiex_dbg(adapter, ERROR,
- "Rx of mgmt packet failed");
+ mwifiex_dbg(adapter, DATA, "Rx of mgmt packet failed");
dev_kfree_skb_any(skb);
return ret;
}
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
index b50d873145d5..d26018f30b7d 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2500usb.c
@@ -229,7 +229,10 @@ static void _rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
const unsigned int offset,
u32 *value)
{
- rt2500usb_register_read(rt2x00dev, offset, (u16 *)value);
+ u16 tmp;
+
+ rt2500usb_register_read(rt2x00dev, offset, &tmp);
+ *value = tmp;
}
static void _rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00pci.c b/drivers/net/wireless/ralink/rt2x00/rt2x00pci.c
index d93db4b0371b..eb6dbcd4fddf 100644
--- a/drivers/net/wireless/ralink/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/ralink/rt2x00/rt2x00pci.c
@@ -149,6 +149,7 @@ exit_free_device:
ieee80211_free_hw(hw);
exit_release_regions:
+ pci_clear_mwi(pci_dev);
pci_release_regions(pci_dev);
exit_disable_device:
@@ -173,6 +174,7 @@ void rt2x00pci_remove(struct pci_dev *pci_dev)
/*
* Free the PCI device data.
*/
+ pci_clear_mwi(pci_dev);
pci_disable_device(pci_dev);
pci_release_regions(pci_dev);
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
index 53261d6f8578..451456835f87 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8192e2ant.c
@@ -3356,9 +3356,8 @@ void ex_halbtc8192e2ant_display_coex_info(struct btc_coexist *btcoexist)
"Dot11 channel / HsMode(HsChnl)",
wifi_dot11_chnl, bt_hson, wifi_hs_chnl);
- RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %02x %02x %02x ",
- "H2C Wifi inform bt chnl Info", coex_dm->wifi_chnl_info[0],
- coex_dm->wifi_chnl_info[1], coex_dm->wifi_chnl_info[2]);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %3ph ",
+ "H2C Wifi inform bt chnl Info", coex_dm->wifi_chnl_info);
btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifirssi);
btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi);
@@ -3409,17 +3408,9 @@ void ex_halbtc8192e2ant_display_coex_info(struct btc_coexist *btcoexist)
for (i = 0; i < BT_INFO_SRC_8192E_2ANT_MAX; i++) {
if (coex_sta->bt_info_c2h_cnt[i]) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "\r\n %-35s = %02x %02x %02x %02x ",
+ "\r\n %-35s = %7ph(%d)",
GLBtInfoSrc8192e2Ant[i],
- coex_sta->bt_info_c2h[i][0],
- coex_sta->bt_info_c2h[i][1],
- coex_sta->bt_info_c2h[i][2],
- coex_sta->bt_info_c2h[i][3]);
- RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "%02x %02x %02x(%d)",
- coex_sta->bt_info_c2h[i][4],
- coex_sta->bt_info_c2h[i][5],
- coex_sta->bt_info_c2h[i][6],
+ coex_sta->bt_info_c2h[i],
coex_sta->bt_info_c2h_cnt[i]);
}
}
@@ -3453,10 +3444,8 @@ void ex_halbtc8192e2ant_display_coex_info(struct btc_coexist *btcoexist)
ps_tdma_case = coex_dm->cur_ps_tdma;
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)",
- "PS TDMA", coex_dm->ps_tdma_para[0],
- coex_dm->ps_tdma_para[1], coex_dm->ps_tdma_para[2],
- coex_dm->ps_tdma_para[3], coex_dm->ps_tdma_para[4],
+ "\r\n %-35s = %5ph case-%d (auto:%d)",
+ "PS TDMA", coex_dm->ps_tdma_para,
ps_tdma_case, coex_dm->auto_tdma_adjust);
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d ",
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
index c4acd403e5f6..7e239d3cea26 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b1ant.c
@@ -2457,10 +2457,9 @@ void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
"Dot11 channel / HsChnl(HsMode)",
wifi_dot11_chnl, wifi_hs_chnl, bt_hs_on);
- RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %02x %02x %02x ",
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %3ph ",
"H2C Wifi inform bt chnl Info",
- coex_dm->wifi_chnl_info[0], coex_dm->wifi_chnl_info[1],
- coex_dm->wifi_chnl_info[2]);
+ coex_dm->wifi_chnl_info);
btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi);
btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi);
@@ -2525,15 +2524,9 @@ void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
for (i = 0; i < BT_INFO_SRC_8723B_1ANT_MAX; i++) {
if (coex_sta->bt_info_c2h_cnt[i]) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)",
+ "\r\n %-35s = %7ph(%d)",
GLBtInfoSrc8723b1Ant[i],
- coex_sta->bt_info_c2h[i][0],
- coex_sta->bt_info_c2h[i][1],
- coex_sta->bt_info_c2h[i][2],
- coex_sta->bt_info_c2h[i][3],
- coex_sta->bt_info_c2h[i][4],
- coex_sta->bt_info_c2h[i][5],
- coex_sta->bt_info_c2h[i][6],
+ coex_sta->bt_info_c2h[i],
coex_sta->bt_info_c2h_cnt[i]);
}
}
@@ -2569,10 +2562,8 @@ void ex_halbtc8723b1ant_display_coex_info(struct btc_coexist *btcoexist)
pstdmacase = coex_dm->cur_ps_tdma;
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)",
- "PS TDMA", coex_dm->ps_tdma_para[0],
- coex_dm->ps_tdma_para[1], coex_dm->ps_tdma_para[2],
- coex_dm->ps_tdma_para[3], coex_dm->ps_tdma_para[4],
+ "\r\n %-35s = %5ph case-%d (auto:%d)",
+ "PS TDMA", coex_dm->ps_tdma_para,
pstdmacase, coex_dm->auto_tdma_adjust);
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d ",
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
index f2b9d11adc9e..c43ab59a690a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8723b2ant.c
@@ -3215,9 +3215,8 @@ void ex_btc8723b2ant_display_coex_info(struct btc_coexist *btcoexist)
"Dot11 channel / HsChnl(HsMode)",
wifi_dot11_chnl, wifi_hs_chnl, bt_hs_on);
- RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %02x %02x %02x ",
- "H2C Wifi inform bt chnl Info", coex_dm->wifi_chnl_info[0],
- coex_dm->wifi_chnl_info[1], coex_dm->wifi_chnl_info[2]);
+ RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %3ph ",
+ "H2C Wifi inform bt chnl Info", coex_dm->wifi_chnl_info);
btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi);
btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi);
@@ -3259,16 +3258,9 @@ void ex_btc8723b2ant_display_coex_info(struct btc_coexist *btcoexist)
for (i = 0; i < BT_INFO_SRC_8723B_2ANT_MAX; i++) {
if (coex_sta->bt_info_c2h_cnt[i]) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "\r\n %-35s = %02x %02x %02x "
- "%02x %02x %02x %02x(%d)",
+ "\r\n %-35s = %7ph(%d)",
glbt_info_src_8723b_2ant[i],
- coex_sta->bt_info_c2h[i][0],
- coex_sta->bt_info_c2h[i][1],
- coex_sta->bt_info_c2h[i][2],
- coex_sta->bt_info_c2h[i][3],
- coex_sta->bt_info_c2h[i][4],
- coex_sta->bt_info_c2h[i][5],
- coex_sta->bt_info_c2h[i][6],
+ coex_sta->bt_info_c2h[i],
coex_sta->bt_info_c2h_cnt[i]);
}
}
@@ -3296,10 +3288,8 @@ void ex_btc8723b2ant_display_coex_info(struct btc_coexist *btcoexist)
ps_tdma_case = coex_dm->cur_ps_tdma;
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)",
- "PS TDMA", coex_dm->ps_tdma_para[0],
- coex_dm->ps_tdma_para[1], coex_dm->ps_tdma_para[2],
- coex_dm->ps_tdma_para[3], coex_dm->ps_tdma_para[4],
+ "\r\n %-35s = %5ph case-%d (auto:%d)",
+ "PS TDMA", coex_dm->ps_tdma_para,
ps_tdma_case, coex_dm->auto_tdma_adjust);
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "\r\n %-35s = %d/ %d ",
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
index b72e5377bdbc..9cecf174a37d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a1ant.c
@@ -2302,10 +2302,9 @@ void ex_halbtc8821a1ant_display_coex_info(struct btc_coexist *btcoexist)
wifi_dot11_chnl, wifi_hs_chnl, bt_hs_on);
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "\r\n %-35s = %02x %02x %02x ",
+ "\r\n %-35s = %3ph ",
"H2C Wifi inform bt chnl Info",
- coex_dm->wifi_chnl_info[0], coex_dm->wifi_chnl_info[1],
- coex_dm->wifi_chnl_info[2]);
+ coex_dm->wifi_chnl_info);
btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi);
btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi);
@@ -2366,15 +2365,9 @@ void ex_halbtc8821a1ant_display_coex_info(struct btc_coexist *btcoexist)
for (i = 0; i < BT_INFO_SRC_8821A_1ANT_MAX; i++) {
if (coex_sta->bt_info_c2h_cnt[i]) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)",
+ "\r\n %-35s = %7ph(%d)",
glbt_info_src_8821a_1ant[i],
- coex_sta->bt_info_c2h[i][0],
- coex_sta->bt_info_c2h[i][1],
- coex_sta->bt_info_c2h[i][2],
- coex_sta->bt_info_c2h[i][3],
- coex_sta->bt_info_c2h[i][4],
- coex_sta->bt_info_c2h[i][5],
- coex_sta->bt_info_c2h[i][6],
+ coex_sta->bt_info_c2h[i],
coex_sta->bt_info_c2h_cnt[i]);
}
}
@@ -2412,13 +2405,9 @@ void ex_halbtc8821a1ant_display_coex_info(struct btc_coexist *btcoexist)
ps_tdma_case = coex_dm->cur_ps_tdma;
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "\r\n %-35s = %02x %02x %02x %02x %02x case-%d (auto:%d)",
+ "\r\n %-35s = %5ph case-%d (auto:%d)",
"PS TDMA",
- coex_dm->ps_tdma_para[0],
- coex_dm->ps_tdma_para[1],
- coex_dm->ps_tdma_para[2],
- coex_dm->ps_tdma_para[3],
- coex_dm->ps_tdma_para[4],
+ coex_dm->ps_tdma_para,
ps_tdma_case,
coex_dm->auto_tdma_adjust);
diff --git a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
index cf819f02ed23..044d914291c0 100644
--- a/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
+++ b/drivers/net/wireless/realtek/rtlwifi/btcoexist/halbtc8821a2ant.c
@@ -3393,10 +3393,9 @@ ex_halbtc8821a2ant_display_coex_info(
wifi_dot_11_chnl, bt_hs_on, wifi_hs_chnl);
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "\r\n %-35s = %02x %02x %02x ",
+ "\r\n %-35s = %3ph ",
"H2C Wifi inform bt chnl Info",
- coex_dm->wifi_chnl_info[0], coex_dm->wifi_chnl_info[1],
- coex_dm->wifi_chnl_info[2]);
+ coex_dm->wifi_chnl_info);
btcoexist->btc_get(btcoexist, BTC_GET_S4_WIFI_RSSI, &wifi_rssi);
btcoexist->btc_get(btcoexist, BTC_GET_S4_HS_RSSI, &bt_hs_rssi);
@@ -3454,15 +3453,9 @@ ex_halbtc8821a2ant_display_coex_info(
for (i = 0; i < BT_INFO_SRC_8821A_2ANT_MAX; i++) {
if (coex_sta->bt_info_c2h_cnt[i]) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "\r\n %-35s = %02x %02x %02x %02x %02x %02x %02x(%d)",
+ "\r\n %-35s = %7ph(%d)",
glbt_info_src_8821a_2ant[i],
- coex_sta->bt_info_c2h[i][0],
- coex_sta->bt_info_c2h[i][1],
- coex_sta->bt_info_c2h[i][2],
- coex_sta->bt_info_c2h[i][3],
- coex_sta->bt_info_c2h[i][4],
- coex_sta->bt_info_c2h[i][5],
- coex_sta->bt_info_c2h[i][6],
+ coex_sta->bt_info_c2h[i],
coex_sta->bt_info_c2h_cnt[i]);
}
}
@@ -3494,11 +3487,9 @@ ex_halbtc8821a2ant_display_coex_info(
if (!btcoexist->manual_control) {
ps_tdma_case = coex_dm->cur_ps_tdma;
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
- "\r\n %-35s = %02x %02x %02x %02x %02x case-%d",
+ "\r\n %-35s = %5ph case-%d",
"PS TDMA",
- coex_dm->ps_tdma_para[0], coex_dm->ps_tdma_para[1],
- coex_dm->ps_tdma_para[2], coex_dm->ps_tdma_para[3],
- coex_dm->ps_tdma_para[4], ps_tdma_case);
+ coex_dm->ps_tdma_para, ps_tdma_case);
RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
"\r\n %-35s = %d/ %d ", "DecBtPwr/ IgnWlanAct",
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
index c925a4dff599..4ae421ef30d9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
@@ -1833,8 +1833,7 @@ bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb)
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
pskb = __skb_dequeue(&ring->queue);
- if (pskb)
- kfree_skb(pskb);
+ kfree_skb(pskb);
/*this is wrong, fill_tx_cmddesc needs update*/
pdesc = &ring->desc[0];
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index f46c9d7f6528..7f471bff435c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -801,7 +801,9 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
hw_queue);
if (rx_remained_cnt == 0)
return;
-
+ buffer_desc = &rtlpci->rx_ring[rxring_idx].buffer_desc[
+ rtlpci->rx_ring[rxring_idx].idx];
+ pdesc = (struct rtl_rx_desc *)skb->data;
} else { /* rx descriptor */
pdesc = &rtlpci->rx_ring[rxring_idx].desc[
rtlpci->rx_ring[rxring_idx].idx];
@@ -824,13 +826,6 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
if (unlikely(!new_skb))
goto no_new;
- if (rtlpriv->use_new_trx_flow) {
- buffer_desc =
- &rtlpci->rx_ring[rxring_idx].buffer_desc
- [rtlpci->rx_ring[rxring_idx].idx];
- /*means rx wifi info*/
- pdesc = (struct rtl_rx_desc *)skb->data;
- }
memset(&rx_status , 0 , sizeof(rx_status));
rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
&rx_status, (u8 *)pdesc, skb);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
index 11344121c55e..47e32cb0ec1a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
@@ -88,8 +88,6 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw)
u8 tid;
rtl8188ee_bt_reg_init(hw);
- rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
-
rtlpriv->dm.dm_initialgain_enable = 1;
rtlpriv->dm.dm_flag = 0;
rtlpriv->dm.disable_framebursting = 0;
@@ -138,6 +136,11 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw)
rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+ rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+ rtlpriv->cfg->mod_params->sw_crypto =
+ rtlpriv->cfg->mod_params->sw_crypto;
+ rtlpriv->cfg->mod_params->disable_watchdog =
+ rtlpriv->cfg->mod_params->disable_watchdog;
if (rtlpriv->cfg->mod_params->disable_watchdog)
pr_info("watchdog disabled\n");
if (!rtlpriv->psc.inactiveps)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
index de6cb6c3a48c..4780bdc63b2b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
@@ -139,6 +139,8 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+ rtlpriv->cfg->mod_params->sw_crypto =
+ rtlpriv->cfg->mod_params->sw_crypto;
if (!rtlpriv->psc.inactiveps)
pr_info("rtl8192ce: Power Save off (module option)\n");
if (!rtlpriv->psc.fwctrl_lps)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
index fd4a5353d216..7c6f7f0d18c6 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
@@ -65,6 +65,8 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
rtlpriv->dm.disable_framebursting = false;
rtlpriv->dm.thermalvalue = 0;
rtlpriv->dbg.global_debuglevel = rtlpriv->cfg->mod_params->debug;
+ rtlpriv->cfg->mod_params->sw_crypto =
+ rtlpriv->cfg->mod_params->sw_crypto;
/* for firmware buf */
rtlpriv->rtlhal.pfirmware = vzalloc(0x4000);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
index b19d0398215f..c6e09a19de1a 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
@@ -376,8 +376,8 @@ module_param_named(swlps, rtl92de_mod_params.swctrl_lps, bool, 0444);
module_param_named(fwlps, rtl92de_mod_params.fwctrl_lps, bool, 0444);
MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
-MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
-MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
+MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 1)\n");
+MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 0)\n");
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
index e1fd27c888bf..31baca41ac2f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
@@ -187,6 +187,8 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+ rtlpriv->cfg->mod_params->sw_crypto =
+ rtlpriv->cfg->mod_params->sw_crypto;
if (!rtlpriv->psc.inactiveps)
pr_info("Power Save off (module option)\n");
if (!rtlpriv->psc.fwctrl_lps)
@@ -425,8 +427,8 @@ module_param_named(swlps, rtl92se_mod_params.swctrl_lps, bool, 0444);
module_param_named(fwlps, rtl92se_mod_params.fwctrl_lps, bool, 0444);
MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
-MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
-MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
+MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 1)\n");
+MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 0)\n");
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
index 3859b3e3d158..ff49a8c0ff61 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
@@ -150,6 +150,11 @@ int rtl8723e_init_sw_vars(struct ieee80211_hw *hw)
rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps;
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
+ rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+ rtlpriv->cfg->mod_params->sw_crypto =
+ rtlpriv->cfg->mod_params->sw_crypto;
+ rtlpriv->cfg->mod_params->disable_watchdog =
+ rtlpriv->cfg->mod_params->disable_watchdog;
if (rtlpriv->cfg->mod_params->disable_watchdog)
pr_info("watchdog disabled\n");
rtlpriv->psc.reg_fwctrl_lps = 3;
@@ -267,6 +272,8 @@ static struct rtl_mod_params rtl8723e_mod_params = {
.swctrl_lps = false,
.fwctrl_lps = true,
.debug = DBG_EMERG,
+ .msi_support = false,
+ .disable_watchdog = false,
};
static struct rtl_hal_cfg rtl8723e_hal_cfg = {
@@ -383,12 +390,14 @@ module_param_named(debug, rtl8723e_mod_params.debug, int, 0444);
module_param_named(ips, rtl8723e_mod_params.inactiveps, bool, 0444);
module_param_named(swlps, rtl8723e_mod_params.swctrl_lps, bool, 0444);
module_param_named(fwlps, rtl8723e_mod_params.fwctrl_lps, bool, 0444);
+module_param_named(msi, rtl8723e_mod_params.msi_support, bool, 0444);
module_param_named(disable_watchdog, rtl8723e_mod_params.disable_watchdog,
bool, 0444);
MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
+MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 0)\n");
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
MODULE_PARM_DESC(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n");
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
index d091f1d5f91e..a78eaeda0008 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
@@ -93,7 +93,6 @@ int rtl8723be_init_sw_vars(struct ieee80211_hw *hw)
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
rtl8723be_bt_reg_init(hw);
- rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
rtlpriv->dm.dm_initialgain_enable = 1;
@@ -151,6 +150,10 @@ int rtl8723be_init_sw_vars(struct ieee80211_hw *hw)
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
+ rtlpriv->cfg->mod_params->sw_crypto =
+ rtlpriv->cfg->mod_params->sw_crypto;
+ rtlpriv->cfg->mod_params->disable_watchdog =
+ rtlpriv->cfg->mod_params->disable_watchdog;
if (rtlpriv->cfg->mod_params->disable_watchdog)
pr_info("watchdog disabled\n");
rtlpriv->psc.reg_fwctrl_lps = 3;
@@ -267,6 +270,9 @@ static struct rtl_mod_params rtl8723be_mod_params = {
.inactiveps = true,
.swctrl_lps = false,
.fwctrl_lps = true,
+ .msi_support = false,
+ .disable_watchdog = false,
+ .debug = DBG_EMERG,
};
static struct rtl_hal_cfg rtl8723be_hal_cfg = {
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c
index a2f5e89bedfe..6e518625edbe 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723com/fw_common.c
@@ -318,9 +318,7 @@ bool rtl8723_cmd_send_packet(struct ieee80211_hw *hw,
ring = &rtlpci->tx_ring[BEACON_QUEUE];
pskb = __skb_dequeue(&ring->queue);
- if (pskb)
- kfree_skb(pskb);
-
+ kfree_skb(pskb);
spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
pdesc = &ring->desc[0];
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
index 6e9418ed90c2..bbb789f8990b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c
@@ -2272,7 +2272,7 @@ void rtl8821ae_enable_interrupt(struct ieee80211_hw *hw)
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- if (!rtlpci->int_clear)
+ if (rtlpci->int_clear)
rtl8821ae_clear_interrupt(hw);/*clear it here first*/
rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
index 8ee141a55bc5..4159f9b14db6 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
@@ -95,8 +95,6 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
rtl8821ae_bt_reg_init(hw);
- rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
- rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear;
rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
rtlpriv->dm.dm_initialgain_enable = 1;
@@ -168,12 +166,15 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
- rtlpci->msi_support = rtlpriv->cfg->mod_params->int_clear;
+ rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear;
+ rtlpriv->cfg->mod_params->sw_crypto =
+ rtlpriv->cfg->mod_params->sw_crypto;
+ rtlpriv->cfg->mod_params->disable_watchdog =
+ rtlpriv->cfg->mod_params->disable_watchdog;
if (rtlpriv->cfg->mod_params->disable_watchdog)
pr_info("watchdog disabled\n");
rtlpriv->psc.reg_fwctrl_lps = 3;
rtlpriv->psc.reg_max_lps_awakeintvl = 5;
- rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
/* for ASPM, you can close aspm through
* set const_support_pciaspm = 0
@@ -448,7 +449,7 @@ MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 1)\n");
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
MODULE_PARM_DESC(disable_watchdog, "Set to 1 to disable the watchdog (default 0)\n");
-MODULE_PARM_DESC(int_clear, "Set to 1 to disable interrupt clear before set (default 0)\n");
+MODULE_PARM_DESC(int_clear, "Set to 0 to disable interrupt clear before set (default 1)\n");
static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
index 2721cf89fb16..aac1ed3f7bb4 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -531,6 +531,8 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw,
ieee80211_rx(hw, skb);
else
dev_kfree_skb_any(skb);
+ } else {
+ dev_kfree_skb_any(skb);
}
}
diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
index 8d110fd9eba1..e43b59d5b53b 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c
@@ -1023,7 +1023,7 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
return -ENOMEM;
}
- selected_rates = kmalloc(2 * RSI_TBL_SZ, GFP_KERNEL);
+ selected_rates = kzalloc(2 * RSI_TBL_SZ, GFP_KERNEL);
if (!selected_rates) {
rsi_dbg(ERR_ZONE, "%s: Failed in allocation of mem\n",
__func__);
@@ -1032,7 +1032,6 @@ static int rsi_send_auto_rate_request(struct rsi_common *common)
}
memset(skb->data, 0, sizeof(struct rsi_auto_rate));
- memset(selected_rates, 0, 2 * RSI_TBL_SZ);
auto_rate = (struct rsi_auto_rate *)skb->data;
@@ -1227,7 +1226,7 @@ int rsi_send_block_unblock_frame(struct rsi_common *common, bool block_event)
mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12);
mgmt_frame->desc_word[1] = cpu_to_le16(BLOCK_HW_QUEUE);
- if (block_event == true) {
+ if (block_event) {
rsi_dbg(INFO_ZONE, "blocking the data qs\n");
mgmt_frame->desc_word[4] = cpu_to_le16(0xf);
} else {
diff --git a/drivers/net/wireless/st/cw1200/sta.c b/drivers/net/wireless/st/cw1200/sta.c
index 95a7fdb3cc1c..06321c799c90 100644
--- a/drivers/net/wireless/st/cw1200/sta.c
+++ b/drivers/net/wireless/st/cw1200/sta.c
@@ -873,12 +873,6 @@ int cw1200_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
else
val32 = 0; /* disabled */
- if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) {
- /* device is down, can _not_ set threshold */
- ret = -ENODEV;
- goto out;
- }
-
if (priv->rts_threshold == value)
goto out;
diff --git a/drivers/net/wireless/ti/wl12xx/conf.h b/drivers/net/wireless/ti/wl12xx/conf.h
index 75e29897a0f5..a606ba9ef041 100644
--- a/drivers/net/wireless/ti/wl12xx/conf.h
+++ b/drivers/net/wireless/ti/wl12xx/conf.h
@@ -47,4 +47,237 @@ struct wl12xx_priv_conf {
struct conf_memory_settings mem_wl127x;
};
+enum wl12xx_sg_params {
+ /*
+ * Configure the min and max time BT gains the antenna
+ * in WLAN / BT master basic rate
+ *
+ * Range: 0 - 255 (ms)
+ */
+ WL12XX_CONF_SG_ACL_BT_MASTER_MIN_BR = 0,
+ WL12XX_CONF_SG_ACL_BT_MASTER_MAX_BR,
+
+ /*
+ * Configure the min and max time BT gains the antenna
+ * in WLAN / BT slave basic rate
+ *
+ * Range: 0 - 255 (ms)
+ */
+ WL12XX_CONF_SG_ACL_BT_SLAVE_MIN_BR,
+ WL12XX_CONF_SG_ACL_BT_SLAVE_MAX_BR,
+
+ /*
+ * Configure the min and max time BT gains the antenna
+ * in WLAN / BT master EDR
+ *
+ * Range: 0 - 255 (ms)
+ */
+ WL12XX_CONF_SG_ACL_BT_MASTER_MIN_EDR,
+ WL12XX_CONF_SG_ACL_BT_MASTER_MAX_EDR,
+
+ /*
+ * Configure the min and max time BT gains the antenna
+ * in WLAN / BT slave EDR
+ *
+ * Range: 0 - 255 (ms)
+ */
+ WL12XX_CONF_SG_ACL_BT_SLAVE_MIN_EDR,
+ WL12XX_CONF_SG_ACL_BT_SLAVE_MAX_EDR,
+
+ /*
+ * The maximum time WLAN can gain the antenna
+ * in WLAN PSM / BT master/slave BR
+ *
+ * Range: 0 - 255 (ms)
+ */
+ WL12XX_CONF_SG_ACL_WLAN_PS_MASTER_BR,
+ WL12XX_CONF_SG_ACL_WLAN_PS_SLAVE_BR,
+
+ /*
+ * The maximum time WLAN can gain the antenna
+ * in WLAN PSM / BT master/slave EDR
+ *
+ * Range: 0 - 255 (ms)
+ */
+ WL12XX_CONF_SG_ACL_WLAN_PS_MASTER_EDR,
+ WL12XX_CONF_SG_ACL_WLAN_PS_SLAVE_EDR,
+
+ /* TODO: explain these values */
+ WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR,
+ WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR,
+ WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR,
+ WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR,
+ WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR,
+ WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR,
+ WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR,
+ WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR,
+
+ WL12XX_CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR,
+ WL12XX_CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR,
+ WL12XX_CONF_SG_ACL_PASSIVE_SCAN_BT_BR,
+ WL12XX_CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR,
+ WL12XX_CONF_SG_ACL_PASSIVE_SCAN_BT_EDR,
+ WL12XX_CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR,
+
+ /*
+ * Compensation percentage of probe requests when scan initiated
+ * during BT voice/ACL link.
+ *
+ * Range: 0 - 255 (%)
+ */
+ WL12XX_CONF_SG_AUTO_SCAN_PROBE_REQ,
+
+ /*
+ * Compensation percentage of probe requests when active scan initiated
+ * during BT voice
+ *
+ * Range: 0 - 255 (%)
+ */
+ WL12XX_CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3,
+
+ /*
+ * Compensation percentage of WLAN active scan window if initiated
+ * during BT A2DP
+ *
+ * Range: 0 - 1000 (%)
+ */
+ WL12XX_CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP,
+
+ /*
+ * Compensation percentage of WLAN passive scan window if initiated
+ * during BT A2DP BR
+ *
+ * Range: 0 - 1000 (%)
+ */
+ WL12XX_CONF_SG_PASSIVE_SCAN_DUR_FACTOR_A2DP_BR,
+
+ /*
+ * Compensation percentage of WLAN passive scan window if initiated
+ * during BT A2DP EDR
+ *
+ * Range: 0 - 1000 (%)
+ */
+ WL12XX_CONF_SG_PASSIVE_SCAN_DUR_FACTOR_A2DP_EDR,
+
+ /*
+ * Compensation percentage of WLAN passive scan window if initiated
+ * during BT voice
+ *
+ * Range: 0 - 1000 (%)
+ */
+ WL12XX_CONF_SG_PASSIVE_SCAN_DUR_FACTOR_HV3,
+
+ /* TODO: explain these values */
+ WL12XX_CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN,
+ WL12XX_CONF_SG_BCN_HV3_COLL_THR_IN_PASSIVE_SCAN,
+ WL12XX_CONF_SG_TX_RX_PROTECT_BW_IN_PASSIVE_SCAN,
+
+ /*
+ * Defines whether the SG will force WLAN host to enter/exit PSM
+ *
+ * Range: 1 - SG can force, 0 - host handles PSM
+ */
+ WL12XX_CONF_SG_STA_FORCE_PS_IN_BT_SCO,
+
+ /*
+ * Defines antenna configuration (single/dual antenna)
+ *
+ * Range: 0 - single antenna, 1 - dual antenna
+ */
+ WL12XX_CONF_SG_ANTENNA_CONFIGURATION,
+
+ /*
+ * The threshold (percent) of max consecutive beacon misses before
+ * increasing priority of beacon reception.
+ *
+ * Range: 0 - 100 (%)
+ */
+ WL12XX_CONF_SG_BEACON_MISS_PERCENT,
+
+ /*
+ * Protection time of the DHCP procedure.
+ *
+ * Range: 0 - 100000 (ms)
+ */
+ WL12XX_CONF_SG_DHCP_TIME,
+
+ /*
+ * RX guard time before the beginning of a new BT voice frame during
+ * which no new WLAN trigger frame is transmitted.
+ *
+ * Range: 0 - 100000 (us)
+ */
+ WL12XX_CONF_SG_RXT,
+
+ /*
+ * TX guard time before the beginning of a new BT voice frame during
+ * which no new WLAN frame is transmitted.
+ *
+ * Range: 0 - 100000 (us)
+ */
+ WL12XX_CONF_SG_TXT,
+
+ /*
+ * Enable adaptive RXT/TXT algorithm. If disabled, the host values
+ * will be utilized.
+ *
+ * Range: 0 - disable, 1 - enable
+ */
+ WL12XX_CONF_SG_ADAPTIVE_RXT_TXT,
+
+ /* TODO: explain this value */
+ WL12XX_CONF_SG_GENERAL_USAGE_BIT_MAP,
+
+ /*
+ * Number of consecutive BT voice frames not interrupted by WLAN
+ *
+ * Range: 0 - 100
+ */
+ WL12XX_CONF_SG_HV3_MAX_SERVED,
+
+ /*
+ * The used WLAN legacy service period during active BT ACL link
+ *
+ * Range: 0 - 255 (ms)
+ */
+ WL12XX_CONF_SG_PS_POLL_TIMEOUT,
+
+ /*
+ * The used WLAN UPSD service period during active BT ACL link
+ *
+ * Range: 0 - 255 (ms)
+ */
+ WL12XX_CONF_SG_UPSD_TIMEOUT,
+
+ WL12XX_CONF_SG_CONSECUTIVE_CTS_THRESHOLD,
+ WL12XX_CONF_SG_STA_RX_WINDOW_AFTER_DTIM,
+ WL12XX_CONF_SG_STA_CONNECTION_PROTECTION_TIME,
+
+ /* AP params */
+ WL12XX_CONF_AP_BEACON_MISS_TX,
+ WL12XX_CONF_AP_RX_WINDOW_AFTER_BEACON,
+ WL12XX_CONF_AP_BEACON_WINDOW_INTERVAL,
+ WL12XX_CONF_AP_CONNECTION_PROTECTION_TIME,
+ WL12XX_CONF_AP_BT_ACL_VAL_BT_SERVE_TIME,
+ WL12XX_CONF_AP_BT_ACL_VAL_WL_SERVE_TIME,
+
+ /* CTS Diluting params */
+ WL12XX_CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH,
+ WL12XX_CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER,
+
+ WL12XX_CONF_SG_TEMP_PARAM_1,
+ WL12XX_CONF_SG_TEMP_PARAM_2,
+ WL12XX_CONF_SG_TEMP_PARAM_3,
+ WL12XX_CONF_SG_TEMP_PARAM_4,
+ WL12XX_CONF_SG_TEMP_PARAM_5,
+ WL12XX_CONF_SG_TEMP_PARAM_6,
+ WL12XX_CONF_SG_TEMP_PARAM_7,
+ WL12XX_CONF_SG_TEMP_PARAM_8,
+ WL12XX_CONF_SG_TEMP_PARAM_9,
+ WL12XX_CONF_SG_TEMP_PARAM_10,
+
+ WL12XX_CONF_SG_PARAMS_MAX,
+ WL12XX_CONF_SG_PARAMS_ALL = 0xff
+};
+
#endif /* __WL12XX_CONF_H__ */
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index af0fe2e17151..a0d6cccc56f3 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -39,6 +39,7 @@
#include "scan.h"
#include "event.h"
#include "debugfs.h"
+#include "conf.h"
static char *fref_param;
static char *tcxo_param;
@@ -46,69 +47,69 @@ static char *tcxo_param;
static struct wlcore_conf wl12xx_conf = {
.sg = {
.params = {
- [CONF_SG_ACL_BT_MASTER_MIN_BR] = 10,
- [CONF_SG_ACL_BT_MASTER_MAX_BR] = 180,
- [CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10,
- [CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180,
- [CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10,
- [CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80,
- [CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10,
- [CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80,
- [CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8,
- [CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8,
- [CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20,
- [CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20,
- [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20,
- [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35,
- [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16,
- [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35,
- [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32,
- [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50,
- [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28,
- [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50,
- [CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10,
- [CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20,
- [CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75,
- [CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15,
- [CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27,
- [CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17,
+ [WL12XX_CONF_SG_ACL_BT_MASTER_MIN_BR] = 10,
+ [WL12XX_CONF_SG_ACL_BT_MASTER_MAX_BR] = 180,
+ [WL12XX_CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10,
+ [WL12XX_CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180,
+ [WL12XX_CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10,
+ [WL12XX_CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80,
+ [WL12XX_CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10,
+ [WL12XX_CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80,
+ [WL12XX_CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8,
+ [WL12XX_CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8,
+ [WL12XX_CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20,
+ [WL12XX_CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20,
+ [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20,
+ [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35,
+ [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16,
+ [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35,
+ [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32,
+ [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50,
+ [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28,
+ [WL12XX_CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50,
+ [WL12XX_CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10,
+ [WL12XX_CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20,
+ [WL12XX_CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75,
+ [WL12XX_CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15,
+ [WL12XX_CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27,
+ [WL12XX_CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17,
/* active scan params */
- [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
- [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
- [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
+ [WL12XX_CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
+ [WL12XX_CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
+ [WL12XX_CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
/* passive scan params */
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800,
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200,
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
+ [WL12XX_CONF_SG_PASSIVE_SCAN_DUR_FACTOR_A2DP_BR] = 800,
+ [WL12XX_CONF_SG_PASSIVE_SCAN_DUR_FACTOR_A2DP_EDR] = 200,
+ [WL12XX_CONF_SG_PASSIVE_SCAN_DUR_FACTOR_HV3] = 200,
/* passive scan in dual antenna params */
- [CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0,
- [CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0,
- [CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0,
+ [WL12XX_CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0,
+ [WL12XX_CONF_SG_BCN_HV3_COLL_THR_IN_PASSIVE_SCAN] = 0,
+ [WL12XX_CONF_SG_TX_RX_PROTECT_BW_IN_PASSIVE_SCAN] = 0,
/* general params */
- [CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1,
- [CONF_SG_ANTENNA_CONFIGURATION] = 0,
- [CONF_SG_BEACON_MISS_PERCENT] = 60,
- [CONF_SG_DHCP_TIME] = 5000,
- [CONF_SG_RXT] = 1200,
- [CONF_SG_TXT] = 1000,
- [CONF_SG_ADAPTIVE_RXT_TXT] = 1,
- [CONF_SG_GENERAL_USAGE_BIT_MAP] = 3,
- [CONF_SG_HV3_MAX_SERVED] = 6,
- [CONF_SG_PS_POLL_TIMEOUT] = 10,
- [CONF_SG_UPSD_TIMEOUT] = 10,
- [CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2,
- [CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5,
- [CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30,
+ [WL12XX_CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1,
+ [WL12XX_CONF_SG_ANTENNA_CONFIGURATION] = 0,
+ [WL12XX_CONF_SG_BEACON_MISS_PERCENT] = 60,
+ [WL12XX_CONF_SG_DHCP_TIME] = 5000,
+ [WL12XX_CONF_SG_RXT] = 1200,
+ [WL12XX_CONF_SG_TXT] = 1000,
+ [WL12XX_CONF_SG_ADAPTIVE_RXT_TXT] = 1,
+ [WL12XX_CONF_SG_GENERAL_USAGE_BIT_MAP] = 3,
+ [WL12XX_CONF_SG_HV3_MAX_SERVED] = 6,
+ [WL12XX_CONF_SG_PS_POLL_TIMEOUT] = 10,
+ [WL12XX_CONF_SG_UPSD_TIMEOUT] = 10,
+ [WL12XX_CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2,
+ [WL12XX_CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5,
+ [WL12XX_CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30,
/* AP params */
- [CONF_AP_BEACON_MISS_TX] = 3,
- [CONF_AP_RX_WINDOW_AFTER_BEACON] = 10,
- [CONF_AP_BEACON_WINDOW_INTERVAL] = 2,
- [CONF_AP_CONNECTION_PROTECTION_TIME] = 0,
- [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25,
- [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25,
+ [WL12XX_CONF_AP_BEACON_MISS_TX] = 3,
+ [WL12XX_CONF_AP_RX_WINDOW_AFTER_BEACON] = 10,
+ [WL12XX_CONF_AP_BEACON_WINDOW_INTERVAL] = 2,
+ [WL12XX_CONF_AP_CONNECTION_PROTECTION_TIME] = 0,
+ [WL12XX_CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25,
+ [WL12XX_CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25,
/* CTS Diluting params */
- [CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0,
- [CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0,
+ [WL12XX_CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0,
+ [WL12XX_CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0,
},
.state = CONF_SG_PROTECTIVE,
},
@@ -1809,6 +1810,7 @@ static int wl12xx_setup(struct wl1271 *wl)
BUILD_BUG_ON(WL12XX_MAX_LINKS > WLCORE_MAX_LINKS);
BUILD_BUG_ON(WL12XX_MAX_AP_STATIONS > WL12XX_MAX_LINKS);
+ BUILD_BUG_ON(WL12XX_CONF_SG_PARAMS_MAX > WLCORE_CONF_SG_PARAMS_MAX);
wl->rtable = wl12xx_rtable;
wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS;
diff --git a/drivers/net/wireless/ti/wl18xx/conf.h b/drivers/net/wireless/ti/wl18xx/conf.h
index 71f1ec448ba5..7aa880f14ccb 100644
--- a/drivers/net/wireless/ti/wl18xx/conf.h
+++ b/drivers/net/wireless/ti/wl18xx/conf.h
@@ -139,4 +139,94 @@ struct wl18xx_priv_conf {
struct conf_ap_sleep_settings ap_sleep;
} __packed;
+enum wl18xx_sg_params {
+ WL18XX_CONF_SG_PARAM_0 = 0,
+
+ /* Configuration Parameters */
+ WL18XX_CONF_SG_ANTENNA_CONFIGURATION,
+ WL18XX_CONF_SG_ZIGBEE_COEX,
+ WL18XX_CONF_SG_TIME_SYNC,
+
+ WL18XX_CONF_SG_PARAM_4,
+ WL18XX_CONF_SG_PARAM_5,
+ WL18XX_CONF_SG_PARAM_6,
+ WL18XX_CONF_SG_PARAM_7,
+ WL18XX_CONF_SG_PARAM_8,
+ WL18XX_CONF_SG_PARAM_9,
+ WL18XX_CONF_SG_PARAM_10,
+ WL18XX_CONF_SG_PARAM_11,
+ WL18XX_CONF_SG_PARAM_12,
+ WL18XX_CONF_SG_PARAM_13,
+ WL18XX_CONF_SG_PARAM_14,
+ WL18XX_CONF_SG_PARAM_15,
+ WL18XX_CONF_SG_PARAM_16,
+ WL18XX_CONF_SG_PARAM_17,
+ WL18XX_CONF_SG_PARAM_18,
+ WL18XX_CONF_SG_PARAM_19,
+ WL18XX_CONF_SG_PARAM_20,
+ WL18XX_CONF_SG_PARAM_21,
+ WL18XX_CONF_SG_PARAM_22,
+ WL18XX_CONF_SG_PARAM_23,
+ WL18XX_CONF_SG_PARAM_24,
+ WL18XX_CONF_SG_PARAM_25,
+
+ /* Active Scan Parameters */
+ WL18XX_CONF_SG_AUTO_SCAN_PROBE_REQ,
+ WL18XX_CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3,
+
+ WL18XX_CONF_SG_PARAM_28,
+
+ /* Passive Scan Parameters */
+ WL18XX_CONF_SG_PARAM_29,
+ WL18XX_CONF_SG_PARAM_30,
+ WL18XX_CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3,
+
+ /* Passive Scan in Dual Antenna Parameters */
+ WL18XX_CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN,
+ WL18XX_CONF_SG_BEACON_HV3_COLL_TH_IN_PASSIVE_SCAN,
+ WL18XX_CONF_SG_TX_RX_PROTECT_BW_IN_PASSIVE_SCAN,
+
+ /* General Parameters */
+ WL18XX_CONF_SG_STA_FORCE_PS_IN_BT_SCO,
+ WL18XX_CONF_SG_PARAM_36,
+ WL18XX_CONF_SG_BEACON_MISS_PERCENT,
+ WL18XX_CONF_SG_PARAM_38,
+ WL18XX_CONF_SG_RXT,
+ WL18XX_CONF_SG_UNUSED,
+ WL18XX_CONF_SG_ADAPTIVE_RXT_TXT,
+ WL18XX_CONF_SG_GENERAL_USAGE_BIT_MAP,
+ WL18XX_CONF_SG_HV3_MAX_SERVED,
+ WL18XX_CONF_SG_PARAM_44,
+ WL18XX_CONF_SG_PARAM_45,
+ WL18XX_CONF_SG_CONSECUTIVE_CTS_THRESHOLD,
+ WL18XX_CONF_SG_GEMINI_PARAM_47,
+ WL18XX_CONF_SG_STA_CONNECTION_PROTECTION_TIME,
+
+ /* AP Parameters */
+ WL18XX_CONF_SG_AP_BEACON_MISS_TX,
+ WL18XX_CONF_SG_PARAM_50,
+ WL18XX_CONF_SG_AP_BEACON_WINDOW_INTERVAL,
+ WL18XX_CONF_SG_AP_CONNECTION_PROTECTION_TIME,
+ WL18XX_CONF_SG_PARAM_53,
+ WL18XX_CONF_SG_PARAM_54,
+
+ /* CTS Diluting Parameters */
+ WL18XX_CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH,
+ WL18XX_CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER,
+
+ WL18XX_CONF_SG_TEMP_PARAM_1,
+ WL18XX_CONF_SG_TEMP_PARAM_2,
+ WL18XX_CONF_SG_TEMP_PARAM_3,
+ WL18XX_CONF_SG_TEMP_PARAM_4,
+ WL18XX_CONF_SG_TEMP_PARAM_5,
+ WL18XX_CONF_SG_TEMP_PARAM_6,
+ WL18XX_CONF_SG_TEMP_PARAM_7,
+ WL18XX_CONF_SG_TEMP_PARAM_8,
+ WL18XX_CONF_SG_TEMP_PARAM_9,
+ WL18XX_CONF_SG_TEMP_PARAM_10,
+
+ WL18XX_CONF_SG_PARAMS_MAX,
+ WL18XX_CONF_SG_PARAMS_ALL = 0xff
+};
+
#endif /* __WL18XX_CONF_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/event.c b/drivers/net/wireless/ti/wl18xx/event.c
index 09c7e098f460..719907a0a2c2 100644
--- a/drivers/net/wireless/ti/wl18xx/event.c
+++ b/drivers/net/wireless/ti/wl18xx/event.c
@@ -205,6 +205,8 @@ int wl18xx_process_mailbox_events(struct wl1271 *wl)
mbox->sc_ssid,
mbox->sc_pwd_len,
mbox->sc_pwd);
+ if (vector & FW_LOGGER_INDICATION)
+ wlcore_event_fw_logger(wl);
return 0;
}
diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h
index f3d4f13379cb..070de1274694 100644
--- a/drivers/net/wireless/ti/wl18xx/event.h
+++ b/drivers/net/wireless/ti/wl18xx/event.h
@@ -41,6 +41,7 @@ enum {
SMART_CONFIG_SYNC_EVENT_ID = BIT(22),
SMART_CONFIG_DECODE_EVENT_ID = BIT(23),
TIME_SYNC_EVENT_ID = BIT(24),
+ FW_LOGGER_INDICATION = BIT(25),
};
enum wl18xx_radar_types {
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 50cce42089a5..1bf26cc7374e 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -177,69 +177,80 @@ enum wl18xx_hw_rates {
static struct wlcore_conf wl18xx_conf = {
.sg = {
.params = {
- [CONF_SG_ACL_BT_MASTER_MIN_BR] = 10,
- [CONF_SG_ACL_BT_MASTER_MAX_BR] = 180,
- [CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10,
- [CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180,
- [CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10,
- [CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80,
- [CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10,
- [CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80,
- [CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8,
- [CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8,
- [CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20,
- [CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20,
- [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20,
- [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35,
- [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16,
- [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35,
- [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32,
- [CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50,
- [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28,
- [CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50,
- [CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10,
- [CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20,
- [CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75,
- [CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15,
- [CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27,
- [CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17,
- /* active scan params */
- [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
- [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
- [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
- /* passive scan params */
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800,
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200,
- [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
- /* passive scan in dual antenna params */
- [CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0,
- [CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0,
- [CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0,
- /* general params */
- [CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1,
- [CONF_SG_ANTENNA_CONFIGURATION] = 0,
- [CONF_SG_BEACON_MISS_PERCENT] = 60,
- [CONF_SG_DHCP_TIME] = 5000,
- [CONF_SG_RXT] = 1200,
- [CONF_SG_TXT] = 1000,
- [CONF_SG_ADAPTIVE_RXT_TXT] = 1,
- [CONF_SG_GENERAL_USAGE_BIT_MAP] = 3,
- [CONF_SG_HV3_MAX_SERVED] = 6,
- [CONF_SG_PS_POLL_TIMEOUT] = 10,
- [CONF_SG_UPSD_TIMEOUT] = 10,
- [CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2,
- [CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5,
- [CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30,
- /* AP params */
- [CONF_AP_BEACON_MISS_TX] = 3,
- [CONF_AP_RX_WINDOW_AFTER_BEACON] = 10,
- [CONF_AP_BEACON_WINDOW_INTERVAL] = 2,
- [CONF_AP_CONNECTION_PROTECTION_TIME] = 0,
- [CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25,
- [CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25,
- /* CTS Diluting params */
- [CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0,
- [CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0,
+ [WL18XX_CONF_SG_PARAM_0] = 0,
+ /* Configuartion Parameters */
+ [WL18XX_CONF_SG_ANTENNA_CONFIGURATION] = 0,
+ [WL18XX_CONF_SG_ZIGBEE_COEX] = 0,
+ [WL18XX_CONF_SG_TIME_SYNC] = 0,
+ [WL18XX_CONF_SG_PARAM_4] = 0,
+ [WL18XX_CONF_SG_PARAM_5] = 0,
+ [WL18XX_CONF_SG_PARAM_6] = 0,
+ [WL18XX_CONF_SG_PARAM_7] = 0,
+ [WL18XX_CONF_SG_PARAM_8] = 0,
+ [WL18XX_CONF_SG_PARAM_9] = 0,
+ [WL18XX_CONF_SG_PARAM_10] = 0,
+ [WL18XX_CONF_SG_PARAM_11] = 0,
+ [WL18XX_CONF_SG_PARAM_12] = 0,
+ [WL18XX_CONF_SG_PARAM_13] = 0,
+ [WL18XX_CONF_SG_PARAM_14] = 0,
+ [WL18XX_CONF_SG_PARAM_15] = 0,
+ [WL18XX_CONF_SG_PARAM_16] = 0,
+ [WL18XX_CONF_SG_PARAM_17] = 0,
+ [WL18XX_CONF_SG_PARAM_18] = 0,
+ [WL18XX_CONF_SG_PARAM_19] = 0,
+ [WL18XX_CONF_SG_PARAM_20] = 0,
+ [WL18XX_CONF_SG_PARAM_21] = 0,
+ [WL18XX_CONF_SG_PARAM_22] = 0,
+ [WL18XX_CONF_SG_PARAM_23] = 0,
+ [WL18XX_CONF_SG_PARAM_24] = 0,
+ [WL18XX_CONF_SG_PARAM_25] = 0,
+ /* Active Scan Parameters */
+ [WL18XX_CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
+ [WL18XX_CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
+ [WL18XX_CONF_SG_PARAM_28] = 0,
+ /* Passive Scan Parameters */
+ [WL18XX_CONF_SG_PARAM_29] = 0,
+ [WL18XX_CONF_SG_PARAM_30] = 0,
+ [WL18XX_CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
+ /* Passive Scan in Dual Antenna Parameters */
+ [WL18XX_CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0,
+ [WL18XX_CONF_SG_BEACON_HV3_COLL_TH_IN_PASSIVE_SCAN] = 0,
+ [WL18XX_CONF_SG_TX_RX_PROTECT_BW_IN_PASSIVE_SCAN] = 0,
+ /* General Parameters */
+ [WL18XX_CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1,
+ [WL18XX_CONF_SG_PARAM_36] = 0,
+ [WL18XX_CONF_SG_BEACON_MISS_PERCENT] = 60,
+ [WL18XX_CONF_SG_PARAM_38] = 0,
+ [WL18XX_CONF_SG_RXT] = 1200,
+ [WL18XX_CONF_SG_UNUSED] = 0,
+ [WL18XX_CONF_SG_ADAPTIVE_RXT_TXT] = 1,
+ [WL18XX_CONF_SG_GENERAL_USAGE_BIT_MAP] = 3,
+ [WL18XX_CONF_SG_HV3_MAX_SERVED] = 6,
+ [WL18XX_CONF_SG_PARAM_44] = 0,
+ [WL18XX_CONF_SG_PARAM_45] = 0,
+ [WL18XX_CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2,
+ [WL18XX_CONF_SG_GEMINI_PARAM_47] = 0,
+ [WL18XX_CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 0,
+ /* AP Parameters */
+ [WL18XX_CONF_SG_AP_BEACON_MISS_TX] = 3,
+ [WL18XX_CONF_SG_PARAM_50] = 0,
+ [WL18XX_CONF_SG_AP_BEACON_WINDOW_INTERVAL] = 2,
+ [WL18XX_CONF_SG_AP_CONNECTION_PROTECTION_TIME] = 30,
+ [WL18XX_CONF_SG_PARAM_53] = 0,
+ [WL18XX_CONF_SG_PARAM_54] = 0,
+ /* CTS Diluting Parameters */
+ [WL18XX_CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH] = 0,
+ [WL18XX_CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER] = 0,
+ [WL18XX_CONF_SG_TEMP_PARAM_1] = 0,
+ [WL18XX_CONF_SG_TEMP_PARAM_2] = 0,
+ [WL18XX_CONF_SG_TEMP_PARAM_3] = 0,
+ [WL18XX_CONF_SG_TEMP_PARAM_4] = 0,
+ [WL18XX_CONF_SG_TEMP_PARAM_5] = 0,
+ [WL18XX_CONF_SG_TEMP_PARAM_6] = 0,
+ [WL18XX_CONF_SG_TEMP_PARAM_7] = 0,
+ [WL18XX_CONF_SG_TEMP_PARAM_8] = 0,
+ [WL18XX_CONF_SG_TEMP_PARAM_9] = 0,
+ [WL18XX_CONF_SG_TEMP_PARAM_10] = 0,
},
.state = CONF_SG_PROTECTIVE,
},
@@ -461,7 +472,7 @@ static struct wlcore_conf wl18xx_conf = {
},
.fwlog = {
.mode = WL12XX_FWLOG_CONTINUOUS,
- .mem_blocks = 2,
+ .mem_blocks = 0,
.severity = 0,
.timestamp = WL12XX_FWLOG_TIMESTAMP_DISABLED,
.output = WL12XX_FWLOG_OUTPUT_DBG_PINS,
@@ -584,7 +595,7 @@ static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = {
.mem = { .start = 0x00A00000, .size = 0x00012000 },
.reg = { .start = 0x00807000, .size = 0x00005000 },
.mem2 = { .start = 0x00800000, .size = 0x0000B000 },
- .mem3 = { .start = 0x00000000, .size = 0x00000000 },
+ .mem3 = { .start = 0x00401594, .size = 0x00001020 },
},
[PART_DOWN] = {
.mem = { .start = 0x00000000, .size = 0x00014000 },
@@ -602,7 +613,7 @@ static const struct wlcore_partition_set wl18xx_ptable[PART_TABLE_LEN] = {
.mem = { .start = 0x00800000, .size = 0x000050FC },
.reg = { .start = 0x00B00404, .size = 0x00001000 },
.mem2 = { .start = 0x00C00000, .size = 0x00000400 },
- .mem3 = { .start = 0x00000000, .size = 0x00000000 },
+ .mem3 = { .start = 0x00401594, .size = 0x00001020 },
},
[PART_PHY_INIT] = {
.mem = { .start = WL18XX_PHY_INIT_MEM_ADDR,
@@ -1029,7 +1040,8 @@ static int wl18xx_boot(struct wl1271 *wl)
DFS_CHANNELS_CONFIG_COMPLETE_EVENT |
SMART_CONFIG_SYNC_EVENT_ID |
SMART_CONFIG_DECODE_EVENT_ID |
- TIME_SYNC_EVENT_ID;
+ TIME_SYNC_EVENT_ID |
+ FW_LOGGER_INDICATION;
wl->ap_event_mask = MAX_TX_FAILURE_EVENT_ID;
@@ -1895,6 +1907,7 @@ static int wl18xx_setup(struct wl1271 *wl)
BUILD_BUG_ON(WL18XX_MAX_LINKS > WLCORE_MAX_LINKS);
BUILD_BUG_ON(WL18XX_MAX_AP_STATIONS > WL18XX_MAX_LINKS);
+ BUILD_BUG_ON(WL18XX_CONF_SG_PARAMS_MAX > WLCORE_CONF_SG_PARAMS_MAX);
wl->rtable = wl18xx_rtable;
wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS;
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c
index f28fa3b5029d..26cc23f32241 100644
--- a/drivers/net/wireless/ti/wlcore/acx.c
+++ b/drivers/net/wireless/ti/wlcore/acx.c
@@ -534,9 +534,9 @@ int wl12xx_acx_sg_cfg(struct wl1271 *wl)
}
/* BT-WLAN coext parameters */
- for (i = 0; i < CONF_SG_PARAMS_MAX; i++)
+ for (i = 0; i < WLCORE_CONF_SG_PARAMS_MAX; i++)
param->params[i] = cpu_to_le32(c->params[i]);
- param->param_idx = CONF_SG_PARAMS_ALL;
+ param->param_idx = WLCORE_CONF_SG_PARAMS_ALL;
ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
if (ret < 0) {
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h
index 954d57ec98f4..0d61fae88dcb 100644
--- a/drivers/net/wireless/ti/wlcore/acx.h
+++ b/drivers/net/wireless/ti/wlcore/acx.h
@@ -300,7 +300,7 @@ struct acx_bt_wlan_coex {
struct acx_bt_wlan_coex_param {
struct acx_header header;
- __le32 params[CONF_SG_PARAMS_MAX];
+ __le32 params[WLCORE_CONF_SG_PARAMS_MAX];
u8 param_idx;
u8 padding[3];
} __packed;
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h
index 8dc46c0a489a..e28e2f2303ce 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.h
+++ b/drivers/net/wireless/ti/wlcore/cmd.h
@@ -626,7 +626,6 @@ struct wl12xx_cmd_remove_peer {
*/
enum wl12xx_fwlogger_log_mode {
WL12XX_FWLOG_CONTINUOUS,
- WL12XX_FWLOG_ON_DEMAND
};
/* Include/exclude timestamps from the log messages */
diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h
index 52a9d1b14020..44d898fe0afc 100644
--- a/drivers/net/wireless/ti/wlcore/conf.h
+++ b/drivers/net/wireless/ti/wlcore/conf.h
@@ -110,242 +110,11 @@ enum {
CONF_SG_OPPORTUNISTIC
};
-enum {
- /*
- * Configure the min and max time BT gains the antenna
- * in WLAN / BT master basic rate
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_ACL_BT_MASTER_MIN_BR = 0,
- CONF_SG_ACL_BT_MASTER_MAX_BR,
-
- /*
- * Configure the min and max time BT gains the antenna
- * in WLAN / BT slave basic rate
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_ACL_BT_SLAVE_MIN_BR,
- CONF_SG_ACL_BT_SLAVE_MAX_BR,
-
- /*
- * Configure the min and max time BT gains the antenna
- * in WLAN / BT master EDR
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_ACL_BT_MASTER_MIN_EDR,
- CONF_SG_ACL_BT_MASTER_MAX_EDR,
-
- /*
- * Configure the min and max time BT gains the antenna
- * in WLAN / BT slave EDR
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_ACL_BT_SLAVE_MIN_EDR,
- CONF_SG_ACL_BT_SLAVE_MAX_EDR,
-
- /*
- * The maximum time WLAN can gain the antenna
- * in WLAN PSM / BT master/slave BR
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_ACL_WLAN_PS_MASTER_BR,
- CONF_SG_ACL_WLAN_PS_SLAVE_BR,
-
- /*
- * The maximum time WLAN can gain the antenna
- * in WLAN PSM / BT master/slave EDR
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_ACL_WLAN_PS_MASTER_EDR,
- CONF_SG_ACL_WLAN_PS_SLAVE_EDR,
-
- /* TODO: explain these values */
- CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR,
- CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR,
- CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR,
- CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR,
- CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR,
- CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR,
- CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR,
- CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR,
-
- CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR,
- CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR,
- CONF_SG_ACL_PASSIVE_SCAN_BT_BR,
- CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR,
- CONF_SG_ACL_PASSIVE_SCAN_BT_EDR,
- CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR,
-
- /*
- * Compensation percentage of probe requests when scan initiated
- * during BT voice/ACL link.
- *
- * Range: 0 - 255 (%)
- */
- CONF_SG_AUTO_SCAN_PROBE_REQ,
-
- /*
- * Compensation percentage of probe requests when active scan initiated
- * during BT voice
- *
- * Range: 0 - 255 (%)
- */
- CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3,
-
- /*
- * Compensation percentage of WLAN active scan window if initiated
- * during BT A2DP
- *
- * Range: 0 - 1000 (%)
- */
- CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP,
-
- /*
- * Compensation percentage of WLAN passive scan window if initiated
- * during BT A2DP BR
- *
- * Range: 0 - 1000 (%)
- */
- CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR,
-
- /*
- * Compensation percentage of WLAN passive scan window if initiated
- * during BT A2DP EDR
- *
- * Range: 0 - 1000 (%)
- */
- CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR,
-
- /*
- * Compensation percentage of WLAN passive scan window if initiated
- * during BT voice
- *
- * Range: 0 - 1000 (%)
- */
- CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3,
-
- /* TODO: explain these values */
- CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN,
- CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN,
- CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN,
-
- /*
- * Defines whether the SG will force WLAN host to enter/exit PSM
- *
- * Range: 1 - SG can force, 0 - host handles PSM
- */
- CONF_SG_STA_FORCE_PS_IN_BT_SCO,
-
- /*
- * Defines antenna configuration (single/dual antenna)
- *
- * Range: 0 - single antenna, 1 - dual antenna
- */
- CONF_SG_ANTENNA_CONFIGURATION,
-
- /*
- * The threshold (percent) of max consecutive beacon misses before
- * increasing priority of beacon reception.
- *
- * Range: 0 - 100 (%)
- */
- CONF_SG_BEACON_MISS_PERCENT,
-
- /*
- * Protection time of the DHCP procedure.
- *
- * Range: 0 - 100000 (ms)
- */
- CONF_SG_DHCP_TIME,
-
- /*
- * RX guard time before the beginning of a new BT voice frame during
- * which no new WLAN trigger frame is transmitted.
- *
- * Range: 0 - 100000 (us)
- */
- CONF_SG_RXT,
-
- /*
- * TX guard time before the beginning of a new BT voice frame during
- * which no new WLAN frame is transmitted.
- *
- * Range: 0 - 100000 (us)
- */
-
- CONF_SG_TXT,
-
- /*
- * Enable adaptive RXT/TXT algorithm. If disabled, the host values
- * will be utilized.
- *
- * Range: 0 - disable, 1 - enable
- */
- CONF_SG_ADAPTIVE_RXT_TXT,
-
- /* TODO: explain this value */
- CONF_SG_GENERAL_USAGE_BIT_MAP,
-
- /*
- * Number of consecutive BT voice frames not interrupted by WLAN
- *
- * Range: 0 - 100
- */
- CONF_SG_HV3_MAX_SERVED,
-
- /*
- * The used WLAN legacy service period during active BT ACL link
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_PS_POLL_TIMEOUT,
-
- /*
- * The used WLAN UPSD service period during active BT ACL link
- *
- * Range: 0 - 255 (ms)
- */
- CONF_SG_UPSD_TIMEOUT,
-
- CONF_SG_CONSECUTIVE_CTS_THRESHOLD,
- CONF_SG_STA_RX_WINDOW_AFTER_DTIM,
- CONF_SG_STA_CONNECTION_PROTECTION_TIME,
-
- /* AP params */
- CONF_AP_BEACON_MISS_TX,
- CONF_AP_RX_WINDOW_AFTER_BEACON,
- CONF_AP_BEACON_WINDOW_INTERVAL,
- CONF_AP_CONNECTION_PROTECTION_TIME,
- CONF_AP_BT_ACL_VAL_BT_SERVE_TIME,
- CONF_AP_BT_ACL_VAL_WL_SERVE_TIME,
-
- /* CTS Diluting params */
- CONF_SG_CTS_DILUTED_BAD_RX_PACKETS_TH,
- CONF_SG_CTS_CHOP_IN_DUAL_ANT_SCO_MASTER,
-
- CONF_SG_TEMP_PARAM_1,
- CONF_SG_TEMP_PARAM_2,
- CONF_SG_TEMP_PARAM_3,
- CONF_SG_TEMP_PARAM_4,
- CONF_SG_TEMP_PARAM_5,
- CONF_SG_TEMP_PARAM_6,
- CONF_SG_TEMP_PARAM_7,
- CONF_SG_TEMP_PARAM_8,
- CONF_SG_TEMP_PARAM_9,
- CONF_SG_TEMP_PARAM_10,
-
- CONF_SG_PARAMS_MAX,
- CONF_SG_PARAMS_ALL = 0xff
-};
+#define WLCORE_CONF_SG_PARAMS_MAX 67
+#define WLCORE_CONF_SG_PARAMS_ALL 0xff
struct conf_sg_settings {
- u32 params[CONF_SG_PARAMS_MAX];
+ u32 params[WLCORE_CONF_SG_PARAMS_MAX];
u8 state;
} __packed;
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c
index eb43f94a1597..8367f9edfb11 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -1234,6 +1234,65 @@ static const struct file_operations dev_mem_ops = {
.llseek = dev_mem_seek,
};
+static ssize_t fw_logger_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+
+ return wl1271_format_buffer(user_buf, count,
+ ppos, "%d\n",
+ wl->conf.fwlog.output);
+}
+
+static ssize_t fw_logger_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wl1271 *wl = file->private_data;
+ unsigned long value;
+ int ret;
+
+ ret = kstrtoul_from_user(user_buf, count, 0, &value);
+ if (ret < 0) {
+ wl1271_warning("illegal value in fw_logger");
+ return -EINVAL;
+ }
+
+ if ((value > 2) || (value == 0)) {
+ wl1271_warning("fw_logger value must be 1-UART 2-SDIO");
+ return -ERANGE;
+ }
+
+ if (wl->conf.fwlog.output == 0) {
+ wl1271_warning("iligal opperation - fw logger disabled by default, please change mode via wlconf");
+ return -EINVAL;
+ }
+
+ mutex_lock(&wl->mutex);
+ ret = wl1271_ps_elp_wakeup(wl);
+ if (ret < 0) {
+ count = ret;
+ goto out;
+ }
+
+ wl->conf.fwlog.output = value;
+
+ ret = wl12xx_cmd_config_fwlog(wl);
+
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+ return count;
+}
+
+static const struct file_operations fw_logger_ops = {
+ .open = simple_open,
+ .read = fw_logger_read,
+ .write = fw_logger_write,
+ .llseek = default_llseek,
+};
+
static int wl1271_debugfs_add_files(struct wl1271 *wl,
struct dentry *rootdir)
{
@@ -1260,6 +1319,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl,
DEBUGFS_ADD(irq_timeout, rootdir);
DEBUGFS_ADD(fw_stats_raw, rootdir);
DEBUGFS_ADD(sleep_auth, rootdir);
+ DEBUGFS_ADD(fw_logger, rootdir);
streaming = debugfs_create_dir("rx_streaming", rootdir);
if (!streaming || IS_ERR(streaming))
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c
index c42e78955e7b..c96405498bf4 100644
--- a/drivers/net/wireless/ti/wlcore/event.c
+++ b/drivers/net/wireless/ti/wlcore/event.c
@@ -28,6 +28,88 @@
#include "ps.h"
#include "scan.h"
#include "wl12xx_80211.h"
+#include "hw_ops.h"
+
+#define WL18XX_LOGGER_SDIO_BUFF_MAX (0x1020)
+#define WL18XX_DATA_RAM_BASE_ADDRESS (0x20000000)
+#define WL18XX_LOGGER_SDIO_BUFF_ADDR (0x40159c)
+#define WL18XX_LOGGER_BUFF_OFFSET (sizeof(struct fw_logger_information))
+#define WL18XX_LOGGER_READ_POINT_OFFSET (12)
+
+int wlcore_event_fw_logger(struct wl1271 *wl)
+{
+ u32 ret;
+ struct fw_logger_information fw_log;
+ u8 *buffer;
+ u32 internal_fw_addrbase = WL18XX_DATA_RAM_BASE_ADDRESS;
+ u32 addr = WL18XX_LOGGER_SDIO_BUFF_ADDR;
+ u32 end_buff_addr = WL18XX_LOGGER_SDIO_BUFF_ADDR +
+ WL18XX_LOGGER_BUFF_OFFSET;
+ u32 available_len;
+ u32 actual_len;
+ u32 clear_addr;
+ size_t len;
+ u32 start_loc;
+
+ buffer = kzalloc(WL18XX_LOGGER_SDIO_BUFF_MAX, GFP_KERNEL);
+ if (!buffer) {
+ wl1271_error("Fail to allocate fw logger memory");
+ fw_log.actual_buff_size = cpu_to_le32(0);
+ goto out;
+ }
+
+ ret = wlcore_read(wl, addr, buffer, WL18XX_LOGGER_SDIO_BUFF_MAX,
+ false);
+ if (ret < 0) {
+ wl1271_error("Fail to read logger buffer, error_id = %d",
+ ret);
+ fw_log.actual_buff_size = cpu_to_le32(0);
+ goto free_out;
+ }
+
+ memcpy(&fw_log, buffer, sizeof(fw_log));
+
+ if (le32_to_cpu(fw_log.actual_buff_size) == 0)
+ goto free_out;
+
+ actual_len = le32_to_cpu(fw_log.actual_buff_size);
+ start_loc = (le32_to_cpu(fw_log.buff_read_ptr) -
+ internal_fw_addrbase) - addr;
+ end_buff_addr += le32_to_cpu(fw_log.max_buff_size);
+ available_len = end_buff_addr -
+ (le32_to_cpu(fw_log.buff_read_ptr) -
+ internal_fw_addrbase);
+ actual_len = min(actual_len, available_len);
+ len = actual_len;
+
+ wl12xx_copy_fwlog(wl, &buffer[start_loc], len);
+ clear_addr = addr + start_loc + le32_to_cpu(fw_log.actual_buff_size) +
+ internal_fw_addrbase;
+
+ len = le32_to_cpu(fw_log.actual_buff_size) - len;
+ if (len) {
+ wl12xx_copy_fwlog(wl,
+ &buffer[WL18XX_LOGGER_BUFF_OFFSET],
+ len);
+ clear_addr = addr + WL18XX_LOGGER_BUFF_OFFSET + len +
+ internal_fw_addrbase;
+ }
+
+ /* double check that clear address and write pointer are the same */
+ if (clear_addr != le32_to_cpu(fw_log.buff_write_ptr)) {
+ wl1271_error("Calculate of clear addr Clear = %x, write = %x",
+ clear_addr, le32_to_cpu(fw_log.buff_write_ptr));
+ }
+
+ /* indicate FW about Clear buffer */
+ ret = wlcore_write32(wl, addr + WL18XX_LOGGER_READ_POINT_OFFSET,
+ fw_log.buff_write_ptr);
+free_out:
+ kfree(buffer);
+out:
+ return le32_to_cpu(fw_log.actual_buff_size);
+}
+EXPORT_SYMBOL_GPL(wlcore_event_fw_logger);
void wlcore_event_rssi_trigger(struct wl1271 *wl, s8 *metric_arr)
{
diff --git a/drivers/net/wireless/ti/wlcore/event.h b/drivers/net/wireless/ti/wlcore/event.h
index acc7a59d3828..75e8e98da2fe 100644
--- a/drivers/net/wireless/ti/wlcore/event.h
+++ b/drivers/net/wireless/ti/wlcore/event.h
@@ -64,6 +64,14 @@ enum {
#define NUM_OF_RSSI_SNR_TRIGGERS 8
+struct fw_logger_information {
+ __le32 max_buff_size;
+ __le32 actual_buff_size;
+ __le32 num_trace_drop;
+ __le32 buff_read_ptr;
+ __le32 buff_write_ptr;
+} __packed;
+
struct wl1271;
int wl1271_event_unmask(struct wl1271 *wl);
@@ -84,4 +92,5 @@ void wlcore_event_max_tx_failure(struct wl1271 *wl, unsigned long sta_bitmap);
void wlcore_event_inactive_sta(struct wl1271 *wl, unsigned long sta_bitmap);
void wlcore_event_roc_complete(struct wl1271 *wl);
void wlcore_event_rssi_trigger(struct wl1271 *wl, s8 *metric_arr);
+int wlcore_event_fw_logger(struct wl1271 *wl);
#endif
diff --git a/drivers/net/wireless/ti/wlcore/io.c b/drivers/net/wireless/ti/wlcore/io.c
index 68e74eefd296..9ac118e727e9 100644
--- a/drivers/net/wireless/ti/wlcore/io.c
+++ b/drivers/net/wireless/ti/wlcore/io.c
@@ -175,12 +175,13 @@ int wlcore_set_partition(struct wl1271 *wl,
if (ret < 0)
goto out;
- /*
- * We don't need the size of the last partition, as it is
- * automatically calculated based on the total memory size and
- * the sizes of the previous partitions.
- */
ret = wlcore_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start);
+ if (ret < 0)
+ goto out;
+
+ ret = wlcore_raw_write32(wl, HW_PART3_SIZE_ADDR, p->mem3.size);
+ if (ret < 0)
+ goto out;
out:
return ret;
diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h
index 0305729d0986..6c257b54f415 100644
--- a/drivers/net/wireless/ti/wlcore/io.h
+++ b/drivers/net/wireless/ti/wlcore/io.h
@@ -36,8 +36,8 @@
#define HW_PART1_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 12)
#define HW_PART2_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 16)
#define HW_PART2_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 20)
-#define HW_PART3_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 24)
-
+#define HW_PART3_SIZE_ADDR (HW_PARTITION_REGISTERS_ADDR + 24)
+#define HW_PART3_START_ADDR (HW_PARTITION_REGISTERS_ADDR + 28)
#define HW_ACCESS_REGISTER_SIZE 4
#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000
@@ -207,19 +207,23 @@ static inline int __must_check wlcore_write_reg(struct wl1271 *wl, int reg,
static inline void wl1271_power_off(struct wl1271 *wl)
{
- int ret;
+ int ret = 0;
if (!test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags))
return;
- ret = wl->if_ops->power(wl->dev, false);
+ if (wl->if_ops->power)
+ ret = wl->if_ops->power(wl->dev, false);
if (!ret)
clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
}
static inline int wl1271_power_on(struct wl1271 *wl)
{
- int ret = wl->if_ops->power(wl->dev, true);
+ int ret = 0;
+
+ if (wl->if_ops->power)
+ ret = wl->if_ops->power(wl->dev, true);
if (ret == 0)
set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index ec7f6af3fab2..d1109c4f0f0d 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -1,4 +1,3 @@
-
/*
* This file is part of wlcore
*
@@ -303,25 +302,11 @@ out:
static void wlcore_adjust_conf(struct wl1271 *wl)
{
- /* Adjust settings according to optional module parameters */
-
- /* Firmware Logger params */
- if (fwlog_mem_blocks != -1) {
- if (fwlog_mem_blocks >= CONF_FWLOG_MIN_MEM_BLOCKS &&
- fwlog_mem_blocks <= CONF_FWLOG_MAX_MEM_BLOCKS) {
- wl->conf.fwlog.mem_blocks = fwlog_mem_blocks;
- } else {
- wl1271_error(
- "Illegal fwlog_mem_blocks=%d using default %d",
- fwlog_mem_blocks, wl->conf.fwlog.mem_blocks);
- }
- }
if (fwlog_param) {
if (!strcmp(fwlog_param, "continuous")) {
wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS;
- } else if (!strcmp(fwlog_param, "ondemand")) {
- wl->conf.fwlog.mode = WL12XX_FWLOG_ON_DEMAND;
+ wl->conf.fwlog.output = WL12XX_FWLOG_OUTPUT_HOST;
} else if (!strcmp(fwlog_param, "dbgpins")) {
wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS;
wl->conf.fwlog.output = WL12XX_FWLOG_OUTPUT_DBG_PINS;
@@ -825,91 +810,32 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen)
static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
{
- struct wlcore_partition_set part, old_part;
- u32 addr;
- u32 offset;
- u32 end_of_log;
- u8 *block;
- int ret;
+ u32 end_of_log = 0;
- if ((wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED) ||
- (wl->conf.fwlog.mem_blocks == 0))
+ if (wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED)
return;
wl1271_info("Reading FW panic log");
- block = kmalloc(wl->fw_mem_block_size, GFP_KERNEL);
- if (!block)
- return;
-
/*
* Make sure the chip is awake and the logger isn't active.
* Do not send a stop fwlog command if the fw is hanged or if
* dbgpins are used (due to some fw bug).
*/
if (wl1271_ps_elp_wakeup(wl))
- goto out;
+ return;
if (!wl->watchdog_recovery &&
wl->conf.fwlog.output != WL12XX_FWLOG_OUTPUT_DBG_PINS)
wl12xx_cmd_stop_fwlog(wl);
- /* Read the first memory block address */
- ret = wlcore_fw_status(wl, wl->fw_status);
- if (ret < 0)
- goto out;
-
- addr = wl->fw_status->log_start_addr;
- if (!addr)
- goto out;
-
- if (wl->conf.fwlog.mode == WL12XX_FWLOG_CONTINUOUS) {
- offset = sizeof(addr) + sizeof(struct wl1271_rx_descriptor);
- end_of_log = wl->fwlog_end;
- } else {
- offset = sizeof(addr);
- end_of_log = addr;
- }
-
- old_part = wl->curr_part;
- memset(&part, 0, sizeof(part));
-
/* Traverse the memory blocks linked list */
do {
- part.mem.start = wlcore_hw_convert_hwaddr(wl, addr);
- part.mem.size = PAGE_SIZE;
-
- ret = wlcore_set_partition(wl, &part);
- if (ret < 0) {
- wl1271_error("%s: set_partition start=0x%X size=%d",
- __func__, part.mem.start, part.mem.size);
- goto out;
+ end_of_log = wlcore_event_fw_logger(wl);
+ if (end_of_log == 0) {
+ msleep(100);
+ end_of_log = wlcore_event_fw_logger(wl);
}
-
- memset(block, 0, wl->fw_mem_block_size);
- ret = wlcore_read_hwaddr(wl, addr, block,
- wl->fw_mem_block_size, false);
-
- if (ret < 0)
- goto out;
-
- /*
- * Memory blocks are linked to one another. The first 4 bytes
- * of each memory block hold the hardware address of the next
- * one. The last memory block points to the first one in
- * on demand mode and is equal to 0x2000000 in continuous mode.
- */
- addr = le32_to_cpup((__le32 *)block);
-
- if (!wl12xx_copy_fwlog(wl, block + offset,
- wl->fw_mem_block_size - offset))
- break;
- } while (addr && (addr != end_of_log));
-
- wake_up_interruptible(&wl->fwlog_waitq);
-
-out:
- kfree(block);
- wlcore_set_partition(wl, &old_part);
+ } while (end_of_log != 0);
}
static void wlcore_save_freed_pkts(struct wl1271 *wl, struct wl12xx_vif *wlvif,
@@ -6291,7 +6217,6 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size,
wl->active_sta_count = 0;
wl->active_link_count = 0;
wl->fwlog_size = 0;
- init_waitqueue_head(&wl->fwlog_waitq);
/* The system link is always allocated */
__set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
@@ -6377,7 +6302,6 @@ int wlcore_free_hw(struct wl1271 *wl)
/* Unblock any fwlog readers */
mutex_lock(&wl->mutex);
wl->fwlog_size = -1;
- wake_up_interruptible_all(&wl->fwlog_waitq);
mutex_unlock(&wl->mutex);
wlcore_sysfs_free(wl);
@@ -6584,7 +6508,7 @@ MODULE_PARM_DESC(debug_level, "wl12xx debugging level");
module_param_named(fwlog, fwlog_param, charp, 0);
MODULE_PARM_DESC(fwlog,
- "FW logger options: continuous, ondemand, dbgpins or disable");
+ "FW logger options: continuous, dbgpins or disable");
module_param(fwlog_mem_blocks, int, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC(fwlog_mem_blocks, "fwlog mem_blocks");
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c
index 5b2927391d1c..34e7e938ede4 100644
--- a/drivers/net/wireless/ti/wlcore/rx.c
+++ b/drivers/net/wireless/ti/wlcore/rx.c
@@ -149,7 +149,6 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
if (desc->packet_class == WL12XX_RX_CLASS_LOGGER) {
size_t len = length - sizeof(*desc);
wl12xx_copy_fwlog(wl, data + sizeof(*desc), len);
- wake_up_interruptible(&wl->fwlog_waitq);
return 0;
}
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c
index 236b41090827..44f059f7f34e 100644
--- a/drivers/net/wireless/ti/wlcore/spi.c
+++ b/drivers/net/wireless/ti/wlcore/spi.c
@@ -73,7 +73,10 @@
*/
#define SPI_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
-#define WSPI_MAX_NUM_OF_CHUNKS (SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
+/* Maximum number of SPI write chunks */
+#define WSPI_MAX_NUM_OF_CHUNKS \
+ ((SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) + 1)
+
struct wl12xx_spi_glue {
struct device *dev;
@@ -268,9 +271,10 @@ static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
void *buf, size_t len, bool fixed)
{
struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
- struct spi_transfer t[2 * (WSPI_MAX_NUM_OF_CHUNKS + 1)];
+ /* SPI write buffers - 2 for each chunk */
+ struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS];
struct spi_message m;
- u32 commands[WSPI_MAX_NUM_OF_CHUNKS];
+ u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; /* 1 command per chunk */
u32 *cmd;
u32 chunk_len;
int i;
diff --git a/drivers/net/wireless/ti/wlcore/sysfs.c b/drivers/net/wireless/ti/wlcore/sysfs.c
index 24dd288d6809..a9218e5b0efc 100644
--- a/drivers/net/wireless/ti/wlcore/sysfs.c
+++ b/drivers/net/wireless/ti/wlcore/sysfs.c
@@ -119,32 +119,6 @@ static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj,
if (ret < 0)
return -ERESTARTSYS;
- /* Let only one thread read the log at a time, blocking others */
- while (wl->fwlog_size == 0) {
- DEFINE_WAIT(wait);
-
- prepare_to_wait_exclusive(&wl->fwlog_waitq,
- &wait,
- TASK_INTERRUPTIBLE);
-
- if (wl->fwlog_size != 0) {
- finish_wait(&wl->fwlog_waitq, &wait);
- break;
- }
-
- mutex_unlock(&wl->mutex);
-
- schedule();
- finish_wait(&wl->fwlog_waitq, &wait);
-
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- ret = mutex_lock_interruptible(&wl->mutex);
- if (ret < 0)
- return -ERESTARTSYS;
- }
-
/* Check if the fwlog is still valid */
if (wl->fwlog_size < 0) {
mutex_unlock(&wl->mutex);
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 906be6aa4eb6..dda01b118c26 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -310,9 +310,6 @@ struct wl1271 {
/* FW memory block size */
u32 fw_mem_block_size;
- /* Sysfs FW log entry readers wait queue */
- wait_queue_head_t fwlog_waitq;
-
/* Hardware recovery work */
struct work_struct recovery_work;
bool watchdog_recovery;