···224224225225 switch (sec_ctl & TX_CMD_SEC_MSK) {226226 case TX_CMD_SEC_CCM:227227- len += CCMP_MIC_LEN;227227+ len += IEEE80211_CCMP_MIC_LEN;228228 break;229229 case TX_CMD_SEC_TKIP:230230- len += TKIP_ICV_LEN;230230+ len += IEEE80211_TKIP_ICV_LEN;231231 break;232232 case TX_CMD_SEC_WEP:233233- len += WEP_IV_LEN + WEP_ICV_LEN;233233+ len += IEEE80211_WEP_IV_LEN + IEEE80211_WEP_ICV_LEN;234234 break;235235 }236236
···753753 * @STATION_INFO_LOCAL_PM: @local_pm filled754754 * @STATION_INFO_PEER_PM: @peer_pm filled755755 * @STATION_INFO_NONPEER_PM: @nonpeer_pm filled756756+ * @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled757757+ * @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled756758 */757759enum station_info_flags {758760 STATION_INFO_INACTIVE_TIME = 1<<0,···783781 STATION_INFO_NONPEER_PM = 1<<23,784782 STATION_INFO_RX_BYTES64 = 1<<24,785783 STATION_INFO_TX_BYTES64 = 1<<25,784784+ STATION_INFO_CHAIN_SIGNAL = 1<<26,785785+ STATION_INFO_CHAIN_SIGNAL_AVG = 1<<27,786786};787787788788/**···861857 u16 beacon_interval;862858};863859860860+#define IEEE80211_MAX_CHAINS 4861861+864862/**865863 * struct station_info - station information866864 *···880874 * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.881875 * @signal_avg: Average signal strength, type depends on the wiphy's signal_type.882876 * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_.877877+ * @chains: bitmask for filled values in @chain_signal, @chain_signal_avg878878+ * @chain_signal: per-chain signal strength of last received packet in dBm879879+ * @chain_signal_avg: per-chain signal strength average in dBm883880 * @txrate: current unicast bitrate from this station884881 * @rxrate: current unicast bitrate to this station885882 * @rx_packets: packets received from this station···918909 u8 plink_state;919910 s8 signal;920911 s8 signal_avg;912912+913913+ u8 chains;914914+ s8 chain_signal[IEEE80211_MAX_CHAINS];915915+ s8 chain_signal_avg[IEEE80211_MAX_CHAINS];916916+921917 struct rate_info txrate;922918 struct rate_info rxrate;923919 u32 rx_packets;···11611147 * @sync_method: which synchronization method to use11621148 * @path_sel_proto: which path selection protocol to use11631149 * @path_metric: which metric to use11501150+ * @auth_id: which authentication method this mesh is using11641151 * @ie: vendor information elements (optional)11651152 * @ie_len: length of vendor information elements11661153 * @is_authenticated: this mesh requires authentication···11801165 u8 sync_method;11811166 u8 path_sel_proto;11821167 u8 path_metric;11681168+ u8 auth_id;11831169 const u8 *ie;11841170 u8 ie_len;11851171 bool is_authenticated;···12571241 * @scan_start: time (in jiffies) when the scan started12581242 * @wdev: the wireless device to scan for12591243 * @aborted: (internal) scan request was notified as aborted12441244+ * @notified: (internal) scan request was notified as done or aborted12601245 * @no_cck: used to send probe requests at non CCK rate in 2GHz band12611246 */12621247struct cfg80211_scan_request {···12751258 /* internal */12761259 struct wiphy *wiphy;12771260 unsigned long scan_start;12781278- bool aborted;12611261+ bool aborted, notified;12791262 bool no_cck;1280126312811264 /* keep last */···18671850 * @get_mpath: get a mesh path for the given parameters18681851 * @dump_mpath: dump mesh path callback -- resume dump at index @idx18691852 * @join_mesh: join the mesh network with the specified parameters18531853+ * (invoked with the wireless_dev mutex held)18701854 * @leave_mesh: leave the current mesh network18551855+ * (invoked with the wireless_dev mutex held)18711856 *18721857 * @get_mesh_config: Get the current mesh configuration18731858 *···18961877 * the scan/scan_done bracket too.18971878 *18981879 * @auth: Request to authenticate with the specified peer18801880+ * (invoked with the wireless_dev mutex held)18991881 * @assoc: Request to (re)associate with the specified peer18821882+ * (invoked with the wireless_dev mutex held)19001883 * @deauth: Request to deauthenticate from the specified peer18841884+ * (invoked with the wireless_dev mutex held)19011885 * @disassoc: Request to disassociate from the specified peer18861886+ * (invoked with the wireless_dev mutex held)19021887 *19031888 * @connect: Connect to the ESS with the specified parameters. When connected,19041889 * call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS.19051890 * If the connection fails for some reason, call cfg80211_connect_result()19061891 * with the status from the AP.18921892+ * (invoked with the wireless_dev mutex held)19071893 * @disconnect: Disconnect from the BSS/ESS.18941894+ * (invoked with the wireless_dev mutex held)19081895 *19091896 * @join_ibss: Join the specified IBSS (or create if necessary). Once done, call19101897 * cfg80211_ibss_joined(), also call that function when changing BSSID due19111898 * to a merge.18991899+ * (invoked with the wireless_dev mutex held)19121900 * @leave_ibss: Leave the IBSS.19011901+ * (invoked with the wireless_dev mutex held)19131902 *19141903 * @set_mcast_rate: Set the specified multicast rate (only if vif is in ADHOC or19151904 * MESH mode)···25832556 * may request, if implemented.25842557 *25852558 * @wowlan: WoWLAN support information25592559+ * @wowlan_config: current WoWLAN configuration; this should usually not be25602560+ * used since access to it is necessarily racy, use the parameter passed25612561+ * to the suspend() operation instead.25862562 *25872563 * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.25882564 * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden.···2653262326542624#ifdef CONFIG_PM26552625 struct wiphy_wowlan_support wowlan;26262626+ struct cfg80211_wowlan *wowlan_config;26562627#endif2657262826582629 u16 max_remain_on_channel_duration;···28652834 * by cfg80211 on change_interface28662835 * @mgmt_registrations: list of registrations for management frames28672836 * @mgmt_registrations_lock: lock for the list28682868- * @mtx: mutex used to lock data in this struct28372837+ * @mtx: mutex used to lock data in this struct, may be used by drivers28382838+ * and some API functions require it held28692839 * @cleanup_work: work struct used for cleanup that can't be done directly28702840 * @beacon_interval: beacon interval used on this device for transmitting28712841 * beacons, 0 when not valid···28892857 spinlock_t mgmt_registrations_lock;2890285828912859 struct mutex mtx;28922892-28932893- struct work_struct cleanup_work;2894286028952861 bool use_4addr, p2p_started;28962862···30182988struct ieee80211_rate *30192989ieee80211_get_response_rate(struct ieee80211_supported_band *sband,30202990 u32 basic_rates, int bitrate);29912991+29922992+/**29932993+ * ieee80211_mandatory_rates - get mandatory rates for a given band29942994+ * @sband: the band to look for rates in29952995+ *29962996+ * This function returns a bitmap of the mandatory rates for the given29972997+ * band, bits are set according to the rate position in the bitrates array.29982998+ */29992999+u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband);3021300030223001/*30233002 * Radiotap parsing functions -- for controlled injection support···34393400 * This function is called whenever an authentication has been processed in34403401 * station mode. The driver is required to call either this function or34413402 * cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth()34423442- * call. This function may sleep.34033403+ * call. This function may sleep. The caller must hold the corresponding wdev's34043404+ * mutex.34433405 */34443406void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);34453407···34493409 * @dev: network device34503410 * @addr: The MAC address of the device with which the authentication timed out34513411 *34523452- * This function may sleep.34123412+ * This function may sleep. The caller must hold the corresponding wdev's34133413+ * mutex.34533414 */34543415void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);34553416···34653424 * This function is called whenever a (re)association response has been34663425 * processed in station mode. The driver is required to call either this34673426 * function or cfg80211_send_assoc_timeout() to indicate the result of34683468- * cfg80211_ops::assoc() call. This function may sleep.34273427+ * cfg80211_ops::assoc() call. This function may sleep. The caller must hold34283428+ * the corresponding wdev's mutex.34693429 */34703430void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,34713431 const u8 *buf, size_t len);···34763434 * @dev: network device34773435 * @addr: The MAC address of the device with which the association timed out34783436 *34793479- * This function may sleep.34373437+ * This function may sleep. The caller must hold the corresponding wdev's mutex.34803438 */34813439void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);34823440···34883446 *34893447 * This function is called whenever deauthentication has been processed in34903448 * station mode. This includes both received deauthentication frames and34913491- * locally generated ones. This function may sleep.34493449+ * locally generated ones. This function may sleep. The caller must hold the34503450+ * corresponding wdev's mutex.34923451 */34933452void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);34943494-34953495-/**34963496- * __cfg80211_send_deauth - notification of processed deauthentication34973497- * @dev: network device34983498- * @buf: deauthentication frame (header + body)34993499- * @len: length of the frame data35003500- *35013501- * Like cfg80211_send_deauth(), but doesn't take the wdev lock.35023502- */35033503-void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);3504345335053454/**35063455 * cfg80211_send_disassoc - notification of processed disassociation···35013468 *35023469 * This function is called whenever disassociation has been processed in35033470 * station mode. This includes both received disassociation frames and locally35043504- * generated ones. This function may sleep.34713471+ * generated ones. This function may sleep. The caller must hold the34723472+ * corresponding wdev's mutex.35053473 */35063474void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len);35073507-35083508-/**35093509- * __cfg80211_send_disassoc - notification of processed disassociation35103510- * @dev: network device35113511- * @buf: disassociation response frame (header + body)35123512- * @len: length of the frame data35133513- *35143514- * Like cfg80211_send_disassoc(), but doesn't take the wdev lock.35153515- */35163516-void __cfg80211_send_disassoc(struct net_device *dev, const u8 *buf,35173517- size_t len);3518347535193476/**35203477 * cfg80211_send_unprot_deauth - notification of unprotected deauthentication···41764153 * cfg80211_crit_proto_stopped() - indicate critical protocol stopped by driver.41774154 *41784155 * @wdev: the wireless device for which critical protocol is stopped.41564156+ * @gfp: allocation flags41794157 *41804158 * This function can be called by the driver to indicate it has reverted41814159 * operation back to normal. One reason could be that the duration given
···805805 * on this subframe806806 * @RX_FLAG_AMPDU_DELIM_CRC_KNOWN: The delimiter CRC field is known (the CRC807807 * is stored in the @ampdu_delimiter_crc field)808808+ * @RX_FLAG_STBC_MASK: STBC 2 bit bitmask. 1 - Nss=1, 2 - Nss=2, 3 - Nss=3808809 */809810enum mac80211_rx_flags {810811 RX_FLAG_MMIC_ERROR = BIT(0),···833832 RX_FLAG_80MHZ = BIT(23),834833 RX_FLAG_80P80MHZ = BIT(24),835834 RX_FLAG_160MHZ = BIT(25),835835+ RX_FLAG_STBC_MASK = BIT(26) | BIT(27),836836};837837+838838+#define RX_FLAG_STBC_SHIFT 26837839838840/**839841 * struct ieee80211_rx_status - receive status···854850 * @signal: signal strength when receiving this frame, either in dBm, in dB or855851 * unspecified depending on the hardware capabilities flags856852 * @IEEE80211_HW_SIGNAL_*853853+ * @chains: bitmask of receive chains for which separate signal strength854854+ * values were filled.855855+ * @chain_signal: per-chain signal strength, in dBm (unlike @signal, doesn't856856+ * support dB or unspecified units)857857 * @antenna: antenna used858858 * @rate_idx: index of data rate into band's supported rates or MCS index if859859 * HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)···889881 u8 band;890882 u8 antenna;891883 s8 signal;884884+ u8 chains;885885+ s8 chain_signal[IEEE80211_MAX_CHAINS];892886 u8 ampdu_delimiter_crc;893887 u8 vendor_radiotap_align;894888 u8 vendor_radiotap_oui[3];···12451235 * struct ieee80211_sta_rates - station rate selection table12461236 *12471237 * @rcu_head: RCU head used for freeing the table on update12481248- * @rates: transmit rates/flags to be used by default.12381238+ * @rate: transmit rates/flags to be used by default.12491239 * Overriding entries per-packet is possible by using cb tx control.12501240 */12511241struct ieee80211_sta_rates {···12861276 * notifications and capabilities. The value is only valid after12871277 * the station moves to associated state.12881278 * @smps_mode: current SMPS mode (off, static or dynamic)12891289- * @tx_rates: rate control selection table12791279+ * @rates: rate control selection table12901280 */12911281struct ieee80211_sta {12921282 u32 supp_rates[IEEE80211_NUM_BANDS];···30533043 * This function may not be called in IRQ context. Calls to this function30543044 * for a single hardware must be synchronized against each other. Calls to30553045 * this function, ieee80211_rx_ni() and ieee80211_rx_irqsafe() may not be30563056- * mixed for a single hardware.30463046+ * mixed for a single hardware. Must not run concurrently with30473047+ * ieee80211_tx_status() or ieee80211_tx_status_ni().30573048 *30583049 * In process context use instead ieee80211_rx_ni().30593050 *···30703059 * (internally defers to a tasklet.)30713060 *30723061 * Calls to this function, ieee80211_rx() or ieee80211_rx_ni() may not30733073- * be mixed for a single hardware.30623062+ * be mixed for a single hardware.Must not run concurrently with30633063+ * ieee80211_tx_status() or ieee80211_tx_status_ni().30743064 *30753065 * @hw: the hardware this frame came in on30763066 * @skb: the buffer to receive, owned by mac80211 after this call···30853073 * (internally disables bottom halves).30863074 *30873075 * Calls to this function, ieee80211_rx() and ieee80211_rx_irqsafe() may30883088- * not be mixed for a single hardware.30763076+ * not be mixed for a single hardware. Must not run concurrently with30773077+ * ieee80211_tx_status() or ieee80211_tx_status_ni().30893078 *30903079 * @hw: the hardware this frame came in on30913080 * @skb: the buffer to receive, owned by mac80211 after this call···32093196 * This function may not be called in IRQ context. Calls to this function32103197 * for a single hardware must be synchronized against each other. Calls32113198 * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()32123212- * may not be mixed for a single hardware.31993199+ * may not be mixed for a single hardware. Must not run concurrently with32003200+ * ieee80211_rx() or ieee80211_rx_ni().32133201 *32143202 * @hw: the hardware the frame was transmitted by32153203 * @skb: the frame that was transmitted, owned by mac80211 after this call
+20
include/uapi/linux/nl80211.h
···27272828#include <linux/types.h>29293030+#define NL80211_GENL_NAME "nl80211"3131+3032/**3133 * DOC: Station handling3234 *···14311429 * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which14321430 * the connection should have increased reliability (u16).14331431 *14321432+ * @NL80211_ATTR_PEER_AID: Association ID for the peer TDLS station (u16).14331433+ * This is similar to @NL80211_ATTR_STA_AID but with a difference of being14341434+ * allowed to be used with the first @NL80211_CMD_SET_STATION command to14351435+ * update a TDLS peer STA entry.14361436+ *14341437 * @NL80211_ATTR_MAX: highest attribute number currently defined14351438 * @__NL80211_ATTR_AFTER_LAST: internal use14361439 */···17341727 NL80211_ATTR_CRIT_PROT_ID,17351728 NL80211_ATTR_MAX_CRIT_PROT_DURATION,1736172917301730+ NL80211_ATTR_PEER_AID,17311731+17371732 /* add attributes here, update the policy in nl80211.c */1738173317391734 __NL80211_ATTR_AFTER_LAST,···20001991 * @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode20011992 * @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards20021993 * non-peer STA19941994+ * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU19951995+ * Contains a nested array of signal strength attributes (u8, dBm)19961996+ * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average19971997+ * Same format as NL80211_STA_INFO_CHAIN_SIGNAL.20031998 * @__NL80211_STA_INFO_AFTER_LAST: internal20041999 * @NL80211_STA_INFO_MAX: highest possible station info attribute20052000 */···20332020 NL80211_STA_INFO_NONPEER_PM,20342021 NL80211_STA_INFO_RX_BYTES64,20352022 NL80211_STA_INFO_TX_BYTES64,20232023+ NL80211_STA_INFO_CHAIN_SIGNAL,20242024+ NL80211_STA_INFO_CHAIN_SIGNAL_AVG,2036202520372026 /* keep last */20382027 __NL80211_STA_INFO_AFTER_LAST,···26522637 * @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will26532638 * implement an MPM which handles peer allocation and state.26542639 *26402640+ * @NL80211_MESH_SETUP_AUTH_PROTOCOL: Inform the kernel of the authentication26412641+ * method (u8, as defined in IEEE 8.4.2.100.6, e.g. 0x1 for SAE).26422642+ * Default is no authentication method required.26432643+ *26552644 * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number26562645 *26572646 * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use···26692650 NL80211_MESH_SETUP_USERSPACE_AMPE,26702651 NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC,26712652 NL80211_MESH_SETUP_USERSPACE_MPM,26532653+ NL80211_MESH_SETUP_AUTH_PROTOCOL,2672265426732655 /* keep last */26742656 __NL80211_MESH_SETUP_ATTR_AFTER_LAST,
+3-3
net/mac80211/aes_ccm.c
···8585 *cpos++ = *pos++ ^ e[i];8686 }87878888- for (i = 0; i < CCMP_MIC_LEN; i++)8888+ for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++)8989 mic[i] = b[i] ^ s_0[i];9090}9191···123123 crypto_cipher_encrypt_one(tfm, a, a);124124 }125125126126- for (i = 0; i < CCMP_MIC_LEN; i++) {126126+ for (i = 0; i < IEEE80211_CCMP_MIC_LEN; i++) {127127 if ((mic[i] ^ s_0[i]) != a[i])128128 return -1;129129 }···138138139139 tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC);140140 if (!IS_ERR(tfm))141141- crypto_cipher_setkey(tfm, key, ALG_CCMP_KEY_LEN);141141+ crypto_cipher_setkey(tfm, key, WLAN_KEY_LEN_CCMP);142142143143 return tfm;144144}
+15-5
net/mac80211/cfg.c
···444444 struct ieee80211_local *local = sdata->local;445445 struct timespec uptime;446446 u64 packets = 0;447447- int ac;447447+ int i, ac;448448449449 sinfo->generation = sdata->local->sta_generation;450450···487487 drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal))488488 sinfo->signal = (s8)sta->last_signal;489489 sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);490490+ }491491+ if (sta->chains) {492492+ sinfo->filled |= STATION_INFO_CHAIN_SIGNAL |493493+ STATION_INFO_CHAIN_SIGNAL_AVG;494494+495495+ sinfo->chains = sta->chains;496496+ for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {497497+ sinfo->chain_signal[i] = sta->chain_signal_last[i];498498+ sinfo->chain_signal_avg[i] =499499+ (s8) -ewma_read(&sta->chain_signal_avg[i]);500500+ }490501 }491502492503 sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);···739728740729 if (sset == ETH_SS_STATS) {741730 sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats);742742- memcpy(data, *ieee80211_gstrings_sta_stats, sz_sta_stats);731731+ memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats);743732 }744733 drv_get_et_strings(sdata, sset, &(data[sz_sta_stats]));745734}···17461735 ifmsh->mesh_pp_id = setup->path_sel_proto;17471736 ifmsh->mesh_pm_id = setup->path_metric;17481737 ifmsh->user_mpm = setup->user_mpm;17381738+ ifmsh->mesh_auth_id = setup->auth_id;17491739 ifmsh->security = IEEE80211_MESH_SEC_NONE;17501740 if (setup->is_authenticated)17511741 ifmsh->security |= IEEE80211_MESH_SEC_AUTHED;···23182306 enum ieee80211_smps_mode old_req;23192307 int err;2320230823212321- lockdep_assert_held(&sdata->u.mgd.mtx);23092309+ lockdep_assert_held(&sdata->wdev.mtx);2322231023232311 old_req = sdata->u.mgd.req_smps;23242312 sdata->u.mgd.req_smps = smps_mode;···23752363 local->dynamic_ps_forced_timeout = timeout;2376236423772365 /* no change, but if automatic follow powersave */23782378- mutex_lock(&sdata->u.mgd.mtx);23792366 __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps);23802380- mutex_unlock(&sdata->u.mgd.mtx);2381236723822368 if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)23832369 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
···474474 master->control_port_protocol;475475 sdata->control_port_no_encrypt =476476 master->control_port_no_encrypt;477477+ sdata->vif.cab_queue = master->vif.cab_queue;478478+ memcpy(sdata->vif.hw_queue, master->vif.hw_queue,479479+ sizeof(sdata->vif.hw_queue));477480 break;478481 }479482 case NL80211_IFTYPE_AP:···656653657654 ieee80211_recalc_ps(local, -1);658655659659- if (dev) {656656+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||657657+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {658658+ /* XXX: for AP_VLAN, actually track AP queues */659659+ netif_tx_start_all_queues(dev);660660+ } else if (dev) {660661 unsigned long flags;661662 int n_acs = IEEE80211_NUM_ACS;662663 int ac;···17021695 LIST_HEAD(wdev_list);1703169617041697 ASSERT_RTNL();16981698+16991699+ /*17001700+ * Close all AP_VLAN interfaces first, as otherwise they17011701+ * might be closed while the AP interface they belong to17021702+ * is closed, causing unregister_netdevice_many() to crash.17031703+ */17041704+ list_for_each_entry(sdata, &local->interfaces, list)17051705+ if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)17061706+ dev_close(sdata->dev);1705170717061708 mutex_lock(&local->iflist_mtx);17071709 list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
+12-12
net/mac80211/key.c
···335335 switch (cipher) {336336 case WLAN_CIPHER_SUITE_WEP40:337337 case WLAN_CIPHER_SUITE_WEP104:338338- key->conf.iv_len = WEP_IV_LEN;339339- key->conf.icv_len = WEP_ICV_LEN;338338+ key->conf.iv_len = IEEE80211_WEP_IV_LEN;339339+ key->conf.icv_len = IEEE80211_WEP_ICV_LEN;340340 break;341341 case WLAN_CIPHER_SUITE_TKIP:342342- key->conf.iv_len = TKIP_IV_LEN;343343- key->conf.icv_len = TKIP_ICV_LEN;342342+ key->conf.iv_len = IEEE80211_TKIP_IV_LEN;343343+ key->conf.icv_len = IEEE80211_TKIP_ICV_LEN;344344 if (seq) {345345 for (i = 0; i < IEEE80211_NUM_TIDS; i++) {346346 key->u.tkip.rx[i].iv32 =···352352 spin_lock_init(&key->u.tkip.txlock);353353 break;354354 case WLAN_CIPHER_SUITE_CCMP:355355- key->conf.iv_len = CCMP_HDR_LEN;356356- key->conf.icv_len = CCMP_MIC_LEN;355355+ key->conf.iv_len = IEEE80211_CCMP_HDR_LEN;356356+ key->conf.icv_len = IEEE80211_CCMP_MIC_LEN;357357 if (seq) {358358 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++)359359- for (j = 0; j < CCMP_PN_LEN; j++)359359+ for (j = 0; j < IEEE80211_CCMP_PN_LEN; j++)360360 key->u.ccmp.rx_pn[i][j] =361361- seq[CCMP_PN_LEN - j - 1];361361+ seq[IEEE80211_CCMP_PN_LEN - j - 1];362362 }363363 /*364364 * Initialize AES key state here as an optimization so that···375375 key->conf.iv_len = 0;376376 key->conf.icv_len = sizeof(struct ieee80211_mmie);377377 if (seq)378378- for (j = 0; j < CMAC_PN_LEN; j++)378378+ for (j = 0; j < IEEE80211_CMAC_PN_LEN; j++)379379 key->u.aes_cmac.rx_pn[j] =380380- seq[CMAC_PN_LEN - j - 1];380380+ seq[IEEE80211_CMAC_PN_LEN - j - 1];381381 /*382382 * Initialize AES key state here as an optimization so that383383 * it does not need to be initialized for every packet.···740740 pn = key->u.ccmp.rx_pn[IEEE80211_NUM_TIDS];741741 else742742 pn = key->u.ccmp.rx_pn[tid];743743- memcpy(seq->ccmp.pn, pn, CCMP_PN_LEN);743743+ memcpy(seq->ccmp.pn, pn, IEEE80211_CCMP_PN_LEN);744744 break;745745 case WLAN_CIPHER_SUITE_AES_CMAC:746746 if (WARN_ON(tid != 0))747747 return;748748 pn = key->u.aes_cmac.rx_pn;749749- memcpy(seq->aes_cmac.pn, pn, CMAC_PN_LEN);749749+ memcpy(seq->aes_cmac.pn, pn, IEEE80211_CMAC_PN_LEN);750750 break;751751 }752752}
···517517 ieee80211_mps_frame_release(sta, elems);518518out:519519 rcu_read_unlock();520520+ sdata_lock(sdata);520521 ieee80211_mbss_info_change_notify(sdata, changed);522522+ sdata_unlock(sdata);521523}522524523525static void mesh_plink_timer(unsigned long data)···1070106810711069 rcu_read_unlock();1072107010731073- if (changed)10711071+ if (changed) {10721072+ sdata_lock(sdata);10741073 ieee80211_mbss_info_change_notify(sdata, changed);10741074+ sdata_unlock(sdata);10751075+ }10751076}
+175-235
net/mac80211/mlme.c
···9191#define IEEE80211_SIGNAL_AVE_MIN_COUNT 492929393/*9494- * All cfg80211 functions have to be called outside a locked9595- * section so that they can acquire a lock themselves... This9696- * is much simpler than queuing up things in cfg80211, but we9797- * do need some indirection for that here.9898- */9999-enum rx_mgmt_action {100100- /* no action required */101101- RX_MGMT_NONE,102102-103103- /* caller must call cfg80211_send_deauth() */104104- RX_MGMT_CFG80211_DEAUTH,105105-106106- /* caller must call cfg80211_send_disassoc() */107107- RX_MGMT_CFG80211_DISASSOC,108108-109109- /* caller must call cfg80211_send_rx_auth() */110110- RX_MGMT_CFG80211_RX_AUTH,111111-112112- /* caller must call cfg80211_send_rx_assoc() */113113- RX_MGMT_CFG80211_RX_ASSOC,114114-115115- /* caller must call cfg80211_send_assoc_timeout() */116116- RX_MGMT_CFG80211_ASSOC_TIMEOUT,117117-118118- /* used when a processed beacon causes a deauth */119119- RX_MGMT_CFG80211_TX_DEAUTH,120120-};121121-122122-/* utils */123123-static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)124124-{125125- lockdep_assert_held(&ifmgd->mtx);126126-}127127-128128-/*12994 * We can have multiple work items (and connection probing)13095 * scheduling this timer, but we need to take care to only13196 * reschedule it when it should fire _earlier_ than it was···100135 * has happened -- the work that runs from this timer will101136 * do that.102137 */103103-static void run_again(struct ieee80211_if_managed *ifmgd, unsigned long timeout)138138+static void run_again(struct ieee80211_sub_if_data *sdata,139139+ unsigned long timeout)104140{105105- ASSERT_MGD_MTX(ifmgd);141141+ sdata_assert_lock(sdata);106142107107- if (!timer_pending(&ifmgd->timer) ||108108- time_before(timeout, ifmgd->timer.expires))109109- mod_timer(&ifmgd->timer, timeout);143143+ if (!timer_pending(&sdata->u.mgd.timer) ||144144+ time_before(timeout, sdata->u.mgd.timer.expires))145145+ mod_timer(&sdata->u.mgd.timer, timeout);110146}111147112148void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)···618652 struct ieee80211_channel *chan;619653 u32 rates = 0;620654621621- lockdep_assert_held(&ifmgd->mtx);655655+ sdata_assert_lock(sdata);622656623657 rcu_read_lock();624658 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);···928962 if (!ieee80211_sdata_running(sdata))929963 return;930964931931- mutex_lock(&ifmgd->mtx);965965+ sdata_lock(sdata);932966 if (!ifmgd->associated)933967 goto out;934968···951985 IEEE80211_QUEUE_STOP_REASON_CSA);952986 out:953987 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;954954- mutex_unlock(&ifmgd->mtx);988988+ sdata_unlock(sdata);955989}956990957991void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)···98110159821016static void9831017ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,984984- u64 timestamp, struct ieee802_11_elems *elems)10181018+ u64 timestamp, struct ieee802_11_elems *elems,10191019+ bool beacon)9851020{9861021 struct ieee80211_local *local = sdata->local;9871022 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;···9991032 struct cfg80211_chan_def new_vht_chandef = {};10001033 const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;10011034 const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;10351035+ const struct ieee80211_ht_operation *ht_oper;10021036 int secondary_channel_offset = -1;1003103710041004- ASSERT_MGD_MTX(ifmgd);10381038+ sdata_assert_lock(sdata);1005103910061040 if (!cbss)10071041 return;···1016104810171049 sec_chan_offs = elems->sec_chan_offs;10181050 wide_bw_chansw_ie = elems->wide_bw_chansw_ie;10511051+ ht_oper = elems->ht_operation;1019105210201053 if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |10211054 IEEE80211_STA_DISABLE_40MHZ)) {10221055 sec_chan_offs = NULL;10231056 wide_bw_chansw_ie = NULL;10571057+ /* only used for bandwidth here */10581058+ ht_oper = NULL;10241059 }1025106010261061 if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT)···10651094 return;10661095 }1067109610681068- if (sec_chan_offs) {10971097+ if (!beacon && sec_chan_offs) {10691098 secondary_channel_offset = sec_chan_offs->sec_chan_offs;10991099+ } else if (beacon && ht_oper) {11001100+ secondary_channel_offset =11011101+ ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET;10701102 } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {10711071- /* if HT is enabled and the IE not present, it's still HT */11031103+ /*11041104+ * If it's not a beacon, HT is enabled and the IE not present,11051105+ * it's 20 MHz, 802.11-2012 8.5.2.6:11061106+ * This element [the Secondary Channel Offset Element] is11071107+ * present when switching to a 40 MHz channel. It may be11081108+ * present when switching to a 20 MHz channel (in which11091109+ * case the secondary channel offset is set to SCN).11101110+ */10721111 secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;10731112 }10741113···1354137313551374 if (mgd->flags & (IEEE80211_STA_BEACON_POLL |13561375 IEEE80211_STA_CONNECTION_POLL))13761376+ return false;13771377+13781378+ if (!sdata->vif.bss_conf.dtim_period)13571379 return false;1358138013591381 rcu_read_lock();···18111827 struct ieee80211_local *local = sdata->local;18121828 u32 changed = 0;1813182918141814- ASSERT_MGD_MTX(ifmgd);18301830+ sdata_assert_lock(sdata);1815183118161832 if (WARN_ON_ONCE(tx && !frame_buf))18171833 return;···20202036 }2021203720222038 ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);20232023- run_again(ifmgd, ifmgd->probe_timeout);20392039+ run_again(sdata, ifmgd->probe_timeout);20242040 if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)20252041 ieee80211_flush_queues(sdata->local, sdata);20262042}···20342050 if (!ieee80211_sdata_running(sdata))20352051 return;2036205220372037- mutex_lock(&ifmgd->mtx);20532053+ sdata_lock(sdata);2038205420392055 if (!ifmgd->associated)20402056 goto out;···20882104 ifmgd->probe_send_count = 0;20892105 ieee80211_mgd_probe_ap_send(sdata);20902106 out:20912091- mutex_unlock(&ifmgd->mtx);21072107+ sdata_unlock(sdata);20922108}2093210920942110struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,···21042120 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))21052121 return NULL;2106212221072107- ASSERT_MGD_MTX(ifmgd);21232123+ sdata_assert_lock(sdata);2108212421092125 if (ifmgd->associated)21102126 cbss = ifmgd->associated;···21372153 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;21382154 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];2139215521402140- mutex_lock(&ifmgd->mtx);21562156+ sdata_lock(sdata);21412157 if (!ifmgd->associated) {21422142- mutex_unlock(&ifmgd->mtx);21582158+ sdata_unlock(sdata);21432159 return;21442160 }21452161···21502166 ieee80211_wake_queues_by_reason(&sdata->local->hw,21512167 IEEE80211_MAX_QUEUE_MAP,21522168 IEEE80211_QUEUE_STOP_REASON_CSA);21532153- mutex_unlock(&ifmgd->mtx);2154216921552155- /*21562156- * must be outside lock due to cfg80211,21572157- * but that's not a problem.21582158- */21592170 cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);21712171+ sdata_unlock(sdata);21602172}2161217321622174static void ieee80211_beacon_connection_loss_work(struct work_struct *work)···22192239{22202240 struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data;2221224122222222- lockdep_assert_held(&sdata->u.mgd.mtx);22422242+ sdata_assert_lock(sdata);2223224322242244 if (!assoc) {22252245 sta_info_destroy_addr(sdata, auth_data->bss->bssid);···22602280 auth_data->key_idx, tx_flags);22612281}2262228222632263-static enum rx_mgmt_action __must_check22642264-ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,22652265- struct ieee80211_mgmt *mgmt, size_t len)22832283+static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,22842284+ struct ieee80211_mgmt *mgmt, size_t len)22662285{22672286 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;22682287 u8 bssid[ETH_ALEN];22692288 u16 auth_alg, auth_transaction, status_code;22702289 struct sta_info *sta;2271229022722272- lockdep_assert_held(&ifmgd->mtx);22912291+ sdata_assert_lock(sdata);2273229222742293 if (len < 24 + 6)22752275- return RX_MGMT_NONE;22942294+ return;2276229522772296 if (!ifmgd->auth_data || ifmgd->auth_data->done)22782278- return RX_MGMT_NONE;22972297+ return;2279229822802299 memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN);2281230022822301 if (!ether_addr_equal(bssid, mgmt->bssid))22832283- return RX_MGMT_NONE;23022302+ return;2284230322852304 auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);22862305 auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);···22912312 mgmt->sa, auth_alg, ifmgd->auth_data->algorithm,22922313 auth_transaction,22932314 ifmgd->auth_data->expected_transaction);22942294- return RX_MGMT_NONE;23152315+ return;22952316 }2296231722972318 if (status_code != WLAN_STATUS_SUCCESS) {22982319 sdata_info(sdata, "%pM denied authentication (status %d)\n",22992320 mgmt->sa, status_code);23002321 ieee80211_destroy_auth_data(sdata, false);23012301- return RX_MGMT_CFG80211_RX_AUTH;23222322+ cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);23232323+ return;23022324 }2303232523042326 switch (ifmgd->auth_data->algorithm) {···23122332 if (ifmgd->auth_data->expected_transaction != 4) {23132333 ieee80211_auth_challenge(sdata, mgmt, len);23142334 /* need another frame */23152315- return RX_MGMT_NONE;23352335+ return;23162336 }23172337 break;23182338 default:23192339 WARN_ONCE(1, "invalid auth alg %d",23202340 ifmgd->auth_data->algorithm);23212321- return RX_MGMT_NONE;23412341+ return;23222342 }2323234323242344 sdata_info(sdata, "authenticated\n");23252345 ifmgd->auth_data->done = true;23262346 ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;23272347 ifmgd->auth_data->timeout_started = true;23282328- run_again(ifmgd, ifmgd->auth_data->timeout);23482348+ run_again(sdata, ifmgd->auth_data->timeout);2329234923302350 if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&23312351 ifmgd->auth_data->expected_transaction != 2) {···23332353 * Report auth frame to user space for processing since another23342354 * round of Authentication frames is still needed.23352355 */23362336- return RX_MGMT_CFG80211_RX_AUTH;23562356+ cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);23572357+ return;23372358 }2338235923392360 /* move station state to auth */···23502369 }23512370 mutex_unlock(&sdata->local->sta_mtx);2352237123532353- return RX_MGMT_CFG80211_RX_AUTH;23722372+ cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);23732373+ return;23542374 out_err:23552375 mutex_unlock(&sdata->local->sta_mtx);23562376 /* ignore frame -- wait for timeout */23572357- return RX_MGMT_NONE;23582377}235923782360237923612361-static enum rx_mgmt_action __must_check23622362-ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,23632363- struct ieee80211_mgmt *mgmt, size_t len)23802380+static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,23812381+ struct ieee80211_mgmt *mgmt, size_t len)23642382{23652383 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;23662384 const u8 *bssid = NULL;23672385 u16 reason_code;2368238623692369- lockdep_assert_held(&ifmgd->mtx);23872387+ sdata_assert_lock(sdata);2370238823712389 if (len < 24 + 2)23722372- return RX_MGMT_NONE;23902390+ return;2373239123742392 if (!ifmgd->associated ||23752393 !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))23762376- return RX_MGMT_NONE;23942394+ return;2377239523782396 bssid = ifmgd->associated->bssid;23792397···2383240323842404 ieee80211_set_disassoc(sdata, 0, 0, false, NULL);2385240523862386- return RX_MGMT_CFG80211_DEAUTH;24062406+ cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, len);23872407}238824082389240923902390-static enum rx_mgmt_action __must_check23912391-ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,23922392- struct ieee80211_mgmt *mgmt, size_t len)24102410+static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,24112411+ struct ieee80211_mgmt *mgmt, size_t len)23932412{23942413 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;23952414 u16 reason_code;2396241523972397- lockdep_assert_held(&ifmgd->mtx);24162416+ sdata_assert_lock(sdata);2398241723992418 if (len < 24 + 2)24002400- return RX_MGMT_NONE;24192419+ return;2401242024022421 if (!ifmgd->associated ||24032422 !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))24042404- return RX_MGMT_NONE;24232423+ return;2405242424062425 reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);24072426···2409243024102431 ieee80211_set_disassoc(sdata, 0, 0, false, NULL);2411243224122412- return RX_MGMT_CFG80211_DISASSOC;24332433+ cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, len);24132434}2414243524152436static void ieee80211_get_rates(struct ieee80211_supported_band *sband,···24592480{24602481 struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;2461248224622462- lockdep_assert_held(&sdata->u.mgd.mtx);24832483+ sdata_assert_lock(sdata);2463248424642485 if (!assoc) {24652486 sta_info_destroy_addr(sdata, assoc_data->bss->bssid);···26402661 return true;26412662}2642266326432643-static enum rx_mgmt_action __must_check26442644-ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,26452645- struct ieee80211_mgmt *mgmt, size_t len,26462646- struct cfg80211_bss **bss)26642664+static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,26652665+ struct ieee80211_mgmt *mgmt,26662666+ size_t len)26472667{26482668 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;26492669 struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;···26502672 struct ieee802_11_elems elems;26512673 u8 *pos;26522674 bool reassoc;26752675+ struct cfg80211_bss *bss;2653267626542654- lockdep_assert_held(&ifmgd->mtx);26772677+ sdata_assert_lock(sdata);2655267826562679 if (!assoc_data)26572657- return RX_MGMT_NONE;26802680+ return;26582681 if (!ether_addr_equal(assoc_data->bss->bssid, mgmt->bssid))26592659- return RX_MGMT_NONE;26822682+ return;2660268326612684 /*26622685 * AssocResp and ReassocResp have identical structure, so process both···26652686 */2666268726672688 if (len < 24 + 6)26682668- return RX_MGMT_NONE;26892689+ return;2669269026702691 reassoc = ieee80211_is_reassoc_req(mgmt->frame_control);26712692 capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);···26922713 assoc_data->timeout = jiffies + msecs_to_jiffies(ms);26932714 assoc_data->timeout_started = true;26942715 if (ms > IEEE80211_ASSOC_TIMEOUT)26952695- run_again(ifmgd, assoc_data->timeout);26962696- return RX_MGMT_NONE;27162716+ run_again(sdata, assoc_data->timeout);27172717+ return;26972718 }2698271926992699- *bss = assoc_data->bss;27202720+ bss = assoc_data->bss;2700272127012722 if (status_code != WLAN_STATUS_SUCCESS) {27022723 sdata_info(sdata, "%pM denied association (code=%d)\n",27032724 mgmt->sa, status_code);27042725 ieee80211_destroy_assoc_data(sdata, false);27052726 } else {27062706- if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) {27272727+ if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) {27072728 /* oops -- internal error -- send timeout for now */27082729 ieee80211_destroy_assoc_data(sdata, false);27092709- cfg80211_put_bss(sdata->local->hw.wiphy, *bss);27102710- return RX_MGMT_CFG80211_ASSOC_TIMEOUT;27302730+ cfg80211_put_bss(sdata->local->hw.wiphy, bss);27312731+ cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid);27322732+ return;27112733 }27122734 sdata_info(sdata, "associated\n");27132735···27202740 ieee80211_destroy_assoc_data(sdata, true);27212741 }2722274227232723- return RX_MGMT_CFG80211_RX_ASSOC;27432743+ cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, len);27242744}2725274527262746static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,···27342754 struct ieee80211_channel *channel;27352755 bool need_ps = false;2736275627372737- lockdep_assert_held(&sdata->u.mgd.mtx);27572757+ sdata_assert_lock(sdata);2738275827392759 if ((sdata->u.mgd.associated &&27402760 ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) ||···27762796 mutex_unlock(&local->iflist_mtx);27772797 }2778279827792779- ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, elems);27992799+ ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,28002800+ elems, true);2780280127812802}27822803···2793281227942813 ifmgd = &sdata->u.mgd;2795281427962796- ASSERT_MGD_MTX(ifmgd);28152815+ sdata_assert_lock(sdata);2797281627982817 if (!ether_addr_equal(mgmt->da, sdata->vif.addr))27992818 return; /* ignore ProbeResp to foreign address */···28182837 ifmgd->auth_data->tries = 0;28192838 ifmgd->auth_data->timeout = jiffies;28202839 ifmgd->auth_data->timeout_started = true;28212821- run_again(ifmgd, ifmgd->auth_data->timeout);28402840+ run_again(sdata, ifmgd->auth_data->timeout);28222841 }28232842}28242843···28432862 (1ULL << WLAN_EID_HT_CAPABILITY) |28442863 (1ULL << WLAN_EID_HT_OPERATION);2845286428462846-static enum rx_mgmt_action28472847-ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,28482848- struct ieee80211_mgmt *mgmt, size_t len,28492849- u8 *deauth_buf, struct ieee80211_rx_status *rx_status)28652865+static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,28662866+ struct ieee80211_mgmt *mgmt, size_t len,28672867+ struct ieee80211_rx_status *rx_status)28502868{28512869 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;28522870 struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;···28602880 u8 erp_value = 0;28612881 u32 ncrc;28622882 u8 *bssid;28832883+ u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];2863288428642864- lockdep_assert_held(&ifmgd->mtx);28852885+ sdata_assert_lock(sdata);2865288628662887 /* Process beacon from the current BSS */28672888 baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;28682889 if (baselen > len)28692869- return RX_MGMT_NONE;28902890+ return;2870289128712892 rcu_read_lock();28722893 chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);28732894 if (!chanctx_conf) {28742895 rcu_read_unlock();28752875- return RX_MGMT_NONE;28962896+ return;28762897 }2877289828782899 if (rx_status->freq != chanctx_conf->def.chan->center_freq) {28792900 rcu_read_unlock();28802880- return RX_MGMT_NONE;29012901+ return;28812902 }28822903 chan = chanctx_conf->def.chan;28832904 rcu_read_unlock();···29052924 /* continue assoc process */29062925 ifmgd->assoc_data->timeout = jiffies;29072926 ifmgd->assoc_data->timeout_started = true;29082908- run_again(ifmgd, ifmgd->assoc_data->timeout);29092909- return RX_MGMT_NONE;29272927+ run_again(sdata, ifmgd->assoc_data->timeout);29282928+ return;29102929 }2911293029122931 if (!ifmgd->associated ||29132932 !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))29142914- return RX_MGMT_NONE;29332933+ return;29152934 bssid = ifmgd->associated->bssid;2916293529172936 /* Track average RSSI from the Beacon frames of the current AP */···30573076 }3058307730593078 if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)30603060- return RX_MGMT_NONE;30793079+ return;30613080 ifmgd->beacon_crc = ncrc;30623081 ifmgd->beacon_crc_valid = true;30633082···30913110 }3092311130933112 changed |= BSS_CHANGED_DTIM_PERIOD;31133113+ ieee80211_recalc_ps_vif(sdata);30943114 }3095311530963116 if (elems.erp_info) {···31133131 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,31143132 WLAN_REASON_DEAUTH_LEAVING,31153133 true, deauth_buf);31163116- return RX_MGMT_CFG80211_TX_DEAUTH;31343134+ cfg80211_send_deauth(sdata->dev, deauth_buf,31353135+ sizeof(deauth_buf));31363136+ return;31173137 }3118313831193139 if (sta && elems.opmode_notif)···31323148 elems.pwr_constr_elem);3133314931343150 ieee80211_bss_info_change_notify(sdata, changed);31353135-31363136- return RX_MGMT_NONE;31373151}3138315231393153void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,31403154 struct sk_buff *skb)31413155{31423142- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;31433156 struct ieee80211_rx_status *rx_status;31443157 struct ieee80211_mgmt *mgmt;31453145- struct cfg80211_bss *bss = NULL;31463146- enum rx_mgmt_action rma = RX_MGMT_NONE;31473147- u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];31483158 u16 fc;31493159 struct ieee802_11_elems elems;31503160 int ies_len;···31473169 mgmt = (struct ieee80211_mgmt *) skb->data;31483170 fc = le16_to_cpu(mgmt->frame_control);3149317131503150- mutex_lock(&ifmgd->mtx);31723172+ sdata_lock(sdata);3151317331523174 switch (fc & IEEE80211_FCTL_STYPE) {31533175 case IEEE80211_STYPE_BEACON:31543154- rma = ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,31553155- deauth_buf, rx_status);31763176+ ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status);31563177 break;31573178 case IEEE80211_STYPE_PROBE_RESP:31583179 ieee80211_rx_mgmt_probe_resp(sdata, skb);31593180 break;31603181 case IEEE80211_STYPE_AUTH:31613161- rma = ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);31823182+ ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);31623183 break;31633184 case IEEE80211_STYPE_DEAUTH:31643164- rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);31853185+ ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);31653186 break;31663187 case IEEE80211_STYPE_DISASSOC:31673167- rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);31883188+ ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);31683189 break;31693190 case IEEE80211_STYPE_ASSOC_RESP:31703191 case IEEE80211_STYPE_REASSOC_RESP:31713171- rma = ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, &bss);31923192+ ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len);31723193 break;31733194 case IEEE80211_STYPE_ACTION:31743195 if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {···3187321031883211 ieee80211_sta_process_chanswitch(sdata,31893212 rx_status->mactime,31903190- &elems);32133213+ &elems, false);31913214 } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {31923215 ies_len = skb->len -31933216 offsetof(struct ieee80211_mgmt,···3209323232103233 ieee80211_sta_process_chanswitch(sdata,32113234 rx_status->mactime,32123212- &elems);32353235+ &elems, false);32133236 }32143237 break;32153238 }32163216- mutex_unlock(&ifmgd->mtx);32173217-32183218- switch (rma) {32193219- case RX_MGMT_NONE:32203220- /* no action */32213221- break;32223222- case RX_MGMT_CFG80211_DEAUTH:32233223- cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);32243224- break;32253225- case RX_MGMT_CFG80211_DISASSOC:32263226- cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);32273227- break;32283228- case RX_MGMT_CFG80211_RX_AUTH:32293229- cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, skb->len);32303230- break;32313231- case RX_MGMT_CFG80211_RX_ASSOC:32323232- cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, skb->len);32333233- break;32343234- case RX_MGMT_CFG80211_ASSOC_TIMEOUT:32353235- cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid);32363236- break;32373237- case RX_MGMT_CFG80211_TX_DEAUTH:32383238- cfg80211_send_deauth(sdata->dev, deauth_buf,32393239- sizeof(deauth_buf));32403240- break;32413241- default:32423242- WARN(1, "unexpected: %d", rma);32433243- }32393239+ sdata_unlock(sdata);32443240}3245324132463242static void ieee80211_sta_timer(unsigned long data)···32273277static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,32283278 u8 *bssid, u8 reason, bool tx)32293279{32303230- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;32313280 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];3232328132333282 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,32343283 tx, frame_buf);32353235- mutex_unlock(&ifmgd->mtx);3236328432373237- /*32383238- * must be outside lock due to cfg80211,32393239- * but that's not a problem.32403240- */32413285 cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);32423242-32433243- mutex_lock(&ifmgd->mtx);32443286}3245328732463288static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)···32423300 struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data;32433301 u32 tx_flags = 0;3244330232453245- lockdep_assert_held(&ifmgd->mtx);33033303+ sdata_assert_lock(sdata);3246330432473305 if (WARN_ON_ONCE(!auth_data))32483306 return -EINVAL;32493249-32503250- if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)32513251- tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |32523252- IEEE80211_TX_INTFL_MLME_CONN_TX;3253330732543308 auth_data->tries++;32553309···32803342 auth_data->expected_transaction = trans;32813343 }3282334433453345+ if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)33463346+ tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |33473347+ IEEE80211_TX_INTFL_MLME_CONN_TX;33483348+32833349 ieee80211_send_auth(sdata, trans, auth_data->algorithm, status,32843350 auth_data->data, auth_data->data_len,32853351 auth_data->bss->bssid,···33073365 * will not answer to direct packet in unassociated state.33083366 */33093367 ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],33103310- NULL, 0, (u32) -1, true, tx_flags,33683368+ NULL, 0, (u32) -1, true, 0,33113369 auth_data->bss->channel, false);33123370 rcu_read_unlock();33133371 }3314337233153315- if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {33733373+ if (tx_flags == 0) {33163374 auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;33173375 ifmgd->auth_data->timeout_started = true;33183318- run_again(ifmgd, auth_data->timeout);33763376+ run_again(sdata, auth_data->timeout);33193377 } else {33203378 auth_data->timeout_started = false;33213379 }···33283386 struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;33293387 struct ieee80211_local *local = sdata->local;3330338833313331- lockdep_assert_held(&sdata->u.mgd.mtx);33893389+ sdata_assert_lock(sdata);3332339033333391 assoc_data->tries++;33343392 if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) {···33523410 if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {33533411 assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;33543412 assoc_data->timeout_started = true;33553355- run_again(&sdata->u.mgd, assoc_data->timeout);34133413+ run_again(sdata, assoc_data->timeout);33563414 } else {33573415 assoc_data->timeout_started = false;33583416 }···33773435 struct ieee80211_local *local = sdata->local;33783436 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;3379343733803380- mutex_lock(&ifmgd->mtx);34383438+ sdata_lock(sdata);3381343933823440 if (ifmgd->status_received) {33833441 __le16 fc = ifmgd->status_fc;···33893447 if (status_acked) {33903448 ifmgd->auth_data->timeout =33913449 jiffies + IEEE80211_AUTH_TIMEOUT_SHORT;33923392- run_again(ifmgd, ifmgd->auth_data->timeout);34503450+ run_again(sdata, ifmgd->auth_data->timeout);33933451 } else {33943452 ifmgd->auth_data->timeout = jiffies - 1;33953453 }···34003458 if (status_acked) {34013459 ifmgd->assoc_data->timeout =34023460 jiffies + IEEE80211_ASSOC_TIMEOUT_SHORT;34033403- run_again(ifmgd, ifmgd->assoc_data->timeout);34613461+ run_again(sdata, ifmgd->assoc_data->timeout);34043462 } else {34053463 ifmgd->assoc_data->timeout = jiffies - 1;34063464 }···3423348134243482 ieee80211_destroy_auth_data(sdata, false);3425348334263426- mutex_unlock(&ifmgd->mtx);34273484 cfg80211_send_auth_timeout(sdata->dev, bssid);34283428- mutex_lock(&ifmgd->mtx);34293485 }34303486 } else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started)34313431- run_again(ifmgd, ifmgd->auth_data->timeout);34873487+ run_again(sdata, ifmgd->auth_data->timeout);3432348834333489 if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started &&34343490 time_after(jiffies, ifmgd->assoc_data->timeout)) {···3439349934403500 ieee80211_destroy_assoc_data(sdata, false);3441350134423442- mutex_unlock(&ifmgd->mtx);34433502 cfg80211_send_assoc_timeout(sdata->dev, bssid);34443444- mutex_lock(&ifmgd->mtx);34453503 }34463504 } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started)34473447- run_again(ifmgd, ifmgd->assoc_data->timeout);35053505+ run_again(sdata, ifmgd->assoc_data->timeout);3448350634493507 if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |34503508 IEEE80211_STA_CONNECTION_POLL) &&···34763538 false);34773539 }34783540 } else if (time_is_after_jiffies(ifmgd->probe_timeout))34793479- run_again(ifmgd, ifmgd->probe_timeout);35413541+ run_again(sdata, ifmgd->probe_timeout);34803542 else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {34813543 mlme_dbg(sdata,34823544 "Failed to send nullfunc to AP %pM after %dms, disconnecting\n",···35053567 }35063568 }3507356935083508- mutex_unlock(&ifmgd->mtx);35703570+ sdata_unlock(sdata);35093571}3510357235113573static void ieee80211_sta_bcn_mon_timer(unsigned long data)···35613623 }35623624}3563362536263626+#ifdef CONFIG_PM36273627+void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)36283628+{36293629+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;36303630+36313631+ sdata_lock(sdata);36323632+ if (!ifmgd->associated) {36333633+ sdata_unlock(sdata);36343634+ return;36353635+ }36363636+36373637+ if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) {36383638+ sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME;36393639+ mlme_dbg(sdata, "driver requested disconnect after resume\n");36403640+ ieee80211_sta_connection_lost(sdata,36413641+ ifmgd->associated->bssid,36423642+ WLAN_REASON_UNSPECIFIED,36433643+ true);36443644+ sdata_unlock(sdata);36453645+ return;36463646+ }36473647+ sdata_unlock(sdata);36483648+}36493649+#endif36503650+35643651/* interface setup */35653652void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)35663653{···36133650 ifmgd->uapsd_queues = sdata->local->hw.uapsd_queues;36143651 ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len;36153652 ifmgd->p2p_noa_index = -1;36163616-36173617- mutex_init(&ifmgd->mtx);3618365336193654 if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)36203655 ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC;···3969400839704009 /* try to authenticate/probe */3971401039723972- mutex_lock(&ifmgd->mtx);39733973-39744011 if ((ifmgd->auth_data && !ifmgd->auth_data->done) ||39754012 ifmgd->assoc_data) {39764013 err = -EBUSY;···39884029 WLAN_REASON_UNSPECIFIED,39894030 false, frame_buf);3990403139913991- __cfg80211_send_deauth(sdata->dev, frame_buf,39923992- sizeof(frame_buf));40324032+ cfg80211_send_deauth(sdata->dev, frame_buf,40334033+ sizeof(frame_buf));39934034 }3994403539954036 sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);···4006404740074048 /* hold our own reference */40084049 cfg80211_ref_bss(local->hw.wiphy, auth_data->bss);40094009- err = 0;40104010- goto out_unlock;40504050+ return 0;4011405140124052 err_clear:40134053 memset(ifmgd->bssid, 0, ETH_ALEN);···40144056 ifmgd->auth_data = NULL;40154057 err_free:40164058 kfree(auth_data);40174017- out_unlock:40184018- mutex_unlock(&ifmgd->mtx);40194019-40204059 return err;40214060}40224061···40444089 assoc_data->ssid_len = ssidie[1];40454090 rcu_read_unlock();4046409140474047- mutex_lock(&ifmgd->mtx);40484048-40494092 if (ifmgd->associated) {40504093 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];40514094···40514098 WLAN_REASON_UNSPECIFIED,40524099 false, frame_buf);4053410040544054- __cfg80211_send_deauth(sdata->dev, frame_buf,40554055- sizeof(frame_buf));41014101+ cfg80211_send_deauth(sdata->dev, frame_buf,41024102+ sizeof(frame_buf));40564103 }4057410440584105 if (ifmgd->auth_data && !ifmgd->auth_data->done) {···42464293 }42474294 rcu_read_unlock();4248429542494249- run_again(ifmgd, assoc_data->timeout);42964296+ run_again(sdata, assoc_data->timeout);4250429742514298 if (bss->corrupt_data) {42524299 char *corrupt_type = "data";···42624309 corrupt_type);42634310 }4264431142654265- err = 0;42664266- goto out;43124312+ return 0;42674313 err_clear:42684314 memset(ifmgd->bssid, 0, ETH_ALEN);42694315 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);42704316 ifmgd->assoc_data = NULL;42714317 err_free:42724318 kfree(assoc_data);42734273- out:42744274- mutex_unlock(&ifmgd->mtx);42754275-42764319 return err;42774320}42784321···42784329 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;42794330 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];42804331 bool tx = !req->local_state_change;42814281- bool sent_frame = false;42824282-42834283- mutex_lock(&ifmgd->mtx);43324332+ bool report_frame = false;4284433342854334 sdata_info(sdata,42864335 "deauthenticating from %pM by local choice (reason=%d)\n",···42914344 req->reason_code, tx,42924345 frame_buf);42934346 ieee80211_destroy_auth_data(sdata, false);42944294- mutex_unlock(&ifmgd->mtx);4295434742964296- sent_frame = tx;43484348+ report_frame = true;42974349 goto out;42984350 }42994351···43004354 ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {43014355 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,43024356 req->reason_code, tx, frame_buf);43034303- sent_frame = tx;43574357+ report_frame = true;43044358 }43054305- mutex_unlock(&ifmgd->mtx);4306435943074360 out:43084308- if (sent_frame)43094309- __cfg80211_send_deauth(sdata->dev, frame_buf,43104310- IEEE80211_DEAUTH_FRAME_LEN);43614361+ if (report_frame)43624362+ cfg80211_send_deauth(sdata->dev, frame_buf,43634363+ IEEE80211_DEAUTH_FRAME_LEN);4311436443124365 return 0;43134366}···43184373 u8 bssid[ETH_ALEN];43194374 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];4320437543214321- mutex_lock(&ifmgd->mtx);43224322-43234376 /*43244377 * cfg80211 should catch this ... but it's racy since43254378 * we can receive a disassoc frame, process it, hand it43264379 * to cfg80211 while that's in a locked section already43274380 * trying to tell us that the user wants to disconnect.43284381 */43294329- if (ifmgd->associated != req->bss) {43304330- mutex_unlock(&ifmgd->mtx);43824382+ if (ifmgd->associated != req->bss)43314383 return -ENOLINK;43324332- }4333438443344385 sdata_info(sdata,43354386 "disassociating from %pM by local choice (reason=%d)\n",···43354394 ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC,43364395 req->reason_code, !req->local_state_change,43374396 frame_buf);43384338- mutex_unlock(&ifmgd->mtx);4339439743404340- __cfg80211_send_disassoc(sdata->dev, frame_buf,43414341- IEEE80211_DEAUTH_FRAME_LEN);43984398+ cfg80211_send_disassoc(sdata->dev, frame_buf,43994399+ IEEE80211_DEAUTH_FRAME_LEN);4342440043434401 return 0;43444402}···43574417 cancel_work_sync(&ifmgd->csa_connection_drop_work);43584418 cancel_work_sync(&ifmgd->chswitch_work);4359441943604360- mutex_lock(&ifmgd->mtx);44204420+ sdata_lock(sdata);43614421 if (ifmgd->assoc_data)43624422 ieee80211_destroy_assoc_data(sdata, false);43634423 if (ifmgd->auth_data)43644424 ieee80211_destroy_auth_data(sdata, false);43654425 del_timer_sync(&ifmgd->timer);43664366- mutex_unlock(&ifmgd->mtx);44264426+ sdata_unlock(sdata);43674427}4368442843694429void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
+8-1
net/mac80211/rate.c
···688688 struct ieee80211_sta *pubsta,689689 struct ieee80211_sta_rates *rates)690690{691691- struct ieee80211_sta_rates *old = rcu_dereference(pubsta->rates);691691+ struct ieee80211_sta_rates *old;692692693693+ /*694694+ * mac80211 guarantees that this function will not be called695695+ * concurrently, so the following RCU access is safe, even without696696+ * extra locking. This can not be checked easily, so we just set697697+ * the condition to true.698698+ */699699+ old = rcu_dereference_protected(pubsta->rates, true);693700 rcu_assign_pointer(pubsta->rates, rates);694701 if (old)695702 kfree_rcu(old, rcu_head);
+27-6
net/mac80211/rx.c
···258258 pos += 2;259259260260 if (status->flag & RX_FLAG_HT) {261261+ unsigned int stbc;262262+261263 rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_MCS);262264 *pos++ = local->hw.radiotap_mcs_details;263265 *pos = 0;···269267 *pos |= IEEE80211_RADIOTAP_MCS_BW_40;270268 if (status->flag & RX_FLAG_HT_GF)271269 *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF;270270+ stbc = (status->flag & RX_FLAG_STBC_MASK) >> RX_FLAG_STBC_SHIFT;271271+ *pos |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT;272272 pos++;273273 *pos++ = status->rate_idx;274274 }···13761372 struct sk_buff *skb = rx->skb;13771373 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);13781374 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;13751375+ int i;1379137613801377 if (!sta)13811378 return RX_CONTINUE;···14251420 if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {14261421 sta->last_signal = status->signal;14271422 ewma_add(&sta->avg_signal, -status->signal);14231423+ }14241424+14251425+ if (status->chains) {14261426+ sta->chains = status->chains;14271427+ for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) {14281428+ int signal = status->chain_signal[i];14291429+14301430+ if (!(status->chains & BIT(i)))14311431+ continue;14321432+14331433+ sta->chain_signal_last[i] = signal;14341434+ ewma_add(&sta->chain_signal_avg[i], -signal);14351435+ }14281436 }1429143714301438 /*···16261608 entry->ccmp = 1;16271609 memcpy(entry->last_pn,16281610 rx->key->u.ccmp.rx_pn[queue],16291629- CCMP_PN_LEN);16111611+ IEEE80211_CCMP_PN_LEN);16301612 }16311613 return RX_QUEUED;16321614 }···16451627 * (IEEE 802.11i, 8.3.3.4.5) */16461628 if (entry->ccmp) {16471629 int i;16481648- u8 pn[CCMP_PN_LEN], *rpn;16301630+ u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;16491631 int queue;16501632 if (!rx->key || rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP)16511633 return RX_DROP_UNUSABLE;16521652- memcpy(pn, entry->last_pn, CCMP_PN_LEN);16531653- for (i = CCMP_PN_LEN - 1; i >= 0; i--) {16341634+ memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);16351635+ for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {16541636 pn[i]++;16551637 if (pn[i])16561638 break;16571639 }16581640 queue = rx->security_idx;16591641 rpn = rx->key->u.ccmp.rx_pn[queue];16601660- if (memcmp(pn, rpn, CCMP_PN_LEN))16421642+ if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN))16611643 return RX_DROP_UNUSABLE;16621662- memcpy(entry->last_pn, pn, CCMP_PN_LEN);16441644+ memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN);16631645 }1664164616651647 skb_pull(rx->skb, ieee80211_hdrlen(fc));···30543036 * and location updates. Note that mac8021130553037 * itself never looks at these frames.30563038 */30393039+ if (!multicast &&30403040+ !ether_addr_equal(sdata->vif.addr, hdr->addr1))30413041+ return 0;30573042 if (ieee80211_is_public_action(hdr, skb->len))30583043 return 1;30593044 if (!ieee80211_is_beacon(hdr->frame_control))
+2
net/mac80211/sta_info.c
···358358 do_posix_clock_monotonic_gettime(&uptime);359359 sta->last_connected = uptime.tv_sec;360360 ewma_init(&sta->avg_signal, 1024, 8);361361+ for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++)362362+ ewma_init(&sta->chain_signal_avg[i], 1024, 8);361363362364 if (sta_prepare_rate_control(local, sta, gfp)) {363365 kfree(sta);
+5
net/mac80211/sta_info.h
···344344 int last_signal;345345 struct ewma avg_signal;346346 int last_ack_signal;347347+348348+ u8 chains;349349+ s8 chain_signal_last[IEEE80211_MAX_CHAINS];350350+ struct ewma chain_signal_avg[IEEE80211_MAX_CHAINS];351351+347352 /* Plus 1 for non-QoS frames */348353 __le16 last_seq_ctrl[IEEE80211_NUM_TIDS + 1];349354
···3434MODULE_AUTHOR("Johannes Berg");3535MODULE_LICENSE("GPL");3636MODULE_DESCRIPTION("wireless configuration support");3737+MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME);37383838-/* RCU-protected (and cfg80211_mutex for writers) */3939+/* RCU-protected (and RTNL for writers) */3940LIST_HEAD(cfg80211_rdev_list);4041int cfg80211_rdev_list_generation;4141-4242-DEFINE_MUTEX(cfg80211_mutex);43424443/* for debugfs */4544static struct dentry *ieee80211_debugfs_dir;···5152MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz,5253 "Disable 40MHz support in the 2.4GHz band");53545454-/* requires cfg80211_mutex to be held! */5555struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)5656{5757 struct cfg80211_registered_device *result = NULL, *rdev;58585959- assert_cfg80211_lock();5959+ ASSERT_RTNL();60606161 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {6262 if (rdev->wiphy_idx == wiphy_idx) {···7476 return rdev->wiphy_idx;7577}76787777-/* requires cfg80211_rdev_mutex to be held! */7879struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)7980{8081 struct cfg80211_registered_device *rdev;81828282- assert_cfg80211_lock();8383+ ASSERT_RTNL();83848485 rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx);8586 if (!rdev)···8689 return &rdev->wiphy;8790}88918989-struct cfg80211_registered_device *9090-cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)9191-{9292- struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);9393- struct net_device *dev;9494-9595- mutex_lock(&cfg80211_mutex);9696- dev = dev_get_by_index(net, ifindex);9797- if (!dev)9898- goto out;9999- if (dev->ieee80211_ptr) {100100- rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);101101- mutex_lock(&rdev->mtx);102102- } else103103- rdev = ERR_PTR(-ENODEV);104104- dev_put(dev);105105- out:106106- mutex_unlock(&cfg80211_mutex);107107- return rdev;108108-}109109-110110-/* requires cfg80211_mutex to be held */11192int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,11293 char *newname)11394{11495 struct cfg80211_registered_device *rdev2;11596 int wiphy_idx, taken = -1, result, digits;11697117117- assert_cfg80211_lock();9898+ ASSERT_RTNL();11899119100 /* prohibit calling the thing phy%d when %d is not its number */120101 sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);···190215void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,191216 struct wireless_dev *wdev)192217{193193- lockdep_assert_held(&rdev->devlist_mtx);194194- lockdep_assert_held(&rdev->sched_scan_mtx);218218+ ASSERT_RTNL();195219196220 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))197221 return;···204230 rdev->opencount--;205231206232 if (rdev->scan_req && rdev->scan_req->wdev == wdev) {207207- bool busy = work_busy(&rdev->scan_done_wk);208208-209233 /*210210- * If the work isn't pending or running (in which case it would211211- * be waiting for the lock we hold) the driver didn't properly212212- * cancel the scan when the interface was removed. In this case213213- * warn and leak the scan request object to not crash later.234234+ * If the scan request wasn't notified as done, set it235235+ * to aborted and leak it after a warning. The driver236236+ * should have notified us that it ended at the latest237237+ * during rdev_stop_p2p_device().214238 */215215- WARN_ON(!busy);216216-217217- rdev->scan_req->aborted = true;218218- ___cfg80211_scan_done(rdev, !busy);239239+ if (WARN_ON(!rdev->scan_req->notified))240240+ rdev->scan_req->aborted = true;241241+ ___cfg80211_scan_done(rdev, !rdev->scan_req->notified);219242 }220243}221244···226255227256 rtnl_lock();228257229229- /* read-only iteration need not hold the devlist_mtx */230230-231258 list_for_each_entry(wdev, &rdev->wdev_list, list) {232259 if (wdev->netdev) {233260 dev_close(wdev->netdev);···234265 /* otherwise, check iftype */235266 switch (wdev->iftype) {236267 case NL80211_IFTYPE_P2P_DEVICE:237237- /* but this requires it */238238- mutex_lock(&rdev->devlist_mtx);239239- mutex_lock(&rdev->sched_scan_mtx);240268 cfg80211_stop_p2p_device(rdev, wdev);241241- mutex_unlock(&rdev->sched_scan_mtx);242242- mutex_unlock(&rdev->devlist_mtx);243269 break;244270 default:245271 break;···262298 event_work);263299264300 rtnl_lock();265265- cfg80211_lock_rdev(rdev);266266-267301 cfg80211_process_rdev_events(rdev);268268- cfg80211_unlock_rdev(rdev);269302 rtnl_unlock();270303}271304···270309271310struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)272311{273273- static int wiphy_counter;312312+ static atomic_t wiphy_counter = ATOMIC_INIT(0);274313275314 struct cfg80211_registered_device *rdev;276315 int alloc_size;···292331293332 rdev->ops = ops;294333295295- mutex_lock(&cfg80211_mutex);296296-297297- rdev->wiphy_idx = wiphy_counter++;334334+ rdev->wiphy_idx = atomic_inc_return(&wiphy_counter);298335299336 if (unlikely(rdev->wiphy_idx < 0)) {300300- wiphy_counter--;301301- mutex_unlock(&cfg80211_mutex);302337 /* ugh, wrapped! */338338+ atomic_dec(&wiphy_counter);303339 kfree(rdev);304340 return NULL;305341 }306342307307- mutex_unlock(&cfg80211_mutex);308308-309343 /* give it a proper name */310344 dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);311345312312- mutex_init(&rdev->mtx);313313- mutex_init(&rdev->devlist_mtx);314314- mutex_init(&rdev->sched_scan_mtx);315346 INIT_LIST_HEAD(&rdev->wdev_list);316347 INIT_LIST_HEAD(&rdev->beacon_registrations);317348 spin_lock_init(&rdev->beacon_registrations_lock);···551598 /* check and set up bitrates */552599 ieee80211_set_bitrate_flags(wiphy);553600554554- mutex_lock(&cfg80211_mutex);601601+ rtnl_lock();555602556603 res = device_add(&rdev->wiphy.dev);557604 if (res) {558558- mutex_unlock(&cfg80211_mutex);605605+ rtnl_unlock();559606 return res;560607 }561608···584631 }585632586633 cfg80211_debugfs_rdev_add(rdev);587587- mutex_unlock(&cfg80211_mutex);588634589589- /*590590- * due to a locking dependency this has to be outside of the591591- * cfg80211_mutex lock592592- */593635 res = rfkill_register(rdev->rfkill);594594- if (res)595595- goto out_rm_dev;636636+ if (res) {637637+ device_del(&rdev->wiphy.dev);596638597597- rtnl_lock();639639+ debugfs_remove_recursive(rdev->wiphy.debugfsdir);640640+ list_del_rcu(&rdev->list);641641+ wiphy_regulatory_deregister(wiphy);642642+ rtnl_unlock();643643+ return res;644644+ }645645+598646 rdev->wiphy.registered = true;599647 rtnl_unlock();600648 return 0;601601-602602-out_rm_dev:603603- device_del(&rdev->wiphy.dev);604604- return res;605649}606650EXPORT_SYMBOL(wiphy_register);607651···625675{626676 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);627677678678+ wait_event(rdev->dev_wait, ({679679+ int __count;680680+ rtnl_lock();681681+ __count = rdev->opencount;682682+ rtnl_unlock();683683+ __count == 0; }));684684+628685 rtnl_lock();629686 rdev->wiphy.registered = false;630630- rtnl_unlock();631687632688 rfkill_unregister(rdev->rfkill);633689634634- /* protect the device list */635635- mutex_lock(&cfg80211_mutex);636636-637637- wait_event(rdev->dev_wait, ({638638- int __count;639639- mutex_lock(&rdev->devlist_mtx);640640- __count = rdev->opencount;641641- mutex_unlock(&rdev->devlist_mtx);642642- __count == 0; }));643643-644644- mutex_lock(&rdev->devlist_mtx);645690 BUG_ON(!list_empty(&rdev->wdev_list));646646- mutex_unlock(&rdev->devlist_mtx);647691648692 /*649693 * First remove the hardware from everywhere, this makes···648704 synchronize_rcu();649705650706 /*651651- * Try to grab rdev->mtx. If a command is still in progress,652652- * hopefully the driver will refuse it since it's tearing653653- * down the device already. We wait for this command to complete654654- * before unlinking the item from the list.655655- * Note: as codified by the BUG_ON above we cannot get here if656656- * a virtual interface is still present. Hence, we can only get657657- * to lock contention here if userspace issues a command that658658- * identified the hardware by wiphy index.659659- */660660- cfg80211_lock_rdev(rdev);661661- /* nothing */662662- cfg80211_unlock_rdev(rdev);663663-664664- /*665707 * If this device got a regulatory hint tell core its666708 * free to listen now to a new shiny device regulatory hint667709 */···656726 cfg80211_rdev_list_generation++;657727 device_del(&rdev->wiphy.dev);658728659659- mutex_unlock(&cfg80211_mutex);729729+ rtnl_unlock();660730661731 flush_work(&rdev->scan_done_wk);662732 cancel_work_sync(&rdev->conn_work);663733 flush_work(&rdev->event_work);664734 cancel_delayed_work_sync(&rdev->dfs_update_channels_wk);665735666666- if (rdev->wowlan && rdev->ops->set_wakeup)736736+#ifdef CONFIG_PM737737+ if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup)667738 rdev_set_wakeup(rdev, false);739739+#endif668740 cfg80211_rdev_free_wowlan(rdev);669741}670742EXPORT_SYMBOL(wiphy_unregister);···676744 struct cfg80211_internal_bss *scan, *tmp;677745 struct cfg80211_beacon_registration *reg, *treg;678746 rfkill_destroy(rdev->rfkill);679679- mutex_destroy(&rdev->mtx);680680- mutex_destroy(&rdev->devlist_mtx);681681- mutex_destroy(&rdev->sched_scan_mtx);682747 list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {683748 list_del(®->list);684749 kfree(reg);···700771}701772EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);702773703703-static void wdev_cleanup_work(struct work_struct *work)704704-{705705- struct wireless_dev *wdev;706706- struct cfg80211_registered_device *rdev;707707-708708- wdev = container_of(work, struct wireless_dev, cleanup_work);709709- rdev = wiphy_to_dev(wdev->wiphy);710710-711711- mutex_lock(&rdev->sched_scan_mtx);712712-713713- if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {714714- rdev->scan_req->aborted = true;715715- ___cfg80211_scan_done(rdev, true);716716- }717717-718718- if (WARN_ON(rdev->sched_scan_req &&719719- rdev->sched_scan_req->dev == wdev->netdev)) {720720- __cfg80211_stop_sched_scan(rdev, false);721721- }722722-723723- mutex_unlock(&rdev->sched_scan_mtx);724724-725725- mutex_lock(&rdev->devlist_mtx);726726- rdev->opencount--;727727- mutex_unlock(&rdev->devlist_mtx);728728- wake_up(&rdev->dev_wait);729729-730730- dev_put(wdev->netdev);731731-}732732-733774void cfg80211_unregister_wdev(struct wireless_dev *wdev)734775{735776 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);···709810 if (WARN_ON(wdev->netdev))710811 return;711812712712- mutex_lock(&rdev->devlist_mtx);713713- mutex_lock(&rdev->sched_scan_mtx);714813 list_del_rcu(&wdev->list);715814 rdev->devlist_generation++;716815···720823 WARN_ON_ONCE(1);721824 break;722825 }723723- mutex_unlock(&rdev->sched_scan_mtx);724724- mutex_unlock(&rdev->devlist_mtx);725826}726827EXPORT_SYMBOL(cfg80211_unregister_wdev);727828···738843}739844740845void cfg80211_leave(struct cfg80211_registered_device *rdev,741741- struct wireless_dev *wdev)846846+ struct wireless_dev *wdev)742847{743848 struct net_device *dev = wdev->netdev;744849···748853 break;749854 case NL80211_IFTYPE_P2P_CLIENT:750855 case NL80211_IFTYPE_STATION:751751- mutex_lock(&rdev->sched_scan_mtx);752856 __cfg80211_stop_sched_scan(rdev, false);753753- mutex_unlock(&rdev->sched_scan_mtx);754857755858 wdev_lock(wdev);756859#ifdef CONFIG_CFG80211_WEXT···757864 wdev->wext.ie_len = 0;758865 wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC;759866#endif760760- __cfg80211_disconnect(rdev, dev,761761- WLAN_REASON_DEAUTH_LEAVING, true);762762- cfg80211_mlme_down(rdev, dev);867867+ cfg80211_disconnect(rdev, dev,868868+ WLAN_REASON_DEAUTH_LEAVING, true);763869 wdev_unlock(wdev);764870 break;765871 case NL80211_IFTYPE_MESH_POINT:···801909 * are added with nl80211.802910 */803911 mutex_init(&wdev->mtx);804804- INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);805912 INIT_LIST_HEAD(&wdev->event_list);806913 spin_lock_init(&wdev->event_lock);807914 INIT_LIST_HEAD(&wdev->mgmt_registrations);808915 spin_lock_init(&wdev->mgmt_registrations_lock);809916810810- mutex_lock(&rdev->devlist_mtx);811917 wdev->identifier = ++rdev->wdev_id;812918 list_add_rcu(&wdev->list, &rdev->wdev_list);813919 rdev->devlist_generation++;···818928 }819929 wdev->netdev = dev;820930 wdev->sme_state = CFG80211_SME_IDLE;821821- mutex_unlock(&rdev->devlist_mtx);822931#ifdef CONFIG_CFG80211_WEXT823932 wdev->wext.default_key = -1;824933 wdev->wext.default_mgmt_key = -1;···843954 break;844955 case NETDEV_DOWN:845956 cfg80211_update_iface_num(rdev, wdev->iftype, -1);846846- dev_hold(dev);847847- queue_work(cfg80211_wq, &wdev->cleanup_work);957957+ if (rdev->scan_req && rdev->scan_req->wdev == wdev) {958958+ if (WARN_ON(!rdev->scan_req->notified))959959+ rdev->scan_req->aborted = true;960960+ ___cfg80211_scan_done(rdev, true);961961+ }962962+963963+ if (WARN_ON(rdev->sched_scan_req &&964964+ rdev->sched_scan_req->dev == wdev->netdev)) {965965+ __cfg80211_stop_sched_scan(rdev, false);966966+ }967967+968968+ rdev->opencount--;969969+ wake_up(&rdev->dev_wait);848970 break;849971 case NETDEV_UP:850850- /*851851- * If we have a really quick DOWN/UP succession we may852852- * have this work still pending ... cancel it and see853853- * if it was pending, in which case we need to account854854- * for some of the work it would have done.855855- */856856- if (cancel_work_sync(&wdev->cleanup_work)) {857857- mutex_lock(&rdev->devlist_mtx);858858- rdev->opencount--;859859- mutex_unlock(&rdev->devlist_mtx);860860- dev_put(dev);861861- }862972 cfg80211_update_iface_num(rdev, wdev->iftype, 1);863863- cfg80211_lock_rdev(rdev);864864- mutex_lock(&rdev->devlist_mtx);865865- mutex_lock(&rdev->sched_scan_mtx);866973 wdev_lock(wdev);867974 switch (wdev->iftype) {868975#ifdef CONFIG_CFG80211_WEXT···8901005 break;8911006 }8921007 wdev_unlock(wdev);893893- mutex_unlock(&rdev->sched_scan_mtx);8941008 rdev->opencount++;895895- mutex_unlock(&rdev->devlist_mtx);896896- cfg80211_unlock_rdev(rdev);89710098981010 /*8991011 * Configure power management to the driver here so that its···9071025 break;9081026 case NETDEV_UNREGISTER:9091027 /*910910- * NB: cannot take rdev->mtx here because this may be911911- * called within code protected by it when interfaces912912- * are removed with nl80211.913913- */914914- mutex_lock(&rdev->devlist_mtx);915915- /*9161028 * It is possible to get NETDEV_UNREGISTER9171029 * multiple times. To detect that, check9181030 * that the interface is still on the list···9221046 kfree(wdev->wext.keys);9231047#endif9241048 }925925- mutex_unlock(&rdev->devlist_mtx);9261049 /*9271050 * synchronise (so that we won't find this netdev9281051 * from other code any more) and then clear the list···9411066 return notifier_from_errno(-EOPNOTSUPP);9421067 if (rfkill_blocked(rdev->rfkill))9431068 return notifier_from_errno(-ERFKILL);944944- mutex_lock(&rdev->devlist_mtx);9451069 ret = cfg80211_can_add_interface(rdev, wdev->iftype);946946- mutex_unlock(&rdev->devlist_mtx);9471070 if (ret)9481071 return notifier_from_errno(ret);9491072 break;···9591086 struct cfg80211_registered_device *rdev;96010879611088 rtnl_lock();962962- mutex_lock(&cfg80211_mutex);9631089 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {9641090 if (net_eq(wiphy_net(&rdev->wiphy), net))9651091 WARN_ON(cfg80211_switch_netns(rdev, &init_net));9661092 }967967- mutex_unlock(&cfg80211_mutex);9681093 rtnl_unlock();9691094}9701095
+19-74
net/wireless/core.h
···55 */66#ifndef __NET_WIRELESS_CORE_H77#define __NET_WIRELESS_CORE_H88-#include <linux/mutex.h>98#include <linux/list.h>109#include <linux/netdevice.h>1110#include <linux/rbtree.h>···2223struct cfg80211_registered_device {2324 const struct cfg80211_ops *ops;2425 struct list_head list;2525- /* we hold this mutex during any call so that2626- * we cannot do multiple calls at once, and also2727- * to avoid the deregister call to proceed while2828- * any call is in progress */2929- struct mutex mtx;30263127 /* rfkill support */3228 struct rfkill_ops rfkill_ops;···4349 /* wiphy index, internal only */4450 int wiphy_idx;45514646- /* associated wireless interfaces */4747- struct mutex devlist_mtx;4848- /* protected by devlist_mtx or RCU */5252+ /* associated wireless interfaces, protected by rtnl or RCU */4953 struct list_head wdev_list;5054 int devlist_generation, wdev_id;5155 int opencount; /* also protected by devlist_mtx */···6775 struct work_struct scan_done_wk;6876 struct work_struct sched_scan_results_wk;69777070- struct mutex sched_scan_mtx;7171-7278#ifdef CONFIG_NL80211_TESTMODE7379 struct genl_info *testmode_info;7480#endif75817682 struct work_struct conn_work;7783 struct work_struct event_work;7878-7979- struct cfg80211_wowlan *wowlan;80848185 struct delayed_work dfs_update_channels_wk;8286···94106static inline void95107cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev)96108{109109+#ifdef CONFIG_PM97110 int i;981119999- if (!rdev->wowlan)112112+ if (!rdev->wiphy.wowlan_config)100113 return;101101- for (i = 0; i < rdev->wowlan->n_patterns; i++)102102- kfree(rdev->wowlan->patterns[i].mask);103103- kfree(rdev->wowlan->patterns);104104- if (rdev->wowlan->tcp && rdev->wowlan->tcp->sock)105105- sock_release(rdev->wowlan->tcp->sock);106106- kfree(rdev->wowlan->tcp);107107- kfree(rdev->wowlan);114114+ for (i = 0; i < rdev->wiphy.wowlan_config->n_patterns; i++)115115+ kfree(rdev->wiphy.wowlan_config->patterns[i].mask);116116+ kfree(rdev->wiphy.wowlan_config->patterns);117117+ if (rdev->wiphy.wowlan_config->tcp &&118118+ rdev->wiphy.wowlan_config->tcp->sock)119119+ sock_release(rdev->wiphy.wowlan_config->tcp->sock);120120+ kfree(rdev->wiphy.wowlan_config->tcp);121121+ kfree(rdev->wiphy.wowlan_config);122122+#endif108123}109124110125extern struct workqueue_struct *cfg80211_wq;111111-extern struct mutex cfg80211_mutex;112126extern struct list_head cfg80211_rdev_list;113127extern int cfg80211_rdev_list_generation;114114-115115-static inline void assert_cfg80211_lock(void)116116-{117117- lockdep_assert_held(&cfg80211_mutex);118118-}119128120129struct cfg80211_internal_bss {121130 struct list_head list;···146161struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx);147162int get_wiphy_idx(struct wiphy *wiphy);148163149149-/* requires cfg80211_rdev_mutex to be held! */150164struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);151151-152152-/* identical to cfg80211_get_dev_from_info but only operate on ifindex */153153-extern struct cfg80211_registered_device *154154-cfg80211_get_dev_from_ifindex(struct net *net, int ifindex);155165156166int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,157167 struct net *net);158158-159159-static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev)160160-{161161- mutex_lock(&rdev->mtx);162162-}163163-164164-static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *rdev)165165-{166166- BUG_ON(IS_ERR(rdev) || !rdev);167167- mutex_unlock(&rdev->mtx);168168-}169168170169static inline void wdev_lock(struct wireless_dev *wdev)171170 __acquires(wdev)···165196 mutex_unlock(&wdev->mtx);166197}167198168168-#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx)199199+#define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL()169200#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)170201171202static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)···283314 struct net_device *dev);284315285316/* MLME */286286-int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,287287- struct net_device *dev,288288- struct ieee80211_channel *chan,289289- enum nl80211_auth_type auth_type,290290- const u8 *bssid,291291- const u8 *ssid, int ssid_len,292292- const u8 *ie, int ie_len,293293- const u8 *key, int key_len, int key_idx,294294- const u8 *sae_data, int sae_data_len);295317int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,296296- struct net_device *dev, struct ieee80211_channel *chan,297297- enum nl80211_auth_type auth_type, const u8 *bssid,318318+ struct net_device *dev,319319+ struct ieee80211_channel *chan,320320+ enum nl80211_auth_type auth_type,321321+ const u8 *bssid,298322 const u8 *ssid, int ssid_len,299323 const u8 *ie, int ie_len,300324 const u8 *key, int key_len, int key_idx,301325 const u8 *sae_data, int sae_data_len);302302-int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,303303- struct net_device *dev,304304- struct ieee80211_channel *chan,305305- const u8 *bssid,306306- const u8 *ssid, int ssid_len,307307- struct cfg80211_assoc_request *req);308326int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,309327 struct net_device *dev,310328 struct ieee80211_channel *chan,311329 const u8 *bssid,312330 const u8 *ssid, int ssid_len,313331 struct cfg80211_assoc_request *req);314314-int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,315315- struct net_device *dev, const u8 *bssid,316316- const u8 *ie, int ie_len, u16 reason,317317- bool local_state_change);318332int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,319333 struct net_device *dev, const u8 *bssid,320334 const u8 *ie, int ie_len, u16 reason,···329377 const struct ieee80211_vht_cap *vht_capa_mask);330378331379/* SME */332332-int __cfg80211_connect(struct cfg80211_registered_device *rdev,333333- struct net_device *dev,334334- struct cfg80211_connect_params *connect,335335- struct cfg80211_cached_keys *connkeys,336336- const u8 *prev_bssid);337380int cfg80211_connect(struct cfg80211_registered_device *rdev,338381 struct net_device *dev,339382 struct cfg80211_connect_params *connect,340340- struct cfg80211_cached_keys *connkeys);341341-int __cfg80211_disconnect(struct cfg80211_registered_device *rdev,342342- struct net_device *dev, u16 reason,343343- bool wextev);383383+ struct cfg80211_cached_keys *connkeys,384384+ const u8 *prev_bssid);344385int cfg80211_disconnect(struct cfg80211_registered_device *rdev,345386 struct net_device *dev, u16 reason,346387 bool wextev);
+2-2
net/wireless/debugfs.c
···7474 if (!buf)7575 return -ENOMEM;76767777- mutex_lock(&cfg80211_mutex);7777+ rtnl_lock();78787979 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {8080 sband = wiphy->bands[band];···8585 buf, buf_size, offset);8686 }87878888- mutex_unlock(&cfg80211_mutex);8888+ rtnl_unlock();89899090 r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);9191
···37373838/* the netlink family */3939static struct genl_family nl80211_fam = {4040- .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */4141- .name = "nl80211", /* have users key off the name instead */4242- .hdrsize = 0, /* no private header */4343- .version = 1, /* no particular meaning now */4040+ .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */4141+ .name = NL80211_GENL_NAME, /* have users key off the name instead */4242+ .hdrsize = 0, /* no private header */4343+ .version = 1, /* no particular meaning now */4444 .maxattr = NL80211_ATTR_MAX,4545 .netnsok = true,4646 .pre_doit = nl80211_pre_doit,···5959 int wiphy_idx = -1;6060 int ifidx = -1;61616262- assert_cfg80211_lock();6262+ ASSERT_RTNL();63636464 if (!have_ifidx && !have_wdev_id)6565 return ERR_PTR(-EINVAL);···8080 if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)8181 continue;82828383- mutex_lock(&rdev->devlist_mtx);8483 list_for_each_entry(wdev, &rdev->wdev_list, list) {8584 if (have_ifidx && wdev->netdev &&8685 wdev->netdev->ifindex == ifidx) {···9192 break;9293 }9394 }9494- mutex_unlock(&rdev->devlist_mtx);95959696 if (result)9797 break;···107109 struct cfg80211_registered_device *rdev = NULL, *tmp;108110 struct net_device *netdev;109111110110- assert_cfg80211_lock();112112+ ASSERT_RTNL();111113112114 if (!attrs[NL80211_ATTR_WIPHY] &&113115 !attrs[NL80211_ATTR_IFINDEX] &&···126128 tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);127129 if (tmp) {128130 /* make sure wdev exists */129129- mutex_lock(&tmp->devlist_mtx);130131 list_for_each_entry(wdev, &tmp->wdev_list, list) {131132 if (wdev->identifier != (u32)wdev_id)132133 continue;133134 found = true;134135 break;135136 }136136- mutex_unlock(&tmp->devlist_mtx);137137138138 if (!found)139139 tmp = NULL;···178182/*179183 * This function returns a pointer to the driver180184 * that the genl_info item that is passed refers to.181181- * If successful, it returns non-NULL and also locks182182- * the driver's mutex!183183- *184184- * This means that you need to call cfg80211_unlock_rdev()185185- * before being allowed to acquire &cfg80211_mutex!186186- *187187- * This is necessary because we need to lock the global188188- * mutex to get an item off the list safely, and then189189- * we lock the rdev mutex so it doesn't go away under us.190190- *191191- * We don't want to keep cfg80211_mutex locked192192- * for all the time in order to allow requests on193193- * other interfaces to go through at the same time.194185 *195186 * The result of this can be a PTR_ERR and hence must196187 * be checked with IS_ERR() for errors.···185202static struct cfg80211_registered_device *186203cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)187204{188188- struct cfg80211_registered_device *rdev;189189-190190- mutex_lock(&cfg80211_mutex);191191- rdev = __cfg80211_rdev_from_attrs(netns, info->attrs);192192-193193- /* if it is not an error we grab the lock on194194- * it to assure it won't be going away while195195- * we operate on it */196196- if (!IS_ERR(rdev))197197- mutex_lock(&rdev->mtx);198198-199199- mutex_unlock(&cfg80211_mutex);200200-201201- return rdev;205205+ return __cfg80211_rdev_from_attrs(netns, info->attrs);202206}203207204208/* policy for the attributes */···348378 [NL80211_ATTR_MDID] = { .type = NLA_U16 },349379 [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,350380 .len = IEEE80211_MAX_DATA_LEN },381381+ [NL80211_ATTR_PEER_AID] = { .type = NLA_U16 },351382};352383353384/* policy for the key attributes */···426455 int err;427456428457 rtnl_lock();429429- mutex_lock(&cfg80211_mutex);430458431459 if (!cb->args[0]) {432460 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,···454484 *rdev = wiphy_to_dev(wiphy);455485 *wdev = NULL;456486457457- mutex_lock(&(*rdev)->devlist_mtx);458487 list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {459488 if (tmp->identifier == cb->args[1]) {460489 *wdev = tmp;461490 break;462491 }463492 }464464- mutex_unlock(&(*rdev)->devlist_mtx);465493466494 if (!*wdev) {467495 err = -ENODEV;···467499 }468500 }469501470470- cfg80211_lock_rdev(*rdev);471471-472472- mutex_unlock(&cfg80211_mutex);473502 return 0;474503 out_unlock:475475- mutex_unlock(&cfg80211_mutex);476504 rtnl_unlock();477505 return err;478506}479507480508static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)481509{482482- cfg80211_unlock_rdev(rdev);483510 rtnl_unlock();484511}485512···15301567 struct nlattr **tb = nl80211_fam.attrbuf;15311568 int res;1532156915331533- mutex_lock(&cfg80211_mutex);15701570+ rtnl_lock();15341571 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,15351572 tb, nl80211_fam.maxattr, nl80211_policy);15361573 if (res == 0) {···15441581 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);1545158215461583 netdev = dev_get_by_index(sock_net(skb->sk), ifidx);15471547- if (!netdev) {15481548- mutex_unlock(&cfg80211_mutex);15841584+ if (!netdev)15491585 return -ENODEV;15501550- }15511586 if (netdev->ieee80211_ptr) {15521587 dev = wiphy_to_dev(15531588 netdev->ieee80211_ptr->wiphy);···15891628 !skb->len &&15901629 cb->min_dump_alloc < 4096) {15911630 cb->min_dump_alloc = 4096;15921592- mutex_unlock(&cfg80211_mutex);15931631 return 1;15941632 }15951633 idx--;···15971637 } while (cb->args[1] > 0);15981638 break;15991639 }16001600- mutex_unlock(&cfg80211_mutex);16401640+ rtnl_unlock();1601164116021642 cb->args[0] = idx;16031643···17521792 if (result)17531793 return result;1754179417551755- mutex_lock(&rdev->devlist_mtx);17561795 switch (iftype) {17571796 case NL80211_IFTYPE_AP:17581797 case NL80211_IFTYPE_P2P_GO:···17751816 default:17761817 result = -EINVAL;17771818 }17781778- mutex_unlock(&rdev->devlist_mtx);1779181917801820 return result;17811821}···18231865 u32 frag_threshold = 0, rts_threshold = 0;18241866 u8 coverage_class = 0;1825186718681868+ ASSERT_RTNL();18691869+18261870 /*18271871 * Try to find the wiphy and netdev. Normally this18281872 * function shouldn't need the netdev, but this is···18341874 * also passed a netdev to set_wiphy, so that it is18351875 * possible to let that go to the right netdev!18361876 */18371837- mutex_lock(&cfg80211_mutex);1838187718391878 if (info->attrs[NL80211_ATTR_IFINDEX]) {18401879 int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);1841188018421881 netdev = dev_get_by_index(genl_info_net(info), ifindex);18431843- if (netdev && netdev->ieee80211_ptr) {18821882+ if (netdev && netdev->ieee80211_ptr)18441883 rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy);18451845- mutex_lock(&rdev->mtx);18461846- } else18841884+ else18471885 netdev = NULL;18481886 }1849188718501888 if (!netdev) {18511889 rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),18521890 info->attrs);18531853- if (IS_ERR(rdev)) {18541854- mutex_unlock(&cfg80211_mutex);18911891+ if (IS_ERR(rdev))18551892 return PTR_ERR(rdev);18561856- }18571893 wdev = NULL;18581894 netdev = NULL;18591895 result = 0;18601860-18611861- mutex_lock(&rdev->mtx);18621896 } else18631897 wdev = netdev->ieee80211_ptr;18641898···18641910 if (info->attrs[NL80211_ATTR_WIPHY_NAME])18651911 result = cfg80211_dev_rename(18661912 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));18671867-18681868- mutex_unlock(&cfg80211_mutex);1869191318701914 if (result)18711915 goto bad_res;···20712119 }2072212020732121 bad_res:20742074- mutex_unlock(&rdev->mtx);20752122 if (netdev)20762123 dev_put(netdev);20772124 return result;···21682217 struct cfg80211_registered_device *rdev;21692218 struct wireless_dev *wdev;2170221921712171- mutex_lock(&cfg80211_mutex);22202220+ rtnl_lock();21722221 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {21732222 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))21742223 continue;···21782227 }21792228 if_idx = 0;2180222921812181- mutex_lock(&rdev->devlist_mtx);21822230 list_for_each_entry(wdev, &rdev->wdev_list, list) {21832231 if (if_idx < if_start) {21842232 if_idx++;···21862236 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,21872237 cb->nlh->nlmsg_seq, NLM_F_MULTI,21882238 rdev, wdev) < 0) {21892189- mutex_unlock(&rdev->devlist_mtx);21902239 goto out;21912240 }21922241 if_idx++;21932242 }21942194- mutex_unlock(&rdev->devlist_mtx);2195224321962244 wp_idx++;21972245 }21982246 out:21992199- mutex_unlock(&cfg80211_mutex);22472247+ rtnl_unlock();2200224822012249 cb->args[0] = wp_idx;22022250 cb->args[1] = if_idx;···24272479 INIT_LIST_HEAD(&wdev->mgmt_registrations);24282480 spin_lock_init(&wdev->mgmt_registrations_lock);2429248124302430- mutex_lock(&rdev->devlist_mtx);24312482 wdev->identifier = ++rdev->wdev_id;24322483 list_add_rcu(&wdev->list, &rdev->wdev_list);24332484 rdev->devlist_generation++;24342434- mutex_unlock(&rdev->devlist_mtx);24352485 break;24362486 default:24372487 break;···29382992 struct wireless_dev *wdev;29392993 bool ret = false;2940299429412941- mutex_lock(&rdev->devlist_mtx);29422942-29432995 list_for_each_entry(wdev, &rdev->wdev_list, list) {29442996 if (wdev->iftype != NL80211_IFTYPE_AP &&29452997 wdev->iftype != NL80211_IFTYPE_P2P_GO)···29503006 ret = true;29513007 break;29523008 }29532953-29542954- mutex_unlock(&rdev->devlist_mtx);2955300929563010 return ret;29573011}···31123170 params.radar_required = true;31133171 }3114317231153115- mutex_lock(&rdev->devlist_mtx);31163173 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,31173174 params.chandef.chan,31183175 CHAN_MODE_SHARED,31193176 radar_detect_width);31203120- mutex_unlock(&rdev->devlist_mtx);31213121-31223177 if (err)31233178 return err;31243179···33153376 return true;33163377}3317337833793379+static bool nl80211_put_signal(struct sk_buff *msg, u8 mask, s8 *signal,33803380+ int id)33813381+{33823382+ void *attr;33833383+ int i = 0;33843384+33853385+ if (!mask)33863386+ return true;33873387+33883388+ attr = nla_nest_start(msg, id);33893389+ if (!attr)33903390+ return false;33913391+33923392+ for (i = 0; i < IEEE80211_MAX_CHAINS; i++) {33933393+ if (!(mask & BIT(i)))33943394+ continue;33953395+33963396+ if (nla_put_u8(msg, i, signal[i]))33973397+ return false;33983398+ }33993399+34003400+ nla_nest_end(msg, attr);34013401+34023402+ return true;34033403+}34043404+33183405static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,33193406 int flags,33203407 struct cfg80211_registered_device *rdev,···33763411 (u32)sinfo->rx_bytes))33773412 goto nla_put_failure;33783413 if ((sinfo->filled & (STATION_INFO_TX_BYTES |33793379- NL80211_STA_INFO_TX_BYTES64)) &&34143414+ STATION_INFO_TX_BYTES64)) &&33803415 nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,33813416 (u32)sinfo->tx_bytes))33823417 goto nla_put_failure;···34113446 break;34123447 default:34133448 break;34493449+ }34503450+ if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL) {34513451+ if (!nl80211_put_signal(msg, sinfo->chains,34523452+ sinfo->chain_signal,34533453+ NL80211_STA_INFO_CHAIN_SIGNAL))34543454+ goto nla_put_failure;34553455+ }34563456+ if (sinfo->filled & STATION_INFO_CHAIN_SIGNAL_AVG) {34573457+ if (!nl80211_put_signal(msg, sinfo->chains,34583458+ sinfo->chain_signal_avg,34593459+ NL80211_STA_INFO_CHAIN_SIGNAL_AVG))34603460+ goto nla_put_failure;34143461 }34153462 if (sinfo->filled & STATION_INFO_TX_BITRATE) {34163463 if (!nl80211_put_sta_rate(msg, &sinfo->txrate,···38113834 struct station_parameters *params)38123835{38133836 /* Dummy STA entry gets updated once the peer capabilities are known */38373837+ if (info->attrs[NL80211_ATTR_PEER_AID])38383838+ params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);38143839 if (info->attrs[NL80211_ATTR_HT_CAPABILITY])38153840 params->ht_capa =38163841 nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]);···39533974 if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES])39543975 return -EINVAL;3955397639563956- if (!info->attrs[NL80211_ATTR_STA_AID])39773977+ if (!info->attrs[NL80211_ATTR_STA_AID] &&39783978+ !info->attrs[NL80211_ATTR_PEER_AID])39573979 return -EINVAL;3958398039593981 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);···39653985 params.listen_interval =39663986 nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]);3967398739683968- params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);39883988+ if (info->attrs[NL80211_ATTR_STA_AID])39893989+ params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]);39903990+ else39913991+ params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]);39693992 if (!params.aid || params.aid > IEEE80211_MAX_AID)39703993 return -EINVAL;39713994···46174634 [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },46184635 [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },46194636 [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },46374637+ [NL80211_MESH_SETUP_AUTH_PROTOCOL] = { .type = NLA_U8 },46204638 [NL80211_MESH_SETUP_USERSPACE_MPM] = { .type = NLA_FLAG },46214639 [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY,46224640 .len = IEEE80211_MAX_DATA_LEN },···48034819 if (setup->is_secure)48044820 setup->user_mpm = true;4805482148224822+ if (tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]) {48234823+ if (!setup->user_mpm)48244824+ return -EINVAL;48254825+ setup->auth_id =48264826+ nla_get_u8(tb[NL80211_MESH_SETUP_AUTH_PROTOCOL]);48274827+ }48284828+48064829 return 0;48074830}48084831···48524861 void *hdr = NULL;48534862 struct nlattr *nl_reg_rules;48544863 unsigned int i;48554855- int err = -EINVAL;48564856-48574857- mutex_lock(&cfg80211_mutex);4858486448594865 if (!cfg80211_regdomain)48604860- goto out;48664866+ return -EINVAL;4861486748624868 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);48634863- if (!msg) {48644864- err = -ENOBUFS;48654865- goto out;48664866- }48694869+ if (!msg)48704870+ return -ENOBUFS;4867487148684872 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,48694873 NL80211_CMD_GET_REG);···49174931 nla_nest_end(msg, nl_reg_rules);4918493249194933 genlmsg_end(msg, hdr);49204920- err = genlmsg_reply(msg, info);49214921- goto out;49344934+ return genlmsg_reply(msg, info);4922493549234936nla_put_failure_rcu:49244937 rcu_read_unlock();···49254940 genlmsg_cancel(msg, hdr);49264941put_failure:49274942 nlmsg_free(msg);49284928- err = -EMSGSIZE;49294929-out:49304930- mutex_unlock(&cfg80211_mutex);49314931- return err;49434943+ return -EMSGSIZE;49324944}4933494549344946static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)···49915009 }49925010 }4993501149944994- mutex_lock(&cfg80211_mutex);49954995-49965012 r = set_regdom(rd);49975013 /* set_regdom took ownership */49985014 rd = NULL;49994999- mutex_unlock(&cfg80211_mutex);5000501550015016 bad_reg:50025017 kfree(rd);···50435064 if (!rdev->ops->scan)50445065 return -EOPNOTSUPP;5045506650465046- mutex_lock(&rdev->sched_scan_mtx);50475067 if (rdev->scan_req) {50485068 err = -EBUSY;50495069 goto unlock;···52285250 }5229525152305252 unlock:52315231- mutex_unlock(&rdev->sched_scan_mtx);52325253 return err;52335254}52345255···5298532152995322 if (ie_len > wiphy->max_sched_scan_ie_len)53005323 return -EINVAL;53015301-53025302- mutex_lock(&rdev->sched_scan_mtx);5303532453045325 if (rdev->sched_scan_req) {53055326 err = -EINPROGRESS;···54665491out_free:54675492 kfree(request);54685493out:54695469- mutex_unlock(&rdev->sched_scan_mtx);54705494 return err;54715495}54725496···54735499 struct genl_info *info)54745500{54755501 struct cfg80211_registered_device *rdev = info->user_ptr[0];54765476- int err;5477550254785503 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||54795504 !rdev->ops->sched_scan_stop)54805505 return -EOPNOTSUPP;5481550654825482- mutex_lock(&rdev->sched_scan_mtx);54835483- err = __cfg80211_stop_sched_scan(rdev, false);54845484- mutex_unlock(&rdev->sched_scan_mtx);54855485-54865486- return err;55075507+ return __cfg80211_stop_sched_scan(rdev, false);54875508}5488550954895510static int nl80211_start_radar_detection(struct sk_buff *skb,···55105541 if (!rdev->ops->start_radar_detection)55115542 return -EOPNOTSUPP;5512554355135513- mutex_lock(&rdev->devlist_mtx);55145544 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,55155545 chandef.chan, CHAN_MODE_SHARED,55165546 BIT(chandef.width));55175547 if (err)55185518- goto err_locked;55485548+ return err;5519554955205550 err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);55215551 if (!err) {···55225554 wdev->cac_started = true;55235555 wdev->cac_start_time = jiffies;55245556 }55255525-err_locked:55265526- mutex_unlock(&rdev->devlist_mtx);55275527-55285557 return err;55295558}55305559···59045939 if (local_state_change)59055940 return 0;5906594159075907- return cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,59085908- ssid, ssid_len, ie, ie_len,59095909- key.p.key, key.p.key_len, key.idx,59105910- sae_data, sae_data_len);59425942+ wdev_lock(dev->ieee80211_ptr);59435943+ err = cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,59445944+ ssid, ssid_len, ie, ie_len,59455945+ key.p.key, key.p.key_len, key.idx,59465946+ sae_data, sae_data_len);59475947+ wdev_unlock(dev->ieee80211_ptr);59485948+ return err;59115949}5912595059135951static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev,···60776109 }6078611060796111 err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);60806080- if (!err)61126112+ if (!err) {61136113+ wdev_lock(dev->ieee80211_ptr);60816114 err = cfg80211_mlme_assoc(rdev, dev, chan, bssid,60826115 ssid, ssid_len, &req);61166116+ wdev_unlock(dev->ieee80211_ptr);61176117+ }6083611860846119 return err;60856120}···60926121 struct cfg80211_registered_device *rdev = info->user_ptr[0];60936122 struct net_device *dev = info->user_ptr[1];60946123 const u8 *ie = NULL, *bssid;60956095- int ie_len = 0;61246124+ int ie_len = 0, err;60966125 u16 reason_code;60976126 bool local_state_change;60986127···6127615661286157 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];6129615861306130- return cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,61316131- local_state_change);61596159+ wdev_lock(dev->ieee80211_ptr);61606160+ err = cfg80211_mlme_deauth(rdev, dev, bssid, ie, ie_len, reason_code,61616161+ local_state_change);61626162+ wdev_unlock(dev->ieee80211_ptr);61636163+ return err;61326164}6133616561346166static int nl80211_disassociate(struct sk_buff *skb, struct genl_info *info)···61396165 struct cfg80211_registered_device *rdev = info->user_ptr[0];61406166 struct net_device *dev = info->user_ptr[1];61416167 const u8 *ie = NULL, *bssid;61426142- int ie_len = 0;61686168+ int ie_len = 0, err;61436169 u16 reason_code;61446170 bool local_state_change;61456171···6174620061756201 local_state_change = !!info->attrs[NL80211_ATTR_LOCAL_STATE_CHANGE];6176620261776177- return cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,61786178- local_state_change);62036203+ wdev_lock(dev->ieee80211_ptr);62046204+ err = cfg80211_mlme_disassoc(rdev, dev, bssid, ie, ie_len, reason_code,62056205+ local_state_change);62066206+ wdev_unlock(dev->ieee80211_ptr);62076207+ return err;61796208}6180620961816210static bool···63966419 void *data = NULL;63976420 int data_len = 0;6398642164226422+ rtnl_lock();64236423+63996424 if (cb->args[0]) {64006425 /*64016426 * 0 is a valid index, but not valid for args[0],···64096430 nl80211_fam.attrbuf, nl80211_fam.maxattr,64106431 nl80211_policy);64116432 if (err)64126412- return err;64336433+ goto out_err;6413643464146414- mutex_lock(&cfg80211_mutex);64156435 rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),64166436 nl80211_fam.attrbuf);64176437 if (IS_ERR(rdev)) {64186418- mutex_unlock(&cfg80211_mutex);64196419- return PTR_ERR(rdev);64386438+ err = PTR_ERR(rdev);64396439+ goto out_err;64206440 }64216441 phy_idx = rdev->wiphy_idx;64226442 rdev = NULL;64236423- mutex_unlock(&cfg80211_mutex);6424644364256444 if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])64266445 cb->args[1] =···64306453 data_len = nla_len((void *)cb->args[1]);64316454 }6432645564336433- mutex_lock(&cfg80211_mutex);64346456 rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);64356457 if (!rdev) {64366436- mutex_unlock(&cfg80211_mutex);64376437- return -ENOENT;64586458+ err = -ENOENT;64596459+ goto out_err;64386460 }64396439- cfg80211_lock_rdev(rdev);64406440- mutex_unlock(&cfg80211_mutex);6441646164426462 if (!rdev->ops->testmode_dump) {64436463 err = -EOPNOTSUPP;···64756501 /* see above */64766502 cb->args[0] = phy_idx + 1;64776503 out_err:64786478- cfg80211_unlock_rdev(rdev);65046504+ rtnl_unlock();64796505 return err;64806506}64816507···66836709 sizeof(connect.vht_capa));66846710 }6685671166866686- err = cfg80211_connect(rdev, dev, &connect, connkeys);67126712+ wdev_lock(dev->ieee80211_ptr);67136713+ err = cfg80211_connect(rdev, dev, &connect, connkeys, NULL);67146714+ wdev_unlock(dev->ieee80211_ptr);66876715 if (err)66886716 kfree(connkeys);66896717 return err;···66966720 struct cfg80211_registered_device *rdev = info->user_ptr[0];66976721 struct net_device *dev = info->user_ptr[1];66986722 u16 reason;67236723+ int ret;6699672467006725 if (!info->attrs[NL80211_ATTR_REASON_CODE])67016726 reason = WLAN_REASON_DEAUTH_LEAVING;···67106733 dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT)67116734 return -EOPNOTSUPP;6712673567136713- return cfg80211_disconnect(rdev, dev, reason, true);67366736+ wdev_lock(dev->ieee80211_ptr);67376737+ ret = cfg80211_disconnect(rdev, dev, reason, true);67386738+ wdev_unlock(dev->ieee80211_ptr);67396739+ return ret;67146740}6715674167166742static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)···74897509static int nl80211_send_wowlan_patterns(struct sk_buff *msg,74907510 struct cfg80211_registered_device *rdev)74917511{75127512+ struct cfg80211_wowlan *wowlan = rdev->wiphy.wowlan_config;74927513 struct nlattr *nl_pats, *nl_pat;74937514 int i, pat_len;7494751574957495- if (!rdev->wowlan->n_patterns)75167516+ if (!wowlan->n_patterns)74967517 return 0;7497751874987519 nl_pats = nla_nest_start(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN);74997520 if (!nl_pats)75007521 return -ENOBUFS;7501752275027502- for (i = 0; i < rdev->wowlan->n_patterns; i++) {75237523+ for (i = 0; i < wowlan->n_patterns; i++) {75037524 nl_pat = nla_nest_start(msg, i + 1);75047525 if (!nl_pat)75057526 return -ENOBUFS;75067506- pat_len = rdev->wowlan->patterns[i].pattern_len;75277527+ pat_len = wowlan->patterns[i].pattern_len;75077528 if (nla_put(msg, NL80211_WOWLAN_PKTPAT_MASK,75087529 DIV_ROUND_UP(pat_len, 8),75097509- rdev->wowlan->patterns[i].mask) ||75307530+ wowlan->patterns[i].mask) ||75107531 nla_put(msg, NL80211_WOWLAN_PKTPAT_PATTERN,75117511- pat_len, rdev->wowlan->patterns[i].pattern) ||75327532+ pat_len, wowlan->patterns[i].pattern) ||75127533 nla_put_u32(msg, NL80211_WOWLAN_PKTPAT_OFFSET,75137513- rdev->wowlan->patterns[i].pkt_offset))75347534+ wowlan->patterns[i].pkt_offset))75147535 return -ENOBUFS;75157536 nla_nest_end(msg, nl_pat);75167537 }···75587577 &tcp->payload_tok))75597578 return -ENOBUFS;7560757975807580+ nla_nest_end(msg, nl_tcp);75817581+75617582 return 0;75627583}75637584···75747591 !rdev->wiphy.wowlan.tcp)75757592 return -EOPNOTSUPP;7576759375777577- if (rdev->wowlan && rdev->wowlan->tcp) {75947594+ if (rdev->wiphy.wowlan_config && rdev->wiphy.wowlan_config->tcp) {75787595 /* adjust size to have room for all the data */75797579- size += rdev->wowlan->tcp->tokens_size +75807580- rdev->wowlan->tcp->payload_len +75817581- rdev->wowlan->tcp->wake_len +75827582- rdev->wowlan->tcp->wake_len / 8;75967596+ size += rdev->wiphy.wowlan_config->tcp->tokens_size +75977597+ rdev->wiphy.wowlan_config->tcp->payload_len +75987598+ rdev->wiphy.wowlan_config->tcp->wake_len +75997599+ rdev->wiphy.wowlan_config->tcp->wake_len / 8;75837600 }7584760175857602 msg = nlmsg_new(size, GFP_KERNEL);···75917608 if (!hdr)75927609 goto nla_put_failure;7593761075947594- if (rdev->wowlan) {76117611+ if (rdev->wiphy.wowlan_config) {75957612 struct nlattr *nl_wowlan;7596761375977614 nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS);75987615 if (!nl_wowlan)75997616 goto nla_put_failure;7600761776017601- if ((rdev->wowlan->any &&76187618+ if ((rdev->wiphy.wowlan_config->any &&76027619 nla_put_flag(msg, NL80211_WOWLAN_TRIG_ANY)) ||76037603- (rdev->wowlan->disconnect &&76207620+ (rdev->wiphy.wowlan_config->disconnect &&76047621 nla_put_flag(msg, NL80211_WOWLAN_TRIG_DISCONNECT)) ||76057605- (rdev->wowlan->magic_pkt &&76227622+ (rdev->wiphy.wowlan_config->magic_pkt &&76067623 nla_put_flag(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT)) ||76077607- (rdev->wowlan->gtk_rekey_failure &&76247624+ (rdev->wiphy.wowlan_config->gtk_rekey_failure &&76087625 nla_put_flag(msg, NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE)) ||76097609- (rdev->wowlan->eap_identity_req &&76267626+ (rdev->wiphy.wowlan_config->eap_identity_req &&76107627 nla_put_flag(msg, NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST)) ||76117611- (rdev->wowlan->four_way_handshake &&76287628+ (rdev->wiphy.wowlan_config->four_way_handshake &&76127629 nla_put_flag(msg, NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE)) ||76137613- (rdev->wowlan->rfkill_release &&76307630+ (rdev->wiphy.wowlan_config->rfkill_release &&76147631 nla_put_flag(msg, NL80211_WOWLAN_TRIG_RFKILL_RELEASE)))76157632 goto nla_put_failure;7616763376177634 if (nl80211_send_wowlan_patterns(msg, rdev))76187635 goto nla_put_failure;7619763676207620- if (nl80211_send_wowlan_tcp(msg, rdev->wowlan->tcp))76377637+ if (nl80211_send_wowlan_tcp(msg,76387638+ rdev->wiphy.wowlan_config->tcp))76217639 goto nla_put_failure;7622764076237641 nla_nest_end(msg, nl_wowlan);···77857801 struct cfg80211_wowlan *ntrig;77867802 struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan;77877803 int err, i;77887788- bool prev_enabled = rdev->wowlan;78047804+ bool prev_enabled = rdev->wiphy.wowlan_config;7789780577907806 if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns &&77917807 !rdev->wiphy.wowlan.tcp)···7793780977947810 if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) {77957811 cfg80211_rdev_free_wowlan(rdev);77967796- rdev->wowlan = NULL;78127812+ rdev->wiphy.wowlan_config = NULL;77977813 goto set_wakeup;77987814 }77997815···79297945 goto error;79307946 }79317947 cfg80211_rdev_free_wowlan(rdev);79327932- rdev->wowlan = ntrig;79487948+ rdev->wiphy.wowlan_config = ntrig;7933794979347950 set_wakeup:79357935- if (rdev->ops->set_wakeup && prev_enabled != !!rdev->wowlan)79367936- rdev_set_wakeup(rdev, rdev->wowlan);79517951+ if (rdev->ops->set_wakeup &&79527952+ prev_enabled != !!rdev->wiphy.wowlan_config)79537953+ rdev_set_wakeup(rdev, rdev->wiphy.wowlan_config);7937795479387955 return 0;79397956 error:···81198134 if (wdev->p2p_started)81208135 return 0;8121813681228122- mutex_lock(&rdev->devlist_mtx);81238137 err = cfg80211_can_add_interface(rdev, wdev->iftype);81248124- mutex_unlock(&rdev->devlist_mtx);81258138 if (err)81268139 return err;81278140···81288145 return err;8129814681308147 wdev->p2p_started = true;81318131- mutex_lock(&rdev->devlist_mtx);81328148 rdev->opencount++;81338133- mutex_unlock(&rdev->devlist_mtx);8134814981358150 return 0;81368151}···81448163 if (!rdev->ops->stop_p2p_device)81458164 return -EOPNOTSUPP;8146816581478147- mutex_lock(&rdev->devlist_mtx);81488148- mutex_lock(&rdev->sched_scan_mtx);81498166 cfg80211_stop_p2p_device(rdev, wdev);81508150- mutex_unlock(&rdev->sched_scan_mtx);81518151- mutex_unlock(&rdev->devlist_mtx);8152816781538168 return 0;81548169}···82878310 info->user_ptr[0] = rdev;82888311 } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||82898312 ops->internal_flags & NL80211_FLAG_NEED_WDEV) {82908290- mutex_lock(&cfg80211_mutex);83138313+ ASSERT_RTNL();83148314+82918315 wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),82928316 info->attrs);82938317 if (IS_ERR(wdev)) {82948294- mutex_unlock(&cfg80211_mutex);82958318 if (rtnl)82968319 rtnl_unlock();82978320 return PTR_ERR(wdev);···8302832583038326 if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {83048327 if (!dev) {83058305- mutex_unlock(&cfg80211_mutex);83068328 if (rtnl)83078329 rtnl_unlock();83088330 return -EINVAL;···83158339 if (dev) {83168340 if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&83178341 !netif_running(dev)) {83188318- mutex_unlock(&cfg80211_mutex);83198342 if (rtnl)83208343 rtnl_unlock();83218344 return -ENETDOWN;···83238348 dev_hold(dev);83248349 } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {83258350 if (!wdev->p2p_started) {83268326- mutex_unlock(&cfg80211_mutex);83278351 if (rtnl)83288352 rtnl_unlock();83298353 return -ENETDOWN;83308354 }83318355 }83328332-83338333- cfg80211_lock_rdev(rdev);83348334-83358335- mutex_unlock(&cfg80211_mutex);8336835683378357 info->user_ptr[0] = rdev;83388358 }···83388368static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,83398369 struct genl_info *info)83408370{83418341- if (info->user_ptr[0])83428342- cfg80211_unlock_rdev(info->user_ptr[0]);83438371 if (info->user_ptr[1]) {83448372 if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {83458373 struct wireless_dev *wdev = info->user_ptr[1];···83598391 .dumpit = nl80211_dump_wiphy,83608392 .policy = nl80211_policy,83618393 /* can be retrieved by unprivileged users */83628362- .internal_flags = NL80211_FLAG_NEED_WIPHY,83948394+ .internal_flags = NL80211_FLAG_NEED_WIPHY |83958395+ NL80211_FLAG_NEED_RTNL,83638396 },83648397 {83658398 .cmd = NL80211_CMD_SET_WIPHY,···83758406 .dumpit = nl80211_dump_interface,83768407 .policy = nl80211_policy,83778408 /* can be retrieved by unprivileged users */83788378- .internal_flags = NL80211_FLAG_NEED_WDEV,84098409+ .internal_flags = NL80211_FLAG_NEED_WDEV |84108410+ NL80211_FLAG_NEED_RTNL,83798411 },83808412 {83818413 .cmd = NL80211_CMD_SET_INTERFACE,···85358565 .cmd = NL80211_CMD_GET_REG,85368566 .doit = nl80211_get_reg,85378567 .policy = nl80211_policy,85688568+ .internal_flags = NL80211_FLAG_NEED_RTNL,85388569 /* can be retrieved by unprivileged users */85398570 },85408571 {···85438572 .doit = nl80211_set_reg,85448573 .policy = nl80211_policy,85458574 .flags = GENL_ADMIN_PERM,85758575+ .internal_flags = NL80211_FLAG_NEED_RTNL,85468576 },85478577 {85488578 .cmd = NL80211_CMD_REQ_SET_REG,···89989026 struct cfg80211_scan_request *req = rdev->scan_req;89999027 struct nlattr *nest;90009028 int i;90019001-90029002- lockdep_assert_held(&rdev->sched_scan_mtx);9003902990049030 if (WARN_ON(!req))90059031 return 0;···99409970 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||99419971 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,99429972 netdev->ifindex)) ||99739973+ nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||99439974 nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) ||99449975 (sig_dbm &&99459976 nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) ||···998110010 if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||998210011 (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX,998310012 netdev->ifindex)) ||1001310013+ nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) ||998410014 nla_put(msg, NL80211_ATTR_FRAME, len, buf) ||998510015 nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) ||998610016 (ack && nla_put_flag(msg, NL80211_ATTR_ACK)))
+44-92
net/wireless/reg.c
···8181 .country_ie_env = ENVIRON_ANY,8282};83838484-/* Receipt of information from last regulatory request */8484+/*8585+ * Receipt of information from last regulatory request,8686+ * protected by RTNL (and can be accessed with RCU protection)8787+ */8588static struct regulatory_request __rcu *last_request =8689 (void __rcu *)&core_request_world;8790···9996 * Central wireless core regulatory domains, we only need two,10097 * the current one and a world regulatory domain in case we have no10198 * information to give us an alpha2.9999+ * (protected by RTNL, can be read under RCU)102100 */103101const struct ieee80211_regdomain __rcu *cfg80211_regdomain;104102105103/*106106- * Protects static reg.c components:107107- * - cfg80211_regdomain (if not used with RCU)108108- * - cfg80211_world_regdom109109- * - last_request (if not used with RCU)110110- * - reg_num_devs_support_basehint111111- */112112-static DEFINE_MUTEX(reg_mutex);113113-114114-/*115104 * Number of devices that registered to the core116105 * that support cellular base station regulatory hints106106+ * (protected by RTNL)117107 */118108static int reg_num_devs_support_basehint;119109120120-static inline void assert_reg_lock(void)121121-{122122- lockdep_assert_held(®_mutex);123123-}124124-125110static const struct ieee80211_regdomain *get_cfg80211_regdom(void)126111{127127- return rcu_dereference_protected(cfg80211_regdomain,128128- lockdep_is_held(®_mutex));112112+ return rtnl_dereference(cfg80211_regdomain);129113}130114131115static const struct ieee80211_regdomain *get_wiphy_regdom(struct wiphy *wiphy)132116{133133- return rcu_dereference_protected(wiphy->regd,134134- lockdep_is_held(®_mutex));117117+ return rtnl_dereference(wiphy->regd);135118}136119137120static void rcu_free_regdom(const struct ieee80211_regdomain *r)···129140130141static struct regulatory_request *get_last_request(void)131142{132132- return rcu_dereference_check(last_request,133133- lockdep_is_held(®_mutex));143143+ return rcu_dereference_rtnl(last_request);134144}135145136146/* Used to queue up regulatory hints */···188200 }189201};190202203203+/* protected by RTNL */191204static const struct ieee80211_regdomain *cfg80211_world_regdom =192205 &world_regdom;193206···204215 const struct ieee80211_regdomain *r;205216 struct regulatory_request *lr;206217207207- assert_reg_lock();218218+ ASSERT_RTNL();208219209220 r = get_cfg80211_regdom();210221···366377 const struct ieee80211_regdomain *curdom, *regdom = NULL;367378 int i;368379369369- mutex_lock(&cfg80211_mutex);380380+ rtnl_lock();370381371382 mutex_lock(®_regdb_search_mutex);372383 while (!list_empty(®_regdb_search_list)) {···391402 if (!IS_ERR_OR_NULL(regdom))392403 set_regdom(regdom);393404394394- mutex_unlock(&cfg80211_mutex);405405+ rtnl_unlock();395406}396407397408static DECLARE_WORK(reg_regdb_work, reg_regdb_search);···925936926937bool reg_last_request_cell_base(void)927938{928928- bool val;929929-930930- mutex_lock(®_mutex);931931- val = reg_request_cell_base(get_last_request());932932- mutex_unlock(®_mutex);933933-934934- return val;939939+ return reg_request_cell_base(get_last_request());935940}936941937942#ifdef CONFIG_CFG80211_CERTIFICATION_ONUS···12081225 struct cfg80211_registered_device *rdev;12091226 struct wiphy *wiphy;1210122712111211- assert_cfg80211_lock();12281228+ ASSERT_RTNL();1212122912131230 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {12141231 wiphy = &rdev->wiphy;···14271444 * what it believes should be the current regulatory domain.14281445 *14291446 * Returns one of the different reg request treatment values.14301430- *14311431- * Caller must hold ®_mutex14321447 */14331448static enum reg_request_treatment14341449__regulatory_hint(struct wiphy *wiphy,···15511570{15521571 struct regulatory_request *reg_request, *lr;1553157215541554- mutex_lock(&cfg80211_mutex);15551555- mutex_lock(®_mutex);15561573 lr = get_last_request();1557157415581575 /* When last_request->processed becomes true this will be rescheduled */15591576 if (lr && !lr->processed) {15601577 REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n");15611561- goto out;15781578+ return;15621579 }1563158015641581 spin_lock(®_requests_lock);1565158215661583 if (list_empty(®_requests_list)) {15671584 spin_unlock(®_requests_lock);15681568- goto out;15851585+ return;15691586 }1570158715711588 reg_request = list_first_entry(®_requests_list,···15741595 spin_unlock(®_requests_lock);1575159615761597 reg_process_hint(reg_request, reg_request->initiator);15771577-15781578-out:15791579- mutex_unlock(®_mutex);15801580- mutex_unlock(&cfg80211_mutex);15811598}1582159915831600/* Processes beacon hints -- this has nothing to do with country IEs */···15811606{15821607 struct cfg80211_registered_device *rdev;15831608 struct reg_beacon *pending_beacon, *tmp;15841584-15851585- mutex_lock(&cfg80211_mutex);15861586- mutex_lock(®_mutex);1587160915881610 /* This goes through the _pending_ beacon list */15891611 spin_lock_bh(®_pending_beacons_lock);···15981626 }1599162716001628 spin_unlock_bh(®_pending_beacons_lock);16011601- mutex_unlock(®_mutex);16021602- mutex_unlock(&cfg80211_mutex);16031629}1604163016051631static void reg_todo(struct work_struct *work)16061632{16331633+ rtnl_lock();16071634 reg_process_pending_hints();16081635 reg_process_pending_beacon_hints();16361636+ rtnl_unlock();16091637}1610163816111639static void queue_regulatory_request(struct regulatory_request *request)···16891717}16901718EXPORT_SYMBOL(regulatory_hint);1691171916921692-/*16931693- * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and16941694- * therefore cannot iterate over the rdev list here.16951695- */16961720void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,16971721 const u8 *country_ie, u8 country_ie_len)16981722{16991723 char alpha2[2];17001724 enum environment_cap env = ENVIRON_ANY;17011701- struct regulatory_request *request, *lr;17021702-17031703- mutex_lock(®_mutex);17041704- lr = get_last_request();17051705-17061706- if (unlikely(!lr))17071707- goto out;17251725+ struct regulatory_request *request = NULL, *lr;1708172617091727 /* IE len must be evenly divisible by 2 */17101728 if (country_ie_len & 0x01)17111711- goto out;17291729+ return;1712173017131731 if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)17141714- goto out;17321732+ return;17331733+17341734+ request = kzalloc(sizeof(*request), GFP_KERNEL);17351735+ if (!request)17361736+ return;1715173717161738 alpha2[0] = country_ie[0];17171739 alpha2[1] = country_ie[1];···17151749 else if (country_ie[2] == 'O')17161750 env = ENVIRON_OUTDOOR;1717175117521752+ rcu_read_lock();17531753+ lr = get_last_request();17541754+17551755+ if (unlikely(!lr))17561756+ goto out;17571757+17181758 /*17191759 * We will run this only upon a successful connection on cfg80211.17201760 * We leave conflict resolution to the workqueue, where can hold17211721- * cfg80211_mutex.17611761+ * the RTNL.17221762 */17231763 if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&17241764 lr->wiphy_idx != WIPHY_IDX_INVALID)17251725- goto out;17261726-17271727- request = kzalloc(sizeof(struct regulatory_request), GFP_KERNEL);17281728- if (!request)17291765 goto out;1730176617311767 request->wiphy_idx = get_wiphy_idx(wiphy);···17371769 request->country_ie_env = env;1738177017391771 queue_regulatory_request(request);17721772+ request = NULL;17401773out:17411741- mutex_unlock(®_mutex);17741774+ kfree(request);17751775+ rcu_read_unlock();17421776}1743177717441778static void restore_alpha2(char *alpha2, bool reset_user)···18281858 LIST_HEAD(tmp_reg_req_list);18291859 struct cfg80211_registered_device *rdev;1830186018311831- mutex_lock(&cfg80211_mutex);18321832- mutex_lock(®_mutex);18611861+ ASSERT_RTNL();1833186218341863 reset_regdomains(true, &world_regdom);18351864 restore_alpha2(alpha2, reset_user);···18821913 spin_lock(®_requests_lock);18831914 list_splice_tail_init(&tmp_reg_req_list, ®_requests_list);18841915 spin_unlock(®_requests_lock);18851885-18861886- mutex_unlock(®_mutex);18871887- mutex_unlock(&cfg80211_mutex);1888191618891917 REG_DBG_PRINT("Kicking the queue\n");18901918···21972231 struct regulatory_request *lr;21982232 int r;2199223322002200- mutex_lock(®_mutex);22012234 lr = get_last_request();2202223522032236 /* Note that this doesn't update the wiphys, this is done below */···22062241 reg_set_request_processed();2207224222082243 kfree(rd);22092209- goto out;22442244+ return r;22102245 }2211224622122247 /* This would make this whole thing pointless */22132213- if (WARN_ON(!lr->intersect && rd != get_cfg80211_regdom())) {22142214- r = -EINVAL;22152215- goto out;22162216- }22482248+ if (WARN_ON(!lr->intersect && rd != get_cfg80211_regdom()))22492249+ return -EINVAL;2217225022182251 /* update all wiphys now with the new established regulatory domain */22192252 update_all_wiphy_regulatory(lr->initiator);···2222225922232260 reg_set_request_processed();2224226122252225- out:22262226- mutex_unlock(®_mutex);22272227-22282228- return r;22622262+ return 0;22292263}2230226422312265int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env)···2247228722482288void wiphy_regulatory_register(struct wiphy *wiphy)22492289{22502250- mutex_lock(®_mutex);22512251-22522290 if (!reg_dev_ignore_cell_hint(wiphy))22532291 reg_num_devs_support_basehint++;2254229222552293 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);22562256-22572257- mutex_unlock(®_mutex);22582294}2259229522602260-/* Caller must hold cfg80211_mutex */22612296void wiphy_regulatory_deregister(struct wiphy *wiphy)22622297{22632298 struct wiphy *request_wiphy = NULL;22642299 struct regulatory_request *lr;2265230022662266- mutex_lock(®_mutex);22672301 lr = get_last_request();2268230222692303 if (!reg_dev_ignore_cell_hint(wiphy))···22702316 request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx);2271231722722318 if (!request_wiphy || request_wiphy != wiphy)22732273- goto out;23192319+ return;2274232022752321 lr->wiphy_idx = WIPHY_IDX_INVALID;22762322 lr->country_ie_env = ENVIRON_ANY;22772277-out:22782278- mutex_unlock(®_mutex);22792323}2280232422812325static void reg_timeout_work(struct work_struct *work)···23372385 cancel_delayed_work_sync(®_timeout);2338238623392387 /* Lock to suppress warnings */23402340- mutex_lock(®_mutex);23882388+ rtnl_lock();23412389 reset_regdomains(true, NULL);23422342- mutex_unlock(®_mutex);23902390+ rtnl_unlock();2343239123442392 dev_set_uevent_suppress(®_pdev->dev, true);23452393
+30-17
net/wireless/scan.c
···169169 union iwreq_data wrqu;170170#endif171171172172- lockdep_assert_held(&rdev->sched_scan_mtx);172172+ ASSERT_RTNL();173173174174 request = rdev->scan_req;175175···230230 rdev = container_of(wk, struct cfg80211_registered_device,231231 scan_done_wk);232232233233- mutex_lock(&rdev->sched_scan_mtx);233233+ rtnl_lock();234234 ___cfg80211_scan_done(rdev, false);235235- mutex_unlock(&rdev->sched_scan_mtx);235235+ rtnl_unlock();236236}237237238238void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)···241241 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);242242243243 request->aborted = aborted;244244+ request->notified = true;244245 queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk);245246}246247EXPORT_SYMBOL(cfg80211_scan_done);···256255257256 request = rdev->sched_scan_req;258257259259- mutex_lock(&rdev->sched_scan_mtx);258258+ rtnl_lock();260259261260 /* we don't have sched_scan_req anymore if the scan is stopping */262261 if (request) {···271270 nl80211_send_sched_scan_results(rdev, request->dev);272271 }273272274274- mutex_unlock(&rdev->sched_scan_mtx);273273+ rtnl_unlock();275274}276275277276void cfg80211_sched_scan_results(struct wiphy *wiphy)···290289291290 trace_cfg80211_sched_scan_stopped(wiphy);292291293293- mutex_lock(&rdev->sched_scan_mtx);292292+ rtnl_lock();294293 __cfg80211_stop_sched_scan(rdev, true);295295- mutex_unlock(&rdev->sched_scan_mtx);294294+ rtnl_unlock();296295}297296EXPORT_SYMBOL(cfg80211_sched_scan_stopped);298297···301300{302301 struct net_device *dev;303302304304- lockdep_assert_held(&rdev->sched_scan_mtx);303303+ ASSERT_RTNL();305304306305 if (!rdev->sched_scan_req)307306 return -ENOENT;···10411040EXPORT_SYMBOL(cfg80211_unlink_bss);1042104110431042#ifdef CONFIG_CFG80211_WEXT10431043+static struct cfg80211_registered_device *10441044+cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)10451045+{10461046+ struct cfg80211_registered_device *rdev;10471047+ struct net_device *dev;10481048+10491049+ ASSERT_RTNL();10501050+10511051+ dev = dev_get_by_index(net, ifindex);10521052+ if (!dev)10531053+ return ERR_PTR(-ENODEV);10541054+ if (dev->ieee80211_ptr)10551055+ rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);10561056+ else10571057+ rdev = ERR_PTR(-ENODEV);10581058+ dev_put(dev);10591059+ return rdev;10601060+}10611061+10441062int cfg80211_wext_siwscan(struct net_device *dev,10451063 struct iw_request_info *info,10461064 union iwreq_data *wrqu, char *extra)···10821062 if (IS_ERR(rdev))10831063 return PTR_ERR(rdev);1084106410851085- mutex_lock(&rdev->sched_scan_mtx);10861065 if (rdev->scan_req) {10871066 err = -EBUSY;10881067 goto out;···11881169 dev_hold(dev);11891170 }11901171 out:11911191- mutex_unlock(&rdev->sched_scan_mtx);11921172 kfree(creq);11931193- cfg80211_unlock_rdev(rdev);11941173 return err;11951174}11961175EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);···14871470 if (IS_ERR(rdev))14881471 return PTR_ERR(rdev);1489147214901490- if (rdev->scan_req) {14911491- res = -EAGAIN;14921492- goto out;14931493- }14731473+ if (rdev->scan_req)14741474+ return -EAGAIN;1494147514951476 res = ieee80211_scan_results(rdev, info, extra, data->length);14961477 data->length = 0;···14971482 res = 0;14981483 }1499148415001500- out:15011501- cfg80211_unlock_rdev(rdev);15021485 return res;15031486}15041487EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);