aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r--drivers/net/wireless/libertas/Makefile3
-rw-r--r--drivers/net/wireless/libertas/README12
-rw-r--r--drivers/net/wireless/libertas/assoc.c2264
-rw-r--r--drivers/net/wireless/libertas/assoc.h155
-rw-r--r--drivers/net/wireless/libertas/cfg.c1861
-rw-r--r--drivers/net/wireless/libertas/cfg.h15
-rw-r--r--drivers/net/wireless/libertas/cmd.c767
-rw-r--r--drivers/net/wireless/libertas/cmd.h27
-rw-r--r--drivers/net/wireless/libertas/cmdresp.c190
-rw-r--r--drivers/net/wireless/libertas/debugfs.c191
-rw-r--r--drivers/net/wireless/libertas/decl.h7
-rw-r--r--drivers/net/wireless/libertas/defs.h18
-rw-r--r--drivers/net/wireless/libertas/dev.h68
-rw-r--r--drivers/net/wireless/libertas/ethtool.c29
-rw-r--r--drivers/net/wireless/libertas/host.h250
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c58
-rw-r--r--drivers/net/wireless/libertas/if_usb.c16
-rw-r--r--drivers/net/wireless/libertas/main.c326
-rw-r--r--drivers/net/wireless/libertas/mesh.c222
-rw-r--r--drivers/net/wireless/libertas/mesh.h19
-rw-r--r--drivers/net/wireless/libertas/radiotap.h4
-rw-r--r--drivers/net/wireless/libertas/rx.c129
-rw-r--r--drivers/net/wireless/libertas/scan.c1354
-rw-r--r--drivers/net/wireless/libertas/scan.h63
-rw-r--r--drivers/net/wireless/libertas/tx.c12
-rw-r--r--drivers/net/wireless/libertas/types.h66
-rw-r--r--drivers/net/wireless/libertas/wext.c2353
-rw-r--r--drivers/net/wireless/libertas/wext.h17
28 files changed, 2910 insertions, 7586 deletions
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
index 45e870e33117..f7d01bfa2e4a 100644
--- a/drivers/net/wireless/libertas/Makefile
+++ b/drivers/net/wireless/libertas/Makefile
@@ -1,4 +1,3 @@
1libertas-y += assoc.o
2libertas-y += cfg.o 1libertas-y += cfg.o
3libertas-y += cmd.o 2libertas-y += cmd.o
4libertas-y += cmdresp.o 3libertas-y += cmdresp.o
@@ -6,9 +5,7 @@ libertas-y += debugfs.o
6libertas-y += ethtool.o 5libertas-y += ethtool.o
7libertas-y += main.o 6libertas-y += main.o
8libertas-y += rx.o 7libertas-y += rx.o
9libertas-y += scan.o
10libertas-y += tx.o 8libertas-y += tx.o
11libertas-y += wext.o
12libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o 9libertas-$(CONFIG_LIBERTAS_MESH) += mesh.o
13 10
14usb8xxx-objs += if_usb.o 11usb8xxx-objs += if_usb.o
diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README
index 2726c044430f..60fd1afe89ac 100644
--- a/drivers/net/wireless/libertas/README
+++ b/drivers/net/wireless/libertas/README
@@ -226,6 +226,18 @@ setuserscan
226 All entries in the scan table (not just the new scan data when keep=1) 226 All entries in the scan table (not just the new scan data when keep=1)
227 will be displayed upon completion by use of the getscantable ioctl. 227 will be displayed upon completion by use of the getscantable ioctl.
228 228
229hostsleep
230 This command is used to enable/disable host sleep.
231 Note: Host sleep parameters should be configured using
232 "ethtool -s ethX wol X" command before enabling host sleep.
233
234 Path: /sys/kernel/debug/libertas_wireless/ethX/
235
236 Usage:
237 cat hostsleep: reads the current hostsleep state
238 echo "1" > hostsleep : enable host sleep.
239 echo "0" > hostsleep : disable host sleep
240
229======================== 241========================
230IWCONFIG COMMANDS 242IWCONFIG COMMANDS
231======================== 243========================
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
deleted file mode 100644
index aa06070e5eab..000000000000
--- a/drivers/net/wireless/libertas/assoc.c
+++ /dev/null
@@ -1,2264 +0,0 @@
1/* Copyright (C) 2006, Red Hat, Inc. */
2
3#include <linux/types.h>
4#include <linux/etherdevice.h>
5#include <linux/ieee80211.h>
6#include <linux/if_arp.h>
7#include <linux/slab.h>
8#include <net/lib80211.h>
9
10#include "assoc.h"
11#include "decl.h"
12#include "host.h"
13#include "scan.h"
14#include "cmd.h"
15
16static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) =
17 { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
18static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) =
19 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
20
21/* The firmware needs the following bits masked out of the beacon-derived
22 * capability field when associating/joining to a BSS:
23 * 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused)
24 */
25#define CAPINFO_MASK (~(0xda00))
26
27/**
28 * 802.11b/g supported bitrates (in 500Kb/s units)
29 */
30u8 lbs_bg_rates[MAX_RATES] =
31 { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
320x00, 0x00 };
33
34
35static int assoc_helper_wep_keys(struct lbs_private *priv,
36 struct assoc_request *assoc_req);
37
38/**
39 * @brief This function finds common rates between rates and card rates.
40 *
41 * It will fill common rates in rates as output if found.
42 *
43 * NOTE: Setting the MSB of the basic rates need to be taken
44 * care, either before or after calling this function
45 *
46 * @param priv A pointer to struct lbs_private structure
47 * @param rates the buffer which keeps input and output
48 * @param rates_size the size of rates buffer; new size of buffer on return,
49 * which will be less than or equal to original rates_size
50 *
51 * @return 0 on success, or -1 on error
52 */
53static int get_common_rates(struct lbs_private *priv,
54 u8 *rates,
55 u16 *rates_size)
56{
57 int i, j;
58 u8 intersection[MAX_RATES];
59 u16 intersection_size;
60 u16 num_rates = 0;
61
62 intersection_size = min_t(u16, *rates_size, ARRAY_SIZE(intersection));
63
64 /* Allow each rate from 'rates' that is supported by the hardware */
65 for (i = 0; i < ARRAY_SIZE(lbs_bg_rates) && lbs_bg_rates[i]; i++) {
66 for (j = 0; j < intersection_size && rates[j]; j++) {
67 if (rates[j] == lbs_bg_rates[i])
68 intersection[num_rates++] = rates[j];
69 }
70 }
71
72 lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size);
73 lbs_deb_hex(LBS_DEB_JOIN, "card rates ", lbs_bg_rates,
74 ARRAY_SIZE(lbs_bg_rates));
75 lbs_deb_hex(LBS_DEB_JOIN, "common rates", intersection, num_rates);
76 lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate);
77
78 if (!priv->enablehwauto) {
79 for (i = 0; i < num_rates; i++) {
80 if (intersection[i] == priv->cur_rate)
81 goto done;
82 }
83 lbs_pr_alert("Previously set fixed data rate %#x isn't "
84 "compatible with the network.\n", priv->cur_rate);
85 return -1;
86 }
87
88done:
89 memset(rates, 0, *rates_size);
90 *rates_size = num_rates;
91 memcpy(rates, intersection, num_rates);
92 return 0;
93}
94
95
96/**
97 * @brief Sets the MSB on basic rates as the firmware requires
98 *
99 * Scan through an array and set the MSB for basic data rates.
100 *
101 * @param rates buffer of data rates
102 * @param len size of buffer
103 */
104static void lbs_set_basic_rate_flags(u8 *rates, size_t len)
105{
106 int i;
107
108 for (i = 0; i < len; i++) {
109 if (rates[i] == 0x02 || rates[i] == 0x04 ||
110 rates[i] == 0x0b || rates[i] == 0x16)
111 rates[i] |= 0x80;
112 }
113}
114
115
116static u8 iw_auth_to_ieee_auth(u8 auth)
117{
118 if (auth == IW_AUTH_ALG_OPEN_SYSTEM)
119 return 0x00;
120 else if (auth == IW_AUTH_ALG_SHARED_KEY)
121 return 0x01;
122 else if (auth == IW_AUTH_ALG_LEAP)
123 return 0x80;
124
125 lbs_deb_join("%s: invalid auth alg 0x%X\n", __func__, auth);
126 return 0;
127}
128
129/**
130 * @brief This function prepares the authenticate command. AUTHENTICATE only
131 * sets the authentication suite for future associations, as the firmware
132 * handles authentication internally during the ASSOCIATE command.
133 *
134 * @param priv A pointer to struct lbs_private structure
135 * @param bssid The peer BSSID with which to authenticate
136 * @param auth The authentication mode to use (from wireless.h)
137 *
138 * @return 0 or -1
139 */
140static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth)
141{
142 struct cmd_ds_802_11_authenticate cmd;
143 int ret = -1;
144
145 lbs_deb_enter(LBS_DEB_JOIN);
146
147 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
148 memcpy(cmd.bssid, bssid, ETH_ALEN);
149
150 cmd.authtype = iw_auth_to_ieee_auth(auth);
151
152 lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", bssid, cmd.authtype);
153
154 ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd);
155
156 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
157 return ret;
158}
159
160
161int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
162 struct assoc_request *assoc)
163{
164 struct cmd_ds_802_11_set_wep cmd;
165 int ret = 0;
166
167 lbs_deb_enter(LBS_DEB_CMD);
168
169 memset(&cmd, 0, sizeof(cmd));
170 cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP);
171 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
172
173 cmd.action = cpu_to_le16(cmd_action);
174
175 if (cmd_action == CMD_ACT_ADD) {
176 int i;
177
178 /* default tx key index */
179 cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx &
180 CMD_WEP_KEY_INDEX_MASK);
181
182 /* Copy key types and material to host command structure */
183 for (i = 0; i < 4; i++) {
184 struct enc_key *pkey = &assoc->wep_keys[i];
185
186 switch (pkey->len) {
187 case KEY_LEN_WEP_40:
188 cmd.keytype[i] = CMD_TYPE_WEP_40_BIT;
189 memmove(cmd.keymaterial[i], pkey->key, pkey->len);
190 lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i);
191 break;
192 case KEY_LEN_WEP_104:
193 cmd.keytype[i] = CMD_TYPE_WEP_104_BIT;
194 memmove(cmd.keymaterial[i], pkey->key, pkey->len);
195 lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i);
196 break;
197 case 0:
198 break;
199 default:
200 lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n",
201 i, pkey->len);
202 ret = -1;
203 goto done;
204 break;
205 }
206 }
207 } else if (cmd_action == CMD_ACT_REMOVE) {
208 /* ACT_REMOVE clears _all_ WEP keys */
209
210 /* default tx key index */
211 cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx &
212 CMD_WEP_KEY_INDEX_MASK);
213 lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx);
214 }
215
216 ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
217done:
218 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
219 return ret;
220}
221
222int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
223 uint16_t *enable)
224{
225 struct cmd_ds_802_11_enable_rsn cmd;
226 int ret;
227
228 lbs_deb_enter(LBS_DEB_CMD);
229
230 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
231 cmd.action = cpu_to_le16(cmd_action);
232
233 if (cmd_action == CMD_ACT_GET)
234 cmd.enable = 0;
235 else {
236 if (*enable)
237 cmd.enable = cpu_to_le16(CMD_ENABLE_RSN);
238 else
239 cmd.enable = cpu_to_le16(CMD_DISABLE_RSN);
240 lbs_deb_cmd("ENABLE_RSN: %d\n", *enable);
241 }
242
243 ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
244 if (!ret && cmd_action == CMD_ACT_GET)
245 *enable = le16_to_cpu(cmd.enable);
246
247 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
248 return ret;
249}
250
251static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam,
252 struct enc_key *key)
253{
254 lbs_deb_enter(LBS_DEB_CMD);
255
256 if (key->flags & KEY_INFO_WPA_ENABLED)
257 keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED);
258 if (key->flags & KEY_INFO_WPA_UNICAST)
259 keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST);
260 if (key->flags & KEY_INFO_WPA_MCAST)
261 keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST);
262
263 keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
264 keyparam->keytypeid = cpu_to_le16(key->type);
265 keyparam->keylen = cpu_to_le16(key->len);
266 memcpy(keyparam->key, key->key, key->len);
267
268 /* Length field doesn't include the {type,length} header */
269 keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4);
270 lbs_deb_leave(LBS_DEB_CMD);
271}
272
273int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
274 struct assoc_request *assoc)
275{
276 struct cmd_ds_802_11_key_material cmd;
277 int ret = 0;
278 int index = 0;
279
280 lbs_deb_enter(LBS_DEB_CMD);
281
282 cmd.action = cpu_to_le16(cmd_action);
283 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
284
285 if (cmd_action == CMD_ACT_GET) {
286 cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_header) + 2);
287 } else {
288 memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet));
289
290 if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) {
291 set_one_wpa_key(&cmd.keyParamSet[index],
292 &assoc->wpa_unicast_key);
293 index++;
294 }
295
296 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) {
297 set_one_wpa_key(&cmd.keyParamSet[index],
298 &assoc->wpa_mcast_key);
299 index++;
300 }
301
302 /* The common header and as many keys as we included */
303 cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd),
304 keyParamSet[index]));
305 }
306 ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
307 /* Copy the returned key to driver private data */
308 if (!ret && cmd_action == CMD_ACT_GET) {
309 void *buf_ptr = cmd.keyParamSet;
310 void *resp_end = &(&cmd)[1];
311
312 while (buf_ptr < resp_end) {
313 struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
314 struct enc_key *key;
315 uint16_t param_set_len = le16_to_cpu(keyparam->length);
316 uint16_t key_len = le16_to_cpu(keyparam->keylen);
317 uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
318 uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
319 void *end;
320
321 end = (void *)keyparam + sizeof(keyparam->type)
322 + sizeof(keyparam->length) + param_set_len;
323
324 /* Make sure we don't access past the end of the IEs */
325 if (end > resp_end)
326 break;
327
328 if (key_flags & KEY_INFO_WPA_UNICAST)
329 key = &priv->wpa_unicast_key;
330 else if (key_flags & KEY_INFO_WPA_MCAST)
331 key = &priv->wpa_mcast_key;
332 else
333 break;
334
335 /* Copy returned key into driver */
336 memset(key, 0, sizeof(struct enc_key));
337 if (key_len > sizeof(key->key))
338 break;
339 key->type = key_type;
340 key->flags = key_flags;
341 key->len = key_len;
342 memcpy(key->key, keyparam->key, key->len);
343
344 buf_ptr = end + 1;
345 }
346 }
347
348 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
349 return ret;
350}
351
352static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok)
353{
354/* Bit Rate
355* 15:13 Reserved
356* 12 54 Mbps
357* 11 48 Mbps
358* 10 36 Mbps
359* 9 24 Mbps
360* 8 18 Mbps
361* 7 12 Mbps
362* 6 9 Mbps
363* 5 6 Mbps
364* 4 Reserved
365* 3 11 Mbps
366* 2 5.5 Mbps
367* 1 2 Mbps
368* 0 1 Mbps
369**/
370
371 uint16_t ratemask;
372 int i = lbs_data_rate_to_fw_index(rate);
373 if (lower_rates_ok)
374 ratemask = (0x1fef >> (12 - i));
375 else
376 ratemask = (1 << i);
377 return cpu_to_le16(ratemask);
378}
379
380int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
381 uint16_t cmd_action)
382{
383 struct cmd_ds_802_11_rate_adapt_rateset cmd;
384 int ret;
385
386 lbs_deb_enter(LBS_DEB_CMD);
387
388 if (!priv->cur_rate && !priv->enablehwauto)
389 return -EINVAL;
390
391 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
392
393 cmd.action = cpu_to_le16(cmd_action);
394 cmd.enablehwauto = cpu_to_le16(priv->enablehwauto);
395 cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto);
396 ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd);
397 if (!ret && cmd_action == CMD_ACT_GET)
398 priv->enablehwauto = le16_to_cpu(cmd.enablehwauto);
399
400 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
401 return ret;
402}
403
404/**
405 * @brief Set the data rate
406 *
407 * @param priv A pointer to struct lbs_private structure
408 * @param rate The desired data rate, or 0 to clear a locked rate
409 *
410 * @return 0 on success, error on failure
411 */
412int lbs_set_data_rate(struct lbs_private *priv, u8 rate)
413{
414 struct cmd_ds_802_11_data_rate cmd;
415 int ret = 0;
416
417 lbs_deb_enter(LBS_DEB_CMD);
418
419 memset(&cmd, 0, sizeof(cmd));
420 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
421
422 if (rate > 0) {
423 cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE);
424 cmd.rates[0] = lbs_data_rate_to_fw_index(rate);
425 if (cmd.rates[0] == 0) {
426 lbs_deb_cmd("DATA_RATE: invalid requested rate of"
427 " 0x%02X\n", rate);
428 ret = 0;
429 goto out;
430 }
431 lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]);
432 } else {
433 cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO);
434 lbs_deb_cmd("DATA_RATE: setting auto\n");
435 }
436
437 ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd);
438 if (ret)
439 goto out;
440
441 lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof(cmd));
442
443 /* FIXME: get actual rates FW can do if this command actually returns
444 * all data rates supported.
445 */
446 priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]);
447 lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate);
448
449out:
450 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
451 return ret;
452}
453
454
455int lbs_cmd_802_11_rssi(struct lbs_private *priv,
456 struct cmd_ds_command *cmd)
457{
458
459 lbs_deb_enter(LBS_DEB_CMD);
460 cmd->command = cpu_to_le16(CMD_802_11_RSSI);
461 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) +
462 sizeof(struct cmd_header));
463 cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR);
464
465 /* reset Beacon SNR/NF/RSSI values */
466 priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
467 priv->SNR[TYPE_BEACON][TYPE_AVG] = 0;
468 priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
469 priv->NF[TYPE_BEACON][TYPE_AVG] = 0;
470 priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
471 priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
472
473 lbs_deb_leave(LBS_DEB_CMD);
474 return 0;
475}
476
477int lbs_ret_802_11_rssi(struct lbs_private *priv,
478 struct cmd_ds_command *resp)
479{
480 struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp;
481
482 lbs_deb_enter(LBS_DEB_CMD);
483
484 /* store the non average value */
485 priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR);
486 priv->NF[TYPE_BEACON][TYPE_NOAVG] =
487 get_unaligned_le16(&rssirsp->noisefloor);
488
489 priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR);
490 priv->NF[TYPE_BEACON][TYPE_AVG] =
491 get_unaligned_le16(&rssirsp->avgnoisefloor);
492
493 priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
494 CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
495 priv->NF[TYPE_BEACON][TYPE_NOAVG]);
496
497 priv->RSSI[TYPE_BEACON][TYPE_AVG] =
498 CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
499 priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
500
501 lbs_deb_cmd("RSSI: beacon %d, avg %d\n",
502 priv->RSSI[TYPE_BEACON][TYPE_NOAVG],
503 priv->RSSI[TYPE_BEACON][TYPE_AVG]);
504
505 lbs_deb_leave(LBS_DEB_CMD);
506 return 0;
507}
508
509
510int lbs_cmd_bcn_ctrl(struct lbs_private *priv,
511 struct cmd_ds_command *cmd,
512 u16 cmd_action)
513{
514 struct cmd_ds_802_11_beacon_control
515 *bcn_ctrl = &cmd->params.bcn_ctrl;
516
517 lbs_deb_enter(LBS_DEB_CMD);
518 cmd->size =
519 cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control)
520 + sizeof(struct cmd_header));
521 cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL);
522
523 bcn_ctrl->action = cpu_to_le16(cmd_action);
524 bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable);
525 bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period);
526
527 lbs_deb_leave(LBS_DEB_CMD);
528 return 0;
529}
530
531int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv,
532 struct cmd_ds_command *resp)
533{
534 struct cmd_ds_802_11_beacon_control *bcn_ctrl =
535 &resp->params.bcn_ctrl;
536
537 lbs_deb_enter(LBS_DEB_CMD);
538
539 if (bcn_ctrl->action == CMD_ACT_GET) {
540 priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable);
541 priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period);
542 }
543
544 lbs_deb_enter(LBS_DEB_CMD);
545 return 0;
546}
547
548
549
550static int lbs_assoc_post(struct lbs_private *priv,
551 struct cmd_ds_802_11_associate_response *resp)
552{
553 int ret = 0;
554 union iwreq_data wrqu;
555 struct bss_descriptor *bss;
556 u16 status_code;
557
558 lbs_deb_enter(LBS_DEB_ASSOC);
559
560 if (!priv->in_progress_assoc_req) {
561 lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n");
562 ret = -1;
563 goto done;
564 }
565 bss = &priv->in_progress_assoc_req->bss;
566
567 /*
568 * Older FW versions map the IEEE 802.11 Status Code in the association
569 * response to the following values returned in resp->statuscode:
570 *
571 * IEEE Status Code Marvell Status Code
572 * 0 -> 0x0000 ASSOC_RESULT_SUCCESS
573 * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
574 * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
575 * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
576 * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED
577 * others -> 0x0003 ASSOC_RESULT_REFUSED
578 *
579 * Other response codes:
580 * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused)
581 * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for
582 * association response from the AP)
583 */
584
585 status_code = le16_to_cpu(resp->statuscode);
586 if (priv->fwrelease < 0x09000000) {
587 switch (status_code) {
588 case 0x00:
589 break;
590 case 0x01:
591 lbs_deb_assoc("ASSOC_RESP: invalid parameters\n");
592 break;
593 case 0x02:
594 lbs_deb_assoc("ASSOC_RESP: internal timer "
595 "expired while waiting for the AP\n");
596 break;
597 case 0x03:
598 lbs_deb_assoc("ASSOC_RESP: association "
599 "refused by AP\n");
600 break;
601 case 0x04:
602 lbs_deb_assoc("ASSOC_RESP: authentication "
603 "refused by AP\n");
604 break;
605 default:
606 lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x "
607 " unknown\n", status_code);
608 break;
609 }
610 } else {
611 /* v9+ returns the AP's association response */
612 lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x\n", status_code);
613 }
614
615 if (status_code) {
616 lbs_mac_event_disconnected(priv);
617 ret = status_code;
618 goto done;
619 }
620
621 lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP",
622 (void *) (resp + sizeof (resp->hdr)),
623 le16_to_cpu(resp->hdr.size) - sizeof (resp->hdr));
624
625 /* Send a Media Connected event, according to the Spec */
626 priv->connect_status = LBS_CONNECTED;
627
628 /* Update current SSID and BSSID */
629 memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN);
630 priv->curbssparams.ssid_len = bss->ssid_len;
631 memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
632
633 priv->SNR[TYPE_RXPD][TYPE_AVG] = 0;
634 priv->NF[TYPE_RXPD][TYPE_AVG] = 0;
635
636 memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
637 memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
638 priv->nextSNRNF = 0;
639 priv->numSNRNF = 0;
640
641 netif_carrier_on(priv->dev);
642 if (!priv->tx_pending_len)
643 netif_wake_queue(priv->dev);
644
645 memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
646 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
647 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
648
649done:
650 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
651 return ret;
652}
653
654/**
655 * @brief This function prepares an association-class command.
656 *
657 * @param priv A pointer to struct lbs_private structure
658 * @param assoc_req The association request describing the BSS to associate
659 * or reassociate with
660 * @param command The actual command, either CMD_802_11_ASSOCIATE or
661 * CMD_802_11_REASSOCIATE
662 *
663 * @return 0 or -1
664 */
665static int lbs_associate(struct lbs_private *priv,
666 struct assoc_request *assoc_req,
667 u16 command)
668{
669 struct cmd_ds_802_11_associate cmd;
670 int ret = 0;
671 struct bss_descriptor *bss = &assoc_req->bss;
672 u8 *pos = &(cmd.iebuf[0]);
673 u16 tmpcap, tmplen, tmpauth;
674 struct mrvl_ie_ssid_param_set *ssid;
675 struct mrvl_ie_ds_param_set *ds;
676 struct mrvl_ie_cf_param_set *cf;
677 struct mrvl_ie_rates_param_set *rates;
678 struct mrvl_ie_rsn_param_set *rsn;
679 struct mrvl_ie_auth_type *auth;
680
681 lbs_deb_enter(LBS_DEB_ASSOC);
682
683 BUG_ON((command != CMD_802_11_ASSOCIATE) &&
684 (command != CMD_802_11_REASSOCIATE));
685
686 memset(&cmd, 0, sizeof(cmd));
687 cmd.hdr.command = cpu_to_le16(command);
688
689 /* Fill in static fields */
690 memcpy(cmd.bssid, bss->bssid, ETH_ALEN);
691 cmd.listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
692
693 /* Capability info */
694 tmpcap = (bss->capability & CAPINFO_MASK);
695 if (bss->mode == IW_MODE_INFRA)
696 tmpcap |= WLAN_CAPABILITY_ESS;
697 cmd.capability = cpu_to_le16(tmpcap);
698 lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap);
699
700 /* SSID */
701 ssid = (struct mrvl_ie_ssid_param_set *) pos;
702 ssid->header.type = cpu_to_le16(TLV_TYPE_SSID);
703 tmplen = bss->ssid_len;
704 ssid->header.len = cpu_to_le16(tmplen);
705 memcpy(ssid->ssid, bss->ssid, tmplen);
706 pos += sizeof(ssid->header) + tmplen;
707
708 ds = (struct mrvl_ie_ds_param_set *) pos;
709 ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
710 ds->header.len = cpu_to_le16(1);
711 ds->channel = bss->phy.ds.channel;
712 pos += sizeof(ds->header) + 1;
713
714 cf = (struct mrvl_ie_cf_param_set *) pos;
715 cf->header.type = cpu_to_le16(TLV_TYPE_CF);
716 tmplen = sizeof(*cf) - sizeof (cf->header);
717 cf->header.len = cpu_to_le16(tmplen);
718 /* IE payload should be zeroed, firmware fills it in for us */
719 pos += sizeof(*cf);
720
721 rates = (struct mrvl_ie_rates_param_set *) pos;
722 rates->header.type = cpu_to_le16(TLV_TYPE_RATES);
723 tmplen = min_t(u16, ARRAY_SIZE(bss->rates), MAX_RATES);
724 memcpy(&rates->rates, &bss->rates, tmplen);
725 if (get_common_rates(priv, rates->rates, &tmplen)) {
726 ret = -1;
727 goto done;
728 }
729 pos += sizeof(rates->header) + tmplen;
730 rates->header.len = cpu_to_le16(tmplen);
731 lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen);
732
733 /* Copy the infra. association rates into Current BSS state structure */
734 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
735 memcpy(&priv->curbssparams.rates, &rates->rates, tmplen);
736
737 /* Set MSB on basic rates as the firmware requires, but _after_
738 * copying to current bss rates.
739 */
740 lbs_set_basic_rate_flags(rates->rates, tmplen);
741
742 /* Firmware v9+ indicate authentication suites as a TLV */
743 if (priv->fwrelease >= 0x09000000) {
744 auth = (struct mrvl_ie_auth_type *) pos;
745 auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
746 auth->header.len = cpu_to_le16(2);
747 tmpauth = iw_auth_to_ieee_auth(priv->secinfo.auth_mode);
748 auth->auth = cpu_to_le16(tmpauth);
749 pos += sizeof(auth->header) + 2;
750
751 lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n",
752 bss->bssid, priv->secinfo.auth_mode);
753 }
754
755 /* WPA/WPA2 IEs */
756 if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
757 rsn = (struct mrvl_ie_rsn_param_set *) pos;
758 /* WPA_IE or WPA2_IE */
759 rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]);
760 tmplen = (u16) assoc_req->wpa_ie[1];
761 rsn->header.len = cpu_to_le16(tmplen);
762 memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen);
763 lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: WPA/RSN IE", (u8 *) rsn,
764 sizeof(rsn->header) + tmplen);
765 pos += sizeof(rsn->header) + tmplen;
766 }
767
768 cmd.hdr.size = cpu_to_le16((sizeof(cmd) - sizeof(cmd.iebuf)) +
769 (u16)(pos - (u8 *) &cmd.iebuf));
770
771 /* update curbssparams */
772 priv->channel = bss->phy.ds.channel;
773
774 ret = lbs_cmd_with_response(priv, command, &cmd);
775 if (ret == 0) {
776 ret = lbs_assoc_post(priv,
777 (struct cmd_ds_802_11_associate_response *) &cmd);
778 }
779
780done:
781 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
782 return ret;
783}
784
785/**
786 * @brief Associate to a specific BSS discovered in a scan
787 *
788 * @param priv A pointer to struct lbs_private structure
789 * @param assoc_req The association request describing the BSS to associate with
790 *
791 * @return 0-success, otherwise fail
792 */
793static int lbs_try_associate(struct lbs_private *priv,
794 struct assoc_request *assoc_req)
795{
796 int ret;
797 u8 preamble = RADIO_PREAMBLE_LONG;
798
799 lbs_deb_enter(LBS_DEB_ASSOC);
800
801 /* FW v9 and higher indicate authentication suites as a TLV in the
802 * association command, not as a separate authentication command.
803 */
804 if (priv->fwrelease < 0x09000000) {
805 ret = lbs_set_authentication(priv, assoc_req->bss.bssid,
806 priv->secinfo.auth_mode);
807 if (ret)
808 goto out;
809 }
810
811 /* Use short preamble only when both the BSS and firmware support it */
812 if (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
813 preamble = RADIO_PREAMBLE_SHORT;
814
815 ret = lbs_set_radio(priv, preamble, 1);
816 if (ret)
817 goto out;
818
819 ret = lbs_associate(priv, assoc_req, CMD_802_11_ASSOCIATE);
820 /* If the association fails with current auth mode, let's
821 * try by changing the auth mode
822 */
823 if ((priv->authtype_auto) &&
824 (ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) &&
825 (assoc_req->secinfo.wep_enabled) &&
826 (priv->connect_status != LBS_CONNECTED)) {
827 if (priv->secinfo.auth_mode == IW_AUTH_ALG_OPEN_SYSTEM)
828 priv->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
829 else
830 priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
831 if (!assoc_helper_wep_keys(priv, assoc_req))
832 ret = lbs_associate(priv, assoc_req,
833 CMD_802_11_ASSOCIATE);
834 }
835
836 if (ret)
837 ret = -1;
838out:
839 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
840 return ret;
841}
842
843static int lbs_adhoc_post(struct lbs_private *priv,
844 struct cmd_ds_802_11_ad_hoc_result *resp)
845{
846 int ret = 0;
847 u16 command = le16_to_cpu(resp->hdr.command);
848 u16 result = le16_to_cpu(resp->hdr.result);
849 union iwreq_data wrqu;
850 struct bss_descriptor *bss;
851 DECLARE_SSID_BUF(ssid);
852
853 lbs_deb_enter(LBS_DEB_JOIN);
854
855 if (!priv->in_progress_assoc_req) {
856 lbs_deb_join("ADHOC_RESP: no in-progress association "
857 "request\n");
858 ret = -1;
859 goto done;
860 }
861 bss = &priv->in_progress_assoc_req->bss;
862
863 /*
864 * Join result code 0 --> SUCCESS
865 */
866 if (result) {
867 lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result);
868 if (priv->connect_status == LBS_CONNECTED)
869 lbs_mac_event_disconnected(priv);
870 ret = -1;
871 goto done;
872 }
873
874 /* Send a Media Connected event, according to the Spec */
875 priv->connect_status = LBS_CONNECTED;
876
877 if (command == CMD_RET(CMD_802_11_AD_HOC_START)) {
878 /* Update the created network descriptor with the new BSSID */
879 memcpy(bss->bssid, resp->bssid, ETH_ALEN);
880 }
881
882 /* Set the BSSID from the joined/started descriptor */
883 memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN);
884
885 /* Set the new SSID to current SSID */
886 memcpy(&priv->curbssparams.ssid, &bss->ssid, IEEE80211_MAX_SSID_LEN);
887 priv->curbssparams.ssid_len = bss->ssid_len;
888
889 netif_carrier_on(priv->dev);
890 if (!priv->tx_pending_len)
891 netif_wake_queue(priv->dev);
892
893 memset(&wrqu, 0, sizeof(wrqu));
894 memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN);
895 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
896 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
897
898 lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n",
899 print_ssid(ssid, bss->ssid, bss->ssid_len),
900 priv->curbssparams.bssid,
901 priv->channel);
902
903done:
904 lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret);
905 return ret;
906}
907
908/**
909 * @brief Join an adhoc network found in a previous scan
910 *
911 * @param priv A pointer to struct lbs_private structure
912 * @param assoc_req The association request describing the BSS to join
913 *
914 * @return 0 on success, error on failure
915 */
916static int lbs_adhoc_join(struct lbs_private *priv,
917 struct assoc_request *assoc_req)
918{
919 struct cmd_ds_802_11_ad_hoc_join cmd;
920 struct bss_descriptor *bss = &assoc_req->bss;
921 u8 preamble = RADIO_PREAMBLE_LONG;
922 DECLARE_SSID_BUF(ssid);
923 u16 ratesize = 0;
924 int ret = 0;
925
926 lbs_deb_enter(LBS_DEB_ASSOC);
927
928 lbs_deb_join("current SSID '%s', ssid length %u\n",
929 print_ssid(ssid, priv->curbssparams.ssid,
930 priv->curbssparams.ssid_len),
931 priv->curbssparams.ssid_len);
932 lbs_deb_join("requested ssid '%s', ssid length %u\n",
933 print_ssid(ssid, bss->ssid, bss->ssid_len),
934 bss->ssid_len);
935
936 /* check if the requested SSID is already joined */
937 if (priv->curbssparams.ssid_len &&
938 !lbs_ssid_cmp(priv->curbssparams.ssid,
939 priv->curbssparams.ssid_len,
940 bss->ssid, bss->ssid_len) &&
941 (priv->mode == IW_MODE_ADHOC) &&
942 (priv->connect_status == LBS_CONNECTED)) {
943 union iwreq_data wrqu;
944
945 lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as "
946 "current, not attempting to re-join");
947
948 /* Send the re-association event though, because the association
949 * request really was successful, even if just a null-op.
950 */
951 memset(&wrqu, 0, sizeof(wrqu));
952 memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid,
953 ETH_ALEN);
954 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
955 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
956 goto out;
957 }
958
959 /* Use short preamble only when both the BSS and firmware support it */
960 if (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) {
961 lbs_deb_join("AdhocJoin: Short preamble\n");
962 preamble = RADIO_PREAMBLE_SHORT;
963 }
964
965 ret = lbs_set_radio(priv, preamble, 1);
966 if (ret)
967 goto out;
968
969 lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel);
970 lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band);
971
972 priv->adhoccreate = 0;
973 priv->channel = bss->channel;
974
975 /* Build the join command */
976 memset(&cmd, 0, sizeof(cmd));
977 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
978
979 cmd.bss.type = CMD_BSS_TYPE_IBSS;
980 cmd.bss.beaconperiod = cpu_to_le16(bss->beaconperiod);
981
982 memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN);
983 memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len);
984
985 memcpy(&cmd.bss.ds, &bss->phy.ds, sizeof(struct ieee_ie_ds_param_set));
986
987 memcpy(&cmd.bss.ibss, &bss->ss.ibss,
988 sizeof(struct ieee_ie_ibss_param_set));
989
990 cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
991 lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n",
992 bss->capability, CAPINFO_MASK);
993
994 /* information on BSSID descriptor passed to FW */
995 lbs_deb_join("ADHOC_J_CMD: BSSID = %pM, SSID = '%s'\n",
996 cmd.bss.bssid, cmd.bss.ssid);
997
998 /* Only v8 and below support setting these */
999 if (priv->fwrelease < 0x09000000) {
1000 /* failtimeout */
1001 cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
1002 /* probedelay */
1003 cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
1004 }
1005
1006 /* Copy Data rates from the rates recorded in scan response */
1007 memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates));
1008 ratesize = min_t(u16, ARRAY_SIZE(cmd.bss.rates), ARRAY_SIZE (bss->rates));
1009 memcpy(cmd.bss.rates, bss->rates, ratesize);
1010 if (get_common_rates(priv, cmd.bss.rates, &ratesize)) {
1011 lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n");
1012 ret = -1;
1013 goto out;
1014 }
1015
1016 /* Copy the ad-hoc creation rates into Current BSS state structure */
1017 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
1018 memcpy(&priv->curbssparams.rates, cmd.bss.rates, ratesize);
1019
1020 /* Set MSB on basic rates as the firmware requires, but _after_
1021 * copying to current bss rates.
1022 */
1023 lbs_set_basic_rate_flags(cmd.bss.rates, ratesize);
1024
1025 cmd.bss.ibss.atimwindow = bss->atimwindow;
1026
1027 if (assoc_req->secinfo.wep_enabled) {
1028 u16 tmp = le16_to_cpu(cmd.bss.capability);
1029 tmp |= WLAN_CAPABILITY_PRIVACY;
1030 cmd.bss.capability = cpu_to_le16(tmp);
1031 }
1032
1033 if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
1034 __le32 local_ps_mode = cpu_to_le32(LBS802_11POWERMODECAM);
1035
1036 /* wake up first */
1037 ret = lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1038 CMD_ACT_SET, 0, 0,
1039 &local_ps_mode);
1040 if (ret) {
1041 ret = -1;
1042 goto out;
1043 }
1044 }
1045
1046 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd);
1047 if (ret == 0) {
1048 ret = lbs_adhoc_post(priv,
1049 (struct cmd_ds_802_11_ad_hoc_result *)&cmd);
1050 }
1051
1052out:
1053 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1054 return ret;
1055}
1056
1057/**
1058 * @brief Start an Adhoc Network
1059 *
1060 * @param priv A pointer to struct lbs_private structure
1061 * @param assoc_req The association request describing the BSS to start
1062 *
1063 * @return 0 on success, error on failure
1064 */
1065static int lbs_adhoc_start(struct lbs_private *priv,
1066 struct assoc_request *assoc_req)
1067{
1068 struct cmd_ds_802_11_ad_hoc_start cmd;
1069 u8 preamble = RADIO_PREAMBLE_SHORT;
1070 size_t ratesize = 0;
1071 u16 tmpcap = 0;
1072 int ret = 0;
1073 DECLARE_SSID_BUF(ssid);
1074
1075 lbs_deb_enter(LBS_DEB_ASSOC);
1076
1077 ret = lbs_set_radio(priv, preamble, 1);
1078 if (ret)
1079 goto out;
1080
1081 /* Build the start command */
1082 memset(&cmd, 0, sizeof(cmd));
1083 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1084
1085 memcpy(cmd.ssid, assoc_req->ssid, assoc_req->ssid_len);
1086
1087 lbs_deb_join("ADHOC_START: SSID '%s', ssid length %u\n",
1088 print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len),
1089 assoc_req->ssid_len);
1090
1091 cmd.bsstype = CMD_BSS_TYPE_IBSS;
1092
1093 if (priv->beacon_period == 0)
1094 priv->beacon_period = MRVDRV_BEACON_INTERVAL;
1095 cmd.beaconperiod = cpu_to_le16(priv->beacon_period);
1096
1097 WARN_ON(!assoc_req->channel);
1098
1099 /* set Physical parameter set */
1100 cmd.ds.header.id = WLAN_EID_DS_PARAMS;
1101 cmd.ds.header.len = 1;
1102 cmd.ds.channel = assoc_req->channel;
1103
1104 /* set IBSS parameter set */
1105 cmd.ibss.header.id = WLAN_EID_IBSS_PARAMS;
1106 cmd.ibss.header.len = 2;
1107 cmd.ibss.atimwindow = cpu_to_le16(0);
1108
1109 /* set capability info */
1110 tmpcap = WLAN_CAPABILITY_IBSS;
1111 if (assoc_req->secinfo.wep_enabled ||
1112 assoc_req->secinfo.WPAenabled ||
1113 assoc_req->secinfo.WPA2enabled) {
1114 lbs_deb_join("ADHOC_START: WEP/WPA enabled, privacy on\n");
1115 tmpcap |= WLAN_CAPABILITY_PRIVACY;
1116 } else
1117 lbs_deb_join("ADHOC_START: WEP disabled, privacy off\n");
1118
1119 cmd.capability = cpu_to_le16(tmpcap);
1120
1121 /* Only v8 and below support setting probe delay */
1122 if (priv->fwrelease < 0x09000000)
1123 cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
1124
1125 ratesize = min(sizeof(cmd.rates), sizeof(lbs_bg_rates));
1126 memcpy(cmd.rates, lbs_bg_rates, ratesize);
1127
1128 /* Copy the ad-hoc creating rates into Current BSS state structure */
1129 memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates));
1130 memcpy(&priv->curbssparams.rates, &cmd.rates, ratesize);
1131
1132 /* Set MSB on basic rates as the firmware requires, but _after_
1133 * copying to current bss rates.
1134 */
1135 lbs_set_basic_rate_flags(cmd.rates, ratesize);
1136
1137 lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n",
1138 cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]);
1139
1140 lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n",
1141 assoc_req->channel, assoc_req->band);
1142
1143 priv->adhoccreate = 1;
1144 priv->mode = IW_MODE_ADHOC;
1145
1146 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd);
1147 if (ret == 0)
1148 ret = lbs_adhoc_post(priv,
1149 (struct cmd_ds_802_11_ad_hoc_result *)&cmd);
1150
1151out:
1152 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1153 return ret;
1154}
1155
1156/**
1157 * @brief Stop and Ad-Hoc network and exit Ad-Hoc mode
1158 *
1159 * @param priv A pointer to struct lbs_private structure
1160 * @return 0 on success, or an error
1161 */
1162int lbs_adhoc_stop(struct lbs_private *priv)
1163{
1164 struct cmd_ds_802_11_ad_hoc_stop cmd;
1165 int ret;
1166
1167 lbs_deb_enter(LBS_DEB_JOIN);
1168
1169 memset(&cmd, 0, sizeof (cmd));
1170 cmd.hdr.size = cpu_to_le16 (sizeof (cmd));
1171
1172 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd);
1173
1174 /* Clean up everything even if there was an error */
1175 lbs_mac_event_disconnected(priv);
1176
1177 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1178 return ret;
1179}
1180
1181static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
1182 struct bss_descriptor *match_bss)
1183{
1184 if (!secinfo->wep_enabled &&
1185 !secinfo->WPAenabled && !secinfo->WPA2enabled &&
1186 match_bss->wpa_ie[0] != WLAN_EID_GENERIC &&
1187 match_bss->rsn_ie[0] != WLAN_EID_RSN &&
1188 !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
1189 return 1;
1190 else
1191 return 0;
1192}
1193
1194static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo,
1195 struct bss_descriptor *match_bss)
1196{
1197 if (secinfo->wep_enabled &&
1198 !secinfo->WPAenabled && !secinfo->WPA2enabled &&
1199 (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
1200 return 1;
1201 else
1202 return 0;
1203}
1204
1205static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
1206 struct bss_descriptor *match_bss)
1207{
1208 if (!secinfo->wep_enabled && secinfo->WPAenabled &&
1209 (match_bss->wpa_ie[0] == WLAN_EID_GENERIC)
1210 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
1211 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
1212 )
1213 return 1;
1214 else
1215 return 0;
1216}
1217
1218static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
1219 struct bss_descriptor *match_bss)
1220{
1221 if (!secinfo->wep_enabled && secinfo->WPA2enabled &&
1222 (match_bss->rsn_ie[0] == WLAN_EID_RSN)
1223 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
1224 (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
1225 )
1226 return 1;
1227 else
1228 return 0;
1229}
1230
1231static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
1232 struct bss_descriptor *match_bss)
1233{
1234 if (!secinfo->wep_enabled &&
1235 !secinfo->WPAenabled && !secinfo->WPA2enabled &&
1236 (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) &&
1237 (match_bss->rsn_ie[0] != WLAN_EID_RSN) &&
1238 (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
1239 return 1;
1240 else
1241 return 0;
1242}
1243
1244/**
1245 * @brief Check if a scanned network compatible with the driver settings
1246 *
1247 * WEP WPA WPA2 ad-hoc encrypt Network
1248 * enabled enabled enabled AES mode privacy WPA WPA2 Compatible
1249 * 0 0 0 0 NONE 0 0 0 yes No security
1250 * 1 0 0 0 NONE 1 0 0 yes Static WEP
1251 * 0 1 0 0 x 1x 1 x yes WPA
1252 * 0 0 1 0 x 1x x 1 yes WPA2
1253 * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES
1254 * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP
1255 *
1256 *
1257 * @param priv A pointer to struct lbs_private
1258 * @param index Index in scantable to check against current driver settings
1259 * @param mode Network mode: Infrastructure or IBSS
1260 *
1261 * @return Index in scantable, or error code if negative
1262 */
1263static int is_network_compatible(struct lbs_private *priv,
1264 struct bss_descriptor *bss, uint8_t mode)
1265{
1266 int matched = 0;
1267
1268 lbs_deb_enter(LBS_DEB_SCAN);
1269
1270 if (bss->mode != mode)
1271 goto done;
1272
1273 matched = match_bss_no_security(&priv->secinfo, bss);
1274 if (matched)
1275 goto done;
1276 matched = match_bss_static_wep(&priv->secinfo, bss);
1277 if (matched)
1278 goto done;
1279 matched = match_bss_wpa(&priv->secinfo, bss);
1280 if (matched) {
1281 lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x "
1282 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
1283 "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
1284 priv->secinfo.wep_enabled ? "e" : "d",
1285 priv->secinfo.WPAenabled ? "e" : "d",
1286 priv->secinfo.WPA2enabled ? "e" : "d",
1287 (bss->capability & WLAN_CAPABILITY_PRIVACY));
1288 goto done;
1289 }
1290 matched = match_bss_wpa2(&priv->secinfo, bss);
1291 if (matched) {
1292 lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x "
1293 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s "
1294 "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0],
1295 priv->secinfo.wep_enabled ? "e" : "d",
1296 priv->secinfo.WPAenabled ? "e" : "d",
1297 priv->secinfo.WPA2enabled ? "e" : "d",
1298 (bss->capability & WLAN_CAPABILITY_PRIVACY));
1299 goto done;
1300 }
1301 matched = match_bss_dynamic_wep(&priv->secinfo, bss);
1302 if (matched) {
1303 lbs_deb_scan("is_network_compatible() dynamic WEP: "
1304 "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n",
1305 bss->wpa_ie[0], bss->rsn_ie[0],
1306 (bss->capability & WLAN_CAPABILITY_PRIVACY));
1307 goto done;
1308 }
1309
1310 /* bss security settings don't match those configured on card */
1311 lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x "
1312 "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n",
1313 bss->wpa_ie[0], bss->rsn_ie[0],
1314 priv->secinfo.wep_enabled ? "e" : "d",
1315 priv->secinfo.WPAenabled ? "e" : "d",
1316 priv->secinfo.WPA2enabled ? "e" : "d",
1317 (bss->capability & WLAN_CAPABILITY_PRIVACY));
1318
1319done:
1320 lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched);
1321 return matched;
1322}
1323
1324/**
1325 * @brief This function finds a specific compatible BSSID in the scan list
1326 *
1327 * Used in association code
1328 *
1329 * @param priv A pointer to struct lbs_private
1330 * @param bssid BSSID to find in the scan list
1331 * @param mode Network mode: Infrastructure or IBSS
1332 *
1333 * @return index in BSSID list, or error return code (< 0)
1334 */
1335static struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv,
1336 uint8_t *bssid, uint8_t mode)
1337{
1338 struct bss_descriptor *iter_bss;
1339 struct bss_descriptor *found_bss = NULL;
1340
1341 lbs_deb_enter(LBS_DEB_SCAN);
1342
1343 if (!bssid)
1344 goto out;
1345
1346 lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN);
1347
1348 /* Look through the scan table for a compatible match. The loop will
1349 * continue past a matched bssid that is not compatible in case there
1350 * is an AP with multiple SSIDs assigned to the same BSSID
1351 */
1352 mutex_lock(&priv->lock);
1353 list_for_each_entry(iter_bss, &priv->network_list, list) {
1354 if (compare_ether_addr(iter_bss->bssid, bssid))
1355 continue; /* bssid doesn't match */
1356 switch (mode) {
1357 case IW_MODE_INFRA:
1358 case IW_MODE_ADHOC:
1359 if (!is_network_compatible(priv, iter_bss, mode))
1360 break;
1361 found_bss = iter_bss;
1362 break;
1363 default:
1364 found_bss = iter_bss;
1365 break;
1366 }
1367 }
1368 mutex_unlock(&priv->lock);
1369
1370out:
1371 lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
1372 return found_bss;
1373}
1374
1375/**
1376 * @brief This function finds ssid in ssid list.
1377 *
1378 * Used in association code
1379 *
1380 * @param priv A pointer to struct lbs_private
1381 * @param ssid SSID to find in the list
1382 * @param bssid BSSID to qualify the SSID selection (if provided)
1383 * @param mode Network mode: Infrastructure or IBSS
1384 *
1385 * @return index in BSSID list
1386 */
1387static struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv,
1388 uint8_t *ssid, uint8_t ssid_len,
1389 uint8_t *bssid, uint8_t mode,
1390 int channel)
1391{
1392 u32 bestrssi = 0;
1393 struct bss_descriptor *iter_bss = NULL;
1394 struct bss_descriptor *found_bss = NULL;
1395 struct bss_descriptor *tmp_oldest = NULL;
1396
1397 lbs_deb_enter(LBS_DEB_SCAN);
1398
1399 mutex_lock(&priv->lock);
1400
1401 list_for_each_entry(iter_bss, &priv->network_list, list) {
1402 if (!tmp_oldest ||
1403 (iter_bss->last_scanned < tmp_oldest->last_scanned))
1404 tmp_oldest = iter_bss;
1405
1406 if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len,
1407 ssid, ssid_len) != 0)
1408 continue; /* ssid doesn't match */
1409 if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0)
1410 continue; /* bssid doesn't match */
1411 if ((channel > 0) && (iter_bss->channel != channel))
1412 continue; /* channel doesn't match */
1413
1414 switch (mode) {
1415 case IW_MODE_INFRA:
1416 case IW_MODE_ADHOC:
1417 if (!is_network_compatible(priv, iter_bss, mode))
1418 break;
1419
1420 if (bssid) {
1421 /* Found requested BSSID */
1422 found_bss = iter_bss;
1423 goto out;
1424 }
1425
1426 if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
1427 bestrssi = SCAN_RSSI(iter_bss->rssi);
1428 found_bss = iter_bss;
1429 }
1430 break;
1431 case IW_MODE_AUTO:
1432 default:
1433 if (SCAN_RSSI(iter_bss->rssi) > bestrssi) {
1434 bestrssi = SCAN_RSSI(iter_bss->rssi);
1435 found_bss = iter_bss;
1436 }
1437 break;
1438 }
1439 }
1440
1441out:
1442 mutex_unlock(&priv->lock);
1443 lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss);
1444 return found_bss;
1445}
1446
1447static int assoc_helper_essid(struct lbs_private *priv,
1448 struct assoc_request * assoc_req)
1449{
1450 int ret = 0;
1451 struct bss_descriptor * bss;
1452 int channel = -1;
1453 DECLARE_SSID_BUF(ssid);
1454
1455 lbs_deb_enter(LBS_DEB_ASSOC);
1456
1457 /* FIXME: take channel into account when picking SSIDs if a channel
1458 * is set.
1459 */
1460
1461 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
1462 channel = assoc_req->channel;
1463
1464 lbs_deb_assoc("SSID '%s' requested\n",
1465 print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len));
1466 if (assoc_req->mode == IW_MODE_INFRA) {
1467 lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
1468 assoc_req->ssid_len);
1469
1470 bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
1471 assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel);
1472 if (bss != NULL) {
1473 memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
1474 ret = lbs_try_associate(priv, assoc_req);
1475 } else {
1476 lbs_deb_assoc("SSID not found; cannot associate\n");
1477 }
1478 } else if (assoc_req->mode == IW_MODE_ADHOC) {
1479 /* Scan for the network, do not save previous results. Stale
1480 * scan data will cause us to join a non-existant adhoc network
1481 */
1482 lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
1483 assoc_req->ssid_len);
1484
1485 /* Search for the requested SSID in the scan table */
1486 bss = lbs_find_ssid_in_list(priv, assoc_req->ssid,
1487 assoc_req->ssid_len, NULL, IW_MODE_ADHOC, channel);
1488 if (bss != NULL) {
1489 lbs_deb_assoc("SSID found, will join\n");
1490 memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
1491 lbs_adhoc_join(priv, assoc_req);
1492 } else {
1493 /* else send START command */
1494 lbs_deb_assoc("SSID not found, creating adhoc network\n");
1495 memcpy(&assoc_req->bss.ssid, &assoc_req->ssid,
1496 IEEE80211_MAX_SSID_LEN);
1497 assoc_req->bss.ssid_len = assoc_req->ssid_len;
1498 lbs_adhoc_start(priv, assoc_req);
1499 }
1500 }
1501
1502 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1503 return ret;
1504}
1505
1506
1507static int assoc_helper_bssid(struct lbs_private *priv,
1508 struct assoc_request * assoc_req)
1509{
1510 int ret = 0;
1511 struct bss_descriptor * bss;
1512
1513 lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID %pM", assoc_req->bssid);
1514
1515 /* Search for index position in list for requested MAC */
1516 bss = lbs_find_bssid_in_list(priv, assoc_req->bssid,
1517 assoc_req->mode);
1518 if (bss == NULL) {
1519 lbs_deb_assoc("ASSOC: WAP: BSSID %pM not found, "
1520 "cannot associate.\n", assoc_req->bssid);
1521 goto out;
1522 }
1523
1524 memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor));
1525 if (assoc_req->mode == IW_MODE_INFRA) {
1526 ret = lbs_try_associate(priv, assoc_req);
1527 lbs_deb_assoc("ASSOC: lbs_try_associate(bssid) returned %d\n",
1528 ret);
1529 } else if (assoc_req->mode == IW_MODE_ADHOC) {
1530 lbs_adhoc_join(priv, assoc_req);
1531 }
1532
1533out:
1534 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1535 return ret;
1536}
1537
1538
1539static int assoc_helper_associate(struct lbs_private *priv,
1540 struct assoc_request * assoc_req)
1541{
1542 int ret = 0, done = 0;
1543
1544 lbs_deb_enter(LBS_DEB_ASSOC);
1545
1546 /* If we're given and 'any' BSSID, try associating based on SSID */
1547
1548 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
1549 if (compare_ether_addr(bssid_any, assoc_req->bssid) &&
1550 compare_ether_addr(bssid_off, assoc_req->bssid)) {
1551 ret = assoc_helper_bssid(priv, assoc_req);
1552 done = 1;
1553 }
1554 }
1555
1556 if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
1557 ret = assoc_helper_essid(priv, assoc_req);
1558 }
1559
1560 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1561 return ret;
1562}
1563
1564
1565static int assoc_helper_mode(struct lbs_private *priv,
1566 struct assoc_request * assoc_req)
1567{
1568 int ret = 0;
1569
1570 lbs_deb_enter(LBS_DEB_ASSOC);
1571
1572 if (assoc_req->mode == priv->mode)
1573 goto done;
1574
1575 if (assoc_req->mode == IW_MODE_INFRA) {
1576 if (priv->psstate != PS_STATE_FULL_POWER)
1577 lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
1578 priv->psmode = LBS802_11POWERMODECAM;
1579 }
1580
1581 priv->mode = assoc_req->mode;
1582 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE,
1583 assoc_req->mode == IW_MODE_ADHOC ? 2 : 1);
1584
1585done:
1586 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1587 return ret;
1588}
1589
1590static int assoc_helper_channel(struct lbs_private *priv,
1591 struct assoc_request * assoc_req)
1592{
1593 int ret = 0;
1594
1595 lbs_deb_enter(LBS_DEB_ASSOC);
1596
1597 ret = lbs_update_channel(priv);
1598 if (ret) {
1599 lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
1600 goto done;
1601 }
1602
1603 if (assoc_req->channel == priv->channel)
1604 goto done;
1605
1606 if (priv->mesh_dev) {
1607 /* Change mesh channel first; 21.p21 firmware won't let
1608 you change channel otherwise (even though it'll return
1609 an error to this */
1610 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP,
1611 assoc_req->channel);
1612 }
1613
1614 lbs_deb_assoc("ASSOC: channel: %d -> %d\n",
1615 priv->channel, assoc_req->channel);
1616
1617 ret = lbs_set_channel(priv, assoc_req->channel);
1618 if (ret < 0)
1619 lbs_deb_assoc("ASSOC: channel: error setting channel.\n");
1620
1621 /* FIXME: shouldn't need to grab the channel _again_ after setting
1622 * it since the firmware is supposed to return the new channel, but
1623 * whatever... */
1624 ret = lbs_update_channel(priv);
1625 if (ret) {
1626 lbs_deb_assoc("ASSOC: channel: error getting channel.\n");
1627 goto done;
1628 }
1629
1630 if (assoc_req->channel != priv->channel) {
1631 lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n",
1632 assoc_req->channel);
1633 goto restore_mesh;
1634 }
1635
1636 if (assoc_req->secinfo.wep_enabled &&
1637 (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len ||
1638 assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)) {
1639 /* Make sure WEP keys are re-sent to firmware */
1640 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
1641 }
1642
1643 /* Must restart/rejoin adhoc networks after channel change */
1644 set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
1645
1646 restore_mesh:
1647 if (priv->mesh_dev)
1648 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
1649 priv->channel);
1650
1651 done:
1652 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1653 return ret;
1654}
1655
1656
1657static int assoc_helper_wep_keys(struct lbs_private *priv,
1658 struct assoc_request *assoc_req)
1659{
1660 int i;
1661 int ret = 0;
1662
1663 lbs_deb_enter(LBS_DEB_ASSOC);
1664
1665 /* Set or remove WEP keys */
1666 if (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len ||
1667 assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len)
1668 ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_ADD, assoc_req);
1669 else
1670 ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_REMOVE, assoc_req);
1671
1672 if (ret)
1673 goto out;
1674
1675 /* enable/disable the MAC's WEP packet filter */
1676 if (assoc_req->secinfo.wep_enabled)
1677 priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE;
1678 else
1679 priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE;
1680
1681 lbs_set_mac_control(priv);
1682
1683 mutex_lock(&priv->lock);
1684
1685 /* Copy WEP keys into priv wep key fields */
1686 for (i = 0; i < 4; i++) {
1687 memcpy(&priv->wep_keys[i], &assoc_req->wep_keys[i],
1688 sizeof(struct enc_key));
1689 }
1690 priv->wep_tx_keyidx = assoc_req->wep_tx_keyidx;
1691
1692 mutex_unlock(&priv->lock);
1693
1694out:
1695 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1696 return ret;
1697}
1698
1699static int assoc_helper_secinfo(struct lbs_private *priv,
1700 struct assoc_request * assoc_req)
1701{
1702 int ret = 0;
1703 uint16_t do_wpa;
1704 uint16_t rsn = 0;
1705
1706 lbs_deb_enter(LBS_DEB_ASSOC);
1707
1708 memcpy(&priv->secinfo, &assoc_req->secinfo,
1709 sizeof(struct lbs_802_11_security));
1710
1711 lbs_set_mac_control(priv);
1712
1713 /* If RSN is already enabled, don't try to enable it again, since
1714 * ENABLE_RSN resets internal state machines and will clobber the
1715 * 4-way WPA handshake.
1716 */
1717
1718 /* Get RSN enabled/disabled */
1719 ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_GET, &rsn);
1720 if (ret) {
1721 lbs_deb_assoc("Failed to get RSN status: %d\n", ret);
1722 goto out;
1723 }
1724
1725 /* Don't re-enable RSN if it's already enabled */
1726 do_wpa = assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled;
1727 if (do_wpa == rsn)
1728 goto out;
1729
1730 /* Set RSN enabled/disabled */
1731 ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_SET, &do_wpa);
1732
1733out:
1734 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1735 return ret;
1736}
1737
1738
1739static int assoc_helper_wpa_keys(struct lbs_private *priv,
1740 struct assoc_request * assoc_req)
1741{
1742 int ret = 0;
1743 unsigned int flags = assoc_req->flags;
1744
1745 lbs_deb_enter(LBS_DEB_ASSOC);
1746
1747 /* Work around older firmware bug where WPA unicast and multicast
1748 * keys must be set independently. Seen in SDIO parts with firmware
1749 * version 5.0.11p0.
1750 */
1751
1752 if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
1753 clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
1754 ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
1755 assoc_req->flags = flags;
1756 }
1757
1758 if (ret)
1759 goto out;
1760
1761 memcpy(&priv->wpa_unicast_key, &assoc_req->wpa_unicast_key,
1762 sizeof(struct enc_key));
1763
1764 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
1765 clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
1766
1767 ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req);
1768 assoc_req->flags = flags;
1769
1770 memcpy(&priv->wpa_mcast_key, &assoc_req->wpa_mcast_key,
1771 sizeof(struct enc_key));
1772 }
1773
1774out:
1775 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1776 return ret;
1777}
1778
1779
1780static int assoc_helper_wpa_ie(struct lbs_private *priv,
1781 struct assoc_request * assoc_req)
1782{
1783 int ret = 0;
1784
1785 lbs_deb_enter(LBS_DEB_ASSOC);
1786
1787 if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) {
1788 memcpy(&priv->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len);
1789 priv->wpa_ie_len = assoc_req->wpa_ie_len;
1790 } else {
1791 memset(&priv->wpa_ie, 0, MAX_WPA_IE_LEN);
1792 priv->wpa_ie_len = 0;
1793 }
1794
1795 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1796 return ret;
1797}
1798
1799
1800static int should_deauth_infrastructure(struct lbs_private *priv,
1801 struct assoc_request * assoc_req)
1802{
1803 int ret = 0;
1804
1805 if (priv->connect_status != LBS_CONNECTED)
1806 return 0;
1807
1808 lbs_deb_enter(LBS_DEB_ASSOC);
1809 if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
1810 lbs_deb_assoc("Deauthenticating due to new SSID\n");
1811 ret = 1;
1812 goto out;
1813 }
1814
1815 if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
1816 if (priv->secinfo.auth_mode != assoc_req->secinfo.auth_mode) {
1817 lbs_deb_assoc("Deauthenticating due to new security\n");
1818 ret = 1;
1819 goto out;
1820 }
1821 }
1822
1823 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
1824 lbs_deb_assoc("Deauthenticating due to new BSSID\n");
1825 ret = 1;
1826 goto out;
1827 }
1828
1829 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
1830 lbs_deb_assoc("Deauthenticating due to channel switch\n");
1831 ret = 1;
1832 goto out;
1833 }
1834
1835 /* FIXME: deal with 'auto' mode somehow */
1836 if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
1837 if (assoc_req->mode != IW_MODE_INFRA) {
1838 lbs_deb_assoc("Deauthenticating due to leaving "
1839 "infra mode\n");
1840 ret = 1;
1841 goto out;
1842 }
1843 }
1844
1845out:
1846 lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret);
1847 return ret;
1848}
1849
1850
1851static int should_stop_adhoc(struct lbs_private *priv,
1852 struct assoc_request * assoc_req)
1853{
1854 lbs_deb_enter(LBS_DEB_ASSOC);
1855
1856 if (priv->connect_status != LBS_CONNECTED)
1857 return 0;
1858
1859 if (lbs_ssid_cmp(priv->curbssparams.ssid,
1860 priv->curbssparams.ssid_len,
1861 assoc_req->ssid, assoc_req->ssid_len) != 0)
1862 return 1;
1863
1864 /* FIXME: deal with 'auto' mode somehow */
1865 if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
1866 if (assoc_req->mode != IW_MODE_ADHOC)
1867 return 1;
1868 }
1869
1870 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
1871 if (assoc_req->channel != priv->channel)
1872 return 1;
1873 }
1874
1875 lbs_deb_leave(LBS_DEB_ASSOC);
1876 return 0;
1877}
1878
1879
1880/**
1881 * @brief This function finds the best SSID in the Scan List
1882 *
1883 * Search the scan table for the best SSID that also matches the current
1884 * adapter network preference (infrastructure or adhoc)
1885 *
1886 * @param priv A pointer to struct lbs_private
1887 *
1888 * @return index in BSSID list
1889 */
1890static struct bss_descriptor *lbs_find_best_ssid_in_list(
1891 struct lbs_private *priv, uint8_t mode)
1892{
1893 uint8_t bestrssi = 0;
1894 struct bss_descriptor *iter_bss;
1895 struct bss_descriptor *best_bss = NULL;
1896
1897 lbs_deb_enter(LBS_DEB_SCAN);
1898
1899 mutex_lock(&priv->lock);
1900
1901 list_for_each_entry(iter_bss, &priv->network_list, list) {
1902 switch (mode) {
1903 case IW_MODE_INFRA:
1904 case IW_MODE_ADHOC:
1905 if (!is_network_compatible(priv, iter_bss, mode))
1906 break;
1907 if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
1908 break;
1909 bestrssi = SCAN_RSSI(iter_bss->rssi);
1910 best_bss = iter_bss;
1911 break;
1912 case IW_MODE_AUTO:
1913 default:
1914 if (SCAN_RSSI(iter_bss->rssi) <= bestrssi)
1915 break;
1916 bestrssi = SCAN_RSSI(iter_bss->rssi);
1917 best_bss = iter_bss;
1918 break;
1919 }
1920 }
1921
1922 mutex_unlock(&priv->lock);
1923 lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss);
1924 return best_bss;
1925}
1926
1927/**
1928 * @brief Find the best AP
1929 *
1930 * Used from association worker.
1931 *
1932 * @param priv A pointer to struct lbs_private structure
1933 * @param pSSID A pointer to AP's ssid
1934 *
1935 * @return 0--success, otherwise--fail
1936 */
1937static int lbs_find_best_network_ssid(struct lbs_private *priv,
1938 uint8_t *out_ssid, uint8_t *out_ssid_len, uint8_t preferred_mode,
1939 uint8_t *out_mode)
1940{
1941 int ret = -1;
1942 struct bss_descriptor *found;
1943
1944 lbs_deb_enter(LBS_DEB_SCAN);
1945
1946 priv->scan_ssid_len = 0;
1947 lbs_scan_networks(priv, 1);
1948 if (priv->surpriseremoved)
1949 goto out;
1950
1951 found = lbs_find_best_ssid_in_list(priv, preferred_mode);
1952 if (found && (found->ssid_len > 0)) {
1953 memcpy(out_ssid, &found->ssid, IEEE80211_MAX_SSID_LEN);
1954 *out_ssid_len = found->ssid_len;
1955 *out_mode = found->mode;
1956 ret = 0;
1957 }
1958
1959out:
1960 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
1961 return ret;
1962}
1963
1964
1965void lbs_association_worker(struct work_struct *work)
1966{
1967 struct lbs_private *priv = container_of(work, struct lbs_private,
1968 assoc_work.work);
1969 struct assoc_request * assoc_req = NULL;
1970 int ret = 0;
1971 int find_any_ssid = 0;
1972 DECLARE_SSID_BUF(ssid);
1973
1974 lbs_deb_enter(LBS_DEB_ASSOC);
1975
1976 mutex_lock(&priv->lock);
1977 assoc_req = priv->pending_assoc_req;
1978 priv->pending_assoc_req = NULL;
1979 priv->in_progress_assoc_req = assoc_req;
1980 mutex_unlock(&priv->lock);
1981
1982 if (!assoc_req)
1983 goto done;
1984
1985 lbs_deb_assoc(
1986 "Association Request:\n"
1987 " flags: 0x%08lx\n"
1988 " SSID: '%s'\n"
1989 " chann: %d\n"
1990 " band: %d\n"
1991 " mode: %d\n"
1992 " BSSID: %pM\n"
1993 " secinfo: %s%s%s\n"
1994 " auth_mode: %d\n",
1995 assoc_req->flags,
1996 print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len),
1997 assoc_req->channel, assoc_req->band, assoc_req->mode,
1998 assoc_req->bssid,
1999 assoc_req->secinfo.WPAenabled ? " WPA" : "",
2000 assoc_req->secinfo.WPA2enabled ? " WPA2" : "",
2001 assoc_req->secinfo.wep_enabled ? " WEP" : "",
2002 assoc_req->secinfo.auth_mode);
2003
2004 /* If 'any' SSID was specified, find an SSID to associate with */
2005 if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) &&
2006 !assoc_req->ssid_len)
2007 find_any_ssid = 1;
2008
2009 /* But don't use 'any' SSID if there's a valid locked BSSID to use */
2010 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
2011 if (compare_ether_addr(assoc_req->bssid, bssid_any) &&
2012 compare_ether_addr(assoc_req->bssid, bssid_off))
2013 find_any_ssid = 0;
2014 }
2015
2016 if (find_any_ssid) {
2017 u8 new_mode = assoc_req->mode;
2018
2019 ret = lbs_find_best_network_ssid(priv, assoc_req->ssid,
2020 &assoc_req->ssid_len, assoc_req->mode, &new_mode);
2021 if (ret) {
2022 lbs_deb_assoc("Could not find best network\n");
2023 ret = -ENETUNREACH;
2024 goto out;
2025 }
2026
2027 /* Ensure we switch to the mode of the AP */
2028 if (assoc_req->mode == IW_MODE_AUTO) {
2029 set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
2030 assoc_req->mode = new_mode;
2031 }
2032 }
2033
2034 /*
2035 * Check if the attributes being changing require deauthentication
2036 * from the currently associated infrastructure access point.
2037 */
2038 if (priv->mode == IW_MODE_INFRA) {
2039 if (should_deauth_infrastructure(priv, assoc_req)) {
2040 ret = lbs_cmd_80211_deauthenticate(priv,
2041 priv->curbssparams.bssid,
2042 WLAN_REASON_DEAUTH_LEAVING);
2043 if (ret) {
2044 lbs_deb_assoc("Deauthentication due to new "
2045 "configuration request failed: %d\n",
2046 ret);
2047 }
2048 }
2049 } else if (priv->mode == IW_MODE_ADHOC) {
2050 if (should_stop_adhoc(priv, assoc_req)) {
2051 ret = lbs_adhoc_stop(priv);
2052 if (ret) {
2053 lbs_deb_assoc("Teardown of AdHoc network due to "
2054 "new configuration request failed: %d\n",
2055 ret);
2056 }
2057
2058 }
2059 }
2060
2061 /* Send the various configuration bits to the firmware */
2062 if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) {
2063 ret = assoc_helper_mode(priv, assoc_req);
2064 if (ret)
2065 goto out;
2066 }
2067
2068 if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) {
2069 ret = assoc_helper_channel(priv, assoc_req);
2070 if (ret)
2071 goto out;
2072 }
2073
2074 if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
2075 ret = assoc_helper_secinfo(priv, assoc_req);
2076 if (ret)
2077 goto out;
2078 }
2079
2080 if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
2081 ret = assoc_helper_wpa_ie(priv, assoc_req);
2082 if (ret)
2083 goto out;
2084 }
2085
2086 /*
2087 * v10 FW wants WPA keys to be set/cleared before WEP key operations,
2088 * otherwise it will fail to correctly associate to WEP networks.
2089 * Other firmware versions don't appear to care.
2090 */
2091 if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) ||
2092 test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
2093 ret = assoc_helper_wpa_keys(priv, assoc_req);
2094 if (ret)
2095 goto out;
2096 }
2097
2098 if (test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) ||
2099 test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) {
2100 ret = assoc_helper_wep_keys(priv, assoc_req);
2101 if (ret)
2102 goto out;
2103 }
2104
2105
2106 /* SSID/BSSID should be the _last_ config option set, because they
2107 * trigger the association attempt.
2108 */
2109 if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) ||
2110 test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
2111 int success = 1;
2112
2113 ret = assoc_helper_associate(priv, assoc_req);
2114 if (ret) {
2115 lbs_deb_assoc("ASSOC: association unsuccessful: %d\n",
2116 ret);
2117 success = 0;
2118 }
2119
2120 if (priv->connect_status != LBS_CONNECTED) {
2121 lbs_deb_assoc("ASSOC: association unsuccessful, "
2122 "not connected\n");
2123 success = 0;
2124 }
2125
2126 if (success) {
2127 lbs_deb_assoc("associated to %pM\n",
2128 priv->curbssparams.bssid);
2129 lbs_prepare_and_send_command(priv,
2130 CMD_802_11_RSSI,
2131 0, CMD_OPTION_WAITFORRSP, 0, NULL);
2132 } else {
2133 ret = -1;
2134 }
2135 }
2136
2137out:
2138 if (ret) {
2139 lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n",
2140 ret);
2141 }
2142
2143 mutex_lock(&priv->lock);
2144 priv->in_progress_assoc_req = NULL;
2145 mutex_unlock(&priv->lock);
2146 kfree(assoc_req);
2147
2148done:
2149 lbs_deb_leave(LBS_DEB_ASSOC);
2150}
2151
2152
2153/*
2154 * Caller MUST hold any necessary locks
2155 */
2156struct assoc_request *lbs_get_association_request(struct lbs_private *priv)
2157{
2158 struct assoc_request * assoc_req;
2159
2160 lbs_deb_enter(LBS_DEB_ASSOC);
2161 if (!priv->pending_assoc_req) {
2162 priv->pending_assoc_req = kzalloc(sizeof(struct assoc_request),
2163 GFP_KERNEL);
2164 if (!priv->pending_assoc_req) {
2165 lbs_pr_info("Not enough memory to allocate association"
2166 " request!\n");
2167 return NULL;
2168 }
2169 }
2170
2171 /* Copy current configuration attributes to the association request,
2172 * but don't overwrite any that are already set.
2173 */
2174 assoc_req = priv->pending_assoc_req;
2175 if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) {
2176 memcpy(&assoc_req->ssid, &priv->curbssparams.ssid,
2177 IEEE80211_MAX_SSID_LEN);
2178 assoc_req->ssid_len = priv->curbssparams.ssid_len;
2179 }
2180
2181 if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags))
2182 assoc_req->channel = priv->channel;
2183
2184 if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags))
2185 assoc_req->band = priv->curbssparams.band;
2186
2187 if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags))
2188 assoc_req->mode = priv->mode;
2189
2190 if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) {
2191 memcpy(&assoc_req->bssid, priv->curbssparams.bssid,
2192 ETH_ALEN);
2193 }
2194
2195 if (!test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)) {
2196 int i;
2197 for (i = 0; i < 4; i++) {
2198 memcpy(&assoc_req->wep_keys[i], &priv->wep_keys[i],
2199 sizeof(struct enc_key));
2200 }
2201 }
2202
2203 if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags))
2204 assoc_req->wep_tx_keyidx = priv->wep_tx_keyidx;
2205
2206 if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) {
2207 memcpy(&assoc_req->wpa_mcast_key, &priv->wpa_mcast_key,
2208 sizeof(struct enc_key));
2209 }
2210
2211 if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) {
2212 memcpy(&assoc_req->wpa_unicast_key, &priv->wpa_unicast_key,
2213 sizeof(struct enc_key));
2214 }
2215
2216 if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) {
2217 memcpy(&assoc_req->secinfo, &priv->secinfo,
2218 sizeof(struct lbs_802_11_security));
2219 }
2220
2221 if (!test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) {
2222 memcpy(&assoc_req->wpa_ie, &priv->wpa_ie,
2223 MAX_WPA_IE_LEN);
2224 assoc_req->wpa_ie_len = priv->wpa_ie_len;
2225 }
2226
2227 lbs_deb_leave(LBS_DEB_ASSOC);
2228 return assoc_req;
2229}
2230
2231
2232/**
2233 * @brief Deauthenticate from a specific BSS
2234 *
2235 * @param priv A pointer to struct lbs_private structure
2236 * @param bssid The specific BSS to deauthenticate from
2237 * @param reason The 802.11 sec. 7.3.1.7 Reason Code for deauthenticating
2238 *
2239 * @return 0 on success, error on failure
2240 */
2241int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN],
2242 u16 reason)
2243{
2244 struct cmd_ds_802_11_deauthenticate cmd;
2245 int ret;
2246
2247 lbs_deb_enter(LBS_DEB_JOIN);
2248
2249 memset(&cmd, 0, sizeof(cmd));
2250 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
2251 memcpy(cmd.macaddr, &bssid[0], ETH_ALEN);
2252 cmd.reasoncode = cpu_to_le16(reason);
2253
2254 ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd);
2255
2256 /* Clean up everything even if there was an error; can't assume that
2257 * we're still authenticated to the AP after trying to deauth.
2258 */
2259 lbs_mac_event_disconnected(priv);
2260
2261 lbs_deb_leave(LBS_DEB_JOIN);
2262 return ret;
2263}
2264
diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h
deleted file mode 100644
index 40621b789fc5..000000000000
--- a/drivers/net/wireless/libertas/assoc.h
+++ /dev/null
@@ -1,155 +0,0 @@
1/* Copyright (C) 2006, Red Hat, Inc. */
2
3#ifndef _LBS_ASSOC_H_
4#define _LBS_ASSOC_H_
5
6
7#include "defs.h"
8#include "host.h"
9
10
11struct lbs_private;
12
13/*
14 * In theory, the IE is limited to the IE length, 255,
15 * but in practice 64 bytes are enough.
16 */
17#define MAX_WPA_IE_LEN 64
18
19
20
21struct lbs_802_11_security {
22 u8 WPAenabled;
23 u8 WPA2enabled;
24 u8 wep_enabled;
25 u8 auth_mode;
26 u32 key_mgmt;
27};
28
29/** Current Basic Service Set State Structure */
30struct current_bss_params {
31 /** bssid */
32 u8 bssid[ETH_ALEN];
33 /** ssid */
34 u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
35 u8 ssid_len;
36
37 /** band */
38 u8 band;
39 /** channel is directly in priv->channel */
40 /** zero-terminated array of supported data rates */
41 u8 rates[MAX_RATES + 1];
42};
43
44/**
45 * @brief Structure used to store information for each beacon/probe response
46 */
47struct bss_descriptor {
48 u8 bssid[ETH_ALEN];
49
50 u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
51 u8 ssid_len;
52
53 u16 capability;
54 u32 rssi;
55 u32 channel;
56 u16 beaconperiod;
57 __le16 atimwindow;
58
59 /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */
60 u8 mode;
61
62 /* zero-terminated array of supported data rates */
63 u8 rates[MAX_RATES + 1];
64
65 unsigned long last_scanned;
66
67 union ieee_phy_param_set phy;
68 union ieee_ss_param_set ss;
69
70 u8 wpa_ie[MAX_WPA_IE_LEN];
71 size_t wpa_ie_len;
72 u8 rsn_ie[MAX_WPA_IE_LEN];
73 size_t rsn_ie_len;
74
75 u8 mesh;
76
77 struct list_head list;
78};
79
80/** Association request
81 *
82 * Encapsulates all the options that describe a specific assocation request
83 * or configuration of the wireless card's radio, mode, and security settings.
84 */
85struct assoc_request {
86#define ASSOC_FLAG_SSID 1
87#define ASSOC_FLAG_CHANNEL 2
88#define ASSOC_FLAG_BAND 3
89#define ASSOC_FLAG_MODE 4
90#define ASSOC_FLAG_BSSID 5
91#define ASSOC_FLAG_WEP_KEYS 6
92#define ASSOC_FLAG_WEP_TX_KEYIDX 7
93#define ASSOC_FLAG_WPA_MCAST_KEY 8
94#define ASSOC_FLAG_WPA_UCAST_KEY 9
95#define ASSOC_FLAG_SECINFO 10
96#define ASSOC_FLAG_WPA_IE 11
97 unsigned long flags;
98
99 u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
100 u8 ssid_len;
101 u8 channel;
102 u8 band;
103 u8 mode;
104 u8 bssid[ETH_ALEN] __attribute__ ((aligned (2)));
105
106 /** WEP keys */
107 struct enc_key wep_keys[4];
108 u16 wep_tx_keyidx;
109
110 /** WPA keys */
111 struct enc_key wpa_mcast_key;
112 struct enc_key wpa_unicast_key;
113
114 struct lbs_802_11_security secinfo;
115
116 /** WPA Information Elements*/
117 u8 wpa_ie[MAX_WPA_IE_LEN];
118 u8 wpa_ie_len;
119
120 /* BSS to associate with for infrastructure of Ad-Hoc join */
121 struct bss_descriptor bss;
122};
123
124
125extern u8 lbs_bg_rates[MAX_RATES];
126
127void lbs_association_worker(struct work_struct *work);
128struct assoc_request *lbs_get_association_request(struct lbs_private *priv);
129
130int lbs_adhoc_stop(struct lbs_private *priv);
131
132int lbs_cmd_80211_deauthenticate(struct lbs_private *priv,
133 u8 bssid[ETH_ALEN], u16 reason);
134
135int lbs_cmd_802_11_rssi(struct lbs_private *priv,
136 struct cmd_ds_command *cmd);
137int lbs_ret_802_11_rssi(struct lbs_private *priv,
138 struct cmd_ds_command *resp);
139
140int lbs_cmd_bcn_ctrl(struct lbs_private *priv,
141 struct cmd_ds_command *cmd,
142 u16 cmd_action);
143int lbs_ret_802_11_bcn_ctrl(struct lbs_private *priv,
144 struct cmd_ds_command *resp);
145
146int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action,
147 struct assoc_request *assoc);
148
149int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
150 uint16_t *enable);
151
152int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
153 struct assoc_request *assoc);
154
155#endif /* _LBS_ASSOC_H */
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 9d5d3ccf08c8..25f902760980 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -7,8 +7,11 @@
7 */ 7 */
8 8
9#include <linux/slab.h> 9#include <linux/slab.h>
10#include <linux/ieee80211.h>
10#include <net/cfg80211.h> 11#include <net/cfg80211.h>
12#include <asm/unaligned.h>
11 13
14#include "decl.h"
12#include "cfg.h" 15#include "cfg.h"
13#include "cmd.h" 16#include "cmd.h"
14 17
@@ -39,26 +42,27 @@ static struct ieee80211_channel lbs_2ghz_channels[] = {
39 CHAN2G(14, 2484, 0), 42 CHAN2G(14, 2484, 0),
40}; 43};
41 44
42#define RATETAB_ENT(_rate, _rateid, _flags) { \ 45#define RATETAB_ENT(_rate, _hw_value, _flags) { \
43 .bitrate = (_rate), \ 46 .bitrate = (_rate), \
44 .hw_value = (_rateid), \ 47 .hw_value = (_hw_value), \
45 .flags = (_flags), \ 48 .flags = (_flags), \
46} 49}
47 50
48 51
52/* Table 6 in section 3.2.1.1 */
49static struct ieee80211_rate lbs_rates[] = { 53static struct ieee80211_rate lbs_rates[] = {
50 RATETAB_ENT(10, 0x1, 0), 54 RATETAB_ENT(10, 0, 0),
51 RATETAB_ENT(20, 0x2, 0), 55 RATETAB_ENT(20, 1, 0),
52 RATETAB_ENT(55, 0x4, 0), 56 RATETAB_ENT(55, 2, 0),
53 RATETAB_ENT(110, 0x8, 0), 57 RATETAB_ENT(110, 3, 0),
54 RATETAB_ENT(60, 0x10, 0), 58 RATETAB_ENT(60, 9, 0),
55 RATETAB_ENT(90, 0x20, 0), 59 RATETAB_ENT(90, 6, 0),
56 RATETAB_ENT(120, 0x40, 0), 60 RATETAB_ENT(120, 7, 0),
57 RATETAB_ENT(180, 0x80, 0), 61 RATETAB_ENT(180, 8, 0),
58 RATETAB_ENT(240, 0x100, 0), 62 RATETAB_ENT(240, 9, 0),
59 RATETAB_ENT(360, 0x200, 0), 63 RATETAB_ENT(360, 10, 0),
60 RATETAB_ENT(480, 0x400, 0), 64 RATETAB_ENT(480, 11, 0),
61 RATETAB_ENT(540, 0x800, 0), 65 RATETAB_ENT(540, 12, 0),
62}; 66};
63 67
64static struct ieee80211_supported_band lbs_band_2ghz = { 68static struct ieee80211_supported_band lbs_band_2ghz = {
@@ -76,22 +80,1616 @@ static const u32 cipher_suites[] = {
76 WLAN_CIPHER_SUITE_CCMP, 80 WLAN_CIPHER_SUITE_CCMP,
77}; 81};
78 82
83/* Time to stay on the channel */
84#define LBS_DWELL_PASSIVE 100
85#define LBS_DWELL_ACTIVE 40
79 86
80 87
88/***************************************************************************
89 * Misc utility functions
90 *
91 * TLVs are Marvell specific. They are very similar to IEs, they have the
92 * same structure: type, length, data*. The only difference: for IEs, the
93 * type and length are u8, but for TLVs they're __le16.
94 */
95
96/*
97 * Convert NL80211's auth_type to the one from Libertas, see chapter 5.9.1
98 * in the firmware spec
99 */
100static u8 lbs_auth_to_authtype(enum nl80211_auth_type auth_type)
101{
102 int ret = -ENOTSUPP;
103
104 switch (auth_type) {
105 case NL80211_AUTHTYPE_OPEN_SYSTEM:
106 case NL80211_AUTHTYPE_SHARED_KEY:
107 ret = auth_type;
108 break;
109 case NL80211_AUTHTYPE_AUTOMATIC:
110 ret = NL80211_AUTHTYPE_OPEN_SYSTEM;
111 break;
112 case NL80211_AUTHTYPE_NETWORK_EAP:
113 ret = 0x80;
114 break;
115 default:
116 /* silence compiler */
117 break;
118 }
119 return ret;
120}
121
122
123/* Various firmware commands need the list of supported rates, but with
124 the hight-bit set for basic rates */
125static int lbs_add_rates(u8 *rates)
126{
127 size_t i;
128
129 for (i = 0; i < ARRAY_SIZE(lbs_rates); i++) {
130 u8 rate = lbs_rates[i].bitrate / 5;
131 if (rate == 0x02 || rate == 0x04 ||
132 rate == 0x0b || rate == 0x16)
133 rate |= 0x80;
134 rates[i] = rate;
135 }
136 return ARRAY_SIZE(lbs_rates);
137}
138
139
140/***************************************************************************
141 * TLV utility functions
142 *
143 * TLVs are Marvell specific. They are very similar to IEs, they have the
144 * same structure: type, length, data*. The only difference: for IEs, the
145 * type and length are u8, but for TLVs they're __le16.
146 */
147
148
149/*
150 * Add ssid TLV
151 */
152#define LBS_MAX_SSID_TLV_SIZE \
153 (sizeof(struct mrvl_ie_header) \
154 + IEEE80211_MAX_SSID_LEN)
155
156static int lbs_add_ssid_tlv(u8 *tlv, const u8 *ssid, int ssid_len)
157{
158 struct mrvl_ie_ssid_param_set *ssid_tlv = (void *)tlv;
159
160 /*
161 * TLV-ID SSID 00 00
162 * length 06 00
163 * ssid 4d 4e 54 45 53 54
164 */
165 ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
166 ssid_tlv->header.len = cpu_to_le16(ssid_len);
167 memcpy(ssid_tlv->ssid, ssid, ssid_len);
168 return sizeof(ssid_tlv->header) + ssid_len;
169}
170
171
172/*
173 * Add channel list TLV (section 8.4.2)
174 *
175 * Actual channel data comes from priv->wdev->wiphy->channels.
176 */
177#define LBS_MAX_CHANNEL_LIST_TLV_SIZE \
178 (sizeof(struct mrvl_ie_header) \
179 + (LBS_SCAN_BEFORE_NAP * sizeof(struct chanscanparamset)))
180
181static int lbs_add_channel_list_tlv(struct lbs_private *priv, u8 *tlv,
182 int last_channel, int active_scan)
183{
184 int chanscanparamsize = sizeof(struct chanscanparamset) *
185 (last_channel - priv->scan_channel);
186
187 struct mrvl_ie_header *header = (void *) tlv;
188
189 /*
190 * TLV-ID CHANLIST 01 01
191 * length 0e 00
192 * channel 00 01 00 00 00 64 00
193 * radio type 00
194 * channel 01
195 * scan type 00
196 * min scan time 00 00
197 * max scan time 64 00
198 * channel 2 00 02 00 00 00 64 00
199 *
200 */
201
202 header->type = cpu_to_le16(TLV_TYPE_CHANLIST);
203 header->len = cpu_to_le16(chanscanparamsize);
204 tlv += sizeof(struct mrvl_ie_header);
205
206 /* lbs_deb_scan("scan: channels %d to %d\n", priv->scan_channel,
207 last_channel); */
208 memset(tlv, 0, chanscanparamsize);
209
210 while (priv->scan_channel < last_channel) {
211 struct chanscanparamset *param = (void *) tlv;
212
213 param->radiotype = CMD_SCAN_RADIO_TYPE_BG;
214 param->channumber =
215 priv->scan_req->channels[priv->scan_channel]->hw_value;
216 if (active_scan) {
217 param->maxscantime = cpu_to_le16(LBS_DWELL_ACTIVE);
218 } else {
219 param->chanscanmode.passivescan = 1;
220 param->maxscantime = cpu_to_le16(LBS_DWELL_PASSIVE);
221 }
222 tlv += sizeof(struct chanscanparamset);
223 priv->scan_channel++;
224 }
225 return sizeof(struct mrvl_ie_header) + chanscanparamsize;
226}
227
228
229/*
230 * Add rates TLV
231 *
232 * The rates are in lbs_bg_rates[], but for the 802.11b
233 * rates the high bit is set. We add this TLV only because
234 * there's a firmware which otherwise doesn't report all
235 * APs in range.
236 */
237#define LBS_MAX_RATES_TLV_SIZE \
238 (sizeof(struct mrvl_ie_header) \
239 + (ARRAY_SIZE(lbs_rates)))
240
241/* Adds a TLV with all rates the hardware supports */
242static int lbs_add_supported_rates_tlv(u8 *tlv)
243{
244 size_t i;
245 struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv;
246
247 /*
248 * TLV-ID RATES 01 00
249 * length 0e 00
250 * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c
251 */
252 rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
253 tlv += sizeof(rate_tlv->header);
254 i = lbs_add_rates(tlv);
255 tlv += i;
256 rate_tlv->header.len = cpu_to_le16(i);
257 return sizeof(rate_tlv->header) + i;
258}
259
260
261/*
262 * Adds a TLV with all rates the hardware *and* BSS supports.
263 */
264static int lbs_add_common_rates_tlv(u8 *tlv, struct cfg80211_bss *bss)
265{
266 struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv;
267 const u8 *rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
268 int n;
269
270 /*
271 * 01 00 TLV_TYPE_RATES
272 * 04 00 len
273 * 82 84 8b 96 rates
274 */
275 rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
276 tlv += sizeof(rate_tlv->header);
277
278 if (!rates_eid) {
279 /* Fallback: add basic 802.11b rates */
280 *tlv++ = 0x82;
281 *tlv++ = 0x84;
282 *tlv++ = 0x8b;
283 *tlv++ = 0x96;
284 n = 4;
285 } else {
286 int hw, ap;
287 u8 ap_max = rates_eid[1];
288 n = 0;
289 for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) {
290 u8 hw_rate = lbs_rates[hw].bitrate / 5;
291 for (ap = 0; ap < ap_max; ap++) {
292 if (hw_rate == (rates_eid[ap+2] & 0x7f)) {
293 *tlv++ = rates_eid[ap+2];
294 n++;
295 }
296 }
297 }
298 }
299
300 rate_tlv->header.len = cpu_to_le16(n);
301 return sizeof(rate_tlv->header) + n;
302}
303
304
305/*
306 * Add auth type TLV.
307 *
308 * This is only needed for newer firmware (V9 and up).
309 */
310#define LBS_MAX_AUTH_TYPE_TLV_SIZE \
311 sizeof(struct mrvl_ie_auth_type)
312
313static int lbs_add_auth_type_tlv(u8 *tlv, enum nl80211_auth_type auth_type)
314{
315 struct mrvl_ie_auth_type *auth = (void *) tlv;
316
317 /*
318 * 1f 01 TLV_TYPE_AUTH_TYPE
319 * 01 00 len
320 * 01 auth type
321 */
322 auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE);
323 auth->header.len = cpu_to_le16(sizeof(*auth)-sizeof(auth->header));
324 auth->auth = cpu_to_le16(lbs_auth_to_authtype(auth_type));
325 return sizeof(*auth);
326}
327
328
329/*
330 * Add channel (phy ds) TLV
331 */
332#define LBS_MAX_CHANNEL_TLV_SIZE \
333 sizeof(struct mrvl_ie_header)
334
335static int lbs_add_channel_tlv(u8 *tlv, u8 channel)
336{
337 struct mrvl_ie_ds_param_set *ds = (void *) tlv;
338
339 /*
340 * 03 00 TLV_TYPE_PHY_DS
341 * 01 00 len
342 * 06 channel
343 */
344 ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS);
345 ds->header.len = cpu_to_le16(sizeof(*ds)-sizeof(ds->header));
346 ds->channel = channel;
347 return sizeof(*ds);
348}
349
350
351/*
352 * Add (empty) CF param TLV of the form:
353 */
354#define LBS_MAX_CF_PARAM_TLV_SIZE \
355 sizeof(struct mrvl_ie_header)
356
357static int lbs_add_cf_param_tlv(u8 *tlv)
358{
359 struct mrvl_ie_cf_param_set *cf = (void *)tlv;
360
361 /*
362 * 04 00 TLV_TYPE_CF
363 * 06 00 len
364 * 00 cfpcnt
365 * 00 cfpperiod
366 * 00 00 cfpmaxduration
367 * 00 00 cfpdurationremaining
368 */
369 cf->header.type = cpu_to_le16(TLV_TYPE_CF);
370 cf->header.len = cpu_to_le16(sizeof(*cf)-sizeof(cf->header));
371 return sizeof(*cf);
372}
373
374/*
375 * Add WPA TLV
376 */
377#define LBS_MAX_WPA_TLV_SIZE \
378 (sizeof(struct mrvl_ie_header) \
379 + 128 /* TODO: I guessed the size */)
380
381static int lbs_add_wpa_tlv(u8 *tlv, const u8 *ie, u8 ie_len)
382{
383 size_t tlv_len;
384
385 /*
386 * We need just convert an IE to an TLV. IEs use u8 for the header,
387 * u8 type
388 * u8 len
389 * u8[] data
390 * but TLVs use __le16 instead:
391 * __le16 type
392 * __le16 len
393 * u8[] data
394 */
395 *tlv++ = *ie++;
396 *tlv++ = 0;
397 tlv_len = *tlv++ = *ie++;
398 *tlv++ = 0;
399 while (tlv_len--)
400 *tlv++ = *ie++;
401 /* the TLV is two bytes larger than the IE */
402 return ie_len + 2;
403}
404
405/***************************************************************************
406 * Set Channel
407 */
408
81static int lbs_cfg_set_channel(struct wiphy *wiphy, 409static int lbs_cfg_set_channel(struct wiphy *wiphy,
82 struct net_device *netdev, 410 struct net_device *netdev,
83 struct ieee80211_channel *chan, 411 struct ieee80211_channel *channel,
84 enum nl80211_channel_type channel_type) 412 enum nl80211_channel_type channel_type)
85{ 413{
86 struct lbs_private *priv = wiphy_priv(wiphy); 414 struct lbs_private *priv = wiphy_priv(wiphy);
87 int ret = -ENOTSUPP; 415 int ret = -ENOTSUPP;
88 416
89 lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", chan->center_freq, channel_type); 417 lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d",
418 channel->center_freq, channel_type);
90 419
91 if (channel_type != NL80211_CHAN_NO_HT) 420 if (channel_type != NL80211_CHAN_NO_HT)
92 goto out; 421 goto out;
93 422
94 ret = lbs_set_channel(priv, chan->hw_value); 423 ret = lbs_set_channel(priv, channel->hw_value);
424
425 out:
426 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
427 return ret;
428}
429
430
431
432/***************************************************************************
433 * Scanning
434 */
435
436/*
437 * When scanning, the firmware doesn't send a nul packet with the power-safe
438 * bit to the AP. So we cannot stay away from our current channel too long,
439 * otherwise we loose data. So take a "nap" while scanning every other
440 * while.
441 */
442#define LBS_SCAN_BEFORE_NAP 4
443
444
445/*
446 * When the firmware reports back a scan-result, it gives us an "u8 rssi",
447 * which isn't really an RSSI, as it becomes larger when moving away from
448 * the AP. Anyway, we need to convert that into mBm.
449 */
450#define LBS_SCAN_RSSI_TO_MBM(rssi) \
451 ((-(int)rssi + 3)*100)
452
453static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
454 struct cmd_header *resp)
455{
456 struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;
457 int bsssize;
458 const u8 *pos;
459 u16 nr_sets;
460 const u8 *tsfdesc;
461 int tsfsize;
462 int i;
463 int ret = -EILSEQ;
464
465 lbs_deb_enter(LBS_DEB_CFG80211);
466
467 bsssize = get_unaligned_le16(&scanresp->bssdescriptsize);
468 nr_sets = le16_to_cpu(resp->size);
469
470 /*
471 * The general layout of the scan response is described in chapter
472 * 5.7.1. Basically we have a common part, then any number of BSS
473 * descriptor sections. Finally we have section with the same number
474 * of TSFs.
475 *
476 * cmd_ds_802_11_scan_rsp
477 * cmd_header
478 * pos_size
479 * nr_sets
480 * bssdesc 1
481 * bssid
482 * rssi
483 * timestamp
484 * intvl
485 * capa
486 * IEs
487 * bssdesc 2
488 * bssdesc n
489 * MrvlIEtypes_TsfFimestamp_t
490 * TSF for BSS 1
491 * TSF for BSS 2
492 * TSF for BSS n
493 */
494
495 pos = scanresp->bssdesc_and_tlvbuffer;
496
497 tsfdesc = pos + bsssize;
498 tsfsize = 4 + 8 * scanresp->nr_sets;
499
500 /* Validity check: we expect a Marvell-Local TLV */
501 i = get_unaligned_le16(tsfdesc);
502 tsfdesc += 2;
503 if (i != TLV_TYPE_TSFTIMESTAMP)
504 goto done;
505 /* Validity check: the TLV holds TSF values with 8 bytes each, so
506 * the size in the TLV must match the nr_sets value */
507 i = get_unaligned_le16(tsfdesc);
508 tsfdesc += 2;
509 if (i / 8 != scanresp->nr_sets)
510 goto done;
511
512 for (i = 0; i < scanresp->nr_sets; i++) {
513 const u8 *bssid;
514 const u8 *ie;
515 int left;
516 int ielen;
517 int rssi;
518 u16 intvl;
519 u16 capa;
520 int chan_no = -1;
521 const u8 *ssid = NULL;
522 u8 ssid_len = 0;
523 DECLARE_SSID_BUF(ssid_buf);
524
525 int len = get_unaligned_le16(pos);
526 pos += 2;
527
528 /* BSSID */
529 bssid = pos;
530 pos += ETH_ALEN;
531 /* RSSI */
532 rssi = *pos++;
533 /* Packet time stamp */
534 pos += 8;
535 /* Beacon interval */
536 intvl = get_unaligned_le16(pos);
537 pos += 2;
538 /* Capabilities */
539 capa = get_unaligned_le16(pos);
540 pos += 2;
541
542 /* To find out the channel, we must parse the IEs */
543 ie = pos;
544 /* 6+1+8+2+2: size of BSSID, RSSI, time stamp, beacon
545 interval, capabilities */
546 ielen = left = len - (6 + 1 + 8 + 2 + 2);
547 while (left >= 2) {
548 u8 id, elen;
549 id = *pos++;
550 elen = *pos++;
551 left -= 2;
552 if (elen > left || elen == 0)
553 goto done;
554 if (id == WLAN_EID_DS_PARAMS)
555 chan_no = *pos;
556 if (id == WLAN_EID_SSID) {
557 ssid = pos;
558 ssid_len = elen;
559 }
560 left -= elen;
561 pos += elen;
562 }
563
564 /* No channel, no luck */
565 if (chan_no != -1) {
566 struct wiphy *wiphy = priv->wdev->wiphy;
567 int freq = ieee80211_channel_to_frequency(chan_no);
568 struct ieee80211_channel *channel =
569 ieee80211_get_channel(wiphy, freq);
570
571 lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %s, "
572 "%d dBm\n",
573 bssid, capa, chan_no,
574 print_ssid(ssid_buf, ssid, ssid_len),
575 LBS_SCAN_RSSI_TO_MBM(rssi)/100);
576
577 if (channel ||
578 !(channel->flags & IEEE80211_CHAN_DISABLED))
579 cfg80211_inform_bss(wiphy, channel,
580 bssid, le64_to_cpu(*(__le64 *)tsfdesc),
581 capa, intvl, ie, ielen,
582 LBS_SCAN_RSSI_TO_MBM(rssi),
583 GFP_KERNEL);
584 }
585 tsfdesc += 8;
586 }
587 ret = 0;
588
589 done:
590 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
591 return ret;
592}
593
594
595/*
596 * Our scan command contains a TLV, consting of a SSID TLV, a channel list
597 * TLV and a rates TLV. Determine the maximum size of them:
598 */
599#define LBS_SCAN_MAX_CMD_SIZE \
600 (sizeof(struct cmd_ds_802_11_scan) \
601 + LBS_MAX_SSID_TLV_SIZE \
602 + LBS_MAX_CHANNEL_LIST_TLV_SIZE \
603 + LBS_MAX_RATES_TLV_SIZE)
604
605/*
606 * Assumes priv->scan_req is initialized and valid
607 * Assumes priv->scan_channel is initialized
608 */
609static void lbs_scan_worker(struct work_struct *work)
610{
611 struct lbs_private *priv =
612 container_of(work, struct lbs_private, scan_work.work);
613 struct cmd_ds_802_11_scan *scan_cmd;
614 u8 *tlv; /* pointer into our current, growing TLV storage area */
615 int last_channel;
616 int running, carrier;
617
618 lbs_deb_enter(LBS_DEB_SCAN);
619
620 scan_cmd = kzalloc(LBS_SCAN_MAX_CMD_SIZE, GFP_KERNEL);
621 if (scan_cmd == NULL)
622 goto out_no_scan_cmd;
623
624 /* prepare fixed part of scan command */
625 scan_cmd->bsstype = CMD_BSS_TYPE_ANY;
626
627 /* stop network while we're away from our main channel */
628 running = !netif_queue_stopped(priv->dev);
629 carrier = netif_carrier_ok(priv->dev);
630 if (running)
631 netif_stop_queue(priv->dev);
632 if (carrier)
633 netif_carrier_off(priv->dev);
634
635 /* prepare fixed part of scan command */
636 tlv = scan_cmd->tlvbuffer;
637
638 /* add SSID TLV */
639 if (priv->scan_req->n_ssids)
640 tlv += lbs_add_ssid_tlv(tlv,
641 priv->scan_req->ssids[0].ssid,
642 priv->scan_req->ssids[0].ssid_len);
643
644 /* add channel TLVs */
645 last_channel = priv->scan_channel + LBS_SCAN_BEFORE_NAP;
646 if (last_channel > priv->scan_req->n_channels)
647 last_channel = priv->scan_req->n_channels;
648 tlv += lbs_add_channel_list_tlv(priv, tlv, last_channel,
649 priv->scan_req->n_ssids);
650
651 /* add rates TLV */
652 tlv += lbs_add_supported_rates_tlv(tlv);
653
654 if (priv->scan_channel < priv->scan_req->n_channels) {
655 cancel_delayed_work(&priv->scan_work);
656 queue_delayed_work(priv->work_thread, &priv->scan_work,
657 msecs_to_jiffies(300));
658 }
659
660 /* This is the final data we are about to send */
661 scan_cmd->hdr.size = cpu_to_le16(tlv - (u8 *)scan_cmd);
662 lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd,
663 sizeof(*scan_cmd));
664 lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer,
665 tlv - scan_cmd->tlvbuffer);
666
667 __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr,
668 le16_to_cpu(scan_cmd->hdr.size),
669 lbs_ret_scan, 0);
670
671 if (priv->scan_channel >= priv->scan_req->n_channels) {
672 /* Mark scan done */
673 cfg80211_scan_done(priv->scan_req, false);
674 priv->scan_req = NULL;
675 }
676
677 /* Restart network */
678 if (carrier)
679 netif_carrier_on(priv->dev);
680 if (running && !priv->tx_pending_len)
681 netif_wake_queue(priv->dev);
682
683 kfree(scan_cmd);
684
685 out_no_scan_cmd:
686 lbs_deb_leave(LBS_DEB_SCAN);
687}
688
689
690static int lbs_cfg_scan(struct wiphy *wiphy,
691 struct net_device *dev,
692 struct cfg80211_scan_request *request)
693{
694 struct lbs_private *priv = wiphy_priv(wiphy);
695 int ret = 0;
696
697 lbs_deb_enter(LBS_DEB_CFG80211);
698
699 if (priv->scan_req || delayed_work_pending(&priv->scan_work)) {
700 /* old scan request not yet processed */
701 ret = -EAGAIN;
702 goto out;
703 }
704
705 lbs_deb_scan("scan: ssids %d, channels %d, ie_len %zd\n",
706 request->n_ssids, request->n_channels, request->ie_len);
707
708 priv->scan_channel = 0;
709 queue_delayed_work(priv->work_thread, &priv->scan_work,
710 msecs_to_jiffies(50));
711
712 if (priv->surpriseremoved)
713 ret = -EIO;
714
715 priv->scan_req = request;
716
717 out:
718 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
719 return ret;
720}
721
722
723
724
725/***************************************************************************
726 * Events
727 */
728
729void lbs_send_disconnect_notification(struct lbs_private *priv)
730{
731 lbs_deb_enter(LBS_DEB_CFG80211);
732
733 cfg80211_disconnected(priv->dev,
734 0,
735 NULL, 0,
736 GFP_KERNEL);
737
738 lbs_deb_leave(LBS_DEB_CFG80211);
739}
740
741void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event)
742{
743 lbs_deb_enter(LBS_DEB_CFG80211);
744
745 cfg80211_michael_mic_failure(priv->dev,
746 priv->assoc_bss,
747 event == MACREG_INT_CODE_MIC_ERR_MULTICAST ?
748 NL80211_KEYTYPE_GROUP :
749 NL80211_KEYTYPE_PAIRWISE,
750 -1,
751 NULL,
752 GFP_KERNEL);
753
754 lbs_deb_leave(LBS_DEB_CFG80211);
755}
756
757
758
759
760/***************************************************************************
761 * Connect/disconnect
762 */
763
764
765/*
766 * This removes all WEP keys
767 */
768static int lbs_remove_wep_keys(struct lbs_private *priv)
769{
770 struct cmd_ds_802_11_set_wep cmd;
771 int ret;
772
773 lbs_deb_enter(LBS_DEB_CFG80211);
774
775 memset(&cmd, 0, sizeof(cmd));
776 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
777 cmd.keyindex = cpu_to_le16(priv->wep_tx_key);
778 cmd.action = cpu_to_le16(CMD_ACT_REMOVE);
779
780 ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
781
782 lbs_deb_leave(LBS_DEB_CFG80211);
783 return ret;
784}
785
786/*
787 * Set WEP keys
788 */
789static int lbs_set_wep_keys(struct lbs_private *priv)
790{
791 struct cmd_ds_802_11_set_wep cmd;
792 int i;
793 int ret;
794
795 lbs_deb_enter(LBS_DEB_CFG80211);
796
797 /*
798 * command 13 00
799 * size 50 00
800 * sequence xx xx
801 * result 00 00
802 * action 02 00 ACT_ADD
803 * transmit key 00 00
804 * type for key 1 01 WEP40
805 * type for key 2 00
806 * type for key 3 00
807 * type for key 4 00
808 * key 1 39 39 39 39 39 00 00 00
809 * 00 00 00 00 00 00 00 00
810 * key 2 00 00 00 00 00 00 00 00
811 * 00 00 00 00 00 00 00 00
812 * key 3 00 00 00 00 00 00 00 00
813 * 00 00 00 00 00 00 00 00
814 * key 4 00 00 00 00 00 00 00 00
815 */
816 if (priv->wep_key_len[0] || priv->wep_key_len[1] ||
817 priv->wep_key_len[2] || priv->wep_key_len[3]) {
818 /* Only set wep keys if we have at least one of them */
819 memset(&cmd, 0, sizeof(cmd));
820 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
821 cmd.keyindex = cpu_to_le16(priv->wep_tx_key);
822 cmd.action = cpu_to_le16(CMD_ACT_ADD);
823
824 for (i = 0; i < 4; i++) {
825 switch (priv->wep_key_len[i]) {
826 case WLAN_KEY_LEN_WEP40:
827 cmd.keytype[i] = CMD_TYPE_WEP_40_BIT;
828 break;
829 case WLAN_KEY_LEN_WEP104:
830 cmd.keytype[i] = CMD_TYPE_WEP_104_BIT;
831 break;
832 default:
833 cmd.keytype[i] = 0;
834 break;
835 }
836 memcpy(cmd.keymaterial[i], priv->wep_key[i],
837 priv->wep_key_len[i]);
838 }
839
840 ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd);
841 } else {
842 /* Otherwise remove all wep keys */
843 ret = lbs_remove_wep_keys(priv);
844 }
845
846 lbs_deb_leave(LBS_DEB_CFG80211);
847 return ret;
848}
849
850
851/*
852 * Enable/Disable RSN status
853 */
854static int lbs_enable_rsn(struct lbs_private *priv, int enable)
855{
856 struct cmd_ds_802_11_enable_rsn cmd;
857 int ret;
858
859 lbs_deb_enter_args(LBS_DEB_CFG80211, "%d", enable);
860
861 /*
862 * cmd 2f 00
863 * size 0c 00
864 * sequence xx xx
865 * result 00 00
866 * action 01 00 ACT_SET
867 * enable 01 00
868 */
869 memset(&cmd, 0, sizeof(cmd));
870 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
871 cmd.action = cpu_to_le16(CMD_ACT_SET);
872 cmd.enable = cpu_to_le16(enable);
873
874 ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
875
876 lbs_deb_leave(LBS_DEB_CFG80211);
877 return ret;
878}
879
880
881/*
882 * Set WPA/WPA key material
883 */
884
885/* like "struct cmd_ds_802_11_key_material", but with cmd_header. Once we
886 * get rid of WEXT, this should go into host.h */
887
888struct cmd_key_material {
889 struct cmd_header hdr;
890
891 __le16 action;
892 struct MrvlIEtype_keyParamSet param;
893} __packed;
894
895static int lbs_set_key_material(struct lbs_private *priv,
896 int key_type,
897 int key_info,
898 u8 *key, u16 key_len)
899{
900 struct cmd_key_material cmd;
901 int ret;
902
903 lbs_deb_enter(LBS_DEB_CFG80211);
904
905 /*
906 * Example for WPA (TKIP):
907 *
908 * cmd 5e 00
909 * size 34 00
910 * sequence xx xx
911 * result 00 00
912 * action 01 00
913 * TLV type 00 01 key param
914 * length 00 26
915 * key type 01 00 TKIP
916 * key info 06 00 UNICAST | ENABLED
917 * key len 20 00
918 * key 32 bytes
919 */
920 memset(&cmd, 0, sizeof(cmd));
921 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
922 cmd.action = cpu_to_le16(CMD_ACT_SET);
923 cmd.param.type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
924 cmd.param.length = cpu_to_le16(sizeof(cmd.param) - 4);
925 cmd.param.keytypeid = cpu_to_le16(key_type);
926 cmd.param.keyinfo = cpu_to_le16(key_info);
927 cmd.param.keylen = cpu_to_le16(key_len);
928 if (key && key_len)
929 memcpy(cmd.param.key, key, key_len);
930
931 ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd);
932
933 lbs_deb_leave(LBS_DEB_CFG80211);
934 return ret;
935}
936
937
938/*
939 * Sets the auth type (open, shared, etc) in the firmware. That
940 * we use CMD_802_11_AUTHENTICATE is misleading, this firmware
941 * command doesn't send an authentication frame at all, it just
942 * stores the auth_type.
943 */
944static int lbs_set_authtype(struct lbs_private *priv,
945 struct cfg80211_connect_params *sme)
946{
947 struct cmd_ds_802_11_authenticate cmd;
948 int ret;
949
950 lbs_deb_enter_args(LBS_DEB_CFG80211, "%d", sme->auth_type);
951
952 /*
953 * cmd 11 00
954 * size 19 00
955 * sequence xx xx
956 * result 00 00
957 * BSS id 00 13 19 80 da 30
958 * auth type 00
959 * reserved 00 00 00 00 00 00 00 00 00 00
960 */
961 memset(&cmd, 0, sizeof(cmd));
962 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
963 if (sme->bssid)
964 memcpy(cmd.bssid, sme->bssid, ETH_ALEN);
965 /* convert auth_type */
966 ret = lbs_auth_to_authtype(sme->auth_type);
967 if (ret < 0)
968 goto done;
969
970 cmd.authtype = ret;
971 ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd);
972
973 done:
974 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
975 return ret;
976}
977
978
979/*
980 * Create association request
981 */
982#define LBS_ASSOC_MAX_CMD_SIZE \
983 (sizeof(struct cmd_ds_802_11_associate) \
984 - 512 /* cmd_ds_802_11_associate.iebuf */ \
985 + LBS_MAX_SSID_TLV_SIZE \
986 + LBS_MAX_CHANNEL_TLV_SIZE \
987 + LBS_MAX_CF_PARAM_TLV_SIZE \
988 + LBS_MAX_AUTH_TYPE_TLV_SIZE \
989 + LBS_MAX_WPA_TLV_SIZE)
990
991static int lbs_associate(struct lbs_private *priv,
992 struct cfg80211_bss *bss,
993 struct cfg80211_connect_params *sme)
994{
995 struct cmd_ds_802_11_associate_response *resp;
996 struct cmd_ds_802_11_associate *cmd = kzalloc(LBS_ASSOC_MAX_CMD_SIZE,
997 GFP_KERNEL);
998 const u8 *ssid_eid;
999 size_t len, resp_ie_len;
1000 int status;
1001 int ret;
1002 u8 *pos = &(cmd->iebuf[0]);
1003
1004 lbs_deb_enter(LBS_DEB_CFG80211);
1005
1006 if (!cmd) {
1007 ret = -ENOMEM;
1008 goto done;
1009 }
1010
1011 /*
1012 * cmd 50 00
1013 * length 34 00
1014 * sequence xx xx
1015 * result 00 00
1016 * BSS id 00 13 19 80 da 30
1017 * capabilities 11 00
1018 * listen interval 0a 00
1019 * beacon interval 00 00
1020 * DTIM period 00
1021 * TLVs xx (up to 512 bytes)
1022 */
1023 cmd->hdr.command = cpu_to_le16(CMD_802_11_ASSOCIATE);
1024
1025 /* Fill in static fields */
1026 memcpy(cmd->bssid, bss->bssid, ETH_ALEN);
1027 cmd->listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL);
1028 cmd->capability = cpu_to_le16(bss->capability);
1029
1030 /* add SSID TLV */
1031 ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
1032 if (ssid_eid)
1033 pos += lbs_add_ssid_tlv(pos, ssid_eid + 2, ssid_eid[1]);
1034 else
1035 lbs_deb_assoc("no SSID\n");
1036
1037 /* add DS param TLV */
1038 if (bss->channel)
1039 pos += lbs_add_channel_tlv(pos, bss->channel->hw_value);
1040 else
1041 lbs_deb_assoc("no channel\n");
1042
1043 /* add (empty) CF param TLV */
1044 pos += lbs_add_cf_param_tlv(pos);
1045
1046 /* add rates TLV */
1047 pos += lbs_add_common_rates_tlv(pos, bss);
1048
1049 /* add auth type TLV */
1050 if (priv->fwrelease >= 0x09000000)
1051 pos += lbs_add_auth_type_tlv(pos, sme->auth_type);
1052
1053 /* add WPA/WPA2 TLV */
1054 if (sme->ie && sme->ie_len)
1055 pos += lbs_add_wpa_tlv(pos, sme->ie, sme->ie_len);
1056
1057 len = (sizeof(*cmd) - sizeof(cmd->iebuf)) +
1058 (u16)(pos - (u8 *) &cmd->iebuf);
1059 cmd->hdr.size = cpu_to_le16(len);
1060
1061 /* store for later use */
1062 memcpy(priv->assoc_bss, bss->bssid, ETH_ALEN);
1063
1064 ret = lbs_cmd_with_response(priv, CMD_802_11_ASSOCIATE, cmd);
1065 if (ret)
1066 goto done;
1067
1068
1069 /* generate connect message to cfg80211 */
1070
1071 resp = (void *) cmd; /* recast for easier field access */
1072 status = le16_to_cpu(resp->statuscode);
1073
1074 /* Convert statis code of old firmware */
1075 if (priv->fwrelease < 0x09000000)
1076 switch (status) {
1077 case 0:
1078 break;
1079 case 1:
1080 lbs_deb_assoc("invalid association parameters\n");
1081 status = WLAN_STATUS_CAPS_UNSUPPORTED;
1082 break;
1083 case 2:
1084 lbs_deb_assoc("timer expired while waiting for AP\n");
1085 status = WLAN_STATUS_AUTH_TIMEOUT;
1086 break;
1087 case 3:
1088 lbs_deb_assoc("association refused by AP\n");
1089 status = WLAN_STATUS_ASSOC_DENIED_UNSPEC;
1090 break;
1091 case 4:
1092 lbs_deb_assoc("authentication refused by AP\n");
1093 status = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1094 break;
1095 default:
1096 lbs_deb_assoc("association failure %d\n", status);
1097 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1098 }
1099
1100 lbs_deb_assoc("status %d, capability 0x%04x\n", status,
1101 le16_to_cpu(resp->capability));
1102
1103 resp_ie_len = le16_to_cpu(resp->hdr.size)
1104 - sizeof(resp->hdr)
1105 - 6;
1106 cfg80211_connect_result(priv->dev,
1107 priv->assoc_bss,
1108 sme->ie, sme->ie_len,
1109 resp->iebuf, resp_ie_len,
1110 status,
1111 GFP_KERNEL);
1112
1113 if (status == 0) {
1114 /* TODO: get rid of priv->connect_status */
1115 priv->connect_status = LBS_CONNECTED;
1116 netif_carrier_on(priv->dev);
1117 if (!priv->tx_pending_len)
1118 netif_tx_wake_all_queues(priv->dev);
1119 }
1120
1121
1122done:
1123 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1124 return ret;
1125}
1126
1127
1128
1129static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
1130 struct cfg80211_connect_params *sme)
1131{
1132 struct lbs_private *priv = wiphy_priv(wiphy);
1133 struct cfg80211_bss *bss = NULL;
1134 int ret = 0;
1135 u8 preamble = RADIO_PREAMBLE_SHORT;
1136
1137 lbs_deb_enter(LBS_DEB_CFG80211);
1138
1139 if (sme->bssid) {
1140 bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
1141 sme->ssid, sme->ssid_len,
1142 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
1143 } else {
1144 /*
1145 * Here we have an impedance mismatch. The firmware command
1146 * CMD_802_11_ASSOCIATE always needs a BSSID, it cannot
1147 * connect otherwise. However, for the connect-API of
1148 * cfg80211 the bssid is purely optional. We don't get one,
1149 * except the user specifies one on the "iw" command line.
1150 *
1151 * If we don't got one, we could initiate a scan and look
1152 * for the best matching cfg80211_bss entry.
1153 *
1154 * Or, better yet, net/wireless/sme.c get's rewritten into
1155 * something more generally useful.
1156 */
1157 lbs_pr_err("TODO: no BSS specified\n");
1158 ret = -ENOTSUPP;
1159 goto done;
1160 }
1161
1162
1163 if (!bss) {
1164 lbs_pr_err("assicate: bss %pM not in scan results\n",
1165 sme->bssid);
1166 ret = -ENOENT;
1167 goto done;
1168 }
1169 lbs_deb_assoc("trying %pM", sme->bssid);
1170 lbs_deb_assoc("cipher 0x%x, key index %d, key len %d\n",
1171 sme->crypto.cipher_group,
1172 sme->key_idx, sme->key_len);
1173
1174 /* As this is a new connection, clear locally stored WEP keys */
1175 priv->wep_tx_key = 0;
1176 memset(priv->wep_key, 0, sizeof(priv->wep_key));
1177 memset(priv->wep_key_len, 0, sizeof(priv->wep_key_len));
1178
1179 /* set/remove WEP keys */
1180 switch (sme->crypto.cipher_group) {
1181 case WLAN_CIPHER_SUITE_WEP40:
1182 case WLAN_CIPHER_SUITE_WEP104:
1183 /* Store provided WEP keys in priv-> */
1184 priv->wep_tx_key = sme->key_idx;
1185 priv->wep_key_len[sme->key_idx] = sme->key_len;
1186 memcpy(priv->wep_key[sme->key_idx], sme->key, sme->key_len);
1187 /* Set WEP keys and WEP mode */
1188 lbs_set_wep_keys(priv);
1189 priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE;
1190 lbs_set_mac_control(priv);
1191 /* No RSN mode for WEP */
1192 lbs_enable_rsn(priv, 0);
1193 break;
1194 case 0: /* there's no WLAN_CIPHER_SUITE_NONE definition */
1195 /*
1196 * If we don't have no WEP, no WPA and no WPA2,
1197 * we remove all keys like in the WPA/WPA2 setup,
1198 * we just don't set RSN.
1199 *
1200 * Therefore: fall-throught
1201 */
1202 case WLAN_CIPHER_SUITE_TKIP:
1203 case WLAN_CIPHER_SUITE_CCMP:
1204 /* Remove WEP keys and WEP mode */
1205 lbs_remove_wep_keys(priv);
1206 priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE;
1207 lbs_set_mac_control(priv);
1208
1209 /* clear the WPA/WPA2 keys */
1210 lbs_set_key_material(priv,
1211 KEY_TYPE_ID_WEP, /* doesn't matter */
1212 KEY_INFO_WPA_UNICAST,
1213 NULL, 0);
1214 lbs_set_key_material(priv,
1215 KEY_TYPE_ID_WEP, /* doesn't matter */
1216 KEY_INFO_WPA_MCAST,
1217 NULL, 0);
1218 /* RSN mode for WPA/WPA2 */
1219 lbs_enable_rsn(priv, sme->crypto.cipher_group != 0);
1220 break;
1221 default:
1222 lbs_pr_err("unsupported cipher group 0x%x\n",
1223 sme->crypto.cipher_group);
1224 ret = -ENOTSUPP;
1225 goto done;
1226 }
1227
1228 lbs_set_authtype(priv, sme);
1229 lbs_set_radio(priv, preamble, 1);
1230
1231 /* Do the actual association */
1232 lbs_associate(priv, bss, sme);
1233
1234 done:
1235 if (bss)
1236 cfg80211_put_bss(bss);
1237 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1238 return ret;
1239}
1240
1241static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
1242 u16 reason_code)
1243{
1244 struct lbs_private *priv = wiphy_priv(wiphy);
1245 struct cmd_ds_802_11_deauthenticate cmd;
1246
1247 lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);
1248
1249 /* store for lbs_cfg_ret_disconnect() */
1250 priv->disassoc_reason = reason_code;
1251
1252 memset(&cmd, 0, sizeof(cmd));
1253 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1254 /* Mildly ugly to use a locally store my own BSSID ... */
1255 memcpy(cmd.macaddr, &priv->assoc_bss, ETH_ALEN);
1256 cmd.reasoncode = cpu_to_le16(reason_code);
1257
1258 if (lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd))
1259 return -EFAULT;
1260
1261 cfg80211_disconnected(priv->dev,
1262 priv->disassoc_reason,
1263 NULL, 0,
1264 GFP_KERNEL);
1265 priv->connect_status = LBS_DISCONNECTED;
1266
1267 return 0;
1268}
1269
1270
1271static int lbs_cfg_set_default_key(struct wiphy *wiphy,
1272 struct net_device *netdev,
1273 u8 key_index)
1274{
1275 struct lbs_private *priv = wiphy_priv(wiphy);
1276
1277 lbs_deb_enter(LBS_DEB_CFG80211);
1278
1279 if (key_index != priv->wep_tx_key) {
1280 lbs_deb_assoc("set_default_key: to %d\n", key_index);
1281 priv->wep_tx_key = key_index;
1282 lbs_set_wep_keys(priv);
1283 }
1284
1285 return 0;
1286}
1287
1288
1289static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
1290 u8 idx, const u8 *mac_addr,
1291 struct key_params *params)
1292{
1293 struct lbs_private *priv = wiphy_priv(wiphy);
1294 u16 key_info;
1295 u16 key_type;
1296 int ret = 0;
1297
1298 lbs_deb_enter(LBS_DEB_CFG80211);
1299
1300 lbs_deb_assoc("add_key: cipher 0x%x, mac_addr %pM\n",
1301 params->cipher, mac_addr);
1302 lbs_deb_assoc("add_key: key index %d, key len %d\n",
1303 idx, params->key_len);
1304 if (params->key_len)
1305 lbs_deb_hex(LBS_DEB_CFG80211, "KEY",
1306 params->key, params->key_len);
1307
1308 lbs_deb_assoc("add_key: seq len %d\n", params->seq_len);
1309 if (params->seq_len)
1310 lbs_deb_hex(LBS_DEB_CFG80211, "SEQ",
1311 params->seq, params->seq_len);
1312
1313 switch (params->cipher) {
1314 case WLAN_CIPHER_SUITE_WEP40:
1315 case WLAN_CIPHER_SUITE_WEP104:
1316 /* actually compare if something has changed ... */
1317 if ((priv->wep_key_len[idx] != params->key_len) ||
1318 memcmp(priv->wep_key[idx],
1319 params->key, params->key_len) != 0) {
1320 priv->wep_key_len[idx] = params->key_len;
1321 memcpy(priv->wep_key[idx],
1322 params->key, params->key_len);
1323 lbs_set_wep_keys(priv);
1324 }
1325 break;
1326 case WLAN_CIPHER_SUITE_TKIP:
1327 case WLAN_CIPHER_SUITE_CCMP:
1328 key_info = KEY_INFO_WPA_ENABLED | ((idx == 0)
1329 ? KEY_INFO_WPA_UNICAST
1330 : KEY_INFO_WPA_MCAST);
1331 key_type = (params->cipher == WLAN_CIPHER_SUITE_TKIP)
1332 ? KEY_TYPE_ID_TKIP
1333 : KEY_TYPE_ID_AES;
1334 lbs_set_key_material(priv,
1335 key_type,
1336 key_info,
1337 params->key, params->key_len);
1338 break;
1339 default:
1340 lbs_pr_err("unhandled cipher 0x%x\n", params->cipher);
1341 ret = -ENOTSUPP;
1342 break;
1343 }
1344
1345 return ret;
1346}
1347
1348
1349static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev,
1350 u8 key_index, const u8 *mac_addr)
1351{
1352
1353 lbs_deb_enter(LBS_DEB_CFG80211);
1354
1355 lbs_deb_assoc("del_key: key_idx %d, mac_addr %pM\n",
1356 key_index, mac_addr);
1357
1358#ifdef TODO
1359 struct lbs_private *priv = wiphy_priv(wiphy);
1360 /*
1361 * I think can keep this a NO-OP, because:
1362
1363 * - we clear all keys whenever we do lbs_cfg_connect() anyway
1364 * - neither "iw" nor "wpa_supplicant" won't call this during
1365 * an ongoing connection
1366 * - TODO: but I have to check if this is still true when
1367 * I set the AP to periodic re-keying
1368 * - we've not kzallec() something when we've added a key at
1369 * lbs_cfg_connect() or lbs_cfg_add_key().
1370 *
1371 * This causes lbs_cfg_del_key() only called at disconnect time,
1372 * where we'd just waste time deleting a key that is not going
1373 * to be used anyway.
1374 */
1375 if (key_index < 3 && priv->wep_key_len[key_index]) {
1376 priv->wep_key_len[key_index] = 0;
1377 lbs_set_wep_keys(priv);
1378 }
1379#endif
1380
1381 return 0;
1382}
1383
1384
1385/***************************************************************************
1386 * Get station
1387 */
1388
1389static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,
1390 u8 *mac, struct station_info *sinfo)
1391{
1392 struct lbs_private *priv = wiphy_priv(wiphy);
1393 s8 signal, noise;
1394 int ret;
1395 size_t i;
1396
1397 lbs_deb_enter(LBS_DEB_CFG80211);
1398
1399 sinfo->filled |= STATION_INFO_TX_BYTES |
1400 STATION_INFO_TX_PACKETS |
1401 STATION_INFO_RX_BYTES |
1402 STATION_INFO_RX_PACKETS;
1403 sinfo->tx_bytes = priv->dev->stats.tx_bytes;
1404 sinfo->tx_packets = priv->dev->stats.tx_packets;
1405 sinfo->rx_bytes = priv->dev->stats.rx_bytes;
1406 sinfo->rx_packets = priv->dev->stats.rx_packets;
1407
1408 /* Get current RSSI */
1409 ret = lbs_get_rssi(priv, &signal, &noise);
1410 if (ret == 0) {
1411 sinfo->signal = signal;
1412 sinfo->filled |= STATION_INFO_SIGNAL;
1413 }
1414
1415 /* Convert priv->cur_rate from hw_value to NL80211 value */
1416 for (i = 0; i < ARRAY_SIZE(lbs_rates); i++) {
1417 if (priv->cur_rate == lbs_rates[i].hw_value) {
1418 sinfo->txrate.legacy = lbs_rates[i].bitrate;
1419 sinfo->filled |= STATION_INFO_TX_BITRATE;
1420 break;
1421 }
1422 }
1423
1424 return 0;
1425}
1426
1427
1428
1429
1430/***************************************************************************
1431 * "Site survey", here just current channel and noise level
1432 */
1433
1434static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev,
1435 int idx, struct survey_info *survey)
1436{
1437 struct lbs_private *priv = wiphy_priv(wiphy);
1438 s8 signal, noise;
1439 int ret;
1440
1441 if (idx != 0)
1442 ret = -ENOENT;
1443
1444 lbs_deb_enter(LBS_DEB_CFG80211);
1445
1446 survey->channel = ieee80211_get_channel(wiphy,
1447 ieee80211_channel_to_frequency(priv->channel));
1448
1449 ret = lbs_get_rssi(priv, &signal, &noise);
1450 if (ret == 0) {
1451 survey->filled = SURVEY_INFO_NOISE_DBM;
1452 survey->noise = noise;
1453 }
1454
1455 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1456 return ret;
1457}
1458
1459
1460
1461
1462/***************************************************************************
1463 * Change interface
1464 */
1465
1466static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev,
1467 enum nl80211_iftype type, u32 *flags,
1468 struct vif_params *params)
1469{
1470 struct lbs_private *priv = wiphy_priv(wiphy);
1471 int ret = 0;
1472
1473 lbs_deb_enter(LBS_DEB_CFG80211);
1474
1475 switch (type) {
1476 case NL80211_IFTYPE_MONITOR:
1477 ret = lbs_set_monitor_mode(priv, 1);
1478 break;
1479 case NL80211_IFTYPE_STATION:
1480 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
1481 ret = lbs_set_monitor_mode(priv, 0);
1482 if (!ret)
1483 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1);
1484 break;
1485 case NL80211_IFTYPE_ADHOC:
1486 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
1487 ret = lbs_set_monitor_mode(priv, 0);
1488 if (!ret)
1489 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2);
1490 break;
1491 default:
1492 ret = -ENOTSUPP;
1493 }
1494
1495 if (!ret)
1496 priv->wdev->iftype = type;
1497
1498 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1499 return ret;
1500}
1501
1502
1503
1504/***************************************************************************
1505 * IBSS (Ad-Hoc)
1506 */
1507
1508/* The firmware needs the following bits masked out of the beacon-derived
1509 * capability field when associating/joining to a BSS:
1510 * 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused)
1511 */
1512#define CAPINFO_MASK (~(0xda00))
1513
1514
1515static void lbs_join_post(struct lbs_private *priv,
1516 struct cfg80211_ibss_params *params,
1517 u8 *bssid, u16 capability)
1518{
1519 u8 fake_ie[2 + IEEE80211_MAX_SSID_LEN + /* ssid */
1520 2 + 4 + /* basic rates */
1521 2 + 1 + /* DS parameter */
1522 2 + 2 + /* atim */
1523 2 + 8]; /* extended rates */
1524 u8 *fake = fake_ie;
1525
1526 lbs_deb_enter(LBS_DEB_CFG80211);
1527
1528 /*
1529 * For cfg80211_inform_bss, we'll need a fake IE, as we can't get
1530 * the real IE from the firmware. So we fabricate a fake IE based on
1531 * what the firmware actually sends (sniffed with wireshark).
1532 */
1533 /* Fake SSID IE */
1534 *fake++ = WLAN_EID_SSID;
1535 *fake++ = params->ssid_len;
1536 memcpy(fake, params->ssid, params->ssid_len);
1537 fake += params->ssid_len;
1538 /* Fake supported basic rates IE */
1539 *fake++ = WLAN_EID_SUPP_RATES;
1540 *fake++ = 4;
1541 *fake++ = 0x82;
1542 *fake++ = 0x84;
1543 *fake++ = 0x8b;
1544 *fake++ = 0x96;
1545 /* Fake DS channel IE */
1546 *fake++ = WLAN_EID_DS_PARAMS;
1547 *fake++ = 1;
1548 *fake++ = params->channel->hw_value;
1549 /* Fake IBSS params IE */
1550 *fake++ = WLAN_EID_IBSS_PARAMS;
1551 *fake++ = 2;
1552 *fake++ = 0; /* ATIM=0 */
1553 *fake++ = 0;
1554 /* Fake extended rates IE, TODO: don't add this for 802.11b only,
1555 * but I don't know how this could be checked */
1556 *fake++ = WLAN_EID_EXT_SUPP_RATES;
1557 *fake++ = 8;
1558 *fake++ = 0x0c;
1559 *fake++ = 0x12;
1560 *fake++ = 0x18;
1561 *fake++ = 0x24;
1562 *fake++ = 0x30;
1563 *fake++ = 0x48;
1564 *fake++ = 0x60;
1565 *fake++ = 0x6c;
1566 lbs_deb_hex(LBS_DEB_CFG80211, "IE", fake_ie, fake - fake_ie);
1567
1568 cfg80211_inform_bss(priv->wdev->wiphy,
1569 params->channel,
1570 bssid,
1571 0,
1572 capability,
1573 params->beacon_interval,
1574 fake_ie, fake - fake_ie,
1575 0, GFP_KERNEL);
1576
1577 memcpy(priv->wdev->ssid, params->ssid, params->ssid_len);
1578 priv->wdev->ssid_len = params->ssid_len;
1579
1580 cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL);
1581
1582 /* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */
1583 priv->connect_status = LBS_CONNECTED;
1584 netif_carrier_on(priv->dev);
1585 if (!priv->tx_pending_len)
1586 netif_wake_queue(priv->dev);
1587
1588 lbs_deb_leave(LBS_DEB_CFG80211);
1589}
1590
1591static int lbs_ibss_join_existing(struct lbs_private *priv,
1592 struct cfg80211_ibss_params *params,
1593 struct cfg80211_bss *bss)
1594{
1595 const u8 *rates_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
1596 struct cmd_ds_802_11_ad_hoc_join cmd;
1597 u8 preamble = RADIO_PREAMBLE_SHORT;
1598 int ret = 0;
1599
1600 lbs_deb_enter(LBS_DEB_CFG80211);
1601
1602 /* TODO: set preamble based on scan result */
1603 ret = lbs_set_radio(priv, preamble, 1);
1604 if (ret)
1605 goto out;
1606
1607 /*
1608 * Example CMD_802_11_AD_HOC_JOIN command:
1609 *
1610 * command 2c 00 CMD_802_11_AD_HOC_JOIN
1611 * size 65 00
1612 * sequence xx xx
1613 * result 00 00
1614 * bssid 02 27 27 97 2f 96
1615 * ssid 49 42 53 53 00 00 00 00
1616 * 00 00 00 00 00 00 00 00
1617 * 00 00 00 00 00 00 00 00
1618 * 00 00 00 00 00 00 00 00
1619 * type 02 CMD_BSS_TYPE_IBSS
1620 * beacon period 64 00
1621 * dtim period 00
1622 * timestamp 00 00 00 00 00 00 00 00
1623 * localtime 00 00 00 00 00 00 00 00
1624 * IE DS 03
1625 * IE DS len 01
1626 * IE DS channel 01
1627 * reserveed 00 00 00 00
1628 * IE IBSS 06
1629 * IE IBSS len 02
1630 * IE IBSS atim 00 00
1631 * reserved 00 00 00 00
1632 * capability 02 00
1633 * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c 00
1634 * fail timeout ff 00
1635 * probe delay 00 00
1636 */
1637 memset(&cmd, 0, sizeof(cmd));
1638 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1639
1640 memcpy(cmd.bss.bssid, bss->bssid, ETH_ALEN);
1641 memcpy(cmd.bss.ssid, params->ssid, params->ssid_len);
1642 cmd.bss.type = CMD_BSS_TYPE_IBSS;
1643 cmd.bss.beaconperiod = cpu_to_le16(params->beacon_interval);
1644 cmd.bss.ds.header.id = WLAN_EID_DS_PARAMS;
1645 cmd.bss.ds.header.len = 1;
1646 cmd.bss.ds.channel = params->channel->hw_value;
1647 cmd.bss.ibss.header.id = WLAN_EID_IBSS_PARAMS;
1648 cmd.bss.ibss.header.len = 2;
1649 cmd.bss.ibss.atimwindow = 0;
1650 cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK);
1651
1652 /* set rates to the intersection of our rates and the rates in the
1653 bss */
1654 if (!rates_eid) {
1655 lbs_add_rates(cmd.bss.rates);
1656 } else {
1657 int hw, i;
1658 u8 rates_max = rates_eid[1];
1659 u8 *rates = cmd.bss.rates;
1660 for (hw = 0; hw < ARRAY_SIZE(lbs_rates); hw++) {
1661 u8 hw_rate = lbs_rates[hw].bitrate / 5;
1662 for (i = 0; i < rates_max; i++) {
1663 if (hw_rate == (rates_eid[i+2] & 0x7f)) {
1664 u8 rate = rates_eid[i+2];
1665 if (rate == 0x02 || rate == 0x04 ||
1666 rate == 0x0b || rate == 0x16)
1667 rate |= 0x80;
1668 *rates++ = rate;
1669 }
1670 }
1671 }
1672 }
1673
1674 /* Only v8 and below support setting this */
1675 if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) {
1676 cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
1677 cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
1678 }
1679 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd);
1680 if (ret)
1681 goto out;
1682
1683 /*
1684 * This is a sample response to CMD_802_11_AD_HOC_JOIN:
1685 *
1686 * response 2c 80
1687 * size 09 00
1688 * sequence xx xx
1689 * result 00 00
1690 * reserved 00
1691 */
1692 lbs_join_post(priv, params, bss->bssid, bss->capability);
95 1693
96 out: 1694 out:
97 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); 1695 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
@@ -100,9 +1698,169 @@ static int lbs_cfg_set_channel(struct wiphy *wiphy,
100 1698
101 1699
102 1700
1701static int lbs_ibss_start_new(struct lbs_private *priv,
1702 struct cfg80211_ibss_params *params)
1703{
1704 struct cmd_ds_802_11_ad_hoc_start cmd;
1705 struct cmd_ds_802_11_ad_hoc_result *resp =
1706 (struct cmd_ds_802_11_ad_hoc_result *) &cmd;
1707 u8 preamble = RADIO_PREAMBLE_SHORT;
1708 int ret = 0;
1709 u16 capability;
1710
1711 lbs_deb_enter(LBS_DEB_CFG80211);
1712
1713 ret = lbs_set_radio(priv, preamble, 1);
1714 if (ret)
1715 goto out;
1716
1717 /*
1718 * Example CMD_802_11_AD_HOC_START command:
1719 *
1720 * command 2b 00 CMD_802_11_AD_HOC_START
1721 * size b1 00
1722 * sequence xx xx
1723 * result 00 00
1724 * ssid 54 45 53 54 00 00 00 00
1725 * 00 00 00 00 00 00 00 00
1726 * 00 00 00 00 00 00 00 00
1727 * 00 00 00 00 00 00 00 00
1728 * bss type 02
1729 * beacon period 64 00
1730 * dtim period 00
1731 * IE IBSS 06
1732 * IE IBSS len 02
1733 * IE IBSS atim 00 00
1734 * reserved 00 00 00 00
1735 * IE DS 03
1736 * IE DS len 01
1737 * IE DS channel 01
1738 * reserved 00 00 00 00
1739 * probe delay 00 00
1740 * capability 02 00
1741 * rates 82 84 8b 96 (basic rates with have bit 7 set)
1742 * 0c 12 18 24 30 48 60 6c
1743 * padding 100 bytes
1744 */
1745 memset(&cmd, 0, sizeof(cmd));
1746 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1747 memcpy(cmd.ssid, params->ssid, params->ssid_len);
1748 cmd.bsstype = CMD_BSS_TYPE_IBSS;
1749 cmd.beaconperiod = cpu_to_le16(params->beacon_interval);
1750 cmd.ibss.header.id = WLAN_EID_IBSS_PARAMS;
1751 cmd.ibss.header.len = 2;
1752 cmd.ibss.atimwindow = 0;
1753 cmd.ds.header.id = WLAN_EID_DS_PARAMS;
1754 cmd.ds.header.len = 1;
1755 cmd.ds.channel = params->channel->hw_value;
1756 /* Only v8 and below support setting probe delay */
1757 if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8)
1758 cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME);
1759 /* TODO: mix in WLAN_CAPABILITY_PRIVACY */
1760 capability = WLAN_CAPABILITY_IBSS;
1761 cmd.capability = cpu_to_le16(capability);
1762 lbs_add_rates(cmd.rates);
1763
1764
1765 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd);
1766 if (ret)
1767 goto out;
1768
1769 /*
1770 * This is a sample response to CMD_802_11_AD_HOC_JOIN:
1771 *
1772 * response 2b 80
1773 * size 14 00
1774 * sequence xx xx
1775 * result 00 00
1776 * reserved 00
1777 * bssid 02 2b 7b 0f 86 0e
1778 */
1779 lbs_join_post(priv, params, resp->bssid, capability);
1780
1781 out:
1782 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1783 return ret;
1784}
1785
1786
1787static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
1788 struct cfg80211_ibss_params *params)
1789{
1790 struct lbs_private *priv = wiphy_priv(wiphy);
1791 int ret = 0;
1792 struct cfg80211_bss *bss;
1793 DECLARE_SSID_BUF(ssid_buf);
1794
1795 lbs_deb_enter(LBS_DEB_CFG80211);
1796
1797 if (!params->channel) {
1798 ret = -ENOTSUPP;
1799 goto out;
1800 }
1801
1802 ret = lbs_set_channel(priv, params->channel->hw_value);
1803 if (ret)
1804 goto out;
1805
1806 /* Search if someone is beaconing. This assumes that the
1807 * bss list is populated already */
1808 bss = cfg80211_get_bss(wiphy, params->channel, params->bssid,
1809 params->ssid, params->ssid_len,
1810 WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
1811
1812 if (bss) {
1813 ret = lbs_ibss_join_existing(priv, params, bss);
1814 cfg80211_put_bss(bss);
1815 } else
1816 ret = lbs_ibss_start_new(priv, params);
1817
1818
1819 out:
1820 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1821 return ret;
1822}
1823
1824
1825static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
1826{
1827 struct lbs_private *priv = wiphy_priv(wiphy);
1828 struct cmd_ds_802_11_ad_hoc_stop cmd;
1829 int ret = 0;
1830
1831 lbs_deb_enter(LBS_DEB_CFG80211);
1832
1833 memset(&cmd, 0, sizeof(cmd));
1834 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1835 ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd);
1836
1837 /* TODO: consider doing this at MACREG_INT_CODE_ADHOC_BCN_LOST time */
1838 lbs_mac_event_disconnected(priv);
1839
1840 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
1841 return ret;
1842}
1843
1844
1845
1846
1847/***************************************************************************
1848 * Initialization
1849 */
103 1850
104static struct cfg80211_ops lbs_cfg80211_ops = { 1851static struct cfg80211_ops lbs_cfg80211_ops = {
105 .set_channel = lbs_cfg_set_channel, 1852 .set_channel = lbs_cfg_set_channel,
1853 .scan = lbs_cfg_scan,
1854 .connect = lbs_cfg_connect,
1855 .disconnect = lbs_cfg_disconnect,
1856 .add_key = lbs_cfg_add_key,
1857 .del_key = lbs_cfg_del_key,
1858 .set_default_key = lbs_cfg_set_default_key,
1859 .get_station = lbs_cfg_get_station,
1860 .dump_survey = lbs_get_survey,
1861 .change_virtual_intf = lbs_change_intf,
1862 .join_ibss = lbs_join_ibss,
1863 .leave_ibss = lbs_leave_ibss,
106}; 1864};
107 1865
108 1866
@@ -142,6 +1900,36 @@ struct wireless_dev *lbs_cfg_alloc(struct device *dev)
142} 1900}
143 1901
144 1902
1903static void lbs_cfg_set_regulatory_hint(struct lbs_private *priv)
1904{
1905 struct region_code_mapping {
1906 const char *cn;
1907 int code;
1908 };
1909
1910 /* Section 5.17.2 */
1911 static struct region_code_mapping regmap[] = {
1912 {"US ", 0x10}, /* US FCC */
1913 {"CA ", 0x20}, /* Canada */
1914 {"EU ", 0x30}, /* ETSI */
1915 {"ES ", 0x31}, /* Spain */
1916 {"FR ", 0x32}, /* France */
1917 {"JP ", 0x40}, /* Japan */
1918 };
1919 size_t i;
1920
1921 lbs_deb_enter(LBS_DEB_CFG80211);
1922
1923 for (i = 0; i < ARRAY_SIZE(regmap); i++)
1924 if (regmap[i].code == priv->regioncode) {
1925 regulatory_hint(priv->wdev->wiphy, regmap[i].cn);
1926 break;
1927 }
1928
1929 lbs_deb_leave(LBS_DEB_CFG80211);
1930}
1931
1932
145/* 1933/*
146 * This function get's called after lbs_setup_firmware() determined the 1934 * This function get's called after lbs_setup_firmware() determined the
147 * firmware capabities. So we can setup the wiphy according to our 1935 * firmware capabities. So we can setup the wiphy according to our
@@ -157,10 +1945,12 @@ int lbs_cfg_register(struct lbs_private *priv)
157 wdev->wiphy->max_scan_ssids = 1; 1945 wdev->wiphy->max_scan_ssids = 1;
158 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; 1946 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
159 1947
160 /* TODO: BIT(NL80211_IFTYPE_ADHOC); */ 1948 wdev->wiphy->interface_modes =
161 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); 1949 BIT(NL80211_IFTYPE_STATION) |
1950 BIT(NL80211_IFTYPE_ADHOC);
1951 if (lbs_rtap_supported(priv))
1952 wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
162 1953
163 /* TODO: honor priv->regioncode */
164 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz; 1954 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz;
165 1955
166 /* 1956 /*
@@ -169,6 +1959,7 @@ int lbs_cfg_register(struct lbs_private *priv)
169 */ 1959 */
170 wdev->wiphy->cipher_suites = cipher_suites; 1960 wdev->wiphy->cipher_suites = cipher_suites;
171 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 1961 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
1962 wdev->wiphy->reg_notifier = lbs_reg_notifier;
172 1963
173 ret = wiphy_register(wdev->wiphy); 1964 ret = wiphy_register(wdev->wiphy);
174 if (ret < 0) 1965 if (ret < 0)
@@ -180,10 +1971,36 @@ int lbs_cfg_register(struct lbs_private *priv)
180 if (ret) 1971 if (ret)
181 lbs_pr_err("cannot register network device\n"); 1972 lbs_pr_err("cannot register network device\n");
182 1973
1974 INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
1975
1976 lbs_cfg_set_regulatory_hint(priv);
1977
183 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); 1978 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
184 return ret; 1979 return ret;
185} 1980}
186 1981
1982int lbs_reg_notifier(struct wiphy *wiphy,
1983 struct regulatory_request *request)
1984{
1985 struct lbs_private *priv = wiphy_priv(wiphy);
1986 int ret;
1987
1988 lbs_deb_enter_args(LBS_DEB_CFG80211, "cfg80211 regulatory domain "
1989 "callback for domain %c%c\n", request->alpha2[0],
1990 request->alpha2[1]);
1991
1992 ret = lbs_set_11d_domain_info(priv, request, wiphy->bands);
1993
1994 lbs_deb_leave(LBS_DEB_CFG80211);
1995 return ret;
1996}
1997
1998void lbs_scan_deinit(struct lbs_private *priv)
1999{
2000 lbs_deb_enter(LBS_DEB_CFG80211);
2001 cancel_delayed_work_sync(&priv->scan_work);
2002}
2003
187 2004
188void lbs_cfg_free(struct lbs_private *priv) 2005void lbs_cfg_free(struct lbs_private *priv)
189{ 2006{
diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h
index e09a193a34d6..4f46bb744bee 100644
--- a/drivers/net/wireless/libertas/cfg.h
+++ b/drivers/net/wireless/libertas/cfg.h
@@ -1,16 +1,21 @@
1#ifndef __LBS_CFG80211_H__ 1#ifndef __LBS_CFG80211_H__
2#define __LBS_CFG80211_H__ 2#define __LBS_CFG80211_H__
3 3
4#include "dev.h" 4struct device;
5struct lbs_private;
6struct regulatory_request;
7struct wiphy;
5 8
6struct wireless_dev *lbs_cfg_alloc(struct device *dev); 9struct wireless_dev *lbs_cfg_alloc(struct device *dev);
7int lbs_cfg_register(struct lbs_private *priv); 10int lbs_cfg_register(struct lbs_private *priv);
8void lbs_cfg_free(struct lbs_private *priv); 11void lbs_cfg_free(struct lbs_private *priv);
9 12
10int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, 13int lbs_reg_notifier(struct wiphy *wiphy,
11 u8 ssid_len); 14 struct regulatory_request *request);
12int lbs_scan_networks(struct lbs_private *priv, int full_scan);
13void lbs_cfg_scan_worker(struct work_struct *work);
14 15
16void lbs_send_disconnect_notification(struct lbs_private *priv);
17void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
18
19void lbs_scan_deinit(struct lbs_private *priv);
15 20
16#endif 21#endif
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index cdb9b9650d73..70745928f3f8 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -6,18 +6,14 @@
6#include <linux/kfifo.h> 6#include <linux/kfifo.h>
7#include <linux/sched.h> 7#include <linux/sched.h>
8#include <linux/slab.h> 8#include <linux/slab.h>
9#include <linux/if_arp.h>
9 10
10#include "host.h"
11#include "decl.h" 11#include "decl.h"
12#include "defs.h" 12#include "cfg.h"
13#include "dev.h"
14#include "assoc.h"
15#include "wext.h"
16#include "scan.h"
17#include "cmd.h" 13#include "cmd.h"
18 14
19 15#define CAL_NF(nf) ((s32)(-(s32)(nf)))
20static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); 16#define CAL_RSSI(snr, nf) ((s32)((s32)(snr) + CAL_NF(nf)))
21 17
22/** 18/**
23 * @brief Simple callback that copies response back into command 19 * @brief Simple callback that copies response back into command
@@ -70,6 +66,8 @@ static u8 is_command_allowed_in_ps(u16 cmd)
70 switch (cmd) { 66 switch (cmd) {
71 case CMD_802_11_RSSI: 67 case CMD_802_11_RSSI:
72 return 1; 68 return 1;
69 case CMD_802_11_HOST_SLEEP_CFG:
70 return 1;
73 default: 71 default:
74 break; 72 break;
75 } 73 }
@@ -77,30 +75,6 @@ static u8 is_command_allowed_in_ps(u16 cmd)
77} 75}
78 76
79/** 77/**
80 * @brief This function checks if the command is allowed.
81 *
82 * @param priv A pointer to lbs_private structure
83 * @return allowed or not allowed.
84 */
85
86static int lbs_is_cmd_allowed(struct lbs_private *priv)
87{
88 int ret = 1;
89
90 lbs_deb_enter(LBS_DEB_CMD);
91
92 if (!priv->is_auto_deep_sleep_enabled) {
93 if (priv->is_deep_sleep) {
94 lbs_deb_cmd("command not allowed in deep sleep\n");
95 ret = 0;
96 }
97 }
98
99 lbs_deb_leave(LBS_DEB_CMD);
100 return ret;
101}
102
103/**
104 * @brief Updates the hardware details like MAC address and regulatory region 78 * @brief Updates the hardware details like MAC address and regulatory region
105 * 79 *
106 * @param priv A pointer to struct lbs_private structure 80 * @param priv A pointer to struct lbs_private structure
@@ -175,16 +149,28 @@ int lbs_update_hw_spec(struct lbs_private *priv)
175 if (priv->mesh_dev) 149 if (priv->mesh_dev)
176 memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN); 150 memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
177 151
178 if (lbs_set_regiontable(priv, priv->regioncode, 0)) {
179 ret = -1;
180 goto out;
181 }
182
183out: 152out:
184 lbs_deb_leave(LBS_DEB_CMD); 153 lbs_deb_leave(LBS_DEB_CMD);
185 return ret; 154 return ret;
186} 155}
187 156
157static int lbs_ret_host_sleep_cfg(struct lbs_private *priv, unsigned long dummy,
158 struct cmd_header *resp)
159{
160 lbs_deb_enter(LBS_DEB_CMD);
161 if (priv->is_host_sleep_activated) {
162 priv->is_host_sleep_configured = 0;
163 if (priv->psstate == PS_STATE_FULL_POWER) {
164 priv->is_host_sleep_activated = 0;
165 wake_up_interruptible(&priv->host_sleep_q);
166 }
167 } else {
168 priv->is_host_sleep_configured = 1;
169 }
170 lbs_deb_leave(LBS_DEB_CMD);
171 return 0;
172}
173
188int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, 174int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
189 struct wol_config *p_wol_config) 175 struct wol_config *p_wol_config)
190{ 176{
@@ -202,12 +188,11 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
202 else 188 else
203 cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE; 189 cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE;
204 190
205 ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config); 191 ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config.hdr,
192 le16_to_cpu(cmd_config.hdr.size),
193 lbs_ret_host_sleep_cfg, 0);
206 if (!ret) { 194 if (!ret) {
207 if (criteria) { 195 if (p_wol_config)
208 lbs_deb_cmd("Set WOL criteria to %x\n", criteria);
209 priv->wol_criteria = criteria;
210 } else
211 memcpy((uint8_t *) p_wol_config, 196 memcpy((uint8_t *) p_wol_config,
212 (uint8_t *)&cmd_config.wol_conf, 197 (uint8_t *)&cmd_config.wol_conf,
213 sizeof(struct wol_config)); 198 sizeof(struct wol_config));
@@ -219,42 +204,49 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
219} 204}
220EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg); 205EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);
221 206
222static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd, 207/**
223 u16 cmd_action) 208 * @brief Sets the Power Save mode
209 *
210 * @param priv A pointer to struct lbs_private structure
211 * @param cmd_action The Power Save operation (PS_MODE_ACTION_ENTER_PS or
212 * PS_MODE_ACTION_EXIT_PS)
213 * @param block Whether to block on a response or not
214 *
215 * @return 0 on success, error on failure
216 */
217int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block)
224{ 218{
225 struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode; 219 struct cmd_ds_802_11_ps_mode cmd;
220 int ret = 0;
226 221
227 lbs_deb_enter(LBS_DEB_CMD); 222 lbs_deb_enter(LBS_DEB_CMD);
228 223
229 cmd->command = cpu_to_le16(CMD_802_11_PS_MODE); 224 memset(&cmd, 0, sizeof(cmd));
230 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) + 225 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
231 sizeof(struct cmd_header)); 226 cmd.action = cpu_to_le16(cmd_action);
232 psm->action = cpu_to_le16(cmd_action);
233 psm->multipledtim = 0;
234 switch (cmd_action) {
235 case CMD_SUBCMD_ENTER_PS:
236 lbs_deb_cmd("PS command:" "SubCode- Enter PS\n");
237
238 psm->locallisteninterval = 0;
239 psm->nullpktinterval = 0;
240 psm->multipledtim =
241 cpu_to_le16(MRVDRV_DEFAULT_MULTIPLE_DTIM);
242 break;
243
244 case CMD_SUBCMD_EXIT_PS:
245 lbs_deb_cmd("PS command:" "SubCode- Exit PS\n");
246 break;
247
248 case CMD_SUBCMD_SLEEP_CONFIRMED:
249 lbs_deb_cmd("PS command: SubCode- sleep confirm\n");
250 break;
251 227
252 default: 228 if (cmd_action == PS_MODE_ACTION_ENTER_PS) {
253 break; 229 lbs_deb_cmd("PS_MODE: action ENTER_PS\n");
230 cmd.multipledtim = cpu_to_le16(1); /* Default DTIM multiple */
231 } else if (cmd_action == PS_MODE_ACTION_EXIT_PS) {
232 lbs_deb_cmd("PS_MODE: action EXIT_PS\n");
233 } else {
234 /* We don't handle CONFIRM_SLEEP here because it needs to
235 * be fastpathed to the firmware.
236 */
237 lbs_deb_cmd("PS_MODE: unknown action 0x%X\n", cmd_action);
238 ret = -EOPNOTSUPP;
239 goto out;
254 } 240 }
255 241
256 lbs_deb_leave(LBS_DEB_CMD); 242 if (block)
257 return 0; 243 ret = lbs_cmd_with_response(priv, CMD_802_11_PS_MODE, &cmd);
244 else
245 lbs_cmd_async(priv, CMD_802_11_PS_MODE, &cmd.hdr, sizeof (cmd));
246
247out:
248 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
249 return ret;
258} 250}
259 251
260int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, 252int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
@@ -353,6 +345,65 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep)
353 return ret; 345 return ret;
354} 346}
355 347
348static int lbs_ret_host_sleep_activate(struct lbs_private *priv,
349 unsigned long dummy,
350 struct cmd_header *cmd)
351{
352 lbs_deb_enter(LBS_DEB_FW);
353 priv->is_host_sleep_activated = 1;
354 wake_up_interruptible(&priv->host_sleep_q);
355 lbs_deb_leave(LBS_DEB_FW);
356 return 0;
357}
358
359int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep)
360{
361 struct cmd_header cmd;
362 int ret = 0;
363 uint32_t criteria = EHS_REMOVE_WAKEUP;
364
365 lbs_deb_enter(LBS_DEB_CMD);
366
367 if (host_sleep) {
368 if (priv->is_host_sleep_activated != 1) {
369 memset(&cmd, 0, sizeof(cmd));
370 ret = lbs_host_sleep_cfg(priv, priv->wol_criteria,
371 (struct wol_config *)NULL);
372 if (ret) {
373 lbs_pr_info("Host sleep configuration failed: "
374 "%d\n", ret);
375 return ret;
376 }
377 if (priv->psstate == PS_STATE_FULL_POWER) {
378 ret = __lbs_cmd(priv,
379 CMD_802_11_HOST_SLEEP_ACTIVATE,
380 &cmd,
381 sizeof(cmd),
382 lbs_ret_host_sleep_activate, 0);
383 if (ret)
384 lbs_pr_info("HOST_SLEEP_ACTIVATE "
385 "failed: %d\n", ret);
386 }
387
388 if (!wait_event_interruptible_timeout(
389 priv->host_sleep_q,
390 priv->is_host_sleep_activated,
391 (10 * HZ))) {
392 lbs_pr_err("host_sleep_q: timer expired\n");
393 ret = -1;
394 }
395 } else {
396 lbs_pr_err("host sleep: already enabled\n");
397 }
398 } else {
399 if (priv->is_host_sleep_activated)
400 ret = lbs_host_sleep_cfg(priv, criteria,
401 (struct wol_config *)NULL);
402 }
403
404 return ret;
405}
406
356/** 407/**
357 * @brief Set an SNMP MIB value 408 * @brief Set an SNMP MIB value
358 * 409 *
@@ -509,23 +560,35 @@ int lbs_set_tx_power(struct lbs_private *priv, s16 dbm)
509 return ret; 560 return ret;
510} 561}
511 562
512static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, 563/**
513 u16 cmd_action, void *pdata_buf) 564 * @brief Enable or disable monitor mode (only implemented on OLPC usb8388 FW)
565 *
566 * @param priv A pointer to struct lbs_private structure
567 * @param enable 1 to enable monitor mode, 0 to disable
568 *
569 * @return 0 on success, error on failure
570 */
571int lbs_set_monitor_mode(struct lbs_private *priv, int enable)
514{ 572{
515 struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor; 573 struct cmd_ds_802_11_monitor_mode cmd;
574 int ret;
575
576 memset(&cmd, 0, sizeof(cmd));
577 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
578 cmd.action = cpu_to_le16(CMD_ACT_SET);
579 if (enable)
580 cmd.mode = cpu_to_le16(0x1);
516 581
517 cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE); 582 lbs_deb_cmd("SET_MONITOR_MODE: %d\n", enable);
518 cmd->size =
519 cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) +
520 sizeof(struct cmd_header));
521 583
522 monitor->action = cpu_to_le16(cmd_action); 584 ret = lbs_cmd_with_response(priv, CMD_802_11_MONITOR_MODE, &cmd);
523 if (cmd_action == CMD_ACT_SET) { 585 if (ret == 0) {
524 monitor->mode = 586 priv->dev->type = enable ? ARPHRD_IEEE80211_RADIOTAP :
525 cpu_to_le16((u16) (*(u32 *) pdata_buf)); 587 ARPHRD_ETHER;
526 } 588 }
527 589
528 return 0; 590 lbs_deb_leave(LBS_DEB_CMD);
591 return ret;
529} 592}
530 593
531/** 594/**
@@ -610,78 +673,242 @@ out:
610 return ret; 673 return ret;
611} 674}
612 675
613static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, 676/**
614 u8 cmd_action, void *pdata_buf) 677 * @brief Get current RSSI and noise floor
678 *
679 * @param priv A pointer to struct lbs_private structure
680 * @param rssi On successful return, signal level in mBm
681 *
682 * @return The channel on success, error on failure
683 */
684int lbs_get_rssi(struct lbs_private *priv, s8 *rssi, s8 *nf)
615{ 685{
616 struct lbs_offset_value *offval; 686 struct cmd_ds_802_11_rssi cmd;
687 int ret = 0;
617 688
618 lbs_deb_enter(LBS_DEB_CMD); 689 lbs_deb_enter(LBS_DEB_CMD);
619 690
620 offval = (struct lbs_offset_value *)pdata_buf; 691 BUG_ON(rssi == NULL);
692 BUG_ON(nf == NULL);
621 693
622 switch (le16_to_cpu(cmdptr->command)) { 694 memset(&cmd, 0, sizeof(cmd));
623 case CMD_MAC_REG_ACCESS: 695 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
624 { 696 /* Average SNR over last 8 beacons */
625 struct cmd_ds_mac_reg_access *macreg; 697 cmd.n_or_snr = cpu_to_le16(8);
626 698
627 cmdptr->size = 699 ret = lbs_cmd_with_response(priv, CMD_802_11_RSSI, &cmd);
628 cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access) 700 if (ret == 0) {
629 + sizeof(struct cmd_header)); 701 *nf = CAL_NF(le16_to_cpu(cmd.nf));
630 macreg = 702 *rssi = CAL_RSSI(le16_to_cpu(cmd.n_or_snr), le16_to_cpu(cmd.nf));
631 (struct cmd_ds_mac_reg_access *)&cmdptr->params. 703 }
632 macreg;
633 704
634 macreg->action = cpu_to_le16(cmd_action); 705 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
635 macreg->offset = cpu_to_le16((u16) offval->offset); 706 return ret;
636 macreg->value = cpu_to_le32(offval->value); 707}
637 708
638 break; 709/**
639 } 710 * @brief Send regulatory and 802.11d domain information to the firmware
711 *
712 * @param priv pointer to struct lbs_private
713 * @param request cfg80211 regulatory request structure
714 * @param bands the device's supported bands and channels
715 *
716 * @return 0 on success, error code on failure
717*/
718int lbs_set_11d_domain_info(struct lbs_private *priv,
719 struct regulatory_request *request,
720 struct ieee80211_supported_band **bands)
721{
722 struct cmd_ds_802_11d_domain_info cmd;
723 struct mrvl_ie_domain_param_set *domain = &cmd.domain;
724 struct ieee80211_country_ie_triplet *t;
725 enum ieee80211_band band;
726 struct ieee80211_channel *ch;
727 u8 num_triplet = 0;
728 u8 num_parsed_chan = 0;
729 u8 first_channel = 0, next_chan = 0, max_pwr = 0;
730 u8 i, flag = 0;
731 size_t triplet_size;
732 int ret;
640 733
641 case CMD_BBP_REG_ACCESS: 734 lbs_deb_enter(LBS_DEB_11D);
642 {
643 struct cmd_ds_bbp_reg_access *bbpreg;
644 735
645 cmdptr->size = 736 memset(&cmd, 0, sizeof(cmd));
646 cpu_to_le16(sizeof 737 cmd.action = cpu_to_le16(CMD_ACT_SET);
647 (struct cmd_ds_bbp_reg_access)
648 + sizeof(struct cmd_header));
649 bbpreg =
650 (struct cmd_ds_bbp_reg_access *)&cmdptr->params.
651 bbpreg;
652 738
653 bbpreg->action = cpu_to_le16(cmd_action); 739 lbs_deb_11d("Setting country code '%c%c'\n",
654 bbpreg->offset = cpu_to_le16((u16) offval->offset); 740 request->alpha2[0], request->alpha2[1]);
655 bbpreg->value = (u8) offval->value;
656 741
657 break; 742 domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN);
658 }
659 743
660 case CMD_RF_REG_ACCESS: 744 /* Set country code */
661 { 745 domain->country_code[0] = request->alpha2[0];
662 struct cmd_ds_rf_reg_access *rfreg; 746 domain->country_code[1] = request->alpha2[1];
747 domain->country_code[2] = ' ';
663 748
664 cmdptr->size = 749 /* Now set up the channel triplets; firmware is somewhat picky here
665 cpu_to_le16(sizeof 750 * and doesn't validate channel numbers and spans; hence it would
666 (struct cmd_ds_rf_reg_access) + 751 * interpret a triplet of (36, 4, 20) as channels 36, 37, 38, 39. Since
667 sizeof(struct cmd_header)); 752 * the last 3 aren't valid channels, the driver is responsible for
668 rfreg = 753 * splitting that up into 4 triplet pairs of (36, 1, 20) + (40, 1, 20)
669 (struct cmd_ds_rf_reg_access *)&cmdptr->params. 754 * etc.
670 rfreg; 755 */
756 for (band = 0;
757 (band < IEEE80211_NUM_BANDS) && (num_triplet < MAX_11D_TRIPLETS);
758 band++) {
759
760 if (!bands[band])
761 continue;
762
763 for (i = 0;
764 (i < bands[band]->n_channels) && (num_triplet < MAX_11D_TRIPLETS);
765 i++) {
766 ch = &bands[band]->channels[i];
767 if (ch->flags & IEEE80211_CHAN_DISABLED)
768 continue;
769
770 if (!flag) {
771 flag = 1;
772 next_chan = first_channel = (u32) ch->hw_value;
773 max_pwr = ch->max_power;
774 num_parsed_chan = 1;
775 continue;
776 }
671 777
672 rfreg->action = cpu_to_le16(cmd_action); 778 if ((ch->hw_value == next_chan + 1) &&
673 rfreg->offset = cpu_to_le16((u16) offval->offset); 779 (ch->max_power == max_pwr)) {
674 rfreg->value = (u8) offval->value; 780 /* Consolidate adjacent channels */
781 next_chan++;
782 num_parsed_chan++;
783 } else {
784 /* Add this triplet */
785 lbs_deb_11d("11D triplet (%d, %d, %d)\n",
786 first_channel, num_parsed_chan,
787 max_pwr);
788 t = &domain->triplet[num_triplet];
789 t->chans.first_channel = first_channel;
790 t->chans.num_channels = num_parsed_chan;
791 t->chans.max_power = max_pwr;
792 num_triplet++;
793 flag = 0;
794 }
795 }
675 796
676 break; 797 if (flag) {
798 /* Add last triplet */
799 lbs_deb_11d("11D triplet (%d, %d, %d)\n", first_channel,
800 num_parsed_chan, max_pwr);
801 t = &domain->triplet[num_triplet];
802 t->chans.first_channel = first_channel;
803 t->chans.num_channels = num_parsed_chan;
804 t->chans.max_power = max_pwr;
805 num_triplet++;
677 } 806 }
807 }
678 808
679 default: 809 lbs_deb_11d("# triplets %d\n", num_triplet);
680 break; 810
811 /* Set command header sizes */
812 triplet_size = num_triplet * sizeof(struct ieee80211_country_ie_triplet);
813 domain->header.len = cpu_to_le16(sizeof(domain->country_code) +
814 triplet_size);
815
816 lbs_deb_hex(LBS_DEB_11D, "802.11D domain param set",
817 (u8 *) &cmd.domain.country_code,
818 le16_to_cpu(domain->header.len));
819
820 cmd.hdr.size = cpu_to_le16(sizeof(cmd.hdr) +
821 sizeof(cmd.action) +
822 sizeof(cmd.domain.header) +
823 sizeof(cmd.domain.country_code) +
824 triplet_size);
825
826 ret = lbs_cmd_with_response(priv, CMD_802_11D_DOMAIN_INFO, &cmd);
827
828 lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret);
829 return ret;
830}
831
832/**
833 * @brief Read a MAC, Baseband, or RF register
834 *
835 * @param priv pointer to struct lbs_private
836 * @param cmd register command, one of CMD_MAC_REG_ACCESS,
837 * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS
838 * @param offset byte offset of the register to get
839 * @param value on success, the value of the register at 'offset'
840 *
841 * @return 0 on success, error code on failure
842*/
843int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value)
844{
845 struct cmd_ds_reg_access cmd;
846 int ret = 0;
847
848 lbs_deb_enter(LBS_DEB_CMD);
849
850 BUG_ON(value == NULL);
851
852 memset(&cmd, 0, sizeof(cmd));
853 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
854 cmd.action = cpu_to_le16(CMD_ACT_GET);
855
856 if (reg != CMD_MAC_REG_ACCESS &&
857 reg != CMD_BBP_REG_ACCESS &&
858 reg != CMD_RF_REG_ACCESS) {
859 ret = -EINVAL;
860 goto out;
681 } 861 }
682 862
683 lbs_deb_leave(LBS_DEB_CMD); 863 ret = lbs_cmd_with_response(priv, reg, &cmd);
684 return 0; 864 if (ret) {
865 if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
866 *value = cmd.value.bbp_rf;
867 else if (reg == CMD_MAC_REG_ACCESS)
868 *value = le32_to_cpu(cmd.value.mac);
869 }
870
871out:
872 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
873 return ret;
874}
875
876/**
877 * @brief Write a MAC, Baseband, or RF register
878 *
879 * @param priv pointer to struct lbs_private
880 * @param cmd register command, one of CMD_MAC_REG_ACCESS,
881 * CMD_BBP_REG_ACCESS, or CMD_RF_REG_ACCESS
882 * @param offset byte offset of the register to set
883 * @param value the value to write to the register at 'offset'
884 *
885 * @return 0 on success, error code on failure
886*/
887int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value)
888{
889 struct cmd_ds_reg_access cmd;
890 int ret = 0;
891
892 lbs_deb_enter(LBS_DEB_CMD);
893
894 memset(&cmd, 0, sizeof(cmd));
895 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
896 cmd.action = cpu_to_le16(CMD_ACT_SET);
897
898 if (reg == CMD_BBP_REG_ACCESS || reg == CMD_RF_REG_ACCESS)
899 cmd.value.bbp_rf = (u8) (value & 0xFF);
900 else if (reg == CMD_MAC_REG_ACCESS)
901 cmd.value.mac = cpu_to_le32(value);
902 else {
903 ret = -EINVAL;
904 goto out;
905 }
906
907 ret = lbs_cmd_with_response(priv, reg, &cmd);
908
909out:
910 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
911 return ret;
685} 912}
686 913
687static void lbs_queue_cmd(struct lbs_private *priv, 914static void lbs_queue_cmd(struct lbs_private *priv,
@@ -704,14 +931,17 @@ static void lbs_queue_cmd(struct lbs_private *priv,
704 931
705 /* Exit_PS command needs to be queued in the header always. */ 932 /* Exit_PS command needs to be queued in the header always. */
706 if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) { 933 if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) {
707 struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf[1]; 934 struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf;
708 935
709 if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) { 936 if (psm->action == cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
710 if (priv->psstate != PS_STATE_FULL_POWER) 937 if (priv->psstate != PS_STATE_FULL_POWER)
711 addtail = 0; 938 addtail = 0;
712 } 939 }
713 } 940 }
714 941
942 if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_WAKEUP_CONFIRM)
943 addtail = 0;
944
715 spin_lock_irqsave(&priv->driver_lock, flags); 945 spin_lock_irqsave(&priv->driver_lock, flags);
716 946
717 if (addtail) 947 if (addtail)
@@ -744,7 +974,6 @@ static void lbs_submit_command(struct lbs_private *priv,
744 974
745 spin_lock_irqsave(&priv->driver_lock, flags); 975 spin_lock_irqsave(&priv->driver_lock, flags);
746 priv->cur_cmd = cmdnode; 976 priv->cur_cmd = cmdnode;
747 priv->cur_cmd_retcode = 0;
748 spin_unlock_irqrestore(&priv->driver_lock, flags); 977 spin_unlock_irqrestore(&priv->driver_lock, flags);
749 978
750 cmdsize = le16_to_cpu(cmd->size); 979 cmdsize = le16_to_cpu(cmd->size);
@@ -817,9 +1046,6 @@ static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv,
817void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, 1046void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
818 int result) 1047 int result)
819{ 1048{
820 if (cmd == priv->cur_cmd)
821 priv->cur_cmd_retcode = result;
822
823 cmd->result = result; 1049 cmd->result = result;
824 cmd->cmdwaitqwoken = 1; 1050 cmd->cmdwaitqwoken = 1;
825 wake_up_interruptible(&cmd->cmdwait_q); 1051 wake_up_interruptible(&cmd->cmdwait_q);
@@ -887,175 +1113,6 @@ void lbs_set_mac_control(struct lbs_private *priv)
887} 1113}
888 1114
889/** 1115/**
890 * @brief This function prepare the command before send to firmware.
891 *
892 * @param priv A pointer to struct lbs_private structure
893 * @param cmd_no command number
894 * @param cmd_action command action: GET or SET
895 * @param wait_option wait option: wait response or not
896 * @param cmd_oid cmd oid: treated as sub command
897 * @param pdata_buf A pointer to informaion buffer
898 * @return 0 or -1
899 */
900int lbs_prepare_and_send_command(struct lbs_private *priv,
901 u16 cmd_no,
902 u16 cmd_action,
903 u16 wait_option, u32 cmd_oid, void *pdata_buf)
904{
905 int ret = 0;
906 struct cmd_ctrl_node *cmdnode;
907 struct cmd_ds_command *cmdptr;
908 unsigned long flags;
909
910 lbs_deb_enter(LBS_DEB_HOST);
911
912 if (!priv) {
913 lbs_deb_host("PREP_CMD: priv is NULL\n");
914 ret = -1;
915 goto done;
916 }
917
918 if (priv->surpriseremoved) {
919 lbs_deb_host("PREP_CMD: card removed\n");
920 ret = -1;
921 goto done;
922 }
923
924 if (!lbs_is_cmd_allowed(priv)) {
925 ret = -EBUSY;
926 goto done;
927 }
928
929 cmdnode = lbs_get_cmd_ctrl_node(priv);
930
931 if (cmdnode == NULL) {
932 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
933
934 /* Wake up main thread to execute next command */
935 wake_up_interruptible(&priv->waitq);
936 ret = -1;
937 goto done;
938 }
939
940 cmdnode->callback = NULL;
941 cmdnode->callback_arg = (unsigned long)pdata_buf;
942
943 cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf;
944
945 lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no);
946
947 /* Set sequence number, command and INT option */
948 priv->seqnum++;
949 cmdptr->seqnum = cpu_to_le16(priv->seqnum);
950
951 cmdptr->command = cpu_to_le16(cmd_no);
952 cmdptr->result = 0;
953
954 switch (cmd_no) {
955 case CMD_802_11_PS_MODE:
956 ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action);
957 break;
958
959 case CMD_MAC_REG_ACCESS:
960 case CMD_BBP_REG_ACCESS:
961 case CMD_RF_REG_ACCESS:
962 ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf);
963 break;
964
965 case CMD_802_11_MONITOR_MODE:
966 ret = lbs_cmd_802_11_monitor_mode(cmdptr,
967 cmd_action, pdata_buf);
968 break;
969
970 case CMD_802_11_RSSI:
971 ret = lbs_cmd_802_11_rssi(priv, cmdptr);
972 break;
973
974 case CMD_802_11_SET_AFC:
975 case CMD_802_11_GET_AFC:
976
977 cmdptr->command = cpu_to_le16(cmd_no);
978 cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) +
979 sizeof(struct cmd_header));
980
981 memmove(&cmdptr->params.afc,
982 pdata_buf, sizeof(struct cmd_ds_802_11_afc));
983
984 ret = 0;
985 goto done;
986
987 case CMD_802_11_TPC_CFG:
988 cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG);
989 cmdptr->size =
990 cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) +
991 sizeof(struct cmd_header));
992
993 memmove(&cmdptr->params.tpccfg,
994 pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg));
995
996 ret = 0;
997 break;
998
999#ifdef CONFIG_LIBERTAS_MESH
1000
1001 case CMD_BT_ACCESS:
1002 ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf);
1003 break;
1004
1005 case CMD_FWT_ACCESS:
1006 ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
1007 break;
1008
1009#endif
1010
1011 case CMD_802_11_BEACON_CTRL:
1012 ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
1013 break;
1014 case CMD_802_11_DEEP_SLEEP:
1015 cmdptr->command = cpu_to_le16(CMD_802_11_DEEP_SLEEP);
1016 cmdptr->size = cpu_to_le16(sizeof(struct cmd_header));
1017 break;
1018 default:
1019 lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
1020 ret = -1;
1021 break;
1022 }
1023
1024 /* return error, since the command preparation failed */
1025 if (ret != 0) {
1026 lbs_deb_host("PREP_CMD: command preparation failed\n");
1027 lbs_cleanup_and_insert_cmd(priv, cmdnode);
1028 ret = -1;
1029 goto done;
1030 }
1031
1032 cmdnode->cmdwaitqwoken = 0;
1033
1034 lbs_queue_cmd(priv, cmdnode);
1035 wake_up_interruptible(&priv->waitq);
1036
1037 if (wait_option & CMD_OPTION_WAITFORRSP) {
1038 lbs_deb_host("PREP_CMD: wait for response\n");
1039 might_sleep();
1040 wait_event_interruptible(cmdnode->cmdwait_q,
1041 cmdnode->cmdwaitqwoken);
1042 }
1043
1044 spin_lock_irqsave(&priv->driver_lock, flags);
1045 if (priv->cur_cmd_retcode) {
1046 lbs_deb_host("PREP_CMD: command failed with return code %d\n",
1047 priv->cur_cmd_retcode);
1048 priv->cur_cmd_retcode = 0;
1049 ret = -1;
1050 }
1051 spin_unlock_irqrestore(&priv->driver_lock, flags);
1052
1053done:
1054 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
1055 return ret;
1056}
1057
1058/**
1059 * @brief This function allocates the command buffer and link 1116 * @brief This function allocates the command buffer and link
1060 * it to command free queue. 1117 * it to command free queue.
1061 * 1118 *
@@ -1148,7 +1205,7 @@ done:
1148 * @param priv A pointer to struct lbs_private structure 1205 * @param priv A pointer to struct lbs_private structure
1149 * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL 1206 * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL
1150 */ 1207 */
1151static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv) 1208static struct cmd_ctrl_node *lbs_get_free_cmd_node(struct lbs_private *priv)
1152{ 1209{
1153 struct cmd_ctrl_node *tempnode; 1210 struct cmd_ctrl_node *tempnode;
1154 unsigned long flags; 1211 unsigned long flags;
@@ -1231,10 +1288,10 @@ int lbs_execute_next_command(struct lbs_private *priv)
1231 /* 1288 /*
1232 * 1. Non-PS command: 1289 * 1. Non-PS command:
1233 * Queue it. set needtowakeup to TRUE if current state 1290 * Queue it. set needtowakeup to TRUE if current state
1234 * is SLEEP, otherwise call lbs_ps_wakeup to send Exit_PS. 1291 * is SLEEP, otherwise call send EXIT_PS.
1235 * 2. PS command but not Exit_PS: 1292 * 2. PS command but not EXIT_PS:
1236 * Ignore it. 1293 * Ignore it.
1237 * 3. PS command Exit_PS: 1294 * 3. PS command EXIT_PS:
1238 * Set needtowakeup to TRUE if current state is SLEEP, 1295 * Set needtowakeup to TRUE if current state is SLEEP,
1239 * otherwise send this command down to firmware 1296 * otherwise send this command down to firmware
1240 * immediately. 1297 * immediately.
@@ -1248,8 +1305,11 @@ int lbs_execute_next_command(struct lbs_private *priv)
1248 /* w/ new scheme, it will not reach here. 1305 /* w/ new scheme, it will not reach here.
1249 since it is blocked in main_thread. */ 1306 since it is blocked in main_thread. */
1250 priv->needtowakeup = 1; 1307 priv->needtowakeup = 1;
1251 } else 1308 } else {
1252 lbs_ps_wakeup(priv, 0); 1309 lbs_set_ps_mode(priv,
1310 PS_MODE_ACTION_EXIT_PS,
1311 false);
1312 }
1253 1313
1254 ret = 0; 1314 ret = 0;
1255 goto done; 1315 goto done;
@@ -1264,7 +1324,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
1264 "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n", 1324 "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n",
1265 psm->action); 1325 psm->action);
1266 if (psm->action != 1326 if (psm->action !=
1267 cpu_to_le16(CMD_SUBCMD_EXIT_PS)) { 1327 cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
1268 lbs_deb_host( 1328 lbs_deb_host(
1269 "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n"); 1329 "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
1270 list_del(&cmdnode->list); 1330 list_del(&cmdnode->list);
@@ -1303,6 +1363,15 @@ int lbs_execute_next_command(struct lbs_private *priv)
1303 * check if in power save mode, if yes, put the device back 1363 * check if in power save mode, if yes, put the device back
1304 * to PS mode 1364 * to PS mode
1305 */ 1365 */
1366#ifdef TODO
1367 /*
1368 * This was the old code for libertas+wext. Someone that
1369 * understands this beast should re-code it in a sane way.
1370 *
1371 * I actually don't understand why this is related to WPA
1372 * and to connection status, shouldn't powering should be
1373 * independ of such things?
1374 */
1306 if ((priv->psmode != LBS802_11POWERMODECAM) && 1375 if ((priv->psmode != LBS802_11POWERMODECAM) &&
1307 (priv->psstate == PS_STATE_FULL_POWER) && 1376 (priv->psstate == PS_STATE_FULL_POWER) &&
1308 ((priv->connect_status == LBS_CONNECTED) || 1377 ((priv->connect_status == LBS_CONNECTED) ||
@@ -1315,15 +1384,19 @@ int lbs_execute_next_command(struct lbs_private *priv)
1315 lbs_deb_host( 1384 lbs_deb_host(
1316 "EXEC_NEXT_CMD: WPA enabled and GTK_SET" 1385 "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
1317 " go back to PS_SLEEP"); 1386 " go back to PS_SLEEP");
1318 lbs_ps_sleep(priv, 0); 1387 lbs_set_ps_mode(priv,
1388 PS_MODE_ACTION_ENTER_PS,
1389 false);
1319 } 1390 }
1320 } else { 1391 } else {
1321 lbs_deb_host( 1392 lbs_deb_host(
1322 "EXEC_NEXT_CMD: cmdpendingq empty, " 1393 "EXEC_NEXT_CMD: cmdpendingq empty, "
1323 "go back to PS_SLEEP"); 1394 "go back to PS_SLEEP");
1324 lbs_ps_sleep(priv, 0); 1395 lbs_set_ps_mode(priv, PS_MODE_ACTION_ENTER_PS,
1396 false);
1325 } 1397 }
1326 } 1398 }
1399#endif
1327 } 1400 }
1328 1401
1329 ret = 0; 1402 ret = 0;
@@ -1353,6 +1426,11 @@ static void lbs_send_confirmsleep(struct lbs_private *priv)
1353 /* We don't get a response on the sleep-confirmation */ 1426 /* We don't get a response on the sleep-confirmation */
1354 priv->dnld_sent = DNLD_RES_RECEIVED; 1427 priv->dnld_sent = DNLD_RES_RECEIVED;
1355 1428
1429 if (priv->is_host_sleep_configured) {
1430 priv->is_host_sleep_activated = 1;
1431 wake_up_interruptible(&priv->host_sleep_q);
1432 }
1433
1356 /* If nothing to do, go back to sleep (?) */ 1434 /* If nothing to do, go back to sleep (?) */
1357 if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx]) 1435 if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx])
1358 priv->psstate = PS_STATE_SLEEP; 1436 priv->psstate = PS_STATE_SLEEP;
@@ -1363,43 +1441,6 @@ out:
1363 lbs_deb_leave(LBS_DEB_HOST); 1441 lbs_deb_leave(LBS_DEB_HOST);
1364} 1442}
1365 1443
1366void lbs_ps_sleep(struct lbs_private *priv, int wait_option)
1367{
1368 lbs_deb_enter(LBS_DEB_HOST);
1369
1370 /*
1371 * PS is currently supported only in Infrastructure mode
1372 * Remove this check if it is to be supported in IBSS mode also
1373 */
1374
1375 lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1376 CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL);
1377
1378 lbs_deb_leave(LBS_DEB_HOST);
1379}
1380
1381/**
1382 * @brief This function sends Exit_PS command to firmware.
1383 *
1384 * @param priv A pointer to struct lbs_private structure
1385 * @param wait_option wait response or not
1386 * @return n/a
1387 */
1388void lbs_ps_wakeup(struct lbs_private *priv, int wait_option)
1389{
1390 __le32 Localpsmode;
1391
1392 lbs_deb_enter(LBS_DEB_HOST);
1393
1394 Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM);
1395
1396 lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE,
1397 CMD_SUBCMD_EXIT_PS,
1398 wait_option, 0, &Localpsmode);
1399
1400 lbs_deb_leave(LBS_DEB_HOST);
1401}
1402
1403/** 1444/**
1404 * @brief This function checks condition and prepares to 1445 * @brief This function checks condition and prepares to
1405 * send sleep confirm command to firmware if ok. 1446 * send sleep confirm command to firmware if ok.
@@ -1524,12 +1565,18 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
1524 goto done; 1565 goto done;
1525 } 1566 }
1526 1567
1527 if (!lbs_is_cmd_allowed(priv)) { 1568 /* No commands are allowed in Deep Sleep until we toggle the GPIO
1528 cmdnode = ERR_PTR(-EBUSY); 1569 * to wake up the card and it has signaled that it's ready.
1529 goto done; 1570 */
1571 if (!priv->is_auto_deep_sleep_enabled) {
1572 if (priv->is_deep_sleep) {
1573 lbs_deb_cmd("command not allowed in deep sleep\n");
1574 cmdnode = ERR_PTR(-EBUSY);
1575 goto done;
1576 }
1530 } 1577 }
1531 1578
1532 cmdnode = lbs_get_cmd_ctrl_node(priv); 1579 cmdnode = lbs_get_free_cmd_node(priv);
1533 if (cmdnode == NULL) { 1580 if (cmdnode == NULL) {
1534 lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); 1581 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
1535 1582
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
index cb4138a55fdf..7109d6b717ea 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -3,6 +3,8 @@
3#ifndef _LBS_CMD_H_ 3#ifndef _LBS_CMD_H_
4#define _LBS_CMD_H_ 4#define _LBS_CMD_H_
5 5
6#include <net/cfg80211.h>
7
6#include "host.h" 8#include "host.h"
7#include "dev.h" 9#include "dev.h"
8 10
@@ -37,11 +39,6 @@ struct cmd_ctrl_node {
37#define lbs_cmd_with_response(priv, cmdnr, cmd) \ 39#define lbs_cmd_with_response(priv, cmdnr, cmd) \
38 lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd)) 40 lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd))
39 41
40int lbs_prepare_and_send_command(struct lbs_private *priv,
41 u16 cmd_no,
42 u16 cmd_action,
43 u16 wait_option, u32 cmd_oid, void *pdata_buf);
44
45void lbs_cmd_async(struct lbs_private *priv, uint16_t command, 42void lbs_cmd_async(struct lbs_private *priv, uint16_t command,
46 struct cmd_header *in_cmd, int in_cmd_size); 43 struct cmd_header *in_cmd, int in_cmd_size);
47 44
@@ -92,10 +89,6 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
92int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, 89int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
93 struct sleep_params *sp); 90 struct sleep_params *sp);
94 91
95void lbs_ps_sleep(struct lbs_private *priv, int wait_option);
96
97void lbs_ps_wakeup(struct lbs_private *priv, int wait_option);
98
99void lbs_ps_confirm_sleep(struct lbs_private *priv); 92void lbs_ps_confirm_sleep(struct lbs_private *priv);
100 93
101int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on); 94int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on);
@@ -127,4 +120,20 @@ int lbs_set_tx_power(struct lbs_private *priv, s16 dbm);
127 120
128int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep); 121int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep);
129 122
123int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep);
124
125int lbs_set_monitor_mode(struct lbs_private *priv, int enable);
126
127int lbs_get_rssi(struct lbs_private *priv, s8 *snr, s8 *nf);
128
129int lbs_set_11d_domain_info(struct lbs_private *priv,
130 struct regulatory_request *request,
131 struct ieee80211_supported_band **bands);
132
133int lbs_get_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 *value);
134
135int lbs_set_reg(struct lbs_private *priv, u16 reg, u16 offset, u32 value);
136
137int lbs_set_ps_mode(struct lbs_private *priv, u16 cmd_action, bool block);
138
130#endif /* _LBS_CMD_H */ 139#endif /* _LBS_CMD_H */
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 88f7131d66e9..5e95da9dcc2e 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -5,18 +5,11 @@
5#include <linux/slab.h> 5#include <linux/slab.h>
6#include <linux/delay.h> 6#include <linux/delay.h>
7#include <linux/sched.h> 7#include <linux/sched.h>
8#include <linux/if_arp.h>
9#include <linux/netdevice.h>
10#include <asm/unaligned.h> 8#include <asm/unaligned.h>
11#include <net/iw_handler.h> 9#include <net/cfg80211.h>
12 10
13#include "host.h" 11#include "cfg.h"
14#include "decl.h"
15#include "cmd.h" 12#include "cmd.h"
16#include "defs.h"
17#include "dev.h"
18#include "assoc.h"
19#include "wext.h"
20 13
21/** 14/**
22 * @brief This function handles disconnect event. it 15 * @brief This function handles disconnect event. it
@@ -38,7 +31,9 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
38 * It causes problem in the Supplicant 31 * It causes problem in the Supplicant
39 */ 32 */
40 msleep_interruptible(1000); 33 msleep_interruptible(1000);
41 lbs_send_disconnect_notification(priv); 34
35 if (priv->wdev->iftype == NL80211_IFTYPE_STATION)
36 lbs_send_disconnect_notification(priv);
42 37
43 /* report disconnect to upper layer */ 38 /* report disconnect to upper layer */
44 netif_stop_queue(priv->dev); 39 netif_stop_queue(priv->dev);
@@ -49,141 +44,16 @@ void lbs_mac_event_disconnected(struct lbs_private *priv)
49 priv->currenttxskb = NULL; 44 priv->currenttxskb = NULL;
50 priv->tx_pending_len = 0; 45 priv->tx_pending_len = 0;
51 46
52 /* reset SNR/NF/RSSI values */
53 memset(priv->SNR, 0x00, sizeof(priv->SNR));
54 memset(priv->NF, 0x00, sizeof(priv->NF));
55 memset(priv->RSSI, 0x00, sizeof(priv->RSSI));
56 memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR));
57 memset(priv->rawNF, 0x00, sizeof(priv->rawNF));
58 priv->nextSNRNF = 0;
59 priv->numSNRNF = 0;
60 priv->connect_status = LBS_DISCONNECTED; 47 priv->connect_status = LBS_DISCONNECTED;
61 48
62 /* Clear out associated SSID and BSSID since connection is
63 * no longer valid.
64 */
65 memset(&priv->curbssparams.bssid, 0, ETH_ALEN);
66 memset(&priv->curbssparams.ssid, 0, IEEE80211_MAX_SSID_LEN);
67 priv->curbssparams.ssid_len = 0;
68
69 if (priv->psstate != PS_STATE_FULL_POWER) { 49 if (priv->psstate != PS_STATE_FULL_POWER) {
70 /* make firmware to exit PS mode */ 50 /* make firmware to exit PS mode */
71 lbs_deb_cmd("disconnected, so exit PS mode\n"); 51 lbs_deb_cmd("disconnected, so exit PS mode\n");
72 lbs_ps_wakeup(priv, 0); 52 lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false);
73 } 53 }
74 lbs_deb_leave(LBS_DEB_ASSOC); 54 lbs_deb_leave(LBS_DEB_ASSOC);
75} 55}
76 56
77static int lbs_ret_reg_access(struct lbs_private *priv,
78 u16 type, struct cmd_ds_command *resp)
79{
80 int ret = 0;
81
82 lbs_deb_enter(LBS_DEB_CMD);
83
84 switch (type) {
85 case CMD_RET(CMD_MAC_REG_ACCESS):
86 {
87 struct cmd_ds_mac_reg_access *reg = &resp->params.macreg;
88
89 priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
90 priv->offsetvalue.value = le32_to_cpu(reg->value);
91 break;
92 }
93
94 case CMD_RET(CMD_BBP_REG_ACCESS):
95 {
96 struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg;
97
98 priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
99 priv->offsetvalue.value = reg->value;
100 break;
101 }
102
103 case CMD_RET(CMD_RF_REG_ACCESS):
104 {
105 struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg;
106
107 priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
108 priv->offsetvalue.value = reg->value;
109 break;
110 }
111
112 default:
113 ret = -1;
114 }
115
116 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
117 return ret;
118}
119
120static inline int handle_cmd_response(struct lbs_private *priv,
121 struct cmd_header *cmd_response)
122{
123 struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response;
124 int ret = 0;
125 unsigned long flags;
126 uint16_t respcmd = le16_to_cpu(resp->command);
127
128 lbs_deb_enter(LBS_DEB_HOST);
129
130 switch (respcmd) {
131 case CMD_RET(CMD_MAC_REG_ACCESS):
132 case CMD_RET(CMD_BBP_REG_ACCESS):
133 case CMD_RET(CMD_RF_REG_ACCESS):
134 ret = lbs_ret_reg_access(priv, respcmd, resp);
135 break;
136
137 case CMD_RET(CMD_802_11_SET_AFC):
138 case CMD_RET(CMD_802_11_GET_AFC):
139 spin_lock_irqsave(&priv->driver_lock, flags);
140 memmove((void *)priv->cur_cmd->callback_arg, &resp->params.afc,
141 sizeof(struct cmd_ds_802_11_afc));
142 spin_unlock_irqrestore(&priv->driver_lock, flags);
143
144 break;
145
146 case CMD_RET(CMD_802_11_BEACON_STOP):
147 break;
148
149 case CMD_RET(CMD_802_11_RSSI):
150 ret = lbs_ret_802_11_rssi(priv, resp);
151 break;
152
153 case CMD_RET(CMD_802_11_TPC_CFG):
154 spin_lock_irqsave(&priv->driver_lock, flags);
155 memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg,
156 sizeof(struct cmd_ds_802_11_tpc_cfg));
157 spin_unlock_irqrestore(&priv->driver_lock, flags);
158 break;
159
160 case CMD_RET(CMD_BT_ACCESS):
161 spin_lock_irqsave(&priv->driver_lock, flags);
162 if (priv->cur_cmd->callback_arg)
163 memcpy((void *)priv->cur_cmd->callback_arg,
164 &resp->params.bt.addr1, 2 * ETH_ALEN);
165 spin_unlock_irqrestore(&priv->driver_lock, flags);
166 break;
167 case CMD_RET(CMD_FWT_ACCESS):
168 spin_lock_irqsave(&priv->driver_lock, flags);
169 if (priv->cur_cmd->callback_arg)
170 memcpy((void *)priv->cur_cmd->callback_arg, &resp->params.fwt,
171 sizeof(resp->params.fwt));
172 spin_unlock_irqrestore(&priv->driver_lock, flags);
173 break;
174 case CMD_RET(CMD_802_11_BEACON_CTRL):
175 ret = lbs_ret_802_11_bcn_ctrl(priv, resp);
176 break;
177
178 default:
179 lbs_pr_err("CMD_RESP: unknown cmd response 0x%04x\n",
180 le16_to_cpu(resp->command));
181 break;
182 }
183 lbs_deb_leave(LBS_DEB_HOST);
184 return ret;
185}
186
187int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) 57int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
188{ 58{
189 uint16_t respcmd, curcmd; 59 uint16_t respcmd, curcmd;
@@ -242,9 +112,6 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
242 del_timer(&priv->command_timer); 112 del_timer(&priv->command_timer);
243 priv->cmd_timed_out = 0; 113 priv->cmd_timed_out = 0;
244 114
245 /* Store the response code to cur_cmd_retcode. */
246 priv->cur_cmd_retcode = result;
247
248 if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) { 115 if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
249 struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1]; 116 struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1];
250 u16 action = le16_to_cpu(psmode->action); 117 u16 action = le16_to_cpu(psmode->action);
@@ -261,10 +128,10 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
261 * ad-hoc mode. It takes place in 128 * ad-hoc mode. It takes place in
262 * lbs_execute_next_command(). 129 * lbs_execute_next_command().
263 */ 130 */
264 if (priv->mode == IW_MODE_ADHOC && 131 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR &&
265 action == CMD_SUBCMD_ENTER_PS) 132 action == PS_MODE_ACTION_ENTER_PS)
266 priv->psmode = LBS802_11POWERMODECAM; 133 priv->psmode = LBS802_11POWERMODECAM;
267 } else if (action == CMD_SUBCMD_ENTER_PS) { 134 } else if (action == PS_MODE_ACTION_ENTER_PS) {
268 priv->needtowakeup = 0; 135 priv->needtowakeup = 0;
269 priv->psstate = PS_STATE_AWAKE; 136 priv->psstate = PS_STATE_AWAKE;
270 137
@@ -279,11 +146,12 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
279 146
280 spin_unlock_irqrestore(&priv->driver_lock, flags); 147 spin_unlock_irqrestore(&priv->driver_lock, flags);
281 mutex_unlock(&priv->lock); 148 mutex_unlock(&priv->lock);
282 lbs_ps_wakeup(priv, 0); 149 lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS,
150 false);
283 mutex_lock(&priv->lock); 151 mutex_lock(&priv->lock);
284 spin_lock_irqsave(&priv->driver_lock, flags); 152 spin_lock_irqsave(&priv->driver_lock, flags);
285 } 153 }
286 } else if (action == CMD_SUBCMD_EXIT_PS) { 154 } else if (action == PS_MODE_ACTION_EXIT_PS) {
287 priv->needtowakeup = 0; 155 priv->needtowakeup = 0;
288 priv->psstate = PS_STATE_FULL_POWER; 156 priv->psstate = PS_STATE_FULL_POWER;
289 lbs_deb_host("CMD_RESP: EXIT_PS command response\n"); 157 lbs_deb_host("CMD_RESP: EXIT_PS command response\n");
@@ -324,8 +192,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
324 if (priv->cur_cmd && priv->cur_cmd->callback) { 192 if (priv->cur_cmd && priv->cur_cmd->callback) {
325 ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg, 193 ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg,
326 resp); 194 resp);
327 } else 195 }
328 ret = handle_cmd_response(priv, resp);
329 196
330 spin_lock_irqsave(&priv->driver_lock, flags); 197 spin_lock_irqsave(&priv->driver_lock, flags);
331 198
@@ -341,32 +208,10 @@ done:
341 return ret; 208 return ret;
342} 209}
343 210
344static int lbs_send_confirmwake(struct lbs_private *priv)
345{
346 struct cmd_header cmd;
347 int ret = 0;
348
349 lbs_deb_enter(LBS_DEB_HOST);
350
351 cmd.command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM);
352 cmd.size = cpu_to_le16(sizeof(cmd));
353 cmd.seqnum = cpu_to_le16(++priv->seqnum);
354 cmd.result = 0;
355
356 lbs_deb_hex(LBS_DEB_HOST, "wake confirm", (u8 *) &cmd,
357 sizeof(cmd));
358
359 ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd));
360 if (ret)
361 lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n");
362
363 lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret);
364 return ret;
365}
366
367int lbs_process_event(struct lbs_private *priv, u32 event) 211int lbs_process_event(struct lbs_private *priv, u32 event)
368{ 212{
369 int ret = 0; 213 int ret = 0;
214 struct cmd_header cmd;
370 215
371 lbs_deb_enter(LBS_DEB_CMD); 216 lbs_deb_enter(LBS_DEB_CMD);
372 217
@@ -410,7 +255,10 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
410 if (priv->reset_deep_sleep_wakeup) 255 if (priv->reset_deep_sleep_wakeup)
411 priv->reset_deep_sleep_wakeup(priv); 256 priv->reset_deep_sleep_wakeup(priv);
412 priv->is_deep_sleep = 0; 257 priv->is_deep_sleep = 0;
413 lbs_send_confirmwake(priv); 258 lbs_cmd_async(priv, CMD_802_11_WAKEUP_CONFIRM, &cmd,
259 sizeof(cmd));
260 priv->is_host_sleep_activated = 0;
261 wake_up_interruptible(&priv->host_sleep_q);
414 break; 262 break;
415 263
416 case MACREG_INT_CODE_DEEP_SLEEP_AWAKE: 264 case MACREG_INT_CODE_DEEP_SLEEP_AWAKE:
@@ -441,7 +289,7 @@ int lbs_process_event(struct lbs_private *priv, u32 event)
441 * in lbs_ps_wakeup() 289 * in lbs_ps_wakeup()
442 */ 290 */
443 lbs_deb_cmd("waking up ...\n"); 291 lbs_deb_cmd("waking up ...\n");
444 lbs_ps_wakeup(priv, 0); 292 lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, false);
445 } 293 }
446 break; 294 break;
447 295
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index de2caac11dd6..651a79c8de8a 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -1,18 +1,13 @@
1#include <linux/module.h>
2#include <linux/dcache.h> 1#include <linux/dcache.h>
3#include <linux/debugfs.h> 2#include <linux/debugfs.h>
4#include <linux/delay.h> 3#include <linux/delay.h>
5#include <linux/mm.h> 4#include <linux/mm.h>
6#include <linux/string.h> 5#include <linux/string.h>
7#include <linux/slab.h> 6#include <linux/slab.h>
8#include <net/iw_handler.h>
9#include <net/lib80211.h>
10 7
11#include "dev.h"
12#include "decl.h" 8#include "decl.h"
13#include "host.h"
14#include "debugfs.h"
15#include "cmd.h" 9#include "cmd.h"
10#include "debugfs.h"
16 11
17static struct dentry *lbs_dir; 12static struct dentry *lbs_dir;
18static char *szStates[] = { 13static char *szStates[] = {
@@ -60,51 +55,6 @@ static ssize_t lbs_dev_info(struct file *file, char __user *userbuf,
60 return res; 55 return res;
61} 56}
62 57
63
64static ssize_t lbs_getscantable(struct file *file, char __user *userbuf,
65 size_t count, loff_t *ppos)
66{
67 struct lbs_private *priv = file->private_data;
68 size_t pos = 0;
69 int numscansdone = 0, res;
70 unsigned long addr = get_zeroed_page(GFP_KERNEL);
71 char *buf = (char *)addr;
72 DECLARE_SSID_BUF(ssid);
73 struct bss_descriptor * iter_bss;
74 if (!buf)
75 return -ENOMEM;
76
77 pos += snprintf(buf+pos, len-pos,
78 "# | ch | rssi | bssid | cap | Qual | SSID\n");
79
80 mutex_lock(&priv->lock);
81 list_for_each_entry (iter_bss, &priv->network_list, list) {
82 u16 ibss = (iter_bss->capability & WLAN_CAPABILITY_IBSS);
83 u16 privacy = (iter_bss->capability & WLAN_CAPABILITY_PRIVACY);
84 u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT);
85
86 pos += snprintf(buf+pos, len-pos, "%02u| %03d | %04d | %pM |",
87 numscansdone, iter_bss->channel, iter_bss->rssi,
88 iter_bss->bssid);
89 pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability);
90 pos += snprintf(buf+pos, len-pos, "%c%c%c |",
91 ibss ? 'A' : 'I', privacy ? 'P' : ' ',
92 spectrum_mgmt ? 'S' : ' ');
93 pos += snprintf(buf+pos, len-pos, " %04d |", SCAN_RSSI(iter_bss->rssi));
94 pos += snprintf(buf+pos, len-pos, " %s\n",
95 print_ssid(ssid, iter_bss->ssid,
96 iter_bss->ssid_len));
97
98 numscansdone++;
99 }
100 mutex_unlock(&priv->lock);
101
102 res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
103
104 free_page(addr);
105 return res;
106}
107
108static ssize_t lbs_sleepparams_write(struct file *file, 58static ssize_t lbs_sleepparams_write(struct file *file,
109 const char __user *user_buf, size_t count, 59 const char __user *user_buf, size_t count,
110 loff_t *ppos) 60 loff_t *ppos)
@@ -174,6 +124,70 @@ out_unlock:
174 return ret; 124 return ret;
175} 125}
176 126
127static ssize_t lbs_host_sleep_write(struct file *file,
128 const char __user *user_buf, size_t count,
129 loff_t *ppos)
130{
131 struct lbs_private *priv = file->private_data;
132 ssize_t buf_size, ret;
133 int host_sleep;
134 unsigned long addr = get_zeroed_page(GFP_KERNEL);
135 char *buf = (char *)addr;
136 if (!buf)
137 return -ENOMEM;
138
139 buf_size = min(count, len - 1);
140 if (copy_from_user(buf, user_buf, buf_size)) {
141 ret = -EFAULT;
142 goto out_unlock;
143 }
144 ret = sscanf(buf, "%d", &host_sleep);
145 if (ret != 1) {
146 ret = -EINVAL;
147 goto out_unlock;
148 }
149
150 if (host_sleep == 0)
151 ret = lbs_set_host_sleep(priv, 0);
152 else if (host_sleep == 1) {
153 if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
154 lbs_pr_info("wake parameters not configured");
155 ret = -EINVAL;
156 goto out_unlock;
157 }
158 ret = lbs_set_host_sleep(priv, 1);
159 } else {
160 lbs_pr_err("invalid option\n");
161 ret = -EINVAL;
162 }
163
164 if (!ret)
165 ret = count;
166
167out_unlock:
168 free_page(addr);
169 return ret;
170}
171
172static ssize_t lbs_host_sleep_read(struct file *file, char __user *userbuf,
173 size_t count, loff_t *ppos)
174{
175 struct lbs_private *priv = file->private_data;
176 ssize_t ret;
177 size_t pos = 0;
178 unsigned long addr = get_zeroed_page(GFP_KERNEL);
179 char *buf = (char *)addr;
180 if (!buf)
181 return -ENOMEM;
182
183 pos += snprintf(buf, len, "%d\n", priv->is_host_sleep_activated);
184
185 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
186
187 free_page(addr);
188 return ret;
189}
190
177/* 191/*
178 * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might 192 * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might
179 * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the 193 * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the
@@ -432,30 +446,24 @@ static ssize_t lbs_bcnmiss_write(struct file *file, const char __user *userbuf,
432} 446}
433 447
434 448
435
436static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf, 449static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf,
437 size_t count, loff_t *ppos) 450 size_t count, loff_t *ppos)
438{ 451{
439 struct lbs_private *priv = file->private_data; 452 struct lbs_private *priv = file->private_data;
440 struct lbs_offset_value offval;
441 ssize_t pos = 0; 453 ssize_t pos = 0;
442 int ret; 454 int ret;
443 unsigned long addr = get_zeroed_page(GFP_KERNEL); 455 unsigned long addr = get_zeroed_page(GFP_KERNEL);
444 char *buf = (char *)addr; 456 char *buf = (char *)addr;
457 u32 val = 0;
458
445 if (!buf) 459 if (!buf)
446 return -ENOMEM; 460 return -ENOMEM;
447 461
448 offval.offset = priv->mac_offset; 462 ret = lbs_get_reg(priv, CMD_MAC_REG_ACCESS, priv->mac_offset, &val);
449 offval.value = 0;
450
451 ret = lbs_prepare_and_send_command(priv,
452 CMD_MAC_REG_ACCESS, 0,
453 CMD_OPTION_WAITFORRSP, 0, &offval);
454 mdelay(10); 463 mdelay(10);
455 if (!ret) { 464 if (!ret) {
456 pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n", 465 pos = snprintf(buf, len, "MAC[0x%x] = 0x%08x\n",
457 priv->mac_offset, priv->offsetvalue.value); 466 priv->mac_offset, val);
458
459 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 467 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
460 } 468 }
461 free_page(addr); 469 free_page(addr);
@@ -493,7 +501,6 @@ static ssize_t lbs_wrmac_write(struct file *file,
493 struct lbs_private *priv = file->private_data; 501 struct lbs_private *priv = file->private_data;
494 ssize_t res, buf_size; 502 ssize_t res, buf_size;
495 u32 offset, value; 503 u32 offset, value;
496 struct lbs_offset_value offval;
497 unsigned long addr = get_zeroed_page(GFP_KERNEL); 504 unsigned long addr = get_zeroed_page(GFP_KERNEL);
498 char *buf = (char *)addr; 505 char *buf = (char *)addr;
499 if (!buf) 506 if (!buf)
@@ -510,11 +517,7 @@ static ssize_t lbs_wrmac_write(struct file *file,
510 goto out_unlock; 517 goto out_unlock;
511 } 518 }
512 519
513 offval.offset = offset; 520 res = lbs_set_reg(priv, CMD_MAC_REG_ACCESS, offset, value);
514 offval.value = value;
515 res = lbs_prepare_and_send_command(priv,
516 CMD_MAC_REG_ACCESS, 1,
517 CMD_OPTION_WAITFORRSP, 0, &offval);
518 mdelay(10); 521 mdelay(10);
519 522
520 if (!res) 523 if (!res)
@@ -528,25 +531,20 @@ static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf,
528 size_t count, loff_t *ppos) 531 size_t count, loff_t *ppos)
529{ 532{
530 struct lbs_private *priv = file->private_data; 533 struct lbs_private *priv = file->private_data;
531 struct lbs_offset_value offval;
532 ssize_t pos = 0; 534 ssize_t pos = 0;
533 int ret; 535 int ret;
534 unsigned long addr = get_zeroed_page(GFP_KERNEL); 536 unsigned long addr = get_zeroed_page(GFP_KERNEL);
535 char *buf = (char *)addr; 537 char *buf = (char *)addr;
538 u32 val;
539
536 if (!buf) 540 if (!buf)
537 return -ENOMEM; 541 return -ENOMEM;
538 542
539 offval.offset = priv->bbp_offset; 543 ret = lbs_get_reg(priv, CMD_BBP_REG_ACCESS, priv->bbp_offset, &val);
540 offval.value = 0;
541
542 ret = lbs_prepare_and_send_command(priv,
543 CMD_BBP_REG_ACCESS, 0,
544 CMD_OPTION_WAITFORRSP, 0, &offval);
545 mdelay(10); 544 mdelay(10);
546 if (!ret) { 545 if (!ret) {
547 pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n", 546 pos = snprintf(buf, len, "BBP[0x%x] = 0x%08x\n",
548 priv->bbp_offset, priv->offsetvalue.value); 547 priv->bbp_offset, val);
549
550 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 548 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
551 } 549 }
552 free_page(addr); 550 free_page(addr);
@@ -585,7 +583,6 @@ static ssize_t lbs_wrbbp_write(struct file *file,
585 struct lbs_private *priv = file->private_data; 583 struct lbs_private *priv = file->private_data;
586 ssize_t res, buf_size; 584 ssize_t res, buf_size;
587 u32 offset, value; 585 u32 offset, value;
588 struct lbs_offset_value offval;
589 unsigned long addr = get_zeroed_page(GFP_KERNEL); 586 unsigned long addr = get_zeroed_page(GFP_KERNEL);
590 char *buf = (char *)addr; 587 char *buf = (char *)addr;
591 if (!buf) 588 if (!buf)
@@ -602,11 +599,7 @@ static ssize_t lbs_wrbbp_write(struct file *file,
602 goto out_unlock; 599 goto out_unlock;
603 } 600 }
604 601
605 offval.offset = offset; 602 res = lbs_set_reg(priv, CMD_BBP_REG_ACCESS, offset, value);
606 offval.value = value;
607 res = lbs_prepare_and_send_command(priv,
608 CMD_BBP_REG_ACCESS, 1,
609 CMD_OPTION_WAITFORRSP, 0, &offval);
610 mdelay(10); 603 mdelay(10);
611 604
612 if (!res) 605 if (!res)
@@ -620,25 +613,20 @@ static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf,
620 size_t count, loff_t *ppos) 613 size_t count, loff_t *ppos)
621{ 614{
622 struct lbs_private *priv = file->private_data; 615 struct lbs_private *priv = file->private_data;
623 struct lbs_offset_value offval;
624 ssize_t pos = 0; 616 ssize_t pos = 0;
625 int ret; 617 int ret;
626 unsigned long addr = get_zeroed_page(GFP_KERNEL); 618 unsigned long addr = get_zeroed_page(GFP_KERNEL);
627 char *buf = (char *)addr; 619 char *buf = (char *)addr;
620 u32 val;
621
628 if (!buf) 622 if (!buf)
629 return -ENOMEM; 623 return -ENOMEM;
630 624
631 offval.offset = priv->rf_offset; 625 ret = lbs_get_reg(priv, CMD_RF_REG_ACCESS, priv->rf_offset, &val);
632 offval.value = 0;
633
634 ret = lbs_prepare_and_send_command(priv,
635 CMD_RF_REG_ACCESS, 0,
636 CMD_OPTION_WAITFORRSP, 0, &offval);
637 mdelay(10); 626 mdelay(10);
638 if (!ret) { 627 if (!ret) {
639 pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n", 628 pos = snprintf(buf, len, "RF[0x%x] = 0x%08x\n",
640 priv->rf_offset, priv->offsetvalue.value); 629 priv->rf_offset, val);
641
642 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); 630 ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
643 } 631 }
644 free_page(addr); 632 free_page(addr);
@@ -677,7 +665,6 @@ static ssize_t lbs_wrrf_write(struct file *file,
677 struct lbs_private *priv = file->private_data; 665 struct lbs_private *priv = file->private_data;
678 ssize_t res, buf_size; 666 ssize_t res, buf_size;
679 u32 offset, value; 667 u32 offset, value;
680 struct lbs_offset_value offval;
681 unsigned long addr = get_zeroed_page(GFP_KERNEL); 668 unsigned long addr = get_zeroed_page(GFP_KERNEL);
682 char *buf = (char *)addr; 669 char *buf = (char *)addr;
683 if (!buf) 670 if (!buf)
@@ -694,11 +681,7 @@ static ssize_t lbs_wrrf_write(struct file *file,
694 goto out_unlock; 681 goto out_unlock;
695 } 682 }
696 683
697 offval.offset = offset; 684 res = lbs_set_reg(priv, CMD_RF_REG_ACCESS, offset, value);
698 offval.value = value;
699 res = lbs_prepare_and_send_command(priv,
700 CMD_RF_REG_ACCESS, 1,
701 CMD_OPTION_WAITFORRSP, 0, &offval);
702 mdelay(10); 685 mdelay(10);
703 686
704 if (!res) 687 if (!res)
@@ -723,10 +706,10 @@ struct lbs_debugfs_files {
723 706
724static const struct lbs_debugfs_files debugfs_files[] = { 707static const struct lbs_debugfs_files debugfs_files[] = {
725 { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), }, 708 { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), },
726 { "getscantable", 0444, FOPS(lbs_getscantable,
727 write_file_dummy), },
728 { "sleepparams", 0644, FOPS(lbs_sleepparams_read, 709 { "sleepparams", 0644, FOPS(lbs_sleepparams_read,
729 lbs_sleepparams_write), }, 710 lbs_sleepparams_write), },
711 { "hostsleep", 0644, FOPS(lbs_host_sleep_read,
712 lbs_host_sleep_write), },
730}; 713};
731 714
732static const struct lbs_debugfs_files debugfs_events_files[] = { 715static const struct lbs_debugfs_files debugfs_events_files[] = {
@@ -891,7 +874,7 @@ static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf,
891 874
892 p = buf; 875 p = buf;
893 876
894 d = (struct debug_data *)file->private_data; 877 d = file->private_data;
895 878
896 for (i = 0; i < num_of_items; i++) { 879 for (i = 0; i < num_of_items; i++) {
897 if (d[i].size == 1) 880 if (d[i].size == 1)
@@ -930,7 +913,7 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf,
930 char *p0; 913 char *p0;
931 char *p1; 914 char *p1;
932 char *p2; 915 char *p2;
933 struct debug_data *d = (struct debug_data *)f->private_data; 916 struct debug_data *d = f->private_data;
934 917
935 pdata = kmalloc(cnt, GFP_KERNEL); 918 pdata = kmalloc(cnt, GFP_KERNEL);
936 if (pdata == NULL) 919 if (pdata == NULL)
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 709ffcad22ad..1d141fefd767 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -1,3 +1,4 @@
1
1/** 2/**
2 * This file contains declaration referring to 3 * This file contains declaration referring to
3 * functions defined in other source files 4 * functions defined in other source files
@@ -12,6 +13,7 @@
12struct lbs_private; 13struct lbs_private;
13struct sk_buff; 14struct sk_buff;
14struct net_device; 15struct net_device;
16struct cmd_ds_command;
15 17
16 18
17/* ethtool.c */ 19/* ethtool.c */
@@ -34,11 +36,13 @@ int lbs_start_card(struct lbs_private *priv);
34void lbs_stop_card(struct lbs_private *priv); 36void lbs_stop_card(struct lbs_private *priv);
35void lbs_host_to_card_done(struct lbs_private *priv); 37void lbs_host_to_card_done(struct lbs_private *priv);
36 38
39int lbs_rtap_supported(struct lbs_private *priv);
40
37int lbs_set_mac_address(struct net_device *dev, void *addr); 41int lbs_set_mac_address(struct net_device *dev, void *addr);
38void lbs_set_multicast_list(struct net_device *dev); 42void lbs_set_multicast_list(struct net_device *dev);
39 43
40int lbs_suspend(struct lbs_private *priv); 44int lbs_suspend(struct lbs_private *priv);
41void lbs_resume(struct lbs_private *priv); 45int lbs_resume(struct lbs_private *priv);
42 46
43void lbs_queue_event(struct lbs_private *priv, u32 event); 47void lbs_queue_event(struct lbs_private *priv, u32 event);
44void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); 48void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx);
@@ -49,5 +53,4 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv);
49u32 lbs_fw_index_to_data_rate(u8 index); 53u32 lbs_fw_index_to_data_rate(u8 index);
50u8 lbs_data_rate_to_fw_index(u32 rate); 54u8 lbs_data_rate_to_fw_index(u32 rate);
51 55
52
53#endif 56#endif
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index ea3f10ef4e00..d00c728cec47 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -172,11 +172,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
172#define MRVDRV_MAX_BSS_DESCRIPTS 16 172#define MRVDRV_MAX_BSS_DESCRIPTS 16
173#define MRVDRV_MAX_REGION_CODE 6 173#define MRVDRV_MAX_REGION_CODE 6
174 174
175#define MRVDRV_IGNORE_MULTIPLE_DTIM 0xfffe
176#define MRVDRV_MIN_MULTIPLE_DTIM 1
177#define MRVDRV_MAX_MULTIPLE_DTIM 5
178#define MRVDRV_DEFAULT_MULTIPLE_DTIM 1
179
180#define MRVDRV_DEFAULT_LISTEN_INTERVAL 10 175#define MRVDRV_DEFAULT_LISTEN_INTERVAL 10
181 176
182#define MRVDRV_CHANNELS_PER_SCAN 4 177#define MRVDRV_CHANNELS_PER_SCAN 4
@@ -301,19 +296,6 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
301#define BAND_G (0x02) 296#define BAND_G (0x02)
302#define ALL_802_11_BANDS (BAND_B | BAND_G) 297#define ALL_802_11_BANDS (BAND_B | BAND_G)
303 298
304/** MACRO DEFINITIONS */
305#define CAL_NF(NF) ((s32)(-(s32)(NF)))
306#define CAL_RSSI(SNR, NF) ((s32)((s32)(SNR) + CAL_NF(NF)))
307#define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI)))
308
309#define DEFAULT_BCN_AVG_FACTOR 8
310#define DEFAULT_DATA_AVG_FACTOR 8
311#define AVG_SCALE 100
312#define CAL_AVG_SNR_NF(AVG, SNRNF, N) \
313 (((AVG) == 0) ? ((u16)(SNRNF) * AVG_SCALE) : \
314 ((((int)(AVG) * (N -1)) + ((u16)(SNRNF) * \
315 AVG_SCALE)) / N))
316
317#define MAX_RATES 14 299#define MAX_RATES 14
318 300
319#define MAX_LEDS 8 301#define MAX_LEDS 8
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index a54880e4ad2b..3c7e255e18c7 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -7,8 +7,8 @@
7#define _LBS_DEV_H_ 7#define _LBS_DEV_H_
8 8
9#include "mesh.h" 9#include "mesh.h"
10#include "scan.h" 10#include "defs.h"
11#include "assoc.h" 11#include "host.h"
12 12
13#include <linux/kfifo.h> 13#include <linux/kfifo.h>
14 14
@@ -29,7 +29,6 @@ struct lbs_private {
29 /* Basic networking */ 29 /* Basic networking */
30 struct net_device *dev; 30 struct net_device *dev;
31 u32 connect_status; 31 u32 connect_status;
32 int infra_open;
33 struct work_struct mcast_work; 32 struct work_struct mcast_work;
34 u32 nr_of_multicastmacaddr; 33 u32 nr_of_multicastmacaddr;
35 u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; 34 u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
@@ -37,6 +36,9 @@ struct lbs_private {
37 /* CFG80211 */ 36 /* CFG80211 */
38 struct wireless_dev *wdev; 37 struct wireless_dev *wdev;
39 bool wiphy_registered; 38 bool wiphy_registered;
39 struct cfg80211_scan_request *scan_req;
40 u8 assoc_bss[ETH_ALEN];
41 u8 disassoc_reason;
40 42
41 /* Mesh */ 43 /* Mesh */
42 struct net_device *mesh_dev; /* Virtual device */ 44 struct net_device *mesh_dev; /* Virtual device */
@@ -49,10 +51,6 @@ struct lbs_private {
49 u8 mesh_ssid_len; 51 u8 mesh_ssid_len;
50#endif 52#endif
51 53
52 /* Monitor mode */
53 struct net_device *rtap_net_dev;
54 u32 monitormode;
55
56 /* Debugfs */ 54 /* Debugfs */
57 struct dentry *debugfs_dir; 55 struct dentry *debugfs_dir;
58 struct dentry *debugfs_debug; 56 struct dentry *debugfs_debug;
@@ -66,7 +64,6 @@ struct lbs_private {
66 u32 mac_offset; 64 u32 mac_offset;
67 u32 bbp_offset; 65 u32 bbp_offset;
68 u32 rf_offset; 66 u32 rf_offset;
69 struct lbs_offset_value offsetvalue;
70 67
71 /* Power management */ 68 /* Power management */
72 u16 psmode; 69 u16 psmode;
@@ -75,6 +72,7 @@ struct lbs_private {
75 72
76 /* Deep sleep */ 73 /* Deep sleep */
77 int is_deep_sleep; 74 int is_deep_sleep;
75 int deep_sleep_required;
78 int is_auto_deep_sleep_enabled; 76 int is_auto_deep_sleep_enabled;
79 int wakeup_dev_required; 77 int wakeup_dev_required;
80 int is_activity_detected; 78 int is_activity_detected;
@@ -82,6 +80,11 @@ struct lbs_private {
82 wait_queue_head_t ds_awake_q; 80 wait_queue_head_t ds_awake_q;
83 struct timer_list auto_deepsleep_timer; 81 struct timer_list auto_deepsleep_timer;
84 82
83 /* Host sleep*/
84 int is_host_sleep_configured;
85 int is_host_sleep_activated;
86 wait_queue_head_t host_sleep_q;
87
85 /* Hardware access */ 88 /* Hardware access */
86 void *card; 89 void *card;
87 u8 fw_ready; 90 u8 fw_ready;
@@ -108,12 +111,10 @@ struct lbs_private {
108 struct cmd_ctrl_node *cur_cmd; 111 struct cmd_ctrl_node *cur_cmd;
109 struct list_head cmdfreeq; /* free command buffers */ 112 struct list_head cmdfreeq; /* free command buffers */
110 struct list_head cmdpendingq; /* pending command buffers */ 113 struct list_head cmdpendingq; /* pending command buffers */
111 wait_queue_head_t cmd_pending;
112 struct timer_list command_timer; 114 struct timer_list command_timer;
113 int cmd_timed_out; 115 int cmd_timed_out;
114 116
115 /* Command responses sent from the hardware to the driver */ 117 /* Command responses sent from the hardware to the driver */
116 int cur_cmd_retcode;
117 u8 resp_idx; 118 u8 resp_idx;
118 u8 resp_buf[2][LBS_UPLD_SIZE]; 119 u8 resp_buf[2][LBS_UPLD_SIZE];
119 u32 resp_len[2]; 120 u32 resp_len[2];
@@ -127,14 +128,10 @@ struct lbs_private {
127 struct workqueue_struct *work_thread; 128 struct workqueue_struct *work_thread;
128 129
129 /** Encryption stuff */ 130 /** Encryption stuff */
130 struct lbs_802_11_security secinfo;
131 struct enc_key wpa_mcast_key;
132 struct enc_key wpa_unicast_key;
133 u8 wpa_ie[MAX_WPA_IE_LEN];
134 u8 wpa_ie_len;
135 u16 wep_tx_keyidx;
136 struct enc_key wep_keys[4];
137 u8 authtype_auto; 131 u8 authtype_auto;
132 u8 wep_tx_key;
133 u8 wep_key[4][WLAN_KEY_LEN_WEP104];
134 u8 wep_key_len[4];
138 135
139 /* Wake On LAN */ 136 /* Wake On LAN */
140 uint32_t wol_criteria; 137 uint32_t wol_criteria;
@@ -155,6 +152,7 @@ struct lbs_private {
155 /* NIC/link operation characteristics */ 152 /* NIC/link operation characteristics */
156 u16 mac_control; 153 u16 mac_control;
157 u8 radio_on; 154 u8 radio_on;
155 u8 cur_rate;
158 u8 channel; 156 u8 channel;
159 s16 txpower_cur; 157 s16 txpower_cur;
160 s16 txpower_min; 158 s16 txpower_min;
@@ -163,42 +161,6 @@ struct lbs_private {
163 /** Scanning */ 161 /** Scanning */
164 struct delayed_work scan_work; 162 struct delayed_work scan_work;
165 int scan_channel; 163 int scan_channel;
166 /* remember which channel was scanned last, != 0 if currently scanning */
167 u8 scan_ssid[IEEE80211_MAX_SSID_LEN + 1];
168 u8 scan_ssid_len;
169
170 /* Associating */
171 struct delayed_work assoc_work;
172 struct current_bss_params curbssparams;
173 u8 mode;
174 struct list_head network_list;
175 struct list_head network_free_list;
176 struct bss_descriptor *networks;
177 struct assoc_request * pending_assoc_req;
178 struct assoc_request * in_progress_assoc_req;
179 uint16_t enablehwauto;
180
181 /* ADHOC */
182 u16 beacon_period;
183 u8 beacon_enable;
184 u8 adhoccreate;
185
186 /* WEXT */
187 char name[DEV_NAME_LEN];
188 u8 nodename[16];
189 struct iw_statistics wstats;
190 u8 cur_rate;
191#define MAX_REGION_CHANNEL_NUM 2
192 struct region_channel region_channel[MAX_REGION_CHANNEL_NUM];
193
194 /** Requested Signal Strength*/
195 u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG];
196 u16 NF[MAX_TYPE_B][MAX_TYPE_AVG];
197 u8 RSSI[MAX_TYPE_B][MAX_TYPE_AVG];
198 u8 rawSNR[DEFAULT_DATA_AVG_FACTOR];
199 u8 rawNF[DEFAULT_DATA_AVG_FACTOR];
200 u16 nextSNRNF;
201 u16 numSNRNF;
202}; 164};
203 165
204extern struct cmd_confirm_sleep confirm_sleep; 166extern struct cmd_confirm_sleep confirm_sleep;
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 3804a58d7f4e..50193aac679e 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -2,13 +2,8 @@
2#include <linux/ethtool.h> 2#include <linux/ethtool.h>
3#include <linux/delay.h> 3#include <linux/delay.h>
4 4
5#include "host.h"
6#include "decl.h" 5#include "decl.h"
7#include "defs.h"
8#include "dev.h"
9#include "wext.h"
10#include "cmd.h" 6#include "cmd.h"
11#include "mesh.h"
12 7
13 8
14static void lbs_ethtool_get_drvinfo(struct net_device *dev, 9static void lbs_ethtool_get_drvinfo(struct net_device *dev,
@@ -69,14 +64,11 @@ static void lbs_ethtool_get_wol(struct net_device *dev,
69{ 64{
70 struct lbs_private *priv = dev->ml_priv; 65 struct lbs_private *priv = dev->ml_priv;
71 66
72 if (priv->wol_criteria == 0xffffffff) {
73 /* Interface driver didn't configure wake */
74 wol->supported = wol->wolopts = 0;
75 return;
76 }
77
78 wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY; 67 wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY;
79 68
69 if (priv->wol_criteria == EHS_REMOVE_WAKEUP)
70 return;
71
80 if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA) 72 if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA)
81 wol->wolopts |= WAKE_UCAST; 73 wol->wolopts |= WAKE_UCAST;
82 if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA) 74 if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA)
@@ -91,23 +83,22 @@ static int lbs_ethtool_set_wol(struct net_device *dev,
91 struct ethtool_wolinfo *wol) 83 struct ethtool_wolinfo *wol)
92{ 84{
93 struct lbs_private *priv = dev->ml_priv; 85 struct lbs_private *priv = dev->ml_priv;
94 uint32_t criteria = 0;
95 86
96 if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY)) 87 if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY))
97 return -EOPNOTSUPP; 88 return -EOPNOTSUPP;
98 89
90 priv->wol_criteria = 0;
99 if (wol->wolopts & WAKE_UCAST) 91 if (wol->wolopts & WAKE_UCAST)
100 criteria |= EHS_WAKE_ON_UNICAST_DATA; 92 priv->wol_criteria |= EHS_WAKE_ON_UNICAST_DATA;
101 if (wol->wolopts & WAKE_MCAST) 93 if (wol->wolopts & WAKE_MCAST)
102 criteria |= EHS_WAKE_ON_MULTICAST_DATA; 94 priv->wol_criteria |= EHS_WAKE_ON_MULTICAST_DATA;
103 if (wol->wolopts & WAKE_BCAST) 95 if (wol->wolopts & WAKE_BCAST)
104 criteria |= EHS_WAKE_ON_BROADCAST_DATA; 96 priv->wol_criteria |= EHS_WAKE_ON_BROADCAST_DATA;
105 if (wol->wolopts & WAKE_PHY) 97 if (wol->wolopts & WAKE_PHY)
106 criteria |= EHS_WAKE_ON_MAC_EVENT; 98 priv->wol_criteria |= EHS_WAKE_ON_MAC_EVENT;
107 if (wol->wolopts == 0) 99 if (wol->wolopts == 0)
108 criteria |= EHS_REMOVE_WAKEUP; 100 priv->wol_criteria |= EHS_REMOVE_WAKEUP;
109 101 return 0;
110 return lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL);
111} 102}
112 103
113const struct ethtool_ops lbs_ethtool_ops = { 104const struct ethtool_ops lbs_ethtool_ops = {
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index 3809c0b49464..5eac1351a021 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -94,11 +94,9 @@
94#define CMD_802_11_BEACON_CTRL 0x00b0 94#define CMD_802_11_BEACON_CTRL 0x00b0
95 95
96/* For the IEEE Power Save */ 96/* For the IEEE Power Save */
97#define CMD_SUBCMD_ENTER_PS 0x0030 97#define PS_MODE_ACTION_ENTER_PS 0x0030
98#define CMD_SUBCMD_EXIT_PS 0x0031 98#define PS_MODE_ACTION_EXIT_PS 0x0031
99#define CMD_SUBCMD_SLEEP_CONFIRMED 0x0034 99#define PS_MODE_ACTION_SLEEP_CONFIRMED 0x0034
100#define CMD_SUBCMD_FULL_POWERDOWN 0x0035
101#define CMD_SUBCMD_FULL_POWERUP 0x0036
102 100
103#define CMD_ENABLE_RSN 0x0001 101#define CMD_ENABLE_RSN 0x0001
104#define CMD_DISABLE_RSN 0x0000 102#define CMD_DISABLE_RSN 0x0000
@@ -163,11 +161,6 @@
163#define CMD_ACT_SET_TX_FIX_RATE 0x0001 161#define CMD_ACT_SET_TX_FIX_RATE 0x0001
164#define CMD_ACT_GET_TX_RATE 0x0002 162#define CMD_ACT_GET_TX_RATE 0x0002
165 163
166/* Define action or option for CMD_802_11_PS_MODE */
167#define CMD_TYPE_CAM 0x0000
168#define CMD_TYPE_MAX_PSP 0x0001
169#define CMD_TYPE_FAST_PSP 0x0002
170
171/* Options for CMD_802_11_FW_WAKE_METHOD */ 164/* Options for CMD_802_11_FW_WAKE_METHOD */
172#define CMD_WAKE_METHOD_UNCHANGED 0x0000 165#define CMD_WAKE_METHOD_UNCHANGED 0x0000
173#define CMD_WAKE_METHOD_COMMAND_INT 0x0001 166#define CMD_WAKE_METHOD_COMMAND_INT 0x0001
@@ -326,7 +319,7 @@ struct txpd {
326 u8 pktdelay_2ms; 319 u8 pktdelay_2ms;
327 /* reserved */ 320 /* reserved */
328 u8 reserved1; 321 u8 reserved1;
329} __attribute__ ((packed)); 322} __packed;
330 323
331/* RxPD Descriptor */ 324/* RxPD Descriptor */
332struct rxpd { 325struct rxpd {
@@ -339,8 +332,8 @@ struct rxpd {
339 u8 bss_type; 332 u8 bss_type;
340 /* BSS number */ 333 /* BSS number */
341 u8 bss_num; 334 u8 bss_num;
342 } __attribute__ ((packed)) bss; 335 } __packed bss;
343 } __attribute__ ((packed)) u; 336 } __packed u;
344 337
345 /* SNR */ 338 /* SNR */
346 u8 snr; 339 u8 snr;
@@ -366,14 +359,14 @@ struct rxpd {
366 /* Pkt Priority */ 359 /* Pkt Priority */
367 u8 priority; 360 u8 priority;
368 u8 reserved[3]; 361 u8 reserved[3];
369} __attribute__ ((packed)); 362} __packed;
370 363
371struct cmd_header { 364struct cmd_header {
372 __le16 command; 365 __le16 command;
373 __le16 size; 366 __le16 size;
374 __le16 seqnum; 367 __le16 seqnum;
375 __le16 result; 368 __le16 result;
376} __attribute__ ((packed)); 369} __packed;
377 370
378/* Generic structure to hold all key types. */ 371/* Generic structure to hold all key types. */
379struct enc_key { 372struct enc_key {
@@ -387,7 +380,23 @@ struct enc_key {
387struct lbs_offset_value { 380struct lbs_offset_value {
388 u32 offset; 381 u32 offset;
389 u32 value; 382 u32 value;
390} __attribute__ ((packed)); 383} __packed;
384
385#define MAX_11D_TRIPLETS 83
386
387struct mrvl_ie_domain_param_set {
388 struct mrvl_ie_header header;
389
390 u8 country_code[3];
391 struct ieee80211_country_ie_triplet triplet[MAX_11D_TRIPLETS];
392} __packed;
393
394struct cmd_ds_802_11d_domain_info {
395 struct cmd_header hdr;
396
397 __le16 action;
398 struct mrvl_ie_domain_param_set domain;
399} __packed;
391 400
392/* 401/*
393 * Define data structure for CMD_GET_HW_SPEC 402 * Define data structure for CMD_GET_HW_SPEC
@@ -426,7 +435,7 @@ struct cmd_ds_get_hw_spec {
426 435
427 /*FW/HW capability */ 436 /*FW/HW capability */
428 __le32 fwcapinfo; 437 __le32 fwcapinfo;
429} __attribute__ ((packed)); 438} __packed;
430 439
431struct cmd_ds_802_11_subscribe_event { 440struct cmd_ds_802_11_subscribe_event {
432 struct cmd_header hdr; 441 struct cmd_header hdr;
@@ -440,7 +449,7 @@ struct cmd_ds_802_11_subscribe_event {
440 * bump this up a bit. 449 * bump this up a bit.
441 */ 450 */
442 uint8_t tlv[128]; 451 uint8_t tlv[128];
443} __attribute__ ((packed)); 452} __packed;
444 453
445/* 454/*
446 * This scan handle Country Information IE(802.11d compliant) 455 * This scan handle Country Information IE(802.11d compliant)
@@ -452,7 +461,7 @@ struct cmd_ds_802_11_scan {
452 uint8_t bsstype; 461 uint8_t bsstype;
453 uint8_t bssid[ETH_ALEN]; 462 uint8_t bssid[ETH_ALEN];
454 uint8_t tlvbuffer[0]; 463 uint8_t tlvbuffer[0];
455} __attribute__ ((packed)); 464} __packed;
456 465
457struct cmd_ds_802_11_scan_rsp { 466struct cmd_ds_802_11_scan_rsp {
458 struct cmd_header hdr; 467 struct cmd_header hdr;
@@ -460,7 +469,7 @@ struct cmd_ds_802_11_scan_rsp {
460 __le16 bssdescriptsize; 469 __le16 bssdescriptsize;
461 uint8_t nr_sets; 470 uint8_t nr_sets;
462 uint8_t bssdesc_and_tlvbuffer[0]; 471 uint8_t bssdesc_and_tlvbuffer[0];
463} __attribute__ ((packed)); 472} __packed;
464 473
465struct cmd_ds_802_11_get_log { 474struct cmd_ds_802_11_get_log {
466 struct cmd_header hdr; 475 struct cmd_header hdr;
@@ -478,20 +487,20 @@ struct cmd_ds_802_11_get_log {
478 __le32 fcserror; 487 __le32 fcserror;
479 __le32 txframe; 488 __le32 txframe;
480 __le32 wepundecryptable; 489 __le32 wepundecryptable;
481} __attribute__ ((packed)); 490} __packed;
482 491
483struct cmd_ds_mac_control { 492struct cmd_ds_mac_control {
484 struct cmd_header hdr; 493 struct cmd_header hdr;
485 __le16 action; 494 __le16 action;
486 u16 reserved; 495 u16 reserved;
487} __attribute__ ((packed)); 496} __packed;
488 497
489struct cmd_ds_mac_multicast_adr { 498struct cmd_ds_mac_multicast_adr {
490 struct cmd_header hdr; 499 struct cmd_header hdr;
491 __le16 action; 500 __le16 action;
492 __le16 nr_of_adrs; 501 __le16 nr_of_adrs;
493 u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; 502 u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
494} __attribute__ ((packed)); 503} __packed;
495 504
496struct cmd_ds_802_11_authenticate { 505struct cmd_ds_802_11_authenticate {
497 struct cmd_header hdr; 506 struct cmd_header hdr;
@@ -499,14 +508,14 @@ struct cmd_ds_802_11_authenticate {
499 u8 bssid[ETH_ALEN]; 508 u8 bssid[ETH_ALEN];
500 u8 authtype; 509 u8 authtype;
501 u8 reserved[10]; 510 u8 reserved[10];
502} __attribute__ ((packed)); 511} __packed;
503 512
504struct cmd_ds_802_11_deauthenticate { 513struct cmd_ds_802_11_deauthenticate {
505 struct cmd_header hdr; 514 struct cmd_header hdr;
506 515
507 u8 macaddr[ETH_ALEN]; 516 u8 macaddr[ETH_ALEN];
508 __le16 reasoncode; 517 __le16 reasoncode;
509} __attribute__ ((packed)); 518} __packed;
510 519
511struct cmd_ds_802_11_associate { 520struct cmd_ds_802_11_associate {
512 struct cmd_header hdr; 521 struct cmd_header hdr;
@@ -517,7 +526,7 @@ struct cmd_ds_802_11_associate {
517 __le16 bcnperiod; 526 __le16 bcnperiod;
518 u8 dtimperiod; 527 u8 dtimperiod;
519 u8 iebuf[512]; /* Enough for required and most optional IEs */ 528 u8 iebuf[512]; /* Enough for required and most optional IEs */
520} __attribute__ ((packed)); 529} __packed;
521 530
522struct cmd_ds_802_11_associate_response { 531struct cmd_ds_802_11_associate_response {
523 struct cmd_header hdr; 532 struct cmd_header hdr;
@@ -526,7 +535,7 @@ struct cmd_ds_802_11_associate_response {
526 __le16 statuscode; 535 __le16 statuscode;
527 __le16 aid; 536 __le16 aid;
528 u8 iebuf[512]; 537 u8 iebuf[512];
529} __attribute__ ((packed)); 538} __packed;
530 539
531struct cmd_ds_802_11_set_wep { 540struct cmd_ds_802_11_set_wep {
532 struct cmd_header hdr; 541 struct cmd_header hdr;
@@ -540,7 +549,7 @@ struct cmd_ds_802_11_set_wep {
540 /* 40, 128bit or TXWEP */ 549 /* 40, 128bit or TXWEP */
541 uint8_t keytype[4]; 550 uint8_t keytype[4];
542 uint8_t keymaterial[4][16]; 551 uint8_t keymaterial[4][16];
543} __attribute__ ((packed)); 552} __packed;
544 553
545struct cmd_ds_802_11_snmp_mib { 554struct cmd_ds_802_11_snmp_mib {
546 struct cmd_header hdr; 555 struct cmd_header hdr;
@@ -549,40 +558,33 @@ struct cmd_ds_802_11_snmp_mib {
549 __le16 oid; 558 __le16 oid;
550 __le16 bufsize; 559 __le16 bufsize;
551 u8 value[128]; 560 u8 value[128];
552} __attribute__ ((packed)); 561} __packed;
553
554struct cmd_ds_mac_reg_access {
555 __le16 action;
556 __le16 offset;
557 __le32 value;
558} __attribute__ ((packed));
559 562
560struct cmd_ds_bbp_reg_access { 563struct cmd_ds_reg_access {
561 __le16 action; 564 struct cmd_header hdr;
562 __le16 offset;
563 u8 value;
564 u8 reserved[3];
565} __attribute__ ((packed));
566 565
567struct cmd_ds_rf_reg_access {
568 __le16 action; 566 __le16 action;
569 __le16 offset; 567 __le16 offset;
570 u8 value; 568 union {
571 u8 reserved[3]; 569 u8 bbp_rf; /* for BBP and RF registers */
572} __attribute__ ((packed)); 570 __le32 mac; /* for MAC registers */
571 } value;
572} __packed;
573 573
574struct cmd_ds_802_11_radio_control { 574struct cmd_ds_802_11_radio_control {
575 struct cmd_header hdr; 575 struct cmd_header hdr;
576 576
577 __le16 action; 577 __le16 action;
578 __le16 control; 578 __le16 control;
579} __attribute__ ((packed)); 579} __packed;
580 580
581struct cmd_ds_802_11_beacon_control { 581struct cmd_ds_802_11_beacon_control {
582 struct cmd_header hdr;
583
582 __le16 action; 584 __le16 action;
583 __le16 beacon_enable; 585 __le16 beacon_enable;
584 __le16 beacon_period; 586 __le16 beacon_period;
585} __attribute__ ((packed)); 587} __packed;
586 588
587struct cmd_ds_802_11_sleep_params { 589struct cmd_ds_802_11_sleep_params {
588 struct cmd_header hdr; 590 struct cmd_header hdr;
@@ -607,7 +609,7 @@ struct cmd_ds_802_11_sleep_params {
607 609
608 /* reserved field, should be set to zero */ 610 /* reserved field, should be set to zero */
609 __le16 reserved; 611 __le16 reserved;
610} __attribute__ ((packed)); 612} __packed;
611 613
612struct cmd_ds_802_11_rf_channel { 614struct cmd_ds_802_11_rf_channel {
613 struct cmd_header hdr; 615 struct cmd_header hdr;
@@ -617,30 +619,30 @@ struct cmd_ds_802_11_rf_channel {
617 __le16 rftype; /* unused */ 619 __le16 rftype; /* unused */
618 __le16 reserved; /* unused */ 620 __le16 reserved; /* unused */
619 u8 channellist[32]; /* unused */ 621 u8 channellist[32]; /* unused */
620} __attribute__ ((packed)); 622} __packed;
621 623
622struct cmd_ds_802_11_rssi { 624struct cmd_ds_802_11_rssi {
623 /* weighting factor */ 625 struct cmd_header hdr;
624 __le16 N;
625 626
626 __le16 reserved_0; 627 /* request: number of beacons (N) to average the SNR and NF over
627 __le16 reserved_1; 628 * response: SNR of most recent beacon
628 __le16 reserved_2; 629 */
629} __attribute__ ((packed)); 630 __le16 n_or_snr;
630 631
631struct cmd_ds_802_11_rssi_rsp { 632 /* The following fields are only set in the response.
632 __le16 SNR; 633 * In the request these are reserved and should be set to 0.
633 __le16 noisefloor; 634 */
634 __le16 avgSNR; 635 __le16 nf; /* most recent beacon noise floor */
635 __le16 avgnoisefloor; 636 __le16 avg_snr; /* average SNR weighted by N from request */
636} __attribute__ ((packed)); 637 __le16 avg_nf; /* average noise floor weighted by N from request */
638} __packed;
637 639
638struct cmd_ds_802_11_mac_address { 640struct cmd_ds_802_11_mac_address {
639 struct cmd_header hdr; 641 struct cmd_header hdr;
640 642
641 __le16 action; 643 __le16 action;
642 u8 macadd[ETH_ALEN]; 644 u8 macadd[ETH_ALEN];
643} __attribute__ ((packed)); 645} __packed;
644 646
645struct cmd_ds_802_11_rf_tx_power { 647struct cmd_ds_802_11_rf_tx_power {
646 struct cmd_header hdr; 648 struct cmd_header hdr;
@@ -649,34 +651,61 @@ struct cmd_ds_802_11_rf_tx_power {
649 __le16 curlevel; 651 __le16 curlevel;
650 s8 maxlevel; 652 s8 maxlevel;
651 s8 minlevel; 653 s8 minlevel;
652} __attribute__ ((packed)); 654} __packed;
653 655
656/* MONITOR_MODE only exists in OLPC v5 firmware */
654struct cmd_ds_802_11_monitor_mode { 657struct cmd_ds_802_11_monitor_mode {
658 struct cmd_header hdr;
659
655 __le16 action; 660 __le16 action;
656 __le16 mode; 661 __le16 mode;
657} __attribute__ ((packed)); 662} __packed;
658 663
659struct cmd_ds_set_boot2_ver { 664struct cmd_ds_set_boot2_ver {
660 struct cmd_header hdr; 665 struct cmd_header hdr;
661 666
662 __le16 action; 667 __le16 action;
663 __le16 version; 668 __le16 version;
664} __attribute__ ((packed)); 669} __packed;
665 670
666struct cmd_ds_802_11_fw_wake_method { 671struct cmd_ds_802_11_fw_wake_method {
667 struct cmd_header hdr; 672 struct cmd_header hdr;
668 673
669 __le16 action; 674 __le16 action;
670 __le16 method; 675 __le16 method;
671} __attribute__ ((packed)); 676} __packed;
672 677
673struct cmd_ds_802_11_ps_mode { 678struct cmd_ds_802_11_ps_mode {
679 struct cmd_header hdr;
680
674 __le16 action; 681 __le16 action;
682
683 /* Interval for keepalive in PS mode:
684 * 0x0000 = don't change
685 * 0x001E = firmware default
686 * 0xFFFF = disable
687 */
675 __le16 nullpktinterval; 688 __le16 nullpktinterval;
689
690 /* Number of DTIM intervals to wake up for:
691 * 0 = don't change
692 * 1 = firmware default
693 * 5 = max
694 */
676 __le16 multipledtim; 695 __le16 multipledtim;
696
677 __le16 reserved; 697 __le16 reserved;
678 __le16 locallisteninterval; 698 __le16 locallisteninterval;
679} __attribute__ ((packed)); 699
700 /* AdHoc awake period (FW v9+ only):
701 * 0 = don't change
702 * 1 = always awake (IEEE standard behavior)
703 * 2 - 31 = sleep for (n - 1) periods and awake for 1 period
704 * 32 - 254 = invalid
705 * 255 = sleep at each ATIM
706 */
707 __le16 adhoc_awake_period;
708} __packed;
680 709
681struct cmd_confirm_sleep { 710struct cmd_confirm_sleep {
682 struct cmd_header hdr; 711 struct cmd_header hdr;
@@ -686,7 +715,7 @@ struct cmd_confirm_sleep {
686 __le16 multipledtim; 715 __le16 multipledtim;
687 __le16 reserved; 716 __le16 reserved;
688 __le16 locallisteninterval; 717 __le16 locallisteninterval;
689} __attribute__ ((packed)); 718} __packed;
690 719
691struct cmd_ds_802_11_data_rate { 720struct cmd_ds_802_11_data_rate {
692 struct cmd_header hdr; 721 struct cmd_header hdr;
@@ -694,14 +723,14 @@ struct cmd_ds_802_11_data_rate {
694 __le16 action; 723 __le16 action;
695 __le16 reserved; 724 __le16 reserved;
696 u8 rates[MAX_RATES]; 725 u8 rates[MAX_RATES];
697} __attribute__ ((packed)); 726} __packed;
698 727
699struct cmd_ds_802_11_rate_adapt_rateset { 728struct cmd_ds_802_11_rate_adapt_rateset {
700 struct cmd_header hdr; 729 struct cmd_header hdr;
701 __le16 action; 730 __le16 action;
702 __le16 enablehwauto; 731 __le16 enablehwauto;
703 __le16 bitmap; 732 __le16 bitmap;
704} __attribute__ ((packed)); 733} __packed;
705 734
706struct cmd_ds_802_11_ad_hoc_start { 735struct cmd_ds_802_11_ad_hoc_start {
707 struct cmd_header hdr; 736 struct cmd_header hdr;
@@ -718,14 +747,14 @@ struct cmd_ds_802_11_ad_hoc_start {
718 __le16 capability; 747 __le16 capability;
719 u8 rates[MAX_RATES]; 748 u8 rates[MAX_RATES];
720 u8 tlv_memory_size_pad[100]; 749 u8 tlv_memory_size_pad[100];
721} __attribute__ ((packed)); 750} __packed;
722 751
723struct cmd_ds_802_11_ad_hoc_result { 752struct cmd_ds_802_11_ad_hoc_result {
724 struct cmd_header hdr; 753 struct cmd_header hdr;
725 754
726 u8 pad[3]; 755 u8 pad[3];
727 u8 bssid[ETH_ALEN]; 756 u8 bssid[ETH_ALEN];
728} __attribute__ ((packed)); 757} __packed;
729 758
730struct adhoc_bssdesc { 759struct adhoc_bssdesc {
731 u8 bssid[ETH_ALEN]; 760 u8 bssid[ETH_ALEN];
@@ -746,7 +775,7 @@ struct adhoc_bssdesc {
746 * Adhoc join command and will cause a binary layout mismatch with 775 * Adhoc join command and will cause a binary layout mismatch with
747 * the firmware 776 * the firmware
748 */ 777 */
749} __attribute__ ((packed)); 778} __packed;
750 779
751struct cmd_ds_802_11_ad_hoc_join { 780struct cmd_ds_802_11_ad_hoc_join {
752 struct cmd_header hdr; 781 struct cmd_header hdr;
@@ -754,18 +783,18 @@ struct cmd_ds_802_11_ad_hoc_join {
754 struct adhoc_bssdesc bss; 783 struct adhoc_bssdesc bss;
755 __le16 failtimeout; /* Reserved on v9 and later */ 784 __le16 failtimeout; /* Reserved on v9 and later */
756 __le16 probedelay; /* Reserved on v9 and later */ 785 __le16 probedelay; /* Reserved on v9 and later */
757} __attribute__ ((packed)); 786} __packed;
758 787
759struct cmd_ds_802_11_ad_hoc_stop { 788struct cmd_ds_802_11_ad_hoc_stop {
760 struct cmd_header hdr; 789 struct cmd_header hdr;
761} __attribute__ ((packed)); 790} __packed;
762 791
763struct cmd_ds_802_11_enable_rsn { 792struct cmd_ds_802_11_enable_rsn {
764 struct cmd_header hdr; 793 struct cmd_header hdr;
765 794
766 __le16 action; 795 __le16 action;
767 __le16 enable; 796 __le16 enable;
768} __attribute__ ((packed)); 797} __packed;
769 798
770struct MrvlIEtype_keyParamSet { 799struct MrvlIEtype_keyParamSet {
771 /* type ID */ 800 /* type ID */
@@ -785,7 +814,7 @@ struct MrvlIEtype_keyParamSet {
785 814
786 /* key material of size keylen */ 815 /* key material of size keylen */
787 u8 key[32]; 816 u8 key[32];
788} __attribute__ ((packed)); 817} __packed;
789 818
790#define MAX_WOL_RULES 16 819#define MAX_WOL_RULES 16
791 820
@@ -797,7 +826,7 @@ struct host_wol_rule {
797 __le16 reserve; 826 __le16 reserve;
798 __be32 sig_mask; 827 __be32 sig_mask;
799 __be32 signature; 828 __be32 signature;
800} __attribute__ ((packed)); 829} __packed;
801 830
802struct wol_config { 831struct wol_config {
803 uint8_t action; 832 uint8_t action;
@@ -805,7 +834,7 @@ struct wol_config {
805 uint8_t no_rules_in_cmd; 834 uint8_t no_rules_in_cmd;
806 uint8_t result; 835 uint8_t result;
807 struct host_wol_rule rule[MAX_WOL_RULES]; 836 struct host_wol_rule rule[MAX_WOL_RULES];
808} __attribute__ ((packed)); 837} __packed;
809 838
810struct cmd_ds_host_sleep { 839struct cmd_ds_host_sleep {
811 struct cmd_header hdr; 840 struct cmd_header hdr;
@@ -813,7 +842,7 @@ struct cmd_ds_host_sleep {
813 uint8_t gpio; 842 uint8_t gpio;
814 uint16_t gap; 843 uint16_t gap;
815 struct wol_config wol_conf; 844 struct wol_config wol_conf;
816} __attribute__ ((packed)); 845} __packed;
817 846
818 847
819 848
@@ -822,7 +851,7 @@ struct cmd_ds_802_11_key_material {
822 851
823 __le16 action; 852 __le16 action;
824 struct MrvlIEtype_keyParamSet keyParamSet[2]; 853 struct MrvlIEtype_keyParamSet keyParamSet[2];
825} __attribute__ ((packed)); 854} __packed;
826 855
827struct cmd_ds_802_11_eeprom_access { 856struct cmd_ds_802_11_eeprom_access {
828 struct cmd_header hdr; 857 struct cmd_header hdr;
@@ -832,7 +861,7 @@ struct cmd_ds_802_11_eeprom_access {
832 /* firmware says it returns a maximum of 20 bytes */ 861 /* firmware says it returns a maximum of 20 bytes */
833#define LBS_EEPROM_READ_LEN 20 862#define LBS_EEPROM_READ_LEN 20
834 u8 value[LBS_EEPROM_READ_LEN]; 863 u8 value[LBS_EEPROM_READ_LEN];
835} __attribute__ ((packed)); 864} __packed;
836 865
837struct cmd_ds_802_11_tpc_cfg { 866struct cmd_ds_802_11_tpc_cfg {
838 struct cmd_header hdr; 867 struct cmd_header hdr;
@@ -843,7 +872,7 @@ struct cmd_ds_802_11_tpc_cfg {
843 int8_t P1; 872 int8_t P1;
844 int8_t P2; 873 int8_t P2;
845 uint8_t usesnr; 874 uint8_t usesnr;
846} __attribute__ ((packed)); 875} __packed;
847 876
848 877
849struct cmd_ds_802_11_pa_cfg { 878struct cmd_ds_802_11_pa_cfg {
@@ -854,16 +883,21 @@ struct cmd_ds_802_11_pa_cfg {
854 int8_t P0; 883 int8_t P0;
855 int8_t P1; 884 int8_t P1;
856 int8_t P2; 885 int8_t P2;
857} __attribute__ ((packed)); 886} __packed;
858 887
859 888
860struct cmd_ds_802_11_led_ctrl { 889struct cmd_ds_802_11_led_ctrl {
890 struct cmd_header hdr;
891
861 __le16 action; 892 __le16 action;
862 __le16 numled; 893 __le16 numled;
863 u8 data[256]; 894 u8 data[256];
864} __attribute__ ((packed)); 895} __packed;
865 896
897/* Automatic Frequency Control */
866struct cmd_ds_802_11_afc { 898struct cmd_ds_802_11_afc {
899 struct cmd_header hdr;
900
867 __le16 afc_auto; 901 __le16 afc_auto;
868 union { 902 union {
869 struct { 903 struct {
@@ -875,24 +909,28 @@ struct cmd_ds_802_11_afc {
875 __le16 carrier_offset; /* signed */ 909 __le16 carrier_offset; /* signed */
876 }; 910 };
877 }; 911 };
878} __attribute__ ((packed)); 912} __packed;
879 913
880struct cmd_tx_rate_query { 914struct cmd_tx_rate_query {
881 __le16 txrate; 915 __le16 txrate;
882} __attribute__ ((packed)); 916} __packed;
883 917
884struct cmd_ds_get_tsf { 918struct cmd_ds_get_tsf {
885 __le64 tsfvalue; 919 __le64 tsfvalue;
886} __attribute__ ((packed)); 920} __packed;
887 921
888struct cmd_ds_bt_access { 922struct cmd_ds_bt_access {
923 struct cmd_header hdr;
924
889 __le16 action; 925 __le16 action;
890 __le32 id; 926 __le32 id;
891 u8 addr1[ETH_ALEN]; 927 u8 addr1[ETH_ALEN];
892 u8 addr2[ETH_ALEN]; 928 u8 addr2[ETH_ALEN];
893} __attribute__ ((packed)); 929} __packed;
894 930
895struct cmd_ds_fwt_access { 931struct cmd_ds_fwt_access {
932 struct cmd_header hdr;
933
896 __le16 action; 934 __le16 action;
897 __le32 id; 935 __le32 id;
898 u8 valid; 936 u8 valid;
@@ -910,7 +948,7 @@ struct cmd_ds_fwt_access {
910 __le32 snr; 948 __le32 snr;
911 __le32 references; 949 __le32 references;
912 u8 prec[ETH_ALEN]; 950 u8 prec[ETH_ALEN];
913} __attribute__ ((packed)); 951} __packed;
914 952
915struct cmd_ds_mesh_config { 953struct cmd_ds_mesh_config {
916 struct cmd_header hdr; 954 struct cmd_header hdr;
@@ -920,43 +958,15 @@ struct cmd_ds_mesh_config {
920 __le16 type; 958 __le16 type;
921 __le16 length; 959 __le16 length;
922 u8 data[128]; /* last position reserved */ 960 u8 data[128]; /* last position reserved */
923} __attribute__ ((packed)); 961} __packed;
924 962
925struct cmd_ds_mesh_access { 963struct cmd_ds_mesh_access {
926 struct cmd_header hdr; 964 struct cmd_header hdr;
927 965
928 __le16 action; 966 __le16 action;
929 __le32 data[32]; /* last position reserved */ 967 __le32 data[32]; /* last position reserved */
930} __attribute__ ((packed)); 968} __packed;
931 969
932/* Number of stats counters returned by the firmware */ 970/* Number of stats counters returned by the firmware */
933#define MESH_STATS_NUM 8 971#define MESH_STATS_NUM 8
934
935struct cmd_ds_command {
936 /* command header */
937 __le16 command;
938 __le16 size;
939 __le16 seqnum;
940 __le16 result;
941
942 /* command Body */
943 union {
944 struct cmd_ds_802_11_ps_mode psmode;
945 struct cmd_ds_802_11_monitor_mode monitor;
946 struct cmd_ds_802_11_rssi rssi;
947 struct cmd_ds_802_11_rssi_rsp rssirsp;
948 struct cmd_ds_mac_reg_access macreg;
949 struct cmd_ds_bbp_reg_access bbpreg;
950 struct cmd_ds_rf_reg_access rfreg;
951
952 struct cmd_ds_802_11_tpc_cfg tpccfg;
953 struct cmd_ds_802_11_afc afc;
954 struct cmd_ds_802_11_led_ctrl ledgpio;
955
956 struct cmd_ds_bt_access bt;
957 struct cmd_ds_fwt_access fwt;
958 struct cmd_ds_802_11_beacon_control bcn_ctrl;
959 } params;
960} __attribute__ ((packed));
961
962#endif 972#endif
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 64dd345d30f5..6e71346a7550 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -1182,11 +1182,69 @@ static void if_sdio_remove(struct sdio_func *func)
1182 lbs_deb_leave(LBS_DEB_SDIO); 1182 lbs_deb_leave(LBS_DEB_SDIO);
1183} 1183}
1184 1184
1185static int if_sdio_suspend(struct device *dev)
1186{
1187 struct sdio_func *func = dev_to_sdio_func(dev);
1188 int ret;
1189 struct if_sdio_card *card = sdio_get_drvdata(func);
1190
1191 mmc_pm_flag_t flags = sdio_get_host_pm_caps(func);
1192
1193 lbs_pr_info("%s: suspend: PM flags = 0x%x\n",
1194 sdio_func_id(func), flags);
1195
1196 /* If we aren't being asked to wake on anything, we should bail out
1197 * and let the SD stack power down the card.
1198 */
1199 if (card->priv->wol_criteria == EHS_REMOVE_WAKEUP) {
1200 lbs_pr_info("Suspend without wake params -- "
1201 "powering down card.");
1202 return -ENOSYS;
1203 }
1204
1205 if (!(flags & MMC_PM_KEEP_POWER)) {
1206 lbs_pr_err("%s: cannot remain alive while host is suspended\n",
1207 sdio_func_id(func));
1208 return -ENOSYS;
1209 }
1210
1211 ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
1212 if (ret)
1213 return ret;
1214
1215 ret = lbs_suspend(card->priv);
1216 if (ret)
1217 return ret;
1218
1219 return sdio_set_host_pm_flags(func, MMC_PM_WAKE_SDIO_IRQ);
1220}
1221
1222static int if_sdio_resume(struct device *dev)
1223{
1224 struct sdio_func *func = dev_to_sdio_func(dev);
1225 struct if_sdio_card *card = sdio_get_drvdata(func);
1226 int ret;
1227
1228 lbs_pr_info("%s: resume: we're back\n", sdio_func_id(func));
1229
1230 ret = lbs_resume(card->priv);
1231
1232 return ret;
1233}
1234
1235static const struct dev_pm_ops if_sdio_pm_ops = {
1236 .suspend = if_sdio_suspend,
1237 .resume = if_sdio_resume,
1238};
1239
1185static struct sdio_driver if_sdio_driver = { 1240static struct sdio_driver if_sdio_driver = {
1186 .name = "libertas_sdio", 1241 .name = "libertas_sdio",
1187 .id_table = if_sdio_ids, 1242 .id_table = if_sdio_ids,
1188 .probe = if_sdio_probe, 1243 .probe = if_sdio_probe,
1189 .remove = if_sdio_remove, 1244 .remove = if_sdio_remove,
1245 .drv = {
1246 .pm = &if_sdio_pm_ops,
1247 },
1190}; 1248};
1191 1249
1192/*******************************************************************/ 1250/*******************************************************************/
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index f41594c7ac16..07ece9d26c63 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -433,7 +433,7 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp)
433 433
434static int if_usb_reset_device(struct if_usb_card *cardp) 434static int if_usb_reset_device(struct if_usb_card *cardp)
435{ 435{
436 struct cmd_ds_command *cmd = cardp->ep_out_buf + 4; 436 struct cmd_header *cmd = cardp->ep_out_buf + 4;
437 int ret; 437 int ret;
438 438
439 lbs_deb_enter(LBS_DEB_USB); 439 lbs_deb_enter(LBS_DEB_USB);
@@ -441,7 +441,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp)
441 *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST); 441 *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST);
442 442
443 cmd->command = cpu_to_le16(CMD_802_11_RESET); 443 cmd->command = cpu_to_le16(CMD_802_11_RESET);
444 cmd->size = cpu_to_le16(sizeof(struct cmd_header)); 444 cmd->size = cpu_to_le16(sizeof(cmd));
445 cmd->result = cpu_to_le16(0); 445 cmd->result = cpu_to_le16(0);
446 cmd->seqnum = cpu_to_le16(0x5a5a); 446 cmd->seqnum = cpu_to_le16(0x5a5a);
447 usb_tx_block(cardp, cardp->ep_out_buf, 4 + sizeof(struct cmd_header)); 447 usb_tx_block(cardp, cardp->ep_out_buf, 4 + sizeof(struct cmd_header));
@@ -613,16 +613,14 @@ static void if_usb_receive_fwload(struct urb *urb)
613 return; 613 return;
614 } 614 }
615 615
616 syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC); 616 syncfwheader = kmemdup(skb->data + IPFIELD_ALIGN_OFFSET,
617 sizeof(struct fwsyncheader), GFP_ATOMIC);
617 if (!syncfwheader) { 618 if (!syncfwheader) {
618 lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); 619 lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n");
619 kfree_skb(skb); 620 kfree_skb(skb);
620 return; 621 return;
621 } 622 }
622 623
623 memcpy(syncfwheader, skb->data + IPFIELD_ALIGN_OFFSET,
624 sizeof(struct fwsyncheader));
625
626 if (!syncfwheader->cmd) { 624 if (!syncfwheader->cmd) {
627 lbs_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); 625 lbs_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n");
628 lbs_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", 626 lbs_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n",
@@ -1043,6 +1041,12 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
1043 if (priv->psstate != PS_STATE_FULL_POWER) 1041 if (priv->psstate != PS_STATE_FULL_POWER)
1044 return -1; 1042 return -1;
1045 1043
1044 if (priv->wol_criteria == EHS_REMOVE_WAKEUP) {
1045 lbs_pr_info("Suspend attempt without "
1046 "configuring wake params!\n");
1047 return -ENOSYS;
1048 }
1049
1046 ret = lbs_suspend(priv); 1050 ret = lbs_suspend(priv);
1047 if (ret) 1051 if (ret)
1048 goto out; 1052 goto out;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index d9b8ee130c45..258967144b96 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -11,20 +11,14 @@
11#include <linux/if_arp.h> 11#include <linux/if_arp.h>
12#include <linux/kthread.h> 12#include <linux/kthread.h>
13#include <linux/kfifo.h> 13#include <linux/kfifo.h>
14#include <linux/stddef.h>
15#include <linux/ieee80211.h>
16#include <linux/slab.h> 14#include <linux/slab.h>
17#include <net/iw_handler.h>
18#include <net/cfg80211.h> 15#include <net/cfg80211.h>
19 16
20#include "host.h" 17#include "host.h"
21#include "decl.h" 18#include "decl.h"
22#include "dev.h" 19#include "dev.h"
23#include "wext.h"
24#include "cfg.h" 20#include "cfg.h"
25#include "debugfs.h" 21#include "debugfs.h"
26#include "scan.h"
27#include "assoc.h"
28#include "cmd.h" 22#include "cmd.h"
29 23
30#define DRIVER_RELEASE_VERSION "323.p0" 24#define DRIVER_RELEASE_VERSION "323.p0"
@@ -96,72 +90,6 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
96} 90}
97 91
98 92
99static int lbs_add_rtap(struct lbs_private *priv);
100static void lbs_remove_rtap(struct lbs_private *priv);
101
102
103/**
104 * Get function for sysfs attribute rtap
105 */
106static ssize_t lbs_rtap_get(struct device *dev,
107 struct device_attribute *attr, char * buf)
108{
109 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
110 return snprintf(buf, 5, "0x%X\n", priv->monitormode);
111}
112
113/**
114 * Set function for sysfs attribute rtap
115 */
116static ssize_t lbs_rtap_set(struct device *dev,
117 struct device_attribute *attr, const char * buf, size_t count)
118{
119 int monitor_mode;
120 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
121
122 sscanf(buf, "%x", &monitor_mode);
123 if (monitor_mode) {
124 if (priv->monitormode == monitor_mode)
125 return strlen(buf);
126 if (!priv->monitormode) {
127 if (priv->infra_open || lbs_mesh_open(priv))
128 return -EBUSY;
129 if (priv->mode == IW_MODE_INFRA)
130 lbs_cmd_80211_deauthenticate(priv,
131 priv->curbssparams.bssid,
132 WLAN_REASON_DEAUTH_LEAVING);
133 else if (priv->mode == IW_MODE_ADHOC)
134 lbs_adhoc_stop(priv);
135 lbs_add_rtap(priv);
136 }
137 priv->monitormode = monitor_mode;
138 } else {
139 if (!priv->monitormode)
140 return strlen(buf);
141 priv->monitormode = 0;
142 lbs_remove_rtap(priv);
143
144 if (priv->currenttxskb) {
145 dev_kfree_skb_any(priv->currenttxskb);
146 priv->currenttxskb = NULL;
147 }
148
149 /* Wake queues, command thread, etc. */
150 lbs_host_to_card_done(priv);
151 }
152
153 lbs_prepare_and_send_command(priv,
154 CMD_802_11_MONITOR_MODE, CMD_ACT_SET,
155 CMD_OPTION_WAITFORRSP, 0, &priv->monitormode);
156 return strlen(buf);
157}
158
159/**
160 * lbs_rtap attribute to be exported per ethX interface
161 * through sysfs (/sys/class/net/ethX/lbs_rtap)
162 */
163static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set );
164
165/** 93/**
166 * @brief This function opens the ethX interface 94 * @brief This function opens the ethX interface
167 * 95 *
@@ -177,13 +105,6 @@ static int lbs_dev_open(struct net_device *dev)
177 105
178 spin_lock_irq(&priv->driver_lock); 106 spin_lock_irq(&priv->driver_lock);
179 107
180 if (priv->monitormode) {
181 ret = -EBUSY;
182 goto out;
183 }
184
185 priv->infra_open = 1;
186
187 if (priv->connect_status == LBS_CONNECTED) 108 if (priv->connect_status == LBS_CONNECTED)
188 netif_carrier_on(dev); 109 netif_carrier_on(dev);
189 else 110 else
@@ -191,7 +112,6 @@ static int lbs_dev_open(struct net_device *dev)
191 112
192 if (!priv->tx_pending_len) 113 if (!priv->tx_pending_len)
193 netif_wake_queue(dev); 114 netif_wake_queue(dev);
194 out:
195 115
196 spin_unlock_irq(&priv->driver_lock); 116 spin_unlock_irq(&priv->driver_lock);
197 lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); 117 lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
@@ -211,7 +131,6 @@ static int lbs_eth_stop(struct net_device *dev)
211 lbs_deb_enter(LBS_DEB_NET); 131 lbs_deb_enter(LBS_DEB_NET);
212 132
213 spin_lock_irq(&priv->driver_lock); 133 spin_lock_irq(&priv->driver_lock);
214 priv->infra_open = 0;
215 netif_stop_queue(dev); 134 netif_stop_queue(dev);
216 spin_unlock_irq(&priv->driver_lock); 135 spin_unlock_irq(&priv->driver_lock);
217 136
@@ -238,12 +157,7 @@ static void lbs_tx_timeout(struct net_device *dev)
238 to kick it somehow? */ 157 to kick it somehow? */
239 lbs_host_to_card_done(priv); 158 lbs_host_to_card_done(priv);
240 159
241 /* More often than not, this actually happens because the 160 /* FIXME: reset the card */
242 firmware has crapped itself -- rather than just a very
243 busy medium. So send a harmless command, and if/when
244 _that_ times out, we'll kick it in the head. */
245 lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
246 0, 0, NULL);
247 161
248 lbs_deb_leave(LBS_DEB_TX); 162 lbs_deb_leave(LBS_DEB_TX);
249} 163}
@@ -588,12 +502,6 @@ static int lbs_thread(void *data)
588 if (!priv->dnld_sent && !priv->cur_cmd) 502 if (!priv->dnld_sent && !priv->cur_cmd)
589 lbs_execute_next_command(priv); 503 lbs_execute_next_command(priv);
590 504
591 /* Wake-up command waiters which can't sleep in
592 * lbs_prepare_and_send_command
593 */
594 if (!list_empty(&priv->cmdpendingq))
595 wake_up_all(&priv->cmd_pending);
596
597 spin_lock_irq(&priv->driver_lock); 505 spin_lock_irq(&priv->driver_lock);
598 if (!priv->dnld_sent && priv->tx_pending_len > 0) { 506 if (!priv->dnld_sent && priv->tx_pending_len > 0) {
599 int ret = priv->hw_host_to_card(priv, MVMS_DAT, 507 int ret = priv->hw_host_to_card(priv, MVMS_DAT,
@@ -619,66 +527,58 @@ static int lbs_thread(void *data)
619 527
620 del_timer(&priv->command_timer); 528 del_timer(&priv->command_timer);
621 del_timer(&priv->auto_deepsleep_timer); 529 del_timer(&priv->auto_deepsleep_timer);
622 wake_up_all(&priv->cmd_pending);
623 530
624 lbs_deb_leave(LBS_DEB_THREAD); 531 lbs_deb_leave(LBS_DEB_THREAD);
625 return 0; 532 return 0;
626} 533}
627 534
628static int lbs_suspend_callback(struct lbs_private *priv, unsigned long dummy,
629 struct cmd_header *cmd)
630{
631 lbs_deb_enter(LBS_DEB_FW);
632
633 netif_device_detach(priv->dev);
634 if (priv->mesh_dev)
635 netif_device_detach(priv->mesh_dev);
636
637 priv->fw_ready = 0;
638 lbs_deb_leave(LBS_DEB_FW);
639 return 0;
640}
641
642int lbs_suspend(struct lbs_private *priv) 535int lbs_suspend(struct lbs_private *priv)
643{ 536{
644 struct cmd_header cmd;
645 int ret; 537 int ret;
646 538
647 lbs_deb_enter(LBS_DEB_FW); 539 lbs_deb_enter(LBS_DEB_FW);
648 540
649 if (priv->wol_criteria == 0xffffffff) { 541 if (priv->is_deep_sleep) {
650 lbs_pr_info("Suspend attempt without configuring wake params!\n"); 542 ret = lbs_set_deep_sleep(priv, 0);
651 return -EINVAL; 543 if (ret) {
544 lbs_pr_err("deep sleep cancellation failed: %d\n", ret);
545 return ret;
546 }
547 priv->deep_sleep_required = 1;
652 } 548 }
653 549
654 memset(&cmd, 0, sizeof(cmd)); 550 ret = lbs_set_host_sleep(priv, 1);
655 551
656 ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd, 552 netif_device_detach(priv->dev);
657 sizeof(cmd), lbs_suspend_callback, 0); 553 if (priv->mesh_dev)
658 if (ret) 554 netif_device_detach(priv->mesh_dev);
659 lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret);
660 555
661 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); 556 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
662 return ret; 557 return ret;
663} 558}
664EXPORT_SYMBOL_GPL(lbs_suspend); 559EXPORT_SYMBOL_GPL(lbs_suspend);
665 560
666void lbs_resume(struct lbs_private *priv) 561int lbs_resume(struct lbs_private *priv)
667{ 562{
668 lbs_deb_enter(LBS_DEB_FW); 563 int ret;
669 564
670 priv->fw_ready = 1; 565 lbs_deb_enter(LBS_DEB_FW);
671 566
672 /* Firmware doesn't seem to give us RX packets any more 567 ret = lbs_set_host_sleep(priv, 0);
673 until we send it some command. Might as well update */
674 lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
675 0, 0, NULL);
676 568
677 netif_device_attach(priv->dev); 569 netif_device_attach(priv->dev);
678 if (priv->mesh_dev) 570 if (priv->mesh_dev)
679 netif_device_attach(priv->mesh_dev); 571 netif_device_attach(priv->mesh_dev);
680 572
681 lbs_deb_leave(LBS_DEB_FW); 573 if (priv->deep_sleep_required) {
574 priv->deep_sleep_required = 0;
575 ret = lbs_set_deep_sleep(priv, 1);
576 if (ret)
577 lbs_pr_err("deep sleep activation failed: %d\n", ret);
578 }
579
580 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
581 return ret;
682} 582}
683EXPORT_SYMBOL_GPL(lbs_resume); 583EXPORT_SYMBOL_GPL(lbs_resume);
684 584
@@ -710,6 +610,9 @@ static int lbs_setup_firmware(struct lbs_private *priv)
710 priv->txpower_max = maxlevel; 610 priv->txpower_max = maxlevel;
711 } 611 }
712 612
613 /* Send cmd to FW to enable 11D function */
614 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1);
615
713 lbs_set_mac_control(priv); 616 lbs_set_mac_control(priv);
714done: 617done:
715 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); 618 lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
@@ -748,7 +651,6 @@ out:
748static void auto_deepsleep_timer_fn(unsigned long data) 651static void auto_deepsleep_timer_fn(unsigned long data)
749{ 652{
750 struct lbs_private *priv = (struct lbs_private *)data; 653 struct lbs_private *priv = (struct lbs_private *)data;
751 int ret;
752 654
753 lbs_deb_enter(LBS_DEB_CMD); 655 lbs_deb_enter(LBS_DEB_CMD);
754 656
@@ -756,14 +658,15 @@ static void auto_deepsleep_timer_fn(unsigned long data)
756 priv->is_activity_detected = 0; 658 priv->is_activity_detected = 0;
757 } else { 659 } else {
758 if (priv->is_auto_deep_sleep_enabled && 660 if (priv->is_auto_deep_sleep_enabled &&
759 (!priv->wakeup_dev_required) && 661 (!priv->wakeup_dev_required) &&
760 (priv->connect_status != LBS_CONNECTED)) { 662 (priv->connect_status != LBS_CONNECTED)) {
663 struct cmd_header cmd;
664
761 lbs_deb_main("Entering auto deep sleep mode...\n"); 665 lbs_deb_main("Entering auto deep sleep mode...\n");
762 ret = lbs_prepare_and_send_command(priv, 666 memset(&cmd, 0, sizeof(cmd));
763 CMD_802_11_DEEP_SLEEP, 0, 667 cmd.size = cpu_to_le16(sizeof(cmd));
764 0, 0, NULL); 668 lbs_cmd_async(priv, CMD_802_11_DEEP_SLEEP, &cmd,
765 if (ret) 669 sizeof(cmd));
766 lbs_pr_err("Enter Deep Sleep command failed\n");
767 } 670 }
768 } 671 }
769 mod_timer(&priv->auto_deepsleep_timer , jiffies + 672 mod_timer(&priv->auto_deepsleep_timer , jiffies +
@@ -799,45 +702,27 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv)
799 702
800static int lbs_init_adapter(struct lbs_private *priv) 703static int lbs_init_adapter(struct lbs_private *priv)
801{ 704{
802 size_t bufsize; 705 int ret;
803 int i, ret = 0;
804 706
805 lbs_deb_enter(LBS_DEB_MAIN); 707 lbs_deb_enter(LBS_DEB_MAIN);
806 708
807 /* Allocate buffer to store the BSSID list */
808 bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor);
809 priv->networks = kzalloc(bufsize, GFP_KERNEL);
810 if (!priv->networks) {
811 lbs_pr_err("Out of memory allocating beacons\n");
812 ret = -1;
813 goto out;
814 }
815
816 /* Initialize scan result lists */
817 INIT_LIST_HEAD(&priv->network_free_list);
818 INIT_LIST_HEAD(&priv->network_list);
819 for (i = 0; i < MAX_NETWORK_COUNT; i++) {
820 list_add_tail(&priv->networks[i].list,
821 &priv->network_free_list);
822 }
823
824 memset(priv->current_addr, 0xff, ETH_ALEN); 709 memset(priv->current_addr, 0xff, ETH_ALEN);
825 710
826 priv->connect_status = LBS_DISCONNECTED; 711 priv->connect_status = LBS_DISCONNECTED;
827 priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
828 priv->mode = IW_MODE_INFRA;
829 priv->channel = DEFAULT_AD_HOC_CHANNEL; 712 priv->channel = DEFAULT_AD_HOC_CHANNEL;
830 priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; 713 priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON;
831 priv->radio_on = 1; 714 priv->radio_on = 1;
832 priv->enablehwauto = 1;
833 priv->psmode = LBS802_11POWERMODECAM; 715 priv->psmode = LBS802_11POWERMODECAM;
834 priv->psstate = PS_STATE_FULL_POWER; 716 priv->psstate = PS_STATE_FULL_POWER;
835 priv->is_deep_sleep = 0; 717 priv->is_deep_sleep = 0;
836 priv->is_auto_deep_sleep_enabled = 0; 718 priv->is_auto_deep_sleep_enabled = 0;
719 priv->deep_sleep_required = 0;
837 priv->wakeup_dev_required = 0; 720 priv->wakeup_dev_required = 0;
838 init_waitqueue_head(&priv->ds_awake_q); 721 init_waitqueue_head(&priv->ds_awake_q);
839 priv->authtype_auto = 1; 722 priv->authtype_auto = 1;
840 723 priv->is_host_sleep_configured = 0;
724 priv->is_host_sleep_activated = 0;
725 init_waitqueue_head(&priv->host_sleep_q);
841 mutex_init(&priv->lock); 726 mutex_init(&priv->lock);
842 727
843 setup_timer(&priv->command_timer, lbs_cmd_timeout_handler, 728 setup_timer(&priv->command_timer, lbs_cmd_timeout_handler,
@@ -849,7 +734,6 @@ static int lbs_init_adapter(struct lbs_private *priv)
849 INIT_LIST_HEAD(&priv->cmdpendingq); 734 INIT_LIST_HEAD(&priv->cmdpendingq);
850 735
851 spin_lock_init(&priv->driver_lock); 736 spin_lock_init(&priv->driver_lock);
852 init_waitqueue_head(&priv->cmd_pending);
853 737
854 /* Allocate the command buffers */ 738 /* Allocate the command buffers */
855 if (lbs_allocate_cmd_buffer(priv)) { 739 if (lbs_allocate_cmd_buffer(priv)) {
@@ -881,8 +765,6 @@ static void lbs_free_adapter(struct lbs_private *priv)
881 kfifo_free(&priv->event_fifo); 765 kfifo_free(&priv->event_fifo);
882 del_timer(&priv->command_timer); 766 del_timer(&priv->command_timer);
883 del_timer(&priv->auto_deepsleep_timer); 767 del_timer(&priv->auto_deepsleep_timer);
884 kfree(priv->networks);
885 priv->networks = NULL;
886 768
887 lbs_deb_leave(LBS_DEB_MAIN); 769 lbs_deb_leave(LBS_DEB_MAIN);
888} 770}
@@ -919,7 +801,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
919 lbs_pr_err("cfg80211 init failed\n"); 801 lbs_pr_err("cfg80211 init failed\n");
920 goto done; 802 goto done;
921 } 803 }
922 /* TODO? */ 804
923 wdev->iftype = NL80211_IFTYPE_STATION; 805 wdev->iftype = NL80211_IFTYPE_STATION;
924 priv = wdev_priv(wdev); 806 priv = wdev_priv(wdev);
925 priv->wdev = wdev; 807 priv->wdev = wdev;
@@ -929,7 +811,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
929 goto err_wdev; 811 goto err_wdev;
930 } 812 }
931 813
932 //TODO? dev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES);
933 dev = alloc_netdev(0, "wlan%d", ether_setup); 814 dev = alloc_netdev(0, "wlan%d", ether_setup);
934 if (!dev) { 815 if (!dev) {
935 dev_err(dmdev, "no memory for network device instance\n"); 816 dev_err(dmdev, "no memory for network device instance\n");
@@ -945,20 +826,10 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
945 dev->netdev_ops = &lbs_netdev_ops; 826 dev->netdev_ops = &lbs_netdev_ops;
946 dev->watchdog_timeo = 5 * HZ; 827 dev->watchdog_timeo = 5 * HZ;
947 dev->ethtool_ops = &lbs_ethtool_ops; 828 dev->ethtool_ops = &lbs_ethtool_ops;
948#ifdef WIRELESS_EXT
949 dev->wireless_handlers = &lbs_handler_def;
950#endif
951 dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 829 dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
952 830
953
954 // TODO: kzalloc + iwm_init_default_profile(iwm, iwm->umac_profile); ??
955
956
957 priv->card = card; 831 priv->card = card;
958 priv->infra_open = 0;
959 832
960
961 priv->rtap_net_dev = NULL;
962 strcpy(dev->name, "wlan%d"); 833 strcpy(dev->name, "wlan%d");
963 834
964 lbs_deb_thread("Starting main thread...\n"); 835 lbs_deb_thread("Starting main thread...\n");
@@ -970,12 +841,11 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
970 } 841 }
971 842
972 priv->work_thread = create_singlethread_workqueue("lbs_worker"); 843 priv->work_thread = create_singlethread_workqueue("lbs_worker");
973 INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker);
974 INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker);
975 INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); 844 INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
976 845
977 priv->wol_criteria = 0xffffffff; 846 priv->wol_criteria = 0xffffffff;
978 priv->wol_gpio = 0xff; 847 priv->wol_gpio = 0xff;
848 priv->wol_gap = 20;
979 849
980 goto done; 850 goto done;
981 851
@@ -1004,12 +874,10 @@ void lbs_remove_card(struct lbs_private *priv)
1004 lbs_deb_enter(LBS_DEB_MAIN); 874 lbs_deb_enter(LBS_DEB_MAIN);
1005 875
1006 lbs_remove_mesh(priv); 876 lbs_remove_mesh(priv);
1007 lbs_remove_rtap(priv); 877 lbs_scan_deinit(priv);
1008 878
1009 dev = priv->dev; 879 dev = priv->dev;
1010 880
1011 cancel_delayed_work_sync(&priv->scan_work);
1012 cancel_delayed_work_sync(&priv->assoc_work);
1013 cancel_work_sync(&priv->mcast_work); 881 cancel_work_sync(&priv->mcast_work);
1014 882
1015 /* worker thread destruction blocks on the in-flight command which 883 /* worker thread destruction blocks on the in-flight command which
@@ -1021,16 +889,18 @@ void lbs_remove_card(struct lbs_private *priv)
1021 889
1022 if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { 890 if (priv->psmode == LBS802_11POWERMODEMAX_PSP) {
1023 priv->psmode = LBS802_11POWERMODECAM; 891 priv->psmode = LBS802_11POWERMODECAM;
1024 lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); 892 lbs_set_ps_mode(priv, PS_MODE_ACTION_EXIT_PS, true);
1025 } 893 }
1026 894
1027 lbs_send_disconnect_notification(priv);
1028
1029 if (priv->is_deep_sleep) { 895 if (priv->is_deep_sleep) {
1030 priv->is_deep_sleep = 0; 896 priv->is_deep_sleep = 0;
1031 wake_up_interruptible(&priv->ds_awake_q); 897 wake_up_interruptible(&priv->ds_awake_q);
1032 } 898 }
1033 899
900 priv->is_host_sleep_configured = 0;
901 priv->is_host_sleep_activated = 0;
902 wake_up_interruptible(&priv->host_sleep_q);
903
1034 /* Stop the thread servicing the interrupts */ 904 /* Stop the thread servicing the interrupts */
1035 priv->surpriseremoved = 1; 905 priv->surpriseremoved = 1;
1036 kthread_stop(priv->main_thread); 906 kthread_stop(priv->main_thread);
@@ -1046,7 +916,7 @@ void lbs_remove_card(struct lbs_private *priv)
1046EXPORT_SYMBOL_GPL(lbs_remove_card); 916EXPORT_SYMBOL_GPL(lbs_remove_card);
1047 917
1048 918
1049static int lbs_rtap_supported(struct lbs_private *priv) 919int lbs_rtap_supported(struct lbs_private *priv)
1050{ 920{
1051 if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) 921 if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5)
1052 return 1; 922 return 1;
@@ -1078,16 +948,6 @@ int lbs_start_card(struct lbs_private *priv)
1078 948
1079 lbs_init_mesh(priv); 949 lbs_init_mesh(priv);
1080 950
1081 /*
1082 * While rtap isn't related to mesh, only mesh-enabled
1083 * firmware implements the rtap functionality via
1084 * CMD_802_11_MONITOR_MODE.
1085 */
1086 if (lbs_rtap_supported(priv)) {
1087 if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
1088 lbs_pr_err("cannot register lbs_rtap attribute\n");
1089 }
1090
1091 lbs_debugfs_init_one(priv, dev); 951 lbs_debugfs_init_one(priv, dev);
1092 952
1093 lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); 953 lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name);
@@ -1119,9 +979,6 @@ void lbs_stop_card(struct lbs_private *priv)
1119 lbs_debugfs_remove_one(priv); 979 lbs_debugfs_remove_one(priv);
1120 lbs_deinit_mesh(priv); 980 lbs_deinit_mesh(priv);
1121 981
1122 if (lbs_rtap_supported(priv))
1123 device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
1124
1125 /* Delete the timeout of the currently processing command */ 982 /* Delete the timeout of the currently processing command */
1126 del_timer_sync(&priv->command_timer); 983 del_timer_sync(&priv->command_timer);
1127 del_timer_sync(&priv->auto_deepsleep_timer); 984 del_timer_sync(&priv->auto_deepsleep_timer);
@@ -1195,7 +1052,7 @@ static int __init lbs_init_module(void)
1195 memset(&confirm_sleep, 0, sizeof(confirm_sleep)); 1052 memset(&confirm_sleep, 0, sizeof(confirm_sleep));
1196 confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE); 1053 confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE);
1197 confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep)); 1054 confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep));
1198 confirm_sleep.action = cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED); 1055 confirm_sleep.action = cpu_to_le16(PS_MODE_ACTION_SLEEP_CONFIRMED);
1199 lbs_debugfs_init(); 1056 lbs_debugfs_init();
1200 lbs_deb_leave(LBS_DEB_MAIN); 1057 lbs_deb_leave(LBS_DEB_MAIN);
1201 return 0; 1058 return 0;
@@ -1208,87 +1065,6 @@ static void __exit lbs_exit_module(void)
1208 lbs_deb_leave(LBS_DEB_MAIN); 1065 lbs_deb_leave(LBS_DEB_MAIN);
1209} 1066}
1210 1067
1211/*
1212 * rtap interface support fuctions
1213 */
1214
1215static int lbs_rtap_open(struct net_device *dev)
1216{
1217 /* Yes, _stop_ the queue. Because we don't support injection */
1218 lbs_deb_enter(LBS_DEB_MAIN);
1219 netif_carrier_off(dev);
1220 netif_stop_queue(dev);
1221 lbs_deb_leave(LBS_DEB_LEAVE);
1222 return 0;
1223}
1224
1225static int lbs_rtap_stop(struct net_device *dev)
1226{
1227 lbs_deb_enter(LBS_DEB_MAIN);
1228 lbs_deb_leave(LBS_DEB_MAIN);
1229 return 0;
1230}
1231
1232static netdev_tx_t lbs_rtap_hard_start_xmit(struct sk_buff *skb,
1233 struct net_device *dev)
1234{
1235 netif_stop_queue(dev);
1236 return NETDEV_TX_BUSY;
1237}
1238
1239static void lbs_remove_rtap(struct lbs_private *priv)
1240{
1241 lbs_deb_enter(LBS_DEB_MAIN);
1242 if (priv->rtap_net_dev == NULL)
1243 goto out;
1244 unregister_netdev(priv->rtap_net_dev);
1245 free_netdev(priv->rtap_net_dev);
1246 priv->rtap_net_dev = NULL;
1247out:
1248 lbs_deb_leave(LBS_DEB_MAIN);
1249}
1250
1251static const struct net_device_ops rtap_netdev_ops = {
1252 .ndo_open = lbs_rtap_open,
1253 .ndo_stop = lbs_rtap_stop,
1254 .ndo_start_xmit = lbs_rtap_hard_start_xmit,
1255};
1256
1257static int lbs_add_rtap(struct lbs_private *priv)
1258{
1259 int ret = 0;
1260 struct net_device *rtap_dev;
1261
1262 lbs_deb_enter(LBS_DEB_MAIN);
1263 if (priv->rtap_net_dev) {
1264 ret = -EPERM;
1265 goto out;
1266 }
1267
1268 rtap_dev = alloc_netdev(0, "rtap%d", ether_setup);
1269 if (rtap_dev == NULL) {
1270 ret = -ENOMEM;
1271 goto out;
1272 }
1273
1274 memcpy(rtap_dev->dev_addr, priv->current_addr, ETH_ALEN);
1275 rtap_dev->type = ARPHRD_IEEE80211_RADIOTAP;
1276 rtap_dev->netdev_ops = &rtap_netdev_ops;
1277 rtap_dev->ml_priv = priv;
1278 SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent);
1279
1280 ret = register_netdev(rtap_dev);
1281 if (ret) {
1282 free_netdev(rtap_dev);
1283 goto out;
1284 }
1285 priv->rtap_net_dev = rtap_dev;
1286
1287out:
1288 lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
1289 return ret;
1290}
1291
1292module_init(lbs_init_module); 1068module_init(lbs_init_module);
1293module_exit(lbs_exit_module); 1069module_exit(lbs_exit_module);
1294 1070
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index e385af1f4583..194762ab0142 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -5,6 +5,7 @@
5#include <linux/if_arp.h> 5#include <linux/if_arp.h>
6#include <linux/kthread.h> 6#include <linux/kthread.h>
7#include <linux/kfifo.h> 7#include <linux/kfifo.h>
8#include <net/cfg80211.h>
8 9
9#include "mesh.h" 10#include "mesh.h"
10#include "decl.h" 11#include "decl.h"
@@ -314,7 +315,7 @@ static int lbs_mesh_dev_open(struct net_device *dev)
314 315
315 spin_lock_irq(&priv->driver_lock); 316 spin_lock_irq(&priv->driver_lock);
316 317
317 if (priv->monitormode) { 318 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
318 ret = -EBUSY; 319 ret = -EBUSY;
319 goto out; 320 goto out;
320 } 321 }
@@ -369,9 +370,6 @@ int lbs_add_mesh(struct lbs_private *priv)
369 370
370 SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); 371 SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
371 372
372#ifdef WIRELESS_EXT
373 mesh_dev->wireless_handlers = &mesh_handler_def;
374#endif
375 mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; 373 mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
376 /* Register virtual mesh interface */ 374 /* Register virtual mesh interface */
377 ret = register_netdev(mesh_dev); 375 ret = register_netdev(mesh_dev);
@@ -457,65 +455,189 @@ void lbs_mesh_set_txpd(struct lbs_private *priv,
457 * Mesh command handling 455 * Mesh command handling
458 */ 456 */
459 457
460int lbs_cmd_bt_access(struct cmd_ds_command *cmd, 458/**
461 u16 cmd_action, void *pdata_buf) 459 * @brief Add or delete Mesh Blinding Table entries
460 *
461 * @param priv A pointer to struct lbs_private structure
462 * @param add TRUE to add the entry, FALSE to delete it
463 * @param addr1 Destination address to blind or unblind
464 *
465 * @return 0 on success, error on failure
466 */
467int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1)
462{ 468{
463 struct cmd_ds_bt_access *bt_access = &cmd->params.bt; 469 struct cmd_ds_bt_access cmd;
464 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); 470 int ret = 0;
465 471
466 cmd->command = cpu_to_le16(CMD_BT_ACCESS); 472 lbs_deb_enter(LBS_DEB_CMD);
467 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) +
468 sizeof(struct cmd_header));
469 cmd->result = 0;
470 bt_access->action = cpu_to_le16(cmd_action);
471 473
472 switch (cmd_action) { 474 BUG_ON(addr1 == NULL);
473 case CMD_ACT_BT_ACCESS_ADD: 475
474 memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN); 476 memset(&cmd, 0, sizeof(cmd));
477 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
478 memcpy(cmd.addr1, addr1, ETH_ALEN);
479 if (add) {
480 cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_ADD);
475 lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", 481 lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr",
476 bt_access->addr1, 6); 482 addr1, ETH_ALEN);
477 break; 483 } else {
478 case CMD_ACT_BT_ACCESS_DEL: 484 cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_DEL);
479 memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN);
480 lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", 485 lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr",
481 bt_access->addr1, 6); 486 addr1, ETH_ALEN);
482 break;
483 case CMD_ACT_BT_ACCESS_LIST:
484 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
485 break;
486 case CMD_ACT_BT_ACCESS_RESET:
487 break;
488 case CMD_ACT_BT_ACCESS_SET_INVERT:
489 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
490 break;
491 case CMD_ACT_BT_ACCESS_GET_INVERT:
492 break;
493 default:
494 break;
495 } 487 }
496 lbs_deb_leave(LBS_DEB_CMD); 488
497 return 0; 489 ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
490
491 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
492 return ret;
498} 493}
499 494
500int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, 495/**
501 u16 cmd_action, void *pdata_buf) 496 * @brief Reset/clear the mesh blinding table
497 *
498 * @param priv A pointer to struct lbs_private structure
499 *
500 * @return 0 on success, error on failure
501 */
502int lbs_mesh_bt_reset(struct lbs_private *priv)
502{ 503{
503 struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt; 504 struct cmd_ds_bt_access cmd;
504 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); 505 int ret = 0;
505 506
506 cmd->command = cpu_to_le16(CMD_FWT_ACCESS); 507 lbs_deb_enter(LBS_DEB_CMD);
507 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) +
508 sizeof(struct cmd_header));
509 cmd->result = 0;
510 508
511 if (pdata_buf) 509 memset(&cmd, 0, sizeof(cmd));
512 memcpy(fwt_access, pdata_buf, sizeof(*fwt_access)); 510 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
513 else 511 cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_RESET);
514 memset(fwt_access, 0, sizeof(*fwt_access));
515 512
516 fwt_access->action = cpu_to_le16(cmd_action); 513 ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
517 514
518 lbs_deb_leave(LBS_DEB_CMD); 515 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
516 return ret;
517}
518
519/**
520 * @brief Gets the inverted status of the mesh blinding table
521 *
522 * Normally the firmware "blinds" or ignores traffic from mesh nodes in the
523 * table, but an inverted table allows *only* traffic from nodes listed in
524 * the table.
525 *
526 * @param priv A pointer to struct lbs_private structure
527 * @param invert On success, TRUE if the blinding table is inverted,
528 * FALSE if it is not inverted
529 *
530 * @return 0 on success, error on failure
531 */
532int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted)
533{
534 struct cmd_ds_bt_access cmd;
535 int ret = 0;
536
537 lbs_deb_enter(LBS_DEB_CMD);
538
539 BUG_ON(inverted == NULL);
540
541 memset(&cmd, 0, sizeof(cmd));
542 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
543 cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_GET_INVERT);
544
545 ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
546 if (ret == 0)
547 *inverted = !!cmd.id;
548
549 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
550 return ret;
551}
552
553/**
554 * @brief Sets the inverted status of the mesh blinding table
555 *
556 * Normally the firmware "blinds" or ignores traffic from mesh nodes in the
557 * table, but an inverted table allows *only* traffic from nodes listed in
558 * the table.
559 *
560 * @param priv A pointer to struct lbs_private structure
561 * @param invert TRUE to invert the blinding table (only traffic from
562 * listed nodes allowed), FALSE to return it
563 * to normal state (listed nodes ignored)
564 *
565 * @return 0 on success, error on failure
566 */
567int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted)
568{
569 struct cmd_ds_bt_access cmd;
570 int ret = 0;
571
572 lbs_deb_enter(LBS_DEB_CMD);
573
574 memset(&cmd, 0, sizeof(cmd));
575 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
576 cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
577 cmd.id = !!inverted;
578
579 ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
580
581 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
582 return ret;
583}
584
585/**
586 * @brief List an entry in the mesh blinding table
587 *
588 * @param priv A pointer to struct lbs_private structure
589 * @param id The ID of the entry to list
590 * @param addr1 MAC address associated with the table entry
591 *
592 * @return 0 on success, error on failure
593 */
594int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1)
595{
596 struct cmd_ds_bt_access cmd;
597 int ret = 0;
598
599 lbs_deb_enter(LBS_DEB_CMD);
600
601 BUG_ON(addr1 == NULL);
602
603 memset(&cmd, 0, sizeof(cmd));
604 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
605 cmd.action = cpu_to_le16(CMD_ACT_BT_ACCESS_SET_INVERT);
606 cmd.id = cpu_to_le32(id);
607
608 ret = lbs_cmd_with_response(priv, CMD_BT_ACCESS, &cmd);
609 if (ret == 0)
610 memcpy(addr1, cmd.addr1, sizeof(cmd.addr1));
611
612 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
613 return ret;
614}
615
616/**
617 * @brief Access the mesh forwarding table
618 *
619 * @param priv A pointer to struct lbs_private structure
620 * @param cmd_action The forwarding table action to perform
621 * @param cmd The pre-filled FWT_ACCESS command
622 *
623 * @return 0 on success and 'cmd' will be filled with the
624 * firmware's response
625 */
626int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action,
627 struct cmd_ds_fwt_access *cmd)
628{
629 int ret;
630
631 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
632
633 cmd->hdr.command = cpu_to_le16(CMD_FWT_ACCESS);
634 cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access));
635 cmd->hdr.result = 0;
636 cmd->action = cpu_to_le16(cmd_action);
637
638 ret = lbs_cmd_with_response(priv, CMD_FWT_ACCESS, cmd);
639
640 lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
519 return 0; 641 return 0;
520} 642}
521 643
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h
index e2573303a328..afb2e8dead3f 100644
--- a/drivers/net/wireless/libertas/mesh.h
+++ b/drivers/net/wireless/libertas/mesh.h
@@ -8,6 +8,7 @@
8#include <net/iw_handler.h> 8#include <net/iw_handler.h>
9#include <net/lib80211.h> 9#include <net/lib80211.h>
10 10
11#include "host.h"
11 12
12#ifdef CONFIG_LIBERTAS_MESH 13#ifdef CONFIG_LIBERTAS_MESH
13 14
@@ -51,10 +52,15 @@ struct cmd_ds_command;
51struct cmd_ds_mesh_access; 52struct cmd_ds_mesh_access;
52struct cmd_ds_mesh_config; 53struct cmd_ds_mesh_config;
53 54
54int lbs_cmd_bt_access(struct cmd_ds_command *cmd, 55int lbs_mesh_bt_add_del(struct lbs_private *priv, bool add, u8 *addr1);
55 u16 cmd_action, void *pdata_buf); 56int lbs_mesh_bt_reset(struct lbs_private *priv);
56int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, 57int lbs_mesh_bt_get_inverted(struct lbs_private *priv, bool *inverted);
57 u16 cmd_action, void *pdata_buf); 58int lbs_mesh_bt_set_inverted(struct lbs_private *priv, bool inverted);
59int lbs_mesh_bt_get_entry(struct lbs_private *priv, u32 id, u8 *addr1);
60
61int lbs_cmd_fwt_access(struct lbs_private *priv, u16 cmd_action,
62 struct cmd_ds_fwt_access *cmd);
63
58int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, 64int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
59 struct cmd_ds_mesh_access *cmd); 65 struct cmd_ds_mesh_access *cmd);
60int lbs_mesh_config_send(struct lbs_private *priv, 66int lbs_mesh_config_send(struct lbs_private *priv,
@@ -70,11 +76,6 @@ void lbs_persist_config_init(struct net_device *net);
70void lbs_persist_config_remove(struct net_device *net); 76void lbs_persist_config_remove(struct net_device *net);
71 77
72 78
73/* WEXT handler */
74
75extern struct iw_handler_def mesh_handler_def;
76
77
78/* Ethtool statistics */ 79/* Ethtool statistics */
79 80
80struct ethtool_stats; 81struct ethtool_stats;
diff --git a/drivers/net/wireless/libertas/radiotap.h b/drivers/net/wireless/libertas/radiotap.h
index d16b26416e82..b3c8ea6d610e 100644
--- a/drivers/net/wireless/libertas/radiotap.h
+++ b/drivers/net/wireless/libertas/radiotap.h
@@ -6,7 +6,7 @@ struct tx_radiotap_hdr {
6 u8 txpower; 6 u8 txpower;
7 u8 rts_retries; 7 u8 rts_retries;
8 u8 data_retries; 8 u8 data_retries;
9} __attribute__ ((packed)); 9} __packed;
10 10
11#define TX_RADIOTAP_PRESENT ( \ 11#define TX_RADIOTAP_PRESENT ( \
12 (1 << IEEE80211_RADIOTAP_RATE) | \ 12 (1 << IEEE80211_RADIOTAP_RATE) | \
@@ -34,7 +34,7 @@ struct rx_radiotap_hdr {
34 u8 flags; 34 u8 flags;
35 u8 rate; 35 u8 rate;
36 u8 antsignal; 36 u8 antsignal;
37} __attribute__ ((packed)); 37} __packed;
38 38
39#define RX_RADIOTAP_PRESENT ( \ 39#define RX_RADIOTAP_PRESENT ( \
40 (1 << IEEE80211_RADIOTAP_FLAGS) | \ 40 (1 << IEEE80211_RADIOTAP_FLAGS) | \
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index 7a377f5b7662..a4d0bca9ef2c 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -4,18 +4,19 @@
4#include <linux/etherdevice.h> 4#include <linux/etherdevice.h>
5#include <linux/slab.h> 5#include <linux/slab.h>
6#include <linux/types.h> 6#include <linux/types.h>
7#include <net/cfg80211.h>
7 8
9#include "defs.h"
8#include "host.h" 10#include "host.h"
9#include "radiotap.h" 11#include "radiotap.h"
10#include "decl.h" 12#include "decl.h"
11#include "dev.h" 13#include "dev.h"
12#include "wext.h"
13 14
14struct eth803hdr { 15struct eth803hdr {
15 u8 dest_addr[6]; 16 u8 dest_addr[6];
16 u8 src_addr[6]; 17 u8 src_addr[6];
17 u16 h803_len; 18 u16 h803_len;
18} __attribute__ ((packed)); 19} __packed;
19 20
20struct rfc1042hdr { 21struct rfc1042hdr {
21 u8 llc_dsap; 22 u8 llc_dsap;
@@ -23,114 +24,22 @@ struct rfc1042hdr {
23 u8 llc_ctrl; 24 u8 llc_ctrl;
24 u8 snap_oui[3]; 25 u8 snap_oui[3];
25 u16 snap_type; 26 u16 snap_type;
26} __attribute__ ((packed)); 27} __packed;
27 28
28struct rxpackethdr { 29struct rxpackethdr {
29 struct eth803hdr eth803_hdr; 30 struct eth803hdr eth803_hdr;
30 struct rfc1042hdr rfc1042_hdr; 31 struct rfc1042hdr rfc1042_hdr;
31} __attribute__ ((packed)); 32} __packed;
32 33
33struct rx80211packethdr { 34struct rx80211packethdr {
34 struct rxpd rx_pd; 35 struct rxpd rx_pd;
35 void *eth80211_hdr; 36 void *eth80211_hdr;
36} __attribute__ ((packed)); 37} __packed;
37 38
38static int process_rxed_802_11_packet(struct lbs_private *priv, 39static int process_rxed_802_11_packet(struct lbs_private *priv,
39 struct sk_buff *skb); 40 struct sk_buff *skb);
40 41
41/** 42/**
42 * @brief This function computes the avgSNR .
43 *
44 * @param priv A pointer to struct lbs_private structure
45 * @return avgSNR
46 */
47static u8 lbs_getavgsnr(struct lbs_private *priv)
48{
49 u8 i;
50 u16 temp = 0;
51 if (priv->numSNRNF == 0)
52 return 0;
53 for (i = 0; i < priv->numSNRNF; i++)
54 temp += priv->rawSNR[i];
55 return (u8) (temp / priv->numSNRNF);
56
57}
58
59/**
60 * @brief This function computes the AvgNF
61 *
62 * @param priv A pointer to struct lbs_private structure
63 * @return AvgNF
64 */
65static u8 lbs_getavgnf(struct lbs_private *priv)
66{
67 u8 i;
68 u16 temp = 0;
69 if (priv->numSNRNF == 0)
70 return 0;
71 for (i = 0; i < priv->numSNRNF; i++)
72 temp += priv->rawNF[i];
73 return (u8) (temp / priv->numSNRNF);
74
75}
76
77/**
78 * @brief This function save the raw SNR/NF to our internel buffer
79 *
80 * @param priv A pointer to struct lbs_private structure
81 * @param prxpd A pointer to rxpd structure of received packet
82 * @return n/a
83 */
84static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd)
85{
86 if (priv->numSNRNF < DEFAULT_DATA_AVG_FACTOR)
87 priv->numSNRNF++;
88 priv->rawSNR[priv->nextSNRNF] = p_rx_pd->snr;
89 priv->rawNF[priv->nextSNRNF] = p_rx_pd->nf;
90 priv->nextSNRNF++;
91 if (priv->nextSNRNF >= DEFAULT_DATA_AVG_FACTOR)
92 priv->nextSNRNF = 0;
93}
94
95/**
96 * @brief This function computes the RSSI in received packet.
97 *
98 * @param priv A pointer to struct lbs_private structure
99 * @param prxpd A pointer to rxpd structure of received packet
100 * @return n/a
101 */
102static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd)
103{
104
105 lbs_deb_enter(LBS_DEB_RX);
106
107 lbs_deb_rx("rxpd: SNR %d, NF %d\n", p_rx_pd->snr, p_rx_pd->nf);
108 lbs_deb_rx("before computing SNR: SNR-avg = %d, NF-avg = %d\n",
109 priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
110 priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
111
112 priv->SNR[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->snr;
113 priv->NF[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->nf;
114 lbs_save_rawSNRNF(priv, p_rx_pd);
115
116 priv->SNR[TYPE_RXPD][TYPE_AVG] = lbs_getavgsnr(priv) * AVG_SCALE;
117 priv->NF[TYPE_RXPD][TYPE_AVG] = lbs_getavgnf(priv) * AVG_SCALE;
118 lbs_deb_rx("after computing SNR: SNR-avg = %d, NF-avg = %d\n",
119 priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
120 priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
121
122 priv->RSSI[TYPE_RXPD][TYPE_NOAVG] =
123 CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_NOAVG],
124 priv->NF[TYPE_RXPD][TYPE_NOAVG]);
125
126 priv->RSSI[TYPE_RXPD][TYPE_AVG] =
127 CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
128 priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
129
130 lbs_deb_leave(LBS_DEB_RX);
131}
132
133/**
134 * @brief This function processes received packet and forwards it 43 * @brief This function processes received packet and forwards it
135 * to kernel/upper layer 44 * to kernel/upper layer
136 * 45 *
@@ -154,7 +63,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
154 63
155 skb->ip_summed = CHECKSUM_NONE; 64 skb->ip_summed = CHECKSUM_NONE;
156 65
157 if (priv->monitormode) 66 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
158 return process_rxed_802_11_packet(priv, skb); 67 return process_rxed_802_11_packet(priv, skb);
159 68
160 p_rx_pd = (struct rxpd *) skb->data; 69 p_rx_pd = (struct rxpd *) skb->data;
@@ -225,13 +134,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
225 */ 134 */
226 skb_pull(skb, hdrchop); 135 skb_pull(skb, hdrchop);
227 136
228 /* Take the data rate from the rxpd structure 137 priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
229 * only if the rate is auto
230 */
231 if (priv->enablehwauto)
232 priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate);
233
234 lbs_compute_rssi(priv, p_rx_pd);
235 138
236 lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); 139 lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
237 dev->stats.rx_bytes += skb->len; 140 dev->stats.rx_bytes += skb->len;
@@ -352,20 +255,18 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
352 pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr)); 255 pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr));
353 memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr)); 256 memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr));
354 257
355 /* Take the data rate from the rxpd structure 258 priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
356 * only if the rate is auto
357 */
358 if (priv->enablehwauto)
359 priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate);
360
361 lbs_compute_rssi(priv, prxpd);
362 259
363 lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); 260 lbs_deb_rx("rx data: size of actual packet %d\n", skb->len);
364 dev->stats.rx_bytes += skb->len; 261 dev->stats.rx_bytes += skb->len;
365 dev->stats.rx_packets++; 262 dev->stats.rx_packets++;
366 263
367 skb->protocol = eth_type_trans(skb, priv->rtap_net_dev); 264 skb->protocol = eth_type_trans(skb, priv->dev);
368 netif_rx(skb); 265
266 if (in_interrupt())
267 netif_rx(skb);
268 else
269 netif_rx_ni(skb);
369 270
370 ret = 0; 271 ret = 0;
371 272
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
deleted file mode 100644
index 24cd54b3a806..000000000000
--- a/drivers/net/wireless/libertas/scan.c
+++ /dev/null
@@ -1,1354 +0,0 @@
1/**
2 * Functions implementing wlan scan IOCTL and firmware command APIs
3 *
4 * IOCTL handlers as well as command preperation and response routines
5 * for sending scan commands to the firmware.
6 */
7#include <linux/slab.h>
8#include <linux/types.h>
9#include <linux/kernel.h>
10#include <linux/etherdevice.h>
11#include <linux/if_arp.h>
12#include <asm/unaligned.h>
13#include <net/lib80211.h>
14
15#include "host.h"
16#include "dev.h"
17#include "scan.h"
18#include "assoc.h"
19#include "wext.h"
20#include "cmd.h"
21
22//! Approximate amount of data needed to pass a scan result back to iwlist
23#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \
24 + IEEE80211_MAX_SSID_LEN \
25 + IW_EV_UINT_LEN \
26 + IW_EV_FREQ_LEN \
27 + IW_EV_QUAL_LEN \
28 + IEEE80211_MAX_SSID_LEN \
29 + IW_EV_PARAM_LEN \
30 + 40) /* 40 for WPAIE */
31
32//! Memory needed to store a max sized channel List TLV for a firmware scan
33#define CHAN_TLV_MAX_SIZE (sizeof(struct mrvl_ie_header) \
34 + (MRVDRV_MAX_CHANNELS_PER_SCAN \
35 * sizeof(struct chanscanparamset)))
36
37//! Memory needed to store a max number/size SSID TLV for a firmware scan
38#define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvl_ie_ssid_param_set))
39
40//! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max
41#define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan) \
42 + CHAN_TLV_MAX_SIZE + SSID_TLV_MAX_SIZE)
43
44//! The maximum number of channels the firmware can scan per command
45#define MRVDRV_MAX_CHANNELS_PER_SCAN 14
46
47/**
48 * @brief Number of channels to scan per firmware scan command issuance.
49 *
50 * Number restricted to prevent hitting the limit on the amount of scan data
51 * returned in a single firmware scan command.
52 */
53#define MRVDRV_CHANNELS_PER_SCAN_CMD 4
54
55//! Scan time specified in the channel TLV for each channel for passive scans
56#define MRVDRV_PASSIVE_SCAN_CHAN_TIME 100
57
58//! Scan time specified in the channel TLV for each channel for active scans
59#define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100
60
61#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
62
63static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
64 struct cmd_header *resp);
65
66/*********************************************************************/
67/* */
68/* Misc helper functions */
69/* */
70/*********************************************************************/
71
72/**
73 * @brief Unsets the MSB on basic rates
74 *
75 * Scan through an array and unset the MSB for basic data rates.
76 *
77 * @param rates buffer of data rates
78 * @param len size of buffer
79 */
80static void lbs_unset_basic_rate_flags(u8 *rates, size_t len)
81{
82 int i;
83
84 for (i = 0; i < len; i++)
85 rates[i] &= 0x7f;
86}
87
88
89static inline void clear_bss_descriptor(struct bss_descriptor *bss)
90{
91 /* Don't blow away ->list, just BSS data */
92 memset(bss, 0, offsetof(struct bss_descriptor, list));
93}
94
95/**
96 * @brief Compare two SSIDs
97 *
98 * @param ssid1 A pointer to ssid to compare
99 * @param ssid2 A pointer to ssid to compare
100 *
101 * @return 0: ssid is same, otherwise is different
102 */
103int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2,
104 uint8_t ssid2_len)
105{
106 if (ssid1_len != ssid2_len)
107 return -1;
108
109 return memcmp(ssid1, ssid2, ssid1_len);
110}
111
112static inline int is_same_network(struct bss_descriptor *src,
113 struct bss_descriptor *dst)
114{
115 /* A network is only a duplicate if the channel, BSSID, and ESSID
116 * all match. We treat all <hidden> with the same BSSID and channel
117 * as one network */
118 return ((src->ssid_len == dst->ssid_len) &&
119 (src->channel == dst->channel) &&
120 !compare_ether_addr(src->bssid, dst->bssid) &&
121 !memcmp(src->ssid, dst->ssid, src->ssid_len));
122}
123
124
125
126/*********************************************************************/
127/* */
128/* Region channel support */
129/* */
130/*********************************************************************/
131
132#define LBS_TX_PWR_DEFAULT 20 /*100mW */
133#define LBS_TX_PWR_US_DEFAULT 20 /*100mW */
134#define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */
135#define LBS_TX_PWR_FR_DEFAULT 20 /*100mW */
136#define LBS_TX_PWR_EMEA_DEFAULT 20 /*100mW */
137
138/* Format { channel, frequency (MHz), maxtxpower } */
139/* band: 'B/G', region: USA FCC/Canada IC */
140static struct chan_freq_power channel_freq_power_US_BG[] = {
141 {1, 2412, LBS_TX_PWR_US_DEFAULT},
142 {2, 2417, LBS_TX_PWR_US_DEFAULT},
143 {3, 2422, LBS_TX_PWR_US_DEFAULT},
144 {4, 2427, LBS_TX_PWR_US_DEFAULT},
145 {5, 2432, LBS_TX_PWR_US_DEFAULT},
146 {6, 2437, LBS_TX_PWR_US_DEFAULT},
147 {7, 2442, LBS_TX_PWR_US_DEFAULT},
148 {8, 2447, LBS_TX_PWR_US_DEFAULT},
149 {9, 2452, LBS_TX_PWR_US_DEFAULT},
150 {10, 2457, LBS_TX_PWR_US_DEFAULT},
151 {11, 2462, LBS_TX_PWR_US_DEFAULT}
152};
153
154/* band: 'B/G', region: Europe ETSI */
155static struct chan_freq_power channel_freq_power_EU_BG[] = {
156 {1, 2412, LBS_TX_PWR_EMEA_DEFAULT},
157 {2, 2417, LBS_TX_PWR_EMEA_DEFAULT},
158 {3, 2422, LBS_TX_PWR_EMEA_DEFAULT},
159 {4, 2427, LBS_TX_PWR_EMEA_DEFAULT},
160 {5, 2432, LBS_TX_PWR_EMEA_DEFAULT},
161 {6, 2437, LBS_TX_PWR_EMEA_DEFAULT},
162 {7, 2442, LBS_TX_PWR_EMEA_DEFAULT},
163 {8, 2447, LBS_TX_PWR_EMEA_DEFAULT},
164 {9, 2452, LBS_TX_PWR_EMEA_DEFAULT},
165 {10, 2457, LBS_TX_PWR_EMEA_DEFAULT},
166 {11, 2462, LBS_TX_PWR_EMEA_DEFAULT},
167 {12, 2467, LBS_TX_PWR_EMEA_DEFAULT},
168 {13, 2472, LBS_TX_PWR_EMEA_DEFAULT}
169};
170
171/* band: 'B/G', region: Spain */
172static struct chan_freq_power channel_freq_power_SPN_BG[] = {
173 {10, 2457, LBS_TX_PWR_DEFAULT},
174 {11, 2462, LBS_TX_PWR_DEFAULT}
175};
176
177/* band: 'B/G', region: France */
178static struct chan_freq_power channel_freq_power_FR_BG[] = {
179 {10, 2457, LBS_TX_PWR_FR_DEFAULT},
180 {11, 2462, LBS_TX_PWR_FR_DEFAULT},
181 {12, 2467, LBS_TX_PWR_FR_DEFAULT},
182 {13, 2472, LBS_TX_PWR_FR_DEFAULT}
183};
184
185/* band: 'B/G', region: Japan */
186static struct chan_freq_power channel_freq_power_JPN_BG[] = {
187 {1, 2412, LBS_TX_PWR_JP_DEFAULT},
188 {2, 2417, LBS_TX_PWR_JP_DEFAULT},
189 {3, 2422, LBS_TX_PWR_JP_DEFAULT},
190 {4, 2427, LBS_TX_PWR_JP_DEFAULT},
191 {5, 2432, LBS_TX_PWR_JP_DEFAULT},
192 {6, 2437, LBS_TX_PWR_JP_DEFAULT},
193 {7, 2442, LBS_TX_PWR_JP_DEFAULT},
194 {8, 2447, LBS_TX_PWR_JP_DEFAULT},
195 {9, 2452, LBS_TX_PWR_JP_DEFAULT},
196 {10, 2457, LBS_TX_PWR_JP_DEFAULT},
197 {11, 2462, LBS_TX_PWR_JP_DEFAULT},
198 {12, 2467, LBS_TX_PWR_JP_DEFAULT},
199 {13, 2472, LBS_TX_PWR_JP_DEFAULT},
200 {14, 2484, LBS_TX_PWR_JP_DEFAULT}
201};
202
203/**
204 * the structure for channel, frequency and power
205 */
206struct region_cfp_table {
207 u8 region;
208 struct chan_freq_power *cfp_BG;
209 int cfp_no_BG;
210};
211
212/**
213 * the structure for the mapping between region and CFP
214 */
215static struct region_cfp_table region_cfp_table[] = {
216 {0x10, /*US FCC */
217 channel_freq_power_US_BG,
218 ARRAY_SIZE(channel_freq_power_US_BG),
219 }
220 ,
221 {0x20, /*CANADA IC */
222 channel_freq_power_US_BG,
223 ARRAY_SIZE(channel_freq_power_US_BG),
224 }
225 ,
226 {0x30, /*EU*/ channel_freq_power_EU_BG,
227 ARRAY_SIZE(channel_freq_power_EU_BG),
228 }
229 ,
230 {0x31, /*SPAIN*/ channel_freq_power_SPN_BG,
231 ARRAY_SIZE(channel_freq_power_SPN_BG),
232 }
233 ,
234 {0x32, /*FRANCE*/ channel_freq_power_FR_BG,
235 ARRAY_SIZE(channel_freq_power_FR_BG),
236 }
237 ,
238 {0x40, /*JAPAN*/ channel_freq_power_JPN_BG,
239 ARRAY_SIZE(channel_freq_power_JPN_BG),
240 }
241 ,
242/*Add new region here */
243};
244
245/**
246 * @brief This function finds the CFP in
247 * region_cfp_table based on region and band parameter.
248 *
249 * @param region The region code
250 * @param band The band
251 * @param cfp_no A pointer to CFP number
252 * @return A pointer to CFP
253 */
254static struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no)
255{
256 int i, end;
257
258 lbs_deb_enter(LBS_DEB_MAIN);
259
260 end = ARRAY_SIZE(region_cfp_table);
261
262 for (i = 0; i < end ; i++) {
263 lbs_deb_main("region_cfp_table[i].region=%d\n",
264 region_cfp_table[i].region);
265 if (region_cfp_table[i].region == region) {
266 *cfp_no = region_cfp_table[i].cfp_no_BG;
267 lbs_deb_leave(LBS_DEB_MAIN);
268 return region_cfp_table[i].cfp_BG;
269 }
270 }
271
272 lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL");
273 return NULL;
274}
275
276int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band)
277{
278 int ret = 0;
279 int i = 0;
280
281 struct chan_freq_power *cfp;
282 int cfp_no;
283
284 lbs_deb_enter(LBS_DEB_MAIN);
285
286 memset(priv->region_channel, 0, sizeof(priv->region_channel));
287
288 cfp = lbs_get_region_cfp_table(region, &cfp_no);
289 if (cfp != NULL) {
290 priv->region_channel[i].nrcfp = cfp_no;
291 priv->region_channel[i].CFP = cfp;
292 } else {
293 lbs_deb_main("wrong region code %#x in band B/G\n",
294 region);
295 ret = -1;
296 goto out;
297 }
298 priv->region_channel[i].valid = 1;
299 priv->region_channel[i].region = region;
300 priv->region_channel[i].band = band;
301 i++;
302out:
303 lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret);
304 return ret;
305}
306
307
308
309
310/*********************************************************************/
311/* */
312/* Main scanning support */
313/* */
314/*********************************************************************/
315
316/**
317 * @brief Create a channel list for the driver to scan based on region info
318 *
319 * Only used from lbs_scan_setup_scan_config()
320 *
321 * Use the driver region/band information to construct a comprehensive list
322 * of channels to scan. This routine is used for any scan that is not
323 * provided a specific channel list to scan.
324 *
325 * @param priv A pointer to struct lbs_private structure
326 * @param scanchanlist Output parameter: resulting channel list to scan
327 *
328 * @return void
329 */
330static int lbs_scan_create_channel_list(struct lbs_private *priv,
331 struct chanscanparamset *scanchanlist)
332{
333 struct region_channel *scanregion;
334 struct chan_freq_power *cfp;
335 int rgnidx;
336 int chanidx;
337 int nextchan;
338 uint8_t scantype;
339
340 chanidx = 0;
341
342 /* Set the default scan type to the user specified type, will later
343 * be changed to passive on a per channel basis if restricted by
344 * regulatory requirements (11d or 11h)
345 */
346 scantype = CMD_SCAN_TYPE_ACTIVE;
347
348 for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) {
349 if (!priv->region_channel[rgnidx].valid)
350 continue;
351 scanregion = &priv->region_channel[rgnidx];
352
353 for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) {
354 struct chanscanparamset *chan = &scanchanlist[chanidx];
355
356 cfp = scanregion->CFP + nextchan;
357
358 if (scanregion->band == BAND_B || scanregion->band == BAND_G)
359 chan->radiotype = CMD_SCAN_RADIO_TYPE_BG;
360
361 if (scantype == CMD_SCAN_TYPE_PASSIVE) {
362 chan->maxscantime = cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME);
363 chan->chanscanmode.passivescan = 1;
364 } else {
365 chan->maxscantime = cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME);
366 chan->chanscanmode.passivescan = 0;
367 }
368
369 chan->channumber = cfp->channel;
370 }
371 }
372 return chanidx;
373}
374
375/*
376 * Add SSID TLV of the form:
377 *
378 * TLV-ID SSID 00 00
379 * length 06 00
380 * ssid 4d 4e 54 45 53 54
381 */
382static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv)
383{
384 struct mrvl_ie_ssid_param_set *ssid_tlv = (void *)tlv;
385
386 ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID);
387 ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len);
388 memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len);
389 return sizeof(ssid_tlv->header) + priv->scan_ssid_len;
390}
391
392/*
393 * Add CHANLIST TLV of the form
394 *
395 * TLV-ID CHANLIST 01 01
396 * length 5b 00
397 * channel 1 00 01 00 00 00 64 00
398 * radio type 00
399 * channel 01
400 * scan type 00
401 * min scan time 00 00
402 * max scan time 64 00
403 * channel 2 00 02 00 00 00 64 00
404 * channel 3 00 03 00 00 00 64 00
405 * channel 4 00 04 00 00 00 64 00
406 * channel 5 00 05 00 00 00 64 00
407 * channel 6 00 06 00 00 00 64 00
408 * channel 7 00 07 00 00 00 64 00
409 * channel 8 00 08 00 00 00 64 00
410 * channel 9 00 09 00 00 00 64 00
411 * channel 10 00 0a 00 00 00 64 00
412 * channel 11 00 0b 00 00 00 64 00
413 * channel 12 00 0c 00 00 00 64 00
414 * channel 13 00 0d 00 00 00 64 00
415 *
416 */
417static int lbs_scan_add_chanlist_tlv(uint8_t *tlv,
418 struct chanscanparamset *chan_list,
419 int chan_count)
420{
421 size_t size = sizeof(struct chanscanparamset) *chan_count;
422 struct mrvl_ie_chanlist_param_set *chan_tlv = (void *)tlv;
423
424 chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
425 memcpy(chan_tlv->chanscanparam, chan_list, size);
426 chan_tlv->header.len = cpu_to_le16(size);
427 return sizeof(chan_tlv->header) + size;
428}
429
430/*
431 * Add RATES TLV of the form
432 *
433 * TLV-ID RATES 01 00
434 * length 0e 00
435 * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c
436 *
437 * The rates are in lbs_bg_rates[], but for the 802.11b
438 * rates the high bit isn't set.
439 */
440static int lbs_scan_add_rates_tlv(uint8_t *tlv)
441{
442 int i;
443 struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv;
444
445 rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES);
446 tlv += sizeof(rate_tlv->header);
447 for (i = 0; i < MAX_RATES; i++) {
448 *tlv = lbs_bg_rates[i];
449 if (*tlv == 0)
450 break;
451 /* This code makes sure that the 802.11b rates (1 MBit/s, 2
452 MBit/s, 5.5 MBit/s and 11 MBit/s get's the high bit set.
453 Note that the values are MBit/s * 2, to mark them as
454 basic rates so that the firmware likes it better */
455 if (*tlv == 0x02 || *tlv == 0x04 ||
456 *tlv == 0x0b || *tlv == 0x16)
457 *tlv |= 0x80;
458 tlv++;
459 }
460 rate_tlv->header.len = cpu_to_le16(i);
461 return sizeof(rate_tlv->header) + i;
462}
463
464/*
465 * Generate the CMD_802_11_SCAN command with the proper tlv
466 * for a bunch of channels.
467 */
468static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype,
469 struct chanscanparamset *chan_list, int chan_count)
470{
471 int ret = -ENOMEM;
472 struct cmd_ds_802_11_scan *scan_cmd;
473 uint8_t *tlv; /* pointer into our current, growing TLV storage area */
474
475 lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, chan_count %d",
476 bsstype, chan_list ? chan_list[0].channumber : -1,
477 chan_count);
478
479 /* create the fixed part for scan command */
480 scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL);
481 if (scan_cmd == NULL)
482 goto out;
483
484 tlv = scan_cmd->tlvbuffer;
485 /* TODO: do we need to scan for a specific BSSID?
486 memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */
487 scan_cmd->bsstype = bsstype;
488
489 /* add TLVs */
490 if (priv->scan_ssid_len)
491 tlv += lbs_scan_add_ssid_tlv(priv, tlv);
492 if (chan_list && chan_count)
493 tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count);
494 tlv += lbs_scan_add_rates_tlv(tlv);
495
496 /* This is the final data we are about to send */
497 scan_cmd->hdr.size = cpu_to_le16(tlv - (uint8_t *)scan_cmd);
498 lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd,
499 sizeof(*scan_cmd));
500 lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer,
501 tlv - scan_cmd->tlvbuffer);
502
503 ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr,
504 le16_to_cpu(scan_cmd->hdr.size),
505 lbs_ret_80211_scan, 0);
506
507out:
508 kfree(scan_cmd);
509 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
510 return ret;
511}
512
513/**
514 * @brief Internal function used to start a scan based on an input config
515 *
516 * Use the input user scan configuration information when provided in
517 * order to send the appropriate scan commands to firmware to populate or
518 * update the internal driver scan table
519 *
520 * @param priv A pointer to struct lbs_private structure
521 * @param full_scan Do a full-scan (blocking)
522 *
523 * @return 0 or < 0 if error
524 */
525int lbs_scan_networks(struct lbs_private *priv, int full_scan)
526{
527 int ret = -ENOMEM;
528 struct chanscanparamset *chan_list;
529 struct chanscanparamset *curr_chans;
530 int chan_count;
531 uint8_t bsstype = CMD_BSS_TYPE_ANY;
532 int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD;
533 union iwreq_data wrqu;
534#ifdef CONFIG_LIBERTAS_DEBUG
535 struct bss_descriptor *iter;
536 int i = 0;
537 DECLARE_SSID_BUF(ssid);
538#endif
539
540 lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan);
541
542 /* Cancel any partial outstanding partial scans if this scan
543 * is a full scan.
544 */
545 if (full_scan && delayed_work_pending(&priv->scan_work))
546 cancel_delayed_work(&priv->scan_work);
547
548 /* User-specified bsstype or channel list
549 TODO: this can be implemented if some user-space application
550 need the feature. Formerly, it was accessible from debugfs,
551 but then nowhere used.
552 if (user_cfg) {
553 if (user_cfg->bsstype)
554 bsstype = user_cfg->bsstype;
555 } */
556
557 lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype);
558
559 /* Create list of channels to scan */
560 chan_list = kzalloc(sizeof(struct chanscanparamset) *
561 LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL);
562 if (!chan_list) {
563 lbs_pr_alert("SCAN: chan_list empty\n");
564 goto out;
565 }
566
567 /* We want to scan all channels */
568 chan_count = lbs_scan_create_channel_list(priv, chan_list);
569
570 netif_stop_queue(priv->dev);
571 if (priv->mesh_dev)
572 netif_stop_queue(priv->mesh_dev);
573
574 /* Prepare to continue an interrupted scan */
575 lbs_deb_scan("chan_count %d, scan_channel %d\n",
576 chan_count, priv->scan_channel);
577 curr_chans = chan_list;
578 /* advance channel list by already-scanned-channels */
579 if (priv->scan_channel > 0) {
580 curr_chans += priv->scan_channel;
581 chan_count -= priv->scan_channel;
582 }
583
584 /* Send scan command(s)
585 * numchannels contains the number of channels we should maximally scan
586 * chan_count is the total number of channels to scan
587 */
588
589 while (chan_count) {
590 int to_scan = min(numchannels, chan_count);
591 lbs_deb_scan("scanning %d of %d channels\n",
592 to_scan, chan_count);
593 ret = lbs_do_scan(priv, bsstype, curr_chans,
594 to_scan);
595 if (ret) {
596 lbs_pr_err("SCAN_CMD failed\n");
597 goto out2;
598 }
599 curr_chans += to_scan;
600 chan_count -= to_scan;
601
602 /* somehow schedule the next part of the scan */
603 if (chan_count && !full_scan &&
604 !priv->surpriseremoved) {
605 /* -1 marks just that we're currently scanning */
606 if (priv->scan_channel < 0)
607 priv->scan_channel = to_scan;
608 else
609 priv->scan_channel += to_scan;
610 cancel_delayed_work(&priv->scan_work);
611 queue_delayed_work(priv->work_thread, &priv->scan_work,
612 msecs_to_jiffies(300));
613 /* skip over GIWSCAN event */
614 goto out;
615 }
616
617 }
618 memset(&wrqu, 0, sizeof(union iwreq_data));
619 wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL);
620
621#ifdef CONFIG_LIBERTAS_DEBUG
622 /* Dump the scan table */
623 mutex_lock(&priv->lock);
624 lbs_deb_scan("scan table:\n");
625 list_for_each_entry(iter, &priv->network_list, list)
626 lbs_deb_scan("%02d: BSSID %pM, RSSI %d, SSID '%s'\n",
627 i++, iter->bssid, iter->rssi,
628 print_ssid(ssid, iter->ssid, iter->ssid_len));
629 mutex_unlock(&priv->lock);
630#endif
631
632out2:
633 priv->scan_channel = 0;
634
635out:
636 if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len)
637 netif_wake_queue(priv->dev);
638
639 if (priv->mesh_dev && lbs_mesh_connected(priv) &&
640 !priv->tx_pending_len)
641 netif_wake_queue(priv->mesh_dev);
642
643 kfree(chan_list);
644
645 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
646 return ret;
647}
648
649void lbs_scan_worker(struct work_struct *work)
650{
651 struct lbs_private *priv =
652 container_of(work, struct lbs_private, scan_work.work);
653
654 lbs_deb_enter(LBS_DEB_SCAN);
655 lbs_scan_networks(priv, 0);
656 lbs_deb_leave(LBS_DEB_SCAN);
657}
658
659
660/*********************************************************************/
661/* */
662/* Result interpretation */
663/* */
664/*********************************************************************/
665
666/**
667 * @brief Interpret a BSS scan response returned from the firmware
668 *
669 * Parse the various fixed fields and IEs passed back for a a BSS probe
670 * response or beacon from the scan command. Record information as needed
671 * in the scan table struct bss_descriptor for that entry.
672 *
673 * @param bss Output parameter: Pointer to the BSS Entry
674 *
675 * @return 0 or -1
676 */
677static int lbs_process_bss(struct bss_descriptor *bss,
678 uint8_t **pbeaconinfo, int *bytesleft)
679{
680 struct ieee_ie_fh_param_set *fh;
681 struct ieee_ie_ds_param_set *ds;
682 struct ieee_ie_cf_param_set *cf;
683 struct ieee_ie_ibss_param_set *ibss;
684 DECLARE_SSID_BUF(ssid);
685 uint8_t *pos, *end, *p;
686 uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
687 uint16_t beaconsize = 0;
688 int ret;
689
690 lbs_deb_enter(LBS_DEB_SCAN);
691
692 if (*bytesleft >= sizeof(beaconsize)) {
693 /* Extract & convert beacon size from the command buffer */
694 beaconsize = get_unaligned_le16(*pbeaconinfo);
695 *bytesleft -= sizeof(beaconsize);
696 *pbeaconinfo += sizeof(beaconsize);
697 }
698
699 if (beaconsize == 0 || beaconsize > *bytesleft) {
700 *pbeaconinfo += *bytesleft;
701 *bytesleft = 0;
702 ret = -1;
703 goto done;
704 }
705
706 /* Initialize the current working beacon pointer for this BSS iteration */
707 pos = *pbeaconinfo;
708 end = pos + beaconsize;
709
710 /* Advance the return beacon pointer past the current beacon */
711 *pbeaconinfo += beaconsize;
712 *bytesleft -= beaconsize;
713
714 memcpy(bss->bssid, pos, ETH_ALEN);
715 lbs_deb_scan("process_bss: BSSID %pM\n", bss->bssid);
716 pos += ETH_ALEN;
717
718 if ((end - pos) < 12) {
719 lbs_deb_scan("process_bss: Not enough bytes left\n");
720 ret = -1;
721 goto done;
722 }
723
724 /*
725 * next 4 fields are RSSI, time stamp, beacon interval,
726 * and capability information
727 */
728
729 /* RSSI is 1 byte long */
730 bss->rssi = *pos;
731 lbs_deb_scan("process_bss: RSSI %d\n", *pos);
732 pos++;
733
734 /* time stamp is 8 bytes long */
735 pos += 8;
736
737 /* beacon interval is 2 bytes long */
738 bss->beaconperiod = get_unaligned_le16(pos);
739 pos += 2;
740
741 /* capability information is 2 bytes long */
742 bss->capability = get_unaligned_le16(pos);
743 lbs_deb_scan("process_bss: capabilities 0x%04x\n", bss->capability);
744 pos += 2;
745
746 if (bss->capability & WLAN_CAPABILITY_PRIVACY)
747 lbs_deb_scan("process_bss: WEP enabled\n");
748 if (bss->capability & WLAN_CAPABILITY_IBSS)
749 bss->mode = IW_MODE_ADHOC;
750 else
751 bss->mode = IW_MODE_INFRA;
752
753 /* rest of the current buffer are IE's */
754 lbs_deb_scan("process_bss: IE len %zd\n", end - pos);
755 lbs_deb_hex(LBS_DEB_SCAN, "process_bss: IE info", pos, end - pos);
756
757 /* process variable IE */
758 while (pos <= end - 2) {
759 if (pos + pos[1] > end) {
760 lbs_deb_scan("process_bss: error in processing IE, "
761 "bytes left < IE length\n");
762 break;
763 }
764
765 switch (pos[0]) {
766 case WLAN_EID_SSID:
767 bss->ssid_len = min_t(int, IEEE80211_MAX_SSID_LEN, pos[1]);
768 memcpy(bss->ssid, pos + 2, bss->ssid_len);
769 lbs_deb_scan("got SSID IE: '%s', len %u\n",
770 print_ssid(ssid, bss->ssid, bss->ssid_len),
771 bss->ssid_len);
772 break;
773
774 case WLAN_EID_SUPP_RATES:
775 n_basic_rates = min_t(uint8_t, MAX_RATES, pos[1]);
776 memcpy(bss->rates, pos + 2, n_basic_rates);
777 got_basic_rates = 1;
778 lbs_deb_scan("got RATES IE\n");
779 break;
780
781 case WLAN_EID_FH_PARAMS:
782 fh = (struct ieee_ie_fh_param_set *) pos;
783 memcpy(&bss->phy.fh, fh, sizeof(*fh));
784 lbs_deb_scan("got FH IE\n");
785 break;
786
787 case WLAN_EID_DS_PARAMS:
788 ds = (struct ieee_ie_ds_param_set *) pos;
789 bss->channel = ds->channel;
790 memcpy(&bss->phy.ds, ds, sizeof(*ds));
791 lbs_deb_scan("got DS IE, channel %d\n", bss->channel);
792 break;
793
794 case WLAN_EID_CF_PARAMS:
795 cf = (struct ieee_ie_cf_param_set *) pos;
796 memcpy(&bss->ss.cf, cf, sizeof(*cf));
797 lbs_deb_scan("got CF IE\n");
798 break;
799
800 case WLAN_EID_IBSS_PARAMS:
801 ibss = (struct ieee_ie_ibss_param_set *) pos;
802 bss->atimwindow = ibss->atimwindow;
803 memcpy(&bss->ss.ibss, ibss, sizeof(*ibss));
804 lbs_deb_scan("got IBSS IE\n");
805 break;
806
807 case WLAN_EID_EXT_SUPP_RATES:
808 /* only process extended supported rate if data rate is
809 * already found. Data rate IE should come before
810 * extended supported rate IE
811 */
812 lbs_deb_scan("got RATESEX IE\n");
813 if (!got_basic_rates) {
814 lbs_deb_scan("... but ignoring it\n");
815 break;
816 }
817
818 n_ex_rates = pos[1];
819 if (n_basic_rates + n_ex_rates > MAX_RATES)
820 n_ex_rates = MAX_RATES - n_basic_rates;
821
822 p = bss->rates + n_basic_rates;
823 memcpy(p, pos + 2, n_ex_rates);
824 break;
825
826 case WLAN_EID_GENERIC:
827 if (pos[1] >= 4 &&
828 pos[2] == 0x00 && pos[3] == 0x50 &&
829 pos[4] == 0xf2 && pos[5] == 0x01) {
830 bss->wpa_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
831 memcpy(bss->wpa_ie, pos, bss->wpa_ie_len);
832 lbs_deb_scan("got WPA IE\n");
833 lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie,
834 bss->wpa_ie_len);
835 } else if (pos[1] >= MARVELL_MESH_IE_LENGTH &&
836 pos[2] == 0x00 && pos[3] == 0x50 &&
837 pos[4] == 0x43 && pos[5] == 0x04) {
838 lbs_deb_scan("got mesh IE\n");
839 bss->mesh = 1;
840 } else {
841 lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n",
842 pos[2], pos[3],
843 pos[4], pos[5],
844 pos[1]);
845 }
846 break;
847
848 case WLAN_EID_RSN:
849 lbs_deb_scan("got RSN IE\n");
850 bss->rsn_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
851 memcpy(bss->rsn_ie, pos, bss->rsn_ie_len);
852 lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE",
853 bss->rsn_ie, bss->rsn_ie_len);
854 break;
855
856 default:
857 lbs_deb_scan("got IE 0x%04x, len %d\n",
858 pos[0], pos[1]);
859 break;
860 }
861
862 pos += pos[1] + 2;
863 }
864
865 /* Timestamp */
866 bss->last_scanned = jiffies;
867 lbs_unset_basic_rate_flags(bss->rates, sizeof(bss->rates));
868
869 ret = 0;
870
871done:
872 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
873 return ret;
874}
875
876/**
877 * @brief Send a scan command for all available channels filtered on a spec
878 *
879 * Used in association code and from debugfs
880 *
881 * @param priv A pointer to struct lbs_private structure
882 * @param ssid A pointer to the SSID to scan for
883 * @param ssid_len Length of the SSID
884 *
885 * @return 0-success, otherwise fail
886 */
887int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid,
888 uint8_t ssid_len)
889{
890 DECLARE_SSID_BUF(ssid_buf);
891 int ret = 0;
892
893 lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n",
894 print_ssid(ssid_buf, ssid, ssid_len));
895
896 if (!ssid_len)
897 goto out;
898
899 memcpy(priv->scan_ssid, ssid, ssid_len);
900 priv->scan_ssid_len = ssid_len;
901
902 lbs_scan_networks(priv, 1);
903 if (priv->surpriseremoved) {
904 ret = -1;
905 goto out;
906 }
907
908out:
909 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
910 return ret;
911}
912
913
914
915
916/*********************************************************************/
917/* */
918/* Support for Wireless Extensions */
919/* */
920/*********************************************************************/
921
922
923#define MAX_CUSTOM_LEN 64
924
925static inline char *lbs_translate_scan(struct lbs_private *priv,
926 struct iw_request_info *info,
927 char *start, char *stop,
928 struct bss_descriptor *bss)
929{
930 struct chan_freq_power *cfp;
931 char *current_val; /* For rates */
932 struct iw_event iwe; /* Temporary buffer */
933 int j;
934#define PERFECT_RSSI ((uint8_t)50)
935#define WORST_RSSI ((uint8_t)0)
936#define RSSI_DIFF ((uint8_t)(PERFECT_RSSI - WORST_RSSI))
937 uint8_t rssi;
938
939 lbs_deb_enter(LBS_DEB_SCAN);
940
941 cfp = lbs_find_cfp_by_band_and_channel(priv, 0, bss->channel);
942 if (!cfp) {
943 lbs_deb_scan("Invalid channel number %d\n", bss->channel);
944 start = NULL;
945 goto out;
946 }
947
948 /* First entry *MUST* be the BSSID */
949 iwe.cmd = SIOCGIWAP;
950 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
951 memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN);
952 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
953
954 /* SSID */
955 iwe.cmd = SIOCGIWESSID;
956 iwe.u.data.flags = 1;
957 iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IEEE80211_MAX_SSID_LEN);
958 start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
959
960 /* Mode */
961 iwe.cmd = SIOCGIWMODE;
962 iwe.u.mode = bss->mode;
963 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
964
965 /* Frequency */
966 iwe.cmd = SIOCGIWFREQ;
967 iwe.u.freq.m = (long)cfp->freq * 100000;
968 iwe.u.freq.e = 1;
969 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
970
971 /* Add quality statistics */
972 iwe.cmd = IWEVQUAL;
973 iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;
974 iwe.u.qual.level = SCAN_RSSI(bss->rssi);
975
976 rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;
977 iwe.u.qual.qual =
978 (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) *
979 (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) /
980 (RSSI_DIFF * RSSI_DIFF);
981 if (iwe.u.qual.qual > 100)
982 iwe.u.qual.qual = 100;
983
984 if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
985 iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
986 } else {
987 iwe.u.qual.noise = CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
988 }
989
990 /* Locally created ad-hoc BSSs won't have beacons if this is the
991 * only station in the adhoc network; so get signal strength
992 * from receive statistics.
993 */
994 if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate
995 && !lbs_ssid_cmp(priv->curbssparams.ssid,
996 priv->curbssparams.ssid_len,
997 bss->ssid, bss->ssid_len)) {
998 int snr, nf;
999 snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
1000 nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
1001 iwe.u.qual.level = CAL_RSSI(snr, nf);
1002 }
1003 start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
1004
1005 /* Add encryption capability */
1006 iwe.cmd = SIOCGIWENCODE;
1007 if (bss->capability & WLAN_CAPABILITY_PRIVACY) {
1008 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
1009 } else {
1010 iwe.u.data.flags = IW_ENCODE_DISABLED;
1011 }
1012 iwe.u.data.length = 0;
1013 start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid);
1014
1015 current_val = start + iwe_stream_lcp_len(info);
1016
1017 iwe.cmd = SIOCGIWRATE;
1018 iwe.u.bitrate.fixed = 0;
1019 iwe.u.bitrate.disabled = 0;
1020 iwe.u.bitrate.value = 0;
1021
1022 for (j = 0; j < ARRAY_SIZE(bss->rates) && bss->rates[j]; j++) {
1023 /* Bit rate given in 500 kb/s units */
1024 iwe.u.bitrate.value = bss->rates[j] * 500000;
1025 current_val = iwe_stream_add_value(info, start, current_val,
1026 stop, &iwe, IW_EV_PARAM_LEN);
1027 }
1028 if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate
1029 && !lbs_ssid_cmp(priv->curbssparams.ssid,
1030 priv->curbssparams.ssid_len,
1031 bss->ssid, bss->ssid_len)) {
1032 iwe.u.bitrate.value = 22 * 500000;
1033 current_val = iwe_stream_add_value(info, start, current_val,
1034 stop, &iwe, IW_EV_PARAM_LEN);
1035 }
1036 /* Check if we added any event */
1037 if ((current_val - start) > iwe_stream_lcp_len(info))
1038 start = current_val;
1039
1040 memset(&iwe, 0, sizeof(iwe));
1041 if (bss->wpa_ie_len) {
1042 char buf[MAX_WPA_IE_LEN];
1043 memcpy(buf, bss->wpa_ie, bss->wpa_ie_len);
1044 iwe.cmd = IWEVGENIE;
1045 iwe.u.data.length = bss->wpa_ie_len;
1046 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
1047 }
1048
1049 memset(&iwe, 0, sizeof(iwe));
1050 if (bss->rsn_ie_len) {
1051 char buf[MAX_WPA_IE_LEN];
1052 memcpy(buf, bss->rsn_ie, bss->rsn_ie_len);
1053 iwe.cmd = IWEVGENIE;
1054 iwe.u.data.length = bss->rsn_ie_len;
1055 start = iwe_stream_add_point(info, start, stop, &iwe, buf);
1056 }
1057
1058 if (bss->mesh) {
1059 char custom[MAX_CUSTOM_LEN];
1060 char *p = custom;
1061
1062 iwe.cmd = IWEVCUSTOM;
1063 p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc");
1064 iwe.u.data.length = p - custom;
1065 if (iwe.u.data.length)
1066 start = iwe_stream_add_point(info, start, stop,
1067 &iwe, custom);
1068 }
1069
1070out:
1071 lbs_deb_leave_args(LBS_DEB_SCAN, "start %p", start);
1072 return start;
1073}
1074
1075
1076/**
1077 * @brief Handle Scan Network ioctl
1078 *
1079 * @param dev A pointer to net_device structure
1080 * @param info A pointer to iw_request_info structure
1081 * @param vwrq A pointer to iw_param structure
1082 * @param extra A pointer to extra data buf
1083 *
1084 * @return 0 --success, otherwise fail
1085 */
1086int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
1087 union iwreq_data *wrqu, char *extra)
1088{
1089 DECLARE_SSID_BUF(ssid);
1090 struct lbs_private *priv = dev->ml_priv;
1091 int ret = 0;
1092
1093 lbs_deb_enter(LBS_DEB_WEXT);
1094
1095 if (!priv->radio_on) {
1096 ret = -EINVAL;
1097 goto out;
1098 }
1099
1100 if (!netif_running(dev)) {
1101 ret = -ENETDOWN;
1102 goto out;
1103 }
1104
1105 /* mac80211 does this:
1106 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1107 if (sdata->type != IEEE80211_IF_TYPE_xxx) {
1108 ret = -EOPNOTSUPP;
1109 goto out;
1110 }
1111 */
1112
1113 if (wrqu->data.length == sizeof(struct iw_scan_req) &&
1114 wrqu->data.flags & IW_SCAN_THIS_ESSID) {
1115 struct iw_scan_req *req = (struct iw_scan_req *)extra;
1116 priv->scan_ssid_len = req->essid_len;
1117 memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
1118 lbs_deb_wext("set_scan, essid '%s'\n",
1119 print_ssid(ssid, priv->scan_ssid, priv->scan_ssid_len));
1120 } else {
1121 priv->scan_ssid_len = 0;
1122 }
1123
1124 if (!delayed_work_pending(&priv->scan_work))
1125 queue_delayed_work(priv->work_thread, &priv->scan_work,
1126 msecs_to_jiffies(50));
1127 /* set marker that currently a scan is taking place */
1128 priv->scan_channel = -1;
1129
1130 if (priv->surpriseremoved)
1131 ret = -EIO;
1132
1133out:
1134 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1135 return ret;
1136}
1137
1138
1139/**
1140 * @brief Handle Retrieve scan table ioctl
1141 *
1142 * @param dev A pointer to net_device structure
1143 * @param info A pointer to iw_request_info structure
1144 * @param dwrq A pointer to iw_point structure
1145 * @param extra A pointer to extra data buf
1146 *
1147 * @return 0 --success, otherwise fail
1148 */
1149int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
1150 struct iw_point *dwrq, char *extra)
1151{
1152#define SCAN_ITEM_SIZE 128
1153 struct lbs_private *priv = dev->ml_priv;
1154 int err = 0;
1155 char *ev = extra;
1156 char *stop = ev + dwrq->length;
1157 struct bss_descriptor *iter_bss;
1158 struct bss_descriptor *safe;
1159
1160 lbs_deb_enter(LBS_DEB_WEXT);
1161
1162 /* iwlist should wait until the current scan is finished */
1163 if (priv->scan_channel)
1164 return -EAGAIN;
1165
1166 /* Update RSSI if current BSS is a locally created ad-hoc BSS */
1167 if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) {
1168 err = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
1169 CMD_OPTION_WAITFORRSP, 0, NULL);
1170 if (err)
1171 goto out;
1172 }
1173
1174 mutex_lock(&priv->lock);
1175 list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
1176 char *next_ev;
1177 unsigned long stale_time;
1178
1179 if (stop - ev < SCAN_ITEM_SIZE) {
1180 err = -E2BIG;
1181 break;
1182 }
1183
1184 /* For mesh device, list only mesh networks */
1185 if (dev == priv->mesh_dev && !iter_bss->mesh)
1186 continue;
1187
1188 /* Prune old an old scan result */
1189 stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
1190 if (time_after(jiffies, stale_time)) {
1191 list_move_tail(&iter_bss->list, &priv->network_free_list);
1192 clear_bss_descriptor(iter_bss);
1193 continue;
1194 }
1195
1196 /* Translate to WE format this entry */
1197 next_ev = lbs_translate_scan(priv, info, ev, stop, iter_bss);
1198 if (next_ev == NULL)
1199 continue;
1200 ev = next_ev;
1201 }
1202 mutex_unlock(&priv->lock);
1203
1204 dwrq->length = (ev - extra);
1205 dwrq->flags = 0;
1206out:
1207 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err);
1208 return err;
1209}
1210
1211
1212
1213
1214/*********************************************************************/
1215/* */
1216/* Command execution */
1217/* */
1218/*********************************************************************/
1219
1220
1221/**
1222 * @brief This function handles the command response of scan
1223 *
1224 * Called from handle_cmd_response() in cmdrespc.
1225 *
1226 * The response buffer for the scan command has the following
1227 * memory layout:
1228 *
1229 * .-----------------------------------------------------------.
1230 * | header (4 * sizeof(u16)): Standard command response hdr |
1231 * .-----------------------------------------------------------.
1232 * | bufsize (u16) : sizeof the BSS Description data |
1233 * .-----------------------------------------------------------.
1234 * | NumOfSet (u8) : Number of BSS Descs returned |
1235 * .-----------------------------------------------------------.
1236 * | BSSDescription data (variable, size given in bufsize) |
1237 * .-----------------------------------------------------------.
1238 * | TLV data (variable, size calculated using header->size, |
1239 * | bufsize and sizeof the fixed fields above) |
1240 * .-----------------------------------------------------------.
1241 *
1242 * @param priv A pointer to struct lbs_private structure
1243 * @param resp A pointer to cmd_ds_command
1244 *
1245 * @return 0 or -1
1246 */
1247static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
1248 struct cmd_header *resp)
1249{
1250 struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp;
1251 struct bss_descriptor *iter_bss;
1252 struct bss_descriptor *safe;
1253 uint8_t *bssinfo;
1254 uint16_t scanrespsize;
1255 int bytesleft;
1256 int idx;
1257 int tlvbufsize;
1258 int ret;
1259
1260 lbs_deb_enter(LBS_DEB_SCAN);
1261
1262 /* Prune old entries from scan table */
1263 list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) {
1264 unsigned long stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE;
1265 if (time_before(jiffies, stale_time))
1266 continue;
1267 list_move_tail (&iter_bss->list, &priv->network_free_list);
1268 clear_bss_descriptor(iter_bss);
1269 }
1270
1271 if (scanresp->nr_sets > MAX_NETWORK_COUNT) {
1272 lbs_deb_scan("SCAN_RESP: too many scan results (%d, max %d)\n",
1273 scanresp->nr_sets, MAX_NETWORK_COUNT);
1274 ret = -1;
1275 goto done;
1276 }
1277
1278 bytesleft = get_unaligned_le16(&scanresp->bssdescriptsize);
1279 lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);
1280
1281 scanrespsize = le16_to_cpu(resp->size);
1282 lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets);
1283
1284 bssinfo = scanresp->bssdesc_and_tlvbuffer;
1285
1286 /* The size of the TLV buffer is equal to the entire command response
1287 * size (scanrespsize) minus the fixed fields (sizeof()'s), the
1288 * BSS Descriptions (bssdescriptsize as bytesLef) and the command
1289 * response header (sizeof(struct cmd_header))
1290 */
1291 tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize)
1292 + sizeof(scanresp->nr_sets)
1293 + sizeof(struct cmd_header));
1294
1295 /*
1296 * Process each scan response returned (scanresp->nr_sets). Save
1297 * the information in the newbssentry and then insert into the
1298 * driver scan table either as an update to an existing entry
1299 * or as an addition at the end of the table
1300 */
1301 for (idx = 0; idx < scanresp->nr_sets && bytesleft; idx++) {
1302 struct bss_descriptor new;
1303 struct bss_descriptor *found = NULL;
1304 struct bss_descriptor *oldest = NULL;
1305
1306 /* Process the data fields and IEs returned for this BSS */
1307 memset(&new, 0, sizeof (struct bss_descriptor));
1308 if (lbs_process_bss(&new, &bssinfo, &bytesleft) != 0) {
1309 /* error parsing the scan response, skipped */
1310 lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n");
1311 continue;
1312 }
1313
1314 /* Try to find this bss in the scan table */
1315 list_for_each_entry (iter_bss, &priv->network_list, list) {
1316 if (is_same_network(iter_bss, &new)) {
1317 found = iter_bss;
1318 break;
1319 }
1320
1321 if ((oldest == NULL) ||
1322 (iter_bss->last_scanned < oldest->last_scanned))
1323 oldest = iter_bss;
1324 }
1325
1326 if (found) {
1327 /* found, clear it */
1328 clear_bss_descriptor(found);
1329 } else if (!list_empty(&priv->network_free_list)) {
1330 /* Pull one from the free list */
1331 found = list_entry(priv->network_free_list.next,
1332 struct bss_descriptor, list);
1333 list_move_tail(&found->list, &priv->network_list);
1334 } else if (oldest) {
1335 /* If there are no more slots, expire the oldest */
1336 found = oldest;
1337 clear_bss_descriptor(found);
1338 list_move_tail(&found->list, &priv->network_list);
1339 } else {
1340 continue;
1341 }
1342
1343 lbs_deb_scan("SCAN_RESP: BSSID %pM\n", new.bssid);
1344
1345 /* Copy the locally created newbssentry to the scan table */
1346 memcpy(found, &new, offsetof(struct bss_descriptor, list));
1347 }
1348
1349 ret = 0;
1350
1351done:
1352 lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret);
1353 return ret;
1354}
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h
deleted file mode 100644
index 8fb1706d7526..000000000000
--- a/drivers/net/wireless/libertas/scan.h
+++ /dev/null
@@ -1,63 +0,0 @@
1/**
2 * Interface for the wlan network scan routines
3 *
4 * Driver interface functions and type declarations for the scan module
5 * implemented in scan.c.
6 */
7#ifndef _LBS_SCAN_H
8#define _LBS_SCAN_H
9
10#include <net/iw_handler.h>
11
12struct lbs_private;
13
14#define MAX_NETWORK_COUNT 128
15
16/** Chan-freq-TxPower mapping table*/
17struct chan_freq_power {
18 /** channel Number */
19 u16 channel;
20 /** frequency of this channel */
21 u32 freq;
22 /** Max allowed Tx power level */
23 u16 maxtxpower;
24 /** TRUE:channel unsupported; FLASE:supported*/
25 u8 unsupported;
26};
27
28/** region-band mapping table*/
29struct region_channel {
30 /** TRUE if this entry is valid */
31 u8 valid;
32 /** region code for US, Japan ... */
33 u8 region;
34 /** band B/G/A, used for BAND_CONFIG cmd */
35 u8 band;
36 /** Actual No. of elements in the array below */
37 u8 nrcfp;
38 /** chan-freq-txpower mapping table*/
39 struct chan_freq_power *CFP;
40};
41
42/**
43 * @brief Maximum number of channels that can be sent in a setuserscan ioctl
44 */
45#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50
46
47int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len);
48
49int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band);
50
51int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid,
52 u8 ssid_len);
53
54int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
55 struct iw_point *dwrq, char *extra);
56int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
57 union iwreq_data *wrqu, char *extra);
58
59int lbs_scan_networks(struct lbs_private *priv, int full_scan);
60
61void lbs_scan_worker(struct work_struct *work);
62
63#endif
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index a9bf658659eb..8000ca6165d0 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -4,13 +4,13 @@
4#include <linux/netdevice.h> 4#include <linux/netdevice.h>
5#include <linux/etherdevice.h> 5#include <linux/etherdevice.h>
6#include <linux/sched.h> 6#include <linux/sched.h>
7#include <net/cfg80211.h>
7 8
8#include "host.h" 9#include "host.h"
9#include "radiotap.h" 10#include "radiotap.h"
10#include "decl.h" 11#include "decl.h"
11#include "defs.h" 12#include "defs.h"
12#include "dev.h" 13#include "dev.h"
13#include "wext.h"
14 14
15/** 15/**
16 * @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE 16 * @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE
@@ -111,7 +111,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
111 p802x_hdr = skb->data; 111 p802x_hdr = skb->data;
112 pkt_len = skb->len; 112 pkt_len = skb->len;
113 113
114 if (dev == priv->rtap_net_dev) { 114 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
115 struct tx_radiotap_hdr *rtap_hdr = (void *)skb->data; 115 struct tx_radiotap_hdr *rtap_hdr = (void *)skb->data;
116 116
117 /* set txpd fields from the radiotap header */ 117 /* set txpd fields from the radiotap header */
@@ -147,7 +147,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
147 dev->stats.tx_packets++; 147 dev->stats.tx_packets++;
148 dev->stats.tx_bytes += skb->len; 148 dev->stats.tx_bytes += skb->len;
149 149
150 if (priv->monitormode) { 150 if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
151 /* Keep the skb to echo it back once Tx feedback is 151 /* Keep the skb to echo it back once Tx feedback is
152 received from FW */ 152 received from FW */
153 skb_orphan(skb); 153 skb_orphan(skb);
@@ -158,6 +158,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
158 free: 158 free:
159 dev_kfree_skb_any(skb); 159 dev_kfree_skb_any(skb);
160 } 160 }
161
161 unlock: 162 unlock:
162 spin_unlock_irqrestore(&priv->driver_lock, flags); 163 spin_unlock_irqrestore(&priv->driver_lock, flags);
163 wake_up(&priv->waitq); 164 wake_up(&priv->waitq);
@@ -179,7 +180,8 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
179{ 180{
180 struct tx_radiotap_hdr *radiotap_hdr; 181 struct tx_radiotap_hdr *radiotap_hdr;
181 182
182 if (!priv->monitormode || priv->currenttxskb == NULL) 183 if (priv->wdev->iftype != NL80211_IFTYPE_MONITOR ||
184 priv->currenttxskb == NULL)
183 return; 185 return;
184 186
185 radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data; 187 radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data;
@@ -188,7 +190,7 @@ void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count)
188 (1 + priv->txretrycount - try_count) : 0; 190 (1 + priv->txretrycount - try_count) : 0;
189 191
190 priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb, 192 priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb,
191 priv->rtap_net_dev); 193 priv->dev);
192 netif_rx(priv->currenttxskb); 194 netif_rx(priv->currenttxskb);
193 195
194 priv->currenttxskb = NULL; 196 priv->currenttxskb = NULL;
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h
index 3e72c86ceca8..462fbb4cb743 100644
--- a/drivers/net/wireless/libertas/types.h
+++ b/drivers/net/wireless/libertas/types.h
@@ -11,7 +11,7 @@
11struct ieee_ie_header { 11struct ieee_ie_header {
12 u8 id; 12 u8 id;
13 u8 len; 13 u8 len;
14} __attribute__ ((packed)); 14} __packed;
15 15
16struct ieee_ie_cf_param_set { 16struct ieee_ie_cf_param_set {
17 struct ieee_ie_header header; 17 struct ieee_ie_header header;
@@ -20,19 +20,19 @@ struct ieee_ie_cf_param_set {
20 u8 cfpperiod; 20 u8 cfpperiod;
21 __le16 cfpmaxduration; 21 __le16 cfpmaxduration;
22 __le16 cfpdurationremaining; 22 __le16 cfpdurationremaining;
23} __attribute__ ((packed)); 23} __packed;
24 24
25 25
26struct ieee_ie_ibss_param_set { 26struct ieee_ie_ibss_param_set {
27 struct ieee_ie_header header; 27 struct ieee_ie_header header;
28 28
29 __le16 atimwindow; 29 __le16 atimwindow;
30} __attribute__ ((packed)); 30} __packed;
31 31
32union ieee_ss_param_set { 32union ieee_ss_param_set {
33 struct ieee_ie_cf_param_set cf; 33 struct ieee_ie_cf_param_set cf;
34 struct ieee_ie_ibss_param_set ibss; 34 struct ieee_ie_ibss_param_set ibss;
35} __attribute__ ((packed)); 35} __packed;
36 36
37struct ieee_ie_fh_param_set { 37struct ieee_ie_fh_param_set {
38 struct ieee_ie_header header; 38 struct ieee_ie_header header;
@@ -41,18 +41,18 @@ struct ieee_ie_fh_param_set {
41 u8 hopset; 41 u8 hopset;
42 u8 hoppattern; 42 u8 hoppattern;
43 u8 hopindex; 43 u8 hopindex;
44} __attribute__ ((packed)); 44} __packed;
45 45
46struct ieee_ie_ds_param_set { 46struct ieee_ie_ds_param_set {
47 struct ieee_ie_header header; 47 struct ieee_ie_header header;
48 48
49 u8 channel; 49 u8 channel;
50} __attribute__ ((packed)); 50} __packed;
51 51
52union ieee_phy_param_set { 52union ieee_phy_param_set {
53 struct ieee_ie_fh_param_set fh; 53 struct ieee_ie_fh_param_set fh;
54 struct ieee_ie_ds_param_set ds; 54 struct ieee_ie_ds_param_set ds;
55} __attribute__ ((packed)); 55} __packed;
56 56
57/** TLV type ID definition */ 57/** TLV type ID definition */
58#define PROPRIETARY_TLV_BASE_ID 0x0100 58#define PROPRIETARY_TLV_BASE_ID 0x0100
@@ -100,28 +100,28 @@ union ieee_phy_param_set {
100struct mrvl_ie_header { 100struct mrvl_ie_header {
101 __le16 type; 101 __le16 type;
102 __le16 len; 102 __le16 len;
103} __attribute__ ((packed)); 103} __packed;
104 104
105struct mrvl_ie_data { 105struct mrvl_ie_data {
106 struct mrvl_ie_header header; 106 struct mrvl_ie_header header;
107 u8 Data[1]; 107 u8 Data[1];
108} __attribute__ ((packed)); 108} __packed;
109 109
110struct mrvl_ie_rates_param_set { 110struct mrvl_ie_rates_param_set {
111 struct mrvl_ie_header header; 111 struct mrvl_ie_header header;
112 u8 rates[1]; 112 u8 rates[1];
113} __attribute__ ((packed)); 113} __packed;
114 114
115struct mrvl_ie_ssid_param_set { 115struct mrvl_ie_ssid_param_set {
116 struct mrvl_ie_header header; 116 struct mrvl_ie_header header;
117 u8 ssid[1]; 117 u8 ssid[1];
118} __attribute__ ((packed)); 118} __packed;
119 119
120struct mrvl_ie_wildcard_ssid_param_set { 120struct mrvl_ie_wildcard_ssid_param_set {
121 struct mrvl_ie_header header; 121 struct mrvl_ie_header header;
122 u8 MaxSsidlength; 122 u8 MaxSsidlength;
123 u8 ssid[1]; 123 u8 ssid[1];
124} __attribute__ ((packed)); 124} __packed;
125 125
126struct chanscanmode { 126struct chanscanmode {
127#ifdef __BIG_ENDIAN_BITFIELD 127#ifdef __BIG_ENDIAN_BITFIELD
@@ -133,7 +133,7 @@ struct chanscanmode {
133 u8 disablechanfilt:1; 133 u8 disablechanfilt:1;
134 u8 reserved_2_7:6; 134 u8 reserved_2_7:6;
135#endif 135#endif
136} __attribute__ ((packed)); 136} __packed;
137 137
138struct chanscanparamset { 138struct chanscanparamset {
139 u8 radiotype; 139 u8 radiotype;
@@ -141,12 +141,12 @@ struct chanscanparamset {
141 struct chanscanmode chanscanmode; 141 struct chanscanmode chanscanmode;
142 __le16 minscantime; 142 __le16 minscantime;
143 __le16 maxscantime; 143 __le16 maxscantime;
144} __attribute__ ((packed)); 144} __packed;
145 145
146struct mrvl_ie_chanlist_param_set { 146struct mrvl_ie_chanlist_param_set {
147 struct mrvl_ie_header header; 147 struct mrvl_ie_header header;
148 struct chanscanparamset chanscanparam[1]; 148 struct chanscanparamset chanscanparam[1];
149} __attribute__ ((packed)); 149} __packed;
150 150
151struct mrvl_ie_cf_param_set { 151struct mrvl_ie_cf_param_set {
152 struct mrvl_ie_header header; 152 struct mrvl_ie_header header;
@@ -154,86 +154,86 @@ struct mrvl_ie_cf_param_set {
154 u8 cfpperiod; 154 u8 cfpperiod;
155 __le16 cfpmaxduration; 155 __le16 cfpmaxduration;
156 __le16 cfpdurationremaining; 156 __le16 cfpdurationremaining;
157} __attribute__ ((packed)); 157} __packed;
158 158
159struct mrvl_ie_ds_param_set { 159struct mrvl_ie_ds_param_set {
160 struct mrvl_ie_header header; 160 struct mrvl_ie_header header;
161 u8 channel; 161 u8 channel;
162} __attribute__ ((packed)); 162} __packed;
163 163
164struct mrvl_ie_rsn_param_set { 164struct mrvl_ie_rsn_param_set {
165 struct mrvl_ie_header header; 165 struct mrvl_ie_header header;
166 u8 rsnie[1]; 166 u8 rsnie[1];
167} __attribute__ ((packed)); 167} __packed;
168 168
169struct mrvl_ie_tsf_timestamp { 169struct mrvl_ie_tsf_timestamp {
170 struct mrvl_ie_header header; 170 struct mrvl_ie_header header;
171 __le64 tsftable[1]; 171 __le64 tsftable[1];
172} __attribute__ ((packed)); 172} __packed;
173 173
174/* v9 and later firmware only */ 174/* v9 and later firmware only */
175struct mrvl_ie_auth_type { 175struct mrvl_ie_auth_type {
176 struct mrvl_ie_header header; 176 struct mrvl_ie_header header;
177 __le16 auth; 177 __le16 auth;
178} __attribute__ ((packed)); 178} __packed;
179 179
180/** Local Power capability */ 180/** Local Power capability */
181struct mrvl_ie_power_capability { 181struct mrvl_ie_power_capability {
182 struct mrvl_ie_header header; 182 struct mrvl_ie_header header;
183 s8 minpower; 183 s8 minpower;
184 s8 maxpower; 184 s8 maxpower;
185} __attribute__ ((packed)); 185} __packed;
186 186
187/* used in CMD_802_11_SUBSCRIBE_EVENT for SNR, RSSI and Failure */ 187/* used in CMD_802_11_SUBSCRIBE_EVENT for SNR, RSSI and Failure */
188struct mrvl_ie_thresholds { 188struct mrvl_ie_thresholds {
189 struct mrvl_ie_header header; 189 struct mrvl_ie_header header;
190 u8 value; 190 u8 value;
191 u8 freq; 191 u8 freq;
192} __attribute__ ((packed)); 192} __packed;
193 193
194struct mrvl_ie_beacons_missed { 194struct mrvl_ie_beacons_missed {
195 struct mrvl_ie_header header; 195 struct mrvl_ie_header header;
196 u8 beaconmissed; 196 u8 beaconmissed;
197 u8 reserved; 197 u8 reserved;
198} __attribute__ ((packed)); 198} __packed;
199 199
200struct mrvl_ie_num_probes { 200struct mrvl_ie_num_probes {
201 struct mrvl_ie_header header; 201 struct mrvl_ie_header header;
202 __le16 numprobes; 202 __le16 numprobes;
203} __attribute__ ((packed)); 203} __packed;
204 204
205struct mrvl_ie_bcast_probe { 205struct mrvl_ie_bcast_probe {
206 struct mrvl_ie_header header; 206 struct mrvl_ie_header header;
207 __le16 bcastprobe; 207 __le16 bcastprobe;
208} __attribute__ ((packed)); 208} __packed;
209 209
210struct mrvl_ie_num_ssid_probe { 210struct mrvl_ie_num_ssid_probe {
211 struct mrvl_ie_header header; 211 struct mrvl_ie_header header;
212 __le16 numssidprobe; 212 __le16 numssidprobe;
213} __attribute__ ((packed)); 213} __packed;
214 214
215struct led_pin { 215struct led_pin {
216 u8 led; 216 u8 led;
217 u8 pin; 217 u8 pin;
218} __attribute__ ((packed)); 218} __packed;
219 219
220struct mrvl_ie_ledgpio { 220struct mrvl_ie_ledgpio {
221 struct mrvl_ie_header header; 221 struct mrvl_ie_header header;
222 struct led_pin ledpin[1]; 222 struct led_pin ledpin[1];
223} __attribute__ ((packed)); 223} __packed;
224 224
225struct led_bhv { 225struct led_bhv {
226 uint8_t firmwarestate; 226 uint8_t firmwarestate;
227 uint8_t led; 227 uint8_t led;
228 uint8_t ledstate; 228 uint8_t ledstate;
229 uint8_t ledarg; 229 uint8_t ledarg;
230} __attribute__ ((packed)); 230} __packed;
231 231
232 232
233struct mrvl_ie_ledbhv { 233struct mrvl_ie_ledbhv {
234 struct mrvl_ie_header header; 234 struct mrvl_ie_header header;
235 struct led_bhv ledbhv[1]; 235 struct led_bhv ledbhv[1];
236} __attribute__ ((packed)); 236} __packed;
237 237
238/* Meant to be packed as the value member of a struct ieee80211_info_element. 238/* Meant to be packed as the value member of a struct ieee80211_info_element.
239 * Note that the len member of the ieee80211_info_element varies depending on 239 * Note that the len member of the ieee80211_info_element varies depending on
@@ -248,12 +248,12 @@ struct mrvl_meshie_val {
248 uint8_t mesh_capability; 248 uint8_t mesh_capability;
249 uint8_t mesh_id_len; 249 uint8_t mesh_id_len;
250 uint8_t mesh_id[IEEE80211_MAX_SSID_LEN]; 250 uint8_t mesh_id[IEEE80211_MAX_SSID_LEN];
251} __attribute__ ((packed)); 251} __packed;
252 252
253struct mrvl_meshie { 253struct mrvl_meshie {
254 u8 id, len; 254 u8 id, len;
255 struct mrvl_meshie_val val; 255 struct mrvl_meshie_val val;
256} __attribute__ ((packed)); 256} __packed;
257 257
258struct mrvl_mesh_defaults { 258struct mrvl_mesh_defaults {
259 __le32 bootflag; 259 __le32 bootflag;
@@ -261,6 +261,6 @@ struct mrvl_mesh_defaults {
261 uint8_t reserved; 261 uint8_t reserved;
262 __le16 channel; 262 __le16 channel;
263 struct mrvl_meshie meshie; 263 struct mrvl_meshie meshie;
264} __attribute__ ((packed)); 264} __packed;
265 265
266#endif 266#endif
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
deleted file mode 100644
index f96a96031a50..000000000000
--- a/drivers/net/wireless/libertas/wext.c
+++ /dev/null
@@ -1,2353 +0,0 @@
1/**
2 * This file contains ioctl functions
3 */
4#include <linux/ctype.h>
5#include <linux/slab.h>
6#include <linux/delay.h>
7#include <linux/if.h>
8#include <linux/if_arp.h>
9#include <linux/wireless.h>
10#include <linux/bitops.h>
11
12#include <net/lib80211.h>
13#include <net/iw_handler.h>
14
15#include "host.h"
16#include "radiotap.h"
17#include "decl.h"
18#include "defs.h"
19#include "dev.h"
20#include "wext.h"
21#include "scan.h"
22#include "assoc.h"
23#include "cmd.h"
24
25
26static inline void lbs_postpone_association_work(struct lbs_private *priv)
27{
28 if (priv->surpriseremoved)
29 return;
30 cancel_delayed_work(&priv->assoc_work);
31 queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2);
32}
33
34static inline void lbs_do_association_work(struct lbs_private *priv)
35{
36 if (priv->surpriseremoved)
37 return;
38 cancel_delayed_work(&priv->assoc_work);
39 queue_delayed_work(priv->work_thread, &priv->assoc_work, 0);
40}
41
42static inline void lbs_cancel_association_work(struct lbs_private *priv)
43{
44 cancel_delayed_work(&priv->assoc_work);
45 kfree(priv->pending_assoc_req);
46 priv->pending_assoc_req = NULL;
47}
48
49void lbs_send_disconnect_notification(struct lbs_private *priv)
50{
51 union iwreq_data wrqu;
52
53 memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
54 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
55 wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
56}
57
58static void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str)
59{
60 union iwreq_data iwrq;
61 u8 buf[50];
62
63 lbs_deb_enter(LBS_DEB_WEXT);
64
65 memset(&iwrq, 0, sizeof(union iwreq_data));
66 memset(buf, 0, sizeof(buf));
67
68 snprintf(buf, sizeof(buf) - 1, "%s", str);
69
70 iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
71
72 /* Send Event to upper layer */
73 lbs_deb_wext("event indication string %s\n", (char *)buf);
74 lbs_deb_wext("event indication length %d\n", iwrq.data.length);
75 lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str);
76
77 wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf);
78
79 lbs_deb_leave(LBS_DEB_WEXT);
80}
81
82/**
83 * @brief This function handles MIC failure event.
84 *
85 * @param priv A pointer to struct lbs_private structure
86 * @para event the event id
87 * @return n/a
88 */
89void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event)
90{
91 char buf[50];
92
93 lbs_deb_enter(LBS_DEB_CMD);
94 memset(buf, 0, sizeof(buf));
95
96 sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
97
98 if (event == MACREG_INT_CODE_MIC_ERR_UNICAST)
99 strcat(buf, "unicast ");
100 else
101 strcat(buf, "multicast ");
102
103 lbs_send_iwevcustom_event(priv, buf);
104 lbs_deb_leave(LBS_DEB_CMD);
105}
106
107/**
108 * @brief Find the channel frequency power info with specific channel
109 *
110 * @param priv A pointer to struct lbs_private structure
111 * @param band it can be BAND_A, BAND_G or BAND_B
112 * @param channel the channel for looking
113 * @return A pointer to struct chan_freq_power structure or NULL if not find.
114 */
115struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
116 struct lbs_private *priv,
117 u8 band,
118 u16 channel)
119{
120 struct chan_freq_power *cfp = NULL;
121 struct region_channel *rc;
122 int i, j;
123
124 for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
125 rc = &priv->region_channel[j];
126
127 if (!rc->valid || !rc->CFP)
128 continue;
129 if (rc->band != band)
130 continue;
131 for (i = 0; i < rc->nrcfp; i++) {
132 if (rc->CFP[i].channel == channel) {
133 cfp = &rc->CFP[i];
134 break;
135 }
136 }
137 }
138
139 if (!cfp && channel)
140 lbs_deb_wext("lbs_find_cfp_by_band_and_channel: can't find "
141 "cfp by band %d / channel %d\n", band, channel);
142
143 return cfp;
144}
145
146/**
147 * @brief Find the channel frequency power info with specific frequency
148 *
149 * @param priv A pointer to struct lbs_private structure
150 * @param band it can be BAND_A, BAND_G or BAND_B
151 * @param freq the frequency for looking
152 * @return A pointer to struct chan_freq_power structure or NULL if not find.
153 */
154static struct chan_freq_power *find_cfp_by_band_and_freq(
155 struct lbs_private *priv,
156 u8 band,
157 u32 freq)
158{
159 struct chan_freq_power *cfp = NULL;
160 struct region_channel *rc;
161 int i, j;
162
163 for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) {
164 rc = &priv->region_channel[j];
165
166 if (!rc->valid || !rc->CFP)
167 continue;
168 if (rc->band != band)
169 continue;
170 for (i = 0; i < rc->nrcfp; i++) {
171 if (rc->CFP[i].freq == freq) {
172 cfp = &rc->CFP[i];
173 break;
174 }
175 }
176 }
177
178 if (!cfp && freq)
179 lbs_deb_wext("find_cfp_by_band_and_freql: can't find cfp by "
180 "band %d / freq %d\n", band, freq);
181
182 return cfp;
183}
184
185/**
186 * @brief Copy active data rates based on adapter mode and status
187 *
188 * @param priv A pointer to struct lbs_private structure
189 * @param rate The buf to return the active rates
190 */
191static void copy_active_data_rates(struct lbs_private *priv, u8 *rates)
192{
193 lbs_deb_enter(LBS_DEB_WEXT);
194
195 if ((priv->connect_status != LBS_CONNECTED) &&
196 !lbs_mesh_connected(priv))
197 memcpy(rates, lbs_bg_rates, MAX_RATES);
198 else
199 memcpy(rates, priv->curbssparams.rates, MAX_RATES);
200
201 lbs_deb_leave(LBS_DEB_WEXT);
202}
203
204static int lbs_get_name(struct net_device *dev, struct iw_request_info *info,
205 char *cwrq, char *extra)
206{
207
208 lbs_deb_enter(LBS_DEB_WEXT);
209
210 /* We could add support for 802.11n here as needed. Jean II */
211 snprintf(cwrq, IFNAMSIZ, "IEEE 802.11b/g");
212
213 lbs_deb_leave(LBS_DEB_WEXT);
214 return 0;
215}
216
217static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
218 struct iw_freq *fwrq, char *extra)
219{
220 struct lbs_private *priv = dev->ml_priv;
221 struct chan_freq_power *cfp;
222
223 lbs_deb_enter(LBS_DEB_WEXT);
224
225 cfp = lbs_find_cfp_by_band_and_channel(priv, 0,
226 priv->channel);
227
228 if (!cfp) {
229 if (priv->channel)
230 lbs_deb_wext("invalid channel %d\n",
231 priv->channel);
232 return -EINVAL;
233 }
234
235 fwrq->m = (long)cfp->freq * 100000;
236 fwrq->e = 1;
237
238 lbs_deb_wext("freq %u\n", fwrq->m);
239 lbs_deb_leave(LBS_DEB_WEXT);
240 return 0;
241}
242
243static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info,
244 struct sockaddr *awrq, char *extra)
245{
246 struct lbs_private *priv = dev->ml_priv;
247
248 lbs_deb_enter(LBS_DEB_WEXT);
249
250 if (priv->connect_status == LBS_CONNECTED) {
251 memcpy(awrq->sa_data, priv->curbssparams.bssid, ETH_ALEN);
252 } else {
253 memset(awrq->sa_data, 0, ETH_ALEN);
254 }
255 awrq->sa_family = ARPHRD_ETHER;
256
257 lbs_deb_leave(LBS_DEB_WEXT);
258 return 0;
259}
260
261static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info,
262 struct iw_point *dwrq, char *extra)
263{
264 struct lbs_private *priv = dev->ml_priv;
265
266 lbs_deb_enter(LBS_DEB_WEXT);
267
268 /*
269 * Check the size of the string
270 */
271
272 if (dwrq->length > 16) {
273 return -E2BIG;
274 }
275
276 mutex_lock(&priv->lock);
277 memset(priv->nodename, 0, sizeof(priv->nodename));
278 memcpy(priv->nodename, extra, dwrq->length);
279 mutex_unlock(&priv->lock);
280
281 lbs_deb_leave(LBS_DEB_WEXT);
282 return 0;
283}
284
285static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info,
286 struct iw_point *dwrq, char *extra)
287{
288 struct lbs_private *priv = dev->ml_priv;
289
290 lbs_deb_enter(LBS_DEB_WEXT);
291
292 dwrq->length = strlen(priv->nodename);
293 memcpy(extra, priv->nodename, dwrq->length);
294 extra[dwrq->length] = '\0';
295
296 dwrq->flags = 1; /* active */
297
298 lbs_deb_leave(LBS_DEB_WEXT);
299 return 0;
300}
301
302#ifdef CONFIG_LIBERTAS_MESH
303static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
304 struct iw_point *dwrq, char *extra)
305{
306 struct lbs_private *priv = dev->ml_priv;
307
308 lbs_deb_enter(LBS_DEB_WEXT);
309
310 /* Use nickname to indicate that mesh is on */
311
312 if (lbs_mesh_connected(priv)) {
313 strncpy(extra, "Mesh", 12);
314 extra[12] = '\0';
315 dwrq->length = strlen(extra);
316 }
317
318 else {
319 extra[0] = '\0';
320 dwrq->length = 0;
321 }
322
323 lbs_deb_leave(LBS_DEB_WEXT);
324 return 0;
325}
326#endif
327
328static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
329 struct iw_param *vwrq, char *extra)
330{
331 int ret = 0;
332 struct lbs_private *priv = dev->ml_priv;
333 u32 val = vwrq->value;
334
335 lbs_deb_enter(LBS_DEB_WEXT);
336
337 if (vwrq->disabled)
338 val = MRVDRV_RTS_MAX_VALUE;
339
340 if (val > MRVDRV_RTS_MAX_VALUE) /* min rts value is 0 */
341 return -EINVAL;
342
343 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, (u16) val);
344
345 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
346 return ret;
347}
348
349static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
350 struct iw_param *vwrq, char *extra)
351{
352 struct lbs_private *priv = dev->ml_priv;
353 int ret = 0;
354 u16 val = 0;
355
356 lbs_deb_enter(LBS_DEB_WEXT);
357
358 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val);
359 if (ret)
360 goto out;
361
362 vwrq->value = val;
363 vwrq->disabled = val > MRVDRV_RTS_MAX_VALUE; /* min rts value is 0 */
364 vwrq->fixed = 1;
365
366out:
367 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
368 return ret;
369}
370
371static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
372 struct iw_param *vwrq, char *extra)
373{
374 struct lbs_private *priv = dev->ml_priv;
375 int ret = 0;
376 u32 val = vwrq->value;
377
378 lbs_deb_enter(LBS_DEB_WEXT);
379
380 if (vwrq->disabled)
381 val = MRVDRV_FRAG_MAX_VALUE;
382
383 if (val < MRVDRV_FRAG_MIN_VALUE || val > MRVDRV_FRAG_MAX_VALUE)
384 return -EINVAL;
385
386 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, (u16) val);
387
388 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
389 return ret;
390}
391
392static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info,
393 struct iw_param *vwrq, char *extra)
394{
395 struct lbs_private *priv = dev->ml_priv;
396 int ret = 0;
397 u16 val = 0;
398
399 lbs_deb_enter(LBS_DEB_WEXT);
400
401 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val);
402 if (ret)
403 goto out;
404
405 vwrq->value = val;
406 vwrq->disabled = ((val < MRVDRV_FRAG_MIN_VALUE)
407 || (val > MRVDRV_FRAG_MAX_VALUE));
408 vwrq->fixed = 1;
409
410out:
411 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
412 return ret;
413}
414
415static int lbs_get_mode(struct net_device *dev,
416 struct iw_request_info *info, u32 * uwrq, char *extra)
417{
418 struct lbs_private *priv = dev->ml_priv;
419
420 lbs_deb_enter(LBS_DEB_WEXT);
421
422 *uwrq = priv->mode;
423
424 lbs_deb_leave(LBS_DEB_WEXT);
425 return 0;
426}
427
428#ifdef CONFIG_LIBERTAS_MESH
429static int mesh_wlan_get_mode(struct net_device *dev,
430 struct iw_request_info *info, u32 * uwrq,
431 char *extra)
432{
433 lbs_deb_enter(LBS_DEB_WEXT);
434
435 *uwrq = IW_MODE_REPEAT;
436
437 lbs_deb_leave(LBS_DEB_WEXT);
438 return 0;
439}
440#endif
441
442static int lbs_get_txpow(struct net_device *dev,
443 struct iw_request_info *info,
444 struct iw_param *vwrq, char *extra)
445{
446 struct lbs_private *priv = dev->ml_priv;
447 s16 curlevel = 0;
448 int ret = 0;
449
450 lbs_deb_enter(LBS_DEB_WEXT);
451
452 if (!priv->radio_on) {
453 lbs_deb_wext("tx power off\n");
454 vwrq->value = 0;
455 vwrq->disabled = 1;
456 goto out;
457 }
458
459 ret = lbs_get_tx_power(priv, &curlevel, NULL, NULL);
460 if (ret)
461 goto out;
462
463 lbs_deb_wext("tx power level %d dbm\n", curlevel);
464 priv->txpower_cur = curlevel;
465
466 vwrq->value = curlevel;
467 vwrq->fixed = 1;
468 vwrq->disabled = 0;
469 vwrq->flags = IW_TXPOW_DBM;
470
471out:
472 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
473 return ret;
474}
475
476static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info,
477 struct iw_param *vwrq, char *extra)
478{
479 struct lbs_private *priv = dev->ml_priv;
480 int ret = 0;
481 u16 slimit = 0, llimit = 0;
482
483 lbs_deb_enter(LBS_DEB_WEXT);
484
485 if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
486 return -EOPNOTSUPP;
487
488 /* The MAC has a 4-bit Total_Tx_Count register
489 Total_Tx_Count = 1 + Tx_Retry_Count */
490#define TX_RETRY_MIN 0
491#define TX_RETRY_MAX 14
492 if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX)
493 return -EINVAL;
494
495 /* Add 1 to convert retry count to try count */
496 if (vwrq->flags & IW_RETRY_SHORT)
497 slimit = (u16) (vwrq->value + 1);
498 else if (vwrq->flags & IW_RETRY_LONG)
499 llimit = (u16) (vwrq->value + 1);
500 else
501 slimit = llimit = (u16) (vwrq->value + 1); /* set both */
502
503 if (llimit) {
504 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT,
505 llimit);
506 if (ret)
507 goto out;
508 }
509
510 if (slimit) {
511 /* txretrycount follows the short retry limit */
512 priv->txretrycount = slimit;
513 ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT,
514 slimit);
515 if (ret)
516 goto out;
517 }
518
519out:
520 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
521 return ret;
522}
523
524static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info,
525 struct iw_param *vwrq, char *extra)
526{
527 struct lbs_private *priv = dev->ml_priv;
528 int ret = 0;
529 u16 val = 0;
530
531 lbs_deb_enter(LBS_DEB_WEXT);
532
533 vwrq->disabled = 0;
534
535 if (vwrq->flags & IW_RETRY_LONG) {
536 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT, &val);
537 if (ret)
538 goto out;
539
540 /* Subtract 1 to convert try count to retry count */
541 vwrq->value = val - 1;
542 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
543 } else {
544 ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT, &val);
545 if (ret)
546 goto out;
547
548 /* txretry count follows the short retry limit */
549 priv->txretrycount = val;
550 /* Subtract 1 to convert try count to retry count */
551 vwrq->value = val - 1;
552 vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT;
553 }
554
555out:
556 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
557 return ret;
558}
559
560static inline void sort_channels(struct iw_freq *freq, int num)
561{
562 int i, j;
563 struct iw_freq temp;
564
565 for (i = 0; i < num; i++)
566 for (j = i + 1; j < num; j++)
567 if (freq[i].i > freq[j].i) {
568 temp.i = freq[i].i;
569 temp.m = freq[i].m;
570
571 freq[i].i = freq[j].i;
572 freq[i].m = freq[j].m;
573
574 freq[j].i = temp.i;
575 freq[j].m = temp.m;
576 }
577}
578
579/* data rate listing
580 MULTI_BANDS:
581 abg a b b/g
582 Infra G(12) A(8) B(4) G(12)
583 Adhoc A+B(12) A(8) B(4) B(4)
584
585 non-MULTI_BANDS:
586 b b/g
587 Infra B(4) G(12)
588 Adhoc B(4) B(4)
589 */
590/**
591 * @brief Get Range Info
592 *
593 * @param dev A pointer to net_device structure
594 * @param info A pointer to iw_request_info structure
595 * @param vwrq A pointer to iw_param structure
596 * @param extra A pointer to extra data buf
597 * @return 0 --success, otherwise fail
598 */
599static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
600 struct iw_point *dwrq, char *extra)
601{
602 int i, j;
603 struct lbs_private *priv = dev->ml_priv;
604 struct iw_range *range = (struct iw_range *)extra;
605 struct chan_freq_power *cfp;
606 u8 rates[MAX_RATES + 1];
607
608 lbs_deb_enter(LBS_DEB_WEXT);
609
610 dwrq->length = sizeof(struct iw_range);
611 memset(range, 0, sizeof(struct iw_range));
612
613 range->min_nwid = 0;
614 range->max_nwid = 0;
615
616 memset(rates, 0, sizeof(rates));
617 copy_active_data_rates(priv, rates);
618 range->num_bitrates = strnlen(rates, IW_MAX_BITRATES);
619 for (i = 0; i < range->num_bitrates; i++)
620 range->bitrate[i] = rates[i] * 500000;
621 range->num_bitrates = i;
622 lbs_deb_wext("IW_MAX_BITRATES %d, num_bitrates %d\n", IW_MAX_BITRATES,
623 range->num_bitrates);
624
625 range->num_frequency = 0;
626
627 range->scan_capa = IW_SCAN_CAPA_ESSID;
628
629 for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
630 && (j < ARRAY_SIZE(priv->region_channel)); j++) {
631 cfp = priv->region_channel[j].CFP;
632 for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
633 && priv->region_channel[j].valid
634 && cfp
635 && (i < priv->region_channel[j].nrcfp); i++) {
636 range->freq[range->num_frequency].i =
637 (long)cfp->channel;
638 range->freq[range->num_frequency].m =
639 (long)cfp->freq * 100000;
640 range->freq[range->num_frequency].e = 1;
641 cfp++;
642 range->num_frequency++;
643 }
644 }
645
646 lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n",
647 IW_MAX_FREQUENCIES, range->num_frequency);
648
649 range->num_channels = range->num_frequency;
650
651 sort_channels(&range->freq[0], range->num_frequency);
652
653 /*
654 * Set an indication of the max TCP throughput in bit/s that we can
655 * expect using this interface
656 */
657 if (i > 2)
658 range->throughput = 5000 * 1000;
659 else
660 range->throughput = 1500 * 1000;
661
662 range->min_rts = MRVDRV_RTS_MIN_VALUE;
663 range->max_rts = MRVDRV_RTS_MAX_VALUE;
664 range->min_frag = MRVDRV_FRAG_MIN_VALUE;
665 range->max_frag = MRVDRV_FRAG_MAX_VALUE;
666
667 range->encoding_size[0] = 5;
668 range->encoding_size[1] = 13;
669 range->num_encoding_sizes = 2;
670 range->max_encoding_tokens = 4;
671
672 /*
673 * Right now we support only "iwconfig ethX power on|off"
674 */
675 range->pm_capa = IW_POWER_ON;
676
677 /*
678 * Minimum version we recommend
679 */
680 range->we_version_source = 15;
681
682 /*
683 * Version we are compiled with
684 */
685 range->we_version_compiled = WIRELESS_EXT;
686
687 range->retry_capa = IW_RETRY_LIMIT;
688 range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
689
690 range->min_retry = TX_RETRY_MIN;
691 range->max_retry = TX_RETRY_MAX;
692
693 /*
694 * Set the qual, level and noise range values
695 */
696 range->max_qual.qual = 100;
697 range->max_qual.level = 0;
698 range->max_qual.noise = 0;
699 range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
700
701 range->avg_qual.qual = 70;
702 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
703 range->avg_qual.level = 0;
704 range->avg_qual.noise = 0;
705 range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
706
707 range->sensitivity = 0;
708
709 /* Setup the supported power level ranges */
710 memset(range->txpower, 0, sizeof(range->txpower));
711 range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE;
712 range->txpower[0] = priv->txpower_min;
713 range->txpower[1] = priv->txpower_max;
714 range->num_txpower = 2;
715
716 range->event_capa[0] = (IW_EVENT_CAPA_K_0 |
717 IW_EVENT_CAPA_MASK(SIOCGIWAP) |
718 IW_EVENT_CAPA_MASK(SIOCGIWSCAN));
719 range->event_capa[1] = IW_EVENT_CAPA_K_1;
720
721 if (priv->fwcapinfo & FW_CAPINFO_WPA) {
722 range->enc_capa = IW_ENC_CAPA_WPA
723 | IW_ENC_CAPA_WPA2
724 | IW_ENC_CAPA_CIPHER_TKIP
725 | IW_ENC_CAPA_CIPHER_CCMP;
726 }
727
728 lbs_deb_leave(LBS_DEB_WEXT);
729 return 0;
730}
731
732static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
733 struct iw_param *vwrq, char *extra)
734{
735 struct lbs_private *priv = dev->ml_priv;
736 int ret = 0;
737
738 lbs_deb_enter(LBS_DEB_WEXT);
739
740 if (!(priv->fwcapinfo & FW_CAPINFO_PS)) {
741 if (vwrq->disabled)
742 return 0;
743 else
744 return -EINVAL;
745 }
746
747 /* PS is currently supported only in Infrastructure mode
748 * Remove this check if it is to be supported in IBSS mode also
749 */
750
751 if (vwrq->disabled) {
752 priv->psmode = LBS802_11POWERMODECAM;
753 if (priv->psstate != PS_STATE_FULL_POWER) {
754 lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP);
755 }
756
757 return 0;
758 }
759
760 if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
761 lbs_deb_wext(
762 "setting power timeout is not supported\n");
763 return -EINVAL;
764 } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
765 vwrq->value = vwrq->value / 1000;
766 if (!priv->enter_deep_sleep) {
767 lbs_pr_err("deep sleep feature is not implemented "
768 "for this interface driver\n");
769 return -EINVAL;
770 }
771
772 if (priv->connect_status == LBS_CONNECTED) {
773 if ((priv->is_auto_deep_sleep_enabled) &&
774 (vwrq->value == -1000)) {
775 lbs_exit_auto_deep_sleep(priv);
776 return 0;
777 } else {
778 lbs_pr_err("can't use deep sleep cmd in "
779 "connected state\n");
780 return -EINVAL;
781 }
782 }
783
784 if ((vwrq->value < 0) && (vwrq->value != -1000)) {
785 lbs_pr_err("unknown option\n");
786 return -EINVAL;
787 }
788
789 if (vwrq->value > 0) {
790 if (!priv->is_auto_deep_sleep_enabled) {
791 priv->is_activity_detected = 0;
792 priv->auto_deep_sleep_timeout = vwrq->value;
793 lbs_enter_auto_deep_sleep(priv);
794 } else {
795 priv->auto_deep_sleep_timeout = vwrq->value;
796 lbs_deb_debugfs("auto deep sleep: "
797 "already enabled\n");
798 }
799 return 0;
800 } else {
801 if (priv->is_auto_deep_sleep_enabled) {
802 lbs_exit_auto_deep_sleep(priv);
803 /* Try to exit deep sleep if auto */
804 /*deep sleep disabled */
805 ret = lbs_set_deep_sleep(priv, 0);
806 }
807 if (vwrq->value == 0)
808 ret = lbs_set_deep_sleep(priv, 1);
809 else if (vwrq->value == -1000)
810 ret = lbs_set_deep_sleep(priv, 0);
811 return ret;
812 }
813 }
814
815 if (priv->psmode != LBS802_11POWERMODECAM) {
816 return 0;
817 }
818
819 priv->psmode = LBS802_11POWERMODEMAX_PSP;
820
821 if (priv->connect_status == LBS_CONNECTED) {
822 lbs_ps_sleep(priv, CMD_OPTION_WAITFORRSP);
823 }
824
825 lbs_deb_leave(LBS_DEB_WEXT);
826
827 return 0;
828}
829
830static int lbs_get_power(struct net_device *dev, struct iw_request_info *info,
831 struct iw_param *vwrq, char *extra)
832{
833 struct lbs_private *priv = dev->ml_priv;
834
835 lbs_deb_enter(LBS_DEB_WEXT);
836
837 vwrq->value = 0;
838 vwrq->flags = 0;
839 vwrq->disabled = priv->psmode == LBS802_11POWERMODECAM
840 || priv->connect_status == LBS_DISCONNECTED;
841
842 lbs_deb_leave(LBS_DEB_WEXT);
843 return 0;
844}
845
846static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
847{
848 enum {
849 POOR = 30,
850 FAIR = 60,
851 GOOD = 80,
852 VERY_GOOD = 90,
853 EXCELLENT = 95,
854 PERFECT = 100
855 };
856 struct lbs_private *priv = dev->ml_priv;
857 u32 rssi_qual;
858 u32 tx_qual;
859 u32 quality = 0;
860 int ret, stats_valid = 0;
861 u8 rssi;
862 u32 tx_retries;
863 struct cmd_ds_802_11_get_log log;
864
865 lbs_deb_enter(LBS_DEB_WEXT);
866
867 priv->wstats.status = priv->mode;
868
869 /* If we're not associated, all quality values are meaningless */
870 if ((priv->connect_status != LBS_CONNECTED) &&
871 !lbs_mesh_connected(priv))
872 goto out;
873
874 /* Quality by RSSI */
875 priv->wstats.qual.level =
876 CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
877 priv->NF[TYPE_BEACON][TYPE_NOAVG]);
878
879 if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
880 priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
881 } else {
882 priv->wstats.qual.noise =
883 CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
884 }
885
886 lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level);
887 lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise);
888
889 rssi = priv->wstats.qual.level - priv->wstats.qual.noise;
890 if (rssi < 15)
891 rssi_qual = rssi * POOR / 10;
892 else if (rssi < 20)
893 rssi_qual = (rssi - 15) * (FAIR - POOR) / 5 + POOR;
894 else if (rssi < 30)
895 rssi_qual = (rssi - 20) * (GOOD - FAIR) / 5 + FAIR;
896 else if (rssi < 40)
897 rssi_qual = (rssi - 30) * (VERY_GOOD - GOOD) /
898 10 + GOOD;
899 else
900 rssi_qual = (rssi - 40) * (PERFECT - VERY_GOOD) /
901 10 + VERY_GOOD;
902 quality = rssi_qual;
903
904 /* Quality by TX errors */
905 priv->wstats.discard.retries = dev->stats.tx_errors;
906
907 memset(&log, 0, sizeof(log));
908 log.hdr.size = cpu_to_le16(sizeof(log));
909 ret = lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
910 if (ret)
911 goto out;
912
913 tx_retries = le32_to_cpu(log.retry);
914
915 if (tx_retries > 75)
916 tx_qual = (90 - tx_retries) * POOR / 15;
917 else if (tx_retries > 70)
918 tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR;
919 else if (tx_retries > 65)
920 tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR;
921 else if (tx_retries > 50)
922 tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) /
923 15 + GOOD;
924 else
925 tx_qual = (50 - tx_retries) *
926 (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
927 quality = min(quality, tx_qual);
928
929 priv->wstats.discard.code = le32_to_cpu(log.wepundecryptable);
930 priv->wstats.discard.retries = tx_retries;
931 priv->wstats.discard.misc = le32_to_cpu(log.ackfailure);
932
933 /* Calculate quality */
934 priv->wstats.qual.qual = min_t(u8, quality, 100);
935 priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
936 stats_valid = 1;
937
938 /* update stats asynchronously for future calls */
939 ret = lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
940 0, 0, NULL);
941 if (ret)
942 lbs_pr_err("RSSI command failed\n");
943out:
944 if (!stats_valid) {
945 priv->wstats.miss.beacon = 0;
946 priv->wstats.discard.retries = 0;
947 priv->wstats.qual.qual = 0;
948 priv->wstats.qual.level = 0;
949 priv->wstats.qual.noise = 0;
950 priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED;
951 priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID |
952 IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
953 }
954
955 lbs_deb_leave(LBS_DEB_WEXT);
956 return &priv->wstats;
957
958
959}
960
961static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info,
962 struct iw_freq *fwrq, char *extra)
963{
964 int ret = -EINVAL;
965 struct lbs_private *priv = dev->ml_priv;
966 struct chan_freq_power *cfp;
967 struct assoc_request * assoc_req;
968
969 lbs_deb_enter(LBS_DEB_WEXT);
970
971 mutex_lock(&priv->lock);
972 assoc_req = lbs_get_association_request(priv);
973 if (!assoc_req) {
974 ret = -ENOMEM;
975 goto out;
976 }
977
978 /* If setting by frequency, convert to a channel */
979 if (fwrq->e == 1) {
980 long f = fwrq->m / 100000;
981
982 cfp = find_cfp_by_band_and_freq(priv, 0, f);
983 if (!cfp) {
984 lbs_deb_wext("invalid freq %ld\n", f);
985 goto out;
986 }
987
988 fwrq->e = 0;
989 fwrq->m = (int) cfp->channel;
990 }
991
992 /* Setting by channel number */
993 if (fwrq->m > 1000 || fwrq->e > 0) {
994 goto out;
995 }
996
997 cfp = lbs_find_cfp_by_band_and_channel(priv, 0, fwrq->m);
998 if (!cfp) {
999 goto out;
1000 }
1001
1002 assoc_req->channel = fwrq->m;
1003 ret = 0;
1004
1005out:
1006 if (ret == 0) {
1007 set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags);
1008 lbs_postpone_association_work(priv);
1009 } else {
1010 lbs_cancel_association_work(priv);
1011 }
1012 mutex_unlock(&priv->lock);
1013
1014 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1015 return ret;
1016}
1017
1018#ifdef CONFIG_LIBERTAS_MESH
1019static int lbs_mesh_set_freq(struct net_device *dev,
1020 struct iw_request_info *info,
1021 struct iw_freq *fwrq, char *extra)
1022{
1023 struct lbs_private *priv = dev->ml_priv;
1024 struct chan_freq_power *cfp;
1025 int ret = -EINVAL;
1026
1027 lbs_deb_enter(LBS_DEB_WEXT);
1028
1029 /* If setting by frequency, convert to a channel */
1030 if (fwrq->e == 1) {
1031 long f = fwrq->m / 100000;
1032
1033 cfp = find_cfp_by_band_and_freq(priv, 0, f);
1034 if (!cfp) {
1035 lbs_deb_wext("invalid freq %ld\n", f);
1036 goto out;
1037 }
1038
1039 fwrq->e = 0;
1040 fwrq->m = (int) cfp->channel;
1041 }
1042
1043 /* Setting by channel number */
1044 if (fwrq->m > 1000 || fwrq->e > 0) {
1045 goto out;
1046 }
1047
1048 cfp = lbs_find_cfp_by_band_and_channel(priv, 0, fwrq->m);
1049 if (!cfp) {
1050 goto out;
1051 }
1052
1053 if (fwrq->m != priv->channel) {
1054 lbs_deb_wext("mesh channel change forces eth disconnect\n");
1055 if (priv->mode == IW_MODE_INFRA)
1056 lbs_cmd_80211_deauthenticate(priv,
1057 priv->curbssparams.bssid,
1058 WLAN_REASON_DEAUTH_LEAVING);
1059 else if (priv->mode == IW_MODE_ADHOC)
1060 lbs_adhoc_stop(priv);
1061 }
1062 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, fwrq->m);
1063 lbs_update_channel(priv);
1064 ret = 0;
1065
1066out:
1067 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1068 return ret;
1069}
1070#endif
1071
1072static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
1073 struct iw_param *vwrq, char *extra)
1074{
1075 struct lbs_private *priv = dev->ml_priv;
1076 u8 new_rate = 0;
1077 int ret = -EINVAL;
1078 u8 rates[MAX_RATES + 1];
1079
1080 lbs_deb_enter(LBS_DEB_WEXT);
1081
1082 lbs_deb_wext("vwrq->value %d\n", vwrq->value);
1083 lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed);
1084
1085 if (vwrq->fixed && vwrq->value == -1)
1086 goto out;
1087
1088 /* Auto rate? */
1089 priv->enablehwauto = !vwrq->fixed;
1090
1091 if (vwrq->value == -1)
1092 priv->cur_rate = 0;
1093 else {
1094 if (vwrq->value % 100000)
1095 goto out;
1096
1097 new_rate = vwrq->value / 500000;
1098 priv->cur_rate = new_rate;
1099 /* the rest is only needed for lbs_set_data_rate() */
1100 memset(rates, 0, sizeof(rates));
1101 copy_active_data_rates(priv, rates);
1102 if (!memchr(rates, new_rate, sizeof(rates))) {
1103 lbs_pr_alert("fixed data rate 0x%X out of range\n",
1104 new_rate);
1105 goto out;
1106 }
1107 if (priv->fwrelease < 0x09000000) {
1108 ret = lbs_set_power_adapt_cfg(priv, 0,
1109 POW_ADAPT_DEFAULT_P0,
1110 POW_ADAPT_DEFAULT_P1,
1111 POW_ADAPT_DEFAULT_P2);
1112 if (ret)
1113 goto out;
1114 }
1115 ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
1116 TPC_DEFAULT_P2, 1);
1117 if (ret)
1118 goto out;
1119 }
1120
1121 /* Try the newer command first (Firmware Spec 5.1 and above) */
1122 ret = lbs_cmd_802_11_rate_adapt_rateset(priv, CMD_ACT_SET);
1123
1124 /* Fallback to older version */
1125 if (ret)
1126 ret = lbs_set_data_rate(priv, new_rate);
1127
1128out:
1129 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1130 return ret;
1131}
1132
1133static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info,
1134 struct iw_param *vwrq, char *extra)
1135{
1136 struct lbs_private *priv = dev->ml_priv;
1137
1138 lbs_deb_enter(LBS_DEB_WEXT);
1139
1140 if (priv->connect_status == LBS_CONNECTED) {
1141 vwrq->value = priv->cur_rate * 500000;
1142
1143 if (priv->enablehwauto)
1144 vwrq->fixed = 0;
1145 else
1146 vwrq->fixed = 1;
1147
1148 } else {
1149 vwrq->fixed = 0;
1150 vwrq->value = 0;
1151 }
1152
1153 lbs_deb_leave(LBS_DEB_WEXT);
1154 return 0;
1155}
1156
1157static int lbs_set_mode(struct net_device *dev,
1158 struct iw_request_info *info, u32 * uwrq, char *extra)
1159{
1160 int ret = 0;
1161 struct lbs_private *priv = dev->ml_priv;
1162 struct assoc_request * assoc_req;
1163
1164 lbs_deb_enter(LBS_DEB_WEXT);
1165
1166 if ( (*uwrq != IW_MODE_ADHOC)
1167 && (*uwrq != IW_MODE_INFRA)
1168 && (*uwrq != IW_MODE_AUTO)) {
1169 lbs_deb_wext("Invalid mode: 0x%x\n", *uwrq);
1170 ret = -EINVAL;
1171 goto out;
1172 }
1173
1174 mutex_lock(&priv->lock);
1175 assoc_req = lbs_get_association_request(priv);
1176 if (!assoc_req) {
1177 ret = -ENOMEM;
1178 lbs_cancel_association_work(priv);
1179 } else {
1180 assoc_req->mode = *uwrq;
1181 set_bit(ASSOC_FLAG_MODE, &assoc_req->flags);
1182 lbs_postpone_association_work(priv);
1183 lbs_deb_wext("Switching to mode: 0x%x\n", *uwrq);
1184 }
1185 mutex_unlock(&priv->lock);
1186
1187out:
1188 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1189 return ret;
1190}
1191
1192
1193/**
1194 * @brief Get Encryption key
1195 *
1196 * @param dev A pointer to net_device structure
1197 * @param info A pointer to iw_request_info structure
1198 * @param vwrq A pointer to iw_param structure
1199 * @param extra A pointer to extra data buf
1200 * @return 0 --success, otherwise fail
1201 */
1202static int lbs_get_encode(struct net_device *dev,
1203 struct iw_request_info *info,
1204 struct iw_point *dwrq, u8 * extra)
1205{
1206 struct lbs_private *priv = dev->ml_priv;
1207 int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
1208
1209 lbs_deb_enter(LBS_DEB_WEXT);
1210
1211 lbs_deb_wext("flags 0x%x, index %d, length %d, wep_tx_keyidx %d\n",
1212 dwrq->flags, index, dwrq->length, priv->wep_tx_keyidx);
1213
1214 dwrq->flags = 0;
1215
1216 /* Authentication method */
1217 switch (priv->secinfo.auth_mode) {
1218 case IW_AUTH_ALG_OPEN_SYSTEM:
1219 dwrq->flags = IW_ENCODE_OPEN;
1220 break;
1221
1222 case IW_AUTH_ALG_SHARED_KEY:
1223 case IW_AUTH_ALG_LEAP:
1224 dwrq->flags = IW_ENCODE_RESTRICTED;
1225 break;
1226 default:
1227 dwrq->flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN;
1228 break;
1229 }
1230
1231 memset(extra, 0, 16);
1232
1233 mutex_lock(&priv->lock);
1234
1235 /* Default to returning current transmit key */
1236 if (index < 0)
1237 index = priv->wep_tx_keyidx;
1238
1239 if ((priv->wep_keys[index].len) && priv->secinfo.wep_enabled) {
1240 memcpy(extra, priv->wep_keys[index].key,
1241 priv->wep_keys[index].len);
1242 dwrq->length = priv->wep_keys[index].len;
1243
1244 dwrq->flags |= (index + 1);
1245 /* Return WEP enabled */
1246 dwrq->flags &= ~IW_ENCODE_DISABLED;
1247 } else if ((priv->secinfo.WPAenabled)
1248 || (priv->secinfo.WPA2enabled)) {
1249 /* return WPA enabled */
1250 dwrq->flags &= ~IW_ENCODE_DISABLED;
1251 dwrq->flags |= IW_ENCODE_NOKEY;
1252 } else {
1253 dwrq->flags |= IW_ENCODE_DISABLED;
1254 }
1255
1256 mutex_unlock(&priv->lock);
1257
1258 lbs_deb_wext("key: %02x:%02x:%02x:%02x:%02x:%02x, keylen %d\n",
1259 extra[0], extra[1], extra[2],
1260 extra[3], extra[4], extra[5], dwrq->length);
1261
1262 lbs_deb_wext("return flags 0x%x\n", dwrq->flags);
1263
1264 lbs_deb_leave(LBS_DEB_WEXT);
1265 return 0;
1266}
1267
1268/**
1269 * @brief Set Encryption key (internal)
1270 *
1271 * @param priv A pointer to private card structure
1272 * @param key_material A pointer to key material
1273 * @param key_length length of key material
1274 * @param index key index to set
1275 * @param set_tx_key Force set TX key (1 = yes, 0 = no)
1276 * @return 0 --success, otherwise fail
1277 */
1278static int lbs_set_wep_key(struct assoc_request *assoc_req,
1279 const char *key_material,
1280 u16 key_length,
1281 u16 index,
1282 int set_tx_key)
1283{
1284 int ret = 0;
1285 struct enc_key *pkey;
1286
1287 lbs_deb_enter(LBS_DEB_WEXT);
1288
1289 /* Paranoid validation of key index */
1290 if (index > 3) {
1291 ret = -EINVAL;
1292 goto out;
1293 }
1294
1295 /* validate max key length */
1296 if (key_length > KEY_LEN_WEP_104) {
1297 ret = -EINVAL;
1298 goto out;
1299 }
1300
1301 pkey = &assoc_req->wep_keys[index];
1302
1303 if (key_length > 0) {
1304 memset(pkey, 0, sizeof(struct enc_key));
1305 pkey->type = KEY_TYPE_ID_WEP;
1306
1307 /* Standardize the key length */
1308 pkey->len = (key_length > KEY_LEN_WEP_40) ?
1309 KEY_LEN_WEP_104 : KEY_LEN_WEP_40;
1310 memcpy(pkey->key, key_material, key_length);
1311 }
1312
1313 if (set_tx_key) {
1314 /* Ensure the chosen key is valid */
1315 if (!pkey->len) {
1316 lbs_deb_wext("key not set, so cannot enable it\n");
1317 ret = -EINVAL;
1318 goto out;
1319 }
1320 assoc_req->wep_tx_keyidx = index;
1321 }
1322
1323 assoc_req->secinfo.wep_enabled = 1;
1324
1325out:
1326 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1327 return ret;
1328}
1329
1330static int validate_key_index(u16 def_index, u16 raw_index,
1331 u16 *out_index, u16 *is_default)
1332{
1333 if (!out_index || !is_default)
1334 return -EINVAL;
1335
1336 /* Verify index if present, otherwise use default TX key index */
1337 if (raw_index > 0) {
1338 if (raw_index > 4)
1339 return -EINVAL;
1340 *out_index = raw_index - 1;
1341 } else {
1342 *out_index = def_index;
1343 *is_default = 1;
1344 }
1345 return 0;
1346}
1347
1348static void disable_wep(struct assoc_request *assoc_req)
1349{
1350 int i;
1351
1352 lbs_deb_enter(LBS_DEB_WEXT);
1353
1354 /* Set Open System auth mode */
1355 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1356
1357 /* Clear WEP keys and mark WEP as disabled */
1358 assoc_req->secinfo.wep_enabled = 0;
1359 for (i = 0; i < 4; i++)
1360 assoc_req->wep_keys[i].len = 0;
1361
1362 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1363 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
1364
1365 lbs_deb_leave(LBS_DEB_WEXT);
1366}
1367
1368static void disable_wpa(struct assoc_request *assoc_req)
1369{
1370 lbs_deb_enter(LBS_DEB_WEXT);
1371
1372 memset(&assoc_req->wpa_mcast_key, 0, sizeof (struct enc_key));
1373 assoc_req->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST;
1374 set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
1375
1376 memset(&assoc_req->wpa_unicast_key, 0, sizeof (struct enc_key));
1377 assoc_req->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST;
1378 set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
1379
1380 assoc_req->secinfo.WPAenabled = 0;
1381 assoc_req->secinfo.WPA2enabled = 0;
1382 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1383
1384 lbs_deb_leave(LBS_DEB_WEXT);
1385}
1386
1387/**
1388 * @brief Set Encryption key
1389 *
1390 * @param dev A pointer to net_device structure
1391 * @param info A pointer to iw_request_info structure
1392 * @param vwrq A pointer to iw_param structure
1393 * @param extra A pointer to extra data buf
1394 * @return 0 --success, otherwise fail
1395 */
1396static int lbs_set_encode(struct net_device *dev,
1397 struct iw_request_info *info,
1398 struct iw_point *dwrq, char *extra)
1399{
1400 int ret = 0;
1401 struct lbs_private *priv = dev->ml_priv;
1402 struct assoc_request * assoc_req;
1403 u16 is_default = 0, index = 0, set_tx_key = 0;
1404
1405 lbs_deb_enter(LBS_DEB_WEXT);
1406
1407 mutex_lock(&priv->lock);
1408 assoc_req = lbs_get_association_request(priv);
1409 if (!assoc_req) {
1410 ret = -ENOMEM;
1411 goto out;
1412 }
1413
1414 if (dwrq->flags & IW_ENCODE_DISABLED) {
1415 disable_wep (assoc_req);
1416 disable_wpa (assoc_req);
1417 goto out;
1418 }
1419
1420 ret = validate_key_index(assoc_req->wep_tx_keyidx,
1421 (dwrq->flags & IW_ENCODE_INDEX),
1422 &index, &is_default);
1423 if (ret) {
1424 ret = -EINVAL;
1425 goto out;
1426 }
1427
1428 /* If WEP isn't enabled, or if there is no key data but a valid
1429 * index, set the TX key.
1430 */
1431 if (!assoc_req->secinfo.wep_enabled || (dwrq->length == 0 && !is_default))
1432 set_tx_key = 1;
1433
1434 ret = lbs_set_wep_key(assoc_req, extra, dwrq->length, index, set_tx_key);
1435 if (ret)
1436 goto out;
1437
1438 if (dwrq->length)
1439 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
1440 if (set_tx_key)
1441 set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
1442
1443 if (dwrq->flags & IW_ENCODE_RESTRICTED) {
1444 priv->authtype_auto = 0;
1445 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
1446 } else if (dwrq->flags & IW_ENCODE_OPEN) {
1447 priv->authtype_auto = 0;
1448 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1449 }
1450
1451out:
1452 if (ret == 0) {
1453 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1454 lbs_postpone_association_work(priv);
1455 } else {
1456 lbs_cancel_association_work(priv);
1457 }
1458 mutex_unlock(&priv->lock);
1459
1460 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1461 return ret;
1462}
1463
1464/**
1465 * @brief Get Extended Encryption key (WPA/802.1x and WEP)
1466 *
1467 * @param dev A pointer to net_device structure
1468 * @param info A pointer to iw_request_info structure
1469 * @param vwrq A pointer to iw_param structure
1470 * @param extra A pointer to extra data buf
1471 * @return 0 on success, otherwise failure
1472 */
1473static int lbs_get_encodeext(struct net_device *dev,
1474 struct iw_request_info *info,
1475 struct iw_point *dwrq,
1476 char *extra)
1477{
1478 int ret = -EINVAL;
1479 struct lbs_private *priv = dev->ml_priv;
1480 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1481 int index, max_key_len;
1482
1483 lbs_deb_enter(LBS_DEB_WEXT);
1484
1485 max_key_len = dwrq->length - sizeof(*ext);
1486 if (max_key_len < 0)
1487 goto out;
1488
1489 index = dwrq->flags & IW_ENCODE_INDEX;
1490 if (index) {
1491 if (index < 1 || index > 4)
1492 goto out;
1493 index--;
1494 } else {
1495 index = priv->wep_tx_keyidx;
1496 }
1497
1498 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
1499 ext->alg != IW_ENCODE_ALG_WEP) {
1500 if (index != 0 || priv->mode != IW_MODE_INFRA)
1501 goto out;
1502 }
1503
1504 dwrq->flags = index + 1;
1505 memset(ext, 0, sizeof(*ext));
1506
1507 if ( !priv->secinfo.wep_enabled
1508 && !priv->secinfo.WPAenabled
1509 && !priv->secinfo.WPA2enabled) {
1510 ext->alg = IW_ENCODE_ALG_NONE;
1511 ext->key_len = 0;
1512 dwrq->flags |= IW_ENCODE_DISABLED;
1513 } else {
1514 u8 *key = NULL;
1515
1516 if ( priv->secinfo.wep_enabled
1517 && !priv->secinfo.WPAenabled
1518 && !priv->secinfo.WPA2enabled) {
1519 /* WEP */
1520 ext->alg = IW_ENCODE_ALG_WEP;
1521 ext->key_len = priv->wep_keys[index].len;
1522 key = &priv->wep_keys[index].key[0];
1523 } else if ( !priv->secinfo.wep_enabled
1524 && (priv->secinfo.WPAenabled ||
1525 priv->secinfo.WPA2enabled)) {
1526 /* WPA */
1527 struct enc_key * pkey = NULL;
1528
1529 if ( priv->wpa_mcast_key.len
1530 && (priv->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED))
1531 pkey = &priv->wpa_mcast_key;
1532 else if ( priv->wpa_unicast_key.len
1533 && (priv->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED))
1534 pkey = &priv->wpa_unicast_key;
1535
1536 if (pkey) {
1537 if (pkey->type == KEY_TYPE_ID_AES) {
1538 ext->alg = IW_ENCODE_ALG_CCMP;
1539 } else {
1540 ext->alg = IW_ENCODE_ALG_TKIP;
1541 }
1542 ext->key_len = pkey->len;
1543 key = &pkey->key[0];
1544 } else {
1545 ext->alg = IW_ENCODE_ALG_TKIP;
1546 ext->key_len = 0;
1547 }
1548 } else {
1549 goto out;
1550 }
1551
1552 if (ext->key_len > max_key_len) {
1553 ret = -E2BIG;
1554 goto out;
1555 }
1556
1557 if (ext->key_len)
1558 memcpy(ext->key, key, ext->key_len);
1559 else
1560 dwrq->flags |= IW_ENCODE_NOKEY;
1561 dwrq->flags |= IW_ENCODE_ENABLED;
1562 }
1563 ret = 0;
1564
1565out:
1566 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1567 return ret;
1568}
1569
1570/**
1571 * @brief Set Encryption key Extended (WPA/802.1x and WEP)
1572 *
1573 * @param dev A pointer to net_device structure
1574 * @param info A pointer to iw_request_info structure
1575 * @param vwrq A pointer to iw_param structure
1576 * @param extra A pointer to extra data buf
1577 * @return 0 --success, otherwise fail
1578 */
1579static int lbs_set_encodeext(struct net_device *dev,
1580 struct iw_request_info *info,
1581 struct iw_point *dwrq,
1582 char *extra)
1583{
1584 int ret = 0;
1585 struct lbs_private *priv = dev->ml_priv;
1586 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1587 int alg = ext->alg;
1588 struct assoc_request * assoc_req;
1589
1590 lbs_deb_enter(LBS_DEB_WEXT);
1591
1592 mutex_lock(&priv->lock);
1593 assoc_req = lbs_get_association_request(priv);
1594 if (!assoc_req) {
1595 ret = -ENOMEM;
1596 goto out;
1597 }
1598
1599 if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) {
1600 disable_wep (assoc_req);
1601 disable_wpa (assoc_req);
1602 } else if (alg == IW_ENCODE_ALG_WEP) {
1603 u16 is_default = 0, index, set_tx_key = 0;
1604
1605 ret = validate_key_index(assoc_req->wep_tx_keyidx,
1606 (dwrq->flags & IW_ENCODE_INDEX),
1607 &index, &is_default);
1608 if (ret)
1609 goto out;
1610
1611 /* If WEP isn't enabled, or if there is no key data but a valid
1612 * index, or if the set-TX-key flag was passed, set the TX key.
1613 */
1614 if ( !assoc_req->secinfo.wep_enabled
1615 || (dwrq->length == 0 && !is_default)
1616 || (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY))
1617 set_tx_key = 1;
1618
1619 /* Copy key to driver */
1620 ret = lbs_set_wep_key(assoc_req, ext->key, ext->key_len, index,
1621 set_tx_key);
1622 if (ret)
1623 goto out;
1624
1625 if (dwrq->flags & IW_ENCODE_RESTRICTED) {
1626 priv->authtype_auto = 0;
1627 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
1628 } else if (dwrq->flags & IW_ENCODE_OPEN) {
1629 priv->authtype_auto = 0;
1630 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1631 }
1632
1633 /* Mark the various WEP bits as modified */
1634 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1635 if (dwrq->length)
1636 set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags);
1637 if (set_tx_key)
1638 set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags);
1639 } else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
1640 struct enc_key * pkey;
1641
1642 /* validate key length */
1643 if (((alg == IW_ENCODE_ALG_TKIP)
1644 && (ext->key_len != KEY_LEN_WPA_TKIP))
1645 || ((alg == IW_ENCODE_ALG_CCMP)
1646 && (ext->key_len != KEY_LEN_WPA_AES))) {
1647 lbs_deb_wext("invalid size %d for key of alg "
1648 "type %d\n",
1649 ext->key_len,
1650 alg);
1651 ret = -EINVAL;
1652 goto out;
1653 }
1654
1655 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1656 pkey = &assoc_req->wpa_mcast_key;
1657 set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags);
1658 } else {
1659 pkey = &assoc_req->wpa_unicast_key;
1660 set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags);
1661 }
1662
1663 memset(pkey, 0, sizeof (struct enc_key));
1664 memcpy(pkey->key, ext->key, ext->key_len);
1665 pkey->len = ext->key_len;
1666 if (pkey->len)
1667 pkey->flags |= KEY_INFO_WPA_ENABLED;
1668
1669 /* Do this after zeroing key structure */
1670 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1671 pkey->flags |= KEY_INFO_WPA_MCAST;
1672 } else {
1673 pkey->flags |= KEY_INFO_WPA_UNICAST;
1674 }
1675
1676 if (alg == IW_ENCODE_ALG_TKIP) {
1677 pkey->type = KEY_TYPE_ID_TKIP;
1678 } else if (alg == IW_ENCODE_ALG_CCMP) {
1679 pkey->type = KEY_TYPE_ID_AES;
1680 }
1681
1682 /* If WPA isn't enabled yet, do that now */
1683 if ( assoc_req->secinfo.WPAenabled == 0
1684 && assoc_req->secinfo.WPA2enabled == 0) {
1685 assoc_req->secinfo.WPAenabled = 1;
1686 assoc_req->secinfo.WPA2enabled = 1;
1687 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1688 }
1689
1690 /* Only disable wep if necessary: can't waste time here. */
1691 if (priv->mac_control & CMD_ACT_MAC_WEP_ENABLE)
1692 disable_wep(assoc_req);
1693 }
1694
1695out:
1696 if (ret == 0) {
1697 /* 802.1x and WPA rekeying must happen as quickly as possible,
1698 * especially during the 4-way handshake; thus if in
1699 * infrastructure mode, and either (a) 802.1x is enabled or
1700 * (b) WPA is being used, set the key right away.
1701 */
1702 if (assoc_req->mode == IW_MODE_INFRA &&
1703 ((assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_802_1X) ||
1704 (assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_PSK) ||
1705 assoc_req->secinfo.WPAenabled ||
1706 assoc_req->secinfo.WPA2enabled)) {
1707 lbs_do_association_work(priv);
1708 } else
1709 lbs_postpone_association_work(priv);
1710 } else {
1711 lbs_cancel_association_work(priv);
1712 }
1713 mutex_unlock(&priv->lock);
1714
1715 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1716 return ret;
1717}
1718
1719
1720static int lbs_set_genie(struct net_device *dev,
1721 struct iw_request_info *info,
1722 struct iw_point *dwrq,
1723 char *extra)
1724{
1725 struct lbs_private *priv = dev->ml_priv;
1726 int ret = 0;
1727 struct assoc_request * assoc_req;
1728
1729 lbs_deb_enter(LBS_DEB_WEXT);
1730
1731 mutex_lock(&priv->lock);
1732 assoc_req = lbs_get_association_request(priv);
1733 if (!assoc_req) {
1734 ret = -ENOMEM;
1735 goto out;
1736 }
1737
1738 if (dwrq->length > MAX_WPA_IE_LEN ||
1739 (dwrq->length && extra == NULL)) {
1740 ret = -EINVAL;
1741 goto out;
1742 }
1743
1744 if (dwrq->length) {
1745 memcpy(&assoc_req->wpa_ie[0], extra, dwrq->length);
1746 assoc_req->wpa_ie_len = dwrq->length;
1747 } else {
1748 memset(&assoc_req->wpa_ie[0], 0, sizeof(priv->wpa_ie));
1749 assoc_req->wpa_ie_len = 0;
1750 }
1751
1752out:
1753 if (ret == 0) {
1754 set_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags);
1755 lbs_postpone_association_work(priv);
1756 } else {
1757 lbs_cancel_association_work(priv);
1758 }
1759 mutex_unlock(&priv->lock);
1760
1761 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1762 return ret;
1763}
1764
1765static int lbs_get_genie(struct net_device *dev,
1766 struct iw_request_info *info,
1767 struct iw_point *dwrq,
1768 char *extra)
1769{
1770 int ret = 0;
1771 struct lbs_private *priv = dev->ml_priv;
1772
1773 lbs_deb_enter(LBS_DEB_WEXT);
1774
1775 if (priv->wpa_ie_len == 0) {
1776 dwrq->length = 0;
1777 goto out;
1778 }
1779
1780 if (dwrq->length < priv->wpa_ie_len) {
1781 ret = -E2BIG;
1782 goto out;
1783 }
1784
1785 dwrq->length = priv->wpa_ie_len;
1786 memcpy(extra, &priv->wpa_ie[0], priv->wpa_ie_len);
1787
1788out:
1789 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1790 return ret;
1791}
1792
1793
1794static int lbs_set_auth(struct net_device *dev,
1795 struct iw_request_info *info,
1796 struct iw_param *dwrq,
1797 char *extra)
1798{
1799 struct lbs_private *priv = dev->ml_priv;
1800 struct assoc_request * assoc_req;
1801 int ret = 0;
1802 int updated = 0;
1803
1804 lbs_deb_enter(LBS_DEB_WEXT);
1805
1806 mutex_lock(&priv->lock);
1807 assoc_req = lbs_get_association_request(priv);
1808 if (!assoc_req) {
1809 ret = -ENOMEM;
1810 goto out;
1811 }
1812
1813 switch (dwrq->flags & IW_AUTH_INDEX) {
1814 case IW_AUTH_PRIVACY_INVOKED:
1815 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
1816 case IW_AUTH_TKIP_COUNTERMEASURES:
1817 case IW_AUTH_CIPHER_PAIRWISE:
1818 case IW_AUTH_CIPHER_GROUP:
1819 case IW_AUTH_DROP_UNENCRYPTED:
1820 /*
1821 * libertas does not use these parameters
1822 */
1823 break;
1824
1825 case IW_AUTH_KEY_MGMT:
1826 assoc_req->secinfo.key_mgmt = dwrq->value;
1827 updated = 1;
1828 break;
1829
1830 case IW_AUTH_WPA_VERSION:
1831 if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) {
1832 assoc_req->secinfo.WPAenabled = 0;
1833 assoc_req->secinfo.WPA2enabled = 0;
1834 disable_wpa (assoc_req);
1835 }
1836 if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) {
1837 assoc_req->secinfo.WPAenabled = 1;
1838 assoc_req->secinfo.wep_enabled = 0;
1839 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1840 }
1841 if (dwrq->value & IW_AUTH_WPA_VERSION_WPA2) {
1842 assoc_req->secinfo.WPA2enabled = 1;
1843 assoc_req->secinfo.wep_enabled = 0;
1844 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1845 }
1846 updated = 1;
1847 break;
1848
1849 case IW_AUTH_80211_AUTH_ALG:
1850 if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) {
1851 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY;
1852 } else if (dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM) {
1853 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1854 } else if (dwrq->value & IW_AUTH_ALG_LEAP) {
1855 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_LEAP;
1856 } else {
1857 ret = -EINVAL;
1858 }
1859 updated = 1;
1860 break;
1861
1862 case IW_AUTH_WPA_ENABLED:
1863 if (dwrq->value) {
1864 if (!assoc_req->secinfo.WPAenabled &&
1865 !assoc_req->secinfo.WPA2enabled) {
1866 assoc_req->secinfo.WPAenabled = 1;
1867 assoc_req->secinfo.WPA2enabled = 1;
1868 assoc_req->secinfo.wep_enabled = 0;
1869 assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM;
1870 }
1871 } else {
1872 assoc_req->secinfo.WPAenabled = 0;
1873 assoc_req->secinfo.WPA2enabled = 0;
1874 disable_wpa (assoc_req);
1875 }
1876 updated = 1;
1877 break;
1878
1879 default:
1880 ret = -EOPNOTSUPP;
1881 break;
1882 }
1883
1884out:
1885 if (ret == 0) {
1886 if (updated)
1887 set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags);
1888 lbs_postpone_association_work(priv);
1889 } else if (ret != -EOPNOTSUPP) {
1890 lbs_cancel_association_work(priv);
1891 }
1892 mutex_unlock(&priv->lock);
1893
1894 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1895 return ret;
1896}
1897
1898static int lbs_get_auth(struct net_device *dev,
1899 struct iw_request_info *info,
1900 struct iw_param *dwrq,
1901 char *extra)
1902{
1903 int ret = 0;
1904 struct lbs_private *priv = dev->ml_priv;
1905
1906 lbs_deb_enter(LBS_DEB_WEXT);
1907
1908 switch (dwrq->flags & IW_AUTH_INDEX) {
1909 case IW_AUTH_KEY_MGMT:
1910 dwrq->value = priv->secinfo.key_mgmt;
1911 break;
1912
1913 case IW_AUTH_WPA_VERSION:
1914 dwrq->value = 0;
1915 if (priv->secinfo.WPAenabled)
1916 dwrq->value |= IW_AUTH_WPA_VERSION_WPA;
1917 if (priv->secinfo.WPA2enabled)
1918 dwrq->value |= IW_AUTH_WPA_VERSION_WPA2;
1919 if (!dwrq->value)
1920 dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED;
1921 break;
1922
1923 case IW_AUTH_80211_AUTH_ALG:
1924 dwrq->value = priv->secinfo.auth_mode;
1925 break;
1926
1927 case IW_AUTH_WPA_ENABLED:
1928 if (priv->secinfo.WPAenabled && priv->secinfo.WPA2enabled)
1929 dwrq->value = 1;
1930 break;
1931
1932 default:
1933 ret = -EOPNOTSUPP;
1934 }
1935
1936 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
1937 return ret;
1938}
1939
1940
1941static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
1942 struct iw_param *vwrq, char *extra)
1943{
1944 int ret = 0;
1945 struct lbs_private *priv = dev->ml_priv;
1946 s16 dbm = (s16) vwrq->value;
1947
1948 lbs_deb_enter(LBS_DEB_WEXT);
1949
1950 if (vwrq->disabled) {
1951 lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0);
1952 goto out;
1953 }
1954
1955 if (vwrq->fixed == 0) {
1956 /* User requests automatic tx power control, however there are
1957 * many auto tx settings. For now use firmware defaults until
1958 * we come up with a good way to expose these to the user. */
1959 if (priv->fwrelease < 0x09000000) {
1960 ret = lbs_set_power_adapt_cfg(priv, 1,
1961 POW_ADAPT_DEFAULT_P0,
1962 POW_ADAPT_DEFAULT_P1,
1963 POW_ADAPT_DEFAULT_P2);
1964 if (ret)
1965 goto out;
1966 }
1967 ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
1968 TPC_DEFAULT_P2, 1);
1969 if (ret)
1970 goto out;
1971 dbm = priv->txpower_max;
1972 } else {
1973 /* Userspace check in iwrange if it should use dBm or mW,
1974 * therefore this should never happen... Jean II */
1975 if ((vwrq->flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) {
1976 ret = -EOPNOTSUPP;
1977 goto out;
1978 }
1979
1980 /* Validate requested power level against firmware allowed
1981 * levels */
1982 if (priv->txpower_min && (dbm < priv->txpower_min)) {
1983 ret = -EINVAL;
1984 goto out;
1985 }
1986
1987 if (priv->txpower_max && (dbm > priv->txpower_max)) {
1988 ret = -EINVAL;
1989 goto out;
1990 }
1991 if (priv->fwrelease < 0x09000000) {
1992 ret = lbs_set_power_adapt_cfg(priv, 0,
1993 POW_ADAPT_DEFAULT_P0,
1994 POW_ADAPT_DEFAULT_P1,
1995 POW_ADAPT_DEFAULT_P2);
1996 if (ret)
1997 goto out;
1998 }
1999 ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
2000 TPC_DEFAULT_P2, 1);
2001 if (ret)
2002 goto out;
2003 }
2004
2005 /* If the radio was off, turn it on */
2006 if (!priv->radio_on) {
2007 ret = lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 1);
2008 if (ret)
2009 goto out;
2010 }
2011
2012 lbs_deb_wext("txpower set %d dBm\n", dbm);
2013
2014 ret = lbs_set_tx_power(priv, dbm);
2015
2016out:
2017 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
2018 return ret;
2019}
2020
2021static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info,
2022 struct iw_point *dwrq, char *extra)
2023{
2024 struct lbs_private *priv = dev->ml_priv;
2025
2026 lbs_deb_enter(LBS_DEB_WEXT);
2027
2028 /*
2029 * Note : if dwrq->flags != 0, we should get the relevant SSID from
2030 * the SSID list...
2031 */
2032
2033 /*
2034 * Get the current SSID
2035 */
2036 if (priv->connect_status == LBS_CONNECTED) {
2037 memcpy(extra, priv->curbssparams.ssid,
2038 priv->curbssparams.ssid_len);
2039 } else {
2040 memset(extra, 0, 32);
2041 }
2042 /*
2043 * If none, we may want to get the one that was set
2044 */
2045
2046 dwrq->length = priv->curbssparams.ssid_len;
2047
2048 dwrq->flags = 1; /* active */
2049
2050 lbs_deb_leave(LBS_DEB_WEXT);
2051 return 0;
2052}
2053
2054static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
2055 struct iw_point *dwrq, char *extra)
2056{
2057 struct lbs_private *priv = dev->ml_priv;
2058 int ret = 0;
2059 u8 ssid[IEEE80211_MAX_SSID_LEN];
2060 u8 ssid_len = 0;
2061 struct assoc_request * assoc_req;
2062 int in_ssid_len = dwrq->length;
2063 DECLARE_SSID_BUF(ssid_buf);
2064
2065 lbs_deb_enter(LBS_DEB_WEXT);
2066
2067 if (!priv->radio_on) {
2068 ret = -EINVAL;
2069 goto out;
2070 }
2071
2072 /* Check the size of the string */
2073 if (in_ssid_len > IEEE80211_MAX_SSID_LEN) {
2074 ret = -E2BIG;
2075 goto out;
2076 }
2077
2078 memset(&ssid, 0, sizeof(ssid));
2079
2080 if (!dwrq->flags || !in_ssid_len) {
2081 /* "any" SSID requested; leave SSID blank */
2082 } else {
2083 /* Specific SSID requested */
2084 memcpy(&ssid, extra, in_ssid_len);
2085 ssid_len = in_ssid_len;
2086 }
2087
2088 if (!ssid_len) {
2089 lbs_deb_wext("requested any SSID\n");
2090 } else {
2091 lbs_deb_wext("requested SSID '%s'\n",
2092 print_ssid(ssid_buf, ssid, ssid_len));
2093 }
2094
2095out:
2096 mutex_lock(&priv->lock);
2097 if (ret == 0) {
2098 /* Get or create the current association request */
2099 assoc_req = lbs_get_association_request(priv);
2100 if (!assoc_req) {
2101 ret = -ENOMEM;
2102 } else {
2103 /* Copy the SSID to the association request */
2104 memcpy(&assoc_req->ssid, &ssid, IEEE80211_MAX_SSID_LEN);
2105 assoc_req->ssid_len = ssid_len;
2106 set_bit(ASSOC_FLAG_SSID, &assoc_req->flags);
2107 lbs_postpone_association_work(priv);
2108 }
2109 }
2110
2111 /* Cancel the association request if there was an error */
2112 if (ret != 0) {
2113 lbs_cancel_association_work(priv);
2114 }
2115
2116 mutex_unlock(&priv->lock);
2117
2118 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
2119 return ret;
2120}
2121
2122#ifdef CONFIG_LIBERTAS_MESH
2123static int lbs_mesh_get_essid(struct net_device *dev,
2124 struct iw_request_info *info,
2125 struct iw_point *dwrq, char *extra)
2126{
2127 struct lbs_private *priv = dev->ml_priv;
2128
2129 lbs_deb_enter(LBS_DEB_WEXT);
2130
2131 memcpy(extra, priv->mesh_ssid, priv->mesh_ssid_len);
2132
2133 dwrq->length = priv->mesh_ssid_len;
2134
2135 dwrq->flags = 1; /* active */
2136
2137 lbs_deb_leave(LBS_DEB_WEXT);
2138 return 0;
2139}
2140
2141static int lbs_mesh_set_essid(struct net_device *dev,
2142 struct iw_request_info *info,
2143 struct iw_point *dwrq, char *extra)
2144{
2145 struct lbs_private *priv = dev->ml_priv;
2146 int ret = 0;
2147
2148 lbs_deb_enter(LBS_DEB_WEXT);
2149
2150 if (!priv->radio_on) {
2151 ret = -EINVAL;
2152 goto out;
2153 }
2154
2155 /* Check the size of the string */
2156 if (dwrq->length > IEEE80211_MAX_SSID_LEN) {
2157 ret = -E2BIG;
2158 goto out;
2159 }
2160
2161 if (!dwrq->flags || !dwrq->length) {
2162 ret = -EINVAL;
2163 goto out;
2164 } else {
2165 /* Specific SSID requested */
2166 memcpy(priv->mesh_ssid, extra, dwrq->length);
2167 priv->mesh_ssid_len = dwrq->length;
2168 }
2169
2170 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
2171 priv->channel);
2172 out:
2173 lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret);
2174 return ret;
2175}
2176#endif
2177
2178/**
2179 * @brief Connect to the AP or Ad-hoc Network with specific bssid
2180 *
2181 * @param dev A pointer to net_device structure
2182 * @param info A pointer to iw_request_info structure
2183 * @param awrq A pointer to iw_param structure
2184 * @param extra A pointer to extra data buf
2185 * @return 0 --success, otherwise fail
2186 */
2187static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
2188 struct sockaddr *awrq, char *extra)
2189{
2190 struct lbs_private *priv = dev->ml_priv;
2191 struct assoc_request * assoc_req;
2192 int ret = 0;
2193
2194 lbs_deb_enter(LBS_DEB_WEXT);
2195
2196 if (!priv->radio_on)
2197 return -EINVAL;
2198
2199 if (awrq->sa_family != ARPHRD_ETHER)
2200 return -EINVAL;
2201
2202 lbs_deb_wext("ASSOC: WAP: sa_data %pM\n", awrq->sa_data);
2203
2204 mutex_lock(&priv->lock);
2205
2206 /* Get or create the current association request */
2207 assoc_req = lbs_get_association_request(priv);
2208 if (!assoc_req) {
2209 lbs_cancel_association_work(priv);
2210 ret = -ENOMEM;
2211 } else {
2212 /* Copy the BSSID to the association request */
2213 memcpy(&assoc_req->bssid, awrq->sa_data, ETH_ALEN);
2214 set_bit(ASSOC_FLAG_BSSID, &assoc_req->flags);
2215 lbs_postpone_association_work(priv);
2216 }
2217
2218 mutex_unlock(&priv->lock);
2219
2220 return ret;
2221}
2222
2223/*
2224 * iwconfig settable callbacks
2225 */
2226static const iw_handler lbs_handler[] = {
2227 (iw_handler) NULL, /* SIOCSIWCOMMIT */
2228 (iw_handler) lbs_get_name, /* SIOCGIWNAME */
2229 (iw_handler) NULL, /* SIOCSIWNWID */
2230 (iw_handler) NULL, /* SIOCGIWNWID */
2231 (iw_handler) lbs_set_freq, /* SIOCSIWFREQ */
2232 (iw_handler) lbs_get_freq, /* SIOCGIWFREQ */
2233 (iw_handler) lbs_set_mode, /* SIOCSIWMODE */
2234 (iw_handler) lbs_get_mode, /* SIOCGIWMODE */
2235 (iw_handler) NULL, /* SIOCSIWSENS */
2236 (iw_handler) NULL, /* SIOCGIWSENS */
2237 (iw_handler) NULL, /* SIOCSIWRANGE */
2238 (iw_handler) lbs_get_range, /* SIOCGIWRANGE */
2239 (iw_handler) NULL, /* SIOCSIWPRIV */
2240 (iw_handler) NULL, /* SIOCGIWPRIV */
2241 (iw_handler) NULL, /* SIOCSIWSTATS */
2242 (iw_handler) NULL, /* SIOCGIWSTATS */
2243 iw_handler_set_spy, /* SIOCSIWSPY */
2244 iw_handler_get_spy, /* SIOCGIWSPY */
2245 iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
2246 iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
2247 (iw_handler) lbs_set_wap, /* SIOCSIWAP */
2248 (iw_handler) lbs_get_wap, /* SIOCGIWAP */
2249 (iw_handler) NULL, /* SIOCSIWMLME */
2250 (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
2251 (iw_handler) lbs_set_scan, /* SIOCSIWSCAN */
2252 (iw_handler) lbs_get_scan, /* SIOCGIWSCAN */
2253 (iw_handler) lbs_set_essid, /* SIOCSIWESSID */
2254 (iw_handler) lbs_get_essid, /* SIOCGIWESSID */
2255 (iw_handler) lbs_set_nick, /* SIOCSIWNICKN */
2256 (iw_handler) lbs_get_nick, /* SIOCGIWNICKN */
2257 (iw_handler) NULL, /* -- hole -- */
2258 (iw_handler) NULL, /* -- hole -- */
2259 (iw_handler) lbs_set_rate, /* SIOCSIWRATE */
2260 (iw_handler) lbs_get_rate, /* SIOCGIWRATE */
2261 (iw_handler) lbs_set_rts, /* SIOCSIWRTS */
2262 (iw_handler) lbs_get_rts, /* SIOCGIWRTS */
2263 (iw_handler) lbs_set_frag, /* SIOCSIWFRAG */
2264 (iw_handler) lbs_get_frag, /* SIOCGIWFRAG */
2265 (iw_handler) lbs_set_txpow, /* SIOCSIWTXPOW */
2266 (iw_handler) lbs_get_txpow, /* SIOCGIWTXPOW */
2267 (iw_handler) lbs_set_retry, /* SIOCSIWRETRY */
2268 (iw_handler) lbs_get_retry, /* SIOCGIWRETRY */
2269 (iw_handler) lbs_set_encode, /* SIOCSIWENCODE */
2270 (iw_handler) lbs_get_encode, /* SIOCGIWENCODE */
2271 (iw_handler) lbs_set_power, /* SIOCSIWPOWER */
2272 (iw_handler) lbs_get_power, /* SIOCGIWPOWER */
2273 (iw_handler) NULL, /* -- hole -- */
2274 (iw_handler) NULL, /* -- hole -- */
2275 (iw_handler) lbs_set_genie, /* SIOCSIWGENIE */
2276 (iw_handler) lbs_get_genie, /* SIOCGIWGENIE */
2277 (iw_handler) lbs_set_auth, /* SIOCSIWAUTH */
2278 (iw_handler) lbs_get_auth, /* SIOCGIWAUTH */
2279 (iw_handler) lbs_set_encodeext,/* SIOCSIWENCODEEXT */
2280 (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */
2281 (iw_handler) NULL, /* SIOCSIWPMKSA */
2282};
2283struct iw_handler_def lbs_handler_def = {
2284 .num_standard = ARRAY_SIZE(lbs_handler),
2285 .standard = (iw_handler *) lbs_handler,
2286 .get_wireless_stats = lbs_get_wireless_stats,
2287};
2288
2289#ifdef CONFIG_LIBERTAS_MESH
2290static const iw_handler mesh_wlan_handler[] = {
2291 (iw_handler) NULL, /* SIOCSIWCOMMIT */
2292 (iw_handler) lbs_get_name, /* SIOCGIWNAME */
2293 (iw_handler) NULL, /* SIOCSIWNWID */
2294 (iw_handler) NULL, /* SIOCGIWNWID */
2295 (iw_handler) lbs_mesh_set_freq, /* SIOCSIWFREQ */
2296 (iw_handler) lbs_get_freq, /* SIOCGIWFREQ */
2297 (iw_handler) NULL, /* SIOCSIWMODE */
2298 (iw_handler) mesh_wlan_get_mode, /* SIOCGIWMODE */
2299 (iw_handler) NULL, /* SIOCSIWSENS */
2300 (iw_handler) NULL, /* SIOCGIWSENS */
2301 (iw_handler) NULL, /* SIOCSIWRANGE */
2302 (iw_handler) lbs_get_range, /* SIOCGIWRANGE */
2303 (iw_handler) NULL, /* SIOCSIWPRIV */
2304 (iw_handler) NULL, /* SIOCGIWPRIV */
2305 (iw_handler) NULL, /* SIOCSIWSTATS */
2306 (iw_handler) NULL, /* SIOCGIWSTATS */
2307 iw_handler_set_spy, /* SIOCSIWSPY */
2308 iw_handler_get_spy, /* SIOCGIWSPY */
2309 iw_handler_set_thrspy, /* SIOCSIWTHRSPY */
2310 iw_handler_get_thrspy, /* SIOCGIWTHRSPY */
2311 (iw_handler) NULL, /* SIOCSIWAP */
2312 (iw_handler) NULL, /* SIOCGIWAP */
2313 (iw_handler) NULL, /* SIOCSIWMLME */
2314 (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */
2315 (iw_handler) lbs_set_scan, /* SIOCSIWSCAN */
2316 (iw_handler) lbs_get_scan, /* SIOCGIWSCAN */
2317 (iw_handler) lbs_mesh_set_essid,/* SIOCSIWESSID */
2318 (iw_handler) lbs_mesh_get_essid,/* SIOCGIWESSID */
2319 (iw_handler) NULL, /* SIOCSIWNICKN */
2320 (iw_handler) mesh_get_nick, /* SIOCGIWNICKN */
2321 (iw_handler) NULL, /* -- hole -- */
2322 (iw_handler) NULL, /* -- hole -- */
2323 (iw_handler) lbs_set_rate, /* SIOCSIWRATE */
2324 (iw_handler) lbs_get_rate, /* SIOCGIWRATE */
2325 (iw_handler) lbs_set_rts, /* SIOCSIWRTS */
2326 (iw_handler) lbs_get_rts, /* SIOCGIWRTS */
2327 (iw_handler) lbs_set_frag, /* SIOCSIWFRAG */
2328 (iw_handler) lbs_get_frag, /* SIOCGIWFRAG */
2329 (iw_handler) lbs_set_txpow, /* SIOCSIWTXPOW */
2330 (iw_handler) lbs_get_txpow, /* SIOCGIWTXPOW */
2331 (iw_handler) lbs_set_retry, /* SIOCSIWRETRY */
2332 (iw_handler) lbs_get_retry, /* SIOCGIWRETRY */
2333 (iw_handler) lbs_set_encode, /* SIOCSIWENCODE */
2334 (iw_handler) lbs_get_encode, /* SIOCGIWENCODE */
2335 (iw_handler) lbs_set_power, /* SIOCSIWPOWER */
2336 (iw_handler) lbs_get_power, /* SIOCGIWPOWER */
2337 (iw_handler) NULL, /* -- hole -- */
2338 (iw_handler) NULL, /* -- hole -- */
2339 (iw_handler) lbs_set_genie, /* SIOCSIWGENIE */
2340 (iw_handler) lbs_get_genie, /* SIOCGIWGENIE */
2341 (iw_handler) lbs_set_auth, /* SIOCSIWAUTH */
2342 (iw_handler) lbs_get_auth, /* SIOCGIWAUTH */
2343 (iw_handler) lbs_set_encodeext,/* SIOCSIWENCODEEXT */
2344 (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */
2345 (iw_handler) NULL, /* SIOCSIWPMKSA */
2346};
2347
2348struct iw_handler_def mesh_handler_def = {
2349 .num_standard = ARRAY_SIZE(mesh_wlan_handler),
2350 .standard = (iw_handler *) mesh_wlan_handler,
2351 .get_wireless_stats = lbs_get_wireless_stats,
2352};
2353#endif
diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h
deleted file mode 100644
index f3f19fe8c6c6..000000000000
--- a/drivers/net/wireless/libertas/wext.h
+++ /dev/null
@@ -1,17 +0,0 @@
1/**
2 * This file contains definition for IOCTL call.
3 */
4#ifndef _LBS_WEXT_H_
5#define _LBS_WEXT_H_
6
7void lbs_send_disconnect_notification(struct lbs_private *priv);
8void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
9
10struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
11 struct lbs_private *priv,
12 u8 band,
13 u16 channel);
14
15extern struct iw_handler_def lbs_handler_def;
16
17#endif