diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 4752a76e13cd95f1bfc428661abf56c165c421f7..faefc23750d3cd5046942f18f40c51d4db3ed4f7 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -888,6 +888,26 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, key_usage, key->seq_len); ar->def_txkey_index = key_index; + + if (ar->nw_type == AP_NETWORK && !pairwise && + (key_type == TKIP_CRYPT || key_type == AES_CRYPT) && params) { + ar->ap_mode_bkey.valid = true; + ar->ap_mode_bkey.key_index = key_index; + ar->ap_mode_bkey.key_type = key_type; + ar->ap_mode_bkey.key_len = key->key_len; + memcpy(ar->ap_mode_bkey.key, key->key, key->key_len); + if (!test_bit(CONNECTED, &ar->flag)) { + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group " + "key configuration until AP mode has been " + "started\n"); + /* + * The key will be set in ath6kl_connect_ap_mode() once + * the connected event is received from the target. + */ + return 0; + } + } + status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index, key_type, key_usage, key->key_len, key->seq, key->key, KEY_OP_INIT_VAL, @@ -997,6 +1017,9 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy, if (ar->prwise_crypto == WEP_CRYPT) key_usage |= TX_USAGE; + if (ar->nw_type == AP_NETWORK && !test_bit(CONNECTED, &ar->flag)) + return 0; /* Delay until AP mode has been started */ + status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index, ar->prwise_crypto, key_usage, key->key_len, key->seq, key->key, @@ -1495,6 +1518,8 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev, if (!add) return 0; + ar->ap_mode_bkey.valid = false; + /* TODO: * info->interval * info->dtim_period @@ -1580,7 +1605,11 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev, p.dot11_auth_mode = ar->dot11_auth_mode; p.ch = cpu_to_le16(ar->next_chan); - return ath6kl_wmi_ap_profile_commit(ar->wmi, &p); + res = ath6kl_wmi_ap_profile_commit(ar->wmi, &p); + if (res < 0) + return res; + + return 0; } static int ath6kl_add_beacon(struct wiphy *wiphy, struct net_device *dev, diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 00d0add2ab46c800a6e5277debf7a0f116d6d231..f0b1dff1ce09b9fe8abf2605d9ccac983e5ecc70 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -335,26 +335,13 @@ struct ath6kl_mbox_info { #define ATH6KL_KEY_RECV 0x02 #define ATH6KL_KEY_DEFAULT 0x80 /* default xmit key */ -/* - * WPA/RSN get/set key request. Specify the key/cipher - * type and whether the key is to be used for sending and/or - * receiving. The key index should be set only when working - * with global keys (use IEEE80211_KEYIX_NONE for ``no index''). - * Otherwise a unicast/pairwise key is specified by the bssid - * (on a station) or mac address (on an ap). They key length - * must include any MIC key data; otherwise it should be no - * more than ATH6KL_KEYBUF_SIZE. - */ +/* Initial group key for AP mode */ struct ath6kl_req_key { - u8 ik_type; /* key/cipher type */ - u8 ik_pad; - u16 ik_keyix; /* key index */ - u8 ik_keylen; /* key length in bytes */ - u8 ik_flags; - u8 ik_macaddr[ETH_ALEN]; - u64 ik_keyrsc; /* key receive sequence counter */ - u64 ik_keytsc; /* key transmit sequence counter */ - u8 ik_keydata[ATH6KL_KEYBUF_SIZE + ATH6KL_MICBUF_SIZE]; + bool valid; + u8 key_index; + int key_type; + u8 key[WLAN_MAX_KEY_LEN]; + u8 key_len; }; /* Flag info */ diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 89e29ead254fabd55c5bc5c6d7c1bece1b35c683..a19caecdfdeb8221c7585d8876c475f6ceeb4fb8 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -437,11 +437,15 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid, size_t ies_len = 0; struct station_info sinfo; struct ath6kl_req_key *ik; - enum crypto_type keyType = NONE_CRYPT; + int res; + u8 key_rsc[ATH6KL_KEY_SEQ_LEN]; if (memcmp(dev->dev_addr, bssid, ETH_ALEN) == 0) { ik = &ar->ap_mode_bkey; + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "AP mode started on %u MHz\n", + channel); + switch (ar->auth_mode) { case NONE_AUTH: if (ar->prwise_crypto == WEP_CRYPT) @@ -450,26 +454,26 @@ static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid, case WPA_PSK_AUTH: case WPA2_PSK_AUTH: case (WPA_PSK_AUTH|WPA2_PSK_AUTH): - switch (ik->ik_type) { - case ATH6KL_CIPHER_TKIP: - keyType = TKIP_CRYPT; - break; - case ATH6KL_CIPHER_AES_CCM: - keyType = AES_CRYPT; + if (!ik->valid) break; - default: - goto skip_key; + + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for " + "the initial group key for AP mode\n"); + memset(key_rsc, 0, sizeof(key_rsc)); + res = ath6kl_wmi_addkey_cmd( + ar->wmi, ik->key_index, ik->key_type, + GROUP_USAGE, ik->key_len, key_rsc, ik->key, + KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG); + if (res) { + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed " + "addkey failed: %d\n", res); } - ath6kl_wmi_addkey_cmd(ar->wmi, ik->ik_keyix, keyType, - GROUP_USAGE, ik->ik_keylen, - (u8 *)&ik->ik_keyrsc, - ik->ik_keydata, - KEY_OP_INIT_VAL, ik->ik_macaddr, - SYNC_BOTH_WMIFLAG); break; } -skip_key: + + ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0); set_bit(CONNECTED, &ar->flag); + netif_carrier_on(ar->net_dev); return; } diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 0114a7136977836cbff89d74dcc6094549ec743b..d587f84b41cf4c1beba460498ba394d002e04a03 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -1764,6 +1764,10 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index, struct wmi_add_cipher_key_cmd *cmd; int ret; + ath6kl_dbg(ATH6KL_DBG_WMI, "addkey cmd: key_index=%u key_type=%d " + "key_usage=%d key_len=%d key_op_ctrl=%d\n", + key_index, key_type, key_usage, key_len, key_op_ctrl); + if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) || (key_material == NULL)) return -EINVAL;