diff options
Diffstat (limited to 'net/mac80211/ibss.c')
| -rw-r--r-- | net/mac80211/ibss.c | 171 |
1 files changed, 86 insertions, 85 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index b2cc1fda6cfd..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 | ||
| @@ -172,11 +176,13 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
| 172 | rcu_assign_pointer(ifibss->presp, skb); | 176 | rcu_assign_pointer(ifibss->presp, skb); |
| 173 | 177 | ||
| 174 | sdata->vif.bss_conf.beacon_int = beacon_int; | 178 | sdata->vif.bss_conf.beacon_int = beacon_int; |
| 179 | sdata->vif.bss_conf.basic_rates = basic_rates; | ||
| 175 | bss_change = BSS_CHANGED_BEACON_INT; | 180 | bss_change = BSS_CHANGED_BEACON_INT; |
| 176 | bss_change |= ieee80211_reset_erp_info(sdata); | 181 | bss_change |= ieee80211_reset_erp_info(sdata); |
| 177 | bss_change |= BSS_CHANGED_BSSID; | 182 | bss_change |= BSS_CHANGED_BSSID; |
| 178 | bss_change |= BSS_CHANGED_BEACON; | 183 | bss_change |= BSS_CHANGED_BEACON; |
| 179 | bss_change |= BSS_CHANGED_BEACON_ENABLED; | 184 | bss_change |= BSS_CHANGED_BEACON_ENABLED; |
| 185 | bss_change |= BSS_CHANGED_BASIC_RATES; | ||
| 180 | bss_change |= BSS_CHANGED_IBSS; | 186 | bss_change |= BSS_CHANGED_IBSS; |
| 181 | sdata->vif.bss_conf.ibss_joined = true; | 187 | sdata->vif.bss_conf.ibss_joined = true; |
| 182 | ieee80211_bss_info_change_notify(sdata, bss_change); | 188 | ieee80211_bss_info_change_notify(sdata, bss_change); |
| @@ -203,6 +209,8 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
| 203 | int i, j; | 209 | int i, j; |
| 204 | u16 beacon_int = cbss->beacon_interval; | 210 | u16 beacon_int = cbss->beacon_interval; |
| 205 | 211 | ||
| 212 | lockdep_assert_held(&sdata->u.ibss.mtx); | ||
| 213 | |||
| 206 | if (beacon_int < 10) | 214 | if (beacon_int < 10) |
| 207 | beacon_int = 10; | 215 | beacon_int = 10; |
| 208 | 216 | ||
| @@ -447,6 +455,8 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata) | |||
| 447 | int active = 0; | 455 | int active = 0; |
| 448 | struct sta_info *sta; | 456 | struct sta_info *sta; |
| 449 | 457 | ||
| 458 | lockdep_assert_held(&sdata->u.ibss.mtx); | ||
| 459 | |||
| 450 | rcu_read_lock(); | 460 | rcu_read_lock(); |
| 451 | 461 | ||
| 452 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 462 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
| @@ -471,6 +481,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) | |||
| 471 | { | 481 | { |
| 472 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 482 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
| 473 | 483 | ||
| 484 | lockdep_assert_held(&ifibss->mtx); | ||
| 485 | |||
| 474 | mod_timer(&ifibss->timer, | 486 | mod_timer(&ifibss->timer, |
| 475 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); | 487 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); |
| 476 | 488 | ||
| @@ -503,6 +515,8 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
| 503 | u16 capability; | 515 | u16 capability; |
| 504 | int i; | 516 | int i; |
| 505 | 517 | ||
| 518 | lockdep_assert_held(&ifibss->mtx); | ||
| 519 | |||
| 506 | if (ifibss->fixed_bssid) { | 520 | if (ifibss->fixed_bssid) { |
| 507 | memcpy(bssid, ifibss->bssid, ETH_ALEN); | 521 | memcpy(bssid, ifibss->bssid, ETH_ALEN); |
| 508 | } else { | 522 | } else { |
| @@ -529,7 +543,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) | |||
| 529 | sdata->drop_unencrypted = 0; | 543 | sdata->drop_unencrypted = 0; |
| 530 | 544 | ||
| 531 | __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, | 545 | __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, |
| 532 | ifibss->channel, 3, /* first two are basic */ | 546 | ifibss->channel, ifibss->basic_rates, |
| 533 | capability, 0); | 547 | capability, 0); |
| 534 | } | 548 | } |
| 535 | 549 | ||
| @@ -547,6 +561,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
| 547 | int active_ibss; | 561 | int active_ibss; |
| 548 | u16 capability; | 562 | u16 capability; |
| 549 | 563 | ||
| 564 | lockdep_assert_held(&ifibss->mtx); | ||
| 565 | |||
| 550 | active_ibss = ieee80211_sta_active_ibss(sdata); | 566 | active_ibss = ieee80211_sta_active_ibss(sdata); |
| 551 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 567 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
| 552 | printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", | 568 | printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n", |
| @@ -635,6 +651,8 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
| 635 | struct ieee80211_mgmt *resp; | 651 | struct ieee80211_mgmt *resp; |
| 636 | u8 *pos, *end; | 652 | u8 *pos, *end; |
| 637 | 653 | ||
| 654 | lockdep_assert_held(&ifibss->mtx); | ||
| 655 | |||
| 638 | if (ifibss->state != IEEE80211_IBSS_MLME_JOINED || | 656 | if (ifibss->state != IEEE80211_IBSS_MLME_JOINED || |
| 639 | len < 24 + 2 || !ifibss->presp) | 657 | len < 24 + 2 || !ifibss->presp) |
| 640 | return; | 658 | return; |
| @@ -727,8 +745,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
| 727 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true); | 745 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true); |
| 728 | } | 746 | } |
| 729 | 747 | ||
| 730 | static void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 748 | void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
| 731 | struct sk_buff *skb) | 749 | struct sk_buff *skb) |
| 732 | { | 750 | { |
| 733 | struct ieee80211_rx_status *rx_status; | 751 | struct ieee80211_rx_status *rx_status; |
| 734 | struct ieee80211_mgmt *mgmt; | 752 | struct ieee80211_mgmt *mgmt; |
| @@ -738,6 +756,8 @@ static void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
| 738 | mgmt = (struct ieee80211_mgmt *) skb->data; | 756 | mgmt = (struct ieee80211_mgmt *) skb->data; |
| 739 | fc = le16_to_cpu(mgmt->frame_control); | 757 | fc = le16_to_cpu(mgmt->frame_control); |
| 740 | 758 | ||
| 759 | mutex_lock(&sdata->u.ibss.mtx); | ||
| 760 | |||
| 741 | switch (fc & IEEE80211_FCTL_STYPE) { | 761 | switch (fc & IEEE80211_FCTL_STYPE) { |
| 742 | case IEEE80211_STYPE_PROBE_REQ: | 762 | case IEEE80211_STYPE_PROBE_REQ: |
| 743 | ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len); | 763 | ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len); |
| @@ -755,35 +775,22 @@ static void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
| 755 | break; | 775 | break; |
| 756 | } | 776 | } |
| 757 | 777 | ||
| 758 | kfree_skb(skb); | 778 | mutex_unlock(&sdata->u.ibss.mtx); |
| 759 | } | 779 | } |
| 760 | 780 | ||
| 761 | static void ieee80211_ibss_work(struct work_struct *work) | 781 | void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata) |
| 762 | { | 782 | { |
| 763 | struct ieee80211_sub_if_data *sdata = | 783 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
| 764 | container_of(work, struct ieee80211_sub_if_data, u.ibss.work); | ||
| 765 | struct ieee80211_local *local = sdata->local; | ||
| 766 | struct ieee80211_if_ibss *ifibss; | ||
| 767 | struct sk_buff *skb; | ||
| 768 | |||
| 769 | if (WARN_ON(local->suspended)) | ||
| 770 | return; | ||
| 771 | |||
| 772 | if (!ieee80211_sdata_running(sdata)) | ||
| 773 | return; | ||
| 774 | |||
| 775 | if (local->scanning) | ||
| 776 | return; | ||
| 777 | |||
| 778 | if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_ADHOC)) | ||
| 779 | return; | ||
| 780 | ifibss = &sdata->u.ibss; | ||
| 781 | 784 | ||
| 782 | while ((skb = skb_dequeue(&ifibss->skb_queue))) | 785 | mutex_lock(&ifibss->mtx); |
| 783 | ieee80211_ibss_rx_queued_mgmt(sdata, skb); | ||
| 784 | 786 | ||
| 785 | if (!test_and_clear_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request)) | 787 | /* |
| 786 | return; | 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; | ||
| 787 | 794 | ||
| 788 | switch (ifibss->state) { | 795 | switch (ifibss->state) { |
| 789 | case IEEE80211_IBSS_MLME_SEARCH: | 796 | case IEEE80211_IBSS_MLME_SEARCH: |
| @@ -796,6 +803,9 @@ static void ieee80211_ibss_work(struct work_struct *work) | |||
| 796 | WARN_ON(1); | 803 | WARN_ON(1); |
| 797 | break; | 804 | break; |
| 798 | } | 805 | } |
| 806 | |||
| 807 | out: | ||
| 808 | mutex_unlock(&ifibss->mtx); | ||
| 799 | } | 809 | } |
| 800 | 810 | ||
| 801 | static void ieee80211_ibss_timer(unsigned long data) | 811 | static void ieee80211_ibss_timer(unsigned long data) |
| @@ -810,8 +820,7 @@ static void ieee80211_ibss_timer(unsigned long data) | |||
| 810 | return; | 820 | return; |
| 811 | } | 821 | } |
| 812 | 822 | ||
| 813 | set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request); | 823 | ieee80211_queue_work(&local->hw, &sdata->work); |
| 814 | ieee80211_queue_work(&local->hw, &ifibss->work); | ||
| 815 | } | 824 | } |
| 816 | 825 | ||
| 817 | #ifdef CONFIG_PM | 826 | #ifdef CONFIG_PM |
| @@ -819,7 +828,6 @@ void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata) | |||
| 819 | { | 828 | { |
| 820 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 829 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
| 821 | 830 | ||
| 822 | cancel_work_sync(&ifibss->work); | ||
| 823 | if (del_timer_sync(&ifibss->timer)) | 831 | if (del_timer_sync(&ifibss->timer)) |
| 824 | ifibss->timer_running = true; | 832 | ifibss->timer_running = true; |
| 825 | } | 833 | } |
| @@ -839,10 +847,9 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
| 839 | { | 847 | { |
| 840 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 848 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
| 841 | 849 | ||
| 842 | INIT_WORK(&ifibss->work, ieee80211_ibss_work); | ||
| 843 | setup_timer(&ifibss->timer, ieee80211_ibss_timer, | 850 | setup_timer(&ifibss->timer, ieee80211_ibss_timer, |
| 844 | (unsigned long) sdata); | 851 | (unsigned long) sdata); |
| 845 | skb_queue_head_init(&ifibss->skb_queue); | 852 | mutex_init(&ifibss->mtx); |
| 846 | } | 853 | } |
| 847 | 854 | ||
| 848 | /* scan finished notification */ | 855 | /* scan finished notification */ |
| @@ -856,45 +863,28 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) | |||
| 856 | continue; | 863 | continue; |
| 857 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | 864 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) |
| 858 | continue; | 865 | continue; |
| 859 | if (!sdata->u.ibss.ssid_len) | ||
| 860 | continue; | ||
| 861 | sdata->u.ibss.last_scan_completed = jiffies; | 866 | sdata->u.ibss.last_scan_completed = jiffies; |
| 862 | mod_timer(&sdata->u.ibss.timer, 0); | 867 | ieee80211_queue_work(&local->hw, &sdata->work); |
| 863 | } | 868 | } |
| 864 | mutex_unlock(&local->iflist_mtx); | 869 | mutex_unlock(&local->iflist_mtx); |
| 865 | } | 870 | } |
| 866 | 871 | ||
| 867 | ieee80211_rx_result | ||
| 868 | ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | ||
| 869 | { | ||
| 870 | struct ieee80211_local *local = sdata->local; | ||
| 871 | struct ieee80211_mgmt *mgmt; | ||
| 872 | u16 fc; | ||
| 873 | |||
| 874 | if (skb->len < 24) | ||
| 875 | return RX_DROP_MONITOR; | ||
| 876 | |||
| 877 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
| 878 | fc = le16_to_cpu(mgmt->frame_control); | ||
| 879 | |||
| 880 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
| 881 | case IEEE80211_STYPE_PROBE_RESP: | ||
| 882 | case IEEE80211_STYPE_BEACON: | ||
| 883 | case IEEE80211_STYPE_PROBE_REQ: | ||
| 884 | case IEEE80211_STYPE_AUTH: | ||
| 885 | skb_queue_tail(&sdata->u.ibss.skb_queue, skb); | ||
| 886 | ieee80211_queue_work(&local->hw, &sdata->u.ibss.work); | ||
| 887 | return RX_QUEUED; | ||
| 888 | } | ||
| 889 | |||
| 890 | return RX_DROP_MONITOR; | ||
| 891 | } | ||
| 892 | |||
| 893 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | 872 | int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, |
| 894 | struct cfg80211_ibss_params *params) | 873 | struct cfg80211_ibss_params *params) |
| 895 | { | 874 | { |
| 896 | struct sk_buff *skb; | 875 | struct sk_buff *skb; |
| 897 | 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 | |||
| 898 | if (params->bssid) { | 888 | if (params->bssid) { |
| 899 | memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); | 889 | memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN); |
| 900 | sdata->u.ibss.fixed_bssid = true; | 890 | sdata->u.ibss.fixed_bssid = true; |
| @@ -902,6 +892,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
| 902 | sdata->u.ibss.fixed_bssid = false; | 892 | sdata->u.ibss.fixed_bssid = false; |
| 903 | 893 | ||
| 904 | sdata->u.ibss.privacy = params->privacy; | 894 | sdata->u.ibss.privacy = params->privacy; |
| 895 | sdata->u.ibss.basic_rates = params->basic_rates; | ||
| 905 | 896 | ||
| 906 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | 897 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
| 907 | 898 | ||
| @@ -922,34 +913,18 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
| 922 | sdata->u.ibss.ie_len = params->ie_len; | 913 | sdata->u.ibss.ie_len = params->ie_len; |
| 923 | } | 914 | } |
| 924 | 915 | ||
| 925 | skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + | ||
| 926 | 36 /* bitrates */ + | ||
| 927 | 34 /* SSID */ + | ||
| 928 | 3 /* DS params */ + | ||
| 929 | 4 /* IBSS params */ + | ||
| 930 | params->ie_len); | ||
| 931 | if (!skb) | ||
| 932 | return -ENOMEM; | ||
| 933 | |||
| 934 | sdata->u.ibss.skb = skb; | 916 | sdata->u.ibss.skb = skb; |
| 935 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; | 917 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; |
| 936 | sdata->u.ibss.ibss_join_req = jiffies; | 918 | sdata->u.ibss.ibss_join_req = jiffies; |
| 937 | 919 | ||
| 938 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); | 920 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); |
| 939 | |||
| 940 | /* | ||
| 941 | * The ssid_len setting below is used to see whether | ||
| 942 | * we are active, and we need all other settings | ||
| 943 | * before that may get visible. | ||
| 944 | */ | ||
| 945 | mb(); | ||
| 946 | |||
| 947 | sdata->u.ibss.ssid_len = params->ssid_len; | 921 | sdata->u.ibss.ssid_len = params->ssid_len; |
| 948 | 922 | ||
| 949 | ieee80211_recalc_idle(sdata->local); | 923 | ieee80211_recalc_idle(sdata->local); |
| 950 | 924 | ||
| 951 | set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); | 925 | ieee80211_queue_work(&sdata->local->hw, &sdata->work); |
| 952 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.ibss.work); | 926 | |
| 927 | mutex_unlock(&sdata->u.ibss.mtx); | ||
| 953 | 928 | ||
| 954 | return 0; | 929 | return 0; |
| 955 | } | 930 | } |
| @@ -957,11 +932,33 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
| 957 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | 932 | int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) |
| 958 | { | 933 | { |
| 959 | struct sk_buff *skb; | 934 | struct sk_buff *skb; |
| 935 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
| 936 | struct ieee80211_local *local = sdata->local; | ||
| 937 | struct cfg80211_bss *cbss; | ||
| 938 | u16 capability; | ||
| 939 | int active_ibss; | ||
| 960 | 940 | ||
| 961 | del_timer_sync(&sdata->u.ibss.timer); | 941 | mutex_lock(&sdata->u.ibss.mtx); |
| 962 | clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); | 942 | |
| 963 | cancel_work_sync(&sdata->u.ibss.work); | 943 | active_ibss = ieee80211_sta_active_ibss(sdata); |
| 964 | clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request); | 944 | |
| 945 | if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { | ||
| 946 | capability = WLAN_CAPABILITY_IBSS; | ||
| 947 | |||
| 948 | if (ifibss->privacy) | ||
| 949 | capability |= WLAN_CAPABILITY_PRIVACY; | ||
| 950 | |||
| 951 | cbss = cfg80211_get_bss(local->hw.wiphy, ifibss->channel, | ||
| 952 | ifibss->bssid, ifibss->ssid, | ||
| 953 | ifibss->ssid_len, WLAN_CAPABILITY_IBSS | | ||
| 954 | WLAN_CAPABILITY_PRIVACY, | ||
| 955 | capability); | ||
| 956 | |||
| 957 | if (cbss) { | ||
| 958 | cfg80211_unlink_bss(local->hw.wiphy, cbss); | ||
| 959 | cfg80211_put_bss(cbss); | ||
| 960 | } | ||
| 961 | } | ||
| 965 | 962 | ||
| 966 | sta_info_flush(sdata->local, sdata); | 963 | sta_info_flush(sdata->local, sdata); |
| 967 | 964 | ||
| @@ -975,10 +972,14 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
| 975 | synchronize_rcu(); | 972 | synchronize_rcu(); |
| 976 | kfree_skb(skb); | 973 | kfree_skb(skb); |
| 977 | 974 | ||
| 978 | skb_queue_purge(&sdata->u.ibss.skb_queue); | 975 | skb_queue_purge(&sdata->skb_queue); |
| 979 | memset(sdata->u.ibss.bssid, 0, ETH_ALEN); | 976 | memset(sdata->u.ibss.bssid, 0, ETH_ALEN); |
| 980 | sdata->u.ibss.ssid_len = 0; | 977 | sdata->u.ibss.ssid_len = 0; |
| 981 | 978 | ||
| 979 | del_timer_sync(&sdata->u.ibss.timer); | ||
| 980 | |||
| 981 | mutex_unlock(&sdata->u.ibss.mtx); | ||
| 982 | |||
| 982 | ieee80211_recalc_idle(sdata->local); | 983 | ieee80211_recalc_idle(sdata->local); |
| 983 | 984 | ||
| 984 | return 0; | 985 | return 0; |
