Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'mac80211-next-for-net-next-2021-01-27' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next

Johannes Berg says:

====================
More updates:
* many minstrel improvements, including removal of the old
minstrel in favour of minstrel_ht
* speed improvements on FQ
* support for RX decapsulation (header conversion) offload
* RTNL reduction: limit RTNL usage in the wireless stack
mostly to where really needed (regulatory not yet) to
reduce contention on it

* tag 'mac80211-next-for-net-next-2021-01-27' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next: (24 commits)
mac80211: minstrel_ht: fix regression in the max_prob_rate fix
virt_wifi: fix deadlock on RTNL
cfg80211: avoid holding the RTNL when calling the driver
cfg80211: change netdev registration/unregistration semantics
mac80211: minstrel_ht: fix rounding error in throughput calculation
mac80211: minstrel_ht: increase stats update interval
mac80211: minstrel_ht: fix max probability rate selection
mac80211: minstrel_ht: improve sample rate selection
mac80211: minstrel_ht: improve ampdu length estimation
mac80211: minstrel_ht: remove old ewma based rate average code
mac80211: remove legacy minstrel rate control
mac80211: minstrel_ht: add support for OFDM rates on non-HT clients
mac80211: minstrel_ht: clean up CCK code
mac80211: introduce aql_enable node in debugfs
cfg80211: Add phyrate conversion support for extended MCS in 60GHz band
cfg80211: add VHT rate entries for MCS-10 and MCS-11
mac80211: reduce peer HE MCS/NSS to own capabilities
mac80211: remove NSS number of 160MHz if not support 160MHz for HE
mac80211_hwsim: add 6GHz channels
mac80211: add LDPC encoding to ieee80211_parse_tx_radiotap
...
====================

Link: https://lore.kernel.org/r/20210127210915.135550-1-johannes@sipsolutions.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+2103 -1940
+3 -1
drivers/net/wireless/ath/ath11k/reg.c
··· 247 247 } 248 248 249 249 rtnl_lock(); 250 - ret = regulatory_set_wiphy_regd_sync_rtnl(ar->hw->wiphy, regd_copy); 250 + wiphy_lock(ar->hw->wiphy); 251 + ret = regulatory_set_wiphy_regd_sync(ar->hw->wiphy, regd_copy); 252 + wiphy_unlock(ar->hw->wiphy); 251 253 rtnl_unlock(); 252 254 253 255 kfree(regd_copy);
+2 -2
drivers/net/wireless/ath/ath6kl/cfg80211.c
··· 3648 3648 kfree(mc_filter); 3649 3649 } 3650 3650 3651 - unregister_netdevice(vif->ndev); 3651 + cfg80211_unregister_netdevice(vif->ndev); 3652 3652 3653 3653 ar->num_vif--; 3654 3654 } ··· 3821 3821 3822 3822 netdev_set_default_ethtool_ops(ndev, &ath6kl_ethtool_ops); 3823 3823 3824 - if (register_netdevice(ndev)) 3824 + if (cfg80211_register_netdevice(ndev)) 3825 3825 goto err; 3826 3826 3827 3827 ar->avail_idx_map &= ~BIT(fw_vif_idx);
+2
drivers/net/wireless/ath/ath6kl/core.c
··· 212 212 ar->avail_idx_map |= BIT(i); 213 213 214 214 rtnl_lock(); 215 + wiphy_lock(ar->wiphy); 215 216 216 217 /* Add an initial station interface */ 217 218 wdev = ath6kl_interface_add(ar, "wlan%d", NET_NAME_ENUM, 218 219 NL80211_IFTYPE_STATION, 0, INFRA_NETWORK); 219 220 221 + wiphy_unlock(ar->wiphy); 220 222 rtnl_unlock(); 221 223 222 224 if (!wdev) {
+2
drivers/net/wireless/ath/ath6kl/init.c
··· 1904 1904 spin_unlock_bh(&ar->list_lock); 1905 1905 ath6kl_cfg80211_vif_stop(vif, test_bit(WMI_READY, &ar->flag)); 1906 1906 rtnl_lock(); 1907 + wiphy_lock(ar->wiphy); 1907 1908 ath6kl_cfg80211_vif_cleanup(vif); 1909 + wiphy_unlock(ar->wiphy); 1908 1910 rtnl_unlock(); 1909 1911 spin_lock_bh(&ar->list_lock); 1910 1912 }
+2
drivers/net/wireless/ath/wil6210/cfg80211.c
··· 2820 2820 wil->radio_wdev = wil->main_ndev->ieee80211_ptr; 2821 2821 mutex_unlock(&wil->vif_mutex); 2822 2822 if (p2p_wdev) { 2823 + wiphy_lock(wil->wiphy); 2823 2824 cfg80211_unregister_wdev(p2p_wdev); 2825 + wiphy_unlock(wil->wiphy); 2824 2826 kfree(p2p_wdev); 2825 2827 } 2826 2828 }
+8 -3
drivers/net/wireless/ath/wil6210/netdev.c
··· 424 424 if (rc) 425 425 return rc; 426 426 } 427 - rc = register_netdevice(ndev); 427 + rc = cfg80211_register_netdevice(ndev); 428 428 if (rc < 0) { 429 429 dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); 430 430 if (any_active && vif->mid != 0) ··· 473 473 wil_update_net_queues_bh(wil, vif, NULL, true); 474 474 475 475 rtnl_lock(); 476 + wiphy_lock(wiphy); 476 477 rc = wil_vif_add(wil, vif); 478 + wiphy_unlock(wiphy); 477 479 rtnl_unlock(); 478 480 if (rc < 0) 479 481 goto out_wiphy; ··· 513 511 /* during unregister_netdevice cfg80211_leave may perform operations 514 512 * such as stop AP, disconnect, so we only clear the VIF afterwards 515 513 */ 516 - unregister_netdevice(ndev); 514 + cfg80211_unregister_netdevice(ndev); 517 515 518 516 if (any_active && vif->mid != 0) 519 517 wmi_port_delete(wil, vif->mid); ··· 545 543 { 546 544 struct net_device *ndev = wil->main_ndev; 547 545 struct wireless_dev *wdev = ndev->ieee80211_ptr; 546 + struct wiphy *wiphy = wdev->wiphy; 548 547 549 548 wil_dbg_misc(wil, "if_remove\n"); 550 549 551 550 rtnl_lock(); 551 + wiphy_lock(wiphy); 552 552 wil_vif_remove(wil, 0); 553 + wiphy_unlock(wiphy); 553 554 rtnl_unlock(); 554 555 555 556 netif_napi_del(&wil->napi_tx); 556 557 netif_napi_del(&wil->napi_rx); 557 558 558 - wiphy_unregister(wdev->wiphy); 559 + wiphy_unregister(wiphy); 559 560 }
+2
drivers/net/wireless/ath/wil6210/pcie_bus.c
··· 473 473 474 474 wil6210_debugfs_remove(wil); 475 475 rtnl_lock(); 476 + wiphy_lock(wil->wiphy); 476 477 wil_p2p_wdev_free(wil); 477 478 wil_remove_all_additional_vifs(wil); 479 + wiphy_unlock(wil->wiphy); 478 480 rtnl_unlock(); 479 481 wil_if_remove(wil); 480 482 wil_if_pcie_disable(wil);
+12 -12
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
··· 633 633 .ndo_set_rx_mode = brcmf_netdev_set_multicast_list 634 634 }; 635 635 636 - int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked) 636 + int brcmf_net_attach(struct brcmf_if *ifp, bool locked) 637 637 { 638 638 struct brcmf_pub *drvr = ifp->drvr; 639 639 struct net_device *ndev; ··· 656 656 INIT_WORK(&ifp->multicast_work, _brcmf_set_multicast_list); 657 657 INIT_WORK(&ifp->ndoffload_work, _brcmf_update_ndtable); 658 658 659 - if (rtnl_locked) 660 - err = register_netdevice(ndev); 659 + if (locked) 660 + err = cfg80211_register_netdevice(ndev); 661 661 else 662 662 err = register_netdev(ndev); 663 663 if (err != 0) { ··· 677 677 return -EBADE; 678 678 } 679 679 680 - void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked) 680 + void brcmf_net_detach(struct net_device *ndev, bool locked) 681 681 { 682 682 if (ndev->reg_state == NETREG_REGISTERED) { 683 - if (rtnl_locked) 684 - unregister_netdevice(ndev); 683 + if (locked) 684 + cfg80211_unregister_netdevice(ndev); 685 685 else 686 686 unregister_netdev(ndev); 687 687 } else { ··· 758 758 ndev = ifp->ndev; 759 759 ndev->netdev_ops = &brcmf_netdev_ops_mon; 760 760 761 - err = register_netdevice(ndev); 761 + err = cfg80211_register_netdevice(ndev); 762 762 if (err) 763 763 bphy_err(drvr, "Failed to register %s device\n", ndev->name); 764 764 ··· 909 909 } 910 910 911 911 static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx, 912 - bool rtnl_locked) 912 + bool locked) 913 913 { 914 914 struct brcmf_if *ifp; 915 915 int ifidx; ··· 938 938 cancel_work_sync(&ifp->multicast_work); 939 939 cancel_work_sync(&ifp->ndoffload_work); 940 940 } 941 - brcmf_net_detach(ifp->ndev, rtnl_locked); 941 + brcmf_net_detach(ifp->ndev, locked); 942 942 } else { 943 943 /* Only p2p device interfaces which get dynamically created 944 944 * end up here. In this case the p2p module should be informed ··· 947 947 * serious troublesome side effects. The p2p module will clean 948 948 * up the ifp if needed. 949 949 */ 950 - brcmf_p2p_ifp_removed(ifp, rtnl_locked); 950 + brcmf_p2p_ifp_removed(ifp, locked); 951 951 kfree(ifp); 952 952 } 953 953 ··· 956 956 drvr->if2bss[ifidx] = BRCMF_BSSIDX_INVALID; 957 957 } 958 958 959 - void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked) 959 + void brcmf_remove_interface(struct brcmf_if *ifp, bool locked) 960 960 { 961 961 if (!ifp || WARN_ON(ifp->drvr->iflist[ifp->bsscfgidx] != ifp)) 962 962 return; 963 963 brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", ifp->bsscfgidx, 964 964 ifp->ifidx); 965 965 brcmf_proto_del_if(ifp->drvr, ifp); 966 - brcmf_del_if(ifp->drvr, ifp->bsscfgidx, rtnl_locked); 966 + brcmf_del_if(ifp->drvr, ifp->bsscfgidx, locked); 967 967 } 968 968 969 969 static int brcmf_psm_watchdog_notify(struct brcmf_if *ifp,
+3 -3
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
··· 201 201 char *brcmf_ifname(struct brcmf_if *ifp); 202 202 struct brcmf_if *brcmf_get_ifp(struct brcmf_pub *drvr, int ifidx); 203 203 void brcmf_configure_arp_nd_offload(struct brcmf_if *ifp, bool enable); 204 - int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked); 204 + int brcmf_net_attach(struct brcmf_if *ifp, bool locked); 205 205 struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bsscfgidx, s32 ifidx, 206 206 bool is_p2pdev, const char *name, u8 *mac_addr); 207 - void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked); 207 + void brcmf_remove_interface(struct brcmf_if *ifp, bool locked); 208 208 void brcmf_txflowblock_if(struct brcmf_if *ifp, 209 209 enum brcmf_netif_stop_reason reason, bool state); 210 210 void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success); 211 211 void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb, bool inirq); 212 212 void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb); 213 - void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked); 213 + void brcmf_net_detach(struct net_device *ndev, bool locked); 214 214 int brcmf_net_mon_attach(struct brcmf_if *ifp); 215 215 void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); 216 216 int __init brcmf_core_init(void);
+8 -4
drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c
··· 2430 2430 return err; 2431 2431 } 2432 2432 2433 - void brcmf_p2p_ifp_removed(struct brcmf_if *ifp, bool rtnl_locked) 2433 + void brcmf_p2p_ifp_removed(struct brcmf_if *ifp, bool locked) 2434 2434 { 2435 2435 struct brcmf_cfg80211_info *cfg; 2436 2436 struct brcmf_cfg80211_vif *vif; ··· 2439 2439 vif = ifp->vif; 2440 2440 cfg = wdev_to_cfg(&vif->wdev); 2441 2441 cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; 2442 - if (!rtnl_locked) 2442 + if (locked) { 2443 2443 rtnl_lock(); 2444 - cfg80211_unregister_wdev(&vif->wdev); 2445 - if (!rtnl_locked) 2444 + wiphy_lock(cfg->wiphy); 2445 + cfg80211_unregister_wdev(&vif->wdev); 2446 + wiphy_unlock(cfg->wiphy); 2446 2447 rtnl_unlock(); 2448 + } else { 2449 + cfg80211_unregister_wdev(&vif->wdev); 2450 + } 2447 2451 brcmf_free_vif(vif); 2448 2452 } 2449 2453
+1 -1
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
··· 2143 2143 2144 2144 out_iterate: 2145 2145 if (!test) 2146 - ieee80211_iterate_active_interfaces_rtnl(mvm->hw, 2146 + ieee80211_iterate_active_interfaces_mtx(mvm->hw, 2147 2147 IEEE80211_IFACE_ITER_NORMAL, 2148 2148 iwl_mvm_d3_disconnect_iter, keep ? vif : NULL); 2149 2149
+2 -2
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
··· 260 260 int ret; 261 261 bool changed; 262 262 const struct ieee80211_regdomain *r = 263 - rtnl_dereference(mvm->hw->wiphy->regd); 263 + wiphy_dereference(mvm->hw->wiphy, mvm->hw->wiphy->regd); 264 264 265 265 if (!r) 266 266 return -ENOENT; ··· 282 282 283 283 /* update cfg80211 if the regdomain was changed */ 284 284 if (changed) 285 - ret = regulatory_set_wiphy_regd_sync_rtnl(mvm->hw->wiphy, regd); 285 + ret = regulatory_set_wiphy_regd_sync(mvm->hw->wiphy, regd); 286 286 else 287 287 ret = 0; 288 288
+1 -1
drivers/net/wireless/intel/iwlwifi/mvm/nvm.c
··· 545 545 return -EIO; 546 546 } 547 547 548 - retval = regulatory_set_wiphy_regd_sync_rtnl(mvm->hw->wiphy, regd); 548 + retval = regulatory_set_wiphy_regd_sync(mvm->hw->wiphy, regd); 549 549 kfree(regd); 550 550 return retval; 551 551 }
+73 -1
drivers/net/wireless/mac80211_hwsim.c
··· 311 311 .hw_value = (_freq), \ 312 312 } 313 313 314 + #define CHAN6G(_freq) { \ 315 + .band = NL80211_BAND_6GHZ, \ 316 + .center_freq = (_freq), \ 317 + .hw_value = (_freq), \ 318 + } 319 + 314 320 static const struct ieee80211_channel hwsim_channels_2ghz[] = { 315 321 CHAN2G(2412), /* Channel 1 */ 316 322 CHAN2G(2417), /* Channel 2 */ ··· 381 375 CHAN5G(5915), /* Channel 183 */ 382 376 CHAN5G(5920), /* Channel 184 */ 383 377 CHAN5G(5925), /* Channel 185 */ 378 + }; 379 + 380 + static const struct ieee80211_channel hwsim_channels_6ghz[] = { 381 + CHAN6G(5955), /* Channel 1 */ 382 + CHAN6G(5975), /* Channel 5 */ 383 + CHAN6G(5995), /* Channel 9 */ 384 + CHAN6G(6015), /* Channel 13 */ 385 + CHAN6G(6035), /* Channel 17 */ 386 + CHAN6G(6055), /* Channel 21 */ 387 + CHAN6G(6075), /* Channel 25 */ 388 + CHAN6G(6095), /* Channel 29 */ 389 + CHAN6G(6115), /* Channel 33 */ 390 + CHAN6G(6135), /* Channel 37 */ 391 + CHAN6G(6155), /* Channel 41 */ 392 + CHAN6G(6175), /* Channel 45 */ 393 + CHAN6G(6195), /* Channel 49 */ 394 + CHAN6G(6215), /* Channel 53 */ 395 + CHAN6G(6235), /* Channel 57 */ 396 + CHAN6G(6255), /* Channel 61 */ 397 + CHAN6G(6275), /* Channel 65 */ 398 + CHAN6G(6295), /* Channel 69 */ 399 + CHAN6G(6315), /* Channel 73 */ 400 + CHAN6G(6335), /* Channel 77 */ 401 + CHAN6G(6355), /* Channel 81 */ 402 + CHAN6G(6375), /* Channel 85 */ 403 + CHAN6G(6395), /* Channel 89 */ 404 + CHAN6G(6415), /* Channel 93 */ 405 + CHAN6G(6435), /* Channel 97 */ 406 + CHAN6G(6455), /* Channel 181 */ 407 + CHAN6G(6475), /* Channel 105 */ 408 + CHAN6G(6495), /* Channel 109 */ 409 + CHAN6G(6515), /* Channel 113 */ 410 + CHAN6G(6535), /* Channel 117 */ 411 + CHAN6G(6555), /* Channel 121 */ 412 + CHAN6G(6575), /* Channel 125 */ 413 + CHAN6G(6595), /* Channel 129 */ 414 + CHAN6G(6615), /* Channel 133 */ 415 + CHAN6G(6635), /* Channel 137 */ 416 + CHAN6G(6655), /* Channel 141 */ 417 + CHAN6G(6675), /* Channel 145 */ 418 + CHAN6G(6695), /* Channel 149 */ 419 + CHAN6G(6715), /* Channel 153 */ 420 + CHAN6G(6735), /* Channel 157 */ 421 + CHAN6G(6755), /* Channel 161 */ 422 + CHAN6G(6775), /* Channel 165 */ 423 + CHAN6G(6795), /* Channel 169 */ 424 + CHAN6G(6815), /* Channel 173 */ 425 + CHAN6G(6835), /* Channel 177 */ 426 + CHAN6G(6855), /* Channel 181 */ 427 + CHAN6G(6875), /* Channel 185 */ 428 + CHAN6G(6895), /* Channel 189 */ 429 + CHAN6G(6915), /* Channel 193 */ 430 + CHAN6G(6935), /* Channel 197 */ 431 + CHAN6G(6955), /* Channel 201 */ 432 + CHAN6G(6975), /* Channel 205 */ 433 + CHAN6G(6995), /* Channel 209 */ 434 + CHAN6G(7015), /* Channel 213 */ 435 + CHAN6G(7035), /* Channel 217 */ 436 + CHAN6G(7055), /* Channel 221 */ 437 + CHAN6G(7075), /* Channel 225 */ 438 + CHAN6G(7095), /* Channel 229 */ 439 + CHAN6G(7115), /* Channel 233 */ 384 440 }; 385 441 386 442 #define NUM_S1G_CHANS_US 51 ··· 616 548 struct ieee80211_supported_band bands[NUM_NL80211_BANDS]; 617 549 struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)]; 618 550 struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; 551 + struct ieee80211_channel channels_6ghz[ARRAY_SIZE(hwsim_channels_6ghz)]; 619 552 struct ieee80211_channel channels_s1g[ARRAY_SIZE(hwsim_channels_s1g)]; 620 553 struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; 621 554 struct ieee80211_iface_combination if_combination; ··· 647 578 struct ieee80211_channel *channel; 648 579 unsigned long next_start, start, end; 649 580 } survey_data[ARRAY_SIZE(hwsim_channels_2ghz) + 650 - ARRAY_SIZE(hwsim_channels_5ghz)]; 581 + ARRAY_SIZE(hwsim_channels_5ghz) + 582 + ARRAY_SIZE(hwsim_channels_6ghz)]; 651 583 652 584 struct ieee80211_channel *channel; 653 585 u64 beacon_int /* beacon interval in us */; ··· 3219 3149 sizeof(hwsim_channels_2ghz)); 3220 3150 memcpy(data->channels_5ghz, hwsim_channels_5ghz, 3221 3151 sizeof(hwsim_channels_5ghz)); 3152 + memcpy(data->channels_6ghz, hwsim_channels_6ghz, 3153 + sizeof(hwsim_channels_6ghz)); 3222 3154 memcpy(data->channels_s1g, hwsim_channels_s1g, 3223 3155 sizeof(hwsim_channels_s1g)); 3224 3156 memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates));
+5 -5
drivers/net/wireless/marvell/mwifiex/cfg80211.c
··· 2097 2097 struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); 2098 2098 2099 2099 if (!mwifiex_stop_bg_scan(priv)) 2100 - cfg80211_sched_scan_stopped_rtnl(priv->wdev.wiphy, 0); 2100 + cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0); 2101 2101 2102 2102 if (mwifiex_deauthenticate(priv, NULL)) 2103 2103 return -EFAULT; ··· 2366 2366 (int)sme->ssid_len, (char *)sme->ssid, sme->bssid); 2367 2367 2368 2368 if (!mwifiex_stop_bg_scan(priv)) 2369 - cfg80211_sched_scan_stopped_rtnl(priv->wdev.wiphy, 0); 2369 + cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0); 2370 2370 2371 2371 ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, 2372 2372 priv->bss_mode, sme->channel, sme, 0); ··· 2576 2576 priv->scan_block = false; 2577 2577 2578 2578 if (!mwifiex_stop_bg_scan(priv)) 2579 - cfg80211_sched_scan_stopped_rtnl(priv->wdev.wiphy, 0); 2579 + cfg80211_sched_scan_stopped_locked(priv->wdev.wiphy, 0); 2580 2580 2581 2581 user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL); 2582 2582 if (!user_scan_cfg) ··· 3081 3081 mutex_init(&priv->async_mutex); 3082 3082 3083 3083 /* Register network device */ 3084 - if (register_netdevice(dev)) { 3084 + if (cfg80211_register_netdevice(dev)) { 3085 3085 mwifiex_dbg(adapter, ERROR, "cannot register network device\n"); 3086 3086 ret = -EFAULT; 3087 3087 goto err_reg_netdev; ··· 3160 3160 netif_carrier_off(priv->netdev); 3161 3161 3162 3162 if (wdev->netdev->reg_state == NETREG_REGISTERED) 3163 - unregister_netdevice(wdev->netdev); 3163 + cfg80211_unregister_netdevice(wdev->netdev); 3164 3164 3165 3165 if (priv->dfs_cac_workqueue) { 3166 3166 flush_workqueue(priv->dfs_cac_workqueue);
+7
drivers/net/wireless/marvell/mwifiex/main.c
··· 598 598 } 599 599 600 600 rtnl_lock(); 601 + wiphy_lock(adapter->wiphy); 601 602 /* Create station interface by default */ 602 603 wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", NET_NAME_ENUM, 603 604 NL80211_IFTYPE_STATION, NULL); 604 605 if (IS_ERR(wdev)) { 605 606 mwifiex_dbg(adapter, ERROR, 606 607 "cannot create default STA interface\n"); 608 + wiphy_unlock(adapter->wiphy); 607 609 rtnl_unlock(); 608 610 goto err_add_intf; 609 611 } ··· 616 614 if (IS_ERR(wdev)) { 617 615 mwifiex_dbg(adapter, ERROR, 618 616 "cannot create AP interface\n"); 617 + wiphy_unlock(adapter->wiphy); 619 618 rtnl_unlock(); 620 619 goto err_add_intf; 621 620 } ··· 628 625 if (IS_ERR(wdev)) { 629 626 mwifiex_dbg(adapter, ERROR, 630 627 "cannot create p2p client interface\n"); 628 + wiphy_unlock(adapter->wiphy); 631 629 rtnl_unlock(); 632 630 goto err_add_intf; 633 631 } 634 632 } 633 + wiphy_unlock(adapter->wiphy); 635 634 rtnl_unlock(); 636 635 637 636 mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); ··· 1445 1440 if (!priv) 1446 1441 continue; 1447 1442 rtnl_lock(); 1443 + wiphy_lock(adapter->wiphy); 1448 1444 if (priv->netdev && 1449 1445 priv->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED) 1450 1446 mwifiex_del_virtual_intf(adapter->wiphy, &priv->wdev); 1447 + wiphy_unlock(adapter->wiphy); 1451 1448 rtnl_unlock(); 1452 1449 } 1453 1450
+1 -1
drivers/net/wireless/microchip/wilc1000/cfg80211.c
··· 1538 1538 wilc_wfi_deinit_mon_interface(wl, true); 1539 1539 vif = netdev_priv(wdev->netdev); 1540 1540 cfg80211_stop_iface(wiphy, wdev, GFP_KERNEL); 1541 - unregister_netdevice(vif->ndev); 1541 + cfg80211_unregister_netdevice(vif->ndev); 1542 1542 vif->monitor_flag = 0; 1543 1543 1544 1544 wilc_set_operation_mode(vif, 0, 0, 0);
+2 -2
drivers/net/wireless/microchip/wilc1000/mon.c
··· 233 233 wl->monitor_dev->netdev_ops = &wilc_wfi_netdev_ops; 234 234 wl->monitor_dev->needs_free_netdev = true; 235 235 236 - if (register_netdevice(wl->monitor_dev)) { 236 + if (cfg80211_register_netdevice(wl->monitor_dev)) { 237 237 netdev_err(real_dev, "register_netdevice failed\n"); 238 238 free_netdev(wl->monitor_dev); 239 239 return NULL; ··· 251 251 return; 252 252 253 253 if (rtnl_locked) 254 - unregister_netdevice(wl->monitor_dev); 254 + cfg80211_unregister_netdevice(wl->monitor_dev); 255 255 else 256 256 unregister_netdev(wl->monitor_dev); 257 257 wl->monitor_dev = NULL;
+1 -1
drivers/net/wireless/microchip/wilc1000/netdev.c
··· 950 950 vif->priv.dev = ndev; 951 951 952 952 if (rtnl_locked) 953 - ret = register_netdevice(ndev); 953 + ret = cfg80211_register_netdevice(ndev); 954 954 else 955 955 ret = register_netdev(ndev); 956 956
+2 -2
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
··· 180 180 cancel_work_sync(&vif->high_pri_tx_work); 181 181 182 182 if (netdev->reg_state == NETREG_REGISTERED) 183 - unregister_netdevice(netdev); 183 + cfg80211_unregister_netdevice(netdev); 184 184 185 185 if (qtnf_cmd_send_del_intf(vif)) 186 186 pr_err("VIF%u.%u: failed to delete VIF\n", vif->mac->macid, ··· 267 267 if (qtnf_hwcap_is_set(&mac->bus->hw_info, QLINK_HW_CAPAB_HW_BRIDGE)) { 268 268 ret = qtnf_cmd_netdev_changeupper(vif, vif->netdev->ifindex); 269 269 if (ret) { 270 - unregister_netdevice(vif->netdev); 270 + cfg80211_unregister_netdevice(vif->netdev); 271 271 vif->netdev = NULL; 272 272 goto error_del_vif; 273 273 }
+3 -2
drivers/net/wireless/quantenna/qtnfmac/core.c
··· 492 492 493 493 SET_NETDEV_DEV(dev, wiphy_dev(wiphy)); 494 494 495 - ret = register_netdevice(dev); 495 + ret = cfg80211_register_netdevice(dev); 496 496 if (ret) { 497 497 free_netdev(dev); 498 498 vif->netdev = NULL; ··· 611 611 mac->wiphy_registered = 1; 612 612 613 613 rtnl_lock(); 614 - 614 + wiphy_lock(priv_to_wiphy(mac)); 615 615 ret = qtnf_core_net_attach(mac, vif, "wlan%d", NET_NAME_ENUM); 616 + wiphy_unlock(priv_to_wiphy(mac)); 616 617 rtnl_unlock(); 617 618 618 619 if (ret) {
+123 -23
include/net/cfg80211.h
··· 1460 1460 * @RATE_INFO_FLAGS_DMG: 60GHz MCS 1461 1461 * @RATE_INFO_FLAGS_HE_MCS: HE MCS information 1462 1462 * @RATE_INFO_FLAGS_EDMG: 60GHz MCS in EDMG mode 1463 + * @RATE_INFO_FLAGS_EXTENDED_SC_DMG: 60GHz extended SC MCS 1463 1464 */ 1464 1465 enum rate_info_flags { 1465 1466 RATE_INFO_FLAGS_MCS = BIT(0), ··· 1469 1468 RATE_INFO_FLAGS_DMG = BIT(3), 1470 1469 RATE_INFO_FLAGS_HE_MCS = BIT(4), 1471 1470 RATE_INFO_FLAGS_EDMG = BIT(5), 1471 + RATE_INFO_FLAGS_EXTENDED_SC_DMG = BIT(6), 1472 1472 }; 1473 1473 1474 1474 /** ··· 3632 3630 * All callbacks except where otherwise noted should return 0 3633 3631 * on success or a negative error code. 3634 3632 * 3635 - * All operations are currently invoked under rtnl for consistency with the 3636 - * wireless extensions but this is subject to reevaluation as soon as this 3637 - * code is used more widely and we have a first user without wext. 3633 + * All operations are invoked with the wiphy mutex held. The RTNL may be 3634 + * held in addition (due to wireless extensions) but this cannot be relied 3635 + * upon except in cases where documented below. Note that due to ordering, 3636 + * the RTNL also cannot be acquired in any handlers. 3638 3637 * 3639 3638 * @suspend: wiphy device needs to be suspended. The variable @wow will 3640 3639 * be %NULL or contain the enabled Wake-on-Wireless triggers that are ··· 3650 3647 * the new netdev in the wiphy's network namespace! Returns the struct 3651 3648 * wireless_dev, or an ERR_PTR. For P2P device wdevs, the driver must 3652 3649 * also set the address member in the wdev. 3650 + * This additionally holds the RTNL to be able to do netdev changes. 3653 3651 * 3654 3652 * @del_virtual_intf: remove the virtual interface 3653 + * This additionally holds the RTNL to be able to do netdev changes. 3655 3654 * 3656 3655 * @change_virtual_intf: change type/configuration of virtual interface, 3657 3656 * keep the struct wireless_dev's iftype updated. 3657 + * This additionally holds the RTNL to be able to do netdev changes. 3658 3658 * 3659 3659 * @add_key: add a key with the given parameters. @mac_addr will be %NULL 3660 3660 * when adding a group key. ··· 4747 4741 4748 4742 /** 4749 4743 * struct wiphy - wireless hardware description 4744 + * @mtx: mutex for the data (structures) of this device 4750 4745 * @reg_notifier: the driver's regulatory notification callback, 4751 4746 * note that if your driver uses wiphy_apply_custom_regulatory() 4752 4747 * the reg_notifier's request can be passed as NULL ··· 4941 4934 * @sar_capa: SAR control capabilities 4942 4935 */ 4943 4936 struct wiphy { 4937 + struct mutex mtx; 4938 + 4944 4939 /* assign these fields before you register the wiphy */ 4945 4940 4946 4941 u8 perm_addr[ETH_ALEN]; ··· 5195 5186 */ 5196 5187 int wiphy_register(struct wiphy *wiphy); 5197 5188 5189 + /* this is a define for better error reporting (file/line) */ 5190 + #define lockdep_assert_wiphy(wiphy) lockdep_assert_held(&(wiphy)->mtx) 5191 + 5192 + /** 5193 + * rcu_dereference_wiphy - rcu_dereference with debug checking 5194 + * @wiphy: the wiphy to check the locking on 5195 + * @p: The pointer to read, prior to dereferencing 5196 + * 5197 + * Do an rcu_dereference(p), but check caller either holds rcu_read_lock() 5198 + * or RTNL. Note: Please prefer wiphy_dereference() or rcu_dereference(). 5199 + */ 5200 + #define rcu_dereference_wiphy(wiphy, p) \ 5201 + rcu_dereference_check(p, lockdep_is_held(&wiphy->mtx)) 5202 + 5203 + /** 5204 + * wiphy_dereference - fetch RCU pointer when updates are prevented by wiphy mtx 5205 + * @wiphy: the wiphy to check the locking on 5206 + * @p: The pointer to read, prior to dereferencing 5207 + * 5208 + * Return the value of the specified RCU-protected pointer, but omit the 5209 + * READ_ONCE(), because caller holds the wiphy mutex used for updates. 5210 + */ 5211 + #define wiphy_dereference(wiphy, p) \ 5212 + rcu_dereference_protected(p, lockdep_is_held(&wiphy->mtx)) 5213 + 5214 + /** 5215 + * get_wiphy_regdom - get custom regdomain for the given wiphy 5216 + * @wiphy: the wiphy to get the regdomain from 5217 + */ 5218 + const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy); 5219 + 5198 5220 /** 5199 5221 * wiphy_unregister - deregister a wiphy from cfg80211 5200 5222 * ··· 5251 5211 struct cfg80211_cqm_config; 5252 5212 5253 5213 /** 5214 + * wiphy_lock - lock the wiphy 5215 + * @wiphy: the wiphy to lock 5216 + * 5217 + * This is mostly exposed so it can be done around registering and 5218 + * unregistering netdevs that aren't created through cfg80211 calls, 5219 + * since that requires locking in cfg80211 when the notifiers is 5220 + * called, but that cannot differentiate which way it's called. 5221 + * 5222 + * When cfg80211 ops are called, the wiphy is already locked. 5223 + */ 5224 + static inline void wiphy_lock(struct wiphy *wiphy) 5225 + __acquires(&wiphy->mtx) 5226 + { 5227 + mutex_lock(&wiphy->mtx); 5228 + __acquire(&wiphy->mtx); 5229 + } 5230 + 5231 + /** 5232 + * wiphy_unlock - unlock the wiphy again 5233 + * @wiphy: the wiphy to unlock 5234 + */ 5235 + static inline void wiphy_unlock(struct wiphy *wiphy) 5236 + __releases(&wiphy->mtx) 5237 + { 5238 + __release(&wiphy->mtx); 5239 + mutex_unlock(&wiphy->mtx); 5240 + } 5241 + 5242 + /** 5254 5243 * struct wireless_dev - wireless device state 5255 5244 * 5256 5245 * For netdevs, this structure must be allocated by the driver 5257 5246 * that uses the ieee80211_ptr field in struct net_device (this 5258 5247 * is intentional so it can be allocated along with the netdev.) 5259 5248 * It need not be registered then as netdev registration will 5260 - * be intercepted by cfg80211 to see the new wireless device. 5249 + * be intercepted by cfg80211 to see the new wireless device, 5250 + * however, drivers must lock the wiphy before registering or 5251 + * unregistering netdevs if they pre-create any netdevs (in ops 5252 + * called from cfg80211, the wiphy is already locked.) 5261 5253 * 5262 5254 * For non-netdev uses, it must also be allocated by the driver 5263 5255 * in response to the cfg80211 callbacks that require it, as ··· 5298 5226 * 5299 5227 * @wiphy: pointer to hardware description 5300 5228 * @iftype: interface type 5229 + * @registered: is this wdev already registered with cfg80211 5301 5230 * @list: (private) Used to collect the interfaces 5302 5231 * @netdev: (private) Used to reference back to the netdev, may be %NULL 5303 5232 * @identifier: (private) Identifier used in nl80211 to identify this ··· 5382 5309 5383 5310 struct mutex mtx; 5384 5311 5385 - bool use_4addr, is_running; 5312 + bool use_4addr, is_running, registered; 5386 5313 5387 5314 u8 address[ETH_ALEN] __aligned(sizeof(u16)); 5388 5315 ··· 6051 5978 struct ieee80211_regdomain *rd); 6052 5979 6053 5980 /** 6054 - * regulatory_set_wiphy_regd_sync_rtnl - set regdom for self-managed drivers 5981 + * regulatory_set_wiphy_regd_sync - set regdom for self-managed drivers 6055 5982 * @wiphy: the wireless device we want to process the regulatory domain on 6056 5983 * @rd: the regulatory domain information to use for this wiphy 6057 5984 * 6058 - * This functions requires the RTNL to be held and applies the new regdomain 6059 - * synchronously to this wiphy. For more details see 6060 - * regulatory_set_wiphy_regd(). 5985 + * This functions requires the RTNL and the wiphy mutex to be held and 5986 + * applies the new regdomain synchronously to this wiphy. For more details 5987 + * see regulatory_set_wiphy_regd(). 6061 5988 * 6062 5989 * Return: 0 on success. -EINVAL, -EPERM 6063 5990 */ 6064 - int regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy, 6065 - struct ieee80211_regdomain *rd); 5991 + int regulatory_set_wiphy_regd_sync(struct wiphy *wiphy, 5992 + struct ieee80211_regdomain *rd); 6066 5993 6067 5994 /** 6068 5995 * wiphy_apply_custom_regulatory - apply a custom driver regulatory domain ··· 6180 6107 void cfg80211_sched_scan_stopped(struct wiphy *wiphy, u64 reqid); 6181 6108 6182 6109 /** 6183 - * cfg80211_sched_scan_stopped_rtnl - notify that the scheduled scan has stopped 6110 + * cfg80211_sched_scan_stopped_locked - notify that the scheduled scan has stopped 6184 6111 * 6185 6112 * @wiphy: the wiphy on which the scheduled scan stopped 6186 6113 * @reqid: identifier for the related scheduled scan request ··· 6188 6115 * The driver can call this function to inform cfg80211 that the 6189 6116 * scheduled scan had to be stopped, for whatever reason. The driver 6190 6117 * is then called back via the sched_scan_stop operation when done. 6191 - * This function should be called with rtnl locked. 6118 + * This function should be called with the wiphy mutex held. 6192 6119 */ 6193 - void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy, u64 reqid); 6120 + void cfg80211_sched_scan_stopped_locked(struct wiphy *wiphy, u64 reqid); 6194 6121 6195 6122 /** 6196 6123 * cfg80211_inform_bss_frame_data - inform cfg80211 of a received BSS frame ··· 7627 7554 * also checks if IR-relaxation conditions apply, to allow beaconing under 7628 7555 * more permissive conditions. 7629 7556 * 7630 - * Requires the RTNL to be held. 7557 + * Requires the wiphy mutex to be held. 7631 7558 */ 7632 7559 bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy, 7633 7560 struct cfg80211_chan_def *chandef, ··· 7725 7652 * cfg80211_unregister_wdev - remove the given wdev 7726 7653 * @wdev: struct wireless_dev to remove 7727 7654 * 7728 - * Call this function only for wdevs that have no netdev assigned, 7729 - * e.g. P2P Devices. It removes the device from the list so that 7730 - * it can no longer be used. It is necessary to call this function 7731 - * even when cfg80211 requests the removal of the interface by 7732 - * calling the del_virtual_intf() callback. The function must also 7733 - * be called when the driver wishes to unregister the wdev, e.g. 7734 - * when the device is unbound from the driver. 7655 + * This function removes the device so it can no longer be used. It is necessary 7656 + * to call this function even when cfg80211 requests the removal of the device 7657 + * by calling the del_virtual_intf() callback. The function must also be called 7658 + * when the driver wishes to unregister the wdev, e.g. when the hardware device 7659 + * is unbound from the driver. 7735 7660 * 7736 - * Requires the RTNL to be held. 7661 + * Requires the RTNL and wiphy mutex to be held. 7737 7662 */ 7738 7663 void cfg80211_unregister_wdev(struct wireless_dev *wdev); 7664 + 7665 + /** 7666 + * cfg80211_register_netdevice - register the given netdev 7667 + * @dev: the netdev to register 7668 + * 7669 + * Note: In contexts coming from cfg80211 callbacks, you must call this rather 7670 + * than register_netdevice(), unregister_netdev() is impossible as the RTNL is 7671 + * held. Otherwise, both register_netdevice() and register_netdev() are usable 7672 + * instead as well. 7673 + * 7674 + * Requires the RTNL and wiphy mutex to be held. 7675 + */ 7676 + int cfg80211_register_netdevice(struct net_device *dev); 7677 + 7678 + /** 7679 + * cfg80211_unregister_netdevice - unregister the given netdev 7680 + * @dev: the netdev to register 7681 + * 7682 + * Note: In contexts coming from cfg80211 callbacks, you must call this rather 7683 + * than unregister_netdevice(), unregister_netdev() is impossible as the RTNL 7684 + * is held. Otherwise, both unregister_netdevice() and unregister_netdev() are 7685 + * usable instead as well. 7686 + * 7687 + * Requires the RTNL and wiphy mutex to be held. 7688 + */ 7689 + static inline void cfg80211_unregister_netdevice(struct net_device *dev) 7690 + { 7691 + cfg80211_unregister_wdev(dev->ieee80211_ptr); 7692 + } 7739 7693 7740 7694 /** 7741 7695 * struct cfg80211_ft_event_params - FT Information Elements
+5 -6
include/net/fq.h
··· 19 19 * @flowchain: can be linked to fq_tin's new_flows or old_flows. Used for DRR++ 20 20 * (deficit round robin) based round robin queuing similar to the one 21 21 * found in net/sched/sch_fq_codel.c 22 - * @backlogchain: can be linked to other fq_flow and fq. Used to keep track of 23 - * fat flows and efficient head-dropping if packet limit is reached 24 22 * @queue: sk_buff queue to hold packets 25 23 * @backlog: number of bytes pending in the queue. The number of packets can be 26 24 * found in @queue.qlen ··· 27 29 struct fq_flow { 28 30 struct fq_tin *tin; 29 31 struct list_head flowchain; 30 - struct list_head backlogchain; 31 32 struct sk_buff_head queue; 32 33 u32 backlog; 33 34 int deficit; ··· 44 47 struct fq_tin { 45 48 struct list_head new_flows; 46 49 struct list_head old_flows; 50 + struct list_head tin_list; 51 + struct fq_flow default_flow; 47 52 u32 backlog_bytes; 48 53 u32 backlog_packets; 49 54 u32 overlimit; ··· 58 59 /** 59 60 * struct fq - main container for fair queuing purposes 60 61 * 61 - * @backlogs: linked to fq_flows. Used to maintain fat flows for efficient 62 - * head-dropping when @backlog reaches @limit 63 62 * @limit: max number of packets that can be queued across all flows 64 63 * @backlog: number of packets queued across all flows 65 64 */ 66 65 struct fq { 67 66 struct fq_flow *flows; 68 - struct list_head backlogs; 67 + unsigned long *flows_bitmap; 68 + 69 + struct list_head tin_backlog; 69 70 spinlock_t lock; 70 71 u32 flows_cnt; 71 72 u32 limit;
+115 -62
include/net/fq_impl.h
··· 11 11 12 12 /* functions that are embedded into includer */ 13 13 14 + 15 + static void 16 + __fq_adjust_removal(struct fq *fq, struct fq_flow *flow, unsigned int packets, 17 + unsigned int bytes, unsigned int truesize) 18 + { 19 + struct fq_tin *tin = flow->tin; 20 + int idx; 21 + 22 + tin->backlog_bytes -= bytes; 23 + tin->backlog_packets -= packets; 24 + flow->backlog -= bytes; 25 + fq->backlog -= packets; 26 + fq->memory_usage -= truesize; 27 + 28 + if (flow->backlog) 29 + return; 30 + 31 + if (flow == &tin->default_flow) { 32 + list_del_init(&tin->tin_list); 33 + return; 34 + } 35 + 36 + idx = flow - fq->flows; 37 + __clear_bit(idx, fq->flows_bitmap); 38 + } 39 + 14 40 static void fq_adjust_removal(struct fq *fq, 15 41 struct fq_flow *flow, 16 42 struct sk_buff *skb) 17 43 { 18 - struct fq_tin *tin = flow->tin; 19 - 20 - tin->backlog_bytes -= skb->len; 21 - tin->backlog_packets--; 22 - flow->backlog -= skb->len; 23 - fq->backlog--; 24 - fq->memory_usage -= skb->truesize; 25 - } 26 - 27 - static void fq_rejigger_backlog(struct fq *fq, struct fq_flow *flow) 28 - { 29 - struct fq_flow *i; 30 - 31 - if (flow->backlog == 0) { 32 - list_del_init(&flow->backlogchain); 33 - } else { 34 - i = flow; 35 - 36 - list_for_each_entry_continue(i, &fq->backlogs, backlogchain) 37 - if (i->backlog < flow->backlog) 38 - break; 39 - 40 - list_move_tail(&flow->backlogchain, 41 - &i->backlogchain); 42 - } 44 + __fq_adjust_removal(fq, flow, 1, skb->len, skb->truesize); 43 45 } 44 46 45 47 static struct sk_buff *fq_flow_dequeue(struct fq *fq, ··· 56 54 return NULL; 57 55 58 56 fq_adjust_removal(fq, flow, skb); 59 - fq_rejigger_backlog(fq, flow); 60 57 61 58 return skb; 59 + } 60 + 61 + static int fq_flow_drop(struct fq *fq, struct fq_flow *flow, 62 + fq_skb_free_t free_func) 63 + { 64 + unsigned int packets = 0, bytes = 0, truesize = 0; 65 + struct fq_tin *tin = flow->tin; 66 + struct sk_buff *skb; 67 + int pending; 68 + 69 + lockdep_assert_held(&fq->lock); 70 + 71 + pending = min_t(int, 32, skb_queue_len(&flow->queue) / 2); 72 + do { 73 + skb = __skb_dequeue(&flow->queue); 74 + if (!skb) 75 + break; 76 + 77 + packets++; 78 + bytes += skb->len; 79 + truesize += skb->truesize; 80 + free_func(fq, tin, flow, skb); 81 + } while (packets < pending); 82 + 83 + __fq_adjust_removal(fq, flow, packets, bytes, truesize); 84 + 85 + return packets; 62 86 } 63 87 64 88 static struct sk_buff *fq_tin_dequeue(struct fq *fq, ··· 143 115 144 116 static struct fq_flow *fq_flow_classify(struct fq *fq, 145 117 struct fq_tin *tin, u32 idx, 146 - struct sk_buff *skb, 147 - fq_flow_get_default_t get_default_func) 118 + struct sk_buff *skb) 148 119 { 149 120 struct fq_flow *flow; 150 121 ··· 151 124 152 125 flow = &fq->flows[idx]; 153 126 if (flow->tin && flow->tin != tin) { 154 - flow = get_default_func(fq, tin, idx, skb); 127 + flow = &tin->default_flow; 155 128 tin->collisions++; 156 129 fq->collisions++; 157 130 } ··· 162 135 return flow; 163 136 } 164 137 165 - static void fq_recalc_backlog(struct fq *fq, 166 - struct fq_tin *tin, 167 - struct fq_flow *flow) 138 + static struct fq_flow *fq_find_fattest_flow(struct fq *fq) 168 139 { 169 - struct fq_flow *i; 140 + struct fq_tin *tin; 141 + struct fq_flow *flow = NULL; 142 + u32 len = 0; 143 + int i; 170 144 171 - if (list_empty(&flow->backlogchain)) 172 - list_add_tail(&flow->backlogchain, &fq->backlogs); 145 + for_each_set_bit(i, fq->flows_bitmap, fq->flows_cnt) { 146 + struct fq_flow *cur = &fq->flows[i]; 147 + unsigned int cur_len; 173 148 174 - i = flow; 175 - list_for_each_entry_continue_reverse(i, &fq->backlogs, 176 - backlogchain) 177 - if (i->backlog > flow->backlog) 178 - break; 149 + cur_len = cur->backlog; 150 + if (cur_len <= len) 151 + continue; 179 152 180 - list_move(&flow->backlogchain, &i->backlogchain); 153 + flow = cur; 154 + len = cur_len; 155 + } 156 + 157 + list_for_each_entry(tin, &fq->tin_backlog, tin_list) { 158 + unsigned int cur_len = tin->default_flow.backlog; 159 + 160 + if (cur_len <= len) 161 + continue; 162 + 163 + flow = &tin->default_flow; 164 + len = cur_len; 165 + } 166 + 167 + return flow; 181 168 } 182 169 183 170 static void fq_tin_enqueue(struct fq *fq, 184 171 struct fq_tin *tin, u32 idx, 185 172 struct sk_buff *skb, 186 - fq_skb_free_t free_func, 187 - fq_flow_get_default_t get_default_func) 173 + fq_skb_free_t free_func) 188 174 { 189 175 struct fq_flow *flow; 190 176 bool oom; 191 177 192 178 lockdep_assert_held(&fq->lock); 193 179 194 - flow = fq_flow_classify(fq, tin, idx, skb, get_default_func); 180 + flow = fq_flow_classify(fq, tin, idx, skb); 181 + 182 + if (!flow->backlog) { 183 + if (flow != &tin->default_flow) 184 + __set_bit(idx, fq->flows_bitmap); 185 + else if (list_empty(&tin->tin_list)) 186 + list_add(&tin->tin_list, &fq->tin_backlog); 187 + } 195 188 196 189 flow->tin = tin; 197 190 flow->backlog += skb->len; ··· 219 172 tin->backlog_packets++; 220 173 fq->memory_usage += skb->truesize; 221 174 fq->backlog++; 222 - 223 - fq_recalc_backlog(fq, tin, flow); 224 175 225 176 if (list_empty(&flow->flowchain)) { 226 177 flow->deficit = fq->quantum; ··· 229 184 __skb_queue_tail(&flow->queue, skb); 230 185 oom = (fq->memory_usage > fq->memory_limit); 231 186 while (fq->backlog > fq->limit || oom) { 232 - flow = list_first_entry_or_null(&fq->backlogs, 233 - struct fq_flow, 234 - backlogchain); 187 + flow = fq_find_fattest_flow(fq); 235 188 if (!flow) 236 189 return; 237 190 238 - skb = fq_flow_dequeue(fq, flow); 239 - if (!skb) 191 + if (!fq_flow_drop(fq, flow, free_func)) 240 192 return; 241 - 242 - free_func(fq, flow->tin, flow, skb); 243 193 244 194 flow->tin->overlimit++; 245 195 fq->overlimit++; ··· 264 224 fq_adjust_removal(fq, flow, skb); 265 225 free_func(fq, tin, flow, skb); 266 226 } 267 - 268 - fq_rejigger_backlog(fq, flow); 269 227 } 270 228 271 229 static void fq_tin_filter(struct fq *fq, ··· 286 248 struct fq_flow *flow, 287 249 fq_skb_free_t free_func) 288 250 { 251 + struct fq_tin *tin = flow->tin; 289 252 struct sk_buff *skb; 290 253 291 254 while ((skb = fq_flow_dequeue(fq, flow))) 292 - free_func(fq, flow->tin, flow, skb); 255 + free_func(fq, tin, flow, skb); 293 256 294 - if (!list_empty(&flow->flowchain)) 257 + if (!list_empty(&flow->flowchain)) { 295 258 list_del_init(&flow->flowchain); 296 - 297 - if (!list_empty(&flow->backlogchain)) 298 - list_del_init(&flow->backlogchain); 259 + if (list_empty(&tin->new_flows) && 260 + list_empty(&tin->old_flows)) 261 + list_del_init(&tin->tin_list); 262 + } 299 263 300 264 flow->tin = NULL; 301 265 ··· 323 283 fq_flow_reset(fq, flow, free_func); 324 284 } 325 285 286 + WARN_ON_ONCE(!list_empty(&tin->tin_list)); 326 287 WARN_ON_ONCE(tin->backlog_bytes); 327 288 WARN_ON_ONCE(tin->backlog_packets); 328 289 } ··· 331 290 static void fq_flow_init(struct fq_flow *flow) 332 291 { 333 292 INIT_LIST_HEAD(&flow->flowchain); 334 - INIT_LIST_HEAD(&flow->backlogchain); 335 293 __skb_queue_head_init(&flow->queue); 336 294 } 337 295 ··· 338 298 { 339 299 INIT_LIST_HEAD(&tin->new_flows); 340 300 INIT_LIST_HEAD(&tin->old_flows); 301 + INIT_LIST_HEAD(&tin->tin_list); 302 + fq_flow_init(&tin->default_flow); 341 303 } 342 304 343 305 static int fq_init(struct fq *fq, int flows_cnt) ··· 347 305 int i; 348 306 349 307 memset(fq, 0, sizeof(fq[0])); 350 - INIT_LIST_HEAD(&fq->backlogs); 351 308 spin_lock_init(&fq->lock); 309 + INIT_LIST_HEAD(&fq->tin_backlog); 352 310 fq->flows_cnt = max_t(u32, flows_cnt, 1); 353 311 fq->quantum = 300; 354 312 fq->limit = 8192; ··· 357 315 fq->flows = kvcalloc(fq->flows_cnt, sizeof(fq->flows[0]), GFP_KERNEL); 358 316 if (!fq->flows) 359 317 return -ENOMEM; 318 + 319 + fq->flows_bitmap = kcalloc(BITS_TO_LONGS(fq->flows_cnt), sizeof(long), 320 + GFP_KERNEL); 321 + if (!fq->flows_bitmap) { 322 + kvfree(fq->flows); 323 + fq->flows = NULL; 324 + return -ENOMEM; 325 + } 360 326 361 327 for (i = 0; i < fq->flows_cnt; i++) 362 328 fq_flow_init(&fq->flows[i]); ··· 382 332 383 333 kvfree(fq->flows); 384 334 fq->flows = NULL; 335 + 336 + kfree(fq->flows_bitmap); 337 + fq->flows_bitmap = NULL; 385 338 } 386 339 387 340 #endif
+21 -5
include/net/mac80211.h
··· 1296 1296 * the "0-length PSDU" field included there. The value for it is 1297 1297 * in &struct ieee80211_rx_status. Note that if this value isn't 1298 1298 * known the frame shouldn't be reported. 1299 + * @RX_FLAG_8023: the frame has an 802.3 header (decap offload performed by 1300 + * hardware or driver) 1299 1301 */ 1300 1302 enum mac80211_rx_flags { 1301 1303 RX_FLAG_MMIC_ERROR = BIT(0), ··· 1330 1328 RX_FLAG_RADIOTAP_HE_MU = BIT(27), 1331 1329 RX_FLAG_RADIOTAP_LSIG = BIT(28), 1332 1330 RX_FLAG_NO_PSDU = BIT(29), 1331 + RX_FLAG_8023 = BIT(30), 1333 1332 }; 1334 1333 1335 1334 /** ··· 1652 1649 * The driver supports sending frames passed as 802.3 frames by mac80211. 1653 1650 * It must also support sending 802.11 packets for the same interface. 1654 1651 * @IEEE80211_OFFLOAD_ENCAP_4ADDR: support 4-address mode encapsulation offload 1652 + * @IEEE80211_OFFLOAD_DECAP_ENABLED: rx encapsulation offload is enabled 1653 + * The driver supports passing received 802.11 frames as 802.3 frames to 1654 + * mac80211. 1655 1655 */ 1656 1656 1657 1657 enum ieee80211_offload_flags { 1658 1658 IEEE80211_OFFLOAD_ENCAP_ENABLED = BIT(0), 1659 1659 IEEE80211_OFFLOAD_ENCAP_4ADDR = BIT(1), 1660 + IEEE80211_OFFLOAD_DECAP_ENABLED = BIT(2), 1660 1661 }; 1661 1662 1662 1663 /** ··· 2396 2389 * @IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD: Hardware supports tx encapsulation 2397 2390 * offload 2398 2391 * 2392 + * @IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD: Hardware supports rx decapsulation 2393 + * offload 2394 + * 2399 2395 * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays 2400 2396 */ 2401 2397 enum ieee80211_hw_flags { ··· 2452 2442 IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID, 2453 2443 IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT, 2454 2444 IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD, 2445 + IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD, 2455 2446 2456 2447 /* keep last, obviously */ 2457 2448 NUM_IEEE80211_HW_FLAGS ··· 3892 3881 * @sta_set_4addr: Called to notify the driver when a station starts/stops using 3893 3882 * 4-address mode 3894 3883 * @set_sar_specs: Update the SAR (TX power) settings. 3884 + * @sta_set_decap_offload: Called to notify the driver when a station is allowed 3885 + * to use rx decapsulation offload 3895 3886 */ 3896 3887 struct ieee80211_ops { 3897 3888 void (*tx)(struct ieee80211_hw *hw, ··· 4211 4198 struct ieee80211_sta *sta, bool enabled); 4212 4199 int (*set_sar_specs)(struct ieee80211_hw *hw, 4213 4200 const struct cfg80211_sar_specs *sar); 4201 + void (*sta_set_decap_offload)(struct ieee80211_hw *hw, 4202 + struct ieee80211_vif *vif, 4203 + struct ieee80211_sta *sta, bool enabled); 4214 4204 }; 4215 4205 4216 4206 /** ··· 5529 5513 void *data); 5530 5514 5531 5515 /** 5532 - * ieee80211_iterate_active_interfaces_rtnl - iterate active interfaces 5516 + * ieee80211_iterate_active_interfaces_mtx - iterate active interfaces 5533 5517 * 5534 5518 * This function iterates over the interfaces associated with a given 5535 5519 * hardware that are currently active and calls the callback for them. ··· 5540 5524 * @iterator: the iterator function to call, cannot sleep 5541 5525 * @data: first argument of the iterator function 5542 5526 */ 5543 - void ieee80211_iterate_active_interfaces_rtnl(struct ieee80211_hw *hw, 5544 - u32 iter_flags, 5545 - void (*iterator)(void *data, 5527 + void ieee80211_iterate_active_interfaces_mtx(struct ieee80211_hw *hw, 5528 + u32 iter_flags, 5529 + void (*iterator)(void *data, 5546 5530 u8 *mac, 5547 5531 struct ieee80211_vif *vif), 5548 - void *data); 5532 + void *data); 5549 5533 5550 5534 /** 5551 5535 * ieee80211_iterate_stations_atomic - iterate stations
-2
net/mac80211/Makefile
··· 56 56 CFLAGS_trace.o := -I$(src) 57 57 58 58 rc80211_minstrel-y := \ 59 - rc80211_minstrel.o \ 60 59 rc80211_minstrel_ht.o 61 60 62 61 rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += \ 63 - rc80211_minstrel_debugfs.o \ 64 62 rc80211_minstrel_ht_debugfs.o 65 63 66 64 mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y)
+52
net/mac80211/debugfs.c
··· 281 281 .llseek = default_llseek, 282 282 }; 283 283 284 + static ssize_t aql_enable_read(struct file *file, char __user *user_buf, 285 + size_t count, loff_t *ppos) 286 + { 287 + char buf[3]; 288 + int len; 289 + 290 + len = scnprintf(buf, sizeof(buf), "%d\n", 291 + !static_key_false(&aql_disable.key)); 292 + 293 + return simple_read_from_buffer(user_buf, count, ppos, buf, len); 294 + } 295 + 296 + static ssize_t aql_enable_write(struct file *file, const char __user *user_buf, 297 + size_t count, loff_t *ppos) 298 + { 299 + bool aql_disabled = static_key_false(&aql_disable.key); 300 + char buf[3]; 301 + size_t len; 302 + 303 + if (count > sizeof(buf)) 304 + return -EINVAL; 305 + 306 + if (copy_from_user(buf, user_buf, count)) 307 + return -EFAULT; 308 + 309 + buf[sizeof(buf) - 1] = '\0'; 310 + len = strlen(buf); 311 + if (len > 0 && buf[len - 1] == '\n') 312 + buf[len - 1] = 0; 313 + 314 + if (buf[0] == '0' && buf[1] == '\0') { 315 + if (!aql_disabled) 316 + static_branch_inc(&aql_disable); 317 + } else if (buf[0] == '1' && buf[1] == '\0') { 318 + if (aql_disabled) 319 + static_branch_dec(&aql_disable); 320 + } else { 321 + return -EINVAL; 322 + } 323 + 324 + return count; 325 + } 326 + 327 + static const struct file_operations aql_enable_ops = { 328 + .write = aql_enable_write, 329 + .read = aql_enable_read, 330 + .open = simple_open, 331 + .llseek = default_llseek, 332 + }; 333 + 284 334 static ssize_t force_tx_status_read(struct file *file, 285 335 char __user *user_buf, 286 336 size_t count, ··· 455 405 FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID), 456 406 FLAG(AMPDU_KEYBORDER_SUPPORT), 457 407 FLAG(SUPPORTS_TX_ENCAP_OFFLOAD), 408 + FLAG(SUPPORTS_RX_DECAP_OFFLOAD), 458 409 #undef FLAG 459 410 }; 460 411 ··· 619 568 DEBUGFS_ADD(power); 620 569 DEBUGFS_ADD(hw_conf); 621 570 DEBUGFS_ADD_MODE(force_tx_status, 0600); 571 + DEBUGFS_ADD_MODE(aql_enable, 0600); 622 572 623 573 if (local->ops->wake_tx_queue) 624 574 DEBUGFS_ADD_MODE(aqm, 0600);
+1
net/mac80211/debugfs_sta.c
··· 79 79 FLAG(MPSP_RECIPIENT), 80 80 FLAG(PS_DELIVER), 81 81 FLAG(USES_ENCRYPTION), 82 + FLAG(DECAP_OFFLOAD), 82 83 #undef FLAG 83 84 }; 84 85
+16
net/mac80211/driver-ops.h
··· 1413 1413 trace_drv_return_void(local); 1414 1414 } 1415 1415 1416 + static inline void drv_sta_set_decap_offload(struct ieee80211_local *local, 1417 + struct ieee80211_sub_if_data *sdata, 1418 + struct ieee80211_sta *sta, 1419 + bool enabled) 1420 + { 1421 + sdata = get_bss_sdata(sdata); 1422 + if (!check_sdata_in_driver(sdata)) 1423 + return; 1424 + 1425 + trace_drv_sta_set_decap_offload(local, sdata, sta, enabled); 1426 + if (local->ops->sta_set_decap_offload) 1427 + local->ops->sta_set_decap_offload(&local->hw, &sdata->vif, sta, 1428 + enabled); 1429 + trace_drv_return_void(local); 1430 + } 1431 + 1416 1432 #endif /* __MAC80211_DRIVER_OPS */
+92
net/mac80211/he.c
··· 52 52 sta->sta.he_6ghz_capa = *he_6ghz_capa; 53 53 } 54 54 55 + static void ieee80211_he_mcs_disable(__le16 *he_mcs) 56 + { 57 + u32 i; 58 + 59 + for (i = 0; i < 8; i++) 60 + *he_mcs |= cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << i * 2); 61 + } 62 + 63 + static void ieee80211_he_mcs_intersection(__le16 *he_own_rx, __le16 *he_peer_rx, 64 + __le16 *he_own_tx, __le16 *he_peer_tx) 65 + { 66 + u32 i; 67 + u16 own_rx, own_tx, peer_rx, peer_tx; 68 + 69 + for (i = 0; i < 8; i++) { 70 + own_rx = le16_to_cpu(*he_own_rx); 71 + own_rx = (own_rx >> i * 2) & IEEE80211_HE_MCS_NOT_SUPPORTED; 72 + 73 + own_tx = le16_to_cpu(*he_own_tx); 74 + own_tx = (own_tx >> i * 2) & IEEE80211_HE_MCS_NOT_SUPPORTED; 75 + 76 + peer_rx = le16_to_cpu(*he_peer_rx); 77 + peer_rx = (peer_rx >> i * 2) & IEEE80211_HE_MCS_NOT_SUPPORTED; 78 + 79 + peer_tx = le16_to_cpu(*he_peer_tx); 80 + peer_tx = (peer_tx >> i * 2) & IEEE80211_HE_MCS_NOT_SUPPORTED; 81 + 82 + if (peer_tx != IEEE80211_HE_MCS_NOT_SUPPORTED) { 83 + if (own_rx == IEEE80211_HE_MCS_NOT_SUPPORTED) 84 + peer_tx = IEEE80211_HE_MCS_NOT_SUPPORTED; 85 + else if (own_rx < peer_tx) 86 + peer_tx = own_rx; 87 + } 88 + 89 + if (peer_rx != IEEE80211_HE_MCS_NOT_SUPPORTED) { 90 + if (own_tx == IEEE80211_HE_MCS_NOT_SUPPORTED) 91 + peer_rx = IEEE80211_HE_MCS_NOT_SUPPORTED; 92 + else if (own_tx < peer_rx) 93 + peer_rx = own_tx; 94 + } 95 + 96 + *he_peer_rx &= 97 + ~cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << i * 2); 98 + *he_peer_rx |= cpu_to_le16(peer_rx << i * 2); 99 + 100 + *he_peer_tx &= 101 + ~cpu_to_le16(IEEE80211_HE_MCS_NOT_SUPPORTED << i * 2); 102 + *he_peer_tx |= cpu_to_le16(peer_tx << i * 2); 103 + } 104 + } 105 + 55 106 void 56 107 ieee80211_he_cap_ie_to_sta_he_cap(struct ieee80211_sub_if_data *sdata, 57 108 struct ieee80211_supported_band *sband, ··· 111 60 struct sta_info *sta) 112 61 { 113 62 struct ieee80211_sta_he_cap *he_cap = &sta->sta.he_cap; 63 + struct ieee80211_sta_he_cap own_he_cap = sband->iftype_data->he_cap; 114 64 struct ieee80211_he_cap_elem *he_cap_ie_elem = (void *)he_cap_ie; 115 65 u8 he_ppe_size; 116 66 u8 mcs_nss_size; 117 67 u8 he_total_size; 68 + bool own_160, peer_160, own_80p80, peer_80p80; 118 69 119 70 memset(he_cap, 0, sizeof(*he_cap)); 120 71 ··· 154 101 155 102 if (sband->band == NL80211_BAND_6GHZ && he_6ghz_capa) 156 103 ieee80211_update_from_he_6ghz_capa(he_6ghz_capa, sta); 104 + 105 + ieee80211_he_mcs_intersection(&own_he_cap.he_mcs_nss_supp.rx_mcs_80, 106 + &he_cap->he_mcs_nss_supp.rx_mcs_80, 107 + &own_he_cap.he_mcs_nss_supp.tx_mcs_80, 108 + &he_cap->he_mcs_nss_supp.tx_mcs_80); 109 + 110 + own_160 = own_he_cap.he_cap_elem.phy_cap_info[0] & 111 + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; 112 + peer_160 = he_cap->he_cap_elem.phy_cap_info[0] & 113 + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; 114 + 115 + if (peer_160 && own_160) { 116 + ieee80211_he_mcs_intersection(&own_he_cap.he_mcs_nss_supp.rx_mcs_160, 117 + &he_cap->he_mcs_nss_supp.rx_mcs_160, 118 + &own_he_cap.he_mcs_nss_supp.tx_mcs_160, 119 + &he_cap->he_mcs_nss_supp.tx_mcs_160); 120 + } else if (peer_160 && !own_160) { 121 + ieee80211_he_mcs_disable(&he_cap->he_mcs_nss_supp.rx_mcs_160); 122 + ieee80211_he_mcs_disable(&he_cap->he_mcs_nss_supp.tx_mcs_160); 123 + he_cap->he_cap_elem.phy_cap_info[0] &= 124 + ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; 125 + } 126 + 127 + own_80p80 = own_he_cap.he_cap_elem.phy_cap_info[0] & 128 + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G; 129 + peer_80p80 = he_cap->he_cap_elem.phy_cap_info[0] & 130 + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G; 131 + 132 + if (peer_80p80 && own_80p80) { 133 + ieee80211_he_mcs_intersection(&own_he_cap.he_mcs_nss_supp.rx_mcs_80p80, 134 + &he_cap->he_mcs_nss_supp.rx_mcs_80p80, 135 + &own_he_cap.he_mcs_nss_supp.tx_mcs_80p80, 136 + &he_cap->he_mcs_nss_supp.tx_mcs_80p80); 137 + } else if (peer_80p80 && !own_80p80) { 138 + ieee80211_he_mcs_disable(&he_cap->he_mcs_nss_supp.rx_mcs_80p80); 139 + ieee80211_he_mcs_disable(&he_cap->he_mcs_nss_supp.tx_mcs_80p80); 140 + he_cap->he_cap_elem.phy_cap_info[0] &= 141 + ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G; 142 + } 157 143 } 158 144 159 145 void
+2 -1
net/mac80211/ieee80211_i.h
··· 848 848 */ 849 849 struct txq_info { 850 850 struct fq_tin tin; 851 - struct fq_flow def_flow; 852 851 struct codel_vars def_cvars; 853 852 struct codel_stats cstats; 854 853 struct sk_buff_head frags; ··· 1141 1142 SCAN_RESUME, 1142 1143 SCAN_ABORT, 1143 1144 }; 1145 + 1146 + DECLARE_STATIC_KEY_FALSE(aql_disable); 1144 1147 1145 1148 struct ieee80211_local { 1146 1149 /* embed the driver visible part.
+29 -11
net/mac80211/iface.c
··· 357 357 if (err) 358 358 return err; 359 359 360 - return ieee80211_do_open(&sdata->wdev, true); 360 + wiphy_lock(sdata->local->hw.wiphy); 361 + err = ieee80211_do_open(&sdata->wdev, true); 362 + wiphy_unlock(sdata->local->hw.wiphy); 363 + 364 + return err; 361 365 } 362 366 363 - static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, 364 - bool going_down) 367 + static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_down) 365 368 { 366 369 struct ieee80211_local *local = sdata->local; 367 370 unsigned long flags; ··· 640 637 { 641 638 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 642 639 640 + wiphy_lock(sdata->local->hw.wiphy); 643 641 ieee80211_do_stop(sdata, true); 642 + wiphy_unlock(sdata->local->hw.wiphy); 644 643 645 644 return 0; 646 645 } ··· 770 765 .ndo_get_stats64 = ieee80211_get_stats64, 771 766 }; 772 767 773 - static bool ieee80211_iftype_supports_encap_offload(enum nl80211_iftype iftype) 768 + static bool ieee80211_iftype_supports_hdr_offload(enum nl80211_iftype iftype) 774 769 { 775 770 switch (iftype) { 776 771 /* P2P GO and client are mapped to AP/STATION types */ ··· 790 785 flags = sdata->vif.offload_flags; 791 786 792 787 if (ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) && 793 - ieee80211_iftype_supports_encap_offload(sdata->vif.type)) { 788 + ieee80211_iftype_supports_hdr_offload(sdata->vif.type)) { 794 789 flags |= IEEE80211_OFFLOAD_ENCAP_ENABLED; 795 790 796 791 if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_FRAG) && ··· 803 798 flags &= ~IEEE80211_OFFLOAD_ENCAP_ENABLED; 804 799 } 805 800 801 + if (ieee80211_hw_check(&local->hw, SUPPORTS_RX_DECAP_OFFLOAD) && 802 + ieee80211_iftype_supports_hdr_offload(sdata->vif.type)) { 803 + flags |= IEEE80211_OFFLOAD_DECAP_ENABLED; 804 + 805 + if (local->monitors) 806 + flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED; 807 + } else { 808 + flags &= ~IEEE80211_OFFLOAD_DECAP_ENABLED; 809 + } 810 + 806 811 if (sdata->vif.offload_flags == flags) 807 812 return false; 808 813 809 814 sdata->vif.offload_flags = flags; 815 + ieee80211_check_fast_rx_iface(sdata); 810 816 return true; 811 817 } 812 818 ··· 835 819 } 836 820 837 821 if (!ieee80211_hw_check(&local->hw, SUPPORTS_TX_ENCAP_OFFLOAD) || 838 - !ieee80211_iftype_supports_encap_offload(bss->vif.type)) 822 + !ieee80211_iftype_supports_hdr_offload(bss->vif.type)) 839 823 return; 840 824 841 825 enabled = bss->vif.offload_flags & IEEE80211_OFFLOAD_ENCAP_ENABLED; ··· 1981 1965 ndev->min_mtu = 256; 1982 1966 ndev->max_mtu = local->hw.max_mtu; 1983 1967 1984 - ret = register_netdevice(ndev); 1968 + ret = cfg80211_register_netdevice(ndev); 1985 1969 if (ret) { 1986 1970 free_netdev(ndev); 1987 1971 return ret; ··· 2011 1995 2012 1996 synchronize_rcu(); 2013 1997 2014 - if (sdata->dev) { 2015 - unregister_netdevice(sdata->dev); 2016 - } else { 2017 - cfg80211_unregister_wdev(&sdata->wdev); 1998 + cfg80211_unregister_wdev(&sdata->wdev); 1999 + 2000 + if (!sdata->dev) { 2018 2001 ieee80211_teardown_sdata(sdata); 2019 2002 kfree(sdata); 2020 2003 } ··· 2062 2047 list_add(&sdata->list, &wdev_list); 2063 2048 } 2064 2049 mutex_unlock(&local->iflist_mtx); 2050 + 2065 2051 unregister_netdevice_many(&unreg_list); 2066 2052 2053 + wiphy_lock(local->hw.wiphy); 2067 2054 list_for_each_entry_safe(sdata, tmp, &wdev_list, list) { 2068 2055 list_del(&sdata->list); 2069 2056 cfg80211_unregister_wdev(&sdata->wdev); 2070 2057 kfree(sdata); 2071 2058 } 2059 + wiphy_unlock(local->hw.wiphy); 2072 2060 } 2073 2061 2074 2062 static int netdev_notify(struct notifier_block *nb,
+2 -2
net/mac80211/key.c
··· 887 887 struct ieee80211_key *key; 888 888 struct ieee80211_sub_if_data *vlan; 889 889 890 - ASSERT_RTNL(); 890 + lockdep_assert_wiphy(sdata->local->hw.wiphy); 891 891 892 892 mutex_lock(&sdata->local->key_mtx); 893 893 ··· 924 924 struct ieee80211_key *key, *tmp; 925 925 struct ieee80211_sub_if_data *sdata; 926 926 927 - ASSERT_RTNL(); 927 + lockdep_assert_wiphy(hw->wiphy); 928 928 929 929 mutex_lock(&local->key_mtx); 930 930 if (vif) {
+5
net/mac80211/main.c
··· 261 261 "%s called with hardware scan in progress\n", __func__); 262 262 263 263 flush_work(&local->radar_detected_work); 264 + /* we might do interface manipulations, so need both */ 264 265 rtnl_lock(); 266 + wiphy_lock(local->hw.wiphy); 265 267 list_for_each_entry(sdata, &local->interfaces, list) { 266 268 /* 267 269 * XXX: there may be more work for other vif types and even ··· 295 293 synchronize_net(); 296 294 297 295 ieee80211_reconfig(local); 296 + wiphy_unlock(local->hw.wiphy); 298 297 rtnl_unlock(); 299 298 } 300 299 ··· 1275 1272 rate_control_add_debugfs(local); 1276 1273 1277 1274 rtnl_lock(); 1275 + wiphy_lock(hw->wiphy); 1278 1276 1279 1277 /* add one default STA interface if supported */ 1280 1278 if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION) && ··· 1289 1285 "Failed to add default virtual iface\n"); 1290 1286 } 1291 1287 1288 + wiphy_unlock(hw->wiphy); 1292 1289 rtnl_unlock(); 1293 1290 1294 1291 #ifdef CONFIG_INET
+5 -1
net/mac80211/pm.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Portions 4 + * Copyright (C) 2020-2021 Intel Corporation 5 + */ 2 6 #include <net/mac80211.h> 3 7 #include <net/rtnetlink.h> 4 8 ··· 15 11 { 16 12 if (ieee80211_request_sched_scan_stop(local)) 17 13 return; 18 - cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy, 0); 14 + cfg80211_sched_scan_stopped_locked(local->hw.wiphy, 0); 19 15 } 20 16 21 17 int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
-574
net/mac80211/rc80211_minstrel.c
··· 1 - /* 2 - * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License version 2 as 6 - * published by the Free Software Foundation. 7 - * 8 - * Based on minstrel.c: 9 - * Copyright (C) 2005-2007 Derek Smithies <derek@indranet.co.nz> 10 - * Sponsored by Indranet Technologies Ltd 11 - * 12 - * Based on sample.c: 13 - * Copyright (c) 2005 John Bicket 14 - * All rights reserved. 15 - * 16 - * Redistribution and use in source and binary forms, with or without 17 - * modification, are permitted provided that the following conditions 18 - * are met: 19 - * 1. Redistributions of source code must retain the above copyright 20 - * notice, this list of conditions and the following disclaimer, 21 - * without modification. 22 - * 2. Redistributions in binary form must reproduce at minimum a disclaimer 23 - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 24 - * redistribution must be conditioned upon including a substantially 25 - * similar Disclaimer requirement for further binary redistribution. 26 - * 3. Neither the names of the above-listed copyright holders nor the names 27 - * of any contributors may be used to endorse or promote products derived 28 - * from this software without specific prior written permission. 29 - * 30 - * Alternatively, this software may be distributed under the terms of the 31 - * GNU General Public License ("GPL") version 2 as published by the Free 32 - * Software Foundation. 33 - * 34 - * NO WARRANTY 35 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 36 - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 37 - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 38 - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 39 - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 40 - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 41 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 42 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 43 - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 44 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 45 - * THE POSSIBILITY OF SUCH DAMAGES. 46 - */ 47 - #include <linux/netdevice.h> 48 - #include <linux/types.h> 49 - #include <linux/skbuff.h> 50 - #include <linux/debugfs.h> 51 - #include <linux/random.h> 52 - #include <linux/ieee80211.h> 53 - #include <linux/slab.h> 54 - #include <net/mac80211.h> 55 - #include "rate.h" 56 - #include "rc80211_minstrel.h" 57 - 58 - #define SAMPLE_TBL(_mi, _idx, _col) \ 59 - _mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col] 60 - 61 - /* convert mac80211 rate index to local array index */ 62 - static inline int 63 - rix_to_ndx(struct minstrel_sta_info *mi, int rix) 64 - { 65 - int i = rix; 66 - for (i = rix; i >= 0; i--) 67 - if (mi->r[i].rix == rix) 68 - break; 69 - return i; 70 - } 71 - 72 - /* return current EMWA throughput */ 73 - int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg) 74 - { 75 - int usecs; 76 - 77 - usecs = mr->perfect_tx_time; 78 - if (!usecs) 79 - usecs = 1000000; 80 - 81 - /* reset thr. below 10% success */ 82 - if (mr->stats.prob_avg < MINSTREL_FRAC(10, 100)) 83 - return 0; 84 - 85 - if (prob_avg > MINSTREL_FRAC(90, 100)) 86 - return MINSTREL_TRUNC(100000 * (MINSTREL_FRAC(90, 100) / usecs)); 87 - else 88 - return MINSTREL_TRUNC(100000 * (prob_avg / usecs)); 89 - } 90 - 91 - /* find & sort topmost throughput rates */ 92 - static inline void 93 - minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list) 94 - { 95 - int j; 96 - struct minstrel_rate_stats *tmp_mrs; 97 - struct minstrel_rate_stats *cur_mrs = &mi->r[i].stats; 98 - 99 - for (j = MAX_THR_RATES; j > 0; --j) { 100 - tmp_mrs = &mi->r[tp_list[j - 1]].stats; 101 - if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_avg) <= 102 - minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_avg)) 103 - break; 104 - } 105 - 106 - if (j < MAX_THR_RATES - 1) 107 - memmove(&tp_list[j + 1], &tp_list[j], MAX_THR_RATES - (j + 1)); 108 - if (j < MAX_THR_RATES) 109 - tp_list[j] = i; 110 - } 111 - 112 - static void 113 - minstrel_set_rate(struct minstrel_sta_info *mi, struct ieee80211_sta_rates *ratetbl, 114 - int offset, int idx) 115 - { 116 - struct minstrel_rate *r = &mi->r[idx]; 117 - 118 - ratetbl->rate[offset].idx = r->rix; 119 - ratetbl->rate[offset].count = r->adjusted_retry_count; 120 - ratetbl->rate[offset].count_cts = r->retry_count_cts; 121 - ratetbl->rate[offset].count_rts = r->stats.retry_count_rtscts; 122 - } 123 - 124 - static void 125 - minstrel_update_rates(struct minstrel_priv *mp, struct minstrel_sta_info *mi) 126 - { 127 - struct ieee80211_sta_rates *ratetbl; 128 - int i = 0; 129 - 130 - ratetbl = kzalloc(sizeof(*ratetbl), GFP_ATOMIC); 131 - if (!ratetbl) 132 - return; 133 - 134 - /* Start with max_tp_rate */ 135 - minstrel_set_rate(mi, ratetbl, i++, mi->max_tp_rate[0]); 136 - 137 - if (mp->hw->max_rates >= 3) { 138 - /* At least 3 tx rates supported, use max_tp_rate2 next */ 139 - minstrel_set_rate(mi, ratetbl, i++, mi->max_tp_rate[1]); 140 - } 141 - 142 - if (mp->hw->max_rates >= 2) { 143 - /* At least 2 tx rates supported, use max_prob_rate next */ 144 - minstrel_set_rate(mi, ratetbl, i++, mi->max_prob_rate); 145 - } 146 - 147 - /* Use lowest rate last */ 148 - ratetbl->rate[i].idx = mi->lowest_rix; 149 - ratetbl->rate[i].count = mp->max_retry; 150 - ratetbl->rate[i].count_cts = mp->max_retry; 151 - ratetbl->rate[i].count_rts = mp->max_retry; 152 - 153 - rate_control_set_rates(mp->hw, mi->sta, ratetbl); 154 - } 155 - 156 - /* 157 - * Recalculate statistics and counters of a given rate 158 - */ 159 - void 160 - minstrel_calc_rate_stats(struct minstrel_priv *mp, 161 - struct minstrel_rate_stats *mrs) 162 - { 163 - unsigned int cur_prob; 164 - 165 - if (unlikely(mrs->attempts > 0)) { 166 - mrs->sample_skipped = 0; 167 - cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); 168 - if (mp->new_avg) { 169 - minstrel_filter_avg_add(&mrs->prob_avg, 170 - &mrs->prob_avg_1, cur_prob); 171 - } else if (unlikely(!mrs->att_hist)) { 172 - mrs->prob_avg = cur_prob; 173 - } else { 174 - /*update exponential weighted moving avarage */ 175 - mrs->prob_avg = minstrel_ewma(mrs->prob_avg, 176 - cur_prob, 177 - EWMA_LEVEL); 178 - } 179 - mrs->att_hist += mrs->attempts; 180 - mrs->succ_hist += mrs->success; 181 - } else { 182 - mrs->sample_skipped++; 183 - } 184 - 185 - mrs->last_success = mrs->success; 186 - mrs->last_attempts = mrs->attempts; 187 - mrs->success = 0; 188 - mrs->attempts = 0; 189 - } 190 - 191 - static void 192 - minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) 193 - { 194 - u8 tmp_tp_rate[MAX_THR_RATES]; 195 - u8 tmp_prob_rate = 0; 196 - int i, tmp_cur_tp, tmp_prob_tp; 197 - 198 - for (i = 0; i < MAX_THR_RATES; i++) 199 - tmp_tp_rate[i] = 0; 200 - 201 - for (i = 0; i < mi->n_rates; i++) { 202 - struct minstrel_rate *mr = &mi->r[i]; 203 - struct minstrel_rate_stats *mrs = &mi->r[i].stats; 204 - struct minstrel_rate_stats *tmp_mrs = &mi->r[tmp_prob_rate].stats; 205 - 206 - /* Update statistics of success probability per rate */ 207 - minstrel_calc_rate_stats(mp, mrs); 208 - 209 - /* Sample less often below the 10% chance of success. 210 - * Sample less often above the 95% chance of success. */ 211 - if (mrs->prob_avg > MINSTREL_FRAC(95, 100) || 212 - mrs->prob_avg < MINSTREL_FRAC(10, 100)) { 213 - mr->adjusted_retry_count = mrs->retry_count >> 1; 214 - if (mr->adjusted_retry_count > 2) 215 - mr->adjusted_retry_count = 2; 216 - mr->sample_limit = 4; 217 - } else { 218 - mr->sample_limit = -1; 219 - mr->adjusted_retry_count = mrs->retry_count; 220 - } 221 - if (!mr->adjusted_retry_count) 222 - mr->adjusted_retry_count = 2; 223 - 224 - minstrel_sort_best_tp_rates(mi, i, tmp_tp_rate); 225 - 226 - /* To determine the most robust rate (max_prob_rate) used at 227 - * 3rd mmr stage we distinct between two cases: 228 - * (1) if any success probabilitiy >= 95%, out of those rates 229 - * choose the maximum throughput rate as max_prob_rate 230 - * (2) if all success probabilities < 95%, the rate with 231 - * highest success probability is chosen as max_prob_rate */ 232 - if (mrs->prob_avg >= MINSTREL_FRAC(95, 100)) { 233 - tmp_cur_tp = minstrel_get_tp_avg(mr, mrs->prob_avg); 234 - tmp_prob_tp = minstrel_get_tp_avg(&mi->r[tmp_prob_rate], 235 - tmp_mrs->prob_avg); 236 - if (tmp_cur_tp >= tmp_prob_tp) 237 - tmp_prob_rate = i; 238 - } else { 239 - if (mrs->prob_avg >= tmp_mrs->prob_avg) 240 - tmp_prob_rate = i; 241 - } 242 - } 243 - 244 - /* Assign the new rate set */ 245 - memcpy(mi->max_tp_rate, tmp_tp_rate, sizeof(mi->max_tp_rate)); 246 - mi->max_prob_rate = tmp_prob_rate; 247 - 248 - #ifdef CONFIG_MAC80211_DEBUGFS 249 - /* use fixed index if set */ 250 - if (mp->fixed_rate_idx != -1) { 251 - mi->max_tp_rate[0] = mp->fixed_rate_idx; 252 - mi->max_tp_rate[1] = mp->fixed_rate_idx; 253 - mi->max_prob_rate = mp->fixed_rate_idx; 254 - } 255 - #endif 256 - 257 - /* Reset update timer */ 258 - mi->last_stats_update = jiffies; 259 - 260 - minstrel_update_rates(mp, mi); 261 - } 262 - 263 - static void 264 - minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, 265 - void *priv_sta, struct ieee80211_tx_status *st) 266 - { 267 - struct ieee80211_tx_info *info = st->info; 268 - struct minstrel_priv *mp = priv; 269 - struct minstrel_sta_info *mi = priv_sta; 270 - struct ieee80211_tx_rate *ar = info->status.rates; 271 - int i, ndx; 272 - int success; 273 - 274 - success = !!(info->flags & IEEE80211_TX_STAT_ACK); 275 - 276 - for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { 277 - if (ar[i].idx < 0 || !ar[i].count) 278 - break; 279 - 280 - ndx = rix_to_ndx(mi, ar[i].idx); 281 - if (ndx < 0) 282 - continue; 283 - 284 - mi->r[ndx].stats.attempts += ar[i].count; 285 - 286 - if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) 287 - mi->r[ndx].stats.success += success; 288 - } 289 - 290 - if (time_after(jiffies, mi->last_stats_update + 291 - mp->update_interval / (mp->new_avg ? 2 : 1))) 292 - minstrel_update_stats(mp, mi); 293 - } 294 - 295 - 296 - static inline unsigned int 297 - minstrel_get_retry_count(struct minstrel_rate *mr, 298 - struct ieee80211_tx_info *info) 299 - { 300 - u8 retry = mr->adjusted_retry_count; 301 - 302 - if (info->control.use_rts) 303 - retry = max_t(u8, 2, min(mr->stats.retry_count_rtscts, retry)); 304 - else if (info->control.use_cts_prot) 305 - retry = max_t(u8, 2, min(mr->retry_count_cts, retry)); 306 - return retry; 307 - } 308 - 309 - 310 - static int 311 - minstrel_get_next_sample(struct minstrel_sta_info *mi) 312 - { 313 - unsigned int sample_ndx; 314 - sample_ndx = SAMPLE_TBL(mi, mi->sample_row, mi->sample_column); 315 - mi->sample_row++; 316 - if ((int) mi->sample_row >= mi->n_rates) { 317 - mi->sample_row = 0; 318 - mi->sample_column++; 319 - if (mi->sample_column >= SAMPLE_COLUMNS) 320 - mi->sample_column = 0; 321 - } 322 - return sample_ndx; 323 - } 324 - 325 - static void 326 - minstrel_get_rate(void *priv, struct ieee80211_sta *sta, 327 - void *priv_sta, struct ieee80211_tx_rate_control *txrc) 328 - { 329 - struct sk_buff *skb = txrc->skb; 330 - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 331 - struct minstrel_sta_info *mi = priv_sta; 332 - struct minstrel_priv *mp = priv; 333 - struct ieee80211_tx_rate *rate = &info->control.rates[0]; 334 - struct minstrel_rate *msr, *mr; 335 - unsigned int ndx; 336 - bool mrr_capable; 337 - bool prev_sample; 338 - int delta; 339 - int sampling_ratio; 340 - 341 - /* check multi-rate-retry capabilities & adjust lookaround_rate */ 342 - mrr_capable = mp->has_mrr && 343 - !txrc->rts && 344 - !txrc->bss_conf->use_cts_prot; 345 - if (mrr_capable) 346 - sampling_ratio = mp->lookaround_rate_mrr; 347 - else 348 - sampling_ratio = mp->lookaround_rate; 349 - 350 - /* increase sum packet counter */ 351 - mi->total_packets++; 352 - 353 - #ifdef CONFIG_MAC80211_DEBUGFS 354 - if (mp->fixed_rate_idx != -1) 355 - return; 356 - #endif 357 - 358 - /* Don't use EAPOL frames for sampling on non-mrr hw */ 359 - if (mp->hw->max_rates == 1 && 360 - (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) 361 - return; 362 - 363 - delta = (mi->total_packets * sampling_ratio / 100) - 364 - mi->sample_packets; 365 - 366 - /* delta < 0: no sampling required */ 367 - prev_sample = mi->prev_sample; 368 - mi->prev_sample = false; 369 - if (delta < 0 || (!mrr_capable && prev_sample)) 370 - return; 371 - 372 - if (mi->total_packets >= 10000) { 373 - mi->sample_packets = 0; 374 - mi->total_packets = 0; 375 - } else if (delta > mi->n_rates * 2) { 376 - /* With multi-rate retry, not every planned sample 377 - * attempt actually gets used, due to the way the retry 378 - * chain is set up - [max_tp,sample,prob,lowest] for 379 - * sample_rate < max_tp. 380 - * 381 - * If there's too much sampling backlog and the link 382 - * starts getting worse, minstrel would start bursting 383 - * out lots of sampling frames, which would result 384 - * in a large throughput loss. */ 385 - mi->sample_packets += (delta - mi->n_rates * 2); 386 - } 387 - 388 - /* get next random rate sample */ 389 - ndx = minstrel_get_next_sample(mi); 390 - msr = &mi->r[ndx]; 391 - mr = &mi->r[mi->max_tp_rate[0]]; 392 - 393 - /* Decide if direct ( 1st mrr stage) or indirect (2nd mrr stage) 394 - * rate sampling method should be used. 395 - * Respect such rates that are not sampled for 20 interations. 396 - */ 397 - if (msr->perfect_tx_time < mr->perfect_tx_time || 398 - msr->stats.sample_skipped >= 20) { 399 - if (!msr->sample_limit) 400 - return; 401 - 402 - mi->sample_packets++; 403 - if (msr->sample_limit > 0) 404 - msr->sample_limit--; 405 - } 406 - 407 - /* If we're not using MRR and the sampling rate already 408 - * has a probability of >95%, we shouldn't be attempting 409 - * to use it, as this only wastes precious airtime */ 410 - if (!mrr_capable && 411 - (mi->r[ndx].stats.prob_avg > MINSTREL_FRAC(95, 100))) 412 - return; 413 - 414 - mi->prev_sample = true; 415 - 416 - rate->idx = mi->r[ndx].rix; 417 - rate->count = minstrel_get_retry_count(&mi->r[ndx], info); 418 - info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; 419 - } 420 - 421 - 422 - static void 423 - calc_rate_durations(enum nl80211_band band, 424 - struct minstrel_rate *d, 425 - struct ieee80211_rate *rate, 426 - struct cfg80211_chan_def *chandef) 427 - { 428 - int erp = !!(rate->flags & IEEE80211_RATE_ERP_G); 429 - int shift = ieee80211_chandef_get_shift(chandef); 430 - 431 - d->perfect_tx_time = ieee80211_frame_duration(band, 1200, 432 - DIV_ROUND_UP(rate->bitrate, 1 << shift), erp, 1, 433 - shift); 434 - d->ack_time = ieee80211_frame_duration(band, 10, 435 - DIV_ROUND_UP(rate->bitrate, 1 << shift), erp, 1, 436 - shift); 437 - } 438 - 439 - static void 440 - init_sample_table(struct minstrel_sta_info *mi) 441 - { 442 - unsigned int i, col, new_idx; 443 - u8 rnd[8]; 444 - 445 - mi->sample_column = 0; 446 - mi->sample_row = 0; 447 - memset(mi->sample_table, 0xff, SAMPLE_COLUMNS * mi->n_rates); 448 - 449 - for (col = 0; col < SAMPLE_COLUMNS; col++) { 450 - prandom_bytes(rnd, sizeof(rnd)); 451 - for (i = 0; i < mi->n_rates; i++) { 452 - new_idx = (i + rnd[i & 7]) % mi->n_rates; 453 - while (SAMPLE_TBL(mi, new_idx, col) != 0xff) 454 - new_idx = (new_idx + 1) % mi->n_rates; 455 - 456 - SAMPLE_TBL(mi, new_idx, col) = i; 457 - } 458 - } 459 - } 460 - 461 - static void 462 - minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, 463 - struct cfg80211_chan_def *chandef, 464 - struct ieee80211_sta *sta, void *priv_sta) 465 - { 466 - struct minstrel_sta_info *mi = priv_sta; 467 - struct minstrel_priv *mp = priv; 468 - struct ieee80211_rate *ctl_rate; 469 - unsigned int i, n = 0; 470 - unsigned int t_slot = 9; /* FIXME: get real slot time */ 471 - u32 rate_flags; 472 - 473 - mi->sta = sta; 474 - mi->lowest_rix = rate_lowest_index(sband, sta); 475 - ctl_rate = &sband->bitrates[mi->lowest_rix]; 476 - mi->sp_ack_dur = ieee80211_frame_duration(sband->band, 10, 477 - ctl_rate->bitrate, 478 - !!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1, 479 - ieee80211_chandef_get_shift(chandef)); 480 - 481 - rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); 482 - memset(mi->max_tp_rate, 0, sizeof(mi->max_tp_rate)); 483 - mi->max_prob_rate = 0; 484 - 485 - for (i = 0; i < sband->n_bitrates; i++) { 486 - struct minstrel_rate *mr = &mi->r[n]; 487 - struct minstrel_rate_stats *mrs = &mi->r[n].stats; 488 - unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0; 489 - unsigned int tx_time_single; 490 - unsigned int cw = mp->cw_min; 491 - int shift; 492 - 493 - if (!rate_supported(sta, sband->band, i)) 494 - continue; 495 - if ((rate_flags & sband->bitrates[i].flags) != rate_flags) 496 - continue; 497 - 498 - n++; 499 - memset(mr, 0, sizeof(*mr)); 500 - memset(mrs, 0, sizeof(*mrs)); 501 - 502 - mr->rix = i; 503 - shift = ieee80211_chandef_get_shift(chandef); 504 - mr->bitrate = DIV_ROUND_UP(sband->bitrates[i].bitrate, 505 - (1 << shift) * 5); 506 - calc_rate_durations(sband->band, mr, &sband->bitrates[i], 507 - chandef); 508 - 509 - /* calculate maximum number of retransmissions before 510 - * fallback (based on maximum segment size) */ 511 - mr->sample_limit = -1; 512 - mrs->retry_count = 1; 513 - mr->retry_count_cts = 1; 514 - mrs->retry_count_rtscts = 1; 515 - tx_time = mr->perfect_tx_time + mi->sp_ack_dur; 516 - do { 517 - /* add one retransmission */ 518 - tx_time_single = mr->ack_time + mr->perfect_tx_time; 519 - 520 - /* contention window */ 521 - tx_time_single += (t_slot * cw) >> 1; 522 - cw = min((cw << 1) | 1, mp->cw_max); 523 - 524 - tx_time += tx_time_single; 525 - tx_time_cts += tx_time_single + mi->sp_ack_dur; 526 - tx_time_rtscts += tx_time_single + 2 * mi->sp_ack_dur; 527 - if ((tx_time_cts < mp->segment_size) && 528 - (mr->retry_count_cts < mp->max_retry)) 529 - mr->retry_count_cts++; 530 - if ((tx_time_rtscts < mp->segment_size) && 531 - (mrs->retry_count_rtscts < mp->max_retry)) 532 - mrs->retry_count_rtscts++; 533 - } while ((tx_time < mp->segment_size) && 534 - (++mr->stats.retry_count < mp->max_retry)); 535 - mr->adjusted_retry_count = mrs->retry_count; 536 - if (!(sband->bitrates[i].flags & IEEE80211_RATE_ERP_G)) 537 - mr->retry_count_cts = mrs->retry_count; 538 - } 539 - 540 - for (i = n; i < sband->n_bitrates; i++) { 541 - struct minstrel_rate *mr = &mi->r[i]; 542 - mr->rix = -1; 543 - } 544 - 545 - mi->n_rates = n; 546 - mi->last_stats_update = jiffies; 547 - 548 - init_sample_table(mi); 549 - minstrel_update_rates(mp, mi); 550 - } 551 - 552 - static u32 minstrel_get_expected_throughput(void *priv_sta) 553 - { 554 - struct minstrel_sta_info *mi = priv_sta; 555 - struct minstrel_rate_stats *tmp_mrs; 556 - int idx = mi->max_tp_rate[0]; 557 - int tmp_cur_tp; 558 - 559 - /* convert pkt per sec in kbps (1200 is the average pkt size used for 560 - * computing cur_tp 561 - */ 562 - tmp_mrs = &mi->r[idx].stats; 563 - tmp_cur_tp = minstrel_get_tp_avg(&mi->r[idx], tmp_mrs->prob_avg) * 10; 564 - tmp_cur_tp = tmp_cur_tp * 1200 * 8 / 1024; 565 - 566 - return tmp_cur_tp; 567 - } 568 - 569 - const struct rate_control_ops mac80211_minstrel = { 570 - .tx_status_ext = minstrel_tx_status, 571 - .get_rate = minstrel_get_rate, 572 - .rate_init = minstrel_rate_init, 573 - .get_expected_throughput = minstrel_get_expected_throughput, 574 - };
-184
net/mac80211/rc80211_minstrel.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0-only */ 2 - /* 3 - * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> 4 - */ 5 - 6 - #ifndef __RC_MINSTREL_H 7 - #define __RC_MINSTREL_H 8 - 9 - #define EWMA_LEVEL 96 /* ewma weighting factor [/EWMA_DIV] */ 10 - #define EWMA_DIV 128 11 - #define SAMPLE_COLUMNS 10 /* number of columns in sample table */ 12 - 13 - /* scaled fraction values */ 14 - #define MINSTREL_SCALE 12 15 - #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) 16 - #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) 17 - 18 - /* number of highest throughput rates to consider*/ 19 - #define MAX_THR_RATES 4 20 - 21 - /* 22 - * Coefficients for moving average with noise filter (period=16), 23 - * scaled by 10 bits 24 - * 25 - * a1 = exp(-pi * sqrt(2) / period) 26 - * coeff2 = 2 * a1 * cos(sqrt(2) * 2 * pi / period) 27 - * coeff3 = -sqr(a1) 28 - * coeff1 = 1 - coeff2 - coeff3 29 - */ 30 - #define MINSTREL_AVG_COEFF1 (MINSTREL_FRAC(1, 1) - \ 31 - MINSTREL_AVG_COEFF2 - \ 32 - MINSTREL_AVG_COEFF3) 33 - #define MINSTREL_AVG_COEFF2 0x00001499 34 - #define MINSTREL_AVG_COEFF3 -0x0000092e 35 - 36 - /* 37 - * Perform EWMA (Exponentially Weighted Moving Average) calculation 38 - */ 39 - static inline int 40 - minstrel_ewma(int old, int new, int weight) 41 - { 42 - int diff, incr; 43 - 44 - diff = new - old; 45 - incr = (EWMA_DIV - weight) * diff / EWMA_DIV; 46 - 47 - return old + incr; 48 - } 49 - 50 - static inline int minstrel_filter_avg_add(u16 *prev_1, u16 *prev_2, s32 in) 51 - { 52 - s32 out_1 = *prev_1; 53 - s32 out_2 = *prev_2; 54 - s32 val; 55 - 56 - if (!in) 57 - in += 1; 58 - 59 - if (!out_1) { 60 - val = out_1 = in; 61 - goto out; 62 - } 63 - 64 - val = MINSTREL_AVG_COEFF1 * in; 65 - val += MINSTREL_AVG_COEFF2 * out_1; 66 - val += MINSTREL_AVG_COEFF3 * out_2; 67 - val >>= MINSTREL_SCALE; 68 - 69 - if (val > 1 << MINSTREL_SCALE) 70 - val = 1 << MINSTREL_SCALE; 71 - if (val < 0) 72 - val = 1; 73 - 74 - out: 75 - *prev_2 = out_1; 76 - *prev_1 = val; 77 - 78 - return val; 79 - } 80 - 81 - struct minstrel_rate_stats { 82 - /* current / last sampling period attempts/success counters */ 83 - u16 attempts, last_attempts; 84 - u16 success, last_success; 85 - 86 - /* total attempts/success counters */ 87 - u32 att_hist, succ_hist; 88 - 89 - /* prob_avg - moving average of prob */ 90 - u16 prob_avg; 91 - u16 prob_avg_1; 92 - 93 - /* maximum retry counts */ 94 - u8 retry_count; 95 - u8 retry_count_rtscts; 96 - 97 - u8 sample_skipped; 98 - bool retry_updated; 99 - }; 100 - 101 - struct minstrel_rate { 102 - int bitrate; 103 - 104 - s8 rix; 105 - u8 retry_count_cts; 106 - u8 adjusted_retry_count; 107 - 108 - unsigned int perfect_tx_time; 109 - unsigned int ack_time; 110 - 111 - int sample_limit; 112 - 113 - struct minstrel_rate_stats stats; 114 - }; 115 - 116 - struct minstrel_sta_info { 117 - struct ieee80211_sta *sta; 118 - 119 - unsigned long last_stats_update; 120 - unsigned int sp_ack_dur; 121 - unsigned int rate_avg; 122 - 123 - unsigned int lowest_rix; 124 - 125 - u8 max_tp_rate[MAX_THR_RATES]; 126 - u8 max_prob_rate; 127 - unsigned int total_packets; 128 - unsigned int sample_packets; 129 - 130 - unsigned int sample_row; 131 - unsigned int sample_column; 132 - 133 - int n_rates; 134 - struct minstrel_rate *r; 135 - bool prev_sample; 136 - 137 - /* sampling table */ 138 - u8 *sample_table; 139 - }; 140 - 141 - struct minstrel_priv { 142 - struct ieee80211_hw *hw; 143 - bool has_mrr; 144 - bool new_avg; 145 - u32 sample_switch; 146 - unsigned int cw_min; 147 - unsigned int cw_max; 148 - unsigned int max_retry; 149 - unsigned int segment_size; 150 - unsigned int update_interval; 151 - unsigned int lookaround_rate; 152 - unsigned int lookaround_rate_mrr; 153 - 154 - u8 cck_rates[4]; 155 - 156 - #ifdef CONFIG_MAC80211_DEBUGFS 157 - /* 158 - * enable fixed rate processing per RC 159 - * - write static index to debugfs:ieee80211/phyX/rc/fixed_rate_idx 160 - * - write -1 to enable RC processing again 161 - * - setting will be applied on next update 162 - */ 163 - u32 fixed_rate_idx; 164 - #endif 165 - }; 166 - 167 - struct minstrel_debugfs_info { 168 - size_t len; 169 - char buf[]; 170 - }; 171 - 172 - extern const struct rate_control_ops mac80211_minstrel; 173 - void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); 174 - 175 - /* Recalculate success probabilities and counters for a given rate using EWMA */ 176 - void minstrel_calc_rate_stats(struct minstrel_priv *mp, 177 - struct minstrel_rate_stats *mrs); 178 - int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg); 179 - 180 - /* debugfs */ 181 - int minstrel_stats_open(struct inode *inode, struct file *file); 182 - int minstrel_stats_csv_open(struct inode *inode, struct file *file); 183 - 184 - #endif
-172
net/mac80211/rc80211_minstrel_debugfs.c
··· 1 - /* 2 - * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> 3 - * 4 - * This program is free software; you can redistribute it and/or modify 5 - * it under the terms of the GNU General Public License version 2 as 6 - * published by the Free Software Foundation. 7 - * 8 - * Based on minstrel.c: 9 - * Copyright (C) 2005-2007 Derek Smithies <derek@indranet.co.nz> 10 - * Sponsored by Indranet Technologies Ltd 11 - * 12 - * Based on sample.c: 13 - * Copyright (c) 2005 John Bicket 14 - * All rights reserved. 15 - * 16 - * Redistribution and use in source and binary forms, with or without 17 - * modification, are permitted provided that the following conditions 18 - * are met: 19 - * 1. Redistributions of source code must retain the above copyright 20 - * notice, this list of conditions and the following disclaimer, 21 - * without modification. 22 - * 2. Redistributions in binary form must reproduce at minimum a disclaimer 23 - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 24 - * redistribution must be conditioned upon including a substantially 25 - * similar Disclaimer requirement for further binary redistribution. 26 - * 3. Neither the names of the above-listed copyright holders nor the names 27 - * of any contributors may be used to endorse or promote products derived 28 - * from this software without specific prior written permission. 29 - * 30 - * Alternatively, this software may be distributed under the terms of the 31 - * GNU General Public License ("GPL") version 2 as published by the Free 32 - * Software Foundation. 33 - * 34 - * NO WARRANTY 35 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 36 - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 37 - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 38 - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 39 - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 40 - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 41 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 42 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 43 - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 44 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 45 - * THE POSSIBILITY OF SUCH DAMAGES. 46 - */ 47 - #include <linux/netdevice.h> 48 - #include <linux/types.h> 49 - #include <linux/skbuff.h> 50 - #include <linux/debugfs.h> 51 - #include <linux/ieee80211.h> 52 - #include <linux/slab.h> 53 - #include <linux/export.h> 54 - #include <net/mac80211.h> 55 - #include "rc80211_minstrel.h" 56 - 57 - int 58 - minstrel_stats_open(struct inode *inode, struct file *file) 59 - { 60 - struct minstrel_sta_info *mi = inode->i_private; 61 - struct minstrel_debugfs_info *ms; 62 - unsigned int i, tp_max, tp_avg, eprob; 63 - char *p; 64 - 65 - ms = kmalloc(2048, GFP_KERNEL); 66 - if (!ms) 67 - return -ENOMEM; 68 - 69 - file->private_data = ms; 70 - p = ms->buf; 71 - p += sprintf(p, "\n"); 72 - p += sprintf(p, 73 - "best __________rate_________ ____statistics___ ____last_____ ______sum-of________\n"); 74 - p += sprintf(p, 75 - "rate [name idx airtime max_tp] [avg(tp) avg(prob)] [retry|suc|att] [#success | #attempts]\n"); 76 - 77 - for (i = 0; i < mi->n_rates; i++) { 78 - struct minstrel_rate *mr = &mi->r[i]; 79 - struct minstrel_rate_stats *mrs = &mi->r[i].stats; 80 - 81 - *(p++) = (i == mi->max_tp_rate[0]) ? 'A' : ' '; 82 - *(p++) = (i == mi->max_tp_rate[1]) ? 'B' : ' '; 83 - *(p++) = (i == mi->max_tp_rate[2]) ? 'C' : ' '; 84 - *(p++) = (i == mi->max_tp_rate[3]) ? 'D' : ' '; 85 - *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; 86 - 87 - p += sprintf(p, " %3u%s ", mr->bitrate / 2, 88 - (mr->bitrate & 1 ? ".5" : " ")); 89 - p += sprintf(p, "%3u ", i); 90 - p += sprintf(p, "%6u ", mr->perfect_tx_time); 91 - 92 - tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); 93 - tp_avg = minstrel_get_tp_avg(mr, mrs->prob_avg); 94 - eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000); 95 - 96 - p += sprintf(p, "%4u.%1u %4u.%1u %3u.%1u" 97 - " %3u %3u %-3u " 98 - "%9llu %-9llu\n", 99 - tp_max / 10, tp_max % 10, 100 - tp_avg / 10, tp_avg % 10, 101 - eprob / 10, eprob % 10, 102 - mrs->retry_count, 103 - mrs->last_success, 104 - mrs->last_attempts, 105 - (unsigned long long)mrs->succ_hist, 106 - (unsigned long long)mrs->att_hist); 107 - } 108 - p += sprintf(p, "\nTotal packet count:: ideal %d " 109 - "lookaround %d\n\n", 110 - mi->total_packets - mi->sample_packets, 111 - mi->sample_packets); 112 - ms->len = p - ms->buf; 113 - 114 - WARN_ON(ms->len + sizeof(*ms) > 2048); 115 - 116 - return 0; 117 - } 118 - 119 - int 120 - minstrel_stats_csv_open(struct inode *inode, struct file *file) 121 - { 122 - struct minstrel_sta_info *mi = inode->i_private; 123 - struct minstrel_debugfs_info *ms; 124 - unsigned int i, tp_max, tp_avg, eprob; 125 - char *p; 126 - 127 - ms = kmalloc(2048, GFP_KERNEL); 128 - if (!ms) 129 - return -ENOMEM; 130 - 131 - file->private_data = ms; 132 - p = ms->buf; 133 - 134 - for (i = 0; i < mi->n_rates; i++) { 135 - struct minstrel_rate *mr = &mi->r[i]; 136 - struct minstrel_rate_stats *mrs = &mi->r[i].stats; 137 - 138 - p += sprintf(p, "%s" ,((i == mi->max_tp_rate[0]) ? "A" : "")); 139 - p += sprintf(p, "%s" ,((i == mi->max_tp_rate[1]) ? "B" : "")); 140 - p += sprintf(p, "%s" ,((i == mi->max_tp_rate[2]) ? "C" : "")); 141 - p += sprintf(p, "%s" ,((i == mi->max_tp_rate[3]) ? "D" : "")); 142 - p += sprintf(p, "%s" ,((i == mi->max_prob_rate) ? "P" : "")); 143 - 144 - p += sprintf(p, ",%u%s", mr->bitrate / 2, 145 - (mr->bitrate & 1 ? ".5," : ",")); 146 - p += sprintf(p, "%u,", i); 147 - p += sprintf(p, "%u,",mr->perfect_tx_time); 148 - 149 - tp_max = minstrel_get_tp_avg(mr, MINSTREL_FRAC(100,100)); 150 - tp_avg = minstrel_get_tp_avg(mr, mrs->prob_avg); 151 - eprob = MINSTREL_TRUNC(mrs->prob_avg * 1000); 152 - 153 - p += sprintf(p, "%u.%u,%u.%u,%u.%u,%u,%u,%u," 154 - "%llu,%llu,%d,%d\n", 155 - tp_max / 10, tp_max % 10, 156 - tp_avg / 10, tp_avg % 10, 157 - eprob / 10, eprob % 10, 158 - mrs->retry_count, 159 - mrs->last_success, 160 - mrs->last_attempts, 161 - (unsigned long long)mrs->succ_hist, 162 - (unsigned long long)mrs->att_hist, 163 - mi->total_packets - mi->sample_packets, 164 - mi->sample_packets); 165 - 166 - } 167 - ms->len = p - ms->buf; 168 - 169 - WARN_ON(ms->len + sizeof(*ms) > 2048); 170 - 171 - return 0; 172 - }
+377 -189
net/mac80211/rc80211_minstrel_ht.c
··· 13 13 #include <net/mac80211.h> 14 14 #include "rate.h" 15 15 #include "sta_info.h" 16 - #include "rc80211_minstrel.h" 17 16 #include "rc80211_minstrel_ht.h" 18 17 19 18 #define AVG_AMPDU_SIZE 16 ··· 135 136 __VHT_GROUP(_streams, _sgi, _bw, \ 136 137 VHT_GROUP_SHIFT(_streams, _sgi, _bw)) 137 138 138 - #define CCK_DURATION(_bitrate, _short, _len) \ 139 + #define CCK_DURATION(_bitrate, _short) \ 139 140 (1000 * (10 /* SIFS */ + \ 140 141 (_short ? 72 + 24 : 144 + 48) + \ 141 - (8 * (_len + 4) * 10) / (_bitrate))) 142 - 143 - #define CCK_ACK_DURATION(_bitrate, _short) \ 144 - (CCK_DURATION((_bitrate > 10 ? 20 : 10), false, 60) + \ 145 - CCK_DURATION(_bitrate, _short, AVG_PKT_SIZE)) 142 + (8 * (AVG_PKT_SIZE + 4) * 10) / (_bitrate))) 146 143 147 144 #define CCK_DURATION_LIST(_short, _s) \ 148 - CCK_ACK_DURATION(10, _short) >> _s, \ 149 - CCK_ACK_DURATION(20, _short) >> _s, \ 150 - CCK_ACK_DURATION(55, _short) >> _s, \ 151 - CCK_ACK_DURATION(110, _short) >> _s 145 + CCK_DURATION(10, _short) >> _s, \ 146 + CCK_DURATION(20, _short) >> _s, \ 147 + CCK_DURATION(55, _short) >> _s, \ 148 + CCK_DURATION(110, _short) >> _s 152 149 153 150 #define __CCK_GROUP(_s) \ 154 151 [MINSTREL_CCK_GROUP] = { \ ··· 158 163 } 159 164 160 165 #define CCK_GROUP_SHIFT \ 161 - GROUP_SHIFT(CCK_ACK_DURATION(10, false)) 166 + GROUP_SHIFT(CCK_DURATION(10, false)) 162 167 163 168 #define CCK_GROUP __CCK_GROUP(CCK_GROUP_SHIFT) 169 + 170 + #define OFDM_DURATION(_bitrate) \ 171 + (1000 * (16 /* SIFS + signal ext */ + \ 172 + 16 /* T_PREAMBLE */ + \ 173 + 4 /* T_SIGNAL */ + \ 174 + 4 * (((16 + 80 * (AVG_PKT_SIZE + 4) + 6) / \ 175 + ((_bitrate) * 4))))) 176 + 177 + #define OFDM_DURATION_LIST(_s) \ 178 + OFDM_DURATION(60) >> _s, \ 179 + OFDM_DURATION(90) >> _s, \ 180 + OFDM_DURATION(120) >> _s, \ 181 + OFDM_DURATION(180) >> _s, \ 182 + OFDM_DURATION(240) >> _s, \ 183 + OFDM_DURATION(360) >> _s, \ 184 + OFDM_DURATION(480) >> _s, \ 185 + OFDM_DURATION(540) >> _s 186 + 187 + #define __OFDM_GROUP(_s) \ 188 + [MINSTREL_OFDM_GROUP] = { \ 189 + .streams = 1, \ 190 + .flags = 0, \ 191 + .shift = _s, \ 192 + .duration = { \ 193 + OFDM_DURATION_LIST(_s), \ 194 + } \ 195 + } 196 + 197 + #define OFDM_GROUP_SHIFT \ 198 + GROUP_SHIFT(OFDM_DURATION(60)) 199 + 200 + #define OFDM_GROUP __OFDM_GROUP(OFDM_GROUP_SHIFT) 164 201 165 202 166 203 static bool minstrel_vht_only = true; ··· 230 203 MCS_GROUP(4, 1, BW_40), 231 204 232 205 CCK_GROUP, 206 + OFDM_GROUP, 233 207 234 208 VHT_GROUP(1, 0, BW_20), 235 209 VHT_GROUP(2, 0, BW_20), ··· 263 235 VHT_GROUP(4, 1, BW_80), 264 236 }; 265 237 238 + const s16 minstrel_cck_bitrates[4] = { 10, 20, 55, 110 }; 239 + const s16 minstrel_ofdm_bitrates[8] = { 60, 90, 120, 180, 240, 360, 480, 540 }; 266 240 static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly; 267 241 268 242 static void ··· 309 279 return 0x3ff & ~mask; 310 280 } 311 281 282 + static bool 283 + minstrel_ht_is_legacy_group(int group) 284 + { 285 + return group == MINSTREL_CCK_GROUP || 286 + group == MINSTREL_OFDM_GROUP; 287 + } 288 + 312 289 /* 313 290 * Look up an MCS group index based on mac80211 rate information 314 291 */ ··· 345 308 if (rate->flags & IEEE80211_TX_RC_MCS) { 346 309 group = minstrel_ht_get_group_idx(rate); 347 310 idx = rate->idx % 8; 348 - } else if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { 311 + goto out; 312 + } 313 + 314 + if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { 349 315 group = minstrel_vht_get_group_idx(rate); 350 316 idx = ieee80211_rate_get_vht_mcs(rate); 351 - } else { 352 - group = MINSTREL_CCK_GROUP; 317 + goto out; 318 + } 353 319 354 - for (idx = 0; idx < ARRAY_SIZE(mp->cck_rates); idx++) 355 - if (rate->idx == mp->cck_rates[idx]) 356 - break; 320 + group = MINSTREL_CCK_GROUP; 321 + for (idx = 0; idx < ARRAY_SIZE(mp->cck_rates); idx++) { 322 + if (rate->idx != mp->cck_rates[idx]) 323 + continue; 357 324 358 325 /* short preamble */ 359 326 if ((mi->supported[group] & BIT(idx + 4)) && 360 327 (rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)) 361 - idx += 4; 328 + idx += 4; 329 + goto out; 362 330 } 331 + 332 + group = MINSTREL_OFDM_GROUP; 333 + for (idx = 0; idx < ARRAY_SIZE(mp->ofdm_rates[0]); idx++) 334 + if (rate->idx == mp->ofdm_rates[mi->band][idx]) 335 + goto out; 336 + 337 + idx = 0; 338 + out: 363 339 return &mi->groups[group].rates[idx]; 364 340 } 365 341 ··· 382 332 return &mi->groups[index / MCS_GROUP_RATES].rates[index % MCS_GROUP_RATES]; 383 333 } 384 334 335 + static inline int minstrel_get_duration(int index) 336 + { 337 + const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; 338 + unsigned int duration = group->duration[index % MCS_GROUP_RATES]; 339 + 340 + return duration << group->shift; 341 + } 342 + 385 343 static unsigned int 386 344 minstrel_ht_avg_ampdu_len(struct minstrel_ht_sta *mi) 387 345 { 388 - if (!mi->avg_ampdu_len) 389 - return AVG_AMPDU_SIZE; 346 + int duration; 390 347 391 - return MINSTREL_TRUNC(mi->avg_ampdu_len); 348 + if (mi->avg_ampdu_len) 349 + return MINSTREL_TRUNC(mi->avg_ampdu_len); 350 + 351 + if (minstrel_ht_is_legacy_group(mi->max_tp_rate[0] / MCS_GROUP_RATES)) 352 + return 1; 353 + 354 + duration = minstrel_get_duration(mi->max_tp_rate[0]); 355 + 356 + if (duration > 400 * 1000) 357 + return 2; 358 + 359 + if (duration > 250 * 1000) 360 + return 4; 361 + 362 + if (duration > 150 * 1000) 363 + return 8; 364 + 365 + return 16; 392 366 } 393 367 394 368 /* ··· 423 349 minstrel_ht_get_tp_avg(struct minstrel_ht_sta *mi, int group, int rate, 424 350 int prob_avg) 425 351 { 426 - unsigned int nsecs = 0; 352 + unsigned int nsecs = 0, overhead = mi->overhead; 353 + unsigned int ampdu_len = 1; 427 354 428 355 /* do not account throughput if sucess prob is below 10% */ 429 356 if (prob_avg < MINSTREL_FRAC(10, 100)) 430 357 return 0; 431 358 432 - if (group != MINSTREL_CCK_GROUP) 433 - nsecs = 1000 * mi->overhead / minstrel_ht_avg_ampdu_len(mi); 359 + if (minstrel_ht_is_legacy_group(group)) 360 + overhead = mi->overhead_legacy; 361 + else 362 + ampdu_len = minstrel_ht_avg_ampdu_len(mi); 434 363 364 + nsecs = 1000 * overhead / ampdu_len; 435 365 nsecs += minstrel_mcs_groups[group].duration[rate] << 436 366 minstrel_mcs_groups[group].shift; 437 367 ··· 445 367 * (prob is scaled - see MINSTREL_FRAC above) 446 368 */ 447 369 if (prob_avg > MINSTREL_FRAC(90, 100)) 448 - return MINSTREL_TRUNC(100000 * ((MINSTREL_FRAC(90, 100) * 1000) 449 - / nsecs)); 450 - else 451 - return MINSTREL_TRUNC(100000 * ((prob_avg * 1000) / nsecs)); 370 + prob_avg = MINSTREL_FRAC(90, 100); 371 + 372 + return MINSTREL_TRUNC(100 * ((prob_avg * 1000000) / nsecs)); 452 373 } 453 374 454 375 /* ··· 494 417 * Find and set the topmost probability rate per sta and per group 495 418 */ 496 419 static void 497 - minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index) 420 + minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 *dest, u16 index) 498 421 { 499 422 struct minstrel_mcs_group_data *mg; 500 423 struct minstrel_rate_stats *mrs; 501 424 int tmp_group, tmp_idx, tmp_tp_avg, tmp_prob; 502 - int max_tp_group, cur_tp_avg, cur_group, cur_idx; 425 + int max_tp_group, max_tp_idx, max_tp_prob; 426 + int cur_tp_avg, cur_group, cur_idx; 503 427 int max_gpr_group, max_gpr_idx; 504 428 int max_gpr_tp_avg, max_gpr_prob; 505 429 ··· 509 431 mg = &mi->groups[index / MCS_GROUP_RATES]; 510 432 mrs = &mg->rates[index % MCS_GROUP_RATES]; 511 433 512 - tmp_group = mi->max_prob_rate / MCS_GROUP_RATES; 513 - tmp_idx = mi->max_prob_rate % MCS_GROUP_RATES; 434 + tmp_group = *dest / MCS_GROUP_RATES; 435 + tmp_idx = *dest % MCS_GROUP_RATES; 514 436 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; 515 437 tmp_tp_avg = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); 516 438 517 439 /* if max_tp_rate[0] is from MCS_GROUP max_prob_rate get selected from 518 440 * MCS_GROUP as well as CCK_GROUP rates do not allow aggregation */ 519 441 max_tp_group = mi->max_tp_rate[0] / MCS_GROUP_RATES; 520 - if((index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) && 521 - (max_tp_group != MINSTREL_CCK_GROUP)) 442 + max_tp_idx = mi->max_tp_rate[0] % MCS_GROUP_RATES; 443 + max_tp_prob = mi->groups[max_tp_group].rates[max_tp_idx].prob_avg; 444 + 445 + if (minstrel_ht_is_legacy_group(index / MCS_GROUP_RATES) && 446 + !minstrel_ht_is_legacy_group(max_tp_group)) 447 + return; 448 + 449 + /* skip rates faster than max tp rate with lower prob */ 450 + if (minstrel_get_duration(mi->max_tp_rate[0]) > minstrel_get_duration(index) && 451 + mrs->prob_avg < max_tp_prob) 522 452 return; 523 453 524 454 max_gpr_group = mg->max_group_prob_rate / MCS_GROUP_RATES; ··· 537 451 cur_tp_avg = minstrel_ht_get_tp_avg(mi, cur_group, cur_idx, 538 452 mrs->prob_avg); 539 453 if (cur_tp_avg > tmp_tp_avg) 540 - mi->max_prob_rate = index; 454 + *dest = index; 541 455 542 456 max_gpr_tp_avg = minstrel_ht_get_tp_avg(mi, max_gpr_group, 543 457 max_gpr_idx, ··· 546 460 mg->max_group_prob_rate = index; 547 461 } else { 548 462 if (mrs->prob_avg > tmp_prob) 549 - mi->max_prob_rate = index; 463 + *dest = index; 550 464 if (mrs->prob_avg > max_gpr_prob) 551 465 mg->max_group_prob_rate = index; 552 466 } ··· 562 476 static void 563 477 minstrel_ht_assign_best_tp_rates(struct minstrel_ht_sta *mi, 564 478 u16 tmp_mcs_tp_rate[MAX_THR_RATES], 565 - u16 tmp_cck_tp_rate[MAX_THR_RATES]) 479 + u16 tmp_legacy_tp_rate[MAX_THR_RATES]) 566 480 { 567 481 unsigned int tmp_group, tmp_idx, tmp_cck_tp, tmp_mcs_tp, tmp_prob; 568 482 int i; 569 483 570 - tmp_group = tmp_cck_tp_rate[0] / MCS_GROUP_RATES; 571 - tmp_idx = tmp_cck_tp_rate[0] % MCS_GROUP_RATES; 484 + tmp_group = tmp_legacy_tp_rate[0] / MCS_GROUP_RATES; 485 + tmp_idx = tmp_legacy_tp_rate[0] % MCS_GROUP_RATES; 572 486 tmp_prob = mi->groups[tmp_group].rates[tmp_idx].prob_avg; 573 487 tmp_cck_tp = minstrel_ht_get_tp_avg(mi, tmp_group, tmp_idx, tmp_prob); 574 488 ··· 579 493 580 494 if (tmp_cck_tp > tmp_mcs_tp) { 581 495 for(i = 0; i < MAX_THR_RATES; i++) { 582 - minstrel_ht_sort_best_tp_rates(mi, tmp_cck_tp_rate[i], 496 + minstrel_ht_sort_best_tp_rates(mi, tmp_legacy_tp_rate[i], 583 497 tmp_mcs_tp_rate); 584 498 } 585 499 } ··· 596 510 struct minstrel_mcs_group_data *mg; 597 511 int tmp_max_streams, group, tmp_idx, tmp_prob; 598 512 int tmp_tp = 0; 513 + 514 + if (!mi->sta->ht_cap.ht_supported) 515 + return; 599 516 600 517 tmp_max_streams = minstrel_mcs_groups[mi->max_tp_rate[0] / 601 518 MCS_GROUP_RATES].streams; ··· 618 529 tmp_prob); 619 530 } 620 531 } 621 - } 622 - 623 - static inline int 624 - minstrel_get_duration(int index) 625 - { 626 - const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; 627 - unsigned int duration = group->duration[index % MCS_GROUP_RATES]; 628 - return duration << group->shift; 629 532 } 630 533 631 534 static bool ··· 739 658 mi->sample_mode = MINSTREL_SAMPLE_ACTIVE; 740 659 } 741 660 661 + static inline int 662 + minstrel_ewma(int old, int new, int weight) 663 + { 664 + int diff, incr; 665 + 666 + diff = new - old; 667 + incr = (EWMA_DIV - weight) * diff / EWMA_DIV; 668 + 669 + return old + incr; 670 + } 671 + 672 + static inline int minstrel_filter_avg_add(u16 *prev_1, u16 *prev_2, s32 in) 673 + { 674 + s32 out_1 = *prev_1; 675 + s32 out_2 = *prev_2; 676 + s32 val; 677 + 678 + if (!in) 679 + in += 1; 680 + 681 + if (!out_1) { 682 + val = out_1 = in; 683 + goto out; 684 + } 685 + 686 + val = MINSTREL_AVG_COEFF1 * in; 687 + val += MINSTREL_AVG_COEFF2 * out_1; 688 + val += MINSTREL_AVG_COEFF3 * out_2; 689 + val >>= MINSTREL_SCALE; 690 + 691 + if (val > 1 << MINSTREL_SCALE) 692 + val = 1 << MINSTREL_SCALE; 693 + if (val < 0) 694 + val = 1; 695 + 696 + out: 697 + *prev_2 = out_1; 698 + *prev_1 = val; 699 + 700 + return val; 701 + } 702 + 703 + /* 704 + * Recalculate statistics and counters of a given rate 705 + */ 706 + static void 707 + minstrel_ht_calc_rate_stats(struct minstrel_priv *mp, 708 + struct minstrel_rate_stats *mrs) 709 + { 710 + unsigned int cur_prob; 711 + 712 + if (unlikely(mrs->attempts > 0)) { 713 + mrs->sample_skipped = 0; 714 + cur_prob = MINSTREL_FRAC(mrs->success, mrs->attempts); 715 + minstrel_filter_avg_add(&mrs->prob_avg, 716 + &mrs->prob_avg_1, cur_prob); 717 + mrs->att_hist += mrs->attempts; 718 + mrs->succ_hist += mrs->success; 719 + } else { 720 + mrs->sample_skipped++; 721 + } 722 + 723 + mrs->last_success = mrs->success; 724 + mrs->last_attempts = mrs->attempts; 725 + mrs->success = 0; 726 + mrs->attempts = 0; 727 + } 728 + 742 729 /* 743 730 * Update rate statistics and select new primary rates 744 731 * ··· 824 675 struct minstrel_rate_stats *mrs; 825 676 int group, i, j, cur_prob; 826 677 u16 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES]; 827 - u16 tmp_cck_tp_rate[MAX_THR_RATES], index; 678 + u16 tmp_legacy_tp_rate[MAX_THR_RATES], tmp_max_prob_rate; 679 + u16 index; 680 + bool ht_supported = mi->sta->ht_cap.ht_supported; 828 681 829 682 mi->sample_mode = MINSTREL_SAMPLE_IDLE; 830 683 ··· 855 704 mi->sample_count = 0; 856 705 857 706 memset(tmp_mcs_tp_rate, 0, sizeof(tmp_mcs_tp_rate)); 858 - memset(tmp_cck_tp_rate, 0, sizeof(tmp_cck_tp_rate)); 707 + memset(tmp_legacy_tp_rate, 0, sizeof(tmp_legacy_tp_rate)); 859 708 if (mi->supported[MINSTREL_CCK_GROUP]) 860 - for (j = 0; j < ARRAY_SIZE(tmp_cck_tp_rate); j++) 861 - tmp_cck_tp_rate[j] = MINSTREL_CCK_GROUP * MCS_GROUP_RATES; 709 + for (j = 0; j < ARRAY_SIZE(tmp_legacy_tp_rate); j++) 710 + tmp_legacy_tp_rate[j] = MINSTREL_CCK_GROUP * MCS_GROUP_RATES; 711 + else if (mi->supported[MINSTREL_OFDM_GROUP]) 712 + for (j = 0; j < ARRAY_SIZE(tmp_legacy_tp_rate); j++) 713 + tmp_legacy_tp_rate[j] = MINSTREL_OFDM_GROUP * MCS_GROUP_RATES; 862 714 863 715 if (mi->supported[MINSTREL_VHT_GROUP_0]) 864 716 index = MINSTREL_VHT_GROUP_0 * MCS_GROUP_RATES; 865 - else 717 + else if (ht_supported) 866 718 index = MINSTREL_HT_GROUP_0 * MCS_GROUP_RATES; 719 + else if (mi->supported[MINSTREL_CCK_GROUP]) 720 + index = MINSTREL_CCK_GROUP * MCS_GROUP_RATES; 721 + else 722 + index = MINSTREL_OFDM_GROUP * MCS_GROUP_RATES; 867 723 724 + tmp_max_prob_rate = index; 868 725 for (j = 0; j < ARRAY_SIZE(tmp_mcs_tp_rate); j++) 869 726 tmp_mcs_tp_rate[j] = index; 870 727 871 728 /* Find best rate sets within all MCS groups*/ 872 729 for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { 730 + u16 *tp_rate = tmp_mcs_tp_rate; 873 731 874 732 mg = &mi->groups[group]; 875 733 if (!mi->supported[group]) ··· 890 730 for(j = 0; j < MAX_THR_RATES; j++) 891 731 tmp_group_tp_rate[j] = MCS_GROUP_RATES * group; 892 732 733 + if (group == MINSTREL_CCK_GROUP && ht_supported) 734 + tp_rate = tmp_legacy_tp_rate; 735 + 893 736 for (i = 0; i < MCS_GROUP_RATES; i++) { 894 737 if (!(mi->supported[group] & BIT(i))) 895 738 continue; ··· 901 738 902 739 mrs = &mg->rates[i]; 903 740 mrs->retry_updated = false; 904 - minstrel_calc_rate_stats(mp, mrs); 741 + minstrel_ht_calc_rate_stats(mp, mrs); 905 742 cur_prob = mrs->prob_avg; 906 743 907 744 if (minstrel_ht_get_tp_avg(mi, group, i, cur_prob) == 0) 908 745 continue; 909 746 910 747 /* Find max throughput rate set */ 911 - if (group != MINSTREL_CCK_GROUP) { 912 - minstrel_ht_sort_best_tp_rates(mi, index, 913 - tmp_mcs_tp_rate); 914 - } else if (group == MINSTREL_CCK_GROUP) { 915 - minstrel_ht_sort_best_tp_rates(mi, index, 916 - tmp_cck_tp_rate); 917 - } 748 + minstrel_ht_sort_best_tp_rates(mi, index, tp_rate); 918 749 919 750 /* Find max throughput rate set within a group */ 920 751 minstrel_ht_sort_best_tp_rates(mi, index, 921 752 tmp_group_tp_rate); 922 - 923 - /* Find max probability rate per group and global */ 924 - minstrel_ht_set_best_prob_rate(mi, index); 925 753 } 926 754 927 755 memcpy(mg->max_group_tp_rate, tmp_group_tp_rate, ··· 920 766 } 921 767 922 768 /* Assign new rate set per sta */ 923 - minstrel_ht_assign_best_tp_rates(mi, tmp_mcs_tp_rate, tmp_cck_tp_rate); 769 + minstrel_ht_assign_best_tp_rates(mi, tmp_mcs_tp_rate, 770 + tmp_legacy_tp_rate); 924 771 memcpy(mi->max_tp_rate, tmp_mcs_tp_rate, sizeof(mi->max_tp_rate)); 772 + 773 + for (group = 0; group < ARRAY_SIZE(minstrel_mcs_groups); group++) { 774 + if (!mi->supported[group]) 775 + continue; 776 + 777 + mg = &mi->groups[group]; 778 + mg->max_group_prob_rate = MCS_GROUP_RATES * group; 779 + 780 + for (i = 0; i < MCS_GROUP_RATES; i++) { 781 + if (!(mi->supported[group] & BIT(i))) 782 + continue; 783 + 784 + index = MCS_GROUP_RATES * group + i; 785 + 786 + /* Find max probability rate per group and global */ 787 + minstrel_ht_set_best_prob_rate(mi, &tmp_max_prob_rate, 788 + index); 789 + } 790 + } 791 + 792 + mi->max_prob_rate = tmp_max_prob_rate; 925 793 926 794 /* Try to increase robustness of max_prob_rate*/ 927 795 minstrel_ht_prob_rate_reduce_streams(mi); 928 796 929 - /* try to sample all available rates during each interval */ 930 - mi->sample_count *= 8; 931 - if (mp->new_avg) 932 - mi->sample_count /= 2; 797 + /* try to sample half of all available rates during each interval */ 798 + mi->sample_count *= 4; 933 799 934 800 if (sample) 935 801 minstrel_ht_rate_sample_switch(mp, mi); ··· 969 795 } 970 796 971 797 static bool 972 - minstrel_ht_txstat_valid(struct minstrel_priv *mp, struct ieee80211_tx_rate *rate) 798 + minstrel_ht_txstat_valid(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, 799 + struct ieee80211_tx_rate *rate) 973 800 { 801 + int i; 802 + 974 803 if (rate->idx < 0) 975 804 return false; 976 805 ··· 984 807 rate->flags & IEEE80211_TX_RC_VHT_MCS) 985 808 return true; 986 809 987 - return rate->idx == mp->cck_rates[0] || 988 - rate->idx == mp->cck_rates[1] || 989 - rate->idx == mp->cck_rates[2] || 990 - rate->idx == mp->cck_rates[3]; 810 + for (i = 0; i < ARRAY_SIZE(mp->cck_rates); i++) 811 + if (rate->idx == mp->cck_rates[i]) 812 + return true; 813 + 814 + for (i = 0; i < ARRAY_SIZE(mp->ofdm_rates[0]); i++) 815 + if (rate->idx == mp->ofdm_rates[mi->band][i]) 816 + return true; 817 + 818 + return false; 991 819 } 992 820 993 821 static void ··· 1069 887 void *priv_sta, struct ieee80211_tx_status *st) 1070 888 { 1071 889 struct ieee80211_tx_info *info = st->info; 1072 - struct minstrel_ht_sta_priv *msp = priv_sta; 1073 - struct minstrel_ht_sta *mi = &msp->ht; 890 + struct minstrel_ht_sta *mi = priv_sta; 1074 891 struct ieee80211_tx_rate *ar = info->status.rates; 1075 892 struct minstrel_rate_stats *rate, *rate2, *rate_sample = NULL; 1076 893 struct minstrel_priv *mp = priv; 1077 - u32 update_interval = mp->update_interval / 2; 894 + u32 update_interval = mp->update_interval; 1078 895 bool last, update = false; 1079 896 bool sample_status = false; 1080 897 int i; 1081 - 1082 - if (!msp->is_ht) 1083 - return mac80211_minstrel.tx_status_ext(priv, sband, 1084 - &msp->legacy, st); 1085 - 1086 898 1087 899 /* This packet was aggregated but doesn't carry status info */ 1088 900 if ((info->flags & IEEE80211_TX_CTL_AMPDU) && ··· 1106 930 if (mi->sample_mode != MINSTREL_SAMPLE_IDLE) 1107 931 rate_sample = minstrel_get_ratestats(mi, mi->sample_rate); 1108 932 1109 - last = !minstrel_ht_txstat_valid(mp, &ar[0]); 933 + last = !minstrel_ht_txstat_valid(mp, mi, &ar[0]); 1110 934 for (i = 0; !last; i++) { 1111 935 last = (i == IEEE80211_TX_MAX_RATES - 1) || 1112 - !minstrel_ht_txstat_valid(mp, &ar[i + 1]); 936 + !minstrel_ht_txstat_valid(mp, mi, &ar[i + 1]); 1113 937 1114 938 rate = minstrel_ht_get_stats(mp, mi, &ar[i]); 1115 939 if (rate == rate_sample) ··· 1123 947 1124 948 switch (mi->sample_mode) { 1125 949 case MINSTREL_SAMPLE_IDLE: 1126 - if (mp->new_avg && 1127 - (mp->hw->max_rates > 1 || 1128 - mi->total_packets_cur < SAMPLE_SWITCH_THR)) 950 + if (mp->hw->max_rates > 1 || 951 + mi->total_packets_cur < SAMPLE_SWITCH_THR) 1129 952 update_interval /= 2; 1130 953 break; 1131 954 ··· 1206 1031 ctime += (t_slot * cw) >> 1; 1207 1032 cw = min((cw << 1) | 1, mp->cw_max); 1208 1033 1209 - if (index / MCS_GROUP_RATES != MINSTREL_CCK_GROUP) { 1034 + if (minstrel_ht_is_legacy_group(index / MCS_GROUP_RATES)) { 1035 + overhead = mi->overhead_legacy; 1036 + overhead_rtscts = mi->overhead_legacy_rtscts; 1037 + } else { 1210 1038 overhead = mi->overhead; 1211 1039 overhead_rtscts = mi->overhead_rtscts; 1212 1040 } ··· 1239 1061 minstrel_ht_set_rate(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, 1240 1062 struct ieee80211_sta_rates *ratetbl, int offset, int index) 1241 1063 { 1242 - const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; 1064 + int group_idx = index / MCS_GROUP_RATES; 1065 + const struct mcs_group *group = &minstrel_mcs_groups[group_idx]; 1243 1066 struct minstrel_rate_stats *mrs; 1244 1067 u8 idx; 1245 1068 u16 flags = group->flags; ··· 1259 1080 ratetbl->rate[offset].count_rts = mrs->retry_count_rtscts; 1260 1081 } 1261 1082 1262 - if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) 1083 + index %= MCS_GROUP_RATES; 1084 + if (group_idx == MINSTREL_CCK_GROUP) 1263 1085 idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)]; 1086 + else if (group_idx == MINSTREL_OFDM_GROUP) 1087 + idx = mp->ofdm_rates[mi->band][index % 1088 + ARRAY_SIZE(mp->ofdm_rates[0])]; 1264 1089 else if (flags & IEEE80211_TX_RC_VHT_MCS) 1265 1090 idx = ((group->streams - 1) << 4) | 1266 - ((index % MCS_GROUP_RATES) & 0xF); 1091 + (index & 0xF); 1267 1092 else 1268 - idx = index % MCS_GROUP_RATES + (group->streams - 1) * 8; 1093 + idx = index + (group->streams - 1) * 8; 1269 1094 1270 1095 /* enable RTS/CTS if needed: 1271 1096 * - if station is in dynamic SMPS (and streams > 1) ··· 1407 1224 mrs = &mg->rates[sample_idx]; 1408 1225 sample_idx += sample_group * MCS_GROUP_RATES; 1409 1226 1410 - /* Set tp_rate1, tp_rate2 to the highest / second highest max_tp_rate */ 1227 + tp_rate1 = mi->max_tp_rate[0]; 1228 + 1229 + /* Set tp_rate2 to the second highest max_tp_rate */ 1411 1230 if (minstrel_get_duration(mi->max_tp_rate[0]) > 1412 1231 minstrel_get_duration(mi->max_tp_rate[1])) { 1413 - tp_rate1 = mi->max_tp_rate[1]; 1414 1232 tp_rate2 = mi->max_tp_rate[0]; 1415 1233 } else { 1416 - tp_rate1 = mi->max_tp_rate[0]; 1417 1234 tp_rate2 = mi->max_tp_rate[1]; 1418 1235 } 1419 1236 ··· 1479 1296 const struct mcs_group *sample_group; 1480 1297 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(txrc->skb); 1481 1298 struct ieee80211_tx_rate *rate = &info->status.rates[0]; 1482 - struct minstrel_ht_sta_priv *msp = priv_sta; 1483 - struct minstrel_ht_sta *mi = &msp->ht; 1299 + struct minstrel_ht_sta *mi = priv_sta; 1484 1300 struct minstrel_priv *mp = priv; 1485 1301 int sample_idx; 1486 1302 1487 - if (!msp->is_ht) 1488 - return mac80211_minstrel.get_rate(priv, sta, &msp->legacy, txrc); 1489 - 1490 1303 if (!(info->flags & IEEE80211_TX_CTL_AMPDU) && 1491 - mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP) 1304 + !minstrel_ht_is_legacy_group(mi->max_prob_rate / MCS_GROUP_RATES)) 1492 1305 minstrel_aggr_check(sta, txrc->skb); 1493 1306 1494 1307 info->flags |= mi->tx_flags; ··· 1525 1346 if (sample_group == &minstrel_mcs_groups[MINSTREL_CCK_GROUP]) { 1526 1347 int idx = sample_idx % ARRAY_SIZE(mp->cck_rates); 1527 1348 rate->idx = mp->cck_rates[idx]; 1349 + } else if (sample_group == &minstrel_mcs_groups[MINSTREL_OFDM_GROUP]) { 1350 + int idx = sample_idx % ARRAY_SIZE(mp->ofdm_rates[0]); 1351 + rate->idx = mp->ofdm_rates[mi->band][idx]; 1528 1352 } else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) { 1529 1353 ieee80211_rate_set_vht(rate, sample_idx % MCS_GROUP_RATES, 1530 1354 sample_group->streams); ··· 1548 1366 if (sband->band != NL80211_BAND_2GHZ) 1549 1367 return; 1550 1368 1551 - if (!ieee80211_hw_check(mp->hw, SUPPORTS_HT_CCK_RATES)) 1369 + if (sta->ht_cap.ht_supported && 1370 + !ieee80211_hw_check(mp->hw, SUPPORTS_HT_CCK_RATES)) 1552 1371 return; 1553 1372 1554 - mi->cck_supported = 0; 1555 - mi->cck_supported_short = 0; 1556 1373 for (i = 0; i < 4; i++) { 1557 - if (!rate_supported(sta, sband->band, mp->cck_rates[i])) 1374 + if (mp->cck_rates[i] == 0xff || 1375 + !rate_supported(sta, sband->band, mp->cck_rates[i])) 1558 1376 continue; 1559 1377 1560 - mi->cck_supported |= BIT(i); 1378 + mi->supported[MINSTREL_CCK_GROUP] |= BIT(i); 1561 1379 if (sband->bitrates[i].flags & IEEE80211_RATE_SHORT_PREAMBLE) 1562 - mi->cck_supported_short |= BIT(i); 1380 + mi->supported[MINSTREL_CCK_GROUP] |= BIT(i + 4); 1563 1381 } 1382 + } 1564 1383 1565 - mi->supported[MINSTREL_CCK_GROUP] = mi->cck_supported; 1384 + static void 1385 + minstrel_ht_update_ofdm(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, 1386 + struct ieee80211_supported_band *sband, 1387 + struct ieee80211_sta *sta) 1388 + { 1389 + const u8 *rates; 1390 + int i; 1391 + 1392 + if (sta->ht_cap.ht_supported) 1393 + return; 1394 + 1395 + rates = mp->ofdm_rates[sband->band]; 1396 + for (i = 0; i < ARRAY_SIZE(mp->ofdm_rates[0]); i++) { 1397 + if (rates[i] == 0xff || 1398 + !rate_supported(sta, sband->band, rates[i])) 1399 + continue; 1400 + 1401 + mi->supported[MINSTREL_OFDM_GROUP] |= BIT(i); 1402 + } 1566 1403 } 1567 1404 1568 1405 static void 1569 1406 minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, 1570 1407 struct cfg80211_chan_def *chandef, 1571 - struct ieee80211_sta *sta, void *priv_sta) 1408 + struct ieee80211_sta *sta, void *priv_sta) 1572 1409 { 1573 1410 struct minstrel_priv *mp = priv; 1574 - struct minstrel_ht_sta_priv *msp = priv_sta; 1575 - struct minstrel_ht_sta *mi = &msp->ht; 1411 + struct minstrel_ht_sta *mi = priv_sta; 1576 1412 struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs; 1577 1413 u16 ht_cap = sta->ht_cap.cap; 1578 1414 struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; 1415 + const struct ieee80211_rate *ctl_rate; 1416 + bool ldpc, erp; 1579 1417 int use_vht; 1580 1418 int n_supported = 0; 1581 1419 int ack_dur; 1582 1420 int stbc; 1583 1421 int i; 1584 - bool ldpc; 1585 - 1586 - /* fall back to the old minstrel for legacy stations */ 1587 - if (!sta->ht_cap.ht_supported) 1588 - goto use_legacy; 1589 1422 1590 1423 BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != MINSTREL_GROUPS_NB); 1591 1424 ··· 1609 1412 else 1610 1413 use_vht = 0; 1611 1414 1612 - msp->is_ht = true; 1613 1415 memset(mi, 0, sizeof(*mi)); 1614 1416 1615 1417 mi->sta = sta; 1418 + mi->band = sband->band; 1616 1419 mi->last_stats_update = jiffies; 1617 1420 1618 1421 ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1, 0); 1619 1422 mi->overhead = ieee80211_frame_duration(sband->band, 0, 60, 1, 1, 0); 1620 1423 mi->overhead += ack_dur; 1621 1424 mi->overhead_rtscts = mi->overhead + 2 * ack_dur; 1425 + 1426 + ctl_rate = &sband->bitrates[rate_lowest_index(sband, sta)]; 1427 + erp = ctl_rate->flags & IEEE80211_RATE_ERP_G; 1428 + ack_dur = ieee80211_frame_duration(sband->band, 10, 1429 + ctl_rate->bitrate, erp, 1, 1430 + ieee80211_chandef_get_shift(chandef)); 1431 + mi->overhead_legacy = ack_dur; 1432 + mi->overhead_legacy_rtscts = mi->overhead_legacy + 2 * ack_dur; 1622 1433 1623 1434 mi->avg_ampdu_len = MINSTREL_FRAC(1, 1); 1624 1435 ··· 1661 1456 int bw, nss; 1662 1457 1663 1458 mi->supported[i] = 0; 1664 - if (i == MINSTREL_CCK_GROUP) { 1665 - minstrel_ht_update_cck(mp, mi, sband, sta); 1459 + if (minstrel_ht_is_legacy_group(i)) 1666 1460 continue; 1667 - } 1668 1461 1669 1462 if (gflags & IEEE80211_TX_RC_SHORT_GI) { 1670 1463 if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH) { ··· 1723 1520 n_supported++; 1724 1521 } 1725 1522 1726 - if (!n_supported) 1727 - goto use_legacy; 1728 - 1729 - mi->supported[MINSTREL_CCK_GROUP] |= mi->cck_supported_short << 4; 1523 + minstrel_ht_update_cck(mp, mi, sband, sta); 1524 + minstrel_ht_update_ofdm(mp, mi, sband, sta); 1730 1525 1731 1526 /* create an initial rate table with the lowest supported rates */ 1732 1527 minstrel_ht_update_stats(mp, mi, true); 1733 1528 minstrel_ht_update_rates(mp, mi); 1734 - 1735 - return; 1736 - 1737 - use_legacy: 1738 - msp->is_ht = false; 1739 - memset(&msp->legacy, 0, sizeof(msp->legacy)); 1740 - msp->legacy.r = msp->ratelist; 1741 - msp->legacy.sample_table = msp->sample_table; 1742 - return mac80211_minstrel.rate_init(priv, sband, chandef, sta, 1743 - &msp->legacy); 1744 1529 } 1745 1530 1746 1531 static void ··· 1752 1561 minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) 1753 1562 { 1754 1563 struct ieee80211_supported_band *sband; 1755 - struct minstrel_ht_sta_priv *msp; 1564 + struct minstrel_ht_sta *mi; 1756 1565 struct minstrel_priv *mp = priv; 1757 1566 struct ieee80211_hw *hw = mp->hw; 1758 1567 int max_rates = 0; ··· 1764 1573 max_rates = sband->n_bitrates; 1765 1574 } 1766 1575 1767 - msp = kzalloc(sizeof(*msp), gfp); 1768 - if (!msp) 1769 - return NULL; 1770 - 1771 - msp->ratelist = kcalloc(max_rates, sizeof(struct minstrel_rate), gfp); 1772 - if (!msp->ratelist) 1773 - goto error; 1774 - 1775 - msp->sample_table = kmalloc_array(max_rates, SAMPLE_COLUMNS, gfp); 1776 - if (!msp->sample_table) 1777 - goto error1; 1778 - 1779 - return msp; 1780 - 1781 - error1: 1782 - kfree(msp->ratelist); 1783 - error: 1784 - kfree(msp); 1785 - return NULL; 1576 + return kzalloc(sizeof(*mi), gfp); 1786 1577 } 1787 1578 1788 1579 static void 1789 1580 minstrel_ht_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta) 1790 1581 { 1791 - struct minstrel_ht_sta_priv *msp = priv_sta; 1582 + kfree(priv_sta); 1583 + } 1792 1584 1793 - kfree(msp->sample_table); 1794 - kfree(msp->ratelist); 1795 - kfree(msp); 1585 + static void 1586 + minstrel_ht_fill_rate_array(u8 *dest, struct ieee80211_supported_band *sband, 1587 + const s16 *bitrates, int n_rates, u32 rate_flags) 1588 + { 1589 + int i, j; 1590 + 1591 + for (i = 0; i < sband->n_bitrates; i++) { 1592 + struct ieee80211_rate *rate = &sband->bitrates[i]; 1593 + 1594 + if ((rate_flags & sband->bitrates[i].flags) != rate_flags) 1595 + continue; 1596 + 1597 + for (j = 0; j < n_rates; j++) { 1598 + if (rate->bitrate != bitrates[j]) 1599 + continue; 1600 + 1601 + dest[j] = i; 1602 + break; 1603 + } 1604 + } 1796 1605 } 1797 1606 1798 1607 static void 1799 1608 minstrel_ht_init_cck_rates(struct minstrel_priv *mp) 1800 1609 { 1801 - static const int bitrates[4] = { 10, 20, 55, 110 }; 1610 + static const s16 bitrates[4] = { 10, 20, 55, 110 }; 1802 1611 struct ieee80211_supported_band *sband; 1803 1612 u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); 1804 - int i, j; 1805 1613 1614 + memset(mp->cck_rates, 0xff, sizeof(mp->cck_rates)); 1806 1615 sband = mp->hw->wiphy->bands[NL80211_BAND_2GHZ]; 1807 1616 if (!sband) 1808 1617 return; 1809 1618 1810 - for (i = 0; i < sband->n_bitrates; i++) { 1811 - struct ieee80211_rate *rate = &sband->bitrates[i]; 1619 + BUILD_BUG_ON(ARRAY_SIZE(mp->cck_rates) != ARRAY_SIZE(bitrates)); 1620 + minstrel_ht_fill_rate_array(mp->cck_rates, sband, 1621 + minstrel_cck_bitrates, 1622 + ARRAY_SIZE(minstrel_cck_bitrates), 1623 + rate_flags); 1624 + } 1812 1625 1813 - if (rate->flags & IEEE80211_RATE_ERP_G) 1814 - continue; 1626 + static void 1627 + minstrel_ht_init_ofdm_rates(struct minstrel_priv *mp, enum nl80211_band band) 1628 + { 1629 + static const s16 bitrates[8] = { 60, 90, 120, 180, 240, 360, 480, 540 }; 1630 + struct ieee80211_supported_band *sband; 1631 + u32 rate_flags = ieee80211_chandef_rate_flags(&mp->hw->conf.chandef); 1815 1632 1816 - if ((rate_flags & sband->bitrates[i].flags) != rate_flags) 1817 - continue; 1633 + memset(mp->ofdm_rates[band], 0xff, sizeof(mp->ofdm_rates[band])); 1634 + sband = mp->hw->wiphy->bands[band]; 1635 + if (!sband) 1636 + return; 1818 1637 1819 - for (j = 0; j < ARRAY_SIZE(bitrates); j++) { 1820 - if (rate->bitrate != bitrates[j]) 1821 - continue; 1822 - 1823 - mp->cck_rates[j] = i; 1824 - break; 1825 - } 1826 - } 1638 + BUILD_BUG_ON(ARRAY_SIZE(mp->ofdm_rates[band]) != ARRAY_SIZE(bitrates)); 1639 + minstrel_ht_fill_rate_array(mp->ofdm_rates[band], sband, 1640 + minstrel_ofdm_bitrates, 1641 + ARRAY_SIZE(minstrel_ofdm_bitrates), 1642 + rate_flags); 1827 1643 } 1828 1644 1829 1645 static void * 1830 1646 minstrel_ht_alloc(struct ieee80211_hw *hw) 1831 1647 { 1832 1648 struct minstrel_priv *mp; 1649 + int i; 1833 1650 1834 1651 mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC); 1835 1652 if (!mp) ··· 1850 1651 * the calculations and is probably unnecessary */ 1851 1652 mp->cw_min = 15; 1852 1653 mp->cw_max = 1023; 1853 - 1854 - /* number of packets (in %) to use for sampling other rates 1855 - * sample less often for non-mrr packets, because the overhead 1856 - * is much higher than with mrr */ 1857 - mp->lookaround_rate = 5; 1858 - mp->lookaround_rate_mrr = 10; 1859 1654 1860 1655 /* maximum time that the hw is allowed to stay in one MRR segment */ 1861 1656 mp->segment_size = 6000; ··· 1865 1672 1866 1673 mp->hw = hw; 1867 1674 mp->update_interval = HZ / 10; 1868 - mp->new_avg = true; 1869 1675 1870 1676 minstrel_ht_init_cck_rates(mp); 1677 + for (i = 0; i < ARRAY_SIZE(mp->hw->wiphy->bands); i++) 1678 + minstrel_ht_init_ofdm_rates(mp, i); 1871 1679 1872 1680 return mp; 1873 1681 } ··· 1884 1690 &mp->fixed_rate_idx); 1885 1691 debugfs_create_u32("sample_switch", S_IRUGO | S_IWUSR, debugfsdir, 1886 1692 &mp->sample_switch); 1887 - debugfs_create_bool("new_avg", S_IRUGO | S_IWUSR, debugfsdir, 1888 - &mp->new_avg); 1889 1693 } 1890 1694 #endif 1891 1695 ··· 1895 1703 1896 1704 static u32 minstrel_ht_get_expected_throughput(void *priv_sta) 1897 1705 { 1898 - struct minstrel_ht_sta_priv *msp = priv_sta; 1899 - struct minstrel_ht_sta *mi = &msp->ht; 1706 + struct minstrel_ht_sta *mi = priv_sta; 1900 1707 int i, j, prob, tp_avg; 1901 - 1902 - if (!msp->is_ht) 1903 - return mac80211_minstrel.get_expected_throughput(priv_sta); 1904 1708 1905 1709 i = mi->max_tp_rate[0] / MCS_GROUP_RATES; 1906 1710 j = mi->max_tp_rate[0] % MCS_GROUP_RATES;
+81 -15
net/mac80211/rc80211_minstrel_ht.h
··· 6 6 #ifndef __RC_MINSTREL_HT_H 7 7 #define __RC_MINSTREL_HT_H 8 8 9 + /* number of highest throughput rates to consider*/ 10 + #define MAX_THR_RATES 4 11 + #define SAMPLE_COLUMNS 10 /* number of columns in sample table */ 12 + 13 + /* scaled fraction values */ 14 + #define MINSTREL_SCALE 12 15 + #define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) 16 + #define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) 17 + 18 + #define EWMA_LEVEL 96 /* ewma weighting factor [/EWMA_DIV] */ 19 + #define EWMA_DIV 128 20 + 21 + /* 22 + * Coefficients for moving average with noise filter (period=16), 23 + * scaled by 10 bits 24 + * 25 + * a1 = exp(-pi * sqrt(2) / period) 26 + * coeff2 = 2 * a1 * cos(sqrt(2) * 2 * pi / period) 27 + * coeff3 = -sqr(a1) 28 + * coeff1 = 1 - coeff2 - coeff3 29 + */ 30 + #define MINSTREL_AVG_COEFF1 (MINSTREL_FRAC(1, 1) - \ 31 + MINSTREL_AVG_COEFF2 - \ 32 + MINSTREL_AVG_COEFF3) 33 + #define MINSTREL_AVG_COEFF2 0x00001499 34 + #define MINSTREL_AVG_COEFF3 -0x0000092e 35 + 9 36 /* 10 37 * The number of streams can be changed to 2 to reduce code 11 38 * size and memory footprint. ··· 45 18 MINSTREL_HT_STREAM_GROUPS) 46 19 #define MINSTREL_VHT_GROUPS_NB (MINSTREL_MAX_STREAMS * \ 47 20 MINSTREL_VHT_STREAM_GROUPS) 48 - #define MINSTREL_CCK_GROUPS_NB 1 21 + #define MINSTREL_LEGACY_GROUPS_NB 2 49 22 #define MINSTREL_GROUPS_NB (MINSTREL_HT_GROUPS_NB + \ 50 23 MINSTREL_VHT_GROUPS_NB + \ 51 - MINSTREL_CCK_GROUPS_NB) 24 + MINSTREL_LEGACY_GROUPS_NB) 52 25 53 26 #define MINSTREL_HT_GROUP_0 0 54 27 #define MINSTREL_CCK_GROUP (MINSTREL_HT_GROUP_0 + MINSTREL_HT_GROUPS_NB) 55 - #define MINSTREL_VHT_GROUP_0 (MINSTREL_CCK_GROUP + 1) 28 + #define MINSTREL_OFDM_GROUP (MINSTREL_CCK_GROUP + 1) 29 + #define MINSTREL_VHT_GROUP_0 (MINSTREL_OFDM_GROUP + 1) 56 30 57 31 #define MCS_GROUP_RATES 10 32 + 33 + struct minstrel_priv { 34 + struct ieee80211_hw *hw; 35 + bool has_mrr; 36 + u32 sample_switch; 37 + unsigned int cw_min; 38 + unsigned int cw_max; 39 + unsigned int max_retry; 40 + unsigned int segment_size; 41 + unsigned int update_interval; 42 + 43 + u8 cck_rates[4]; 44 + u8 ofdm_rates[NUM_NL80211_BANDS][8]; 45 + 46 + #ifdef CONFIG_MAC80211_DEBUGFS 47 + /* 48 + * enable fixed rate processing per RC 49 + * - write static index to debugfs:ieee80211/phyX/rc/fixed_rate_idx 50 + * - write -1 to enable RC processing again 51 + * - setting will be applied on next update 52 + */ 53 + u32 fixed_rate_idx; 54 + #endif 55 + }; 56 + 58 57 59 58 struct mcs_group { 60 59 u16 flags; ··· 90 37 u16 duration[MCS_GROUP_RATES]; 91 38 }; 92 39 40 + extern const s16 minstrel_cck_bitrates[4]; 41 + extern const s16 minstrel_ofdm_bitrates[8]; 93 42 extern const struct mcs_group minstrel_mcs_groups[]; 43 + 44 + struct minstrel_rate_stats { 45 + /* current / last sampling period attempts/success counters */ 46 + u16 attempts, last_attempts; 47 + u16 success, last_success; 48 + 49 + /* total attempts/success counters */ 50 + u32 att_hist, succ_hist; 51 + 52 + /* prob_avg - moving average of prob */ 53 + u16 prob_avg; 54 + u16 prob_avg_1; 55 + 56 + /* maximum retry counts */ 57 + u8 retry_count; 58 + u8 retry_count_rtscts; 59 + 60 + u8 sample_skipped; 61 + bool retry_updated; 62 + }; 94 63 95 64 struct minstrel_mcs_group_data { 96 65 u8 index; ··· 152 77 /* overhead time in usec for each frame */ 153 78 unsigned int overhead; 154 79 unsigned int overhead_rtscts; 80 + unsigned int overhead_legacy; 81 + unsigned int overhead_legacy_rtscts; 155 82 156 83 unsigned int total_packets_last; 157 84 unsigned int total_packets_cur; ··· 174 97 /* current MCS group to be sampled */ 175 98 u8 sample_group; 176 99 177 - u8 cck_supported; 178 - u8 cck_supported_short; 100 + u8 band; 179 101 180 102 /* Bitfield of supported MCS rates of all groups */ 181 103 u16 supported[MINSTREL_GROUPS_NB]; 182 104 183 105 /* MCS rate group info and statistics */ 184 106 struct minstrel_mcs_group_data groups[MINSTREL_GROUPS_NB]; 185 - }; 186 - 187 - struct minstrel_ht_sta_priv { 188 - union { 189 - struct minstrel_ht_sta ht; 190 - struct minstrel_sta_info legacy; 191 - }; 192 - void *ratelist; 193 - void *sample_table; 194 - bool is_ht; 195 107 }; 196 108 197 109 void minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir);
+27 -30
net/mac80211/rc80211_minstrel_ht_debugfs.c
··· 9 9 #include <linux/ieee80211.h> 10 10 #include <linux/export.h> 11 11 #include <net/mac80211.h> 12 - #include "rc80211_minstrel.h" 13 12 #include "rc80211_minstrel_ht.h" 13 + 14 + struct minstrel_debugfs_info { 15 + size_t len; 16 + char buf[]; 17 + }; 14 18 15 19 static ssize_t 16 20 minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *ppos) ··· 56 52 57 53 for (j = 0; j < MCS_GROUP_RATES; j++) { 58 54 struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j]; 59 - static const int bitrates[4] = { 10, 20, 55, 110 }; 60 55 int idx = i * MCS_GROUP_RATES + j; 61 56 unsigned int duration; 62 57 ··· 70 67 p += sprintf(p, "VHT%c0 ", htmode); 71 68 p += sprintf(p, "%cGI ", gimode); 72 69 p += sprintf(p, "%d ", mg->streams); 70 + } else if (i == MINSTREL_OFDM_GROUP) { 71 + p += sprintf(p, "OFDM "); 72 + p += sprintf(p, "1 "); 73 73 } else { 74 74 p += sprintf(p, "CCK "); 75 75 p += sprintf(p, "%cP ", j < 4 ? 'L' : 'S'); ··· 90 84 } else if (gflags & IEEE80211_TX_RC_VHT_MCS) { 91 85 p += sprintf(p, " MCS%-1u/%1u", j, mg->streams); 92 86 } else { 93 - int r = bitrates[j % 4]; 87 + int r; 88 + 89 + if (i == MINSTREL_OFDM_GROUP) 90 + r = minstrel_ofdm_bitrates[j % 8]; 91 + else 92 + r = minstrel_cck_bitrates[j % 4]; 94 93 95 94 p += sprintf(p, " %2u.%1uM", r / 10, r % 10); 96 95 } ··· 131 120 static int 132 121 minstrel_ht_stats_open(struct inode *inode, struct file *file) 133 122 { 134 - struct minstrel_ht_sta_priv *msp = inode->i_private; 135 - struct minstrel_ht_sta *mi = &msp->ht; 123 + struct minstrel_ht_sta *mi = inode->i_private; 136 124 struct minstrel_debugfs_info *ms; 137 125 unsigned int i; 138 - int ret; 139 126 char *p; 140 - 141 - if (!msp->is_ht) { 142 - inode->i_private = &msp->legacy; 143 - ret = minstrel_stats_open(inode, file); 144 - inode->i_private = msp; 145 - return ret; 146 - } 147 127 148 128 ms = kmalloc(32768, GFP_KERNEL); 149 129 if (!ms) ··· 201 199 202 200 for (j = 0; j < MCS_GROUP_RATES; j++) { 203 201 struct minstrel_rate_stats *mrs = &mi->groups[i].rates[j]; 204 - static const int bitrates[4] = { 10, 20, 55, 110 }; 205 202 int idx = i * MCS_GROUP_RATES + j; 206 203 unsigned int duration; 207 204 ··· 215 214 p += sprintf(p, "VHT%c0,", htmode); 216 215 p += sprintf(p, "%cGI,", gimode); 217 216 p += sprintf(p, "%d,", mg->streams); 217 + } else if (i == MINSTREL_OFDM_GROUP) { 218 + p += sprintf(p, "OFDM,,1,"); 218 219 } else { 219 220 p += sprintf(p, "CCK,"); 220 221 p += sprintf(p, "%cP,", j < 4 ? 'L' : 'S'); ··· 234 231 } else if (gflags & IEEE80211_TX_RC_VHT_MCS) { 235 232 p += sprintf(p, ",MCS%-1u/%1u,", j, mg->streams); 236 233 } else { 237 - int r = bitrates[j % 4]; 234 + int r; 235 + 236 + if (i == MINSTREL_OFDM_GROUP) 237 + r = minstrel_ofdm_bitrates[j % 8]; 238 + else 239 + r = minstrel_cck_bitrates[j % 4]; 240 + 238 241 p += sprintf(p, ",%2u.%1uM,", r / 10, r % 10); 239 242 } 240 243 ··· 279 270 static int 280 271 minstrel_ht_stats_csv_open(struct inode *inode, struct file *file) 281 272 { 282 - struct minstrel_ht_sta_priv *msp = inode->i_private; 283 - struct minstrel_ht_sta *mi = &msp->ht; 273 + struct minstrel_ht_sta *mi = inode->i_private; 284 274 struct minstrel_debugfs_info *ms; 285 275 unsigned int i; 286 - int ret; 287 276 char *p; 288 277 289 - if (!msp->is_ht) { 290 - inode->i_private = &msp->legacy; 291 - ret = minstrel_stats_csv_open(inode, file); 292 - inode->i_private = msp; 293 - return ret; 294 - } 295 - 296 278 ms = kmalloc(32768, GFP_KERNEL); 297 - 298 279 if (!ms) 299 280 return -ENOMEM; 300 281 ··· 315 316 void 316 317 minstrel_ht_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir) 317 318 { 318 - struct minstrel_ht_sta_priv *msp = priv_sta; 319 - 320 - debugfs_create_file("rc_stats", 0444, dir, msp, 319 + debugfs_create_file("rc_stats", 0444, dir, priv_sta, 321 320 &minstrel_ht_stat_fops); 322 - debugfs_create_file("rc_stats_csv", 0444, dir, msp, 321 + debugfs_create_file("rc_stats_csv", 0444, dir, priv_sta, 323 322 &minstrel_ht_stat_csv_fops); 324 323 }
+158 -85
net/mac80211/rx.c
··· 4095 4095 .vif_type = sdata->vif.type, 4096 4096 .control_port_protocol = sdata->control_port_protocol, 4097 4097 }, *old, *new = NULL; 4098 + bool set_offload = false; 4098 4099 bool assign = false; 4100 + bool offload; 4099 4101 4100 4102 /* use sparse to check that we don't return without updating */ 4101 4103 __acquire(check_fast_rx); ··· 4210 4208 if (assign) 4211 4209 new = kmemdup(&fastrx, sizeof(fastrx), GFP_KERNEL); 4212 4210 4211 + offload = assign && 4212 + (sdata->vif.offload_flags & IEEE80211_OFFLOAD_DECAP_ENABLED); 4213 + 4214 + if (offload) 4215 + set_offload = !test_and_set_sta_flag(sta, WLAN_STA_DECAP_OFFLOAD); 4216 + else 4217 + set_offload = test_and_clear_sta_flag(sta, WLAN_STA_DECAP_OFFLOAD); 4218 + 4219 + if (set_offload) 4220 + drv_sta_set_decap_offload(local, sdata, &sta->sta, assign); 4221 + 4213 4222 spin_lock_bh(&sta->lock); 4214 4223 old = rcu_dereference_protected(sta->fast_rx, true); 4215 4224 rcu_assign_pointer(sta->fast_rx, new); ··· 4267 4254 mutex_unlock(&local->sta_mtx); 4268 4255 } 4269 4256 4257 + static void ieee80211_rx_8023(struct ieee80211_rx_data *rx, 4258 + struct ieee80211_fast_rx *fast_rx, 4259 + int orig_len) 4260 + { 4261 + struct ieee80211_sta_rx_stats *stats; 4262 + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); 4263 + struct sta_info *sta = rx->sta; 4264 + struct sk_buff *skb = rx->skb; 4265 + void *sa = skb->data + ETH_ALEN; 4266 + void *da = skb->data; 4267 + 4268 + stats = &sta->rx_stats; 4269 + if (fast_rx->uses_rss) 4270 + stats = this_cpu_ptr(sta->pcpu_rx_stats); 4271 + 4272 + /* statistics part of ieee80211_rx_h_sta_process() */ 4273 + if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { 4274 + stats->last_signal = status->signal; 4275 + if (!fast_rx->uses_rss) 4276 + ewma_signal_add(&sta->rx_stats_avg.signal, 4277 + -status->signal); 4278 + } 4279 + 4280 + if (status->chains) { 4281 + int i; 4282 + 4283 + stats->chains = status->chains; 4284 + for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { 4285 + int signal = status->chain_signal[i]; 4286 + 4287 + if (!(status->chains & BIT(i))) 4288 + continue; 4289 + 4290 + stats->chain_signal_last[i] = signal; 4291 + if (!fast_rx->uses_rss) 4292 + ewma_signal_add(&sta->rx_stats_avg.chain_signal[i], 4293 + -signal); 4294 + } 4295 + } 4296 + /* end of statistics */ 4297 + 4298 + stats->last_rx = jiffies; 4299 + stats->last_rate = sta_stats_encode_rate(status); 4300 + 4301 + stats->fragments++; 4302 + stats->packets++; 4303 + 4304 + skb->dev = fast_rx->dev; 4305 + 4306 + dev_sw_netstats_rx_add(fast_rx->dev, skb->len); 4307 + 4308 + /* The seqno index has the same property as needed 4309 + * for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS 4310 + * for non-QoS-data frames. Here we know it's a data 4311 + * frame, so count MSDUs. 4312 + */ 4313 + u64_stats_update_begin(&stats->syncp); 4314 + stats->msdu[rx->seqno_idx]++; 4315 + stats->bytes += orig_len; 4316 + u64_stats_update_end(&stats->syncp); 4317 + 4318 + if (fast_rx->internal_forward) { 4319 + struct sk_buff *xmit_skb = NULL; 4320 + if (is_multicast_ether_addr(da)) { 4321 + xmit_skb = skb_copy(skb, GFP_ATOMIC); 4322 + } else if (!ether_addr_equal(da, sa) && 4323 + sta_info_get(rx->sdata, da)) { 4324 + xmit_skb = skb; 4325 + skb = NULL; 4326 + } 4327 + 4328 + if (xmit_skb) { 4329 + /* 4330 + * Send to wireless media and increase priority by 256 4331 + * to keep the received priority instead of 4332 + * reclassifying the frame (see cfg80211_classify8021d). 4333 + */ 4334 + xmit_skb->priority += 256; 4335 + xmit_skb->protocol = htons(ETH_P_802_3); 4336 + skb_reset_network_header(xmit_skb); 4337 + skb_reset_mac_header(xmit_skb); 4338 + dev_queue_xmit(xmit_skb); 4339 + } 4340 + 4341 + if (!skb) 4342 + return; 4343 + } 4344 + 4345 + /* deliver to local stack */ 4346 + skb->protocol = eth_type_trans(skb, fast_rx->dev); 4347 + memset(skb->cb, 0, sizeof(skb->cb)); 4348 + if (rx->list) 4349 + list_add_tail(&skb->list, rx->list); 4350 + else 4351 + netif_receive_skb(skb); 4352 + 4353 + } 4354 + 4270 4355 static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, 4271 4356 struct ieee80211_fast_rx *fast_rx) 4272 4357 { ··· 4384 4273 u8 sa[ETH_ALEN]; 4385 4274 } addrs __aligned(2); 4386 4275 struct ieee80211_sta_rx_stats *stats = &sta->rx_stats; 4387 - 4388 - if (fast_rx->uses_rss) 4389 - stats = this_cpu_ptr(sta->pcpu_rx_stats); 4390 4276 4391 4277 /* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write 4392 4278 * to a common data structure; drivers can implement that per queue ··· 4458 4350 pskb_trim(skb, skb->len - fast_rx->icv_len)) 4459 4351 goto drop; 4460 4352 4461 - /* statistics part of ieee80211_rx_h_sta_process() */ 4462 - if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { 4463 - stats->last_signal = status->signal; 4464 - if (!fast_rx->uses_rss) 4465 - ewma_signal_add(&sta->rx_stats_avg.signal, 4466 - -status->signal); 4467 - } 4468 - 4469 - if (status->chains) { 4470 - int i; 4471 - 4472 - stats->chains = status->chains; 4473 - for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { 4474 - int signal = status->chain_signal[i]; 4475 - 4476 - if (!(status->chains & BIT(i))) 4477 - continue; 4478 - 4479 - stats->chain_signal_last[i] = signal; 4480 - if (!fast_rx->uses_rss) 4481 - ewma_signal_add(&sta->rx_stats_avg.chain_signal[i], 4482 - -signal); 4483 - } 4484 - } 4485 - /* end of statistics */ 4486 - 4487 4353 if (rx->key && !ieee80211_has_protected(hdr->frame_control)) 4488 4354 goto drop; 4489 4355 ··· 4469 4387 return true; 4470 4388 } 4471 4389 4472 - stats->last_rx = jiffies; 4473 - stats->last_rate = sta_stats_encode_rate(status); 4474 - 4475 - stats->fragments++; 4476 - stats->packets++; 4477 - 4478 4390 /* do the header conversion - first grab the addresses */ 4479 4391 ether_addr_copy(addrs.da, skb->data + fast_rx->da_offs); 4480 4392 ether_addr_copy(addrs.sa, skb->data + fast_rx->sa_offs); ··· 4477 4401 /* push the addresses in front */ 4478 4402 memcpy(skb_push(skb, sizeof(addrs)), &addrs, sizeof(addrs)); 4479 4403 4480 - skb->dev = fast_rx->dev; 4481 - 4482 - dev_sw_netstats_rx_add(fast_rx->dev, skb->len); 4483 - 4484 - /* The seqno index has the same property as needed 4485 - * for the rx_msdu field, i.e. it is IEEE80211_NUM_TIDS 4486 - * for non-QoS-data frames. Here we know it's a data 4487 - * frame, so count MSDUs. 4488 - */ 4489 - u64_stats_update_begin(&stats->syncp); 4490 - stats->msdu[rx->seqno_idx]++; 4491 - stats->bytes += orig_len; 4492 - u64_stats_update_end(&stats->syncp); 4493 - 4494 - if (fast_rx->internal_forward) { 4495 - struct sk_buff *xmit_skb = NULL; 4496 - if (is_multicast_ether_addr(addrs.da)) { 4497 - xmit_skb = skb_copy(skb, GFP_ATOMIC); 4498 - } else if (!ether_addr_equal(addrs.da, addrs.sa) && 4499 - sta_info_get(rx->sdata, addrs.da)) { 4500 - xmit_skb = skb; 4501 - skb = NULL; 4502 - } 4503 - 4504 - if (xmit_skb) { 4505 - /* 4506 - * Send to wireless media and increase priority by 256 4507 - * to keep the received priority instead of 4508 - * reclassifying the frame (see cfg80211_classify8021d). 4509 - */ 4510 - xmit_skb->priority += 256; 4511 - xmit_skb->protocol = htons(ETH_P_802_3); 4512 - skb_reset_network_header(xmit_skb); 4513 - skb_reset_mac_header(xmit_skb); 4514 - dev_queue_xmit(xmit_skb); 4515 - } 4516 - 4517 - if (!skb) 4518 - return true; 4519 - } 4520 - 4521 - /* deliver to local stack */ 4522 - skb->protocol = eth_type_trans(skb, fast_rx->dev); 4523 - memset(skb->cb, 0, sizeof(skb->cb)); 4524 - if (rx->list) 4525 - list_add_tail(&skb->list, rx->list); 4526 - else 4527 - netif_receive_skb(skb); 4404 + ieee80211_rx_8023(rx, fast_rx, orig_len); 4528 4405 4529 4406 return true; 4530 4407 drop: 4531 4408 dev_kfree_skb(skb); 4409 + if (fast_rx->uses_rss) 4410 + stats = this_cpu_ptr(sta->pcpu_rx_stats); 4411 + 4532 4412 stats->dropped++; 4533 4413 return true; 4534 4414 } ··· 4536 4504 4537 4505 ieee80211_invoke_rx_handlers(rx); 4538 4506 return true; 4507 + } 4508 + 4509 + static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw, 4510 + struct ieee80211_sta *pubsta, 4511 + struct sk_buff *skb, 4512 + struct list_head *list) 4513 + { 4514 + struct ieee80211_local *local = hw_to_local(hw); 4515 + struct ieee80211_fast_rx *fast_rx; 4516 + struct ieee80211_rx_data rx; 4517 + 4518 + memset(&rx, 0, sizeof(rx)); 4519 + rx.skb = skb; 4520 + rx.local = local; 4521 + rx.list = list; 4522 + 4523 + I802_DEBUG_INC(local->dot11ReceivedFragmentCount); 4524 + 4525 + /* drop frame if too short for header */ 4526 + if (skb->len < sizeof(struct ethhdr)) 4527 + goto drop; 4528 + 4529 + if (!pubsta) 4530 + goto drop; 4531 + 4532 + rx.sta = container_of(pubsta, struct sta_info, sta); 4533 + rx.sdata = rx.sta->sdata; 4534 + 4535 + fast_rx = rcu_dereference(rx.sta->fast_rx); 4536 + if (!fast_rx) 4537 + goto drop; 4538 + 4539 + ieee80211_rx_8023(&rx, fast_rx, skb->len); 4540 + return; 4541 + 4542 + drop: 4543 + dev_kfree_skb(skb); 4539 4544 } 4540 4545 4541 4546 /* ··· 4806 4737 * if it was previously present. 4807 4738 * Also, frames with less than 16 bytes are dropped. 4808 4739 */ 4809 - skb = ieee80211_rx_monitor(local, skb, rate); 4740 + if (!(status->flag & RX_FLAG_8023)) 4741 + skb = ieee80211_rx_monitor(local, skb, rate); 4810 4742 if (skb) { 4811 4743 ieee80211_tpt_led_trig_rx(local, 4812 4744 ((struct ieee80211_hdr *)skb->data)->frame_control, 4813 4745 skb->len); 4814 4746 4815 - __ieee80211_rx_handle_packet(hw, pubsta, skb, list); 4747 + if (status->flag & RX_FLAG_8023) 4748 + __ieee80211_rx_handle_8023(hw, pubsta, skb, list); 4749 + else 4750 + __ieee80211_rx_handle_packet(hw, pubsta, skb, list); 4816 4751 } 4817 4752 4818 4753 kcov_remote_stop();
+2
net/mac80211/sta_info.h
··· 71 71 * until pending frames are delivered 72 72 * @WLAN_STA_USES_ENCRYPTION: This station was configured for encryption, 73 73 * so drop all packets without a key later. 74 + * @WLAN_STA_DECAP_OFFLOAD: This station uses rx decap offload 74 75 * 75 76 * @NUM_WLAN_STA_FLAGS: number of defined flags 76 77 */ ··· 103 102 WLAN_STA_MPSP_RECIPIENT, 104 103 WLAN_STA_PS_DELIVER, 105 104 WLAN_STA_USES_ENCRYPTION, 105 + WLAN_STA_DECAP_OFFLOAD, 106 106 107 107 NUM_WLAN_STA_FLAGS, 108 108 };
+3 -3
net/mac80211/tdls.c
··· 1927 1927 struct ieee80211_tdls_data *tf = (void *)skb->data; 1928 1928 struct wiphy *wiphy = sdata->local->hw.wiphy; 1929 1929 1930 - ASSERT_RTNL(); 1930 + lockdep_assert_wiphy(wiphy); 1931 1931 1932 1932 /* make sure the driver supports it */ 1933 1933 if (!(wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH)) ··· 1979 1979 struct sk_buff *skb; 1980 1980 struct ieee80211_tdls_data *tf; 1981 1981 1982 - rtnl_lock(); 1982 + wiphy_lock(local->hw.wiphy); 1983 1983 while ((skb = skb_dequeue(&local->skb_queue_tdls_chsw))) { 1984 1984 tf = (struct ieee80211_tdls_data *)skb->data; 1985 1985 list_for_each_entry(sdata, &local->interfaces, list) { ··· 1994 1994 1995 1995 kfree_skb(skb); 1996 1996 } 1997 - rtnl_unlock(); 1997 + wiphy_unlock(local->hw.wiphy); 1998 1998 } 1999 1999 2000 2000 void ieee80211_tdls_handle_disconnect(struct ieee80211_sub_if_data *sdata,
+17 -1
net/mac80211/trace.h
··· 2761 2761 TP_ARGS(local, sdata) 2762 2762 ); 2763 2763 2764 - TRACE_EVENT(drv_sta_set_4addr, 2764 + DECLARE_EVENT_CLASS(sta_flag_evt, 2765 2765 TP_PROTO(struct ieee80211_local *local, 2766 2766 struct ieee80211_sub_if_data *sdata, 2767 2767 struct ieee80211_sta *sta, bool enabled), ··· 2786 2786 LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " enabled:%d", 2787 2787 LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->enabled 2788 2788 ) 2789 + ); 2790 + 2791 + DEFINE_EVENT(sta_flag_evt, drv_sta_set_4addr, 2792 + TP_PROTO(struct ieee80211_local *local, 2793 + struct ieee80211_sub_if_data *sdata, 2794 + struct ieee80211_sta *sta, bool enabled), 2795 + 2796 + TP_ARGS(local, sdata, sta, enabled) 2797 + ); 2798 + 2799 + DEFINE_EVENT(sta_flag_evt, drv_sta_set_decap_offload, 2800 + TP_PROTO(struct ieee80211_local *local, 2801 + struct ieee80211_sub_if_data *sdata, 2802 + struct ieee80211_sta *sta, bool enabled), 2803 + 2804 + TP_ARGS(local, sdata, sta, enabled) 2789 2805 ); 2790 2806 2791 2807 #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
+13 -20
net/mac80211/tx.c
··· 1309 1309 fq = &local->fq; 1310 1310 1311 1311 if (cvars == &txqi->def_cvars) 1312 - flow = &txqi->def_flow; 1312 + flow = &txqi->tin.default_flow; 1313 1313 else 1314 1314 flow = &fq->flows[cvars - local->cvars]; 1315 1315 ··· 1352 1352 cparams = &local->cparams; 1353 1353 } 1354 1354 1355 - if (flow == &txqi->def_flow) 1355 + if (flow == &tin->default_flow) 1356 1356 cvars = &txqi->def_cvars; 1357 1357 else 1358 1358 cvars = &local->cvars[flow - fq->flows]; ··· 1379 1379 ieee80211_free_txskb(&local->hw, skb); 1380 1380 } 1381 1381 1382 - static struct fq_flow *fq_flow_get_default_func(struct fq *fq, 1383 - struct fq_tin *tin, 1384 - int idx, 1385 - struct sk_buff *skb) 1386 - { 1387 - struct txq_info *txqi; 1388 - 1389 - txqi = container_of(tin, struct txq_info, tin); 1390 - return &txqi->def_flow; 1391 - } 1392 - 1393 1382 static void ieee80211_txq_enqueue(struct ieee80211_local *local, 1394 1383 struct txq_info *txqi, 1395 1384 struct sk_buff *skb) ··· 1391 1402 1392 1403 spin_lock_bh(&fq->lock); 1393 1404 fq_tin_enqueue(fq, tin, flow_idx, skb, 1394 - fq_skb_free_func, 1395 - fq_flow_get_default_func); 1405 + fq_skb_free_func); 1396 1406 spin_unlock_bh(&fq->lock); 1397 1407 } 1398 1408 ··· 1434 1446 struct txq_info *txqi, int tid) 1435 1447 { 1436 1448 fq_tin_init(&txqi->tin); 1437 - fq_flow_init(&txqi->def_flow); 1438 1449 codel_vars_init(&txqi->def_cvars); 1439 1450 codel_stats_init(&txqi->cstats); 1440 1451 __skb_queue_head_init(&txqi->frags); ··· 2120 2133 if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_BW && 2121 2134 mcs_bw == IEEE80211_RADIOTAP_MCS_BW_40) 2122 2135 rate_flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; 2136 + 2137 + if (mcs_known & IEEE80211_RADIOTAP_MCS_HAVE_FEC && 2138 + mcs_flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) 2139 + info->flags |= IEEE80211_TX_CTL_LDPC; 2123 2140 break; 2124 2141 2125 2142 case IEEE80211_RADIOTAP_VHT: ··· 3274 3283 */ 3275 3284 3276 3285 tin = &txqi->tin; 3277 - flow = fq_flow_classify(fq, tin, flow_idx, skb, 3278 - fq_flow_get_default_func); 3286 + flow = fq_flow_classify(fq, tin, flow_idx, skb); 3279 3287 head = skb_peek_tail(&flow->queue); 3280 3288 if (!head || skb_is_gso(head)) 3281 3289 goto out; ··· 3341 3351 if (head->len != orig_len) { 3342 3352 flow->backlog += head->len - orig_len; 3343 3353 tin->backlog_bytes += head->len - orig_len; 3344 - 3345 - fq_recalc_backlog(fq, tin, flow); 3346 3354 } 3347 3355 out: 3348 3356 spin_unlock_bh(&fq->lock); ··· 3811 3823 } 3812 3824 EXPORT_SYMBOL(__ieee80211_schedule_txq); 3813 3825 3826 + DEFINE_STATIC_KEY_FALSE(aql_disable); 3827 + 3814 3828 bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw, 3815 3829 struct ieee80211_txq *txq) 3816 3830 { ··· 3820 3830 struct ieee80211_local *local = hw_to_local(hw); 3821 3831 3822 3832 if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) 3833 + return true; 3834 + 3835 + if (static_branch_unlikely(&aql_disable)) 3823 3836 return true; 3824 3837 3825 3838 if (!txq->sta)
+7 -7
net/mac80211/util.c
··· 832 832 } 833 833 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic); 834 834 835 - void ieee80211_iterate_active_interfaces_rtnl( 835 + void ieee80211_iterate_active_interfaces_mtx( 836 836 struct ieee80211_hw *hw, u32 iter_flags, 837 837 void (*iterator)(void *data, u8 *mac, 838 838 struct ieee80211_vif *vif), ··· 840 840 { 841 841 struct ieee80211_local *local = hw_to_local(hw); 842 842 843 - ASSERT_RTNL(); 843 + lockdep_assert_wiphy(hw->wiphy); 844 844 845 845 __iterate_interfaces(local, iter_flags | IEEE80211_IFACE_ITER_ACTIVE, 846 846 iterator, data); 847 847 } 848 - EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl); 848 + EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_mtx); 849 849 850 850 static void __iterate_stations(struct ieee80211_local *local, 851 851 void (*iterator)(void *data, ··· 2595 2595 mutex_unlock(&local->mtx); 2596 2596 2597 2597 if (sched_scan_stopped) 2598 - cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy, 0); 2598 + cfg80211_sched_scan_stopped_locked(local->hw.wiphy, 0); 2599 2599 2600 2600 wake_up: 2601 2601 ··· 3811 3811 struct cfg80211_chan_def chandef; 3812 3812 3813 3813 /* for interface list, to avoid linking iflist_mtx and chanctx_mtx */ 3814 - ASSERT_RTNL(); 3814 + lockdep_assert_wiphy(local->hw.wiphy); 3815 3815 3816 3816 mutex_lock(&local->mtx); 3817 3817 list_for_each_entry(sdata, &local->interfaces, list) { ··· 3851 3851 } 3852 3852 mutex_unlock(&local->chanctx_mtx); 3853 3853 3854 - rtnl_lock(); 3854 + wiphy_lock(local->hw.wiphy); 3855 3855 ieee80211_dfs_cac_cancel(local); 3856 - rtnl_unlock(); 3856 + wiphy_unlock(local->hw.wiphy); 3857 3857 3858 3858 if (num_chanctx > 1) 3859 3859 /* XXX: multi-channel is not supported yet */
+8 -1
net/mac80211/vht.c
··· 484 484 void ieee80211_sta_set_rx_nss(struct sta_info *sta) 485 485 { 486 486 u8 ht_rx_nss = 0, vht_rx_nss = 0, he_rx_nss = 0, rx_nss; 487 + bool support_160; 487 488 488 489 /* if we received a notification already don't overwrite it */ 489 490 if (sta->sta.rx_nss) ··· 515 514 } 516 515 } 517 516 518 - he_rx_nss = min(rx_mcs_80, rx_mcs_160); 517 + support_160 = he_cap->he_cap_elem.phy_cap_info[0] & 518 + IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; 519 + 520 + if (support_160) 521 + he_rx_nss = min(rx_mcs_80, rx_mcs_160); 522 + else 523 + he_rx_nss = rx_mcs_80; 519 524 } 520 525 521 526 if (sta->sta.ht_cap.ht_supported) {
+3 -2
net/wireless/chan.c
··· 1093 1093 struct wireless_dev *wdev; 1094 1094 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); 1095 1095 1096 - ASSERT_RTNL(); 1096 + lockdep_assert_held(&rdev->wiphy.mtx); 1097 1097 1098 1098 if (!IS_ENABLED(CONFIG_CFG80211_REG_RELAX_NO_IR) || 1099 1099 !(wiphy->regulatory_flags & REGULATORY_ENABLE_RELAX_NO_IR)) ··· 1216 1216 struct cfg80211_chan_def *chandef, 1217 1217 enum nl80211_iftype iftype) 1218 1218 { 1219 + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); 1219 1220 bool check_no_ir; 1220 1221 1221 - ASSERT_RTNL(); 1222 + lockdep_assert_held(&rdev->wiphy.mtx); 1222 1223 1223 1224 /* 1224 1225 * Under certain conditions suggested by some regulatory bodies a
+106 -57
net/wireless/core.c
··· 222 222 void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, 223 223 struct wireless_dev *wdev) 224 224 { 225 - ASSERT_RTNL(); 225 + lockdep_assert_held(&rdev->wiphy.mtx); 226 226 227 227 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)) 228 228 return; ··· 247 247 void cfg80211_stop_nan(struct cfg80211_registered_device *rdev, 248 248 struct wireless_dev *wdev) 249 249 { 250 - ASSERT_RTNL(); 250 + lockdep_assert_held(&rdev->wiphy.mtx); 251 251 252 252 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_NAN)) 253 253 return; ··· 273 273 dev_close(wdev->netdev); 274 274 continue; 275 275 } 276 + 276 277 /* otherwise, check iftype */ 278 + 279 + wiphy_lock(wiphy); 280 + 277 281 switch (wdev->iftype) { 278 282 case NL80211_IFTYPE_P2P_DEVICE: 279 283 cfg80211_stop_p2p_device(rdev, wdev); ··· 288 284 default: 289 285 break; 290 286 } 287 + 288 + wiphy_unlock(wiphy); 291 289 } 292 290 } 293 291 EXPORT_SYMBOL_GPL(cfg80211_shutdown_all_interfaces); ··· 324 318 rdev = container_of(work, struct cfg80211_registered_device, 325 319 event_work); 326 320 327 - rtnl_lock(); 321 + wiphy_lock(&rdev->wiphy); 328 322 cfg80211_process_rdev_events(rdev); 329 - rtnl_unlock(); 323 + wiphy_unlock(&rdev->wiphy); 330 324 } 331 325 332 326 void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev) ··· 481 475 } 482 476 } 483 477 478 + mutex_init(&rdev->wiphy.mtx); 484 479 INIT_LIST_HEAD(&rdev->wiphy.wdev_list); 485 480 INIT_LIST_HEAD(&rdev->beacon_registrations); 486 481 spin_lock_init(&rdev->beacon_registrations_lock); ··· 1014 1007 1015 1008 wait_event(rdev->dev_wait, ({ 1016 1009 int __count; 1017 - rtnl_lock(); 1010 + wiphy_lock(&rdev->wiphy); 1018 1011 __count = rdev->opencount; 1019 - rtnl_unlock(); 1012 + wiphy_unlock(&rdev->wiphy); 1020 1013 __count == 0; })); 1021 1014 1022 1015 if (rdev->rfkill) 1023 1016 rfkill_unregister(rdev->rfkill); 1024 1017 1025 1018 rtnl_lock(); 1019 + wiphy_lock(&rdev->wiphy); 1026 1020 nl80211_notify_wiphy(rdev, NL80211_CMD_DEL_WIPHY); 1027 1021 rdev->wiphy.registered = false; 1028 1022 ··· 1046 1038 cfg80211_rdev_list_generation++; 1047 1039 device_del(&rdev->wiphy.dev); 1048 1040 1041 + wiphy_unlock(&rdev->wiphy); 1049 1042 rtnl_unlock(); 1050 1043 1051 1044 flush_work(&rdev->scan_done_wk); ··· 1079 1070 } 1080 1071 list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) 1081 1072 cfg80211_put_bss(&rdev->wiphy, &scan->pub); 1073 + mutex_destroy(&rdev->wiphy.mtx); 1082 1074 kfree(rdev); 1083 1075 } 1084 1076 ··· 1104 1094 wdev->cqm_config = NULL; 1105 1095 } 1106 1096 1107 - static void __cfg80211_unregister_wdev(struct wireless_dev *wdev, bool sync) 1097 + static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, 1098 + bool unregister_netdev) 1108 1099 { 1109 1100 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); 1110 1101 1111 1102 ASSERT_RTNL(); 1103 + lockdep_assert_held(&rdev->wiphy.mtx); 1112 1104 1113 1105 flush_work(&wdev->pmsr_free_wk); 1114 1106 1115 1107 nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE); 1116 1108 1109 + wdev->registered = false; 1110 + 1111 + if (wdev->netdev) { 1112 + sysfs_remove_link(&wdev->netdev->dev.kobj, "phy80211"); 1113 + if (unregister_netdev) 1114 + unregister_netdevice(wdev->netdev); 1115 + } 1116 + 1117 1117 list_del_rcu(&wdev->list); 1118 - if (sync) 1119 - synchronize_rcu(); 1118 + synchronize_net(); 1120 1119 rdev->devlist_generation++; 1121 1120 1122 1121 cfg80211_mlme_purge_registrations(wdev); ··· 1150 1131 flush_work(&wdev->disconnect_wk); 1151 1132 1152 1133 cfg80211_cqm_config_free(wdev); 1134 + 1135 + /* 1136 + * Ensure that all events have been processed and 1137 + * freed. 1138 + */ 1139 + cfg80211_process_wdev_events(wdev); 1140 + 1141 + if (WARN_ON(wdev->current_bss)) { 1142 + cfg80211_unhold_bss(wdev->current_bss); 1143 + cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); 1144 + wdev->current_bss = NULL; 1145 + } 1153 1146 } 1154 1147 1155 1148 void cfg80211_unregister_wdev(struct wireless_dev *wdev) 1156 1149 { 1157 - if (WARN_ON(wdev->netdev)) 1158 - return; 1159 - 1160 - __cfg80211_unregister_wdev(wdev, true); 1150 + _cfg80211_unregister_wdev(wdev, true); 1161 1151 } 1162 1152 EXPORT_SYMBOL(cfg80211_unregister_wdev); 1163 1153 ··· 1177 1149 void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, 1178 1150 enum nl80211_iftype iftype, int num) 1179 1151 { 1180 - ASSERT_RTNL(); 1152 + lockdep_assert_held(&rdev->wiphy.mtx); 1181 1153 1182 1154 rdev->num_running_ifaces += num; 1183 1155 if (iftype == NL80211_IFTYPE_MONITOR) ··· 1190 1162 struct net_device *dev = wdev->netdev; 1191 1163 struct cfg80211_sched_scan_request *pos, *tmp; 1192 1164 1193 - ASSERT_RTNL(); 1165 + lockdep_assert_held(&rdev->wiphy.mtx); 1194 1166 ASSERT_WDEV_LOCK(wdev); 1195 1167 1196 1168 cfg80211_pmsr_wdev_down(wdev); ··· 1307 1279 void cfg80211_register_wdev(struct cfg80211_registered_device *rdev, 1308 1280 struct wireless_dev *wdev) 1309 1281 { 1282 + ASSERT_RTNL(); 1283 + lockdep_assert_held(&rdev->wiphy.mtx); 1284 + 1310 1285 /* 1311 1286 * We get here also when the interface changes network namespaces, 1312 1287 * as it's registered into the new one, but we don't want it to ··· 1321 1290 wdev->identifier = ++rdev->wdev_id; 1322 1291 list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list); 1323 1292 rdev->devlist_generation++; 1293 + wdev->registered = true; 1324 1294 1325 1295 nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE); 1326 1296 } 1297 + 1298 + int cfg80211_register_netdevice(struct net_device *dev) 1299 + { 1300 + struct wireless_dev *wdev = dev->ieee80211_ptr; 1301 + struct cfg80211_registered_device *rdev; 1302 + int ret; 1303 + 1304 + ASSERT_RTNL(); 1305 + 1306 + if (WARN_ON(!wdev)) 1307 + return -EINVAL; 1308 + 1309 + rdev = wiphy_to_rdev(wdev->wiphy); 1310 + 1311 + lockdep_assert_held(&rdev->wiphy.mtx); 1312 + 1313 + /* we'll take care of this */ 1314 + wdev->registered = true; 1315 + ret = register_netdevice(dev); 1316 + if (ret) 1317 + goto out; 1318 + 1319 + if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj, 1320 + "phy80211")) { 1321 + pr_err("failed to add phy80211 symlink to netdev!\n"); 1322 + unregister_netdevice(dev); 1323 + ret = -EINVAL; 1324 + goto out; 1325 + } 1326 + 1327 + cfg80211_register_wdev(rdev, wdev); 1328 + ret = 0; 1329 + out: 1330 + if (ret) 1331 + wdev->registered = false; 1332 + return ret; 1333 + } 1334 + EXPORT_SYMBOL(cfg80211_register_netdevice); 1327 1335 1328 1336 static int cfg80211_netdev_notifier_call(struct notifier_block *nb, 1329 1337 unsigned long state, void *ptr) ··· 1389 1319 cfg80211_init_wdev(wdev); 1390 1320 break; 1391 1321 case NETDEV_REGISTER: 1392 - /* 1393 - * NB: cannot take rdev->mtx here because this may be 1394 - * called within code protected by it when interfaces 1395 - * are added with nl80211. 1396 - */ 1397 - if (sysfs_create_link(&dev->dev.kobj, &rdev->wiphy.dev.kobj, 1398 - "phy80211")) { 1399 - pr_err("failed to add phy80211 symlink to netdev!\n"); 1322 + if (!wdev->registered) { 1323 + wiphy_lock(&rdev->wiphy); 1324 + cfg80211_register_wdev(rdev, wdev); 1325 + wiphy_unlock(&rdev->wiphy); 1400 1326 } 1401 - 1402 - cfg80211_register_wdev(rdev, wdev); 1327 + break; 1328 + case NETDEV_UNREGISTER: 1329 + /* 1330 + * It is possible to get NETDEV_UNREGISTER multiple times, 1331 + * so check wdev->registered. 1332 + */ 1333 + if (wdev->registered) { 1334 + wiphy_lock(&rdev->wiphy); 1335 + _cfg80211_unregister_wdev(wdev, false); 1336 + wiphy_unlock(&rdev->wiphy); 1337 + } 1403 1338 break; 1404 1339 case NETDEV_GOING_DOWN: 1340 + wiphy_lock(&rdev->wiphy); 1405 1341 cfg80211_leave(rdev, wdev); 1342 + wiphy_unlock(&rdev->wiphy); 1406 1343 break; 1407 1344 case NETDEV_DOWN: 1345 + wiphy_lock(&rdev->wiphy); 1408 1346 cfg80211_update_iface_num(rdev, wdev->iftype, -1); 1409 1347 if (rdev->scan_req && rdev->scan_req->wdev == wdev) { 1410 1348 if (WARN_ON(!rdev->scan_req->notified && ··· 1429 1351 } 1430 1352 1431 1353 rdev->opencount--; 1354 + wiphy_unlock(&rdev->wiphy); 1432 1355 wake_up(&rdev->dev_wait); 1433 1356 break; 1434 1357 case NETDEV_UP: 1358 + wiphy_lock(&rdev->wiphy); 1435 1359 cfg80211_update_iface_num(rdev, wdev->iftype, 1); 1436 1360 wdev_lock(wdev); 1437 1361 switch (wdev->iftype) { ··· 1480 1400 /* assume this means it's off */ 1481 1401 wdev->ps = false; 1482 1402 } 1483 - break; 1484 - case NETDEV_UNREGISTER: 1485 - /* 1486 - * It is possible to get NETDEV_UNREGISTER 1487 - * multiple times. To detect that, check 1488 - * that the interface is still on the list 1489 - * of registered interfaces, and only then 1490 - * remove and clean it up. 1491 - */ 1492 - if (!list_empty(&wdev->list)) { 1493 - __cfg80211_unregister_wdev(wdev, false); 1494 - sysfs_remove_link(&dev->dev.kobj, "phy80211"); 1495 - } 1496 - /* 1497 - * synchronise (so that we won't find this netdev 1498 - * from other code any more) and then clear the list 1499 - * head so that the above code can safely check for 1500 - * !list_empty() to avoid double-cleanup. 1501 - */ 1502 - synchronize_rcu(); 1503 - INIT_LIST_HEAD(&wdev->list); 1504 - /* 1505 - * Ensure that all events have been processed and 1506 - * freed. 1507 - */ 1508 - cfg80211_process_wdev_events(wdev); 1509 - 1510 - if (WARN_ON(wdev->current_bss)) { 1511 - cfg80211_unhold_bss(wdev->current_bss); 1512 - cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); 1513 - wdev->current_bss = NULL; 1514 - } 1403 + wiphy_unlock(&rdev->wiphy); 1515 1404 break; 1516 1405 case NETDEV_PRE_UP: 1517 1406 if (!cfg80211_iftype_allowed(wdev->wiphy, wdev->iftype,
+1 -1
net/wireless/core.h
··· 231 231 232 232 static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) 233 233 { 234 - ASSERT_RTNL(); 234 + lockdep_assert_held(&rdev->wiphy.mtx); 235 235 236 236 return rdev->num_running_ifaces == rdev->num_running_monitor_ifaces && 237 237 rdev->num_running_ifaces > 0;
-4
net/wireless/debugfs.c
··· 73 73 if (!buf) 74 74 return -ENOMEM; 75 75 76 - rtnl_lock(); 77 - 78 76 for (band = 0; band < NUM_NL80211_BANDS; band++) { 79 77 sband = wiphy->bands[band]; 80 78 if (!sband) ··· 81 83 offset += ht_print_chan(&sband->channels[i], 82 84 buf, buf_size, offset); 83 85 } 84 - 85 - rtnl_unlock(); 86 86 87 87 r = simple_read_from_buffer(user_buf, count, ppos, buf, offset); 88 88
+2 -1
net/wireless/ibss.c
··· 3 3 * Some IBSS support code for cfg80211. 4 4 * 5 5 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> 6 + * Copyright (C) 2020-2021 Intel Corporation 6 7 */ 7 8 8 9 #include <linux/etherdevice.h> ··· 93 92 struct wireless_dev *wdev = dev->ieee80211_ptr; 94 93 int err; 95 94 96 - ASSERT_RTNL(); 95 + lockdep_assert_held(&rdev->wiphy.mtx); 97 96 ASSERT_WDEV_LOCK(wdev); 98 97 99 98 if (wdev->ssid_len)
+3 -3
net/wireless/mlme.c
··· 450 450 struct cfg80211_mgmt_registration *reg; 451 451 struct mgmt_frame_regs upd = {}; 452 452 453 - ASSERT_RTNL(); 453 + lockdep_assert_held(&rdev->wiphy.mtx); 454 454 455 455 spin_lock_bh(&wdev->mgmt_registrations_lock); 456 456 if (!wdev->mgmt_registrations_need_update) { ··· 492 492 rdev = container_of(wk, struct cfg80211_registered_device, 493 493 mgmt_registrations_update_wk); 494 494 495 - rtnl_lock(); 495 + wiphy_lock(&rdev->wiphy); 496 496 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) 497 497 cfg80211_mgmt_registrations_update(wdev); 498 - rtnl_unlock(); 498 + wiphy_unlock(&rdev->wiphy); 499 499 } 500 500 501 501 int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
+358 -299
net/wireless/nl80211.c
··· 64 64 65 65 /* returns ERR_PTR values */ 66 66 static struct wireless_dev * 67 - __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs) 67 + __cfg80211_wdev_from_attrs(struct cfg80211_registered_device *rdev, 68 + struct net *netns, struct nlattr **attrs) 68 69 { 69 - struct cfg80211_registered_device *rdev; 70 70 struct wireless_dev *result = NULL; 71 71 bool have_ifidx = attrs[NL80211_ATTR_IFINDEX]; 72 72 bool have_wdev_id = attrs[NL80211_ATTR_WDEV]; 73 73 u64 wdev_id; 74 74 int wiphy_idx = -1; 75 75 int ifidx = -1; 76 - 77 - ASSERT_RTNL(); 78 76 79 77 if (!have_ifidx && !have_wdev_id) 80 78 return ERR_PTR(-EINVAL); ··· 83 85 wdev_id = nla_get_u64(attrs[NL80211_ATTR_WDEV]); 84 86 wiphy_idx = wdev_id >> 32; 85 87 } 88 + 89 + if (rdev) { 90 + struct wireless_dev *wdev; 91 + 92 + lockdep_assert_held(&rdev->wiphy.mtx); 93 + 94 + list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { 95 + if (have_ifidx && wdev->netdev && 96 + wdev->netdev->ifindex == ifidx) { 97 + result = wdev; 98 + break; 99 + } 100 + if (have_wdev_id && wdev->identifier == (u32)wdev_id) { 101 + result = wdev; 102 + break; 103 + } 104 + } 105 + 106 + return result ?: ERR_PTR(-ENODEV); 107 + } 108 + 109 + ASSERT_RTNL(); 86 110 87 111 list_for_each_entry(rdev, &cfg80211_rdev_list, list) { 88 112 struct wireless_dev *wdev; ··· 934 914 return err; 935 915 } 936 916 937 - *wdev = __cfg80211_wdev_from_attrs(sock_net(cb->skb->sk), 917 + rtnl_lock(); 918 + *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(cb->skb->sk), 938 919 attrbuf); 939 920 kfree(attrbuf); 940 - if (IS_ERR(*wdev)) 921 + if (IS_ERR(*wdev)) { 922 + rtnl_unlock(); 941 923 return PTR_ERR(*wdev); 924 + } 942 925 *rdev = wiphy_to_rdev((*wdev)->wiphy); 926 + mutex_lock(&(*rdev)->wiphy.mtx); 927 + rtnl_unlock(); 943 928 /* 0 is the first index - add 1 to parse only once */ 944 929 cb->args[0] = (*rdev)->wiphy_idx + 1; 945 930 cb->args[1] = (*wdev)->identifier; 946 931 } else { 947 932 /* subtract the 1 again here */ 948 - struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); 933 + struct wiphy *wiphy; 949 934 struct wireless_dev *tmp; 950 935 951 - if (!wiphy) 936 + rtnl_lock(); 937 + wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1); 938 + if (!wiphy) { 939 + rtnl_unlock(); 952 940 return -ENODEV; 941 + } 953 942 *rdev = wiphy_to_rdev(wiphy); 954 943 *wdev = NULL; 955 944 ··· 969 940 } 970 941 } 971 942 972 - if (!*wdev) 943 + if (!*wdev) { 944 + rtnl_unlock(); 973 945 return -ENODEV; 946 + } 947 + mutex_lock(&(*rdev)->wiphy.mtx); 948 + rtnl_unlock(); 974 949 } 975 950 976 951 return 0; ··· 3174 3141 3175 3142 static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) 3176 3143 { 3177 - struct cfg80211_registered_device *rdev; 3144 + struct cfg80211_registered_device *rdev = NULL; 3178 3145 struct net_device *netdev = NULL; 3179 3146 struct wireless_dev *wdev; 3180 3147 int result = 0, rem_txq_params = 0; ··· 3185 3152 u8 coverage_class = 0; 3186 3153 u32 txq_limit = 0, txq_memory_limit = 0, txq_quantum = 0; 3187 3154 3188 - ASSERT_RTNL(); 3189 - 3155 + rtnl_lock(); 3190 3156 /* 3191 3157 * Try to find the wiphy and netdev. Normally this 3192 3158 * function shouldn't need the netdev, but this is ··· 3209 3177 if (!netdev) { 3210 3178 rdev = __cfg80211_rdev_from_attrs(genl_info_net(info), 3211 3179 info->attrs); 3212 - if (IS_ERR(rdev)) 3180 + if (IS_ERR(rdev)) { 3181 + rtnl_unlock(); 3213 3182 return PTR_ERR(rdev); 3183 + } 3214 3184 wdev = NULL; 3215 3185 netdev = NULL; 3216 3186 result = 0; 3217 3187 } else 3218 3188 wdev = netdev->ieee80211_ptr; 3189 + 3190 + wiphy_lock(&rdev->wiphy); 3191 + rtnl_unlock(); 3219 3192 3220 3193 /* 3221 3194 * end workaround code, by now the rdev is available ··· 3232 3195 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); 3233 3196 3234 3197 if (result) 3235 - return result; 3198 + goto out; 3236 3199 3237 3200 if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) { 3238 3201 struct ieee80211_txq_params txq_params; 3239 3202 struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1]; 3240 3203 3241 - if (!rdev->ops->set_txq_params) 3242 - return -EOPNOTSUPP; 3204 + if (!rdev->ops->set_txq_params) { 3205 + result = -EOPNOTSUPP; 3206 + goto out; 3207 + } 3243 3208 3244 - if (!netdev) 3245 - return -EINVAL; 3209 + if (!netdev) { 3210 + result = -EINVAL; 3211 + goto out; 3212 + } 3246 3213 3247 3214 if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && 3248 - netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) 3249 - return -EINVAL; 3215 + netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) { 3216 + result = -EINVAL; 3217 + goto out; 3218 + } 3250 3219 3251 - if (!netif_running(netdev)) 3252 - return -ENETDOWN; 3220 + if (!netif_running(netdev)) { 3221 + result = -ENETDOWN; 3222 + goto out; 3223 + } 3253 3224 3254 3225 nla_for_each_nested(nl_txq_params, 3255 3226 info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], ··· 3268 3223 txq_params_policy, 3269 3224 info->extack); 3270 3225 if (result) 3271 - return result; 3226 + goto out; 3272 3227 result = parse_txq_params(tb, &txq_params); 3273 3228 if (result) 3274 - return result; 3229 + goto out; 3275 3230 3276 3231 result = rdev_set_txq_params(rdev, netdev, 3277 3232 &txq_params); 3278 3233 if (result) 3279 - return result; 3234 + goto out; 3280 3235 } 3281 3236 } 3282 3237 ··· 3286 3241 nl80211_can_set_dev_channel(wdev) ? netdev : NULL, 3287 3242 info); 3288 3243 if (result) 3289 - return result; 3244 + goto out; 3290 3245 } 3291 3246 3292 3247 if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) { ··· 3297 3252 if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER)) 3298 3253 txp_wdev = NULL; 3299 3254 3300 - if (!rdev->ops->set_tx_power) 3301 - return -EOPNOTSUPP; 3255 + if (!rdev->ops->set_tx_power) { 3256 + result = -EOPNOTSUPP; 3257 + goto out; 3258 + } 3302 3259 3303 3260 idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING; 3304 3261 type = nla_get_u32(info->attrs[idx]); 3305 3262 3306 3263 if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] && 3307 - (type != NL80211_TX_POWER_AUTOMATIC)) 3308 - return -EINVAL; 3264 + (type != NL80211_TX_POWER_AUTOMATIC)) { 3265 + result = -EINVAL; 3266 + goto out; 3267 + } 3309 3268 3310 3269 if (type != NL80211_TX_POWER_AUTOMATIC) { 3311 3270 idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL; ··· 3318 3269 3319 3270 result = rdev_set_tx_power(rdev, txp_wdev, type, mbm); 3320 3271 if (result) 3321 - return result; 3272 + goto out; 3322 3273 } 3323 3274 3324 3275 if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] && ··· 3327 3278 3328 3279 if ((!rdev->wiphy.available_antennas_tx && 3329 3280 !rdev->wiphy.available_antennas_rx) || 3330 - !rdev->ops->set_antenna) 3331 - return -EOPNOTSUPP; 3281 + !rdev->ops->set_antenna) { 3282 + result = -EOPNOTSUPP; 3283 + goto out; 3284 + } 3332 3285 3333 3286 tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]); 3334 3287 rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]); ··· 3338 3287 /* reject antenna configurations which don't match the 3339 3288 * available antenna masks, except for the "all" mask */ 3340 3289 if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) || 3341 - (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) 3342 - return -EINVAL; 3290 + (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) { 3291 + result = -EINVAL; 3292 + goto out; 3293 + } 3343 3294 3344 3295 tx_ant = tx_ant & rdev->wiphy.available_antennas_tx; 3345 3296 rx_ant = rx_ant & rdev->wiphy.available_antennas_rx; 3346 3297 3347 3298 result = rdev_set_antenna(rdev, tx_ant, rx_ant); 3348 3299 if (result) 3349 - return result; 3300 + goto out; 3350 3301 } 3351 3302 3352 3303 changed = 0; ··· 3370 3317 if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) { 3371 3318 frag_threshold = nla_get_u32( 3372 3319 info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]); 3373 - if (frag_threshold < 256) 3374 - return -EINVAL; 3320 + if (frag_threshold < 256) { 3321 + result = -EINVAL; 3322 + goto out; 3323 + } 3375 3324 3376 3325 if (frag_threshold != (u32) -1) { 3377 3326 /* ··· 3394 3339 } 3395 3340 3396 3341 if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) { 3397 - if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) 3398 - return -EINVAL; 3342 + if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) { 3343 + result = -EINVAL; 3344 + goto out; 3345 + } 3399 3346 3400 3347 coverage_class = nla_get_u8( 3401 3348 info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]); ··· 3405 3348 } 3406 3349 3407 3350 if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) { 3408 - if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION)) 3409 - return -EOPNOTSUPP; 3351 + if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION)) { 3352 + result = -EOPNOTSUPP; 3353 + goto out; 3354 + } 3410 3355 3411 3356 changed |= WIPHY_PARAM_DYN_ACK; 3412 3357 } 3413 3358 3414 3359 if (info->attrs[NL80211_ATTR_TXQ_LIMIT]) { 3415 3360 if (!wiphy_ext_feature_isset(&rdev->wiphy, 3416 - NL80211_EXT_FEATURE_TXQS)) 3417 - return -EOPNOTSUPP; 3361 + NL80211_EXT_FEATURE_TXQS)) { 3362 + result = -EOPNOTSUPP; 3363 + goto out; 3364 + } 3418 3365 txq_limit = nla_get_u32( 3419 3366 info->attrs[NL80211_ATTR_TXQ_LIMIT]); 3420 3367 changed |= WIPHY_PARAM_TXQ_LIMIT; ··· 3426 3365 3427 3366 if (info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]) { 3428 3367 if (!wiphy_ext_feature_isset(&rdev->wiphy, 3429 - NL80211_EXT_FEATURE_TXQS)) 3430 - return -EOPNOTSUPP; 3368 + NL80211_EXT_FEATURE_TXQS)) { 3369 + result = -EOPNOTSUPP; 3370 + goto out; 3371 + } 3431 3372 txq_memory_limit = nla_get_u32( 3432 3373 info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]); 3433 3374 changed |= WIPHY_PARAM_TXQ_MEMORY_LIMIT; ··· 3437 3374 3438 3375 if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) { 3439 3376 if (!wiphy_ext_feature_isset(&rdev->wiphy, 3440 - NL80211_EXT_FEATURE_TXQS)) 3441 - return -EOPNOTSUPP; 3377 + NL80211_EXT_FEATURE_TXQS)) { 3378 + result = -EOPNOTSUPP; 3379 + goto out; 3380 + } 3442 3381 txq_quantum = nla_get_u32( 3443 3382 info->attrs[NL80211_ATTR_TXQ_QUANTUM]); 3444 3383 changed |= WIPHY_PARAM_TXQ_QUANTUM; ··· 3452 3387 u8 old_coverage_class; 3453 3388 u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum; 3454 3389 3455 - if (!rdev->ops->set_wiphy_params) 3456 - return -EOPNOTSUPP; 3390 + if (!rdev->ops->set_wiphy_params) { 3391 + result = -EOPNOTSUPP; 3392 + goto out; 3393 + } 3457 3394 3458 3395 old_retry_short = rdev->wiphy.retry_short; 3459 3396 old_retry_long = rdev->wiphy.retry_long; ··· 3493 3426 rdev->wiphy.txq_limit = old_txq_limit; 3494 3427 rdev->wiphy.txq_memory_limit = old_txq_memory_limit; 3495 3428 rdev->wiphy.txq_quantum = old_txq_quantum; 3496 - return result; 3429 + goto out; 3497 3430 } 3498 3431 } 3499 - return 0; 3432 + 3433 + result = 0; 3434 + 3435 + out: 3436 + wiphy_unlock(&rdev->wiphy); 3437 + return result; 3500 3438 } 3501 3439 3502 3440 static int nl80211_send_chandef(struct sk_buff *msg, ··· 4032 3960 return -EOPNOTSUPP; 4033 3961 4034 3962 /* 3963 + * We hold RTNL, so this is safe, without RTNL opencount cannot 3964 + * reach 0, and thus the rdev cannot be deleted. 3965 + * 3966 + * We need to do it for the dev_close(), since that will call 3967 + * the netdev notifiers, and we need to acquire the mutex there 3968 + * but don't know if we get there from here or from some other 3969 + * place (e.g. "ip link set ... down"). 3970 + */ 3971 + mutex_unlock(&rdev->wiphy.mtx); 3972 + 3973 + /* 4035 3974 * If we remove a wireless device without a netdev then clear 4036 3975 * user_ptr[1] so that nl80211_post_doit won't dereference it 4037 3976 * to check if it needs to do dev_put(). Otherwise it crashes ··· 4051 3968 */ 4052 3969 if (!wdev->netdev) 4053 3970 info->user_ptr[1] = NULL; 3971 + else 3972 + dev_close(wdev->netdev); 3973 + 3974 + mutex_lock(&rdev->wiphy.mtx); 4054 3975 4055 3976 return rdev_del_virtual_intf(rdev, wdev); 4056 3977 } ··· 5971 5884 int sta_idx = cb->args[2]; 5972 5885 int err; 5973 5886 5974 - rtnl_lock(); 5975 5887 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); 5976 5888 if (err) 5977 - goto out_err; 5889 + return err; 5890 + /* nl80211_prepare_wdev_dump acquired it in the successful case */ 5891 + __acquire(&rdev->wiphy.mtx); 5978 5892 5979 5893 if (!wdev->netdev) { 5980 5894 err = -EINVAL; ··· 6010 5922 cb->args[2] = sta_idx; 6011 5923 err = skb->len; 6012 5924 out_err: 6013 - rtnl_unlock(); 5925 + wiphy_unlock(&rdev->wiphy); 6014 5926 6015 5927 return err; 6016 5928 } ··· 6868 6780 int path_idx = cb->args[2]; 6869 6781 int err; 6870 6782 6871 - rtnl_lock(); 6872 6783 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); 6873 6784 if (err) 6874 - goto out_err; 6785 + return err; 6786 + /* nl80211_prepare_wdev_dump acquired it in the successful case */ 6787 + __acquire(&rdev->wiphy.mtx); 6875 6788 6876 6789 if (!rdev->ops->dump_mpath) { 6877 6790 err = -EOPNOTSUPP; ··· 6905 6816 cb->args[2] = path_idx; 6906 6817 err = skb->len; 6907 6818 out_err: 6908 - rtnl_unlock(); 6819 + wiphy_unlock(&rdev->wiphy); 6909 6820 return err; 6910 6821 } 6911 6822 ··· 7068 6979 int path_idx = cb->args[2]; 7069 6980 int err; 7070 6981 7071 - rtnl_lock(); 7072 6982 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); 7073 6983 if (err) 7074 - goto out_err; 6984 + return err; 6985 + /* nl80211_prepare_wdev_dump acquired it in the successful case */ 6986 + __acquire(&rdev->wiphy.mtx); 7075 6987 7076 6988 if (!rdev->ops->dump_mpp) { 7077 6989 err = -EOPNOTSUPP; ··· 7105 7015 cb->args[2] = path_idx; 7106 7016 err = skb->len; 7107 7017 out_err: 7108 - rtnl_unlock(); 7018 + wiphy_unlock(&rdev->wiphy); 7109 7019 return err; 7110 7020 } 7111 7021 ··· 7724 7634 if (!hdr) 7725 7635 goto put_failure; 7726 7636 7637 + rtnl_lock(); 7638 + 7727 7639 if (info->attrs[NL80211_ATTR_WIPHY]) { 7728 7640 bool self_managed; 7729 7641 7730 7642 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info); 7731 7643 if (IS_ERR(rdev)) { 7732 7644 nlmsg_free(msg); 7645 + rtnl_unlock(); 7733 7646 return PTR_ERR(rdev); 7734 7647 } 7735 7648 ··· 7744 7651 /* a self-managed-reg device must have a private regdom */ 7745 7652 if (WARN_ON(!regdom && self_managed)) { 7746 7653 nlmsg_free(msg); 7654 + rtnl_unlock(); 7747 7655 return -EINVAL; 7748 7656 } 7749 7657 ··· 7769 7675 rcu_read_unlock(); 7770 7676 7771 7677 genlmsg_end(msg, hdr); 7678 + rtnl_unlock(); 7772 7679 return genlmsg_reply(msg, info); 7773 7680 7774 7681 nla_put_failure_rcu: 7775 7682 rcu_read_unlock(); 7776 7683 nla_put_failure: 7684 + rtnl_unlock(); 7777 7685 put_failure: 7778 7686 nlmsg_free(msg); 7779 7687 return -EMSGSIZE; ··· 7938 7842 return -EINVAL; 7939 7843 } 7940 7844 7941 - if (!reg_is_valid_request(alpha2)) 7942 - return -EINVAL; 7845 + rtnl_lock(); 7846 + if (!reg_is_valid_request(alpha2)) { 7847 + r = -EINVAL; 7848 + goto out; 7849 + } 7943 7850 7944 7851 rd = kzalloc(struct_size(rd, reg_rules, num_rules), GFP_KERNEL); 7945 - if (!rd) 7946 - return -ENOMEM; 7852 + if (!rd) { 7853 + r = -ENOMEM; 7854 + goto out; 7855 + } 7947 7856 7948 7857 rd->n_reg_rules = num_rules; 7949 7858 rd->alpha2[0] = alpha2[0]; ··· 7980 7879 } 7981 7880 } 7982 7881 7882 + r = set_regdom(rd, REGD_SOURCE_CRDA); 7983 7883 /* set_regdom takes ownership of rd */ 7984 - return set_regdom(rd, REGD_SOURCE_CRDA); 7884 + rd = NULL; 7985 7885 bad_reg: 7986 7886 kfree(rd); 7887 + out: 7888 + rtnl_unlock(); 7987 7889 return r; 7988 7890 } 7989 7891 #endif /* CONFIG_CFG80211_CRDA_SUPPORT */ ··· 9154 9050 struct net_device *dev = info->user_ptr[1]; 9155 9051 struct wireless_dev *wdev = dev->ieee80211_ptr; 9156 9052 struct cfg80211_csa_settings params; 9157 - /* csa_attrs is defined static to avoid waste of stack size - this 9158 - * function is called under RTNL lock, so this should not be a problem. 9159 - */ 9160 - static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1]; 9053 + struct nlattr **csa_attrs = NULL; 9161 9054 int err; 9162 9055 bool need_new_beacon = false; 9163 9056 bool need_handle_dfs_flag = true; ··· 9219 9118 if (err) 9220 9119 return err; 9221 9120 9121 + csa_attrs = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*csa_attrs), 9122 + GFP_KERNEL); 9123 + if (!csa_attrs) 9124 + return -ENOMEM; 9125 + 9222 9126 err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX, 9223 9127 info->attrs[NL80211_ATTR_CSA_IES], 9224 9128 nl80211_policy, info->extack); 9225 9129 if (err) 9226 - return err; 9130 + goto free; 9227 9131 9228 9132 err = nl80211_parse_beacon(rdev, csa_attrs, &params.beacon_csa); 9229 9133 if (err) 9230 - return err; 9134 + goto free; 9231 9135 9232 - if (!csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]) 9233 - return -EINVAL; 9136 + if (!csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]) { 9137 + err = -EINVAL; 9138 + goto free; 9139 + } 9234 9140 9235 9141 len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]); 9236 - if (!len || (len % sizeof(u16))) 9237 - return -EINVAL; 9142 + if (!len || (len % sizeof(u16))) { 9143 + err = -EINVAL; 9144 + goto free; 9145 + } 9238 9146 9239 9147 params.n_counter_offsets_beacon = len / sizeof(u16); 9240 9148 if (rdev->wiphy.max_num_csa_counters && 9241 9149 (params.n_counter_offsets_beacon > 9242 - rdev->wiphy.max_num_csa_counters)) 9243 - return -EINVAL; 9150 + rdev->wiphy.max_num_csa_counters)) { 9151 + err = -EINVAL; 9152 + goto free; 9153 + } 9244 9154 9245 9155 params.counter_offsets_beacon = 9246 9156 nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_BEACON]); ··· 9260 9148 for (i = 0; i < params.n_counter_offsets_beacon; i++) { 9261 9149 u16 offset = params.counter_offsets_beacon[i]; 9262 9150 9263 - if (offset >= params.beacon_csa.tail_len) 9264 - return -EINVAL; 9151 + if (offset >= params.beacon_csa.tail_len) { 9152 + err = -EINVAL; 9153 + goto free; 9154 + } 9265 9155 9266 - if (params.beacon_csa.tail[offset] != params.count) 9267 - return -EINVAL; 9156 + if (params.beacon_csa.tail[offset] != params.count) { 9157 + err = -EINVAL; 9158 + goto free; 9159 + } 9268 9160 } 9269 9161 9270 9162 if (csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]) { 9271 9163 len = nla_len(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]); 9272 - if (!len || (len % sizeof(u16))) 9273 - return -EINVAL; 9164 + if (!len || (len % sizeof(u16))) { 9165 + err = -EINVAL; 9166 + goto free; 9167 + } 9274 9168 9275 9169 params.n_counter_offsets_presp = len / sizeof(u16); 9276 9170 if (rdev->wiphy.max_num_csa_counters && 9277 9171 (params.n_counter_offsets_presp > 9278 - rdev->wiphy.max_num_csa_counters)) 9279 - return -EINVAL; 9172 + rdev->wiphy.max_num_csa_counters)) { 9173 + err = -EINVAL; 9174 + goto free; 9175 + } 9280 9176 9281 9177 params.counter_offsets_presp = 9282 9178 nla_data(csa_attrs[NL80211_ATTR_CNTDWN_OFFS_PRESP]); ··· 9293 9173 for (i = 0; i < params.n_counter_offsets_presp; i++) { 9294 9174 u16 offset = params.counter_offsets_presp[i]; 9295 9175 9296 - if (offset >= params.beacon_csa.probe_resp_len) 9297 - return -EINVAL; 9176 + if (offset >= params.beacon_csa.probe_resp_len) { 9177 + err = -EINVAL; 9178 + goto free; 9179 + } 9298 9180 9299 9181 if (params.beacon_csa.probe_resp[offset] != 9300 - params.count) 9301 - return -EINVAL; 9182 + params.count) { 9183 + err = -EINVAL; 9184 + goto free; 9185 + } 9302 9186 } 9303 9187 } 9304 9188 9305 9189 skip_beacons: 9306 9190 err = nl80211_parse_chandef(rdev, info, &params.chandef); 9307 9191 if (err) 9308 - return err; 9192 + goto free; 9309 9193 9310 9194 if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef, 9311 - wdev->iftype)) 9312 - return -EINVAL; 9195 + wdev->iftype)) { 9196 + err = -EINVAL; 9197 + goto free; 9198 + } 9313 9199 9314 9200 err = cfg80211_chandef_dfs_required(wdev->wiphy, 9315 9201 &params.chandef, 9316 9202 wdev->iftype); 9317 9203 if (err < 0) 9318 - return err; 9204 + goto free; 9319 9205 9320 9206 if (err > 0) { 9321 9207 params.radar_required = true; 9322 9208 if (need_handle_dfs_flag && 9323 9209 !nla_get_flag(info->attrs[NL80211_ATTR_HANDLE_DFS])) { 9324 - return -EINVAL; 9210 + err = -EINVAL; 9211 + goto free; 9325 9212 } 9326 9213 } 9327 9214 ··· 9339 9212 err = rdev_channel_switch(rdev, dev, &params); 9340 9213 wdev_unlock(wdev); 9341 9214 9215 + free: 9216 + kfree(csa_attrs); 9342 9217 return err; 9343 9218 } 9344 9219 ··· 9491 9362 int start = cb->args[2], idx = 0; 9492 9363 int err; 9493 9364 9494 - rtnl_lock(); 9495 9365 err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); 9496 - if (err) { 9497 - rtnl_unlock(); 9366 + if (err) 9498 9367 return err; 9499 - } 9368 + /* nl80211_prepare_wdev_dump acquired it in the successful case */ 9369 + __acquire(&rdev->wiphy.mtx); 9500 9370 9501 9371 wdev_lock(wdev); 9502 9372 spin_lock_bh(&rdev->bss_lock); ··· 9526 9398 wdev_unlock(wdev); 9527 9399 9528 9400 cb->args[2] = idx; 9529 - rtnl_unlock(); 9401 + wiphy_unlock(&rdev->wiphy); 9530 9402 9531 9403 return skb->len; 9532 9404 } ··· 9624 9496 if (!attrbuf) 9625 9497 return -ENOMEM; 9626 9498 9627 - rtnl_lock(); 9628 9499 res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev); 9629 - if (res) 9630 - goto out_err; 9500 + if (res) { 9501 + kfree(attrbuf); 9502 + return res; 9503 + } 9504 + /* nl80211_prepare_wdev_dump acquired it in the successful case */ 9505 + __acquire(&rdev->wiphy.mtx); 9631 9506 9632 9507 /* prepare_wdev_dump parsed the attributes */ 9633 9508 radio_stats = attrbuf[NL80211_ATTR_SURVEY_RADIO_STATS]; ··· 9672 9541 res = skb->len; 9673 9542 out_err: 9674 9543 kfree(attrbuf); 9675 - rtnl_unlock(); 9544 + wiphy_unlock(&rdev->wiphy); 9676 9545 return res; 9677 9546 } 9678 9547 ··· 10534 10403 static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) 10535 10404 { 10536 10405 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 10537 - struct wireless_dev *wdev = 10538 - __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs); 10406 + struct wireless_dev *wdev; 10539 10407 int err; 10408 + 10409 + lockdep_assert_held(&rdev->wiphy.mtx); 10410 + 10411 + wdev = __cfg80211_wdev_from_attrs(rdev, genl_info_net(info), 10412 + info->attrs); 10540 10413 10541 10414 if (!rdev->ops->testmode_cmd) 10542 10415 return -EOPNOTSUPP; ··· 13726 13591 { 13727 13592 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 13728 13593 struct wireless_dev *wdev = 13729 - __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs); 13594 + __cfg80211_wdev_from_attrs(rdev, genl_info_net(info), 13595 + info->attrs); 13730 13596 int i, err; 13731 13597 u32 vid, subcmd; 13732 13598 ··· 13851 13715 goto out; 13852 13716 } 13853 13717 13854 - *wdev = __cfg80211_wdev_from_attrs(sock_net(skb->sk), attrbuf); 13718 + *wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(skb->sk), attrbuf); 13855 13719 if (IS_ERR(*wdev)) 13856 13720 *wdev = NULL; 13857 13721 ··· 14786 14650 static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, 14787 14651 struct genl_info *info) 14788 14652 { 14789 - struct cfg80211_registered_device *rdev; 14653 + struct cfg80211_registered_device *rdev = NULL; 14790 14654 struct wireless_dev *wdev; 14791 14655 struct net_device *dev; 14792 - bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL; 14793 14656 14794 - if (rtnl) 14795 - rtnl_lock(); 14796 - 14657 + rtnl_lock(); 14797 14658 if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) { 14798 14659 rdev = cfg80211_get_dev_from_info(genl_info_net(info), info); 14799 14660 if (IS_ERR(rdev)) { 14800 - if (rtnl) 14801 - rtnl_unlock(); 14661 + rtnl_unlock(); 14802 14662 return PTR_ERR(rdev); 14803 14663 } 14804 14664 info->user_ptr[0] = rdev; 14805 14665 } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV || 14806 14666 ops->internal_flags & NL80211_FLAG_NEED_WDEV) { 14807 - ASSERT_RTNL(); 14808 - 14809 - wdev = __cfg80211_wdev_from_attrs(genl_info_net(info), 14667 + wdev = __cfg80211_wdev_from_attrs(NULL, genl_info_net(info), 14810 14668 info->attrs); 14811 14669 if (IS_ERR(wdev)) { 14812 - if (rtnl) 14813 - rtnl_unlock(); 14670 + rtnl_unlock(); 14814 14671 return PTR_ERR(wdev); 14815 14672 } 14816 14673 ··· 14812 14683 14813 14684 if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { 14814 14685 if (!dev) { 14815 - if (rtnl) 14816 - rtnl_unlock(); 14686 + rtnl_unlock(); 14817 14687 return -EINVAL; 14818 14688 } 14819 14689 ··· 14823 14695 14824 14696 if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && 14825 14697 !wdev_running(wdev)) { 14826 - if (rtnl) 14827 - rtnl_unlock(); 14698 + rtnl_unlock(); 14828 14699 return -ENETDOWN; 14829 14700 } 14830 14701 ··· 14832 14705 14833 14706 info->user_ptr[0] = rdev; 14834 14707 } 14708 + 14709 + if (rdev) { 14710 + wiphy_lock(&rdev->wiphy); 14711 + /* we keep the mutex locked until post_doit */ 14712 + __release(&rdev->wiphy.mtx); 14713 + } 14714 + if (!(ops->internal_flags & NL80211_FLAG_NEED_RTNL)) 14715 + rtnl_unlock(); 14835 14716 14836 14717 return 0; 14837 14718 } ··· 14856 14721 } else { 14857 14722 dev_put(info->user_ptr[1]); 14858 14723 } 14724 + } 14725 + 14726 + if (info->user_ptr[0]) { 14727 + struct cfg80211_registered_device *rdev = info->user_ptr[0]; 14728 + 14729 + /* we kept the mutex locked since pre_doit */ 14730 + __acquire(&rdev->wiphy.mtx); 14731 + wiphy_unlock(&rdev->wiphy); 14859 14732 } 14860 14733 14861 14734 if (ops->internal_flags & NL80211_FLAG_NEED_RTNL) ··· 14994 14851 .dumpit = nl80211_dump_wiphy, 14995 14852 .done = nl80211_dump_wiphy_done, 14996 14853 /* can be retrieved by unprivileged users */ 14997 - .internal_flags = NL80211_FLAG_NEED_WIPHY | 14998 - NL80211_FLAG_NEED_RTNL, 14854 + .internal_flags = NL80211_FLAG_NEED_WIPHY, 14999 14855 }, 15000 14856 }; 15001 14857 ··· 15004 14862 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15005 14863 .doit = nl80211_set_wiphy, 15006 14864 .flags = GENL_UNS_ADMIN_PERM, 15007 - .internal_flags = NL80211_FLAG_NEED_RTNL, 15008 14865 }, 15009 14866 { 15010 14867 .cmd = NL80211_CMD_GET_INTERFACE, ··· 15011 14870 .doit = nl80211_get_interface, 15012 14871 .dumpit = nl80211_dump_interface, 15013 14872 /* can be retrieved by unprivileged users */ 15014 - .internal_flags = NL80211_FLAG_NEED_WDEV | 15015 - NL80211_FLAG_NEED_RTNL, 14873 + .internal_flags = NL80211_FLAG_NEED_WDEV, 15016 14874 }, 15017 14875 { 15018 14876 .cmd = NL80211_CMD_SET_INTERFACE, ··· 15042 14902 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15043 14903 .doit = nl80211_get_key, 15044 14904 .flags = GENL_UNS_ADMIN_PERM, 15045 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15046 - NL80211_FLAG_NEED_RTNL, 14905 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15047 14906 }, 15048 14907 { 15049 14908 .cmd = NL80211_CMD_SET_KEY, ··· 15050 14911 .doit = nl80211_set_key, 15051 14912 .flags = GENL_UNS_ADMIN_PERM, 15052 14913 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15053 - NL80211_FLAG_NEED_RTNL | 15054 14914 NL80211_FLAG_CLEAR_SKB, 15055 14915 }, 15056 14916 { ··· 15058 14920 .doit = nl80211_new_key, 15059 14921 .flags = GENL_UNS_ADMIN_PERM, 15060 14922 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15061 - NL80211_FLAG_NEED_RTNL | 15062 14923 NL80211_FLAG_CLEAR_SKB, 15063 14924 }, 15064 14925 { ··· 15065 14928 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15066 14929 .doit = nl80211_del_key, 15067 14930 .flags = GENL_UNS_ADMIN_PERM, 15068 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15069 - NL80211_FLAG_NEED_RTNL, 14931 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15070 14932 }, 15071 14933 { 15072 14934 .cmd = NL80211_CMD_SET_BEACON, 15073 14935 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15074 14936 .flags = GENL_UNS_ADMIN_PERM, 15075 14937 .doit = nl80211_set_beacon, 15076 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15077 - NL80211_FLAG_NEED_RTNL, 14938 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15078 14939 }, 15079 14940 { 15080 14941 .cmd = NL80211_CMD_START_AP, 15081 14942 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15082 14943 .flags = GENL_UNS_ADMIN_PERM, 15083 14944 .doit = nl80211_start_ap, 15084 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15085 - NL80211_FLAG_NEED_RTNL, 14945 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15086 14946 }, 15087 14947 { 15088 14948 .cmd = NL80211_CMD_STOP_AP, 15089 14949 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15090 14950 .flags = GENL_UNS_ADMIN_PERM, 15091 14951 .doit = nl80211_stop_ap, 15092 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15093 - NL80211_FLAG_NEED_RTNL, 14952 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15094 14953 }, 15095 14954 { 15096 14955 .cmd = NL80211_CMD_GET_STATION, 15097 14956 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15098 14957 .doit = nl80211_get_station, 15099 14958 .dumpit = nl80211_dump_station, 15100 - .internal_flags = NL80211_FLAG_NEED_NETDEV | 15101 - NL80211_FLAG_NEED_RTNL, 14959 + .internal_flags = NL80211_FLAG_NEED_NETDEV, 15102 14960 }, 15103 14961 { 15104 14962 .cmd = NL80211_CMD_SET_STATION, 15105 14963 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15106 14964 .doit = nl80211_set_station, 15107 14965 .flags = GENL_UNS_ADMIN_PERM, 15108 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15109 - NL80211_FLAG_NEED_RTNL, 14966 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15110 14967 }, 15111 14968 { 15112 14969 .cmd = NL80211_CMD_NEW_STATION, 15113 14970 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15114 14971 .doit = nl80211_new_station, 15115 14972 .flags = GENL_UNS_ADMIN_PERM, 15116 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15117 - NL80211_FLAG_NEED_RTNL, 14973 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15118 14974 }, 15119 14975 { 15120 14976 .cmd = NL80211_CMD_DEL_STATION, 15121 14977 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15122 14978 .doit = nl80211_del_station, 15123 14979 .flags = GENL_UNS_ADMIN_PERM, 15124 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15125 - NL80211_FLAG_NEED_RTNL, 14980 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15126 14981 }, 15127 14982 { 15128 14983 .cmd = NL80211_CMD_GET_MPATH, ··· 15122 14993 .doit = nl80211_get_mpath, 15123 14994 .dumpit = nl80211_dump_mpath, 15124 14995 .flags = GENL_UNS_ADMIN_PERM, 15125 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15126 - NL80211_FLAG_NEED_RTNL, 14996 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15127 14997 }, 15128 14998 { 15129 14999 .cmd = NL80211_CMD_GET_MPP, ··· 15130 15002 .doit = nl80211_get_mpp, 15131 15003 .dumpit = nl80211_dump_mpp, 15132 15004 .flags = GENL_UNS_ADMIN_PERM, 15133 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15134 - NL80211_FLAG_NEED_RTNL, 15005 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15135 15006 }, 15136 15007 { 15137 15008 .cmd = NL80211_CMD_SET_MPATH, 15138 15009 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15139 15010 .doit = nl80211_set_mpath, 15140 15011 .flags = GENL_UNS_ADMIN_PERM, 15141 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15142 - NL80211_FLAG_NEED_RTNL, 15012 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15143 15013 }, 15144 15014 { 15145 15015 .cmd = NL80211_CMD_NEW_MPATH, 15146 15016 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15147 15017 .doit = nl80211_new_mpath, 15148 15018 .flags = GENL_UNS_ADMIN_PERM, 15149 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15150 - NL80211_FLAG_NEED_RTNL, 15019 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15151 15020 }, 15152 15021 { 15153 15022 .cmd = NL80211_CMD_DEL_MPATH, 15154 15023 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15155 15024 .doit = nl80211_del_mpath, 15156 15025 .flags = GENL_UNS_ADMIN_PERM, 15157 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15158 - NL80211_FLAG_NEED_RTNL, 15026 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15159 15027 }, 15160 15028 { 15161 15029 .cmd = NL80211_CMD_SET_BSS, 15162 15030 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15163 15031 .doit = nl80211_set_bss, 15164 15032 .flags = GENL_UNS_ADMIN_PERM, 15165 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15166 - NL80211_FLAG_NEED_RTNL, 15033 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15167 15034 }, 15168 15035 { 15169 15036 .cmd = NL80211_CMD_GET_REG, 15170 15037 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15171 15038 .doit = nl80211_get_reg_do, 15172 15039 .dumpit = nl80211_get_reg_dump, 15173 - .internal_flags = NL80211_FLAG_NEED_RTNL, 15040 + .internal_flags = 0, 15174 15041 /* can be retrieved by unprivileged users */ 15175 15042 }, 15176 15043 #ifdef CONFIG_CFG80211_CRDA_SUPPORT ··· 15174 15051 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15175 15052 .doit = nl80211_set_reg, 15176 15053 .flags = GENL_ADMIN_PERM, 15177 - .internal_flags = NL80211_FLAG_NEED_RTNL, 15054 + .internal_flags = 0, 15178 15055 }, 15179 15056 #endif 15180 15057 { ··· 15194 15071 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15195 15072 .doit = nl80211_get_mesh_config, 15196 15073 /* can be retrieved by unprivileged users */ 15197 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15198 - NL80211_FLAG_NEED_RTNL, 15074 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15199 15075 }, 15200 15076 { 15201 15077 .cmd = NL80211_CMD_SET_MESH_CONFIG, 15202 15078 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15203 15079 .doit = nl80211_update_mesh_config, 15204 15080 .flags = GENL_UNS_ADMIN_PERM, 15205 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15206 - NL80211_FLAG_NEED_RTNL, 15081 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15207 15082 }, 15208 15083 { 15209 15084 .cmd = NL80211_CMD_TRIGGER_SCAN, 15210 15085 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15211 15086 .doit = nl80211_trigger_scan, 15212 15087 .flags = GENL_UNS_ADMIN_PERM, 15213 - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | 15214 - NL80211_FLAG_NEED_RTNL, 15088 + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, 15215 15089 }, 15216 15090 { 15217 15091 .cmd = NL80211_CMD_ABORT_SCAN, 15218 15092 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15219 15093 .doit = nl80211_abort_scan, 15220 15094 .flags = GENL_UNS_ADMIN_PERM, 15221 - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | 15222 - NL80211_FLAG_NEED_RTNL, 15095 + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, 15223 15096 }, 15224 15097 { 15225 15098 .cmd = NL80211_CMD_GET_SCAN, ··· 15227 15108 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15228 15109 .doit = nl80211_start_sched_scan, 15229 15110 .flags = GENL_UNS_ADMIN_PERM, 15230 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15231 - NL80211_FLAG_NEED_RTNL, 15111 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15232 15112 }, 15233 15113 { 15234 15114 .cmd = NL80211_CMD_STOP_SCHED_SCAN, 15235 15115 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15236 15116 .doit = nl80211_stop_sched_scan, 15237 15117 .flags = GENL_UNS_ADMIN_PERM, 15238 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15239 - NL80211_FLAG_NEED_RTNL, 15118 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15240 15119 }, 15241 15120 { 15242 15121 .cmd = NL80211_CMD_AUTHENTICATE, ··· 15242 15125 .doit = nl80211_authenticate, 15243 15126 .flags = GENL_UNS_ADMIN_PERM, 15244 15127 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15245 - NL80211_FLAG_NEED_RTNL | 15128 + 0 | 15246 15129 NL80211_FLAG_CLEAR_SKB, 15247 15130 }, 15248 15131 { ··· 15251 15134 .doit = nl80211_associate, 15252 15135 .flags = GENL_UNS_ADMIN_PERM, 15253 15136 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15254 - NL80211_FLAG_NEED_RTNL | 15137 + 0 | 15255 15138 NL80211_FLAG_CLEAR_SKB, 15256 15139 }, 15257 15140 { ··· 15259 15142 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15260 15143 .doit = nl80211_deauthenticate, 15261 15144 .flags = GENL_UNS_ADMIN_PERM, 15262 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15263 - NL80211_FLAG_NEED_RTNL, 15145 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15264 15146 }, 15265 15147 { 15266 15148 .cmd = NL80211_CMD_DISASSOCIATE, 15267 15149 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15268 15150 .doit = nl80211_disassociate, 15269 15151 .flags = GENL_UNS_ADMIN_PERM, 15270 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15271 - NL80211_FLAG_NEED_RTNL, 15152 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15272 15153 }, 15273 15154 { 15274 15155 .cmd = NL80211_CMD_JOIN_IBSS, 15275 15156 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15276 15157 .doit = nl80211_join_ibss, 15277 15158 .flags = GENL_UNS_ADMIN_PERM, 15278 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15279 - NL80211_FLAG_NEED_RTNL, 15159 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15280 15160 }, 15281 15161 { 15282 15162 .cmd = NL80211_CMD_LEAVE_IBSS, 15283 15163 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15284 15164 .doit = nl80211_leave_ibss, 15285 15165 .flags = GENL_UNS_ADMIN_PERM, 15286 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15287 - NL80211_FLAG_NEED_RTNL, 15166 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15288 15167 }, 15289 15168 #ifdef CONFIG_NL80211_TESTMODE 15290 15169 { ··· 15289 15176 .doit = nl80211_testmode_do, 15290 15177 .dumpit = nl80211_testmode_dump, 15291 15178 .flags = GENL_UNS_ADMIN_PERM, 15292 - .internal_flags = NL80211_FLAG_NEED_WIPHY | 15293 - NL80211_FLAG_NEED_RTNL, 15179 + .internal_flags = NL80211_FLAG_NEED_WIPHY, 15294 15180 }, 15295 15181 #endif 15296 15182 { ··· 15298 15186 .doit = nl80211_connect, 15299 15187 .flags = GENL_UNS_ADMIN_PERM, 15300 15188 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15301 - NL80211_FLAG_NEED_RTNL | 15189 + 0 | 15302 15190 NL80211_FLAG_CLEAR_SKB, 15303 15191 }, 15304 15192 { ··· 15307 15195 .doit = nl80211_update_connect_params, 15308 15196 .flags = GENL_ADMIN_PERM, 15309 15197 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15310 - NL80211_FLAG_NEED_RTNL | 15198 + 0 | 15311 15199 NL80211_FLAG_CLEAR_SKB, 15312 15200 }, 15313 15201 { ··· 15315 15203 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15316 15204 .doit = nl80211_disconnect, 15317 15205 .flags = GENL_UNS_ADMIN_PERM, 15318 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15319 - NL80211_FLAG_NEED_RTNL, 15206 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15320 15207 }, 15321 15208 { 15322 15209 .cmd = NL80211_CMD_SET_WIPHY_NETNS, 15323 15210 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15324 15211 .doit = nl80211_wiphy_netns, 15325 15212 .flags = GENL_UNS_ADMIN_PERM, 15326 - .internal_flags = NL80211_FLAG_NEED_WIPHY | 15327 - NL80211_FLAG_NEED_RTNL, 15213 + .internal_flags = NL80211_FLAG_NEED_WIPHY, 15328 15214 }, 15329 15215 { 15330 15216 .cmd = NL80211_CMD_GET_SURVEY, ··· 15335 15225 .doit = nl80211_setdel_pmksa, 15336 15226 .flags = GENL_UNS_ADMIN_PERM, 15337 15227 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15338 - NL80211_FLAG_NEED_RTNL | 15228 + 0 | 15339 15229 NL80211_FLAG_CLEAR_SKB, 15340 15230 }, 15341 15231 { ··· 15343 15233 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15344 15234 .doit = nl80211_setdel_pmksa, 15345 15235 .flags = GENL_UNS_ADMIN_PERM, 15346 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15347 - NL80211_FLAG_NEED_RTNL, 15236 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15348 15237 }, 15349 15238 { 15350 15239 .cmd = NL80211_CMD_FLUSH_PMKSA, 15351 15240 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15352 15241 .doit = nl80211_flush_pmksa, 15353 15242 .flags = GENL_UNS_ADMIN_PERM, 15354 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15355 - NL80211_FLAG_NEED_RTNL, 15243 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15356 15244 }, 15357 15245 { 15358 15246 .cmd = NL80211_CMD_REMAIN_ON_CHANNEL, 15359 15247 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15360 15248 .doit = nl80211_remain_on_channel, 15361 15249 .flags = GENL_UNS_ADMIN_PERM, 15362 - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | 15363 - NL80211_FLAG_NEED_RTNL, 15250 + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, 15364 15251 }, 15365 15252 { 15366 15253 .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, 15367 15254 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15368 15255 .doit = nl80211_cancel_remain_on_channel, 15369 15256 .flags = GENL_UNS_ADMIN_PERM, 15370 - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | 15371 - NL80211_FLAG_NEED_RTNL, 15257 + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, 15372 15258 }, 15373 15259 { 15374 15260 .cmd = NL80211_CMD_SET_TX_BITRATE_MASK, 15375 15261 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15376 15262 .doit = nl80211_set_tx_bitrate_mask, 15377 15263 .flags = GENL_UNS_ADMIN_PERM, 15378 - .internal_flags = NL80211_FLAG_NEED_NETDEV | 15379 - NL80211_FLAG_NEED_RTNL, 15264 + .internal_flags = NL80211_FLAG_NEED_NETDEV, 15380 15265 }, 15381 15266 { 15382 15267 .cmd = NL80211_CMD_REGISTER_FRAME, 15383 15268 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15384 15269 .doit = nl80211_register_mgmt, 15385 15270 .flags = GENL_UNS_ADMIN_PERM, 15386 - .internal_flags = NL80211_FLAG_NEED_WDEV | 15387 - NL80211_FLAG_NEED_RTNL, 15271 + .internal_flags = NL80211_FLAG_NEED_WDEV, 15388 15272 }, 15389 15273 { 15390 15274 .cmd = NL80211_CMD_FRAME, 15391 15275 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15392 15276 .doit = nl80211_tx_mgmt, 15393 15277 .flags = GENL_UNS_ADMIN_PERM, 15394 - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | 15395 - NL80211_FLAG_NEED_RTNL, 15278 + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, 15396 15279 }, 15397 15280 { 15398 15281 .cmd = NL80211_CMD_FRAME_WAIT_CANCEL, 15399 15282 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15400 15283 .doit = nl80211_tx_mgmt_cancel_wait, 15401 15284 .flags = GENL_UNS_ADMIN_PERM, 15402 - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | 15403 - NL80211_FLAG_NEED_RTNL, 15285 + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, 15404 15286 }, 15405 15287 { 15406 15288 .cmd = NL80211_CMD_SET_POWER_SAVE, 15407 15289 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15408 15290 .doit = nl80211_set_power_save, 15409 15291 .flags = GENL_UNS_ADMIN_PERM, 15410 - .internal_flags = NL80211_FLAG_NEED_NETDEV | 15411 - NL80211_FLAG_NEED_RTNL, 15292 + .internal_flags = NL80211_FLAG_NEED_NETDEV, 15412 15293 }, 15413 15294 { 15414 15295 .cmd = NL80211_CMD_GET_POWER_SAVE, 15415 15296 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15416 15297 .doit = nl80211_get_power_save, 15417 15298 /* can be retrieved by unprivileged users */ 15418 - .internal_flags = NL80211_FLAG_NEED_NETDEV | 15419 - NL80211_FLAG_NEED_RTNL, 15299 + .internal_flags = NL80211_FLAG_NEED_NETDEV, 15420 15300 }, 15421 15301 { 15422 15302 .cmd = NL80211_CMD_SET_CQM, 15423 15303 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15424 15304 .doit = nl80211_set_cqm, 15425 15305 .flags = GENL_UNS_ADMIN_PERM, 15426 - .internal_flags = NL80211_FLAG_NEED_NETDEV | 15427 - NL80211_FLAG_NEED_RTNL, 15306 + .internal_flags = NL80211_FLAG_NEED_NETDEV, 15428 15307 }, 15429 15308 { 15430 15309 .cmd = NL80211_CMD_SET_CHANNEL, 15431 15310 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15432 15311 .doit = nl80211_set_channel, 15433 15312 .flags = GENL_UNS_ADMIN_PERM, 15434 - .internal_flags = NL80211_FLAG_NEED_NETDEV | 15435 - NL80211_FLAG_NEED_RTNL, 15313 + .internal_flags = NL80211_FLAG_NEED_NETDEV, 15436 15314 }, 15437 15315 { 15438 15316 .cmd = NL80211_CMD_JOIN_MESH, 15439 15317 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15440 15318 .doit = nl80211_join_mesh, 15441 15319 .flags = GENL_UNS_ADMIN_PERM, 15442 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15443 - NL80211_FLAG_NEED_RTNL, 15320 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15444 15321 }, 15445 15322 { 15446 15323 .cmd = NL80211_CMD_LEAVE_MESH, 15447 15324 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15448 15325 .doit = nl80211_leave_mesh, 15449 15326 .flags = GENL_UNS_ADMIN_PERM, 15450 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15451 - NL80211_FLAG_NEED_RTNL, 15327 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15452 15328 }, 15453 15329 { 15454 15330 .cmd = NL80211_CMD_JOIN_OCB, 15455 15331 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15456 15332 .doit = nl80211_join_ocb, 15457 15333 .flags = GENL_UNS_ADMIN_PERM, 15458 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15459 - NL80211_FLAG_NEED_RTNL, 15334 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15460 15335 }, 15461 15336 { 15462 15337 .cmd = NL80211_CMD_LEAVE_OCB, 15463 15338 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15464 15339 .doit = nl80211_leave_ocb, 15465 15340 .flags = GENL_UNS_ADMIN_PERM, 15466 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15467 - NL80211_FLAG_NEED_RTNL, 15341 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15468 15342 }, 15469 15343 #ifdef CONFIG_PM 15470 15344 { ··· 15456 15362 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15457 15363 .doit = nl80211_get_wowlan, 15458 15364 /* can be retrieved by unprivileged users */ 15459 - .internal_flags = NL80211_FLAG_NEED_WIPHY | 15460 - NL80211_FLAG_NEED_RTNL, 15365 + .internal_flags = NL80211_FLAG_NEED_WIPHY, 15461 15366 }, 15462 15367 { 15463 15368 .cmd = NL80211_CMD_SET_WOWLAN, 15464 15369 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15465 15370 .doit = nl80211_set_wowlan, 15466 15371 .flags = GENL_UNS_ADMIN_PERM, 15467 - .internal_flags = NL80211_FLAG_NEED_WIPHY | 15468 - NL80211_FLAG_NEED_RTNL, 15372 + .internal_flags = NL80211_FLAG_NEED_WIPHY, 15469 15373 }, 15470 15374 #endif 15471 15375 { ··· 15472 15380 .doit = nl80211_set_rekey_data, 15473 15381 .flags = GENL_UNS_ADMIN_PERM, 15474 15382 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15475 - NL80211_FLAG_NEED_RTNL | 15383 + 0 | 15476 15384 NL80211_FLAG_CLEAR_SKB, 15477 15385 }, 15478 15386 { ··· 15480 15388 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15481 15389 .doit = nl80211_tdls_mgmt, 15482 15390 .flags = GENL_UNS_ADMIN_PERM, 15483 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15484 - NL80211_FLAG_NEED_RTNL, 15391 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15485 15392 }, 15486 15393 { 15487 15394 .cmd = NL80211_CMD_TDLS_OPER, 15488 15395 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15489 15396 .doit = nl80211_tdls_oper, 15490 15397 .flags = GENL_UNS_ADMIN_PERM, 15491 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15492 - NL80211_FLAG_NEED_RTNL, 15398 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15493 15399 }, 15494 15400 { 15495 15401 .cmd = NL80211_CMD_UNEXPECTED_FRAME, 15496 15402 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15497 15403 .doit = nl80211_register_unexpected_frame, 15498 15404 .flags = GENL_UNS_ADMIN_PERM, 15499 - .internal_flags = NL80211_FLAG_NEED_NETDEV | 15500 - NL80211_FLAG_NEED_RTNL, 15405 + .internal_flags = NL80211_FLAG_NEED_NETDEV, 15501 15406 }, 15502 15407 { 15503 15408 .cmd = NL80211_CMD_PROBE_CLIENT, 15504 15409 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15505 15410 .doit = nl80211_probe_client, 15506 15411 .flags = GENL_UNS_ADMIN_PERM, 15507 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15508 - NL80211_FLAG_NEED_RTNL, 15412 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15509 15413 }, 15510 15414 { 15511 15415 .cmd = NL80211_CMD_REGISTER_BEACONS, 15512 15416 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15513 15417 .doit = nl80211_register_beacons, 15514 15418 .flags = GENL_UNS_ADMIN_PERM, 15515 - .internal_flags = NL80211_FLAG_NEED_WIPHY | 15516 - NL80211_FLAG_NEED_RTNL, 15419 + .internal_flags = NL80211_FLAG_NEED_WIPHY, 15517 15420 }, 15518 15421 { 15519 15422 .cmd = NL80211_CMD_SET_NOACK_MAP, 15520 15423 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15521 15424 .doit = nl80211_set_noack_map, 15522 15425 .flags = GENL_UNS_ADMIN_PERM, 15523 - .internal_flags = NL80211_FLAG_NEED_NETDEV | 15524 - NL80211_FLAG_NEED_RTNL, 15426 + .internal_flags = NL80211_FLAG_NEED_NETDEV, 15525 15427 }, 15526 15428 { 15527 15429 .cmd = NL80211_CMD_START_P2P_DEVICE, ··· 15554 15468 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15555 15469 .doit = nl80211_nan_add_func, 15556 15470 .flags = GENL_ADMIN_PERM, 15557 - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | 15558 - NL80211_FLAG_NEED_RTNL, 15471 + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, 15559 15472 }, 15560 15473 { 15561 15474 .cmd = NL80211_CMD_DEL_NAN_FUNCTION, 15562 15475 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15563 15476 .doit = nl80211_nan_del_func, 15564 15477 .flags = GENL_ADMIN_PERM, 15565 - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | 15566 - NL80211_FLAG_NEED_RTNL, 15478 + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, 15567 15479 }, 15568 15480 { 15569 15481 .cmd = NL80211_CMD_CHANGE_NAN_CONFIG, 15570 15482 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15571 15483 .doit = nl80211_nan_change_config, 15572 15484 .flags = GENL_ADMIN_PERM, 15573 - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | 15574 - NL80211_FLAG_NEED_RTNL, 15485 + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, 15575 15486 }, 15576 15487 { 15577 15488 .cmd = NL80211_CMD_SET_MCAST_RATE, 15578 15489 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15579 15490 .doit = nl80211_set_mcast_rate, 15580 15491 .flags = GENL_UNS_ADMIN_PERM, 15581 - .internal_flags = NL80211_FLAG_NEED_NETDEV | 15582 - NL80211_FLAG_NEED_RTNL, 15492 + .internal_flags = NL80211_FLAG_NEED_NETDEV, 15583 15493 }, 15584 15494 { 15585 15495 .cmd = NL80211_CMD_SET_MAC_ACL, 15586 15496 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15587 15497 .doit = nl80211_set_mac_acl, 15588 15498 .flags = GENL_UNS_ADMIN_PERM, 15589 - .internal_flags = NL80211_FLAG_NEED_NETDEV | 15590 - NL80211_FLAG_NEED_RTNL, 15499 + .internal_flags = NL80211_FLAG_NEED_NETDEV, 15591 15500 }, 15592 15501 { 15593 15502 .cmd = NL80211_CMD_RADAR_DETECT, 15594 15503 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15595 15504 .doit = nl80211_start_radar_detection, 15596 15505 .flags = GENL_UNS_ADMIN_PERM, 15597 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15598 - NL80211_FLAG_NEED_RTNL, 15506 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15599 15507 }, 15600 15508 { 15601 15509 .cmd = NL80211_CMD_GET_PROTOCOL_FEATURES, ··· 15601 15521 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15602 15522 .doit = nl80211_update_ft_ies, 15603 15523 .flags = GENL_UNS_ADMIN_PERM, 15604 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15605 - NL80211_FLAG_NEED_RTNL, 15524 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15606 15525 }, 15607 15526 { 15608 15527 .cmd = NL80211_CMD_CRIT_PROTOCOL_START, 15609 15528 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15610 15529 .doit = nl80211_crit_protocol_start, 15611 15530 .flags = GENL_UNS_ADMIN_PERM, 15612 - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | 15613 - NL80211_FLAG_NEED_RTNL, 15531 + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, 15614 15532 }, 15615 15533 { 15616 15534 .cmd = NL80211_CMD_CRIT_PROTOCOL_STOP, 15617 15535 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15618 15536 .doit = nl80211_crit_protocol_stop, 15619 15537 .flags = GENL_UNS_ADMIN_PERM, 15620 - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | 15621 - NL80211_FLAG_NEED_RTNL, 15538 + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, 15622 15539 }, 15623 15540 { 15624 15541 .cmd = NL80211_CMD_GET_COALESCE, 15625 15542 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15626 15543 .doit = nl80211_get_coalesce, 15627 - .internal_flags = NL80211_FLAG_NEED_WIPHY | 15628 - NL80211_FLAG_NEED_RTNL, 15544 + .internal_flags = NL80211_FLAG_NEED_WIPHY, 15629 15545 }, 15630 15546 { 15631 15547 .cmd = NL80211_CMD_SET_COALESCE, 15632 15548 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15633 15549 .doit = nl80211_set_coalesce, 15634 15550 .flags = GENL_UNS_ADMIN_PERM, 15635 - .internal_flags = NL80211_FLAG_NEED_WIPHY | 15636 - NL80211_FLAG_NEED_RTNL, 15551 + .internal_flags = NL80211_FLAG_NEED_WIPHY, 15637 15552 }, 15638 15553 { 15639 15554 .cmd = NL80211_CMD_CHANNEL_SWITCH, 15640 15555 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15641 15556 .doit = nl80211_channel_switch, 15642 15557 .flags = GENL_UNS_ADMIN_PERM, 15643 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15644 - NL80211_FLAG_NEED_RTNL, 15558 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15645 15559 }, 15646 15560 { 15647 15561 .cmd = NL80211_CMD_VENDOR, ··· 15644 15570 .dumpit = nl80211_vendor_cmd_dump, 15645 15571 .flags = GENL_UNS_ADMIN_PERM, 15646 15572 .internal_flags = NL80211_FLAG_NEED_WIPHY | 15647 - NL80211_FLAG_NEED_RTNL | 15573 + 0 | 15648 15574 NL80211_FLAG_CLEAR_SKB, 15649 15575 }, 15650 15576 { ··· 15652 15578 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15653 15579 .doit = nl80211_set_qos_map, 15654 15580 .flags = GENL_UNS_ADMIN_PERM, 15655 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15656 - NL80211_FLAG_NEED_RTNL, 15581 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15657 15582 }, 15658 15583 { 15659 15584 .cmd = NL80211_CMD_ADD_TX_TS, 15660 15585 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15661 15586 .doit = nl80211_add_tx_ts, 15662 15587 .flags = GENL_UNS_ADMIN_PERM, 15663 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15664 - NL80211_FLAG_NEED_RTNL, 15588 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15665 15589 }, 15666 15590 { 15667 15591 .cmd = NL80211_CMD_DEL_TX_TS, 15668 15592 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15669 15593 .doit = nl80211_del_tx_ts, 15670 15594 .flags = GENL_UNS_ADMIN_PERM, 15671 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15672 - NL80211_FLAG_NEED_RTNL, 15595 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15673 15596 }, 15674 15597 { 15675 15598 .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH, 15676 15599 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15677 15600 .doit = nl80211_tdls_channel_switch, 15678 15601 .flags = GENL_UNS_ADMIN_PERM, 15679 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15680 - NL80211_FLAG_NEED_RTNL, 15602 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15681 15603 }, 15682 15604 { 15683 15605 .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH, 15684 15606 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15685 15607 .doit = nl80211_tdls_cancel_channel_switch, 15686 15608 .flags = GENL_UNS_ADMIN_PERM, 15687 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15688 - NL80211_FLAG_NEED_RTNL, 15609 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15689 15610 }, 15690 15611 { 15691 15612 .cmd = NL80211_CMD_SET_MULTICAST_TO_UNICAST, 15692 15613 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15693 15614 .doit = nl80211_set_multicast_to_unicast, 15694 15615 .flags = GENL_UNS_ADMIN_PERM, 15695 - .internal_flags = NL80211_FLAG_NEED_NETDEV | 15696 - NL80211_FLAG_NEED_RTNL, 15616 + .internal_flags = NL80211_FLAG_NEED_NETDEV, 15697 15617 }, 15698 15618 { 15699 15619 .cmd = NL80211_CMD_SET_PMK, 15700 15620 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15701 15621 .doit = nl80211_set_pmk, 15702 15622 .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15703 - NL80211_FLAG_NEED_RTNL | 15623 + 0 | 15704 15624 NL80211_FLAG_CLEAR_SKB, 15705 15625 }, 15706 15626 { 15707 15627 .cmd = NL80211_CMD_DEL_PMK, 15708 15628 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15709 15629 .doit = nl80211_del_pmk, 15710 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15711 - NL80211_FLAG_NEED_RTNL, 15630 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15712 15631 }, 15713 15632 { 15714 15633 .cmd = NL80211_CMD_EXTERNAL_AUTH, 15715 15634 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15716 15635 .doit = nl80211_external_auth, 15717 15636 .flags = GENL_ADMIN_PERM, 15718 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15719 - NL80211_FLAG_NEED_RTNL, 15637 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15720 15638 }, 15721 15639 { 15722 15640 .cmd = NL80211_CMD_CONTROL_PORT_FRAME, 15723 15641 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15724 15642 .doit = nl80211_tx_control_port, 15725 15643 .flags = GENL_UNS_ADMIN_PERM, 15726 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15727 - NL80211_FLAG_NEED_RTNL, 15644 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15728 15645 }, 15729 15646 { 15730 15647 .cmd = NL80211_CMD_GET_FTM_RESPONDER_STATS, 15731 15648 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15732 15649 .doit = nl80211_get_ftm_responder_stats, 15733 - .internal_flags = NL80211_FLAG_NEED_NETDEV | 15734 - NL80211_FLAG_NEED_RTNL, 15650 + .internal_flags = NL80211_FLAG_NEED_NETDEV, 15735 15651 }, 15736 15652 { 15737 15653 .cmd = NL80211_CMD_PEER_MEASUREMENT_START, 15738 15654 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15739 15655 .doit = nl80211_pmsr_start, 15740 15656 .flags = GENL_UNS_ADMIN_PERM, 15741 - .internal_flags = NL80211_FLAG_NEED_WDEV_UP | 15742 - NL80211_FLAG_NEED_RTNL, 15657 + .internal_flags = NL80211_FLAG_NEED_WDEV_UP, 15743 15658 }, 15744 15659 { 15745 15660 .cmd = NL80211_CMD_NOTIFY_RADAR, 15746 15661 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 15747 15662 .doit = nl80211_notify_radar_detection, 15748 15663 .flags = GENL_UNS_ADMIN_PERM, 15749 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15750 - NL80211_FLAG_NEED_RTNL, 15664 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15751 15665 }, 15752 15666 { 15753 15667 .cmd = NL80211_CMD_UPDATE_OWE_INFO, 15754 15668 .doit = nl80211_update_owe_info, 15755 15669 .flags = GENL_ADMIN_PERM, 15756 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15757 - NL80211_FLAG_NEED_RTNL, 15670 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15758 15671 }, 15759 15672 { 15760 15673 .cmd = NL80211_CMD_PROBE_MESH_LINK, 15761 15674 .doit = nl80211_probe_mesh_link, 15762 15675 .flags = GENL_UNS_ADMIN_PERM, 15763 - .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | 15764 - NL80211_FLAG_NEED_RTNL, 15676 + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP, 15765 15677 }, 15766 15678 { 15767 15679 .cmd = NL80211_CMD_SET_TID_CONFIG, 15768 15680 .doit = nl80211_set_tid_config, 15769 15681 .flags = GENL_UNS_ADMIN_PERM, 15770 - .internal_flags = NL80211_FLAG_NEED_NETDEV | 15771 - NL80211_FLAG_NEED_RTNL, 15682 + .internal_flags = NL80211_FLAG_NEED_NETDEV, 15772 15683 }, 15773 15684 { 15774 15685 .cmd = NL80211_CMD_SET_SAR_SPECS,
+67 -36
net/wireless/reg.c
··· 142 142 /* 143 143 * Returns the regulatory domain associated with the wiphy. 144 144 * 145 - * Requires either RTNL or RCU protection 145 + * Requires any of RTNL, wiphy mutex or RCU protection. 146 146 */ 147 147 const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy) 148 148 { 149 - return rcu_dereference_rtnl(wiphy->regd); 149 + return rcu_dereference_check(wiphy->regd, 150 + lockdep_is_held(&wiphy->mtx) || 151 + lockdep_rtnl_is_held()); 150 152 } 153 + EXPORT_SYMBOL(get_wiphy_regdom); 151 154 152 155 static const char *reg_dfs_region_str(enum nl80211_dfs_regions dfs_region) 153 156 { ··· 172 169 const struct ieee80211_regdomain *regd = NULL; 173 170 const struct ieee80211_regdomain *wiphy_regd = NULL; 174 171 172 + rcu_read_lock(); 175 173 regd = get_cfg80211_regdom(); 174 + 176 175 if (!wiphy) 177 176 goto out; 178 177 ··· 191 186 reg_dfs_region_str(regd->dfs_region)); 192 187 193 188 out: 189 + rcu_read_unlock(); 190 + 194 191 return regd->dfs_region; 195 192 } 196 193 ··· 2584 2577 return; 2585 2578 2586 2579 rtnl_lock(); 2580 + wiphy_lock(wiphy); 2587 2581 2588 2582 tmp = get_wiphy_regdom(wiphy); 2589 2583 rcu_assign_pointer(wiphy->regd, new_regd); 2590 2584 rcu_free_regdom(tmp); 2591 2585 2586 + wiphy_unlock(wiphy); 2592 2587 rtnl_unlock(); 2593 2588 } 2594 2589 EXPORT_SYMBOL(wiphy_apply_custom_regulatory); ··· 2753 2744 return REG_REQ_IGNORE; 2754 2745 2755 2746 tmp = get_wiphy_regdom(wiphy); 2747 + ASSERT_RTNL(); 2748 + wiphy_lock(wiphy); 2756 2749 rcu_assign_pointer(wiphy->regd, regd); 2750 + wiphy_unlock(wiphy); 2757 2751 rcu_free_regdom(tmp); 2758 2752 } 2759 2753 ··· 3088 3076 spin_unlock_bh(&reg_pending_beacons_lock); 3089 3077 } 3090 3078 3091 - static void reg_process_self_managed_hints(void) 3079 + static void reg_process_self_managed_hint(struct wiphy *wiphy) 3092 3080 { 3093 - struct cfg80211_registered_device *rdev; 3094 - struct wiphy *wiphy; 3081 + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); 3095 3082 const struct ieee80211_regdomain *tmp; 3096 3083 const struct ieee80211_regdomain *regd; 3097 3084 enum nl80211_band band; 3098 3085 struct regulatory_request request = {}; 3099 3086 3087 + ASSERT_RTNL(); 3088 + lockdep_assert_wiphy(wiphy); 3089 + 3090 + spin_lock(&reg_requests_lock); 3091 + regd = rdev->requested_regd; 3092 + rdev->requested_regd = NULL; 3093 + spin_unlock(&reg_requests_lock); 3094 + 3095 + if (!regd) 3096 + return; 3097 + 3098 + tmp = get_wiphy_regdom(wiphy); 3099 + rcu_assign_pointer(wiphy->regd, regd); 3100 + rcu_free_regdom(tmp); 3101 + 3102 + for (band = 0; band < NUM_NL80211_BANDS; band++) 3103 + handle_band_custom(wiphy, wiphy->bands[band], regd); 3104 + 3105 + reg_process_ht_flags(wiphy); 3106 + 3107 + request.wiphy_idx = get_wiphy_idx(wiphy); 3108 + request.alpha2[0] = regd->alpha2[0]; 3109 + request.alpha2[1] = regd->alpha2[1]; 3110 + request.initiator = NL80211_REGDOM_SET_BY_DRIVER; 3111 + 3112 + nl80211_send_wiphy_reg_change_event(&request); 3113 + } 3114 + 3115 + static void reg_process_self_managed_hints(void) 3116 + { 3117 + struct cfg80211_registered_device *rdev; 3118 + 3119 + ASSERT_RTNL(); 3120 + 3100 3121 list_for_each_entry(rdev, &cfg80211_rdev_list, list) { 3101 - wiphy = &rdev->wiphy; 3102 - 3103 - spin_lock(&reg_requests_lock); 3104 - regd = rdev->requested_regd; 3105 - rdev->requested_regd = NULL; 3106 - spin_unlock(&reg_requests_lock); 3107 - 3108 - if (regd == NULL) 3109 - continue; 3110 - 3111 - tmp = get_wiphy_regdom(wiphy); 3112 - rcu_assign_pointer(wiphy->regd, regd); 3113 - rcu_free_regdom(tmp); 3114 - 3115 - for (band = 0; band < NUM_NL80211_BANDS; band++) 3116 - handle_band_custom(wiphy, wiphy->bands[band], regd); 3117 - 3118 - reg_process_ht_flags(wiphy); 3119 - 3120 - request.wiphy_idx = get_wiphy_idx(wiphy); 3121 - request.alpha2[0] = regd->alpha2[0]; 3122 - request.alpha2[1] = regd->alpha2[1]; 3123 - request.initiator = NL80211_REGDOM_SET_BY_DRIVER; 3124 - 3125 - nl80211_send_wiphy_reg_change_event(&request); 3122 + wiphy_lock(&rdev->wiphy); 3123 + reg_process_self_managed_hint(&rdev->wiphy); 3124 + wiphy_unlock(&rdev->wiphy); 3126 3125 } 3127 3126 3128 3127 reg_check_channels(); ··· 3812 3789 return -ENODEV; 3813 3790 3814 3791 if (!driver_request->intersect) { 3815 - if (request_wiphy->regd) 3792 + ASSERT_RTNL(); 3793 + wiphy_lock(request_wiphy); 3794 + if (request_wiphy->regd) { 3795 + wiphy_unlock(request_wiphy); 3816 3796 return -EALREADY; 3797 + } 3817 3798 3818 3799 regd = reg_copy_regd(rd); 3819 - if (IS_ERR(regd)) 3800 + if (IS_ERR(regd)) { 3801 + wiphy_unlock(request_wiphy); 3820 3802 return PTR_ERR(regd); 3803 + } 3821 3804 3822 3805 rcu_assign_pointer(request_wiphy->regd, regd); 3806 + wiphy_unlock(request_wiphy); 3823 3807 reset_regdomains(false, rd); 3824 3808 return 0; 3825 3809 } ··· 4008 3978 } 4009 3979 EXPORT_SYMBOL(regulatory_set_wiphy_regd); 4010 3980 4011 - int regulatory_set_wiphy_regd_sync_rtnl(struct wiphy *wiphy, 4012 - struct ieee80211_regdomain *rd) 3981 + int regulatory_set_wiphy_regd_sync(struct wiphy *wiphy, 3982 + struct ieee80211_regdomain *rd) 4013 3983 { 4014 3984 int ret; 4015 3985 ··· 4020 3990 return ret; 4021 3991 4022 3992 /* process the request immediately */ 4023 - reg_process_self_managed_hints(); 3993 + reg_process_self_managed_hint(wiphy); 3994 + reg_check_channels(); 4024 3995 return 0; 4025 3996 } 4026 - EXPORT_SYMBOL(regulatory_set_wiphy_regd_sync_rtnl); 3997 + EXPORT_SYMBOL(regulatory_set_wiphy_regd_sync); 4027 3998 4028 3999 void wiphy_regulatory_register(struct wiphy *wiphy) 4029 4000 {
-1
net/wireless/reg.h
··· 63 63 const struct ieee80211_reg_rule *rule); 64 64 65 65 bool reg_last_request_cell_base(void); 66 - const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy); 67 66 68 67 /** 69 68 * regulatory_hint_found_beacon - hints a beacon was found on a channel
+19 -16
net/wireless/scan.c
··· 918 918 union iwreq_data wrqu; 919 919 #endif 920 920 921 - ASSERT_RTNL(); 921 + lockdep_assert_held(&rdev->wiphy.mtx); 922 922 923 923 if (rdev->scan_msg) { 924 924 nl80211_send_scan_msg(rdev, rdev->scan_msg); ··· 987 987 rdev = container_of(wk, struct cfg80211_registered_device, 988 988 scan_done_wk); 989 989 990 - rtnl_lock(); 990 + wiphy_lock(&rdev->wiphy); 991 991 ___cfg80211_scan_done(rdev, true); 992 - rtnl_unlock(); 992 + wiphy_unlock(&rdev->wiphy); 993 993 } 994 994 995 995 void cfg80211_scan_done(struct cfg80211_scan_request *request, ··· 1022 1022 void cfg80211_add_sched_scan_req(struct cfg80211_registered_device *rdev, 1023 1023 struct cfg80211_sched_scan_request *req) 1024 1024 { 1025 - ASSERT_RTNL(); 1025 + lockdep_assert_held(&rdev->wiphy.mtx); 1026 1026 1027 1027 list_add_rcu(&req->list, &rdev->sched_scan_req_list); 1028 1028 } ··· 1030 1030 static void cfg80211_del_sched_scan_req(struct cfg80211_registered_device *rdev, 1031 1031 struct cfg80211_sched_scan_request *req) 1032 1032 { 1033 - ASSERT_RTNL(); 1033 + lockdep_assert_held(&rdev->wiphy.mtx); 1034 1034 1035 1035 list_del_rcu(&req->list); 1036 1036 kfree_rcu(req, rcu_head); ··· 1042 1042 struct cfg80211_sched_scan_request *pos; 1043 1043 1044 1044 list_for_each_entry_rcu(pos, &rdev->sched_scan_req_list, list, 1045 - lockdep_rtnl_is_held()) { 1045 + lockdep_is_held(&rdev->wiphy.mtx)) { 1046 1046 if (pos->reqid == reqid) 1047 1047 return pos; 1048 1048 } ··· 1090 1090 rdev = container_of(work, struct cfg80211_registered_device, 1091 1091 sched_scan_res_wk); 1092 1092 1093 - rtnl_lock(); 1093 + wiphy_lock(&rdev->wiphy); 1094 1094 list_for_each_entry_safe(req, tmp, &rdev->sched_scan_req_list, list) { 1095 1095 if (req->report_results) { 1096 1096 req->report_results = false; ··· 1105 1105 NL80211_CMD_SCHED_SCAN_RESULTS); 1106 1106 } 1107 1107 } 1108 - rtnl_unlock(); 1108 + wiphy_unlock(&rdev->wiphy); 1109 1109 } 1110 1110 1111 1111 void cfg80211_sched_scan_results(struct wiphy *wiphy, u64 reqid) ··· 1126 1126 } 1127 1127 EXPORT_SYMBOL(cfg80211_sched_scan_results); 1128 1128 1129 - void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy, u64 reqid) 1129 + void cfg80211_sched_scan_stopped_locked(struct wiphy *wiphy, u64 reqid) 1130 1130 { 1131 1131 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); 1132 1132 1133 - ASSERT_RTNL(); 1133 + lockdep_assert_held(&wiphy->mtx); 1134 1134 1135 1135 trace_cfg80211_sched_scan_stopped(wiphy, reqid); 1136 1136 1137 1137 __cfg80211_stop_sched_scan(rdev, reqid, true); 1138 1138 } 1139 - EXPORT_SYMBOL(cfg80211_sched_scan_stopped_rtnl); 1139 + EXPORT_SYMBOL(cfg80211_sched_scan_stopped_locked); 1140 1140 1141 1141 void cfg80211_sched_scan_stopped(struct wiphy *wiphy, u64 reqid) 1142 1142 { 1143 - rtnl_lock(); 1144 - cfg80211_sched_scan_stopped_rtnl(wiphy, reqid); 1145 - rtnl_unlock(); 1143 + wiphy_lock(wiphy); 1144 + cfg80211_sched_scan_stopped_locked(wiphy, reqid); 1145 + wiphy_unlock(wiphy); 1146 1146 } 1147 1147 EXPORT_SYMBOL(cfg80211_sched_scan_stopped); 1148 1148 ··· 1150 1150 struct cfg80211_sched_scan_request *req, 1151 1151 bool driver_initiated) 1152 1152 { 1153 - ASSERT_RTNL(); 1153 + lockdep_assert_held(&rdev->wiphy.mtx); 1154 1154 1155 1155 if (!driver_initiated) { 1156 1156 int err = rdev_sched_scan_stop(rdev, req->dev, req->reqid); ··· 1170 1170 { 1171 1171 struct cfg80211_sched_scan_request *sched_scan_req; 1172 1172 1173 - ASSERT_RTNL(); 1173 + lockdep_assert_held(&rdev->wiphy.mtx); 1174 1174 1175 1175 sched_scan_req = cfg80211_find_sched_scan_req(rdev, reqid); 1176 1176 if (!sched_scan_req) ··· 2774 2774 2775 2775 eth_broadcast_addr(creq->bssid); 2776 2776 2777 + wiphy_lock(&rdev->wiphy); 2778 + 2777 2779 rdev->scan_req = creq; 2778 2780 err = rdev_scan(rdev, creq); 2779 2781 if (err) { ··· 2787 2785 creq = NULL; 2788 2786 dev_hold(dev); 2789 2787 } 2788 + wiphy_unlock(&rdev->wiphy); 2790 2789 out: 2791 2790 kfree(creq); 2792 2791 return err;
+2 -3
net/wireless/sme.c
··· 67 67 struct cfg80211_scan_request *request; 68 68 int n_channels, err; 69 69 70 - ASSERT_RTNL(); 71 70 ASSERT_WDEV_LOCK(wdev); 72 71 73 72 if (rdev->scan_req || rdev->scan_msg) ··· 232 233 u8 bssid_buf[ETH_ALEN], *bssid = NULL; 233 234 enum nl80211_timeout_reason treason; 234 235 235 - rtnl_lock(); 236 + wiphy_lock(&rdev->wiphy); 236 237 237 238 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) { 238 239 if (!wdev->netdev) ··· 265 266 wdev_unlock(wdev); 266 267 } 267 268 268 - rtnl_unlock(); 269 + wiphy_unlock(&rdev->wiphy); 269 270 } 270 271 271 272 /* Returned bss is reference counted and must be cleaned up appropriately. */
+5
net/wireless/sysfs.c
··· 5 5 * 6 6 * Copyright 2005-2006 Jiri Benc <jbenc@suse.cz> 7 7 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> 8 + * Copyright (C) 2020-2021 Intel Corporation 8 9 */ 9 10 10 11 #include <linux/device.h> ··· 105 104 rdev->suspend_at = ktime_get_boottime_seconds(); 106 105 107 106 rtnl_lock(); 107 + wiphy_lock(&rdev->wiphy); 108 108 if (rdev->wiphy.registered) { 109 109 if (!rdev->wiphy.wowlan_config) { 110 110 cfg80211_leave_all(rdev); ··· 120 118 ret = rdev_suspend(rdev, NULL); 121 119 } 122 120 } 121 + wiphy_unlock(&rdev->wiphy); 123 122 rtnl_unlock(); 124 123 125 124 return ret; ··· 135 132 cfg80211_bss_age(rdev, ktime_get_boottime_seconds() - rdev->suspend_at); 136 133 137 134 rtnl_lock(); 135 + wiphy_lock(&rdev->wiphy); 138 136 if (rdev->wiphy.registered && rdev->ops->resume) 139 137 ret = rdev_resume(rdev); 138 + wiphy_unlock(&rdev->wiphy); 140 139 rtnl_unlock(); 141 140 142 141 return ret;
+34 -5
net/wireless/util.c
··· 997 997 { 998 998 struct wireless_dev *wdev; 999 999 1000 - ASSERT_RTNL(); 1000 + lockdep_assert_held(&rdev->wiphy.mtx); 1001 1001 1002 1002 list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) 1003 1003 cfg80211_process_wdev_events(wdev); ··· 1010 1010 int err; 1011 1011 enum nl80211_iftype otype = dev->ieee80211_ptr->iftype; 1012 1012 1013 - ASSERT_RTNL(); 1013 + lockdep_assert_held(&rdev->wiphy.mtx); 1014 1014 1015 1015 /* don't support changing VLANs, you just re-create them */ 1016 1016 if (otype == NL80211_IFTYPE_AP_VLAN) ··· 1188 1188 return __mcs2bitrate[rate->mcs]; 1189 1189 } 1190 1190 1191 + static u32 cfg80211_calculate_bitrate_extended_sc_dmg(struct rate_info *rate) 1192 + { 1193 + static const u32 __mcs2bitrate[] = { 1194 + [6 - 6] = 26950, /* MCS 9.1 : 2695.0 mbps */ 1195 + [7 - 6] = 50050, /* MCS 12.1 */ 1196 + [8 - 6] = 53900, 1197 + [9 - 6] = 57750, 1198 + [10 - 6] = 63900, 1199 + [11 - 6] = 75075, 1200 + [12 - 6] = 80850, 1201 + }; 1202 + 1203 + /* Extended SC MCS not defined for base MCS below 6 or above 12 */ 1204 + if (WARN_ON_ONCE(rate->mcs < 6 || rate->mcs > 12)) 1205 + return 0; 1206 + 1207 + return __mcs2bitrate[rate->mcs - 6]; 1208 + } 1209 + 1191 1210 static u32 cfg80211_calculate_bitrate_edmg(struct rate_info *rate) 1192 1211 { 1193 1212 static const u32 __mcs2bitrate[] = { ··· 1243 1224 1244 1225 static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) 1245 1226 { 1246 - static const u32 base[4][10] = { 1227 + static const u32 base[4][12] = { 1247 1228 { 6500000, 1248 1229 13000000, 1249 1230 19500000, ··· 1254 1235 65000000, 1255 1236 78000000, 1256 1237 /* not in the spec, but some devices use this: */ 1257 - 86500000, 1238 + 86700000, 1239 + 97500000, 1240 + 108300000, 1258 1241 }, 1259 1242 { 13500000, 1260 1243 27000000, ··· 1268 1247 135000000, 1269 1248 162000000, 1270 1249 180000000, 1250 + 202500000, 1251 + 225000000, 1271 1252 }, 1272 1253 { 29300000, 1273 1254 58500000, ··· 1281 1258 292500000, 1282 1259 351000000, 1283 1260 390000000, 1261 + 438800000, 1262 + 487500000, 1284 1263 }, 1285 1264 { 58500000, 1286 1265 117000000, ··· 1294 1269 585000000, 1295 1270 702000000, 1296 1271 780000000, 1272 + 877500000, 1273 + 975000000, 1297 1274 }, 1298 1275 }; 1299 1276 u32 bitrate; 1300 1277 int idx; 1301 1278 1302 - if (rate->mcs > 9) 1279 + if (rate->mcs > 11) 1303 1280 goto warn; 1304 1281 1305 1282 switch (rate->bw) { ··· 1425 1398 return cfg80211_calculate_bitrate_ht(rate); 1426 1399 if (rate->flags & RATE_INFO_FLAGS_DMG) 1427 1400 return cfg80211_calculate_bitrate_dmg(rate); 1401 + if (rate->flags & RATE_INFO_FLAGS_EXTENDED_SC_DMG) 1402 + return cfg80211_calculate_bitrate_extended_sc_dmg(rate); 1428 1403 if (rate->flags & RATE_INFO_FLAGS_EDMG) 1429 1404 return cfg80211_calculate_bitrate_edmg(rate); 1430 1405 if (rate->flags & RATE_INFO_FLAGS_VHT_MCS)
+197 -74
net/wireless/wext-compat.c
··· 7 7 * we directly assign the wireless handlers of wireless interfaces. 8 8 * 9 9 * Copyright 2008-2009 Johannes Berg <johannes@sipsolutions.net> 10 - * Copyright (C) 2019 Intel Corporation 10 + * Copyright (C) 2019-2021 Intel Corporation 11 11 */ 12 12 13 13 #include <linux/export.h> ··· 253 253 u32 orts = wdev->wiphy->rts_threshold; 254 254 int err; 255 255 256 - if (rts->disabled || !rts->fixed) 256 + wiphy_lock(&rdev->wiphy); 257 + if (rts->disabled || !rts->fixed) { 257 258 wdev->wiphy->rts_threshold = (u32) -1; 258 - else if (rts->value < 0) 259 - return -EINVAL; 260 - else 259 + } else if (rts->value < 0) { 260 + err = -EINVAL; 261 + goto out; 262 + } else { 261 263 wdev->wiphy->rts_threshold = rts->value; 264 + } 262 265 263 266 err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_RTS_THRESHOLD); 267 + 264 268 if (err) 265 269 wdev->wiphy->rts_threshold = orts; 266 270 271 + out: 272 + wiphy_unlock(&rdev->wiphy); 267 273 return err; 268 274 } 269 275 EXPORT_WEXT_HANDLER(cfg80211_wext_siwrts); ··· 297 291 u32 ofrag = wdev->wiphy->frag_threshold; 298 292 int err; 299 293 300 - if (frag->disabled || !frag->fixed) 294 + wiphy_lock(&rdev->wiphy); 295 + if (frag->disabled || !frag->fixed) { 301 296 wdev->wiphy->frag_threshold = (u32) -1; 302 - else if (frag->value < 256) 303 - return -EINVAL; 304 - else { 297 + } else if (frag->value < 256) { 298 + err = -EINVAL; 299 + goto out; 300 + } else { 305 301 /* Fragment length must be even, so strip LSB. */ 306 302 wdev->wiphy->frag_threshold = frag->value & ~0x1; 307 303 } ··· 311 303 err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_FRAG_THRESHOLD); 312 304 if (err) 313 305 wdev->wiphy->frag_threshold = ofrag; 306 + out: 307 + wiphy_unlock(&rdev->wiphy); 314 308 315 309 return err; 316 310 } ··· 347 337 (retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) 348 338 return -EINVAL; 349 339 340 + wiphy_lock(&rdev->wiphy); 350 341 if (retry->flags & IW_RETRY_LONG) { 351 342 wdev->wiphy->retry_long = retry->value; 352 343 changed |= WIPHY_PARAM_RETRY_LONG; ··· 366 355 wdev->wiphy->retry_short = oshort; 367 356 wdev->wiphy->retry_long = olong; 368 357 } 358 + wiphy_unlock(&rdev->wiphy); 369 359 370 360 return err; 371 361 } ··· 589 577 !rdev->ops->set_default_key) 590 578 return -EOPNOTSUPP; 591 579 580 + wiphy_lock(&rdev->wiphy); 592 581 idx = erq->flags & IW_ENCODE_INDEX; 593 582 if (idx == 0) { 594 583 idx = wdev->wext.default_key; 595 584 if (idx < 0) 596 585 idx = 0; 597 - } else if (idx < 1 || idx > 4) 598 - return -EINVAL; 599 - else 586 + } else if (idx < 1 || idx > 4) { 587 + err = -EINVAL; 588 + goto out; 589 + } else { 600 590 idx--; 591 + } 601 592 602 593 if (erq->flags & IW_ENCODE_DISABLED) 603 594 remove = true; ··· 614 599 if (!err) 615 600 wdev->wext.default_key = idx; 616 601 wdev_unlock(wdev); 617 - return err; 602 + goto out; 618 603 } 619 604 620 605 memset(&params, 0, sizeof(params)); 621 606 params.key = keybuf; 622 607 params.key_len = erq->length; 623 - if (erq->length == 5) 608 + if (erq->length == 5) { 624 609 params.cipher = WLAN_CIPHER_SUITE_WEP40; 625 - else if (erq->length == 13) 610 + } else if (erq->length == 13) { 626 611 params.cipher = WLAN_CIPHER_SUITE_WEP104; 627 - else if (!remove) 628 - return -EINVAL; 612 + } else if (!remove) { 613 + err = -EINVAL; 614 + goto out; 615 + } 629 616 630 - return cfg80211_set_encryption(rdev, dev, false, NULL, remove, 631 - wdev->wext.default_key == -1, 632 - idx, &params); 617 + err = cfg80211_set_encryption(rdev, dev, false, NULL, remove, 618 + wdev->wext.default_key == -1, 619 + idx, &params); 620 + out: 621 + wiphy_unlock(&rdev->wiphy); 622 + 623 + return err; 633 624 } 634 625 635 626 static int cfg80211_wext_siwencodeext(struct net_device *dev, ··· 775 754 struct cfg80211_chan_def chandef = { 776 755 .width = NL80211_CHAN_WIDTH_20_NOHT, 777 756 }; 778 - int freq; 757 + int freq, ret; 758 + 759 + wiphy_lock(&rdev->wiphy); 779 760 780 761 switch (wdev->iftype) { 781 762 case NL80211_IFTYPE_STATION: 782 - return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra); 763 + ret = cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra); 764 + break; 783 765 case NL80211_IFTYPE_ADHOC: 784 - return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra); 766 + ret = cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra); 767 + break; 785 768 case NL80211_IFTYPE_MONITOR: 786 769 freq = cfg80211_wext_freq(wextfreq); 787 - if (freq < 0) 788 - return freq; 789 - if (freq == 0) 790 - return -EINVAL; 770 + if (freq < 0) { 771 + ret = freq; 772 + break; 773 + } 774 + if (freq == 0) { 775 + ret = -EINVAL; 776 + break; 777 + } 791 778 chandef.center_freq1 = freq; 792 779 chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); 793 - if (!chandef.chan) 794 - return -EINVAL; 795 - return cfg80211_set_monitor_channel(rdev, &chandef); 780 + if (!chandef.chan) { 781 + ret = -EINVAL; 782 + break; 783 + } 784 + ret = cfg80211_set_monitor_channel(rdev, &chandef); 785 + break; 796 786 case NL80211_IFTYPE_MESH_POINT: 797 787 freq = cfg80211_wext_freq(wextfreq); 798 - if (freq < 0) 799 - return freq; 800 - if (freq == 0) 801 - return -EINVAL; 788 + if (freq < 0) { 789 + ret = freq; 790 + break; 791 + } 792 + if (freq == 0) { 793 + ret = -EINVAL; 794 + break; 795 + } 802 796 chandef.center_freq1 = freq; 803 797 chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq); 804 - if (!chandef.chan) 805 - return -EINVAL; 806 - return cfg80211_set_mesh_channel(rdev, wdev, &chandef); 798 + if (!chandef.chan) { 799 + ret = -EINVAL; 800 + break; 801 + } 802 + ret = cfg80211_set_mesh_channel(rdev, wdev, &chandef); 803 + break; 807 804 default: 808 - return -EOPNOTSUPP; 805 + ret = -EOPNOTSUPP; 806 + break; 809 807 } 808 + 809 + wiphy_unlock(&rdev->wiphy); 810 + 811 + return ret; 810 812 } 811 813 812 814 static int cfg80211_wext_giwfreq(struct net_device *dev, ··· 841 797 struct cfg80211_chan_def chandef = {}; 842 798 int ret; 843 799 800 + wiphy_lock(&rdev->wiphy); 844 801 switch (wdev->iftype) { 845 802 case NL80211_IFTYPE_STATION: 846 - return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); 803 + ret = cfg80211_mgd_wext_giwfreq(dev, info, freq, extra); 804 + break; 847 805 case NL80211_IFTYPE_ADHOC: 848 - return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); 806 + ret = cfg80211_ibss_wext_giwfreq(dev, info, freq, extra); 807 + break; 849 808 case NL80211_IFTYPE_MONITOR: 850 - if (!rdev->ops->get_channel) 851 - return -EINVAL; 809 + if (!rdev->ops->get_channel) { 810 + ret = -EINVAL; 811 + break; 812 + } 852 813 853 814 ret = rdev_get_channel(rdev, wdev, &chandef); 854 815 if (ret) 855 - return ret; 816 + break; 856 817 freq->m = chandef.chan->center_freq; 857 818 freq->e = 6; 858 - return 0; 819 + ret = 0; 820 + break; 859 821 default: 860 - return -EINVAL; 822 + ret = -EINVAL; 823 + break; 861 824 } 825 + 826 + wiphy_unlock(&rdev->wiphy); 827 + 828 + return ret; 862 829 } 863 830 864 831 static int cfg80211_wext_siwtxpower(struct net_device *dev, ··· 880 825 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); 881 826 enum nl80211_tx_power_setting type; 882 827 int dbm = 0; 828 + int ret; 883 829 884 830 if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) 885 831 return -EINVAL; ··· 922 866 return 0; 923 867 } 924 868 925 - return rdev_set_tx_power(rdev, wdev, type, DBM_TO_MBM(dbm)); 869 + wiphy_lock(&rdev->wiphy); 870 + ret = rdev_set_tx_power(rdev, wdev, type, DBM_TO_MBM(dbm)); 871 + wiphy_unlock(&rdev->wiphy); 872 + 873 + return ret; 926 874 } 927 875 928 876 static int cfg80211_wext_giwtxpower(struct net_device *dev, ··· 945 885 if (!rdev->ops->get_tx_power) 946 886 return -EOPNOTSUPP; 947 887 888 + wiphy_lock(&rdev->wiphy); 948 889 err = rdev_get_tx_power(rdev, wdev, &val); 890 + wiphy_unlock(&rdev->wiphy); 949 891 if (err) 950 892 return err; 951 893 ··· 1187 1125 timeout = wrq->value / 1000; 1188 1126 } 1189 1127 1128 + wiphy_lock(&rdev->wiphy); 1190 1129 err = rdev_set_power_mgmt(rdev, dev, ps, timeout); 1130 + wiphy_unlock(&rdev->wiphy); 1191 1131 if (err) 1192 1132 return err; 1193 1133 ··· 1220 1156 struct cfg80211_bitrate_mask mask; 1221 1157 u32 fixed, maxrate; 1222 1158 struct ieee80211_supported_band *sband; 1223 - int band, ridx; 1159 + int band, ridx, ret; 1224 1160 bool match = false; 1225 1161 1226 1162 if (!rdev->ops->set_bitrate_mask) ··· 1259 1195 if (!match) 1260 1196 return -EINVAL; 1261 1197 1262 - return rdev_set_bitrate_mask(rdev, dev, NULL, &mask); 1198 + wiphy_lock(&rdev->wiphy); 1199 + ret = rdev_set_bitrate_mask(rdev, dev, NULL, &mask); 1200 + wiphy_unlock(&rdev->wiphy); 1201 + 1202 + return ret; 1263 1203 } 1264 1204 1265 1205 static int cfg80211_wext_giwrate(struct net_device *dev, ··· 1292 1224 if (err) 1293 1225 return err; 1294 1226 1227 + wiphy_lock(&rdev->wiphy); 1295 1228 err = rdev_get_station(rdev, dev, addr, &sinfo); 1229 + wiphy_unlock(&rdev->wiphy); 1296 1230 if (err) 1297 1231 return err; 1298 1232 ··· 1319 1249 static struct iw_statistics wstats; 1320 1250 static struct station_info sinfo = {}; 1321 1251 u8 bssid[ETH_ALEN]; 1252 + int ret; 1322 1253 1323 1254 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) 1324 1255 return NULL; ··· 1338 1267 1339 1268 memset(&sinfo, 0, sizeof(sinfo)); 1340 1269 1341 - if (rdev_get_station(rdev, dev, bssid, &sinfo)) 1270 + wiphy_lock(&rdev->wiphy); 1271 + ret = rdev_get_station(rdev, dev, bssid, &sinfo); 1272 + wiphy_unlock(&rdev->wiphy); 1273 + 1274 + if (ret) 1342 1275 return NULL; 1343 1276 1344 1277 memset(&wstats, 0, sizeof(wstats)); ··· 1393 1318 struct sockaddr *ap_addr, char *extra) 1394 1319 { 1395 1320 struct wireless_dev *wdev = dev->ieee80211_ptr; 1321 + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); 1322 + int ret; 1396 1323 1324 + wiphy_lock(&rdev->wiphy); 1397 1325 switch (wdev->iftype) { 1398 1326 case NL80211_IFTYPE_ADHOC: 1399 - return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); 1327 + ret = cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra); 1328 + break; 1400 1329 case NL80211_IFTYPE_STATION: 1401 - return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); 1330 + ret = cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra); 1331 + break; 1402 1332 default: 1403 - return -EOPNOTSUPP; 1333 + ret = -EOPNOTSUPP; 1334 + break; 1404 1335 } 1336 + wiphy_unlock(&rdev->wiphy); 1337 + 1338 + return ret; 1405 1339 } 1406 1340 1407 1341 static int cfg80211_wext_giwap(struct net_device *dev, ··· 1418 1334 struct sockaddr *ap_addr, char *extra) 1419 1335 { 1420 1336 struct wireless_dev *wdev = dev->ieee80211_ptr; 1337 + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); 1338 + int ret; 1421 1339 1340 + wiphy_lock(&rdev->wiphy); 1422 1341 switch (wdev->iftype) { 1423 1342 case NL80211_IFTYPE_ADHOC: 1424 - return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); 1343 + ret = cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra); 1344 + break; 1425 1345 case NL80211_IFTYPE_STATION: 1426 - return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); 1346 + ret = cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra); 1347 + break; 1427 1348 default: 1428 - return -EOPNOTSUPP; 1349 + ret = -EOPNOTSUPP; 1350 + break; 1429 1351 } 1352 + wiphy_unlock(&rdev->wiphy); 1353 + 1354 + return ret; 1430 1355 } 1431 1356 1432 1357 static int cfg80211_wext_siwessid(struct net_device *dev, ··· 1443 1350 struct iw_point *data, char *ssid) 1444 1351 { 1445 1352 struct wireless_dev *wdev = dev->ieee80211_ptr; 1353 + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); 1354 + int ret; 1446 1355 1356 + wiphy_lock(&rdev->wiphy); 1447 1357 switch (wdev->iftype) { 1448 1358 case NL80211_IFTYPE_ADHOC: 1449 - return cfg80211_ibss_wext_siwessid(dev, info, data, ssid); 1359 + ret = cfg80211_ibss_wext_siwessid(dev, info, data, ssid); 1360 + break; 1450 1361 case NL80211_IFTYPE_STATION: 1451 - return cfg80211_mgd_wext_siwessid(dev, info, data, ssid); 1362 + ret = cfg80211_mgd_wext_siwessid(dev, info, data, ssid); 1363 + break; 1452 1364 default: 1453 - return -EOPNOTSUPP; 1365 + ret = -EOPNOTSUPP; 1366 + break; 1454 1367 } 1368 + wiphy_unlock(&rdev->wiphy); 1369 + 1370 + return ret; 1455 1371 } 1456 1372 1457 1373 static int cfg80211_wext_giwessid(struct net_device *dev, ··· 1468 1366 struct iw_point *data, char *ssid) 1469 1367 { 1470 1368 struct wireless_dev *wdev = dev->ieee80211_ptr; 1369 + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); 1370 + int ret; 1471 1371 1472 1372 data->flags = 0; 1473 1373 data->length = 0; 1474 1374 1375 + wiphy_lock(&rdev->wiphy); 1475 1376 switch (wdev->iftype) { 1476 1377 case NL80211_IFTYPE_ADHOC: 1477 - return cfg80211_ibss_wext_giwessid(dev, info, data, ssid); 1378 + ret = cfg80211_ibss_wext_giwessid(dev, info, data, ssid); 1379 + break; 1478 1380 case NL80211_IFTYPE_STATION: 1479 - return cfg80211_mgd_wext_giwessid(dev, info, data, ssid); 1381 + ret = cfg80211_mgd_wext_giwessid(dev, info, data, ssid); 1382 + break; 1480 1383 default: 1481 - return -EOPNOTSUPP; 1384 + ret = -EOPNOTSUPP; 1385 + break; 1482 1386 } 1387 + wiphy_unlock(&rdev->wiphy); 1388 + 1389 + return ret; 1483 1390 } 1484 1391 1485 1392 static int cfg80211_wext_siwpmksa(struct net_device *dev, ··· 1499 1388 struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); 1500 1389 struct cfg80211_pmksa cfg_pmksa; 1501 1390 struct iw_pmksa *pmksa = (struct iw_pmksa *)extra; 1391 + int ret; 1502 1392 1503 1393 memset(&cfg_pmksa, 0, sizeof(struct cfg80211_pmksa)); 1504 1394 ··· 1509 1397 cfg_pmksa.bssid = pmksa->bssid.sa_data; 1510 1398 cfg_pmksa.pmkid = pmksa->pmkid; 1511 1399 1400 + wiphy_lock(&rdev->wiphy); 1512 1401 switch (pmksa->cmd) { 1513 1402 case IW_PMKSA_ADD: 1514 - if (!rdev->ops->set_pmksa) 1515 - return -EOPNOTSUPP; 1403 + if (!rdev->ops->set_pmksa) { 1404 + ret = -EOPNOTSUPP; 1405 + break; 1406 + } 1516 1407 1517 - return rdev_set_pmksa(rdev, dev, &cfg_pmksa); 1518 - 1408 + ret = rdev_set_pmksa(rdev, dev, &cfg_pmksa); 1409 + break; 1519 1410 case IW_PMKSA_REMOVE: 1520 - if (!rdev->ops->del_pmksa) 1521 - return -EOPNOTSUPP; 1411 + if (!rdev->ops->del_pmksa) { 1412 + ret = -EOPNOTSUPP; 1413 + break; 1414 + } 1522 1415 1523 - return rdev_del_pmksa(rdev, dev, &cfg_pmksa); 1524 - 1416 + ret = rdev_del_pmksa(rdev, dev, &cfg_pmksa); 1417 + break; 1525 1418 case IW_PMKSA_FLUSH: 1526 - if (!rdev->ops->flush_pmksa) 1527 - return -EOPNOTSUPP; 1419 + if (!rdev->ops->flush_pmksa) { 1420 + ret = -EOPNOTSUPP; 1421 + break; 1422 + } 1528 1423 1529 - return rdev_flush_pmksa(rdev, dev); 1530 - 1424 + ret = rdev_flush_pmksa(rdev, dev); 1425 + break; 1531 1426 default: 1532 - return -EOPNOTSUPP; 1427 + ret = -EOPNOTSUPP; 1428 + break; 1533 1429 } 1430 + wiphy_unlock(&rdev->wiphy); 1431 + 1432 + return ret; 1534 1433 } 1535 1434 1536 1435 #define DEFINE_WEXT_COMPAT_STUB(func, type) \
+3 -1
net/wireless/wext-sme.c
··· 3 3 * cfg80211 wext compat for managed mode. 4 4 * 5 5 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> 6 - * Copyright (C) 2009 Intel Corporation. All rights reserved. 6 + * Copyright (C) 2009, 2020-2021 Intel Corporation. 7 7 */ 8 8 9 9 #include <linux/export.h> ··· 379 379 if (mlme->addr.sa_family != ARPHRD_ETHER) 380 380 return -EINVAL; 381 381 382 + wiphy_lock(&rdev->wiphy); 382 383 wdev_lock(wdev); 383 384 switch (mlme->cmd) { 384 385 case IW_MLME_DEAUTH: ··· 391 390 break; 392 391 } 393 392 wdev_unlock(wdev); 393 + wiphy_unlock(&rdev->wiphy); 394 394 395 395 return err; 396 396 }