Skip to content

Commit

Permalink
mac80211: sparse RCU annotations
Browse files Browse the repository at this point in the history
This adds sparse RCU annotations to most of
mac80211, only the mesh code remains to be
done.

Due the the previous patches, the annotations
are pretty simple. The only thing that this
actually changes is removing the RCU usage of
key->sta in debugfs since this pointer isn't
actually an RCU-managed pointer (it only has
a single assignment done before the key even
goes live). As that is otherwise harmless, I
decided to make it part of this patch.

Signed-off-by: Johannes Berg <[email protected]>
Signed-off-by: John W. Linville <[email protected]>
  • Loading branch information
jmberg-intel authored and linvjw committed May 16, 2011
1 parent ec034b2 commit 40b275b
Show file tree
Hide file tree
Showing 16 changed files with 118 additions and 74 deletions.
3 changes: 2 additions & 1 deletion net/mac80211/agg-rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,

lockdep_assert_held(&sta->ampdu_mlme.mtx);

tid_rx = sta->ampdu_mlme.tid_rx[tid];
tid_rx = rcu_dereference_protected(sta->ampdu_mlme.tid_rx[tid],
lockdep_is_held(&sta->ampdu_mlme.mtx));

if (!tid_rx)
return;
Expand Down
36 changes: 21 additions & 15 deletions net/mac80211/agg-tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,16 +157,19 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
bool tx)
{
struct ieee80211_local *local = sta->local;
struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid];
struct tid_ampdu_tx *tid_tx;
int ret;

lockdep_assert_held(&sta->ampdu_mlme.mtx);

if (!tid_tx)
return -ENOENT;

spin_lock_bh(&sta->lock);

tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
if (!tid_tx) {
spin_unlock_bh(&sta->lock);
return -ENOENT;
}

if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
/* not even started yet! */
ieee80211_assign_tid_tx(sta, tid, NULL);
Expand Down Expand Up @@ -291,13 +294,13 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid)

void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
{
struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid];
struct tid_ampdu_tx *tid_tx;
struct ieee80211_local *local = sta->local;
struct ieee80211_sub_if_data *sdata = sta->sdata;
u16 start_seq_num;
int ret;

lockdep_assert_held(&sta->ampdu_mlme.mtx);
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);

/*
* While we're asking the driver about the aggregation,
Expand Down Expand Up @@ -404,7 +407,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
goto err_unlock_sta;
}

tid_tx = sta->ampdu_mlme.tid_tx[tid];
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
/* check if the TID is not in aggregation flow already */
if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) {
#ifdef CONFIG_MAC80211_HT_DEBUG
Expand Down Expand Up @@ -491,30 +494,33 @@ ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid)
static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
struct sta_info *sta, u16 tid)
{
struct tid_ampdu_tx *tid_tx;

lockdep_assert_held(&sta->ampdu_mlme.mtx);

tid_tx = rcu_dereference_protected_tid_tx(sta, tid);

#ifdef CONFIG_MAC80211_HT_DEBUG
printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid);
#endif

drv_ampdu_action(local, sta->sdata,
IEEE80211_AMPDU_TX_OPERATIONAL,
&sta->sta, tid, NULL,
sta->ampdu_mlme.tid_tx[tid]->buf_size);
&sta->sta, tid, NULL, tid_tx->buf_size);

/*
* synchronize with TX path, while splicing the TX path
* should block so it won't put more packets onto pending.
*/
spin_lock_bh(&sta->lock);

ieee80211_agg_splice_packets(local, sta->ampdu_mlme.tid_tx[tid], tid);
ieee80211_agg_splice_packets(local, tid_tx, tid);
/*
* Now mark as operational. This will be visible
* in the TX path, and lets it go lock-free in
* the common case.
*/
set_bit(HT_AGG_STATE_OPERATIONAL, &sta->ampdu_mlme.tid_tx[tid]->state);
set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
ieee80211_agg_splice_finish(local, tid);

spin_unlock_bh(&sta->lock);
Expand Down Expand Up @@ -548,7 +554,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
}

mutex_lock(&sta->ampdu_mlme.mtx);
tid_tx = sta->ampdu_mlme.tid_tx[tid];
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);

if (WARN_ON(!tid_tx)) {
#ifdef CONFIG_MAC80211_HT_DEBUG
Expand Down Expand Up @@ -626,7 +632,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
return -EINVAL;

spin_lock_bh(&sta->lock);
tid_tx = sta->ampdu_mlme.tid_tx[tid];
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);

if (!tid_tx) {
ret = -ENOENT;
Expand Down Expand Up @@ -682,7 +688,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)

mutex_lock(&sta->ampdu_mlme.mtx);
spin_lock_bh(&sta->lock);
tid_tx = sta->ampdu_mlme.tid_tx[tid];
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);

if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
#ifdef CONFIG_MAC80211_HT_DEBUG
Expand Down Expand Up @@ -763,7 +769,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,

mutex_lock(&sta->ampdu_mlme.mtx);

tid_tx = sta->ampdu_mlme.tid_tx[tid];
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
if (!tid_tx)
goto out;

Expand Down
17 changes: 7 additions & 10 deletions net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,11 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
goto out_unlock;

if (pairwise)
key = sta->ptk;
key = key_mtx_dereference(local, sta->ptk);
else
key = sta->gtk[key_idx];
key = key_mtx_dereference(local, sta->gtk[key_idx]);
} else
key = sdata->keys[key_idx];
key = key_mtx_dereference(local, sdata->keys[key_idx]);

if (!key) {
ret = -ENOENT;
Expand Down Expand Up @@ -463,7 +463,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
int size;
int err = -EINVAL;

old = sdata->u.ap.beacon;
old = rtnl_dereference(sdata->u.ap.beacon);

/* head must not be zero-length */
if (params->head && !params->head_len)
Expand Down Expand Up @@ -558,8 +558,7 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,

sdata = IEEE80211_DEV_TO_SUB_IF(dev);

old = sdata->u.ap.beacon;

old = rtnl_dereference(sdata->u.ap.beacon);
if (old)
return -EALREADY;

Expand All @@ -574,8 +573,7 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,

sdata = IEEE80211_DEV_TO_SUB_IF(dev);

old = sdata->u.ap.beacon;

old = rtnl_dereference(sdata->u.ap.beacon);
if (!old)
return -ENOENT;

Expand All @@ -589,8 +587,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)

sdata = IEEE80211_DEV_TO_SUB_IF(dev);

old = sdata->u.ap.beacon;

old = rtnl_dereference(sdata->u.ap.beacon);
if (!old)
return -ENOENT;

Expand Down
21 changes: 9 additions & 12 deletions net/mac80211/debugfs_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,16 +241,12 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key)
if (!key->debugfs.dir)
return;

rcu_read_lock();
sta = rcu_dereference(key->sta);
if (sta)
sta = key->sta;
if (sta) {
sprintf(buf, "../../stations/%pM", sta->sta.addr);
rcu_read_unlock();

/* using sta as a boolean is fine outside RCU lock */
if (sta)
key->debugfs.stalink =
debugfs_create_symlink("station", key->debugfs.dir, buf);
}

DEBUGFS_ADD(keylen);
DEBUGFS_ADD(flags);
Expand Down Expand Up @@ -286,7 +282,8 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
lockdep_assert_held(&sdata->local->key_mtx);

if (sdata->default_unicast_key) {
key = sdata->default_unicast_key;
key = key_mtx_dereference(sdata->local,
sdata->default_unicast_key);
sprintf(buf, "../keys/%d", key->debugfs.cnt);
sdata->debugfs.default_unicast_key =
debugfs_create_symlink("default_unicast_key",
Expand All @@ -297,7 +294,8 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata)
}

if (sdata->default_multicast_key) {
key = sdata->default_multicast_key;
key = key_mtx_dereference(sdata->local,
sdata->default_multicast_key);
sprintf(buf, "../keys/%d", key->debugfs.cnt);
sdata->debugfs.default_multicast_key =
debugfs_create_symlink("default_multicast_key",
Expand All @@ -316,9 +314,8 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata)
if (!sdata->debugfs.dir)
return;

/* this is running under the key lock */

key = sdata->default_mgmt_key;
key = key_mtx_dereference(sdata->local,
sdata->default_mgmt_key);
if (key) {
sprintf(buf, "../keys/%d", key->debugfs.cnt);
sdata->debugfs.default_mgmt_key =
Expand Down
2 changes: 1 addition & 1 deletion net/mac80211/ht.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ void ieee80211_ba_session_work(struct work_struct *work)
continue;
}

tid_tx = sta->ampdu_mlme.tid_tx[tid];
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP,
&tid_tx->state))
___ieee80211_stop_tx_ba_session(sta, tid,
Expand Down
11 changes: 8 additions & 3 deletions net/mac80211/ibss.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,12 +662,16 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
int tx_last_beacon, len = req->len;
struct sk_buff *skb;
struct ieee80211_mgmt *resp;
struct sk_buff *presp;
u8 *pos, *end;

lockdep_assert_held(&ifibss->mtx);

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

if (ifibss->state != IEEE80211_IBSS_MLME_JOINED ||
len < 24 + 2 || !ifibss->presp)
len < 24 + 2 || !presp)
return;

tx_last_beacon = drv_tx_last_beacon(local);
Expand Down Expand Up @@ -705,7 +709,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
}

/* Reply with ProbeResp */
skb = skb_copy(ifibss->presp, GFP_KERNEL);
skb = skb_copy(presp, GFP_KERNEL);
if (!skb)
return;

Expand Down Expand Up @@ -985,7 +989,8 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)

/* remove beacon */
kfree(sdata->u.ibss.ie);
skb = sdata->u.ibss.presp;
skb = rcu_dereference_protected(sdata->u.ibss.presp,
lockdep_is_held(&sdata->u.ibss.mtx));
rcu_assign_pointer(sdata->u.ibss.presp, NULL);
sdata->vif.bss_conf.ibss_joined = false;
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED |
Expand Down
16 changes: 9 additions & 7 deletions net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ struct beacon_data {
};

struct ieee80211_if_ap {
struct beacon_data *beacon;
struct beacon_data __rcu *beacon;

struct list_head vlans;

Expand All @@ -237,7 +237,7 @@ struct ieee80211_if_vlan {
struct list_head list;

/* used for all tx if the VLAN is configured to 4-addr mode */
struct sta_info *sta;
struct sta_info __rcu *sta;
};

struct mesh_stats {
Expand Down Expand Up @@ -442,7 +442,8 @@ struct ieee80211_if_ibss {

unsigned long ibss_join_req;
/* probe response/beacon for IBSS */
struct sk_buff *presp, *skb;
struct sk_buff __rcu *presp;
struct sk_buff *skb;

enum {
IEEE80211_IBSS_MLME_SEARCH,
Expand Down Expand Up @@ -567,9 +568,10 @@ struct ieee80211_sub_if_data {
struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
unsigned int fragment_next;

struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
struct ieee80211_key *default_unicast_key, *default_multicast_key;
struct ieee80211_key *default_mgmt_key;
struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS];
struct ieee80211_key __rcu *default_unicast_key;
struct ieee80211_key __rcu *default_multicast_key;
struct ieee80211_key __rcu *default_mgmt_key;

u16 sequence_number;
__be16 control_port_protocol;
Expand Down Expand Up @@ -805,7 +807,7 @@ struct ieee80211_local {
spinlock_t sta_lock;
unsigned long num_sta;
struct list_head sta_list, sta_pending_list;
struct sta_info *sta_hash[STA_HASH_SIZE];
struct sta_info __rcu *sta_hash[STA_HASH_SIZE];
struct timer_list sta_cleanup;
struct work_struct sta_finish_work;
int sta_generation;
Expand Down
3 changes: 2 additions & 1 deletion net/mac80211/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
/* APs need special treatment */
if (sdata->vif.type == NL80211_IFTYPE_AP) {
struct ieee80211_sub_if_data *vlan, *tmpsdata;
struct beacon_data *old_beacon = sdata->u.ap.beacon;
struct beacon_data *old_beacon =
rtnl_dereference(sdata->u.ap.beacon);

/* sdata_running will return false, so this will disable */
ieee80211_bss_info_change_notify(sdata,
Expand Down
22 changes: 14 additions & 8 deletions net/mac80211/key.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
assert_key_lock(sdata->local);

if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
key = sdata->keys[idx];
key = key_mtx_dereference(sdata->local, sdata->keys[idx]);

if (uni)
rcu_assign_pointer(sdata->default_unicast_key, key);
Expand All @@ -222,7 +222,7 @@ __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)

if (idx >= NUM_DEFAULT_KEYS &&
idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
key = sdata->keys[idx];
key = key_mtx_dereference(sdata->local, sdata->keys[idx]);

rcu_assign_pointer(sdata->default_mgmt_key, key);

Expand Down Expand Up @@ -266,9 +266,15 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
else
idx = new->conf.keyidx;

defunikey = old && sdata->default_unicast_key == old;
defmultikey = old && sdata->default_multicast_key == old;
defmgmtkey = old && sdata->default_mgmt_key == old;
defunikey = old &&
old == key_mtx_dereference(sdata->local,
sdata->default_unicast_key);
defmultikey = old &&
old == key_mtx_dereference(sdata->local,
sdata->default_multicast_key);
defmgmtkey = old &&
old == key_mtx_dereference(sdata->local,
sdata->default_mgmt_key);

if (defunikey && !new)
__ieee80211_set_default_key(sdata, -1, true, false);
Expand Down Expand Up @@ -451,11 +457,11 @@ int ieee80211_key_link(struct ieee80211_key *key,
mutex_lock(&sdata->local->key_mtx);

if (sta && pairwise)
old_key = sta->ptk;
old_key = key_mtx_dereference(sdata->local, sta->ptk);
else if (sta)
old_key = sta->gtk[idx];
old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]);
else
old_key = sdata->keys[idx];
old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]);

__ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
__ieee80211_key_destroy(old_key);
Expand Down
Loading

0 comments on commit 40b275b

Please sign in to comment.