diff options
author | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-11 10:41:07 +0300 |
---|---|---|
committer | José Pekkarinen <jose.pekkarinen@nokia.com> | 2016-04-13 08:17:18 +0300 |
commit | e09b41010ba33a20a87472ee821fa407a5b8da36 (patch) | |
tree | d10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/net/wireless/mwifiex/ie.c | |
parent | f93b97fd65072de626c074dbe099a1fff05ce060 (diff) |
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page.
During the rebasing, the following patch collided:
Force tick interrupt and get rid of softirq magic(I70131fb85).
Collisions have been removed because its logic was found on the
source already.
Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769
Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/net/wireless/mwifiex/ie.c')
-rw-r--r-- | kernel/drivers/net/wireless/mwifiex/ie.c | 105 |
1 files changed, 63 insertions, 42 deletions
diff --git a/kernel/drivers/net/wireless/mwifiex/ie.c b/kernel/drivers/net/wireless/mwifiex/ie.c index f3b6ed249..abf52d25b 100644 --- a/kernel/drivers/net/wireless/mwifiex/ie.c +++ b/kernel/drivers/net/wireless/mwifiex/ie.c @@ -320,63 +320,81 @@ done: /* 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; - 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); - 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); + 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); + } - vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, + /* 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 (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); - } + 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); + } - 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 (!ie_len) { + kfree(gen_ie); + return 0; } - 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; + 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 (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,9 @@ 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); + + if (ret) return ret; return mwifiex_set_mgmt_beacon_data_ies(priv, info); @@ -459,6 +479,7 @@ int mwifiex_del_mgmt_ies(struct mwifiex_private *priv) ar_ie, &priv->assocresp_idx); done: + kfree(gen_ie); kfree(beacon_ie); kfree(pr_ie); kfree(ar_ie); |