aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-07-30 10:46:07 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-08-16 15:26:37 -0400
commita1699b75a1db31a1da2f0fc610ee696d02a19280 (patch)
treef10a936a42a4bd35b39496d64426b61e465c43a6 /net/mac80211
parentc240879f3488ae0904a7ba5bdaaa54638b2d8852 (diff)
mac80211: unify scan and work mutexes
Having both scan and work mutexes is not just a bit too fine grained, it also creates issues when there's code that needs both since they then need to be acquired in the right order, which can be hard to do. Therefore, use just a single mutex for both. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/main.c4
-rw-r--r--net/mac80211/mlme.c8
-rw-r--r--net/mac80211/scan.c30
-rw-r--r--net/mac80211/work.c35
5 files changed, 38 insertions, 43 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 79d56454484a..fb4363e148f2 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -634,7 +634,6 @@ struct ieee80211_local {
634 /* 634 /*
635 * work stuff, potentially off-channel (in the future) 635 * work stuff, potentially off-channel (in the future)
636 */ 636 */
637 struct mutex work_mtx;
638 struct list_head work_list; 637 struct list_head work_list;
639 struct timer_list work_timer; 638 struct timer_list work_timer;
640 struct work_struct work_work; 639 struct work_struct work_work;
@@ -746,9 +745,10 @@ struct ieee80211_local {
746 */ 745 */
747 struct mutex key_mtx; 746 struct mutex key_mtx;
748 747
748 /* mutex for scan and work locking */
749 struct mutex mtx;
749 750
750 /* Scanning and BSS list */ 751 /* Scanning and BSS list */
751 struct mutex scan_mtx;
752 unsigned long scanning; 752 unsigned long scanning;
753 struct cfg80211_ssid scan_ssid; 753 struct cfg80211_ssid scan_ssid;
754 struct cfg80211_scan_request *int_scan_req; 754 struct cfg80211_scan_request *int_scan_req;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 18b8df922c60..06b9608a2130 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -482,7 +482,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
482 __hw_addr_init(&local->mc_list); 482 __hw_addr_init(&local->mc_list);
483 483
484 mutex_init(&local->iflist_mtx); 484 mutex_init(&local->iflist_mtx);
485 mutex_init(&local->scan_mtx); 485 mutex_init(&local->mtx);
486 486
487 mutex_init(&local->key_mtx); 487 mutex_init(&local->key_mtx);
488 spin_lock_init(&local->filter_lock); 488 spin_lock_init(&local->filter_lock);
@@ -791,7 +791,7 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
791 struct ieee80211_local *local = hw_to_local(hw); 791 struct ieee80211_local *local = hw_to_local(hw);
792 792
793 mutex_destroy(&local->iflist_mtx); 793 mutex_destroy(&local->iflist_mtx);
794 mutex_destroy(&local->scan_mtx); 794 mutex_destroy(&local->mtx);
795 795
796 wiphy_free(local->hw.wiphy); 796 wiphy_free(local->hw.wiphy);
797} 797}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index b6c163ac22da..17e9257a61d8 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1751,7 +1751,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
1751 struct ieee80211_local *local = sdata->local; 1751 struct ieee80211_local *local = sdata->local;
1752 struct ieee80211_work *wk; 1752 struct ieee80211_work *wk;
1753 1753
1754 mutex_lock(&local->work_mtx); 1754 mutex_lock(&local->mtx);
1755 list_for_each_entry(wk, &local->work_list, list) { 1755 list_for_each_entry(wk, &local->work_list, list) {
1756 if (wk->sdata != sdata) 1756 if (wk->sdata != sdata)
1757 continue; 1757 continue;
@@ -1783,7 +1783,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
1783 free_work(wk); 1783 free_work(wk);
1784 break; 1784 break;
1785 } 1785 }
1786 mutex_unlock(&local->work_mtx); 1786 mutex_unlock(&local->mtx);
1787 1787
1788 cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); 1788 cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
1789 } 1789 }
@@ -2275,7 +2275,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2275 2275
2276 mutex_unlock(&ifmgd->mtx); 2276 mutex_unlock(&ifmgd->mtx);
2277 2277
2278 mutex_lock(&local->work_mtx); 2278 mutex_lock(&local->mtx);
2279 list_for_each_entry(wk, &local->work_list, list) { 2279 list_for_each_entry(wk, &local->work_list, list) {
2280 if (wk->sdata != sdata) 2280 if (wk->sdata != sdata)
2281 continue; 2281 continue;
@@ -2294,7 +2294,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2294 free_work(wk); 2294 free_work(wk);
2295 break; 2295 break;
2296 } 2296 }
2297 mutex_unlock(&local->work_mtx); 2297 mutex_unlock(&local->mtx);
2298 2298
2299 /* 2299 /*
2300 * If somebody requests authentication and we haven't 2300 * If somebody requests authentication and we haven't
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 872d7b6ef6b3..f31f549733b1 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -255,7 +255,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
255 255
256 trace_api_scan_completed(local, aborted); 256 trace_api_scan_completed(local, aborted);
257 257
258 mutex_lock(&local->scan_mtx); 258 mutex_lock(&local->mtx);
259 259
260 /* 260 /*
261 * It's ok to abort a not-yet-running scan (that 261 * It's ok to abort a not-yet-running scan (that
@@ -267,7 +267,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
267 aborted = true; 267 aborted = true;
268 268
269 if (WARN_ON(!local->scan_req)) { 269 if (WARN_ON(!local->scan_req)) {
270 mutex_unlock(&local->scan_mtx); 270 mutex_unlock(&local->mtx);
271 return; 271 return;
272 } 272 }
273 273
@@ -275,7 +275,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
275 if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { 275 if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
276 ieee80211_queue_delayed_work(&local->hw, 276 ieee80211_queue_delayed_work(&local->hw,
277 &local->scan_work, 0); 277 &local->scan_work, 0);
278 mutex_unlock(&local->scan_mtx); 278 mutex_unlock(&local->mtx);
279 return; 279 return;
280 } 280 }
281 281
@@ -291,7 +291,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
291 local->scan_channel = NULL; 291 local->scan_channel = NULL;
292 292
293 /* we only have to protect scan_req and hw/sw scan */ 293 /* we only have to protect scan_req and hw/sw scan */
294 mutex_unlock(&local->scan_mtx); 294 mutex_unlock(&local->mtx);
295 295
296 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 296 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
297 if (was_hw_scan) 297 if (was_hw_scan)
@@ -639,15 +639,15 @@ void ieee80211_scan_work(struct work_struct *work)
639 struct ieee80211_sub_if_data *sdata = local->scan_sdata; 639 struct ieee80211_sub_if_data *sdata = local->scan_sdata;
640 unsigned long next_delay = 0; 640 unsigned long next_delay = 0;
641 641
642 mutex_lock(&local->scan_mtx); 642 mutex_lock(&local->mtx);
643 if (!sdata || !local->scan_req) { 643 if (!sdata || !local->scan_req) {
644 mutex_unlock(&local->scan_mtx); 644 mutex_unlock(&local->mtx);
645 return; 645 return;
646 } 646 }
647 647
648 if (local->hw_scan_req) { 648 if (local->hw_scan_req) {
649 int rc = drv_hw_scan(local, sdata, local->hw_scan_req); 649 int rc = drv_hw_scan(local, sdata, local->hw_scan_req);
650 mutex_unlock(&local->scan_mtx); 650 mutex_unlock(&local->mtx);
651 if (rc) 651 if (rc)
652 ieee80211_scan_completed(&local->hw, true); 652 ieee80211_scan_completed(&local->hw, true);
653 return; 653 return;
@@ -661,14 +661,14 @@ void ieee80211_scan_work(struct work_struct *work)
661 local->scan_sdata = NULL; 661 local->scan_sdata = NULL;
662 662
663 rc = __ieee80211_start_scan(sdata, req); 663 rc = __ieee80211_start_scan(sdata, req);
664 mutex_unlock(&local->scan_mtx); 664 mutex_unlock(&local->mtx);
665 665
666 if (rc) 666 if (rc)
667 ieee80211_scan_completed(&local->hw, true); 667 ieee80211_scan_completed(&local->hw, true);
668 return; 668 return;
669 } 669 }
670 670
671 mutex_unlock(&local->scan_mtx); 671 mutex_unlock(&local->mtx);
672 672
673 /* 673 /*
674 * Avoid re-scheduling when the sdata is going away. 674 * Avoid re-scheduling when the sdata is going away.
@@ -711,9 +711,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
711{ 711{
712 int res; 712 int res;
713 713
714 mutex_lock(&sdata->local->scan_mtx); 714 mutex_lock(&sdata->local->mtx);
715 res = __ieee80211_start_scan(sdata, req); 715 res = __ieee80211_start_scan(sdata, req);
716 mutex_unlock(&sdata->local->scan_mtx); 716 mutex_unlock(&sdata->local->mtx);
717 717
718 return res; 718 return res;
719} 719}
@@ -726,7 +726,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
726 int ret = -EBUSY; 726 int ret = -EBUSY;
727 enum ieee80211_band band; 727 enum ieee80211_band band;
728 728
729 mutex_lock(&local->scan_mtx); 729 mutex_lock(&local->mtx);
730 730
731 /* busy scanning */ 731 /* busy scanning */
732 if (local->scan_req) 732 if (local->scan_req)
@@ -761,7 +761,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
761 761
762 ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req); 762 ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req);
763 unlock: 763 unlock:
764 mutex_unlock(&local->scan_mtx); 764 mutex_unlock(&local->mtx);
765 return ret; 765 return ret;
766} 766}
767 767
@@ -775,10 +775,10 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
775 * Only call this function when a scan can't be 775 * Only call this function when a scan can't be
776 * queued -- mostly at suspend under RTNL. 776 * queued -- mostly at suspend under RTNL.
777 */ 777 */
778 mutex_lock(&local->scan_mtx); 778 mutex_lock(&local->mtx);
779 abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) || 779 abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) ||
780 (!local->scanning && local->scan_req); 780 (!local->scanning && local->scan_req);
781 mutex_unlock(&local->scan_mtx); 781 mutex_unlock(&local->mtx);
782 782
783 if (abortscan) 783 if (abortscan)
784 ieee80211_scan_completed(&local->hw, true); 784 ieee80211_scan_completed(&local->hw, true);
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index 81d4ad64184a..b98af64f5862 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -43,7 +43,7 @@ enum work_action {
43/* utils */ 43/* utils */
44static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) 44static inline void ASSERT_WORK_MTX(struct ieee80211_local *local)
45{ 45{
46 WARN_ON(!mutex_is_locked(&local->work_mtx)); 46 lockdep_assert_held(&local->mtx);
47} 47}
48 48
49/* 49/*
@@ -757,7 +757,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
757 mgmt = (struct ieee80211_mgmt *) skb->data; 757 mgmt = (struct ieee80211_mgmt *) skb->data;
758 fc = le16_to_cpu(mgmt->frame_control); 758 fc = le16_to_cpu(mgmt->frame_control);
759 759
760 mutex_lock(&local->work_mtx); 760 mutex_lock(&local->mtx);
761 761
762 list_for_each_entry(wk, &local->work_list, list) { 762 list_for_each_entry(wk, &local->work_list, list) {
763 const u8 *bssid = NULL; 763 const u8 *bssid = NULL;
@@ -833,7 +833,7 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
833 WARN(1, "unexpected: %d", rma); 833 WARN(1, "unexpected: %d", rma);
834 } 834 }
835 835
836 mutex_unlock(&local->work_mtx); 836 mutex_unlock(&local->mtx);
837 837
838 if (rma != WORK_ACT_DONE) 838 if (rma != WORK_ACT_DONE)
839 goto out; 839 goto out;
@@ -845,9 +845,9 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
845 case WORK_DONE_REQUEUE: 845 case WORK_DONE_REQUEUE:
846 synchronize_rcu(); 846 synchronize_rcu();
847 wk->started = false; /* restart */ 847 wk->started = false; /* restart */
848 mutex_lock(&local->work_mtx); 848 mutex_lock(&local->mtx);
849 list_add_tail(&wk->list, &local->work_list); 849 list_add_tail(&wk->list, &local->work_list);
850 mutex_unlock(&local->work_mtx); 850 mutex_unlock(&local->mtx);
851 } 851 }
852 852
853 out: 853 out:
@@ -890,7 +890,7 @@ static void ieee80211_work_work(struct work_struct *work)
890 890
891 ieee80211_recalc_idle(local); 891 ieee80211_recalc_idle(local);
892 892
893 mutex_lock(&local->work_mtx); 893 mutex_lock(&local->mtx);
894 894
895 list_for_each_entry_safe(wk, tmp, &local->work_list, list) { 895 list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
896 bool started = wk->started; 896 bool started = wk->started;
@@ -995,17 +995,13 @@ static void ieee80211_work_work(struct work_struct *work)
995 run_again(local, jiffies + HZ/2); 995 run_again(local, jiffies + HZ/2);
996 } 996 }
997 997
998 mutex_lock(&local->scan_mtx);
999
1000 if (list_empty(&local->work_list) && local->scan_req && 998 if (list_empty(&local->work_list) && local->scan_req &&
1001 !local->scanning) 999 !local->scanning)
1002 ieee80211_queue_delayed_work(&local->hw, 1000 ieee80211_queue_delayed_work(&local->hw,
1003 &local->scan_work, 1001 &local->scan_work,
1004 round_jiffies_relative(0)); 1002 round_jiffies_relative(0));
1005 1003
1006 mutex_unlock(&local->scan_mtx); 1004 mutex_unlock(&local->mtx);
1007
1008 mutex_unlock(&local->work_mtx);
1009 1005
1010 ieee80211_recalc_idle(local); 1006 ieee80211_recalc_idle(local);
1011 1007
@@ -1035,16 +1031,15 @@ void ieee80211_add_work(struct ieee80211_work *wk)
1035 wk->started = false; 1031 wk->started = false;
1036 1032
1037 local = wk->sdata->local; 1033 local = wk->sdata->local;
1038 mutex_lock(&local->work_mtx); 1034 mutex_lock(&local->mtx);
1039 list_add_tail(&wk->list, &local->work_list); 1035 list_add_tail(&wk->list, &local->work_list);
1040 mutex_unlock(&local->work_mtx); 1036 mutex_unlock(&local->mtx);
1041 1037
1042 ieee80211_queue_work(&local->hw, &local->work_work); 1038 ieee80211_queue_work(&local->hw, &local->work_work);
1043} 1039}
1044 1040
1045void ieee80211_work_init(struct ieee80211_local *local) 1041void ieee80211_work_init(struct ieee80211_local *local)
1046{ 1042{
1047 mutex_init(&local->work_mtx);
1048 INIT_LIST_HEAD(&local->work_list); 1043 INIT_LIST_HEAD(&local->work_list);
1049 setup_timer(&local->work_timer, ieee80211_work_timer, 1044 setup_timer(&local->work_timer, ieee80211_work_timer,
1050 (unsigned long)local); 1045 (unsigned long)local);
@@ -1057,7 +1052,7 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
1057 struct ieee80211_local *local = sdata->local; 1052 struct ieee80211_local *local = sdata->local;
1058 struct ieee80211_work *wk; 1053 struct ieee80211_work *wk;
1059 1054
1060 mutex_lock(&local->work_mtx); 1055 mutex_lock(&local->mtx);
1061 list_for_each_entry(wk, &local->work_list, list) { 1056 list_for_each_entry(wk, &local->work_list, list) {
1062 if (wk->sdata != sdata) 1057 if (wk->sdata != sdata)
1063 continue; 1058 continue;
@@ -1065,19 +1060,19 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
1065 wk->started = true; 1060 wk->started = true;
1066 wk->timeout = jiffies; 1061 wk->timeout = jiffies;
1067 } 1062 }
1068 mutex_unlock(&local->work_mtx); 1063 mutex_unlock(&local->mtx);
1069 1064
1070 /* run cleanups etc. */ 1065 /* run cleanups etc. */
1071 ieee80211_work_work(&local->work_work); 1066 ieee80211_work_work(&local->work_work);
1072 1067
1073 mutex_lock(&local->work_mtx); 1068 mutex_lock(&local->mtx);
1074 list_for_each_entry(wk, &local->work_list, list) { 1069 list_for_each_entry(wk, &local->work_list, list) {
1075 if (wk->sdata != sdata) 1070 if (wk->sdata != sdata)
1076 continue; 1071 continue;
1077 WARN_ON(1); 1072 WARN_ON(1);
1078 break; 1073 break;
1079 } 1074 }
1080 mutex_unlock(&local->work_mtx); 1075 mutex_unlock(&local->mtx);
1081} 1076}
1082 1077
1083ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, 1078ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
@@ -1163,7 +1158,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata,
1163 struct ieee80211_work *wk, *tmp; 1158 struct ieee80211_work *wk, *tmp;
1164 bool found = false; 1159 bool found = false;
1165 1160
1166 mutex_lock(&local->work_mtx); 1161 mutex_lock(&local->mtx);
1167 list_for_each_entry_safe(wk, tmp, &local->work_list, list) { 1162 list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
1168 if ((unsigned long) wk == cookie) { 1163 if ((unsigned long) wk == cookie) {
1169 wk->timeout = jiffies; 1164 wk->timeout = jiffies;
@@ -1171,7 +1166,7 @@ int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata,
1171 break; 1166 break;
1172 } 1167 }
1173 } 1168 }
1174 mutex_unlock(&local->work_mtx); 1169 mutex_unlock(&local->mtx);
1175 1170
1176 if (!found) 1171 if (!found)
1177 return -ENOENT; 1172 return -ENOENT;