提交 933faa43 编写于 作者: J John W. Linville
...@@ -132,9 +132,7 @@ ...@@ -132,9 +132,7 @@
!Finclude/net/cfg80211.h cfg80211_send_rx_assoc !Finclude/net/cfg80211.h cfg80211_send_rx_assoc
!Finclude/net/cfg80211.h cfg80211_send_assoc_timeout !Finclude/net/cfg80211.h cfg80211_send_assoc_timeout
!Finclude/net/cfg80211.h cfg80211_send_deauth !Finclude/net/cfg80211.h cfg80211_send_deauth
!Finclude/net/cfg80211.h __cfg80211_send_deauth
!Finclude/net/cfg80211.h cfg80211_send_disassoc !Finclude/net/cfg80211.h cfg80211_send_disassoc
!Finclude/net/cfg80211.h __cfg80211_send_disassoc
!Finclude/net/cfg80211.h cfg80211_ibss_joined !Finclude/net/cfg80211.h cfg80211_ibss_joined
!Finclude/net/cfg80211.h cfg80211_connect_result !Finclude/net/cfg80211.h cfg80211_connect_result
!Finclude/net/cfg80211.h cfg80211_roamed !Finclude/net/cfg80211.h cfg80211_roamed
......
...@@ -1347,14 +1347,6 @@ struct il_rx_mpdu_res_start { ...@@ -1347,14 +1347,6 @@ struct il_rx_mpdu_res_start {
#define TX_CMD_SEC_SHIFT 6 #define TX_CMD_SEC_SHIFT 6
#define TX_CMD_SEC_KEY128 0x08 #define TX_CMD_SEC_KEY128 0x08
/*
* security overhead sizes
*/
#define WEP_IV_LEN 4
#define WEP_ICV_LEN 4
#define CCMP_MIC_LEN 8
#define TKIP_ICV_LEN 4
/* /*
* C_TX = 0x1c (command) * C_TX = 0x1c (command)
*/ */
......
...@@ -1220,14 +1220,6 @@ struct iwl_rx_mpdu_res_start { ...@@ -1220,14 +1220,6 @@ struct iwl_rx_mpdu_res_start {
#define TX_CMD_SEC_SHIFT 6 #define TX_CMD_SEC_SHIFT 6
#define TX_CMD_SEC_KEY128 0x08 #define TX_CMD_SEC_KEY128 0x08
/*
* security overhead sizes
*/
#define WEP_IV_LEN 4
#define WEP_ICV_LEN 4
#define CCMP_MIC_LEN 8
#define TKIP_ICV_LEN 4
/* /*
* REPLY_TX = 0x1c (command) * REPLY_TX = 0x1c (command)
*/ */
......
...@@ -84,15 +84,6 @@ static const struct ieee80211_iface_limit iwl_mvm_limits[] = { ...@@ -84,15 +84,6 @@ static const struct ieee80211_iface_limit iwl_mvm_limits[] = {
.types = BIT(NL80211_IFTYPE_STATION) | .types = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP), BIT(NL80211_IFTYPE_AP),
}, },
{
.max = 1,
.types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO),
},
{
.max = 1,
.types = BIT(NL80211_IFTYPE_P2P_DEVICE),
},
}; };
static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = { static const struct ieee80211_iface_combination iwl_mvm_iface_combinations[] = {
...@@ -173,10 +164,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) ...@@ -173,10 +164,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->chanctx_data_size = sizeof(u16); hw->chanctx_data_size = sizeof(u16);
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_AP);
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_P2P_DEVICE);
hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
WIPHY_FLAG_DISABLE_BEACON_HINTS | WIPHY_FLAG_DISABLE_BEACON_HINTS |
......
...@@ -224,13 +224,13 @@ static void iwl_pcie_txq_update_byte_cnt_tbl(struct iwl_trans *trans, ...@@ -224,13 +224,13 @@ static void iwl_pcie_txq_update_byte_cnt_tbl(struct iwl_trans *trans,
switch (sec_ctl & TX_CMD_SEC_MSK) { switch (sec_ctl & TX_CMD_SEC_MSK) {
case TX_CMD_SEC_CCM: case TX_CMD_SEC_CCM:
len += CCMP_MIC_LEN; len += IEEE80211_CCMP_MIC_LEN;
break; break;
case TX_CMD_SEC_TKIP: case TX_CMD_SEC_TKIP:
len += TKIP_ICV_LEN; len += IEEE80211_TKIP_ICV_LEN;
break; break;
case TX_CMD_SEC_WEP: case TX_CMD_SEC_WEP:
len += WEP_IV_LEN + WEP_ICV_LEN; len += IEEE80211_WEP_IV_LEN + IEEE80211_WEP_ICV_LEN;
break; break;
} }
......
...@@ -1723,11 +1723,11 @@ static void mac80211_hwsim_free(void) ...@@ -1723,11 +1723,11 @@ static void mac80211_hwsim_free(void)
class_destroy(hwsim_class); class_destroy(hwsim_class);
} }
static struct platform_driver mac80211_hwsim_driver = {
static struct device_driver mac80211_hwsim_driver = { .driver = {
.name = "mac80211_hwsim", .name = "mac80211_hwsim",
.bus = &platform_bus_type, .owner = THIS_MODULE,
.owner = THIS_MODULE, },
}; };
static const struct net_device_ops hwsim_netdev_ops = { static const struct net_device_ops hwsim_netdev_ops = {
...@@ -2169,7 +2169,6 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = { ...@@ -2169,7 +2169,6 @@ static const struct ieee80211_iface_limit hwsim_if_limits[] = {
#endif #endif
BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO) }, BIT(NL80211_IFTYPE_P2P_GO) },
{ .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) },
}; };
static struct ieee80211_iface_combination hwsim_if_comb = { static struct ieee80211_iface_combination hwsim_if_comb = {
...@@ -2219,7 +2218,7 @@ static int __init init_mac80211_hwsim(void) ...@@ -2219,7 +2218,7 @@ static int __init init_mac80211_hwsim(void)
spin_lock_init(&hwsim_radio_lock); spin_lock_init(&hwsim_radio_lock);
INIT_LIST_HEAD(&hwsim_radios); INIT_LIST_HEAD(&hwsim_radios);
err = driver_register(&mac80211_hwsim_driver); err = platform_driver_register(&mac80211_hwsim_driver);
if (err) if (err)
return err; return err;
...@@ -2254,7 +2253,7 @@ static int __init init_mac80211_hwsim(void) ...@@ -2254,7 +2253,7 @@ static int __init init_mac80211_hwsim(void)
err = -ENOMEM; err = -ENOMEM;
goto failed_drvdata; goto failed_drvdata;
} }
data->dev->driver = &mac80211_hwsim_driver; data->dev->driver = &mac80211_hwsim_driver.driver;
err = device_bind_driver(data->dev); err = device_bind_driver(data->dev);
if (err != 0) { if (err != 0) {
printk(KERN_DEBUG printk(KERN_DEBUG
...@@ -2295,8 +2294,7 @@ static int __init init_mac80211_hwsim(void) ...@@ -2295,8 +2294,7 @@ static int __init init_mac80211_hwsim(void)
BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_MESH_POINT) | BIT(NL80211_IFTYPE_MESH_POINT);
BIT(NL80211_IFTYPE_P2P_DEVICE);
hw->flags = IEEE80211_HW_MFP_CAPABLE | hw->flags = IEEE80211_HW_MFP_CAPABLE |
IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_SIGNAL_DBM |
...@@ -2564,7 +2562,7 @@ static int __init init_mac80211_hwsim(void) ...@@ -2564,7 +2562,7 @@ static int __init init_mac80211_hwsim(void)
failed: failed:
mac80211_hwsim_free(); mac80211_hwsim_free();
failed_unregister_driver: failed_unregister_driver:
driver_unregister(&mac80211_hwsim_driver); platform_driver_unregister(&mac80211_hwsim_driver);
return err; return err;
} }
module_init(init_mac80211_hwsim); module_init(init_mac80211_hwsim);
...@@ -2577,6 +2575,6 @@ static void __exit exit_mac80211_hwsim(void) ...@@ -2577,6 +2575,6 @@ static void __exit exit_mac80211_hwsim(void)
mac80211_hwsim_free(); mac80211_hwsim_free();
unregister_netdev(hwsim_mon); unregister_netdev(hwsim_mon);
driver_unregister(&mac80211_hwsim_driver); platform_driver_unregister(&mac80211_hwsim_driver);
} }
module_exit(exit_mac80211_hwsim); module_exit(exit_mac80211_hwsim);
...@@ -1829,6 +1829,15 @@ enum ieee80211_key_len { ...@@ -1829,6 +1829,15 @@ enum ieee80211_key_len {
WLAN_KEY_LEN_AES_CMAC = 16, WLAN_KEY_LEN_AES_CMAC = 16,
}; };
#define IEEE80211_WEP_IV_LEN 4
#define IEEE80211_WEP_ICV_LEN 4
#define IEEE80211_CCMP_HDR_LEN 8
#define IEEE80211_CCMP_MIC_LEN 8
#define IEEE80211_CCMP_PN_LEN 6
#define IEEE80211_TKIP_IV_LEN 8
#define IEEE80211_TKIP_ICV_LEN 4
#define IEEE80211_CMAC_PN_LEN 6
/* Public action codes */ /* Public action codes */
enum ieee80211_pub_actioncode { enum ieee80211_pub_actioncode {
WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4, WLAN_PUB_ACTION_EXT_CHANSW_ANN = 4,
......
...@@ -753,6 +753,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy, ...@@ -753,6 +753,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy,
* @STATION_INFO_LOCAL_PM: @local_pm filled * @STATION_INFO_LOCAL_PM: @local_pm filled
* @STATION_INFO_PEER_PM: @peer_pm filled * @STATION_INFO_PEER_PM: @peer_pm filled
* @STATION_INFO_NONPEER_PM: @nonpeer_pm filled * @STATION_INFO_NONPEER_PM: @nonpeer_pm filled
* @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled
* @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled
*/ */
enum station_info_flags { enum station_info_flags {
STATION_INFO_INACTIVE_TIME = 1<<0, STATION_INFO_INACTIVE_TIME = 1<<0,
...@@ -781,6 +783,8 @@ enum station_info_flags { ...@@ -781,6 +783,8 @@ enum station_info_flags {
STATION_INFO_NONPEER_PM = 1<<23, STATION_INFO_NONPEER_PM = 1<<23,
STATION_INFO_RX_BYTES64 = 1<<24, STATION_INFO_RX_BYTES64 = 1<<24,
STATION_INFO_TX_BYTES64 = 1<<25, STATION_INFO_TX_BYTES64 = 1<<25,
STATION_INFO_CHAIN_SIGNAL = 1<<26,
STATION_INFO_CHAIN_SIGNAL_AVG = 1<<27,
}; };
/** /**
...@@ -857,6 +861,8 @@ struct sta_bss_parameters { ...@@ -857,6 +861,8 @@ struct sta_bss_parameters {
u16 beacon_interval; u16 beacon_interval;
}; };
#define IEEE80211_MAX_CHAINS 4
/** /**
* struct station_info - station information * struct station_info - station information
* *
...@@ -874,6 +880,9 @@ struct sta_bss_parameters { ...@@ -874,6 +880,9 @@ struct sta_bss_parameters {
* For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_. * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
* @signal_avg: Average signal strength, type depends on the wiphy's signal_type. * @signal_avg: Average signal strength, type depends on the wiphy's signal_type.
* For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_. * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.
* @chains: bitmask for filled values in @chain_signal, @chain_signal_avg
* @chain_signal: per-chain signal strength of last received packet in dBm
* @chain_signal_avg: per-chain signal strength average in dBm
* @txrate: current unicast bitrate from this station * @txrate: current unicast bitrate from this station
* @rxrate: current unicast bitrate to this station * @rxrate: current unicast bitrate to this station
* @rx_packets: packets received from this station * @rx_packets: packets received from this station
...@@ -909,6 +918,11 @@ struct station_info { ...@@ -909,6 +918,11 @@ struct station_info {
u8 plink_state; u8 plink_state;
s8 signal; s8 signal;
s8 signal_avg; s8 signal_avg;
u8 chains;
s8 chain_signal[IEEE80211_MAX_CHAINS];
s8 chain_signal_avg[IEEE80211_MAX_CHAINS];
struct rate_info txrate; struct rate_info txrate;
struct rate_info rxrate; struct rate_info rxrate;
u32 rx_packets; u32 rx_packets;
...@@ -1147,6 +1161,7 @@ struct mesh_config { ...@@ -1147,6 +1161,7 @@ struct mesh_config {
* @sync_method: which synchronization method to use * @sync_method: which synchronization method to use
* @path_sel_proto: which path selection protocol to use * @path_sel_proto: which path selection protocol to use
* @path_metric: which metric to use * @path_metric: which metric to use
* @auth_id: which authentication method this mesh is using
* @ie: vendor information elements (optional) * @ie: vendor information elements (optional)
* @ie_len: length of vendor information elements * @ie_len: length of vendor information elements
* @is_authenticated: this mesh requires authentication * @is_authenticated: this mesh requires authentication
...@@ -1165,6 +1180,7 @@ struct mesh_setup { ...@@ -1165,6 +1180,7 @@ struct mesh_setup {
u8 sync_method; u8 sync_method;
u8 path_sel_proto; u8 path_sel_proto;
u8 path_metric; u8 path_metric;
u8 auth_id;
const u8 *ie; const u8 *ie;
u8 ie_len; u8 ie_len;
bool is_authenticated; bool is_authenticated;
...@@ -1241,6 +1257,7 @@ struct cfg80211_ssid { ...@@ -1241,6 +1257,7 @@ struct cfg80211_ssid {
* @scan_start: time (in jiffies) when the scan started * @scan_start: time (in jiffies) when the scan started
* @wdev: the wireless device to scan for * @wdev: the wireless device to scan for
* @aborted: (internal) scan request was notified as aborted * @aborted: (internal) scan request was notified as aborted
* @notified: (internal) scan request was notified as done or aborted
* @no_cck: used to send probe requests at non CCK rate in 2GHz band * @no_cck: used to send probe requests at non CCK rate in 2GHz band
*/ */
struct cfg80211_scan_request { struct cfg80211_scan_request {
...@@ -1258,7 +1275,7 @@ struct cfg80211_scan_request { ...@@ -1258,7 +1275,7 @@ struct cfg80211_scan_request {
/* internal */ /* internal */
struct wiphy *wiphy; struct wiphy *wiphy;
unsigned long scan_start; unsigned long scan_start;
bool aborted; bool aborted, notified;
bool no_cck; bool no_cck;
/* keep last */ /* keep last */
...@@ -1850,7 +1867,9 @@ struct cfg80211_update_ft_ies_params { ...@@ -1850,7 +1867,9 @@ struct cfg80211_update_ft_ies_params {
* @get_mpath: get a mesh path for the given parameters * @get_mpath: get a mesh path for the given parameters
* @dump_mpath: dump mesh path callback -- resume dump at index @idx * @dump_mpath: dump mesh path callback -- resume dump at index @idx
* @join_mesh: join the mesh network with the specified parameters * @join_mesh: join the mesh network with the specified parameters
* (invoked with the wireless_dev mutex held)
* @leave_mesh: leave the current mesh network * @leave_mesh: leave the current mesh network
* (invoked with the wireless_dev mutex held)
* *
* @get_mesh_config: Get the current mesh configuration * @get_mesh_config: Get the current mesh configuration
* *
...@@ -1877,20 +1896,28 @@ struct cfg80211_update_ft_ies_params { ...@@ -1877,20 +1896,28 @@ struct cfg80211_update_ft_ies_params {
* the scan/scan_done bracket too. * the scan/scan_done bracket too.
* *
* @auth: Request to authenticate with the specified peer * @auth: Request to authenticate with the specified peer
* (invoked with the wireless_dev mutex held)
* @assoc: Request to (re)associate with the specified peer * @assoc: Request to (re)associate with the specified peer
* (invoked with the wireless_dev mutex held)
* @deauth: Request to deauthenticate from the specified peer * @deauth: Request to deauthenticate from the specified peer
* (invoked with the wireless_dev mutex held)
* @disassoc: Request to disassociate from the specified peer * @disassoc: Request to disassociate from the specified peer
* (invoked with the wireless_dev mutex held)
* *
* @connect: Connect to the ESS with the specified parameters. When connected, * @connect: Connect to the ESS with the specified parameters. When connected,
* call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS. * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS.
* If the connection fails for some reason, call cfg80211_connect_result() * If the connection fails for some reason, call cfg80211_connect_result()
* with the status from the AP. * with the status from the AP.
* (invoked with the wireless_dev mutex held)
* @disconnect: Disconnect from the BSS/ESS. * @disconnect: Disconnect from the BSS/ESS.
* (invoked with the wireless_dev mutex held)
* *
* @join_ibss: Join the specified IBSS (or create if necessary). Once done, call * @join_ibss: Join the specified IBSS (or create if necessary). Once done, call
* cfg80211_ibss_joined(), also call that function when changing BSSID due * cfg80211_ibss_joined(), also call that function when changing BSSID due
* to a merge. * to a merge.
* (invoked with the wireless_dev mutex held)
* @leave_ibss: Leave the IBSS. * @leave_ibss: Leave the IBSS.
* (invoked with the wireless_dev mutex held)
* *
* @set_mcast_rate: Set the specified multicast rate (only if vif is in ADHOC or * @set_mcast_rate: Set the specified multicast rate (only if vif is in ADHOC or
* MESH mode) * MESH mode)
...@@ -2556,6 +2583,9 @@ struct wiphy_wowlan_support { ...@@ -2556,6 +2583,9 @@ struct wiphy_wowlan_support {
* may request, if implemented. * may request, if implemented.
* *
* @wowlan: WoWLAN support information * @wowlan: WoWLAN support information
* @wowlan_config: current WoWLAN configuration; this should usually not be
* used since access to it is necessarily racy, use the parameter passed
* to the suspend() operation instead.
* *
* @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features. * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
* @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden. * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden.
...@@ -2623,6 +2653,7 @@ struct wiphy { ...@@ -2623,6 +2653,7 @@ struct wiphy {
#ifdef CONFIG_PM #ifdef CONFIG_PM
struct wiphy_wowlan_support wowlan; struct wiphy_wowlan_support wowlan;
struct cfg80211_wowlan *wowlan_config;
#endif #endif
u16 max_remain_on_channel_duration; u16 max_remain_on_channel_duration;
...@@ -2834,7 +2865,8 @@ struct cfg80211_cached_keys; ...@@ -2834,7 +2865,8 @@ struct cfg80211_cached_keys;
* by cfg80211 on change_interface * by cfg80211 on change_interface
* @mgmt_registrations: list of registrations for management frames * @mgmt_registrations: list of registrations for management frames
* @mgmt_registrations_lock: lock for the list * @mgmt_registrations_lock: lock for the list
* @mtx: mutex used to lock data in this struct * @mtx: mutex used to lock data in this struct, may be used by drivers
* and some API functions require it held
* @cleanup_work: work struct used for cleanup that can't be done directly * @cleanup_work: work struct used for cleanup that can't be done directly
* @beacon_interval: beacon interval used on this device for transmitting * @beacon_interval: beacon interval used on this device for transmitting
* beacons, 0 when not valid * beacons, 0 when not valid
...@@ -2858,8 +2890,6 @@ struct wireless_dev { ...@@ -2858,8 +2890,6 @@ struct wireless_dev {
struct mutex mtx; struct mutex mtx;
struct work_struct cleanup_work;
bool use_4addr, p2p_started; bool use_4addr, p2p_started;
u8 address[ETH_ALEN] __aligned(sizeof(u16)); u8 address[ETH_ALEN] __aligned(sizeof(u16));
...@@ -2989,6 +3019,15 @@ struct ieee80211_rate * ...@@ -2989,6 +3019,15 @@ struct ieee80211_rate *
ieee80211_get_response_rate(struct ieee80211_supported_band *sband, ieee80211_get_response_rate(struct ieee80211_supported_band *sband,
u32 basic_rates, int bitrate); u32 basic_rates, int bitrate);
/**
* ieee80211_mandatory_rates - get mandatory rates for a given band
* @sband: the band to look for rates in
*
* This function returns a bitmap of the mandatory rates for the given
* band, bits are set according to the rate position in the bitrates array.
*/
u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband);
/* /*
* Radiotap parsing functions -- for controlled injection support * Radiotap parsing functions -- for controlled injection support
* *
...@@ -3400,7 +3439,8 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss); ...@@ -3400,7 +3439,8 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss);
* This function is called whenever an authentication has been processed in * This function is called whenever an authentication has been processed in
* station mode. The driver is required to call either this function or * station mode. The driver is required to call either this function or
* cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth() * cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth()
* call. This function may sleep. * call. This function may sleep. The caller must hold the corresponding wdev's
* mutex.
*/ */
void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len); void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
...@@ -3409,7 +3449,8 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len); ...@@ -3409,7 +3449,8 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
* @dev: network device * @dev: network device
* @addr: The MAC address of the device with which the authentication timed out * @addr: The MAC address of the device with which the authentication timed out
* *
* This function may sleep. * This function may sleep. The caller must hold the corresponding wdev's
* mutex.
*/ */
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr); void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
...@@ -3424,7 +3465,8 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr); ...@@ -3424,7 +3465,8 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
* This function is called whenever a (re)association response has been * This function is called whenever a (re)association response has been
* processed in station mode. The driver is required to call either this * processed in station mode. The driver is required to call either this
* function or cfg80211_send_assoc_timeout() to indicate the result of * function or cfg80211_send_assoc_timeout() to indicate the result of
* cfg80211_ops::assoc() call. This function may sleep. * cfg80211_ops::assoc() call. This function may sleep. The caller must hold
* the corresponding wdev's mutex.
*/ */
void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
const u8 *buf, size_t len); const u8 *buf, size_t len);
...@@ -3434,7 +3476,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, ...@@ -3434,7 +3476,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
* @dev: network device * @dev: network device
* @addr: The MAC address of the device with which the association timed out * @addr: The MAC address of the device with which the association timed out
* *
* This function may sleep. * This function may sleep. The caller must hold the corresponding wdev's mutex.
*/ */
void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr); void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
...@@ -3446,20 +3488,11 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr); ...@@ -3446,20 +3488,11 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
* *
* This function is called whenever deauthentication has been processed in * This function is called whenever deauthentication has been processed in
* station mode. This includes both received deauthentication frames and * station mode. This includes both received deauthentication frames and
* locally generated ones. This function may sleep. * locally generated ones. This function may sleep. The caller must hold the
* corresponding wdev's mutex.
*/ */
void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len); void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
/**
* __cfg80211_send_deauth - notification of processed deauthentication
* @dev: network device
* @buf: deauthentication frame (header + body)
* @len: length of the frame data
*
* Like cfg80211_send_deauth(), but doesn't take the wdev lock.
*/
void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
/** /**
* cfg80211_send_disassoc - notification of processed disassociation * cfg80211_send_disassoc - notification of processed disassociation
* @dev: network device * @dev: network device
...@@ -3468,21 +3501,11 @@ void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len); ...@@ -3468,21 +3501,11 @@ void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
* *
* This function is called whenever disassociation has been processed in * This function is called whenever disassociation has been processed in
* station mode. This includes both received disassociation frames and locally * station mode. This includes both received disassociation frames and locally
* generated ones. This function may sleep. * generated ones. This function may sleep. The caller must hold the
* corresponding wdev's mutex.
*/ */
void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len); void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len);
/**
* __cfg80211_send_disassoc - notification of processed disassociation
* @dev: network device
* @buf: disassociation response frame (header + body)
* @len: length of the frame data
*
* Like cfg80211_send_disassoc(), but doesn't take the wdev lock.
*/
void __cfg80211_send_disassoc(struct net_device *dev, const u8 *buf,
size_t len);
/** /**
* cfg80211_send_unprot_deauth - notification of unprotected deauthentication * cfg80211_send_unprot_deauth - notification of unprotected deauthentication
* @dev: network device * @dev: network device
...@@ -4153,6 +4176,7 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev, ...@@ -4153,6 +4176,7 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
* cfg80211_crit_proto_stopped() - indicate critical protocol stopped by driver. * cfg80211_crit_proto_stopped() - indicate critical protocol stopped by driver.
* *
* @wdev: the wireless device for which critical protocol is stopped. * @wdev: the wireless device for which critical protocol is stopped.
* @gfp: allocation flags
* *
* This function can be called by the driver to indicate it has reverted * This function can be called by the driver to indicate it has reverted
* operation back to normal. One reason could be that the duration given * operation back to normal. One reason could be that the duration given
......
...@@ -269,6 +269,7 @@ enum ieee80211_radiotap_type { ...@@ -269,6 +269,7 @@ enum ieee80211_radiotap_type {
#define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04 #define IEEE80211_RADIOTAP_MCS_HAVE_GI 0x04
#define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08 #define IEEE80211_RADIOTAP_MCS_HAVE_FMT 0x08
#define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10 #define IEEE80211_RADIOTAP_MCS_HAVE_FEC 0x10
#define IEEE80211_RADIOTAP_MCS_HAVE_STBC 0x20
#define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03 #define IEEE80211_RADIOTAP_MCS_BW_MASK 0x03
#define IEEE80211_RADIOTAP_MCS_BW_20 0 #define IEEE80211_RADIOTAP_MCS_BW_20 0
...@@ -278,6 +279,12 @@ enum ieee80211_radiotap_type { ...@@ -278,6 +279,12 @@ enum ieee80211_radiotap_type {
#define IEEE80211_RADIOTAP_MCS_SGI 0x04 #define IEEE80211_RADIOTAP_MCS_SGI 0x04
#define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08 #define IEEE80211_RADIOTAP_MCS_FMT_GF 0x08
#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 #define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
#define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60
#define IEEE80211_RADIOTAP_MCS_STBC_1 1
#define IEEE80211_RADIOTAP_MCS_STBC_2 2
#define IEEE80211_RADIOTAP_MCS_STBC_3 3
#define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5
/* For IEEE80211_RADIOTAP_AMPDU_STATUS */ /* For IEEE80211_RADIOTAP_AMPDU_STATUS */
#define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001 #define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001
......
...@@ -805,6 +805,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) ...@@ -805,6 +805,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* on this subframe * on this subframe
* @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC
* is stored in the @ampdu_delimiter_crc field) * is stored in the @ampdu_delimiter_crc field)
* @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3
*/ */
enum mac80211_rx_flags { enum mac80211_rx_flags {
RX_FLAG_MMIC_ERROR = BIT(0), RX_FLAG_MMIC_ERROR = BIT(0),
...@@ -832,8 +833,11 @@ enum mac80211_rx_flags { ...@@ -832,8 +833,11 @@ enum mac80211_rx_flags {
RX_FLAG_80MHZ = BIT(23), RX_FLAG_80MHZ = BIT(23),
RX_FLAG_80P80MHZ = BIT(24), RX_FLAG_80P80MHZ = BIT(24),
RX_FLAG_160MHZ = BIT(25), RX_FLAG_160MHZ = BIT(25),
RX_FLAG_STBC_MASK = BIT(26) | BIT(27),
}; };
#define RX_FLAG_STBC_SHIFT 26
/** /**
* struct ieee80211_rx_status - receive status * struct ieee80211_rx_status - receive status
* *
...@@ -850,6 +854,10 @@ enum mac80211_rx_flags { ...@@ -850,6 +854,10 @@ enum mac80211_rx_flags {
* @signal: signal strength when receiving this frame, either in dBm, in dB or * @signal: signal strength when receiving this frame, either in dBm, in dB or
* unspecified depending on the hardware capabilities flags * unspecified depending on the hardware capabilities flags
* @IEEE80211_HW_SIGNAL_* * @IEEE80211_HW_SIGNAL_*
* @chains: bitmask of receive chains for which separate signal strength
* values were filled.
* @chain_signal: per-chain signal strength, in dBm (unlike @signal, doesn't
* support dB or unspecified units)
* @antenna: antenna used * @antenna: antenna used
* @rate_idx: index of data rate into band's supported rates or MCS index if * @rate_idx: index of data rate into band's supported rates or MCS index if
* HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT) * HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
...@@ -881,6 +889,8 @@ struct ieee80211_rx_status { ...@@ -881,6 +889,8 @@ struct ieee80211_rx_status {
u8 band; u8 band;
u8 antenna; u8 antenna;
s8 signal; s8 signal;
u8 chains;
s8 chain_signal[IEEE80211_MAX_CHAINS];
u8 ampdu_delimiter_crc; u8 ampdu_delimiter_crc;
u8 vendor_radiotap_align; u8 vendor_radiotap_align;
u8 vendor_radiotap_oui[3]; u8 vendor_radiotap_oui[3];
...@@ -1235,7 +1245,7 @@ enum ieee80211_sta_rx_bandwidth { ...@@ -1235,7 +1245,7 @@ enum ieee80211_sta_rx_bandwidth {
* struct ieee80211_sta_rates - station rate selection table * struct ieee80211_sta_rates - station rate selection table
* *
* @rcu_head: RCU head used for freeing the table on update * @rcu_head: RCU head used for freeing the table on update
* @rates: transmit rates/flags to be used by default. * @rate: transmit rates/flags to be used by default.
* Overriding entries per-packet is possible by using cb tx control. * Overriding entries per-packet is possible by using cb tx control.
*/ */
struct ieee80211_sta_rates { struct ieee80211_sta_rates {
...@@ -1276,7 +1286,7 @@ struct ieee80211_sta_rates { ...@@ -1276,7 +1286,7 @@ struct ieee80211_sta_rates {
* notifications and capabilities. The value is only valid after * notifications and capabilities. The value is only valid after
* the station moves to associated state. * the station moves to associated state.
* @smps_mode: current SMPS mode (off, static or dynamic) * @smps_mode: current SMPS mode (off, static or dynamic)
* @tx_rates: rate control selection table * @rates: rate control selection table
*/ */
struct ieee80211_sta { struct ieee80211_sta {
u32 supp_rates[IEEE80211_NUM_BANDS]; u32 supp_rates[IEEE80211_NUM_BANDS];
...@@ -3043,7 +3053,8 @@ void ieee80211_napi_complete(struct ieee80211_hw *hw); ...@@ -3043,7 +3053,8 @@ void ieee80211_napi_complete(struct ieee80211_hw *hw);
* This function may not be called in IRQ context. Calls to this function * This function may not be called in IRQ context. Calls to this function
* for a single hardware must be synchronized against each other. Calls to * for a single hardware must be synchronized against each other. Calls to
* this function, ieee80211_rx_ni() and ieee80211_rx_irqsafe() may not be * this function, ieee80211_rx_ni() and ieee80211_rx_irqsafe() may not be
* mixed for a single hardware. * mixed for a single hardware. Must not run concurrently with
* ieee80211_tx_status() or ieee80211_tx_status_ni().
* *
* In process context use instead ieee80211_rx_ni(). * In process context use instead ieee80211_rx_ni().
* *
...@@ -3059,7 +3070,8 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb); ...@@ -3059,7 +3070,8 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb);
* (internally defers to a tasklet.) * (internally defers to a tasklet.)
* *
* Calls to this function, ieee80211_rx() or ieee80211_rx_ni() may not * Calls to this function, ieee80211_rx() or ieee80211_rx_ni() may not
* be mixed for a single hardware. * be mixed for a single hardware.Must not run concurrently with
* ieee80211_tx_status() or ieee80211_tx_status_ni().
* *
* @hw: the hardware this frame came in on * @hw: the hardware this frame came in on
* @skb: the buffer to receive, owned by mac80211 after this call * @skb: the buffer to receive, owned by mac80211 after this call
...@@ -3073,7 +3085,8 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb); ...@@ -3073,7 +3085,8 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb);
* (internally disables bottom halves). * (internally disables bottom halves).
* *
* Calls to this function, ieee80211_rx() and ieee80211_rx_irqsafe() may * Calls to this function, ieee80211_rx() and ieee80211_rx_irqsafe() may
* not be mixed for a single hardware. * not be mixed for a single hardware. Must not run concurrently with
* ieee80211_tx_status() or ieee80211_tx_status_ni().
* *
* @hw: the hardware this frame came in on * @hw: the hardware this frame came in on
* @skb: the buffer to receive, owned by mac80211 after this call * @skb: the buffer to receive, owned by mac80211 after this call
...@@ -3196,7 +3209,8 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif, ...@@ -3196,7 +3209,8 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif,
* This function may not be called in IRQ context. Calls to this function * This function may not be called in IRQ context. Calls to this function
* for a single hardware must be synchronized against each other. Calls * for a single hardware must be synchronized against each other. Calls
* to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe() * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
* may not be mixed for a single hardware. * may not be mixed for a single hardware. Must not run concurrently with
* ieee80211_rx() or ieee80211_rx_ni().
* *
* @hw: the hardware the frame was transmitted by * @hw: the hardware the frame was transmitted by
* @skb: the frame that was transmitted, owned by mac80211 after this call * @skb: the frame that was transmitted, owned by mac80211 after this call
......
...@@ -27,6 +27,8 @@ ...@@ -27,6 +27,8 @@
#include <linux/types.h> #include <linux/types.h>
#define NL80211_GENL_NAME "nl80211"
/** /**
* DOC: Station handling * DOC: Station handling
* *
...@@ -1429,6 +1431,11 @@ enum nl80211_commands { ...@@ -1429,6 +1431,11 @@ enum nl80211_commands {
* @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which
* the connection should have increased reliability (u16). * the connection should have increased reliability (u16).
* *
* @NL80211_ATTR_PEER_AID: Association ID for the peer TDLS station (u16).
* This is similar to @NL80211_ATTR_STA_AID but with a difference of being
* allowed to be used with the first @NL80211_CMD_SET_STATION command to
* update a TDLS peer STA entry.
*
* @NL80211_ATTR_MAX: highest attribute number currently defined * @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use * @__NL80211_ATTR_AFTER_LAST: internal use
*/ */
...@@ -1727,6 +1734,8 @@ enum nl80211_attrs { ...@@ -1727,6 +1734,8 @@ enum nl80211_attrs {
NL80211_ATTR_CRIT_PROT_ID, NL80211_ATTR_CRIT_PROT_ID,
NL80211_ATTR_MAX_CRIT_PROT_DURATION, NL80211_ATTR_MAX_CRIT_PROT_DURATION,
NL80211_ATTR_PEER_AID,
/* add attributes here, update the policy in nl80211.c */ /* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST, __NL80211_ATTR_AFTER_LAST,
...@@ -1991,6 +2000,10 @@ enum nl80211_sta_bss_param { ...@@ -1991,6 +2000,10 @@ enum nl80211_sta_bss_param {
* @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode * @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode
* @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards * @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards
* non-peer STA * non-peer STA
* @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU
* Contains a nested array of signal strength attributes (u8, dBm)
* @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average
* Same format as NL80211_STA_INFO_CHAIN_SIGNAL.
* @__NL80211_STA_INFO_AFTER_LAST: internal * @__NL80211_STA_INFO_AFTER_LAST: internal
* @NL80211_STA_INFO_MAX: highest possible station info attribute * @NL80211_STA_INFO_MAX: highest possible station info attribute
*/ */
...@@ -2020,6 +2033,8 @@ enum nl80211_sta_info { ...@@ -2020,6 +2033,8 @@ enum nl80211_sta_info {
NL80211_STA_INFO_NONPEER_PM, NL80211_STA_INFO_NONPEER_PM,
NL80211_STA_INFO_RX_BYTES64, NL80211_STA_INFO_RX_BYTES64,
NL80211_STA_INFO_TX_BYTES64, NL80211_STA_INFO_TX_BYTES64,
NL80211_STA_INFO_CHAIN_SIGNAL,
NL80211_STA_INFO_CHAIN_SIGNAL_AVG,
/* keep last */ /* keep last */
__NL80211_STA_INFO_AFTER_LAST, __NL80211_STA_INFO_AFTER_LAST,
...@@ -2637,6 +2652,10 @@ enum nl80211_meshconf_params { ...@@ -2637,6 +2652,10 @@ enum nl80211_meshconf_params {
* @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will * @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will
* implement an MPM which handles peer allocation and state. * implement an MPM which handles peer allocation and state.
* *
* @NL80211_MESH_SETUP_AUTH_PROTOCOL: Inform the kernel of the authentication
* method (u8, as defined in IEEE 8.4.2.100.6, e.g. 0x1 for SAE).
* Default is no authentication method required.
*
* @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
* *
* @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
...@@ -2650,6 +2669,7 @@ enum nl80211_mesh_setup_params { ...@@ -2650,6 +2669,7 @@ enum nl80211_mesh_setup_params {
NL80211_MESH_SETUP_USERSPACE_AMPE, NL80211_MESH_SETUP_USERSPACE_AMPE,
NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC, NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC,
NL80211_MESH_SETUP_USERSPACE_MPM, NL80211_MESH_SETUP_USERSPACE_MPM,
NL80211_MESH_SETUP_AUTH_PROTOCOL,
/* keep last */ /* keep last */
__NL80211_MESH_SETUP_ATTR_AFTER_LAST, __NL80211_MESH_SETUP_ATTR_AFTER_LAST,
......
...@@ -85,7 +85,7 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch, ...@@ -85,7 +85,7 @@ void ieee80211_aes_ccm_encrypt(struct crypto_cipher *tfm, u8 *scratch,
*cpos++ = *pos++ ^ e[i]; *cpos++ = *pos++ ^ e[i];
} }
for (i = 0; i < CCMP_MIC_LEN; i++) for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++)
mic[i] = b[i] ^ s_0[i]; mic[i] = b[i] ^ s_0[i];
} }
...@@ -123,7 +123,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch, ...@@ -123,7 +123,7 @@ int ieee80211_aes_ccm_decrypt(struct crypto_cipher *tfm, u8 *scratch,
crypto_cipher_encrypt_one(tfm, a, a); crypto_cipher_encrypt_one(tfm, a, a);
} }
for (i = 0; i < CCMP_MIC_LEN; i++) { for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) {
if ((mic[i] ^ s_0[i]) != a[i]) if ((mic[i] ^ s_0[i]) != a[i])
return -1; return -1;
} }
...@@ -138,7 +138,7 @@ struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[]) ...@@ -138,7 +138,7 @@ struct crypto_cipher *ieee80211_aes_key_setup_encrypt(const u8 key[])
tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);
if (!IS_ERR(tfm)) if (!IS_ERR(tfm))
crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN); crypto_cipher_setkey(tfm, key, WLAN_KEY_LEN_CCMP);
return tfm; return tfm;
} }
......
...@@ -444,7 +444,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) ...@@ -444,7 +444,7 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct timespec uptime; struct timespec uptime;
u64 packets = 0; u64 packets = 0;
int ac; int i, ac;
sinfo->generation = sdata->local->sta_generation; sinfo->generation = sdata->local->sta_generation;
...@@ -488,6 +488,17 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) ...@@ -488,6 +488,17 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
sinfo->signal = (s8)sta->last_signal; sinfo->signal = (s8)sta->last_signal;
sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal); sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
} }
if (sta->chains) {
sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |
STATION_INFO_CHAIN_SIGNAL_AVG;
sinfo->chains = sta->chains;
for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
sinfo->chain_signal[i] = sta->chain_signal_last[i];
sinfo->chain_signal_avg[i] =
(s8) -ewma_read(&sta->chain_signal_avg[i]);
}
}
sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
sta_set_rate_info_rx(sta, &sinfo->rxrate); sta_set_rate_info_rx(sta, &sinfo->rxrate);
...@@ -728,7 +739,7 @@ static void ieee80211_get_et_strings(struct wiphy *wiphy, ...@@ -728,7 +739,7 @@ static void ieee80211_get_et_strings(struct wiphy *wiphy,
if (sset == ETH_SS_STATS) { if (sset == ETH_SS_STATS) {
sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats); sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);
memcpy(data, *ieee80211_gstrings_sta_stats, sz_sta_stats); memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats);
} }
drv_get_et_strings(sdata, sset, &(data[sz_sta_stats])); drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));
} }
...@@ -1735,6 +1746,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, ...@@ -1735,6 +1746,7 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
ifmsh->mesh_pp_id = setup->path_sel_proto; ifmsh->mesh_pp_id = setup->path_sel_proto;
ifmsh->mesh_pm_id = setup->path_metric; ifmsh->mesh_pm_id = setup->path_metric;
ifmsh->user_mpm = setup->user_mpm; ifmsh->user_mpm = setup->user_mpm;
ifmsh->mesh_auth_id = setup->auth_id;
ifmsh->security = IEEE80211_MESH_SEC_NONE; ifmsh->security = IEEE80211_MESH_SEC_NONE;
if (setup->is_authenticated) if (setup->is_authenticated)
ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; ifmsh->security |= IEEE80211_MESH_SEC_AUTHED;
...@@ -2306,7 +2318,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, ...@@ -2306,7 +2318,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
enum ieee80211_smps_mode old_req; enum ieee80211_smps_mode old_req;
int err; int err;
lockdep_assert_held(&sdata->u.mgd.mtx); lockdep_assert_held(&sdata->wdev.mtx);
old_req = sdata->u.mgd.req_smps; old_req = sdata->u.mgd.req_smps;
sdata->u.mgd.req_smps = smps_mode; sdata->u.mgd.req_smps = smps_mode;
...@@ -2363,9 +2375,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, ...@@ -2363,9 +2375,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
local->dynamic_ps_forced_timeout = timeout; local->dynamic_ps_forced_timeout = timeout;
/* no change, but if automatic follow powersave */ /* no change, but if automatic follow powersave */
mutex_lock(&sdata->u.mgd.mtx);
__ieee80211_request_smps(sdata, sdata->u.mgd.req_smps); __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps);
mutex_unlock(&sdata->u.mgd.mtx);
if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
......
...@@ -228,9 +228,9 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, ...@@ -228,9 +228,9 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
if (sdata->vif.type != NL80211_IFTYPE_STATION) if (sdata->vif.type != NL80211_IFTYPE_STATION)
return -EOPNOTSUPP; return -EOPNOTSUPP;
mutex_lock(&sdata->u.mgd.mtx); sdata_lock(sdata);
err = __ieee80211_request_smps(sdata, smps_mode); err = __ieee80211_request_smps(sdata, smps_mode);
mutex_unlock(&sdata->u.mgd.mtx); sdata_unlock(sdata);
return err; return err;
} }
...@@ -313,16 +313,16 @@ static ssize_t ieee80211_if_parse_tkip_mic_test( ...@@ -313,16 +313,16 @@ static ssize_t ieee80211_if_parse_tkip_mic_test(
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
fc |= cpu_to_le16(IEEE80211_FCTL_TODS); fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
/* BSSID SA DA */ /* BSSID SA DA */
mutex_lock(&sdata->u.mgd.mtx); sdata_lock(sdata);
if (!sdata->u.mgd.associated) { if (!sdata->u.mgd.associated) {
mutex_unlock(&sdata->u.mgd.mtx); sdata_unlock(sdata);
dev_kfree_skb(skb); dev_kfree_skb(skb);
return -ENOTCONN; return -ENOTCONN;
} }
memcpy(hdr->addr1, sdata->u.mgd.associated->bssid, ETH_ALEN); memcpy(hdr->addr1, sdata->u.mgd.associated->bssid, ETH_ALEN);
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN); memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
memcpy(hdr->addr3, addr, ETH_ALEN); memcpy(hdr->addr3, addr, ETH_ALEN);
mutex_unlock(&sdata->u.mgd.mtx); sdata_unlock(sdata);
break; break;
default: default:
dev_kfree_skb(skb); dev_kfree_skb(skb);
...@@ -471,6 +471,8 @@ __IEEE80211_IF_FILE_W(tsf); ...@@ -471,6 +471,8 @@ __IEEE80211_IF_FILE_W(tsf);
IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC);
#ifdef CONFIG_MAC80211_MESH #ifdef CONFIG_MAC80211_MESH
IEEE80211_IF_FILE(estab_plinks, u.mesh.estab_plinks, ATOMIC);
/* Mesh stats attributes */ /* Mesh stats attributes */
IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC); IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC);
IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC); IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC);
...@@ -480,7 +482,6 @@ IEEE80211_IF_FILE(dropped_frames_congestion, ...@@ -480,7 +482,6 @@ IEEE80211_IF_FILE(dropped_frames_congestion,
u.mesh.mshstats.dropped_frames_congestion, DEC); u.mesh.mshstats.dropped_frames_congestion, DEC);
IEEE80211_IF_FILE(dropped_frames_no_route, IEEE80211_IF_FILE(dropped_frames_no_route,
u.mesh.mshstats.dropped_frames_no_route, DEC); u.mesh.mshstats.dropped_frames_no_route, DEC);
IEEE80211_IF_FILE(estab_plinks, u.mesh.estab_plinks, ATOMIC);
/* Mesh parameters */ /* Mesh parameters */
IEEE80211_IF_FILE(dot11MeshMaxRetries, IEEE80211_IF_FILE(dot11MeshMaxRetries,
...@@ -583,6 +584,7 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata) ...@@ -583,6 +584,7 @@ static void add_wds_files(struct ieee80211_sub_if_data *sdata)
static void add_mesh_files(struct ieee80211_sub_if_data *sdata) static void add_mesh_files(struct ieee80211_sub_if_data *sdata)
{ {
DEBUGFS_ADD_MODE(tsf, 0600); DEBUGFS_ADD_MODE(tsf, 0600);
DEBUGFS_ADD_MODE(estab_plinks, 0400);
} }
static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
...@@ -598,7 +600,6 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) ...@@ -598,7 +600,6 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)
MESHSTATS_ADD(dropped_frames_ttl); MESHSTATS_ADD(dropped_frames_ttl);
MESHSTATS_ADD(dropped_frames_no_route); MESHSTATS_ADD(dropped_frames_no_route);
MESHSTATS_ADD(dropped_frames_congestion); MESHSTATS_ADD(dropped_frames_congestion);
MESHSTATS_ADD(estab_plinks);
#undef MESHSTATS_ADD #undef MESHSTATS_ADD
} }
......
...@@ -429,9 +429,9 @@ void ieee80211_request_smps_work(struct work_struct *work) ...@@ -429,9 +429,9 @@ void ieee80211_request_smps_work(struct work_struct *work)
container_of(work, struct ieee80211_sub_if_data, container_of(work, struct ieee80211_sub_if_data,
u.mgd.request_smps_work); u.mgd.request_smps_work);
mutex_lock(&sdata->u.mgd.mtx); sdata_lock(sdata);
__ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode); __ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode);
mutex_unlock(&sdata->u.mgd.mtx); sdata_unlock(sdata);
} }
void ieee80211_request_smps(struct ieee80211_vif *vif, void ieee80211_request_smps(struct ieee80211_vif *vif,
......
...@@ -54,7 +54,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ...@@ -54,7 +54,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
struct beacon_data *presp; struct beacon_data *presp;
int frame_len; int frame_len;
lockdep_assert_held(&ifibss->mtx); sdata_assert_lock(sdata);
/* Reset own TSF to allow time synchronization work. */ /* Reset own TSF to allow time synchronization work. */
drv_reset_tsf(local, sdata); drv_reset_tsf(local, sdata);
...@@ -74,7 +74,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ...@@ -74,7 +74,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
} }
presp = rcu_dereference_protected(ifibss->presp, presp = rcu_dereference_protected(ifibss->presp,
lockdep_is_held(&ifibss->mtx)); lockdep_is_held(&sdata->wdev.mtx));
rcu_assign_pointer(ifibss->presp, NULL); rcu_assign_pointer(ifibss->presp, NULL);
if (presp) if (presp)
kfree_rcu(presp, rcu_head); kfree_rcu(presp, rcu_head);
...@@ -263,7 +263,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ...@@ -263,7 +263,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
const struct cfg80211_bss_ies *ies; const struct cfg80211_bss_ies *ies;
u64 tsf; u64 tsf;
lockdep_assert_held(&sdata->u.ibss.mtx); sdata_assert_lock(sdata);
if (beacon_int < 10) if (beacon_int < 10)
beacon_int = 10; beacon_int = 10;
...@@ -341,6 +341,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, ...@@ -341,6 +341,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct sta_info *sta; struct sta_info *sta;
struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_supported_band *sband;
int band; int band;
/* /*
...@@ -380,8 +381,9 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, ...@@ -380,8 +381,9 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
sta->last_rx = jiffies; sta->last_rx = jiffies;
/* make sure mandatory rates are always added */ /* make sure mandatory rates are always added */
sband = local->hw.wiphy->bands[band];
sta->sta.supp_rates[band] = supp_rates | sta->sta.supp_rates[band] = supp_rates |
ieee80211_mandatory_rates(local, band); ieee80211_mandatory_rates(sband);
return ieee80211_ibss_finish_sta(sta, auth); return ieee80211_ibss_finish_sta(sta, auth);
} }
...@@ -408,7 +410,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, ...@@ -408,7 +410,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta; struct sta_info *sta;
u8 deauth_frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; u8 deauth_frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
lockdep_assert_held(&sdata->u.ibss.mtx); sdata_assert_lock(sdata);
if (len < 24 + 6) if (len < 24 + 6)
return; return;
...@@ -492,7 +494,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, ...@@ -492,7 +494,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
prev_rates = sta->sta.supp_rates[band]; prev_rates = sta->sta.supp_rates[band];
/* make sure mandatory rates are always added */ /* make sure mandatory rates are always added */
sta->sta.supp_rates[band] = supp_rates | sta->sta.supp_rates[band] = supp_rates |
ieee80211_mandatory_rates(local, band); ieee80211_mandatory_rates(sband);
if (sta->sta.supp_rates[band] != prev_rates) { if (sta->sta.supp_rates[band] != prev_rates) {
ibss_dbg(sdata, ibss_dbg(sdata,
...@@ -624,6 +626,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, ...@@ -624,6 +626,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct sta_info *sta; struct sta_info *sta;
struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_supported_band *sband;
int band; int band;
/* /*
...@@ -658,8 +661,9 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, ...@@ -658,8 +661,9 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata,
sta->last_rx = jiffies; sta->last_rx = jiffies;
/* make sure mandatory rates are always added */ /* make sure mandatory rates are always added */
sband = local->hw.wiphy->bands[band];
sta->sta.supp_rates[band] = supp_rates | sta->sta.supp_rates[band] = supp_rates |
ieee80211_mandatory_rates(local, band); ieee80211_mandatory_rates(sband);
spin_lock(&ifibss->incomplete_lock); spin_lock(&ifibss->incomplete_lock);
list_add(&sta->list, &ifibss->incomplete_stations); list_add(&sta->list, &ifibss->incomplete_stations);
...@@ -673,7 +677,7 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) ...@@ -673,7 +677,7 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
int active = 0; int active = 0;
struct sta_info *sta; struct sta_info *sta;
lockdep_assert_held(&sdata->u.ibss.mtx); sdata_assert_lock(sdata);
rcu_read_lock(); rcu_read_lock();
...@@ -699,7 +703,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) ...@@ -699,7 +703,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
lockdep_assert_held(&ifibss->mtx); sdata_assert_lock(sdata);
mod_timer(&ifibss->timer, mod_timer(&ifibss->timer,
round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
...@@ -730,7 +734,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) ...@@ -730,7 +734,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
u16 capability; u16 capability;
int i; int i;
lockdep_assert_held(&ifibss->mtx); sdata_assert_lock(sdata);
if (ifibss->fixed_bssid) { if (ifibss->fixed_bssid) {
memcpy(bssid, ifibss->bssid, ETH_ALEN); memcpy(bssid, ifibss->bssid, ETH_ALEN);
...@@ -773,7 +777,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) ...@@ -773,7 +777,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
int active_ibss; int active_ibss;
u16 capability; u16 capability;
lockdep_assert_held(&ifibss->mtx); sdata_assert_lock(sdata);
active_ibss = ieee80211_sta_active_ibss(sdata); active_ibss = ieee80211_sta_active_ibss(sdata);
ibss_dbg(sdata, "sta_find_ibss (active_ibss=%d)\n", active_ibss); ibss_dbg(sdata, "sta_find_ibss (active_ibss=%d)\n", active_ibss);
...@@ -843,10 +847,10 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, ...@@ -843,10 +847,10 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
struct beacon_data *presp; struct beacon_data *presp;
u8 *pos, *end; u8 *pos, *end;
lockdep_assert_held(&ifibss->mtx); sdata_assert_lock(sdata);
presp = rcu_dereference_protected(ifibss->presp, presp = rcu_dereference_protected(ifibss->presp,
lockdep_is_held(&ifibss->mtx)); lockdep_is_held(&sdata->wdev.mtx));
if (ifibss->state != IEEE80211_IBSS_MLME_JOINED || if (ifibss->state != IEEE80211_IBSS_MLME_JOINED ||
len < 24 + 2 || !presp) len < 24 + 2 || !presp)
...@@ -930,7 +934,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ...@@ -930,7 +934,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
mgmt = (struct ieee80211_mgmt *) skb->data; mgmt = (struct ieee80211_mgmt *) skb->data;
fc = le16_to_cpu(mgmt->frame_control); fc = le16_to_cpu(mgmt->frame_control);
mutex_lock(&sdata->u.ibss.mtx); sdata_lock(sdata);
if (!sdata->u.ibss.ssid_len) if (!sdata->u.ibss.ssid_len)
goto mgmt_out; /* not ready to merge yet */ goto mgmt_out; /* not ready to merge yet */
...@@ -953,7 +957,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ...@@ -953,7 +957,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
} }
mgmt_out: mgmt_out:
mutex_unlock(&sdata->u.ibss.mtx); sdata_unlock(sdata);
} }
void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
...@@ -961,7 +965,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) ...@@ -961,7 +965,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct sta_info *sta; struct sta_info *sta;
mutex_lock(&ifibss->mtx); sdata_lock(sdata);
/* /*
* Work could be scheduled after scan or similar * Work could be scheduled after scan or similar
...@@ -997,7 +1001,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) ...@@ -997,7 +1001,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
} }
out: out:
mutex_unlock(&ifibss->mtx); sdata_unlock(sdata);
} }
static void ieee80211_ibss_timer(unsigned long data) static void ieee80211_ibss_timer(unsigned long data)
...@@ -1014,7 +1018,6 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) ...@@ -1014,7 +1018,6 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
setup_timer(&ifibss->timer, ieee80211_ibss_timer, setup_timer(&ifibss->timer, ieee80211_ibss_timer,
(unsigned long) sdata); (unsigned long) sdata);
mutex_init(&ifibss->mtx);
INIT_LIST_HEAD(&ifibss->incomplete_stations); INIT_LIST_HEAD(&ifibss->incomplete_stations);
spin_lock_init(&ifibss->incomplete_lock); spin_lock_init(&ifibss->incomplete_lock);
} }
...@@ -1041,8 +1044,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, ...@@ -1041,8 +1044,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
{ {
u32 changed = 0; u32 changed = 0;
mutex_lock(&sdata->u.ibss.mtx);
if (params->bssid) { if (params->bssid) {
memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN);
sdata->u.ibss.fixed_bssid = true; sdata->u.ibss.fixed_bssid = true;
...@@ -1075,8 +1076,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, ...@@ -1075,8 +1076,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len); memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
sdata->u.ibss.ssid_len = params->ssid_len; sdata->u.ibss.ssid_len = params->ssid_len;
mutex_unlock(&sdata->u.ibss.mtx);
/* /*
* 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is * 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is
* reserved, but an HT STA shall protect HT transmissions as though * reserved, but an HT STA shall protect HT transmissions as though
...@@ -1112,8 +1111,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) ...@@ -1112,8 +1111,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
struct sta_info *sta; struct sta_info *sta;
struct beacon_data *presp; struct beacon_data *presp;
mutex_lock(&sdata->u.ibss.mtx);
active_ibss = ieee80211_sta_active_ibss(sdata); active_ibss = ieee80211_sta_active_ibss(sdata);
if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
...@@ -1157,7 +1154,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) ...@@ -1157,7 +1154,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
/* remove beacon */ /* remove beacon */
kfree(sdata->u.ibss.ie); kfree(sdata->u.ibss.ie);
presp = rcu_dereference_protected(ifibss->presp, presp = rcu_dereference_protected(ifibss->presp,
lockdep_is_held(&sdata->u.ibss.mtx)); lockdep_is_held(&sdata->wdev.mtx));
RCU_INIT_POINTER(sdata->u.ibss.presp, NULL); RCU_INIT_POINTER(sdata->u.ibss.presp, NULL);
sdata->vif.bss_conf.ibss_joined = false; sdata->vif.bss_conf.ibss_joined = false;
sdata->vif.bss_conf.ibss_creator = false; sdata->vif.bss_conf.ibss_creator = false;
...@@ -1173,7 +1170,5 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) ...@@ -1173,7 +1170,5 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
del_timer_sync(&sdata->u.ibss.timer); del_timer_sync(&sdata->u.ibss.timer);
mutex_unlock(&sdata->u.ibss.mtx);
return 0; return 0;
} }
...@@ -394,7 +394,6 @@ struct ieee80211_if_managed { ...@@ -394,7 +394,6 @@ struct ieee80211_if_managed {
bool nullfunc_failed; bool nullfunc_failed;
bool connection_loss; bool connection_loss;
struct mutex mtx;
struct cfg80211_bss *associated; struct cfg80211_bss *associated;
struct ieee80211_mgd_auth_data *auth_data; struct ieee80211_mgd_auth_data *auth_data;
struct ieee80211_mgd_assoc_data *assoc_data; struct ieee80211_mgd_assoc_data *assoc_data;
...@@ -488,8 +487,6 @@ struct ieee80211_if_managed { ...@@ -488,8 +487,6 @@ struct ieee80211_if_managed {
struct ieee80211_if_ibss { struct ieee80211_if_ibss {
struct timer_list timer; struct timer_list timer;
struct mutex mtx;
unsigned long last_scan_completed; unsigned long last_scan_completed;
u32 basic_rates; u32 basic_rates;
...@@ -580,8 +577,6 @@ struct ieee80211_if_mesh { ...@@ -580,8 +577,6 @@ struct ieee80211_if_mesh {
bool accepting_plinks; bool accepting_plinks;
int num_gates; int num_gates;
struct beacon_data __rcu *beacon; struct beacon_data __rcu *beacon;
/* just protects beacon updates for now */
struct mutex mtx;
const u8 *ie; const u8 *ie;
u8 ie_len; u8 ie_len;
enum { enum {
...@@ -778,6 +773,26 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p) ...@@ -778,6 +773,26 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
return container_of(p, struct ieee80211_sub_if_data, vif); return container_of(p, struct ieee80211_sub_if_data, vif);
} }
static inline void sdata_lock(struct ieee80211_sub_if_data *sdata)
__acquires(&sdata->wdev.mtx)
{
mutex_lock(&sdata->wdev.mtx);
__acquire(&sdata->wdev.mtx);
}
static inline void sdata_unlock(struct ieee80211_sub_if_data *sdata)
__releases(&sdata->wdev.mtx)
{
mutex_unlock(&sdata->wdev.mtx);
__release(&sdata->wdev.mtx);
}
static inline void
sdata_assert_lock(struct ieee80211_sub_if_data *sdata)
{
lockdep_assert_held(&sdata->wdev.mtx);
}
static inline enum ieee80211_band static inline enum ieee80211_band
ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata) ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata)
{ {
...@@ -1267,6 +1282,7 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); ...@@ -1267,6 +1282,7 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata);
void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata);
void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata,
__le16 fc, bool acked); __le16 fc, bool acked);
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
/* IBSS code */ /* IBSS code */
void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
...@@ -1505,9 +1521,6 @@ static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action, ...@@ -1505,9 +1521,6 @@ static inline void ieee802_11_parse_elems(u8 *start, size_t len, bool action,
ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0);
} }
u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
enum ieee80211_band band);
void ieee80211_dynamic_ps_enable_work(struct work_struct *work); void ieee80211_dynamic_ps_enable_work(struct work_struct *work);
void ieee80211_dynamic_ps_disable_work(struct work_struct *work); void ieee80211_dynamic_ps_disable_work(struct work_struct *work);
void ieee80211_dynamic_ps_timer(unsigned long data); void ieee80211_dynamic_ps_timer(unsigned long data);
......
...@@ -474,6 +474,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) ...@@ -474,6 +474,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
master->control_port_protocol; master->control_port_protocol;
sdata->control_port_no_encrypt = sdata->control_port_no_encrypt =
master->control_port_no_encrypt; master->control_port_no_encrypt;
sdata->vif.cab_queue = master->vif.cab_queue;
memcpy(sdata->vif.hw_queue, master->vif.hw_queue,
sizeof(sdata->vif.hw_queue));
break; break;
} }
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
...@@ -653,7 +656,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) ...@@ -653,7 +656,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
ieee80211_recalc_ps(local, -1); ieee80211_recalc_ps(local, -1);
if (dev) { if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
/* XXX: for AP_VLAN, actually track AP queues */
netif_tx_start_all_queues(dev);
} else if (dev) {
unsigned long flags; unsigned long flags;
int n_acs = IEEE80211_NUM_ACS; int n_acs = IEEE80211_NUM_ACS;
int ac; int ac;
...@@ -1696,6 +1703,15 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) ...@@ -1696,6 +1703,15 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
ASSERT_RTNL(); ASSERT_RTNL();
/*
* Close all AP_VLAN interfaces first, as otherwise they
* might be closed while the AP interface they belong to
* is closed, causing unregister_netdevice_many() to crash.
*/
list_for_each_entry(sdata, &local->interfaces, list)
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
dev_close(sdata->dev);
mutex_lock(&local->iflist_mtx); mutex_lock(&local->iflist_mtx);
list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
list_del(&sdata->list); list_del(&sdata->list);
......
...@@ -335,12 +335,12 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, ...@@ -335,12 +335,12 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
switch (cipher) { switch (cipher) {
case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_WEP104:
key->conf.iv_len = WEP_IV_LEN; key->conf.iv_len = IEEE80211_WEP_IV_LEN;
key->conf.icv_len = WEP_ICV_LEN; key->conf.icv_len = IEEE80211_WEP_ICV_LEN;
break; break;
case WLAN_CIPHER_SUITE_TKIP: case WLAN_CIPHER_SUITE_TKIP:
key->conf.iv_len = TKIP_IV_LEN; key->conf.iv_len = IEEE80211_TKIP_IV_LEN;
key->conf.icv_len = TKIP_ICV_LEN; key->conf.icv_len = IEEE80211_TKIP_ICV_LEN;
if (seq) { if (seq) {
for (i = 0; i < IEEE80211_NUM_TIDS; i++) { for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
key->u.tkip.rx[i].iv32 = key->u.tkip.rx[i].iv32 =
...@@ -352,13 +352,13 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, ...@@ -352,13 +352,13 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
spin_lock_init(&key->u.tkip.txlock); spin_lock_init(&key->u.tkip.txlock);
break; break;
case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_CCMP:
key->conf.iv_len = CCMP_HDR_LEN; key->conf.iv_len = IEEE80211_CCMP_HDR_LEN;
key->conf.icv_len = CCMP_MIC_LEN; key->conf.icv_len = IEEE80211_CCMP_MIC_LEN;
if (seq) { if (seq) {
for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)
for (j = 0; j < CCMP_PN_LEN; j++) for (j = 0; j < IEEE80211_CCMP_PN_LEN; j++)
key->u.ccmp.rx_pn[i][j] = key->u.ccmp.rx_pn[i][j] =
seq[CCMP_PN_LEN - j - 1]; seq[IEEE80211_CCMP_PN_LEN - j - 1];
} }
/* /*
* Initialize AES key state here as an optimization so that * Initialize AES key state here as an optimization so that
...@@ -375,9 +375,9 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, ...@@ -375,9 +375,9 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
key->conf.iv_len = 0; key->conf.iv_len = 0;
key->conf.icv_len = sizeof(struct ieee80211_mmie); key->conf.icv_len = sizeof(struct ieee80211_mmie);
if (seq) if (seq)
for (j = 0; j < CMAC_PN_LEN; j++) for (j = 0; j < IEEE80211_CMAC_PN_LEN; j++)
key->u.aes_cmac.rx_pn[j] = key->u.aes_cmac.rx_pn[j] =
seq[CMAC_PN_LEN - j - 1]; seq[IEEE80211_CMAC_PN_LEN - j - 1];
/* /*
* Initialize AES key state here as an optimization so that * Initialize AES key state here as an optimization so that
* it does not need to be initialized for every packet. * it does not need to be initialized for every packet.
...@@ -740,13 +740,13 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf, ...@@ -740,13 +740,13 @@ void ieee80211_get_key_rx_seq(struct ieee80211_key_conf *keyconf,
pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS]; pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS];
else else
pn = key->u.ccmp.rx_pn[tid]; pn = key->u.ccmp.rx_pn[tid];
memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN); memcpy(seq->ccmp.pn, pn, IEEE80211_CCMP_PN_LEN);
break; break;
case WLAN_CIPHER_SUITE_AES_CMAC: case WLAN_CIPHER_SUITE_AES_CMAC:
if (WARN_ON(tid != 0)) if (WARN_ON(tid != 0))
return; return;
pn = key->u.aes_cmac.rx_pn; pn = key->u.aes_cmac.rx_pn;
memcpy(seq->aes_cmac.pn, pn, CMAC_PN_LEN); memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN);
break; break;
} }
} }
......
...@@ -19,17 +19,6 @@ ...@@ -19,17 +19,6 @@
#define NUM_DEFAULT_KEYS 4 #define NUM_DEFAULT_KEYS 4
#define NUM_DEFAULT_MGMT_KEYS 2 #define NUM_DEFAULT_MGMT_KEYS 2
#define WEP_IV_LEN 4
#define WEP_ICV_LEN 4
#define ALG_CCMP_KEY_LEN 16
#define CCMP_HDR_LEN 8
#define CCMP_MIC_LEN 8
#define CCMP_TK_LEN 16
#define CCMP_PN_LEN 6
#define TKIP_IV_LEN 8
#define TKIP_ICV_LEN 4
#define CMAC_PN_LEN 6
struct ieee80211_local; struct ieee80211_local;
struct ieee80211_sub_if_data; struct ieee80211_sub_if_data;
struct sta_info; struct sta_info;
...@@ -93,13 +82,13 @@ struct ieee80211_key { ...@@ -93,13 +82,13 @@ struct ieee80211_key {
* frames and the last counter is used with Robust * frames and the last counter is used with Robust
* Management frames. * Management frames.
*/ */
u8 rx_pn[IEEE80211_NUM_TIDS + 1][CCMP_PN_LEN]; u8 rx_pn[IEEE80211_NUM_TIDS + 1][IEEE80211_CCMP_PN_LEN];
struct crypto_cipher *tfm; struct crypto_cipher *tfm;
u32 replays; /* dot11RSNAStatsCCMPReplays */ u32 replays; /* dot11RSNAStatsCCMPReplays */
} ccmp; } ccmp;
struct { struct {
atomic64_t tx_pn; atomic64_t tx_pn;
u8 rx_pn[CMAC_PN_LEN]; u8 rx_pn[IEEE80211_CMAC_PN_LEN];
struct crypto_cipher *tfm; struct crypto_cipher *tfm;
u32 replays; /* dot11RSNAStatsCMACReplays */ u32 replays; /* dot11RSNAStatsCMACReplays */
u32 icverrors; /* dot11RSNAStatsCMACICVErrors */ u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
......
...@@ -331,7 +331,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, ...@@ -331,7 +331,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
return NOTIFY_DONE; return NOTIFY_DONE;
ifmgd = &sdata->u.mgd; ifmgd = &sdata->u.mgd;
mutex_lock(&ifmgd->mtx); sdata_lock(sdata);
/* Copy the addresses to the bss_conf list */ /* Copy the addresses to the bss_conf list */
ifa = idev->ifa_list; ifa = idev->ifa_list;
...@@ -349,7 +349,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, ...@@ -349,7 +349,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
ieee80211_bss_info_change_notify(sdata, ieee80211_bss_info_change_notify(sdata,
BSS_CHANGED_ARP_FILTER); BSS_CHANGED_ARP_FILTER);
mutex_unlock(&ifmgd->mtx); sdata_unlock(sdata);
return NOTIFY_DONE; return NOTIFY_DONE;
} }
......
...@@ -161,8 +161,11 @@ void mesh_sta_cleanup(struct sta_info *sta) ...@@ -161,8 +161,11 @@ void mesh_sta_cleanup(struct sta_info *sta)
del_timer_sync(&sta->plink_timer); del_timer_sync(&sta->plink_timer);
} }
if (changed) if (changed) {
sdata_lock(sdata);
ieee80211_mbss_info_change_notify(sdata, changed); ieee80211_mbss_info_change_notify(sdata, changed);
sdata_unlock(sdata);
}
} }
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
...@@ -577,7 +580,9 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata) ...@@ -577,7 +580,9 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata)
mesh_path_expire(sdata); mesh_path_expire(sdata);
changed = mesh_accept_plinks_update(sdata); changed = mesh_accept_plinks_update(sdata);
sdata_lock(sdata);
ieee80211_mbss_info_change_notify(sdata, changed); ieee80211_mbss_info_change_notify(sdata, changed);
sdata_unlock(sdata);
mod_timer(&ifmsh->housekeeping_timer, mod_timer(&ifmsh->housekeeping_timer,
round_jiffies(jiffies + round_jiffies(jiffies +
...@@ -697,25 +702,21 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) ...@@ -697,25 +702,21 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
} }
static int static int
ieee80211_mesh_rebuild_beacon(struct ieee80211_if_mesh *ifmsh) ieee80211_mesh_rebuild_beacon(struct ieee80211_sub_if_data *sdata)
{ {
struct beacon_data *old_bcn; struct beacon_data *old_bcn;
int ret; int ret;
mutex_lock(&ifmsh->mtx); old_bcn = rcu_dereference_protected(sdata->u.mesh.beacon,
lockdep_is_held(&sdata->wdev.mtx));
old_bcn = rcu_dereference_protected(ifmsh->beacon, ret = ieee80211_mesh_build_beacon(&sdata->u.mesh);
lockdep_is_held(&ifmsh->mtx));
ret = ieee80211_mesh_build_beacon(ifmsh);
if (ret) if (ret)
/* just reuse old beacon */ /* just reuse old beacon */
goto out; return ret;
if (old_bcn) if (old_bcn)
kfree_rcu(old_bcn, rcu_head); kfree_rcu(old_bcn, rcu_head);
out: return 0;
mutex_unlock(&ifmsh->mtx);
return ret;
} }
void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata, void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
...@@ -726,7 +727,7 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata, ...@@ -726,7 +727,7 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
BSS_CHANGED_HT | BSS_CHANGED_HT |
BSS_CHANGED_BASIC_RATES | BSS_CHANGED_BASIC_RATES |
BSS_CHANGED_BEACON_INT))) BSS_CHANGED_BEACON_INT)))
if (ieee80211_mesh_rebuild_beacon(&sdata->u.mesh)) if (ieee80211_mesh_rebuild_beacon(sdata))
return; return;
ieee80211_bss_info_change_notify(sdata, changed); ieee80211_bss_info_change_notify(sdata, changed);
} }
...@@ -741,6 +742,8 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) ...@@ -741,6 +742,8 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
BSS_CHANGED_BASIC_RATES | BSS_CHANGED_BASIC_RATES |
BSS_CHANGED_BEACON_INT; BSS_CHANGED_BEACON_INT;
enum ieee80211_band band = ieee80211_get_sdata_band(sdata); enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
struct ieee80211_supported_band *sband =
sdata->local->hw.wiphy->bands[band];
local->fif_other_bss++; local->fif_other_bss++;
/* mesh ifaces must set allmulti to forward mcast traffic */ /* mesh ifaces must set allmulti to forward mcast traffic */
...@@ -748,7 +751,6 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) ...@@ -748,7 +751,6 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
ieee80211_configure_filter(local); ieee80211_configure_filter(local);
ifmsh->mesh_cc_id = 0; /* Disabled */ ifmsh->mesh_cc_id = 0; /* Disabled */
ifmsh->mesh_auth_id = 0; /* Disabled */
/* register sync ops from extensible synchronization framework */ /* register sync ops from extensible synchronization framework */
ifmsh->sync_ops = ieee80211_mesh_sync_ops_get(ifmsh->mesh_sp_id); ifmsh->sync_ops = ieee80211_mesh_sync_ops_get(ifmsh->mesh_sp_id);
ifmsh->adjusting_tbtt = false; ifmsh->adjusting_tbtt = false;
...@@ -759,8 +761,7 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) ...@@ -759,8 +761,7 @@ int ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
sdata->vif.bss_conf.ht_operation_mode = sdata->vif.bss_conf.ht_operation_mode =
ifmsh->mshcfg.ht_opmode; ifmsh->mshcfg.ht_opmode;
sdata->vif.bss_conf.enable_beacon = true; sdata->vif.bss_conf.enable_beacon = true;
sdata->vif.bss_conf.basic_rates = sdata->vif.bss_conf.basic_rates = ieee80211_mandatory_rates(sband);
ieee80211_mandatory_rates(local, band);
changed |= ieee80211_mps_local_status_update(sdata); changed |= ieee80211_mps_local_status_update(sdata);
...@@ -788,12 +789,12 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) ...@@ -788,12 +789,12 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
sdata->vif.bss_conf.enable_beacon = false; sdata->vif.bss_conf.enable_beacon = false;
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state); clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
mutex_lock(&ifmsh->mtx); sdata_lock(sdata);
bcn = rcu_dereference_protected(ifmsh->beacon, bcn = rcu_dereference_protected(ifmsh->beacon,
lockdep_is_held(&ifmsh->mtx)); lockdep_is_held(&sdata->wdev.mtx));
rcu_assign_pointer(ifmsh->beacon, NULL); rcu_assign_pointer(ifmsh->beacon, NULL);
kfree_rcu(bcn, rcu_head); kfree_rcu(bcn, rcu_head);
mutex_unlock(&ifmsh->mtx); sdata_unlock(sdata);
/* flush STAs and mpaths on this iface */ /* flush STAs and mpaths on this iface */
sta_info_flush(sdata); sta_info_flush(sdata);
...@@ -1041,7 +1042,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) ...@@ -1041,7 +1042,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
spin_lock_init(&ifmsh->mesh_preq_queue_lock); spin_lock_init(&ifmsh->mesh_preq_queue_lock);
spin_lock_init(&ifmsh->sync_offset_lock); spin_lock_init(&ifmsh->sync_offset_lock);
RCU_INIT_POINTER(ifmsh->beacon, NULL); RCU_INIT_POINTER(ifmsh->beacon, NULL);
mutex_init(&ifmsh->mtx);
sdata->vif.bss_conf.bssid = zero_addr; sdata->vif.bss_conf.bssid = zero_addr;
} }
...@@ -517,7 +517,9 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, ...@@ -517,7 +517,9 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
ieee80211_mps_frame_release(sta, elems); ieee80211_mps_frame_release(sta, elems);
out: out:
rcu_read_unlock(); rcu_read_unlock();
sdata_lock(sdata);
ieee80211_mbss_info_change_notify(sdata, changed); ieee80211_mbss_info_change_notify(sdata, changed);
sdata_unlock(sdata);
} }
static void mesh_plink_timer(unsigned long data) static void mesh_plink_timer(unsigned long data)
...@@ -1068,6 +1070,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, ...@@ -1068,6 +1070,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock(); rcu_read_unlock();
if (changed) if (changed) {
sdata_lock(sdata);
ieee80211_mbss_info_change_notify(sdata, changed); ieee80211_mbss_info_change_notify(sdata, changed);
sdata_unlock(sdata);
}
} }
此差异已折叠。
...@@ -688,8 +688,15 @@ int rate_control_set_rates(struct ieee80211_hw *hw, ...@@ -688,8 +688,15 @@ int rate_control_set_rates(struct ieee80211_hw *hw,
struct ieee80211_sta *pubsta, struct ieee80211_sta *pubsta,
struct ieee80211_sta_rates *rates) struct ieee80211_sta_rates *rates)
{ {
struct ieee80211_sta_rates *old = rcu_dereference(pubsta->rates); struct ieee80211_sta_rates *old;
/*
* mac80211 guarantees that this function will not be called
* concurrently, so the following RCU access is safe, even without
* extra locking. This can not be checked easily, so we just set
* the condition to true.
*/
old = rcu_dereference_protected(pubsta->rates, true);
rcu_assign_pointer(pubsta->rates, rates); rcu_assign_pointer(pubsta->rates, rates);
if (old) if (old)
kfree_rcu(old, rcu_head); kfree_rcu(old, rcu_head);
......
...@@ -258,6 +258,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, ...@@ -258,6 +258,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
pos += 2; pos += 2;
if (status->flag & RX_FLAG_HT) { if (status->flag & RX_FLAG_HT) {
unsigned int stbc;
rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS); rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);
*pos++ = local->hw.radiotap_mcs_details; *pos++ = local->hw.radiotap_mcs_details;
*pos = 0; *pos = 0;
...@@ -267,6 +269,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, ...@@ -267,6 +269,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
*pos |= IEEE80211_RADIOTAP_MCS_BW_40; *pos |= IEEE80211_RADIOTAP_MCS_BW_40;
if (status->flag & RX_FLAG_HT_GF) if (status->flag & RX_FLAG_HT_GF)
*pos |= IEEE80211_RADIOTAP_MCS_FMT_GF; *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF;
stbc = (status->flag & RX_FLAG_STBC_MASK) >> RX_FLAG_STBC_SHIFT;
*pos |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT;
pos++; pos++;
*pos++ = status->rate_idx; *pos++ = status->rate_idx;
} }
...@@ -1372,6 +1376,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) ...@@ -1372,6 +1376,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
struct sk_buff *skb = rx->skb; struct sk_buff *skb = rx->skb;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
int i;
if (!sta) if (!sta)
return RX_CONTINUE; return RX_CONTINUE;
...@@ -1422,6 +1427,19 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) ...@@ -1422,6 +1427,19 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
ewma_add(&sta->avg_signal, -status->signal); ewma_add(&sta->avg_signal, -status->signal);
} }
if (status->chains) {
sta->chains = status->chains;
for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) {
int signal = status->chain_signal[i];
if (!(status->chains & BIT(i)))
continue;
sta->chain_signal_last[i] = signal;
ewma_add(&sta->chain_signal_avg[i], -signal);
}
}
/* /*
* Change STA power saving mode only at the end of a frame * Change STA power saving mode only at the end of a frame
* exchange sequence. * exchange sequence.
...@@ -1608,7 +1626,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) ...@@ -1608,7 +1626,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
entry->ccmp = 1; entry->ccmp = 1;
memcpy(entry->last_pn, memcpy(entry->last_pn,
rx->key->u.ccmp.rx_pn[queue], rx->key->u.ccmp.rx_pn[queue],
CCMP_PN_LEN); IEEE80211_CCMP_PN_LEN);
} }
return RX_QUEUED; return RX_QUEUED;
} }
...@@ -1627,21 +1645,21 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) ...@@ -1627,21 +1645,21 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
* (IEEE 802.11i, 8.3.3.4.5) */ * (IEEE 802.11i, 8.3.3.4.5) */
if (entry->ccmp) { if (entry->ccmp) {
int i; int i;
u8 pn[CCMP_PN_LEN], *rpn; u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
int queue; int queue;
if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP) if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP)
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
memcpy(pn, entry->last_pn, CCMP_PN_LEN); memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
for (i = CCMP_PN_LEN - 1; i >= 0; i--) { for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
pn[i]++; pn[i]++;
if (pn[i]) if (pn[i])
break; break;
} }
queue = rx->security_idx; queue = rx->security_idx;
rpn = rx->key->u.ccmp.rx_pn[queue]; rpn = rx->key->u.ccmp.rx_pn[queue];
if (memcmp(pn, rpn, CCMP_PN_LEN)) if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN))
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
memcpy(entry->last_pn, pn, CCMP_PN_LEN); memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN);
} }
skb_pull(rx->skb, ieee80211_hdrlen(fc)); skb_pull(rx->skb, ieee80211_hdrlen(fc));
...@@ -3036,6 +3054,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, ...@@ -3036,6 +3054,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
* and location updates. Note that mac80211 * and location updates. Note that mac80211
* itself never looks at these frames. * itself never looks at these frames.
*/ */
if (!multicast &&
!ether_addr_equal(sdata->vif.addr, hdr->addr1))
return 0;
if (ieee80211_is_public_action(hdr, skb->len)) if (ieee80211_is_public_action(hdr, skb->len))
return 1; return 1;
if (!ieee80211_is_beacon(hdr->frame_control)) if (!ieee80211_is_beacon(hdr->frame_control))
......
...@@ -358,6 +358,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, ...@@ -358,6 +358,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
do_posix_clock_monotonic_gettime(&uptime); do_posix_clock_monotonic_gettime(&uptime);
sta->last_connected = uptime.tv_sec; sta->last_connected = uptime.tv_sec;
ewma_init(&sta->avg_signal, 1024, 8); ewma_init(&sta->avg_signal, 1024, 8);
for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++)
ewma_init(&sta->chain_signal_avg[i], 1024, 8);
if (sta_prepare_rate_control(local, sta, gfp)) { if (sta_prepare_rate_control(local, sta, gfp)) {
kfree(sta); kfree(sta);
......
...@@ -344,6 +344,11 @@ struct sta_info { ...@@ -344,6 +344,11 @@ struct sta_info {
int last_signal; int last_signal;
struct ewma avg_signal; struct ewma avg_signal;
int last_ack_signal; int last_ack_signal;
u8 chains;
s8 chain_signal_last[IEEE80211_MAX_CHAINS];
struct ewma chain_signal_avg[IEEE80211_MAX_CHAINS];
/* Plus 1 for non-QoS frames */ /* Plus 1 for non-QoS frames */
__le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1]; __le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1];
......
...@@ -208,10 +208,10 @@ void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf, ...@@ -208,10 +208,10 @@ void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
u32 iv32 = get_unaligned_le32(&data[4]); u32 iv32 = get_unaligned_le32(&data[4]);
u16 iv16 = data[2] | (data[0] << 8); u16 iv16 = data[2] | (data[0] << 8);
spin_lock_bh(&key->u.tkip.txlock); spin_lock(&key->u.tkip.txlock);
ieee80211_compute_tkip_p1k(key, iv32); ieee80211_compute_tkip_p1k(key, iv32);
tkip_mixing_phase2(tk, ctx, iv16, p2k); tkip_mixing_phase2(tk, ctx, iv16, p2k);
spin_unlock_bh(&key->u.tkip.txlock); spin_unlock(&key->u.tkip.txlock);
} }
EXPORT_SYMBOL(ieee80211_get_tkip_p2k); EXPORT_SYMBOL(ieee80211_get_tkip_p2k);
......
...@@ -1072,32 +1072,6 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, ...@@ -1072,32 +1072,6 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
ieee80211_set_wmm_default(sdata, true); ieee80211_set_wmm_default(sdata, true);
} }
u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
enum ieee80211_band band)
{
struct ieee80211_supported_band *sband;
struct ieee80211_rate *bitrates;
u32 mandatory_rates;
enum ieee80211_rate_flags mandatory_flag;
int i;
sband = local->hw.wiphy->bands[band];
if (WARN_ON(!sband))
return 1;
if (band == IEEE80211_BAND_2GHZ)
mandatory_flag = IEEE80211_RATE_MANDATORY_B;
else
mandatory_flag = IEEE80211_RATE_MANDATORY_A;
bitrates = sband->bitrates;
mandatory_rates = 0;
for (i = 0; i < sband->n_bitrates; i++)
if (bitrates[i].flags & mandatory_flag)
mandatory_rates |= BIT(i);
return mandatory_rates;
}
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
u16 transaction, u16 auth_alg, u16 status, u16 transaction, u16 auth_alg, u16 status,
const u8 *extra, size_t extra_len, const u8 *da, const u8 *extra, size_t extra_len, const u8 *da,
...@@ -1607,9 +1581,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) ...@@ -1607,9 +1581,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
if (sdata->u.mgd.dtim_period) if (sdata->u.mgd.dtim_period)
changed |= BSS_CHANGED_DTIM_PERIOD; changed |= BSS_CHANGED_DTIM_PERIOD;
mutex_lock(&sdata->u.mgd.mtx); sdata_lock(sdata);
ieee80211_bss_info_change_notify(sdata, changed); ieee80211_bss_info_change_notify(sdata, changed);
mutex_unlock(&sdata->u.mgd.mtx); sdata_unlock(sdata);
break; break;
case NL80211_IFTYPE_ADHOC: case NL80211_IFTYPE_ADHOC:
changed |= BSS_CHANGED_IBSS; changed |= BSS_CHANGED_IBSS;
...@@ -1740,6 +1714,13 @@ int ieee80211_reconfig(struct ieee80211_local *local) ...@@ -1740,6 +1714,13 @@ int ieee80211_reconfig(struct ieee80211_local *local)
mb(); mb();
local->resuming = false; local->resuming = false;
list_for_each_entry(sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(sdata))
continue;
if (sdata->vif.type == NL80211_IFTYPE_STATION)
ieee80211_sta_restart(sdata);
}
mod_timer(&local->sta_cleanup, jiffies + 1); mod_timer(&local->sta_cleanup, jiffies + 1);
#else #else
WARN_ON(1); WARN_ON(1);
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
int ieee80211_wep_init(struct ieee80211_local *local) int ieee80211_wep_init(struct ieee80211_local *local)
{ {
/* start WEP IV from a random value */ /* start WEP IV from a random value */
get_random_bytes(&local->wep_iv, WEP_IV_LEN); get_random_bytes(&local->wep_iv, IEEE80211_WEP_IV_LEN);
local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC); local->wep_tx_tfm = crypto_alloc_cipher("arc4", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(local->wep_tx_tfm)) { if (IS_ERR(local->wep_tx_tfm)) {
...@@ -98,20 +98,21 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local, ...@@ -98,20 +98,21 @@ static u8 *ieee80211_wep_add_iv(struct ieee80211_local *local,
hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
if (WARN_ON(skb_tailroom(skb) < WEP_ICV_LEN || if (WARN_ON(skb_tailroom(skb) < IEEE80211_WEP_ICV_LEN ||
skb_headroom(skb) < WEP_IV_LEN)) skb_headroom(skb) < IEEE80211_WEP_IV_LEN))
return NULL; return NULL;
hdrlen = ieee80211_hdrlen(hdr->frame_control); hdrlen = ieee80211_hdrlen(hdr->frame_control);
newhdr = skb_push(skb, WEP_IV_LEN); newhdr = skb_push(skb, IEEE80211_WEP_IV_LEN);
memmove(newhdr, newhdr + WEP_IV_LEN, hdrlen); memmove(newhdr, newhdr + IEEE80211_WEP_IV_LEN, hdrlen);
/* the HW only needs room for the IV, but not the actual IV */ /* the HW only needs room for the IV, but not the actual IV */
if (info->control.hw_key && if (info->control.hw_key &&
(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)) (info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
return newhdr + hdrlen; return newhdr + hdrlen;
skb_set_network_header(skb, skb_network_offset(skb) + WEP_IV_LEN); skb_set_network_header(skb, skb_network_offset(skb) +
IEEE80211_WEP_IV_LEN);
ieee80211_wep_get_iv(local, keylen, keyidx, newhdr + hdrlen); ieee80211_wep_get_iv(local, keylen, keyidx, newhdr + hdrlen);
return newhdr + hdrlen; return newhdr + hdrlen;
} }
...@@ -125,8 +126,8 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local, ...@@ -125,8 +126,8 @@ static void ieee80211_wep_remove_iv(struct ieee80211_local *local,
unsigned int hdrlen; unsigned int hdrlen;
hdrlen = ieee80211_hdrlen(hdr->frame_control); hdrlen = ieee80211_hdrlen(hdr->frame_control);
memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen); memmove(skb->data + IEEE80211_WEP_IV_LEN, skb->data, hdrlen);
skb_pull(skb, WEP_IV_LEN); skb_pull(skb, IEEE80211_WEP_IV_LEN);
} }
...@@ -146,7 +147,7 @@ int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key, ...@@ -146,7 +147,7 @@ int ieee80211_wep_encrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
put_unaligned(icv, (__le32 *)(data + data_len)); put_unaligned(icv, (__le32 *)(data + data_len));
crypto_cipher_setkey(tfm, rc4key, klen); crypto_cipher_setkey(tfm, rc4key, klen);
for (i = 0; i < data_len + WEP_ICV_LEN; i++) for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
crypto_cipher_encrypt_one(tfm, data + i, data + i); crypto_cipher_encrypt_one(tfm, data + i, data + i);
return 0; return 0;
...@@ -172,7 +173,7 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, ...@@ -172,7 +173,7 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local,
if (!iv) if (!iv)
return -1; return -1;
len = skb->len - (iv + WEP_IV_LEN - skb->data); len = skb->len - (iv + IEEE80211_WEP_IV_LEN - skb->data);
/* Prepend 24-bit IV to RC4 key */ /* Prepend 24-bit IV to RC4 key */
memcpy(rc4key, iv, 3); memcpy(rc4key, iv, 3);
...@@ -181,10 +182,10 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local, ...@@ -181,10 +182,10 @@ int ieee80211_wep_encrypt(struct ieee80211_local *local,
memcpy(rc4key + 3, key, keylen); memcpy(rc4key + 3, key, keylen);
/* Add room for ICV */ /* Add room for ICV */
skb_put(skb, WEP_ICV_LEN); skb_put(skb, IEEE80211_WEP_ICV_LEN);
return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3, return ieee80211_wep_encrypt_data(local->wep_tx_tfm, rc4key, keylen + 3,
iv + WEP_IV_LEN, len); iv + IEEE80211_WEP_IV_LEN, len);
} }
...@@ -201,11 +202,11 @@ int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key, ...@@ -201,11 +202,11 @@ int ieee80211_wep_decrypt_data(struct crypto_cipher *tfm, u8 *rc4key,
return -1; return -1;
crypto_cipher_setkey(tfm, rc4key, klen); crypto_cipher_setkey(tfm, rc4key, klen);
for (i = 0; i < data_len + WEP_ICV_LEN; i++) for (i = 0; i < data_len + IEEE80211_WEP_ICV_LEN; i++)
crypto_cipher_decrypt_one(tfm, data + i, data + i); crypto_cipher_decrypt_one(tfm, data + i, data + i);
crc = cpu_to_le32(~crc32_le(~0, data, data_len)); crc = cpu_to_le32(~crc32_le(~0, data, data_len));
if (memcmp(&crc, data + data_len, WEP_ICV_LEN) != 0) if (memcmp(&crc, data + data_len, IEEE80211_WEP_ICV_LEN) != 0)
/* ICV mismatch */ /* ICV mismatch */
return -1; return -1;
...@@ -237,10 +238,10 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local, ...@@ -237,10 +238,10 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local,
return -1; return -1;
hdrlen = ieee80211_hdrlen(hdr->frame_control); hdrlen = ieee80211_hdrlen(hdr->frame_control);
if (skb->len < hdrlen + WEP_IV_LEN + WEP_ICV_LEN) if (skb->len < hdrlen + IEEE80211_WEP_IV_LEN + IEEE80211_WEP_ICV_LEN)
return -1; return -1;
len = skb->len - hdrlen - WEP_IV_LEN - WEP_ICV_LEN; len = skb->len - hdrlen - IEEE80211_WEP_IV_LEN - IEEE80211_WEP_ICV_LEN;
keyidx = skb->data[hdrlen + 3] >> 6; keyidx = skb->data[hdrlen + 3] >> 6;
...@@ -256,16 +257,16 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local, ...@@ -256,16 +257,16 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local,
memcpy(rc4key + 3, key->conf.key, key->conf.keylen); memcpy(rc4key + 3, key->conf.key, key->conf.keylen);
if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen, if (ieee80211_wep_decrypt_data(local->wep_rx_tfm, rc4key, klen,
skb->data + hdrlen + WEP_IV_LEN, skb->data + hdrlen +
len)) IEEE80211_WEP_IV_LEN, len))
ret = -1; ret = -1;
/* Trim ICV */ /* Trim ICV */
skb_trim(skb, skb->len - WEP_ICV_LEN); skb_trim(skb, skb->len - IEEE80211_WEP_ICV_LEN);
/* Remove IV */ /* Remove IV */
memmove(skb->data + WEP_IV_LEN, skb->data, hdrlen); memmove(skb->data + IEEE80211_WEP_IV_LEN, skb->data, hdrlen);
skb_pull(skb, WEP_IV_LEN); skb_pull(skb, IEEE80211_WEP_IV_LEN);
return ret; return ret;
} }
...@@ -305,13 +306,14 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) ...@@ -305,13 +306,14 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx)
if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key))
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
} else if (!(status->flag & RX_FLAG_IV_STRIPPED)) { } else if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) + WEP_IV_LEN)) if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) +
IEEE80211_WEP_IV_LEN))
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key)) if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key))
rx->sta->wep_weak_iv_count++; rx->sta->wep_weak_iv_count++;
ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key);
/* remove ICV */ /* remove ICV */
if (pskb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN)) if (pskb_trim(rx->skb, rx->skb->len - IEEE80211_WEP_ICV_LEN))
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
} }
......
...@@ -62,10 +62,10 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx) ...@@ -62,10 +62,10 @@ ieee80211_tx_h_michael_mic_add(struct ieee80211_tx_data *tx)
tail = MICHAEL_MIC_LEN; tail = MICHAEL_MIC_LEN;
if (!info->control.hw_key) if (!info->control.hw_key)
tail += TKIP_ICV_LEN; tail += IEEE80211_TKIP_ICV_LEN;
if (WARN_ON(skb_tailroom(skb) < tail || if (WARN_ON(skb_tailroom(skb) < tail ||
skb_headroom(skb) < TKIP_IV_LEN)) skb_headroom(skb) < IEEE80211_TKIP_IV_LEN))
return TX_DROP; return TX_DROP;
key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY]; key = &tx->key->conf.key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY];
...@@ -198,15 +198,16 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) ...@@ -198,15 +198,16 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
if (info->control.hw_key) if (info->control.hw_key)
tail = 0; tail = 0;
else else
tail = TKIP_ICV_LEN; tail = IEEE80211_TKIP_ICV_LEN;
if (WARN_ON(skb_tailroom(skb) < tail || if (WARN_ON(skb_tailroom(skb) < tail ||
skb_headroom(skb) < TKIP_IV_LEN)) skb_headroom(skb) < IEEE80211_TKIP_IV_LEN))
return -1; return -1;
pos = skb_push(skb, TKIP_IV_LEN); pos = skb_push(skb, IEEE80211_TKIP_IV_LEN);
memmove(pos, pos + TKIP_IV_LEN, hdrlen); memmove(pos, pos + IEEE80211_TKIP_IV_LEN, hdrlen);
skb_set_network_header(skb, skb_network_offset(skb) + TKIP_IV_LEN); skb_set_network_header(skb, skb_network_offset(skb) +
IEEE80211_TKIP_IV_LEN);
pos += hdrlen; pos += hdrlen;
/* the HW only needs room for the IV, but not the actual IV */ /* the HW only needs room for the IV, but not the actual IV */
...@@ -227,7 +228,7 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) ...@@ -227,7 +228,7 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
return 0; return 0;
/* Add room for ICV */ /* Add room for ICV */
skb_put(skb, TKIP_ICV_LEN); skb_put(skb, IEEE80211_TKIP_ICV_LEN);
return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm, return ieee80211_tkip_encrypt_data(tx->local->wep_tx_tfm,
key, skb, pos, len); key, skb, pos, len);
...@@ -290,11 +291,11 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) ...@@ -290,11 +291,11 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
/* Trim ICV */ /* Trim ICV */
skb_trim(skb, skb->len - TKIP_ICV_LEN); skb_trim(skb, skb->len - IEEE80211_TKIP_ICV_LEN);
/* Remove IV */ /* Remove IV */
memmove(skb->data + TKIP_IV_LEN, skb->data, hdrlen); memmove(skb->data + IEEE80211_TKIP_IV_LEN, skb->data, hdrlen);
skb_pull(skb, TKIP_IV_LEN); skb_pull(skb, IEEE80211_TKIP_IV_LEN);
return RX_CONTINUE; return RX_CONTINUE;
} }
...@@ -337,9 +338,9 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, ...@@ -337,9 +338,9 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
else else
qos_tid = 0; qos_tid = 0;
data_len = skb->len - hdrlen - CCMP_HDR_LEN; data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN;
if (encrypted) if (encrypted)
data_len -= CCMP_MIC_LEN; data_len -= IEEE80211_CCMP_MIC_LEN;
/* First block, b_0 */ /* First block, b_0 */
b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */ b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
...@@ -348,7 +349,7 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch, ...@@ -348,7 +349,7 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
*/ */
b_0[1] = qos_tid | (mgmt << 4); b_0[1] = qos_tid | (mgmt << 4);
memcpy(&b_0[2], hdr->addr2, ETH_ALEN); memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
memcpy(&b_0[8], pn, CCMP_PN_LEN); memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
/* l(m) */ /* l(m) */
put_unaligned_be16(data_len, &b_0[14]); put_unaligned_be16(data_len, &b_0[14]);
...@@ -424,15 +425,16 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) ...@@ -424,15 +425,16 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
if (info->control.hw_key) if (info->control.hw_key)
tail = 0; tail = 0;
else else
tail = CCMP_MIC_LEN; tail = IEEE80211_CCMP_MIC_LEN;
if (WARN_ON(skb_tailroom(skb) < tail || if (WARN_ON(skb_tailroom(skb) < tail ||
skb_headroom(skb) < CCMP_HDR_LEN)) skb_headroom(skb) < IEEE80211_CCMP_HDR_LEN))
return -1; return -1;
pos = skb_push(skb, CCMP_HDR_LEN); pos = skb_push(skb, IEEE80211_CCMP_HDR_LEN);
memmove(pos, pos + CCMP_HDR_LEN, hdrlen); memmove(pos, pos + IEEE80211_CCMP_HDR_LEN, hdrlen);
skb_set_network_header(skb, skb_network_offset(skb) + CCMP_HDR_LEN); skb_set_network_header(skb, skb_network_offset(skb) +
IEEE80211_CCMP_HDR_LEN);
/* the HW only needs room for the IV, but not the actual IV */ /* the HW only needs room for the IV, but not the actual IV */
if (info->control.hw_key && if (info->control.hw_key &&
...@@ -457,10 +459,10 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) ...@@ -457,10 +459,10 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
if (info->control.hw_key) if (info->control.hw_key)
return 0; return 0;
pos += CCMP_HDR_LEN; pos += IEEE80211_CCMP_HDR_LEN;
ccmp_special_blocks(skb, pn, scratch, 0); ccmp_special_blocks(skb, pn, scratch, 0);
ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len, ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
pos, skb_put(skb, CCMP_MIC_LEN)); pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN));
return 0; return 0;
} }
...@@ -490,7 +492,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) ...@@ -490,7 +492,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
struct ieee80211_key *key = rx->key; struct ieee80211_key *key = rx->key;
struct sk_buff *skb = rx->skb; struct sk_buff *skb = rx->skb;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
u8 pn[CCMP_PN_LEN]; u8 pn[IEEE80211_CCMP_PN_LEN];
int data_len; int data_len;
int queue; int queue;
...@@ -500,12 +502,13 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) ...@@ -500,12 +502,13 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
!ieee80211_is_robust_mgmt_frame(hdr)) !ieee80211_is_robust_mgmt_frame(hdr))
return RX_CONTINUE; return RX_CONTINUE;
data_len = skb->len - hdrlen - CCMP_HDR_LEN - CCMP_MIC_LEN; data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN -
IEEE80211_CCMP_MIC_LEN;
if (!rx->sta || data_len < 0) if (!rx->sta || data_len < 0)
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
if (status->flag & RX_FLAG_DECRYPTED) { if (status->flag & RX_FLAG_DECRYPTED) {
if (!pskb_may_pull(rx->skb, hdrlen + CCMP_HDR_LEN)) if (!pskb_may_pull(rx->skb, hdrlen + IEEE80211_CCMP_HDR_LEN))
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
} else { } else {
if (skb_linearize(rx->skb)) if (skb_linearize(rx->skb))
...@@ -516,7 +519,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) ...@@ -516,7 +519,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
queue = rx->security_idx; queue = rx->security_idx;
if (memcmp(pn, key->u.ccmp.rx_pn[queue], CCMP_PN_LEN) <= 0) { if (memcmp(pn, key->u.ccmp.rx_pn[queue], IEEE80211_CCMP_PN_LEN) <= 0) {
key->u.ccmp.replays++; key->u.ccmp.replays++;
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
} }
...@@ -528,19 +531,20 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) ...@@ -528,19 +531,20 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
if (ieee80211_aes_ccm_decrypt( if (ieee80211_aes_ccm_decrypt(
key->u.ccmp.tfm, scratch, key->u.ccmp.tfm, scratch,
skb->data + hdrlen + CCMP_HDR_LEN, data_len, skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
skb->data + skb->len - CCMP_MIC_LEN, data_len,
skb->data + hdrlen + CCMP_HDR_LEN)) skb->data + skb->len - IEEE80211_CCMP_MIC_LEN,
skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN))
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
} }
memcpy(key->u.ccmp.rx_pn[queue], pn, CCMP_PN_LEN); memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN);
/* Remove CCMP header and MIC */ /* Remove CCMP header and MIC */
if (pskb_trim(skb, skb->len - CCMP_MIC_LEN)) if (pskb_trim(skb, skb->len - IEEE80211_CCMP_MIC_LEN))
return RX_DROP_UNUSABLE; return RX_DROP_UNUSABLE;
memmove(skb->data + CCMP_HDR_LEN, skb->data, hdrlen); memmove(skb->data + IEEE80211_CCMP_HDR_LEN, skb->data, hdrlen);
skb_pull(skb, CCMP_HDR_LEN); skb_pull(skb, IEEE80211_CCMP_HDR_LEN);
return RX_CONTINUE; return RX_CONTINUE;
} }
......
...@@ -34,13 +34,12 @@ ...@@ -34,13 +34,12 @@
MODULE_AUTHOR("Johannes Berg"); MODULE_AUTHOR("Johannes Berg");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("wireless configuration support"); MODULE_DESCRIPTION("wireless configuration support");
MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME);
/* RCU-protected (and cfg80211_mutex for writers) */ /* RCU-protected (and RTNL for writers) */
LIST_HEAD(cfg80211_rdev_list); LIST_HEAD(cfg80211_rdev_list);
int cfg80211_rdev_list_generation; int cfg80211_rdev_list_generation;
DEFINE_MUTEX(cfg80211_mutex);
/* for debugfs */ /* for debugfs */
static struct dentry *ieee80211_debugfs_dir; static struct dentry *ieee80211_debugfs_dir;
...@@ -52,12 +51,11 @@ module_param(cfg80211_disable_40mhz_24ghz, bool, 0644); ...@@ -52,12 +51,11 @@ module_param(cfg80211_disable_40mhz_24ghz, bool, 0644);
MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz, MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz,
"Disable 40MHz support in the 2.4GHz band"); "Disable 40MHz support in the 2.4GHz band");
/* requires cfg80211_mutex to be held! */
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx) struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
{ {
struct cfg80211_registered_device *result = NULL, *rdev; struct cfg80211_registered_device *result = NULL, *rdev;
assert_cfg80211_lock(); ASSERT_RTNL();
list_for_each_entry(rdev, &cfg80211_rdev_list, list) { list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
if (rdev->wiphy_idx == wiphy_idx) { if (rdev->wiphy_idx == wiphy_idx) {
...@@ -76,12 +74,11 @@ int get_wiphy_idx(struct wiphy *wiphy) ...@@ -76,12 +74,11 @@ int get_wiphy_idx(struct wiphy *wiphy)
return rdev->wiphy_idx; return rdev->wiphy_idx;
} }
/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx) struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
{ {
struct cfg80211_registered_device *rdev; struct cfg80211_registered_device *rdev;
assert_cfg80211_lock(); ASSERT_RTNL();
rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx); rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx);
if (!rdev) if (!rdev)
...@@ -89,35 +86,13 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx) ...@@ -89,35 +86,13 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
return &rdev->wiphy; return &rdev->wiphy;
} }
struct cfg80211_registered_device *
cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
{
struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
struct net_device *dev;
mutex_lock(&cfg80211_mutex);
dev = dev_get_by_index(net, ifindex);
if (!dev)
goto out;
if (dev->ieee80211_ptr) {
rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
mutex_lock(&rdev->mtx);
} else
rdev = ERR_PTR(-ENODEV);
dev_put(dev);
out:
mutex_unlock(&cfg80211_mutex);
return rdev;
}
/* requires cfg80211_mutex to be held */
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev, int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
char *newname) char *newname)
{ {
struct cfg80211_registered_device *rdev2; struct cfg80211_registered_device *rdev2;
int wiphy_idx, taken = -1, result, digits; int wiphy_idx, taken = -1, result, digits;
assert_cfg80211_lock(); ASSERT_RTNL();
/* prohibit calling the thing phy%d when %d is not its number */ /* prohibit calling the thing phy%d when %d is not its number */
sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken); sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
...@@ -215,8 +190,7 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data) ...@@ -215,8 +190,7 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev) struct wireless_dev *wdev)
{ {
lockdep_assert_held(&rdev->devlist_mtx); ASSERT_RTNL();
lockdep_assert_held(&rdev->sched_scan_mtx);
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)) if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
return; return;
...@@ -230,18 +204,15 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, ...@@ -230,18 +204,15 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
rdev->opencount--; rdev->opencount--;
if (rdev->scan_req && rdev->scan_req->wdev == wdev) { if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
bool busy = work_busy(&rdev->scan_done_wk);
/* /*
* If the work isn't pending or running (in which case it would * If the scan request wasn't notified as done, set it
* be waiting for the lock we hold) the driver didn't properly * to aborted and leak it after a warning. The driver
* cancel the scan when the interface was removed. In this case * should have notified us that it ended at the latest
* warn and leak the scan request object to not crash later. * during rdev_stop_p2p_device().
*/ */
WARN_ON(!busy); if (WARN_ON(!rdev->scan_req->notified))
rdev->scan_req->aborted = true;
rdev->scan_req->aborted = true; ___cfg80211_scan_done(rdev, !rdev->scan_req->notified);
___cfg80211_scan_done(rdev, !busy);
} }
} }
...@@ -255,8 +226,6 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) ...@@ -255,8 +226,6 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
rtnl_lock(); rtnl_lock();
/* read-only iteration need not hold the devlist_mtx */
list_for_each_entry(wdev, &rdev->wdev_list, list) { list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (wdev->netdev) { if (wdev->netdev) {
dev_close(wdev->netdev); dev_close(wdev->netdev);
...@@ -265,12 +234,7 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) ...@@ -265,12 +234,7 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
/* otherwise, check iftype */ /* otherwise, check iftype */
switch (wdev->iftype) { switch (wdev->iftype) {
case NL80211_IFTYPE_P2P_DEVICE: case NL80211_IFTYPE_P2P_DEVICE:
/* but this requires it */
mutex_lock(&rdev->devlist_mtx);
mutex_lock(&rdev->sched_scan_mtx);
cfg80211_stop_p2p_device(rdev, wdev); cfg80211_stop_p2p_device(rdev, wdev);
mutex_unlock(&rdev->sched_scan_mtx);
mutex_unlock(&rdev->devlist_mtx);
break; break;
default: default:
break; break;
...@@ -298,10 +262,7 @@ static void cfg80211_event_work(struct work_struct *work) ...@@ -298,10 +262,7 @@ static void cfg80211_event_work(struct work_struct *work)
event_work); event_work);
rtnl_lock(); rtnl_lock();
cfg80211_lock_rdev(rdev);
cfg80211_process_rdev_events(rdev); cfg80211_process_rdev_events(rdev);
cfg80211_unlock_rdev(rdev);
rtnl_unlock(); rtnl_unlock();
} }
...@@ -309,7 +270,7 @@ static void cfg80211_event_work(struct work_struct *work) ...@@ -309,7 +270,7 @@ static void cfg80211_event_work(struct work_struct *work)
struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
{ {
static int wiphy_counter; static atomic_t wiphy_counter = ATOMIC_INIT(0);
struct cfg80211_registered_device *rdev; struct cfg80211_registered_device *rdev;
int alloc_size; int alloc_size;
...@@ -331,26 +292,18 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) ...@@ -331,26 +292,18 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
rdev->ops = ops; rdev->ops = ops;
mutex_lock(&cfg80211_mutex); rdev->wiphy_idx = atomic_inc_return(&wiphy_counter);
rdev->wiphy_idx = wiphy_counter++;
if (unlikely(rdev->wiphy_idx < 0)) { if (unlikely(rdev->wiphy_idx < 0)) {
wiphy_counter--;
mutex_unlock(&cfg80211_mutex);
/* ugh, wrapped! */ /* ugh, wrapped! */
atomic_dec(&wiphy_counter);
kfree(rdev); kfree(rdev);
return NULL; return NULL;
} }
mutex_unlock(&cfg80211_mutex);
/* give it a proper name */ /* give it a proper name */
dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx); dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
mutex_init(&rdev->mtx);
mutex_init(&rdev->devlist_mtx);
mutex_init(&rdev->sched_scan_mtx);
INIT_LIST_HEAD(&rdev->wdev_list); INIT_LIST_HEAD(&rdev->wdev_list);
INIT_LIST_HEAD(&rdev->beacon_registrations); INIT_LIST_HEAD(&rdev->beacon_registrations);
spin_lock_init(&rdev->beacon_registrations_lock); spin_lock_init(&rdev->beacon_registrations_lock);
...@@ -598,11 +551,11 @@ int wiphy_register(struct wiphy *wiphy) ...@@ -598,11 +551,11 @@ int wiphy_register(struct wiphy *wiphy)
/* check and set up bitrates */ /* check and set up bitrates */
ieee80211_set_bitrate_flags(wiphy); ieee80211_set_bitrate_flags(wiphy);
mutex_lock(&cfg80211_mutex); rtnl_lock();
res = device_add(&rdev->wiphy.dev); res = device_add(&rdev->wiphy.dev);
if (res) { if (res) {
mutex_unlock(&cfg80211_mutex); rtnl_unlock();
return res; return res;
} }
...@@ -631,24 +584,21 @@ int wiphy_register(struct wiphy *wiphy) ...@@ -631,24 +584,21 @@ int wiphy_register(struct wiphy *wiphy)
} }
cfg80211_debugfs_rdev_add(rdev); cfg80211_debugfs_rdev_add(rdev);
mutex_unlock(&cfg80211_mutex);
/*
* due to a locking dependency this has to be outside of the
* cfg80211_mutex lock
*/
res = rfkill_register(rdev->rfkill); res = rfkill_register(rdev->rfkill);
if (res) if (res) {
goto out_rm_dev; device_del(&rdev->wiphy.dev);
debugfs_remove_recursive(rdev->wiphy.debugfsdir);
list_del_rcu(&rdev->list);
wiphy_regulatory_deregister(wiphy);
rtnl_unlock();
return res;
}
rtnl_lock();
rdev->wiphy.registered = true; rdev->wiphy.registered = true;
rtnl_unlock(); rtnl_unlock();
return 0; return 0;
out_rm_dev:
device_del(&rdev->wiphy.dev);
return res;
} }
EXPORT_SYMBOL(wiphy_register); EXPORT_SYMBOL(wiphy_register);
...@@ -675,25 +625,19 @@ void wiphy_unregister(struct wiphy *wiphy) ...@@ -675,25 +625,19 @@ void wiphy_unregister(struct wiphy *wiphy)
{ {
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
rtnl_lock();
rdev->wiphy.registered = false;
rtnl_unlock();
rfkill_unregister(rdev->rfkill);
/* protect the device list */
mutex_lock(&cfg80211_mutex);
wait_event(rdev->dev_wait, ({ wait_event(rdev->dev_wait, ({
int __count; int __count;
mutex_lock(&rdev->devlist_mtx); rtnl_lock();
__count = rdev->opencount; __count = rdev->opencount;
mutex_unlock(&rdev->devlist_mtx); rtnl_unlock();
__count == 0; })); __count == 0; }));
mutex_lock(&rdev->devlist_mtx); rtnl_lock();
rdev->wiphy.registered = false;
rfkill_unregister(rdev->rfkill);
BUG_ON(!list_empty(&rdev->wdev_list)); BUG_ON(!list_empty(&rdev->wdev_list));
mutex_unlock(&rdev->devlist_mtx);
/* /*
* First remove the hardware from everywhere, this makes * First remove the hardware from everywhere, this makes
...@@ -703,20 +647,6 @@ void wiphy_unregister(struct wiphy *wiphy) ...@@ -703,20 +647,6 @@ void wiphy_unregister(struct wiphy *wiphy)
list_del_rcu(&rdev->list); list_del_rcu(&rdev->list);
synchronize_rcu(); synchronize_rcu();
/*
* Try to grab rdev->mtx. If a command is still in progress,
* hopefully the driver will refuse it since it's tearing
* down the device already. We wait for this command to complete
* before unlinking the item from the list.
* Note: as codified by the BUG_ON above we cannot get here if
* a virtual interface is still present. Hence, we can only get
* to lock contention here if userspace issues a command that
* identified the hardware by wiphy index.
*/
cfg80211_lock_rdev(rdev);
/* nothing */
cfg80211_unlock_rdev(rdev);
/* /*
* If this device got a regulatory hint tell core its * If this device got a regulatory hint tell core its
* free to listen now to a new shiny device regulatory hint * free to listen now to a new shiny device regulatory hint
...@@ -726,15 +656,17 @@ void wiphy_unregister(struct wiphy *wiphy) ...@@ -726,15 +656,17 @@ void wiphy_unregister(struct wiphy *wiphy)
cfg80211_rdev_list_generation++; cfg80211_rdev_list_generation++;
device_del(&rdev->wiphy.dev); device_del(&rdev->wiphy.dev);
mutex_unlock(&cfg80211_mutex); rtnl_unlock();
flush_work(&rdev->scan_done_wk); flush_work(&rdev->scan_done_wk);
cancel_work_sync(&rdev->conn_work); cancel_work_sync(&rdev->conn_work);
flush_work(&rdev->event_work); flush_work(&rdev->event_work);
cancel_delayed_work_sync(&rdev->dfs_update_channels_wk); cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);
if (rdev->wowlan && rdev->ops->set_wakeup) #ifdef CONFIG_PM
if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)
rdev_set_wakeup(rdev, false); rdev_set_wakeup(rdev, false);
#endif
cfg80211_rdev_free_wowlan(rdev); cfg80211_rdev_free_wowlan(rdev);
} }
EXPORT_SYMBOL(wiphy_unregister); EXPORT_SYMBOL(wiphy_unregister);
...@@ -744,9 +676,6 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) ...@@ -744,9 +676,6 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
struct cfg80211_internal_bss *scan, *tmp; struct cfg80211_internal_bss *scan, *tmp;
struct cfg80211_beacon_registration *reg, *treg; struct cfg80211_beacon_registration *reg, *treg;
rfkill_destroy(rdev->rfkill); rfkill_destroy(rdev->rfkill);
mutex_destroy(&rdev->mtx);
mutex_destroy(&rdev->devlist_mtx);
mutex_destroy(&rdev->sched_scan_mtx);
list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) { list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
list_del(&reg->list); list_del(&reg->list);
kfree(reg); kfree(reg);
...@@ -771,36 +700,6 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked) ...@@ -771,36 +700,6 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
} }
EXPORT_SYMBOL(wiphy_rfkill_set_hw_state); EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
static void wdev_cleanup_work(struct work_struct *work)
{
struct wireless_dev *wdev;
struct cfg80211_registered_device *rdev;
wdev = container_of(work, struct wireless_dev, cleanup_work);
rdev = wiphy_to_dev(wdev->wiphy);
mutex_lock(&rdev->sched_scan_mtx);
if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
rdev->scan_req->aborted = true;
___cfg80211_scan_done(rdev, true);
}
if (WARN_ON(rdev->sched_scan_req &&
rdev->sched_scan_req->dev == wdev->netdev)) {
__cfg80211_stop_sched_scan(rdev, false);
}
mutex_unlock(&rdev->sched_scan_mtx);
mutex_lock(&rdev->devlist_mtx);
rdev->opencount--;
mutex_unlock(&rdev->devlist_mtx);
wake_up(&rdev->dev_wait);
dev_put(wdev->netdev);
}
void cfg80211_unregister_wdev(struct wireless_dev *wdev) void cfg80211_unregister_wdev(struct wireless_dev *wdev)
{ {
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
...@@ -810,8 +709,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev) ...@@ -810,8 +709,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
if (WARN_ON(wdev->netdev)) if (WARN_ON(wdev->netdev))
return; return;
mutex_lock(&rdev->devlist_mtx);
mutex_lock(&rdev->sched_scan_mtx);
list_del_rcu(&wdev->list); list_del_rcu(&wdev->list);
rdev->devlist_generation++; rdev->devlist_generation++;
...@@ -823,8 +720,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev) ...@@ -823,8 +720,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
break; break;
} }
mutex_unlock(&rdev->sched_scan_mtx);
mutex_unlock(&rdev->devlist_mtx);
} }
EXPORT_SYMBOL(cfg80211_unregister_wdev); EXPORT_SYMBOL(cfg80211_unregister_wdev);
...@@ -843,7 +738,7 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev, ...@@ -843,7 +738,7 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
} }
void cfg80211_leave(struct cfg80211_registered_device *rdev, void cfg80211_leave(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev) struct wireless_dev *wdev)
{ {
struct net_device *dev = wdev->netdev; struct net_device *dev = wdev->netdev;
...@@ -853,9 +748,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, ...@@ -853,9 +748,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
break; break;
case NL80211_IFTYPE_P2P_CLIENT: case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
mutex_lock(&rdev->sched_scan_mtx);
__cfg80211_stop_sched_scan(rdev, false); __cfg80211_stop_sched_scan(rdev, false);
mutex_unlock(&rdev->sched_scan_mtx);
wdev_lock(wdev); wdev_lock(wdev);
#ifdef CONFIG_CFG80211_WEXT #ifdef CONFIG_CFG80211_WEXT
...@@ -864,9 +757,8 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, ...@@ -864,9 +757,8 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
wdev->wext.ie_len = 0; wdev->wext.ie_len = 0;
wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
#endif #endif
__cfg80211_disconnect(rdev, dev, cfg80211_disconnect(rdev, dev,
WLAN_REASON_DEAUTH_LEAVING, true); WLAN_REASON_DEAUTH_LEAVING, true);
cfg80211_mlme_down(rdev, dev);
wdev_unlock(wdev); wdev_unlock(wdev);
break; break;
case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_MESH_POINT:
...@@ -909,13 +801,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, ...@@ -909,13 +801,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
* are added with nl80211. * are added with nl80211.
*/ */
mutex_init(&wdev->mtx); mutex_init(&wdev->mtx);
INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
INIT_LIST_HEAD(&wdev->event_list); INIT_LIST_HEAD(&wdev->event_list);
spin_lock_init(&wdev->event_lock); spin_lock_init(&wdev->event_lock);
INIT_LIST_HEAD(&wdev->mgmt_registrations); INIT_LIST_HEAD(&wdev->mgmt_registrations);
spin_lock_init(&wdev->mgmt_registrations_lock); spin_lock_init(&wdev->mgmt_registrations_lock);
mutex_lock(&rdev->devlist_mtx);
wdev->identifier = ++rdev->wdev_id; wdev->identifier = ++rdev->wdev_id;
list_add_rcu(&wdev->list, &rdev->wdev_list); list_add_rcu(&wdev->list, &rdev->wdev_list);
rdev->devlist_generation++; rdev->devlist_generation++;
...@@ -928,7 +818,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, ...@@ -928,7 +818,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
} }
wdev->netdev = dev; wdev->netdev = dev;
wdev->sme_state = CFG80211_SME_IDLE; wdev->sme_state = CFG80211_SME_IDLE;
mutex_unlock(&rdev->devlist_mtx);
#ifdef CONFIG_CFG80211_WEXT #ifdef CONFIG_CFG80211_WEXT
wdev->wext.default_key = -1; wdev->wext.default_key = -1;
wdev->wext.default_mgmt_key = -1; wdev->wext.default_mgmt_key = -1;
...@@ -954,26 +843,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, ...@@ -954,26 +843,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
break; break;
case NETDEV_DOWN: case NETDEV_DOWN:
cfg80211_update_iface_num(rdev, wdev->iftype, -1); cfg80211_update_iface_num(rdev, wdev->iftype, -1);
dev_hold(dev); if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
queue_work(cfg80211_wq, &wdev->cleanup_work); if (WARN_ON(!rdev->scan_req->notified))
rdev->scan_req->aborted = true;
___cfg80211_scan_done(rdev, true);
}
if (WARN_ON(rdev->sched_scan_req &&
rdev->sched_scan_req->dev == wdev->netdev)) {
__cfg80211_stop_sched_scan(rdev, false);
}
rdev->opencount--;
wake_up(&rdev->dev_wait);
break; break;
case NETDEV_UP: case NETDEV_UP:
/*
* If we have a really quick DOWN/UP succession we may
* have this work still pending ... cancel it and see
* if it was pending, in which case we need to account
* for some of the work it would have done.
*/
if (cancel_work_sync(&wdev->cleanup_work)) {
mutex_lock(&rdev->devlist_mtx);
rdev->opencount--;
mutex_unlock(&rdev->devlist_mtx);
dev_put(dev);
}
cfg80211_update_iface_num(rdev, wdev->iftype, 1); cfg80211_update_iface_num(rdev, wdev->iftype, 1);
cfg80211_lock_rdev(rdev);
mutex_lock(&rdev->devlist_mtx);
mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev); wdev_lock(wdev);
switch (wdev->iftype) { switch (wdev->iftype) {
#ifdef CONFIG_CFG80211_WEXT #ifdef CONFIG_CFG80211_WEXT
...@@ -1005,10 +890,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, ...@@ -1005,10 +890,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
break; break;
} }
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->sched_scan_mtx);
rdev->opencount++; rdev->opencount++;
mutex_unlock(&rdev->devlist_mtx);
cfg80211_unlock_rdev(rdev);
/* /*
* Configure power management to the driver here so that its * Configure power management to the driver here so that its
...@@ -1024,12 +906,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, ...@@ -1024,12 +906,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
} }
break; break;
case NETDEV_UNREGISTER: case NETDEV_UNREGISTER:
/*
* NB: cannot take rdev->mtx here because this may be
* called within code protected by it when interfaces
* are removed with nl80211.
*/
mutex_lock(&rdev->devlist_mtx);
/* /*
* It is possible to get NETDEV_UNREGISTER * It is possible to get NETDEV_UNREGISTER
* multiple times. To detect that, check * multiple times. To detect that, check
...@@ -1046,7 +922,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, ...@@ -1046,7 +922,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
kfree(wdev->wext.keys); kfree(wdev->wext.keys);
#endif #endif
} }
mutex_unlock(&rdev->devlist_mtx);
/* /*
* synchronise (so that we won't find this netdev * synchronise (so that we won't find this netdev
* from other code any more) and then clear the list * from other code any more) and then clear the list
...@@ -1066,9 +941,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, ...@@ -1066,9 +941,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
return notifier_from_errno(-EOPNOTSUPP); return notifier_from_errno(-EOPNOTSUPP);
if (rfkill_blocked(rdev->rfkill)) if (rfkill_blocked(rdev->rfkill))
return notifier_from_errno(-ERFKILL); return notifier_from_errno(-ERFKILL);
mutex_lock(&rdev->devlist_mtx);
ret = cfg80211_can_add_interface(rdev, wdev->iftype); ret = cfg80211_can_add_interface(rdev, wdev->iftype);
mutex_unlock(&rdev->devlist_mtx);
if (ret) if (ret)
return notifier_from_errno(ret); return notifier_from_errno(ret);
break; break;
...@@ -1086,12 +959,10 @@ static void __net_exit cfg80211_pernet_exit(struct net *net) ...@@ -1086,12 +959,10 @@ static void __net_exit cfg80211_pernet_exit(struct net *net)
struct cfg80211_registered_device *rdev; struct cfg80211_registered_device *rdev;
rtnl_lock(); rtnl_lock();
mutex_lock(&cfg80211_mutex);
list_for_each_entry(rdev, &cfg80211_rdev_list, list) { list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
if (net_eq(wiphy_net(&rdev->wiphy), net)) if (net_eq(wiphy_net(&rdev->wiphy), net))
WARN_ON(cfg80211_switch_netns(rdev, &init_net)); WARN_ON(cfg80211_switch_netns(rdev, &init_net));
} }
mutex_unlock(&cfg80211_mutex);
rtnl_unlock(); rtnl_unlock();
} }
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
*/ */
#ifndef __NET_WIRELESS_CORE_H #ifndef __NET_WIRELESS_CORE_H
#define __NET_WIRELESS_CORE_H #define __NET_WIRELESS_CORE_H
#include <linux/mutex.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/rbtree.h> #include <linux/rbtree.h>
...@@ -23,11 +22,6 @@ ...@@ -23,11 +22,6 @@
struct cfg80211_registered_device { struct cfg80211_registered_device {
const struct cfg80211_ops *ops; const struct cfg80211_ops *ops;
struct list_head list; struct list_head list;
/* we hold this mutex during any call so that
* we cannot do multiple calls at once, and also
* to avoid the deregister call to proceed while
* any call is in progress */
struct mutex mtx;
/* rfkill support */ /* rfkill support */
struct rfkill_ops rfkill_ops; struct rfkill_ops rfkill_ops;
...@@ -49,9 +43,7 @@ struct cfg80211_registered_device { ...@@ -49,9 +43,7 @@ struct cfg80211_registered_device {
/* wiphy index, internal only */ /* wiphy index, internal only */
int wiphy_idx; int wiphy_idx;
/* associated wireless interfaces */ /* associated wireless interfaces, protected by rtnl or RCU */
struct mutex devlist_mtx;
/* protected by devlist_mtx or RCU */
struct list_head wdev_list; struct list_head wdev_list;
int devlist_generation, wdev_id; int devlist_generation, wdev_id;
int opencount; /* also protected by devlist_mtx */ int opencount; /* also protected by devlist_mtx */
...@@ -75,8 +67,6 @@ struct cfg80211_registered_device { ...@@ -75,8 +67,6 @@ struct cfg80211_registered_device {
struct work_struct scan_done_wk; struct work_struct scan_done_wk;
struct work_struct sched_scan_results_wk; struct work_struct sched_scan_results_wk;
struct mutex sched_scan_mtx;
#ifdef CONFIG_NL80211_TESTMODE #ifdef CONFIG_NL80211_TESTMODE
struct genl_info *testmode_info; struct genl_info *testmode_info;
#endif #endif
...@@ -84,8 +74,6 @@ struct cfg80211_registered_device { ...@@ -84,8 +74,6 @@ struct cfg80211_registered_device {
struct work_struct conn_work; struct work_struct conn_work;
struct work_struct event_work; struct work_struct event_work;
struct cfg80211_wowlan *wowlan;
struct delayed_work dfs_update_channels_wk; struct delayed_work dfs_update_channels_wk;
/* netlink port which started critical protocol (0 means not started) */ /* netlink port which started critical protocol (0 means not started) */
...@@ -106,29 +94,26 @@ struct cfg80211_registered_device *wiphy_to_dev(struct wiphy *wiphy) ...@@ -106,29 +94,26 @@ struct cfg80211_registered_device *wiphy_to_dev(struct wiphy *wiphy)
static inline void static inline void
cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev) cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev)
{ {
#ifdef CONFIG_PM
int i; int i;
if (!rdev->wowlan) if (!rdev->wiphy.wowlan_config)
return; return;
for (i = 0; i < rdev->wowlan->n_patterns; i++) for (i = 0; i < rdev->wiphy.wowlan_config->n_patterns; i++)
kfree(rdev->wowlan->patterns[i].mask); kfree(rdev->wiphy.wowlan_config->patterns[i].mask);
kfree(rdev->wowlan->patterns); kfree(rdev->wiphy.wowlan_config->patterns);
if (rdev->wowlan->tcp && rdev->wowlan->tcp->sock) if (rdev->wiphy.wowlan_config->tcp &&
sock_release(rdev->wowlan->tcp->sock); rdev->wiphy.wowlan_config->tcp->sock)
kfree(rdev->wowlan->tcp); sock_release(rdev->wiphy.wowlan_config->tcp->sock);
kfree(rdev->wowlan); kfree(rdev->wiphy.wowlan_config->tcp);
kfree(rdev->wiphy.wowlan_config);
#endif
} }
extern struct workqueue_struct *cfg80211_wq; extern struct workqueue_struct *cfg80211_wq;
extern struct mutex cfg80211_mutex;
extern struct list_head cfg80211_rdev_list; extern struct list_head cfg80211_rdev_list;
extern int cfg80211_rdev_list_generation; extern int cfg80211_rdev_list_generation;
static inline void assert_cfg80211_lock(void)
{
lockdep_assert_held(&cfg80211_mutex);
}
struct cfg80211_internal_bss { struct cfg80211_internal_bss {
struct list_head list; struct list_head list;
struct list_head hidden_list; struct list_head hidden_list;
...@@ -161,27 +146,11 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss) ...@@ -161,27 +146,11 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx); struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx);
int get_wiphy_idx(struct wiphy *wiphy); int get_wiphy_idx(struct wiphy *wiphy);
/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx); struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
/* identical to cfg80211_get_dev_from_info but only operate on ifindex */
extern struct cfg80211_registered_device *
cfg80211_get_dev_from_ifindex(struct net *net, int ifindex);
int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
struct net *net); struct net *net);
static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev)
{
mutex_lock(&rdev->mtx);
}
static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *rdev)
{
BUG_ON(IS_ERR(rdev) || !rdev);
mutex_unlock(&rdev->mtx);
}
static inline void wdev_lock(struct wireless_dev *wdev) static inline void wdev_lock(struct wireless_dev *wdev)
__acquires(wdev) __acquires(wdev)
{ {
...@@ -196,7 +165,7 @@ static inline void wdev_unlock(struct wireless_dev *wdev) ...@@ -196,7 +165,7 @@ static inline void wdev_unlock(struct wireless_dev *wdev)
mutex_unlock(&wdev->mtx); mutex_unlock(&wdev->mtx);
} }
#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx) #define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL()
#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx) #define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
...@@ -314,38 +283,21 @@ int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, ...@@ -314,38 +283,21 @@ int cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
struct net_device *dev); struct net_device *dev);
/* MLME */ /* MLME */
int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct ieee80211_channel *chan,
enum nl80211_auth_type auth_type,
const u8 *bssid,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len,
const u8 *key, int key_len, int key_idx,
const u8 *sae_data, int sae_data_len);
int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct ieee80211_channel *chan, struct net_device *dev,
enum nl80211_auth_type auth_type, const u8 *bssid, struct ieee80211_channel *chan,
enum nl80211_auth_type auth_type,
const u8 *bssid,
const u8 *ssid, int ssid_len, const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len, const u8 *ie, int ie_len,
const u8 *key, int key_len, int key_idx, const u8 *key, int key_len, int key_idx,
const u8 *sae_data, int sae_data_len); const u8 *sae_data, int sae_data_len);
int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct ieee80211_channel *chan,
const u8 *bssid,
const u8 *ssid, int ssid_len,
struct cfg80211_assoc_request *req);
int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct net_device *dev,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
const u8 *bssid, const u8 *bssid,
const u8 *ssid, int ssid_len, const u8 *ssid, int ssid_len,
struct cfg80211_assoc_request *req); struct cfg80211_assoc_request *req);
int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
struct net_device *dev, const u8 *bssid,
const u8 *ie, int ie_len, u16 reason,
bool local_state_change);
int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
struct net_device *dev, const u8 *bssid, struct net_device *dev, const u8 *bssid,
const u8 *ie, int ie_len, u16 reason, const u8 *ie, int ie_len, u16 reason,
...@@ -377,18 +329,11 @@ void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, ...@@ -377,18 +329,11 @@ void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa,
const struct ieee80211_vht_cap *vht_capa_mask); const struct ieee80211_vht_cap *vht_capa_mask);
/* SME */ /* SME */
int __cfg80211_connect(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct cfg80211_connect_params *connect,
struct cfg80211_cached_keys *connkeys,
const u8 *prev_bssid);
int cfg80211_connect(struct cfg80211_registered_device *rdev, int cfg80211_connect(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct net_device *dev,
struct cfg80211_connect_params *connect, struct cfg80211_connect_params *connect,
struct cfg80211_cached_keys *connkeys); struct cfg80211_cached_keys *connkeys,
int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, const u8 *prev_bssid);
struct net_device *dev, u16 reason,
bool wextev);
int cfg80211_disconnect(struct cfg80211_registered_device *rdev, int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
struct net_device *dev, u16 reason, struct net_device *dev, u16 reason,
bool wextev); bool wextev);
......
...@@ -74,7 +74,7 @@ static ssize_t ht40allow_map_read(struct file *file, ...@@ -74,7 +74,7 @@ static ssize_t ht40allow_map_read(struct file *file,
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
mutex_lock(&cfg80211_mutex); rtnl_lock();
for (band = 0; band < IEEE80211_NUM_BANDS; band++) { for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
sband = wiphy->bands[band]; sband = wiphy->bands[band];
...@@ -85,7 +85,7 @@ static ssize_t ht40allow_map_read(struct file *file, ...@@ -85,7 +85,7 @@ static ssize_t ht40allow_map_read(struct file *file,
buf, buf_size, offset); buf, buf_size, offset);
} }
mutex_unlock(&cfg80211_mutex); rtnl_unlock();
r = simple_read_from_buffer(user_buf, count, ppos, buf, offset); r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
......
...@@ -152,11 +152,11 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, ...@@ -152,11 +152,11 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
int err; int err;
mutex_lock(&rdev->devlist_mtx); ASSERT_RTNL();
wdev_lock(wdev); wdev_lock(wdev);
err = __cfg80211_join_ibss(rdev, dev, params, connkeys); err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->devlist_mtx);
return err; return err;
} }
...@@ -359,11 +359,9 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev, ...@@ -359,11 +359,9 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
wdev->wext.ibss.channel_fixed = false; wdev->wext.ibss.channel_fixed = false;
} }
mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev); wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev); err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->devlist_mtx);
return err; return err;
} }
...@@ -429,11 +427,9 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev, ...@@ -429,11 +427,9 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
memcpy(wdev->wext.ibss.ssid, ssid, len); memcpy(wdev->wext.ibss.ssid, ssid, len);
wdev->wext.ibss.ssid_len = len; wdev->wext.ibss.ssid_len = len;
mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev); wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev); err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->devlist_mtx);
return err; return err;
} }
...@@ -512,11 +508,9 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev, ...@@ -512,11 +508,9 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
} else } else
wdev->wext.ibss.bssid = NULL; wdev->wext.ibss.bssid = NULL;
mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev); wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev); err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->devlist_mtx);
return err; return err;
} }
......
...@@ -82,6 +82,7 @@ const struct mesh_setup default_mesh_setup = { ...@@ -82,6 +82,7 @@ const struct mesh_setup default_mesh_setup = {
.sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET, .sync_method = IEEE80211_SYNC_METHOD_NEIGHBOR_OFFSET,
.path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP, .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP,
.path_metric = IEEE80211_PATH_METRIC_AIRTIME, .path_metric = IEEE80211_PATH_METRIC_AIRTIME,
.auth_id = 0, /* open */
.ie = NULL, .ie = NULL,
.ie_len = 0, .ie_len = 0,
.is_secure = false, .is_secure = false,
...@@ -185,11 +186,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev, ...@@ -185,11 +186,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
int err; int err;
mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev); wdev_lock(wdev);
err = __cfg80211_join_mesh(rdev, dev, setup, conf); err = __cfg80211_join_mesh(rdev, dev, setup, conf);
wdev_unlock(wdev); wdev_unlock(wdev);
mutex_unlock(&rdev->devlist_mtx);
return err; return err;
} }
......
...@@ -25,12 +25,9 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len) ...@@ -25,12 +25,9 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
trace_cfg80211_send_rx_auth(dev); trace_cfg80211_send_rx_auth(dev);
wdev_lock(wdev);
nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL); nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
cfg80211_sme_rx_auth(dev, buf, len); cfg80211_sme_rx_auth(dev, buf, len);
wdev_unlock(wdev);
} }
EXPORT_SYMBOL(cfg80211_send_rx_auth); EXPORT_SYMBOL(cfg80211_send_rx_auth);
...@@ -46,7 +43,6 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, ...@@ -46,7 +43,6 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable); int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
trace_cfg80211_send_rx_assoc(dev, bss); trace_cfg80211_send_rx_assoc(dev, bss);
wdev_lock(wdev);
status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
...@@ -59,7 +55,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, ...@@ -59,7 +55,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
if (status_code != WLAN_STATUS_SUCCESS && wdev->conn && if (status_code != WLAN_STATUS_SUCCESS && wdev->conn &&
cfg80211_sme_failed_reassoc(wdev)) { cfg80211_sme_failed_reassoc(wdev)) {
cfg80211_put_bss(wiphy, bss); cfg80211_put_bss(wiphy, bss);
goto out; return;
} }
nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL); nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
...@@ -71,7 +67,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, ...@@ -71,7 +67,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
* sme will schedule work that does it later. * sme will schedule work that does it later.
*/ */
cfg80211_put_bss(wiphy, bss); cfg80211_put_bss(wiphy, bss);
goto out; return;
} }
if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) { if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) {
...@@ -87,13 +83,11 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss, ...@@ -87,13 +83,11 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
status_code, status_code,
status_code == WLAN_STATUS_SUCCESS, bss); status_code == WLAN_STATUS_SUCCESS, bss);
out:
wdev_unlock(wdev);
} }
EXPORT_SYMBOL(cfg80211_send_rx_assoc); EXPORT_SYMBOL(cfg80211_send_rx_assoc);
void __cfg80211_send_deauth(struct net_device *dev, void cfg80211_send_deauth(struct net_device *dev,
const u8 *buf, size_t len) const u8 *buf, size_t len)
{ {
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy; struct wiphy *wiphy = wdev->wiphy;
...@@ -102,7 +96,7 @@ void __cfg80211_send_deauth(struct net_device *dev, ...@@ -102,7 +96,7 @@ void __cfg80211_send_deauth(struct net_device *dev,
const u8 *bssid = mgmt->bssid; const u8 *bssid = mgmt->bssid;
bool was_current = false; bool was_current = false;
trace___cfg80211_send_deauth(dev); trace_cfg80211_send_deauth(dev);
ASSERT_WDEV_LOCK(wdev); ASSERT_WDEV_LOCK(wdev);
if (wdev->current_bss && if (wdev->current_bss &&
...@@ -129,20 +123,10 @@ void __cfg80211_send_deauth(struct net_device *dev, ...@@ -129,20 +123,10 @@ void __cfg80211_send_deauth(struct net_device *dev,
false, NULL); false, NULL);
} }
} }
EXPORT_SYMBOL(__cfg80211_send_deauth);
void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
wdev_lock(wdev);
__cfg80211_send_deauth(dev, buf, len);
wdev_unlock(wdev);
}
EXPORT_SYMBOL(cfg80211_send_deauth); EXPORT_SYMBOL(cfg80211_send_deauth);
void __cfg80211_send_disassoc(struct net_device *dev, void cfg80211_send_disassoc(struct net_device *dev,
const u8 *buf, size_t len) const u8 *buf, size_t len)
{ {
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy; struct wiphy *wiphy = wdev->wiphy;
...@@ -152,7 +136,7 @@ void __cfg80211_send_disassoc(struct net_device *dev, ...@@ -152,7 +136,7 @@ void __cfg80211_send_disassoc(struct net_device *dev,
u16 reason_code; u16 reason_code;
bool from_ap; bool from_ap;
trace___cfg80211_send_disassoc(dev); trace_cfg80211_send_disassoc(dev);
ASSERT_WDEV_LOCK(wdev); ASSERT_WDEV_LOCK(wdev);
nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL); nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
...@@ -175,16 +159,6 @@ void __cfg80211_send_disassoc(struct net_device *dev, ...@@ -175,16 +159,6 @@ void __cfg80211_send_disassoc(struct net_device *dev,
from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr); from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr);
__cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap); __cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
} }
EXPORT_SYMBOL(__cfg80211_send_disassoc);
void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
wdev_lock(wdev);
__cfg80211_send_disassoc(dev, buf, len);
wdev_unlock(wdev);
}
EXPORT_SYMBOL(cfg80211_send_disassoc); EXPORT_SYMBOL(cfg80211_send_disassoc);
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
...@@ -194,15 +168,12 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) ...@@ -194,15 +168,12 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
trace_cfg80211_send_auth_timeout(dev, addr); trace_cfg80211_send_auth_timeout(dev, addr);
wdev_lock(wdev);
nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL); nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
if (wdev->sme_state == CFG80211_SME_CONNECTING) if (wdev->sme_state == CFG80211_SME_CONNECTING)
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE, WLAN_STATUS_UNSPECIFIED_FAILURE,
false, NULL); false, NULL);
wdev_unlock(wdev);
} }
EXPORT_SYMBOL(cfg80211_send_auth_timeout); EXPORT_SYMBOL(cfg80211_send_auth_timeout);
...@@ -213,15 +184,12 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr) ...@@ -213,15 +184,12 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
trace_cfg80211_send_assoc_timeout(dev, addr); trace_cfg80211_send_assoc_timeout(dev, addr);
wdev_lock(wdev);
nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL); nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
if (wdev->sme_state == CFG80211_SME_CONNECTING) if (wdev->sme_state == CFG80211_SME_CONNECTING)
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE, WLAN_STATUS_UNSPECIFIED_FAILURE,
false, NULL); false, NULL);
wdev_unlock(wdev);
} }
EXPORT_SYMBOL(cfg80211_send_assoc_timeout); EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
...@@ -253,18 +221,27 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr, ...@@ -253,18 +221,27 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
EXPORT_SYMBOL(cfg80211_michael_mic_failure); EXPORT_SYMBOL(cfg80211_michael_mic_failure);
/* some MLME handling for userspace SME */ /* some MLME handling for userspace SME */
int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct net_device *dev,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
enum nl80211_auth_type auth_type, enum nl80211_auth_type auth_type,
const u8 *bssid, const u8 *bssid,
const u8 *ssid, int ssid_len, const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len, const u8 *ie, int ie_len,
const u8 *key, int key_len, int key_idx, const u8 *key, int key_len, int key_idx,
const u8 *sae_data, int sae_data_len) const u8 *sae_data, int sae_data_len)
{ {
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_auth_request req; struct cfg80211_auth_request req = {
.ie = ie,
.ie_len = ie_len,
.sae_data = sae_data,
.sae_data_len = sae_data_len,
.auth_type = auth_type,
.key = key,
.key_len = key_len,
.key_idx = key_idx,
};
int err; int err;
ASSERT_WDEV_LOCK(wdev); ASSERT_WDEV_LOCK(wdev);
...@@ -277,18 +254,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, ...@@ -277,18 +254,8 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
ether_addr_equal(bssid, wdev->current_bss->pub.bssid)) ether_addr_equal(bssid, wdev->current_bss->pub.bssid))
return -EALREADY; return -EALREADY;
memset(&req, 0, sizeof(req));
req.ie = ie;
req.ie_len = ie_len;
req.sae_data = sae_data;
req.sae_data_len = sae_data_len;
req.auth_type = auth_type;
req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len,
WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
req.key = key;
req.key_len = key_len;
req.key_idx = key_idx;
if (!req.bss) if (!req.bss)
return -ENOENT; return -ENOENT;
...@@ -304,28 +271,6 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, ...@@ -304,28 +271,6 @@ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
return err; return err;
} }
int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct ieee80211_channel *chan,
enum nl80211_auth_type auth_type, const u8 *bssid,
const u8 *ssid, int ssid_len,
const u8 *ie, int ie_len,
const u8 *key, int key_len, int key_idx,
const u8 *sae_data, int sae_data_len)
{
int err;
mutex_lock(&rdev->devlist_mtx);
wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
ssid, ssid_len, ie, ie_len,
key, key_len, key_idx,
sae_data, sae_data_len);
wdev_unlock(dev->ieee80211_ptr);
mutex_unlock(&rdev->devlist_mtx);
return err;
}
/* Do a logical ht_capa &= ht_capa_mask. */ /* Do a logical ht_capa &= ht_capa_mask. */
void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa, void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
const struct ieee80211_ht_cap *ht_capa_mask) const struct ieee80211_ht_cap *ht_capa_mask)
...@@ -360,12 +305,12 @@ void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa, ...@@ -360,12 +305,12 @@ void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa,
p1[i] &= p2[i]; p1[i] &= p2[i];
} }
int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct net_device *dev,
struct ieee80211_channel *chan, struct ieee80211_channel *chan,
const u8 *bssid, const u8 *bssid,
const u8 *ssid, int ssid_len, const u8 *ssid, int ssid_len,
struct cfg80211_assoc_request *req) struct cfg80211_assoc_request *req)
{ {
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
int err; int err;
...@@ -415,30 +360,10 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, ...@@ -415,30 +360,10 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
return err; return err;
} }
int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
struct net_device *dev, struct net_device *dev, const u8 *bssid,
struct ieee80211_channel *chan, const u8 *ie, int ie_len, u16 reason,
const u8 *bssid, bool local_state_change)
const u8 *ssid, int ssid_len,
struct cfg80211_assoc_request *req)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid,
ssid, ssid_len, req);
wdev_unlock(wdev);
mutex_unlock(&rdev->devlist_mtx);
return err;
}
int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
struct net_device *dev, const u8 *bssid,
const u8 *ie, int ie_len, u16 reason,
bool local_state_change)
{ {
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_deauth_request req = { struct cfg80211_deauth_request req = {
...@@ -458,29 +383,18 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, ...@@ -458,29 +383,18 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
return rdev_deauth(rdev, dev, &req); return rdev_deauth(rdev, dev, &req);
} }
int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
struct net_device *dev, const u8 *bssid, struct net_device *dev, const u8 *bssid,
const u8 *ie, int ie_len, u16 reason, const u8 *ie, int ie_len, u16 reason,
bool local_state_change) bool local_state_change)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
wdev_lock(wdev);
err = __cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason,
local_state_change);
wdev_unlock(wdev);
return err;
}
static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
struct net_device *dev, const u8 *bssid,
const u8 *ie, int ie_len, u16 reason,
bool local_state_change)
{ {
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_disassoc_request req; struct cfg80211_disassoc_request req = {
.reason_code = reason,
.local_state_change = local_state_change,
.ie = ie,
.ie_len = ie_len,
};
ASSERT_WDEV_LOCK(wdev); ASSERT_WDEV_LOCK(wdev);
...@@ -490,11 +404,6 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, ...@@ -490,11 +404,6 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
if (WARN(!wdev->current_bss, "sme_state=%d\n", wdev->sme_state)) if (WARN(!wdev->current_bss, "sme_state=%d\n", wdev->sme_state))
return -ENOTCONN; return -ENOTCONN;
memset(&req, 0, sizeof(req));
req.reason_code = reason;
req.local_state_change = local_state_change;
req.ie = ie;
req.ie_len = ie_len;
if (ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) if (ether_addr_equal(wdev->current_bss->pub.bssid, bssid))
req.bss = &wdev->current_bss->pub; req.bss = &wdev->current_bss->pub;
else else
...@@ -503,44 +412,25 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev, ...@@ -503,44 +412,25 @@ static int __cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
return rdev_disassoc(rdev, dev, &req); return rdev_disassoc(rdev, dev, &req);
} }
int cfg80211_mlme_disassoc(struct cfg80211_registered_device *rdev,
struct net_device *dev, const u8 *bssid,
const u8 *ie, int ie_len, u16 reason,
bool local_state_change)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
wdev_lock(wdev);
err = __cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason,
local_state_change);
wdev_unlock(wdev);
return err;
}
void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
struct net_device *dev) struct net_device *dev)
{ {
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_deauth_request req;
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
struct cfg80211_deauth_request req = {
.reason_code = WLAN_REASON_DEAUTH_LEAVING,
.bssid = bssid,
};
ASSERT_WDEV_LOCK(wdev); ASSERT_WDEV_LOCK(wdev);
if (!rdev->ops->deauth) if (!rdev->ops->deauth)
return; return;
memset(&req, 0, sizeof(req));
req.reason_code = WLAN_REASON_DEAUTH_LEAVING;
req.ie = NULL;
req.ie_len = 0;
if (!wdev->current_bss) if (!wdev->current_bss)
return; return;
memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN); memcpy(bssid, wdev->current_bss->pub.bssid, ETH_ALEN);
req.bssid = bssid;
rdev_deauth(rdev, dev, &req); rdev_deauth(rdev, dev, &req);
if (wdev->current_bss) { if (wdev->current_bss) {
...@@ -848,7 +738,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work) ...@@ -848,7 +738,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
dfs_update_channels_wk); dfs_update_channels_wk);
wiphy = &rdev->wiphy; wiphy = &rdev->wiphy;
mutex_lock(&cfg80211_mutex); rtnl_lock();
for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) { for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) {
sband = wiphy->bands[bandid]; sband = wiphy->bands[bandid];
if (!sband) if (!sband)
...@@ -881,7 +771,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work) ...@@ -881,7 +771,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
check_again = true; check_again = true;
} }
} }
mutex_unlock(&cfg80211_mutex); rtnl_unlock();
/* reschedule if there are other channels waiting to be cleared again */ /* reschedule if there are other channels waiting to be cleared again */
if (check_again) if (check_again)
......
此差异已折叠。
此差异已折叠。
...@@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) ...@@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
union iwreq_data wrqu; union iwreq_data wrqu;
#endif #endif
lockdep_assert_held(&rdev->sched_scan_mtx); ASSERT_RTNL();
request = rdev->scan_req; request = rdev->scan_req;
...@@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk) ...@@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
rdev = container_of(wk, struct cfg80211_registered_device, rdev = container_of(wk, struct cfg80211_registered_device,
scan_done_wk); scan_done_wk);
mutex_lock(&rdev->sched_scan_mtx); rtnl_lock();
___cfg80211_scan_done(rdev, false); ___cfg80211_scan_done(rdev, false);
mutex_unlock(&rdev->sched_scan_mtx); rtnl_unlock();
} }
void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
...@@ -241,6 +241,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) ...@@ -241,6 +241,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
request->aborted = aborted; request->aborted = aborted;
request->notified = true;
queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk); queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk);
} }
EXPORT_SYMBOL(cfg80211_scan_done); EXPORT_SYMBOL(cfg80211_scan_done);
...@@ -255,7 +256,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) ...@@ -255,7 +256,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
request = rdev->sched_scan_req; request = rdev->sched_scan_req;
mutex_lock(&rdev->sched_scan_mtx); rtnl_lock();
/* we don't have sched_scan_req anymore if the scan is stopping */ /* we don't have sched_scan_req anymore if the scan is stopping */
if (request) { if (request) {
...@@ -270,7 +271,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk) ...@@ -270,7 +271,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
nl80211_send_sched_scan_results(rdev, request->dev); nl80211_send_sched_scan_results(rdev, request->dev);
} }
mutex_unlock(&rdev->sched_scan_mtx); rtnl_unlock();
} }
void cfg80211_sched_scan_results(struct wiphy *wiphy) void cfg80211_sched_scan_results(struct wiphy *wiphy)
...@@ -289,9 +290,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy) ...@@ -289,9 +290,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
trace_cfg80211_sched_scan_stopped(wiphy); trace_cfg80211_sched_scan_stopped(wiphy);
mutex_lock(&rdev->sched_scan_mtx); rtnl_lock();
__cfg80211_stop_sched_scan(rdev, true); __cfg80211_stop_sched_scan(rdev, true);
mutex_unlock(&rdev->sched_scan_mtx); rtnl_unlock();
} }
EXPORT_SYMBOL(cfg80211_sched_scan_stopped); EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
...@@ -300,7 +301,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, ...@@ -300,7 +301,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
{ {
struct net_device *dev; struct net_device *dev;
lockdep_assert_held(&rdev->sched_scan_mtx); ASSERT_RTNL();
if (!rdev->sched_scan_req) if (!rdev->sched_scan_req)
return -ENOENT; return -ENOENT;
...@@ -1040,6 +1041,25 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub) ...@@ -1040,6 +1041,25 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
EXPORT_SYMBOL(cfg80211_unlink_bss); EXPORT_SYMBOL(cfg80211_unlink_bss);
#ifdef CONFIG_CFG80211_WEXT #ifdef CONFIG_CFG80211_WEXT
static struct cfg80211_registered_device *
cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
{
struct cfg80211_registered_device *rdev;
struct net_device *dev;
ASSERT_RTNL();
dev = dev_get_by_index(net, ifindex);
if (!dev)
return ERR_PTR(-ENODEV);
if (dev->ieee80211_ptr)
rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
else
rdev = ERR_PTR(-ENODEV);
dev_put(dev);
return rdev;
}
int cfg80211_wext_siwscan(struct net_device *dev, int cfg80211_wext_siwscan(struct net_device *dev,
struct iw_request_info *info, struct iw_request_info *info,
union iwreq_data *wrqu, char *extra) union iwreq_data *wrqu, char *extra)
...@@ -1062,7 +1082,6 @@ int cfg80211_wext_siwscan(struct net_device *dev, ...@@ -1062,7 +1082,6 @@ int cfg80211_wext_siwscan(struct net_device *dev,
if (IS_ERR(rdev)) if (IS_ERR(rdev))
return PTR_ERR(rdev); return PTR_ERR(rdev);
mutex_lock(&rdev->sched_scan_mtx);
if (rdev->scan_req) { if (rdev->scan_req) {
err = -EBUSY; err = -EBUSY;
goto out; goto out;
...@@ -1169,9 +1188,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, ...@@ -1169,9 +1188,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
dev_hold(dev); dev_hold(dev);
} }
out: out:
mutex_unlock(&rdev->sched_scan_mtx);
kfree(creq); kfree(creq);
cfg80211_unlock_rdev(rdev);
return err; return err;
} }
EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan); EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
...@@ -1470,10 +1487,8 @@ int cfg80211_wext_giwscan(struct net_device *dev, ...@@ -1470,10 +1487,8 @@ int cfg80211_wext_giwscan(struct net_device *dev,
if (IS_ERR(rdev)) if (IS_ERR(rdev))
return PTR_ERR(rdev); return PTR_ERR(rdev);
if (rdev->scan_req) { if (rdev->scan_req)
res = -EAGAIN; return -EAGAIN;
goto out;
}
res = ieee80211_scan_results(rdev, info, extra, data->length); res = ieee80211_scan_results(rdev, info, extra, data->length);
data->length = 0; data->length = 0;
...@@ -1482,8 +1497,6 @@ int cfg80211_wext_giwscan(struct net_device *dev, ...@@ -1482,8 +1497,6 @@ int cfg80211_wext_giwscan(struct net_device *dev,
res = 0; res = 0;
} }
out:
cfg80211_unlock_rdev(rdev);
return res; return res;
} }
EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan); EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册