aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>2012-04-09 11:21:20 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2012-04-09 11:33:07 -0400
commitd97c121bb23d32ef631c553d2656f8ccf8349507 (patch)
tree5ed670bed75b13c29a41fca6eeef255e46f6d569
parentdf90b36940019a879d08bc5e8a20daa0c9fe0122 (diff)
ath6kl: Fix 4-way handshake failure in AP and P2P GO mode
RSN capability field of RSN IE which is generated (which is what really advertised in beacon/probe response) differs from the one generated in wpa_supplicant. This inconsistency in rsn IE results in 4-way handshake failure. To fix this, configure rsn capability used in wpa_supplicant in firmware using a new wmi command, WMI_SET_IE_CMDID. There is a bit (ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE) in fw_capabilities to advertise this support to driver. Signed-off-by: Subramania Sharma <sharmat@qca.qualcomm.com> Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c64
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h3
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c23
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h17
4 files changed, 107 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 900993017d09..86d388f57708 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -2548,6 +2548,52 @@ static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev,
2548 return 0; 2548 return 0;
2549} 2549}
2550 2550
2551static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon,
2552 u8 *rsn_capab)
2553{
2554 const u8 *rsn_ie;
2555 size_t rsn_ie_len;
2556 u16 cnt;
2557
2558 if (!beacon->tail)
2559 return -EINVAL;
2560
2561 rsn_ie = cfg80211_find_ie(WLAN_EID_RSN, beacon->tail, beacon->tail_len);
2562 if (!rsn_ie)
2563 return -EINVAL;
2564
2565 rsn_ie_len = *(rsn_ie + 1);
2566 /* skip element id and length */
2567 rsn_ie += 2;
2568
2569 /* skip version, group cipher */
2570 if (rsn_ie_len < 6)
2571 return -EINVAL;
2572 rsn_ie += 6;
2573 rsn_ie_len -= 6;
2574
2575 /* skip pairwise cipher suite */
2576 if (rsn_ie_len < 2)
2577 return -EINVAL;
2578 cnt = *((u16 *) rsn_ie);
2579 rsn_ie += (2 + cnt * 4);
2580 rsn_ie_len -= (2 + cnt * 4);
2581
2582 /* skip akm suite */
2583 if (rsn_ie_len < 2)
2584 return -EINVAL;
2585 cnt = *((u16 *) rsn_ie);
2586 rsn_ie += (2 + cnt * 4);
2587 rsn_ie_len -= (2 + cnt * 4);
2588
2589 if (rsn_ie_len < 2)
2590 return -EINVAL;
2591
2592 memcpy(rsn_capab, rsn_ie, 2);
2593
2594 return 0;
2595}
2596
2551static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, 2597static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2552 struct cfg80211_ap_settings *info) 2598 struct cfg80211_ap_settings *info)
2553{ 2599{
@@ -2560,6 +2606,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2560 struct wmi_connect_cmd p; 2606 struct wmi_connect_cmd p;
2561 int res; 2607 int res;
2562 int i, ret; 2608 int i, ret;
2609 u16 rsn_capab = 0;
2563 2610
2564 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s:\n", __func__); 2611 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s:\n", __func__);
2565 2612
@@ -2700,6 +2747,23 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
2700 vif->next_ch_type != NL80211_CHAN_NO_HT)) 2747 vif->next_ch_type != NL80211_CHAN_NO_HT))
2701 return -EIO; 2748 return -EIO;
2702 2749
2750 /*
2751 * Get the PTKSA replay counter in the RSN IE. Supplicant
2752 * will use the RSN IE in M3 message and firmware has to
2753 * advertise the same in beacon/probe response. Send
2754 * the complete RSN IE capability field to firmware
2755 */
2756 if (!ath6kl_get_rsn_capab(&info->beacon, (u8 *) &rsn_capab) &&
2757 test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
2758 ar->fw_capabilities)) {
2759 res = ath6kl_wmi_set_ie_cmd(ar->wmi, vif->fw_vif_idx,
2760 WLAN_EID_RSN, WMI_RSN_IE_CAPB,
2761 (const u8 *) &rsn_capab,
2762 sizeof(rsn_capab));
2763 if (res < 0)
2764 return res;
2765 }
2766
2703 res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); 2767 res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p);
2704 if (res < 0) 2768 if (res < 0)
2705 return res; 2769 return res;
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 8e7e9480a786..9d67964a51dd 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -97,6 +97,9 @@ enum ath6kl_fw_capability {
97 */ 97 */
98 ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT, 98 ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT,
99 99
100 /* Firmware has support to override rsn cap of rsn ie */
101 ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE,
102
100 /* this needs to be last */ 103 /* this needs to be last */
101 ATH6KL_FW_CAPABILITY_MAX, 104 ATH6KL_FW_CAPABILITY_MAX,
102}; 105};
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index efd707e69255..7c8a9977faf5 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -3221,6 +3221,29 @@ int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type,
3221 NO_SYNC_WMIFLAG); 3221 NO_SYNC_WMIFLAG);
3222} 3222}
3223 3223
3224int ath6kl_wmi_set_ie_cmd(struct wmi *wmi, u8 if_idx, u8 ie_id, u8 ie_field,
3225 const u8 *ie_info, u8 ie_len)
3226{
3227 struct sk_buff *skb;
3228 struct wmi_set_ie_cmd *p;
3229
3230 skb = ath6kl_wmi_get_new_buf(sizeof(*p) + ie_len);
3231 if (!skb)
3232 return -ENOMEM;
3233
3234 ath6kl_dbg(ATH6KL_DBG_WMI, "set_ie_cmd: ie_id=%u ie_ie_field=%u ie_len=%u\n",
3235 ie_id, ie_field, ie_len);
3236 p = (struct wmi_set_ie_cmd *) skb->data;
3237 p->ie_id = ie_id;
3238 p->ie_field = ie_field;
3239 p->ie_len = ie_len;
3240 if (ie_info && ie_len > 0)
3241 memcpy(p->ie_info, ie_info, ie_len);
3242
3243 return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_IE_CMDID,
3244 NO_SYNC_WMIFLAG);
3245}
3246
3224int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable) 3247int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable)
3225{ 3248{
3226 struct sk_buff *skb; 3249 struct sk_buff *skb;
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index ee45d1022532..d3d2ab5c1689 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -426,6 +426,7 @@ enum wmi_cmd_id {
426 WMI_SET_FRAMERATES_CMDID, 426 WMI_SET_FRAMERATES_CMDID,
427 WMI_SET_AP_PS_CMDID, 427 WMI_SET_AP_PS_CMDID,
428 WMI_SET_QOS_SUPP_CMDID, 428 WMI_SET_QOS_SUPP_CMDID,
429 WMI_SET_IE_CMDID,
429 430
430 /* WMI_THIN_RESERVED_... mark the start and end 431 /* WMI_THIN_RESERVED_... mark the start and end
431 * values for WMI_THIN_RESERVED command IDs. These 432 * values for WMI_THIN_RESERVED command IDs. These
@@ -632,6 +633,11 @@ enum wmi_mgmt_frame_type {
632 WMI_NUM_MGMT_FRAME 633 WMI_NUM_MGMT_FRAME
633}; 634};
634 635
636enum wmi_ie_field_type {
637 WMI_RSN_IE_CAPB = 0x1,
638 WMI_IE_FULL = 0xFF, /* indicats full IE */
639};
640
635/* WMI_CONNECT_CMDID */ 641/* WMI_CONNECT_CMDID */
636enum network_type { 642enum network_type {
637 INFRA_NETWORK = 0x01, 643 INFRA_NETWORK = 0x01,
@@ -1926,6 +1932,14 @@ struct wmi_set_appie_cmd {
1926 u8 ie_info[0]; 1932 u8 ie_info[0];
1927} __packed; 1933} __packed;
1928 1934
1935struct wmi_set_ie_cmd {
1936 u8 ie_id;
1937 u8 ie_field; /* enum wmi_ie_field_type */
1938 u8 ie_len;
1939 u8 reserved;
1940 u8 ie_info[0];
1941} __packed;
1942
1929/* Notify the WSC registration status to the target */ 1943/* Notify the WSC registration status to the target */
1930#define WSC_REG_ACTIVE 1 1944#define WSC_REG_ACTIVE 1
1931#define WSC_REG_INACTIVE 0 1945#define WSC_REG_INACTIVE 0
@@ -2536,6 +2550,9 @@ int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 if_idx,
2536int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, 2550int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type,
2537 const u8 *ie, u8 ie_len); 2551 const u8 *ie, u8 ie_len);
2538 2552
2553int ath6kl_wmi_set_ie_cmd(struct wmi *wmi, u8 if_idx, u8 ie_id, u8 ie_field,
2554 const u8 *ie_info, u8 ie_len);
2555
2539/* P2P */ 2556/* P2P */
2540int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable); 2557int ath6kl_wmi_disable_11b_rates_cmd(struct wmi *wmi, bool disable);
2541 2558