diff options
author | Eliad Peller <eliad@wizery.com> | 2011-08-14 06:17:07 -0400 |
---|---|---|
committer | Luciano Coelho <coelho@ti.com> | 2011-08-22 05:35:24 -0400 |
commit | c690ec816f9fa2ab2b6200c5b79b6933acca49a4 (patch) | |
tree | 984c89b9708b81724daee5f5a77eb9b4d1e2284d /drivers/net/wireless/wl12xx/cmd.c | |
parent | 7f097988f1bff42177b99cb4c8ec62e818d0b1a6 (diff) |
wl12xx: update commands & events
Change the commands and events according to the new fw api
(fw >= 6/7.3.0.0.75).
The main change is the replacement of JOIN/DISCONNECT commands,
with ROLE_START/ROLE_STOP commands.
The use of these commands should be preceded by the ROLE_ENABLE
command (allocating role resources), and followed by the
ROLE_DISABLE command (freeing role resources).
Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers/net/wireless/wl12xx/cmd.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/cmd.c | 515 |
1 files changed, 301 insertions, 214 deletions
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index b6ef65a57b71..b13eed129a92 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c | |||
@@ -363,61 +363,294 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | |||
363 | return 0; | 363 | return 0; |
364 | } | 364 | } |
365 | 365 | ||
366 | int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) | 366 | int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id) |
367 | { | 367 | { |
368 | struct wl1271_cmd_join *join; | 368 | struct wl12xx_cmd_role_enable *cmd; |
369 | int ret, i; | 369 | int ret; |
370 | u8 *bssid; | 370 | |
371 | wl1271_debug(DEBUG_CMD, "cmd role enable"); | ||
372 | |||
373 | if (WARN_ON(*role_id != WL12XX_INVALID_ROLE_ID)) | ||
374 | return -EBUSY; | ||
375 | |||
376 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
377 | if (!cmd) { | ||
378 | ret = -ENOMEM; | ||
379 | goto out; | ||
380 | } | ||
381 | |||
382 | /* get role id */ | ||
383 | cmd->role_id = find_first_zero_bit(wl->roles_map, WL12XX_MAX_ROLES); | ||
384 | if (cmd->role_id >= WL12XX_MAX_ROLES) { | ||
385 | ret = -EBUSY; | ||
386 | goto out_free; | ||
387 | } | ||
388 | |||
389 | memcpy(cmd->mac_address, wl->mac_addr, ETH_ALEN); | ||
390 | cmd->role_type = role_type; | ||
391 | |||
392 | ret = wl1271_cmd_send(wl, CMD_ROLE_ENABLE, cmd, sizeof(*cmd), 0); | ||
393 | if (ret < 0) { | ||
394 | wl1271_error("failed to initiate cmd role enable"); | ||
395 | goto out_free; | ||
396 | } | ||
397 | |||
398 | __set_bit(cmd->role_id, wl->roles_map); | ||
399 | *role_id = cmd->role_id; | ||
371 | 400 | ||
372 | join = kzalloc(sizeof(*join), GFP_KERNEL); | 401 | out_free: |
373 | if (!join) { | 402 | kfree(cmd); |
403 | |||
404 | out: | ||
405 | return ret; | ||
406 | } | ||
407 | |||
408 | int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id) | ||
409 | { | ||
410 | struct wl12xx_cmd_role_disable *cmd; | ||
411 | int ret; | ||
412 | |||
413 | wl1271_debug(DEBUG_CMD, "cmd role disable"); | ||
414 | |||
415 | if (WARN_ON(*role_id == WL12XX_INVALID_ROLE_ID)) | ||
416 | return -ENOENT; | ||
417 | |||
418 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
419 | if (!cmd) { | ||
374 | ret = -ENOMEM; | 420 | ret = -ENOMEM; |
375 | goto out; | 421 | goto out; |
376 | } | 422 | } |
423 | cmd->role_id = *role_id; | ||
424 | |||
425 | ret = wl1271_cmd_send(wl, CMD_ROLE_DISABLE, cmd, sizeof(*cmd), 0); | ||
426 | if (ret < 0) { | ||
427 | wl1271_error("failed to initiate cmd role disable"); | ||
428 | goto out_free; | ||
429 | } | ||
377 | 430 | ||
378 | wl1271_debug(DEBUG_CMD, "cmd join"); | 431 | __clear_bit(*role_id, wl->roles_map); |
432 | *role_id = WL12XX_INVALID_ROLE_ID; | ||
379 | 433 | ||
380 | /* Reverse order BSSID */ | 434 | out_free: |
381 | bssid = (u8 *) &join->bssid_lsb; | 435 | kfree(cmd); |
382 | for (i = 0; i < ETH_ALEN; i++) | 436 | |
383 | bssid[i] = wl->bssid[ETH_ALEN - i - 1]; | 437 | out: |
438 | return ret; | ||
439 | } | ||
440 | |||
441 | static int wl12xx_allocate_link(struct wl1271 *wl, u8 *hlid) | ||
442 | { | ||
443 | u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS); | ||
444 | if (link >= WL12XX_MAX_LINKS) | ||
445 | return -EBUSY; | ||
446 | |||
447 | __set_bit(link, wl->links_map); | ||
448 | *hlid = link; | ||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid) | ||
453 | { | ||
454 | if (*hlid == WL12XX_INVALID_LINK_ID) | ||
455 | return; | ||
456 | |||
457 | __clear_bit(*hlid, wl->links_map); | ||
458 | *hlid = WL12XX_INVALID_LINK_ID; | ||
459 | } | ||
460 | |||
461 | int wl12xx_cmd_role_start_sta(struct wl1271 *wl) | ||
462 | { | ||
463 | struct wl12xx_cmd_role_start *cmd; | ||
464 | int ret; | ||
384 | 465 | ||
385 | join->bss_type = bss_type; | 466 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
386 | join->basic_rate_set = cpu_to_le32(wl->basic_rate_set); | 467 | if (!cmd) { |
387 | join->supported_rate_set = cpu_to_le32(wl->rate_set); | 468 | ret = -ENOMEM; |
469 | goto out; | ||
470 | } | ||
388 | 471 | ||
472 | wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wl->role_id); | ||
473 | |||
474 | cmd->role_id = wl->role_id; | ||
389 | if (wl->band == IEEE80211_BAND_5GHZ) | 475 | if (wl->band == IEEE80211_BAND_5GHZ) |
390 | join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; | 476 | cmd->band = WL12XX_BAND_5GHZ; |
477 | cmd->channel = wl->channel; | ||
478 | cmd->sta.basic_rate_set = cpu_to_le32(wl->basic_rate_set); | ||
479 | cmd->sta.beacon_interval = cpu_to_le16(wl->beacon_int); | ||
480 | cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY; | ||
481 | cmd->sta.ssid_len = wl->ssid_len; | ||
482 | memcpy(cmd->sta.ssid, wl->ssid, wl->ssid_len); | ||
483 | memcpy(cmd->sta.bssid, wl->bssid, ETH_ALEN); | ||
484 | cmd->sta.local_rates = cpu_to_le32(wl->rate_set); | ||
485 | |||
486 | if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { | ||
487 | ret = wl12xx_allocate_link(wl, &wl->sta_hlid); | ||
488 | if (ret) | ||
489 | goto out_free; | ||
490 | } | ||
491 | cmd->sta.hlid = wl->sta_hlid; | ||
492 | cmd->sta.session = wl->session_counter; | ||
493 | cmd->sta.remote_rates = cpu_to_le32(wl->rate_set); | ||
494 | |||
495 | wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " | ||
496 | "basic_rate_set: 0x%x, remote_rates: 0x%x", | ||
497 | wl->role_id, cmd->sta.hlid, cmd->sta.session, | ||
498 | wl->basic_rate_set, wl->rate_set); | ||
499 | |||
500 | ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); | ||
501 | if (ret < 0) { | ||
502 | wl1271_error("failed to initiate cmd role start sta"); | ||
503 | goto err_hlid; | ||
504 | } | ||
505 | |||
506 | goto out_free; | ||
507 | |||
508 | err_hlid: | ||
509 | /* clear links on error. */ | ||
510 | wl12xx_free_link(wl, &wl->sta_hlid); | ||
511 | |||
512 | out_free: | ||
513 | kfree(cmd); | ||
514 | |||
515 | out: | ||
516 | return ret; | ||
517 | } | ||
391 | 518 | ||
392 | join->beacon_interval = cpu_to_le16(wl->beacon_int); | 519 | int wl12xx_cmd_role_stop_sta(struct wl1271 *wl) |
393 | join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; | 520 | { |
521 | struct wl12xx_cmd_role_stop *cmd; | ||
522 | int ret; | ||
523 | |||
524 | if (WARN_ON(wl->sta_hlid == WL12XX_INVALID_LINK_ID)) | ||
525 | return -EINVAL; | ||
526 | |||
527 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
528 | if (!cmd) { | ||
529 | ret = -ENOMEM; | ||
530 | goto out; | ||
531 | } | ||
394 | 532 | ||
395 | join->channel = wl->channel; | 533 | wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wl->role_id); |
396 | join->ssid_len = wl->ssid_len; | ||
397 | memcpy(join->ssid, wl->ssid, wl->ssid_len); | ||
398 | 534 | ||
399 | join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; | 535 | cmd->role_id = wl->role_id; |
536 | cmd->disc_type = DISCONNECT_IMMEDIATE; | ||
537 | cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); | ||
400 | 538 | ||
401 | wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x", | 539 | ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); |
402 | join->basic_rate_set, join->supported_rate_set); | 540 | if (ret < 0) { |
541 | wl1271_error("failed to initiate cmd role stop sta"); | ||
542 | goto out_free; | ||
543 | } | ||
403 | 544 | ||
404 | ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0); | 545 | ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); |
405 | if (ret < 0) { | 546 | if (ret < 0) { |
406 | wl1271_error("failed to initiate cmd join"); | 547 | wl1271_error("cmd role stop sta event completion error"); |
407 | goto out_free; | 548 | goto out_free; |
408 | } | 549 | } |
409 | 550 | ||
410 | ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID); | 551 | wl12xx_free_link(wl, &wl->sta_hlid); |
411 | if (ret < 0) | 552 | |
412 | wl1271_error("cmd join event completion error"); | 553 | out_free: |
554 | kfree(cmd); | ||
555 | |||
556 | out: | ||
557 | return ret; | ||
558 | } | ||
559 | |||
560 | int wl12xx_cmd_role_start_ap(struct wl1271 *wl) | ||
561 | { | ||
562 | struct wl12xx_cmd_role_start *cmd; | ||
563 | struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; | ||
564 | int ret; | ||
565 | |||
566 | wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id); | ||
567 | |||
568 | /* | ||
569 | * We currently do not support hidden SSID. The real SSID | ||
570 | * should be fetched from mac80211 first. | ||
571 | */ | ||
572 | if (wl->ssid_len == 0) { | ||
573 | wl1271_warning("Hidden SSID currently not supported for AP"); | ||
574 | ret = -EINVAL; | ||
575 | goto out; | ||
576 | } | ||
577 | |||
578 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
579 | if (!cmd) { | ||
580 | ret = -ENOMEM; | ||
581 | goto out; | ||
582 | } | ||
583 | |||
584 | cmd->role_id = wl->role_id; | ||
585 | cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); | ||
586 | cmd->ap.bss_index = WL1271_AP_BSS_INDEX; | ||
587 | cmd->ap.global_hlid = WL1271_AP_GLOBAL_HLID; | ||
588 | cmd->ap.broadcast_hlid = WL1271_AP_BROADCAST_HLID; | ||
589 | cmd->ap.basic_rate_set = cpu_to_le32(wl->basic_rate_set); | ||
590 | cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int); | ||
591 | cmd->ap.dtim_interval = bss_conf->dtim_period; | ||
592 | cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; | ||
593 | cmd->channel = wl->channel; | ||
594 | cmd->ap.ssid_len = wl->ssid_len; | ||
595 | cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC; | ||
596 | memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len); | ||
597 | cmd->ap.local_rates = cpu_to_le32(0xffffffff); | ||
598 | |||
599 | switch (wl->band) { | ||
600 | case IEEE80211_BAND_2GHZ: | ||
601 | cmd->band = RADIO_BAND_2_4GHZ; | ||
602 | break; | ||
603 | case IEEE80211_BAND_5GHZ: | ||
604 | cmd->band = RADIO_BAND_5GHZ; | ||
605 | break; | ||
606 | default: | ||
607 | wl1271_warning("ap start - unknown band: %d", (int)wl->band); | ||
608 | cmd->band = RADIO_BAND_2_4GHZ; | ||
609 | break; | ||
610 | } | ||
611 | |||
612 | ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); | ||
613 | if (ret < 0) { | ||
614 | wl1271_error("failed to initiate cmd role start ap"); | ||
615 | goto out_free; | ||
616 | } | ||
413 | 617 | ||
414 | out_free: | 618 | out_free: |
415 | kfree(join); | 619 | kfree(cmd); |
416 | 620 | ||
417 | out: | 621 | out: |
418 | return ret; | 622 | return ret; |
419 | } | 623 | } |
420 | 624 | ||
625 | int wl12xx_cmd_role_stop_ap(struct wl1271 *wl) | ||
626 | { | ||
627 | struct wl12xx_cmd_role_stop *cmd; | ||
628 | int ret; | ||
629 | |||
630 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
631 | if (!cmd) { | ||
632 | ret = -ENOMEM; | ||
633 | goto out; | ||
634 | } | ||
635 | |||
636 | wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wl->role_id); | ||
637 | |||
638 | cmd->role_id = wl->role_id; | ||
639 | |||
640 | ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); | ||
641 | if (ret < 0) { | ||
642 | wl1271_error("failed to initiate cmd role stop ap"); | ||
643 | goto out_free; | ||
644 | } | ||
645 | |||
646 | out_free: | ||
647 | kfree(cmd); | ||
648 | |||
649 | out: | ||
650 | return ret; | ||
651 | } | ||
652 | |||
653 | |||
421 | /** | 654 | /** |
422 | * send test command to firmware | 655 | * send test command to firmware |
423 | * | 656 | * |
@@ -565,6 +798,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) | |||
565 | goto out; | 798 | goto out; |
566 | } | 799 | } |
567 | 800 | ||
801 | ps_params->role_id = wl->role_id; | ||
568 | ps_params->ps_mode = ps_mode; | 802 | ps_params->ps_mode = ps_mode; |
569 | 803 | ||
570 | ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, | 804 | ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, |
@@ -811,9 +1045,9 @@ int wl1271_build_qos_null_data(struct wl1271 *wl) | |||
811 | wl->basic_rate); | 1045 | wl->basic_rate); |
812 | } | 1046 | } |
813 | 1047 | ||
814 | int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id) | 1048 | int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid) |
815 | { | 1049 | { |
816 | struct wl1271_cmd_set_sta_keys *cmd; | 1050 | struct wl1271_cmd_set_keys *cmd; |
817 | int ret = 0; | 1051 | int ret = 0; |
818 | 1052 | ||
819 | wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id); | 1053 | wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id); |
@@ -824,36 +1058,7 @@ int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id) | |||
824 | goto out; | 1058 | goto out; |
825 | } | 1059 | } |
826 | 1060 | ||
827 | cmd->id = id; | 1061 | cmd->hlid = hlid; |
828 | cmd->key_action = cpu_to_le16(KEY_SET_ID); | ||
829 | cmd->key_type = KEY_WEP; | ||
830 | |||
831 | ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); | ||
832 | if (ret < 0) { | ||
833 | wl1271_warning("cmd set_default_wep_key failed: %d", ret); | ||
834 | goto out; | ||
835 | } | ||
836 | |||
837 | out: | ||
838 | kfree(cmd); | ||
839 | |||
840 | return ret; | ||
841 | } | ||
842 | |||
843 | int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id) | ||
844 | { | ||
845 | struct wl1271_cmd_set_ap_keys *cmd; | ||
846 | int ret = 0; | ||
847 | |||
848 | wl1271_debug(DEBUG_CMD, "cmd set_ap_default_wep_key %d", id); | ||
849 | |||
850 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
851 | if (!cmd) { | ||
852 | ret = -ENOMEM; | ||
853 | goto out; | ||
854 | } | ||
855 | |||
856 | cmd->hlid = WL1271_AP_BROADCAST_HLID; | ||
857 | cmd->key_id = id; | 1062 | cmd->key_id = id; |
858 | cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; | 1063 | cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; |
859 | cmd->key_action = cpu_to_le16(KEY_SET_ID); | 1064 | cmd->key_action = cpu_to_le16(KEY_SET_ID); |
@@ -861,7 +1066,7 @@ int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id) | |||
861 | 1066 | ||
862 | ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); | 1067 | ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0); |
863 | if (ret < 0) { | 1068 | if (ret < 0) { |
864 | wl1271_warning("cmd set_ap_default_wep_key failed: %d", ret); | 1069 | wl1271_warning("cmd set_default_wep_key failed: %d", ret); |
865 | goto out; | 1070 | goto out; |
866 | } | 1071 | } |
867 | 1072 | ||
@@ -875,7 +1080,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | |||
875 | u8 key_size, const u8 *key, const u8 *addr, | 1080 | u8 key_size, const u8 *key, const u8 *addr, |
876 | u32 tx_seq_32, u16 tx_seq_16) | 1081 | u32 tx_seq_32, u16 tx_seq_16) |
877 | { | 1082 | { |
878 | struct wl1271_cmd_set_sta_keys *cmd; | 1083 | struct wl1271_cmd_set_keys *cmd; |
879 | int ret = 0; | 1084 | int ret = 0; |
880 | 1085 | ||
881 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 1086 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
@@ -884,8 +1089,14 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | |||
884 | goto out; | 1089 | goto out; |
885 | } | 1090 | } |
886 | 1091 | ||
887 | if (key_type != KEY_WEP) | 1092 | cmd->hlid = wl->sta_hlid; |
888 | memcpy(cmd->addr, addr, ETH_ALEN); | 1093 | |
1094 | if (key_type == KEY_WEP) | ||
1095 | cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; | ||
1096 | else if (is_broadcast_ether_addr(addr)) | ||
1097 | cmd->lid_key_type = BROADCAST_LID_TYPE; | ||
1098 | else | ||
1099 | cmd->lid_key_type = UNICAST_LID_TYPE; | ||
889 | 1100 | ||
890 | cmd->key_action = cpu_to_le16(action); | 1101 | cmd->key_action = cpu_to_le16(action); |
891 | cmd->key_size = key_size; | 1102 | cmd->key_size = key_size; |
@@ -894,10 +1105,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | |||
894 | cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16); | 1105 | cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16); |
895 | cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32); | 1106 | cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32); |
896 | 1107 | ||
897 | /* we have only one SSID profile */ | 1108 | cmd->key_id = id; |
898 | cmd->ssid_profile = 0; | ||
899 | |||
900 | cmd->id = id; | ||
901 | 1109 | ||
902 | if (key_type == KEY_TKIP) { | 1110 | if (key_type == KEY_TKIP) { |
903 | /* | 1111 | /* |
@@ -928,11 +1136,15 @@ out: | |||
928 | return ret; | 1136 | return ret; |
929 | } | 1137 | } |
930 | 1138 | ||
1139 | /* | ||
1140 | * TODO: merge with sta/ibss into 1 set_key function. | ||
1141 | * note there are slight diffs | ||
1142 | */ | ||
931 | int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | 1143 | int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, |
932 | u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, | 1144 | u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, |
933 | u16 tx_seq_16) | 1145 | u16 tx_seq_16) |
934 | { | 1146 | { |
935 | struct wl1271_cmd_set_ap_keys *cmd; | 1147 | struct wl1271_cmd_set_keys *cmd; |
936 | int ret = 0; | 1148 | int ret = 0; |
937 | u8 lid_type; | 1149 | u8 lid_type; |
938 | 1150 | ||
@@ -989,45 +1201,12 @@ out: | |||
989 | return ret; | 1201 | return ret; |
990 | } | 1202 | } |
991 | 1203 | ||
992 | int wl1271_cmd_disconnect(struct wl1271 *wl) | 1204 | int wl12xx_cmd_set_peer_state(struct wl1271 *wl) |
993 | { | ||
994 | struct wl1271_cmd_disconnect *cmd; | ||
995 | int ret = 0; | ||
996 | |||
997 | wl1271_debug(DEBUG_CMD, "cmd disconnect"); | ||
998 | |||
999 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1000 | if (!cmd) { | ||
1001 | ret = -ENOMEM; | ||
1002 | goto out; | ||
1003 | } | ||
1004 | |||
1005 | /* disconnect reason is not used in immediate disconnections */ | ||
1006 | cmd->type = DISCONNECT_IMMEDIATE; | ||
1007 | |||
1008 | ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd), 0); | ||
1009 | if (ret < 0) { | ||
1010 | wl1271_error("failed to send disconnect command"); | ||
1011 | goto out_free; | ||
1012 | } | ||
1013 | |||
1014 | ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID); | ||
1015 | if (ret < 0) | ||
1016 | wl1271_error("cmd disconnect event completion error"); | ||
1017 | |||
1018 | out_free: | ||
1019 | kfree(cmd); | ||
1020 | |||
1021 | out: | ||
1022 | return ret; | ||
1023 | } | ||
1024 | |||
1025 | int wl1271_cmd_set_sta_state(struct wl1271 *wl) | ||
1026 | { | 1205 | { |
1027 | struct wl1271_cmd_set_sta_state *cmd; | 1206 | struct wl12xx_cmd_set_peer_state *cmd; |
1028 | int ret = 0; | 1207 | int ret = 0; |
1029 | 1208 | ||
1030 | wl1271_debug(DEBUG_CMD, "cmd set sta state"); | 1209 | wl1271_debug(DEBUG_CMD, "cmd set peer state (hlid=%d)", wl->sta_hlid); |
1031 | 1210 | ||
1032 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 1211 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
1033 | if (!cmd) { | 1212 | if (!cmd) { |
@@ -1035,11 +1214,12 @@ int wl1271_cmd_set_sta_state(struct wl1271 *wl) | |||
1035 | goto out; | 1214 | goto out; |
1036 | } | 1215 | } |
1037 | 1216 | ||
1217 | cmd->hlid = wl->sta_hlid; | ||
1038 | cmd->state = WL1271_CMD_STA_STATE_CONNECTED; | 1218 | cmd->state = WL1271_CMD_STA_STATE_CONNECTED; |
1039 | 1219 | ||
1040 | ret = wl1271_cmd_send(wl, CMD_SET_STA_STATE, cmd, sizeof(*cmd), 0); | 1220 | ret = wl1271_cmd_send(wl, CMD_SET_PEER_STATE, cmd, sizeof(*cmd), 0); |
1041 | if (ret < 0) { | 1221 | if (ret < 0) { |
1042 | wl1271_error("failed to send set STA state command"); | 1222 | wl1271_error("failed to send set peer state command"); |
1043 | goto out_free; | 1223 | goto out_free; |
1044 | } | 1224 | } |
1045 | 1225 | ||
@@ -1049,106 +1229,12 @@ out_free: | |||
1049 | out: | 1229 | out: |
1050 | return ret; | 1230 | return ret; |
1051 | } | 1231 | } |
1052 | 1232 | int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) | |
1053 | int wl1271_cmd_start_bss(struct wl1271 *wl) | ||
1054 | { | ||
1055 | struct wl1271_cmd_bss_start *cmd; | ||
1056 | struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; | ||
1057 | int ret; | ||
1058 | |||
1059 | wl1271_debug(DEBUG_CMD, "cmd start bss"); | ||
1060 | |||
1061 | /* | ||
1062 | * FIXME: We currently do not support hidden SSID. The real SSID | ||
1063 | * should be fetched from mac80211 first. | ||
1064 | */ | ||
1065 | if (wl->ssid_len == 0) { | ||
1066 | wl1271_warning("Hidden SSID currently not supported for AP"); | ||
1067 | ret = -EINVAL; | ||
1068 | goto out; | ||
1069 | } | ||
1070 | |||
1071 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1072 | if (!cmd) { | ||
1073 | ret = -ENOMEM; | ||
1074 | goto out; | ||
1075 | } | ||
1076 | |||
1077 | memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); | ||
1078 | |||
1079 | cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); | ||
1080 | cmd->bss_index = WL1271_AP_BSS_INDEX; | ||
1081 | cmd->global_hlid = WL1271_AP_GLOBAL_HLID; | ||
1082 | cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; | ||
1083 | cmd->basic_rate_set = cpu_to_le32(wl->basic_rate_set); | ||
1084 | cmd->beacon_interval = cpu_to_le16(wl->beacon_int); | ||
1085 | cmd->dtim_interval = bss_conf->dtim_period; | ||
1086 | cmd->beacon_expiry = WL1271_AP_DEF_BEACON_EXP; | ||
1087 | cmd->channel = wl->channel; | ||
1088 | cmd->ssid_len = wl->ssid_len; | ||
1089 | cmd->ssid_type = SSID_TYPE_PUBLIC; | ||
1090 | memcpy(cmd->ssid, wl->ssid, wl->ssid_len); | ||
1091 | |||
1092 | switch (wl->band) { | ||
1093 | case IEEE80211_BAND_2GHZ: | ||
1094 | cmd->band = RADIO_BAND_2_4GHZ; | ||
1095 | break; | ||
1096 | case IEEE80211_BAND_5GHZ: | ||
1097 | cmd->band = RADIO_BAND_5GHZ; | ||
1098 | break; | ||
1099 | default: | ||
1100 | wl1271_warning("bss start - unknown band: %d", (int)wl->band); | ||
1101 | cmd->band = RADIO_BAND_2_4GHZ; | ||
1102 | break; | ||
1103 | } | ||
1104 | |||
1105 | ret = wl1271_cmd_send(wl, CMD_BSS_START, cmd, sizeof(*cmd), 0); | ||
1106 | if (ret < 0) { | ||
1107 | wl1271_error("failed to initiate cmd start bss"); | ||
1108 | goto out_free; | ||
1109 | } | ||
1110 | |||
1111 | out_free: | ||
1112 | kfree(cmd); | ||
1113 | |||
1114 | out: | ||
1115 | return ret; | ||
1116 | } | ||
1117 | |||
1118 | int wl1271_cmd_stop_bss(struct wl1271 *wl) | ||
1119 | { | ||
1120 | struct wl1271_cmd_bss_start *cmd; | ||
1121 | int ret; | ||
1122 | |||
1123 | wl1271_debug(DEBUG_CMD, "cmd stop bss"); | ||
1124 | |||
1125 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
1126 | if (!cmd) { | ||
1127 | ret = -ENOMEM; | ||
1128 | goto out; | ||
1129 | } | ||
1130 | |||
1131 | cmd->bss_index = WL1271_AP_BSS_INDEX; | ||
1132 | |||
1133 | ret = wl1271_cmd_send(wl, CMD_BSS_STOP, cmd, sizeof(*cmd), 0); | ||
1134 | if (ret < 0) { | ||
1135 | wl1271_error("failed to initiate cmd stop bss"); | ||
1136 | goto out_free; | ||
1137 | } | ||
1138 | |||
1139 | out_free: | ||
1140 | kfree(cmd); | ||
1141 | |||
1142 | out: | ||
1143 | return ret; | ||
1144 | } | ||
1145 | |||
1146 | int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) | ||
1147 | { | 1233 | { |
1148 | struct wl1271_cmd_add_sta *cmd; | 1234 | struct wl12xx_cmd_add_peer *cmd; |
1149 | int ret; | 1235 | int ret; |
1150 | 1236 | ||
1151 | wl1271_debug(DEBUG_CMD, "cmd add sta %d", (int)hlid); | 1237 | wl1271_debug(DEBUG_CMD, "cmd add peer %d", (int)hlid); |
1152 | 1238 | ||
1153 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 1239 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
1154 | if (!cmd) { | 1240 | if (!cmd) { |
@@ -1168,11 +1254,11 @@ int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) | |||
1168 | cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl, | 1254 | cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl, |
1169 | sta->supp_rates[wl->band])); | 1255 | sta->supp_rates[wl->band])); |
1170 | 1256 | ||
1171 | wl1271_debug(DEBUG_CMD, "new sta rates: 0x%x", cmd->supported_rates); | 1257 | wl1271_debug(DEBUG_CMD, "new peer rates: 0x%x", cmd->supported_rates); |
1172 | 1258 | ||
1173 | ret = wl1271_cmd_send(wl, CMD_ADD_STA, cmd, sizeof(*cmd), 0); | 1259 | ret = wl1271_cmd_send(wl, CMD_ADD_PEER, cmd, sizeof(*cmd), 0); |
1174 | if (ret < 0) { | 1260 | if (ret < 0) { |
1175 | wl1271_error("failed to initiate cmd add sta"); | 1261 | wl1271_error("failed to initiate cmd add peer"); |
1176 | goto out_free; | 1262 | goto out_free; |
1177 | } | 1263 | } |
1178 | 1264 | ||
@@ -1183,12 +1269,12 @@ out: | |||
1183 | return ret; | 1269 | return ret; |
1184 | } | 1270 | } |
1185 | 1271 | ||
1186 | int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid) | 1272 | int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) |
1187 | { | 1273 | { |
1188 | struct wl1271_cmd_remove_sta *cmd; | 1274 | struct wl12xx_cmd_remove_peer *cmd; |
1189 | int ret; | 1275 | int ret; |
1190 | 1276 | ||
1191 | wl1271_debug(DEBUG_CMD, "cmd remove sta %d", (int)hlid); | 1277 | wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid); |
1192 | 1278 | ||
1193 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 1279 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
1194 | if (!cmd) { | 1280 | if (!cmd) { |
@@ -1201,9 +1287,9 @@ int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid) | |||
1201 | cmd->reason_opcode = 0; | 1287 | cmd->reason_opcode = 0; |
1202 | cmd->send_deauth_flag = 0; | 1288 | cmd->send_deauth_flag = 0; |
1203 | 1289 | ||
1204 | ret = wl1271_cmd_send(wl, CMD_REMOVE_STA, cmd, sizeof(*cmd), 0); | 1290 | ret = wl1271_cmd_send(wl, CMD_REMOVE_PEER, cmd, sizeof(*cmd), 0); |
1205 | if (ret < 0) { | 1291 | if (ret < 0) { |
1206 | wl1271_error("failed to initiate cmd remove sta"); | 1292 | wl1271_error("failed to initiate cmd remove peer"); |
1207 | goto out_free; | 1293 | goto out_free; |
1208 | } | 1294 | } |
1209 | 1295 | ||
@@ -1211,7 +1297,8 @@ int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid) | |||
1211 | * We are ok with a timeout here. The event is sometimes not sent | 1297 | * We are ok with a timeout here. The event is sometimes not sent |
1212 | * due to a firmware bug. | 1298 | * due to a firmware bug. |
1213 | */ | 1299 | */ |
1214 | wl1271_cmd_wait_for_event_or_timeout(wl, STA_REMOVE_COMPLETE_EVENT_ID); | 1300 | wl1271_cmd_wait_for_event_or_timeout(wl, |
1301 | PEER_REMOVE_COMPLETE_EVENT_ID); | ||
1215 | 1302 | ||
1216 | out_free: | 1303 | out_free: |
1217 | kfree(cmd); | 1304 | kfree(cmd); |