diff options
Diffstat (limited to 'net/mac80211/main.c')
-rw-r--r-- | net/mac80211/main.c | 179 |
1 files changed, 159 insertions, 20 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index ded5c3843e06..fda97bb0018b 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -99,11 +99,13 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
99 | int ret = 0; | 99 | int ret = 0; |
100 | int power; | 100 | int power; |
101 | enum nl80211_channel_type channel_type; | 101 | enum nl80211_channel_type channel_type; |
102 | u32 offchannel_flag; | ||
102 | 103 | ||
103 | might_sleep(); | 104 | might_sleep(); |
104 | 105 | ||
105 | scan_chan = local->scan_channel; | 106 | scan_chan = local->scan_channel; |
106 | 107 | ||
108 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | ||
107 | if (scan_chan) { | 109 | if (scan_chan) { |
108 | chan = scan_chan; | 110 | chan = scan_chan; |
109 | channel_type = NL80211_CHAN_NO_HT; | 111 | channel_type = NL80211_CHAN_NO_HT; |
@@ -117,8 +119,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
117 | channel_type = local->_oper_channel_type; | 119 | channel_type = local->_oper_channel_type; |
118 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; | 120 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; |
119 | } | 121 | } |
122 | offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | ||
120 | 123 | ||
121 | if (chan != local->hw.conf.channel || | 124 | if (offchannel_flag || chan != local->hw.conf.channel || |
122 | channel_type != local->hw.conf.channel_type) { | 125 | channel_type != local->hw.conf.channel_type) { |
123 | local->hw.conf.channel = chan; | 126 | local->hw.conf.channel = chan; |
124 | local->hw.conf.channel_type = channel_type; | 127 | local->hw.conf.channel_type = channel_type; |
@@ -302,7 +305,16 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) | |||
302 | 305 | ||
303 | trace_api_restart_hw(local); | 306 | trace_api_restart_hw(local); |
304 | 307 | ||
305 | /* use this reason, __ieee80211_resume will unblock it */ | 308 | /* wait for scan work complete */ |
309 | flush_workqueue(local->workqueue); | ||
310 | |||
311 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), | ||
312 | "%s called with hardware scan in progress\n", __func__); | ||
313 | |||
314 | if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning))) | ||
315 | ieee80211_scan_cancel(local); | ||
316 | |||
317 | /* use this reason, ieee80211_reconfig will unblock it */ | ||
306 | ieee80211_stop_queues_by_reason(hw, | 318 | ieee80211_stop_queues_by_reason(hw, |
307 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 319 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
308 | 320 | ||
@@ -336,9 +348,6 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
336 | struct ieee80211_if_managed *ifmgd; | 348 | struct ieee80211_if_managed *ifmgd; |
337 | int c = 0; | 349 | int c = 0; |
338 | 350 | ||
339 | if (!netif_running(ndev)) | ||
340 | return NOTIFY_DONE; | ||
341 | |||
342 | /* Make sure it's our interface that got changed */ | 351 | /* Make sure it's our interface that got changed */ |
343 | if (!wdev) | 352 | if (!wdev) |
344 | return NOTIFY_DONE; | 353 | return NOTIFY_DONE; |
@@ -349,11 +358,14 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
349 | sdata = IEEE80211_DEV_TO_SUB_IF(ndev); | 358 | sdata = IEEE80211_DEV_TO_SUB_IF(ndev); |
350 | bss_conf = &sdata->vif.bss_conf; | 359 | bss_conf = &sdata->vif.bss_conf; |
351 | 360 | ||
361 | if (!ieee80211_sdata_running(sdata)) | ||
362 | return NOTIFY_DONE; | ||
363 | |||
352 | /* ARP filtering is only supported in managed mode */ | 364 | /* ARP filtering is only supported in managed mode */ |
353 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 365 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
354 | return NOTIFY_DONE; | 366 | return NOTIFY_DONE; |
355 | 367 | ||
356 | idev = sdata->dev->ip_ptr; | 368 | idev = __in_dev_get_rtnl(sdata->dev); |
357 | if (!idev) | 369 | if (!idev) |
358 | return NOTIFY_DONE; | 370 | return NOTIFY_DONE; |
359 | 371 | ||
@@ -390,6 +402,80 @@ static int ieee80211_ifa_changed(struct notifier_block *nb, | |||
390 | } | 402 | } |
391 | #endif | 403 | #endif |
392 | 404 | ||
405 | static int ieee80211_napi_poll(struct napi_struct *napi, int budget) | ||
406 | { | ||
407 | struct ieee80211_local *local = | ||
408 | container_of(napi, struct ieee80211_local, napi); | ||
409 | |||
410 | return local->ops->napi_poll(&local->hw, budget); | ||
411 | } | ||
412 | |||
413 | void ieee80211_napi_schedule(struct ieee80211_hw *hw) | ||
414 | { | ||
415 | struct ieee80211_local *local = hw_to_local(hw); | ||
416 | |||
417 | napi_schedule(&local->napi); | ||
418 | } | ||
419 | EXPORT_SYMBOL(ieee80211_napi_schedule); | ||
420 | |||
421 | void ieee80211_napi_complete(struct ieee80211_hw *hw) | ||
422 | { | ||
423 | struct ieee80211_local *local = hw_to_local(hw); | ||
424 | |||
425 | napi_complete(&local->napi); | ||
426 | } | ||
427 | EXPORT_SYMBOL(ieee80211_napi_complete); | ||
428 | |||
429 | /* There isn't a lot of sense in it, but you can transmit anything you like */ | ||
430 | static const struct ieee80211_txrx_stypes | ||
431 | ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | ||
432 | [NL80211_IFTYPE_ADHOC] = { | ||
433 | .tx = 0xffff, | ||
434 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4), | ||
435 | }, | ||
436 | [NL80211_IFTYPE_STATION] = { | ||
437 | .tx = 0xffff, | ||
438 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
439 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4), | ||
440 | }, | ||
441 | [NL80211_IFTYPE_AP] = { | ||
442 | .tx = 0xffff, | ||
443 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
444 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
445 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
446 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
447 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
448 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
449 | BIT(IEEE80211_STYPE_ACTION >> 4), | ||
450 | }, | ||
451 | [NL80211_IFTYPE_AP_VLAN] = { | ||
452 | /* copy AP */ | ||
453 | .tx = 0xffff, | ||
454 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
455 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
456 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
457 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
458 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
459 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
460 | BIT(IEEE80211_STYPE_ACTION >> 4), | ||
461 | }, | ||
462 | [NL80211_IFTYPE_P2P_CLIENT] = { | ||
463 | .tx = 0xffff, | ||
464 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
465 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4), | ||
466 | }, | ||
467 | [NL80211_IFTYPE_P2P_GO] = { | ||
468 | .tx = 0xffff, | ||
469 | .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | | ||
470 | BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | | ||
471 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | | ||
472 | BIT(IEEE80211_STYPE_DISASSOC >> 4) | | ||
473 | BIT(IEEE80211_STYPE_AUTH >> 4) | | ||
474 | BIT(IEEE80211_STYPE_DEAUTH >> 4) | | ||
475 | BIT(IEEE80211_STYPE_ACTION >> 4), | ||
476 | }, | ||
477 | }; | ||
478 | |||
393 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | 479 | struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, |
394 | const struct ieee80211_ops *ops) | 480 | const struct ieee80211_ops *ops) |
395 | { | 481 | { |
@@ -419,6 +505,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
419 | if (!wiphy) | 505 | if (!wiphy) |
420 | return NULL; | 506 | return NULL; |
421 | 507 | ||
508 | wiphy->mgmt_stypes = ieee80211_default_mgmt_stypes; | ||
509 | |||
422 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | | 510 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | |
423 | WIPHY_FLAG_4ADDR_AP | | 511 | WIPHY_FLAG_4ADDR_AP | |
424 | WIPHY_FLAG_4ADDR_STATION; | 512 | WIPHY_FLAG_4ADDR_STATION; |
@@ -455,7 +543,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
455 | __hw_addr_init(&local->mc_list); | 543 | __hw_addr_init(&local->mc_list); |
456 | 544 | ||
457 | mutex_init(&local->iflist_mtx); | 545 | mutex_init(&local->iflist_mtx); |
458 | mutex_init(&local->scan_mtx); | 546 | mutex_init(&local->mtx); |
459 | 547 | ||
460 | mutex_init(&local->key_mtx); | 548 | mutex_init(&local->key_mtx); |
461 | spin_lock_init(&local->filter_lock); | 549 | spin_lock_init(&local->filter_lock); |
@@ -494,6 +582,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
494 | skb_queue_head_init(&local->skb_queue); | 582 | skb_queue_head_init(&local->skb_queue); |
495 | skb_queue_head_init(&local->skb_queue_unreliable); | 583 | skb_queue_head_init(&local->skb_queue_unreliable); |
496 | 584 | ||
585 | /* init dummy netdev for use w/ NAPI */ | ||
586 | init_dummy_netdev(&local->napi_dev); | ||
587 | |||
497 | return local_to_hw(local); | 588 | return local_to_hw(local); |
498 | } | 589 | } |
499 | EXPORT_SYMBOL(ieee80211_alloc_hw); | 590 | EXPORT_SYMBOL(ieee80211_alloc_hw); |
@@ -506,6 +597,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
506 | int channels, max_bitrates; | 597 | int channels, max_bitrates; |
507 | bool supp_ht; | 598 | bool supp_ht; |
508 | static const u32 cipher_suites[] = { | 599 | static const u32 cipher_suites[] = { |
600 | /* keep WEP first, it may be removed below */ | ||
509 | WLAN_CIPHER_SUITE_WEP40, | 601 | WLAN_CIPHER_SUITE_WEP40, |
510 | WLAN_CIPHER_SUITE_WEP104, | 602 | WLAN_CIPHER_SUITE_WEP104, |
511 | WLAN_CIPHER_SUITE_TKIP, | 603 | WLAN_CIPHER_SUITE_TKIP, |
@@ -554,6 +646,14 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
554 | /* mac80211 always supports monitor */ | 646 | /* mac80211 always supports monitor */ |
555 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); | 647 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); |
556 | 648 | ||
649 | #ifndef CONFIG_MAC80211_MESH | ||
650 | /* mesh depends on Kconfig, but drivers should set it if they want */ | ||
651 | local->hw.wiphy->interface_modes &= ~BIT(NL80211_IFTYPE_MESH_POINT); | ||
652 | #endif | ||
653 | |||
654 | /* mac80211 supports control port protocol changing */ | ||
655 | local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; | ||
656 | |||
557 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 657 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) |
558 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 658 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
559 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) | 659 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) |
@@ -589,10 +689,41 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
589 | if (local->hw.wiphy->max_scan_ie_len) | 689 | if (local->hw.wiphy->max_scan_ie_len) |
590 | local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; | 690 | local->hw.wiphy->max_scan_ie_len -= local->scan_ies_len; |
591 | 691 | ||
592 | local->hw.wiphy->cipher_suites = cipher_suites; | 692 | /* Set up cipher suites unless driver already did */ |
593 | local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 693 | if (!local->hw.wiphy->cipher_suites) { |
594 | if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) | 694 | local->hw.wiphy->cipher_suites = cipher_suites; |
595 | local->hw.wiphy->n_cipher_suites--; | 695 | local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |
696 | if (!(local->hw.flags & IEEE80211_HW_MFP_CAPABLE)) | ||
697 | local->hw.wiphy->n_cipher_suites--; | ||
698 | } | ||
699 | if (IS_ERR(local->wep_tx_tfm) || IS_ERR(local->wep_rx_tfm)) { | ||
700 | if (local->hw.wiphy->cipher_suites == cipher_suites) { | ||
701 | local->hw.wiphy->cipher_suites += 2; | ||
702 | local->hw.wiphy->n_cipher_suites -= 2; | ||
703 | } else { | ||
704 | u32 *suites; | ||
705 | int r, w = 0; | ||
706 | |||
707 | /* Filter out WEP */ | ||
708 | |||
709 | suites = kmemdup( | ||
710 | local->hw.wiphy->cipher_suites, | ||
711 | sizeof(u32) * local->hw.wiphy->n_cipher_suites, | ||
712 | GFP_KERNEL); | ||
713 | if (!suites) | ||
714 | return -ENOMEM; | ||
715 | for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { | ||
716 | u32 suite = local->hw.wiphy->cipher_suites[r]; | ||
717 | if (suite == WLAN_CIPHER_SUITE_WEP40 || | ||
718 | suite == WLAN_CIPHER_SUITE_WEP104) | ||
719 | continue; | ||
720 | suites[w++] = suite; | ||
721 | } | ||
722 | local->hw.wiphy->cipher_suites = suites; | ||
723 | local->hw.wiphy->n_cipher_suites = w; | ||
724 | local->wiphy_ciphers_allocated = true; | ||
725 | } | ||
726 | } | ||
596 | 727 | ||
597 | result = wiphy_register(local->hw.wiphy); | 728 | result = wiphy_register(local->hw.wiphy); |
598 | if (result < 0) | 729 | if (result < 0) |
@@ -641,16 +772,16 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
641 | 772 | ||
642 | result = ieee80211_wep_init(local); | 773 | result = ieee80211_wep_init(local); |
643 | if (result < 0) | 774 | if (result < 0) |
644 | printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n", | 775 | wiphy_debug(local->hw.wiphy, "Failed to initialize wep: %d\n", |
645 | wiphy_name(local->hw.wiphy), result); | 776 | result); |
646 | 777 | ||
647 | rtnl_lock(); | 778 | rtnl_lock(); |
648 | 779 | ||
649 | result = ieee80211_init_rate_ctrl_alg(local, | 780 | result = ieee80211_init_rate_ctrl_alg(local, |
650 | hw->rate_control_algorithm); | 781 | hw->rate_control_algorithm); |
651 | if (result < 0) { | 782 | if (result < 0) { |
652 | printk(KERN_DEBUG "%s: Failed to initialize rate control " | 783 | wiphy_debug(local->hw.wiphy, |
653 | "algorithm\n", wiphy_name(local->hw.wiphy)); | 784 | "Failed to initialize rate control algorithm\n"); |
654 | goto fail_rate; | 785 | goto fail_rate; |
655 | } | 786 | } |
656 | 787 | ||
@@ -659,8 +790,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
659 | result = ieee80211_if_add(local, "wlan%d", NULL, | 790 | result = ieee80211_if_add(local, "wlan%d", NULL, |
660 | NL80211_IFTYPE_STATION, NULL); | 791 | NL80211_IFTYPE_STATION, NULL); |
661 | if (result) | 792 | if (result) |
662 | printk(KERN_WARNING "%s: Failed to add default virtual iface\n", | 793 | wiphy_warn(local->hw.wiphy, |
663 | wiphy_name(local->hw.wiphy)); | 794 | "Failed to add default virtual iface\n"); |
664 | } | 795 | } |
665 | 796 | ||
666 | rtnl_unlock(); | 797 | rtnl_unlock(); |
@@ -683,6 +814,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
683 | goto fail_ifa; | 814 | goto fail_ifa; |
684 | #endif | 815 | #endif |
685 | 816 | ||
817 | netif_napi_add(&local->napi_dev, &local->napi, ieee80211_napi_poll, | ||
818 | local->hw.napi_weight); | ||
819 | |||
686 | return 0; | 820 | return 0; |
687 | 821 | ||
688 | #ifdef CONFIG_INET | 822 | #ifdef CONFIG_INET |
@@ -703,6 +837,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
703 | fail_workqueue: | 837 | fail_workqueue: |
704 | wiphy_unregister(local->hw.wiphy); | 838 | wiphy_unregister(local->hw.wiphy); |
705 | fail_wiphy_register: | 839 | fail_wiphy_register: |
840 | if (local->wiphy_ciphers_allocated) | ||
841 | kfree(local->hw.wiphy->cipher_suites); | ||
706 | kfree(local->int_scan_req); | 842 | kfree(local->int_scan_req); |
707 | return result; | 843 | return result; |
708 | } | 844 | } |
@@ -738,6 +874,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
738 | */ | 874 | */ |
739 | del_timer_sync(&local->work_timer); | 875 | del_timer_sync(&local->work_timer); |
740 | 876 | ||
877 | cancel_work_sync(&local->restart_work); | ||
741 | cancel_work_sync(&local->reconfig_filter); | 878 | cancel_work_sync(&local->reconfig_filter); |
742 | 879 | ||
743 | ieee80211_clear_tx_pending(local); | 880 | ieee80211_clear_tx_pending(local); |
@@ -746,8 +883,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
746 | 883 | ||
747 | if (skb_queue_len(&local->skb_queue) || | 884 | if (skb_queue_len(&local->skb_queue) || |
748 | skb_queue_len(&local->skb_queue_unreliable)) | 885 | skb_queue_len(&local->skb_queue_unreliable)) |
749 | printk(KERN_WARNING "%s: skb_queue not empty\n", | 886 | wiphy_warn(local->hw.wiphy, "skb_queue not empty\n"); |
750 | wiphy_name(local->hw.wiphy)); | ||
751 | skb_queue_purge(&local->skb_queue); | 887 | skb_queue_purge(&local->skb_queue); |
752 | skb_queue_purge(&local->skb_queue_unreliable); | 888 | skb_queue_purge(&local->skb_queue_unreliable); |
753 | 889 | ||
@@ -764,7 +900,10 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) | |||
764 | struct ieee80211_local *local = hw_to_local(hw); | 900 | struct ieee80211_local *local = hw_to_local(hw); |
765 | 901 | ||
766 | mutex_destroy(&local->iflist_mtx); | 902 | mutex_destroy(&local->iflist_mtx); |
767 | mutex_destroy(&local->scan_mtx); | 903 | mutex_destroy(&local->mtx); |
904 | |||
905 | if (local->wiphy_ciphers_allocated) | ||
906 | kfree(local->hw.wiphy->cipher_suites); | ||
768 | 907 | ||
769 | wiphy_free(local->hw.wiphy); | 908 | wiphy_free(local->hw.wiphy); |
770 | } | 909 | } |