diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/libertas/cmd.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/libertas/cmd.c')
-rw-r--r-- | drivers/net/wireless/libertas/cmd.c | 720 |
1 files changed, 104 insertions, 616 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 0a324dcd264c..cdb9b9650d73 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -3,21 +3,21 @@ | |||
3 | * It prepares command and sends it to firmware when it is ready. | 3 | * It prepares command and sends it to firmware when it is ready. |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <net/iw_handler.h> | ||
7 | #include <net/lib80211.h> | ||
8 | #include <linux/kfifo.h> | 6 | #include <linux/kfifo.h> |
9 | #include <linux/sched.h> | 7 | #include <linux/sched.h> |
8 | #include <linux/slab.h> | ||
9 | |||
10 | #include "host.h" | 10 | #include "host.h" |
11 | #include "hostcmd.h" | ||
12 | #include "decl.h" | 11 | #include "decl.h" |
13 | #include "defs.h" | 12 | #include "defs.h" |
14 | #include "dev.h" | 13 | #include "dev.h" |
15 | #include "assoc.h" | 14 | #include "assoc.h" |
16 | #include "wext.h" | 15 | #include "wext.h" |
16 | #include "scan.h" | ||
17 | #include "cmd.h" | 17 | #include "cmd.h" |
18 | 18 | ||
19 | static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); | ||
20 | 19 | ||
20 | static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); | ||
21 | 21 | ||
22 | /** | 22 | /** |
23 | * @brief Simple callback that copies response back into command | 23 | * @brief Simple callback that copies response back into command |
@@ -77,6 +77,30 @@ static u8 is_command_allowed_in_ps(u16 cmd) | |||
77 | } | 77 | } |
78 | 78 | ||
79 | /** | 79 | /** |
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 | |||
86 | static 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 | /** | ||
80 | * @brief Updates the hardware details like MAC address and regulatory region | 104 | * @brief Updates the hardware details like MAC address and regulatory region |
81 | * | 105 | * |
82 | * @param priv A pointer to struct lbs_private structure | 106 | * @param priv A pointer to struct lbs_private structure |
@@ -120,19 +144,6 @@ int lbs_update_hw_spec(struct lbs_private *priv) | |||
120 | lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", | 144 | lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", |
121 | cmd.hwifversion, cmd.version); | 145 | cmd.hwifversion, cmd.version); |
122 | 146 | ||
123 | /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ | ||
124 | /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ | ||
125 | /* 5.110.22 have mesh command with 0xa3 command id */ | ||
126 | /* 10.0.0.p0 FW brings in mesh config command with different id */ | ||
127 | /* Check FW version MSB and initialize mesh_fw_ver */ | ||
128 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) | ||
129 | priv->mesh_fw_ver = MESH_FW_OLD; | ||
130 | else if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && | ||
131 | (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) | ||
132 | priv->mesh_fw_ver = MESH_FW_NEW; | ||
133 | else | ||
134 | priv->mesh_fw_ver = MESH_NONE; | ||
135 | |||
136 | /* Clamp region code to 8-bit since FW spec indicates that it should | 147 | /* Clamp region code to 8-bit since FW spec indicates that it should |
137 | * only ever be 8-bit, even though the field size is 16-bit. Some firmware | 148 | * only ever be 8-bit, even though the field size is 16-bit. Some firmware |
138 | * returns non-zero high 8 bits here. | 149 | * returns non-zero high 8 bits here. |
@@ -169,11 +180,6 @@ int lbs_update_hw_spec(struct lbs_private *priv) | |||
169 | goto out; | 180 | goto out; |
170 | } | 181 | } |
171 | 182 | ||
172 | if (lbs_set_universaltable(priv, 0)) { | ||
173 | ret = -1; | ||
174 | goto out; | ||
175 | } | ||
176 | |||
177 | out: | 183 | out: |
178 | lbs_deb_leave(LBS_DEB_CMD); | 184 | lbs_deb_leave(LBS_DEB_CMD); |
179 | return ret; | 185 | return ret; |
@@ -222,7 +228,7 @@ static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd, | |||
222 | 228 | ||
223 | cmd->command = cpu_to_le16(CMD_802_11_PS_MODE); | 229 | cmd->command = cpu_to_le16(CMD_802_11_PS_MODE); |
224 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) + | 230 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) + |
225 | S_DS_GEN); | 231 | sizeof(struct cmd_header)); |
226 | psm->action = cpu_to_le16(cmd_action); | 232 | psm->action = cpu_to_le16(cmd_action); |
227 | psm->multipledtim = 0; | 233 | psm->multipledtim = 0; |
228 | switch (cmd_action) { | 234 | switch (cmd_action) { |
@@ -251,33 +257,6 @@ static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd, | |||
251 | return 0; | 257 | return 0; |
252 | } | 258 | } |
253 | 259 | ||
254 | int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv, | ||
255 | uint16_t cmd_action, uint16_t *timeout) | ||
256 | { | ||
257 | struct cmd_ds_802_11_inactivity_timeout cmd; | ||
258 | int ret; | ||
259 | |||
260 | lbs_deb_enter(LBS_DEB_CMD); | ||
261 | |||
262 | cmd.hdr.command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT); | ||
263 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
264 | |||
265 | cmd.action = cpu_to_le16(cmd_action); | ||
266 | |||
267 | if (cmd_action == CMD_ACT_SET) | ||
268 | cmd.timeout = cpu_to_le16(*timeout); | ||
269 | else | ||
270 | cmd.timeout = 0; | ||
271 | |||
272 | ret = lbs_cmd_with_response(priv, CMD_802_11_INACTIVITY_TIMEOUT, &cmd); | ||
273 | |||
274 | if (!ret) | ||
275 | *timeout = le16_to_cpu(cmd.timeout); | ||
276 | |||
277 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, | 260 | int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, |
282 | struct sleep_params *sp) | 261 | struct sleep_params *sp) |
283 | { | 262 | { |
@@ -320,190 +299,53 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, | |||
320 | return 0; | 299 | return 0; |
321 | } | 300 | } |
322 | 301 | ||
323 | int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, | 302 | static int lbs_wait_for_ds_awake(struct lbs_private *priv) |
324 | struct assoc_request *assoc) | ||
325 | { | 303 | { |
326 | struct cmd_ds_802_11_set_wep cmd; | ||
327 | int ret = 0; | 304 | int ret = 0; |
328 | 305 | ||
329 | lbs_deb_enter(LBS_DEB_CMD); | 306 | lbs_deb_enter(LBS_DEB_CMD); |
330 | 307 | ||
331 | memset(&cmd, 0, sizeof(cmd)); | 308 | if (priv->is_deep_sleep) { |
332 | cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP); | 309 | if (!wait_event_interruptible_timeout(priv->ds_awake_q, |
333 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | 310 | !priv->is_deep_sleep, (10 * HZ))) { |
334 | 311 | lbs_pr_err("ds_awake_q: timer expired\n"); | |
335 | cmd.action = cpu_to_le16(cmd_action); | 312 | ret = -1; |
336 | |||
337 | if (cmd_action == CMD_ACT_ADD) { | ||
338 | int i; | ||
339 | |||
340 | /* default tx key index */ | ||
341 | cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx & | ||
342 | CMD_WEP_KEY_INDEX_MASK); | ||
343 | |||
344 | /* Copy key types and material to host command structure */ | ||
345 | for (i = 0; i < 4; i++) { | ||
346 | struct enc_key *pkey = &assoc->wep_keys[i]; | ||
347 | |||
348 | switch (pkey->len) { | ||
349 | case KEY_LEN_WEP_40: | ||
350 | cmd.keytype[i] = CMD_TYPE_WEP_40_BIT; | ||
351 | memmove(cmd.keymaterial[i], pkey->key, pkey->len); | ||
352 | lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i); | ||
353 | break; | ||
354 | case KEY_LEN_WEP_104: | ||
355 | cmd.keytype[i] = CMD_TYPE_WEP_104_BIT; | ||
356 | memmove(cmd.keymaterial[i], pkey->key, pkey->len); | ||
357 | lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i); | ||
358 | break; | ||
359 | case 0: | ||
360 | break; | ||
361 | default: | ||
362 | lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n", | ||
363 | i, pkey->len); | ||
364 | ret = -1; | ||
365 | goto done; | ||
366 | break; | ||
367 | } | ||
368 | } | 313 | } |
369 | } else if (cmd_action == CMD_ACT_REMOVE) { | ||
370 | /* ACT_REMOVE clears _all_ WEP keys */ | ||
371 | |||
372 | /* default tx key index */ | ||
373 | cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx & | ||
374 | CMD_WEP_KEY_INDEX_MASK); | ||
375 | lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx); | ||
376 | } | ||
377 | |||
378 | ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd); | ||
379 | done: | ||
380 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, | ||
385 | uint16_t *enable) | ||
386 | { | ||
387 | struct cmd_ds_802_11_enable_rsn cmd; | ||
388 | int ret; | ||
389 | |||
390 | lbs_deb_enter(LBS_DEB_CMD); | ||
391 | |||
392 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
393 | cmd.action = cpu_to_le16(cmd_action); | ||
394 | |||
395 | if (cmd_action == CMD_ACT_GET) | ||
396 | cmd.enable = 0; | ||
397 | else { | ||
398 | if (*enable) | ||
399 | cmd.enable = cpu_to_le16(CMD_ENABLE_RSN); | ||
400 | else | ||
401 | cmd.enable = cpu_to_le16(CMD_DISABLE_RSN); | ||
402 | lbs_deb_cmd("ENABLE_RSN: %d\n", *enable); | ||
403 | } | 314 | } |
404 | 315 | ||
405 | ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd); | ||
406 | if (!ret && cmd_action == CMD_ACT_GET) | ||
407 | *enable = le16_to_cpu(cmd.enable); | ||
408 | |||
409 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | 316 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); |
410 | return ret; | 317 | return ret; |
411 | } | 318 | } |
412 | 319 | ||
413 | static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam, | 320 | int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep) |
414 | struct enc_key *key) | ||
415 | { | 321 | { |
416 | lbs_deb_enter(LBS_DEB_CMD); | 322 | int ret = 0; |
417 | |||
418 | if (key->flags & KEY_INFO_WPA_ENABLED) | ||
419 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED); | ||
420 | if (key->flags & KEY_INFO_WPA_UNICAST) | ||
421 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); | ||
422 | if (key->flags & KEY_INFO_WPA_MCAST) | ||
423 | keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); | ||
424 | |||
425 | keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); | ||
426 | keyparam->keytypeid = cpu_to_le16(key->type); | ||
427 | keyparam->keylen = cpu_to_le16(key->len); | ||
428 | memcpy(keyparam->key, key->key, key->len); | ||
429 | |||
430 | /* Length field doesn't include the {type,length} header */ | ||
431 | keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4); | ||
432 | lbs_deb_leave(LBS_DEB_CMD); | ||
433 | } | ||
434 | |||
435 | int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, | ||
436 | struct assoc_request *assoc) | ||
437 | { | ||
438 | struct cmd_ds_802_11_key_material cmd; | ||
439 | int ret = 0; | ||
440 | int index = 0; | ||
441 | 323 | ||
442 | lbs_deb_enter(LBS_DEB_CMD); | 324 | lbs_deb_enter(LBS_DEB_CMD); |
443 | 325 | ||
444 | cmd.action = cpu_to_le16(cmd_action); | 326 | if (deep_sleep) { |
445 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | 327 | if (priv->is_deep_sleep != 1) { |
446 | 328 | lbs_deb_cmd("deep sleep: sleep\n"); | |
447 | if (cmd_action == CMD_ACT_GET) { | 329 | BUG_ON(!priv->enter_deep_sleep); |
448 | cmd.hdr.size = cpu_to_le16(S_DS_GEN + 2); | 330 | ret = priv->enter_deep_sleep(priv); |
449 | } else { | 331 | if (!ret) { |
450 | memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet)); | 332 | netif_stop_queue(priv->dev); |
451 | 333 | netif_carrier_off(priv->dev); | |
452 | if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) { | 334 | } |
453 | set_one_wpa_key(&cmd.keyParamSet[index], | 335 | } else { |
454 | &assoc->wpa_unicast_key); | 336 | lbs_pr_err("deep sleep: already enabled\n"); |
455 | index++; | ||
456 | } | ||
457 | |||
458 | if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) { | ||
459 | set_one_wpa_key(&cmd.keyParamSet[index], | ||
460 | &assoc->wpa_mcast_key); | ||
461 | index++; | ||
462 | } | 337 | } |
463 | 338 | } else { | |
464 | /* The common header and as many keys as we included */ | 339 | if (priv->is_deep_sleep) { |
465 | cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd), | 340 | lbs_deb_cmd("deep sleep: wakeup\n"); |
466 | keyParamSet[index])); | 341 | BUG_ON(!priv->exit_deep_sleep); |
467 | } | 342 | ret = priv->exit_deep_sleep(priv); |
468 | ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd); | 343 | if (!ret) { |
469 | /* Copy the returned key to driver private data */ | 344 | ret = lbs_wait_for_ds_awake(priv); |
470 | if (!ret && cmd_action == CMD_ACT_GET) { | 345 | if (ret) |
471 | void *buf_ptr = cmd.keyParamSet; | 346 | lbs_pr_err("deep sleep: wakeup" |
472 | void *resp_end = &(&cmd)[1]; | 347 | "failed\n"); |
473 | 348 | } | |
474 | while (buf_ptr < resp_end) { | ||
475 | struct MrvlIEtype_keyParamSet *keyparam = buf_ptr; | ||
476 | struct enc_key *key; | ||
477 | uint16_t param_set_len = le16_to_cpu(keyparam->length); | ||
478 | uint16_t key_len = le16_to_cpu(keyparam->keylen); | ||
479 | uint16_t key_flags = le16_to_cpu(keyparam->keyinfo); | ||
480 | uint16_t key_type = le16_to_cpu(keyparam->keytypeid); | ||
481 | void *end; | ||
482 | |||
483 | end = (void *)keyparam + sizeof(keyparam->type) | ||
484 | + sizeof(keyparam->length) + param_set_len; | ||
485 | |||
486 | /* Make sure we don't access past the end of the IEs */ | ||
487 | if (end > resp_end) | ||
488 | break; | ||
489 | |||
490 | if (key_flags & KEY_INFO_WPA_UNICAST) | ||
491 | key = &priv->wpa_unicast_key; | ||
492 | else if (key_flags & KEY_INFO_WPA_MCAST) | ||
493 | key = &priv->wpa_mcast_key; | ||
494 | else | ||
495 | break; | ||
496 | |||
497 | /* Copy returned key into driver */ | ||
498 | memset(key, 0, sizeof(struct enc_key)); | ||
499 | if (key_len > sizeof(key->key)) | ||
500 | break; | ||
501 | key->type = key_type; | ||
502 | key->flags = key_flags; | ||
503 | key->len = key_len; | ||
504 | memcpy(key->key, keyparam->key, key->len); | ||
505 | |||
506 | buf_ptr = end + 1; | ||
507 | } | 349 | } |
508 | } | 350 | } |
509 | 351 | ||
@@ -535,7 +377,7 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val) | |||
535 | switch (oid) { | 377 | switch (oid) { |
536 | case SNMP_MIB_OID_BSS_TYPE: | 378 | case SNMP_MIB_OID_BSS_TYPE: |
537 | cmd.bufsize = cpu_to_le16(sizeof(u8)); | 379 | cmd.bufsize = cpu_to_le16(sizeof(u8)); |
538 | cmd.value[0] = (val == IW_MODE_ADHOC) ? 2 : 1; | 380 | cmd.value[0] = val; |
539 | break; | 381 | break; |
540 | case SNMP_MIB_OID_11D_ENABLE: | 382 | case SNMP_MIB_OID_11D_ENABLE: |
541 | case SNMP_MIB_OID_FRAG_THRESHOLD: | 383 | case SNMP_MIB_OID_FRAG_THRESHOLD: |
@@ -588,13 +430,7 @@ int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val) | |||
588 | 430 | ||
589 | switch (le16_to_cpu(cmd.bufsize)) { | 431 | switch (le16_to_cpu(cmd.bufsize)) { |
590 | case sizeof(u8): | 432 | case sizeof(u8): |
591 | if (oid == SNMP_MIB_OID_BSS_TYPE) { | 433 | *out_val = cmd.value[0]; |
592 | if (cmd.value[0] == 2) | ||
593 | *out_val = IW_MODE_ADHOC; | ||
594 | else | ||
595 | *out_val = IW_MODE_INFRA; | ||
596 | } else | ||
597 | *out_val = cmd.value[0]; | ||
598 | break; | 434 | break; |
599 | case sizeof(u16): | 435 | case sizeof(u16): |
600 | *out_val = le16_to_cpu(*((__le16 *)(&cmd.value))); | 436 | *out_val = le16_to_cpu(*((__le16 *)(&cmd.value))); |
@@ -681,7 +517,7 @@ static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, | |||
681 | cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE); | 517 | cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE); |
682 | cmd->size = | 518 | cmd->size = |
683 | cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) + | 519 | cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) + |
684 | S_DS_GEN); | 520 | sizeof(struct cmd_header)); |
685 | 521 | ||
686 | monitor->action = cpu_to_le16(cmd_action); | 522 | monitor->action = cpu_to_le16(cmd_action); |
687 | if (cmd_action == CMD_ACT_SET) { | 523 | if (cmd_action == CMD_ACT_SET) { |
@@ -692,111 +528,6 @@ static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, | |||
692 | return 0; | 528 | return 0; |
693 | } | 529 | } |
694 | 530 | ||
695 | static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok) | ||
696 | { | ||
697 | /* Bit Rate | ||
698 | * 15:13 Reserved | ||
699 | * 12 54 Mbps | ||
700 | * 11 48 Mbps | ||
701 | * 10 36 Mbps | ||
702 | * 9 24 Mbps | ||
703 | * 8 18 Mbps | ||
704 | * 7 12 Mbps | ||
705 | * 6 9 Mbps | ||
706 | * 5 6 Mbps | ||
707 | * 4 Reserved | ||
708 | * 3 11 Mbps | ||
709 | * 2 5.5 Mbps | ||
710 | * 1 2 Mbps | ||
711 | * 0 1 Mbps | ||
712 | **/ | ||
713 | |||
714 | uint16_t ratemask; | ||
715 | int i = lbs_data_rate_to_fw_index(rate); | ||
716 | if (lower_rates_ok) | ||
717 | ratemask = (0x1fef >> (12 - i)); | ||
718 | else | ||
719 | ratemask = (1 << i); | ||
720 | return cpu_to_le16(ratemask); | ||
721 | } | ||
722 | |||
723 | int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, | ||
724 | uint16_t cmd_action) | ||
725 | { | ||
726 | struct cmd_ds_802_11_rate_adapt_rateset cmd; | ||
727 | int ret; | ||
728 | |||
729 | lbs_deb_enter(LBS_DEB_CMD); | ||
730 | |||
731 | if (!priv->cur_rate && !priv->enablehwauto) | ||
732 | return -EINVAL; | ||
733 | |||
734 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
735 | |||
736 | cmd.action = cpu_to_le16(cmd_action); | ||
737 | cmd.enablehwauto = cpu_to_le16(priv->enablehwauto); | ||
738 | cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto); | ||
739 | ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd); | ||
740 | if (!ret && cmd_action == CMD_ACT_GET) { | ||
741 | priv->ratebitmap = le16_to_cpu(cmd.bitmap); | ||
742 | priv->enablehwauto = le16_to_cpu(cmd.enablehwauto); | ||
743 | } | ||
744 | |||
745 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
746 | return ret; | ||
747 | } | ||
748 | EXPORT_SYMBOL_GPL(lbs_cmd_802_11_rate_adapt_rateset); | ||
749 | |||
750 | /** | ||
751 | * @brief Set the data rate | ||
752 | * | ||
753 | * @param priv A pointer to struct lbs_private structure | ||
754 | * @param rate The desired data rate, or 0 to clear a locked rate | ||
755 | * | ||
756 | * @return 0 on success, error on failure | ||
757 | */ | ||
758 | int lbs_set_data_rate(struct lbs_private *priv, u8 rate) | ||
759 | { | ||
760 | struct cmd_ds_802_11_data_rate cmd; | ||
761 | int ret = 0; | ||
762 | |||
763 | lbs_deb_enter(LBS_DEB_CMD); | ||
764 | |||
765 | memset(&cmd, 0, sizeof(cmd)); | ||
766 | cmd.hdr.size = cpu_to_le16(sizeof(cmd)); | ||
767 | |||
768 | if (rate > 0) { | ||
769 | cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE); | ||
770 | cmd.rates[0] = lbs_data_rate_to_fw_index(rate); | ||
771 | if (cmd.rates[0] == 0) { | ||
772 | lbs_deb_cmd("DATA_RATE: invalid requested rate of" | ||
773 | " 0x%02X\n", rate); | ||
774 | ret = 0; | ||
775 | goto out; | ||
776 | } | ||
777 | lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]); | ||
778 | } else { | ||
779 | cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO); | ||
780 | lbs_deb_cmd("DATA_RATE: setting auto\n"); | ||
781 | } | ||
782 | |||
783 | ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd); | ||
784 | if (ret) | ||
785 | goto out; | ||
786 | |||
787 | lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd)); | ||
788 | |||
789 | /* FIXME: get actual rates FW can do if this command actually returns | ||
790 | * all data rates supported. | ||
791 | */ | ||
792 | priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]); | ||
793 | lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate); | ||
794 | |||
795 | out: | ||
796 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | ||
797 | return ret; | ||
798 | } | ||
799 | |||
800 | /** | 531 | /** |
801 | * @brief Get the radio channel | 532 | * @brief Get the radio channel |
802 | * | 533 | * |
@@ -804,7 +535,7 @@ out: | |||
804 | * | 535 | * |
805 | * @return The channel on success, error on failure | 536 | * @return The channel on success, error on failure |
806 | */ | 537 | */ |
807 | int lbs_get_channel(struct lbs_private *priv) | 538 | static int lbs_get_channel(struct lbs_private *priv) |
808 | { | 539 | { |
809 | struct cmd_ds_802_11_rf_channel cmd; | 540 | struct cmd_ds_802_11_rf_channel cmd; |
810 | int ret = 0; | 541 | int ret = 0; |
@@ -836,7 +567,7 @@ int lbs_update_channel(struct lbs_private *priv) | |||
836 | 567 | ||
837 | ret = lbs_get_channel(priv); | 568 | ret = lbs_get_channel(priv); |
838 | if (ret > 0) { | 569 | if (ret > 0) { |
839 | priv->curbssparams.channel = ret; | 570 | priv->channel = ret; |
840 | ret = 0; | 571 | ret = 0; |
841 | } | 572 | } |
842 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); | 573 | lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); |
@@ -855,7 +586,7 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel) | |||
855 | { | 586 | { |
856 | struct cmd_ds_802_11_rf_channel cmd; | 587 | struct cmd_ds_802_11_rf_channel cmd; |
857 | #ifdef DEBUG | 588 | #ifdef DEBUG |
858 | u8 old_channel = priv->curbssparams.channel; | 589 | u8 old_channel = priv->channel; |
859 | #endif | 590 | #endif |
860 | int ret = 0; | 591 | int ret = 0; |
861 | 592 | ||
@@ -870,36 +601,15 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel) | |||
870 | if (ret) | 601 | if (ret) |
871 | goto out; | 602 | goto out; |
872 | 603 | ||
873 | priv->curbssparams.channel = (uint8_t) le16_to_cpu(cmd.channel); | 604 | priv->channel = (uint8_t) le16_to_cpu(cmd.channel); |
874 | lbs_deb_cmd("channel switch from %d to %d\n", old_channel, | 605 | lbs_deb_cmd("channel switch from %d to %d\n", old_channel, |
875 | priv->curbssparams.channel); | 606 | priv->channel); |
876 | 607 | ||
877 | out: | 608 | out: |
878 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); | 609 | lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); |
879 | return ret; | 610 | return ret; |
880 | } | 611 | } |
881 | 612 | ||
882 | static int lbs_cmd_802_11_rssi(struct lbs_private *priv, | ||
883 | struct cmd_ds_command *cmd) | ||
884 | { | ||
885 | |||
886 | lbs_deb_enter(LBS_DEB_CMD); | ||
887 | cmd->command = cpu_to_le16(CMD_802_11_RSSI); | ||
888 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN); | ||
889 | cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR); | ||
890 | |||
891 | /* reset Beacon SNR/NF/RSSI values */ | ||
892 | priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
893 | priv->SNR[TYPE_BEACON][TYPE_AVG] = 0; | ||
894 | priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
895 | priv->NF[TYPE_BEACON][TYPE_AVG] = 0; | ||
896 | priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0; | ||
897 | priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0; | ||
898 | |||
899 | lbs_deb_leave(LBS_DEB_CMD); | ||
900 | return 0; | ||
901 | } | ||
902 | |||
903 | static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | 613 | static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, |
904 | u8 cmd_action, void *pdata_buf) | 614 | u8 cmd_action, void *pdata_buf) |
905 | { | 615 | { |
@@ -916,7 +626,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | |||
916 | 626 | ||
917 | cmdptr->size = | 627 | cmdptr->size = |
918 | cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access) | 628 | cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access) |
919 | + S_DS_GEN); | 629 | + sizeof(struct cmd_header)); |
920 | macreg = | 630 | macreg = |
921 | (struct cmd_ds_mac_reg_access *)&cmdptr->params. | 631 | (struct cmd_ds_mac_reg_access *)&cmdptr->params. |
922 | macreg; | 632 | macreg; |
@@ -935,7 +645,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | |||
935 | cmdptr->size = | 645 | cmdptr->size = |
936 | cpu_to_le16(sizeof | 646 | cpu_to_le16(sizeof |
937 | (struct cmd_ds_bbp_reg_access) | 647 | (struct cmd_ds_bbp_reg_access) |
938 | + S_DS_GEN); | 648 | + sizeof(struct cmd_header)); |
939 | bbpreg = | 649 | bbpreg = |
940 | (struct cmd_ds_bbp_reg_access *)&cmdptr->params. | 650 | (struct cmd_ds_bbp_reg_access *)&cmdptr->params. |
941 | bbpreg; | 651 | bbpreg; |
@@ -954,7 +664,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | |||
954 | cmdptr->size = | 664 | cmdptr->size = |
955 | cpu_to_le16(sizeof | 665 | cpu_to_le16(sizeof |
956 | (struct cmd_ds_rf_reg_access) + | 666 | (struct cmd_ds_rf_reg_access) + |
957 | S_DS_GEN); | 667 | sizeof(struct cmd_header)); |
958 | rfreg = | 668 | rfreg = |
959 | (struct cmd_ds_rf_reg_access *)&cmdptr->params. | 669 | (struct cmd_ds_rf_reg_access *)&cmdptr->params. |
960 | rfreg; | 670 | rfreg; |
@@ -974,192 +684,6 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, | |||
974 | return 0; | 684 | return 0; |
975 | } | 685 | } |
976 | 686 | ||
977 | static int lbs_cmd_bt_access(struct cmd_ds_command *cmd, | ||
978 | u16 cmd_action, void *pdata_buf) | ||
979 | { | ||
980 | struct cmd_ds_bt_access *bt_access = &cmd->params.bt; | ||
981 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | ||
982 | |||
983 | cmd->command = cpu_to_le16(CMD_BT_ACCESS); | ||
984 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN); | ||
985 | cmd->result = 0; | ||
986 | bt_access->action = cpu_to_le16(cmd_action); | ||
987 | |||
988 | switch (cmd_action) { | ||
989 | case CMD_ACT_BT_ACCESS_ADD: | ||
990 | memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN); | ||
991 | lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", bt_access->addr1, 6); | ||
992 | break; | ||
993 | case CMD_ACT_BT_ACCESS_DEL: | ||
994 | memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN); | ||
995 | lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", bt_access->addr1, 6); | ||
996 | break; | ||
997 | case CMD_ACT_BT_ACCESS_LIST: | ||
998 | bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); | ||
999 | break; | ||
1000 | case CMD_ACT_BT_ACCESS_RESET: | ||
1001 | break; | ||
1002 | case CMD_ACT_BT_ACCESS_SET_INVERT: | ||
1003 | bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); | ||
1004 | break; | ||
1005 | case CMD_ACT_BT_ACCESS_GET_INVERT: | ||
1006 | break; | ||
1007 | default: | ||
1008 | break; | ||
1009 | } | ||
1010 | lbs_deb_leave(LBS_DEB_CMD); | ||
1011 | return 0; | ||
1012 | } | ||
1013 | |||
1014 | static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, | ||
1015 | u16 cmd_action, void *pdata_buf) | ||
1016 | { | ||
1017 | struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt; | ||
1018 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | ||
1019 | |||
1020 | cmd->command = cpu_to_le16(CMD_FWT_ACCESS); | ||
1021 | cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN); | ||
1022 | cmd->result = 0; | ||
1023 | |||
1024 | if (pdata_buf) | ||
1025 | memcpy(fwt_access, pdata_buf, sizeof(*fwt_access)); | ||
1026 | else | ||
1027 | memset(fwt_access, 0, sizeof(*fwt_access)); | ||
1028 | |||
1029 | fwt_access->action = cpu_to_le16(cmd_action); | ||
1030 | |||
1031 | lbs_deb_leave(LBS_DEB_CMD); | ||
1032 | return 0; | ||
1033 | } | ||
1034 | |||
1035 | int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, | ||
1036 | struct cmd_ds_mesh_access *cmd) | ||
1037 | { | ||
1038 | int ret; | ||
1039 | |||
1040 | lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); | ||
1041 | |||
1042 | cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS); | ||
1043 | cmd->hdr.size = cpu_to_le16(sizeof(*cmd)); | ||
1044 | cmd->hdr.result = 0; | ||
1045 | |||
1046 | cmd->action = cpu_to_le16(cmd_action); | ||
1047 | |||
1048 | ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd); | ||
1049 | |||
1050 | lbs_deb_leave(LBS_DEB_CMD); | ||
1051 | return ret; | ||
1052 | } | ||
1053 | |||
1054 | static int __lbs_mesh_config_send(struct lbs_private *priv, | ||
1055 | struct cmd_ds_mesh_config *cmd, | ||
1056 | uint16_t action, uint16_t type) | ||
1057 | { | ||
1058 | int ret; | ||
1059 | u16 command = CMD_MESH_CONFIG_OLD; | ||
1060 | |||
1061 | lbs_deb_enter(LBS_DEB_CMD); | ||
1062 | |||
1063 | /* | ||
1064 | * Command id is 0xac for v10 FW along with mesh interface | ||
1065 | * id in bits 14-13-12. | ||
1066 | */ | ||
1067 | if (priv->mesh_fw_ver == MESH_FW_NEW) | ||
1068 | command = CMD_MESH_CONFIG | | ||
1069 | (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); | ||
1070 | |||
1071 | cmd->hdr.command = cpu_to_le16(command); | ||
1072 | cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config)); | ||
1073 | cmd->hdr.result = 0; | ||
1074 | |||
1075 | cmd->type = cpu_to_le16(type); | ||
1076 | cmd->action = cpu_to_le16(action); | ||
1077 | |||
1078 | ret = lbs_cmd_with_response(priv, command, cmd); | ||
1079 | |||
1080 | lbs_deb_leave(LBS_DEB_CMD); | ||
1081 | return ret; | ||
1082 | } | ||
1083 | |||
1084 | int lbs_mesh_config_send(struct lbs_private *priv, | ||
1085 | struct cmd_ds_mesh_config *cmd, | ||
1086 | uint16_t action, uint16_t type) | ||
1087 | { | ||
1088 | int ret; | ||
1089 | |||
1090 | if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG)) | ||
1091 | return -EOPNOTSUPP; | ||
1092 | |||
1093 | ret = __lbs_mesh_config_send(priv, cmd, action, type); | ||
1094 | return ret; | ||
1095 | } | ||
1096 | |||
1097 | /* This function is the CMD_MESH_CONFIG legacy function. It only handles the | ||
1098 | * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG | ||
1099 | * are all handled by preparing a struct cmd_ds_mesh_config and passing it to | ||
1100 | * lbs_mesh_config_send. | ||
1101 | */ | ||
1102 | int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan) | ||
1103 | { | ||
1104 | struct cmd_ds_mesh_config cmd; | ||
1105 | struct mrvl_meshie *ie; | ||
1106 | DECLARE_SSID_BUF(ssid); | ||
1107 | |||
1108 | memset(&cmd, 0, sizeof(cmd)); | ||
1109 | cmd.channel = cpu_to_le16(chan); | ||
1110 | ie = (struct mrvl_meshie *)cmd.data; | ||
1111 | |||
1112 | switch (action) { | ||
1113 | case CMD_ACT_MESH_CONFIG_START: | ||
1114 | ie->id = WLAN_EID_GENERIC; | ||
1115 | ie->val.oui[0] = 0x00; | ||
1116 | ie->val.oui[1] = 0x50; | ||
1117 | ie->val.oui[2] = 0x43; | ||
1118 | ie->val.type = MARVELL_MESH_IE_TYPE; | ||
1119 | ie->val.subtype = MARVELL_MESH_IE_SUBTYPE; | ||
1120 | ie->val.version = MARVELL_MESH_IE_VERSION; | ||
1121 | ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP; | ||
1122 | ie->val.active_metric_id = MARVELL_MESH_METRIC_ID; | ||
1123 | ie->val.mesh_capability = MARVELL_MESH_CAPABILITY; | ||
1124 | ie->val.mesh_id_len = priv->mesh_ssid_len; | ||
1125 | memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len); | ||
1126 | ie->len = sizeof(struct mrvl_meshie_val) - | ||
1127 | IW_ESSID_MAX_SIZE + priv->mesh_ssid_len; | ||
1128 | cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val)); | ||
1129 | break; | ||
1130 | case CMD_ACT_MESH_CONFIG_STOP: | ||
1131 | break; | ||
1132 | default: | ||
1133 | return -1; | ||
1134 | } | ||
1135 | lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n", | ||
1136 | action, priv->mesh_tlv, chan, | ||
1137 | print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len)); | ||
1138 | |||
1139 | return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); | ||
1140 | } | ||
1141 | |||
1142 | static int lbs_cmd_bcn_ctrl(struct lbs_private * priv, | ||
1143 | struct cmd_ds_command *cmd, | ||
1144 | u16 cmd_action) | ||
1145 | { | ||
1146 | struct cmd_ds_802_11_beacon_control | ||
1147 | *bcn_ctrl = &cmd->params.bcn_ctrl; | ||
1148 | |||
1149 | lbs_deb_enter(LBS_DEB_CMD); | ||
1150 | cmd->size = | ||
1151 | cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control) | ||
1152 | + S_DS_GEN); | ||
1153 | cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL); | ||
1154 | |||
1155 | bcn_ctrl->action = cpu_to_le16(cmd_action); | ||
1156 | bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable); | ||
1157 | bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period); | ||
1158 | |||
1159 | lbs_deb_leave(LBS_DEB_CMD); | ||
1160 | return 0; | ||
1161 | } | ||
1162 | |||
1163 | static void lbs_queue_cmd(struct lbs_private *priv, | 687 | static void lbs_queue_cmd(struct lbs_private *priv, |
1164 | struct cmd_ctrl_node *cmdnode) | 688 | struct cmd_ctrl_node *cmdnode) |
1165 | { | 689 | { |
@@ -1243,8 +767,17 @@ static void lbs_submit_command(struct lbs_private *priv, | |||
1243 | timeo = HZ/4; | 767 | timeo = HZ/4; |
1244 | } | 768 | } |
1245 | 769 | ||
1246 | /* Setup the timer after transmit command */ | 770 | if (command == CMD_802_11_DEEP_SLEEP) { |
1247 | mod_timer(&priv->command_timer, jiffies + timeo); | 771 | if (priv->is_auto_deep_sleep_enabled) { |
772 | priv->wakeup_dev_required = 1; | ||
773 | priv->dnld_sent = 0; | ||
774 | } | ||
775 | priv->is_deep_sleep = 1; | ||
776 | lbs_complete_command(priv, cmdnode, 0); | ||
777 | } else { | ||
778 | /* Setup the timer after transmit command */ | ||
779 | mod_timer(&priv->command_timer, jiffies + timeo); | ||
780 | } | ||
1248 | 781 | ||
1249 | lbs_deb_leave(LBS_DEB_HOST); | 782 | lbs_deb_leave(LBS_DEB_HOST); |
1250 | } | 783 | } |
@@ -1310,9 +843,6 @@ int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on) | |||
1310 | if (priv->fwrelease < 0x09000000) { | 843 | if (priv->fwrelease < 0x09000000) { |
1311 | switch (preamble) { | 844 | switch (preamble) { |
1312 | case RADIO_PREAMBLE_SHORT: | 845 | case RADIO_PREAMBLE_SHORT: |
1313 | if (!(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) | ||
1314 | goto out; | ||
1315 | /* Fall through */ | ||
1316 | case RADIO_PREAMBLE_AUTO: | 846 | case RADIO_PREAMBLE_AUTO: |
1317 | case RADIO_PREAMBLE_LONG: | 847 | case RADIO_PREAMBLE_LONG: |
1318 | cmd.control = cpu_to_le16(preamble); | 848 | cmd.control = cpu_to_le16(preamble); |
@@ -1391,6 +921,11 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1391 | goto done; | 921 | goto done; |
1392 | } | 922 | } |
1393 | 923 | ||
924 | if (!lbs_is_cmd_allowed(priv)) { | ||
925 | ret = -EBUSY; | ||
926 | goto done; | ||
927 | } | ||
928 | |||
1394 | cmdnode = lbs_get_cmd_ctrl_node(priv); | 929 | cmdnode = lbs_get_cmd_ctrl_node(priv); |
1395 | 930 | ||
1396 | if (cmdnode == NULL) { | 931 | if (cmdnode == NULL) { |
@@ -1441,7 +976,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1441 | 976 | ||
1442 | cmdptr->command = cpu_to_le16(cmd_no); | 977 | cmdptr->command = cpu_to_le16(cmd_no); |
1443 | cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) + | 978 | cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) + |
1444 | S_DS_GEN); | 979 | sizeof(struct cmd_header)); |
1445 | 980 | ||
1446 | memmove(&cmdptr->params.afc, | 981 | memmove(&cmdptr->params.afc, |
1447 | pdata_buf, sizeof(struct cmd_ds_802_11_afc)); | 982 | pdata_buf, sizeof(struct cmd_ds_802_11_afc)); |
@@ -1449,45 +984,19 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1449 | ret = 0; | 984 | ret = 0; |
1450 | goto done; | 985 | goto done; |
1451 | 986 | ||
1452 | case CMD_802_11D_DOMAIN_INFO: | ||
1453 | ret = lbs_cmd_802_11d_domain_info(priv, cmdptr, | ||
1454 | cmd_no, cmd_action); | ||
1455 | break; | ||
1456 | |||
1457 | case CMD_802_11_TPC_CFG: | 987 | case CMD_802_11_TPC_CFG: |
1458 | cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG); | 988 | cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG); |
1459 | cmdptr->size = | 989 | cmdptr->size = |
1460 | cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) + | 990 | cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) + |
1461 | S_DS_GEN); | 991 | sizeof(struct cmd_header)); |
1462 | 992 | ||
1463 | memmove(&cmdptr->params.tpccfg, | 993 | memmove(&cmdptr->params.tpccfg, |
1464 | pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg)); | 994 | pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg)); |
1465 | 995 | ||
1466 | ret = 0; | 996 | ret = 0; |
1467 | break; | 997 | break; |
1468 | case CMD_802_11_LED_GPIO_CTRL: | ||
1469 | { | ||
1470 | struct mrvl_ie_ledgpio *gpio = | ||
1471 | (struct mrvl_ie_ledgpio*) | ||
1472 | cmdptr->params.ledgpio.data; | ||
1473 | |||
1474 | memmove(&cmdptr->params.ledgpio, | ||
1475 | pdata_buf, | ||
1476 | sizeof(struct cmd_ds_802_11_led_ctrl)); | ||
1477 | 998 | ||
1478 | cmdptr->command = | 999 | #ifdef CONFIG_LIBERTAS_MESH |
1479 | cpu_to_le16(CMD_802_11_LED_GPIO_CTRL); | ||
1480 | |||
1481 | #define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8 | ||
1482 | cmdptr->size = | ||
1483 | cpu_to_le16(le16_to_cpu(gpio->header.len) | ||
1484 | + S_DS_GEN | ||
1485 | + ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN); | ||
1486 | gpio->header.len = gpio->header.len; | ||
1487 | |||
1488 | ret = 0; | ||
1489 | break; | ||
1490 | } | ||
1491 | 1000 | ||
1492 | case CMD_BT_ACCESS: | 1001 | case CMD_BT_ACCESS: |
1493 | ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); | 1002 | ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); |
@@ -1497,15 +1006,15 @@ int lbs_prepare_and_send_command(struct lbs_private *priv, | |||
1497 | ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); | 1006 | ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); |
1498 | break; | 1007 | break; |
1499 | 1008 | ||
1500 | case CMD_GET_TSF: | 1009 | #endif |
1501 | cmdptr->command = cpu_to_le16(CMD_GET_TSF); | 1010 | |
1502 | cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) + | ||
1503 | S_DS_GEN); | ||
1504 | ret = 0; | ||
1505 | break; | ||
1506 | case CMD_802_11_BEACON_CTRL: | 1011 | case CMD_802_11_BEACON_CTRL: |
1507 | ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); | 1012 | ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); |
1508 | break; | 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; | ||
1509 | default: | 1018 | default: |
1510 | lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); | 1019 | lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); |
1511 | ret = -1; | 1020 | ret = -1; |
@@ -1797,7 +1306,7 @@ int lbs_execute_next_command(struct lbs_private *priv) | |||
1797 | if ((priv->psmode != LBS802_11POWERMODECAM) && | 1306 | if ((priv->psmode != LBS802_11POWERMODECAM) && |
1798 | (priv->psstate == PS_STATE_FULL_POWER) && | 1307 | (priv->psstate == PS_STATE_FULL_POWER) && |
1799 | ((priv->connect_status == LBS_CONNECTED) || | 1308 | ((priv->connect_status == LBS_CONNECTED) || |
1800 | (priv->mesh_connect_status == LBS_CONNECTED))) { | 1309 | lbs_mesh_connected(priv))) { |
1801 | if (priv->secinfo.WPAenabled || | 1310 | if (priv->secinfo.WPAenabled || |
1802 | priv->secinfo.WPA2enabled) { | 1311 | priv->secinfo.WPA2enabled) { |
1803 | /* check for valid WPA group keys */ | 1312 | /* check for valid WPA group keys */ |
@@ -1823,30 +1332,6 @@ done: | |||
1823 | return ret; | 1332 | return ret; |
1824 | } | 1333 | } |
1825 | 1334 | ||
1826 | void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str) | ||
1827 | { | ||
1828 | union iwreq_data iwrq; | ||
1829 | u8 buf[50]; | ||
1830 | |||
1831 | lbs_deb_enter(LBS_DEB_WEXT); | ||
1832 | |||
1833 | memset(&iwrq, 0, sizeof(union iwreq_data)); | ||
1834 | memset(buf, 0, sizeof(buf)); | ||
1835 | |||
1836 | snprintf(buf, sizeof(buf) - 1, "%s", str); | ||
1837 | |||
1838 | iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN; | ||
1839 | |||
1840 | /* Send Event to upper layer */ | ||
1841 | lbs_deb_wext("event indication string %s\n", (char *)buf); | ||
1842 | lbs_deb_wext("event indication length %d\n", iwrq.data.length); | ||
1843 | lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str); | ||
1844 | |||
1845 | wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf); | ||
1846 | |||
1847 | lbs_deb_leave(LBS_DEB_WEXT); | ||
1848 | } | ||
1849 | |||
1850 | static void lbs_send_confirmsleep(struct lbs_private *priv) | 1335 | static void lbs_send_confirmsleep(struct lbs_private *priv) |
1851 | { | 1336 | { |
1852 | unsigned long flags; | 1337 | unsigned long flags; |
@@ -1869,7 +1354,7 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) | |||
1869 | priv->dnld_sent = DNLD_RES_RECEIVED; | 1354 | priv->dnld_sent = DNLD_RES_RECEIVED; |
1870 | 1355 | ||
1871 | /* If nothing to do, go back to sleep (?) */ | 1356 | /* If nothing to do, go back to sleep (?) */ |
1872 | if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx]) | 1357 | if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx]) |
1873 | priv->psstate = PS_STATE_SLEEP; | 1358 | priv->psstate = PS_STATE_SLEEP; |
1874 | 1359 | ||
1875 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 1360 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
@@ -1943,7 +1428,7 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv) | |||
1943 | } | 1428 | } |
1944 | 1429 | ||
1945 | /* Pending events or command responses? */ | 1430 | /* Pending events or command responses? */ |
1946 | if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) { | 1431 | if (kfifo_len(&priv->event_fifo) || priv->resp_len[priv->resp_idx]) { |
1947 | allowed = 0; | 1432 | allowed = 0; |
1948 | lbs_deb_host("pending events or command responses\n"); | 1433 | lbs_deb_host("pending events or command responses\n"); |
1949 | } | 1434 | } |
@@ -2024,7 +1509,7 @@ int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, | |||
2024 | } | 1509 | } |
2025 | 1510 | ||
2026 | 1511 | ||
2027 | static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, | 1512 | struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, |
2028 | uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, | 1513 | uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, |
2029 | int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), | 1514 | int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), |
2030 | unsigned long callback_arg) | 1515 | unsigned long callback_arg) |
@@ -2039,6 +1524,11 @@ static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, | |||
2039 | goto done; | 1524 | goto done; |
2040 | } | 1525 | } |
2041 | 1526 | ||
1527 | if (!lbs_is_cmd_allowed(priv)) { | ||
1528 | cmdnode = ERR_PTR(-EBUSY); | ||
1529 | goto done; | ||
1530 | } | ||
1531 | |||
2042 | cmdnode = lbs_get_cmd_ctrl_node(priv); | 1532 | cmdnode = lbs_get_cmd_ctrl_node(priv); |
2043 | if (cmdnode == NULL) { | 1533 | if (cmdnode == NULL) { |
2044 | lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); | 1534 | lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); |
@@ -2117,5 +1607,3 @@ done: | |||
2117 | return ret; | 1607 | return ret; |
2118 | } | 1608 | } |
2119 | EXPORT_SYMBOL_GPL(__lbs_cmd); | 1609 | EXPORT_SYMBOL_GPL(__lbs_cmd); |
2120 | |||
2121 | |||