aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/ibss.c97
-rw-r--r--net/mac80211/ieee80211_i.h7
2 files changed, 54 insertions, 50 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 090e344d5f90..c691780725a7 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -43,6 +43,8 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
43{ 43{
44 u16 auth_alg, auth_transaction, status_code; 44 u16 auth_alg, auth_transaction, status_code;
45 45
46 lockdep_assert_held(&sdata->u.ibss.mtx);
47
46 if (len < 24 + 6) 48 if (len < 24 + 6)
47 return; 49 return;
48 50
@@ -78,6 +80,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
78 u32 bss_change; 80 u32 bss_change;
79 u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; 81 u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
80 82
83 lockdep_assert_held(&ifibss->mtx);
84
81 /* Reset own TSF to allow time synchronization work. */ 85 /* Reset own TSF to allow time synchronization work. */
82 drv_reset_tsf(local); 86 drv_reset_tsf(local);
83 87
@@ -205,6 +209,8 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
205 int i, j; 209 int i, j;
206 u16 beacon_int = cbss->beacon_interval; 210 u16 beacon_int = cbss->beacon_interval;
207 211
212 lockdep_assert_held(&sdata->u.ibss.mtx);
213
208 if (beacon_int < 10) 214 if (beacon_int < 10)
209 beacon_int = 10; 215 beacon_int = 10;
210 216
@@ -449,6 +455,8 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
449 int active = 0; 455 int active = 0;
450 struct sta_info *sta; 456 struct sta_info *sta;
451 457
458 lockdep_assert_held(&sdata->u.ibss.mtx);
459
452 rcu_read_lock(); 460 rcu_read_lock();
453 461
454 list_for_each_entry_rcu(sta, &local->sta_list, list) { 462 list_for_each_entry_rcu(sta, &local->sta_list, list) {
@@ -473,6 +481,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
473{ 481{
474 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 482 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
475 483
484 lockdep_assert_held(&ifibss->mtx);
485
476 mod_timer(&ifibss->timer, 486 mod_timer(&ifibss->timer,
477 round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); 487 round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
478 488
@@ -505,6 +515,8 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
505 u16 capability; 515 u16 capability;
506 int i; 516 int i;
507 517
518 lockdep_assert_held(&ifibss->mtx);
519
508 if (ifibss->fixed_bssid) { 520 if (ifibss->fixed_bssid) {
509 memcpy(bssid, ifibss->bssid, ETH_ALEN); 521 memcpy(bssid, ifibss->bssid, ETH_ALEN);
510 } else { 522 } else {
@@ -549,6 +561,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
549 int active_ibss; 561 int active_ibss;
550 u16 capability; 562 u16 capability;
551 563
564 lockdep_assert_held(&ifibss->mtx);
565
552 active_ibss = ieee80211_sta_active_ibss(sdata); 566 active_ibss = ieee80211_sta_active_ibss(sdata);
553#ifdef CONFIG_MAC80211_IBSS_DEBUG 567#ifdef CONFIG_MAC80211_IBSS_DEBUG
554 printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", 568 printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
@@ -637,6 +651,8 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
637 struct ieee80211_mgmt *resp; 651 struct ieee80211_mgmt *resp;
638 u8 *pos, *end; 652 u8 *pos, *end;
639 653
654 lockdep_assert_held(&ifibss->mtx);
655
640 if (ifibss->state != IEEE80211_IBSS_MLME_JOINED || 656 if (ifibss->state != IEEE80211_IBSS_MLME_JOINED ||
641 len < 24 + 2 || !ifibss->presp) 657 len < 24 + 2 || !ifibss->presp)
642 return; 658 return;
@@ -740,6 +756,8 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
740 mgmt = (struct ieee80211_mgmt *) skb->data; 756 mgmt = (struct ieee80211_mgmt *) skb->data;
741 fc = le16_to_cpu(mgmt->frame_control); 757 fc = le16_to_cpu(mgmt->frame_control);
742 758
759 mutex_lock(&sdata->u.ibss.mtx);
760
743 switch (fc & IEEE80211_FCTL_STYPE) { 761 switch (fc & IEEE80211_FCTL_STYPE) {
744 case IEEE80211_STYPE_PROBE_REQ: 762 case IEEE80211_STYPE_PROBE_REQ:
745 ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len); 763 ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len);
@@ -756,14 +774,23 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
756 ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len); 774 ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len);
757 break; 775 break;
758 } 776 }
777
778 mutex_unlock(&sdata->u.ibss.mtx);
759} 779}
760 780
761void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) 781void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
762{ 782{
763 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 783 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
764 784
765 if (!test_and_clear_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request)) 785 mutex_lock(&ifibss->mtx);
766 return; 786
787 /*
788 * Work could be scheduled after scan or similar
789 * when we aren't even joined (or trying) with a
790 * network.
791 */
792 if (!ifibss->ssid_len)
793 goto out;
767 794
768 switch (ifibss->state) { 795 switch (ifibss->state) {
769 case IEEE80211_IBSS_MLME_SEARCH: 796 case IEEE80211_IBSS_MLME_SEARCH:
@@ -776,15 +803,9 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
776 WARN_ON(1); 803 WARN_ON(1);
777 break; 804 break;
778 } 805 }
779}
780 806
781static void ieee80211_queue_ibss_work(struct ieee80211_sub_if_data *sdata) 807 out:
782{ 808 mutex_unlock(&ifibss->mtx);
783 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
784 struct ieee80211_local *local = sdata->local;
785
786 set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
787 ieee80211_queue_work(&local->hw, &sdata->work);
788} 809}
789 810
790static void ieee80211_ibss_timer(unsigned long data) 811static void ieee80211_ibss_timer(unsigned long data)
@@ -799,7 +820,7 @@ static void ieee80211_ibss_timer(unsigned long data)
799 return; 820 return;
800 } 821 }
801 822
802 ieee80211_queue_ibss_work(sdata); 823 ieee80211_queue_work(&local->hw, &sdata->work);
803} 824}
804 825
805#ifdef CONFIG_PM 826#ifdef CONFIG_PM
@@ -828,6 +849,7 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
828 849
829 setup_timer(&ifibss->timer, ieee80211_ibss_timer, 850 setup_timer(&ifibss->timer, ieee80211_ibss_timer,
830 (unsigned long) sdata); 851 (unsigned long) sdata);
852 mutex_init(&ifibss->mtx);
831} 853}
832 854
833/* scan finished notification */ 855/* scan finished notification */
@@ -841,10 +863,8 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local)
841 continue; 863 continue;
842 if (sdata->vif.type != NL80211_IFTYPE_ADHOC) 864 if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
843 continue; 865 continue;
844 if (!sdata->u.ibss.ssid_len)
845 continue;
846 sdata->u.ibss.last_scan_completed = jiffies; 866 sdata->u.ibss.last_scan_completed = jiffies;
847 ieee80211_queue_ibss_work(sdata); 867 ieee80211_queue_work(&local->hw, &sdata->work);
848 } 868 }
849 mutex_unlock(&local->iflist_mtx); 869 mutex_unlock(&local->iflist_mtx);
850} 870}
@@ -854,6 +874,17 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
854{ 874{
855 struct sk_buff *skb; 875 struct sk_buff *skb;
856 876
877 skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
878 36 /* bitrates */ +
879 34 /* SSID */ +
880 3 /* DS params */ +
881 4 /* IBSS params */ +
882 params->ie_len);
883 if (!skb)
884 return -ENOMEM;
885
886 mutex_lock(&sdata->u.ibss.mtx);
887
857 if (params->bssid) { 888 if (params->bssid) {
858 memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); 889 memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN);
859 sdata->u.ibss.fixed_bssid = true; 890 sdata->u.ibss.fixed_bssid = true;
@@ -882,35 +913,19 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
882 sdata->u.ibss.ie_len = params->ie_len; 913 sdata->u.ibss.ie_len = params->ie_len;
883 } 914 }
884 915
885 skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
886 36 /* bitrates */ +
887 34 /* SSID */ +
888 3 /* DS params */ +
889 4 /* IBSS params */ +
890 params->ie_len);
891 if (!skb)
892 return -ENOMEM;
893
894 sdata->u.ibss.skb = skb; 916 sdata->u.ibss.skb = skb;
895 sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; 917 sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
896 sdata->u.ibss.ibss_join_req = jiffies; 918 sdata->u.ibss.ibss_join_req = jiffies;
897 919
898 memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); 920 memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
899
900 /*
901 * The ssid_len setting below is used to see whether
902 * we are active, and we need all other settings
903 * before that may get visible.
904 */
905 mb();
906
907 sdata->u.ibss.ssid_len = params->ssid_len; 921 sdata->u.ibss.ssid_len = params->ssid_len;
908 922
909 ieee80211_recalc_idle(sdata->local); 923 ieee80211_recalc_idle(sdata->local);
910 924
911 set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
912 ieee80211_queue_work(&sdata->local->hw, &sdata->work); 925 ieee80211_queue_work(&sdata->local->hw, &sdata->work);
913 926
927 mutex_unlock(&sdata->u.ibss.mtx);
928
914 return 0; 929 return 0;
915} 930}
916 931
@@ -921,7 +936,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
921 struct ieee80211_local *local = sdata->local; 936 struct ieee80211_local *local = sdata->local;
922 struct cfg80211_bss *cbss; 937 struct cfg80211_bss *cbss;
923 u16 capability; 938 u16 capability;
924 int active_ibss = 0; 939 int active_ibss;
940
941 mutex_lock(&sdata->u.ibss.mtx);
925 942
926 active_ibss = ieee80211_sta_active_ibss(sdata); 943 active_ibss = ieee80211_sta_active_ibss(sdata);
927 944
@@ -959,19 +976,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
959 memset(sdata->u.ibss.bssid, 0, ETH_ALEN); 976 memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
960 sdata->u.ibss.ssid_len = 0; 977 sdata->u.ibss.ssid_len = 0;
961 978
962 /*
963 * ssid_len indicates active or not, so needs to be visible to
964 * everybody, especially ieee80211_ibss_notify_scan_completed,
965 * so it won't restart the timer after we remove it here.
966 */
967 mb();
968
969 del_timer_sync(&sdata->u.ibss.timer); 979 del_timer_sync(&sdata->u.ibss.timer);
970 clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); 980
971 /* 981 mutex_unlock(&sdata->u.ibss.mtx);
972 * Since the REQ_RUN bit is clear, the work won't do
973 * anything if it runs after this.
974 */
975 982
976 ieee80211_recalc_idle(sdata->local); 983 ieee80211_recalc_idle(sdata->local);
977 984
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f9251d50192c..c6b5c2d3ffde 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -377,14 +377,11 @@ struct ieee80211_if_managed {
377 int last_cqm_event_signal; 377 int last_cqm_event_signal;
378}; 378};
379 379
380enum ieee80211_ibss_request {
381 IEEE80211_IBSS_REQ_RUN = 0,
382};
383
384struct ieee80211_if_ibss { 380struct ieee80211_if_ibss {
385 struct timer_list timer; 381 struct timer_list timer;
386 382
387 unsigned long request; 383 struct mutex mtx;
384
388 unsigned long last_scan_completed; 385 unsigned long last_scan_completed;
389 386
390 u32 basic_rates; 387 u32 basic_rates;