diff options
author | Avinash Patil <patila@marvell.com> | 2012-05-08 21:30:29 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-05-16 12:46:37 -0400 |
commit | f31acabe3dd0699c61a8ec4ba4f70816d58b4dc9 (patch) | |
tree | 5c0dd60d2fd94b798d98b2422db6f65c7ef92a05 | |
parent | ede98bfa914ec3285761da4bb9c25d1e160ea85b (diff) |
mwifiex: retrieve IEs from cfg80211_beacon_data and send to firmware
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>
-rw-r--r-- | drivers/net/wireless/mwifiex/cfg80211.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/fw.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/ie.c | 176 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/mwifiex/main.h | 6 |
5 files changed, 195 insertions, 0 deletions
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index d305b373aee0..2d0952dc593a 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -952,6 +952,8 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | |||
952 | 952 | ||
953 | if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) | 953 | if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) |
954 | return -1; | 954 | return -1; |
955 | if (mwifiex_set_mgmt_ies(priv, params)) | ||
956 | return -1; | ||
955 | 957 | ||
956 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); | 958 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); |
957 | if (!bss_cfg) | 959 | if (!bss_cfg) |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 0cb2b0cc3ee8..9f674bbebe65 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -97,6 +97,13 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
97 | #define UAP_CUSTOM_IE_I 1 | 97 | #define UAP_CUSTOM_IE_I 1 |
98 | #define MWIFIEX_AUTO_IDX_MASK 0xffff | 98 | #define MWIFIEX_AUTO_IDX_MASK 0xffff |
99 | #define MWIFIEX_DELETE_MASK 0x0000 | 99 | #define MWIFIEX_DELETE_MASK 0x0000 |
100 | #define MGMT_MASK_ASSOC_REQ 0x01 | ||
101 | #define MGMT_MASK_REASSOC_REQ 0x04 | ||
102 | #define MGMT_MASK_ASSOC_RESP 0x02 | ||
103 | #define MGMT_MASK_REASSOC_RESP 0x08 | ||
104 | #define MGMT_MASK_PROBE_REQ 0x10 | ||
105 | #define MGMT_MASK_PROBE_RESP 0x20 | ||
106 | #define MGMT_MASK_BEACON 0x100 | ||
100 | 107 | ||
101 | #define TLV_TYPE_UAP_SSID 0x0000 | 108 | #define TLV_TYPE_UAP_SSID 0x0000 |
102 | 109 | ||
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c index 772bf3e57006..ca9ebcf8ab22 100644 --- a/drivers/net/wireless/mwifiex/ie.c +++ b/drivers/net/wireless/mwifiex/ie.c | |||
@@ -147,3 +147,179 @@ mwifiex_update_autoindex_ies(struct mwifiex_private *priv, | |||
147 | 147 | ||
148 | return 0; | 148 | return 0; |
149 | } | 149 | } |
150 | |||
151 | /* Copy individual custom IEs for beacon, probe response and assoc response | ||
152 | * and prepare single structure for IE setting. | ||
153 | * This function also updates allocated IE indices from driver. | ||
154 | */ | ||
155 | static int | ||
156 | mwifiex_update_uap_custom_ie(struct mwifiex_private *priv, | ||
157 | struct mwifiex_ie *beacon_ie, u16 *beacon_idx, | ||
158 | struct mwifiex_ie *pr_ie, u16 *probe_idx, | ||
159 | struct mwifiex_ie *ar_ie, u16 *assoc_idx) | ||
160 | { | ||
161 | struct mwifiex_ie_list *ap_custom_ie; | ||
162 | u8 *pos; | ||
163 | u16 len; | ||
164 | int ret; | ||
165 | |||
166 | ap_custom_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
167 | if (!ap_custom_ie) | ||
168 | return -ENOMEM; | ||
169 | |||
170 | ap_custom_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE); | ||
171 | pos = (u8 *)ap_custom_ie->ie_list; | ||
172 | |||
173 | if (beacon_ie) { | ||
174 | len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE + | ||
175 | le16_to_cpu(beacon_ie->ie_length); | ||
176 | memcpy(pos, beacon_ie, len); | ||
177 | pos += len; | ||
178 | le16_add_cpu(&ap_custom_ie->len, len); | ||
179 | } | ||
180 | if (pr_ie) { | ||
181 | len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE + | ||
182 | le16_to_cpu(pr_ie->ie_length); | ||
183 | memcpy(pos, pr_ie, len); | ||
184 | pos += len; | ||
185 | le16_add_cpu(&ap_custom_ie->len, len); | ||
186 | } | ||
187 | if (ar_ie) { | ||
188 | len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE + | ||
189 | le16_to_cpu(ar_ie->ie_length); | ||
190 | memcpy(pos, ar_ie, len); | ||
191 | pos += len; | ||
192 | le16_add_cpu(&ap_custom_ie->len, len); | ||
193 | } | ||
194 | |||
195 | ret = mwifiex_update_autoindex_ies(priv, ap_custom_ie); | ||
196 | |||
197 | pos = (u8 *)(&ap_custom_ie->ie_list[0].ie_index); | ||
198 | if (beacon_ie && *beacon_idx == MWIFIEX_AUTO_IDX_MASK) { | ||
199 | /* save beacon ie index after auto-indexing */ | ||
200 | *beacon_idx = le16_to_cpu(ap_custom_ie->ie_list[0].ie_index); | ||
201 | len = sizeof(*beacon_ie) - IEEE_MAX_IE_SIZE + | ||
202 | le16_to_cpu(beacon_ie->ie_length); | ||
203 | pos += len; | ||
204 | } | ||
205 | if (pr_ie && le16_to_cpu(pr_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK) { | ||
206 | /* save probe resp ie index after auto-indexing */ | ||
207 | *probe_idx = *((u16 *)pos); | ||
208 | len = sizeof(*pr_ie) - IEEE_MAX_IE_SIZE + | ||
209 | le16_to_cpu(pr_ie->ie_length); | ||
210 | pos += len; | ||
211 | } | ||
212 | if (ar_ie && le16_to_cpu(ar_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK) | ||
213 | /* save assoc resp ie index after auto-indexing */ | ||
214 | *assoc_idx = *((u16 *)pos); | ||
215 | |||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | /* This function parses different IEs- Tail IEs, beacon IEs, probe response IEs, | ||
220 | * association response IEs from cfg80211_ap_settings function and sets these IE | ||
221 | * to FW. | ||
222 | */ | ||
223 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | ||
224 | struct cfg80211_ap_settings *params) | ||
225 | { | ||
226 | struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL; | ||
227 | struct mwifiex_ie *ar_ie = NULL, *rsn_ie = NULL; | ||
228 | struct ieee_types_header *ie = NULL; | ||
229 | u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK; | ||
230 | u16 ar_idx = MWIFIEX_AUTO_IDX_MASK, rsn_idx = MWIFIEX_AUTO_IDX_MASK; | ||
231 | u16 mask; | ||
232 | int ret = 0; | ||
233 | |||
234 | if (params->beacon.tail && params->beacon.tail_len) { | ||
235 | ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, params->beacon.tail, | ||
236 | params->beacon.tail_len); | ||
237 | if (ie) { | ||
238 | rsn_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
239 | if (!rsn_ie) | ||
240 | return -ENOMEM; | ||
241 | |||
242 | rsn_ie->ie_index = cpu_to_le16(rsn_idx); | ||
243 | mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | | ||
244 | MGMT_MASK_ASSOC_RESP; | ||
245 | rsn_ie->mgmt_subtype_mask = cpu_to_le16(mask); | ||
246 | rsn_ie->ie_length = cpu_to_le16(ie->len + 2); | ||
247 | memcpy(rsn_ie->ie_buffer, ie, ie->len + 2); | ||
248 | |||
249 | if (mwifiex_update_uap_custom_ie(priv, rsn_ie, &rsn_idx, | ||
250 | NULL, NULL, | ||
251 | NULL, NULL)) { | ||
252 | ret = -1; | ||
253 | goto done; | ||
254 | } | ||
255 | |||
256 | priv->rsn_idx = rsn_idx; | ||
257 | } | ||
258 | } | ||
259 | |||
260 | if (params->beacon.beacon_ies && params->beacon.beacon_ies_len) { | ||
261 | beacon_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
262 | if (!beacon_ie) { | ||
263 | ret = -ENOMEM; | ||
264 | goto done; | ||
265 | } | ||
266 | |||
267 | beacon_ie->ie_index = cpu_to_le16(beacon_idx); | ||
268 | beacon_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON); | ||
269 | beacon_ie->ie_length = | ||
270 | cpu_to_le16(params->beacon.beacon_ies_len); | ||
271 | memcpy(beacon_ie->ie_buffer, params->beacon.beacon_ies, | ||
272 | params->beacon.beacon_ies_len); | ||
273 | } | ||
274 | |||
275 | if (params->beacon.proberesp_ies && params->beacon.proberesp_ies_len) { | ||
276 | pr_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
277 | if (!pr_ie) { | ||
278 | ret = -ENOMEM; | ||
279 | goto done; | ||
280 | } | ||
281 | |||
282 | pr_ie->ie_index = cpu_to_le16(pr_idx); | ||
283 | pr_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_PROBE_RESP); | ||
284 | pr_ie->ie_length = | ||
285 | cpu_to_le16(params->beacon.proberesp_ies_len); | ||
286 | memcpy(pr_ie->ie_buffer, params->beacon.proberesp_ies, | ||
287 | params->beacon.proberesp_ies_len); | ||
288 | } | ||
289 | |||
290 | if (params->beacon.assocresp_ies && params->beacon.assocresp_ies_len) { | ||
291 | ar_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
292 | if (!ar_ie) { | ||
293 | ret = -ENOMEM; | ||
294 | goto done; | ||
295 | } | ||
296 | |||
297 | ar_ie->ie_index = cpu_to_le16(ar_idx); | ||
298 | mask = MGMT_MASK_ASSOC_RESP | MGMT_MASK_REASSOC_RESP; | ||
299 | ar_ie->mgmt_subtype_mask = cpu_to_le16(mask); | ||
300 | ar_ie->ie_length = | ||
301 | cpu_to_le16(params->beacon.assocresp_ies_len); | ||
302 | memcpy(ar_ie->ie_buffer, params->beacon.assocresp_ies, | ||
303 | params->beacon.assocresp_ies_len); | ||
304 | } | ||
305 | |||
306 | if (beacon_ie || pr_ie || ar_ie) { | ||
307 | ret = mwifiex_update_uap_custom_ie(priv, beacon_ie, | ||
308 | &beacon_idx, pr_ie, | ||
309 | &pr_idx, ar_ie, &ar_idx); | ||
310 | if (ret) | ||
311 | goto done; | ||
312 | } | ||
313 | |||
314 | priv->beacon_idx = beacon_idx; | ||
315 | priv->proberesp_idx = pr_idx; | ||
316 | priv->assocresp_idx = ar_idx; | ||
317 | |||
318 | done: | ||
319 | kfree(beacon_ie); | ||
320 | kfree(pr_ie); | ||
321 | kfree(ar_ie); | ||
322 | kfree(rsn_ie); | ||
323 | |||
324 | return ret; | ||
325 | } | ||
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 49598e6c181f..3192855c31c0 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -642,6 +642,10 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv, | |||
642 | memset(&priv->nick_name, 0, sizeof(priv->nick_name)); | 642 | memset(&priv->nick_name, 0, sizeof(priv->nick_name)); |
643 | memset(priv->mgmt_ie, 0, | 643 | memset(priv->mgmt_ie, 0, |
644 | sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX); | 644 | sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX); |
645 | priv->beacon_idx = MWIFIEX_AUTO_IDX_MASK; | ||
646 | priv->proberesp_idx = MWIFIEX_AUTO_IDX_MASK; | ||
647 | priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK; | ||
648 | priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK; | ||
645 | priv->num_tx_timeout = 0; | 649 | priv->num_tx_timeout = 0; |
646 | memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); | 650 | memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); |
647 | } | 651 | } |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 988d31d6504c..7d882eea2171 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -478,6 +478,10 @@ struct mwifiex_private { | |||
478 | u32 cqm_rssi_hyst; | 478 | u32 cqm_rssi_hyst; |
479 | u8 subsc_evt_rssi_state; | 479 | u8 subsc_evt_rssi_state; |
480 | struct mwifiex_ie mgmt_ie[MAX_MGMT_IE_INDEX]; | 480 | struct mwifiex_ie mgmt_ie[MAX_MGMT_IE_INDEX]; |
481 | u16 beacon_idx; | ||
482 | u16 proberesp_idx; | ||
483 | u16 assocresp_idx; | ||
484 | u16 rsn_idx; | ||
481 | }; | 485 | }; |
482 | 486 | ||
483 | enum mwifiex_ba_status { | 487 | enum mwifiex_ba_status { |
@@ -1001,6 +1005,8 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev); | |||
1001 | 1005 | ||
1002 | void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); | 1006 | void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); |
1003 | 1007 | ||
1008 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | ||
1009 | struct cfg80211_ap_settings *params); | ||
1004 | u8 *mwifiex_11d_code_2_region(u8 code); | 1010 | u8 *mwifiex_11d_code_2_region(u8 code); |
1005 | 1011 | ||
1006 | #ifdef CONFIG_DEBUG_FS | 1012 | #ifdef CONFIG_DEBUG_FS |