From e2fd5dbc1c7031be5b5de043bcc0a18c7a59a68a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 6 Jul 2012 21:39:28 +0200 Subject: mac80211: make scan_sdata pointer usable with RCU Making the scan_sdata pointer usable with RCU makes it possible to dereference it in the RX path to see if a received frame actually matches the interface that is scanning. This is just preparations, making the pointer __rcu. Signed-off-by: Johannes Berg --- net/mac80211/scan.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'net/mac80211/scan.c') diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 1ff04f689d1f..704dcf847761 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -293,7 +293,13 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, return; if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { - int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req); + int rc; + + rc = drv_hw_scan(local, + rcu_dereference_protected(local->scan_sdata, + lockdep_is_held(&local->mtx)), + local->hw_scan_req); + if (rc == 0) return; } @@ -394,7 +400,10 @@ void ieee80211_run_deferred_scan(struct ieee80211_local *local) if (!local->scan_req || local->scanning) return; - if (!ieee80211_can_scan(local, local->scan_sdata)) + if (!ieee80211_can_scan(local, + rcu_dereference_protected( + local->scan_sdata, + lockdep_is_held(&local->mtx)))) return; ieee80211_queue_delayed_work(&local->hw, &local->scan_work, @@ -405,9 +414,12 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, unsigned long *next_delay) { int i; - struct ieee80211_sub_if_data *sdata = local->scan_sdata; + struct ieee80211_sub_if_data *sdata; enum ieee80211_band band = local->hw.conf.channel->band; + sdata = rcu_dereference_protected(local->scan_sdata, + lockdep_is_held(&local->mtx));; + for (i = 0; i < local->scan_req->n_ssids; i++) ieee80211_send_probe_req( sdata, NULL, @@ -439,7 +451,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, if (!ieee80211_can_scan(local, sdata)) { /* wait for the work to finish/time out */ local->scan_req = req; - local->scan_sdata = sdata; + rcu_assign_pointer(local->scan_sdata, sdata); return 0; } @@ -473,7 +485,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, } local->scan_req = req; - local->scan_sdata = sdata; + rcu_assign_pointer(local->scan_sdata, sdata); if (local->ops->hw_scan) { __set_bit(SCAN_HW_SCANNING, &local->scanning); @@ -533,7 +545,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, ieee80211_recalc_idle(local); local->scan_req = NULL; - local->scan_sdata = NULL; + rcu_assign_pointer(local->scan_sdata, NULL); } return rc; @@ -720,7 +732,8 @@ void ieee80211_scan_work(struct work_struct *work) mutex_lock(&local->mtx); - sdata = local->scan_sdata; + sdata = rcu_dereference_protected(local->scan_sdata, + lockdep_is_held(&local->mtx)); /* When scanning on-channel, the first-callback means completed. */ if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) { @@ -741,7 +754,7 @@ void ieee80211_scan_work(struct work_struct *work) int rc; local->scan_req = NULL; - local->scan_sdata = NULL; + rcu_assign_pointer(local->scan_sdata, NULL); rc = __ieee80211_start_scan(sdata, req); if (rc) { @@ -893,7 +906,9 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) if (test_bit(SCAN_HW_SCANNING, &local->scanning)) { if (local->ops->cancel_hw_scan) - drv_cancel_hw_scan(local, local->scan_sdata); + drv_cancel_hw_scan(local, + rcu_dereference_protected(local->scan_sdata, + lockdep_is_held(&local->mtx))); goto out; } -- cgit v1.2.3-70-g09d2