mwifiex: support downloading IEs from tail

Earlier only RSN, WPA and channel switch IEs from tail buffer would
be downloaded to FW.
This patch adds support for downloading more IEs from tail buffer.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Cathy Luo <cluo@marvell.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
This commit is contained in:
Avinash Patil 2015-06-03 16:59:42 +05:30 committed by Kalle Valo
parent 8a73dd6398
commit e4f59aca0b

View file

@ -320,63 +320,81 @@ static int mwifiex_set_mgmt_beacon_data_ies(struct mwifiex_private *priv,
/* This function parses head and tail IEs, from cfg80211_beacon_data and sets
* these IE to FW.
*/
static int mwifiex_uap_set_head_tail_ies(struct mwifiex_private *priv,
struct cfg80211_beacon_data *info)
static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
struct cfg80211_beacon_data *info)
{
struct mwifiex_ie *gen_ie;
struct ieee_types_header *rsn_ie = NULL, *wpa_ie = NULL;
struct ieee_types_header *chsw_ie = NULL;
struct ieee_types_header *hdr;
struct ieee80211_vendor_ie *vendorhdr;
u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
const u8 *vendor_ie;
int left_len, parsed_len = 0;
if (!info->tail || !info->tail_len)
return 0;
gen_ie = kzalloc(sizeof(*gen_ie), GFP_KERNEL);
if (!gen_ie)
return -ENOMEM;
left_len = info->tail_len;
/* Many IEs are generated in FW by parsing bss configuration.
* Let's not add them here; else we may end up duplicating these IEs
*/
while (left_len > sizeof(struct ieee_types_header)) {
hdr = (void *)(info->tail + parsed_len);
switch (hdr->element_id) {
case WLAN_EID_SSID:
case WLAN_EID_SUPP_RATES:
case WLAN_EID_COUNTRY:
case WLAN_EID_PWR_CONSTRAINT:
case WLAN_EID_EXT_SUPP_RATES:
case WLAN_EID_HT_CAPABILITY:
case WLAN_EID_HT_OPERATION:
case WLAN_EID_VHT_CAPABILITY:
case WLAN_EID_VHT_OPERATION:
case WLAN_EID_VENDOR_SPECIFIC:
break;
default:
memcpy(gen_ie->ie_buffer + ie_len, hdr,
hdr->len + sizeof(struct ieee_types_header));
ie_len += hdr->len + sizeof(struct ieee_types_header);
break;
}
left_len -= hdr->len + sizeof(struct ieee_types_header);
parsed_len += hdr->len + sizeof(struct ieee_types_header);
}
/* parse only WPA vendor IE from tail, WMM IE is configured by
* bss_config command
*/
vendorhdr = (void *)cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
WLAN_OUI_TYPE_MICROSOFT_WPA,
info->tail, info->tail_len);
if (vendorhdr) {
memcpy(gen_ie->ie_buffer + ie_len, vendorhdr,
vendorhdr->len + sizeof(struct ieee_types_header));
ie_len += vendorhdr->len + sizeof(struct ieee_types_header);
}
if (!ie_len) {
kfree(gen_ie);
return 0;
}
gen_ie->ie_index = cpu_to_le16(gen_idx);
gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
MGMT_MASK_PROBE_RESP |
MGMT_MASK_ASSOC_RESP);
gen_ie->ie_length = cpu_to_le16(ie_len);
if (info->tail && info->tail_len) {
rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN,
info->tail, info->tail_len);
if (rsn_ie) {
memcpy(gen_ie->ie_buffer, rsn_ie, rsn_ie->len + 2);
ie_len = rsn_ie->len + 2;
gen_ie->ie_length = cpu_to_le16(ie_len);
}
vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
WLAN_OUI_TYPE_MICROSOFT_WPA,
info->tail,
info->tail_len);
if (vendor_ie) {
wpa_ie = (struct ieee_types_header *)vendor_ie;
memcpy(gen_ie->ie_buffer + ie_len,
wpa_ie, wpa_ie->len + 2);
ie_len += wpa_ie->len + 2;
gen_ie->ie_length = cpu_to_le16(ie_len);
}
chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH,
info->tail, info->tail_len);
if (chsw_ie) {
memcpy(gen_ie->ie_buffer + ie_len,
chsw_ie, chsw_ie->len + 2);
ie_len += chsw_ie->len + 2;
gen_ie->ie_length = cpu_to_le16(ie_len);
}
}
if (rsn_ie || wpa_ie || chsw_ie) {
if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL,
NULL, NULL, NULL)) {
kfree(gen_ie);
return -1;
}
priv->gen_idx = gen_idx;
if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL,
NULL, NULL)) {
kfree(gen_ie);
return -1;
}
priv->gen_idx = gen_idx;
kfree(gen_ie);
return 0;
}
@ -390,7 +408,7 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
{
int ret;
ret = mwifiex_uap_set_head_tail_ies(priv, info);
ret = mwifiex_uap_parse_tail_ies(priv, info);
return ret;
return mwifiex_set_mgmt_beacon_data_ies(priv, info);