diff options
Diffstat (limited to 'net/mac80211/main.c')
| -rw-r--r-- | net/mac80211/main.c | 111 |
1 files changed, 68 insertions, 43 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6ab99da38db9..5e09d354c5a5 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -658,7 +658,6 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) | |||
| 658 | bool have_wep = !(IS_ERR(local->wep_tx_tfm) || | 658 | bool have_wep = !(IS_ERR(local->wep_tx_tfm) || |
| 659 | IS_ERR(local->wep_rx_tfm)); | 659 | IS_ERR(local->wep_rx_tfm)); |
| 660 | bool have_mfp = local->hw.flags & IEEE80211_HW_MFP_CAPABLE; | 660 | bool have_mfp = local->hw.flags & IEEE80211_HW_MFP_CAPABLE; |
| 661 | const struct ieee80211_cipher_scheme *cs = local->hw.cipher_schemes; | ||
| 662 | int n_suites = 0, r = 0, w = 0; | 661 | int n_suites = 0, r = 0, w = 0; |
| 663 | u32 *suites; | 662 | u32 *suites; |
| 664 | static const u32 cipher_suites[] = { | 663 | static const u32 cipher_suites[] = { |
| @@ -667,79 +666,109 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) | |||
| 667 | WLAN_CIPHER_SUITE_WEP104, | 666 | WLAN_CIPHER_SUITE_WEP104, |
| 668 | WLAN_CIPHER_SUITE_TKIP, | 667 | WLAN_CIPHER_SUITE_TKIP, |
| 669 | WLAN_CIPHER_SUITE_CCMP, | 668 | WLAN_CIPHER_SUITE_CCMP, |
| 669 | WLAN_CIPHER_SUITE_CCMP_256, | ||
| 670 | WLAN_CIPHER_SUITE_GCMP, | ||
| 671 | WLAN_CIPHER_SUITE_GCMP_256, | ||
| 670 | 672 | ||
| 671 | /* keep last -- depends on hw flags! */ | 673 | /* keep last -- depends on hw flags! */ |
| 672 | WLAN_CIPHER_SUITE_AES_CMAC | 674 | WLAN_CIPHER_SUITE_AES_CMAC, |
| 675 | WLAN_CIPHER_SUITE_BIP_CMAC_256, | ||
| 676 | WLAN_CIPHER_SUITE_BIP_GMAC_128, | ||
| 677 | WLAN_CIPHER_SUITE_BIP_GMAC_256, | ||
| 673 | }; | 678 | }; |
| 674 | 679 | ||
| 675 | /* Driver specifies the ciphers, we have nothing to do... */ | 680 | if (local->hw.flags & IEEE80211_HW_SW_CRYPTO_CONTROL || |
| 676 | if (local->hw.wiphy->cipher_suites && have_wep) | 681 | local->hw.wiphy->cipher_suites) { |
| 677 | return 0; | 682 | /* If the driver advertises, or doesn't support SW crypto, |
| 683 | * we only need to remove WEP if necessary. | ||
| 684 | */ | ||
| 685 | if (have_wep) | ||
| 686 | return 0; | ||
| 687 | |||
| 688 | /* well if it has _no_ ciphers ... fine */ | ||
| 689 | if (!local->hw.wiphy->n_cipher_suites) | ||
| 690 | return 0; | ||
| 691 | |||
| 692 | /* Driver provides cipher suites, but we need to exclude WEP */ | ||
| 693 | suites = kmemdup(local->hw.wiphy->cipher_suites, | ||
| 694 | sizeof(u32) * local->hw.wiphy->n_cipher_suites, | ||
| 695 | GFP_KERNEL); | ||
| 696 | if (!suites) | ||
| 697 | return -ENOMEM; | ||
| 698 | |||
| 699 | for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { | ||
| 700 | u32 suite = local->hw.wiphy->cipher_suites[r]; | ||
| 678 | 701 | ||
| 679 | /* Set up cipher suites if driver relies on mac80211 cipher defs */ | 702 | if (suite == WLAN_CIPHER_SUITE_WEP40 || |
| 680 | if (!local->hw.wiphy->cipher_suites && !cs) { | 703 | suite == WLAN_CIPHER_SUITE_WEP104) |
| 704 | continue; | ||
| 705 | suites[w++] = suite; | ||
| 706 | } | ||
| 707 | } else if (!local->hw.cipher_schemes) { | ||
| 708 | /* If the driver doesn't have cipher schemes, there's nothing | ||
| 709 | * else to do other than assign the (software supported and | ||
| 710 | * perhaps offloaded) cipher suites. | ||
| 711 | */ | ||
| 681 | local->hw.wiphy->cipher_suites = cipher_suites; | 712 | local->hw.wiphy->cipher_suites = cipher_suites; |
| 682 | local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 713 | local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |
| 683 | 714 | ||
| 684 | if (!have_mfp) | 715 | if (!have_mfp) |
| 685 | local->hw.wiphy->n_cipher_suites--; | 716 | local->hw.wiphy->n_cipher_suites -= 4; |
| 686 | 717 | ||
| 687 | if (!have_wep) { | 718 | if (!have_wep) { |
| 688 | local->hw.wiphy->cipher_suites += 2; | 719 | local->hw.wiphy->cipher_suites += 2; |
| 689 | local->hw.wiphy->n_cipher_suites -= 2; | 720 | local->hw.wiphy->n_cipher_suites -= 2; |
| 690 | } | 721 | } |
| 691 | 722 | ||
| 723 | /* not dynamically allocated, so just return */ | ||
| 692 | return 0; | 724 | return 0; |
| 693 | } | 725 | } else { |
| 726 | const struct ieee80211_cipher_scheme *cs; | ||
| 694 | 727 | ||
| 695 | if (!local->hw.wiphy->cipher_suites) { | 728 | cs = local->hw.cipher_schemes; |
| 696 | /* | 729 | |
| 697 | * Driver specifies cipher schemes only | 730 | /* Driver specifies cipher schemes only (but not cipher suites |
| 698 | * We start counting ciphers defined by schemes, TKIP and CCMP | 731 | * including the schemes) |
| 732 | * | ||
| 733 | * We start counting ciphers defined by schemes, TKIP, CCMP, | ||
| 734 | * CCMP-256, GCMP, and GCMP-256 | ||
| 699 | */ | 735 | */ |
| 700 | n_suites = local->hw.n_cipher_schemes + 2; | 736 | n_suites = local->hw.n_cipher_schemes + 5; |
| 701 | 737 | ||
| 702 | /* check if we have WEP40 and WEP104 */ | 738 | /* check if we have WEP40 and WEP104 */ |
| 703 | if (have_wep) | 739 | if (have_wep) |
| 704 | n_suites += 2; | 740 | n_suites += 2; |
| 705 | 741 | ||
| 706 | /* check if we have AES_CMAC */ | 742 | /* check if we have AES_CMAC, BIP-CMAC-256, BIP-GMAC-128, |
| 743 | * BIP-GMAC-256 | ||
| 744 | */ | ||
| 707 | if (have_mfp) | 745 | if (have_mfp) |
| 708 | n_suites++; | 746 | n_suites += 4; |
| 709 | 747 | ||
| 710 | suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL); | 748 | suites = kmalloc(sizeof(u32) * n_suites, GFP_KERNEL); |
| 711 | if (!suites) | 749 | if (!suites) |
| 712 | return -ENOMEM; | 750 | return -ENOMEM; |
| 713 | 751 | ||
| 714 | suites[w++] = WLAN_CIPHER_SUITE_CCMP; | 752 | suites[w++] = WLAN_CIPHER_SUITE_CCMP; |
| 753 | suites[w++] = WLAN_CIPHER_SUITE_CCMP_256; | ||
| 715 | suites[w++] = WLAN_CIPHER_SUITE_TKIP; | 754 | suites[w++] = WLAN_CIPHER_SUITE_TKIP; |
| 755 | suites[w++] = WLAN_CIPHER_SUITE_GCMP; | ||
| 756 | suites[w++] = WLAN_CIPHER_SUITE_GCMP_256; | ||
| 716 | 757 | ||
| 717 | if (have_wep) { | 758 | if (have_wep) { |
| 718 | suites[w++] = WLAN_CIPHER_SUITE_WEP40; | 759 | suites[w++] = WLAN_CIPHER_SUITE_WEP40; |
| 719 | suites[w++] = WLAN_CIPHER_SUITE_WEP104; | 760 | suites[w++] = WLAN_CIPHER_SUITE_WEP104; |
| 720 | } | 761 | } |
| 721 | 762 | ||
| 722 | if (have_mfp) | 763 | if (have_mfp) { |
| 723 | suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC; | 764 | suites[w++] = WLAN_CIPHER_SUITE_AES_CMAC; |
| 765 | suites[w++] = WLAN_CIPHER_SUITE_BIP_CMAC_256; | ||
| 766 | suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_128; | ||
| 767 | suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_256; | ||
| 768 | } | ||
| 724 | 769 | ||
| 725 | for (r = 0; r < local->hw.n_cipher_schemes; r++) | 770 | for (r = 0; r < local->hw.n_cipher_schemes; r++) |
| 726 | suites[w++] = cs[r].cipher; | 771 | suites[w++] = cs[r].cipher; |
| 727 | } else { | ||
| 728 | /* Driver provides cipher suites, but we need to exclude WEP */ | ||
| 729 | suites = kmemdup(local->hw.wiphy->cipher_suites, | ||
| 730 | sizeof(u32) * local->hw.wiphy->n_cipher_suites, | ||
| 731 | GFP_KERNEL); | ||
| 732 | if (!suites) | ||
| 733 | return -ENOMEM; | ||
| 734 | |||
| 735 | for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { | ||
| 736 | u32 suite = local->hw.wiphy->cipher_suites[r]; | ||
| 737 | |||
| 738 | if (suite == WLAN_CIPHER_SUITE_WEP40 || | ||
| 739 | suite == WLAN_CIPHER_SUITE_WEP104) | ||
| 740 | continue; | ||
| 741 | suites[w++] = suite; | ||
| 742 | } | ||
| 743 | } | 772 | } |
| 744 | 773 | ||
| 745 | local->hw.wiphy->cipher_suites = suites; | 774 | local->hw.wiphy->cipher_suites = suites; |
| @@ -916,10 +945,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 916 | } | 945 | } |
| 917 | } | 946 | } |
| 918 | 947 | ||
| 919 | WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) | ||
| 920 | && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK), | ||
| 921 | "U-APSD not supported with HW_PS_NULLFUNC_STACK\n"); | ||
| 922 | |||
| 923 | /* | 948 | /* |
| 924 | * Calculate scan IE length -- we need this to alloc | 949 | * Calculate scan IE length -- we need this to alloc |
| 925 | * memory and to subtract from the driver limit. It | 950 | * memory and to subtract from the driver limit. It |
| @@ -1045,10 +1070,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 1045 | ieee80211_max_network_latency; | 1070 | ieee80211_max_network_latency; |
| 1046 | result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, | 1071 | result = pm_qos_add_notifier(PM_QOS_NETWORK_LATENCY, |
| 1047 | &local->network_latency_notifier); | 1072 | &local->network_latency_notifier); |
| 1048 | if (result) { | 1073 | if (result) |
| 1049 | rtnl_lock(); | ||
| 1050 | goto fail_pm_qos; | 1074 | goto fail_pm_qos; |
| 1051 | } | ||
| 1052 | 1075 | ||
| 1053 | #ifdef CONFIG_INET | 1076 | #ifdef CONFIG_INET |
| 1054 | local->ifa_notifier.notifier_call = ieee80211_ifa_changed; | 1077 | local->ifa_notifier.notifier_call = ieee80211_ifa_changed; |
| @@ -1076,15 +1099,15 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 1076 | fail_ifa: | 1099 | fail_ifa: |
| 1077 | pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, | 1100 | pm_qos_remove_notifier(PM_QOS_NETWORK_LATENCY, |
| 1078 | &local->network_latency_notifier); | 1101 | &local->network_latency_notifier); |
| 1079 | rtnl_lock(); | ||
| 1080 | #endif | 1102 | #endif |
| 1081 | fail_pm_qos: | 1103 | fail_pm_qos: |
| 1082 | ieee80211_led_exit(local); | 1104 | rtnl_lock(); |
| 1105 | rate_control_deinitialize(local); | ||
| 1083 | ieee80211_remove_interfaces(local); | 1106 | ieee80211_remove_interfaces(local); |
| 1084 | fail_rate: | 1107 | fail_rate: |
| 1085 | rtnl_unlock(); | 1108 | rtnl_unlock(); |
| 1109 | ieee80211_led_exit(local); | ||
| 1086 | ieee80211_wep_free(local); | 1110 | ieee80211_wep_free(local); |
| 1087 | sta_info_stop(local); | ||
| 1088 | destroy_workqueue(local->workqueue); | 1111 | destroy_workqueue(local->workqueue); |
| 1089 | fail_workqueue: | 1112 | fail_workqueue: |
| 1090 | wiphy_unregister(local->hw.wiphy); | 1113 | wiphy_unregister(local->hw.wiphy); |
| @@ -1180,6 +1203,8 @@ void ieee80211_free_hw(struct ieee80211_hw *hw) | |||
| 1180 | 1203 | ||
| 1181 | kfree(rcu_access_pointer(local->tx_latency)); | 1204 | kfree(rcu_access_pointer(local->tx_latency)); |
| 1182 | 1205 | ||
| 1206 | sta_info_stop(local); | ||
| 1207 | |||
| 1183 | wiphy_free(local->hw.wiphy); | 1208 | wiphy_free(local->hw.wiphy); |
| 1184 | } | 1209 | } |
| 1185 | EXPORT_SYMBOL(ieee80211_free_hw); | 1210 | EXPORT_SYMBOL(ieee80211_free_hw); |
