diff options
26 files changed, 288 insertions, 114 deletions
diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c index f521af575e9b..c866cfd144c7 100644 --- a/drivers/net/wireless/ath/wil6210/pm.c +++ b/drivers/net/wireless/ath/wil6210/pm.c @@ -458,6 +458,5 @@ void wil_pm_runtime_put(struct wil6210_priv *wil) { struct device *dev = wil_to_dev(wil); - pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); } diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c index b264ed0af923..65d0f805459c 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c @@ -24,6 +24,7 @@ #include <linux/crc-ccitt.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/nvmem-consumer.h> #include <linux/slab.h> #include "rt2x00.h" @@ -10962,6 +10963,36 @@ int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev) } EXPORT_SYMBOL_GPL(rt2800_read_eeprom_efuse); +int rt2800_read_eeprom_nvmem(struct rt2x00_dev *rt2x00dev) +{ + struct device_node *np = rt2x00dev->dev->of_node; + unsigned int len = rt2x00dev->ops->eeprom_size; + struct nvmem_cell *cell; + const void *data; + size_t retlen; + + cell = of_nvmem_cell_get(np, "eeprom"); + if (IS_ERR(cell)) + return PTR_ERR(cell); + + data = nvmem_cell_read(cell, &retlen); + nvmem_cell_put(cell); + + if (IS_ERR(data)) + return PTR_ERR(data); + + if (retlen != len) { + dev_err(rt2x00dev->dev, "invalid eeprom size, required: 0x%04x\n", len); + kfree(data); + return -EINVAL; + } + + memcpy(rt2x00dev->eeprom, data, len); + kfree(data); + return 0; +} +EXPORT_SYMBOL_GPL(rt2800_read_eeprom_nvmem); + static u8 rt2800_get_txmixer_gain_24g(struct rt2x00_dev *rt2x00dev) { u16 word; @@ -11011,7 +11042,9 @@ static int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) * Start validation of the data that has been read. */ mac = rt2800_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); - rt2x00lib_set_mac_address(rt2x00dev, mac); + retval = rt2x00lib_set_mac_address(rt2x00dev, mac); + if (retval) + return retval; word = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0); if (word == 0xffff) { diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h index 620a3d9872ce..a3c3a751f57e 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.h @@ -248,6 +248,8 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); int rt2800_efuse_detect(struct rt2x00_dev *rt2x00dev); int rt2800_read_eeprom_efuse(struct rt2x00_dev *rt2x00dev); +int rt2800_read_eeprom_nvmem(struct rt2x00_dev *rt2x00dev); + int rt2800_probe_hw(struct rt2x00_dev *rt2x00dev); void rt2800_get_key_seq(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c index 14c45aba836f..4fa14bb573ad 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800pci.c @@ -278,6 +278,9 @@ static int rt2800pci_read_eeprom(struct rt2x00_dev *rt2x00dev) { int retval; + if (!rt2800_read_eeprom_nvmem(rt2x00dev)) + return 0; + if (rt2800pci_efuse_detect(rt2x00dev)) retval = rt2800pci_read_eeprom_efuse(rt2x00dev); else diff --git a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c index 8f510a84e7f1..5c29201b34c8 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2800soc.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2800soc.c @@ -92,8 +92,12 @@ static int rt2800soc_set_device_state(struct rt2x00_dev *rt2x00dev, static int rt2800soc_read_eeprom(struct rt2x00_dev *rt2x00dev) { - void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); + void __iomem *base_addr; + if (!rt2800_read_eeprom_nvmem(rt2x00dev)) + return 0; + + base_addr = ioremap(0x1F040000, EEPROM_SIZE); if (!base_addr) return -ENOMEM; diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00.h b/drivers/net/wireless/ralink/rt2x00/rt2x00.h index 09b9d1f9f793..665887e9b118 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00.h +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00.h @@ -1427,7 +1427,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, */ u32 rt2x00lib_get_bssidx(struct rt2x00_dev *rt2x00dev, struct ieee80211_vif *vif); -void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr); +int rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr); /* * Interrupt context handlers. diff --git a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c index f8a6f9c968a1..778a478ab53a 100644 --- a/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/ralink/rt2x00/rt2x00dev.c @@ -988,14 +988,20 @@ static void rt2x00lib_rate(struct ieee80211_rate *entry, entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE; } -void rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr) +int rt2x00lib_set_mac_address(struct rt2x00_dev *rt2x00dev, u8 *eeprom_mac_addr) { - of_get_mac_address(rt2x00dev->dev->of_node, eeprom_mac_addr); + int ret; + + ret = of_get_mac_address(rt2x00dev->dev->of_node, eeprom_mac_addr); + if (ret == -EPROBE_DEFER) + return ret; if (!is_valid_ether_addr(eeprom_mac_addr)) { eth_random_addr(eeprom_mac_addr); rt2x00_eeprom_dbg(rt2x00dev, "MAC: %pM\n", eeprom_mac_addr); } + + return 0; } EXPORT_SYMBOL_GPL(rt2x00lib_set_mac_address); diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c b/drivers/net/wireless/ti/wl18xx/debugfs.c index 80fbf740fe6d..ac756318e8ea 100644 --- a/drivers/net/wireless/ti/wl18xx/debugfs.c +++ b/drivers/net/wireless/ti/wl18xx/debugfs.c @@ -272,7 +272,6 @@ static ssize_t radar_detection_write(struct file *file, if (ret < 0) count = ret; - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -312,7 +311,6 @@ static ssize_t dynamic_fw_traces_write(struct file *file, if (ret < 0) count = ret; - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -374,7 +372,6 @@ static ssize_t radar_debug_mode_write(struct file *file, wl->radar_debug_mode, 0); } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index fa3a3f71dd15..9d73ba933a16 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -213,7 +213,6 @@ int wlcore_cmd_wait_for_event_or_timeout(struct wl1271 *wl, } while (!event); out: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); free_vector: kfree(events_vector); diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index eb3d3f0e0b4d..bbfd2725215b 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c @@ -63,7 +63,6 @@ void wl1271_debugfs_update_stats(struct wl1271 *wl) wl->stats.fw_stats_update = jiffies; } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: @@ -113,7 +112,6 @@ static void chip_op_handler(struct wl1271 *wl, unsigned long value, chip_op = arg; chip_op(wl); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); } @@ -287,7 +285,6 @@ static ssize_t dynamic_ps_timeout_write(struct file *file, wl1271_ps_set_mode(wl, wlvif, STATION_AUTO_PS_MODE); } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: @@ -357,7 +354,6 @@ static ssize_t forced_ps_write(struct file *file, wl1271_ps_set_mode(wl, wlvif, ps_mode); } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: @@ -830,7 +826,6 @@ static ssize_t rx_streaming_interval_write(struct file *file, wl1271_recalc_rx_streaming(wl, wlvif); } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -886,7 +881,6 @@ static ssize_t rx_streaming_always_write(struct file *file, wl1271_recalc_rx_streaming(wl, wlvif); } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -934,7 +928,6 @@ static ssize_t beacon_filtering_write(struct file *file, ret = wl1271_acx_beacon_filter_opt(wl, wlvif, !!value); } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -1015,7 +1008,6 @@ static ssize_t sleep_auth_write(struct file *file, goto out_sleep; out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -1090,7 +1082,6 @@ read_err: goto part_err; part_err: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); skip_read: @@ -1172,7 +1163,6 @@ write_err: goto part_err; part_err: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); skip_write: @@ -1247,7 +1237,6 @@ static ssize_t fw_logger_write(struct file *file, ret = wl12xx_cmd_config_fwlog(wl); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 6116a8522d96..12f0167d7380 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -154,7 +154,6 @@ static void wl1271_rx_streaming_enable_work(struct work_struct *work) jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration)); out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -181,7 +180,6 @@ static void wl1271_rx_streaming_disable_work(struct work_struct *work) goto out_sleep; out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -234,7 +232,6 @@ static void wlcore_rc_update_work(struct work_struct *work) } out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -711,7 +708,6 @@ static int wlcore_irq_locked(struct wl1271 *wl) } err_ret: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: @@ -1047,7 +1043,6 @@ static void wl1271_recovery_work(struct work_struct *work) } wlcore_op_stop_locked(wl); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); ieee80211_restart_hw(wl->hw); @@ -1943,7 +1938,6 @@ static int __maybe_unused wl1271_op_resume(struct ieee80211_hw *hw) goto out_sleep; out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: @@ -2131,7 +2125,6 @@ static void wlcore_channel_switch_work(struct work_struct *work) wl12xx_cmd_stop_channel_switch(wl, wlvif); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -2201,7 +2194,6 @@ static void wlcore_pending_auth_complete_work(struct work_struct *work) /* cancel the ROC if active */ wlcore_update_inconn_sta(wl, wlvif, NULL, false); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -2694,7 +2686,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, else wl->sta_count++; out: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out_unlock: mutex_unlock(&wl->mutex); @@ -2774,7 +2765,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, } } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); } deinit: @@ -3200,7 +3190,6 @@ static int wl1271_op_config(struct ieee80211_hw *hw, int radio_idx, u32 changed) } out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: @@ -3315,7 +3304,6 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, */ out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: @@ -3531,7 +3519,6 @@ static int wlcore_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ret = wlcore_hw_set_key(wl, cmd, vif, sta, key_conf); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out_wake_queues: @@ -3695,7 +3682,6 @@ static void wl1271_op_set_default_key_idx(struct ieee80211_hw *hw, } out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out_unlock: @@ -3724,7 +3710,6 @@ void wlcore_regdomain_config(struct wl1271 *wl) goto out; } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -3772,7 +3757,6 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, ret = wlcore_scan(hw->priv, vif, ssid, len, req); out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -3823,7 +3807,6 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw, ieee80211_scan_completed(wl->hw, &info); out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -3860,7 +3843,6 @@ static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, wl->sched_vif = wlvif; out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -3887,7 +3869,6 @@ static int wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, wl->ops->sched_scan_stop(wl, wlvif); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -3916,7 +3897,6 @@ static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, if (ret < 0) wl1271_warning("wl1271_op_set_frag_threshold failed: %d", ret); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: @@ -3948,7 +3928,6 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx, if (ret < 0) wl1271_warning("set rts threshold failed: %d", ret); } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: @@ -4714,7 +4693,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, else wl1271_bss_info_changed_sta(wl, vif, bss_conf, changed); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: @@ -4779,7 +4757,6 @@ static void wlcore_op_change_chanctx(struct ieee80211_hw *hw, } } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -4828,7 +4805,6 @@ static int wlcore_op_assign_vif_chanctx(struct ieee80211_hw *hw, wlvif->radar_enabled = true; } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -4871,7 +4847,6 @@ static void wlcore_op_unassign_vif_chanctx(struct ieee80211_hw *hw, wlvif->radar_enabled = false; } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -4941,7 +4916,6 @@ wlcore_op_switch_vif_chanctx(struct ieee80211_hw *hw, goto out_sleep; } out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -4995,7 +4969,6 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, 0, 0); out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: @@ -5029,7 +5002,6 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw, goto out_sleep; out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: @@ -5342,7 +5314,6 @@ static int wl12xx_op_sta_state(struct ieee80211_hw *hw, ret = wl12xx_update_sta_state(wl, wlvif, sta, old_state, new_state); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -5467,7 +5438,6 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, ret = -EINVAL; } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: @@ -5511,7 +5481,6 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw, wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); ret = wl1271_acx_sta_rate_policies(wl, wlvif); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); } out: @@ -5566,7 +5535,6 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, } out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: @@ -5645,7 +5613,6 @@ static void wlcore_op_channel_switch_beacon(struct ieee80211_hw *hw, set_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags); out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -5699,7 +5666,6 @@ static int wlcore_op_remain_on_channel(struct ieee80211_hw *hw, ieee80211_queue_delayed_work(hw, &wl->roc_complete_work, msecs_to_jiffies(duration)); out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -5748,7 +5714,6 @@ static int wlcore_roc_completed(struct wl1271 *wl) ret = __wlcore_roc_completed(wl); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -5839,7 +5804,6 @@ static void wlcore_op_sta_statistics(struct ieee80211_hw *hw, sinfo->signal = rssi_dbm; out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c index b414305acc32..f6dc54c1dbad 100644 --- a/drivers/net/wireless/ti/wlcore/scan.c +++ b/drivers/net/wireless/ti/wlcore/scan.c @@ -69,7 +69,6 @@ void wl1271_scan_complete_work(struct work_struct *work) wlcore_cmd_regdomain_config_locked(wl); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); ieee80211_scan_completed(wl->hw, &info); diff --git a/drivers/net/wireless/ti/wlcore/sysfs.c b/drivers/net/wireless/ti/wlcore/sysfs.c index 65ca5dc569a0..5ab6c1683675 100644 --- a/drivers/net/wireless/ti/wlcore/sysfs.c +++ b/drivers/net/wireless/ti/wlcore/sysfs.c @@ -58,7 +58,6 @@ static ssize_t bt_coex_state_store(struct device *dev, goto out; wl1271_acx_sg_enable(wl, wl->sg_enabled); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: diff --git a/drivers/net/wireless/ti/wlcore/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c index fc8ea58bc165..7c0cb1b7fef0 100644 --- a/drivers/net/wireless/ti/wlcore/testmode.c +++ b/drivers/net/wireless/ti/wlcore/testmode.c @@ -127,7 +127,6 @@ static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[]) } out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -192,7 +191,6 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) out_free: kfree(cmd); out_sleep: - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 464587d16ab2..f76087be2f75 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c @@ -863,7 +863,6 @@ void wl1271_tx_work(struct work_struct *work) goto out; } - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); diff --git a/drivers/net/wireless/ti/wlcore/vendor_cmd.c b/drivers/net/wireless/ti/wlcore/vendor_cmd.c index e4269e2b0098..5bb9eb300f97 100644 --- a/drivers/net/wireless/ti/wlcore/vendor_cmd.c +++ b/drivers/net/wireless/ti/wlcore/vendor_cmd.c @@ -60,7 +60,6 @@ wlcore_vendor_cmd_smart_config_start(struct wiphy *wiphy, ret = wlcore_smart_config_start(wl, nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID])); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -92,7 +91,6 @@ wlcore_vendor_cmd_smart_config_stop(struct wiphy *wiphy, ret = wlcore_smart_config_stop(wl); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); @@ -140,7 +138,6 @@ wlcore_vendor_cmd_smart_config_set_group_key(struct wiphy *wiphy, nla_len(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]), nla_data(tb[WLCORE_VENDOR_ATTR_GROUP_KEY])); - pm_runtime_mark_last_busy(wl->dev); pm_runtime_put_autosuspend(wl->dev); out: mutex_unlock(&wl->mutex); diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c index 9f856042a67a..cd84dfd5b47e 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c @@ -5793,6 +5793,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, ieee80211_hw_set(hw, NO_AUTO_VIF); wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); + wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_PUNCT); for (i = 0; i < ARRAY_SIZE(data->link_data); i++) { hrtimer_setup(&data->link_data[i].beacon_timer, mac80211_hwsim_beacon, diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 781624f5913a..53490eb04e87 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -1015,6 +1015,7 @@ const struct cfg80211_chan_def * cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1, const struct cfg80211_chan_def *chandef2); + /** * nl80211_chan_width_to_mhz - get the channel width in MHz * @chan_width: the channel width from &enum nl80211_chan_width @@ -5683,9 +5684,13 @@ struct wiphy_iftype_akm_suites { * * @rts_threshold: RTS threshold (dot11RTSThreshold); * -1 (default) = RTS/CTS disabled + * @radio_debugfsdir: Pointer to debugfs directory containing the radio- + * specific parameters. + * NULL (default) = Debugfs directory not created */ struct wiphy_radio_cfg { u32 rts_threshold; + struct dentry *radio_debugfsdir; }; /** @@ -6883,6 +6888,19 @@ static inline bool cfg80211_channel_is_psc(struct ieee80211_channel *chan) } /** + * ieee80211_radio_freq_range_valid - Check if the radio supports the + * specified frequency range + * + * @radio: wiphy radio + * @freq: the frequency (in KHz) to be queried + * @width: the bandwidth (in KHz) to be queried + * + * Return: whether or not the given frequency range is valid for the given radio + */ +bool ieee80211_radio_freq_range_valid(const struct wiphy_radio *radio, + u32 freq, u32 width); + +/** * cfg80211_radio_chandef_valid - Check if the radio supports the chandef * * @radio: wiphy radio diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h index 813e163ce27c..c60867e7e43c 100644 --- a/include/net/ieee80211_radiotap.h +++ b/include/net/ieee80211_radiotap.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2017 Intel Deutschland GmbH - * Copyright (c) 2018-2019, 2021-2022 Intel Corporation + * Copyright (c) 2018-2019, 2021-2022, 2025 Intel Corporation * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -202,6 +202,24 @@ enum ieee80211_radiotap_vht_coding { IEEE80211_RADIOTAP_CODING_LDPC_USER3 = 0x08, }; +enum ieee80211_radiotap_vht_bandwidth { + /* Note: more values are defined but can't really be used */ + IEEE80211_RADIOTAP_VHT_BW_20 = 0, + IEEE80211_RADIOTAP_VHT_BW_40 = 1, + IEEE80211_RADIOTAP_VHT_BW_80 = 4, + IEEE80211_RADIOTAP_VHT_BW_160 = 11, +}; + +struct ieee80211_radiotap_vht { + __le16 known; + u8 flags; + u8 bandwidth; + u8 mcs_nss[4]; + u8 coding; + u8 group_id; + __le16 partial_aid; +} __packed; + /* for IEEE80211_RADIOTAP_TIMESTAMP */ enum ieee80211_radiotap_timestamp_unit_spos { IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MASK = 0x000F, diff --git a/include/net/mac80211.h b/include/net/mac80211.h index a55085cf4ec4..c326243e1f01 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1529,6 +1529,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * known the frame shouldn't be reported. * @RX_FLAG_8023: the frame has an 802.3 header (decap offload performed by * hardware or driver) + * @RX_FLAG_RADIOTAP_VHT: VHT radiotap data is present */ enum mac80211_rx_flags { RX_FLAG_MMIC_ERROR = BIT(0), @@ -1564,6 +1565,7 @@ enum mac80211_rx_flags { RX_FLAG_RADIOTAP_LSIG = BIT(28), RX_FLAG_NO_PSDU = BIT(29), RX_FLAG_8023 = BIT(30), + RX_FLAG_RADIOTAP_VHT = BIT(31), }; /** diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 3b5827ea438e..025210d50405 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2508,6 +2508,16 @@ static void ieee80211_csa_switch_work(struct wiphy *wiphy, link->u.mgd.csa.waiting_bcn = true; + /* + * The next beacon really should always be different, so this should + * have no effect whatsoever. However, some APs (we observed this in + * an Asus AXE11000), the beacon after the CSA might be identical to + * the last beacon on the old channel - in this case we'd ignore it. + * Resetting the CRC will lead us to handle it better (albeit with a + * disconnect, but clearly the AP is broken.) + */ + link->u.mgd.beacon_crc_valid = false; + /* apply new TPE restrictions immediately on the new channel */ if (link->u.mgd.csa.ap_chandef.chan->band == NL80211_BAND_6GHZ && link->u.mgd.conn.mode >= IEEE80211_CONN_MODE_HE) { @@ -6610,8 +6620,8 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_link_data *link, * Response frame shall be set to the broadcast address [..]" * So, on 6GHz band we should also accept broadcast responses. */ - channel = ieee80211_get_channel(sdata->local->hw.wiphy, - rx_status->freq); + channel = ieee80211_get_channel_khz(sdata->local->hw.wiphy, + ieee80211_rx_status_to_khz(rx_status)); if (!channel) return; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6af43dfefdd6..80067ed1da2f 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -59,7 +59,8 @@ static struct sk_buff *ieee80211_clean_skb(struct sk_buff *skb, status->flag &= ~(RX_FLAG_RADIOTAP_TLV_AT_END | RX_FLAG_RADIOTAP_LSIG | RX_FLAG_RADIOTAP_HE_MU | - RX_FLAG_RADIOTAP_HE); + RX_FLAG_RADIOTAP_HE | + RX_FLAG_RADIOTAP_VHT); hdr = (void *)skb->data; fc = hdr->frame_control; @@ -151,8 +152,10 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local, } if (status->encoding == RX_ENC_VHT) { + /* Included even if RX_FLAG_RADIOTAP_VHT is not set */ len = ALIGN(len, 2); len += 12; + BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_vht) != 12); } if (local->hw.radiotap_timestamp.units_pos >= 0) { @@ -195,6 +198,9 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local, * The position to look at depends on the existence (or non- * existence) of other elements, so take that into account... */ + if (status->flag & RX_FLAG_RADIOTAP_VHT) + tlv_offset += + sizeof(struct ieee80211_radiotap_vht); if (status->flag & RX_FLAG_RADIOTAP_HE) tlv_offset += sizeof(struct ieee80211_radiotap_he); @@ -319,10 +325,17 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, u32 tlvs_len = 0; int mpdulen, chain; unsigned long chains = status->chains; + struct ieee80211_radiotap_vht vht = {}; struct ieee80211_radiotap_he he = {}; struct ieee80211_radiotap_he_mu he_mu = {}; struct ieee80211_radiotap_lsig lsig = {}; + if (status->flag & RX_FLAG_RADIOTAP_VHT) { + vht = *(struct ieee80211_radiotap_vht *)skb->data; + skb_pull(skb, sizeof(vht)); + WARN_ON_ONCE(status->encoding != RX_ENC_VHT); + } + if (status->flag & RX_FLAG_RADIOTAP_HE) { he = *(struct ieee80211_radiotap_he *)skb->data; skb_pull(skb, sizeof(he)); @@ -530,45 +543,61 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, } if (status->encoding == RX_ENC_VHT) { - u16 known = local->hw.radiotap_vht_details; + u16 fill = local->hw.radiotap_vht_details; - rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_VHT)); - put_unaligned_le16(known, pos); - pos += 2; - /* flags */ - if (status->enc_flags & RX_ENC_FLAG_SHORT_GI) - *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; + /* Leave driver filled fields alone */ + fill &= ~le16_to_cpu(vht.known); + vht.known |= cpu_to_le16(fill); + + if (fill & IEEE80211_RADIOTAP_VHT_KNOWN_GI && + status->enc_flags & RX_ENC_FLAG_SHORT_GI) + vht.flags |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; /* in VHT, STBC is binary */ - if (status->enc_flags & RX_ENC_FLAG_STBC_MASK) - *pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC; - if (status->enc_flags & RX_ENC_FLAG_BF) + if (fill & IEEE80211_RADIOTAP_VHT_KNOWN_STBC && + status->enc_flags & RX_ENC_FLAG_STBC_MASK) + vht.flags |= IEEE80211_RADIOTAP_VHT_FLAG_STBC; + if (fill & IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED && + status->enc_flags & RX_ENC_FLAG_BF) *pos |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED; - pos++; - /* bandwidth */ - switch (status->bw) { - case RATE_INFO_BW_80: - *pos++ = 4; - break; - case RATE_INFO_BW_160: - *pos++ = 11; - break; - case RATE_INFO_BW_40: - *pos++ = 1; - break; - default: - *pos++ = 0; + + if (fill & IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH) { + switch (status->bw) { + case RATE_INFO_BW_40: + vht.bandwidth = IEEE80211_RADIOTAP_VHT_BW_40; + break; + case RATE_INFO_BW_80: + vht.bandwidth = IEEE80211_RADIOTAP_VHT_BW_80; + break; + case RATE_INFO_BW_160: + vht.bandwidth = IEEE80211_RADIOTAP_VHT_BW_160; + break; + default: + vht.bandwidth = IEEE80211_RADIOTAP_VHT_BW_20; + break; + } } - /* MCS/NSS */ - *pos = (status->rate_idx << 4) | status->nss; - pos += 4; - /* coding field */ - if (status->enc_flags & RX_ENC_FLAG_LDPC) - *pos |= IEEE80211_RADIOTAP_CODING_LDPC_USER0; - pos++; - /* group ID */ - pos++; - /* partial_aid */ - pos += 2; + + /* + * If the driver filled in mcs_nss[0], then do not touch it. + * + * Otherwise, put some information about MCS/NSS into the + * user 0 field. Note that this is not technically correct for + * an MU frame as we might have decoded a different user. + */ + if (!vht.mcs_nss[0]) { + vht.mcs_nss[0] = (status->rate_idx << 4) | status->nss; + + /* coding field */ + if (status->enc_flags & RX_ENC_FLAG_LDPC) + vht.coding |= IEEE80211_RADIOTAP_CODING_LDPC_USER0; + } + + /* ensure 2 byte alignment */ + while ((pos - (u8 *)rthdr) & 1) + pos++; + rthdr->it_present |= cpu_to_le32(BIT(IEEE80211_RADIOTAP_VHT)); + memcpy(pos, &vht, sizeof(vht)); + pos += sizeof(vht); } if (local->hw.radiotap_timestamp.units_pos >= 0) { @@ -763,6 +792,51 @@ ieee80211_make_monitor_skb(struct ieee80211_local *local, return skb; } +static bool +ieee80211_validate_monitor_radio(struct ieee80211_sub_if_data *sdata, + struct ieee80211_local *local, + struct ieee80211_rx_status *status) +{ + struct wiphy *wiphy = local->hw.wiphy; + int i, freq, bw; + + if (!wiphy->n_radio) + return true; + + switch (status->bw) { + case RATE_INFO_BW_20: + bw = 20000; + break; + case RATE_INFO_BW_40: + bw = 40000; + break; + case RATE_INFO_BW_80: + bw = 80000; + break; + case RATE_INFO_BW_160: + bw = 160000; + break; + case RATE_INFO_BW_320: + bw = 320000; + break; + default: + return false; + } + + freq = MHZ_TO_KHZ(status->freq); + + for (i = 0; i < wiphy->n_radio; i++) { + if (!(sdata->wdev.radio_mask & BIT(i))) + continue; + + if (!ieee80211_radio_freq_range_valid(&wiphy->radio[i], freq, bw)) + continue; + + return true; + } + return false; +} + /* * This function copies a received frame to all monitor interfaces and * returns a cleaned-up SKB that no longer includes the FCS nor the @@ -789,6 +863,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, return NULL; } + if (status->flag & RX_FLAG_RADIOTAP_VHT) + rtap_space += sizeof(struct ieee80211_radiotap_vht); + if (status->flag & RX_FLAG_RADIOTAP_HE) rtap_space += sizeof(struct ieee80211_radiotap_he); @@ -855,6 +932,10 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, chandef->chan->center_freq != status->freq) continue; + if (ieee80211_hw_check(&local->hw, NO_VIRTUAL_MONITOR) && + !ieee80211_validate_monitor_radio(sdata, local, status)) + continue; + if (!prev_sdata) { prev_sdata = sdata; continue; @@ -3521,8 +3602,11 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) switch (mgmt->u.action.category) { case WLAN_CATEGORY_HT: - /* reject HT action frames from stations not supporting HT */ - if (!rx->link_sta->pub->ht_cap.ht_supported) + /* reject HT action frames from stations not supporting HT + * or not HE Capable + */ + if (!rx->link_sta->pub->ht_cap.ht_supported && + !rx->link_sta->pub->he_cap.has_he) goto invalid; if (sdata->vif.type != NL80211_IFTYPE_STATION && @@ -4903,6 +4987,11 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, /* after this point, don't punt to the slowpath! */ + if (fast_rx->uses_rss) + stats = this_cpu_ptr(rx->link_sta->pcpu_rx_stats); + else + stats = &rx->link_sta->rx_stats; + if (rx->key && !(status->flag & RX_FLAG_MIC_STRIPPED) && pskb_trim(skb, skb->len - fast_rx->icv_len)) goto drop; @@ -4937,6 +5026,8 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb); switch (res) { case RX_QUEUED: + stats->last_rx = jiffies; + stats->last_rate = sta_stats_encode_rate(status); return true; case RX_CONTINUE: break; @@ -4950,11 +5041,6 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, drop: dev_kfree_skb(skb); - if (fast_rx->uses_rss) - stats = this_cpu_ptr(rx->link_sta->pcpu_rx_stats); - else - stats = &rx->link_sta->rx_stats; - stats->dropped++; return true; } diff --git a/net/wireless/core.c b/net/wireless/core.c index 797f9f2004a6..f3568eb5e592 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -34,6 +34,9 @@ /* name for sysfs, %d is appended */ #define PHY_NAME "phy" +/* maximum length of radio debugfs directory name */ +#define RADIO_DEBUGFSDIR_MAX_LEN 8 + MODULE_AUTHOR("Johannes Berg"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("wireless configuration support"); @@ -1042,6 +1045,18 @@ int wiphy_register(struct wiphy *wiphy) /* add to debugfs */ rdev->wiphy.debugfsdir = debugfs_create_dir(wiphy_name(&rdev->wiphy), ieee80211_debugfs_dir); + if (wiphy->n_radio > 0) { + int idx; + char radio_name[RADIO_DEBUGFSDIR_MAX_LEN]; + + for (idx = 0; idx < wiphy->n_radio; idx++) { + scnprintf(radio_name, sizeof(radio_name), "radio%d", + idx); + wiphy->radio_cfg[idx].radio_debugfsdir = + debugfs_create_dir(radio_name, + rdev->wiphy.debugfsdir); + } + } cfg80211_debugfs_rdev_add(rdev); nl80211_notify_wiphy(rdev, NL80211_CMD_NEW_WIPHY); diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c index 40e49074e2ee..f9e7fff1ef25 100644 --- a/net/wireless/debugfs.c +++ b/net/wireless/debugfs.c @@ -29,6 +29,24 @@ static const struct file_operations name## _ops = { \ .llseek = generic_file_llseek, \ } +#define DEBUGFS_RADIO_READONLY_FILE(name, buflen, fmt, value...) \ +static ssize_t name## _read(struct file *file, char __user *userbuf, \ + size_t count, loff_t *ppos) \ +{ \ + struct wiphy_radio_cfg *radio_cfg = file->private_data; \ + char buf[buflen]; \ + int res; \ + \ + res = scnprintf(buf, buflen, fmt "\n", ##value); \ + return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ +} \ + \ +static const struct file_operations name## _ops = { \ + .read = name## _read, \ + .open = simple_open, \ + .llseek = generic_file_llseek, \ +} + DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", wiphy->rts_threshold); DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", @@ -38,6 +56,9 @@ DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d", DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", wiphy->retry_long); +DEBUGFS_RADIO_READONLY_FILE(radio_rts_threshold, 20, "%d", + radio_cfg->rts_threshold); + static int ht_print_chan(struct ieee80211_channel *chan, char *buf, int buf_size, int offset) { @@ -100,15 +121,27 @@ static const struct file_operations ht40allow_map_ops = { #define DEBUGFS_ADD(name) \ debugfs_create_file(#name, 0444, phyd, &rdev->wiphy, &name## _ops) +#define DEBUGFS_RADIO_ADD(name, radio_idx) \ + debugfs_create_file(#name, 0444, radiod, \ + &rdev->wiphy.radio_cfg[radio_idx], \ + &name## _ops) + void cfg80211_debugfs_rdev_add(struct cfg80211_registered_device *rdev) { struct dentry *phyd = rdev->wiphy.debugfsdir; + struct dentry *radiod; + u8 i; DEBUGFS_ADD(rts_threshold); DEBUGFS_ADD(fragmentation_threshold); DEBUGFS_ADD(short_retry_limit); DEBUGFS_ADD(long_retry_limit); DEBUGFS_ADD(ht40allow_map); + + for (i = 0; i < rdev->wiphy.n_radio; i++) { + radiod = rdev->wiphy.radio_cfg[i].radio_debugfsdir; + DEBUGFS_RADIO_ADD(radio_rts_threshold, i); + } } struct debugfs_read_work { diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 346dfd2bd987..ceca47cd9e25 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3544,6 +3544,9 @@ static int _nl80211_parse_chandef(struct cfg80211_registered_device *rdev, return -EINVAL; } + if (cfg80211_chandef_is_s1g(chandef)) + chandef->width = NL80211_CHAN_WIDTH_1; + if (attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { enum nl80211_channel_type chantype; diff --git a/net/wireless/util.c b/net/wireless/util.c index 56724b33af04..97f40c6d1e9d 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -2942,9 +2942,8 @@ cfg80211_get_iftype_ext_capa(struct wiphy *wiphy, enum nl80211_iftype type) } EXPORT_SYMBOL(cfg80211_get_iftype_ext_capa); -static bool -ieee80211_radio_freq_range_valid(const struct wiphy_radio *radio, - u32 freq, u32 width) +bool ieee80211_radio_freq_range_valid(const struct wiphy_radio *radio, + u32 freq, u32 width) { const struct wiphy_radio_freq_range *r; int i; @@ -2958,6 +2957,7 @@ ieee80211_radio_freq_range_valid(const struct wiphy_radio *radio, return false; } +EXPORT_SYMBOL(ieee80211_radio_freq_range_valid); bool cfg80211_radio_chandef_valid(const struct wiphy_radio *radio, const struct cfg80211_chan_def *chandef) |
