aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211
diff options
context:
space:
mode:
authorHante Meuleman <meuleman@broadcom.com>2014-12-21 06:43:49 -0500
committerKalle Valo <kvalo@codeaurora.org>2015-01-06 13:28:53 -0500
commit118eb304d0554fbeab8567410bbece5bae533c23 (patch)
tree979d40093395d34913c537f803002e8a902e4021 /drivers/net/wireless/brcm80211
parentf714e58e19a567cc2659ea4645748ba06e3849a7 (diff)
brcmfmac: Fix WEP configuration for AP mode.
When a device is configured for AP mode and it is configured for WEP then the keys are plumbed first, followed by AP configuration. During configuration a down command is given to the firmware which will clear the configured keys. This patch reprograms the WEP keys after AP has been brought up. Reviewed-by: Arend Van Spriel <arend@broadcom.com> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Signed-off-by: Hante Meuleman <meuleman@broadcom.com> Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/brcm80211')
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c95
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h4
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/core.c3
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/core.h4
4 files changed, 76 insertions, 30 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
index 3aecc5f48719..11725518d19a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
@@ -452,16 +452,16 @@ static void convert_key_from_CPU(struct brcmf_wsec_key *key,
452} 452}
453 453
454static int 454static int
455send_key_to_dongle(struct net_device *ndev, struct brcmf_wsec_key *key) 455send_key_to_dongle(struct brcmf_if *ifp, struct brcmf_wsec_key *key)
456{ 456{
457 int err; 457 int err;
458 struct brcmf_wsec_key_le key_le; 458 struct brcmf_wsec_key_le key_le;
459 459
460 convert_key_from_CPU(key, &key_le); 460 convert_key_from_CPU(key, &key_le);
461 461
462 brcmf_netdev_wait_pend8021x(ndev); 462 brcmf_netdev_wait_pend8021x(ifp);
463 463
464 err = brcmf_fil_bsscfg_data_set(netdev_priv(ndev), "wsec_key", &key_le, 464 err = brcmf_fil_bsscfg_data_set(ifp, "wsec_key", &key_le,
465 sizeof(key_le)); 465 sizeof(key_le));
466 466
467 if (err) 467 if (err)
@@ -1670,7 +1670,7 @@ brcmf_set_sharedkey(struct net_device *ndev,
1670 brcmf_dbg(CONN, "key length (%d) key index (%d) algo (%d)\n", 1670 brcmf_dbg(CONN, "key length (%d) key index (%d) algo (%d)\n",
1671 key.len, key.index, key.algo); 1671 key.len, key.index, key.algo);
1672 brcmf_dbg(CONN, "key \"%s\"\n", key.data); 1672 brcmf_dbg(CONN, "key \"%s\"\n", key.data);
1673 err = send_key_to_dongle(ndev, &key); 1673 err = send_key_to_dongle(netdev_priv(ndev), &key);
1674 if (err) 1674 if (err)
1675 return err; 1675 return err;
1676 1676
@@ -2052,7 +2052,7 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
2052 /* check for key index change */ 2052 /* check for key index change */
2053 if (key.len == 0) { 2053 if (key.len == 0) {
2054 /* key delete */ 2054 /* key delete */
2055 err = send_key_to_dongle(ndev, &key); 2055 err = send_key_to_dongle(ifp, &key);
2056 if (err) 2056 if (err)
2057 brcmf_err("key delete error (%d)\n", err); 2057 brcmf_err("key delete error (%d)\n", err);
2058 } else { 2058 } else {
@@ -2108,7 +2108,7 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
2108 brcmf_err("Invalid cipher (0x%x)\n", params->cipher); 2108 brcmf_err("Invalid cipher (0x%x)\n", params->cipher);
2109 return -EINVAL; 2109 return -EINVAL;
2110 } 2110 }
2111 err = send_key_to_dongle(ndev, &key); 2111 err = send_key_to_dongle(ifp, &key);
2112 if (err) 2112 if (err)
2113 brcmf_err("wsec_key error (%d)\n", err); 2113 brcmf_err("wsec_key error (%d)\n", err);
2114 } 2114 }
@@ -2121,7 +2121,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
2121 struct key_params *params) 2121 struct key_params *params)
2122{ 2122{
2123 struct brcmf_if *ifp = netdev_priv(ndev); 2123 struct brcmf_if *ifp = netdev_priv(ndev);
2124 struct brcmf_wsec_key key; 2124 struct brcmf_wsec_key *key;
2125 s32 val; 2125 s32 val;
2126 s32 wsec; 2126 s32 wsec;
2127 s32 err = 0; 2127 s32 err = 0;
@@ -2132,54 +2132,62 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
2132 if (!check_vif_up(ifp->vif)) 2132 if (!check_vif_up(ifp->vif))
2133 return -EIO; 2133 return -EIO;
2134 2134
2135 if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) {
2136 /* we ignore this key index in this case */
2137 brcmf_err("invalid key index (%d)\n", key_idx);
2138 return -EINVAL;
2139 }
2140
2135 if (mac_addr && 2141 if (mac_addr &&
2136 (params->cipher != WLAN_CIPHER_SUITE_WEP40) && 2142 (params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
2137 (params->cipher != WLAN_CIPHER_SUITE_WEP104)) { 2143 (params->cipher != WLAN_CIPHER_SUITE_WEP104)) {
2138 brcmf_dbg(TRACE, "Exit"); 2144 brcmf_dbg(TRACE, "Exit");
2139 return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params); 2145 return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
2140 } 2146 }
2141 memset(&key, 0, sizeof(key));
2142 2147
2143 key.len = (u32) params->key_len; 2148 key = &ifp->vif->profile.key[key_idx];
2144 key.index = (u32) key_idx; 2149 memset(key, 0, sizeof(*key));
2145 2150
2146 if (key.len > sizeof(key.data)) { 2151 if (params->key_len > sizeof(key->data)) {
2147 brcmf_err("Too long key length (%u)\n", key.len); 2152 brcmf_err("Too long key length (%u)\n", params->key_len);
2148 err = -EINVAL; 2153 err = -EINVAL;
2149 goto done; 2154 goto done;
2150 } 2155 }
2151 memcpy(key.data, params->key, key.len); 2156 key->len = params->key_len;
2157 key->index = key_idx;
2152 2158
2153 key.flags = BRCMF_PRIMARY_KEY; 2159 memcpy(key->data, params->key, key->len);
2160
2161 key->flags = BRCMF_PRIMARY_KEY;
2154 switch (params->cipher) { 2162 switch (params->cipher) {
2155 case WLAN_CIPHER_SUITE_WEP40: 2163 case WLAN_CIPHER_SUITE_WEP40:
2156 key.algo = CRYPTO_ALGO_WEP1; 2164 key->algo = CRYPTO_ALGO_WEP1;
2157 val = WEP_ENABLED; 2165 val = WEP_ENABLED;
2158 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n"); 2166 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
2159 break; 2167 break;
2160 case WLAN_CIPHER_SUITE_WEP104: 2168 case WLAN_CIPHER_SUITE_WEP104:
2161 key.algo = CRYPTO_ALGO_WEP128; 2169 key->algo = CRYPTO_ALGO_WEP128;
2162 val = WEP_ENABLED; 2170 val = WEP_ENABLED;
2163 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n"); 2171 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
2164 break; 2172 break;
2165 case WLAN_CIPHER_SUITE_TKIP: 2173 case WLAN_CIPHER_SUITE_TKIP:
2166 if (!brcmf_is_apmode(ifp->vif)) { 2174 if (!brcmf_is_apmode(ifp->vif)) {
2167 brcmf_dbg(CONN, "Swapping RX/TX MIC key\n"); 2175 brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
2168 memcpy(keybuf, &key.data[24], sizeof(keybuf)); 2176 memcpy(keybuf, &key->data[24], sizeof(keybuf));
2169 memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); 2177 memcpy(&key->data[24], &key->data[16], sizeof(keybuf));
2170 memcpy(&key.data[16], keybuf, sizeof(keybuf)); 2178 memcpy(&key->data[16], keybuf, sizeof(keybuf));
2171 } 2179 }
2172 key.algo = CRYPTO_ALGO_TKIP; 2180 key->algo = CRYPTO_ALGO_TKIP;
2173 val = TKIP_ENABLED; 2181 val = TKIP_ENABLED;
2174 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n"); 2182 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
2175 break; 2183 break;
2176 case WLAN_CIPHER_SUITE_AES_CMAC: 2184 case WLAN_CIPHER_SUITE_AES_CMAC:
2177 key.algo = CRYPTO_ALGO_AES_CCM; 2185 key->algo = CRYPTO_ALGO_AES_CCM;
2178 val = AES_ENABLED; 2186 val = AES_ENABLED;
2179 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n"); 2187 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
2180 break; 2188 break;
2181 case WLAN_CIPHER_SUITE_CCMP: 2189 case WLAN_CIPHER_SUITE_CCMP:
2182 key.algo = CRYPTO_ALGO_AES_CCM; 2190 key->algo = CRYPTO_ALGO_AES_CCM;
2183 val = AES_ENABLED; 2191 val = AES_ENABLED;
2184 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n"); 2192 brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n");
2185 break; 2193 break;
@@ -2189,7 +2197,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
2189 goto done; 2197 goto done;
2190 } 2198 }
2191 2199
2192 err = send_key_to_dongle(ndev, &key); 2200 err = send_key_to_dongle(ifp, key);
2193 if (err) 2201 if (err)
2194 goto done; 2202 goto done;
2195 2203
@@ -2222,7 +2230,7 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
2222 if (!check_vif_up(ifp->vif)) 2230 if (!check_vif_up(ifp->vif))
2223 return -EIO; 2231 return -EIO;
2224 2232
2225 if (key_idx >= DOT11_MAX_DEFAULT_KEYS) { 2233 if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) {
2226 /* we ignore this key index in this case */ 2234 /* we ignore this key index in this case */
2227 brcmf_err("invalid key index (%d)\n", key_idx); 2235 brcmf_err("invalid key index (%d)\n", key_idx);
2228 return -EINVAL; 2236 return -EINVAL;
@@ -2237,7 +2245,7 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
2237 brcmf_dbg(CONN, "key index (%d)\n", key_idx); 2245 brcmf_dbg(CONN, "key index (%d)\n", key_idx);
2238 2246
2239 /* Set the new key/index */ 2247 /* Set the new key/index */
2240 err = send_key_to_dongle(ndev, &key); 2248 err = send_key_to_dongle(ifp, &key);
2241 2249
2242 brcmf_dbg(TRACE, "Exit\n"); 2250 brcmf_dbg(TRACE, "Exit\n");
2243 return err; 2251 return err;
@@ -2305,6 +2313,39 @@ brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
2305 return -EOPNOTSUPP; 2313 return -EOPNOTSUPP;
2306} 2314}
2307 2315
2316static void
2317brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp)
2318{
2319 s32 err;
2320 u8 key_idx;
2321 struct brcmf_wsec_key *key;
2322 s32 wsec;
2323
2324 for (key_idx = 0; key_idx < BRCMF_MAX_DEFAULT_KEYS; key_idx++) {
2325 key = &ifp->vif->profile.key[key_idx];
2326 if ((key->algo == CRYPTO_ALGO_WEP1) ||
2327 (key->algo == CRYPTO_ALGO_WEP128))
2328 break;
2329 }
2330 if (key_idx == BRCMF_MAX_DEFAULT_KEYS)
2331 return;
2332
2333 err = send_key_to_dongle(ifp, key);
2334 if (err) {
2335 brcmf_err("Setting WEP key failed (%d)\n", err);
2336 return;
2337 }
2338 err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
2339 if (err) {
2340 brcmf_err("get wsec error (%d)\n", err);
2341 return;
2342 }
2343 wsec |= WEP_ENABLED;
2344 err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
2345 if (err)
2346 brcmf_err("set wsec error (%d)\n", err);
2347}
2348
2308static s32 2349static s32
2309brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, 2350brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
2310 const u8 *mac, struct station_info *sinfo) 2351 const u8 *mac, struct station_info *sinfo)
@@ -4057,6 +4098,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
4057 brcmf_err("BRCMF_C_UP error (%d)\n", err); 4098 brcmf_err("BRCMF_C_UP error (%d)\n", err);
4058 goto exit; 4099 goto exit;
4059 } 4100 }
4101 /* On DOWN the firmware removes the WEP keys, reconfigure
4102 * them if they were set.
4103 */
4104 brcmf_cfg80211_reconfigure_wep(ifp);
4060 4105
4061 memset(&join_params, 0, sizeof(join_params)); 4106 memset(&join_params, 0, sizeof(join_params));
4062 /* join parameters starts with ssid */ 4107 /* join parameters starts with ssid */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
index 9e98b8d52757..a5242af9da4c 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
@@ -75,6 +75,8 @@
75 75
76#define BRCMF_VNDR_IE_P2PAF_SHIFT 12 76#define BRCMF_VNDR_IE_P2PAF_SHIFT 12
77 77
78#define BRCMF_MAX_DEFAULT_KEYS 4
79
78 80
79/** 81/**
80 * enum brcmf_scan_status - scan engine status 82 * enum brcmf_scan_status - scan engine status
@@ -125,11 +127,13 @@ struct brcmf_cfg80211_security {
125 * @ssid: ssid of associated/associating ap. 127 * @ssid: ssid of associated/associating ap.
126 * @bssid: bssid of joined/joining ibss. 128 * @bssid: bssid of joined/joining ibss.
127 * @sec: security information. 129 * @sec: security information.
130 * @key: key information
128 */ 131 */
129struct brcmf_cfg80211_profile { 132struct brcmf_cfg80211_profile {
130 struct brcmf_ssid ssid; 133 struct brcmf_ssid ssid;
131 u8 bssid[ETH_ALEN]; 134 u8 bssid[ETH_ALEN];
132 struct brcmf_cfg80211_security sec; 135 struct brcmf_cfg80211_security sec;
136 struct brcmf_wsec_key key[BRCMF_MAX_DEFAULT_KEYS];
133}; 137};
134 138
135/** 139/**
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c
index effe6d7831d9..e2a9e33f71ab 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c
@@ -1093,9 +1093,8 @@ static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
1093 return atomic_read(&ifp->pend_8021x_cnt); 1093 return atomic_read(&ifp->pend_8021x_cnt);
1094} 1094}
1095 1095
1096int brcmf_netdev_wait_pend8021x(struct net_device *ndev) 1096int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp)
1097{ 1097{
1098 struct brcmf_if *ifp = netdev_priv(ndev);
1099 int err; 1098 int err;
1100 1099
1101 err = wait_event_timeout(ifp->pend_8021x_wait, 1100 err = wait_event_timeout(ifp->pend_8021x_wait,
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h
index 23f74b139cc8..f2f7d3d1a8ef 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h
@@ -29,8 +29,6 @@
29/* For supporting multiple interfaces */ 29/* For supporting multiple interfaces */
30#define BRCMF_MAX_IFS 16 30#define BRCMF_MAX_IFS 16
31 31
32#define DOT11_MAX_DEFAULT_KEYS 4
33
34/* Small, medium and maximum buffer size for dcmd 32/* Small, medium and maximum buffer size for dcmd
35 */ 33 */
36#define BRCMF_DCMD_SMLEN 256 34#define BRCMF_DCMD_SMLEN 256
@@ -167,7 +165,7 @@ struct brcmf_skb_reorder_data {
167 u8 *reorder; 165 u8 *reorder;
168}; 166};
169 167
170int brcmf_netdev_wait_pend8021x(struct net_device *ndev); 168int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
171 169
172/* Return pointer to interface name */ 170/* Return pointer to interface name */
173char *brcmf_ifname(struct brcmf_pub *drvr, int idx); 171char *brcmf_ifname(struct brcmf_pub *drvr, int idx);