diff options
-rw-r--r-- | include/net/mac80211.h | 12 | ||||
-rw-r--r-- | net/mac80211/key.c | 10 | ||||
-rw-r--r-- | net/mac80211/main.c | 65 |
3 files changed, 58 insertions, 29 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 275ee56152ad..33b87c50a4cf 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1634,6 +1634,12 @@ struct ieee80211_tx_control { | |||
1634 | * be created. It is expected user-space will create vifs as | 1634 | * be created. It is expected user-space will create vifs as |
1635 | * desired (and thus have them named as desired). | 1635 | * desired (and thus have them named as desired). |
1636 | * | 1636 | * |
1637 | * @IEEE80211_HW_SW_CRYPTO_CONTROL: The driver wants to control which of the | ||
1638 | * crypto algorithms can be done in software - so don't automatically | ||
1639 | * try to fall back to it if hardware crypto fails, but do so only if | ||
1640 | * the driver returns 1. This also forces the driver to advertise its | ||
1641 | * supported cipher suites. | ||
1642 | * | ||
1637 | * @IEEE80211_HW_QUEUE_CONTROL: The driver wants to control per-interface | 1643 | * @IEEE80211_HW_QUEUE_CONTROL: The driver wants to control per-interface |
1638 | * queue mapping in order to use different queues (not just one per AC) | 1644 | * queue mapping in order to use different queues (not just one per AC) |
1639 | * for different virtual interfaces. See the doc section on HW queue | 1645 | * for different virtual interfaces. See the doc section on HW queue |
@@ -1681,6 +1687,7 @@ enum ieee80211_hw_flags { | |||
1681 | IEEE80211_HW_MFP_CAPABLE = 1<<13, | 1687 | IEEE80211_HW_MFP_CAPABLE = 1<<13, |
1682 | IEEE80211_HW_WANT_MONITOR_VIF = 1<<14, | 1688 | IEEE80211_HW_WANT_MONITOR_VIF = 1<<14, |
1683 | IEEE80211_HW_NO_AUTO_VIF = 1<<15, | 1689 | IEEE80211_HW_NO_AUTO_VIF = 1<<15, |
1690 | IEEE80211_HW_SW_CRYPTO_CONTROL = 1<<16, | ||
1684 | /* free slots */ | 1691 | /* free slots */ |
1685 | IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18, | 1692 | IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18, |
1686 | IEEE80211_HW_CONNECTION_MONITOR = 1<<19, | 1693 | IEEE80211_HW_CONNECTION_MONITOR = 1<<19, |
@@ -1955,6 +1962,11 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
1955 | * added; if you return 0 then hw_key_idx must be assigned to the | 1962 | * added; if you return 0 then hw_key_idx must be assigned to the |
1956 | * hardware key index, you are free to use the full u8 range. | 1963 | * hardware key index, you are free to use the full u8 range. |
1957 | * | 1964 | * |
1965 | * Note that in the case that the @IEEE80211_HW_SW_CRYPTO_CONTROL flag is | ||
1966 | * set, mac80211 will not automatically fall back to software crypto if | ||
1967 | * enabling hardware crypto failed. The set_key() call may also return the | ||
1968 | * value 1 to permit this specific key/algorithm to be done in software. | ||
1969 | * | ||
1958 | * When the cmd is %DISABLE_KEY then it must succeed. | 1970 | * When the cmd is %DISABLE_KEY then it must succeed. |
1959 | * | 1971 | * |
1960 | * Note that it is permissible to not decrypt a frame even if a key | 1972 | * Note that it is permissible to not decrypt a frame even if a key |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index f8d9f0ee59bf..5167c53aa15f 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -90,7 +90,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
90 | { | 90 | { |
91 | struct ieee80211_sub_if_data *sdata; | 91 | struct ieee80211_sub_if_data *sdata; |
92 | struct sta_info *sta; | 92 | struct sta_info *sta; |
93 | int ret; | 93 | int ret = -EOPNOTSUPP; |
94 | 94 | ||
95 | might_sleep(); | 95 | might_sleep(); |
96 | 96 | ||
@@ -150,7 +150,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
150 | return 0; | 150 | return 0; |
151 | } | 151 | } |
152 | 152 | ||
153 | if (ret != -ENOSPC && ret != -EOPNOTSUPP) | 153 | if (ret != -ENOSPC && ret != -EOPNOTSUPP && ret != 1) |
154 | sdata_err(sdata, | 154 | sdata_err(sdata, |
155 | "failed to set key (%d, %pM) to hardware (%d)\n", | 155 | "failed to set key (%d, %pM) to hardware (%d)\n", |
156 | key->conf.keyidx, | 156 | key->conf.keyidx, |
@@ -163,7 +163,11 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) | |||
163 | case WLAN_CIPHER_SUITE_TKIP: | 163 | case WLAN_CIPHER_SUITE_TKIP: |
164 | case WLAN_CIPHER_SUITE_CCMP: | 164 | case WLAN_CIPHER_SUITE_CCMP: |
165 | case WLAN_CIPHER_SUITE_AES_CMAC: | 165 | case WLAN_CIPHER_SUITE_AES_CMAC: |
166 | /* all of these we can do in software */ | 166 | /* all of these we can do in software - if driver can */ |
167 | if (ret == 1) | ||
168 | return 0; | ||
169 | if (key->local->hw.flags & IEEE80211_HW_SW_CRYPTO_CONTROL) | ||
170 | return -EINVAL; | ||
167 | return 0; | 171 | return 0; |
168 | default: | 172 | default: |
169 | return -EINVAL; | 173 | return -EINVAL; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 46264cb6604b..ea6b82ac4f0b 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[] = { |
@@ -672,12 +671,38 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) | |||
672 | WLAN_CIPHER_SUITE_AES_CMAC | 671 | WLAN_CIPHER_SUITE_AES_CMAC |
673 | }; | 672 | }; |
674 | 673 | ||
675 | /* Driver specifies the ciphers, we have nothing to do... */ | 674 | if (local->hw.flags & IEEE80211_HW_SW_CRYPTO_CONTROL || |
676 | if (local->hw.wiphy->cipher_suites && have_wep) | 675 | local->hw.wiphy->cipher_suites) { |
677 | return 0; | 676 | /* If the driver advertises, or doesn't support SW crypto, |
677 | * we only need to remove WEP if necessary. | ||
678 | */ | ||
679 | if (have_wep) | ||
680 | return 0; | ||
681 | |||
682 | /* well if it has _no_ ciphers ... fine */ | ||
683 | if (!local->hw.wiphy->n_cipher_suites) | ||
684 | return 0; | ||
685 | |||
686 | /* Driver provides cipher suites, but we need to exclude WEP */ | ||
687 | suites = kmemdup(local->hw.wiphy->cipher_suites, | ||
688 | sizeof(u32) * local->hw.wiphy->n_cipher_suites, | ||
689 | GFP_KERNEL); | ||
690 | if (!suites) | ||
691 | return -ENOMEM; | ||
678 | 692 | ||
679 | /* Set up cipher suites if driver relies on mac80211 cipher defs */ | 693 | for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) { |
680 | if (!local->hw.wiphy->cipher_suites && !cs) { | 694 | u32 suite = local->hw.wiphy->cipher_suites[r]; |
695 | |||
696 | if (suite == WLAN_CIPHER_SUITE_WEP40 || | ||
697 | suite == WLAN_CIPHER_SUITE_WEP104) | ||
698 | continue; | ||
699 | suites[w++] = suite; | ||
700 | } | ||
701 | } else if (!local->hw.cipher_schemes) { | ||
702 | /* If the driver doesn't have cipher schemes, there's nothing | ||
703 | * else to do other than assign the (software supported and | ||
704 | * perhaps offloaded) cipher suites. | ||
705 | */ | ||
681 | local->hw.wiphy->cipher_suites = cipher_suites; | 706 | local->hw.wiphy->cipher_suites = cipher_suites; |
682 | local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); | 707 | local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); |
683 | 708 | ||
@@ -689,12 +714,16 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) | |||
689 | local->hw.wiphy->n_cipher_suites -= 2; | 714 | local->hw.wiphy->n_cipher_suites -= 2; |
690 | } | 715 | } |
691 | 716 | ||
717 | /* not dynamically allocated, so just return */ | ||
692 | return 0; | 718 | return 0; |
693 | } | 719 | } else { |
720 | const struct ieee80211_cipher_scheme *cs; | ||
694 | 721 | ||
695 | if (!local->hw.wiphy->cipher_suites) { | 722 | cs = local->hw.cipher_schemes; |
696 | /* | 723 | |
697 | * Driver specifies cipher schemes only | 724 | /* Driver specifies cipher schemes only (but not cipher suites |
725 | * including the schemes) | ||
726 | * | ||
698 | * We start counting ciphers defined by schemes, TKIP and CCMP | 727 | * We start counting ciphers defined by schemes, TKIP and CCMP |
699 | */ | 728 | */ |
700 | n_suites = local->hw.n_cipher_schemes + 2; | 729 | n_suites = local->hw.n_cipher_schemes + 2; |
@@ -724,22 +753,6 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) | |||
724 | 753 | ||
725 | for (r = 0; r < local->hw.n_cipher_schemes; r++) | 754 | for (r = 0; r < local->hw.n_cipher_schemes; r++) |
726 | suites[w++] = cs[r].cipher; | 755 | 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 | } | 756 | } |
744 | 757 | ||
745 | local->hw.wiphy->cipher_suites = suites; | 758 | local->hw.wiphy->cipher_suites = suites; |