aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorAvinash Patil <patila@marvell.com>2012-05-08 21:30:28 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-05-16 12:46:36 -0400
commitede98bfa914ec3285761da4bb9c25d1e160ea85b (patch)
tree5be00b8cd4bdf8b9f3d46ea1325b046700118479 /drivers/net/wireless
parente76268da22f9dbe8794d68e6a504a781dfd36998 (diff)
mwifiex: add custom IE framework
1. support for setting custom IE from application hostapd etc. Custom IE addition using auto-indexing and Custom IE deletion using static indices (which are allocated during IE addition and stored in driver) are supported. 2. Separate file for handling IE related execution. 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>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/mwifiex/Makefile1
-rw-r--r--drivers/net/wireless/mwifiex/fw.h17
-rw-r--r--drivers/net/wireless/mwifiex/ie.c149
-rw-r--r--drivers/net/wireless/mwifiex/init.c1
-rw-r--r--drivers/net/wireless/mwifiex/ioctl.h2
-rw-r--r--drivers/net/wireless/mwifiex/main.c2
-rw-r--r--drivers/net/wireless/mwifiex/main.h2
-rw-r--r--drivers/net/wireless/mwifiex/uap_cmd.c28
8 files changed, 201 insertions, 1 deletions
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile
index 3ec71aeb6aa8..3f66ebb0a630 100644
--- a/drivers/net/wireless/mwifiex/Makefile
+++ b/drivers/net/wireless/mwifiex/Makefile
@@ -30,6 +30,7 @@ mwifiex-y += join.o
30mwifiex-y += sta_ioctl.o 30mwifiex-y += sta_ioctl.o
31mwifiex-y += sta_cmd.o 31mwifiex-y += sta_cmd.o
32mwifiex-y += uap_cmd.o 32mwifiex-y += uap_cmd.o
33mwifiex-y += ie.o
33mwifiex-y += sta_cmdresp.o 34mwifiex-y += sta_cmdresp.o
34mwifiex-y += sta_event.o 35mwifiex-y += sta_event.o
35mwifiex-y += sta_tx.o 36mwifiex-y += sta_tx.o
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 4fd7a05fee18..0cb2b0cc3ee8 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -94,6 +94,9 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
94#define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI)-(s16)(NF))) 94#define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI)-(s16)(NF)))
95 95
96#define UAP_BSS_PARAMS_I 0 96#define UAP_BSS_PARAMS_I 0
97#define UAP_CUSTOM_IE_I 1
98#define MWIFIEX_AUTO_IDX_MASK 0xffff
99#define MWIFIEX_DELETE_MASK 0x0000
97 100
98#define TLV_TYPE_UAP_SSID 0x0000 101#define TLV_TYPE_UAP_SSID 0x0000
99 102
@@ -1299,6 +1302,20 @@ struct host_cmd_ds_802_11_subsc_evt {
1299 __le16 events; 1302 __le16 events;
1300} __packed; 1303} __packed;
1301 1304
1305struct mwifiex_ie {
1306 __le16 ie_index;
1307 __le16 mgmt_subtype_mask;
1308 __le16 ie_length;
1309 u8 ie_buffer[IEEE_MAX_IE_SIZE];
1310} __packed;
1311
1312#define MAX_MGMT_IE_INDEX 16
1313struct mwifiex_ie_list {
1314 __le16 type;
1315 __le16 len;
1316 struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX];
1317} __packed;
1318
1302struct host_cmd_ds_command { 1319struct host_cmd_ds_command {
1303 __le16 command; 1320 __le16 command;
1304 __le16 size; 1321 __le16 size;
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c
new file mode 100644
index 000000000000..772bf3e57006
--- /dev/null
+++ b/drivers/net/wireless/mwifiex/ie.c
@@ -0,0 +1,149 @@
1/*
2 * Marvell Wireless LAN device driver: management IE handling- setting and
3 * deleting IE.
4 *
5 * Copyright (C) 2012, Marvell International Ltd.
6 *
7 * This software file (the "File") is distributed by Marvell International
8 * Ltd. under the terms of the GNU General Public License Version 2, June 1991
9 * (the "License"). You may use, redistribute and/or modify this File in
10 * accordance with the terms and conditions of the License, a copy of which
11 * is available by writing to the Free Software Foundation, Inc.,
12 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
13 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
14 *
15 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
17 * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
18 * this warranty disclaimer.
19 */
20
21#include "main.h"
22
23/* This function checks if current IE index is used by any on other interface.
24 * Return: -1: yes, current IE index is used by someone else.
25 * 0: no, current IE index is NOT used by other interface.
26 */
27static int
28mwifiex_ie_index_used_by_other_intf(struct mwifiex_private *priv, u16 idx)
29{
30 int i;
31 struct mwifiex_adapter *adapter = priv->adapter;
32 struct mwifiex_ie *ie;
33
34 for (i = 0; i < adapter->priv_num; i++) {
35 if (adapter->priv[i] != priv) {
36 ie = &adapter->priv[i]->mgmt_ie[idx];
37 if (ie->mgmt_subtype_mask && ie->ie_length)
38 return -1;
39 }
40 }
41
42 return 0;
43}
44
45/* Get unused IE index. This index will be used for setting new IE */
46static int
47mwifiex_ie_get_autoidx(struct mwifiex_private *priv, u16 subtype_mask,
48 struct mwifiex_ie *ie, u16 *index)
49{
50 u16 mask, len, i;
51
52 for (i = 0; i < priv->adapter->max_mgmt_ie_index; i++) {
53 mask = le16_to_cpu(priv->mgmt_ie[i].mgmt_subtype_mask);
54 len = le16_to_cpu(priv->mgmt_ie[i].ie_length) +
55 le16_to_cpu(ie->ie_length);
56
57 if (mask == MWIFIEX_AUTO_IDX_MASK)
58 continue;
59
60 if (mask == subtype_mask) {
61 if (len > IEEE_MAX_IE_SIZE)
62 continue;
63
64 *index = i;
65 return 0;
66 }
67
68 if (!priv->mgmt_ie[i].ie_length) {
69 if (mwifiex_ie_index_used_by_other_intf(priv, i))
70 continue;
71
72 *index = i;
73 return 0;
74 }
75 }
76
77 return -1;
78}
79
80/* This function prepares IE data buffer for command to be sent to FW */
81static int
82mwifiex_update_autoindex_ies(struct mwifiex_private *priv,
83 struct mwifiex_ie_list *ie_list)
84{
85 u16 travel_len, index, mask;
86 s16 input_len;
87 struct mwifiex_ie *ie;
88 u8 *tmp;
89
90 input_len = le16_to_cpu(ie_list->len);
91 travel_len = sizeof(struct host_cmd_tlv);
92
93 ie_list->len = 0;
94
95 while (input_len > 0) {
96 ie = (struct mwifiex_ie *)(((u8 *)ie_list) + travel_len);
97 input_len -= le16_to_cpu(ie->ie_length) + MWIFIEX_IE_HDR_SIZE;
98 travel_len += le16_to_cpu(ie->ie_length) + MWIFIEX_IE_HDR_SIZE;
99
100 index = le16_to_cpu(ie->ie_index);
101 mask = le16_to_cpu(ie->mgmt_subtype_mask);
102
103 if (index == MWIFIEX_AUTO_IDX_MASK) {
104 /* automatic addition */
105 if (mwifiex_ie_get_autoidx(priv, mask, ie, &index))
106 return -1;
107 if (index == MWIFIEX_AUTO_IDX_MASK)
108 return -1;
109
110 tmp = (u8 *)&priv->mgmt_ie[index].ie_buffer;
111 tmp += le16_to_cpu(priv->mgmt_ie[index].ie_length);
112 memcpy(tmp, &ie->ie_buffer, le16_to_cpu(ie->ie_length));
113 le16_add_cpu(&priv->mgmt_ie[index].ie_length,
114 le16_to_cpu(ie->ie_length));
115 priv->mgmt_ie[index].ie_index = cpu_to_le16(index);
116 priv->mgmt_ie[index].mgmt_subtype_mask =
117 cpu_to_le16(mask);
118
119 ie->ie_index = cpu_to_le16(index);
120 ie->ie_length = priv->mgmt_ie[index].ie_length;
121 memcpy(&ie->ie_buffer, &priv->mgmt_ie[index].ie_buffer,
122 le16_to_cpu(priv->mgmt_ie[index].ie_length));
123 } else {
124 if (mask != MWIFIEX_DELETE_MASK)
125 return -1;
126 /*
127 * Check if this index is being used on any
128 * other interface.
129 */
130 if (mwifiex_ie_index_used_by_other_intf(priv, index))
131 return -1;
132
133 ie->ie_length = 0;
134 memcpy(&priv->mgmt_ie[index], ie,
135 sizeof(struct mwifiex_ie));
136 }
137
138 le16_add_cpu(&ie_list->len,
139 le16_to_cpu(priv->mgmt_ie[index].ie_length) +
140 MWIFIEX_IE_HDR_SIZE);
141 }
142
143 if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP)
144 return mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG,
145 HostCmd_ACT_GEN_SET,
146 UAP_CUSTOM_IE_I, ie_list);
147
148 return 0;
149}
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index d440c3eb640b..c1cb004db913 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -279,6 +279,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
279 memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); 279 memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
280 adapter->arp_filter_size = 0; 280 adapter->arp_filter_size = 0;
281 adapter->channel_type = NL80211_CHAN_HT20; 281 adapter->channel_type = NL80211_CHAN_HT20;
282 adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
282} 283}
283 284
284/* 285/*
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index eb14f558b118..e6be6ee75951 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -299,6 +299,8 @@ struct mwifiex_ds_read_eeprom {
299 299
300#define IEEE_MAX_IE_SIZE 256 300#define IEEE_MAX_IE_SIZE 256
301 301
302#define MWIFIEX_IE_HDR_SIZE (sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE)
303
302struct mwifiex_ds_misc_gen_ie { 304struct mwifiex_ds_misc_gen_ie {
303 u32 type; 305 u32 type;
304 u32 len; 306 u32 len;
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 43e4efad4cf7..49598e6c181f 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -640,6 +640,8 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
640 priv->current_key_index = 0; 640 priv->current_key_index = 0;
641 priv->media_connected = false; 641 priv->media_connected = false;
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,
644 sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX);
643 priv->num_tx_timeout = 0; 645 priv->num_tx_timeout = 0;
644 memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); 646 memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN);
645} 647}
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 824bd436c3ae..988d31d6504c 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -477,6 +477,7 @@ struct mwifiex_private {
477 s32 cqm_rssi_thold; 477 s32 cqm_rssi_thold;
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}; 481};
481 482
482enum mwifiex_ba_status { 483enum mwifiex_ba_status {
@@ -680,6 +681,7 @@ struct mwifiex_adapter {
680 spinlock_t queue_lock; /* lock for tx queues */ 681 spinlock_t queue_lock; /* lock for tx queues */
681 struct completion fw_load; 682 struct completion fw_load;
682 u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; 683 u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
684 u16 max_mgmt_ie_index;
683}; 685};
684 686
685int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); 687int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index e43bcaafa1bd..76dfbc42a732 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -315,6 +315,26 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size)
315 return 0; 315 return 0;
316} 316}
317 317
318/* This function parses custom IEs from IE list and prepares command buffer */
319static int mwifiex_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size)
320{
321 struct mwifiex_ie_list *ap_ie = cmd_buf;
322 struct host_cmd_tlv *tlv_ie = (struct host_cmd_tlv *)tlv;
323
324 if (!ap_ie || !ap_ie->len || !ap_ie->ie_list)
325 return -1;
326
327 *ie_size += le16_to_cpu(ap_ie->len) + sizeof(struct host_cmd_tlv);
328
329 tlv_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE);
330 tlv_ie->len = ap_ie->len;
331 tlv += sizeof(struct host_cmd_tlv);
332
333 memcpy(tlv, ap_ie->ie_list, le16_to_cpu(ap_ie->len));
334
335 return 0;
336}
337
318/* Parse AP config structure and prepare TLV based command structure 338/* Parse AP config structure and prepare TLV based command structure
319 * to be sent to FW for uAP configuration 339 * to be sent to FW for uAP configuration
320 */ 340 */
@@ -323,7 +343,7 @@ mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action,
323 u32 type, void *cmd_buf) 343 u32 type, void *cmd_buf)
324{ 344{
325 u8 *tlv; 345 u8 *tlv;
326 u16 cmd_size, param_size; 346 u16 cmd_size, param_size, ie_size;
327 struct host_cmd_ds_sys_config *sys_cfg; 347 struct host_cmd_ds_sys_config *sys_cfg;
328 348
329 cmd->command = cpu_to_le16(HostCmd_CMD_UAP_SYS_CONFIG); 349 cmd->command = cpu_to_le16(HostCmd_CMD_UAP_SYS_CONFIG);
@@ -339,6 +359,12 @@ mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action,
339 return -1; 359 return -1;
340 cmd->size = cpu_to_le16(param_size); 360 cmd->size = cpu_to_le16(param_size);
341 break; 361 break;
362 case UAP_CUSTOM_IE_I:
363 ie_size = cmd_size;
364 if (mwifiex_uap_custom_ie_prepare(tlv, cmd_buf, &ie_size))
365 return -1;
366 cmd->size = cpu_to_le16(ie_size);
367 break;
342 default: 368 default:
343 return -1; 369 return -1;
344 } 370 }