aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h12
-rw-r--r--net/mac80211/key.c10
-rw-r--r--net/mac80211/main.c65
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;