Johannes Berg says: ==================== My last pull request has been a while, we now have: * connection quality monitoring with multiple thresholds * support for FILS shared key authentication offload * pre-CAC regulatory compliance - only ETSI allows this * sanity check for some rate confusion that hit ChromeOS (but nobody else uses it, evidently) * some documentation updates * lots of cleanups ====================
Unified · Split
| @@ -2,6 +2,9 @@ · 1 unmodified line | |||
| 2 | cfg80211 subsystem | 2 | cfg80211 subsystem |
| 3 | ================== | 3 | ================== |
| 4 | 4 | ||
| 5 | .. kernel-doc:: include/net/cfg80211.h | ||
| 6 | :doc: Introduction | ||
| 7 | |||
| 5 | Device registration | 8 | Device registration |
| 6 | =================== | 9 | =================== |
| 7 | 10 | ||
| @@ -179,6 +182,12 @@ Actions and configuration · 171 unmodified lines | |||
| 179 | .. kernel-doc:: include/net/cfg80211.h | 182 | .. kernel-doc:: include/net/cfg80211.h |
| 180 | :functions: cfg80211_ibss_joined | 183 | :functions: cfg80211_ibss_joined |
| 181 | 184 | ||
| 185 | .. kernel-doc:: include/net/cfg80211.h | ||
| 186 | :functions: cfg80211_connect_resp_params | ||
| 187 | |||
| 188 | .. kernel-doc:: include/net/cfg80211.h | ||
| 189 | :functions: cfg80211_connect_done | ||
| 190 | |||
| 182 | .. kernel-doc:: include/net/cfg80211.h | 191 | .. kernel-doc:: include/net/cfg80211.h |
| 183 | :functions: cfg80211_connect_result | 192 | :functions: cfg80211_connect_result |
| 184 | 193 | ||
| @@ -1917,6 +1917,8 @@ static int adm8211_probe(struct pci_dev *pdev, · 1916 unmodified lines | |||
| 1917 | 1917 | ||
| 1918 | dev->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band; | 1918 | dev->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band; |
| 1919 | 1919 | ||
| 1920 | wiphy_ext_feature_set(dev->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 1921 | |||
| 1920 | err = ieee80211_register_hw(dev); | 1922 | err = ieee80211_register_hw(dev); |
| 1921 | if (err) { | 1923 | if (err) { |
| 1922 | printk(KERN_ERR "%s (adm8211): Cannot register device\n", | 1924 | printk(KERN_ERR "%s (adm8211): Cannot register device\n", |
| @@ -1689,6 +1689,8 @@ static int ar5523_probe(struct usb_interface *intf, · 1688 unmodified lines | |||
| 1689 | if (error) | 1689 | if (error) |
| 1690 | goto out_cancel_rx_cmd; | 1690 | goto out_cancel_rx_cmd; |
| 1691 | 1691 | ||
| 1692 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 1693 | |||
| 1692 | usb_set_intfdata(intf, hw); | 1694 | usb_set_intfdata(intf, hw); |
| 1693 | 1695 | ||
| 1694 | error = ieee80211_register_hw(hw); | 1696 | error = ieee80211_register_hw(hw); |
| @@ -8267,6 +8267,8 @@ int ath10k_mac_register(struct ath10k *ar) · 8266 unmodified lines | |||
| 8267 | ar->hw->wiphy->cipher_suites = cipher_suites; | 8267 | ar->hw->wiphy->cipher_suites = cipher_suites; |
| 8268 | ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 8268 | ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |
| 8269 | 8269 | ||
| 8270 | wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 8271 | |||
| 8270 | ret = ieee80211_register_hw(ar->hw); | 8272 | ret = ieee80211_register_hw(ar->hw); |
| 8271 | if (ret) { | 8273 | if (ret) { |
| 8272 | ath10k_err(ar, "failed to register ieee80211: %d\n", ret); | 8274 | ath10k_err(ar, "failed to register ieee80211: %d\n", ret); |
| @@ -2564,6 +2564,8 @@ ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops) · 2563 unmodified lines | |||
| 2564 | 2564 | ||
| 2565 | hw->extra_tx_headroom = 2; | 2565 | hw->extra_tx_headroom = 2; |
| 2566 | 2566 | ||
| 2567 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 2568 | |||
| 2567 | /* | 2569 | /* |
| 2568 | * Mark the device as detached to avoid processing | 2570 | * Mark the device as detached to avoid processing |
| 2569 | * interrupts until setup is complete. | 2571 | * interrupts until setup is complete. |
| @@ -1503,7 +1503,6 @@ static struct wireless_dev *ath6kl_cfg80211_add_iface(struct wiphy *wiphy, · 1502 unmodified lines | |||
| 1503 | const char *name, | 1503 | const char *name, |
| 1504 | unsigned char name_assign_type, | 1504 | unsigned char name_assign_type, |
| 1505 | enum nl80211_iftype type, | 1505 | enum nl80211_iftype type, |
| 1506 | u32 *flags, | ||
| 1507 | struct vif_params *params) | 1506 | struct vif_params *params) |
| 1508 | { | 1507 | { |
| 1509 | struct ath6kl *ar = wiphy_priv(wiphy); | 1508 | struct ath6kl *ar = wiphy_priv(wiphy); |
| @@ -1550,7 +1549,7 @@ static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy, · 40 unmodified lines | |||
| 1550 | 1549 | ||
| 1551 | static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy, | 1550 | static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy, |
| 1552 | struct net_device *ndev, | 1551 | struct net_device *ndev, |
| 1553 | enum nl80211_iftype type, u32 *flags, | 1552 | enum nl80211_iftype type, |
| 1554 | struct vif_params *params) | 1553 | struct vif_params *params) |
| 1555 | { | 1554 | { |
| 1556 | struct ath6kl_vif *vif = netdev_priv(ndev); | 1555 | struct ath6kl_vif *vif = netdev_priv(ndev); |
| @@ -780,6 +780,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, · 779 unmodified lines | |||
| 780 | } | 780 | } |
| 781 | 781 | ||
| 782 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); | 782 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); |
| 783 | |||
| 784 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 783 | } | 785 | } |
| 784 | 786 | ||
| 785 | static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv) | 787 | static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv) |
| @@ -955,6 +955,8 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) · 954 unmodified lines | |||
| 955 | ath9k_cmn_reload_chainmask(ah); | 955 | ath9k_cmn_reload_chainmask(ah); |
| 956 | 956 | ||
| 957 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); | 957 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); |
| 958 | |||
| 959 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 958 | } | 960 | } |
| 959 | 961 | ||
| 960 | int ath9k_init_device(u16 devid, struct ath_softc *sc, | 962 | int ath9k_init_device(u16 devid, struct ath_softc *sc, |
| @@ -1874,6 +1874,8 @@ void *carl9170_alloc(size_t priv_size) · 1873 unmodified lines | |||
| 1874 | for (i = 0; i < ARRAY_SIZE(ar->noise); i++) | 1874 | for (i = 0; i < ARRAY_SIZE(ar->noise); i++) |
| 1875 | ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ | 1875 | ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ |
| 1876 | 1876 | ||
| 1877 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 1878 | |||
| 1877 | return ar; | 1879 | return ar; |
| 1878 | 1880 | ||
| 1879 | err_nomem: | 1881 | err_nomem: |
| @@ -1112,6 +1112,9 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) · 1111 unmodified lines | |||
| 1112 | wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta); | 1112 | wcn->hw->sta_data_size = sizeof(struct wcn36xx_sta); |
| 1113 | wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif); | 1113 | wcn->hw->vif_data_size = sizeof(struct wcn36xx_vif); |
| 1114 | 1114 | ||
| 1115 | wiphy_ext_feature_set(wcn->hw->wiphy, | ||
| 1116 | NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 1117 | |||
| 1115 | return ret; | 1118 | return ret; |
| 1116 | } | 1119 | } |
| 1117 | 1120 | ||
| @@ -178,9 +178,8 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid, · 177 unmodified lines | |||
| 178 | BIT(NL80211_STA_INFO_RX_DROP_MISC) | | 178 | BIT(NL80211_STA_INFO_RX_DROP_MISC) | |
| 179 | BIT(NL80211_STA_INFO_TX_FAILED); | 179 | BIT(NL80211_STA_INFO_TX_FAILED); |
| 180 | 180 | ||
| 181 | sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; | 181 | sinfo->txrate.flags = RATE_INFO_FLAGS_60G; |
| 182 | sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs); | 182 | sinfo->txrate.mcs = le16_to_cpu(reply.evt.bf_mcs); |
| 183 | sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; | ||
| 184 | sinfo->rxrate.mcs = stats->last_mcs_rx; | 183 | sinfo->rxrate.mcs = stats->last_mcs_rx; |
| 185 | sinfo->rx_bytes = stats->rx_bytes; | 184 | sinfo->rx_bytes = stats->rx_bytes; |
| 186 | sinfo->rx_packets = stats->rx_packets; | 185 | sinfo->rx_packets = stats->rx_packets; |
| @@ -256,7 +255,7 @@ static struct wireless_dev * · 69 unmodified lines | |||
| 256 | wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name, | 255 | wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name, |
| 257 | unsigned char name_assign_type, | 256 | unsigned char name_assign_type, |
| 258 | enum nl80211_iftype type, | 257 | enum nl80211_iftype type, |
| 259 | u32 *flags, struct vif_params *params) | 258 | struct vif_params *params) |
| 260 | { | 259 | { |
| 261 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 260 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
| 262 | struct net_device *ndev = wil_to_ndev(wil); | 261 | struct net_device *ndev = wil_to_ndev(wil); |
| @@ -307,7 +306,7 @@ static int wil_cfg80211_del_iface(struct wiphy *wiphy, · 44 unmodified lines | |||
| 307 | 306 | ||
| 308 | static int wil_cfg80211_change_iface(struct wiphy *wiphy, | 307 | static int wil_cfg80211_change_iface(struct wiphy *wiphy, |
| 309 | struct net_device *ndev, | 308 | struct net_device *ndev, |
| 310 | enum nl80211_iftype type, u32 *flags, | 309 | enum nl80211_iftype type, |
| 311 | struct vif_params *params) | 310 | struct vif_params *params) |
| 312 | { | 311 | { |
| 313 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 312 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
| @@ -334,11 +333,8 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy, · 20 unmodified lines | |||
| 334 | case NL80211_IFTYPE_P2P_GO: | 333 | case NL80211_IFTYPE_P2P_GO: |
| 335 | break; | 334 | break; |
| 336 | case NL80211_IFTYPE_MONITOR: | 335 | case NL80211_IFTYPE_MONITOR: |
| 337 | if (flags) | 336 | if (params->flags) |
| 338 | wil->monitor_flags = *flags; | 337 | wil->monitor_flags = params->flags; |
| 339 | else | ||
| 340 | wil->monitor_flags = 0; | ||
| 341 | |||
| 342 | break; | 338 | break; |
| 343 | default: | 339 | default: |
| 344 | return -EOPNOTSUPP; | 340 | return -EOPNOTSUPP; |
| @@ -2377,6 +2377,8 @@ static int at76_init_new_device(struct at76_priv *priv, · 2376 unmodified lines | |||
| 2377 | 2377 | ||
| 2378 | wiphy->hw_version = priv->board_type; | 2378 | wiphy->hw_version = priv->board_type; |
| 2379 | 2379 | ||
| 2380 | wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 2381 | |||
| 2380 | ret = ieee80211_register_hw(priv->hw); | 2382 | ret = ieee80211_register_hw(priv->hw); |
| 2381 | if (ret) { | 2383 | if (ret) { |
| 2382 | printk(KERN_ERR "cannot register mac80211 hw (status %d)!\n", | 2384 | printk(KERN_ERR "cannot register mac80211 hw (status %d)!\n", |
| @@ -5598,6 +5598,8 @@ static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev) · 5597 unmodified lines | |||
| 5598 | 5598 | ||
| 5599 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 5599 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
| 5600 | 5600 | ||
| 5601 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 5602 | |||
| 5601 | wl->hw_registred = false; | 5603 | wl->hw_registred = false; |
| 5602 | hw->max_rates = 2; | 5604 | hw->max_rates = 2; |
| 5603 | SET_IEEE80211_DEV(hw, dev->dev); | 5605 | SET_IEEE80211_DEV(hw, dev->dev); |
| @@ -3850,6 +3850,8 @@ static int b43legacy_wireless_init(struct ssb_device *dev) · 3849 unmodified lines | |||
| 3850 | else | 3850 | else |
| 3851 | SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac); | 3851 | SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac); |
| 3852 | 3852 | ||
| 3853 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 3854 | |||
| 3853 | /* Get and initialize struct b43legacy_wl */ | 3855 | /* Get and initialize struct b43legacy_wl */ |
| 3854 | wl = hw_to_b43legacy_wl(hw); | 3856 | wl = hw_to_b43legacy_wl(hw); |
| 3855 | memset(wl, 0, sizeof(*wl)); | 3857 | memset(wl, 0, sizeof(*wl)); |
| @@ -575,12 +575,11 @@ static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp) · 574 unmodified lines | |||
| 575 | * | 575 | * |
| 576 | * @wiphy: wiphy device of new interface. | 576 | * @wiphy: wiphy device of new interface. |
| 577 | * @name: name of the new interface. | 577 | * @name: name of the new interface. |
| 578 | * @flags: not used. | ||
| 579 | * @params: contains mac address for AP device. | 578 | * @params: contains mac address for AP device. |
| 580 | */ | 579 | */ |
| 581 | static | 580 | static |
| 582 | struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name, | 581 | struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name, |
| 583 | u32 *flags, struct vif_params *params) | 582 | struct vif_params *params) |
| 584 | { | 583 | { |
| 585 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 584 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 586 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | 585 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); |
| @@ -653,7 +652,6 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, · 66 unmodified lines | |||
| 653 | const char *name, | 652 | const char *name, |
| 654 | unsigned char name_assign_type, | 653 | unsigned char name_assign_type, |
| 655 | enum nl80211_iftype type, | 654 | enum nl80211_iftype type, |
| 656 | u32 *flags, | ||
| 657 | struct vif_params *params) | 655 | struct vif_params *params) |
| 658 | { | 656 | { |
| 659 | struct wireless_dev *wdev; | 657 | struct wireless_dev *wdev; |
| @@ -674,12 +672,12 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, · 14 unmodified lines | |||
| 674 | case NL80211_IFTYPE_MESH_POINT: | 672 | case NL80211_IFTYPE_MESH_POINT: |
| 675 | return ERR_PTR(-EOPNOTSUPP); | 673 | return ERR_PTR(-EOPNOTSUPP); |
| 676 | case NL80211_IFTYPE_AP: | 674 | case NL80211_IFTYPE_AP: |
| 677 | wdev = brcmf_ap_add_vif(wiphy, name, flags, params); | 675 | wdev = brcmf_ap_add_vif(wiphy, name, params); |
| 678 | break; | 676 | break; |
| 679 | case NL80211_IFTYPE_P2P_CLIENT: | 677 | case NL80211_IFTYPE_P2P_CLIENT: |
| 680 | case NL80211_IFTYPE_P2P_GO: | 678 | case NL80211_IFTYPE_P2P_GO: |
| 681 | case NL80211_IFTYPE_P2P_DEVICE: | 679 | case NL80211_IFTYPE_P2P_DEVICE: |
| 682 | wdev = brcmf_p2p_add_vif(wiphy, name, name_assign_type, type, flags, params); | 680 | wdev = brcmf_p2p_add_vif(wiphy, name, name_assign_type, type, params); |
| 683 | break; | 681 | break; |
| 684 | case NL80211_IFTYPE_UNSPECIFIED: | 682 | case NL80211_IFTYPE_UNSPECIFIED: |
| 685 | default: | 683 | default: |
| @@ -858,7 +856,7 @@ int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) · 172 unmodified lines | |||
| 858 | 856 | ||
| 859 | static s32 | 857 | static s32 |
| 860 | brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, | 858 | brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, |
| 861 | enum nl80211_iftype type, u32 *flags, | 859 | enum nl80211_iftype type, |
| 862 | struct vif_params *params) | 860 | struct vif_params *params) |
| 863 | { | 861 | { |
| 864 | struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); | 862 | struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); |
| @@ -6553,7 +6551,7 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) · 5688 unmodified lines | |||
| 6553 | if (err) | 6551 | if (err) |
| 6554 | goto default_conf_out; | 6552 | goto default_conf_out; |
| 6555 | err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, | 6553 | err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, |
| 6556 | NULL, NULL); | 6554 | NULL); |
| 6557 | if (err) | 6555 | if (err) |
| 6558 | goto default_conf_out; | 6556 | goto default_conf_out; |
| 6559 | 6557 | ||
| @@ -2141,12 +2141,11 @@ fail: · 2140 unmodified lines | |||
| 2141 | * @name: name of the new interface. | 2141 | * @name: name of the new interface. |
| 2142 | * @name_assign_type: origin of the interface name | 2142 | * @name_assign_type: origin of the interface name |
| 2143 | * @type: nl80211 interface type. | 2143 | * @type: nl80211 interface type. |
| 2144 | * @flags: not used. | ||
| 2145 | * @params: contains mac address for P2P device. | 2144 | * @params: contains mac address for P2P device. |
| 2146 | */ | 2145 | */ |
| 2147 | struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | 2146 | struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, |
| 2148 | unsigned char name_assign_type, | 2147 | unsigned char name_assign_type, |
| 2149 | enum nl80211_iftype type, u32 *flags, | 2148 | enum nl80211_iftype type, |
| 2150 | struct vif_params *params) | 2149 | struct vif_params *params) |
| 2151 | { | 2150 | { |
| 2152 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 2151 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| @@ -150,7 +150,7 @@ s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg, bool p2pdev_forced); · 149 unmodified lines | |||
| 150 | void brcmf_p2p_detach(struct brcmf_p2p_info *p2p); | 150 | void brcmf_p2p_detach(struct brcmf_p2p_info *p2p); |
| 151 | struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, | 151 | struct wireless_dev *brcmf_p2p_add_vif(struct wiphy *wiphy, const char *name, |
| 152 | unsigned char name_assign_type, | 152 | unsigned char name_assign_type, |
| 153 | enum nl80211_iftype type, u32 *flags, | 153 | enum nl80211_iftype type, |
| 154 | struct vif_params *params); | 154 | struct vif_params *params); |
| 155 | int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev); | 155 | int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev); |
| 156 | int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg, | 156 | int brcmf_p2p_ifchange(struct brcmf_cfg80211_info *cfg, |
| @@ -1082,6 +1082,8 @@ static int ieee_hw_init(struct ieee80211_hw *hw) · 1081 unmodified lines | |||
| 1082 | * hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | 1082 | * hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; |
| 1083 | */ | 1083 | */ |
| 1084 | 1084 | ||
| 1085 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 1086 | |||
| 1085 | hw->rate_control_algorithm = "minstrel_ht"; | 1087 | hw->rate_control_algorithm = "minstrel_ht"; |
| 1086 | 1088 | ||
| 1087 | hw->sta_data_size = 0; | 1089 | hw->sta_data_size = 0; |
| @@ -3592,6 +3592,8 @@ il3945_setup_mac(struct il_priv *il) · 3591 unmodified lines | |||
| 3592 | 3592 | ||
| 3593 | il_leds_init(il); | 3593 | il_leds_init(il); |
| 3594 | 3594 | ||
| 3595 | wiphy_ext_feature_set(il->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 3596 | |||
| 3595 | ret = ieee80211_register_hw(il->hw); | 3597 | ret = ieee80211_register_hw(il->hw); |
| 3596 | if (ret) { | 3598 | if (ret) { |
| 3597 | IL_ERR("Failed to register hw (error %d)\n", ret); | 3599 | IL_ERR("Failed to register hw (error %d)\n", ret); |
| @@ -656,7 +656,7 @@ il3945_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta, · 655 unmodified lines | |||
| 656 | rate_mask = sta->supp_rates[sband->band]; | 656 | rate_mask = sta->supp_rates[sband->band]; |
| 657 | 657 | ||
| 658 | /* get user max rate if set */ | 658 | /* get user max rate if set */ |
| 659 | max_rate_idx = txrc->max_rate_idx; | 659 | max_rate_idx = fls(txrc->rate_idx_mask) - 1; |
| 660 | if (sband->band == NL80211_BAND_5GHZ && max_rate_idx != -1) | 660 | if (sband->band == NL80211_BAND_5GHZ && max_rate_idx != -1) |
| 661 | max_rate_idx += IL_FIRST_OFDM_RATE; | 661 | max_rate_idx += IL_FIRST_OFDM_RATE; |
| 662 | if (max_rate_idx < 0 || max_rate_idx >= RATE_COUNT) | 662 | if (max_rate_idx < 0 || max_rate_idx >= RATE_COUNT) |
| @@ -5799,6 +5799,8 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length) · 5798 unmodified lines | |||
| 5799 | 5799 | ||
| 5800 | il_leds_init(il); | 5800 | il_leds_init(il); |
| 5801 | 5801 | ||
| 5802 | wiphy_ext_feature_set(il->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 5803 | |||
| 5802 | ret = ieee80211_register_hw(il->hw); | 5804 | ret = ieee80211_register_hw(il->hw); |
| 5803 | if (ret) { | 5805 | if (ret) { |
| 5804 | IL_ERR("Failed to register hw (error %d)\n", ret); | 5806 | IL_ERR("Failed to register hw (error %d)\n", ret); |
| @@ -2211,7 +2211,7 @@ il4965_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta, · 2210 unmodified lines | |||
| 2211 | 2211 | ||
| 2212 | /* Get max rate if user set max rate */ | 2212 | /* Get max rate if user set max rate */ |
| 2213 | if (lq_sta) { | 2213 | if (lq_sta) { |
| 2214 | lq_sta->max_rate_idx = txrc->max_rate_idx; | 2214 | lq_sta->max_rate_idx = fls(txrc->rate_idx_mask) - 1; |
| 2215 | if (sband->band == NL80211_BAND_5GHZ && | 2215 | if (sband->band == NL80211_BAND_5GHZ && |
| 2216 | lq_sta->max_rate_idx != -1) | 2216 | lq_sta->max_rate_idx != -1) |
| 2217 | lq_sta->max_rate_idx += IL_FIRST_OFDM_RATE; | 2217 | lq_sta->max_rate_idx += IL_FIRST_OFDM_RATE; |
| @@ -213,6 +213,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, · 212 unmodified lines | |||
| 213 | 213 | ||
| 214 | iwl_leds_init(priv); | 214 | iwl_leds_init(priv); |
| 215 | 215 | ||
| 216 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 217 | |||
| 216 | ret = ieee80211_register_hw(priv->hw); | 218 | ret = ieee80211_register_hw(priv->hw); |
| 217 | if (ret) { | 219 | if (ret) { |
| 218 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); | 220 | IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); |
| @@ -2720,7 +2720,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, · 2719 unmodified lines | |||
| 2720 | 2720 | ||
| 2721 | /* Get max rate if user set max rate */ | 2721 | /* Get max rate if user set max rate */ |
| 2722 | if (lq_sta) { | 2722 | if (lq_sta) { |
| 2723 | lq_sta->max_rate_idx = txrc->max_rate_idx; | 2723 | lq_sta->max_rate_idx = fls(txrc->rate_idx_mask) - 1; |
| 2724 | if ((sband->band == NL80211_BAND_5GHZ) && | 2724 | if ((sband->band == NL80211_BAND_5GHZ) && |
| 2725 | (lq_sta->max_rate_idx != -1)) | 2725 | (lq_sta->max_rate_idx != -1)) |
| 2726 | lq_sta->max_rate_idx += IWL_FIRST_OFDM_RATE; | 2726 | lq_sta->max_rate_idx += IWL_FIRST_OFDM_RATE; |
| @@ -97,7 +97,7 @@ int orinoco_wiphy_register(struct wiphy *wiphy) · 96 unmodified lines | |||
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev, | 99 | static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev, |
| 100 | enum nl80211_iftype type, u32 *flags, | 100 | enum nl80211_iftype type, |
| 101 | struct vif_params *params) | 101 | struct vif_params *params) |
| 102 | { | 102 | { |
| 103 | struct orinoco_private *priv = wiphy_priv(wiphy); | 103 | struct orinoco_private *priv = wiphy_priv(wiphy); |
| @@ -350,6 +350,7 @@ static const struct ieee80211_channel hwsim_channels_5ghz[] = { · 349 unmodified lines | |||
| 350 | CHAN5G(5785), /* Channel 157 */ | 350 | CHAN5G(5785), /* Channel 157 */ |
| 351 | CHAN5G(5805), /* Channel 161 */ | 351 | CHAN5G(5805), /* Channel 161 */ |
| 352 | CHAN5G(5825), /* Channel 165 */ | 352 | CHAN5G(5825), /* Channel 165 */ |
| 353 | CHAN5G(5845), /* Channel 169 */ | ||
| 353 | }; | 354 | }; |
| 354 | 355 | ||
| 355 | static const struct ieee80211_rate hwsim_rates[] = { | 356 | static const struct ieee80211_rate hwsim_rates[] = { |
| @@ -525,6 +526,11 @@ struct mac80211_hwsim_data { · 169 unmodified lines | |||
| 525 | struct ieee80211_vif *hw_scan_vif; | 526 | struct ieee80211_vif *hw_scan_vif; |
| 526 | int scan_chan_idx; | 527 | int scan_chan_idx; |
| 527 | u8 scan_addr[ETH_ALEN]; | 528 | u8 scan_addr[ETH_ALEN]; |
| 529 | struct { | ||
| 530 | struct ieee80211_channel *channel; | ||
| 531 | unsigned long next_start, start, end; | ||
| 532 | } survey_data[ARRAY_SIZE(hwsim_channels_2ghz) + | ||
| 533 | ARRAY_SIZE(hwsim_channels_5ghz)]; | ||
| 528 | 534 | ||
| 529 | struct ieee80211_channel *channel; | 535 | struct ieee80211_channel *channel; |
| 530 | u64 beacon_int /* beacon interval in us */; | 536 | u64 beacon_int /* beacon interval in us */; |
| @@ -552,8 +558,6 @@ struct mac80211_hwsim_data { · 21 unmodified lines | |||
| 552 | /* wmediumd portid responsible for netgroup of this radio */ | 558 | /* wmediumd portid responsible for netgroup of this radio */ |
| 553 | u32 wmediumd; | 559 | u32 wmediumd; |
| 554 | 560 | ||
| 555 | int power_level; | ||
| 556 | |||
| 557 | /* difference between this hw's clock and the real clock, in usecs */ | 561 | /* difference between this hw's clock and the real clock, in usecs */ |
| 558 | s64 tsf_offset; | 562 | s64 tsf_offset; |
| 559 | s64 bcn_delta; | 563 | s64 bcn_delta; |
| @@ -1201,7 +1205,9 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, · 641 unmodified lines | |||
| 1201 | if (info->control.rates[0].flags & IEEE80211_TX_RC_SHORT_GI) | 1205 | if (info->control.rates[0].flags & IEEE80211_TX_RC_SHORT_GI) |
| 1202 | rx_status.flag |= RX_FLAG_SHORT_GI; | 1206 | rx_status.flag |= RX_FLAG_SHORT_GI; |
| 1203 | /* TODO: simulate real signal strength (and optional packet loss) */ | 1207 | /* TODO: simulate real signal strength (and optional packet loss) */ |
| 1204 | rx_status.signal = data->power_level - 50; | 1208 | rx_status.signal = -50; |
| 1209 | if (info->control.vif) | ||
| 1210 | rx_status.signal += info->control.vif->bss_conf.txpower; | ||
| 1205 | 1211 | ||
| 1206 | if (data->ps != PS_DISABLED) | 1212 | if (data->ps != PS_DISABLED) |
| 1207 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); | 1213 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); |
| @@ -1576,6 +1582,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) · 368 unmodified lines | |||
| 1576 | [IEEE80211_SMPS_STATIC] = "static", | 1582 | [IEEE80211_SMPS_STATIC] = "static", |
| 1577 | [IEEE80211_SMPS_DYNAMIC] = "dynamic", | 1583 | [IEEE80211_SMPS_DYNAMIC] = "dynamic", |
| 1578 | }; | 1584 | }; |
| 1585 | int idx; | ||
| 1579 | 1586 | ||
| 1580 | if (conf->chandef.chan) | 1587 | if (conf->chandef.chan) |
| 1581 | wiphy_debug(hw->wiphy, | 1588 | wiphy_debug(hw->wiphy, |
| @@ -1598,11 +1605,34 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) · 16 unmodified lines | |||
| 1598 | 1605 | ||
| 1599 | data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); | 1606 | data->idle = !!(conf->flags & IEEE80211_CONF_IDLE); |
| 1600 | 1607 | ||
| 1601 | data->channel = conf->chandef.chan; | 1608 | WARN_ON(conf->chandef.chan && data->use_chanctx); |
| 1609 | |||
| 1610 | mutex_lock(&data->mutex); | ||
| 1611 | if (data->scanning && conf->chandef.chan) { | ||
| 1612 | for (idx = 0; idx < ARRAY_SIZE(data->survey_data); idx++) { | ||
| 1613 | if (data->survey_data[idx].channel == data->channel) { | ||
| 1614 | data->survey_data[idx].start = | ||
| 1615 | data->survey_data[idx].next_start; | ||
| 1616 | data->survey_data[idx].end = jiffies; | ||
| 1617 | break; | ||
| 1618 | } | ||
| 1619 | } | ||
| 1602 | 1620 | ||
| 1603 | WARN_ON(data->channel && data->use_chanctx); | 1621 | data->channel = conf->chandef.chan; |
| 1622 | |||
| 1623 | for (idx = 0; idx < ARRAY_SIZE(data->survey_data); idx++) { | ||
| 1624 | if (data->survey_data[idx].channel && | ||
| 1625 | data->survey_data[idx].channel != data->channel) | ||
| 1626 | continue; | ||
| 1627 | data->survey_data[idx].channel = data->channel; | ||
| 1628 | data->survey_data[idx].next_start = jiffies; | ||
| 1629 | break; | ||
| 1630 | } | ||
| 1631 | } else { | ||
| 1632 | data->channel = conf->chandef.chan; | ||
| 1633 | } | ||
| 1634 | mutex_unlock(&data->mutex); | ||
| 1604 | 1635 | ||
| 1605 | data->power_level = conf->power_level; | ||
| 1606 | if (!data->started || !data->beacon_int) | 1636 | if (!data->started || !data->beacon_int) |
| 1607 | tasklet_hrtimer_cancel(&data->beacon_timer); | 1637 | tasklet_hrtimer_cancel(&data->beacon_timer); |
| 1608 | else if (!hrtimer_is_queued(&data->beacon_timer.timer)) { | 1638 | else if (!hrtimer_is_queued(&data->beacon_timer.timer)) { |
| @@ -1787,28 +1817,37 @@ static int mac80211_hwsim_conf_tx( · 178 unmodified lines | |||
| 1787 | return 0; | 1817 | return 0; |
| 1788 | } | 1818 | } |
| 1789 | 1819 | ||
| 1790 | static int mac80211_hwsim_get_survey( | 1820 | static int mac80211_hwsim_get_survey(struct ieee80211_hw *hw, int idx, |
| 1791 | struct ieee80211_hw *hw, int idx, | 1821 | struct survey_info *survey) |
| 1792 | struct survey_info *survey) | ||
| 1793 | { | 1822 | { |
| 1794 | struct ieee80211_conf *conf = &hw->conf; | 1823 | struct mac80211_hwsim_data *hwsim = hw->priv; |
| 1795 | |||
| 1796 | wiphy_debug(hw->wiphy, "%s (idx=%d)\n", __func__, idx); | ||
| 1797 | 1824 | ||
| 1798 | if (idx != 0) | 1825 | if (idx < 0 || idx >= ARRAY_SIZE(hwsim->survey_data)) |
| 1799 | return -ENOENT; | 1826 | return -ENOENT; |
| 1800 | 1827 | ||
| 1801 | /* Current channel */ | 1828 | mutex_lock(&hwsim->mutex); |
| 1802 | survey->channel = conf->chandef.chan; | 1829 | survey->channel = hwsim->survey_data[idx].channel; |
| 1830 | if (!survey->channel) { | ||
| 1831 | mutex_unlock(&hwsim->mutex); | ||
| 1832 | return -ENOENT; | ||
| 1833 | } | ||
| 1803 | 1834 | ||
| 1804 | /* | 1835 | /* |
| 1805 | * Magically conjured noise level --- this is only ok for simulated hardware. | 1836 | * Magically conjured dummy values --- this is only ok for simulated hardware. |
| 1806 | * | 1837 | * |
| 1807 | * A real driver which cannot determine the real channel noise MUST NOT | 1838 | * A real driver which cannot determine real values noise MUST NOT |
| 1808 | * report any noise, especially not a magically conjured one :-) | 1839 | * report any, especially not a magically conjured ones :-) |
| 1809 | */ | 1840 | */ |
| 1810 | survey->filled = SURVEY_INFO_NOISE_DBM; | 1841 | survey->filled = SURVEY_INFO_NOISE_DBM | |
| 1842 | SURVEY_INFO_TIME | | ||
| 1843 | SURVEY_INFO_TIME_BUSY; | ||
| 1811 | survey->noise = -92; | 1844 | survey->noise = -92; |
| 1845 | survey->time = | ||
| 1846 | jiffies_to_msecs(hwsim->survey_data[idx].end - | ||
| 1847 | hwsim->survey_data[idx].start); | ||
| 1848 | /* report 12.5% of channel time is used */ | ||
| 1849 | survey->time_busy = survey->time/8; | ||
| 1850 | mutex_unlock(&hwsim->mutex); | ||
| 1812 | 1851 | ||
| 1813 | return 0; | 1852 | return 0; |
| 1814 | } | 1853 | } |
| @@ -1986,6 +2025,10 @@ static void hw_scan_work(struct work_struct *work) · 171 unmodified lines | |||
| 1986 | } | 2025 | } |
| 1987 | ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, | 2026 | ieee80211_queue_delayed_work(hwsim->hw, &hwsim->hw_scan, |
| 1988 | msecs_to_jiffies(dwell)); | 2027 | msecs_to_jiffies(dwell)); |
| 2028 | hwsim->survey_data[hwsim->scan_chan_idx].channel = hwsim->tmp_chan; | ||
| 2029 | hwsim->survey_data[hwsim->scan_chan_idx].start = jiffies; | ||
| 2030 | hwsim->survey_data[hwsim->scan_chan_idx].end = | ||
| 2031 | jiffies + msecs_to_jiffies(dwell); | ||
| 1989 | hwsim->scan_chan_idx++; | 2032 | hwsim->scan_chan_idx++; |
| 1990 | mutex_unlock(&hwsim->mutex); | 2033 | mutex_unlock(&hwsim->mutex); |
| 1991 | } | 2034 | } |
| @@ -2011,6 +2054,7 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, · 19 unmodified lines | |||
| 2011 | hw_req->req.mac_addr_mask); | 2054 | hw_req->req.mac_addr_mask); |
| 2012 | else | 2055 | else |
| 2013 | memcpy(hwsim->scan_addr, vif->addr, ETH_ALEN); | 2056 | memcpy(hwsim->scan_addr, vif->addr, ETH_ALEN); |
| 2057 | memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data)); | ||
| 2014 | mutex_unlock(&hwsim->mutex); | 2058 | mutex_unlock(&hwsim->mutex); |
| 2015 | 2059 | ||
| 2016 | wiphy_debug(hw->wiphy, "hwsim hw_scan request\n"); | 2060 | wiphy_debug(hw->wiphy, "hwsim hw_scan request\n"); |
| @@ -2057,6 +2101,7 @@ static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw, · 40 unmodified lines | |||
| 2057 | 2101 | ||
| 2058 | memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN); | 2102 | memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN); |
| 2059 | hwsim->scanning = true; | 2103 | hwsim->scanning = true; |
| 2104 | memset(hwsim->survey_data, 0, sizeof(hwsim->survey_data)); | ||
| 2060 | 2105 | ||
| 2061 | out: | 2106 | out: |
| 2062 | mutex_unlock(&hwsim->mutex); | 2107 | mutex_unlock(&hwsim->mutex); |
| @@ -2207,7 +2252,6 @@ static const char mac80211_hwsim_gstrings_stats[][ETH_GSTRING_LEN] = { · 144 unmodified lines | |||
| 2207 | "d_tx_failed", | 2252 | "d_tx_failed", |
| 2208 | "d_ps_mode", | 2253 | "d_ps_mode", |
| 2209 | "d_group", | 2254 | "d_group", |
| 2210 | "d_tx_power", | ||
| 2211 | }; | 2255 | }; |
| 2212 | 2256 | ||
| 2213 | #define MAC80211_HWSIM_SSTATS_LEN ARRAY_SIZE(mac80211_hwsim_gstrings_stats) | 2257 | #define MAC80211_HWSIM_SSTATS_LEN ARRAY_SIZE(mac80211_hwsim_gstrings_stats) |
| @@ -2244,7 +2288,6 @@ static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw, · 30 unmodified lines | |||
| 2244 | data[i++] = ar->tx_failed; | 2288 | data[i++] = ar->tx_failed; |
| 2245 | data[i++] = ar->ps; | 2289 | data[i++] = ar->ps; |
| 2246 | data[i++] = ar->group; | 2290 | data[i++] = ar->group; |
| 2247 | data[i++] = ar->power_level; | ||
| 2248 | 2291 | ||
| 2249 | WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN); | 2292 | WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN); |
| 2250 | } | 2293 | } |
| @@ -2438,6 +2481,9 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, · 187 unmodified lines | |||
| 2438 | goto failed; | 2481 | goto failed; |
| 2439 | } | 2482 | } |
| 2440 | 2483 | ||
| 2484 | /* ieee80211_alloc_hw_nm may have used a default name */ | ||
| 2485 | param->hwname = wiphy_name(hw->wiphy); | ||
| 2486 | |||
| 2441 | if (info) | 2487 | if (info) |
| 2442 | net = genl_info_net(info); | 2488 | net = genl_info_net(info); |
| 2443 | else | 2489 | else |
| @@ -2645,6 +2691,8 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, · 201 unmodified lines | |||
| 2645 | if (param->no_vif) | 2691 | if (param->no_vif) |
| 2646 | ieee80211_hw_set(hw, NO_AUTO_VIF); | 2692 | ieee80211_hw_set(hw, NO_AUTO_VIF); |
| 2647 | 2693 | ||
| 2694 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 2695 | |||
| 2648 | err = ieee80211_register_hw(hw); | 2696 | err = ieee80211_register_hw(hw); |
| 2649 | if (err < 0) { | 2697 | if (err < 0) { |
| 2650 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n", | 2698 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n", |
| @@ -57,12 +57,12 @@ enum hwsim_tx_control_flags { · 56 unmodified lines | |||
| 57 | * @HWSIM_CMD_REGISTER: request to register and received all broadcasted | 57 | * @HWSIM_CMD_REGISTER: request to register and received all broadcasted |
| 58 | * frames by any mac80211_hwsim radio device. | 58 | * frames by any mac80211_hwsim radio device. |
| 59 | * @HWSIM_CMD_FRAME: send/receive a broadcasted frame from/to kernel/user | 59 | * @HWSIM_CMD_FRAME: send/receive a broadcasted frame from/to kernel/user |
| 60 | * space, uses: | 60 | * space, uses: |
| 61 | * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_ADDR_RECEIVER, | 61 | * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_ADDR_RECEIVER, |
| 62 | * %HWSIM_ATTR_FRAME, %HWSIM_ATTR_FLAGS, %HWSIM_ATTR_RX_RATE, | 62 | * %HWSIM_ATTR_FRAME, %HWSIM_ATTR_FLAGS, %HWSIM_ATTR_RX_RATE, |
| 63 | * %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE, %HWSIM_ATTR_FREQ (optional) | 63 | * %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE, %HWSIM_ATTR_FREQ (optional) |
| 64 | * @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to | 64 | * @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to |
| 65 | * kernel, uses: | 65 | * kernel, uses: |
| 66 | * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS, | 66 | * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS, |
| 67 | * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE | 67 | * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE |
| 68 | * @HWSIM_CMD_NEW_RADIO: create a new radio with the given parameters, | 68 | * @HWSIM_CMD_NEW_RADIO: create a new radio with the given parameters, |
| @@ -1657,7 +1657,7 @@ static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev, · 1656 unmodified lines | |||
| 1657 | */ | 1657 | */ |
| 1658 | 1658 | ||
| 1659 | static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev, | 1659 | static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev, |
| 1660 | enum nl80211_iftype type, u32 *flags, | 1660 | enum nl80211_iftype type, |
| 1661 | struct vif_params *params) | 1661 | struct vif_params *params) |
| 1662 | { | 1662 | { |
| 1663 | struct lbs_private *priv = wiphy_priv(wiphy); | 1663 | struct lbs_private *priv = wiphy_priv(wiphy); |
| @@ -641,6 +641,8 @@ struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev) · 640 unmodified lines | |||
| 641 | BIT(NL80211_IFTYPE_ADHOC); | 641 | BIT(NL80211_IFTYPE_ADHOC); |
| 642 | skb_queue_head_init(&priv->bc_ps_buf); | 642 | skb_queue_head_init(&priv->bc_ps_buf); |
| 643 | 643 | ||
| 644 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 645 | |||
| 644 | SET_IEEE80211_DEV(hw, dmdev); | 646 | SET_IEEE80211_DEV(hw, dmdev); |
| 645 | 647 | ||
| 646 | INIT_WORK(&priv->cmd_work, lbtf_cmd_work); | 648 | INIT_WORK(&priv->cmd_work, lbtf_cmd_work); |
| @@ -935,7 +935,7 @@ mwifiex_init_new_priv_params(struct mwifiex_private *priv, · 934 unmodified lines | |||
| 935 | static int | 935 | static int |
| 936 | mwifiex_change_vif_to_p2p(struct net_device *dev, | 936 | mwifiex_change_vif_to_p2p(struct net_device *dev, |
| 937 | enum nl80211_iftype curr_iftype, | 937 | enum nl80211_iftype curr_iftype, |
| 938 | enum nl80211_iftype type, u32 *flags, | 938 | enum nl80211_iftype type, |
| 939 | struct vif_params *params) | 939 | struct vif_params *params) |
| 940 | { | 940 | { |
| 941 | struct mwifiex_private *priv; | 941 | struct mwifiex_private *priv; |
| @@ -1007,7 +1007,7 @@ mwifiex_change_vif_to_p2p(struct net_device *dev, · 65 unmodified lines | |||
| 1007 | static int | 1007 | static int |
| 1008 | mwifiex_change_vif_to_sta_adhoc(struct net_device *dev, | 1008 | mwifiex_change_vif_to_sta_adhoc(struct net_device *dev, |
| 1009 | enum nl80211_iftype curr_iftype, | 1009 | enum nl80211_iftype curr_iftype, |
| 1010 | enum nl80211_iftype type, u32 *flags, | 1010 | enum nl80211_iftype type, |
| 1011 | struct vif_params *params) | 1011 | struct vif_params *params) |
| 1012 | { | 1012 | { |
| 1013 | struct mwifiex_private *priv; | 1013 | struct mwifiex_private *priv; |
| @@ -1066,7 +1066,7 @@ mwifiex_change_vif_to_sta_adhoc(struct net_device *dev, · 52 unmodified lines | |||
| 1066 | static int | 1066 | static int |
| 1067 | mwifiex_change_vif_to_ap(struct net_device *dev, | 1067 | mwifiex_change_vif_to_ap(struct net_device *dev, |
| 1068 | enum nl80211_iftype curr_iftype, | 1068 | enum nl80211_iftype curr_iftype, |
| 1069 | enum nl80211_iftype type, u32 *flags, | 1069 | enum nl80211_iftype type, |
| 1070 | struct vif_params *params) | 1070 | struct vif_params *params) |
| 1071 | { | 1071 | { |
| 1072 | struct mwifiex_private *priv; | 1072 | struct mwifiex_private *priv; |
| @@ -1122,7 +1122,7 @@ mwifiex_change_vif_to_ap(struct net_device *dev, · 49 unmodified lines | |||
| 1122 | static int | 1122 | static int |
| 1123 | mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | 1123 | mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, |
| 1124 | struct net_device *dev, | 1124 | struct net_device *dev, |
| 1125 | enum nl80211_iftype type, u32 *flags, | 1125 | enum nl80211_iftype type, |
| 1126 | struct vif_params *params) | 1126 | struct vif_params *params) |
| 1127 | { | 1127 | { |
| 1128 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 1128 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
| @@ -1143,10 +1143,10 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, · 14 unmodified lines | |||
| 1143 | case NL80211_IFTYPE_P2P_CLIENT: | 1143 | case NL80211_IFTYPE_P2P_CLIENT: |
| 1144 | case NL80211_IFTYPE_P2P_GO: | 1144 | case NL80211_IFTYPE_P2P_GO: |
| 1145 | return mwifiex_change_vif_to_p2p(dev, curr_iftype, | 1145 | return mwifiex_change_vif_to_p2p(dev, curr_iftype, |
| 1146 | type, flags, params); | 1146 | type, params); |
| 1147 | case NL80211_IFTYPE_AP: | 1147 | case NL80211_IFTYPE_AP: |
| 1148 | return mwifiex_change_vif_to_ap(dev, curr_iftype, type, | 1148 | return mwifiex_change_vif_to_ap(dev, curr_iftype, type, |
| 1149 | flags, params); | 1149 | params); |
| 1150 | case NL80211_IFTYPE_UNSPECIFIED: | 1150 | case NL80211_IFTYPE_UNSPECIFIED: |
| 1151 | mwifiex_dbg(priv->adapter, INFO, | 1151 | mwifiex_dbg(priv->adapter, INFO, |
| 1152 | "%s: kept type as IBSS\n", dev->name); | 1152 | "%s: kept type as IBSS\n", dev->name); |
| @@ -1173,10 +1173,10 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, · 20 unmodified lines | |||
| 1173 | case NL80211_IFTYPE_P2P_CLIENT: | 1173 | case NL80211_IFTYPE_P2P_CLIENT: |
| 1174 | case NL80211_IFTYPE_P2P_GO: | 1174 | case NL80211_IFTYPE_P2P_GO: |
| 1175 | return mwifiex_change_vif_to_p2p(dev, curr_iftype, | 1175 | return mwifiex_change_vif_to_p2p(dev, curr_iftype, |
| 1176 | type, flags, params); | 1176 | type, params); |
| 1177 | case NL80211_IFTYPE_AP: | 1177 | case NL80211_IFTYPE_AP: |
| 1178 | return mwifiex_change_vif_to_ap(dev, curr_iftype, type, | 1178 | return mwifiex_change_vif_to_ap(dev, curr_iftype, type, |
| 1179 | flags, params); | 1179 | params); |
| 1180 | case NL80211_IFTYPE_UNSPECIFIED: | 1180 | case NL80211_IFTYPE_UNSPECIFIED: |
| 1181 | mwifiex_dbg(priv->adapter, INFO, | 1181 | mwifiex_dbg(priv->adapter, INFO, |
| 1182 | "%s: kept type as STA\n", dev->name); | 1182 | "%s: kept type as STA\n", dev->name); |
| @@ -1194,13 +1194,12 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, · 11 unmodified lines | |||
| 1194 | case NL80211_IFTYPE_ADHOC: | 1194 | case NL80211_IFTYPE_ADHOC: |
| 1195 | case NL80211_IFTYPE_STATION: | 1195 | case NL80211_IFTYPE_STATION: |
| 1196 | return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, | 1196 | return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, |
| 1197 | type, flags, | 1197 | type, params); |
| 1198 | params); | ||
| 1199 | break; | 1198 | break; |
| 1200 | case NL80211_IFTYPE_P2P_CLIENT: | 1199 | case NL80211_IFTYPE_P2P_CLIENT: |
| 1201 | case NL80211_IFTYPE_P2P_GO: | 1200 | case NL80211_IFTYPE_P2P_GO: |
| 1202 | return mwifiex_change_vif_to_p2p(dev, curr_iftype, | 1201 | return mwifiex_change_vif_to_p2p(dev, curr_iftype, |
| 1203 | type, flags, params); | 1202 | type, params); |
| 1204 | case NL80211_IFTYPE_UNSPECIFIED: | 1203 | case NL80211_IFTYPE_UNSPECIFIED: |
| 1205 | mwifiex_dbg(priv->adapter, INFO, | 1204 | mwifiex_dbg(priv->adapter, INFO, |
| 1206 | "%s: kept type as AP\n", dev->name); | 1205 | "%s: kept type as AP\n", dev->name); |
| @@ -1233,14 +1232,13 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, · 26 unmodified lines | |||
| 1233 | if (mwifiex_cfg80211_deinit_p2p(priv)) | 1232 | if (mwifiex_cfg80211_deinit_p2p(priv)) |
| 1234 | return -EFAULT; | 1233 | return -EFAULT; |
| 1235 | return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, | 1234 | return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, |
| 1236 | type, flags, | 1235 | type, params); |
| 1237 | params); | ||
| 1238 | break; | 1236 | break; |
| 1239 | case NL80211_IFTYPE_AP: | 1237 | case NL80211_IFTYPE_AP: |
| 1240 | if (mwifiex_cfg80211_deinit_p2p(priv)) | 1238 | if (mwifiex_cfg80211_deinit_p2p(priv)) |
| 1241 | return -EFAULT; | 1239 | return -EFAULT; |
| 1242 | return mwifiex_change_vif_to_ap(dev, curr_iftype, type, | 1240 | return mwifiex_change_vif_to_ap(dev, curr_iftype, type, |
| 1243 | flags, params); | 1241 | params); |
| 1244 | case NL80211_IFTYPE_UNSPECIFIED: | 1242 | case NL80211_IFTYPE_UNSPECIFIED: |
| 1245 | mwifiex_dbg(priv->adapter, INFO, | 1243 | mwifiex_dbg(priv->adapter, INFO, |
| 1246 | "%s: kept type as P2P\n", dev->name); | 1244 | "%s: kept type as P2P\n", dev->name); |
| @@ -2841,7 +2839,6 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, · 1594 unmodified lines | |||
| 2841 | const char *name, | 2839 | const char *name, |
| 2842 | unsigned char name_assign_type, | 2840 | unsigned char name_assign_type, |
| 2843 | enum nl80211_iftype type, | 2841 | enum nl80211_iftype type, |
| 2844 | u32 *flags, | ||
| 2845 | struct vif_params *params) | 2842 | struct vif_params *params) |
| 2846 | { | 2843 | { |
| 2847 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); | 2844 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
| @@ -596,7 +596,7 @@ static int _mwifiex_fw_dpc(const struct firmware *firmware, void *context) · 595 unmodified lines | |||
| 596 | rtnl_lock(); | 596 | rtnl_lock(); |
| 597 | /* Create station interface by default */ | 597 | /* Create station interface by default */ |
| 598 | wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", NET_NAME_ENUM, | 598 | wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", NET_NAME_ENUM, |
| 599 | NL80211_IFTYPE_STATION, NULL, NULL); | 599 | NL80211_IFTYPE_STATION, NULL); |
| 600 | if (IS_ERR(wdev)) { | 600 | if (IS_ERR(wdev)) { |
| 601 | mwifiex_dbg(adapter, ERROR, | 601 | mwifiex_dbg(adapter, ERROR, |
| 602 | "cannot create default STA interface\n"); | 602 | "cannot create default STA interface\n"); |
| @@ -606,7 +606,7 @@ static int _mwifiex_fw_dpc(const struct firmware *firmware, void *context) · 3 unmodified lines | |||
| 606 | 606 | ||
| 607 | if (driver_mode & MWIFIEX_DRIVER_MODE_UAP) { | 607 | if (driver_mode & MWIFIEX_DRIVER_MODE_UAP) { |
| 608 | wdev = mwifiex_add_virtual_intf(adapter->wiphy, "uap%d", NET_NAME_ENUM, | 608 | wdev = mwifiex_add_virtual_intf(adapter->wiphy, "uap%d", NET_NAME_ENUM, |
| 609 | NL80211_IFTYPE_AP, NULL, NULL); | 609 | NL80211_IFTYPE_AP, NULL); |
| 610 | if (IS_ERR(wdev)) { | 610 | if (IS_ERR(wdev)) { |
| 611 | mwifiex_dbg(adapter, ERROR, | 611 | mwifiex_dbg(adapter, ERROR, |
| 612 | "cannot create AP interface\n"); | 612 | "cannot create AP interface\n"); |
| @@ -617,8 +617,7 @@ static int _mwifiex_fw_dpc(const struct firmware *firmware, void *context) · 4 unmodified lines | |||
| 617 | 617 | ||
| 618 | if (driver_mode & MWIFIEX_DRIVER_MODE_P2P) { | 618 | if (driver_mode & MWIFIEX_DRIVER_MODE_P2P) { |
| 619 | wdev = mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d", NET_NAME_ENUM, | 619 | wdev = mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d", NET_NAME_ENUM, |
| 620 | NL80211_IFTYPE_P2P_CLIENT, NULL, | 620 | NL80211_IFTYPE_P2P_CLIENT, NULL); |
| 621 | NULL); | ||
| 622 | if (IS_ERR(wdev)) { | 621 | if (IS_ERR(wdev)) { |
| 623 | mwifiex_dbg(adapter, ERROR, | 622 | mwifiex_dbg(adapter, ERROR, |
| 624 | "cannot create p2p client interface\n"); | 623 | "cannot create p2p client interface\n"); |
| @@ -1529,7 +1529,6 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, · 1528 unmodified lines | |||
| 1529 | const char *name, | 1529 | const char *name, |
| 1530 | unsigned char name_assign_type, | 1530 | unsigned char name_assign_type, |
| 1531 | enum nl80211_iftype type, | 1531 | enum nl80211_iftype type, |
| 1532 | u32 *flags, | ||
| 1533 | struct vif_params *params); | 1532 | struct vif_params *params); |
| 1534 | int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev); | 1533 | int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev); |
| 1535 | 1534 | ||
| @@ -349,7 +349,7 @@ static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv, · 348 unmodified lines | |||
| 349 | chan_bw = IEEE80211_VHT_CHANWIDTH_USE_HT; | 349 | chan_bw = IEEE80211_VHT_CHANWIDTH_USE_HT; |
| 350 | break; | 350 | break; |
| 351 | } | 351 | } |
| 352 | vht_oper->center_freq_seg1_idx = | 352 | vht_oper->center_freq_seg0_idx = |
| 353 | mwifiex_get_center_freq_index(priv, BAND_AAC, | 353 | mwifiex_get_center_freq_index(priv, BAND_AAC, |
| 354 | bss_desc->channel, | 354 | bss_desc->channel, |
| 355 | chan_bw); | 355 | chan_bw); |
| @@ -6144,6 +6144,8 @@ static int mwl8k_firmware_load_success(struct mwl8k_priv *priv) · 6143 unmodified lines | |||
| 6144 | if (priv->sta_macids_supported || priv->device_info->fw_image_sta) | 6144 | if (priv->sta_macids_supported || priv->device_info->fw_image_sta) |
| 6145 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION); | 6145 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION); |
| 6146 | 6146 | ||
| 6147 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 6148 | |||
| 6147 | rc = ieee80211_register_hw(hw); | 6149 | rc = ieee80211_register_hw(hw); |
| 6148 | if (rc) { | 6150 | if (rc) { |
| 6149 | wiphy_err(hw->wiphy, "Cannot register device\n"); | 6151 | wiphy_err(hw->wiphy, "Cannot register device\n"); |
| @@ -615,6 +615,8 @@ int mt7601u_register_device(struct mt7601u_dev *dev) · 614 unmodified lines | |||
| 615 | wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; | 615 | wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR; |
| 616 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 616 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); |
| 617 | 617 | ||
| 618 | wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 619 | |||
| 618 | ret = mt76_init_sband_2g(dev); | 620 | ret = mt76_init_sband_2g(dev); |
| 619 | if (ret) | 621 | if (ret) |
| 620 | return ret; | 622 | return ret; |
| @@ -1456,6 +1456,9 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) · 1455 unmodified lines | |||
| 1456 | 1456 | ||
| 1457 | rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 1457 | rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
| 1458 | 1458 | ||
| 1459 | wiphy_ext_feature_set(rt2x00dev->hw->wiphy, | ||
| 1460 | NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 1461 | |||
| 1459 | /* | 1462 | /* |
| 1460 | * Initialize ieee80211 structure. | 1463 | * Initialize ieee80211 structure. |
| 1461 | */ | 1464 | */ |
| @@ -1877,6 +1877,8 @@ static int rtl8180_probe(struct pci_dev *pdev, · 1876 unmodified lines | |||
| 1877 | else | 1877 | else |
| 1878 | ieee80211_hw_set(dev, SIGNAL_UNSPEC); | 1878 | ieee80211_hw_set(dev, SIGNAL_UNSPEC); |
| 1879 | 1879 | ||
| 1880 | wiphy_ext_feature_set(dev->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 1881 | |||
| 1880 | rtl8180_eeprom_read(priv); | 1882 | rtl8180_eeprom_read(priv); |
| 1881 | 1883 | ||
| 1882 | switch (priv->rf_type) { | 1884 | switch (priv->rf_type) { |
| @@ -1607,6 +1607,8 @@ static int rtl8187_probe(struct usb_interface *intf, · 1606 unmodified lines | |||
| 1607 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 1607 | dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
| 1608 | BIT(NL80211_IFTYPE_ADHOC) ; | 1608 | BIT(NL80211_IFTYPE_ADHOC) ; |
| 1609 | 1609 | ||
| 1610 | wiphy_ext_feature_set(dev->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 1611 | |||
| 1610 | if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) | 1612 | if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) |
| 1611 | printk(KERN_INFO "rtl8187: inconsistency between id with OEM" | 1613 | printk(KERN_INFO "rtl8187: inconsistency between id with OEM" |
| 1612 | " info!\n"); | 1614 | " info!\n"); |
| @@ -6135,6 +6135,8 @@ static int rtl8xxxu_probe(struct usb_interface *interface, · 6134 unmodified lines | |||
| 6135 | ieee80211_hw_set(hw, HAS_RATE_CONTROL); | 6135 | ieee80211_hw_set(hw, HAS_RATE_CONTROL); |
| 6136 | ieee80211_hw_set(hw, AMPDU_AGGREGATION); | 6136 | ieee80211_hw_set(hw, AMPDU_AGGREGATION); |
| 6137 | 6137 | ||
| 6138 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 6139 | |||
| 6138 | ret = ieee80211_register_hw(priv->hw); | 6140 | ret = ieee80211_register_hw(priv->hw); |
| 6139 | if (ret) { | 6141 | if (ret) { |
| 6140 | dev_err(&udev->dev, "%s: Failed to register: %i\n", | 6142 | dev_err(&udev->dev, "%s: Failed to register: %i\n", |
| @@ -479,7 +479,7 @@ struct rndis_wlan_private { · 478 unmodified lines | |||
| 479 | */ | 479 | */ |
| 480 | static int rndis_change_virtual_intf(struct wiphy *wiphy, | 480 | static int rndis_change_virtual_intf(struct wiphy *wiphy, |
| 481 | struct net_device *dev, | 481 | struct net_device *dev, |
| 482 | enum nl80211_iftype type, u32 *flags, | 482 | enum nl80211_iftype type, |
| 483 | struct vif_params *params); | 483 | struct vif_params *params); |
| 484 | 484 | ||
| 485 | static int rndis_scan(struct wiphy *wiphy, | 485 | static int rndis_scan(struct wiphy *wiphy, |
| @@ -1857,7 +1857,7 @@ error: · 1371 unmodified lines | |||
| 1857 | */ | 1857 | */ |
| 1858 | static int rndis_change_virtual_intf(struct wiphy *wiphy, | 1858 | static int rndis_change_virtual_intf(struct wiphy *wiphy, |
| 1859 | struct net_device *dev, | 1859 | struct net_device *dev, |
| 1860 | enum nl80211_iftype type, u32 *flags, | 1860 | enum nl80211_iftype type, |
| 1861 | struct vif_params *params) | 1861 | struct vif_params *params) |
| 1862 | { | 1862 | { |
| 1863 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | 1863 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); |
| @@ -1261,6 +1261,8 @@ int rsi_mac80211_attach(struct rsi_common *common) · 1260 unmodified lines | |||
| 1261 | 1261 | ||
| 1262 | wiphy->reg_notifier = rsi_reg_notify; | 1262 | wiphy->reg_notifier = rsi_reg_notify; |
| 1263 | 1263 | ||
| 1264 | wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 1265 | |||
| 1264 | status = ieee80211_register_hw(hw); | 1266 | status = ieee80211_register_hw(hw); |
| 1265 | if (status) | 1267 | if (status) |
| 1266 | return status; | 1268 | return status; |
| @@ -1408,6 +1408,8 @@ struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) · 1407 unmodified lines | |||
| 1408 | BIT(NL80211_IFTYPE_ADHOC) | | 1408 | BIT(NL80211_IFTYPE_ADHOC) | |
| 1409 | BIT(NL80211_IFTYPE_AP); | 1409 | BIT(NL80211_IFTYPE_AP); |
| 1410 | 1410 | ||
| 1411 | wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); | ||
| 1412 | |||
| 1411 | hw->max_signal = 100; | 1413 | hw->max_signal = 100; |
| 1412 | hw->queues = 1; | 1414 | hw->queues = 1; |
| 1413 | hw->extra_tx_headroom = sizeof(struct zd_ctrlset); | 1415 | hw->extra_tx_headroom = sizeof(struct zd_ctrlset); |
| @@ -1837,7 +1837,7 @@ static int set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, · 1836 unmodified lines | |||
| 1837 | } | 1837 | } |
| 1838 | 1838 | ||
| 1839 | static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, | 1839 | static int change_virtual_intf(struct wiphy *wiphy, struct net_device *dev, |
| 1840 | enum nl80211_iftype type, u32 *flags, struct vif_params *params) | 1840 | enum nl80211_iftype type, struct vif_params *params) |
| 1841 | { | 1841 | { |
| 1842 | struct wilc_priv *priv; | 1842 | struct wilc_priv *priv; |
| 1843 | struct wilc_vif *vif; | 1843 | struct wilc_vif *vif; |
| @@ -2099,7 +2099,6 @@ static struct wireless_dev *add_virtual_intf(struct wiphy *wiphy, · 255 unmodified lines | |||
| 2099 | const char *name, | 2099 | const char *name, |
| 2100 | unsigned char name_assign_type, | 2100 | unsigned char name_assign_type, |
| 2101 | enum nl80211_iftype type, | 2101 | enum nl80211_iftype type, |
| 2102 | u32 *flags, | ||
| 2103 | struct vif_params *params) | 2102 | struct vif_params *params) |
| 2104 | { | 2103 | { |
| 2105 | struct wilc_vif *vif; | 2104 | struct wilc_vif *vif; |
| @@ -100,7 +100,7 @@ static int prism2_domibset_pstr32(struct wlandevice *wlandev, · 99 unmodified lines | |||
| 100 | /* The interface functions, called by the cfg80211 layer */ | 100 | /* The interface functions, called by the cfg80211 layer */ |
| 101 | static int prism2_change_virtual_intf(struct wiphy *wiphy, | 101 | static int prism2_change_virtual_intf(struct wiphy *wiphy, |
| 102 | struct net_device *dev, | 102 | struct net_device *dev, |
| 103 | enum nl80211_iftype type, u32 *flags, | 103 | enum nl80211_iftype type, |
| 104 | struct vif_params *params) | 104 | struct vif_params *params) |
| 105 | { | 105 | { |
| 106 | struct wlandevice *wlandev = dev->ml_priv; | 106 | struct wlandevice *wlandev = dev->ml_priv; |
| @@ -1411,6 +1411,8 @@ struct ieee80211_ht_operation { · 1410 unmodified lines | |||
| 1411 | #define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3 | 1411 | #define IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED 3 |
| 1412 | #define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004 | 1412 | #define IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT 0x0004 |
| 1413 | #define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010 | 1413 | #define IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT 0x0010 |
| 1414 | #define IEEE80211_HT_OP_MODE_CCFS2_SHIFT 5 | ||
| 1415 | #define IEEE80211_HT_OP_MODE_CCFS2_MASK 0x1fe0 | ||
| 1414 | 1416 | ||
| 1415 | /* for stbc_param */ | 1417 | /* for stbc_param */ |
| 1416 | #define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040 | 1418 | #define IEEE80211_HT_STBC_PARAM_DUAL_BEACON 0x0040 |
| @@ -1525,14 +1527,14 @@ enum ieee80211_vht_chanwidth { · 108 unmodified lines | |||
| 1525 | * This structure is the "VHT operation element" as | 1527 | * This structure is the "VHT operation element" as |
| 1526 | * described in 802.11ac D3.0 8.4.2.161 | 1528 | * described in 802.11ac D3.0 8.4.2.161 |
| 1527 | * @chan_width: Operating channel width | 1529 | * @chan_width: Operating channel width |
| 1530 | * @center_freq_seg0_idx: center freq segment 0 index | ||
| 1528 | * @center_freq_seg1_idx: center freq segment 1 index | 1531 | * @center_freq_seg1_idx: center freq segment 1 index |
| 1529 | * @center_freq_seg2_idx: center freq segment 2 index | ||
| 1530 | * @basic_mcs_set: VHT Basic MCS rate set | 1532 | * @basic_mcs_set: VHT Basic MCS rate set |
| 1531 | */ | 1533 | */ |
| 1532 | struct ieee80211_vht_operation { | 1534 | struct ieee80211_vht_operation { |
| 1533 | u8 chan_width; | 1535 | u8 chan_width; |
| 1536 | u8 center_freq_seg0_idx; | ||
| 1534 | u8 center_freq_seg1_idx; | 1537 | u8 center_freq_seg1_idx; |
| 1535 | u8 center_freq_seg2_idx; | ||
| 1536 | __le16 basic_mcs_set; | 1538 | __le16 basic_mcs_set; |
| 1537 | } __packed; | 1539 | } __packed; |
| 1538 | 1540 | ||
| @@ -1721,6 +1723,9 @@ enum ieee80211_statuscode { · 182 unmodified lines | |||
| 1721 | WLAN_STATUS_REJECT_DSE_BAND = 96, | 1723 | WLAN_STATUS_REJECT_DSE_BAND = 96, |
| 1722 | WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL = 99, | 1724 | WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL = 99, |
| 1723 | WLAN_STATUS_DENIED_DUE_TO_SPECTRUM_MANAGEMENT = 103, | 1725 | WLAN_STATUS_DENIED_DUE_TO_SPECTRUM_MANAGEMENT = 103, |
| 1726 | /* 802.11ai */ | ||
| 1727 | WLAN_STATUS_FILS_AUTHENTICATION_FAILURE = 108, | ||
| 1728 | WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER = 109, | ||
| 1724 | }; | 1729 | }; |
| 1725 | 1730 | ||
| 1726 | 1731 | ||
| @@ -2102,6 +2107,12 @@ enum ieee80211_key_len { · 375 unmodified lines | |||
| 2102 | #define FILS_NONCE_LEN 16 | 2107 | #define FILS_NONCE_LEN 16 |
| 2103 | #define FILS_MAX_KEK_LEN 64 | 2108 | #define FILS_MAX_KEK_LEN 64 |
| 2104 | 2109 | ||
| 2110 | #define FILS_ERP_MAX_USERNAME_LEN 16 | ||
| 2111 | #define FILS_ERP_MAX_REALM_LEN 253 | ||
| 2112 | #define FILS_ERP_MAX_RRK_LEN 64 | ||
| 2113 | |||
| 2114 | #define PMK_MAX_LEN 48 | ||
| 2115 | |||
| 2105 | /* Public action codes */ | 2116 | /* Public action codes */ |
| 2106 | enum ieee80211_pub_actioncode { | 2117 | enum ieee80211_pub_actioncode { |
| 2107 | WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4, | 2118 | WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4, |
| @@ -2347,11 +2358,16 @@ enum ieee80211_sa_query_action { · 239 unmodified lines | |||
| 2347 | /* AKM suite selectors */ | 2358 | /* AKM suite selectors */ |
| 2348 | #define WLAN_AKM_SUITE_8021X SUITE(0x000FAC, 1) | 2359 | #define WLAN_AKM_SUITE_8021X SUITE(0x000FAC, 1) |
| 2349 | #define WLAN_AKM_SUITE_PSK SUITE(0x000FAC, 2) | 2360 | #define WLAN_AKM_SUITE_PSK SUITE(0x000FAC, 2) |
| 2361 | #define WLAN_AKM_SUITE_FT_PSK SUITE(0x000FAC, 4) | ||
| 2350 | #define WLAN_AKM_SUITE_8021X_SHA256 SUITE(0x000FAC, 5) | 2362 | #define WLAN_AKM_SUITE_8021X_SHA256 SUITE(0x000FAC, 5) |
| 2351 | #define WLAN_AKM_SUITE_PSK_SHA256 SUITE(0x000FAC, 6) | 2363 | #define WLAN_AKM_SUITE_PSK_SHA256 SUITE(0x000FAC, 6) |
| 2352 | #define WLAN_AKM_SUITE_TDLS SUITE(0x000FAC, 7) | 2364 | #define WLAN_AKM_SUITE_TDLS SUITE(0x000FAC, 7) |
| 2353 | #define WLAN_AKM_SUITE_SAE SUITE(0x000FAC, 8) | 2365 | #define WLAN_AKM_SUITE_SAE SUITE(0x000FAC, 8) |
| 2354 | #define WLAN_AKM_SUITE_FT_OVER_SAE SUITE(0x000FAC, 9) | 2366 | #define WLAN_AKM_SUITE_FT_OVER_SAE SUITE(0x000FAC, 9) |
| 2367 | #define WLAN_AKM_SUITE_FILS_SHA256 SUITE(0x000FAC, 14) | ||
| 2368 | #define WLAN_AKM_SUITE_FILS_SHA384 SUITE(0x000FAC, 15) | ||
| 2369 | #define WLAN_AKM_SUITE_FT_FILS_SHA256 SUITE(0x000FAC, 16) | ||
| 2370 | #define WLAN_AKM_SUITE_FT_FILS_SHA384 SUITE(0x000FAC, 17) | ||
| 2355 | 2371 | ||
| 2356 | #define WLAN_MAX_KEY_LEN 32 | 2372 | #define WLAN_MAX_KEY_LEN 32 |
| 2357 | 2373 | ||
| @@ -363,6 +363,8 @@ static inline void wiphy_read_of_freq_limits(struct wiphy *wiphy) · 362 unmodified lines | |||
| 363 | 363 | ||
| 364 | /** | 364 | /** |
| 365 | * struct vif_params - describes virtual interface parameters | 365 | * struct vif_params - describes virtual interface parameters |
| 366 | * @flags: monitor interface flags, unchanged if 0, otherwise | ||
| 367 | * %MONITOR_FLAG_CHANGED will be set | ||
| 366 | * @use_4addr: use 4-address frames | 368 | * @use_4addr: use 4-address frames |
| 367 | * @macaddr: address to use for this virtual interface. | 369 | * @macaddr: address to use for this virtual interface. |
| 368 | * If this parameter is set to zero address the driver may | 370 | * If this parameter is set to zero address the driver may |
| @@ -370,13 +372,17 @@ static inline void wiphy_read_of_freq_limits(struct wiphy *wiphy) · 1 unmodified line | |||
| 370 | * This feature is only fully supported by drivers that enable the | 372 | * This feature is only fully supported by drivers that enable the |
| 371 | * %NL80211_FEATURE_MAC_ON_CREATE flag. Others may support creating | 373 | * %NL80211_FEATURE_MAC_ON_CREATE flag. Others may support creating |
| 372 | ** only p2p devices with specified MAC. | 374 | ** only p2p devices with specified MAC. |
| 373 | * @vht_mumimo_groups: MU-MIMO groupID. used for monitoring only | 375 | * @vht_mumimo_groups: MU-MIMO groupID, used for monitoring MU-MIMO packets |
| 374 | * packets belonging to that MU-MIMO groupID. | 376 | * belonging to that MU-MIMO groupID; %NULL if not changed |
| 377 | * @vht_mumimo_follow_addr: MU-MIMO follow address, used for monitoring | ||
| 378 | * MU-MIMO packets going to the specified station; %NULL if not changed | ||
| 375 | */ | 379 | */ |
| 376 | struct vif_params { | 380 | struct vif_params { |
| 381 | u32 flags; | ||
| 377 | int use_4addr; | 382 | int use_4addr; |
| 378 | u8 macaddr[ETH_ALEN]; | 383 | u8 macaddr[ETH_ALEN]; |
| 379 | u8 vht_mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN]; | 384 | const u8 *vht_mumimo_groups; |
| 385 | const u8 *vht_mumimo_follow_addr; | ||
| 380 | }; | 386 | }; |
| 381 | 387 | ||
| 382 | /** | 388 | /** |
| @@ -1211,6 +1217,7 @@ static inline int cfg80211_get_station(struct net_device *dev, · 828 unmodified lines | |||
| 1211 | * Monitor interface configuration flags. Note that these must be the bits | 1217 | * Monitor interface configuration flags. Note that these must be the bits |
| 1212 | * according to the nl80211 flags. | 1218 | * according to the nl80211 flags. |
| 1213 | * | 1219 | * |
| 1220 | * @MONITOR_FLAG_CHANGED: set if the flags were changed | ||
| 1214 | * @MONITOR_FLAG_FCSFAIL: pass frames with bad FCS | 1221 | * @MONITOR_FLAG_FCSFAIL: pass frames with bad FCS |
| 1215 | * @MONITOR_FLAG_PLCPFAIL: pass frames with bad PLCP | 1222 | * @MONITOR_FLAG_PLCPFAIL: pass frames with bad PLCP |
| 1216 | * @MONITOR_FLAG_CONTROL: pass control frames | 1223 | * @MONITOR_FLAG_CONTROL: pass control frames |
| @@ -1219,6 +1226,7 @@ static inline int cfg80211_get_station(struct net_device *dev, · 2 unmodified lines | |||
| 1219 | * @MONITOR_FLAG_ACTIVE: active monitor, ACKs frames on its MAC address | 1226 | * @MONITOR_FLAG_ACTIVE: active monitor, ACKs frames on its MAC address |
| 1220 | */ | 1227 | */ |
| 1221 | enum monitor_flags { | 1228 | enum monitor_flags { |
| 1229 | MONITOR_FLAG_CHANGED = 1<<__NL80211_MNTR_FLAG_INVALID, | ||
| 1222 | MONITOR_FLAG_FCSFAIL = 1<<NL80211_MNTR_FLAG_FCSFAIL, | 1230 | MONITOR_FLAG_FCSFAIL = 1<<NL80211_MNTR_FLAG_FCSFAIL, |
| 1223 | MONITOR_FLAG_PLCPFAIL = 1<<NL80211_MNTR_FLAG_PLCPFAIL, | 1231 | MONITOR_FLAG_PLCPFAIL = 1<<NL80211_MNTR_FLAG_PLCPFAIL, |
| 1224 | MONITOR_FLAG_CONTROL = 1<<NL80211_MNTR_FLAG_CONTROL, | 1232 | MONITOR_FLAG_CONTROL = 1<<NL80211_MNTR_FLAG_CONTROL, |
| @@ -1641,6 +1649,7 @@ struct cfg80211_bss_select_adjust { · 416 unmodified lines | |||
| 1641 | /** | 1649 | /** |
| 1642 | * struct cfg80211_sched_scan_request - scheduled scan request description | 1650 | * struct cfg80211_sched_scan_request - scheduled scan request description |
| 1643 | * | 1651 | * |
| 1652 | * @reqid: identifies this request. | ||
| 1644 | * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans) | 1653 | * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans) |
| 1645 | * @n_ssids: number of SSIDs | 1654 | * @n_ssids: number of SSIDs |
| 1646 | * @n_channels: total number of channels to scan | 1655 | * @n_channels: total number of channels to scan |
| @@ -1685,6 +1694,7 @@ struct cfg80211_bss_select_adjust { · 38 unmodified lines | |||
| 1685 | * comparisions. | 1694 | * comparisions. |
| 1686 | */ | 1695 | */ |
| 1687 | struct cfg80211_sched_scan_request { | 1696 | struct cfg80211_sched_scan_request { |
| 1697 | u64 reqid; | ||
| 1688 | struct cfg80211_ssid *ssids; | 1698 | struct cfg80211_ssid *ssids; |
| 1689 | int n_ssids; | 1699 | int n_ssids; |
| 1690 | u32 n_channels; | 1700 | u32 n_channels; |
| @@ -2073,6 +2083,19 @@ struct cfg80211_bss_selection { · 382 unmodified lines | |||
| 2073 | * the BSSID of the current association, i.e., to the value that is | 2083 | * the BSSID of the current association, i.e., to the value that is |
| 2074 | * included in the Current AP address field of the Reassociation Request | 2084 | * included in the Current AP address field of the Reassociation Request |
| 2075 | * frame. | 2085 | * frame. |
| 2086 | * @fils_erp_username: EAP re-authentication protocol (ERP) username part of the | ||
| 2087 | * NAI or %NULL if not specified. This is used to construct FILS wrapped | ||
| 2088 | * data IE. | ||
| 2089 | * @fils_erp_username_len: Length of @fils_erp_username in octets. | ||
| 2090 | * @fils_erp_realm: EAP re-authentication protocol (ERP) realm part of NAI or | ||
| 2091 | * %NULL if not specified. This specifies the domain name of ER server and | ||
| 2092 | * is used to construct FILS wrapped data IE. | ||
| 2093 | * @fils_erp_realm_len: Length of @fils_erp_realm in octets. | ||
| 2094 | * @fils_erp_next_seq_num: The next sequence number to use in the FILS ERP | ||
| 2095 | * messages. This is also used to construct FILS wrapped data IE. | ||
| 2096 | * @fils_erp_rrk: ERP re-authentication Root Key (rRK) used to derive additional | ||
| 2097 | * keys in FILS or %NULL if not specified. | ||
| 2098 | * @fils_erp_rrk_len: Length of @fils_erp_rrk in octets. | ||
| 2076 | */ | 2099 | */ |
| 2077 | struct cfg80211_connect_params { | 2100 | struct cfg80211_connect_params { |
| 2078 | struct ieee80211_channel *channel; | 2101 | struct ieee80211_channel *channel; |
| @@ -2098,6 +2121,13 @@ struct cfg80211_connect_params { · 19 unmodified lines | |||
| 2098 | bool pbss; | 2121 | bool pbss; |
| 2099 | struct cfg80211_bss_selection bss_select; | 2122 | struct cfg80211_bss_selection bss_select; |
| 2100 | const u8 *prev_bssid; | 2123 | const u8 *prev_bssid; |
| 2124 | const u8 *fils_erp_username; | ||
| 2125 | size_t fils_erp_username_len; | ||
| 2126 | const u8 *fils_erp_realm; | ||
| 2127 | size_t fils_erp_realm_len; | ||
| 2128 | u16 fils_erp_next_seq_num; | ||
| 2129 | const u8 *fils_erp_rrk; | ||
| 2130 | size_t fils_erp_rrk_len; | ||
| 2101 | }; | 2131 | }; |
| 2102 | 2132 | ||
| 2103 | /** | 2133 | /** |
| @@ -2136,12 +2166,27 @@ enum wiphy_params_flags { · 32 unmodified lines | |||
| 2136 | * This structure is passed to the set/del_pmksa() method for PMKSA | 2166 | * This structure is passed to the set/del_pmksa() method for PMKSA |
| 2137 | * caching. | 2167 | * caching. |
| 2138 | * | 2168 | * |
| 2139 | * @bssid: The AP's BSSID. | 2169 | * @bssid: The AP's BSSID (may be %NULL). |
| 2140 | * @pmkid: The PMK material itself. | 2170 | * @pmkid: The identifier to refer a PMKSA. |
| 2171 | * @pmk: The PMK for the PMKSA identified by @pmkid. This is used for key | ||
| 2172 | * derivation by a FILS STA. Otherwise, %NULL. | ||
| 2173 | * @pmk_len: Length of the @pmk. The length of @pmk can differ depending on | ||
| 2174 | * the hash algorithm used to generate this. | ||
| 2175 | * @ssid: SSID to specify the ESS within which a PMKSA is valid when using FILS | ||
| 2176 | * cache identifier (may be %NULL). | ||
| 2177 | * @ssid_len: Length of the @ssid in octets. | ||
| 2178 | * @cache_id: 2-octet cache identifier advertized by a FILS AP identifying the | ||
| 2179 | * scope of PMKSA. This is valid only if @ssid_len is non-zero (may be | ||
| 2180 | * %NULL). | ||
| 2141 | */ | 2181 | */ |
| 2142 | struct cfg80211_pmksa { | 2182 | struct cfg80211_pmksa { |
| 2143 | const u8 *bssid; | 2183 | const u8 *bssid; |
| 2144 | const u8 *pmkid; | 2184 | const u8 *pmkid; |
| 2185 | const u8 *pmk; | ||
| 2186 | size_t pmk_len; | ||
| 2187 | const u8 *ssid; | ||
| 2188 | size_t ssid_len; | ||
| 2189 | const u8 *cache_id; | ||
| 2145 | }; | 2190 | }; |
| 2146 | 2191 | ||
| 2147 | /** | 2192 | /** |
| @@ -2712,6 +2757,11 @@ struct cfg80211_nan_func { · 564 unmodified lines | |||
| 2712 | * the current level is above/below the configured threshold; this may | 2757 | * the current level is above/below the configured threshold; this may |
| 2713 | * need some care when the configuration is changed (without first being | 2758 | * need some care when the configuration is changed (without first being |
| 2714 | * disabled.) | 2759 | * disabled.) |
| 2760 | * @set_cqm_rssi_range_config: Configure two RSSI thresholds in the | ||
| 2761 | * connection quality monitor. An event is to be sent only when the | ||
| 2762 | * signal level is found to be outside the two values. The driver should | ||
| 2763 | * set %NL80211_EXT_FEATURE_CQM_RSSI_LIST if this method is implemented. | ||
| 2764 | * If it is provided then there's no point providing @set_cqm_rssi_config. | ||
| 2715 | * @set_cqm_txe_config: Configure connection quality monitor TX error | 2765 | * @set_cqm_txe_config: Configure connection quality monitor TX error |
| 2716 | * thresholds. | 2766 | * thresholds. |
| 2717 | * @sched_scan_start: Tell the driver to start a scheduled scan. | 2767 | * @sched_scan_start: Tell the driver to start a scheduled scan. |
| @@ -2826,13 +2876,12 @@ struct cfg80211_ops { · 108 unmodified lines | |||
| 2826 | const char *name, | 2876 | const char *name, |
| 2827 | unsigned char name_assign_type, | 2877 | unsigned char name_assign_type, |
| 2828 | enum nl80211_iftype type, | 2878 | enum nl80211_iftype type, |
| 2829 | u32 *flags, | ||
| 2830 | struct vif_params *params); | 2879 | struct vif_params *params); |
| 2831 | int (*del_virtual_intf)(struct wiphy *wiphy, | 2880 | int (*del_virtual_intf)(struct wiphy *wiphy, |
| 2832 | struct wireless_dev *wdev); | 2881 | struct wireless_dev *wdev); |
| 2833 | int (*change_virtual_intf)(struct wiphy *wiphy, | 2882 | int (*change_virtual_intf)(struct wiphy *wiphy, |
| 2834 | struct net_device *dev, | 2883 | struct net_device *dev, |
| 2835 | enum nl80211_iftype type, u32 *flags, | 2884 | enum nl80211_iftype type, |
| 2836 | struct vif_params *params); | 2885 | struct vif_params *params); |
| 2837 | 2886 | ||
| 2838 | int (*add_key)(struct wiphy *wiphy, struct net_device *netdev, | 2887 | int (*add_key)(struct wiphy *wiphy, struct net_device *netdev, |
| @@ -3001,6 +3050,10 @@ struct cfg80211_ops { · 162 unmodified lines | |||
| 3001 | struct net_device *dev, | 3050 | struct net_device *dev, |
| 3002 | s32 rssi_thold, u32 rssi_hyst); | 3051 | s32 rssi_thold, u32 rssi_hyst); |
| 3003 | 3052 | ||
| 3053 | int (*set_cqm_rssi_range_config)(struct wiphy *wiphy, | ||
| 3054 | struct net_device *dev, | ||
| 3055 | s32 rssi_low, s32 rssi_high); | ||
| 3056 | |||
| 3004 | int (*set_cqm_txe_config)(struct wiphy *wiphy, | 3057 | int (*set_cqm_txe_config)(struct wiphy *wiphy, |
| 3005 | struct net_device *dev, | 3058 | struct net_device *dev, |
| 3006 | u32 rate, u32 pkts, u32 intvl); | 3059 | u32 rate, u32 pkts, u32 intvl); |
| @@ -3871,6 +3924,7 @@ void wiphy_free(struct wiphy *wiphy); · 864 unmodified lines | |||
| 3871 | struct cfg80211_conn; | 3924 | struct cfg80211_conn; |
| 3872 | struct cfg80211_internal_bss; | 3925 | struct cfg80211_internal_bss; |
| 3873 | struct cfg80211_cached_keys; | 3926 | struct cfg80211_cached_keys; |
| 3927 | struct cfg80211_cqm_config; | ||
| 3874 | 3928 | ||
| 3875 | /** | 3929 | /** |
| 3876 | * struct wireless_dev - wireless device state | 3930 | * struct wireless_dev - wireless device state |
| @@ -3934,6 +3988,7 @@ struct cfg80211_cached_keys; · 57 unmodified lines | |||
| 3934 | * @event_list: (private) list for internal event processing | 3988 | * @event_list: (private) list for internal event processing |
| 3935 | * @event_lock: (private) lock for event list | 3989 | * @event_lock: (private) lock for event list |
| 3936 | * @owner_nlportid: (private) owner socket port ID | 3990 | * @owner_nlportid: (private) owner socket port ID |
| 3991 | * @cqm_config: (private) nl80211 RSSI monitor state | ||
| 3937 | */ | 3992 | */ |
| 3938 | struct wireless_dev { | 3993 | struct wireless_dev { |
| 3939 | struct wiphy *wiphy; | 3994 | struct wiphy *wiphy; |
| @@ -4002,6 +4057,8 @@ struct wireless_dev { · 62 unmodified lines | |||
| 4002 | bool prev_bssid_valid; | 4057 | bool prev_bssid_valid; |
| 4003 | } wext; | 4058 | } wext; |
| 4004 | #endif | 4059 | #endif |
| 4060 | |||
| 4061 | struct cfg80211_cqm_config *cqm_config; | ||
| 4005 | }; | 4062 | }; |
| 4006 | 4063 | ||
| 4007 | static inline u8 *wdev_address(struct wireless_dev *wdev) | 4064 | static inline u8 *wdev_address(struct wireless_dev *wdev) |
| @@ -4651,12 +4708,22 @@ cfg80211_inform_bss(struct wiphy *wiphy, · 643 unmodified lines | |||
| 4651 | gfp); | 4708 | gfp); |
| 4652 | } | 4709 | } |
| 4653 | 4710 | ||
| 4711 | /** | ||
| 4712 | * cfg80211_get_bss - get a BSS reference | ||
| 4713 | * @wiphy: the wiphy this BSS struct belongs to | ||
| 4714 | * @channel: the channel to search on (or %NULL) | ||
| 4715 | * @bssid: the desired BSSID (or %NULL) | ||
| 4716 | * @ssid: the desired SSID (or %NULL) | ||
| 4717 | * @ssid_len: length of the SSID (or 0) | ||
| 4718 | * @bss_type: type of BSS, see &enum ieee80211_bss_type | ||
| 4719 | * @privacy: privacy filter, see &enum ieee80211_privacy | ||
| 4720 | */ | ||
| 4654 | struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, | 4721 | struct cfg80211_bss *cfg80211_get_bss(struct wiphy *wiphy, |
| 4655 | struct ieee80211_channel *channel, | 4722 | struct ieee80211_channel *channel, |
| 4656 | const u8 *bssid, | 4723 | const u8 *bssid, |
| 4657 | const u8 *ssid, size_t ssid_len, | 4724 | const u8 *ssid, size_t ssid_len, |
| 4658 | enum ieee80211_bss_type bss_type, | 4725 | enum ieee80211_bss_type bss_type, |
| 4659 | enum ieee80211_privacy); | 4726 | enum ieee80211_privacy privacy); |
| 4660 | static inline struct cfg80211_bss * | 4727 | static inline struct cfg80211_bss * |
| 4661 | cfg80211_get_ibss(struct wiphy *wiphy, | 4728 | cfg80211_get_ibss(struct wiphy *wiphy, |
| 4662 | struct ieee80211_channel *channel, | 4729 | struct ieee80211_channel *channel, |
| @@ -5122,6 +5189,78 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) · 459 unmodified lines | |||
| 5122 | #define CFG80211_TESTMODE_DUMP(cmd) | 5189 | #define CFG80211_TESTMODE_DUMP(cmd) |
| 5123 | #endif | 5190 | #endif |
| 5124 | 5191 | ||
| 5192 | /** | ||
| 5193 | * struct cfg80211_connect_resp_params - Connection response params | ||
| 5194 | * @status: Status code, %WLAN_STATUS_SUCCESS for successful connection, use | ||
| 5195 | * %WLAN_STATUS_UNSPECIFIED_FAILURE if your device cannot give you | ||
| 5196 | * the real status code for failures. If this call is used to report a | ||
| 5197 | * failure due to a timeout (e.g., not receiving an Authentication frame | ||
| 5198 | * from the AP) instead of an explicit rejection by the AP, -1 is used to | ||
| 5199 | * indicate that this is a failure, but without a status code. | ||
| 5200 | * @timeout_reason is used to report the reason for the timeout in that | ||
| 5201 | * case. | ||
| 5202 | * @bssid: The BSSID of the AP (may be %NULL) | ||
| 5203 | * @bss: Entry of bss to which STA got connected to, can be obtained through | ||
| 5204 | * cfg80211_get_bss() (may be %NULL). Only one parameter among @bssid and | ||
| 5205 | * @bss needs to be specified. | ||
| 5206 | * @req_ie: Association request IEs (may be %NULL) | ||
| 5207 | * @req_ie_len: Association request IEs length | ||
| 5208 | * @resp_ie: Association response IEs (may be %NULL) | ||
| 5209 | * @resp_ie_len: Association response IEs length | ||
| 5210 | * @fils_kek: KEK derived from a successful FILS connection (may be %NULL) | ||
| 5211 | * @fils_kek_len: Length of @fils_kek in octets | ||
| 5212 | * @update_erp_next_seq_num: Boolean value to specify whether the value in | ||
| 5213 | * @fils_erp_next_seq_num is valid. | ||
| 5214 | * @fils_erp_next_seq_num: The next sequence number to use in ERP message in | ||
| 5215 | * FILS Authentication. This value should be specified irrespective of the | ||
| 5216 | * status for a FILS connection. | ||
| 5217 | * @pmk: A new PMK if derived from a successful FILS connection (may be %NULL). | ||
| 5218 | * @pmk_len: Length of @pmk in octets | ||
| 5219 | * @pmkid: A new PMKID if derived from a successful FILS connection or the PMKID | ||
| 5220 | * used for this FILS connection (may be %NULL). | ||
| 5221 | * @timeout_reason: Reason for connection timeout. This is used when the | ||
| 5222 | * connection fails due to a timeout instead of an explicit rejection from | ||
| 5223 | * the AP. %NL80211_TIMEOUT_UNSPECIFIED is used when the timeout reason is | ||
| 5224 | * not known. This value is used only if @status < 0 to indicate that the | ||
| 5225 | * failure is due to a timeout and not due to explicit rejection by the AP. | ||
| 5226 | * This value is ignored in other cases (@status >= 0). | ||
| 5227 | */ | ||
| 5228 | struct cfg80211_connect_resp_params { | ||
| 5229 | int status; | ||
| 5230 | const u8 *bssid; | ||
| 5231 | struct cfg80211_bss *bss; | ||
| 5232 | const u8 *req_ie; | ||
| 5233 | size_t req_ie_len; | ||
| 5234 | const u8 *resp_ie; | ||
| 5235 | size_t resp_ie_len; | ||
| 5236 | const u8 *fils_kek; | ||
| 5237 | size_t fils_kek_len; | ||
| 5238 | bool update_erp_next_seq_num; | ||
| 5239 | u16 fils_erp_next_seq_num; | ||
| 5240 | const u8 *pmk; | ||
| 5241 | size_t pmk_len; | ||
| 5242 | const u8 *pmkid; | ||
| 5243 | enum nl80211_timeout_reason timeout_reason; | ||
| 5244 | }; | ||
| 5245 | |||
| 5246 | /** | ||
| 5247 | * cfg80211_connect_done - notify cfg80211 of connection result | ||
| 5248 | * | ||
| 5249 | * @dev: network device | ||
| 5250 | * @params: connection response parameters | ||
| 5251 | * @gfp: allocation flags | ||
| 5252 | * | ||
| 5253 | * It should be called by the underlying driver once execution of the connection | ||
| 5254 | * request from connect() has been completed. This is similar to | ||
| 5255 | * cfg80211_connect_bss(), but takes a structure pointer for connection response | ||
| 5256 | * parameters. Only one of the functions among cfg80211_connect_bss(), | ||
| 5257 | * cfg80211_connect_result(), cfg80211_connect_timeout(), | ||
| 5258 | * and cfg80211_connect_done() should be called. | ||
| 5259 | */ | ||
| 5260 | void cfg80211_connect_done(struct net_device *dev, | ||
| 5261 | struct cfg80211_connect_resp_params *params, | ||
| 5262 | gfp_t gfp); | ||
| 5263 | |||
| 5125 | /** | 5264 | /** |
| 5126 | * cfg80211_connect_bss - notify cfg80211 of connection result | 5265 | * cfg80211_connect_bss - notify cfg80211 of connection result |
| 5127 | * | 5266 | * |
| @@ -5152,13 +5291,31 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) · 24 unmodified lines | |||
| 5152 | * It should be called by the underlying driver once execution of the connection | 5291 | * It should be called by the underlying driver once execution of the connection |
| 5153 | * request from connect() has been completed. This is similar to | 5292 | * request from connect() has been completed. This is similar to |
| 5154 | * cfg80211_connect_result(), but with the option of identifying the exact bss | 5293 | * cfg80211_connect_result(), but with the option of identifying the exact bss |
| 5155 | * entry for the connection. Only one of these functions should be called. | 5294 | * entry for the connection. Only one of the functions among |
| 5295 | * cfg80211_connect_bss(), cfg80211_connect_result(), | ||
| 5296 | * cfg80211_connect_timeout(), and cfg80211_connect_done() should be called. | ||
| 5156 | */ | 5297 | */ |
| 5157 | void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, | 5298 | static inline void |
| 5158 | struct cfg80211_bss *bss, const u8 *req_ie, | 5299 | cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, |
| 5159 | size_t req_ie_len, const u8 *resp_ie, | 5300 | struct cfg80211_bss *bss, const u8 *req_ie, |
| 5160 | size_t resp_ie_len, int status, gfp_t gfp, | 5301 | size_t req_ie_len, const u8 *resp_ie, |
| 5161 | enum nl80211_timeout_reason timeout_reason); | 5302 | size_t resp_ie_len, int status, gfp_t gfp, |
| 5303 | enum nl80211_timeout_reason timeout_reason) | ||
| 5304 | { | ||
| 5305 | struct cfg80211_connect_resp_params params; | ||
| 5306 | |||
| 5307 | memset(¶ms, 0, sizeof(params)); | ||
| 5308 | params.status = status; | ||
| 5309 | params.bssid = bssid; | ||
| 5310 | params.bss = bss; | ||
| 5311 | params.req_ie = req_ie; | ||
| 5312 | params.req_ie_len = req_ie_len; | ||
| 5313 | params.resp_ie = resp_ie; | ||
| 5314 | params.resp_ie_len = resp_ie_len; | ||
| 5315 | params.timeout_reason = timeout_reason; | ||
| 5316 | |||
| 5317 | cfg80211_connect_done(dev, ¶ms, gfp); | ||
| 5318 | } | ||
| 5162 | 5319 | ||
| 5163 | /** | 5320 | /** |
| 5164 | * cfg80211_connect_result - notify cfg80211 of connection result | 5321 | * cfg80211_connect_result - notify cfg80211 of connection result |
| @@ -5177,7 +5334,8 @@ void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, · 12 unmodified lines | |||
| 5177 | * It should be called by the underlying driver once execution of the connection | 5334 | * It should be called by the underlying driver once execution of the connection |
| 5178 | * request from connect() has been completed. This is similar to | 5335 | * request from connect() has been completed. This is similar to |
| 5179 | * cfg80211_connect_bss() which allows the exact bss entry to be specified. Only | 5336 | * cfg80211_connect_bss() which allows the exact bss entry to be specified. Only |
| 5180 | * one of these functions should be called. | 5337 | * one of the functions among cfg80211_connect_bss(), cfg80211_connect_result(), |
| 5338 | * cfg80211_connect_timeout(), and cfg80211_connect_done() should be called. | ||
| 5181 | */ | 5339 | */ |
| 5182 | static inline void | 5340 | static inline void |
| 5183 | cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 5341 | cfg80211_connect_result(struct net_device *dev, const u8 *bssid, |
| @@ -5204,7 +5362,9 @@ cfg80211_connect_result(struct net_device *dev, const u8 *bssid, · 20 unmodified lines | |||
| 5204 | * in a sequence where no explicit authentication/association rejection was | 5362 | * in a sequence where no explicit authentication/association rejection was |
| 5205 | * received from the AP. This could happen, e.g., due to not being able to send | 5363 | * received from the AP. This could happen, e.g., due to not being able to send |
| 5206 | * out the Authentication or Association Request frame or timing out while | 5364 | * out the Authentication or Association Request frame or timing out while |
| 5207 | * waiting for the response. | 5365 | * waiting for the response. Only one of the functions among |
| 5366 | * cfg80211_connect_bss(), cfg80211_connect_result(), | ||
| 5367 | * cfg80211_connect_timeout(), and cfg80211_connect_done() should be called. | ||
| 5208 | */ | 5368 | */ |
| 5209 | static inline void | 5369 | static inline void |
| 5210 | cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid, | 5370 | cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid, |
| @@ -501,6 +501,10 @@ struct ieee80211_mu_group_data { · 500 unmodified lines | |||
| 501 | * implies disabled. As with the cfg80211 callback, a change here should | 501 | * implies disabled. As with the cfg80211 callback, a change here should |
| 502 | * cause an event to be sent indicating where the current value is in | 502 | * cause an event to be sent indicating where the current value is in |
| 503 | * relation to the newly configured threshold. | 503 | * relation to the newly configured threshold. |
| 504 | * @cqm_rssi_low: Connection quality monitor RSSI lower threshold, a zero value | ||
| 505 | * implies disabled. This is an alternative mechanism to the single | ||
| 506 | * threshold event and can't be enabled simultaneously with it. | ||
| 507 | * @cqm_rssi_high: Connection quality monitor RSSI upper threshold. | ||
| 504 | * @cqm_rssi_hyst: Connection quality monitor RSSI hysteresis | 508 | * @cqm_rssi_hyst: Connection quality monitor RSSI hysteresis |
| 505 | * @arp_addr_list: List of IPv4 addresses for hardware ARP filtering. The | 509 | * @arp_addr_list: List of IPv4 addresses for hardware ARP filtering. The |
| 506 | * may filter ARP queries targeted for other addresses than listed here. | 510 | * may filter ARP queries targeted for other addresses than listed here. |
| @@ -553,6 +557,8 @@ struct ieee80211_bss_conf { · 46 unmodified lines | |||
| 553 | u16 ht_operation_mode; | 557 | u16 ht_operation_mode; |
| 554 | s32 cqm_rssi_thold; | 558 | s32 cqm_rssi_thold; |
| 555 | u32 cqm_rssi_hyst; | 559 | u32 cqm_rssi_hyst; |
| 560 | s32 cqm_rssi_low; | ||
| 561 | s32 cqm_rssi_high; | ||
| 556 | struct cfg80211_chan_def chandef; | 562 | struct cfg80211_chan_def chandef; |
| 557 | struct ieee80211_mu_group_data mu_group; | 563 | struct ieee80211_mu_group_data mu_group; |
| 558 | __be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; | 564 | __be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN]; |
| @@ -5438,9 +5444,6 @@ void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif, · 4879 unmodified lines | |||
| 5438 | * RTS threshold | 5444 | * RTS threshold |
| 5439 | * @short_preamble: whether mac80211 will request short-preamble transmission | 5445 | * @short_preamble: whether mac80211 will request short-preamble transmission |
| 5440 | * if the selected rate supports it | 5446 | * if the selected rate supports it |
| 5441 | * @max_rate_idx: user-requested maximum (legacy) rate | ||
| 5442 | * (deprecated; this will be removed once drivers get updated to use | ||
| 5443 | * rate_idx_mask) | ||
| 5444 | * @rate_idx_mask: user-requested (legacy) rate mask | 5447 | * @rate_idx_mask: user-requested (legacy) rate mask |
| 5445 | * @rate_idx_mcs_mask: user-requested MCS rate mask (NULL if not in use) | 5448 | * @rate_idx_mcs_mask: user-requested MCS rate mask (NULL if not in use) |
| 5446 | * @bss: whether this frame is sent out in AP or IBSS mode | 5449 | * @bss: whether this frame is sent out in AP or IBSS mode |
| @@ -5452,7 +5455,6 @@ struct ieee80211_tx_rate_control { · 5 unmodified lines | |||
| 5452 | struct sk_buff *skb; | 5455 | struct sk_buff *skb; |
| 5453 | struct ieee80211_tx_rate reported_rate; | 5456 | struct ieee80211_tx_rate reported_rate; |
| 5454 | bool rts, short_preamble; | 5457 | bool rts, short_preamble; |
| 5455 | u8 max_rate_idx; | ||
| 5456 | u32 rate_idx_mask; | 5458 | u32 rate_idx_mask; |
| 5457 | u8 *rate_idx_mcs_mask; | 5459 | u8 *rate_idx_mcs_mask; |
| 5458 | bool bss; | 5460 | bool bss; |
| @@ -172,6 +172,42 @@ · 171 unmodified lines | |||
| 172 | * Multiple such rules can be created. | 172 | * Multiple such rules can be created. |
| 173 | */ | 173 | */ |
| 174 | 174 | ||
| 175 | /** | ||
| 176 | * DOC: FILS shared key authentication offload | ||
| 177 | * | ||
| 178 | * FILS shared key authentication offload can be advertized by drivers by | ||
| 179 | * setting @NL80211_EXT_FEATURE_FILS_SK_OFFLOAD flag. The drivers that support | ||
| 180 | * FILS shared key authentication offload should be able to construct the | ||
| 181 | * authentication and association frames for FILS shared key authentication and | ||
| 182 | * eventually do a key derivation as per IEEE 802.11ai. The below additional | ||
| 183 | * parameters should be given to driver in %NL80211_CMD_CONNECT. | ||
| 184 | * %NL80211_ATTR_FILS_ERP_USERNAME - used to construct keyname_nai | ||
| 185 | * %NL80211_ATTR_FILS_ERP_REALM - used to construct keyname_nai | ||
| 186 | * %NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM - used to construct erp message | ||
| 187 | * %NL80211_ATTR_FILS_ERP_RRK - used to generate the rIK and rMSK | ||
| 188 | * rIK should be used to generate an authentication tag on the ERP message and | ||
| 189 | * rMSK should be used to derive a PMKSA. | ||
| 190 | * rIK, rMSK should be generated and keyname_nai, sequence number should be used | ||
| 191 | * as specified in IETF RFC 6696. | ||
| 192 | * | ||
| 193 | * When FILS shared key authentication is completed, driver needs to provide the | ||
| 194 | * below additional parameters to userspace. | ||
| 195 | * %NL80211_ATTR_FILS_KEK - used for key renewal | ||
| 196 | * %NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM - used in further EAP-RP exchanges | ||
| 197 | * %NL80211_ATTR_PMKID - used to identify the PMKSA used/generated | ||
| 198 | * %Nl80211_ATTR_PMK - used to update PMKSA cache in userspace | ||
| 199 | * The PMKSA can be maintained in userspace persistently so that it can be used | ||
| 200 | * later after reboots or wifi turn off/on also. | ||
| 201 | * | ||
| 202 | * %NL80211_ATTR_FILS_CACHE_ID is the cache identifier advertized by a FILS | ||
| 203 | * capable AP supporting PMK caching. It specifies the scope within which the | ||
| 204 | * PMKSAs are cached in an ESS. %NL80211_CMD_SET_PMKSA and | ||
| 205 | * %NL80211_CMD_DEL_PMKSA are enhanced to allow support for PMKSA caching based | ||
| 206 | * on FILS cache identifier. Additionally %NL80211_ATTR_PMK is used with | ||
| 207 | * %NL80211_SET_PMKSA to specify the PMK corresponding to a PMKSA for driver to | ||
| 208 | * use in a FILS shared key connection with PMKSA caching. | ||
| 209 | */ | ||
| 210 | |||
| 175 | /** | 211 | /** |
| 176 | * enum nl80211_commands - supported nl80211 commands | 212 | * enum nl80211_commands - supported nl80211 commands |
| 177 | * | 213 | * |
| @@ -370,10 +406,18 @@ · 192 unmodified lines | |||
| 370 | * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to | 406 | * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to |
| 371 | * NL80211_CMD_GET_SURVEY and on the "scan" multicast group) | 407 | * NL80211_CMD_GET_SURVEY and on the "scan" multicast group) |
| 372 | * | 408 | * |
| 373 | * @NL80211_CMD_SET_PMKSA: Add a PMKSA cache entry, using %NL80211_ATTR_MAC | 409 | * @NL80211_CMD_SET_PMKSA: Add a PMKSA cache entry using %NL80211_ATTR_MAC |
| 374 | * (for the BSSID) and %NL80211_ATTR_PMKID. | 410 | * (for the BSSID), %NL80211_ATTR_PMKID, and optionally %NL80211_ATTR_PMK |
| 411 | * (PMK is used for PTKSA derivation in case of FILS shared key offload) or | ||
| 412 | * using %NL80211_ATTR_SSID, %NL80211_ATTR_FILS_CACHE_ID, | ||
| 413 | * %NL80211_ATTR_PMKID, and %NL80211_ATTR_PMK in case of FILS | ||
| 414 | * authentication where %NL80211_ATTR_FILS_CACHE_ID is the identifier | ||
| 415 | * advertized by a FILS capable AP identifying the scope of PMKSA in an | ||
| 416 | * ESS. | ||
| 375 | * @NL80211_CMD_DEL_PMKSA: Delete a PMKSA cache entry, using %NL80211_ATTR_MAC | 417 | * @NL80211_CMD_DEL_PMKSA: Delete a PMKSA cache entry, using %NL80211_ATTR_MAC |
| 376 | * (for the BSSID) and %NL80211_ATTR_PMKID. | 418 | * (for the BSSID) and %NL80211_ATTR_PMKID or using %NL80211_ATTR_SSID, |
| 419 | * %NL80211_ATTR_FILS_CACHE_ID, and %NL80211_ATTR_PMKID in case of FILS | ||
| 420 | * authentication. | ||
| 377 | * @NL80211_CMD_FLUSH_PMKSA: Flush all PMKSA cache entries. | 421 | * @NL80211_CMD_FLUSH_PMKSA: Flush all PMKSA cache entries. |
| 378 | * | 422 | * |
| 379 | * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain | 423 | * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain |
| @@ -2012,6 +2056,31 @@ enum nl80211_commands { · 1632 unmodified lines | |||
| 2012 | * u32 attribute with an &enum nl80211_timeout_reason value. This is used, | 2056 | * u32 attribute with an &enum nl80211_timeout_reason value. This is used, |
| 2013 | * e.g., with %NL80211_CMD_CONNECT event. | 2057 | * e.g., with %NL80211_CMD_CONNECT event. |
| 2014 | * | 2058 | * |
| 2059 | * @NL80211_ATTR_FILS_ERP_USERNAME: EAP Re-authentication Protocol (ERP) | ||
| 2060 | * username part of NAI used to refer keys rRK and rIK. This is used with | ||
| 2061 | * %NL80211_CMD_CONNECT. | ||
| 2062 | * | ||
| 2063 | * @NL80211_ATTR_FILS_ERP_REALM: EAP Re-authentication Protocol (ERP) realm part | ||
| 2064 | * of NAI specifying the domain name of the ER server. This is used with | ||
| 2065 | * %NL80211_CMD_CONNECT. | ||
| 2066 | * | ||
| 2067 | * @NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM: Unsigned 16-bit ERP next sequence number | ||
| 2068 | * to use in ERP messages. This is used in generating the FILS wrapped data | ||
| 2069 | * for FILS authentication and is used with %NL80211_CMD_CONNECT. | ||
| 2070 | * | ||
| 2071 | * @NL80211_ATTR_FILS_ERP_RRK: ERP re-authentication Root Key (rRK) for the | ||
| 2072 | * NAI specified by %NL80211_ATTR_FILS_ERP_USERNAME and | ||
| 2073 | * %NL80211_ATTR_FILS_ERP_REALM. This is used for generating rIK and rMSK | ||
| 2074 | * from successful FILS authentication and is used with | ||
| 2075 | * %NL80211_CMD_CONNECT. | ||
| 2076 | * | ||
| 2077 | * @NL80211_ATTR_FILS_CACHE_ID: A 2-octet identifier advertized by a FILS AP | ||
| 2078 | * identifying the scope of PMKSAs. This is used with | ||
| 2079 | * @NL80211_CMD_SET_PMKSA and @NL80211_CMD_DEL_PMKSA. | ||
| 2080 | * | ||
| 2081 | * @NL80211_ATTR_PMK: PMK for the PMKSA identified by %NL80211_ATTR_PMKID. | ||
| 2082 | * This is used with @NL80211_CMD_SET_PMKSA. | ||
| 2083 | * | ||
| 2015 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available | 2084 | * @NUM_NL80211_ATTR: total number of nl80211_attrs available |
| 2016 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 2085 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
| 2017 | * @__NL80211_ATTR_AFTER_LAST: internal use | 2086 | * @__NL80211_ATTR_AFTER_LAST: internal use |
| @@ -2423,6 +2492,14 @@ enum nl80211_attrs { · 405 unmodified lines | |||
| 2423 | 2492 | ||
| 2424 | NL80211_ATTR_TIMEOUT_REASON, | 2493 | NL80211_ATTR_TIMEOUT_REASON, |
| 2425 | 2494 | ||
| 2495 | NL80211_ATTR_FILS_ERP_USERNAME, | ||
| 2496 | NL80211_ATTR_FILS_ERP_REALM, | ||
| 2497 | NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM, | ||
| 2498 | NL80211_ATTR_FILS_ERP_RRK, | ||
| 2499 | NL80211_ATTR_FILS_CACHE_ID, | ||
| 2500 | |||
| 2501 | NL80211_ATTR_PMK, | ||
| 2502 | |||
| 2426 | /* add attributes here, update the policy in nl80211.c */ | 2503 | /* add attributes here, update the policy in nl80211.c */ |
| 2427 | 2504 | ||
| 2428 | __NL80211_ATTR_AFTER_LAST, | 2505 | __NL80211_ATTR_AFTER_LAST, |
| @@ -3942,7 +4019,10 @@ enum nl80211_ps_state { · 1513 unmodified lines | |||
| 3942 | * @__NL80211_ATTR_CQM_INVALID: invalid | 4019 | * @__NL80211_ATTR_CQM_INVALID: invalid |
| 3943 | * @NL80211_ATTR_CQM_RSSI_THOLD: RSSI threshold in dBm. This value specifies | 4020 | * @NL80211_ATTR_CQM_RSSI_THOLD: RSSI threshold in dBm. This value specifies |
| 3944 | * the threshold for the RSSI level at which an event will be sent. Zero | 4021 | * the threshold for the RSSI level at which an event will be sent. Zero |
| 3945 | * to disable. | 4022 | * to disable. Alternatively, if %NL80211_EXT_FEATURE_CQM_RSSI_LIST is |
| 4023 | * set, multiple values can be supplied as a low-to-high sorted array of | ||
| 4024 | * threshold values in dBm. Events will be sent when the RSSI value | ||
| 4025 | * crosses any of the thresholds. | ||
| 3946 | * @NL80211_ATTR_CQM_RSSI_HYST: RSSI hysteresis in dBm. This value specifies | 4026 | * @NL80211_ATTR_CQM_RSSI_HYST: RSSI hysteresis in dBm. This value specifies |
| 3947 | * the minimum amount the RSSI level must change after an event before a | 4027 | * the minimum amount the RSSI level must change after an event before a |
| 3948 | * new event may be issued (to reduce effects of RSSI oscillation). | 4028 | * new event may be issued (to reduce effects of RSSI oscillation). |
| @@ -4753,6 +4833,11 @@ enum nl80211_feature_flags { · 804 unmodified lines | |||
| 4753 | * @NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI: The driver supports sched_scan | 4833 | * @NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI: The driver supports sched_scan |
| 4754 | * for reporting BSSs with better RSSI than the current connected BSS | 4834 | * for reporting BSSs with better RSSI than the current connected BSS |
| 4755 | * (%NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI). | 4835 | * (%NL80211_ATTR_SCHED_SCAN_RELATIVE_RSSI). |
| 4836 | * @NL80211_EXT_FEATURE_CQM_RSSI_LIST: With this driver the | ||
| 4837 | * %NL80211_ATTR_CQM_RSSI_THOLD attribute accepts a list of zero or more | ||
| 4838 | * RSSI threshold values to monitor rather than exactly one threshold. | ||
| 4839 | * @NL80211_EXT_FEATURE_FILS_SK_OFFLOAD: Driver SME supports FILS shared key | ||
| 4840 | * authentication with %NL80211_CMD_CONNECT. | ||
| 4756 | * | 4841 | * |
| 4757 | * @NUM_NL80211_EXT_FEATURES: number of extended features. | 4842 | * @NUM_NL80211_EXT_FEATURES: number of extended features. |
| 4758 | * @MAX_NL80211_EXT_FEATURES: highest extended feature index. | 4843 | * @MAX_NL80211_EXT_FEATURES: highest extended feature index. |
| @@ -4771,6 +4856,8 @@ enum nl80211_ext_feature_index { · 12 unmodified lines | |||
| 4771 | NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA, | 4856 | NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA, |
| 4772 | NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED, | 4857 | NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA_CONNECTED, |
| 4773 | NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI, | 4858 | NL80211_EXT_FEATURE_SCHED_SCAN_RELATIVE_RSSI, |
| 4859 | NL80211_EXT_FEATURE_CQM_RSSI_LIST, | ||
| 4860 | NL80211_EXT_FEATURE_FILS_SK_OFFLOAD, | ||
| 4774 | 4861 | ||
| 4775 | /* add new features before the definition below */ | 4862 | /* add new features before the definition below */ |
| 4776 | NUM_NL80211_EXT_FEATURES, | 4863 | NUM_NL80211_EXT_FEATURES, |
| @@ -4906,12 +4993,17 @@ enum nl80211_smps_mode { · 129 unmodified lines | |||
| 4906 | * change to the channel status. | 4993 | * change to the channel status. |
| 4907 | * @NL80211_RADAR_NOP_FINISHED: The Non-Occupancy Period for this channel is | 4994 | * @NL80211_RADAR_NOP_FINISHED: The Non-Occupancy Period for this channel is |
| 4908 | * over, channel becomes usable. | 4995 | * over, channel becomes usable. |
| 4996 | * @NL80211_RADAR_PRE_CAC_EXPIRED: Channel Availability Check done on this | ||
| 4997 | * non-operating channel is expired and no longer valid. New CAC must | ||
| 4998 | * be done on this channel before starting the operation. This is not | ||
| 4999 | * applicable for ETSI dfs domain where pre-CAC is valid for ever. | ||
| 4909 | */ | 5000 | */ |
| 4910 | enum nl80211_radar_event { | 5001 | enum nl80211_radar_event { |
| 4911 | NL80211_RADAR_DETECTED, | 5002 | NL80211_RADAR_DETECTED, |
| 4912 | NL80211_RADAR_CAC_FINISHED, | 5003 | NL80211_RADAR_CAC_FINISHED, |
| 4913 | NL80211_RADAR_CAC_ABORTED, | 5004 | NL80211_RADAR_CAC_ABORTED, |
| 4914 | NL80211_RADAR_NOP_FINISHED, | 5005 | NL80211_RADAR_NOP_FINISHED, |
| 5006 | NL80211_RADAR_PRE_CAC_EXPIRED, | ||
| 4915 | }; | 5007 | }; |
| 4916 | 5008 | ||
| 4917 | /** | 5009 | /** |
| @@ -357,14 +357,14 @@ void __ieee80211_start_rx_ba_session(struct sta_info *sta, · 356 unmodified lines | |||
| 357 | spin_lock_init(&tid_agg_rx->reorder_lock); | 357 | spin_lock_init(&tid_agg_rx->reorder_lock); |
| 358 | 358 | ||
| 359 | /* rx timer */ | 359 | /* rx timer */ |
| 360 | tid_agg_rx->session_timer.function = sta_rx_agg_session_timer_expired; | 360 | setup_deferrable_timer(&tid_agg_rx->session_timer, |
| 361 | tid_agg_rx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 361 | sta_rx_agg_session_timer_expired, |
| 362 | init_timer_deferrable(&tid_agg_rx->session_timer); | 362 | (unsigned long)&sta->timer_to_tid[tid]); |
| 363 | 363 | ||
| 364 | /* rx reorder timer */ | 364 | /* rx reorder timer */ |
| 365 | tid_agg_rx->reorder_timer.function = sta_rx_agg_reorder_timer_expired; | 365 | setup_timer(&tid_agg_rx->reorder_timer, |
| 366 | tid_agg_rx->reorder_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 366 | sta_rx_agg_reorder_timer_expired, |
| 367 | init_timer(&tid_agg_rx->reorder_timer); | 367 | (unsigned long)&sta->timer_to_tid[tid]); |
| 368 | 368 | ||
| 369 | /* prepare reordering buffer */ | 369 | /* prepare reordering buffer */ |
| 370 | tid_agg_rx->reorder_buf = | 370 | tid_agg_rx->reorder_buf = |
| @@ -670,14 +670,14 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, · 669 unmodified lines | |||
| 670 | tid_tx->timeout = timeout; | 670 | tid_tx->timeout = timeout; |
| 671 | 671 | ||
| 672 | /* response timer */ | 672 | /* response timer */ |
| 673 | tid_tx->addba_resp_timer.function = sta_addba_resp_timer_expired; | 673 | setup_timer(&tid_tx->addba_resp_timer, |
| 674 | tid_tx->addba_resp_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 674 | sta_addba_resp_timer_expired, |
| 675 | init_timer(&tid_tx->addba_resp_timer); | 675 | (unsigned long)&sta->timer_to_tid[tid]); |
| 676 | 676 | ||
| 677 | /* tx timer */ | 677 | /* tx timer */ |
| 678 | tid_tx->session_timer.function = sta_tx_agg_session_timer_expired; | 678 | setup_deferrable_timer(&tid_tx->session_timer, |
| 679 | tid_tx->session_timer.data = (unsigned long)&sta->timer_to_tid[tid]; | 679 | sta_tx_agg_session_timer_expired, |
| 680 | init_timer_deferrable(&tid_tx->session_timer); | 680 | (unsigned long)&sta->timer_to_tid[tid]); |
| 681 | 681 | ||
| 682 | /* assign a dialog token */ | 682 | /* assign a dialog token */ |
| 683 | sta->ampdu_mlme.dialog_token_allocator++; | 683 | sta->ampdu_mlme.dialog_token_allocator++; |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | |||
| 3 | * | 3 | * |
| 4 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> | 4 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> |
| 5 | * Copyright 2013-2015 Intel Mobile Communications GmbH | 5 | * Copyright 2013-2015 Intel Mobile Communications GmbH |
| 6 | * Copyright (C) 2015-2016 Intel Deutschland GmbH | 6 | * Copyright (C) 2015-2017 Intel Deutschland GmbH |
| 7 | * | 7 | * |
| 8 | * This file is GPLv2 as found in COPYING. | 8 | * This file is GPLv2 as found in COPYING. |
| 9 | */ | 9 | */ |
| @@ -22,11 +22,98 @@ · 12 unmodified lines | |||
| 22 | #include "mesh.h" | 22 | #include "mesh.h" |
| 23 | #include "wme.h" | 23 | #include "wme.h" |
| 24 | 24 | ||
| 25 | static void ieee80211_set_mu_mimo_follow(struct ieee80211_sub_if_data *sdata, | ||
| 26 | struct vif_params *params) | ||
| 27 | { | ||
| 28 | bool mu_mimo_groups = false; | ||
| 29 | bool mu_mimo_follow = false; | ||
| 30 | |||
| 31 | if (params->vht_mumimo_groups) { | ||
| 32 | u64 membership; | ||
| 33 | |||
| 34 | BUILD_BUG_ON(sizeof(membership) != WLAN_MEMBERSHIP_LEN); | ||
| 35 | |||
| 36 | memcpy(sdata->vif.bss_conf.mu_group.membership, | ||
| 37 | params->vht_mumimo_groups, WLAN_MEMBERSHIP_LEN); | ||
| 38 | memcpy(sdata->vif.bss_conf.mu_group.position, | ||
| 39 | params->vht_mumimo_groups + WLAN_MEMBERSHIP_LEN, | ||
| 40 | WLAN_USER_POSITION_LEN); | ||
| 41 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_MU_GROUPS); | ||
| 42 | /* don't care about endianness - just check for 0 */ | ||
| 43 | memcpy(&membership, params->vht_mumimo_groups, | ||
| 44 | WLAN_MEMBERSHIP_LEN); | ||
| 45 | mu_mimo_groups = membership != 0; | ||
| 46 | } | ||
| 47 | |||
| 48 | if (params->vht_mumimo_follow_addr) { | ||
| 49 | mu_mimo_follow = | ||
| 50 | is_valid_ether_addr(params->vht_mumimo_follow_addr); | ||
| 51 | ether_addr_copy(sdata->u.mntr.mu_follow_addr, | ||
| 52 | params->vht_mumimo_follow_addr); | ||
| 53 | } | ||
| 54 | |||
| 55 | sdata->vif.mu_mimo_owner = mu_mimo_groups || mu_mimo_follow; | ||
| 56 | } | ||
| 57 | |||
| 58 | static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, | ||
| 59 | struct vif_params *params) | ||
| 60 | { | ||
| 61 | struct ieee80211_local *local = sdata->local; | ||
| 62 | struct ieee80211_sub_if_data *monitor_sdata; | ||
| 63 | |||
| 64 | /* check flags first */ | ||
| 65 | if (params->flags && ieee80211_sdata_running(sdata)) { | ||
| 66 | u32 mask = MONITOR_FLAG_COOK_FRAMES | MONITOR_FLAG_ACTIVE; | ||
| 67 | |||
| 68 | /* | ||
| 69 | * Prohibit MONITOR_FLAG_COOK_FRAMES and | ||
| 70 | * MONITOR_FLAG_ACTIVE to be changed while the | ||
| 71 | * interface is up. | ||
| 72 | * Else we would need to add a lot of cruft | ||
| 73 | * to update everything: | ||
| 74 | * cooked_mntrs, monitor and all fif_* counters | ||
| 75 | * reconfigure hardware | ||
| 76 | */ | ||
| 77 | if ((params->flags & mask) != (sdata->u.mntr.flags & mask)) | ||
| 78 | return -EBUSY; | ||
| 79 | } | ||
| 80 | |||
| 81 | /* also validate MU-MIMO change */ | ||
| 82 | monitor_sdata = rtnl_dereference(local->monitor_sdata); | ||
| 83 | |||
| 84 | if (!monitor_sdata && | ||
| 85 | (params->vht_mumimo_groups || params->vht_mumimo_follow_addr)) | ||
| 86 | return -EOPNOTSUPP; | ||
| 87 | |||
| 88 | /* apply all changes now - no failures allowed */ | ||
| 89 | |||
| 90 | if (monitor_sdata) | ||
| 91 | ieee80211_set_mu_mimo_follow(monitor_sdata, params); | ||
| 92 | |||
| 93 | if (params->flags) { | ||
| 94 | if (ieee80211_sdata_running(sdata)) { | ||
| 95 | ieee80211_adjust_monitor_flags(sdata, -1); | ||
| 96 | sdata->u.mntr.flags = params->flags; | ||
| 97 | ieee80211_adjust_monitor_flags(sdata, 1); | ||
| 98 | |||
| 99 | ieee80211_configure_filter(local); | ||
| 100 | } else { | ||
| 101 | /* | ||
| 102 | * Because the interface is down, ieee80211_do_stop | ||
| 103 | * and ieee80211_do_open take care of "everything" | ||
| 104 | * mentioned in the comment above. | ||
| 105 | */ | ||
| 106 | sdata->u.mntr.flags = params->flags; | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | return 0; | ||
| 111 | } | ||
| 112 | |||
| 25 | static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, | 113 | static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, |
| 26 | const char *name, | 114 | const char *name, |
| 27 | unsigned char name_assign_type, | 115 | unsigned char name_assign_type, |
| 28 | enum nl80211_iftype type, | 116 | enum nl80211_iftype type, |
| 29 | u32 *flags, | ||
| 30 | struct vif_params *params) | 117 | struct vif_params *params) |
| 31 | { | 118 | { |
| 32 | struct ieee80211_local *local = wiphy_priv(wiphy); | 119 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| @@ -38,9 +125,14 @@ static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy, · 5 unmodified lines | |||
| 38 | if (err) | 125 | if (err) |
| 39 | return ERR_PTR(err); | 126 | return ERR_PTR(err); |
| 40 | 127 | ||
| 41 | if (type == NL80211_IFTYPE_MONITOR && flags) { | 128 | sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
| 42 | sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | 129 | |
| 43 | sdata->u.mntr.flags = *flags; | 130 | if (type == NL80211_IFTYPE_MONITOR) { |
| 131 | err = ieee80211_set_mon_options(sdata, params); | ||
| 132 | if (err) { | ||
| 133 | ieee80211_if_remove(sdata); | ||
| 134 | return NULL; | ||
| 135 | } | ||
| 44 | } | 136 | } |
| 45 | 137 | ||
| 46 | return wdev; | 138 | return wdev; |
| @@ -55,7 +147,7 @@ static int ieee80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) · 8 unmodified lines | |||
| 55 | 147 | ||
| 56 | static int ieee80211_change_iface(struct wiphy *wiphy, | 148 | static int ieee80211_change_iface(struct wiphy *wiphy, |
| 57 | struct net_device *dev, | 149 | struct net_device *dev, |
| 58 | enum nl80211_iftype type, u32 *flags, | 150 | enum nl80211_iftype type, |
| 59 | struct vif_params *params) | 151 | struct vif_params *params) |
| 60 | { | 152 | { |
| 61 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 153 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| @@ -75,58 +167,9 @@ static int ieee80211_change_iface(struct wiphy *wiphy, · 13 unmodified lines | |||
| 75 | } | 167 | } |
| 76 | 168 | ||
| 77 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { | 169 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { |
| 78 | struct ieee80211_local *local = sdata->local; | 170 | ret = ieee80211_set_mon_options(sdata, params); |
| 79 | struct ieee80211_sub_if_data *monitor_sdata; | 171 | if (ret) |
| 80 | u32 mu_mntr_cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER; | 172 | return ret; |
| 81 | |||
| 82 | monitor_sdata = rtnl_dereference(local->monitor_sdata); | ||
| 83 | if (monitor_sdata && | ||
| 84 | wiphy_ext_feature_isset(wiphy, mu_mntr_cap_flag)) { | ||
| 85 | memcpy(monitor_sdata->vif.bss_conf.mu_group.membership, | ||
| 86 | params->vht_mumimo_groups, WLAN_MEMBERSHIP_LEN); | ||
| 87 | memcpy(monitor_sdata->vif.bss_conf.mu_group.position, | ||
| 88 | params->vht_mumimo_groups + WLAN_MEMBERSHIP_LEN, | ||
| 89 | WLAN_USER_POSITION_LEN); | ||
| 90 | monitor_sdata->vif.mu_mimo_owner = true; | ||
| 91 | ieee80211_bss_info_change_notify(monitor_sdata, | ||
| 92 | BSS_CHANGED_MU_GROUPS); | ||
| 93 | |||
| 94 | ether_addr_copy(monitor_sdata->u.mntr.mu_follow_addr, | ||
| 95 | params->macaddr); | ||
| 96 | } | ||
| 97 | |||
| 98 | if (!flags) | ||
| 99 | return 0; | ||
| 100 | |||
| 101 | if (ieee80211_sdata_running(sdata)) { | ||
| 102 | u32 mask = MONITOR_FLAG_COOK_FRAMES | | ||
| 103 | MONITOR_FLAG_ACTIVE; | ||
| 104 | |||
| 105 | /* | ||
| 106 | * Prohibit MONITOR_FLAG_COOK_FRAMES and | ||
| 107 | * MONITOR_FLAG_ACTIVE to be changed while the | ||
| 108 | * interface is up. | ||
| 109 | * Else we would need to add a lot of cruft | ||
| 110 | * to update everything: | ||
| 111 | * cooked_mntrs, monitor and all fif_* counters | ||
| 112 | * reconfigure hardware | ||
| 113 | */ | ||
| 114 | if ((*flags & mask) != (sdata->u.mntr.flags & mask)) | ||
| 115 | return -EBUSY; | ||
| 116 | |||
| 117 | ieee80211_adjust_monitor_flags(sdata, -1); | ||
| 118 | sdata->u.mntr.flags = *flags; | ||
| 119 | ieee80211_adjust_monitor_flags(sdata, 1); | ||
| 120 | |||
| 121 | ieee80211_configure_filter(local); | ||
| 122 | } else { | ||
| 123 | /* | ||
| 124 | * Because the interface is down, ieee80211_do_stop | ||
| 125 | * and ieee80211_do_open take care of "everything" | ||
| 126 | * mentioned in the comment above. | ||
| 127 | */ | ||
| 128 | sdata->u.mntr.flags = *flags; | ||
| 129 | } | ||
| 130 | } | 173 | } |
| 131 | 174 | ||
| 132 | return 0; | 175 | return 0; |
| @@ -2042,6 +2085,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, · 1909 unmodified lines | |||
| 2042 | params->basic_rates_len, | 2085 | params->basic_rates_len, |
| 2043 | &sdata->vif.bss_conf.basic_rates); | 2086 | &sdata->vif.bss_conf.basic_rates); |
| 2044 | changed |= BSS_CHANGED_BASIC_RATES; | 2087 | changed |= BSS_CHANGED_BASIC_RATES; |
| 2088 | ieee80211_check_rate_mask(sdata); | ||
| 2045 | } | 2089 | } |
| 2046 | 2090 | ||
| 2047 | if (params->ap_isolate >= 0) { | 2091 | if (params->ap_isolate >= 0) { |
| @@ -2630,6 +2674,33 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy, · 582 unmodified lines | |||
| 2630 | 2674 | ||
| 2631 | bss_conf->cqm_rssi_thold = rssi_thold; | 2675 | bss_conf->cqm_rssi_thold = rssi_thold; |
| 2632 | bss_conf->cqm_rssi_hyst = rssi_hyst; | 2676 | bss_conf->cqm_rssi_hyst = rssi_hyst; |
| 2677 | bss_conf->cqm_rssi_low = 0; | ||
| 2678 | bss_conf->cqm_rssi_high = 0; | ||
| 2679 | sdata->u.mgd.last_cqm_event_signal = 0; | ||
| 2680 | |||
| 2681 | /* tell the driver upon association, unless already associated */ | ||
| 2682 | if (sdata->u.mgd.associated && | ||
| 2683 | sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI) | ||
| 2684 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM); | ||
| 2685 | |||
| 2686 | return 0; | ||
| 2687 | } | ||
| 2688 | |||
| 2689 | static int ieee80211_set_cqm_rssi_range_config(struct wiphy *wiphy, | ||
| 2690 | struct net_device *dev, | ||
| 2691 | s32 rssi_low, s32 rssi_high) | ||
| 2692 | { | ||
| 2693 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 2694 | struct ieee80211_vif *vif = &sdata->vif; | ||
| 2695 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
| 2696 | |||
| 2697 | if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER) | ||
| 2698 | return -EOPNOTSUPP; | ||
| 2699 | |||
| 2700 | bss_conf->cqm_rssi_low = rssi_low; | ||
| 2701 | bss_conf->cqm_rssi_high = rssi_high; | ||
| 2702 | bss_conf->cqm_rssi_thold = 0; | ||
| 2703 | bss_conf->cqm_rssi_hyst = 0; | ||
| 2633 | sdata->u.mgd.last_cqm_event_signal = 0; | 2704 | sdata->u.mgd.last_cqm_event_signal = 0; |
| 2634 | 2705 | ||
| 2635 | /* tell the driver upon association, unless already associated */ | 2706 | /* tell the driver upon association, unless already associated */ |
| @@ -2658,6 +2729,21 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, · 22 unmodified lines | |||
| 2658 | return ret; | 2729 | return ret; |
| 2659 | } | 2730 | } |
| 2660 | 2731 | ||
| 2732 | /* | ||
| 2733 | * If active validate the setting and reject it if it doesn't leave | ||
| 2734 | * at least one basic rate usable, since we really have to be able | ||
| 2735 | * to send something, and if we're an AP we have to be able to do | ||
| 2736 | * so at a basic rate so that all clients can receive it. | ||
| 2737 | */ | ||
| 2738 | if (rcu_access_pointer(sdata->vif.chanctx_conf) && | ||
| 2739 | sdata->vif.bss_conf.chandef.chan) { | ||
| 2740 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; | ||
| 2741 | enum nl80211_band band = sdata->vif.bss_conf.chandef.chan->band; | ||
| 2742 | |||
| 2743 | if (!(mask->control[band].legacy & basic_rates)) | ||
| 2744 | return -EINVAL; | ||
| 2745 | } | ||
| 2746 | |||
| 2661 | for (i = 0; i < NUM_NL80211_BANDS; i++) { | 2747 | for (i = 0; i < NUM_NL80211_BANDS; i++) { |
| 2662 | struct ieee80211_supported_band *sband = wiphy->bands[i]; | 2748 | struct ieee80211_supported_band *sband = wiphy->bands[i]; |
| 2663 | int j; | 2749 | int j; |
| @@ -3639,6 +3725,7 @@ const struct cfg80211_ops mac80211_config_ops = { · 975 unmodified lines | |||
| 3639 | .mgmt_tx = ieee80211_mgmt_tx, | 3725 | .mgmt_tx = ieee80211_mgmt_tx, |
| 3640 | .mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait, | 3726 | .mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait, |
| 3641 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, | 3727 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, |
| 3728 | .set_cqm_rssi_range_config = ieee80211_set_cqm_rssi_range_config, | ||
| 3642 | .mgmt_frame_register = ieee80211_mgmt_frame_register, | 3729 | .mgmt_frame_register = ieee80211_mgmt_frame_register, |
| 3643 | .set_antenna = ieee80211_set_antenna, | 3730 | .set_antenna = ieee80211_set_antenna, |
| 3644 | .get_antenna = ieee80211_get_antenna, | 3731 | .get_antenna = ieee80211_get_antenna, |
| @@ -425,7 +425,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, · 424 unmodified lines | |||
| 425 | case NL80211_CHAN_WIDTH_5: | 425 | case NL80211_CHAN_WIDTH_5: |
| 426 | case NL80211_CHAN_WIDTH_10: | 426 | case NL80211_CHAN_WIDTH_10: |
| 427 | cfg80211_chandef_create(&chandef, cbss->channel, | 427 | cfg80211_chandef_create(&chandef, cbss->channel, |
| 428 | NL80211_CHAN_WIDTH_20_NOHT); | 428 | NL80211_CHAN_NO_HT); |
| 429 | chandef.width = sdata->u.ibss.chandef.width; | 429 | chandef.width = sdata->u.ibss.chandef.width; |
| 430 | break; | 430 | break; |
| 431 | case NL80211_CHAN_WIDTH_80: | 431 | case NL80211_CHAN_WIDTH_80: |
| @@ -437,7 +437,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, · 5 unmodified lines | |||
| 437 | default: | 437 | default: |
| 438 | /* fall back to 20 MHz for unsupported modes */ | 438 | /* fall back to 20 MHz for unsupported modes */ |
| 439 | cfg80211_chandef_create(&chandef, cbss->channel, | 439 | cfg80211_chandef_create(&chandef, cbss->channel, |
| 440 | NL80211_CHAN_WIDTH_20_NOHT); | 440 | NL80211_CHAN_NO_HT); |
| 441 | break; | 441 | break; |
| 442 | } | 442 | } |
| 443 | 443 | ||
| @@ -839,6 +839,8 @@ struct txq_info { · 838 unmodified lines | |||
| 839 | struct ieee80211_if_mntr { | 839 | struct ieee80211_if_mntr { |
| 840 | u32 flags; | 840 | u32 flags; |
| 841 | u8 mu_follow_addr[ETH_ALEN] __aligned(2); | 841 | u8 mu_follow_addr[ETH_ALEN] __aligned(2); |
| 842 | |||
| 843 | struct list_head list; | ||
| 842 | }; | 844 | }; |
| 843 | 845 | ||
| 844 | /** | 846 | /** |
| @@ -1259,6 +1261,7 @@ struct ieee80211_local { · 414 unmodified lines | |||
| 1259 | 1261 | ||
| 1260 | /* see iface.c */ | 1262 | /* see iface.c */ |
| 1261 | struct list_head interfaces; | 1263 | struct list_head interfaces; |
| 1264 | struct list_head mon_list; /* only that are IFF_UP && !cooked */ | ||
| 1262 | struct mutex iflist_mtx; | 1265 | struct mutex iflist_mtx; |
| 1263 | 1266 | ||
| 1264 | /* | 1267 | /* |
| @@ -676,7 +676,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) · 675 unmodified lines | |||
| 676 | 676 | ||
| 677 | set_bit(SDATA_STATE_RUNNING, &sdata->state); | 677 | set_bit(SDATA_STATE_RUNNING, &sdata->state); |
| 678 | 678 | ||
| 679 | if (sdata->vif.type == NL80211_IFTYPE_WDS) { | 679 | switch (sdata->vif.type) { |
| 680 | case NL80211_IFTYPE_WDS: | ||
| 680 | /* Create STA entry for the WDS peer */ | 681 | /* Create STA entry for the WDS peer */ |
| 681 | sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, | 682 | sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, |
| 682 | GFP_KERNEL); | 683 | GFP_KERNEL); |
| @@ -697,8 +698,17 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) · 14 unmodified lines | |||
| 697 | 698 | ||
| 698 | rate_control_rate_init(sta); | 699 | rate_control_rate_init(sta); |
| 699 | netif_carrier_on(dev); | 700 | netif_carrier_on(dev); |
| 700 | } else if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) { | 701 | break; |
| 702 | case NL80211_IFTYPE_P2P_DEVICE: | ||
| 701 | rcu_assign_pointer(local->p2p_sdata, sdata); | 703 | rcu_assign_pointer(local->p2p_sdata, sdata); |
| 704 | break; | ||
| 705 | case NL80211_IFTYPE_MONITOR: | ||
| 706 | if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) | ||
| 707 | break; | ||
| 708 | list_add_tail_rcu(&sdata->u.mntr.list, &local->mon_list); | ||
| 709 | break; | ||
| 710 | default: | ||
| 711 | break; | ||
| 702 | } | 712 | } |
| 703 | 713 | ||
| 704 | /* | 714 | /* |
| @@ -817,6 +827,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, · 112 unmodified lines | |||
| 817 | case NL80211_IFTYPE_AP: | 827 | case NL80211_IFTYPE_AP: |
| 818 | cancel_work_sync(&sdata->u.ap.request_smps_work); | 828 | cancel_work_sync(&sdata->u.ap.request_smps_work); |
| 819 | break; | 829 | break; |
| 830 | case NL80211_IFTYPE_MONITOR: | ||
| 831 | if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) | ||
| 832 | break; | ||
| 833 | list_del_rcu(&sdata->u.mntr.list); | ||
| 834 | break; | ||
| 820 | default: | 835 | default: |
| 821 | break; | 836 | break; |
| 822 | } | 837 | } |
| @@ -603,6 +603,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, · 602 unmodified lines | |||
| 603 | ARRAY_SIZE(local->ext_capa); | 603 | ARRAY_SIZE(local->ext_capa); |
| 604 | 604 | ||
| 605 | INIT_LIST_HEAD(&local->interfaces); | 605 | INIT_LIST_HEAD(&local->interfaces); |
| 606 | INIT_LIST_HEAD(&local->mon_list); | ||
| 606 | 607 | ||
| 607 | __hw_addr_init(&local->mc_list); | 608 | __hw_addr_init(&local->mc_list); |
| 608 | 609 | ||
| @@ -1100,8 +1100,14 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, · 1099 unmodified lines | |||
| 1100 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | 1100 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) |
| 1101 | return; | 1101 | return; |
| 1102 | 1102 | ||
| 1103 | if (mesh_matches_local(sdata, &elems)) | 1103 | if (mesh_matches_local(sdata, &elems)) { |
| 1104 | mesh_neighbour_update(sdata, mgmt->sa, &elems); | 1104 | mpl_dbg(sdata, "rssi_threshold=%d,rx_status->signal=%d\n", |
| 1105 | sdata->u.mesh.mshcfg.rssi_threshold, rx_status->signal); | ||
| 1106 | if (!sdata->u.mesh.user_mpm || | ||
| 1107 | sdata->u.mesh.mshcfg.rssi_threshold == 0 || | ||
| 1108 | sdata->u.mesh.mshcfg.rssi_threshold < rx_status->signal) | ||
| 1109 | mesh_neighbour_update(sdata, mgmt->sa, &elems); | ||
| 1110 | } | ||
| 1105 | 1111 | ||
| 1106 | if (ifmsh->sync_ops) | 1112 | if (ifmsh->sync_ops) |
| 1107 | ifmsh->sync_ops->rx_bcn_presp(sdata, | 1113 | ifmsh->sync_ops->rx_bcn_presp(sdata, |
| @@ -16,6 +16,7 @@ · 15 unmodified lines | |||
| 16 | #define TEST_FRAME_LEN 8192 | 16 | #define TEST_FRAME_LEN 8192 |
| 17 | #define MAX_METRIC 0xffffffff | 17 | #define MAX_METRIC 0xffffffff |
| 18 | #define ARITH_SHIFT 8 | 18 | #define ARITH_SHIFT 8 |
| 19 | #define LINK_FAIL_THRESH 95 | ||
| 19 | 20 | ||
| 20 | #define MAX_PREQ_QUEUE_LEN 64 | 21 | #define MAX_PREQ_QUEUE_LEN 64 |
| 21 | 22 | ||
| @@ -307,10 +308,12 @@ void ieee80211s_update_metric(struct ieee80211_local *local, · 285 unmodified lines | |||
| 307 | 308 | ||
| 308 | failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK); | 309 | failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK); |
| 309 | 310 | ||
| 310 | /* moving average, scaled to 100 */ | 311 | /* moving average, scaled to 100. |
| 311 | sta->mesh->fail_avg = | 312 | * feed failure as 100 and success as 0 |
| 312 | ((80 * sta->mesh->fail_avg + 5) / 100 + 20 * failed); | 313 | */ |
| 313 | if (sta->mesh->fail_avg > 95) | 314 | ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, failed * 100); |
| 315 | if (ewma_mesh_fail_avg_read(&sta->mesh->fail_avg) > | ||
| 316 | LINK_FAIL_THRESH) | ||
| 314 | mesh_plink_broken(sta); | 317 | mesh_plink_broken(sta); |
| 315 | } | 318 | } |
| 316 | 319 | ||
| @@ -325,6 +328,8 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, · 8 unmodified lines | |||
| 325 | int rate, err; | 328 | int rate, err; |
| 326 | u32 tx_time, estimated_retx; | 329 | u32 tx_time, estimated_retx; |
| 327 | u64 result; | 330 | u64 result; |
| 331 | unsigned long fail_avg = | ||
| 332 | ewma_mesh_fail_avg_read(&sta->mesh->fail_avg); | ||
| 328 | 333 | ||
| 329 | /* Try to get rate based on HW/SW RC algorithm. | 334 | /* Try to get rate based on HW/SW RC algorithm. |
| 330 | * Rate is returned in units of Kbps, correct this | 335 | * Rate is returned in units of Kbps, correct this |
| @@ -336,7 +341,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, · 5 unmodified lines | |||
| 336 | if (rate) { | 341 | if (rate) { |
| 337 | err = 0; | 342 | err = 0; |
| 338 | } else { | 343 | } else { |
| 339 | if (sta->mesh->fail_avg >= 100) | 344 | if (fail_avg > LINK_FAIL_THRESH) |
| 340 | return MAX_METRIC; | 345 | return MAX_METRIC; |
| 341 | 346 | ||
| 342 | sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo); | 347 | sta_set_rate_info_tx(sta, &sta->tx_stats.last_rate, &rinfo); |
| @@ -344,7 +349,7 @@ static u32 airtime_link_metric_get(struct ieee80211_local *local, · 1 unmodified line | |||
| 344 | if (WARN_ON(!rate)) | 349 | if (WARN_ON(!rate)) |
| 345 | return MAX_METRIC; | 350 | return MAX_METRIC; |
| 346 | 351 | ||
| 347 | err = (sta->mesh->fail_avg << ARITH_SHIFT) / 100; | 352 | err = (fail_avg << ARITH_SHIFT) / 100; |
| 348 | } | 353 | } |
| 349 | 354 | ||
| 350 | /* bitrate is in units of 100 Kbps, while we need rate in units of | 355 | /* bitrate is in units of 100 Kbps, while we need rate in units of |
| @@ -484,6 +489,9 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, · 133 unmodified lines | |||
| 484 | ? mpath->exp_time : exp_time; | 489 | ? mpath->exp_time : exp_time; |
| 485 | mesh_path_activate(mpath); | 490 | mesh_path_activate(mpath); |
| 486 | spin_unlock_bh(&mpath->state_lock); | 491 | spin_unlock_bh(&mpath->state_lock); |
| 492 | ewma_mesh_fail_avg_init(&sta->mesh->fail_avg); | ||
| 493 | /* init it at a low value - 0 start is tricky */ | ||
| 494 | ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, 1); | ||
| 487 | mesh_path_tx_pending(mpath); | 495 | mesh_path_tx_pending(mpath); |
| 488 | /* draft says preq_id should be saved to, but there does | 496 | /* draft says preq_id should be saved to, but there does |
| 489 | * not seem to be any use for it, skipping by now | 497 | * not seem to be any use for it, skipping by now |
| @@ -522,6 +530,9 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, · 32 unmodified lines | |||
| 522 | ? mpath->exp_time : exp_time; | 530 | ? mpath->exp_time : exp_time; |
| 523 | mesh_path_activate(mpath); | 531 | mesh_path_activate(mpath); |
| 524 | spin_unlock_bh(&mpath->state_lock); | 532 | spin_unlock_bh(&mpath->state_lock); |
| 533 | ewma_mesh_fail_avg_init(&sta->mesh->fail_avg); | ||
| 534 | /* init it at a low value - 0 start is tricky */ | ||
| 535 | ewma_mesh_fail_avg_add(&sta->mesh->fail_avg, 1); | ||
| 525 | mesh_path_tx_pending(mpath); | 536 | mesh_path_tx_pending(mpath); |
| 526 | } else | 537 | } else |
| 527 | spin_unlock_bh(&mpath->state_lock); | 538 | spin_unlock_bh(&mpath->state_lock); |
| @@ -397,11 +397,10 @@ struct mesh_path *mesh_path_new(struct ieee80211_sub_if_data *sdata, · 396 unmodified lines | |||
| 397 | new_mpath->sdata = sdata; | 397 | new_mpath->sdata = sdata; |
| 398 | new_mpath->flags = 0; | 398 | new_mpath->flags = 0; |
| 399 | skb_queue_head_init(&new_mpath->frame_queue); | 399 | skb_queue_head_init(&new_mpath->frame_queue); |
| 400 | new_mpath->timer.data = (unsigned long) new_mpath; | ||
| 401 | new_mpath->timer.function = mesh_path_timer; | ||
| 402 | new_mpath->exp_time = jiffies; | 400 | new_mpath->exp_time = jiffies; |
| 403 | spin_lock_init(&new_mpath->state_lock); | 401 | spin_lock_init(&new_mpath->state_lock); |
| 404 | init_timer(&new_mpath->timer); | 402 | setup_timer(&new_mpath->timer, mesh_path_timer, |
| 403 | (unsigned long) new_mpath); | ||
| 405 | 404 | ||
| 406 | return new_mpath; | 405 | return new_mpath; |
| 407 | } | 406 | } |
| @@ -829,6 +828,9 @@ void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop) · 421 unmodified lines | |||
| 829 | mpath->flags = MESH_PATH_FIXED | MESH_PATH_SN_VALID; | 828 | mpath->flags = MESH_PATH_FIXED | MESH_PATH_SN_VALID; |
| 830 | mesh_path_activate(mpath); | 829 | mesh_path_activate(mpath); |
| 831 | spin_unlock_bh(&mpath->state_lock); | 830 | spin_unlock_bh(&mpath->state_lock); |
| 831 | ewma_mesh_fail_avg_init(&next_hop->mesh->fail_avg); | ||
| 832 | /* init it at a low value - 0 start is tricky */ | ||
| 833 | ewma_mesh_fail_avg_add(&next_hop->mesh->fail_avg, 1); | ||
| 832 | mesh_path_tx_pending(mpath); | 834 | mesh_path_tx_pending(mpath); |
| 833 | } | 835 | } |
| 834 | 836 | ||
| @@ -1908,6 +1908,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, · 1907 unmodified lines | |||
| 1908 | sdata->u.mgd.associated = cbss; | 1908 | sdata->u.mgd.associated = cbss; |
| 1909 | memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); | 1909 | memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); |
| 1910 | 1910 | ||
| 1911 | ieee80211_check_rate_mask(sdata); | ||
| 1912 | |||
| 1911 | sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; | 1913 | sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE; |
| 1912 | 1914 | ||
| 1913 | if (sdata->vif.p2p || | 1915 | if (sdata->vif.p2p || |
| @@ -2797,8 +2799,9 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, · 883 unmodified lines | |||
| 2797 | 2799 | ||
| 2798 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 2800 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
| 2799 | 2801 | ||
| 2800 | sdata_info(sdata, "disassociated from %pM (Reason: %u)\n", | 2802 | sdata_info(sdata, "disassociated from %pM (Reason: %u=%s)\n", |
| 2801 | mgmt->sa, reason_code); | 2803 | mgmt->sa, reason_code, |
| 2804 | ieee80211_get_reason_code_string(reason_code)); | ||
| 2802 | 2805 | ||
| 2803 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); | 2806 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); |
| 2804 | 2807 | ||
| @@ -2822,15 +2825,15 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband, · 17 unmodified lines | |||
| 2822 | *have_higher_than_11mbit = true; | 2825 | *have_higher_than_11mbit = true; |
| 2823 | 2826 | ||
| 2824 | /* | 2827 | /* |
| 2825 | * BSS_MEMBERSHIP_SELECTOR_HT_PHY is defined in 802.11n-2009 | 2828 | * Skip HT and VHT BSS membership selectors since they're not |
| 2826 | * 7.3.2.2 as a magic value instead of a rate. Hence, skip it. | 2829 | * rates. |
| 2827 | * | 2830 | * |
| 2828 | * Note: Even through the membership selector and the basic | 2831 | * Note: Even though the membership selector and the basic |
| 2829 | * rate flag share the same bit, they are not exactly | 2832 | * rate flag share the same bit, they are not exactly |
| 2830 | * the same. | 2833 | * the same. |
| 2831 | */ | 2834 | */ |
| 2832 | if (!!(supp_rates[i] & 0x80) && | 2835 | if (supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY) || |
| 2833 | (supp_rates[i] & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HT_PHY) | 2836 | supp_rates[i] == (0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY)) |
| 2834 | continue; | 2837 | continue; |
| 2835 | 2838 | ||
| 2836 | for (j = 0; j < sband->n_bitrates; j++) { | 2839 | for (j = 0; j < sband->n_bitrates; j++) { |
| @@ -3430,6 +3433,30 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, · 593 unmodified lines | |||
| 3430 | } | 3433 | } |
| 3431 | } | 3434 | } |
| 3432 | 3435 | ||
| 3436 | if (bss_conf->cqm_rssi_low && | ||
| 3437 | ifmgd->count_beacon_signal >= IEEE80211_SIGNAL_AVE_MIN_COUNT) { | ||
| 3438 | int sig = -ewma_beacon_signal_read(&ifmgd->ave_beacon_signal); | ||
| 3439 | int last_event = ifmgd->last_cqm_event_signal; | ||
| 3440 | int low = bss_conf->cqm_rssi_low; | ||
| 3441 | int high = bss_conf->cqm_rssi_high; | ||
| 3442 | |||
| 3443 | if (sig < low && | ||
| 3444 | (last_event == 0 || last_event >= low)) { | ||
| 3445 | ifmgd->last_cqm_event_signal = sig; | ||
| 3446 | ieee80211_cqm_rssi_notify( | ||
| 3447 | &sdata->vif, | ||
| 3448 | NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, | ||
| 3449 | sig, GFP_KERNEL); | ||
| 3450 | } else if (sig > high && | ||
| 3451 | (last_event == 0 || last_event <= high)) { | ||
| 3452 | ifmgd->last_cqm_event_signal = sig; | ||
| 3453 | ieee80211_cqm_rssi_notify( | ||
| 3454 | &sdata->vif, | ||
| 3455 | NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, | ||
| 3456 | sig, GFP_KERNEL); | ||
| 3457 | } | ||
| 3458 | } | ||
| 3459 | |||
| 3433 | if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) { | 3460 | if (ifmgd->flags & IEEE80211_STA_CONNECTION_POLL) { |
| 3434 | mlme_dbg_ratelimited(sdata, | 3461 | mlme_dbg_ratelimited(sdata, |
| 3435 | "cancelling AP probe due to a received beacon\n"); | 3462 | "cancelling AP probe due to a received beacon\n"); |
| @@ -2,6 +2,7 @@ · 1 unmodified line | |||
| 2 | * Copyright 2002-2005, Instant802 Networks, Inc. | 2 | * Copyright 2002-2005, Instant802 Networks, Inc. |
| 3 | * Copyright 2005-2006, Devicescape Software, Inc. | 3 | * Copyright 2005-2006, Devicescape Software, Inc. |
| 4 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> | 4 | * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz> |
| 5 | * Copyright 2017 Intel Deutschland GmbH | ||
| 5 | * | 6 | * |
| 6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
| @@ -173,9 +174,11 @@ ieee80211_rate_control_ops_get(const char *name) · 165 unmodified lines | |||
| 173 | /* try default if specific alg requested but not found */ | 174 | /* try default if specific alg requested but not found */ |
| 174 | ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo); | 175 | ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo); |
| 175 | 176 | ||
| 176 | /* try built-in one if specific alg requested but not found */ | 177 | /* Note: check for > 0 is intentional to avoid clang warning */ |
| 177 | if (!ops && strlen(CONFIG_MAC80211_RC_DEFAULT)) | 178 | if (!ops && (strlen(CONFIG_MAC80211_RC_DEFAULT) > 0)) |
| 179 | /* try built-in one if specific alg requested but not found */ | ||
| 178 | ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT); | 180 | ops = ieee80211_try_rate_control_ops_get(CONFIG_MAC80211_RC_DEFAULT); |
| 181 | |||
| 179 | kernel_param_unlock(THIS_MODULE); | 182 | kernel_param_unlock(THIS_MODULE); |
| 180 | 183 | ||
| 181 | return ops; | 184 | return ops; |
| @@ -208,7 +211,6 @@ static struct rate_control_ref *rate_control_alloc(const char *name, · 26 unmodified lines | |||
| 208 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); | 211 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); |
| 209 | if (!ref) | 212 | if (!ref) |
| 210 | return NULL; | 213 | return NULL; |
| 211 | ref->local = local; | ||
| 212 | ref->ops = ieee80211_rate_control_ops_get(name); | 214 | ref->ops = ieee80211_rate_control_ops_get(name); |
| 213 | if (!ref->ops) | 215 | if (!ref->ops) |
| 214 | goto free; | 216 | goto free; |
| @@ -229,18 +231,45 @@ free: · 14 unmodified lines | |||
| 229 | return NULL; | 231 | return NULL; |
| 230 | } | 232 | } |
| 231 | 233 | ||
| 232 | static void rate_control_free(struct rate_control_ref *ctrl_ref) | 234 | static void rate_control_free(struct ieee80211_local *local, |
| 235 | struct rate_control_ref *ctrl_ref) | ||
| 233 | { | 236 | { |
| 234 | ctrl_ref->ops->free(ctrl_ref->priv); | 237 | ctrl_ref->ops->free(ctrl_ref->priv); |
| 235 | 238 | ||
| 236 | #ifdef CONFIG_MAC80211_DEBUGFS | 239 | #ifdef CONFIG_MAC80211_DEBUGFS |
| 237 | debugfs_remove_recursive(ctrl_ref->local->debugfs.rcdir); | 240 | debugfs_remove_recursive(local->debugfs.rcdir); |
| 238 | ctrl_ref->local->debugfs.rcdir = NULL; | 241 | local->debugfs.rcdir = NULL; |
| 239 | #endif | 242 | #endif |
| 240 | 243 | ||
| 241 | kfree(ctrl_ref); | 244 | kfree(ctrl_ref); |
| 242 | } | 245 | } |
| 243 | 246 | ||
| 247 | void ieee80211_check_rate_mask(struct ieee80211_sub_if_data *sdata) | ||
| 248 | { | ||
| 249 | struct ieee80211_local *local = sdata->local; | ||
| 250 | struct ieee80211_supported_band *sband; | ||
| 251 | u32 user_mask, basic_rates = sdata->vif.bss_conf.basic_rates; | ||
| 252 | enum nl80211_band band; | ||
| 253 | |||
| 254 | if (WARN_ON(!sdata->vif.bss_conf.chandef.chan)) | ||
| 255 | return; | ||
| 256 | |||
| 257 | if (WARN_ON_ONCE(!basic_rates)) | ||
| 258 | return; | ||
| 259 | |||
| 260 | band = sdata->vif.bss_conf.chandef.chan->band; | ||
| 261 | user_mask = sdata->rc_rateidx_mask[band]; | ||
| 262 | sband = local->hw.wiphy->bands[band]; | ||
| 263 | |||
| 264 | if (user_mask & basic_rates) | ||
| 265 | return; | ||
| 266 | |||
| 267 | sdata_dbg(sdata, | ||
| 268 | "no overlap between basic rates (0x%x) and user mask (0x%x on band %d) - clearing the latter", | ||
| 269 | basic_rates, user_mask, band); | ||
| 270 | sdata->rc_rateidx_mask[band] = (1 << sband->n_bitrates) - 1; | ||
| 271 | } | ||
| 272 | |||
| 244 | static bool rc_no_data_or_no_ack_use_min(struct ieee80211_tx_rate_control *txrc) | 273 | static bool rc_no_data_or_no_ack_use_min(struct ieee80211_tx_rate_control *txrc) |
| 245 | { | 274 | { |
| 246 | struct sk_buff *skb = txrc->skb; | 275 | struct sk_buff *skb = txrc->skb; |
| @@ -936,6 +965,6 @@ void rate_control_deinitialize(struct ieee80211_local *local) · 689 unmodified lines | |||
| 936 | return; | 965 | return; |
| 937 | 966 | ||
| 938 | local->rate_ctrl = NULL; | 967 | local->rate_ctrl = NULL; |
| 939 | rate_control_free(ref); | 968 | rate_control_free(local, ref); |
| 940 | } | 969 | } |
| 941 | 970 | ||
| @@ -20,7 +20,6 @@ · 19 unmodified lines | |||
| 20 | #include "driver-ops.h" | 20 | #include "driver-ops.h" |
| 21 | 21 | ||
| 22 | struct rate_control_ref { | 22 | struct rate_control_ref { |
| 23 | struct ieee80211_local *local; | ||
| 24 | const struct rate_control_ops *ops; | 23 | const struct rate_control_ops *ops; |
| 25 | void *priv; | 24 | void *priv; |
| 26 | }; | 25 | }; |
| @@ -111,6 +110,8 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) · 84 unmodified lines | |||
| 111 | #endif | 110 | #endif |
| 112 | } | 111 | } |
| 113 | 112 | ||
| 113 | void ieee80211_check_rate_mask(struct ieee80211_sub_if_data *sdata); | ||
| 114 | |||
| 114 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the | 115 | /* Get a reference to the rate control algorithm. If `name' is NULL, get the |
| 115 | * first available algorithm. */ | 116 | * first available algorithm. */ |
| 116 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | 117 | int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, |
| @@ -95,24 +95,13 @@ static u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, · 94 unmodified lines | |||
| 95 | * This function cleans up the SKB, i.e. it removes all the stuff | 95 | * This function cleans up the SKB, i.e. it removes all the stuff |
| 96 | * only useful for monitoring. | 96 | * only useful for monitoring. |
| 97 | */ | 97 | */ |
| 98 | static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | 98 | static void remove_monitor_info(struct sk_buff *skb, |
| 99 | struct sk_buff *skb, | 99 | unsigned int present_fcs_len, |
| 100 | unsigned int rtap_vendor_space) | 100 | unsigned int rtap_vendor_space) |
| 101 | { | 101 | { |
| 102 | if (ieee80211_hw_check(&local->hw, RX_INCLUDES_FCS)) { | 102 | if (present_fcs_len) |
| 103 | if (likely(skb->len > FCS_LEN)) | 103 | __pskb_trim(skb, skb->len - present_fcs_len); |
| 104 | __pskb_trim(skb, skb->len - FCS_LEN); | ||
| 105 | else { | ||
| 106 | /* driver bug */ | ||
| 107 | WARN_ON(1); | ||
| 108 | dev_kfree_skb(skb); | ||
| 109 | return NULL; | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | __pskb_pull(skb, rtap_vendor_space); | 104 | __pskb_pull(skb, rtap_vendor_space); |
| 114 | |||
| 115 | return skb; | ||
| 116 | } | 105 | } |
| 117 | 106 | ||
| 118 | static inline bool should_drop_frame(struct sk_buff *skb, int present_fcs_len, | 107 | static inline bool should_drop_frame(struct sk_buff *skb, int present_fcs_len, |
| @@ -534,8 +523,15 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, · 415 unmodified lines | |||
| 534 | * the SKB because it has a bad FCS/PLCP checksum. | 523 | * the SKB because it has a bad FCS/PLCP checksum. |
| 535 | */ | 524 | */ |
| 536 | 525 | ||
| 537 | if (ieee80211_hw_check(&local->hw, RX_INCLUDES_FCS)) | 526 | if (ieee80211_hw_check(&local->hw, RX_INCLUDES_FCS)) { |
| 527 | if (unlikely(origskb->len <= FCS_LEN)) { | ||
| 528 | /* driver bug */ | ||
| 529 | WARN_ON(1); | ||
| 530 | dev_kfree_skb(origskb); | ||
| 531 | return NULL; | ||
| 532 | } | ||
| 538 | present_fcs_len = FCS_LEN; | 533 | present_fcs_len = FCS_LEN; |
| 534 | } | ||
| 539 | 535 | ||
| 540 | /* ensure hdr->frame_control and vendor radiotap data are in skb head */ | 536 | /* ensure hdr->frame_control and vendor radiotap data are in skb head */ |
| 541 | if (!pskb_may_pull(origskb, 2 + rtap_vendor_space)) { | 537 | if (!pskb_may_pull(origskb, 2 + rtap_vendor_space)) { |
| @@ -550,7 +546,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, · 8 unmodified lines | |||
| 550 | return NULL; | 546 | return NULL; |
| 551 | } | 547 | } |
| 552 | 548 | ||
| 553 | return remove_monitor_info(local, origskb, rtap_vendor_space); | 549 | remove_monitor_info(origskb, present_fcs_len, |
| 550 | rtap_vendor_space); | ||
| 551 | return origskb; | ||
| 554 | } | 552 | } |
| 555 | 553 | ||
| 556 | /* room for the radiotap header based on driver features */ | 554 | /* room for the radiotap header based on driver features */ |
| @@ -580,9 +578,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, · 23 unmodified lines | |||
| 580 | * and FCS from the original. | 578 | * and FCS from the original. |
| 581 | */ | 579 | */ |
| 582 | skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC); | 580 | skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC); |
| 583 | 581 | remove_monitor_info(origskb, present_fcs_len, | |
| 584 | origskb = remove_monitor_info(local, origskb, | 582 | rtap_vendor_space); |
| 585 | rtap_vendor_space); | ||
| 586 | 583 | ||
| 587 | if (!skb) | 584 | if (!skb) |
| 588 | return origskb; | 585 | return origskb; |
| @@ -596,16 +593,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, · 7 unmodified lines | |||
| 596 | skb->pkt_type = PACKET_OTHERHOST; | 593 | skb->pkt_type = PACKET_OTHERHOST; |
| 597 | skb->protocol = htons(ETH_P_802_2); | 594 | skb->protocol = htons(ETH_P_802_2); |
| 598 | 595 | ||
| 599 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 596 | list_for_each_entry_rcu(sdata, &local->mon_list, u.mntr.list) { |
| 600 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | ||
| 601 | continue; | ||
| 602 | |||
| 603 | if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES) | ||
| 604 | continue; | ||
| 605 | |||
| 606 | if (!ieee80211_sdata_running(sdata)) | ||
| 607 | continue; | ||
| 608 | |||
| 609 | if (prev_dev) { | 597 | if (prev_dev) { |
| 610 | skb2 = skb_clone(skb, GFP_ATOMIC); | 598 | skb2 = skb_clone(skb, GFP_ATOMIC); |
| 611 | if (skb2) { | 599 | if (skb2) { |
| @@ -132,9 +132,9 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata, · 131 unmodified lines | |||
| 132 | struct ieee80211_vht_operation vht_oper = { | 132 | struct ieee80211_vht_operation vht_oper = { |
| 133 | .chan_width = | 133 | .chan_width = |
| 134 | wide_bw_chansw_ie->new_channel_width, | 134 | wide_bw_chansw_ie->new_channel_width, |
| 135 | .center_freq_seg1_idx = | 135 | .center_freq_seg0_idx = |
| 136 | wide_bw_chansw_ie->new_center_freq_seg0, | 136 | wide_bw_chansw_ie->new_center_freq_seg0, |
| 137 | .center_freq_seg2_idx = | 137 | .center_freq_seg1_idx = |
| 138 | wide_bw_chansw_ie->new_center_freq_seg1, | 138 | wide_bw_chansw_ie->new_center_freq_seg1, |
| 139 | /* .basic_mcs_set doesn't matter */ | 139 | /* .basic_mcs_set doesn't matter */ |
| 140 | }; | 140 | }; |
| @@ -1960,14 +1960,17 @@ static void sta_stats_decode_rate(struct ieee80211_local *local, u16 rate, · 1959 unmodified lines | |||
| 1960 | rinfo->bw = (rate & STA_STATS_RATE_BW_MASK) >> | 1960 | rinfo->bw = (rate & STA_STATS_RATE_BW_MASK) >> |
| 1961 | STA_STATS_RATE_BW_SHIFT; | 1961 | STA_STATS_RATE_BW_SHIFT; |
| 1962 | 1962 | ||
| 1963 | if (rate & STA_STATS_RATE_VHT) { | 1963 | switch (rate & STA_STATS_RATE_TYPE_MASK) { |
| 1964 | case STA_STATS_RATE_TYPE_VHT: | ||
| 1964 | rinfo->flags = RATE_INFO_FLAGS_VHT_MCS; | 1965 | rinfo->flags = RATE_INFO_FLAGS_VHT_MCS; |
| 1965 | rinfo->mcs = rate & 0xf; | 1966 | rinfo->mcs = rate & 0xf; |
| 1966 | rinfo->nss = (rate & 0xf0) >> 4; | 1967 | rinfo->nss = (rate & 0xf0) >> 4; |
| 1967 | } else if (rate & STA_STATS_RATE_HT) { | 1968 | break; |
| 1969 | case STA_STATS_RATE_TYPE_HT: | ||
| 1968 | rinfo->flags = RATE_INFO_FLAGS_MCS; | 1970 | rinfo->flags = RATE_INFO_FLAGS_MCS; |
| 1969 | rinfo->mcs = rate & 0xff; | 1971 | rinfo->mcs = rate & 0xff; |
| 1970 | } else if (rate & STA_STATS_RATE_LEGACY) { | 1972 | break; |
| 1973 | case STA_STATS_RATE_TYPE_LEGACY: { | ||
| 1971 | struct ieee80211_supported_band *sband; | 1974 | struct ieee80211_supported_band *sband; |
| 1972 | u16 brate; | 1975 | u16 brate; |
| 1973 | unsigned int shift; | 1976 | unsigned int shift; |
| @@ -1982,6 +1985,8 @@ static void sta_stats_decode_rate(struct ieee80211_local *local, u16 rate, · 8 unmodified lines | |||
| 1982 | else | 1985 | else |
| 1983 | shift = 0; | 1986 | shift = 0; |
| 1984 | rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); | 1987 | rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift); |
| 1988 | break; | ||
| 1989 | } | ||
| 1985 | } | 1990 | } |
| 1986 | 1991 | ||
| 1987 | if (rate & STA_STATS_RATE_SGI) | 1992 | if (rate & STA_STATS_RATE_SGI) |
| @@ -324,6 +324,9 @@ struct ieee80211_fast_rx { · 323 unmodified lines | |||
| 324 | struct rcu_head rcu_head; | 324 | struct rcu_head rcu_head; |
| 325 | }; | 325 | }; |
| 326 | 326 | ||
| 327 | /* we use only values in the range 0-100, so pick a large precision */ | ||
| 328 | DECLARE_EWMA(mesh_fail_avg, 20, 8) | ||
| 329 | |||
| 327 | /** | 330 | /** |
| 328 | * struct mesh_sta - mesh STA information | 331 | * struct mesh_sta - mesh STA information |
| 329 | * @plink_lock: serialize access to plink fields | 332 | * @plink_lock: serialize access to plink fields |
| @@ -369,7 +372,7 @@ struct mesh_sta { · 39 unmodified lines | |||
| 369 | enum nl80211_mesh_power_mode nonpeer_pm; | 372 | enum nl80211_mesh_power_mode nonpeer_pm; |
| 370 | 373 | ||
| 371 | /* moving percentage of failed MSDUs */ | 374 | /* moving percentage of failed MSDUs */ |
| 372 | unsigned int fail_avg; | 375 | struct ewma_mesh_fail_avg fail_avg; |
| 373 | }; | 376 | }; |
| 374 | 377 | ||
| 375 | DECLARE_EWMA(signal, 10, 8) | 378 | DECLARE_EWMA(signal, 10, 8) |
| @@ -725,9 +728,10 @@ void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); · 349 unmodified lines | |||
| 725 | unsigned long ieee80211_sta_last_active(struct sta_info *sta); | 728 | unsigned long ieee80211_sta_last_active(struct sta_info *sta); |
| 726 | 729 | ||
| 727 | #define STA_STATS_RATE_INVALID 0 | 730 | #define STA_STATS_RATE_INVALID 0 |
| 728 | #define STA_STATS_RATE_VHT 0x8000 | 731 | #define STA_STATS_RATE_TYPE_MASK 0xC000 |
| 729 | #define STA_STATS_RATE_HT 0x4000 | 732 | #define STA_STATS_RATE_TYPE_LEGACY 0x4000 |
| 730 | #define STA_STATS_RATE_LEGACY 0x2000 | 733 | #define STA_STATS_RATE_TYPE_HT 0x8000 |
| 734 | #define STA_STATS_RATE_TYPE_VHT 0xC000 | ||
| 731 | #define STA_STATS_RATE_SGI 0x1000 | 735 | #define STA_STATS_RATE_SGI 0x1000 |
| 732 | #define STA_STATS_RATE_BW_SHIFT 9 | 736 | #define STA_STATS_RATE_BW_SHIFT 9 |
| 733 | #define STA_STATS_RATE_BW_MASK (0x7 << STA_STATS_RATE_BW_SHIFT) | 737 | #define STA_STATS_RATE_BW_MASK (0x7 << STA_STATS_RATE_BW_SHIFT) |
| @@ -753,11 +757,11 @@ static inline u16 sta_stats_encode_rate(struct ieee80211_rx_status *s) · 19 unmodified lines | |||
| 753 | r |= STA_STATS_RATE_SGI; | 757 | r |= STA_STATS_RATE_SGI; |
| 754 | 758 | ||
| 755 | if (s->flag & RX_FLAG_VHT) | 759 | if (s->flag & RX_FLAG_VHT) |
| 756 | r |= STA_STATS_RATE_VHT | (s->vht_nss << 4); | 760 | r |= STA_STATS_RATE_TYPE_VHT | (s->vht_nss << 4); |
| 757 | else if (s->flag & RX_FLAG_HT) | 761 | else if (s->flag & RX_FLAG_HT) |
| 758 | r |= STA_STATS_RATE_HT; | 762 | r |= STA_STATS_RATE_TYPE_HT; |
| 759 | else | 763 | else |
| 760 | r |= STA_STATS_RATE_LEGACY | (s->band << 4); | 764 | r |= STA_STATS_RATE_TYPE_LEGACY | (s->band << 4); |
| 761 | 765 | ||
| 762 | return r; | 766 | return r; |
| 763 | } | 767 | } |
| @@ -682,10 +682,6 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) · 681 unmodified lines | |||
| 682 | txrc.skb = tx->skb; | 682 | txrc.skb = tx->skb; |
| 683 | txrc.reported_rate.idx = -1; | 683 | txrc.reported_rate.idx = -1; |
| 684 | txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band]; | 684 | txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band]; |
| 685 | if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1) | ||
| 686 | txrc.max_rate_idx = -1; | ||
| 687 | else | ||
| 688 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | ||
| 689 | 685 | ||
| 690 | if (tx->sdata->rc_has_mcs_mask[info->band]) | 686 | if (tx->sdata->rc_has_mcs_mask[info->band]) |
| 691 | txrc.rate_idx_mcs_mask = | 687 | txrc.rate_idx_mcs_mask = |
| @@ -4249,10 +4245,6 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, · 3557 unmodified lines | |||
| 4249 | txrc.skb = skb; | 4245 | txrc.skb = skb; |
| 4250 | txrc.reported_rate.idx = -1; | 4246 | txrc.reported_rate.idx = -1; |
| 4251 | txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; | 4247 | txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; |
| 4252 | if (txrc.rate_idx_mask == (1 << txrc.sband->n_bitrates) - 1) | ||
| 4253 | txrc.max_rate_idx = -1; | ||
| 4254 | else | ||
| 4255 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | ||
| 4256 | txrc.bss = true; | 4248 | txrc.bss = true; |
| 4257 | rate_control_get_rate(sdata, NULL, &txrc); | 4249 | rate_control_get_rate(sdata, NULL, &txrc); |
| 4258 | 4250 | ||
| @@ -2413,13 +2413,13 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, · 2412 unmodified lines | |||
| 2413 | *pos++ = WLAN_EID_VHT_OPERATION; | 2413 | *pos++ = WLAN_EID_VHT_OPERATION; |
| 2414 | *pos++ = sizeof(struct ieee80211_vht_operation); | 2414 | *pos++ = sizeof(struct ieee80211_vht_operation); |
| 2415 | vht_oper = (struct ieee80211_vht_operation *)pos; | 2415 | vht_oper = (struct ieee80211_vht_operation *)pos; |
| 2416 | vht_oper->center_freq_seg1_idx = ieee80211_frequency_to_channel( | 2416 | vht_oper->center_freq_seg0_idx = ieee80211_frequency_to_channel( |
| 2417 | chandef->center_freq1); | 2417 | chandef->center_freq1); |
| 2418 | if (chandef->center_freq2) | 2418 | if (chandef->center_freq2) |
| 2419 | vht_oper->center_freq_seg2_idx = | 2419 | vht_oper->center_freq_seg1_idx = |
| 2420 | ieee80211_frequency_to_channel(chandef->center_freq2); | 2420 | ieee80211_frequency_to_channel(chandef->center_freq2); |
| 2421 | else | 2421 | else |
| 2422 | vht_oper->center_freq_seg2_idx = 0x00; | 2422 | vht_oper->center_freq_seg1_idx = 0x00; |
| 2423 | 2423 | ||
| 2424 | switch (chandef->width) { | 2424 | switch (chandef->width) { |
| 2425 | case NL80211_CHAN_WIDTH_160: | 2425 | case NL80211_CHAN_WIDTH_160: |
| @@ -2428,11 +2428,11 @@ u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, · 2 unmodified lines | |||
| 2428 | * workaround. | 2428 | * workaround. |
| 2429 | */ | 2429 | */ |
| 2430 | vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; | 2430 | vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; |
| 2431 | vht_oper->center_freq_seg2_idx = vht_oper->center_freq_seg1_idx; | 2431 | vht_oper->center_freq_seg1_idx = vht_oper->center_freq_seg0_idx; |
| 2432 | if (chandef->chan->center_freq < chandef->center_freq1) | 2432 | if (chandef->chan->center_freq < chandef->center_freq1) |
| 2433 | vht_oper->center_freq_seg1_idx -= 8; | 2433 | vht_oper->center_freq_seg0_idx -= 8; |
| 2434 | else | 2434 | else |
| 2435 | vht_oper->center_freq_seg1_idx += 8; | 2435 | vht_oper->center_freq_seg0_idx += 8; |
| 2436 | break; | 2436 | break; |
| 2437 | case NL80211_CHAN_WIDTH_80P80: | 2437 | case NL80211_CHAN_WIDTH_80P80: |
| 2438 | /* | 2438 | /* |
| @@ -2491,9 +2491,9 @@ bool ieee80211_chandef_vht_oper(const struct ieee80211_vht_operation *oper, · 52 unmodified lines | |||
| 2491 | if (!oper) | 2491 | if (!oper) |
| 2492 | return false; | 2492 | return false; |
| 2493 | 2493 | ||
| 2494 | cf1 = ieee80211_channel_to_frequency(oper->center_freq_seg1_idx, | 2494 | cf1 = ieee80211_channel_to_frequency(oper->center_freq_seg0_idx, |
| 2495 | chandef->chan->band); | 2495 | chandef->chan->band); |
| 2496 | cf2 = ieee80211_channel_to_frequency(oper->center_freq_seg2_idx, | 2496 | cf2 = ieee80211_channel_to_frequency(oper->center_freq_seg1_idx, |
| 2497 | chandef->chan->band); | 2497 | chandef->chan->band); |
| 2498 | 2498 | ||
| 2499 | switch (oper->chan_width) { | 2499 | switch (oper->chan_width) { |
| @@ -2503,11 +2503,11 @@ bool ieee80211_chandef_vht_oper(const struct ieee80211_vht_operation *oper, · 3 unmodified lines | |||
| 2503 | new.width = NL80211_CHAN_WIDTH_80; | 2503 | new.width = NL80211_CHAN_WIDTH_80; |
| 2504 | new.center_freq1 = cf1; | 2504 | new.center_freq1 = cf1; |
| 2505 | /* If needed, adjust based on the newer interop workaround. */ | 2505 | /* If needed, adjust based on the newer interop workaround. */ |
| 2506 | if (oper->center_freq_seg2_idx) { | 2506 | if (oper->center_freq_seg1_idx) { |
| 2507 | unsigned int diff; | 2507 | unsigned int diff; |
| 2508 | 2508 | ||
| 2509 | diff = abs(oper->center_freq_seg2_idx - | 2509 | diff = abs(oper->center_freq_seg1_idx - |
| 2510 | oper->center_freq_seg1_idx); | 2510 | oper->center_freq_seg0_idx); |
| 2511 | if (diff == 8) { | 2511 | if (diff == 8) { |
| 2512 | new.width = NL80211_CHAN_WIDTH_160; | 2512 | new.width = NL80211_CHAN_WIDTH_160; |
| 2513 | new.center_freq1 = cf2; | 2513 | new.center_freq1 = cf2; |
| @@ -32,6 +32,11 @@ int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, · 31 unmodified lines | |||
| 32 | rdev_set_qos_map(rdev, dev, NULL); | 32 | rdev_set_qos_map(rdev, dev, NULL); |
| 33 | if (notify) | 33 | if (notify) |
| 34 | nl80211_send_ap_stopped(wdev); | 34 | nl80211_send_ap_stopped(wdev); |
| 35 | |||
| 36 | /* Should we apply the grace period during beaconing interface | ||
| 37 | * shutdown also? | ||
| 38 | */ | ||
| 39 | cfg80211_sched_dfs_chan_update(rdev); | ||
| 35 | } | 40 | } |
| 36 | 41 | ||
| 37 | return err; | 42 | return err; |
| @@ -456,6 +456,123 @@ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy, · 455 unmodified lines | |||
| 456 | return (r1 + r2 > 0); | 456 | return (r1 + r2 > 0); |
| 457 | } | 457 | } |
| 458 | 458 | ||
| 459 | /* | ||
| 460 | * Checks if center frequency of chan falls with in the bandwidth | ||
| 461 | * range of chandef. | ||
| 462 | */ | ||
| 463 | bool cfg80211_is_sub_chan(struct cfg80211_chan_def *chandef, | ||
| 464 | struct ieee80211_channel *chan) | ||
| 465 | { | ||
| 466 | int width; | ||
| 467 | u32 cf_offset, freq; | ||
| 468 | |||
| 469 | if (chandef->chan->center_freq == chan->center_freq) | ||
| 470 | return true; | ||
| 471 | |||
| 472 | width = cfg80211_chandef_get_width(chandef); | ||
| 473 | if (width <= 20) | ||
| 474 | return false; | ||
| 475 | |||
| 476 | cf_offset = width / 2 - 10; | ||
| 477 | |||
| 478 | for (freq = chandef->center_freq1 - width / 2 + 10; | ||
| 479 | freq <= chandef->center_freq1 + width / 2 - 10; freq += 20) { | ||
| 480 | if (chan->center_freq == freq) | ||
| 481 | return true; | ||
| 482 | } | ||
| 483 | |||
| 484 | if (!chandef->center_freq2) | ||
| 485 | return false; | ||
| 486 | |||
| 487 | for (freq = chandef->center_freq2 - width / 2 + 10; | ||
| 488 | freq <= chandef->center_freq2 + width / 2 - 10; freq += 20) { | ||
| 489 | if (chan->center_freq == freq) | ||
| 490 | return true; | ||
| 491 | } | ||
| 492 | |||
| 493 | return false; | ||
| 494 | } | ||
| 495 | |||
| 496 | bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev) | ||
| 497 | { | ||
| 498 | bool active = false; | ||
| 499 | |||
| 500 | ASSERT_WDEV_LOCK(wdev); | ||
| 501 | |||
| 502 | if (!wdev->chandef.chan) | ||
| 503 | return false; | ||
| 504 | |||
| 505 | switch (wdev->iftype) { | ||
| 506 | case NL80211_IFTYPE_AP: | ||
| 507 | case NL80211_IFTYPE_P2P_GO: | ||
| 508 | active = wdev->beacon_interval != 0; | ||
| 509 | break; | ||
| 510 | case NL80211_IFTYPE_ADHOC: | ||
| 511 | active = wdev->ssid_len != 0; | ||
| 512 | break; | ||
| 513 | case NL80211_IFTYPE_MESH_POINT: | ||
| 514 | active = wdev->mesh_id_len != 0; | ||
| 515 | break; | ||
| 516 | case NL80211_IFTYPE_STATION: | ||
| 517 | case NL80211_IFTYPE_OCB: | ||
| 518 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 519 | case NL80211_IFTYPE_MONITOR: | ||
| 520 | case NL80211_IFTYPE_AP_VLAN: | ||
| 521 | case NL80211_IFTYPE_WDS: | ||
| 522 | case NL80211_IFTYPE_P2P_DEVICE: | ||
| 523 | /* Can NAN type be considered as beaconing interface? */ | ||
| 524 | case NL80211_IFTYPE_NAN: | ||
| 525 | break; | ||
| 526 | case NL80211_IFTYPE_UNSPECIFIED: | ||
| 527 | case NUM_NL80211_IFTYPES: | ||
| 528 | WARN_ON(1); | ||
| 529 | } | ||
| 530 | |||
| 531 | return active; | ||
| 532 | } | ||
| 533 | |||
| 534 | static bool cfg80211_is_wiphy_oper_chan(struct wiphy *wiphy, | ||
| 535 | struct ieee80211_channel *chan) | ||
| 536 | { | ||
| 537 | struct wireless_dev *wdev; | ||
| 538 | |||
| 539 | list_for_each_entry(wdev, &wiphy->wdev_list, list) { | ||
| 540 | wdev_lock(wdev); | ||
| 541 | if (!cfg80211_beaconing_iface_active(wdev)) { | ||
| 542 | wdev_unlock(wdev); | ||
| 543 | continue; | ||
| 544 | } | ||
| 545 | |||
| 546 | if (cfg80211_is_sub_chan(&wdev->chandef, chan)) { | ||
| 547 | wdev_unlock(wdev); | ||
| 548 | return true; | ||
| 549 | } | ||
| 550 | wdev_unlock(wdev); | ||
| 551 | } | ||
| 552 | |||
| 553 | return false; | ||
| 554 | } | ||
| 555 | |||
| 556 | bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, | ||
| 557 | struct ieee80211_channel *chan) | ||
| 558 | { | ||
| 559 | struct cfg80211_registered_device *rdev; | ||
| 560 | |||
| 561 | ASSERT_RTNL(); | ||
| 562 | |||
| 563 | if (!(chan->flags & IEEE80211_CHAN_RADAR)) | ||
| 564 | return false; | ||
| 565 | |||
| 566 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | ||
| 567 | if (!reg_dfs_domain_same(wiphy, &rdev->wiphy)) | ||
| 568 | continue; | ||
| 569 | |||
| 570 | if (cfg80211_is_wiphy_oper_chan(&rdev->wiphy, chan)) | ||
| 571 | return true; | ||
| 572 | } | ||
| 573 | |||
| 574 | return false; | ||
| 575 | } | ||
| 459 | 576 | ||
| 460 | static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, | 577 | static bool cfg80211_get_chans_dfs_available(struct wiphy *wiphy, |
| 461 | u32 center_freq, | 578 | u32 center_freq, |
| @@ -357,6 +357,38 @@ static void cfg80211_sched_scan_stop_wk(struct work_struct *work) · 356 unmodified lines | |||
| 357 | rtnl_unlock(); | 357 | rtnl_unlock(); |
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | static void cfg80211_propagate_radar_detect_wk(struct work_struct *work) | ||
| 361 | { | ||
| 362 | struct cfg80211_registered_device *rdev; | ||
| 363 | |||
| 364 | rdev = container_of(work, struct cfg80211_registered_device, | ||
| 365 | propagate_radar_detect_wk); | ||
| 366 | |||
| 367 | rtnl_lock(); | ||
| 368 | |||
| 369 | regulatory_propagate_dfs_state(&rdev->wiphy, &rdev->radar_chandef, | ||
| 370 | NL80211_DFS_UNAVAILABLE, | ||
| 371 | NL80211_RADAR_DETECTED); | ||
| 372 | |||
| 373 | rtnl_unlock(); | ||
| 374 | } | ||
| 375 | |||
| 376 | static void cfg80211_propagate_cac_done_wk(struct work_struct *work) | ||
| 377 | { | ||
| 378 | struct cfg80211_registered_device *rdev; | ||
| 379 | |||
| 380 | rdev = container_of(work, struct cfg80211_registered_device, | ||
| 381 | propagate_cac_done_wk); | ||
| 382 | |||
| 383 | rtnl_lock(); | ||
| 384 | |||
| 385 | regulatory_propagate_dfs_state(&rdev->wiphy, &rdev->cac_done_chandef, | ||
| 386 | NL80211_DFS_AVAILABLE, | ||
| 387 | NL80211_RADAR_CAC_FINISHED); | ||
| 388 | |||
| 389 | rtnl_unlock(); | ||
| 390 | } | ||
| 391 | |||
| 360 | /* exported functions */ | 392 | /* exported functions */ |
| 361 | 393 | ||
| 362 | struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, | 394 | struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, |
| @@ -456,6 +488,9 @@ use_default_name: · 93 unmodified lines | |||
| 456 | spin_lock_init(&rdev->destroy_list_lock); | 488 | spin_lock_init(&rdev->destroy_list_lock); |
| 457 | INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk); | 489 | INIT_WORK(&rdev->destroy_work, cfg80211_destroy_iface_wk); |
| 458 | INIT_WORK(&rdev->sched_scan_stop_wk, cfg80211_sched_scan_stop_wk); | 490 | INIT_WORK(&rdev->sched_scan_stop_wk, cfg80211_sched_scan_stop_wk); |
| 491 | INIT_WORK(&rdev->propagate_radar_detect_wk, | ||
| 492 | cfg80211_propagate_radar_detect_wk); | ||
| 493 | INIT_WORK(&rdev->propagate_cac_done_wk, cfg80211_propagate_cac_done_wk); | ||
| 459 | 494 | ||
| 460 | #ifdef CONFIG_CFG80211_DEFAULT_PS | 495 | #ifdef CONFIG_CFG80211_DEFAULT_PS |
| 461 | rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; | 496 | rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; |
| @@ -915,6 +950,8 @@ void wiphy_unregister(struct wiphy *wiphy) · 453 unmodified lines | |||
| 915 | flush_work(&rdev->destroy_work); | 950 | flush_work(&rdev->destroy_work); |
| 916 | flush_work(&rdev->sched_scan_stop_wk); | 951 | flush_work(&rdev->sched_scan_stop_wk); |
| 917 | flush_work(&rdev->mlme_unreg_wk); | 952 | flush_work(&rdev->mlme_unreg_wk); |
| 953 | flush_work(&rdev->propagate_radar_detect_wk); | ||
| 954 | flush_work(&rdev->propagate_cac_done_wk); | ||
| 918 | 955 | ||
| 919 | #ifdef CONFIG_PM | 956 | #ifdef CONFIG_PM |
| 920 | if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) | 957 | if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) |
| @@ -954,6 +991,12 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked) · 33 unmodified lines | |||
| 954 | } | 991 | } |
| 955 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state); | 992 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state); |
| 956 | 993 | ||
| 994 | void cfg80211_cqm_config_free(struct wireless_dev *wdev) | ||
| 995 | { | ||
| 996 | kfree(wdev->cqm_config); | ||
| 997 | wdev->cqm_config = NULL; | ||
| 998 | } | ||
| 999 | |||
| 957 | void cfg80211_unregister_wdev(struct wireless_dev *wdev) | 1000 | void cfg80211_unregister_wdev(struct wireless_dev *wdev) |
| 958 | { | 1001 | { |
| 959 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | 1002 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); |
| @@ -980,6 +1023,8 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev) · 20 unmodified lines | |||
| 980 | WARN_ON_ONCE(1); | 1023 | WARN_ON_ONCE(1); |
| 981 | break; | 1024 | break; |
| 982 | } | 1025 | } |
| 1026 | |||
| 1027 | cfg80211_cqm_config_free(wdev); | ||
| 983 | } | 1028 | } |
| 984 | EXPORT_SYMBOL(cfg80211_unregister_wdev); | 1029 | EXPORT_SYMBOL(cfg80211_unregister_wdev); |
| 985 | 1030 | ||
| @@ -1114,7 +1159,15 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 128 unmodified lines | |||
| 1114 | INIT_LIST_HEAD(&wdev->mgmt_registrations); | 1159 | INIT_LIST_HEAD(&wdev->mgmt_registrations); |
| 1115 | spin_lock_init(&wdev->mgmt_registrations_lock); | 1160 | spin_lock_init(&wdev->mgmt_registrations_lock); |
| 1116 | 1161 | ||
| 1117 | wdev->identifier = ++rdev->wdev_id; | 1162 | /* |
| 1163 | * We get here also when the interface changes network namespaces, | ||
| 1164 | * as it's registered into the new one, but we don't want it to | ||
| 1165 | * change ID in that case. Checking if the ID is already assigned | ||
| 1166 | * works, because 0 isn't considered a valid ID and the memory is | ||
| 1167 | * 0-initialized. | ||
| 1168 | */ | ||
| 1169 | if (!wdev->identifier) | ||
| 1170 | wdev->identifier = ++rdev->wdev_id; | ||
| 1118 | list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list); | 1171 | list_add_rcu(&wdev->list, &rdev->wiphy.wdev_list); |
| 1119 | rdev->devlist_generation++; | 1172 | rdev->devlist_generation++; |
| 1120 | /* can only change netns with wiphy */ | 1173 | /* can only change netns with wiphy */ |
| @@ -1208,12 +1261,12 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 87 unmodified lines | |||
| 1208 | */ | 1261 | */ |
| 1209 | if ((wdev->iftype == NL80211_IFTYPE_STATION || | 1262 | if ((wdev->iftype == NL80211_IFTYPE_STATION || |
| 1210 | wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) && | 1263 | wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) && |
| 1211 | rdev->ops->set_power_mgmt) | 1264 | rdev->ops->set_power_mgmt && |
| 1212 | if (rdev_set_power_mgmt(rdev, dev, wdev->ps, | 1265 | rdev_set_power_mgmt(rdev, dev, wdev->ps, |
| 1213 | wdev->ps_timeout)) { | 1266 | wdev->ps_timeout)) { |
| 1214 | /* assume this means it's off */ | 1267 | /* assume this means it's off */ |
| 1215 | wdev->ps = false; | 1268 | wdev->ps = false; |
| 1216 | } | 1269 | } |
| 1217 | break; | 1270 | break; |
| 1218 | case NETDEV_UNREGISTER: | 1271 | case NETDEV_UNREGISTER: |
| 1219 | /* | 1272 | /* |
| @@ -1234,6 +1287,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, · 14 unmodified lines | |||
| 1234 | kzfree(wdev->wext.keys); | 1287 | kzfree(wdev->wext.keys); |
| 1235 | #endif | 1288 | #endif |
| 1236 | flush_work(&wdev->disconnect_wk); | 1289 | flush_work(&wdev->disconnect_wk); |
| 1290 | cfg80211_cqm_config_free(wdev); | ||
| 1237 | } | 1291 | } |
| 1238 | /* | 1292 | /* |
| 1239 | * synchronise (so that we won't find this netdev | 1293 | * synchronise (so that we won't find this netdev |
| @@ -97,6 +97,12 @@ struct cfg80211_registered_device { · 96 unmodified lines | |||
| 97 | 97 | ||
| 98 | struct work_struct sched_scan_stop_wk; | 98 | struct work_struct sched_scan_stop_wk; |
| 99 | 99 | ||
| 100 | struct cfg80211_chan_def radar_chandef; | ||
| 101 | struct work_struct propagate_radar_detect_wk; | ||
| 102 | |||
| 103 | struct cfg80211_chan_def cac_done_chandef; | ||
| 104 | struct work_struct propagate_cac_done_wk; | ||
| 105 | |||
| 100 | /* must be last because of the way we do wiphy_priv(), | 106 | /* must be last because of the way we do wiphy_priv(), |
| 101 | * and it should at least be aligned to NETDEV_ALIGN */ | 107 | * and it should at least be aligned to NETDEV_ALIGN */ |
| 102 | struct wiphy wiphy __aligned(NETDEV_ALIGN); | 108 | struct wiphy wiphy __aligned(NETDEV_ALIGN); |
| @@ -220,16 +226,7 @@ struct cfg80211_event { · 117 unmodified lines | |||
| 220 | enum cfg80211_event_type type; | 226 | enum cfg80211_event_type type; |
| 221 | 227 | ||
| 222 | union { | 228 | union { |
| 223 | struct { | 229 | struct cfg80211_connect_resp_params cr; |
| 224 | u8 bssid[ETH_ALEN]; | ||
| 225 | const u8 *req_ie; | ||
| 226 | const u8 *resp_ie; | ||
| 227 | size_t req_ie_len; | ||
| 228 | size_t resp_ie_len; | ||
| 229 | struct cfg80211_bss *bss; | ||
| 230 | int status; /* -1 = failed; 0..65535 = status code */ | ||
| 231 | enum nl80211_timeout_reason timeout_reason; | ||
| 232 | } cr; | ||
| 233 | struct { | 230 | struct { |
| 234 | const u8 *req_ie; | 231 | const u8 *req_ie; |
| 235 | const u8 *resp_ie; | 232 | const u8 *resp_ie; |
| @@ -272,6 +269,13 @@ struct cfg80211_iface_destroy { · 36 unmodified lines | |||
| 272 | u32 nlportid; | 269 | u32 nlportid; |
| 273 | }; | 270 | }; |
| 274 | 271 | ||
| 272 | struct cfg80211_cqm_config { | ||
| 273 | u32 rssi_hyst; | ||
| 274 | s32 last_rssi_event_value; | ||
| 275 | int n_rssi_thresholds; | ||
| 276 | s32 rssi_thresholds[0]; | ||
| 277 | }; | ||
| 278 | |||
| 275 | void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev); | 279 | void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev); |
| 276 | 280 | ||
| 277 | /* free object */ | 281 | /* free object */ |
| @@ -385,12 +389,9 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, · 107 unmodified lines | |||
| 385 | struct cfg80211_connect_params *connect, | 389 | struct cfg80211_connect_params *connect, |
| 386 | struct cfg80211_cached_keys *connkeys, | 390 | struct cfg80211_cached_keys *connkeys, |
| 387 | const u8 *prev_bssid); | 391 | const u8 *prev_bssid); |
| 388 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 392 | void __cfg80211_connect_result(struct net_device *dev, |
| 389 | const u8 *req_ie, size_t req_ie_len, | 393 | struct cfg80211_connect_resp_params *params, |
| 390 | const u8 *resp_ie, size_t resp_ie_len, | 394 | bool wextev); |
| 391 | int status, bool wextev, | ||
| 392 | struct cfg80211_bss *bss, | ||
| 393 | enum nl80211_timeout_reason timeout_reason); | ||
| 394 | void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, | 395 | void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, |
| 395 | size_t ie_len, u16 reason, bool from_ap); | 396 | size_t ie_len, u16 reason, bool from_ap); |
| 396 | int cfg80211_disconnect(struct cfg80211_registered_device *rdev, | 397 | int cfg80211_disconnect(struct cfg80211_registered_device *rdev, |
| @@ -429,7 +430,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, · 32 unmodified lines | |||
| 429 | void cfg80211_upload_connect_keys(struct wireless_dev *wdev); | 430 | void cfg80211_upload_connect_keys(struct wireless_dev *wdev); |
| 430 | int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | 431 | int cfg80211_change_iface(struct cfg80211_registered_device *rdev, |
| 431 | struct net_device *dev, enum nl80211_iftype ntype, | 432 | struct net_device *dev, enum nl80211_iftype ntype, |
| 432 | u32 *flags, struct vif_params *params); | 433 | struct vif_params *params); |
| 433 | void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); | 434 | void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); |
| 434 | void cfg80211_process_wdev_events(struct wireless_dev *wdev); | 435 | void cfg80211_process_wdev_events(struct wireless_dev *wdev); |
| 435 | 436 | ||
| @@ -459,6 +460,16 @@ unsigned int · 23 unmodified lines | |||
| 459 | cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, | 460 | cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, |
| 460 | const struct cfg80211_chan_def *chandef); | 461 | const struct cfg80211_chan_def *chandef); |
| 461 | 462 | ||
| 463 | void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev); | ||
| 464 | |||
| 465 | bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy, | ||
| 466 | struct ieee80211_channel *chan); | ||
| 467 | |||
| 468 | bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev); | ||
| 469 | |||
| 470 | bool cfg80211_is_sub_chan(struct cfg80211_chan_def *chandef, | ||
| 471 | struct ieee80211_channel *chan); | ||
| 472 | |||
| 462 | static inline unsigned int elapsed_jiffies_msecs(unsigned long start) | 473 | static inline unsigned int elapsed_jiffies_msecs(unsigned long start) |
| 463 | { | 474 | { |
| 464 | unsigned long end = jiffies; | 475 | unsigned long end = jiffies; |
| @@ -512,4 +523,6 @@ void cfg80211_stop_nan(struct cfg80211_registered_device *rdev, · 47 unmodified lines | |||
| 512 | #define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; }) | 523 | #define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; }) |
| 513 | #endif | 524 | #endif |
| 514 | 525 | ||
| 526 | void cfg80211_cqm_config_free(struct wireless_dev *wdev); | ||
| 527 | |||
| 515 | #endif /* __NET_WIRELESS_CORE_H */ | 528 | #endif /* __NET_WIRELESS_CORE_H */ |
| @@ -190,6 +190,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) · 189 unmodified lines | |||
| 190 | if (!nowext) | 190 | if (!nowext) |
| 191 | wdev->wext.ibss.ssid_len = 0; | 191 | wdev->wext.ibss.ssid_len = 0; |
| 192 | #endif | 192 | #endif |
| 193 | cfg80211_sched_dfs_chan_update(rdev); | ||
| 193 | } | 194 | } |
| 194 | 195 | ||
| 195 | void cfg80211_clear_ibss(struct net_device *dev, bool nowext) | 196 | void cfg80211_clear_ibss(struct net_device *dev, bool nowext) |
| @@ -262,6 +262,7 @@ int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, · 261 unmodified lines | |||
| 262 | wdev->beacon_interval = 0; | 262 | wdev->beacon_interval = 0; |
| 263 | memset(&wdev->chandef, 0, sizeof(wdev->chandef)); | 263 | memset(&wdev->chandef, 0, sizeof(wdev->chandef)); |
| 264 | rdev_set_qos_map(rdev, dev, NULL); | 264 | rdev_set_qos_map(rdev, dev, NULL); |
| 265 | cfg80211_sched_dfs_chan_update(rdev); | ||
| 265 | } | 266 | } |
| 266 | 267 | ||
| 267 | return err; | 268 | return err; |
| @@ -26,9 +26,16 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss, · 25 unmodified lines | |||
| 26 | struct wiphy *wiphy = wdev->wiphy; | 26 | struct wiphy *wiphy = wdev->wiphy; |
| 27 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); | 27 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); |
| 28 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; | 28 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)buf; |
| 29 | u8 *ie = mgmt->u.assoc_resp.variable; | 29 | struct cfg80211_connect_resp_params cr; |
| 30 | int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); | 30 | |
| 31 | u16 status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); | 31 | memset(&cr, 0, sizeof(cr)); |
| 32 | cr.status = (int)le16_to_cpu(mgmt->u.assoc_resp.status_code); | ||
| 33 | cr.bssid = mgmt->bssid; | ||
| 34 | cr.bss = bss; | ||
| 35 | cr.resp_ie = mgmt->u.assoc_resp.variable; | ||
| 36 | cr.resp_ie_len = | ||
| 37 | len - offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); | ||
| 38 | cr.timeout_reason = NL80211_TIMEOUT_UNSPECIFIED; | ||
| 32 | 39 | ||
| 33 | trace_cfg80211_send_rx_assoc(dev, bss); | 40 | trace_cfg80211_send_rx_assoc(dev, bss); |
| 34 | 41 | ||
| @@ -38,7 +45,7 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss, · 3 unmodified lines | |||
| 38 | * and got a reject -- we only try again with an assoc | 45 | * and got a reject -- we only try again with an assoc |
| 39 | * frame instead of reassoc. | 46 | * frame instead of reassoc. |
| 40 | */ | 47 | */ |
| 41 | if (cfg80211_sme_rx_assoc_resp(wdev, status_code)) { | 48 | if (cfg80211_sme_rx_assoc_resp(wdev, cr.status)) { |
| 42 | cfg80211_unhold_bss(bss_from_pub(bss)); | 49 | cfg80211_unhold_bss(bss_from_pub(bss)); |
| 43 | cfg80211_put_bss(wiphy, bss); | 50 | cfg80211_put_bss(wiphy, bss); |
| 44 | return; | 51 | return; |
| @@ -46,10 +53,7 @@ void cfg80211_rx_assoc_resp(struct net_device *dev, struct cfg80211_bss *bss, · 1 unmodified line | |||
| 46 | 53 | ||
| 47 | nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL, uapsd_queues); | 54 | nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL, uapsd_queues); |
| 48 | /* update current_bss etc., consumes the bss reference */ | 55 | /* update current_bss etc., consumes the bss reference */ |
| 49 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, | 56 | __cfg80211_connect_result(dev, &cr, cr.status == WLAN_STATUS_SUCCESS); |
| 50 | status_code, | ||
| 51 | status_code == WLAN_STATUS_SUCCESS, bss, | ||
| 52 | NL80211_TIMEOUT_UNSPECIFIED); | ||
| 53 | } | 57 | } |
| 54 | EXPORT_SYMBOL(cfg80211_rx_assoc_resp); | 58 | EXPORT_SYMBOL(cfg80211_rx_assoc_resp); |
| 55 | 59 | ||
| @@ -745,6 +749,12 @@ bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm, · 689 unmodified lines | |||
| 745 | } | 749 | } |
| 746 | EXPORT_SYMBOL(cfg80211_rx_mgmt); | 750 | EXPORT_SYMBOL(cfg80211_rx_mgmt); |
| 747 | 751 | ||
| 752 | void cfg80211_sched_dfs_chan_update(struct cfg80211_registered_device *rdev) | ||
| 753 | { | ||
| 754 | cancel_delayed_work(&rdev->dfs_update_channels_wk); | ||
| 755 | queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk, 0); | ||
| 756 | } | ||
| 757 | |||
| 748 | void cfg80211_dfs_channels_update_work(struct work_struct *work) | 758 | void cfg80211_dfs_channels_update_work(struct work_struct *work) |
| 749 | { | 759 | { |
| 750 | struct delayed_work *delayed_work = to_delayed_work(work); | 760 | struct delayed_work *delayed_work = to_delayed_work(work); |
| @@ -755,6 +765,8 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work) · 4 unmodified lines | |||
| 755 | struct wiphy *wiphy; | 765 | struct wiphy *wiphy; |
| 756 | bool check_again = false; | 766 | bool check_again = false; |
| 757 | unsigned long timeout, next_time = 0; | 767 | unsigned long timeout, next_time = 0; |
| 768 | unsigned long time_dfs_update; | ||
| 769 | enum nl80211_radar_event radar_event; | ||
| 758 | int bandid, i; | 770 | int bandid, i; |
| 759 | 771 | ||
| 760 | rdev = container_of(delayed_work, struct cfg80211_registered_device, | 772 | rdev = container_of(delayed_work, struct cfg80211_registered_device, |
| @@ -770,11 +782,27 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work) · 9 unmodified lines | |||
| 770 | for (i = 0; i < sband->n_channels; i++) { | 782 | for (i = 0; i < sband->n_channels; i++) { |
| 771 | c = &sband->channels[i]; | 783 | c = &sband->channels[i]; |
| 772 | 784 | ||
| 773 | if (c->dfs_state != NL80211_DFS_UNAVAILABLE) | 785 | if (!(c->flags & IEEE80211_CHAN_RADAR)) |
| 786 | continue; | ||
| 787 | |||
| 788 | if (c->dfs_state != NL80211_DFS_UNAVAILABLE && | ||
| 789 | c->dfs_state != NL80211_DFS_AVAILABLE) | ||
| 774 | continue; | 790 | continue; |
| 775 | 791 | ||
| 776 | timeout = c->dfs_state_entered + msecs_to_jiffies( | 792 | if (c->dfs_state == NL80211_DFS_UNAVAILABLE) { |
| 777 | IEEE80211_DFS_MIN_NOP_TIME_MS); | 793 | time_dfs_update = IEEE80211_DFS_MIN_NOP_TIME_MS; |
| 794 | radar_event = NL80211_RADAR_NOP_FINISHED; | ||
| 795 | } else { | ||
| 796 | if (regulatory_pre_cac_allowed(wiphy) || | ||
| 797 | cfg80211_any_wiphy_oper_chan(wiphy, c)) | ||
| 798 | continue; | ||
| 799 | |||
| 800 | time_dfs_update = REG_PRE_CAC_EXPIRY_GRACE_MS; | ||
| 801 | radar_event = NL80211_RADAR_PRE_CAC_EXPIRED; | ||
| 802 | } | ||
| 803 | |||
| 804 | timeout = c->dfs_state_entered + | ||
| 805 | msecs_to_jiffies(time_dfs_update); | ||
| 778 | 806 | ||
| 779 | if (time_after_eq(jiffies, timeout)) { | 807 | if (time_after_eq(jiffies, timeout)) { |
| 780 | c->dfs_state = NL80211_DFS_USABLE; | 808 | c->dfs_state = NL80211_DFS_USABLE; |
| @@ -784,8 +812,12 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work) · 3 unmodified lines | |||
| 784 | NL80211_CHAN_NO_HT); | 812 | NL80211_CHAN_NO_HT); |
| 785 | 813 | ||
| 786 | nl80211_radar_notify(rdev, &chandef, | 814 | nl80211_radar_notify(rdev, &chandef, |
| 787 | NL80211_RADAR_NOP_FINISHED, | 815 | radar_event, NULL, |
| 788 | NULL, GFP_ATOMIC); | 816 | GFP_ATOMIC); |
| 817 | |||
| 818 | regulatory_propagate_dfs_state(wiphy, &chandef, | ||
| 819 | c->dfs_state, | ||
| 820 | radar_event); | ||
| 789 | continue; | 821 | continue; |
| 790 | } | 822 | } |
| 791 | 823 | ||
| @@ -810,7 +842,6 @@ void cfg80211_radar_event(struct wiphy *wiphy, · 18 unmodified lines | |||
| 810 | gfp_t gfp) | 842 | gfp_t gfp) |
| 811 | { | 843 | { |
| 812 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); | 844 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); |
| 813 | unsigned long timeout; | ||
| 814 | 845 | ||
| 815 | trace_cfg80211_radar_event(wiphy, chandef); | 846 | trace_cfg80211_radar_event(wiphy, chandef); |
| 816 | 847 | ||
| @@ -820,11 +851,12 @@ void cfg80211_radar_event(struct wiphy *wiphy, · 3 unmodified lines | |||
| 820 | */ | 851 | */ |
| 821 | cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE); | 852 | cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_UNAVAILABLE); |
| 822 | 853 | ||
| 823 | timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_NOP_TIME_MS); | 854 | cfg80211_sched_dfs_chan_update(rdev); |
| 824 | queue_delayed_work(cfg80211_wq, &rdev->dfs_update_channels_wk, | ||
| 825 | timeout); | ||
| 826 | 855 | ||
| 827 | nl80211_radar_notify(rdev, chandef, NL80211_RADAR_DETECTED, NULL, gfp); | 856 | nl80211_radar_notify(rdev, chandef, NL80211_RADAR_DETECTED, NULL, gfp); |
| 857 | |||
| 858 | memcpy(&rdev->radar_chandef, chandef, sizeof(struct cfg80211_chan_def)); | ||
| 859 | queue_work(cfg80211_wq, &rdev->propagate_radar_detect_wk); | ||
| 828 | } | 860 | } |
| 829 | EXPORT_SYMBOL(cfg80211_radar_event); | 861 | EXPORT_SYMBOL(cfg80211_radar_event); |
| 830 | 862 | ||
| @@ -851,6 +883,10 @@ void cfg80211_cac_event(struct net_device *netdev, · 20 unmodified lines | |||
| 851 | msecs_to_jiffies(wdev->cac_time_ms); | 883 | msecs_to_jiffies(wdev->cac_time_ms); |
| 852 | WARN_ON(!time_after_eq(jiffies, timeout)); | 884 | WARN_ON(!time_after_eq(jiffies, timeout)); |
| 853 | cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); | 885 | cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); |
| 886 | memcpy(&rdev->cac_done_chandef, chandef, | ||
| 887 | sizeof(struct cfg80211_chan_def)); | ||
| 888 | queue_work(cfg80211_wq, &rdev->propagate_cac_done_wk); | ||
| 889 | cfg80211_sched_dfs_chan_update(rdev); | ||
| 854 | break; | 890 | break; |
| 855 | case NL80211_RADAR_CAC_ABORTED: | 891 | case NL80211_RADAR_CAC_ABORTED: |
| 856 | break; | 892 | break; |
| @@ -410,6 +410,15 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = { · 409 unmodified lines | |||
| 410 | .len = sizeof(struct nl80211_bss_select_rssi_adjust) | 410 | .len = sizeof(struct nl80211_bss_select_rssi_adjust) |
| 411 | }, | 411 | }, |
| 412 | [NL80211_ATTR_TIMEOUT_REASON] = { .type = NLA_U32 }, | 412 | [NL80211_ATTR_TIMEOUT_REASON] = { .type = NLA_U32 }, |
| 413 | [NL80211_ATTR_FILS_ERP_USERNAME] = { .type = NLA_BINARY, | ||
| 414 | .len = FILS_ERP_MAX_USERNAME_LEN }, | ||
| 415 | [NL80211_ATTR_FILS_ERP_REALM] = { .type = NLA_BINARY, | ||
| 416 | .len = FILS_ERP_MAX_REALM_LEN }, | ||
| 417 | [NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] = { .type = NLA_U16 }, | ||
| 418 | [NL80211_ATTR_FILS_ERP_RRK] = { .type = NLA_BINARY, | ||
| 419 | .len = FILS_ERP_MAX_RRK_LEN }, | ||
| 420 | [NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 }, | ||
| 421 | [NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN }, | ||
| 413 | }; | 422 | }; |
| 414 | 423 | ||
| 415 | /* policy for the key attributes */ | 424 | /* policy for the key attributes */ |
| @@ -2705,9 +2714,74 @@ static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags) · 2289 unmodified lines | |||
| 2705 | if (flags[flag]) | 2714 | if (flags[flag]) |
| 2706 | *mntrflags |= (1<<flag); | 2715 | *mntrflags |= (1<<flag); |
| 2707 | 2716 | ||
| 2717 | *mntrflags |= MONITOR_FLAG_CHANGED; | ||
| 2718 | |||
| 2708 | return 0; | 2719 | return 0; |
| 2709 | } | 2720 | } |
| 2710 | 2721 | ||
| 2722 | static int nl80211_parse_mon_options(struct cfg80211_registered_device *rdev, | ||
| 2723 | enum nl80211_iftype type, | ||
| 2724 | struct genl_info *info, | ||
| 2725 | struct vif_params *params) | ||
| 2726 | { | ||
| 2727 | bool change = false; | ||
| 2728 | int err; | ||
| 2729 | |||
| 2730 | if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { | ||
| 2731 | if (type != NL80211_IFTYPE_MONITOR) | ||
| 2732 | return -EINVAL; | ||
| 2733 | |||
| 2734 | err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], | ||
| 2735 | ¶ms->flags); | ||
| 2736 | if (err) | ||
| 2737 | return err; | ||
| 2738 | |||
| 2739 | change = true; | ||
| 2740 | } | ||
| 2741 | |||
| 2742 | if (params->flags & MONITOR_FLAG_ACTIVE && | ||
| 2743 | !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) | ||
| 2744 | return -EOPNOTSUPP; | ||
| 2745 | |||
| 2746 | if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) { | ||
| 2747 | const u8 *mumimo_groups; | ||
| 2748 | u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER; | ||
| 2749 | |||
| 2750 | if (type != NL80211_IFTYPE_MONITOR) | ||
| 2751 | return -EINVAL; | ||
| 2752 | |||
| 2753 | if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag)) | ||
| 2754 | return -EOPNOTSUPP; | ||
| 2755 | |||
| 2756 | mumimo_groups = | ||
| 2757 | nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]); | ||
| 2758 | |||
| 2759 | /* bits 0 and 63 are reserved and must be zero */ | ||
| 2760 | if ((mumimo_groups[0] & BIT(7)) || | ||
| 2761 | (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(0))) | ||
| 2762 | return -EINVAL; | ||
| 2763 | |||
| 2764 | params->vht_mumimo_groups = mumimo_groups; | ||
| 2765 | change = true; | ||
| 2766 | } | ||
| 2767 | |||
| 2768 | if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) { | ||
| 2769 | u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER; | ||
| 2770 | |||
| 2771 | if (type != NL80211_IFTYPE_MONITOR) | ||
| 2772 | return -EINVAL; | ||
| 2773 | |||
| 2774 | if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag)) | ||
| 2775 | return -EOPNOTSUPP; | ||
| 2776 | |||
| 2777 | params->vht_mumimo_follow_addr = | ||
| 2778 | nla_data(info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]); | ||
| 2779 | change = true; | ||
| 2780 | } | ||
| 2781 | |||
| 2782 | return change ? 1 : 0; | ||
| 2783 | } | ||
| 2784 | |||
| 2711 | static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev, | 2785 | static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev, |
| 2712 | struct net_device *netdev, u8 use_4addr, | 2786 | struct net_device *netdev, u8 use_4addr, |
| 2713 | enum nl80211_iftype iftype) | 2787 | enum nl80211_iftype iftype) |
| @@ -2741,7 +2815,6 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) · 27 unmodified lines | |||
| 2741 | int err; | 2815 | int err; |
| 2742 | enum nl80211_iftype otype, ntype; | 2816 | enum nl80211_iftype otype, ntype; |
| 2743 | struct net_device *dev = info->user_ptr[1]; | 2817 | struct net_device *dev = info->user_ptr[1]; |
| 2744 | u32 _flags, *flags = NULL; | ||
| 2745 | bool change = false; | 2818 | bool change = false; |
| 2746 | 2819 | ||
| 2747 | memset(¶ms, 0, sizeof(params)); | 2820 | memset(¶ms, 0, sizeof(params)); |
| @@ -2784,56 +2857,14 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) · 36 unmodified lines | |||
| 2784 | params.use_4addr = -1; | 2857 | params.use_4addr = -1; |
| 2785 | } | 2858 | } |
| 2786 | 2859 | ||
| 2787 | if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { | 2860 | err = nl80211_parse_mon_options(rdev, ntype, info, ¶ms); |
| 2788 | if (ntype != NL80211_IFTYPE_MONITOR) | 2861 | if (err < 0) |
| 2789 | return -EINVAL; | 2862 | return err; |
| 2790 | err = parse_monitor_flags(info->attrs[NL80211_ATTR_MNTR_FLAGS], | 2863 | if (err > 0) |
| 2791 | &_flags); | ||
| 2792 | if (err) | ||
| 2793 | return err; | ||
| 2794 | |||
| 2795 | flags = &_flags; | ||
| 2796 | change = true; | ||
| 2797 | } | ||
| 2798 | |||
| 2799 | if (info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]) { | ||
| 2800 | const u8 *mumimo_groups; | ||
| 2801 | u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER; | ||
| 2802 | |||
| 2803 | if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag)) | ||
| 2804 | return -EOPNOTSUPP; | ||
| 2805 | |||
| 2806 | mumimo_groups = | ||
| 2807 | nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]); | ||
| 2808 | |||
| 2809 | /* bits 0 and 63 are reserved and must be zero */ | ||
| 2810 | if ((mumimo_groups[0] & BIT(7)) || | ||
| 2811 | (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(0))) | ||
| 2812 | return -EINVAL; | ||
| 2813 | |||
| 2814 | memcpy(params.vht_mumimo_groups, mumimo_groups, | ||
| 2815 | VHT_MUMIMO_GROUPS_DATA_LEN); | ||
| 2816 | change = true; | ||
| 2817 | } | ||
| 2818 | |||
| 2819 | if (info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR]) { | ||
| 2820 | u32 cap_flag = NL80211_EXT_FEATURE_MU_MIMO_AIR_SNIFFER; | ||
| 2821 | |||
| 2822 | if (!wiphy_ext_feature_isset(&rdev->wiphy, cap_flag)) | ||
| 2823 | return -EOPNOTSUPP; | ||
| 2824 | |||
| 2825 | nla_memcpy(params.macaddr, | ||
| 2826 | info->attrs[NL80211_ATTR_MU_MIMO_FOLLOW_MAC_ADDR], | ||
| 2827 | ETH_ALEN); | ||
| 2828 | change = true; | 2864 | change = true; |
| 2829 | } | ||
| 2830 | |||
| 2831 | if (flags && (*flags & MONITOR_FLAG_ACTIVE) && | ||
| 2832 | !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) | ||
| 2833 | return -EOPNOTSUPP; | ||
| 2834 | 2865 | ||
| 2835 | if (change) | 2866 | if (change) |
| 2836 | err = cfg80211_change_iface(rdev, dev, ntype, flags, ¶ms); | 2867 | err = cfg80211_change_iface(rdev, dev, ntype, ¶ms); |
| 2837 | else | 2868 | else |
| 2838 | err = 0; | 2869 | err = 0; |
| 2839 | 2870 | ||
| @@ -2851,7 +2882,6 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) · 11 unmodified lines | |||
| 2851 | struct sk_buff *msg; | 2882 | struct sk_buff *msg; |
| 2852 | int err; | 2883 | int err; |
| 2853 | enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; | 2884 | enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; |
| 2854 | u32 flags; | ||
| 2855 | 2885 | ||
| 2856 | /* to avoid failing a new interface creation due to pending removal */ | 2886 | /* to avoid failing a new interface creation due to pending removal */ |
| 2857 | cfg80211_destroy_ifaces(rdev); | 2887 | cfg80211_destroy_ifaces(rdev); |
| @@ -2887,13 +2917,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) · 29 unmodified lines | |||
| 2887 | return err; | 2917 | return err; |
| 2888 | } | 2918 | } |
| 2889 | 2919 | ||
| 2890 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? | 2920 | err = nl80211_parse_mon_options(rdev, type, info, ¶ms); |
| 2891 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, | 2921 | if (err < 0) |
| 2892 | &flags); | 2922 | return err; |
| 2893 | |||
| 2894 | if (!err && (flags & MONITOR_FLAG_ACTIVE) && | ||
| 2895 | !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR)) | ||
| 2896 | return -EOPNOTSUPP; | ||
| 2897 | 2923 | ||
| 2898 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 2924 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
| 2899 | if (!msg) | 2925 | if (!msg) |
| @@ -2901,8 +2927,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) · 1 unmodified line | |||
| 2901 | 2927 | ||
| 2902 | wdev = rdev_add_virtual_intf(rdev, | 2928 | wdev = rdev_add_virtual_intf(rdev, |
| 2903 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), | 2929 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), |
| 2904 | NET_NAME_USER, type, err ? NULL : &flags, | 2930 | NET_NAME_USER, type, ¶ms); |
| 2905 | ¶ms); | ||
| 2906 | if (WARN_ON(!wdev)) { | 2931 | if (WARN_ON(!wdev)) { |
| 2907 | nlmsg_free(msg); | 2932 | nlmsg_free(msg); |
| 2908 | return -EPROTO; | 2933 | return -EPROTO; |
| @@ -3820,6 +3845,19 @@ static bool nl80211_valid_auth_type(struct cfg80211_registered_device *rdev, · 911 unmodified lines | |||
| 3820 | return false; | 3845 | return false; |
| 3821 | return true; | 3846 | return true; |
| 3822 | case NL80211_CMD_CONNECT: | 3847 | case NL80211_CMD_CONNECT: |
| 3848 | /* SAE not supported yet */ | ||
| 3849 | if (auth_type == NL80211_AUTHTYPE_SAE) | ||
| 3850 | return false; | ||
| 3851 | /* FILS with SK PFS or PK not supported yet */ | ||
| 3852 | if (auth_type == NL80211_AUTHTYPE_FILS_SK_PFS || | ||
| 3853 | auth_type == NL80211_AUTHTYPE_FILS_PK) | ||
| 3854 | return false; | ||
| 3855 | if (!wiphy_ext_feature_isset( | ||
| 3856 | &rdev->wiphy, | ||
| 3857 | NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) && | ||
| 3858 | auth_type == NL80211_AUTHTYPE_FILS_SK) | ||
| 3859 | return false; | ||
| 3860 | return true; | ||
| 3823 | case NL80211_CMD_START_AP: | 3861 | case NL80211_CMD_START_AP: |
| 3824 | /* SAE not supported yet */ | 3862 | /* SAE not supported yet */ |
| 3825 | if (auth_type == NL80211_AUTHTYPE_SAE) | 3863 | if (auth_type == NL80211_AUTHTYPE_SAE) |
| @@ -4153,7 +4191,7 @@ static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info, · 327 unmodified lines | |||
| 4153 | struct nlattr *rate; | 4191 | struct nlattr *rate; |
| 4154 | u32 bitrate; | 4192 | u32 bitrate; |
| 4155 | u16 bitrate_compat; | 4193 | u16 bitrate_compat; |
| 4156 | enum nl80211_attrs rate_flg; | 4194 | enum nl80211_rate_info rate_flg; |
| 4157 | 4195 | ||
| 4158 | rate = nla_nest_start(msg, attr); | 4196 | rate = nla_nest_start(msg, attr); |
| 4159 | if (!rate) | 4197 | if (!rate) |
| @@ -5705,7 +5743,7 @@ static int nl80211_get_mesh_config(struct sk_buff *skb, · 1545 unmodified lines | |||
| 5705 | cur_params.dot11MeshGateAnnouncementProtocol) || | 5743 | cur_params.dot11MeshGateAnnouncementProtocol) || |
| 5706 | nla_put_u8(msg, NL80211_MESHCONF_FORWARDING, | 5744 | nla_put_u8(msg, NL80211_MESHCONF_FORWARDING, |
| 5707 | cur_params.dot11MeshForwarding) || | 5745 | cur_params.dot11MeshForwarding) || |
| 5708 | nla_put_u32(msg, NL80211_MESHCONF_RSSI_THRESHOLD, | 5746 | nla_put_s32(msg, NL80211_MESHCONF_RSSI_THRESHOLD, |
| 5709 | cur_params.rssi_threshold) || | 5747 | cur_params.rssi_threshold) || |
| 5710 | nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE, | 5748 | nla_put_u32(msg, NL80211_MESHCONF_HT_OPMODE, |
| 5711 | cur_params.ht_opmode) || | 5749 | cur_params.ht_opmode) || |
| @@ -6548,6 +6586,19 @@ static int nl80211_parse_random_mac(struct nlattr **attrs, · 836 unmodified lines | |||
| 6548 | return 0; | 6586 | return 0; |
| 6549 | } | 6587 | } |
| 6550 | 6588 | ||
| 6589 | static bool cfg80211_off_channel_oper_allowed(struct wireless_dev *wdev) | ||
| 6590 | { | ||
| 6591 | ASSERT_WDEV_LOCK(wdev); | ||
| 6592 | |||
| 6593 | if (!cfg80211_beaconing_iface_active(wdev)) | ||
| 6594 | return true; | ||
| 6595 | |||
| 6596 | if (!(wdev->chandef.chan->flags & IEEE80211_CHAN_RADAR)) | ||
| 6597 | return true; | ||
| 6598 | |||
| 6599 | return regulatory_pre_cac_allowed(wdev->wiphy); | ||
| 6600 | } | ||
| 6601 | |||
| 6551 | static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | 6602 | static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) |
| 6552 | { | 6603 | { |
| 6553 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 6604 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| @@ -6673,6 +6724,25 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) · 119 unmodified lines | |||
| 6673 | 6724 | ||
| 6674 | request->n_channels = i; | 6725 | request->n_channels = i; |
| 6675 | 6726 | ||
| 6727 | wdev_lock(wdev); | ||
| 6728 | if (!cfg80211_off_channel_oper_allowed(wdev)) { | ||
| 6729 | struct ieee80211_channel *chan; | ||
| 6730 | |||
| 6731 | if (request->n_channels != 1) { | ||
| 6732 | wdev_unlock(wdev); | ||
| 6733 | err = -EBUSY; | ||
| 6734 | goto out_free; | ||
| 6735 | } | ||
| 6736 | |||
| 6737 | chan = request->channels[0]; | ||
| 6738 | if (chan->center_freq != wdev->chandef.chan->center_freq) { | ||
| 6739 | wdev_unlock(wdev); | ||
| 6740 | err = -EBUSY; | ||
| 6741 | goto out_free; | ||
| 6742 | } | ||
| 6743 | } | ||
| 6744 | wdev_unlock(wdev); | ||
| 6745 | |||
| 6676 | i = 0; | 6746 | i = 0; |
| 6677 | if (n_ssids) { | 6747 | if (n_ssids) { |
| 6678 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { | 6748 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { |
| @@ -7295,8 +7365,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, · 616 unmodified lines | |||
| 7295 | 7365 | ||
| 7296 | rcu_assign_pointer(rdev->sched_scan_req, sched_scan_req); | 7366 | rcu_assign_pointer(rdev->sched_scan_req, sched_scan_req); |
| 7297 | 7367 | ||
| 7298 | nl80211_send_sched_scan(rdev, dev, | 7368 | nl80211_send_sched_scan(sched_scan_req, NL80211_CMD_START_SCHED_SCAN); |
| 7299 | NL80211_CMD_START_SCHED_SCAN); | ||
| 7300 | return 0; | 7369 | return 0; |
| 7301 | 7370 | ||
| 7302 | out_free: | 7371 | out_free: |
| @@ -8873,6 +8942,35 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) · 1570 unmodified lines | |||
| 8873 | } | 8942 | } |
| 8874 | } | 8943 | } |
| 8875 | 8944 | ||
| 8945 | if (wiphy_ext_feature_isset(&rdev->wiphy, | ||
| 8946 | NL80211_EXT_FEATURE_FILS_SK_OFFLOAD) && | ||
| 8947 | info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] && | ||
| 8948 | info->attrs[NL80211_ATTR_FILS_ERP_REALM] && | ||
| 8949 | info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] && | ||
| 8950 | info->attrs[NL80211_ATTR_FILS_ERP_RRK]) { | ||
| 8951 | connect.fils_erp_username = | ||
| 8952 | nla_data(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]); | ||
| 8953 | connect.fils_erp_username_len = | ||
| 8954 | nla_len(info->attrs[NL80211_ATTR_FILS_ERP_USERNAME]); | ||
| 8955 | connect.fils_erp_realm = | ||
| 8956 | nla_data(info->attrs[NL80211_ATTR_FILS_ERP_REALM]); | ||
| 8957 | connect.fils_erp_realm_len = | ||
| 8958 | nla_len(info->attrs[NL80211_ATTR_FILS_ERP_REALM]); | ||
| 8959 | connect.fils_erp_next_seq_num = | ||
| 8960 | nla_get_u16( | ||
| 8961 | info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM]); | ||
| 8962 | connect.fils_erp_rrk = | ||
| 8963 | nla_data(info->attrs[NL80211_ATTR_FILS_ERP_RRK]); | ||
| 8964 | connect.fils_erp_rrk_len = | ||
| 8965 | nla_len(info->attrs[NL80211_ATTR_FILS_ERP_RRK]); | ||
| 8966 | } else if (info->attrs[NL80211_ATTR_FILS_ERP_USERNAME] || | ||
| 8967 | info->attrs[NL80211_ATTR_FILS_ERP_REALM] || | ||
| 8968 | info->attrs[NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM] || | ||
| 8969 | info->attrs[NL80211_ATTR_FILS_ERP_RRK]) { | ||
| 8970 | kzfree(connkeys); | ||
| 8971 | return -EINVAL; | ||
| 8972 | } | ||
| 8973 | |||
| 8876 | wdev_lock(dev->ieee80211_ptr); | 8974 | wdev_lock(dev->ieee80211_ptr); |
| 8877 | 8975 | ||
| 8878 | err = cfg80211_connect(rdev, dev, &connect, connkeys, | 8976 | err = cfg80211_connect(rdev, dev, &connect, connkeys, |
| @@ -8992,14 +9090,28 @@ static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info) · 113 unmodified lines | |||
| 8992 | 9090 | ||
| 8993 | memset(&pmksa, 0, sizeof(struct cfg80211_pmksa)); | 9091 | memset(&pmksa, 0, sizeof(struct cfg80211_pmksa)); |
| 8994 | 9092 | ||
| 8995 | if (!info->attrs[NL80211_ATTR_MAC]) | ||
| 8996 | return -EINVAL; | ||
| 8997 | |||
| 8998 | if (!info->attrs[NL80211_ATTR_PMKID]) | 9093 | if (!info->attrs[NL80211_ATTR_PMKID]) |
| 8999 | return -EINVAL; | 9094 | return -EINVAL; |
| 9000 | 9095 | ||
| 9001 | pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]); | 9096 | pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]); |
| 9002 | pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 9097 | |
| 9098 | if (info->attrs[NL80211_ATTR_MAC]) { | ||
| 9099 | pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | ||
| 9100 | } else if (info->attrs[NL80211_ATTR_SSID] && | ||
| 9101 | info->attrs[NL80211_ATTR_FILS_CACHE_ID] && | ||
| 9102 | (info->genlhdr->cmd == NL80211_CMD_DEL_PMKSA || | ||
| 9103 | info->attrs[NL80211_ATTR_PMK])) { | ||
| 9104 | pmksa.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | ||
| 9105 | pmksa.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); | ||
| 9106 | pmksa.cache_id = | ||
| 9107 | nla_data(info->attrs[NL80211_ATTR_FILS_CACHE_ID]); | ||
| 9108 | } else { | ||
| 9109 | return -EINVAL; | ||
| 9110 | } | ||
| 9111 | if (info->attrs[NL80211_ATTR_PMK]) { | ||
| 9112 | pmksa.pmk = nla_data(info->attrs[NL80211_ATTR_PMK]); | ||
| 9113 | pmksa.pmk_len = nla_len(info->attrs[NL80211_ATTR_PMK]); | ||
| 9114 | } | ||
| 9003 | 9115 | ||
| 9004 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | 9116 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && |
| 9005 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) | 9117 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT) |
| @@ -9102,6 +9214,7 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, · 96 unmodified lines | |||
| 9102 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 9214 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| 9103 | struct wireless_dev *wdev = info->user_ptr[1]; | 9215 | struct wireless_dev *wdev = info->user_ptr[1]; |
| 9104 | struct cfg80211_chan_def chandef; | 9216 | struct cfg80211_chan_def chandef; |
| 9217 | const struct cfg80211_chan_def *compat_chandef; | ||
| 9105 | struct sk_buff *msg; | 9218 | struct sk_buff *msg; |
| 9106 | void *hdr; | 9219 | void *hdr; |
| 9107 | u64 cookie; | 9220 | u64 cookie; |
| @@ -9130,6 +9243,18 @@ static int nl80211_remain_on_channel(struct sk_buff *skb, · 22 unmodified lines | |||
| 9130 | if (err) | 9243 | if (err) |
| 9131 | return err; | 9244 | return err; |
| 9132 | 9245 | ||
| 9246 | wdev_lock(wdev); | ||
| 9247 | if (!cfg80211_off_channel_oper_allowed(wdev) && | ||
| 9248 | !cfg80211_chandef_identical(&wdev->chandef, &chandef)) { | ||
| 9249 | compat_chandef = cfg80211_chandef_compatible(&wdev->chandef, | ||
| 9250 | &chandef); | ||
| 9251 | if (compat_chandef != &chandef) { | ||
| 9252 | wdev_unlock(wdev); | ||
| 9253 | return -EBUSY; | ||
| 9254 | } | ||
| 9255 | } | ||
| 9256 | wdev_unlock(wdev); | ||
| 9257 | |||
| 9133 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 9258 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
| 9134 | if (!msg) | 9259 | if (!msg) |
| 9135 | return -ENOMEM; | 9260 | return -ENOMEM; |
| @@ -9305,6 +9430,13 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) · 169 unmodified lines | |||
| 9305 | if (!chandef.chan && params.offchan) | 9430 | if (!chandef.chan && params.offchan) |
| 9306 | return -EINVAL; | 9431 | return -EINVAL; |
| 9307 | 9432 | ||
| 9433 | wdev_lock(wdev); | ||
| 9434 | if (params.offchan && !cfg80211_off_channel_oper_allowed(wdev)) { | ||
| 9435 | wdev_unlock(wdev); | ||
| 9436 | return -EBUSY; | ||
| 9437 | } | ||
| 9438 | wdev_unlock(wdev); | ||
| 9439 | |||
| 9308 | params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); | 9440 | params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]); |
| 9309 | params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]); | 9441 | params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]); |
| 9310 | 9442 | ||
| @@ -9472,7 +9604,7 @@ static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info) · 161 unmodified lines | |||
| 9472 | 9604 | ||
| 9473 | static const struct nla_policy | 9605 | static const struct nla_policy |
| 9474 | nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = { | 9606 | nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = { |
| 9475 | [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, | 9607 | [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_BINARY }, |
| 9476 | [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, | 9608 | [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, |
| 9477 | [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, | 9609 | [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, |
| 9478 | [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 }, | 9610 | [NL80211_ATTR_CQM_TXE_RATE] = { .type = NLA_U32 }, |
| @@ -9501,28 +9633,123 @@ static int nl80211_set_cqm_txe(struct genl_info *info, · 22 unmodified lines | |||
| 9501 | return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl); | 9633 | return rdev_set_cqm_txe_config(rdev, dev, rate, pkts, intvl); |
| 9502 | } | 9634 | } |
| 9503 | 9635 | ||
| 9636 | static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, | ||
| 9637 | struct net_device *dev) | ||
| 9638 | { | ||
| 9639 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
| 9640 | s32 last, low, high; | ||
| 9641 | u32 hyst; | ||
| 9642 | int i, n; | ||
| 9643 | int err; | ||
| 9644 | |||
| 9645 | /* RSSI reporting disabled? */ | ||
| 9646 | if (!wdev->cqm_config) | ||
| 9647 | return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0); | ||
| 9648 | |||
| 9649 | /* | ||
| 9650 | * Obtain current RSSI value if possible, if not and no RSSI threshold | ||
| 9651 | * event has been received yet, we should receive an event after a | ||
| 9652 | * connection is established and enough beacons received to calculate | ||
| 9653 | * the average. | ||
| 9654 | */ | ||
| 9655 | if (!wdev->cqm_config->last_rssi_event_value && wdev->current_bss && | ||
| 9656 | rdev->ops->get_station) { | ||
| 9657 | struct station_info sinfo; | ||
| 9658 | u8 *mac_addr; | ||
| 9659 | |||
| 9660 | mac_addr = wdev->current_bss->pub.bssid; | ||
| 9661 | |||
| 9662 | err = rdev_get_station(rdev, dev, mac_addr, &sinfo); | ||
| 9663 | if (err) | ||
| 9664 | return err; | ||
| 9665 | |||
| 9666 | if (sinfo.filled & BIT(NL80211_STA_INFO_BEACON_SIGNAL_AVG)) | ||
| 9667 | wdev->cqm_config->last_rssi_event_value = | ||
| 9668 | (s8) sinfo.rx_beacon_signal_avg; | ||
| 9669 | } | ||
| 9670 | |||
| 9671 | last = wdev->cqm_config->last_rssi_event_value; | ||
| 9672 | hyst = wdev->cqm_config->rssi_hyst; | ||
| 9673 | n = wdev->cqm_config->n_rssi_thresholds; | ||
| 9674 | |||
| 9675 | for (i = 0; i < n; i++) | ||
| 9676 | if (last < wdev->cqm_config->rssi_thresholds[i]) | ||
| 9677 | break; | ||
| 9678 | |||
| 9679 | low = i > 0 ? | ||
| 9680 | (wdev->cqm_config->rssi_thresholds[i - 1] - hyst) : S32_MIN; | ||
| 9681 | high = i < n ? | ||
| 9682 | (wdev->cqm_config->rssi_thresholds[i] + hyst - 1) : S32_MAX; | ||
| 9683 | |||
| 9684 | return rdev_set_cqm_rssi_range_config(rdev, dev, low, high); | ||
| 9685 | } | ||
| 9686 | |||
| 9504 | static int nl80211_set_cqm_rssi(struct genl_info *info, | 9687 | static int nl80211_set_cqm_rssi(struct genl_info *info, |
| 9505 | s32 threshold, u32 hysteresis) | 9688 | const s32 *thresholds, int n_thresholds, |
| 9689 | u32 hysteresis) | ||
| 9506 | { | 9690 | { |
| 9507 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 9691 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| 9508 | struct net_device *dev = info->user_ptr[1]; | 9692 | struct net_device *dev = info->user_ptr[1]; |
| 9509 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 9693 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 9694 | int i, err; | ||
| 9695 | s32 prev = S32_MIN; | ||
| 9510 | 9696 | ||
| 9511 | if (threshold > 0) | 9697 | /* Check all values negative and sorted */ |
| 9512 | return -EINVAL; | 9698 | for (i = 0; i < n_thresholds; i++) { |
| 9513 | 9699 | if (thresholds[i] > 0 || thresholds[i] <= prev) | |
| 9514 | /* disabling - hysteresis should also be zero then */ | 9700 | return -EINVAL; |
| 9515 | if (threshold == 0) | ||
| 9516 | hysteresis = 0; | ||
| 9517 | 9701 | ||
| 9518 | if (!rdev->ops->set_cqm_rssi_config) | 9702 | prev = thresholds[i]; |
| 9519 | return -EOPNOTSUPP; | 9703 | } |
| 9520 | 9704 | ||
| 9521 | if (wdev->iftype != NL80211_IFTYPE_STATION && | 9705 | if (wdev->iftype != NL80211_IFTYPE_STATION && |
| 9522 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) | 9706 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) |
| 9523 | return -EOPNOTSUPP; | 9707 | return -EOPNOTSUPP; |
| 9524 | 9708 | ||
| 9525 | return rdev_set_cqm_rssi_config(rdev, dev, threshold, hysteresis); | 9709 | wdev_lock(wdev); |
| 9710 | cfg80211_cqm_config_free(wdev); | ||
| 9711 | wdev_unlock(wdev); | ||
| 9712 | |||
| 9713 | if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) { | ||
| 9714 | if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */ | ||
| 9715 | return rdev_set_cqm_rssi_config(rdev, dev, 0, 0); | ||
| 9716 | |||
| 9717 | return rdev_set_cqm_rssi_config(rdev, dev, | ||
| 9718 | thresholds[0], hysteresis); | ||
| 9719 | } | ||
| 9720 | |||
| 9721 | if (!wiphy_ext_feature_isset(&rdev->wiphy, | ||
| 9722 | NL80211_EXT_FEATURE_CQM_RSSI_LIST)) | ||
| 9723 | return -EOPNOTSUPP; | ||
| 9724 | |||
| 9725 | if (n_thresholds == 1 && thresholds[0] == 0) /* Disabling */ | ||
| 9726 | n_thresholds = 0; | ||
| 9727 | |||
| 9728 | wdev_lock(wdev); | ||
| 9729 | if (n_thresholds) { | ||
| 9730 | struct cfg80211_cqm_config *cqm_config; | ||
| 9731 | |||
| 9732 | cqm_config = kzalloc(sizeof(struct cfg80211_cqm_config) + | ||
| 9733 | n_thresholds * sizeof(s32), GFP_KERNEL); | ||
| 9734 | if (!cqm_config) { | ||
| 9735 | err = -ENOMEM; | ||
| 9736 | goto unlock; | ||
| 9737 | } | ||
| 9738 | |||
| 9739 | cqm_config->rssi_hyst = hysteresis; | ||
| 9740 | cqm_config->n_rssi_thresholds = n_thresholds; | ||
| 9741 | memcpy(cqm_config->rssi_thresholds, thresholds, | ||
| 9742 | n_thresholds * sizeof(s32)); | ||
| 9743 | |||
| 9744 | wdev->cqm_config = cqm_config; | ||
| 9745 | } | ||
| 9746 | |||
| 9747 | err = cfg80211_cqm_rssi_update(rdev, dev); | ||
| 9748 | |||
| 9749 | unlock: | ||
| 9750 | wdev_unlock(wdev); | ||
| 9751 | |||
| 9752 | return err; | ||
| 9526 | } | 9753 | } |
| 9527 | 9754 | ||
| 9528 | static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) | 9755 | static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) |
| @@ -9542,10 +9769,16 @@ static int nl80211_set_cqm(struct sk_buff *skb, struct genl_info *info) · 13 unmodified lines | |||
| 9542 | 9769 | ||
| 9543 | if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] && | 9770 | if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] && |
| 9544 | attrs[NL80211_ATTR_CQM_RSSI_HYST]) { | 9771 | attrs[NL80211_ATTR_CQM_RSSI_HYST]) { |
| 9545 | s32 threshold = nla_get_s32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]); | 9772 | const s32 *thresholds = |
| 9773 | nla_data(attrs[NL80211_ATTR_CQM_RSSI_THOLD]); | ||
| 9774 | int len = nla_len(attrs[NL80211_ATTR_CQM_RSSI_THOLD]); | ||
| 9546 | u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]); | 9775 | u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]); |
| 9547 | 9776 | ||
| 9548 | return nl80211_set_cqm_rssi(info, threshold, hysteresis); | 9777 | if (len % 4) |
| 9778 | return -EINVAL; | ||
| 9779 | |||
| 9780 | return nl80211_set_cqm_rssi(info, thresholds, len / 4, | ||
| 9781 | hysteresis); | ||
| 9549 | } | 9782 | } |
| 9550 | 9783 | ||
| 9551 | if (attrs[NL80211_ATTR_CQM_TXE_RATE] && | 9784 | if (attrs[NL80211_ATTR_CQM_TXE_RATE] && |
| @@ -12977,18 +13210,19 @@ static int nl80211_prep_scan_msg(struct sk_buff *msg, · 3425 unmodified lines | |||
| 12977 | 13210 | ||
| 12978 | static int | 13211 | static int |
| 12979 | nl80211_prep_sched_scan_msg(struct sk_buff *msg, | 13212 | nl80211_prep_sched_scan_msg(struct sk_buff *msg, |
| 12980 | struct cfg80211_registered_device *rdev, | 13213 | struct cfg80211_sched_scan_request *req, u32 cmd) |
| 12981 | struct net_device *netdev, | ||
| 12982 | u32 portid, u32 seq, int flags, u32 cmd) | ||
| 12983 | { | 13214 | { |
| 12984 | void *hdr; | 13215 | void *hdr; |
| 12985 | 13216 | ||
| 12986 | hdr = nl80211hdr_put(msg, portid, seq, flags, cmd); | 13217 | hdr = nl80211hdr_put(msg, 0, 0, 0, cmd); |
| 12987 | if (!hdr) | 13218 | if (!hdr) |
| 12988 | return -1; | 13219 | return -1; |
| 12989 | 13220 | ||
| 12990 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 13221 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, |
| 12991 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) | 13222 | wiphy_to_rdev(req->wiphy)->wiphy_idx) || |
| 13223 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, req->dev->ifindex) || | ||
| 13224 | nla_put_u64_64bit(msg, NL80211_ATTR_COOKIE, req->reqid, | ||
| 13225 | NL80211_ATTR_PAD)) | ||
| 12992 | goto nla_put_failure; | 13226 | goto nla_put_failure; |
| 12993 | 13227 | ||
| 12994 | genlmsg_end(msg, hdr); | 13228 | genlmsg_end(msg, hdr); |
| @@ -13048,8 +13282,7 @@ void nl80211_send_scan_msg(struct cfg80211_registered_device *rdev, · 53 unmodified lines | |||
| 13048 | NL80211_MCGRP_SCAN, GFP_KERNEL); | 13282 | NL80211_MCGRP_SCAN, GFP_KERNEL); |
| 13049 | } | 13283 | } |
| 13050 | 13284 | ||
| 13051 | void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, | 13285 | void nl80211_send_sched_scan(struct cfg80211_sched_scan_request *req, u32 cmd) |
| 13052 | struct net_device *netdev, u32 cmd) | ||
| 13053 | { | 13286 | { |
| 13054 | struct sk_buff *msg; | 13287 | struct sk_buff *msg; |
| 13055 | 13288 | ||
| @@ -13057,12 +13290,12 @@ void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, · 1 unmodified line | |||
| 13057 | if (!msg) | 13290 | if (!msg) |
| 13058 | return; | 13291 | return; |
| 13059 | 13292 | ||
| 13060 | if (nl80211_prep_sched_scan_msg(msg, rdev, netdev, 0, 0, 0, cmd) < 0) { | 13293 | if (nl80211_prep_sched_scan_msg(msg, req, cmd) < 0) { |
| 13061 | nlmsg_free(msg); | 13294 | nlmsg_free(msg); |
| 13062 | return; | 13295 | return; |
| 13063 | } | 13296 | } |
| 13064 | 13297 | ||
| 13065 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, | 13298 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(req->wiphy), msg, 0, |
| 13066 | NL80211_MCGRP_SCAN, GFP_KERNEL); | 13299 | NL80211_MCGRP_SCAN, GFP_KERNEL); |
| 13067 | } | 13300 | } |
| 13068 | 13301 | ||
| @@ -13303,17 +13536,16 @@ void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev, · 234 unmodified lines | |||
| 13303 | } | 13536 | } |
| 13304 | 13537 | ||
| 13305 | void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, | 13538 | void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, |
| 13306 | struct net_device *netdev, const u8 *bssid, | 13539 | struct net_device *netdev, |
| 13307 | const u8 *req_ie, size_t req_ie_len, | 13540 | struct cfg80211_connect_resp_params *cr, |
| 13308 | const u8 *resp_ie, size_t resp_ie_len, | ||
| 13309 | int status, | ||
| 13310 | enum nl80211_timeout_reason timeout_reason, | ||
| 13311 | gfp_t gfp) | 13541 | gfp_t gfp) |
| 13312 | { | 13542 | { |
| 13313 | struct sk_buff *msg; | 13543 | struct sk_buff *msg; |
| 13314 | void *hdr; | 13544 | void *hdr; |
| 13315 | 13545 | ||
| 13316 | msg = nlmsg_new(100 + req_ie_len + resp_ie_len, gfp); | 13546 | msg = nlmsg_new(100 + cr->req_ie_len + cr->resp_ie_len + |
| 13547 | cr->fils_kek_len + cr->pmk_len + | ||
| 13548 | (cr->pmkid ? WLAN_PMKID_LEN : 0), gfp); | ||
| 13317 | if (!msg) | 13549 | if (!msg) |
| 13318 | return; | 13550 | return; |
| 13319 | 13551 | ||
| @@ -13325,17 +13557,31 @@ void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, · 5 unmodified lines | |||
| 13325 | 13557 | ||
| 13326 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 13558 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
| 13327 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || | 13559 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex) || |
| 13328 | (bssid && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, bssid)) || | 13560 | (cr->bssid && |
| 13561 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, cr->bssid)) || | ||
| 13329 | nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, | 13562 | nla_put_u16(msg, NL80211_ATTR_STATUS_CODE, |
| 13330 | status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE : | 13563 | cr->status < 0 ? WLAN_STATUS_UNSPECIFIED_FAILURE : |
| 13331 | status) || | 13564 | cr->status) || |
| 13332 | (status < 0 && | 13565 | (cr->status < 0 && |
| 13333 | (nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) || | 13566 | (nla_put_flag(msg, NL80211_ATTR_TIMED_OUT) || |
| 13334 | nla_put_u32(msg, NL80211_ATTR_TIMEOUT_REASON, timeout_reason))) || | 13567 | nla_put_u32(msg, NL80211_ATTR_TIMEOUT_REASON, |
| 13335 | (req_ie && | 13568 | cr->timeout_reason))) || |
| 13336 | nla_put(msg, NL80211_ATTR_REQ_IE, req_ie_len, req_ie)) || | 13569 | (cr->req_ie && |
| 13337 | (resp_ie && | 13570 | nla_put(msg, NL80211_ATTR_REQ_IE, cr->req_ie_len, cr->req_ie)) || |
| 13338 | nla_put(msg, NL80211_ATTR_RESP_IE, resp_ie_len, resp_ie))) | 13571 | (cr->resp_ie && |
| 13572 | nla_put(msg, NL80211_ATTR_RESP_IE, cr->resp_ie_len, | ||
| 13573 | cr->resp_ie)) || | ||
| 13574 | (cr->update_erp_next_seq_num && | ||
| 13575 | nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM, | ||
| 13576 | cr->fils_erp_next_seq_num)) || | ||
| 13577 | (cr->status == WLAN_STATUS_SUCCESS && | ||
| 13578 | ((cr->fils_kek && | ||
| 13579 | nla_put(msg, NL80211_ATTR_FILS_KEK, cr->fils_kek_len, | ||
| 13580 | cr->fils_kek)) || | ||
| 13581 | (cr->pmk && | ||
| 13582 | nla_put(msg, NL80211_ATTR_PMK, cr->pmk_len, cr->pmk)) || | ||
| 13583 | (cr->pmkid && | ||
| 13584 | nla_put(msg, NL80211_ATTR_PMKID, WLAN_PMKID_LEN, cr->pmkid))))) | ||
| 13339 | goto nla_put_failure; | 13585 | goto nla_put_failure; |
| 13340 | 13586 | ||
| 13341 | genlmsg_end(msg, hdr); | 13587 | genlmsg_end(msg, hdr); |
| @@ -13975,6 +14221,8 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, · 633 unmodified lines | |||
| 13975 | s32 rssi_level, gfp_t gfp) | 14221 | s32 rssi_level, gfp_t gfp) |
| 13976 | { | 14222 | { |
| 13977 | struct sk_buff *msg; | 14223 | struct sk_buff *msg; |
| 14224 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
| 14225 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | ||
| 13978 | 14226 | ||
| 13979 | trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level); | 14227 | trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level); |
| 13980 | 14228 | ||
| @@ -13982,6 +14230,15 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, · 1 unmodified line | |||
| 13982 | rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH)) | 14230 | rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH)) |
| 13983 | return; | 14231 | return; |
| 13984 | 14232 | ||
| 14233 | if (wdev->cqm_config) { | ||
| 14234 | wdev->cqm_config->last_rssi_event_value = rssi_level; | ||
| 14235 | |||
| 14236 | cfg80211_cqm_rssi_update(rdev, dev); | ||
| 14237 | |||
| 14238 | if (rssi_level == 0) | ||
| 14239 | rssi_level = wdev->cqm_config->last_rssi_event_value; | ||
| 14240 | } | ||
| 14241 | |||
| 13985 | msg = cfg80211_prepare_cqm(dev, NULL, gfp); | 14242 | msg = cfg80211_prepare_cqm(dev, NULL, gfp); |
| 13986 | if (!msg) | 14243 | if (!msg) |
| 13987 | return; | 14244 | return; |
| @@ -16,8 +16,7 @@ struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, · 15 unmodified lines | |||
| 16 | struct wireless_dev *wdev, bool aborted); | 16 | struct wireless_dev *wdev, bool aborted); |
| 17 | void nl80211_send_scan_msg(struct cfg80211_registered_device *rdev, | 17 | void nl80211_send_scan_msg(struct cfg80211_registered_device *rdev, |
| 18 | struct sk_buff *msg); | 18 | struct sk_buff *msg); |
| 19 | void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, | 19 | void nl80211_send_sched_scan(struct cfg80211_sched_scan_request *req, u32 cmd); |
| 20 | struct net_device *netdev, u32 cmd); | ||
| 21 | void nl80211_common_reg_change_event(enum nl80211_commands cmd_id, | 20 | void nl80211_common_reg_change_event(enum nl80211_commands cmd_id, |
| 22 | struct regulatory_request *request); | 21 | struct regulatory_request *request); |
| 23 | 22 | ||
| @@ -53,11 +52,8 @@ void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev, · 29 unmodified lines | |||
| 53 | struct net_device *netdev, | 52 | struct net_device *netdev, |
| 54 | const u8 *addr, gfp_t gfp); | 53 | const u8 *addr, gfp_t gfp); |
| 55 | void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, | 54 | void nl80211_send_connect_result(struct cfg80211_registered_device *rdev, |
| 56 | struct net_device *netdev, const u8 *bssid, | 55 | struct net_device *netdev, |
| 57 | const u8 *req_ie, size_t req_ie_len, | 56 | struct cfg80211_connect_resp_params *params, |
| 58 | const u8 *resp_ie, size_t resp_ie_len, | ||
| 59 | int status, | ||
| 60 | enum nl80211_timeout_reason timeout_reason, | ||
| 61 | gfp_t gfp); | 57 | gfp_t gfp); |
| 62 | void nl80211_send_roamed(struct cfg80211_registered_device *rdev, | 58 | void nl80211_send_roamed(struct cfg80211_registered_device *rdev, |
| 63 | struct net_device *netdev, const u8 *bssid, | 59 | struct net_device *netdev, const u8 *bssid, |
| @@ -36,13 +36,13 @@ static inline void rdev_set_wakeup(struct cfg80211_registered_device *rdev, · 35 unmodified lines | |||
| 36 | static inline struct wireless_dev | 36 | static inline struct wireless_dev |
| 37 | *rdev_add_virtual_intf(struct cfg80211_registered_device *rdev, char *name, | 37 | *rdev_add_virtual_intf(struct cfg80211_registered_device *rdev, char *name, |
| 38 | unsigned char name_assign_type, | 38 | unsigned char name_assign_type, |
| 39 | enum nl80211_iftype type, u32 *flags, | 39 | enum nl80211_iftype type, |
| 40 | struct vif_params *params) | 40 | struct vif_params *params) |
| 41 | { | 41 | { |
| 42 | struct wireless_dev *ret; | 42 | struct wireless_dev *ret; |
| 43 | trace_rdev_add_virtual_intf(&rdev->wiphy, name, type); | 43 | trace_rdev_add_virtual_intf(&rdev->wiphy, name, type); |
| 44 | ret = rdev->ops->add_virtual_intf(&rdev->wiphy, name, name_assign_type, | 44 | ret = rdev->ops->add_virtual_intf(&rdev->wiphy, name, name_assign_type, |
| 45 | type, flags, params); | 45 | type, params); |
| 46 | trace_rdev_return_wdev(&rdev->wiphy, ret); | 46 | trace_rdev_return_wdev(&rdev->wiphy, ret); |
| 47 | return ret; | 47 | return ret; |
| 48 | } | 48 | } |
| @@ -61,12 +61,11 @@ rdev_del_virtual_intf(struct cfg80211_registered_device *rdev, · 12 unmodified lines | |||
| 61 | static inline int | 61 | static inline int |
| 62 | rdev_change_virtual_intf(struct cfg80211_registered_device *rdev, | 62 | rdev_change_virtual_intf(struct cfg80211_registered_device *rdev, |
| 63 | struct net_device *dev, enum nl80211_iftype type, | 63 | struct net_device *dev, enum nl80211_iftype type, |
| 64 | u32 *flags, struct vif_params *params) | 64 | struct vif_params *params) |
| 65 | { | 65 | { |
| 66 | int ret; | 66 | int ret; |
| 67 | trace_rdev_change_virtual_intf(&rdev->wiphy, dev, type); | 67 | trace_rdev_change_virtual_intf(&rdev->wiphy, dev, type); |
| 68 | ret = rdev->ops->change_virtual_intf(&rdev->wiphy, dev, type, flags, | 68 | ret = rdev->ops->change_virtual_intf(&rdev->wiphy, dev, type, params); |
| 69 | params); | ||
| 70 | trace_rdev_return_int(&rdev->wiphy, ret); | 69 | trace_rdev_return_int(&rdev->wiphy, ret); |
| 71 | return ret; | 70 | return ret; |
| 72 | } | 71 | } |
| @@ -749,6 +748,18 @@ rdev_set_cqm_rssi_config(struct cfg80211_registered_device *rdev, · 676 unmodified lines | |||
| 749 | return ret; | 748 | return ret; |
| 750 | } | 749 | } |
| 751 | 750 | ||
| 751 | static inline int | ||
| 752 | rdev_set_cqm_rssi_range_config(struct cfg80211_registered_device *rdev, | ||
| 753 | struct net_device *dev, s32 low, s32 high) | ||
| 754 | { | ||
| 755 | int ret; | ||
| 756 | trace_rdev_set_cqm_rssi_range_config(&rdev->wiphy, dev, low, high); | ||
| 757 | ret = rdev->ops->set_cqm_rssi_range_config(&rdev->wiphy, dev, | ||
| 758 | low, high); | ||
| 759 | trace_rdev_return_int(&rdev->wiphy, ret); | ||
| 760 | return ret; | ||
| 761 | } | ||
| 762 | |||
| 752 | static inline int | 763 | static inline int |
| 753 | rdev_set_cqm_txe_config(struct cfg80211_registered_device *rdev, | 764 | rdev_set_cqm_txe_config(struct cfg80211_registered_device *rdev, |
| 754 | struct net_device *dev, u32 rate, u32 pkts, u32 intvl) | 765 | struct net_device *dev, u32 rate, u32 pkts, u32 intvl) |
| @@ -2067,6 +2067,88 @@ reg_process_hint_country_ie(struct wiphy *wiphy, · 2066 unmodified lines | |||
| 2067 | return REG_REQ_IGNORE; | 2067 | return REG_REQ_IGNORE; |
| 2068 | } | 2068 | } |
| 2069 | 2069 | ||
| 2070 | bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2) | ||
| 2071 | { | ||
| 2072 | const struct ieee80211_regdomain *wiphy1_regd = NULL; | ||
| 2073 | const struct ieee80211_regdomain *wiphy2_regd = NULL; | ||
| 2074 | const struct ieee80211_regdomain *cfg80211_regd = NULL; | ||
| 2075 | bool dfs_domain_same; | ||
| 2076 | |||
| 2077 | rcu_read_lock(); | ||
| 2078 | |||
| 2079 | cfg80211_regd = rcu_dereference(cfg80211_regdomain); | ||
| 2080 | wiphy1_regd = rcu_dereference(wiphy1->regd); | ||
| 2081 | if (!wiphy1_regd) | ||
| 2082 | wiphy1_regd = cfg80211_regd; | ||
| 2083 | |||
| 2084 | wiphy2_regd = rcu_dereference(wiphy2->regd); | ||
| 2085 | if (!wiphy2_regd) | ||
| 2086 | wiphy2_regd = cfg80211_regd; | ||
| 2087 | |||
| 2088 | dfs_domain_same = wiphy1_regd->dfs_region == wiphy2_regd->dfs_region; | ||
| 2089 | |||
| 2090 | rcu_read_unlock(); | ||
| 2091 | |||
| 2092 | return dfs_domain_same; | ||
| 2093 | } | ||
| 2094 | |||
| 2095 | static void reg_copy_dfs_chan_state(struct ieee80211_channel *dst_chan, | ||
| 2096 | struct ieee80211_channel *src_chan) | ||
| 2097 | { | ||
| 2098 | if (!(dst_chan->flags & IEEE80211_CHAN_RADAR) || | ||
| 2099 | !(src_chan->flags & IEEE80211_CHAN_RADAR)) | ||
| 2100 | return; | ||
| 2101 | |||
| 2102 | if (dst_chan->flags & IEEE80211_CHAN_DISABLED || | ||
| 2103 | src_chan->flags & IEEE80211_CHAN_DISABLED) | ||
| 2104 | return; | ||
| 2105 | |||
| 2106 | if (src_chan->center_freq == dst_chan->center_freq && | ||
| 2107 | dst_chan->dfs_state == NL80211_DFS_USABLE) { | ||
| 2108 | dst_chan->dfs_state = src_chan->dfs_state; | ||
| 2109 | dst_chan->dfs_state_entered = src_chan->dfs_state_entered; | ||
| 2110 | } | ||
| 2111 | } | ||
| 2112 | |||
| 2113 | static void wiphy_share_dfs_chan_state(struct wiphy *dst_wiphy, | ||
| 2114 | struct wiphy *src_wiphy) | ||
| 2115 | { | ||
| 2116 | struct ieee80211_supported_band *src_sband, *dst_sband; | ||
| 2117 | struct ieee80211_channel *src_chan, *dst_chan; | ||
| 2118 | int i, j, band; | ||
| 2119 | |||
| 2120 | if (!reg_dfs_domain_same(dst_wiphy, src_wiphy)) | ||
| 2121 | return; | ||
| 2122 | |||
| 2123 | for (band = 0; band < NUM_NL80211_BANDS; band++) { | ||
| 2124 | dst_sband = dst_wiphy->bands[band]; | ||
| 2125 | src_sband = src_wiphy->bands[band]; | ||
| 2126 | if (!dst_sband || !src_sband) | ||
| 2127 | continue; | ||
| 2128 | |||
| 2129 | for (i = 0; i < dst_sband->n_channels; i++) { | ||
| 2130 | dst_chan = &dst_sband->channels[i]; | ||
| 2131 | for (j = 0; j < src_sband->n_channels; j++) { | ||
| 2132 | src_chan = &src_sband->channels[j]; | ||
| 2133 | reg_copy_dfs_chan_state(dst_chan, src_chan); | ||
| 2134 | } | ||
| 2135 | } | ||
| 2136 | } | ||
| 2137 | } | ||
| 2138 | |||
| 2139 | static void wiphy_all_share_dfs_chan_state(struct wiphy *wiphy) | ||
| 2140 | { | ||
| 2141 | struct cfg80211_registered_device *rdev; | ||
| 2142 | |||
| 2143 | ASSERT_RTNL(); | ||
| 2144 | |||
| 2145 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | ||
| 2146 | if (wiphy == &rdev->wiphy) | ||
| 2147 | continue; | ||
| 2148 | wiphy_share_dfs_chan_state(wiphy, &rdev->wiphy); | ||
| 2149 | } | ||
| 2150 | } | ||
| 2151 | |||
| 2070 | /* This processes *all* regulatory hints */ | 2152 | /* This processes *all* regulatory hints */ |
| 2071 | static void reg_process_hint(struct regulatory_request *reg_request) | 2153 | static void reg_process_hint(struct regulatory_request *reg_request) |
| 2072 | { | 2154 | { |
| @@ -2110,6 +2192,7 @@ static void reg_process_hint(struct regulatory_request *reg_request) · 37 unmodified lines | |||
| 2110 | if (treatment == REG_REQ_ALREADY_SET && wiphy && | 2192 | if (treatment == REG_REQ_ALREADY_SET && wiphy && |
| 2111 | wiphy->regulatory_flags & REGULATORY_STRICT_REG) { | 2193 | wiphy->regulatory_flags & REGULATORY_STRICT_REG) { |
| 2112 | wiphy_update_regulatory(wiphy, reg_request->initiator); | 2194 | wiphy_update_regulatory(wiphy, reg_request->initiator); |
| 2195 | wiphy_all_share_dfs_chan_state(wiphy); | ||
| 2113 | reg_check_channels(); | 2196 | reg_check_channels(); |
| 2114 | } | 2197 | } |
| 2115 | 2198 | ||
| @@ -3061,6 +3144,7 @@ void wiphy_regulatory_register(struct wiphy *wiphy) · 945 unmodified lines | |||
| 3061 | 3144 | ||
| 3062 | lr = get_last_request(); | 3145 | lr = get_last_request(); |
| 3063 | wiphy_update_regulatory(wiphy, lr->initiator); | 3146 | wiphy_update_regulatory(wiphy, lr->initiator); |
| 3147 | wiphy_all_share_dfs_chan_state(wiphy); | ||
| 3064 | } | 3148 | } |
| 3065 | 3149 | ||
| 3066 | void wiphy_regulatory_deregister(struct wiphy *wiphy) | 3150 | void wiphy_regulatory_deregister(struct wiphy *wiphy) |
| @@ -3120,6 +3204,70 @@ bool regulatory_indoor_allowed(void) · 53 unmodified lines | |||
| 3120 | return reg_is_indoor; | 3204 | return reg_is_indoor; |
| 3121 | } | 3205 | } |
| 3122 | 3206 | ||
| 3207 | bool regulatory_pre_cac_allowed(struct wiphy *wiphy) | ||
| 3208 | { | ||
| 3209 | const struct ieee80211_regdomain *regd = NULL; | ||
| 3210 | const struct ieee80211_regdomain *wiphy_regd = NULL; | ||
| 3211 | bool pre_cac_allowed = false; | ||
| 3212 | |||
| 3213 | rcu_read_lock(); | ||
| 3214 | |||
| 3215 | regd = rcu_dereference(cfg80211_regdomain); | ||
| 3216 | wiphy_regd = rcu_dereference(wiphy->regd); | ||
| 3217 | if (!wiphy_regd) { | ||
| 3218 | if (regd->dfs_region == NL80211_DFS_ETSI) | ||
| 3219 | pre_cac_allowed = true; | ||
| 3220 | |||
| 3221 | rcu_read_unlock(); | ||
| 3222 | |||
| 3223 | return pre_cac_allowed; | ||
| 3224 | } | ||
| 3225 | |||
| 3226 | if (regd->dfs_region == wiphy_regd->dfs_region && | ||
| 3227 | wiphy_regd->dfs_region == NL80211_DFS_ETSI) | ||
| 3228 | pre_cac_allowed = true; | ||
| 3229 | |||
| 3230 | rcu_read_unlock(); | ||
| 3231 | |||
| 3232 | return pre_cac_allowed; | ||
| 3233 | } | ||
| 3234 | |||
| 3235 | void regulatory_propagate_dfs_state(struct wiphy *wiphy, | ||
| 3236 | struct cfg80211_chan_def *chandef, | ||
| 3237 | enum nl80211_dfs_state dfs_state, | ||
| 3238 | enum nl80211_radar_event event) | ||
| 3239 | { | ||
| 3240 | struct cfg80211_registered_device *rdev; | ||
| 3241 | |||
| 3242 | ASSERT_RTNL(); | ||
| 3243 | |||
| 3244 | if (WARN_ON(!cfg80211_chandef_valid(chandef))) | ||
| 3245 | return; | ||
| 3246 | |||
| 3247 | if (WARN_ON(!(chandef->chan->flags & IEEE80211_CHAN_RADAR))) | ||
| 3248 | return; | ||
| 3249 | |||
| 3250 | list_for_each_entry(rdev, &cfg80211_rdev_list, list) { | ||
| 3251 | if (wiphy == &rdev->wiphy) | ||
| 3252 | continue; | ||
| 3253 | |||
| 3254 | if (!reg_dfs_domain_same(wiphy, &rdev->wiphy)) | ||
| 3255 | continue; | ||
| 3256 | |||
| 3257 | if (!ieee80211_get_channel(&rdev->wiphy, | ||
| 3258 | chandef->chan->center_freq)) | ||
| 3259 | continue; | ||
| 3260 | |||
| 3261 | cfg80211_set_dfs_state(&rdev->wiphy, chandef, dfs_state); | ||
| 3262 | |||
| 3263 | if (event == NL80211_RADAR_DETECTED || | ||
| 3264 | event == NL80211_RADAR_CAC_FINISHED) | ||
| 3265 | cfg80211_sched_dfs_chan_update(rdev); | ||
| 3266 | |||
| 3267 | nl80211_radar_notify(rdev, chandef, event, NULL, GFP_KERNEL); | ||
| 3268 | } | ||
| 3269 | } | ||
| 3270 | |||
| 3123 | int __init regulatory_init(void) | 3271 | int __init regulatory_init(void) |
| 3124 | { | 3272 | { |
| 3125 | int err = 0; | 3273 | int err = 0; |
| @@ -143,4 +143,40 @@ int cfg80211_get_unii(int freq); · 142 unmodified lines | |||
| 143 | */ | 143 | */ |
| 144 | bool regulatory_indoor_allowed(void); | 144 | bool regulatory_indoor_allowed(void); |
| 145 | 145 | ||
| 146 | /* | ||
| 147 | * Grace period to timeout pre-CAC results on the dfs channels. This timeout | ||
| 148 | * value is used for Non-ETSI domain. | ||
| 149 | * TODO: May be make this timeout available through regdb? | ||
| 150 | */ | ||
| 151 | #define REG_PRE_CAC_EXPIRY_GRACE_MS 2000 | ||
| 152 | |||
| 153 | /** | ||
| 154 | * regulatory_pre_cac_allowed - if pre-CAC allowed in the current dfs domain | ||
| 155 | * @wiphy: wiphy for which pre-CAC capability is checked. | ||
| 156 | |||
| 157 | * Pre-CAC is allowed only in ETSI domain. | ||
| 158 | */ | ||
| 159 | bool regulatory_pre_cac_allowed(struct wiphy *wiphy); | ||
| 160 | |||
| 161 | /** | ||
| 162 | * regulatory_propagate_dfs_state - Propagate DFS channel state to other wiphys | ||
| 163 | * @wiphy - wiphy on which radar is detected and the event will be propagated | ||
| 164 | * to other available wiphys having the same DFS domain | ||
| 165 | * @chandef - Channel definition of radar detected channel | ||
| 166 | * @dfs_state - DFS channel state to be set | ||
| 167 | * @event - Type of radar event which triggered this DFS state change | ||
| 168 | * | ||
| 169 | * This function should be called with rtnl lock held. | ||
| 170 | */ | ||
| 171 | void regulatory_propagate_dfs_state(struct wiphy *wiphy, | ||
| 172 | struct cfg80211_chan_def *chandef, | ||
| 173 | enum nl80211_dfs_state dfs_state, | ||
| 174 | enum nl80211_radar_event event); | ||
| 175 | |||
| 176 | /** | ||
| 177 | * reg_dfs_domain_same - Checks if both wiphy have same DFS domain configured | ||
| 178 | * @wiphy1 - wiphy it's dfs_region to be checked against that of wiphy2 | ||
| 179 | * @wiphy2 - wiphy it's dfs_region to be checked against that of wiphy1 | ||
| 180 | */ | ||
| 181 | bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2); | ||
| 146 | #endif /* __NET_WIRELESS_REG_H */ | 182 | #endif /* __NET_WIRELESS_REG_H */ |
| @@ -321,8 +321,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) · 320 unmodified lines | |||
| 321 | spin_unlock_bh(&rdev->bss_lock); | 321 | spin_unlock_bh(&rdev->bss_lock); |
| 322 | request->scan_start = jiffies; | 322 | request->scan_start = jiffies; |
| 323 | } | 323 | } |
| 324 | nl80211_send_sched_scan(rdev, request->dev, | 324 | nl80211_send_sched_scan(request, NL80211_CMD_SCHED_SCAN_RESULTS); |
| 325 | NL80211_CMD_SCHED_SCAN_RESULTS); | ||
| 326 | } | 325 | } |
| 327 | 326 | ||
| 328 | rtnl_unlock(); | 327 | rtnl_unlock(); |
| @@ -379,7 +378,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, · 50 unmodified lines | |||
| 379 | return err; | 378 | return err; |
| 380 | } | 379 | } |
| 381 | 380 | ||
| 382 | nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED); | 381 | nl80211_send_sched_scan(sched_scan_req, NL80211_CMD_SCHED_SCAN_STOPPED); |
| 383 | 382 | ||
| 384 | RCU_INIT_POINTER(rdev->sched_scan_req, NULL); | 383 | RCU_INIT_POINTER(rdev->sched_scan_req, NULL); |
| 385 | kfree_rcu(sched_scan_req, rcu_head); | 384 | kfree_rcu(sched_scan_req, rcu_head); |
| @@ -253,10 +253,13 @@ void cfg80211_conn_work(struct work_struct *work) · 252 unmodified lines | |||
| 253 | } | 253 | } |
| 254 | treason = NL80211_TIMEOUT_UNSPECIFIED; | 254 | treason = NL80211_TIMEOUT_UNSPECIFIED; |
| 255 | if (cfg80211_conn_do_work(wdev, &treason)) { | 255 | if (cfg80211_conn_do_work(wdev, &treason)) { |
| 256 | __cfg80211_connect_result( | 256 | struct cfg80211_connect_resp_params cr; |
| 257 | wdev->netdev, bssid, | 257 | |
| 258 | NULL, 0, NULL, 0, -1, false, NULL, | 258 | memset(&cr, 0, sizeof(cr)); |
| 259 | treason); | 259 | cr.status = -1; |
| 260 | cr.bssid = bssid; | ||
| 261 | cr.timeout_reason = treason; | ||
| 262 | __cfg80211_connect_result(wdev->netdev, &cr, false); | ||
| 260 | } | 263 | } |
| 261 | wdev_unlock(wdev); | 264 | wdev_unlock(wdev); |
| 262 | } | 265 | } |
| @@ -359,10 +362,13 @@ void cfg80211_sme_rx_auth(struct wireless_dev *wdev, const u8 *buf, size_t len) · 96 unmodified lines | |||
| 359 | wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; | 362 | wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT; |
| 360 | schedule_work(&rdev->conn_work); | 363 | schedule_work(&rdev->conn_work); |
| 361 | } else if (status_code != WLAN_STATUS_SUCCESS) { | 364 | } else if (status_code != WLAN_STATUS_SUCCESS) { |
| 362 | __cfg80211_connect_result(wdev->netdev, mgmt->bssid, | 365 | struct cfg80211_connect_resp_params cr; |
| 363 | NULL, 0, NULL, 0, | 366 | |
| 364 | status_code, false, NULL, | 367 | memset(&cr, 0, sizeof(cr)); |
| 365 | NL80211_TIMEOUT_UNSPECIFIED); | 368 | cr.status = status_code; |
| 369 | cr.bssid = mgmt->bssid; | ||
| 370 | cr.timeout_reason = NL80211_TIMEOUT_UNSPECIFIED; | ||
| 371 | __cfg80211_connect_result(wdev->netdev, &cr, false); | ||
| 366 | } else if (wdev->conn->state == CFG80211_CONN_AUTHENTICATING) { | 372 | } else if (wdev->conn->state == CFG80211_CONN_AUTHENTICATING) { |
| 367 | wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT; | 373 | wdev->conn->state = CFG80211_CONN_ASSOCIATE_NEXT; |
| 368 | schedule_work(&rdev->conn_work); | 374 | schedule_work(&rdev->conn_work); |
| @@ -669,12 +675,9 @@ static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work); · 300 unmodified lines | |||
| 669 | */ | 675 | */ |
| 670 | 676 | ||
| 671 | /* This method must consume bss one way or another */ | 677 | /* This method must consume bss one way or another */ |
| 672 | void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | 678 | void __cfg80211_connect_result(struct net_device *dev, |
| 673 | const u8 *req_ie, size_t req_ie_len, | 679 | struct cfg80211_connect_resp_params *cr, |
| 674 | const u8 *resp_ie, size_t resp_ie_len, | 680 | bool wextev) |
| 675 | int status, bool wextev, | ||
| 676 | struct cfg80211_bss *bss, | ||
| 677 | enum nl80211_timeout_reason timeout_reason) | ||
| 678 | { | 681 | { |
| 679 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 682 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 680 | const u8 *country_ie; | 683 | const u8 *country_ie; |
| @@ -686,48 +689,48 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, · 5 unmodified lines | |||
| 686 | 689 | ||
| 687 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && | 690 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && |
| 688 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) { | 691 | wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) { |
| 689 | cfg80211_put_bss(wdev->wiphy, bss); | 692 | cfg80211_put_bss(wdev->wiphy, cr->bss); |
| 690 | return; | 693 | return; |
| 691 | } | 694 | } |
| 692 | 695 | ||
| 693 | nl80211_send_connect_result(wiphy_to_rdev(wdev->wiphy), dev, | 696 | nl80211_send_connect_result(wiphy_to_rdev(wdev->wiphy), dev, cr, |
| 694 | bssid, req_ie, req_ie_len, | 697 | GFP_KERNEL); |
| 695 | resp_ie, resp_ie_len, | ||
| 696 | status, timeout_reason, GFP_KERNEL); | ||
| 697 | 698 | ||
| 698 | #ifdef CONFIG_CFG80211_WEXT | 699 | #ifdef CONFIG_CFG80211_WEXT |
| 699 | if (wextev) { | 700 | if (wextev) { |
| 700 | if (req_ie && status == WLAN_STATUS_SUCCESS) { | 701 | if (cr->req_ie && cr->status == WLAN_STATUS_SUCCESS) { |
| 701 | memset(&wrqu, 0, sizeof(wrqu)); | 702 | memset(&wrqu, 0, sizeof(wrqu)); |
| 702 | wrqu.data.length = req_ie_len; | 703 | wrqu.data.length = cr->req_ie_len; |
| 703 | wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, req_ie); | 704 | wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, |
| 705 | cr->req_ie); | ||
| 704 | } | 706 | } |
| 705 | 707 | ||
| 706 | if (resp_ie && status == WLAN_STATUS_SUCCESS) { | 708 | if (cr->resp_ie && cr->status == WLAN_STATUS_SUCCESS) { |
| 707 | memset(&wrqu, 0, sizeof(wrqu)); | 709 | memset(&wrqu, 0, sizeof(wrqu)); |
| 708 | wrqu.data.length = resp_ie_len; | 710 | wrqu.data.length = cr->resp_ie_len; |
| 709 | wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, resp_ie); | 711 | wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, |
| 712 | cr->resp_ie); | ||
| 710 | } | 713 | } |
| 711 | 714 | ||
| 712 | memset(&wrqu, 0, sizeof(wrqu)); | 715 | memset(&wrqu, 0, sizeof(wrqu)); |
| 713 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; | 716 | wrqu.ap_addr.sa_family = ARPHRD_ETHER; |
| 714 | if (bssid && status == WLAN_STATUS_SUCCESS) { | 717 | if (cr->bssid && cr->status == WLAN_STATUS_SUCCESS) { |
| 715 | memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); | 718 | memcpy(wrqu.ap_addr.sa_data, cr->bssid, ETH_ALEN); |
| 716 | memcpy(wdev->wext.prev_bssid, bssid, ETH_ALEN); | 719 | memcpy(wdev->wext.prev_bssid, cr->bssid, ETH_ALEN); |
| 717 | wdev->wext.prev_bssid_valid = true; | 720 | wdev->wext.prev_bssid_valid = true; |
| 718 | } | 721 | } |
| 719 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); | 722 | wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); |
| 720 | } | 723 | } |
| 721 | #endif | 724 | #endif |
| 722 | 725 | ||
| 723 | if (!bss && (status == WLAN_STATUS_SUCCESS)) { | 726 | if (!cr->bss && (cr->status == WLAN_STATUS_SUCCESS)) { |
| 724 | WARN_ON_ONCE(!wiphy_to_rdev(wdev->wiphy)->ops->connect); | 727 | WARN_ON_ONCE(!wiphy_to_rdev(wdev->wiphy)->ops->connect); |
| 725 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, | 728 | cr->bss = cfg80211_get_bss(wdev->wiphy, NULL, cr->bssid, |
| 726 | wdev->ssid, wdev->ssid_len, | 729 | wdev->ssid, wdev->ssid_len, |
| 727 | wdev->conn_bss_type, | 730 | wdev->conn_bss_type, |
| 728 | IEEE80211_PRIVACY_ANY); | 731 | IEEE80211_PRIVACY_ANY); |
| 729 | if (bss) | 732 | if (cr->bss) |
| 730 | cfg80211_hold_bss(bss_from_pub(bss)); | 733 | cfg80211_hold_bss(bss_from_pub(cr->bss)); |
| 731 | } | 734 | } |
| 732 | 735 | ||
| 733 | if (wdev->current_bss) { | 736 | if (wdev->current_bss) { |
| @@ -736,29 +739,29 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, · 2 unmodified lines | |||
| 736 | wdev->current_bss = NULL; | 739 | wdev->current_bss = NULL; |
| 737 | } | 740 | } |
| 738 | 741 | ||
| 739 | if (status != WLAN_STATUS_SUCCESS) { | 742 | if (cr->status != WLAN_STATUS_SUCCESS) { |
| 740 | kzfree(wdev->connect_keys); | 743 | kzfree(wdev->connect_keys); |
| 741 | wdev->connect_keys = NULL; | 744 | wdev->connect_keys = NULL; |
| 742 | wdev->ssid_len = 0; | 745 | wdev->ssid_len = 0; |
| 743 | wdev->conn_owner_nlportid = 0; | 746 | wdev->conn_owner_nlportid = 0; |
| 744 | if (bss) { | 747 | if (cr->bss) { |
| 745 | cfg80211_unhold_bss(bss_from_pub(bss)); | 748 | cfg80211_unhold_bss(bss_from_pub(cr->bss)); |
| 746 | cfg80211_put_bss(wdev->wiphy, bss); | 749 | cfg80211_put_bss(wdev->wiphy, cr->bss); |
| 747 | } | 750 | } |
| 748 | cfg80211_sme_free(wdev); | 751 | cfg80211_sme_free(wdev); |
| 749 | return; | 752 | return; |
| 750 | } | 753 | } |
| 751 | 754 | ||
| 752 | if (WARN_ON(!bss)) | 755 | if (WARN_ON(!cr->bss)) |
| 753 | return; | 756 | return; |
| 754 | 757 | ||
| 755 | wdev->current_bss = bss_from_pub(bss); | 758 | wdev->current_bss = bss_from_pub(cr->bss); |
| 756 | 759 | ||
| 757 | if (!(wdev->wiphy->flags & WIPHY_FLAG_HAS_STATIC_WEP)) | 760 | if (!(wdev->wiphy->flags & WIPHY_FLAG_HAS_STATIC_WEP)) |
| 758 | cfg80211_upload_connect_keys(wdev); | 761 | cfg80211_upload_connect_keys(wdev); |
| 759 | 762 | ||
| 760 | rcu_read_lock(); | 763 | rcu_read_lock(); |
| 761 | country_ie = ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); | 764 | country_ie = ieee80211_bss_get_ie(cr->bss, WLAN_EID_COUNTRY); |
| 762 | if (!country_ie) { | 765 | if (!country_ie) { |
| 763 | rcu_read_unlock(); | 766 | rcu_read_unlock(); |
| 764 | return; | 767 | return; |
| @@ -775,64 +778,95 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, · 10 unmodified lines | |||
| 775 | * - country_ie + 2, the start of the country ie data, and | 778 | * - country_ie + 2, the start of the country ie data, and |
| 776 | * - and country_ie[1] which is the IE length | 779 | * - and country_ie[1] which is the IE length |
| 777 | */ | 780 | */ |
| 778 | regulatory_hint_country_ie(wdev->wiphy, bss->channel->band, | 781 | regulatory_hint_country_ie(wdev->wiphy, cr->bss->channel->band, |
| 779 | country_ie + 2, country_ie[1]); | 782 | country_ie + 2, country_ie[1]); |
| 780 | kfree(country_ie); | 783 | kfree(country_ie); |
| 781 | } | 784 | } |
| 782 | 785 | ||
| 783 | /* Consumes bss object one way or another */ | 786 | /* Consumes bss object one way or another */ |
| 784 | void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid, | 787 | void cfg80211_connect_done(struct net_device *dev, |
| 785 | struct cfg80211_bss *bss, const u8 *req_ie, | 788 | struct cfg80211_connect_resp_params *params, |
| 786 | size_t req_ie_len, const u8 *resp_ie, | 789 | gfp_t gfp) |
| 787 | size_t resp_ie_len, int status, gfp_t gfp, | ||
| 788 | enum nl80211_timeout_reason timeout_reason) | ||
| 789 | { | 790 | { |
| 790 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 791 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 791 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | 792 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); |
| 792 | struct cfg80211_event *ev; | 793 | struct cfg80211_event *ev; |
| 793 | unsigned long flags; | 794 | unsigned long flags; |
| 795 | u8 *next; | ||
| 794 | 796 | ||
| 795 | if (bss) { | 797 | if (params->bss) { |
| 796 | /* Make sure the bss entry provided by the driver is valid. */ | 798 | /* Make sure the bss entry provided by the driver is valid. */ |
| 797 | struct cfg80211_internal_bss *ibss = bss_from_pub(bss); | 799 | struct cfg80211_internal_bss *ibss = bss_from_pub(params->bss); |
| 798 | 800 | ||
| 799 | if (WARN_ON(list_empty(&ibss->list))) { | 801 | if (WARN_ON(list_empty(&ibss->list))) { |
| 800 | cfg80211_put_bss(wdev->wiphy, bss); | 802 | cfg80211_put_bss(wdev->wiphy, params->bss); |
| 801 | return; | 803 | return; |
| 802 | } | 804 | } |
| 803 | } | 805 | } |
| 804 | 806 | ||
| 805 | ev = kzalloc(sizeof(*ev) + req_ie_len + resp_ie_len, gfp); | 807 | ev = kzalloc(sizeof(*ev) + (params->bssid ? ETH_ALEN : 0) + |
| 808 | params->req_ie_len + params->resp_ie_len + | ||
| 809 | params->fils_kek_len + params->pmk_len + | ||
| 810 | (params->pmkid ? WLAN_PMKID_LEN : 0), gfp); | ||
| 806 | if (!ev) { | 811 | if (!ev) { |
| 807 | cfg80211_put_bss(wdev->wiphy, bss); | 812 | cfg80211_put_bss(wdev->wiphy, params->bss); |
| 808 | return; | 813 | return; |
| 809 | } | 814 | } |
| 810 | 815 | ||
| 811 | ev->type = EVENT_CONNECT_RESULT; | 816 | ev->type = EVENT_CONNECT_RESULT; |
| 812 | if (bssid) | 817 | next = ((u8 *)ev) + sizeof(*ev); |
| 813 | memcpy(ev->cr.bssid, bssid, ETH_ALEN); | 818 | if (params->bssid) { |
| 814 | if (req_ie_len) { | 819 | ev->cr.bssid = next; |
| 815 | ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev); | 820 | memcpy((void *)ev->cr.bssid, params->bssid, ETH_ALEN); |
| 816 | ev->cr.req_ie_len = req_ie_len; | 821 | next += ETH_ALEN; |
| 817 | memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len); | ||
| 818 | } | 822 | } |
| 819 | if (resp_ie_len) { | 823 | if (params->req_ie_len) { |
| 820 | ev->cr.resp_ie = ((u8 *)ev) + sizeof(*ev) + req_ie_len; | 824 | ev->cr.req_ie = next; |
| 821 | ev->cr.resp_ie_len = resp_ie_len; | 825 | ev->cr.req_ie_len = params->req_ie_len; |
| 822 | memcpy((void *)ev->cr.resp_ie, resp_ie, resp_ie_len); | 826 | memcpy((void *)ev->cr.req_ie, params->req_ie, |
| 827 | params->req_ie_len); | ||
| 828 | next += params->req_ie_len; | ||
| 823 | } | 829 | } |
| 824 | if (bss) | 830 | if (params->resp_ie_len) { |
| 825 | cfg80211_hold_bss(bss_from_pub(bss)); | 831 | ev->cr.resp_ie = next; |
| 826 | ev->cr.bss = bss; | 832 | ev->cr.resp_ie_len = params->resp_ie_len; |
| 827 | ev->cr.status = status; | 833 | memcpy((void *)ev->cr.resp_ie, params->resp_ie, |
| 828 | ev->cr.timeout_reason = timeout_reason; | 834 | params->resp_ie_len); |
| 835 | next += params->resp_ie_len; | ||
| 836 | } | ||
| 837 | if (params->fils_kek_len) { | ||
| 838 | ev->cr.fils_kek = next; | ||
| 839 | ev->cr.fils_kek_len = params->fils_kek_len; | ||
| 840 | memcpy((void *)ev->cr.fils_kek, params->fils_kek, | ||
| 841 | params->fils_kek_len); | ||
| 842 | next += params->fils_kek_len; | ||
| 843 | } | ||
| 844 | if (params->pmk_len) { | ||
| 845 | ev->cr.pmk = next; | ||
| 846 | ev->cr.pmk_len = params->pmk_len; | ||
| 847 | memcpy((void *)ev->cr.pmk, params->pmk, params->pmk_len); | ||
| 848 | next += params->pmk_len; | ||
| 849 | } | ||
| 850 | if (params->pmkid) { | ||
| 851 | ev->cr.pmkid = next; | ||
| 852 | memcpy((void *)ev->cr.pmkid, params->pmkid, WLAN_PMKID_LEN); | ||
| 853 | next += WLAN_PMKID_LEN; | ||
| 854 | } | ||
| 855 | ev->cr.update_erp_next_seq_num = params->update_erp_next_seq_num; | ||
| 856 | if (params->update_erp_next_seq_num) | ||
| 857 | ev->cr.fils_erp_next_seq_num = params->fils_erp_next_seq_num; | ||
| 858 | if (params->bss) | ||
| 859 | cfg80211_hold_bss(bss_from_pub(params->bss)); | ||
| 860 | ev->cr.bss = params->bss; | ||
| 861 | ev->cr.status = params->status; | ||
| 862 | ev->cr.timeout_reason = params->timeout_reason; | ||
| 829 | 863 | ||
| 830 | spin_lock_irqsave(&wdev->event_lock, flags); | 864 | spin_lock_irqsave(&wdev->event_lock, flags); |
| 831 | list_add_tail(&ev->list, &wdev->event_list); | 865 | list_add_tail(&ev->list, &wdev->event_list); |
| 832 | spin_unlock_irqrestore(&wdev->event_lock, flags); | 866 | spin_unlock_irqrestore(&wdev->event_lock, flags); |
| 833 | queue_work(cfg80211_wq, &rdev->event_work); | 867 | queue_work(cfg80211_wq, &rdev->event_work); |
| 834 | } | 868 | } |
| 835 | EXPORT_SYMBOL(cfg80211_connect_bss); | 869 | EXPORT_SYMBOL(cfg80211_connect_done); |
| 836 | 870 | ||
| 837 | /* Consumes bss object one way or another */ | 871 | /* Consumes bss object one way or another */ |
| 838 | void __cfg80211_roamed(struct wireless_dev *wdev, | 872 | void __cfg80211_roamed(struct wireless_dev *wdev, |
| @@ -1322,6 +1322,28 @@ TRACE_EVENT(rdev_set_cqm_rssi_config, · 1321 unmodified lines | |||
| 1322 | __entry->rssi_thold, __entry->rssi_hyst) | 1322 | __entry->rssi_thold, __entry->rssi_hyst) |
| 1323 | ); | 1323 | ); |
| 1324 | 1324 | ||
| 1325 | TRACE_EVENT(rdev_set_cqm_rssi_range_config, | ||
| 1326 | TP_PROTO(struct wiphy *wiphy, | ||
| 1327 | struct net_device *netdev, s32 low, s32 high), | ||
| 1328 | TP_ARGS(wiphy, netdev, low, high), | ||
| 1329 | TP_STRUCT__entry( | ||
| 1330 | WIPHY_ENTRY | ||
| 1331 | NETDEV_ENTRY | ||
| 1332 | __field(s32, rssi_low) | ||
| 1333 | __field(s32, rssi_high) | ||
| 1334 | ), | ||
| 1335 | TP_fast_assign( | ||
| 1336 | WIPHY_ASSIGN; | ||
| 1337 | NETDEV_ASSIGN; | ||
| 1338 | __entry->rssi_low = low; | ||
| 1339 | __entry->rssi_high = high; | ||
| 1340 | ), | ||
| 1341 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT | ||
| 1342 | ", range: %d - %d ", | ||
| 1343 | WIPHY_PR_ARG, NETDEV_PR_ARG, | ||
| 1344 | __entry->rssi_low, __entry->rssi_high) | ||
| 1345 | ); | ||
| 1346 | |||
| 1325 | TRACE_EVENT(rdev_set_cqm_txe_config, | 1347 | TRACE_EVENT(rdev_set_cqm_txe_config, |
| 1326 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u32 rate, | 1348 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u32 rate, |
| 1327 | u32 pkts, u32 intvl), | 1349 | u32 pkts, u32 intvl), |
| @@ -659,7 +659,7 @@ __ieee80211_amsdu_copy_frag(struct sk_buff *skb, struct sk_buff *frame, · 658 unmodified lines | |||
| 659 | int offset, int len) | 659 | int offset, int len) |
| 660 | { | 660 | { |
| 661 | struct skb_shared_info *sh = skb_shinfo(skb); | 661 | struct skb_shared_info *sh = skb_shinfo(skb); |
| 662 | const skb_frag_t *frag = &sh->frags[-1]; | 662 | const skb_frag_t *frag = &sh->frags[0]; |
| 663 | struct page *frag_page; | 663 | struct page *frag_page; |
| 664 | void *frag_ptr; | 664 | void *frag_ptr; |
| 665 | int frag_len, frag_size; | 665 | int frag_len, frag_size; |
| @@ -672,10 +672,10 @@ __ieee80211_amsdu_copy_frag(struct sk_buff *skb, struct sk_buff *frame, · 6 unmodified lines | |||
| 672 | 672 | ||
| 673 | while (offset >= frag_size) { | 673 | while (offset >= frag_size) { |
| 674 | offset -= frag_size; | 674 | offset -= frag_size; |
| 675 | frag++; | ||
| 676 | frag_page = skb_frag_page(frag); | 675 | frag_page = skb_frag_page(frag); |
| 677 | frag_ptr = skb_frag_address(frag); | 676 | frag_ptr = skb_frag_address(frag); |
| 678 | frag_size = skb_frag_size(frag); | 677 | frag_size = skb_frag_size(frag); |
| 678 | frag++; | ||
| 679 | } | 679 | } |
| 680 | 680 | ||
| 681 | frag_ptr += offset; | 681 | frag_ptr += offset; |
| @@ -687,12 +687,12 @@ __ieee80211_amsdu_copy_frag(struct sk_buff *skb, struct sk_buff *frame, · 5 unmodified lines | |||
| 687 | len -= cur_len; | 687 | len -= cur_len; |
| 688 | 688 | ||
| 689 | while (len > 0) { | 689 | while (len > 0) { |
| 690 | frag++; | ||
| 691 | frag_len = skb_frag_size(frag); | 690 | frag_len = skb_frag_size(frag); |
| 692 | cur_len = min(len, frag_len); | 691 | cur_len = min(len, frag_len); |
| 693 | __frame_add_frag(frame, skb_frag_page(frag), | 692 | __frame_add_frag(frame, skb_frag_page(frag), |
| 694 | skb_frag_address(frag), cur_len, frag_len); | 693 | skb_frag_address(frag), cur_len, frag_len); |
| 695 | len -= cur_len; | 694 | len -= cur_len; |
| 695 | frag++; | ||
| 696 | } | 696 | } |
| 697 | } | 697 | } |
| 698 | 698 | ||
| @@ -914,11 +914,11 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev) · 215 unmodified lines | |||
| 914 | netdev_err(dev, "failed to set key %d\n", i); | 914 | netdev_err(dev, "failed to set key %d\n", i); |
| 915 | continue; | 915 | continue; |
| 916 | } | 916 | } |
| 917 | if (wdev->connect_keys->def == i) | 917 | if (wdev->connect_keys->def == i && |
| 918 | if (rdev_set_default_key(rdev, dev, i, true, true)) { | 918 | rdev_set_default_key(rdev, dev, i, true, true)) { |
| 919 | netdev_err(dev, "failed to set defkey %d\n", i); | 919 | netdev_err(dev, "failed to set defkey %d\n", i); |
| 920 | continue; | 920 | continue; |
| 921 | } | 921 | } |
| 922 | } | 922 | } |
| 923 | 923 | ||
| 924 | kzfree(wdev->connect_keys); | 924 | kzfree(wdev->connect_keys); |
| @@ -929,7 +929,6 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) · 4 unmodified lines | |||
| 929 | { | 929 | { |
| 930 | struct cfg80211_event *ev; | 930 | struct cfg80211_event *ev; |
| 931 | unsigned long flags; | 931 | unsigned long flags; |
| 932 | const u8 *bssid = NULL; | ||
| 933 | 932 | ||
| 934 | spin_lock_irqsave(&wdev->event_lock, flags); | 933 | spin_lock_irqsave(&wdev->event_lock, flags); |
| 935 | while (!list_empty(&wdev->event_list)) { | 934 | while (!list_empty(&wdev->event_list)) { |
| @@ -941,15 +940,10 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) · 5 unmodified lines | |||
| 941 | wdev_lock(wdev); | 940 | wdev_lock(wdev); |
| 942 | switch (ev->type) { | 941 | switch (ev->type) { |
| 943 | case EVENT_CONNECT_RESULT: | 942 | case EVENT_CONNECT_RESULT: |
| 944 | if (!is_zero_ether_addr(ev->cr.bssid)) | ||
| 945 | bssid = ev->cr.bssid; | ||
| 946 | __cfg80211_connect_result( | 943 | __cfg80211_connect_result( |
| 947 | wdev->netdev, bssid, | 944 | wdev->netdev, |
| 948 | ev->cr.req_ie, ev->cr.req_ie_len, | 945 | &ev->cr, |
| 949 | ev->cr.resp_ie, ev->cr.resp_ie_len, | 946 | ev->cr.status == WLAN_STATUS_SUCCESS); |
| 950 | ev->cr.status, | ||
| 951 | ev->cr.status == WLAN_STATUS_SUCCESS, | ||
| 952 | ev->cr.bss, ev->cr.timeout_reason); | ||
| 953 | break; | 947 | break; |
| 954 | case EVENT_ROAMED: | 948 | case EVENT_ROAMED: |
| 955 | __cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie, | 949 | __cfg80211_roamed(wdev, ev->rm.bss, ev->rm.req_ie, |
| @@ -991,7 +985,7 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev) · 35 unmodified lines | |||
| 991 | 985 | ||
| 992 | int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | 986 | int cfg80211_change_iface(struct cfg80211_registered_device *rdev, |
| 993 | struct net_device *dev, enum nl80211_iftype ntype, | 987 | struct net_device *dev, enum nl80211_iftype ntype, |
| 994 | u32 *flags, struct vif_params *params) | 988 | struct vif_params *params) |
| 995 | { | 989 | { |
| 996 | int err; | 990 | int err; |
| 997 | enum nl80211_iftype otype = dev->ieee80211_ptr->iftype; | 991 | enum nl80211_iftype otype = dev->ieee80211_ptr->iftype; |
| @@ -1049,7 +1043,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, · 51 unmodified lines | |||
| 1049 | cfg80211_process_rdev_events(rdev); | 1043 | cfg80211_process_rdev_events(rdev); |
| 1050 | } | 1044 | } |
| 1051 | 1045 | ||
| 1052 | err = rdev_change_virtual_intf(rdev, dev, ntype, flags, params); | 1046 | err = rdev_change_virtual_intf(rdev, dev, ntype, params); |
| 1053 | 1047 | ||
| 1054 | WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype); | 1048 | WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype); |
| 1055 | 1049 | ||
| @@ -1097,6 +1091,35 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, · 41 unmodified lines | |||
| 1097 | return err; | 1091 | return err; |
| 1098 | } | 1092 | } |
| 1099 | 1093 | ||
| 1094 | static u32 cfg80211_calculate_bitrate_ht(struct rate_info *rate) | ||
| 1095 | { | ||
| 1096 | int modulation, streams, bitrate; | ||
| 1097 | |||
| 1098 | /* the formula below does only work for MCS values smaller than 32 */ | ||
| 1099 | if (WARN_ON_ONCE(rate->mcs >= 32)) | ||
| 1100 | return 0; | ||
| 1101 | |||
| 1102 | modulation = rate->mcs & 7; | ||
| 1103 | streams = (rate->mcs >> 3) + 1; | ||
| 1104 | |||
| 1105 | bitrate = (rate->bw == RATE_INFO_BW_40) ? 13500000 : 6500000; | ||
| 1106 | |||
| 1107 | if (modulation < 4) | ||
| 1108 | bitrate *= (modulation + 1); | ||
| 1109 | else if (modulation == 4) | ||
| 1110 | bitrate *= (modulation + 2); | ||
| 1111 | else | ||
| 1112 | bitrate *= (modulation + 3); | ||
| 1113 | |||
| 1114 | bitrate *= streams; | ||
| 1115 | |||
| 1116 | if (rate->flags & RATE_INFO_FLAGS_SHORT_GI) | ||
| 1117 | bitrate = (bitrate / 9) * 10; | ||
| 1118 | |||
| 1119 | /* do NOT round down here */ | ||
| 1120 | return (bitrate + 50000) / 100000; | ||
| 1121 | } | ||
| 1122 | |||
| 1100 | static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate) | 1123 | static u32 cfg80211_calculate_bitrate_60g(struct rate_info *rate) |
| 1101 | { | 1124 | { |
| 1102 | static const u32 __mcs2bitrate[] = { | 1125 | static const u32 __mcs2bitrate[] = { |
| @@ -1230,39 +1253,14 @@ static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate) · 127 unmodified lines | |||
| 1230 | 1253 | ||
| 1231 | u32 cfg80211_calculate_bitrate(struct rate_info *rate) | 1254 | u32 cfg80211_calculate_bitrate(struct rate_info *rate) |
| 1232 | { | 1255 | { |
| 1233 | int modulation, streams, bitrate; | 1256 | if (rate->flags & RATE_INFO_FLAGS_MCS) |
| 1234 | 1257 | return cfg80211_calculate_bitrate_ht(rate); | |
| 1235 | if (!(rate->flags & RATE_INFO_FLAGS_MCS) && | ||
| 1236 | !(rate->flags & RATE_INFO_FLAGS_VHT_MCS)) | ||
| 1237 | return rate->legacy; | ||
| 1238 | if (rate->flags & RATE_INFO_FLAGS_60G) | 1258 | if (rate->flags & RATE_INFO_FLAGS_60G) |
| 1239 | return cfg80211_calculate_bitrate_60g(rate); | 1259 | return cfg80211_calculate_bitrate_60g(rate); |
| 1240 | if (rate->flags & RATE_INFO_FLAGS_VHT_MCS) | 1260 | if (rate->flags & RATE_INFO_FLAGS_VHT_MCS) |
| 1241 | return cfg80211_calculate_bitrate_vht(rate); | 1261 | return cfg80211_calculate_bitrate_vht(rate); |
| 1242 | 1262 | ||
| 1243 | /* the formula below does only work for MCS values smaller than 32 */ | 1263 | return rate->legacy; |
| 1244 | if (WARN_ON_ONCE(rate->mcs >= 32)) | ||
| 1245 | return 0; | ||
| 1246 | |||
| 1247 | modulation = rate->mcs & 7; | ||
| 1248 | streams = (rate->mcs >> 3) + 1; | ||
| 1249 | |||
| 1250 | bitrate = (rate->bw == RATE_INFO_BW_40) ? 13500000 : 6500000; | ||
| 1251 | |||
| 1252 | if (modulation < 4) | ||
| 1253 | bitrate *= (modulation + 1); | ||
| 1254 | else if (modulation == 4) | ||
| 1255 | bitrate *= (modulation + 2); | ||
| 1256 | else | ||
| 1257 | bitrate *= (modulation + 3); | ||
| 1258 | |||
| 1259 | bitrate *= streams; | ||
| 1260 | |||
| 1261 | if (rate->flags & RATE_INFO_FLAGS_SHORT_GI) | ||
| 1262 | bitrate = (bitrate / 9) * 10; | ||
| 1263 | |||
| 1264 | /* do NOT round down here */ | ||
| 1265 | return (bitrate + 50000) / 100000; | ||
| 1266 | } | 1264 | } |
| 1267 | EXPORT_SYMBOL(cfg80211_calculate_bitrate); | 1265 | EXPORT_SYMBOL(cfg80211_calculate_bitrate); |
| 1268 | 1266 | ||
| @@ -62,7 +62,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, · 61 unmodified lines | |||
| 62 | 62 | ||
| 63 | memset(&vifparams, 0, sizeof(vifparams)); | 63 | memset(&vifparams, 0, sizeof(vifparams)); |
| 64 | 64 | ||
| 65 | return cfg80211_change_iface(rdev, dev, type, NULL, &vifparams); | 65 | return cfg80211_change_iface(rdev, dev, type, &vifparams); |
| 66 | } | 66 | } |
| 67 | EXPORT_WEXT_HANDLER(cfg80211_wext_siwmode); | 67 | EXPORT_WEXT_HANDLER(cfg80211_wext_siwmode); |
| 68 | 68 | ||