Skip to content

Commit

Permalink
cfg80211/mac80211: use cfg80211 wdev mutex in mac80211
Browse files Browse the repository at this point in the history
Using separate locks in cfg80211 and mac80211 has always
caused issues, for example having to unlock in places in
mac80211 to call cfg80211, which even needed a framework
to make cfg80211 calls after some functions returned etc.

Additionally, I suspect some issues people have reported
with the cfg80211 state getting confused could be due to
such issues, when cfg80211 is asking mac80211 to change
state but mac80211 is in the process of telling cfg80211
that the state changed (in another way.)

Signed-off-by: Johannes Berg <[email protected]>
  • Loading branch information
jmberg-intel committed May 24, 2013
1 parent 5fe231e commit 8d61ffa
Show file tree
Hide file tree
Showing 14 changed files with 220 additions and 355 deletions.
2 changes: 0 additions & 2 deletions Documentation/DocBook/80211.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,7 @@
!Finclude/net/cfg80211.h cfg80211_send_rx_assoc
!Finclude/net/cfg80211.h cfg80211_send_assoc_timeout
!Finclude/net/cfg80211.h cfg80211_send_deauth
!Finclude/net/cfg80211.h __cfg80211_send_deauth
!Finclude/net/cfg80211.h cfg80211_send_disassoc
!Finclude/net/cfg80211.h __cfg80211_send_disassoc
!Finclude/net/cfg80211.h cfg80211_ibss_joined
!Finclude/net/cfg80211.h cfg80211_connect_result
!Finclude/net/cfg80211.h cfg80211_roamed
Expand Down
51 changes: 23 additions & 28 deletions include/net/cfg80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -1867,7 +1867,9 @@ struct cfg80211_update_ft_ies_params {
* @get_mpath: get a mesh path for the given parameters
* @dump_mpath: dump mesh path callback -- resume dump at index @idx
* @join_mesh: join the mesh network with the specified parameters
* (invoked with the wireless_dev mutex held)
* @leave_mesh: leave the current mesh network
* (invoked with the wireless_dev mutex held)
*
* @get_mesh_config: Get the current mesh configuration
*
Expand All @@ -1894,20 +1896,28 @@ struct cfg80211_update_ft_ies_params {
* the scan/scan_done bracket too.
*
* @auth: Request to authenticate with the specified peer
* (invoked with the wireless_dev mutex held)
* @assoc: Request to (re)associate with the specified peer
* (invoked with the wireless_dev mutex held)
* @deauth: Request to deauthenticate from the specified peer
* (invoked with the wireless_dev mutex held)
* @disassoc: Request to disassociate from the specified peer
* (invoked with the wireless_dev mutex held)
*
* @connect: Connect to the ESS with the specified parameters. When connected,
* call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS.
* If the connection fails for some reason, call cfg80211_connect_result()
* with the status from the AP.
* (invoked with the wireless_dev mutex held)
* @disconnect: Disconnect from the BSS/ESS.
* (invoked with the wireless_dev mutex held)
*
* @join_ibss: Join the specified IBSS (or create if necessary). Once done, call
* cfg80211_ibss_joined(), also call that function when changing BSSID due
* to a merge.
* (invoked with the wireless_dev mutex held)
* @leave_ibss: Leave the IBSS.
* (invoked with the wireless_dev mutex held)
*
* @set_mcast_rate: Set the specified multicast rate (only if vif is in ADHOC or
* MESH mode)
Expand Down Expand Up @@ -2851,7 +2861,8 @@ struct cfg80211_cached_keys;
* by cfg80211 on change_interface
* @mgmt_registrations: list of registrations for management frames
* @mgmt_registrations_lock: lock for the list
* @mtx: mutex used to lock data in this struct
* @mtx: mutex used to lock data in this struct, may be used by drivers
* and some API functions require it held
* @cleanup_work: work struct used for cleanup that can't be done directly
* @beacon_interval: beacon interval used on this device for transmitting
* beacons, 0 when not valid
Expand Down Expand Up @@ -3424,7 +3435,8 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss);
* This function is called whenever an authentication has been processed in
* station mode. The driver is required to call either this function or
* cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth()
* call. This function may sleep.
* call. This function may sleep. The caller must hold the corresponding wdev's
* mutex.
*/
void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);

Expand All @@ -3433,7 +3445,8 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
* @dev: network device
* @addr: The MAC address of the device with which the authentication timed out
*
* This function may sleep.
* This function may sleep. The caller must hold the corresponding wdev's
* mutex.
*/
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);

Expand All @@ -3448,7 +3461,8 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
* This function is called whenever a (re)association response has been
* processed in station mode. The driver is required to call either this
* function or cfg80211_send_assoc_timeout() to indicate the result of
* cfg80211_ops::assoc() call. This function may sleep.
* cfg80211_ops::assoc() call. This function may sleep. The caller must hold
* the corresponding wdev's mutex.
*/
void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
const u8 *buf, size_t len);
Expand All @@ -3458,7 +3472,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
* @dev: network device
* @addr: The MAC address of the device with which the association timed out
*
* This function may sleep.
* This function may sleep. The caller must hold the corresponding wdev's mutex.
*/
void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);

Expand All @@ -3470,20 +3484,11 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
*
* This function is called whenever deauthentication has been processed in
* station mode. This includes both received deauthentication frames and
* locally generated ones. This function may sleep.
* locally generated ones. This function may sleep. The caller must hold the
* corresponding wdev's mutex.
*/
void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);

/**
* __cfg80211_send_deauth - notification of processed deauthentication
* @dev: network device
* @buf: deauthentication frame (header + body)
* @len: length of the frame data
*
* Like cfg80211_send_deauth(), but doesn't take the wdev lock.
*/
void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);

/**
* cfg80211_send_disassoc - notification of processed disassociation
* @dev: network device
Expand All @@ -3492,21 +3497,11 @@ void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
*
* This function is called whenever disassociation has been processed in
* station mode. This includes both received disassociation frames and locally
* generated ones. This function may sleep.
* generated ones. This function may sleep. The caller must hold the
* corresponding wdev's mutex.
*/
void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len);

/**
* __cfg80211_send_disassoc - notification of processed disassociation
* @dev: network device
* @buf: disassociation response frame (header + body)
* @len: length of the frame data
*
* Like cfg80211_send_disassoc(), but doesn't take the wdev lock.
*/
void __cfg80211_send_disassoc(struct net_device *dev, const u8 *buf,
size_t len);

/**
* cfg80211_send_unprot_deauth - notification of unprotected deauthentication
* @dev: network device
Expand Down
4 changes: 1 addition & 3 deletions net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -2318,7 +2318,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
enum ieee80211_smps_mode old_req;
int err;

lockdep_assert_held(&sdata->u.mgd.mtx);
lockdep_assert_held(&sdata->wdev.mtx);

old_req = sdata->u.mgd.req_smps;
sdata->u.mgd.req_smps = smps_mode;
Expand Down Expand Up @@ -2375,9 +2375,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
local->dynamic_ps_forced_timeout = timeout;

/* no change, but if automatic follow powersave */
mutex_lock(&sdata->u.mgd.mtx);
__ieee80211_request_smps(sdata, sdata->u.mgd.req_smps);
mutex_unlock(&sdata->u.mgd.mtx);

if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
Expand Down
10 changes: 5 additions & 5 deletions net/mac80211/debugfs_netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,9 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
if (sdata->vif.type != NL80211_IFTYPE_STATION)
return -EOPNOTSUPP;

mutex_lock(&sdata->u.mgd.mtx);
sdata_lock(sdata);
err = __ieee80211_request_smps(sdata, smps_mode);
mutex_unlock(&sdata->u.mgd.mtx);
sdata_unlock(sdata);

return err;
}
Expand Down Expand Up @@ -313,16 +313,16 @@ static ssize_t ieee80211_if_parse_tkip_mic_test(
case NL80211_IFTYPE_STATION:
fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
/* BSSID SA DA */
mutex_lock(&sdata->u.mgd.mtx);
sdata_lock(sdata);
if (!sdata->u.mgd.associated) {
mutex_unlock(&sdata->u.mgd.mtx);
sdata_unlock(sdata);
dev_kfree_skb(skb);
return -ENOTCONN;
}
memcpy(hdr->addr1, sdata->u.mgd.associated->bssid, ETH_ALEN);
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
memcpy(hdr->addr3, addr, ETH_ALEN);
mutex_unlock(&sdata->u.mgd.mtx);
sdata_unlock(sdata);
break;
default:
dev_kfree_skb(skb);
Expand Down
4 changes: 2 additions & 2 deletions net/mac80211/ht.c
Original file line number Diff line number Diff line change
Expand Up @@ -429,9 +429,9 @@ void ieee80211_request_smps_work(struct work_struct *work)
container_of(work, struct ieee80211_sub_if_data,
u.mgd.request_smps_work);

mutex_lock(&sdata->u.mgd.mtx);
sdata_lock(sdata);
__ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode);
mutex_unlock(&sdata->u.mgd.mtx);
sdata_unlock(sdata);
}

void ieee80211_request_smps(struct ieee80211_vif *vif,
Expand Down
39 changes: 15 additions & 24 deletions net/mac80211/ibss.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
struct beacon_data *presp;
int frame_len;

lockdep_assert_held(&ifibss->mtx);
sdata_assert_lock(sdata);

/* Reset own TSF to allow time synchronization work. */
drv_reset_tsf(local, sdata);
Expand All @@ -74,7 +74,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
}

presp = rcu_dereference_protected(ifibss->presp,
lockdep_is_held(&ifibss->mtx));
lockdep_is_held(&sdata->wdev.mtx));
rcu_assign_pointer(ifibss->presp, NULL);
if (presp)
kfree_rcu(presp, rcu_head);
Expand Down Expand Up @@ -263,7 +263,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
const struct cfg80211_bss_ies *ies;
u64 tsf;

lockdep_assert_held(&sdata->u.ibss.mtx);
sdata_assert_lock(sdata);

if (beacon_int < 10)
beacon_int = 10;
Expand Down Expand Up @@ -410,7 +410,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta;
u8 deauth_frame_buf[IEEE80211_DEAUTH_FRAME_LEN];

lockdep_assert_held(&sdata->u.ibss.mtx);
sdata_assert_lock(sdata);

if (len < 24 + 6)
return;
Expand Down Expand Up @@ -677,7 +677,7 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
int active = 0;
struct sta_info *sta;

lockdep_assert_held(&sdata->u.ibss.mtx);
sdata_assert_lock(sdata);

rcu_read_lock();

Expand All @@ -703,7 +703,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;

lockdep_assert_held(&ifibss->mtx);
sdata_assert_lock(sdata);

mod_timer(&ifibss->timer,
round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
Expand Down Expand Up @@ -734,7 +734,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
u16 capability;
int i;

lockdep_assert_held(&ifibss->mtx);
sdata_assert_lock(sdata);

if (ifibss->fixed_bssid) {
memcpy(bssid, ifibss->bssid, ETH_ALEN);
Expand Down Expand Up @@ -777,7 +777,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
int active_ibss;
u16 capability;

lockdep_assert_held(&ifibss->mtx);
sdata_assert_lock(sdata);

active_ibss = ieee80211_sta_active_ibss(sdata);
ibss_dbg(sdata, "sta_find_ibss (active_ibss=%d)\n", active_ibss);
Expand Down Expand Up @@ -847,10 +847,10 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
struct beacon_data *presp;
u8 *pos, *end;

lockdep_assert_held(&ifibss->mtx);
sdata_assert_lock(sdata);

presp = rcu_dereference_protected(ifibss->presp,
lockdep_is_held(&ifibss->mtx));
lockdep_is_held(&sdata->wdev.mtx));

if (ifibss->state != IEEE80211_IBSS_MLME_JOINED ||
len < 24 + 2 || !presp)
Expand Down Expand Up @@ -934,7 +934,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
mgmt = (struct ieee80211_mgmt *) skb->data;
fc = le16_to_cpu(mgmt->frame_control);

mutex_lock(&sdata->u.ibss.mtx);
sdata_lock(sdata);

if (!sdata->u.ibss.ssid_len)
goto mgmt_out; /* not ready to merge yet */
Expand All @@ -957,15 +957,15 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
}

mgmt_out:
mutex_unlock(&sdata->u.ibss.mtx);
sdata_unlock(sdata);
}

void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct sta_info *sta;

mutex_lock(&ifibss->mtx);
sdata_lock(sdata);

/*
* Work could be scheduled after scan or similar
Expand Down Expand Up @@ -1001,7 +1001,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
}

out:
mutex_unlock(&ifibss->mtx);
sdata_unlock(sdata);
}

static void ieee80211_ibss_timer(unsigned long data)
Expand All @@ -1018,7 +1018,6 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)

setup_timer(&ifibss->timer, ieee80211_ibss_timer,
(unsigned long) sdata);
mutex_init(&ifibss->mtx);
INIT_LIST_HEAD(&ifibss->incomplete_stations);
spin_lock_init(&ifibss->incomplete_lock);
}
Expand All @@ -1045,8 +1044,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
{
u32 changed = 0;

mutex_lock(&sdata->u.ibss.mtx);

if (params->bssid) {
memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN);
sdata->u.ibss.fixed_bssid = true;
Expand Down Expand Up @@ -1079,8 +1076,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
sdata->u.ibss.ssid_len = params->ssid_len;

mutex_unlock(&sdata->u.ibss.mtx);

/*
* 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is
* reserved, but an HT STA shall protect HT transmissions as though
Expand Down Expand Up @@ -1116,8 +1111,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
struct sta_info *sta;
struct beacon_data *presp;

mutex_lock(&sdata->u.ibss.mtx);

active_ibss = ieee80211_sta_active_ibss(sdata);

if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
Expand Down Expand Up @@ -1161,7 +1154,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
/* remove beacon */
kfree(sdata->u.ibss.ie);
presp = rcu_dereference_protected(ifibss->presp,
lockdep_is_held(&sdata->u.ibss.mtx));
lockdep_is_held(&sdata->wdev.mtx));
RCU_INIT_POINTER(sdata->u.ibss.presp, NULL);
sdata->vif.bss_conf.ibss_joined = false;
sdata->vif.bss_conf.ibss_creator = false;
Expand All @@ -1177,7 +1170,5 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)

del_timer_sync(&sdata->u.ibss.timer);

mutex_unlock(&sdata->u.ibss.mtx);

return 0;
}
Loading

0 comments on commit 8d61ffa

Please sign in to comment.