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.c82
1 files changed, 64 insertions, 18 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index a53feac4618c..a06b6ee63c07 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -305,7 +305,13 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw)
305 305
306 trace_api_restart_hw(local); 306 trace_api_restart_hw(local);
307 307
308 /* use this reason, __ieee80211_resume will unblock it */ 308 WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
309 "%s called with hardware scan in progress\n", __func__);
310
311 if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning)))
312 ieee80211_scan_cancel(local);
313
314 /* use this reason, ieee80211_reconfig will unblock it */
309 ieee80211_stop_queues_by_reason(hw, 315 ieee80211_stop_queues_by_reason(hw,
310 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 316 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
311 317
@@ -339,9 +345,6 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
339 struct ieee80211_if_managed *ifmgd; 345 struct ieee80211_if_managed *ifmgd;
340 int c = 0; 346 int c = 0;
341 347
342 if (!netif_running(ndev))
343 return NOTIFY_DONE;
344
345 /* Make sure it's our interface that got changed */ 348 /* Make sure it's our interface that got changed */
346 if (!wdev) 349 if (!wdev)
347 return NOTIFY_DONE; 350 return NOTIFY_DONE;
@@ -352,6 +355,9 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
352 sdata = IEEE80211_DEV_TO_SUB_IF(ndev); 355 sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
353 bss_conf = &sdata->vif.bss_conf; 356 bss_conf = &sdata->vif.bss_conf;
354 357
358 if (!ieee80211_sdata_running(sdata))
359 return NOTIFY_DONE;
360
355 /* ARP filtering is only supported in managed mode */ 361 /* ARP filtering is only supported in managed mode */
356 if (sdata->vif.type != NL80211_IFTYPE_STATION) 362 if (sdata->vif.type != NL80211_IFTYPE_STATION)
357 return NOTIFY_DONE; 363 return NOTIFY_DONE;
@@ -622,6 +628,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
622 /* mac80211 always supports monitor */ 628 /* mac80211 always supports monitor */
623 local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); 629 local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
624 630
631#ifndef CONFIG_MAC80211_MESH
632 /* mesh depends on Kconfig, but drivers should set it if they want */
633 local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT);
634#endif
635
636 /* mac80211 supports control port protocol changing */
637 local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL;
638
625 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) 639 if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
626 local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 640 local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
627 else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) 641 else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
@@ -657,13 +671,40 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
657 if (local->hw.wiphy->max_scan_ie_len) 671 if (local->hw.wiphy->max_scan_ie_len)
658 local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; 672 local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len;
659 673
660 local->hw.wiphy->cipher_suites = cipher_suites; 674 /* Set up cipher suites unless driver already did */
661 local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 675 if (!local->hw.wiphy->cipher_suites) {
662 if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) 676 local->hw.wiphy->cipher_suites = cipher_suites;
663 local->hw.wiphy->n_cipher_suites--; 677 local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
678 if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE))
679 local->hw.wiphy->n_cipher_suites--;
680 }
664 if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) { 681 if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) {
665 local->hw.wiphy->cipher_suites += 2; 682 if (local->hw.wiphy->cipher_suites == cipher_suites) {
666 local->hw.wiphy->n_cipher_suites -= 2; 683 local->hw.wiphy->cipher_suites += 2;
684 local->hw.wiphy->n_cipher_suites -= 2;
685 } else {
686 u32 *suites;
687 int r, w = 0;
688
689 /* Filter out WEP */
690
691 suites = kmemdup(
692 local->hw.wiphy->cipher_suites,
693 sizeof(u32) * local->hw.wiphy->n_cipher_suites,
694 GFP_KERNEL);
695 if (!suites)
696 return -ENOMEM;
697 for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
698 u32 suite = local->hw.wiphy->cipher_suites[r];
699 if (suite == WLAN_CIPHER_SUITE_WEP40 ||
700 suite == WLAN_CIPHER_SUITE_WEP104)
701 continue;
702 suites[w++] = suite;
703 }
704 local->hw.wiphy->cipher_suites = suites;
705 local->hw.wiphy->n_cipher_suites = w;
706 local->wiphy_ciphers_allocated = true;
707 }
667 } 708 }
668 709
669 result = wiphy_register(local->hw.wiphy); 710 result = wiphy_register(local->hw.wiphy);
@@ -713,16 +754,16 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
713 754
714 result = ieee80211_wep_init(local); 755 result = ieee80211_wep_init(local);
715 if (result < 0) 756 if (result < 0)
716 printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", 757 wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n",
717 wiphy_name(local->hw.wiphy), result); 758 result);
718 759
719 rtnl_lock(); 760 rtnl_lock();
720 761
721 result = ieee80211_init_rate_ctrl_alg(local, 762 result = ieee80211_init_rate_ctrl_alg(local,
722 hw->rate_control_algorithm); 763 hw->rate_control_algorithm);
723 if (result < 0) { 764 if (result < 0) {
724 printk(KERN_DEBUG "%s: Failed to initialize rate control " 765 wiphy_debug(local->hw.wiphy,
725 "algorithm\n", wiphy_name(local->hw.wiphy)); 766 "Failed to initialize rate control algorithm\n");
726 goto fail_rate; 767 goto fail_rate;
727 } 768 }
728 769
@@ -731,8 +772,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
731 result = ieee80211_if_add(local, "wlan%d", NULL, 772 result = ieee80211_if_add(local, "wlan%d", NULL,
732 NL80211_IFTYPE_STATION, NULL); 773 NL80211_IFTYPE_STATION, NULL);
733 if (result) 774 if (result)
734 printk(KERN_WARNING "%s: Failed to add default virtual iface\n", 775 wiphy_warn(local->hw.wiphy,
735 wiphy_name(local->hw.wiphy)); 776 "Failed to add default virtual iface\n");
736 } 777 }
737 778
738 rtnl_unlock(); 779 rtnl_unlock();
@@ -778,6 +819,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
778 fail_workqueue: 819 fail_workqueue:
779 wiphy_unregister(local->hw.wiphy); 820 wiphy_unregister(local->hw.wiphy);
780 fail_wiphy_register: 821 fail_wiphy_register:
822 if (local->wiphy_ciphers_allocated)
823 kfree(local->hw.wiphy->cipher_suites);
781 kfree(local->int_scan_req); 824 kfree(local->int_scan_req);
782 return result; 825 return result;
783} 826}
@@ -807,6 +850,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
807 850
808 rtnl_unlock(); 851 rtnl_unlock();
809 852
853 cancel_work_sync(&local->restart_work);
810 cancel_work_sync(&local->reconfig_filter); 854 cancel_work_sync(&local->reconfig_filter);
811 855
812 ieee80211_clear_tx_pending(local); 856 ieee80211_clear_tx_pending(local);
@@ -815,8 +859,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
815 859
816 if (skb_queue_len(&local->skb_queue) || 860 if (skb_queue_len(&local->skb_queue) ||
817 skb_queue_len(&local->skb_queue_unreliable)) 861 skb_queue_len(&local->skb_queue_unreliable))
818 printk(KERN_WARNING "%s: skb_queue not empty\n", 862 wiphy_warn(local->hw.wiphy, "skb_queue not empty\n");
819 wiphy_name(local->hw.wiphy));
820 skb_queue_purge(&local->skb_queue); 863 skb_queue_purge(&local->skb_queue);
821 skb_queue_purge(&local->skb_queue_unreliable); 864 skb_queue_purge(&local->skb_queue_unreliable);
822 865
@@ -835,6 +878,9 @@ void ieee80211_free_hw(struct ieee80211_hw *hw)
835 mutex_destroy(&local->iflist_mtx); 878 mutex_destroy(&local->iflist_mtx);
836 mutex_destroy(&local->mtx); 879 mutex_destroy(&local->mtx);
837 880
881 if (local->wiphy_ciphers_allocated)
882 kfree(local->hw.wiphy->cipher_suites);
883
838 wiphy_free(local->hw.wiphy); 884 wiphy_free(local->hw.wiphy);
839} 885}
840EXPORT_SYMBOL(ieee80211_free_hw); 886EXPORT_SYMBOL(ieee80211_free_hw);