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:
parent
8a73dd6398
commit
e4f59aca0b
|
@ -320,63 +320,81 @@ done:
|
||||||
/* This function parses head and tail IEs, from cfg80211_beacon_data and sets
|
/* This function parses head and tail IEs, from cfg80211_beacon_data and sets
|
||||||
* these IE to FW.
|
* these IE to FW.
|
||||||
*/
|
*/
|
||||||
static int mwifiex_uap_set_head_tail_ies(struct mwifiex_private *priv,
|
static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv,
|
||||||
struct cfg80211_beacon_data *info)
|
struct cfg80211_beacon_data *info)
|
||||||
{
|
{
|
||||||
struct mwifiex_ie *gen_ie;
|
struct mwifiex_ie *gen_ie;
|
||||||
struct ieee_types_header *rsn_ie = NULL, *wpa_ie = NULL;
|
struct ieee_types_header *hdr;
|
||||||
struct ieee_types_header *chsw_ie = NULL;
|
struct ieee80211_vendor_ie *vendorhdr;
|
||||||
u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0;
|
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);
|
gen_ie = kzalloc(sizeof(*gen_ie), GFP_KERNEL);
|
||||||
if (!gen_ie)
|
if (!gen_ie)
|
||||||
return -ENOMEM;
|
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->ie_index = cpu_to_le16(gen_idx);
|
||||||
gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
|
gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON |
|
||||||
MGMT_MASK_PROBE_RESP |
|
MGMT_MASK_PROBE_RESP |
|
||||||
MGMT_MASK_ASSOC_RESP);
|
MGMT_MASK_ASSOC_RESP);
|
||||||
|
gen_ie->ie_length = cpu_to_le16(ie_len);
|
||||||
|
|
||||||
if (info->tail && info->tail_len) {
|
if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL,
|
||||||
rsn_ie = (void *)cfg80211_find_ie(WLAN_EID_RSN,
|
NULL, NULL)) {
|
||||||
info->tail, info->tail_len);
|
kfree(gen_ie);
|
||||||
if (rsn_ie) {
|
return -1;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
priv->gen_idx = gen_idx;
|
||||||
kfree(gen_ie);
|
kfree(gen_ie);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -390,7 +408,7 @@ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = mwifiex_uap_set_head_tail_ies(priv, info);
|
ret = mwifiex_uap_parse_tail_ies(priv, info);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return mwifiex_set_mgmt_beacon_data_ies(priv, info);
|
return mwifiex_set_mgmt_beacon_data_ies(priv, info);
|
||||||
|
|
Loading…
Reference in New Issue