Skip to content

Commit

Permalink
mwifiex: retrieve IEs from cfg80211_beacon_data and send to firmware
Browse files Browse the repository at this point in the history
This patch adds logic for setting tail beacon IE, probe response IE
and assoc response IE from cfg80211_ap_settings parameter of
start_ap handler into FW.

RSN IE is also retrieved from tail IE buffer and sent to firmware.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Avinash Patil authored and John W. Linville committed May 16, 2012
1 parent ede98bf commit f31acab
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 0 deletions.
2 changes: 2 additions & 0 deletions drivers/net/wireless/mwifiex/cfg80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,8 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy,

if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP)
return -1;
if (mwifiex_set_mgmt_ies(priv, params))
return -1;

bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL);
if (!bss_cfg)
Expand Down
7 changes: 7 additions & 0 deletions drivers/net/wireless/mwifiex/fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define UAP_CUSTOM_IE_I 1
#define MWIFIEX_AUTO_IDX_MASK 0xffff
#define MWIFIEX_DELETE_MASK 0x0000
#define MGMT_MASK_ASSOC_REQ 0x01
#define MGMT_MASK_REASSOC_REQ 0x04
#define MGMT_MASK_ASSOC_RESP 0x02
#define MGMT_MASK_REASSOC_RESP 0x08
#define MGMT_MASK_PROBE_REQ 0x10
#define MGMT_MASK_PROBE_RESP 0x20
#define MGMT_MASK_BEACON 0x100

#define TLV_TYPE_UAP_SSID 0x0000

Expand Down
176 changes: 176 additions & 0 deletions drivers/net/wireless/mwifiex/ie.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,3 +147,179 @@ mwifiex_update_autoindex_ies(struct mwifiex_private *priv,

return 0;
}

/* Copy individual custom IEs for beacon, probe response and assoc response
* and prepare single structure for IE setting.
* This function also updates allocated IE indices from driver.
*/
static int
mwifiex_update_uap_custom_ie(struct mwifiex_private *priv,
struct mwifiex_ie *beacon_ie, u16 *beacon_idx,
struct mwifiex_ie *pr_ie, u16 *probe_idx,
struct mwifiex_ie *ar_ie, u16 *assoc_idx)
{
struct mwifiex_ie_list *ap_custom_ie;
u8 *pos;
u16 len;
int ret;

ap_custom_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
if (!ap_custom_ie)
return -ENOMEM;

ap_custom_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE);
pos = (u8 *)ap_custom_ie->ie_list;

if (beacon_ie) {
len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
le16_to_cpu(beacon_ie->ie_length);
memcpy(pos, beacon_ie, len);
pos += len;
le16_add_cpu(&ap_custom_ie->len, len);
}
if (pr_ie) {
len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
le16_to_cpu(pr_ie->ie_length);
memcpy(pos, pr_ie, len);
pos += len;
le16_add_cpu(&ap_custom_ie->len, len);
}
if (ar_ie) {
len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
le16_to_cpu(ar_ie->ie_length);
memcpy(pos, ar_ie, len);
pos += len;
le16_add_cpu(&ap_custom_ie->len, len);
}

ret = mwifiex_update_autoindex_ies(priv, ap_custom_ie);

pos = (u8 *)(&ap_custom_ie->ie_list[0].ie_index);
if (beacon_ie && *beacon_idx == MWIFIEX_AUTO_IDX_MASK) {
/* save beacon ie index after auto-indexing */
*beacon_idx = le16_to_cpu(ap_custom_ie->ie_list[0].ie_index);
len = sizeof(*beacon_ie) - IEEE_MAX_IE_SIZE +
le16_to_cpu(beacon_ie->ie_length);
pos += len;
}
if (pr_ie && le16_to_cpu(pr_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK) {
/* save probe resp ie index after auto-indexing */
*probe_idx = *((u16 *)pos);
len = sizeof(*pr_ie) - IEEE_MAX_IE_SIZE +
le16_to_cpu(pr_ie->ie_length);
pos += len;
}
if (ar_ie && le16_to_cpu(ar_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK)
/* save assoc resp ie index after auto-indexing */
*assoc_idx = *((u16 *)pos);

return ret;
}

/* This function parses different IEs- Tail IEs, beacon IEs, probe response IEs,
* association response IEs from cfg80211_ap_settings function and sets these IE
* to FW.
*/
int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
struct cfg80211_ap_settings *params)
{
struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL;
struct mwifiex_ie *ar_ie = NULL, *rsn_ie = NULL;
struct ieee_types_header *ie = NULL;
u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK;
u16 ar_idx = MWIFIEX_AUTO_IDX_MASK, rsn_idx = MWIFIEX_AUTO_IDX_MASK;
u16 mask;
int ret = 0;

if (params->beacon.tail && params->beacon.tail_len) {
ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, params->beacon.tail,
params->beacon.tail_len);
if (ie) {
rsn_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
if (!rsn_ie)
return -ENOMEM;

rsn_ie->ie_index = cpu_to_le16(rsn_idx);
mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP |
MGMT_MASK_ASSOC_RESP;
rsn_ie->mgmt_subtype_mask = cpu_to_le16(mask);
rsn_ie->ie_length = cpu_to_le16(ie->len + 2);
memcpy(rsn_ie->ie_buffer, ie, ie->len + 2);

if (mwifiex_update_uap_custom_ie(priv, rsn_ie, &rsn_idx,
NULL, NULL,
NULL, NULL)) {
ret = -1;
goto done;
}

priv->rsn_idx = rsn_idx;
}
}

if (params->beacon.beacon_ies && params->beacon.beacon_ies_len) {
beacon_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
if (!beacon_ie) {
ret = -ENOMEM;
goto done;
}

beacon_ie->ie_index = cpu_to_le16(beacon_idx);
beacon_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON);
beacon_ie->ie_length =
cpu_to_le16(params->beacon.beacon_ies_len);
memcpy(beacon_ie->ie_buffer, params->beacon.beacon_ies,
params->beacon.beacon_ies_len);
}

if (params->beacon.proberesp_ies && params->beacon.proberesp_ies_len) {
pr_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
if (!pr_ie) {
ret = -ENOMEM;
goto done;
}

pr_ie->ie_index = cpu_to_le16(pr_idx);
pr_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_PROBE_RESP);
pr_ie->ie_length =
cpu_to_le16(params->beacon.proberesp_ies_len);
memcpy(pr_ie->ie_buffer, params->beacon.proberesp_ies,
params->beacon.proberesp_ies_len);
}

if (params->beacon.assocresp_ies && params->beacon.assocresp_ies_len) {
ar_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL);
if (!ar_ie) {
ret = -ENOMEM;
goto done;
}

ar_ie->ie_index = cpu_to_le16(ar_idx);
mask = MGMT_MASK_ASSOC_RESP | MGMT_MASK_REASSOC_RESP;
ar_ie->mgmt_subtype_mask = cpu_to_le16(mask);
ar_ie->ie_length =
cpu_to_le16(params->beacon.assocresp_ies_len);
memcpy(ar_ie->ie_buffer, params->beacon.assocresp_ies,
params->beacon.assocresp_ies_len);
}

if (beacon_ie || pr_ie || ar_ie) {
ret = mwifiex_update_uap_custom_ie(priv, beacon_ie,
&beacon_idx, pr_ie,
&pr_idx, ar_ie, &ar_idx);
if (ret)
goto done;
}

priv->beacon_idx = beacon_idx;
priv->proberesp_idx = pr_idx;
priv->assocresp_idx = ar_idx;

done:
kfree(beacon_ie);
kfree(pr_ie);
kfree(ar_ie);
kfree(rsn_ie);

return ret;
}
4 changes: 4 additions & 0 deletions drivers/net/wireless/mwifiex/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,10 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
memset(&priv->nick_name, 0, sizeof(priv->nick_name));
memset(priv->mgmt_ie, 0,
sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX);
priv->beacon_idx = MWIFIEX_AUTO_IDX_MASK;
priv->proberesp_idx = MWIFIEX_AUTO_IDX_MASK;
priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK;
priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK;
priv->num_tx_timeout = 0;
memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
}
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/wireless/mwifiex/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,10 @@ struct mwifiex_private {
u32 cqm_rssi_hyst;
u8 subsc_evt_rssi_state;
struct mwifiex_ie mgmt_ie[MAX_MGMT_IE_INDEX];
u16 beacon_idx;
u16 proberesp_idx;
u16 assocresp_idx;
u16 rsn_idx;
};

enum mwifiex_ba_status {
Expand Down Expand Up @@ -1001,6 +1005,8 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev);

void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config);

int mwifiex_set_mgmt_ies(struct mwifiex_private *priv,
struct cfg80211_ap_settings *params);
u8 *mwifiex_11d_code_2_region(u8 code);

#ifdef CONFIG_DEBUG_FS
Expand Down

0 comments on commit f31acab

Please sign in to comment.