diff options
Diffstat (limited to 'drivers/net/wireless')
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/core.c | 6 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/hw.h | 1 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.c | 12 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/regd.c | 16 | ||||
| -rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | 37 | ||||
| -rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h | 5 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/main.c | 11 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/pci.c | 101 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/pci.h | 1 | ||||
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-nvm-parse.c | 70 | ||||
| -rw-r--r-- | drivers/net/wireless/iwlwifi/mvm/mac80211.c | 10 | ||||
| -rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 28 | ||||
| -rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/mwifiex/scan.c | 6 | ||||
| -rw-r--r-- | drivers/net/wireless/p54/fwio.c | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/realtek/rtlwifi/pci.c | 4 | ||||
| -rw-r--r-- | drivers/net/wireless/ti/wl1251/main.c | 1 |
17 files changed, 239 insertions, 74 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 041d1d5eb718..8b8bea5d546a 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -1698,7 +1698,11 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ar->max_num_stations = TARGET_TLV_NUM_STATIONS; ar->max_num_vdevs = TARGET_TLV_NUM_VDEVS; ar->max_num_tdls_vdevs = TARGET_TLV_NUM_TDLS_VDEVS; - ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC; + if (QCA_REV_WCN3990(ar)) + ar->htt.max_num_pending_tx = + TARGET_HL_1_0_NUM_MSDU_DESC; + else + ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC; ar->wow.max_num_patterns = TARGET_TLV_NUM_WOW_PATTERNS; ar->fw_stats_req_mask = WMI_STAT_PDEV | WMI_STAT_VDEV | WMI_STAT_PEER; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 37479589b8e1..e0af0f766b02 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -628,6 +628,7 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw, #define TARGET_HL_10_TLV_NUM_PEERS 14 #define TARGET_HL_10_TLV_AST_SKID_LIMIT 6 #define TARGET_HL_10_TLV_NUM_WDS_ENTRIES 2 +#define TARGET_HL_1_0_NUM_MSDU_DESC (3600) /* Diagnostic Window */ #define CE_DIAG_PIPE 7 diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 01175d94adca..5a84626dff14 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -7887,6 +7887,12 @@ static struct ieee80211_iface_combination ath10k_wcn3990_qcs_if_comb[] = { .num_different_channels = 1, .max_interfaces = 4, .n_limits = ARRAY_SIZE(ath10k_wcn3990_if_limit), +#ifdef CONFIG_ATH10K_DFS_CERTIFIED + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80), +#endif }, { .limits = ath10k_wcn3990_qcs_if_limit, @@ -7899,6 +7905,12 @@ static struct ieee80211_iface_combination ath10k_wcn3990_qcs_if_comb[] = { .num_different_channels = 1, .max_interfaces = 2, .n_limits = ARRAY_SIZE(ath10k_wcn3990_if_limit_ibss), +#ifdef CONFIG_ATH10K_DFS_CERTIFIED + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | + BIT(NL80211_CHAN_WIDTH_20) | + BIT(NL80211_CHAN_WIDTH_40) | + BIT(NL80211_CHAN_WIDTH_80), +#endif }, }; diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 096818610d40..213569d384e7 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -631,6 +631,8 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, struct regulatory_request *request)) { const struct ieee80211_regdomain *regd; + u32 chan_num; + struct ieee80211_channel *chan; wiphy->reg_notifier = reg_notifier; wiphy->regulatory_flags |= REGULATORY_STRICT_REG | @@ -653,6 +655,20 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, } wiphy_apply_custom_regulatory(wiphy, regd); + + /* For regulatory rules similar to the following: + * REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), channels 12/13 are enabled + * due to support of 5/10 MHz. + * Therefore, disable 2.4 Ghz channels that dont have 20 mhz bw + */ + for (chan_num = 0; + chan_num < wiphy->bands[IEEE80211_BAND_2GHZ]->n_channels; + chan_num++) { + chan = &wiphy->bands[IEEE80211_BAND_2GHZ]->channels[chan_num]; + if (chan->flags & IEEE80211_CHAN_NO_20MHZ) + chan->flags |= IEEE80211_CHAN_DISABLED; + } + ath_reg_apply_radar_flags(wiphy); ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg); return 0; diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index da5826d788d6..5fecae0ba52e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c @@ -876,7 +876,7 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, eth_broadcast_addr(params_le->bssid); params_le->bss_type = DOT11_BSSTYPE_ANY; - params_le->scan_type = 0; + params_le->scan_type = BRCMF_SCANTYPE_ACTIVE; params_le->channel_num = 0; params_le->nprobes = cpu_to_le32(-1); params_le->active_time = cpu_to_le32(-1); @@ -884,12 +884,9 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, params_le->home_time = cpu_to_le32(-1); memset(¶ms_le->ssid_le, 0, sizeof(params_le->ssid_le)); - /* if request is null exit so it will be all channel broadcast scan */ - if (!request) - return; - n_ssids = request->n_ssids; n_channels = request->n_channels; + /* Copy channel array if applicable */ brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n", n_channels); @@ -926,16 +923,8 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, ptr += sizeof(ssid_le); } } else { - brcmf_dbg(SCAN, "Broadcast scan %p\n", request->ssids); - if ((request->ssids) && request->ssids->ssid_len) { - brcmf_dbg(SCAN, "SSID %s len=%d\n", - params_le->ssid_le.SSID, - request->ssids->ssid_len); - params_le->ssid_le.SSID_len = - cpu_to_le32(request->ssids->ssid_len); - memcpy(¶ms_le->ssid_le.SSID, request->ssids->ssid, - request->ssids->ssid_len); - } + brcmf_dbg(SCAN, "Performing passive scan\n"); + params_le->scan_type = BRCMF_SCANTYPE_PASSIVE; } /* Adding mask to channel numbers */ params_le->channel_num = @@ -2914,6 +2903,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, struct brcmf_cfg80211_info *cfg = ifp->drvr->config; s32 status; struct brcmf_escan_result_le *escan_result_le; + u32 escan_buflen; struct brcmf_bss_info_le *bss_info_le; struct brcmf_bss_info_le *bss = NULL; u32 bi_length; @@ -2930,11 +2920,23 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, if (status == BRCMF_E_STATUS_PARTIAL) { brcmf_dbg(SCAN, "ESCAN Partial result\n"); + if (e->datalen < sizeof(*escan_result_le)) { + brcmf_err("invalid event data length\n"); + goto exit; + } escan_result_le = (struct brcmf_escan_result_le *) data; if (!escan_result_le) { brcmf_err("Invalid escan result (NULL pointer)\n"); goto exit; } + escan_buflen = le32_to_cpu(escan_result_le->buflen); + if (escan_buflen > WL_ESCAN_BUF_SIZE || + escan_buflen > e->datalen || + escan_buflen < sizeof(*escan_result_le)) { + brcmf_err("Invalid escan buffer length: %d\n", + escan_buflen); + goto exit; + } if (le16_to_cpu(escan_result_le->bss_count) != 1) { brcmf_err("Invalid bss_count %d: ignoring\n", escan_result_le->bss_count); @@ -2951,9 +2953,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, } bi_length = le32_to_cpu(bss_info_le->length); - if (bi_length != (le32_to_cpu(escan_result_le->buflen) - - WL_ESCAN_RESULTS_FIXED_SIZE)) { - brcmf_err("Invalid bss_info length %d: ignoring\n", + if (bi_length != escan_buflen - WL_ESCAN_RESULTS_FIXED_SIZE) { + brcmf_err("Ignoring invalid bss_info length: %d\n", bi_length); goto exit; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index daa427b46712..4320c4cae53e 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h @@ -45,6 +45,11 @@ #define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff #define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16 +/* scan type definitions */ +#define BRCMF_SCANTYPE_DEFAULT 0xFF +#define BRCMF_SCANTYPE_ACTIVE 0 +#define BRCMF_SCANTYPE_PASSIVE 1 + /* primary (ie tx) key */ #define BRCMF_PRIMARY_KEY (1 << 1) #define DOT11_BSSTYPE_ANY 2 diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index 80e2c8d7c86a..d3afb516b119 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -58,6 +58,7 @@ MODULE_PARM_DESC(enable_waltest, "Enable to handle firmware waltest"); enum cnss_debug_quirks { LINK_DOWN_SELF_RECOVERY, SKIP_DEVICE_BOOT, + USE_CORE_ONLY_FW, }; unsigned long quirks; @@ -1043,6 +1044,8 @@ static int cnss_qca6174_shutdown(struct cnss_plat_data *plat_priv) if (!pci_priv) return -ENODEV; + cnss_pm_request_resume(pci_priv); + cnss_driver_call_remove(plat_priv); cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_NONE); @@ -1111,6 +1114,12 @@ static int cnss_qca6290_powerup(struct cnss_plat_data *plat_priv) return 0; } + if (test_bit(USE_CORE_ONLY_FW, &quirks)) { + clear_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state); + clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); + return 0; + } + cnss_set_pin_connect_status(plat_priv); if (qmi_bypass) { @@ -1141,6 +1150,8 @@ static int cnss_qca6290_shutdown(struct cnss_plat_data *plat_priv) if (!pci_priv) return -ENODEV; + cnss_pm_request_resume(pci_priv); + cnss_driver_call_remove(plat_priv); cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_NONE); diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 22fad9210945..2efc3aa63a75 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -117,6 +117,7 @@ int cnss_suspend_pci_link(struct cnss_pci_data *pci_priv) if (!pci_priv) return -ENODEV; + cnss_pr_dbg("Suspending PCI link\n"); if (!pci_priv->pci_link_state) { cnss_pr_info("PCI link is already suspended!\n"); goto out; @@ -150,6 +151,7 @@ int cnss_resume_pci_link(struct cnss_pci_data *pci_priv) if (!pci_priv) return -ENODEV; + cnss_pr_dbg("Resuming PCI link\n"); if (pci_priv->pci_link_state) { cnss_pr_info("PCI link is already resumed!\n"); goto out; @@ -368,27 +370,37 @@ static int cnss_pci_suspend(struct device *dev) driver_ops = plat_priv->driver_ops; if (driver_ops && driver_ops->suspend) { ret = driver_ops->suspend(pci_dev, state); - if (pci_priv->pci_link_state) { - if (cnss_pci_set_mhi_state(pci_priv, - CNSS_MHI_SUSPEND)) { + if (ret) { + cnss_pr_err("Failed to suspend host driver, err = %d\n", + ret); + ret = -EAGAIN; + goto out; + } + } + + if (pci_priv->pci_link_state) { + ret = cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_SUSPEND); + if (ret) { + if (driver_ops && driver_ops->resume) driver_ops->resume(pci_dev); - ret = -EAGAIN; - goto out; - } - - cnss_set_pci_config_space(pci_priv, - SAVE_PCI_CONFIG_SPACE); - pci_disable_device(pci_dev); - - ret = pci_set_power_state(pci_dev, PCI_D3hot); - if (ret) - cnss_pr_err("Failed to set D3Hot, err = %d\n", - ret); + ret = -EAGAIN; + goto out; } + + cnss_set_pci_config_space(pci_priv, + SAVE_PCI_CONFIG_SPACE); + pci_disable_device(pci_dev); + + ret = pci_set_power_state(pci_dev, PCI_D3hot); + if (ret) + cnss_pr_err("Failed to set D3Hot, err = %d\n", + ret); } cnss_pci_set_monitor_wake_intr(pci_priv, false); + return 0; + out: return ret; } @@ -408,23 +420,30 @@ static int cnss_pci_resume(struct device *dev) if (!plat_priv) goto out; - driver_ops = plat_priv->driver_ops; - if (driver_ops && driver_ops->resume && !pci_priv->pci_link_down_ind) { - ret = pci_enable_device(pci_dev); - if (ret) - cnss_pr_err("Failed to enable PCI device, err = %d\n", - ret); + if (pci_priv->pci_link_down_ind) + goto out; - if (pci_priv->saved_state) - cnss_set_pci_config_space(pci_priv, - RESTORE_PCI_CONFIG_SPACE); + ret = pci_enable_device(pci_dev); + if (ret) + cnss_pr_err("Failed to enable PCI device, err = %d\n", ret); - pci_set_master(pci_dev); - cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RESUME); + if (pci_priv->saved_state) + cnss_set_pci_config_space(pci_priv, + RESTORE_PCI_CONFIG_SPACE); + + pci_set_master(pci_dev); + cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RESUME); + driver_ops = plat_priv->driver_ops; + if (driver_ops && driver_ops->resume) { ret = driver_ops->resume(pci_dev); + if (ret) + cnss_pr_err("Failed to resume host driver, err = %d\n", + ret); } + return 0; + out: return ret; } @@ -600,14 +619,17 @@ int cnss_auto_suspend(void) ret = pci_set_power_state(pci_dev, PCI_D3hot); if (ret) cnss_pr_err("Failed to set D3Hot, err = %d\n", ret); + + cnss_pr_dbg("Suspending PCI link\n"); if (cnss_set_pci_link(pci_priv, PCI_LINK_DOWN)) { - cnss_pr_err("Failed to shutdown PCI link!\n"); + cnss_pr_err("Failed to suspend PCI link!\n"); ret = -EAGAIN; goto resume_mhi; } + + pci_priv->pci_link_state = PCI_LINK_DOWN; } - pci_priv->pci_link_state = PCI_LINK_DOWN; cnss_pci_set_auto_suspended(pci_priv, 1); cnss_pci_set_monitor_wake_intr(pci_priv, true); @@ -643,21 +665,24 @@ int cnss_auto_resume(void) pci_dev = pci_priv->pci_dev; if (!pci_priv->pci_link_state) { + cnss_pr_dbg("Resuming PCI link\n"); if (cnss_set_pci_link(pci_priv, PCI_LINK_UP)) { cnss_pr_err("Failed to resume PCI link!\n"); ret = -EAGAIN; goto out; } pci_priv->pci_link_state = PCI_LINK_UP; + ret = pci_enable_device(pci_dev); if (ret) cnss_pr_err("Failed to enable PCI device, err = %d\n", ret); + + cnss_set_pci_config_space(pci_priv, RESTORE_PCI_CONFIG_SPACE); + pci_set_master(pci_dev); + cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RESUME); } - cnss_set_pci_config_space(pci_priv, RESTORE_PCI_CONFIG_SPACE); - pci_set_master(pci_dev); - cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RESUME); cnss_pci_set_auto_suspended(pci_priv, 0); bus_bw_info = &plat_priv->bus_bw_info; @@ -668,6 +693,20 @@ out: } EXPORT_SYMBOL(cnss_auto_resume); +int cnss_pm_request_resume(struct cnss_pci_data *pci_priv) +{ + struct pci_dev *pci_dev; + + if (!pci_priv) + return -ENODEV; + + pci_dev = pci_priv->pci_dev; + if (!pci_dev) + return -ENODEV; + + return pm_request_resume(&pci_dev->dev); +} + int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv) { struct cnss_plat_data *plat_priv = pci_priv->plat_priv; diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h index e26e331e2f8a..89edc6020d35 100644 --- a/drivers/net/wireless/cnss2/pci.h +++ b/drivers/net/wireless/cnss2/pci.h @@ -138,5 +138,6 @@ int cnss_pci_start_mhi(struct cnss_pci_data *pci_priv); void cnss_pci_stop_mhi(struct cnss_pci_data *pci_priv); void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv); void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv); +int cnss_pm_request_resume(struct cnss_pci_data *pci_priv); #endif /* _CNSS_PCI_H */ diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index d82984912e04..95b82cc132e6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c @@ -73,6 +73,7 @@ /* NVM offsets (in words) definitions */ enum wkp_nvm_offsets { /* NVM HW-Section offset (in words) definitions */ + SUBSYSTEM_ID = 0x0A, HW_ADDR = 0x15, /* NVM SW-Section offset (in words) definitions */ @@ -257,13 +258,12 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz, static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, struct iwl_nvm_data *data, const __le16 * const nvm_ch_flags, - bool lar_supported) + bool lar_supported, bool no_wide_in_5ghz) { int ch_idx; int n_channels = 0; struct ieee80211_channel *channel; u16 ch_flags; - bool is_5ghz; int num_of_ch, num_2ghz_channels; const u8 *nvm_chan; @@ -278,12 +278,20 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, } for (ch_idx = 0; ch_idx < num_of_ch; ch_idx++) { + bool is_5ghz = (ch_idx >= num_2ghz_channels); + ch_flags = __le16_to_cpup(nvm_ch_flags + ch_idx); - if (ch_idx >= num_2ghz_channels && - !data->sku_cap_band_52GHz_enable) + if (is_5ghz && !data->sku_cap_band_52GHz_enable) continue; + /* workaround to disable wide channels in 5GHz */ + if (no_wide_in_5ghz && is_5ghz) { + ch_flags &= ~(NVM_CHANNEL_40MHZ | + NVM_CHANNEL_80MHZ | + NVM_CHANNEL_160MHZ); + } + if (!lar_supported && !(ch_flags & NVM_CHANNEL_VALID)) { /* * Channels might become valid later if lar is @@ -303,8 +311,8 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, n_channels++; channel->hw_value = nvm_chan[ch_idx]; - channel->band = (ch_idx < num_2ghz_channels) ? - IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; + channel->band = is_5ghz ? + IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ; channel->center_freq = ieee80211_channel_to_frequency( channel->hw_value, channel->band); @@ -316,7 +324,6 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, * is not used in mvm, and is used for backwards compatibility */ channel->max_power = IWL_DEFAULT_MAX_TX_POWER; - is_5ghz = channel->band == IEEE80211_BAND_5GHZ; /* don't put limitations in case we're using LAR */ if (!lar_supported) @@ -405,7 +412,8 @@ static void iwl_init_vht_hw_capab(const struct iwl_cfg *cfg, static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, struct iwl_nvm_data *data, const __le16 *ch_section, - u8 tx_chains, u8 rx_chains, bool lar_supported) + u8 tx_chains, u8 rx_chains, bool lar_supported, + bool no_wide_in_5ghz) { int n_channels; int n_used = 0; @@ -414,12 +422,14 @@ static void iwl_init_sbands(struct device *dev, const struct iwl_cfg *cfg, if (cfg->device_family != IWL_DEVICE_FAMILY_8000) n_channels = iwl_init_channel_map( dev, cfg, data, - &ch_section[NVM_CHANNELS], lar_supported); + &ch_section[NVM_CHANNELS], lar_supported, + no_wide_in_5ghz); else n_channels = iwl_init_channel_map( dev, cfg, data, &ch_section[NVM_CHANNELS_FAMILY_8000], - lar_supported); + lar_supported, + no_wide_in_5ghz); sband = &data->bands[IEEE80211_BAND_2GHZ]; sband->band = IEEE80211_BAND_2GHZ; @@ -582,6 +592,39 @@ static void iwl_set_hw_address_family_8000(struct device *dev, #define IWL_4165_DEVICE_ID 0x5501 +static bool +iwl_nvm_no_wide_in_5ghz(struct device *dev, const struct iwl_cfg *cfg, + const __le16 *nvm_hw) +{ + /* + * Workaround a bug in Indonesia SKUs where the regulatory in + * some 7000-family OTPs erroneously allow wide channels in + * 5GHz. To check for Indonesia, we take the SKU value from + * bits 1-4 in the subsystem ID and check if it is either 5 or + * 9. In those cases, we need to force-disable wide channels + * in 5GHz otherwise the FW will throw a sysassert when we try + * to use them. + */ + if (cfg->device_family == IWL_DEVICE_FAMILY_7000) { + /* + * Unlike the other sections in the NVM, the hw + * section uses big-endian. + */ + u16 subsystem_id = be16_to_cpup((const __be16 *)nvm_hw + + SUBSYSTEM_ID); + u8 sku = (subsystem_id & 0x1e) >> 1; + + if (sku == 5 || sku == 9) { + IWL_DEBUG_EEPROM(dev, + "disabling wide channels in 5GHz (0x%0x %d)\n", + subsystem_id, sku); + return true; + } + } + + return false; +} + struct iwl_nvm_data * iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, const __le16 *nvm_hw, const __le16 *nvm_sw, @@ -591,6 +634,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, u32 mac_addr0, u32 mac_addr1, u32 hw_id) { struct iwl_nvm_data *data; + bool no_wide_in_5ghz = iwl_nvm_no_wide_in_5ghz(dev, cfg, nvm_hw); u32 sku; u32 radio_cfg; u16 lar_config; @@ -657,7 +701,8 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, iwl_set_hw_address(cfg, data, nvm_hw); iwl_init_sbands(dev, cfg, data, nvm_sw, - tx_chains, rx_chains, lar_fw_supported); + tx_chains, rx_chains, lar_fw_supported, + no_wide_in_5ghz); } else { u16 lar_offset = data->nvm_version < 0xE39 ? NVM_LAR_OFFSET_FAMILY_8000_OLD : @@ -673,7 +718,8 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg, iwl_init_sbands(dev, cfg, data, regulatory, tx_chains, rx_chains, - lar_fw_supported && data->lar_enabled); + lar_fw_supported && data->lar_enabled, + no_wide_in_5ghz); } data->calib_version = 255; diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 1a8ea775de08..984cd2f05c4a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1906,6 +1906,11 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac, struct iwl_mvm_mc_iter_data *data = _data; struct iwl_mvm *mvm = data->mvm; struct iwl_mcast_filter_cmd *cmd = mvm->mcast_filter_cmd; + struct iwl_host_cmd hcmd = { + .id = MCAST_FILTER_CMD, + .flags = CMD_ASYNC, + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, + }; int ret, len; /* if we don't have free ports, mcast frames will be dropped */ @@ -1920,7 +1925,10 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac, memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4); - ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_ASYNC, len, cmd); + hcmd.len[0] = len; + hcmd.data[0] = cmd; + + ret = iwl_mvm_send_cmd(mvm, &hcmd); if (ret) IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret); } diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 019d7165a045..2a996a68fc2b 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2884,6 +2884,7 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2, static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) { struct hwsim_new_radio_params param = { 0 }; + const char *hwname = NULL; param.reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; param.p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; @@ -2897,8 +2898,14 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) if (info->attrs[HWSIM_ATTR_NO_VIF]) param.no_vif = true; - if (info->attrs[HWSIM_ATTR_RADIO_NAME]) - param.hwname = nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]); + if (info->attrs[HWSIM_ATTR_RADIO_NAME]) { + hwname = kasprintf(GFP_KERNEL, "%.*s", + nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]), + (char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME])); + if (!hwname) + return -ENOMEM; + param.hwname = hwname; + } if (info->attrs[HWSIM_ATTR_USE_CHANCTX]) param.use_chanctx = true; @@ -2926,11 +2933,15 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) s64 idx = -1; const char *hwname = NULL; - if (info->attrs[HWSIM_ATTR_RADIO_ID]) + if (info->attrs[HWSIM_ATTR_RADIO_ID]) { idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); - else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) - hwname = (void *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]); - else + } else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) { + hwname = kasprintf(GFP_KERNEL, "%.*s", + nla_len(info->attrs[HWSIM_ATTR_RADIO_NAME]), + (char *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME])); + if (!hwname) + return -ENOMEM; + } else return -EINVAL; spin_lock_bh(&hwsim_radio_lock); @@ -2939,7 +2950,8 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) if (data->idx != idx) continue; } else { - if (strcmp(hwname, wiphy_name(data->hw->wiphy))) + if (!hwname || + strcmp(hwname, wiphy_name(data->hw->wiphy))) continue; } @@ -2947,10 +2959,12 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) spin_unlock_bh(&hwsim_radio_lock); mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), info); + kfree(hwname); return 0; } spin_unlock_bh(&hwsim_radio_lock); + kfree(hwname); return -ENODEV; } diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index c3331d6201c3..9a8982f581c5 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -3740,7 +3740,7 @@ int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter) if (adapter->config_bands & BAND_A) n_channels_a = mwifiex_band_5ghz.n_channels; - adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a); + adapter->num_in_chan_stats = n_channels_bg + n_channels_a; adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) * adapter->num_in_chan_stats); diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index c20017ced566..fb98f42cb5e7 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -2170,6 +2170,12 @@ mwifiex_update_chan_statistics(struct mwifiex_private *priv, sizeof(struct mwifiex_chan_stats); for (i = 0 ; i < num_chan; i++) { + if (adapter->survey_idx >= adapter->num_in_chan_stats) { + mwifiex_dbg(adapter, WARN, + "FW reported too many channel results (max %d)\n", + adapter->num_in_chan_stats); + return; + } chan_stats.chan_num = fw_chan_stats->chan_num; chan_stats.bandcfg = fw_chan_stats->bandcfg; chan_stats.flags = fw_chan_stats->flags; diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index 257a9eadd595..4ac6764f4897 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c @@ -488,7 +488,7 @@ int p54_scan(struct p54_common *priv, u16 mode, u16 dwell) entry += sizeof(__le16); chan->pa_points_per_curve = 8; - memset(chan->curve_data, 0, sizeof(*chan->curve_data)); + memset(chan->curve_data, 0, sizeof(chan->curve_data)); memcpy(chan->curve_data, entry, sizeof(struct p54_pa_curve_data_sample) * min((u8)8, curve_data->points_per_channel)); diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index a52230377e2c..c48b7e8ee0d6 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -2269,7 +2269,7 @@ int rtl_pci_probe(struct pci_dev *pdev, /* find adapter */ if (!_rtl_pci_find_adapter(pdev, hw)) { err = -ENODEV; - goto fail3; + goto fail2; } /* Init IO handler */ @@ -2339,10 +2339,10 @@ fail3: pci_set_drvdata(pdev, NULL); rtl_deinit_core(hw); +fail2: if (rtlpriv->io.pci_mem_start != 0) pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start); -fail2: pci_release_regions(pdev); complete(&rtlpriv->firmware_loading_complete); diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index cd4777954f87..9bee3f11898a 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c @@ -1567,6 +1567,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void) wl->state = WL1251_STATE_OFF; mutex_init(&wl->mutex); + spin_lock_init(&wl->wl_lock); wl->tx_mgmt_frm_rate = DEFAULT_HW_GEN_TX_RATE; wl->tx_mgmt_frm_mod = DEFAULT_HW_GEN_MODULATION_TYPE; |
