aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r--net/mac80211/main.c194
1 files changed, 172 insertions, 22 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index ded5c3843e06..22bc42b18991 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -54,6 +54,9 @@ void ieee80211_configure_filter(struct ieee80211_local *local)
54 if (local->monitors || local->scanning) 54 if (local->monitors || local->scanning)
55 new_flags |= FIF_BCN_PRBRESP_PROMISC; 55 new_flags |= FIF_BCN_PRBRESP_PROMISC;
56 56
57 if (local->fif_probe_req || local->probe_req_reg)
58 new_flags |= FIF_PROBE_REQ;
59
57 if (local->fif_fcsfail) 60 if (local->fif_fcsfail)
58 new_flags |= FIF_FCSFAIL; 61 new_flags |= FIF_FCSFAIL;
59 62
@@ -99,16 +102,19 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
99 int ret = 0; 102 int ret = 0;
100 int power; 103 int power;
101 enum nl80211_channel_type channel_type; 104 enum nl80211_channel_type channel_type;
105 u32 offchannel_flag;
102 106
103 might_sleep(); 107 might_sleep();
104 108
105 scan_chan = local->scan_channel; 109 scan_chan = local->scan_channel;
106 110
111 offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
107 if (scan_chan) { 112 if (scan_chan) {
108 chan = scan_chan; 113 chan = scan_chan;
109 channel_type = NL80211_CHAN_NO_HT; 114 channel_type = NL80211_CHAN_NO_HT;
110 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; 115 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
111 } else if (local->tmp_channel) { 116 } else if (local->tmp_channel &&
117 local->oper_channel != local->tmp_channel) {
112 chan = scan_chan = local->tmp_channel; 118 chan = scan_chan = local->tmp_channel;
113 channel_type = local->tmp_channel_type; 119 channel_type = local->tmp_channel_type;
114 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; 120 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
@@ -117,8 +123,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
117 channel_type = local->_oper_channel_type; 123 channel_type = local->_oper_channel_type;
118 local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; 124 local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
119 } 125 }
126 offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
120 127
121 if (chan != local->hw.conf.channel || 128 if (offchannel_flag || chan != local->hw.conf.channel ||
122 channel_type != local->hw.conf.channel_type) { 129 channel_type != local->hw.conf.channel_type) {
123 local->hw.conf.channel = chan; 130 local->hw.conf.channel = chan;
124 local->hw.conf.channel_type = channel_type; 131 local->hw.conf.channel_type = channel_type;
@@ -197,6 +204,8 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
197 sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; 204 sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
198 else if (sdata->vif.type == NL80211_IFTYPE_AP) 205 else if (sdata->vif.type == NL80211_IFTYPE_AP)
199 sdata->vif.bss_conf.bssid = sdata->vif.addr; 206 sdata->vif.bss_conf.bssid = sdata->vif.addr;
207 else if (sdata->vif.type == NL80211_IFTYPE_WDS)
208 sdata->vif.bss_conf.bssid = NULL;
200 else if (ieee80211_vif_is_mesh(&sdata->vif)) { 209 else if (ieee80211_vif_is_mesh(&sdata->vif)) {
201 sdata->vif.bss_conf.bssid = zero; 210 sdata->vif.bss_conf.bssid = zero;
202 } else { 211 } else {
@@ -207,6 +216,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
207 switch (sdata->vif.type) { 216 switch (sdata->vif.type) {
208 case NL80211_IFTYPE_AP: 217 case NL80211_IFTYPE_AP:
209 case NL80211_IFTYPE_ADHOC: 218 case NL80211_IFTYPE_ADHOC:
219 case NL80211_IFTYPE_WDS:
210 case NL80211_IFTYPE_MESH_POINT: 220 case NL80211_IFTYPE_MESH_POINT:
211 break; 221 break;
212 default: 222 default:
@@ -291,7 +301,16 @@ static void ieee80211_restart_work(struct work_struct *work)
291 struct ieee80211_local *local = 301 struct ieee80211_local *local =
292 container_of(work, struct ieee80211_local, restart_work); 302 container_of(work, struct ieee80211_local, restart_work);
293 303
304 /* wait for scan work complete */
305 flush_workqueue(local->workqueue);
306
307 mutex_lock(&local->mtx);
308 WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
309 "%s called with hardware scan in progress\n", __func__);
310 mutex_unlock(&local->mtx);
311
294 rtnl_lock(); 312 rtnl_lock();
313 ieee80211_scan_cancel(local);
295 ieee80211_reconfig(local); 314 ieee80211_reconfig(local);
296 rtnl_unlock(); 315 rtnl_unlock();
297} 316}
@@ -302,7 +321,7 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
302 321
303 trace_api_restart_hw(local); 322 trace_api_restart_hw(local);
304 323
305 /* use this reason, __ieee80211_resume will unblock it */ 324 /* use this reason, ieee80211_reconfig will unblock it */
306 ieee80211_stop_queues_by_reason(hw, 325 ieee80211_stop_queues_by_reason(hw,
307 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 326 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
308 327
@@ -316,7 +335,7 @@ static void ieee80211_recalc_smps_work(struct work_struct *work)
316 container_of(work, struct ieee80211_local, recalc_smps); 335 container_of(work, struct ieee80211_local, recalc_smps);
317 336
318 mutex_lock(&local->iflist_mtx); 337 mutex_lock(&local->iflist_mtx);
319 ieee80211_recalc_smps(local, NULL); 338 ieee80211_recalc_smps(local);
320 mutex_unlock(&local->iflist_mtx); 339 mutex_unlock(&local->iflist_mtx);
321} 340}
322 341
@@ -336,9 +355,6 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
336 struct ieee80211_if_managed *ifmgd; 355 struct ieee80211_if_managed *ifmgd;
337 int c = 0; 356 int c = 0;
338 357
339 if (!netif_running(ndev))
340 return NOTIFY_DONE;
341
342 /* Make sure it's our interface that got changed */ 358 /* Make sure it's our interface that got changed */
343 if (!wdev) 359 if (!wdev)
344 return NOTIFY_DONE; 360 return NOTIFY_DONE;
@@ -349,11 +365,14 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
349 sdata = IEEE80211_DEV_TO_SUB_IF(ndev); 365 sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
350 bss_conf = &sdata->vif.bss_conf; 366 bss_conf = &sdata->vif.bss_conf;
351 367
368 if (!ieee80211_sdata_running(sdata))
369 return NOTIFY_DONE;
370
352 /* ARP filtering is only supported in managed mode */ 371 /* ARP filtering is only supported in managed mode */
353 if (sdata->vif.type != NL80211_IFTYPE_STATION) 372 if (sdata->vif.type != NL80211_IFTYPE_STATION)
354 return NOTIFY_DONE; 373 return NOTIFY_DONE;
355 374
356 idev = sdata->dev->ip_ptr; 375 idev = __in_dev_get_rtnl(sdata->dev);
357 if (!idev) 376 if (!idev)
358 return NOTIFY_DONE; 377 return NOTIFY_DONE;
359 378
@@ -390,6 +409,80 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
390} 409}
391#endif 410#endif
392 411
412static int ieee80211_napi_poll(struct napi_struct *napi, int budget)
413{
414 struct ieee80211_local *local =
415 container_of(napi, struct ieee80211_local, napi);
416
417 return local->ops->napi_poll(&local->hw, budget);
418}
419
420void ieee80211_napi_schedule(struct ieee80211_hw *hw)
421{
422 struct ieee80211_local *local = hw_to_local(hw);
423
424 napi_schedule(&local->napi);
425}
426EXPORT_SYMBOL(ieee80211_napi_schedule);
427
428void ieee80211_napi_complete(struct ieee80211_hw *hw)
429{
430 struct ieee80211_local *local = hw_to_local(hw);
431
432 napi_complete(&local->napi);
433}
434EXPORT_SYMBOL(ieee80211_napi_complete);
435
436/* There isn't a lot of sense in it, but you can transmit anything you like */
437static const struct ieee80211_txrx_stypes
438ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
439 [NL80211_IFTYPE_ADHOC] = {
440 .tx = 0xffff,
441 .rx = BIT(IEEE80211_STYPE_ACTION >> 4),
442 },
443 [NL80211_IFTYPE_STATION] = {
444 .tx = 0xffff,
445 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
446 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
447 },
448 [NL80211_IFTYPE_AP] = {
449 .tx = 0xffff,
450 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
451 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
452 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
453 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
454 BIT(IEEE80211_STYPE_AUTH >> 4) |
455 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
456 BIT(IEEE80211_STYPE_ACTION >> 4),
457 },
458 [NL80211_IFTYPE_AP_VLAN] = {
459 /* copy AP */
460 .tx = 0xffff,
461 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
462 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
463 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
464 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
465 BIT(IEEE80211_STYPE_AUTH >> 4) |
466 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
467 BIT(IEEE80211_STYPE_ACTION >> 4),
468 },
469 [NL80211_IFTYPE_P2P_CLIENT] = {
470 .tx = 0xffff,
471 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
472 BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
473 },
474 [NL80211_IFTYPE_P2P_GO] = {
475 .tx = 0xffff,
476 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
477 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
478 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
479 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
480 BIT(IEEE80211_STYPE_AUTH >> 4) |
481 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
482 BIT(IEEE80211_STYPE_ACTION >> 4),
483 },
484};
485
393struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, 486struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
394 const struct ieee80211_ops *ops) 487 const struct ieee80211_ops *ops)
395{ 488{
@@ -419,6 +512,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
419 if (!wiphy) 512 if (!wiphy)
420 return NULL; 513 return NULL;
421 514
515 wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes;
516
422 wiphy->flags |= WIPHY_FLAG_NETNS_OK | 517 wiphy->flags |= WIPHY_FLAG_NETNS_OK |
423 WIPHY_FLAG_4ADDR_AP | 518 WIPHY_FLAG_4ADDR_AP |
424 WIPHY_FLAG_4ADDR_STATION; 519 WIPHY_FLAG_4ADDR_STATION;
@@ -444,6 +539,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
444 /* set up some defaults */ 539 /* set up some defaults */
445 local->hw.queues = 1; 540 local->hw.queues = 1;
446 local->hw.max_rates = 1; 541 local->hw.max_rates = 1;
542 local->hw.max_report_rates = 0;
447 local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; 543 local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
448 local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; 544 local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
449 local->user_power_level = -1; 545 local->user_power_level = -1;
@@ -455,7 +551,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
455 __hw_addr_init(&local->mc_list); 551 __hw_addr_init(&local->mc_list);
456 552
457 mutex_init(&local->iflist_mtx); 553 mutex_init(&local->iflist_mtx);
458 mutex_init(&local->scan_mtx); 554 mutex_init(&local->mtx);
459 555
460 mutex_init(&local->key_mtx); 556 mutex_init(&local->key_mtx);
461 spin_lock_init(&local->filter_lock); 557 spin_lock_init(&local->filter_lock);
@@ -494,6 +590,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
494 skb_queue_head_init(&local->skb_queue); 590 skb_queue_head_init(&local->skb_queue);
495 skb_queue_head_init(&local->skb_queue_unreliable); 591 skb_queue_head_init(&local->skb_queue_unreliable);
496 592
593 /* init dummy netdev for use w/ NAPI */
594 init_dummy_netdev(&local->napi_dev);
595
497 return local_to_hw(local); 596 return local_to_hw(local);
498} 597}
499EXPORT_SYMBOL(ieee80211_alloc_hw); 598EXPORT_SYMBOL(ieee80211_alloc_hw);
@@ -506,6 +605,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
506 int channels, max_bitrates; 605 int channels, max_bitrates;
507 bool supp_ht; 606 bool supp_ht;
508 static const u32 cipher_suites[] = { 607 static const u32 cipher_suites[] = {
608 /* keep WEP first, it may be removed below */
509 WLAN_CIPHER_SUITE_WEP40, 609 WLAN_CIPHER_SUITE_WEP40,
510 WLAN_CIPHER_SUITE_WEP104, 610 WLAN_CIPHER_SUITE_WEP104,
511 WLAN_CIPHER_SUITE_TKIP, 611 WLAN_CIPHER_SUITE_TKIP,
@@ -515,6 +615,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
515 WLAN_CIPHER_SUITE_AES_CMAC 615 WLAN_CIPHER_SUITE_AES_CMAC
516 }; 616 };
517 617
618 if (hw->max_report_rates == 0)
619 hw->max_report_rates = hw->max_rates;
620
518 /* 621 /*
519 * generic code guarantees at least one band, 622 * generic code guarantees at least one band,
520 * set this very early because much code assumes 623 * set this very early because much code assumes
@@ -554,6 +657,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
554 /* mac80211 always supports monitor */ 657 /* mac80211 always supports monitor */
555 local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); 658 local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
556 659
660#ifndef CONFIG_MAC80211_MESH
661 /* mesh depends on Kconfig, but drivers should set it if they want */
662 local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT);
663#endif
664
665 /* mac80211 supports control port protocol changing */
666 local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;
667
557 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) 668 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
558 local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 669 local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
559 else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) 670 else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
@@ -589,10 +700,41 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
589 if (local->hw.wiphy->max_scan_ie_len) 700 if (local->hw.wiphy->max_scan_ie_len)
590 local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; 701 local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;
591 702
592 local->hw.wiphy->cipher_suites = cipher_suites; 703 /* Set up cipher suites unless driver already did */
593 local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 704 if (!local->hw.wiphy->cipher_suites) {
594 if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) 705 local->hw.wiphy->cipher_suites = cipher_suites;
595 local->hw.wiphy->n_cipher_suites--; 706 local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
707 if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE))
708 local->hw.wiphy->n_cipher_suites--;
709 }
710 if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) {
711 if (local->hw.wiphy->cipher_suites == cipher_suites) {
712 local->hw.wiphy->cipher_suites += 2;
713 local->hw.wiphy->n_cipher_suites -= 2;
714 } else {
715 u32 *suites;
716 int r, w = 0;
717
718 /* Filter out WEP */
719
720 suites = kmemdup(
721 local->hw.wiphy->cipher_suites,
722 sizeof(u32) * local->hw.wiphy->n_cipher_suites,
723 GFP_KERNEL);
724 if (!suites)
725 return -ENOMEM;
726 for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
727 u32 suite = local->hw.wiphy->cipher_suites[r];
728 if (suite == WLAN_CIPHER_SUITE_WEP40 ||
729 suite == WLAN_CIPHER_SUITE_WEP104)
730 continue;
731 suites[w++] = suite;
732 }
733 local->hw.wiphy->cipher_suites = suites;
734 local->hw.wiphy->n_cipher_suites = w;
735 local->wiphy_ciphers_allocated = true;
736 }
737 }
596 738
597 result = wiphy_register(local->hw.wiphy); 739 result = wiphy_register(local->hw.wiphy);
598 if (result < 0) 740 if (result < 0)
@@ -641,16 +783,16 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
641 783
642 result = ieee80211_wep_init(local); 784 result = ieee80211_wep_init(local);
643 if (result < 0) 785 if (result < 0)
644 printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", 786 wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
645 wiphy_name(local->hw.wiphy), result); 787 result);
646 788
647 rtnl_lock(); 789 rtnl_lock();
648 790
649 result = ieee80211_init_rate_ctrl_alg(local, 791 result = ieee80211_init_rate_ctrl_alg(local,
650 hw->rate_control_algorithm); 792 hw->rate_control_algorithm);
651 if (result < 0) { 793 if (result < 0) {
652 printk(KERN_DEBUG "%s: Failed to initialize rate control " 794 wiphy_debug(local->hw.wiphy,
653 "algorithm\n", wiphy_name(local->hw.wiphy)); 795 "Failed to initialize rate control algorithm\n");
654 goto fail_rate; 796 goto fail_rate;
655 } 797 }
656 798
@@ -659,8 +801,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
659 result = ieee80211_if_add(local, "wlan%d", NULL, 801 result = ieee80211_if_add(local, "wlan%d", NULL,
660 NL80211_IFTYPE_STATION, NULL); 802 NL80211_IFTYPE_STATION, NULL);
661 if (result) 803 if (result)
662 printk(KERN_WARNING "%s: Failed to add default virtual iface\n", 804 wiphy_warn(local->hw.wiphy,
663 wiphy_name(local->hw.wiphy)); 805 "Failed to add default virtual iface\n");
664 } 806 }
665 807
666 rtnl_unlock(); 808 rtnl_unlock();
@@ -683,6 +825,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
683 goto fail_ifa; 825 goto fail_ifa;
684#endif 826#endif
685 827
828 netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll,
829 local->hw.napi_weight);
830
686 return 0; 831 return 0;
687 832
688#ifdef CONFIG_INET 833#ifdef CONFIG_INET
@@ -703,6 +848,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
703 fail_workqueue: 848 fail_workqueue:
704 wiphy_unregister(local->hw.wiphy); 849 wiphy_unregister(local->hw.wiphy);
705 fail_wiphy_register: 850 fail_wiphy_register:
851 if (local->wiphy_ciphers_allocated)
852 kfree(local->hw.wiphy->cipher_suites);
706 kfree(local->int_scan_req); 853 kfree(local->int_scan_req);
707 return result; 854 return result;
708} 855}
@@ -738,6 +885,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
738 */ 885 */
739 del_timer_sync(&local->work_timer); 886 del_timer_sync(&local->work_timer);
740 887
888 cancel_work_sync(&local->restart_work);
741 cancel_work_sync(&local->reconfig_filter); 889 cancel_work_sync(&local->reconfig_filter);
742 890
743 ieee80211_clear_tx_pending(local); 891 ieee80211_clear_tx_pending(local);
@@ -746,8 +894,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
746 894
747 if (skb_queue_len(&local->skb_queue) || 895 if (skb_queue_len(&local->skb_queue) ||
748 skb_queue_len(&local->skb_queue_unreliable)) 896 skb_queue_len(&local->skb_queue_unreliable))
749 printk(KERN_WARNING "%s: skb_queue not empty\n", 897 wiphy_warn(local->hw.wiphy, "skb_queue not empty\n");
750 wiphy_name(local->hw.wiphy));
751 skb_queue_purge(&local->skb_queue); 898 skb_queue_purge(&local->skb_queue);
752 skb_queue_purge(&local->skb_queue_unreliable); 899 skb_queue_purge(&local->skb_queue_unreliable);
753 900
@@ -764,7 +911,10 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
764 struct ieee80211_local *local = hw_to_local(hw); 911 struct ieee80211_local *local = hw_to_local(hw);
765 912
766 mutex_destroy(&local->iflist_mtx); 913 mutex_destroy(&local->iflist_mtx);
767 mutex_destroy(&local->scan_mtx); 914 mutex_destroy(&local->mtx);
915
916 if (local->wiphy_ciphers_allocated)
917 kfree(local->hw.wiphy->cipher_suites);
768 918
769 wiphy_free(local->hw.wiphy); 919 wiphy_free(local->hw.wiphy);
770} 920}