aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/cmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/wl12xx/cmd.c')
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c368
1 files changed, 231 insertions, 137 deletions
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index a52299e548fa..e0d217979485 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -29,6 +29,7 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30 30
31#include "wl12xx.h" 31#include "wl12xx.h"
32#include "debug.h"
32#include "reg.h" 33#include "reg.h"
33#include "io.h" 34#include "io.h"
34#include "acx.h" 35#include "acx.h"
@@ -120,6 +121,11 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
120 if (!wl->nvs) 121 if (!wl->nvs)
121 return -ENODEV; 122 return -ENODEV;
122 123
124 if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
125 wl1271_warning("FEM index from INI out of bounds");
126 return -EINVAL;
127 }
128
123 gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); 129 gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
124 if (!gen_parms) 130 if (!gen_parms)
125 return -ENOMEM; 131 return -ENOMEM;
@@ -143,6 +149,12 @@ int wl1271_cmd_general_parms(struct wl1271 *wl)
143 gp->tx_bip_fem_manufacturer = 149 gp->tx_bip_fem_manufacturer =
144 gen_parms->general_params.tx_bip_fem_manufacturer; 150 gen_parms->general_params.tx_bip_fem_manufacturer;
145 151
152 if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
153 wl1271_warning("FEM index from FW out of bounds");
154 ret = -EINVAL;
155 goto out;
156 }
157
146 wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", 158 wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
147 answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); 159 answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer);
148 160
@@ -162,6 +174,11 @@ int wl128x_cmd_general_parms(struct wl1271 *wl)
162 if (!wl->nvs) 174 if (!wl->nvs)
163 return -ENODEV; 175 return -ENODEV;
164 176
177 if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
178 wl1271_warning("FEM index from ini out of bounds");
179 return -EINVAL;
180 }
181
165 gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); 182 gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
166 if (!gen_parms) 183 if (!gen_parms)
167 return -ENOMEM; 184 return -ENOMEM;
@@ -186,6 +203,12 @@ int wl128x_cmd_general_parms(struct wl1271 *wl)
186 gp->tx_bip_fem_manufacturer = 203 gp->tx_bip_fem_manufacturer =
187 gen_parms->general_params.tx_bip_fem_manufacturer; 204 gen_parms->general_params.tx_bip_fem_manufacturer;
188 205
206 if (gp->tx_bip_fem_manufacturer >= WL1271_INI_FEM_MODULE_COUNT) {
207 wl1271_warning("FEM index from FW out of bounds");
208 ret = -EINVAL;
209 goto out;
210 }
211
189 wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n", 212 wl1271_debug(DEBUG_CMD, "FEM autodetect: %s, manufacturer: %d\n",
190 answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer); 213 answer ? "auto" : "manual", gp->tx_bip_fem_manufacturer);
191 214
@@ -358,7 +381,8 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
358 return 0; 381 return 0;
359} 382}
360 383
361int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id) 384int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type,
385 u8 *role_id)
362{ 386{
363 struct wl12xx_cmd_role_enable *cmd; 387 struct wl12xx_cmd_role_enable *cmd;
364 int ret; 388 int ret;
@@ -381,7 +405,7 @@ int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id)
381 goto out_free; 405 goto out_free;
382 } 406 }
383 407
384 memcpy(cmd->mac_address, wl->mac_addr, ETH_ALEN); 408 memcpy(cmd->mac_address, addr, ETH_ALEN);
385 cmd->role_type = role_type; 409 cmd->role_type = role_type;
386 410
387 ret = wl1271_cmd_send(wl, CMD_ROLE_ENABLE, cmd, sizeof(*cmd), 0); 411 ret = wl1271_cmd_send(wl, CMD_ROLE_ENABLE, cmd, sizeof(*cmd), 0);
@@ -433,37 +457,41 @@ out:
433 return ret; 457 return ret;
434} 458}
435 459
436static int wl12xx_allocate_link(struct wl1271 *wl, u8 *hlid) 460int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
437{ 461{
438 u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS); 462 u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS);
439 if (link >= WL12XX_MAX_LINKS) 463 if (link >= WL12XX_MAX_LINKS)
440 return -EBUSY; 464 return -EBUSY;
441 465
442 __set_bit(link, wl->links_map); 466 __set_bit(link, wl->links_map);
467 __set_bit(link, wlvif->links_map);
443 *hlid = link; 468 *hlid = link;
444 return 0; 469 return 0;
445} 470}
446 471
447static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid) 472void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
448{ 473{
449 if (*hlid == WL12XX_INVALID_LINK_ID) 474 if (*hlid == WL12XX_INVALID_LINK_ID)
450 return; 475 return;
451 476
452 __clear_bit(*hlid, wl->links_map); 477 __clear_bit(*hlid, wl->links_map);
478 __clear_bit(*hlid, wlvif->links_map);
453 *hlid = WL12XX_INVALID_LINK_ID; 479 *hlid = WL12XX_INVALID_LINK_ID;
454} 480}
455 481
456static int wl12xx_get_new_session_id(struct wl1271 *wl) 482static int wl12xx_get_new_session_id(struct wl1271 *wl,
483 struct wl12xx_vif *wlvif)
457{ 484{
458 if (wl->session_counter >= SESSION_COUNTER_MAX) 485 if (wlvif->session_counter >= SESSION_COUNTER_MAX)
459 wl->session_counter = 0; 486 wlvif->session_counter = 0;
460 487
461 wl->session_counter++; 488 wlvif->session_counter++;
462 489
463 return wl->session_counter; 490 return wlvif->session_counter;
464} 491}
465 492
466int wl12xx_cmd_role_start_dev(struct wl1271 *wl) 493static int wl12xx_cmd_role_start_dev(struct wl1271 *wl,
494 struct wl12xx_vif *wlvif)
467{ 495{
468 struct wl12xx_cmd_role_start *cmd; 496 struct wl12xx_cmd_role_start *cmd;
469 int ret; 497 int ret;
@@ -474,20 +502,20 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl)
474 goto out; 502 goto out;
475 } 503 }
476 504
477 wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wl->dev_role_id); 505 wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wlvif->dev_role_id);
478 506
479 cmd->role_id = wl->dev_role_id; 507 cmd->role_id = wlvif->dev_role_id;
480 if (wl->band == IEEE80211_BAND_5GHZ) 508 if (wlvif->band == IEEE80211_BAND_5GHZ)
481 cmd->band = WL12XX_BAND_5GHZ; 509 cmd->band = WL12XX_BAND_5GHZ;
482 cmd->channel = wl->channel; 510 cmd->channel = wlvif->channel;
483 511
484 if (wl->dev_hlid == WL12XX_INVALID_LINK_ID) { 512 if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) {
485 ret = wl12xx_allocate_link(wl, &wl->dev_hlid); 513 ret = wl12xx_allocate_link(wl, wlvif, &wlvif->dev_hlid);
486 if (ret) 514 if (ret)
487 goto out_free; 515 goto out_free;
488 } 516 }
489 cmd->device.hlid = wl->dev_hlid; 517 cmd->device.hlid = wlvif->dev_hlid;
490 cmd->device.session = wl->session_counter; 518 cmd->device.session = wlvif->session_counter;
491 519
492 wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d", 520 wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d",
493 cmd->role_id, cmd->device.hlid, cmd->device.session); 521 cmd->role_id, cmd->device.hlid, cmd->device.session);
@@ -502,9 +530,7 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl)
502 530
503err_hlid: 531err_hlid:
504 /* clear links on error */ 532 /* clear links on error */
505 __clear_bit(wl->dev_hlid, wl->links_map); 533 wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid);
506 wl->dev_hlid = WL12XX_INVALID_LINK_ID;
507
508 534
509out_free: 535out_free:
510 kfree(cmd); 536 kfree(cmd);
@@ -513,12 +539,13 @@ out:
513 return ret; 539 return ret;
514} 540}
515 541
516int wl12xx_cmd_role_stop_dev(struct wl1271 *wl) 542static int wl12xx_cmd_role_stop_dev(struct wl1271 *wl,
543 struct wl12xx_vif *wlvif)
517{ 544{
518 struct wl12xx_cmd_role_stop *cmd; 545 struct wl12xx_cmd_role_stop *cmd;
519 int ret; 546 int ret;
520 547
521 if (WARN_ON(wl->dev_hlid == WL12XX_INVALID_LINK_ID)) 548 if (WARN_ON(wlvif->dev_hlid == WL12XX_INVALID_LINK_ID))
522 return -EINVAL; 549 return -EINVAL;
523 550
524 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 551 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@@ -529,7 +556,7 @@ int wl12xx_cmd_role_stop_dev(struct wl1271 *wl)
529 556
530 wl1271_debug(DEBUG_CMD, "cmd role stop dev"); 557 wl1271_debug(DEBUG_CMD, "cmd role stop dev");
531 558
532 cmd->role_id = wl->dev_role_id; 559 cmd->role_id = wlvif->dev_role_id;
533 cmd->disc_type = DISCONNECT_IMMEDIATE; 560 cmd->disc_type = DISCONNECT_IMMEDIATE;
534 cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); 561 cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED);
535 562
@@ -545,7 +572,7 @@ int wl12xx_cmd_role_stop_dev(struct wl1271 *wl)
545 goto out_free; 572 goto out_free;
546 } 573 }
547 574
548 wl12xx_free_link(wl, &wl->dev_hlid); 575 wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid);
549 576
550out_free: 577out_free:
551 kfree(cmd); 578 kfree(cmd);
@@ -554,8 +581,9 @@ out:
554 return ret; 581 return ret;
555} 582}
556 583
557int wl12xx_cmd_role_start_sta(struct wl1271 *wl) 584int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
558{ 585{
586 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
559 struct wl12xx_cmd_role_start *cmd; 587 struct wl12xx_cmd_role_start *cmd;
560 int ret; 588 int ret;
561 589
@@ -565,33 +593,33 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl)
565 goto out; 593 goto out;
566 } 594 }
567 595
568 wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wl->role_id); 596 wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wlvif->role_id);
569 597
570 cmd->role_id = wl->role_id; 598 cmd->role_id = wlvif->role_id;
571 if (wl->band == IEEE80211_BAND_5GHZ) 599 if (wlvif->band == IEEE80211_BAND_5GHZ)
572 cmd->band = WL12XX_BAND_5GHZ; 600 cmd->band = WL12XX_BAND_5GHZ;
573 cmd->channel = wl->channel; 601 cmd->channel = wlvif->channel;
574 cmd->sta.basic_rate_set = cpu_to_le32(wl->basic_rate_set); 602 cmd->sta.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set);
575 cmd->sta.beacon_interval = cpu_to_le16(wl->beacon_int); 603 cmd->sta.beacon_interval = cpu_to_le16(wlvif->beacon_int);
576 cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY; 604 cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY;
577 cmd->sta.ssid_len = wl->ssid_len; 605 cmd->sta.ssid_len = wlvif->ssid_len;
578 memcpy(cmd->sta.ssid, wl->ssid, wl->ssid_len); 606 memcpy(cmd->sta.ssid, wlvif->ssid, wlvif->ssid_len);
579 memcpy(cmd->sta.bssid, wl->bssid, ETH_ALEN); 607 memcpy(cmd->sta.bssid, vif->bss_conf.bssid, ETH_ALEN);
580 cmd->sta.local_rates = cpu_to_le32(wl->rate_set); 608 cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set);
581 609
582 if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { 610 if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) {
583 ret = wl12xx_allocate_link(wl, &wl->sta_hlid); 611 ret = wl12xx_allocate_link(wl, wlvif, &wlvif->sta.hlid);
584 if (ret) 612 if (ret)
585 goto out_free; 613 goto out_free;
586 } 614 }
587 cmd->sta.hlid = wl->sta_hlid; 615 cmd->sta.hlid = wlvif->sta.hlid;
588 cmd->sta.session = wl12xx_get_new_session_id(wl); 616 cmd->sta.session = wl12xx_get_new_session_id(wl, wlvif);
589 cmd->sta.remote_rates = cpu_to_le32(wl->rate_set); 617 cmd->sta.remote_rates = cpu_to_le32(wlvif->rate_set);
590 618
591 wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " 619 wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d "
592 "basic_rate_set: 0x%x, remote_rates: 0x%x", 620 "basic_rate_set: 0x%x, remote_rates: 0x%x",
593 wl->role_id, cmd->sta.hlid, cmd->sta.session, 621 wlvif->role_id, cmd->sta.hlid, cmd->sta.session,
594 wl->basic_rate_set, wl->rate_set); 622 wlvif->basic_rate_set, wlvif->rate_set);
595 623
596 ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); 624 ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
597 if (ret < 0) { 625 if (ret < 0) {
@@ -603,7 +631,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl)
603 631
604err_hlid: 632err_hlid:
605 /* clear links on error. */ 633 /* clear links on error. */
606 wl12xx_free_link(wl, &wl->sta_hlid); 634 wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid);
607 635
608out_free: 636out_free:
609 kfree(cmd); 637 kfree(cmd);
@@ -613,12 +641,12 @@ out:
613} 641}
614 642
615/* use this function to stop ibss as well */ 643/* use this function to stop ibss as well */
616int wl12xx_cmd_role_stop_sta(struct wl1271 *wl) 644int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
617{ 645{
618 struct wl12xx_cmd_role_stop *cmd; 646 struct wl12xx_cmd_role_stop *cmd;
619 int ret; 647 int ret;
620 648
621 if (WARN_ON(wl->sta_hlid == WL12XX_INVALID_LINK_ID)) 649 if (WARN_ON(wlvif->sta.hlid == WL12XX_INVALID_LINK_ID))
622 return -EINVAL; 650 return -EINVAL;
623 651
624 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 652 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@@ -627,9 +655,9 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl)
627 goto out; 655 goto out;
628 } 656 }
629 657
630 wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wl->role_id); 658 wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wlvif->role_id);
631 659
632 cmd->role_id = wl->role_id; 660 cmd->role_id = wlvif->role_id;
633 cmd->disc_type = DISCONNECT_IMMEDIATE; 661 cmd->disc_type = DISCONNECT_IMMEDIATE;
634 cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED); 662 cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED);
635 663
@@ -639,7 +667,7 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl)
639 goto out_free; 667 goto out_free;
640 } 668 }
641 669
642 wl12xx_free_link(wl, &wl->sta_hlid); 670 wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid);
643 671
644out_free: 672out_free:
645 kfree(cmd); 673 kfree(cmd);
@@ -648,16 +676,17 @@ out:
648 return ret; 676 return ret;
649} 677}
650 678
651int wl12xx_cmd_role_start_ap(struct wl1271 *wl) 679int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
652{ 680{
653 struct wl12xx_cmd_role_start *cmd; 681 struct wl12xx_cmd_role_start *cmd;
654 struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; 682 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
683 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
655 int ret; 684 int ret;
656 685
657 wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id); 686 wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wlvif->role_id);
658 687
659 /* trying to use hidden SSID with an old hostapd version */ 688 /* trying to use hidden SSID with an old hostapd version */
660 if (wl->ssid_len == 0 && !bss_conf->hidden_ssid) { 689 if (wlvif->ssid_len == 0 && !bss_conf->hidden_ssid) {
661 wl1271_error("got a null SSID from beacon/bss"); 690 wl1271_error("got a null SSID from beacon/bss");
662 ret = -EINVAL; 691 ret = -EINVAL;
663 goto out; 692 goto out;
@@ -669,30 +698,30 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
669 goto out; 698 goto out;
670 } 699 }
671 700
672 ret = wl12xx_allocate_link(wl, &wl->ap_global_hlid); 701 ret = wl12xx_allocate_link(wl, wlvif, &wlvif->ap.global_hlid);
673 if (ret < 0) 702 if (ret < 0)
674 goto out_free; 703 goto out_free;
675 704
676 ret = wl12xx_allocate_link(wl, &wl->ap_bcast_hlid); 705 ret = wl12xx_allocate_link(wl, wlvif, &wlvif->ap.bcast_hlid);
677 if (ret < 0) 706 if (ret < 0)
678 goto out_free_global; 707 goto out_free_global;
679 708
680 cmd->role_id = wl->role_id; 709 cmd->role_id = wlvif->role_id;
681 cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); 710 cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
682 cmd->ap.bss_index = WL1271_AP_BSS_INDEX; 711 cmd->ap.bss_index = WL1271_AP_BSS_INDEX;
683 cmd->ap.global_hlid = wl->ap_global_hlid; 712 cmd->ap.global_hlid = wlvif->ap.global_hlid;
684 cmd->ap.broadcast_hlid = wl->ap_bcast_hlid; 713 cmd->ap.broadcast_hlid = wlvif->ap.bcast_hlid;
685 cmd->ap.basic_rate_set = cpu_to_le32(wl->basic_rate_set); 714 cmd->ap.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set);
686 cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int); 715 cmd->ap.beacon_interval = cpu_to_le16(wlvif->beacon_int);
687 cmd->ap.dtim_interval = bss_conf->dtim_period; 716 cmd->ap.dtim_interval = bss_conf->dtim_period;
688 cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; 717 cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
689 cmd->channel = wl->channel; 718 cmd->channel = wlvif->channel;
690 719
691 if (!bss_conf->hidden_ssid) { 720 if (!bss_conf->hidden_ssid) {
692 /* take the SSID from the beacon for backward compatibility */ 721 /* take the SSID from the beacon for backward compatibility */
693 cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC; 722 cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC;
694 cmd->ap.ssid_len = wl->ssid_len; 723 cmd->ap.ssid_len = wlvif->ssid_len;
695 memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len); 724 memcpy(cmd->ap.ssid, wlvif->ssid, wlvif->ssid_len);
696 } else { 725 } else {
697 cmd->ap.ssid_type = WL12XX_SSID_TYPE_HIDDEN; 726 cmd->ap.ssid_type = WL12XX_SSID_TYPE_HIDDEN;
698 cmd->ap.ssid_len = bss_conf->ssid_len; 727 cmd->ap.ssid_len = bss_conf->ssid_len;
@@ -701,7 +730,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
701 730
702 cmd->ap.local_rates = cpu_to_le32(0xffffffff); 731 cmd->ap.local_rates = cpu_to_le32(0xffffffff);
703 732
704 switch (wl->band) { 733 switch (wlvif->band) {
705 case IEEE80211_BAND_2GHZ: 734 case IEEE80211_BAND_2GHZ:
706 cmd->band = RADIO_BAND_2_4GHZ; 735 cmd->band = RADIO_BAND_2_4GHZ;
707 break; 736 break;
@@ -709,7 +738,7 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
709 cmd->band = RADIO_BAND_5GHZ; 738 cmd->band = RADIO_BAND_5GHZ;
710 break; 739 break;
711 default: 740 default:
712 wl1271_warning("ap start - unknown band: %d", (int)wl->band); 741 wl1271_warning("ap start - unknown band: %d", (int)wlvif->band);
713 cmd->band = RADIO_BAND_2_4GHZ; 742 cmd->band = RADIO_BAND_2_4GHZ;
714 break; 743 break;
715 } 744 }
@@ -723,10 +752,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
723 goto out_free; 752 goto out_free;
724 753
725out_free_bcast: 754out_free_bcast:
726 wl12xx_free_link(wl, &wl->ap_bcast_hlid); 755 wl12xx_free_link(wl, wlvif, &wlvif->ap.bcast_hlid);
727 756
728out_free_global: 757out_free_global:
729 wl12xx_free_link(wl, &wl->ap_global_hlid); 758 wl12xx_free_link(wl, wlvif, &wlvif->ap.global_hlid);
730 759
731out_free: 760out_free:
732 kfree(cmd); 761 kfree(cmd);
@@ -735,7 +764,7 @@ out:
735 return ret; 764 return ret;
736} 765}
737 766
738int wl12xx_cmd_role_stop_ap(struct wl1271 *wl) 767int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
739{ 768{
740 struct wl12xx_cmd_role_stop *cmd; 769 struct wl12xx_cmd_role_stop *cmd;
741 int ret; 770 int ret;
@@ -746,9 +775,9 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl)
746 goto out; 775 goto out;
747 } 776 }
748 777
749 wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wl->role_id); 778 wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wlvif->role_id);
750 779
751 cmd->role_id = wl->role_id; 780 cmd->role_id = wlvif->role_id;
752 781
753 ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0); 782 ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
754 if (ret < 0) { 783 if (ret < 0) {
@@ -756,8 +785,8 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl)
756 goto out_free; 785 goto out_free;
757 } 786 }
758 787
759 wl12xx_free_link(wl, &wl->ap_bcast_hlid); 788 wl12xx_free_link(wl, wlvif, &wlvif->ap.bcast_hlid);
760 wl12xx_free_link(wl, &wl->ap_global_hlid); 789 wl12xx_free_link(wl, wlvif, &wlvif->ap.global_hlid);
761 790
762out_free: 791out_free:
763 kfree(cmd); 792 kfree(cmd);
@@ -766,10 +795,11 @@ out:
766 return ret; 795 return ret;
767} 796}
768 797
769int wl12xx_cmd_role_start_ibss(struct wl1271 *wl) 798int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif)
770{ 799{
800 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
771 struct wl12xx_cmd_role_start *cmd; 801 struct wl12xx_cmd_role_start *cmd;
772 struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; 802 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
773 int ret; 803 int ret;
774 804
775 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 805 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@@ -778,35 +808,36 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl)
778 goto out; 808 goto out;
779 } 809 }
780 810
781 wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wl->role_id); 811 wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wlvif->role_id);
782 812
783 cmd->role_id = wl->role_id; 813 cmd->role_id = wlvif->role_id;
784 if (wl->band == IEEE80211_BAND_5GHZ) 814 if (wlvif->band == IEEE80211_BAND_5GHZ)
785 cmd->band = WL12XX_BAND_5GHZ; 815 cmd->band = WL12XX_BAND_5GHZ;
786 cmd->channel = wl->channel; 816 cmd->channel = wlvif->channel;
787 cmd->ibss.basic_rate_set = cpu_to_le32(wl->basic_rate_set); 817 cmd->ibss.basic_rate_set = cpu_to_le32(wlvif->basic_rate_set);
788 cmd->ibss.beacon_interval = cpu_to_le16(wl->beacon_int); 818 cmd->ibss.beacon_interval = cpu_to_le16(wlvif->beacon_int);
789 cmd->ibss.dtim_interval = bss_conf->dtim_period; 819 cmd->ibss.dtim_interval = bss_conf->dtim_period;
790 cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY; 820 cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY;
791 cmd->ibss.ssid_len = wl->ssid_len; 821 cmd->ibss.ssid_len = wlvif->ssid_len;
792 memcpy(cmd->ibss.ssid, wl->ssid, wl->ssid_len); 822 memcpy(cmd->ibss.ssid, wlvif->ssid, wlvif->ssid_len);
793 memcpy(cmd->ibss.bssid, wl->bssid, ETH_ALEN); 823 memcpy(cmd->ibss.bssid, vif->bss_conf.bssid, ETH_ALEN);
794 cmd->sta.local_rates = cpu_to_le32(wl->rate_set); 824 cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set);
795 825
796 if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) { 826 if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) {
797 ret = wl12xx_allocate_link(wl, &wl->sta_hlid); 827 ret = wl12xx_allocate_link(wl, wlvif, &wlvif->sta.hlid);
798 if (ret) 828 if (ret)
799 goto out_free; 829 goto out_free;
800 } 830 }
801 cmd->ibss.hlid = wl->sta_hlid; 831 cmd->ibss.hlid = wlvif->sta.hlid;
802 cmd->ibss.remote_rates = cpu_to_le32(wl->rate_set); 832 cmd->ibss.remote_rates = cpu_to_le32(wlvif->rate_set);
803 833
804 wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d " 834 wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d "
805 "basic_rate_set: 0x%x, remote_rates: 0x%x", 835 "basic_rate_set: 0x%x, remote_rates: 0x%x",
806 wl->role_id, cmd->sta.hlid, cmd->sta.session, 836 wlvif->role_id, cmd->sta.hlid, cmd->sta.session,
807 wl->basic_rate_set, wl->rate_set); 837 wlvif->basic_rate_set, wlvif->rate_set);
808 838
809 wl1271_debug(DEBUG_CMD, "wl->bssid = %pM", wl->bssid); 839 wl1271_debug(DEBUG_CMD, "vif->bss_conf.bssid = %pM",
840 vif->bss_conf.bssid);
810 841
811 ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0); 842 ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
812 if (ret < 0) { 843 if (ret < 0) {
@@ -818,7 +849,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl)
818 849
819err_hlid: 850err_hlid:
820 /* clear links on error. */ 851 /* clear links on error. */
821 wl12xx_free_link(wl, &wl->sta_hlid); 852 wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid);
822 853
823out_free: 854out_free:
824 kfree(cmd); 855 kfree(cmd);
@@ -962,7 +993,8 @@ out:
962 return ret; 993 return ret;
963} 994}
964 995
965int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) 996int wl1271_cmd_ps_mode(struct wl1271 *wl, struct wl12xx_vif *wlvif,
997 u8 ps_mode)
966{ 998{
967 struct wl1271_cmd_ps_params *ps_params = NULL; 999 struct wl1271_cmd_ps_params *ps_params = NULL;
968 int ret = 0; 1000 int ret = 0;
@@ -975,7 +1007,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
975 goto out; 1007 goto out;
976 } 1008 }
977 1009
978 ps_params->role_id = wl->role_id; 1010 ps_params->role_id = wlvif->role_id;
979 ps_params->ps_mode = ps_mode; 1011 ps_params->ps_mode = ps_mode;
980 1012
981 ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, 1013 ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
@@ -1030,7 +1062,7 @@ out:
1030 return ret; 1062 return ret;
1031} 1063}
1032 1064
1033int wl1271_cmd_build_null_data(struct wl1271 *wl) 1065int wl12xx_cmd_build_null_data(struct wl1271 *wl, struct wl12xx_vif *wlvif)
1034{ 1066{
1035 struct sk_buff *skb = NULL; 1067 struct sk_buff *skb = NULL;
1036 int size; 1068 int size;
@@ -1038,11 +1070,12 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl)
1038 int ret = -ENOMEM; 1070 int ret = -ENOMEM;
1039 1071
1040 1072
1041 if (wl->bss_type == BSS_TYPE_IBSS) { 1073 if (wlvif->bss_type == BSS_TYPE_IBSS) {
1042 size = sizeof(struct wl12xx_null_data_template); 1074 size = sizeof(struct wl12xx_null_data_template);
1043 ptr = NULL; 1075 ptr = NULL;
1044 } else { 1076 } else {
1045 skb = ieee80211_nullfunc_get(wl->hw, wl->vif); 1077 skb = ieee80211_nullfunc_get(wl->hw,
1078 wl12xx_wlvif_to_vif(wlvif));
1046 if (!skb) 1079 if (!skb)
1047 goto out; 1080 goto out;
1048 size = skb->len; 1081 size = skb->len;
@@ -1050,7 +1083,7 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl)
1050 } 1083 }
1051 1084
1052 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0, 1085 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0,
1053 wl->basic_rate); 1086 wlvif->basic_rate);
1054 1087
1055out: 1088out:
1056 dev_kfree_skb(skb); 1089 dev_kfree_skb(skb);
@@ -1061,19 +1094,21 @@ out:
1061 1094
1062} 1095}
1063 1096
1064int wl1271_cmd_build_klv_null_data(struct wl1271 *wl) 1097int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl,
1098 struct wl12xx_vif *wlvif)
1065{ 1099{
1100 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
1066 struct sk_buff *skb = NULL; 1101 struct sk_buff *skb = NULL;
1067 int ret = -ENOMEM; 1102 int ret = -ENOMEM;
1068 1103
1069 skb = ieee80211_nullfunc_get(wl->hw, wl->vif); 1104 skb = ieee80211_nullfunc_get(wl->hw, vif);
1070 if (!skb) 1105 if (!skb)
1071 goto out; 1106 goto out;
1072 1107
1073 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, 1108 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV,
1074 skb->data, skb->len, 1109 skb->data, skb->len,
1075 CMD_TEMPL_KLV_IDX_NULL_DATA, 1110 CMD_TEMPL_KLV_IDX_NULL_DATA,
1076 wl->basic_rate); 1111 wlvif->basic_rate);
1077 1112
1078out: 1113out:
1079 dev_kfree_skb(skb); 1114 dev_kfree_skb(skb);
@@ -1084,32 +1119,35 @@ out:
1084 1119
1085} 1120}
1086 1121
1087int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) 1122int wl1271_cmd_build_ps_poll(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1123 u16 aid)
1088{ 1124{
1125 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
1089 struct sk_buff *skb; 1126 struct sk_buff *skb;
1090 int ret = 0; 1127 int ret = 0;
1091 1128
1092 skb = ieee80211_pspoll_get(wl->hw, wl->vif); 1129 skb = ieee80211_pspoll_get(wl->hw, vif);
1093 if (!skb) 1130 if (!skb)
1094 goto out; 1131 goto out;
1095 1132
1096 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data, 1133 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data,
1097 skb->len, 0, wl->basic_rate_set); 1134 skb->len, 0, wlvif->basic_rate_set);
1098 1135
1099out: 1136out:
1100 dev_kfree_skb(skb); 1137 dev_kfree_skb(skb);
1101 return ret; 1138 return ret;
1102} 1139}
1103 1140
1104int wl1271_cmd_build_probe_req(struct wl1271 *wl, 1141int wl1271_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1105 const u8 *ssid, size_t ssid_len, 1142 const u8 *ssid, size_t ssid_len,
1106 const u8 *ie, size_t ie_len, u8 band) 1143 const u8 *ie, size_t ie_len, u8 band)
1107{ 1144{
1145 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
1108 struct sk_buff *skb; 1146 struct sk_buff *skb;
1109 int ret; 1147 int ret;
1110 u32 rate; 1148 u32 rate;
1111 1149
1112 skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, 1150 skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len,
1113 ie, ie_len); 1151 ie, ie_len);
1114 if (!skb) { 1152 if (!skb) {
1115 ret = -ENOMEM; 1153 ret = -ENOMEM;
@@ -1118,7 +1156,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
1118 1156
1119 wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); 1157 wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len);
1120 1158
1121 rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]); 1159 rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[band]);
1122 if (band == IEEE80211_BAND_2GHZ) 1160 if (band == IEEE80211_BAND_2GHZ)
1123 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, 1161 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
1124 skb->data, skb->len, 0, rate); 1162 skb->data, skb->len, 0, rate);
@@ -1132,20 +1170,22 @@ out:
1132} 1170}
1133 1171
1134struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, 1172struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
1173 struct wl12xx_vif *wlvif,
1135 struct sk_buff *skb) 1174 struct sk_buff *skb)
1136{ 1175{
1176 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
1137 int ret; 1177 int ret;
1138 u32 rate; 1178 u32 rate;
1139 1179
1140 if (!skb) 1180 if (!skb)
1141 skb = ieee80211_ap_probereq_get(wl->hw, wl->vif); 1181 skb = ieee80211_ap_probereq_get(wl->hw, vif);
1142 if (!skb) 1182 if (!skb)
1143 goto out; 1183 goto out;
1144 1184
1145 wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len); 1185 wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len);
1146 1186
1147 rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[wl->band]); 1187 rate = wl1271_tx_min_rate_get(wl, wlvif->bitrate_masks[wlvif->band]);
1148 if (wl->band == IEEE80211_BAND_2GHZ) 1188 if (wlvif->band == IEEE80211_BAND_2GHZ)
1149 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, 1189 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
1150 skb->data, skb->len, 0, rate); 1190 skb->data, skb->len, 0, rate);
1151 else 1191 else
@@ -1159,9 +1199,11 @@ out:
1159 return skb; 1199 return skb;
1160} 1200}
1161 1201
1162int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr) 1202int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1203 __be32 ip_addr)
1163{ 1204{
1164 int ret; 1205 int ret;
1206 struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
1165 struct wl12xx_arp_rsp_template tmpl; 1207 struct wl12xx_arp_rsp_template tmpl;
1166 struct ieee80211_hdr_3addr *hdr; 1208 struct ieee80211_hdr_3addr *hdr;
1167 struct arphdr *arp_hdr; 1209 struct arphdr *arp_hdr;
@@ -1173,8 +1215,8 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr)
1173 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | 1215 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
1174 IEEE80211_STYPE_DATA | 1216 IEEE80211_STYPE_DATA |
1175 IEEE80211_FCTL_TODS); 1217 IEEE80211_FCTL_TODS);
1176 memcpy(hdr->addr1, wl->vif->bss_conf.bssid, ETH_ALEN); 1218 memcpy(hdr->addr1, vif->bss_conf.bssid, ETH_ALEN);
1177 memcpy(hdr->addr2, wl->vif->addr, ETH_ALEN); 1219 memcpy(hdr->addr2, vif->addr, ETH_ALEN);
1178 memset(hdr->addr3, 0xff, ETH_ALEN); 1220 memset(hdr->addr3, 0xff, ETH_ALEN);
1179 1221
1180 /* llc layer */ 1222 /* llc layer */
@@ -1190,25 +1232,26 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr)
1190 arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY); 1232 arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY);
1191 1233
1192 /* arp payload */ 1234 /* arp payload */
1193 memcpy(tmpl.sender_hw, wl->vif->addr, ETH_ALEN); 1235 memcpy(tmpl.sender_hw, vif->addr, ETH_ALEN);
1194 tmpl.sender_ip = ip_addr; 1236 tmpl.sender_ip = ip_addr;
1195 1237
1196 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, 1238 ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP,
1197 &tmpl, sizeof(tmpl), 0, 1239 &tmpl, sizeof(tmpl), 0,
1198 wl->basic_rate); 1240 wlvif->basic_rate);
1199 1241
1200 return ret; 1242 return ret;
1201} 1243}
1202 1244
1203int wl1271_build_qos_null_data(struct wl1271 *wl) 1245int wl1271_build_qos_null_data(struct wl1271 *wl, struct ieee80211_vif *vif)
1204{ 1246{
1247 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
1205 struct ieee80211_qos_hdr template; 1248 struct ieee80211_qos_hdr template;
1206 1249
1207 memset(&template, 0, sizeof(template)); 1250 memset(&template, 0, sizeof(template));
1208 1251
1209 memcpy(template.addr1, wl->bssid, ETH_ALEN); 1252 memcpy(template.addr1, vif->bss_conf.bssid, ETH_ALEN);
1210 memcpy(template.addr2, wl->mac_addr, ETH_ALEN); 1253 memcpy(template.addr2, vif->addr, ETH_ALEN);
1211 memcpy(template.addr3, wl->bssid, ETH_ALEN); 1254 memcpy(template.addr3, vif->bss_conf.bssid, ETH_ALEN);
1212 1255
1213 template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | 1256 template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
1214 IEEE80211_STYPE_QOS_NULLFUNC | 1257 IEEE80211_STYPE_QOS_NULLFUNC |
@@ -1219,7 +1262,7 @@ int wl1271_build_qos_null_data(struct wl1271 *wl)
1219 1262
1220 return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template, 1263 return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template,
1221 sizeof(template), 0, 1264 sizeof(template), 0,
1222 wl->basic_rate); 1265 wlvif->basic_rate);
1223} 1266}
1224 1267
1225int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid) 1268int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid)
@@ -1253,7 +1296,8 @@ out:
1253 return ret; 1296 return ret;
1254} 1297}
1255 1298
1256int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, 1299int wl1271_cmd_set_sta_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1300 u16 action, u8 id, u8 key_type,
1257 u8 key_size, const u8 *key, const u8 *addr, 1301 u8 key_size, const u8 *key, const u8 *addr,
1258 u32 tx_seq_32, u16 tx_seq_16) 1302 u32 tx_seq_32, u16 tx_seq_16)
1259{ 1303{
@@ -1261,7 +1305,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
1261 int ret = 0; 1305 int ret = 0;
1262 1306
1263 /* hlid might have already been deleted */ 1307 /* hlid might have already been deleted */
1264 if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) 1308 if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID)
1265 return 0; 1309 return 0;
1266 1310
1267 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); 1311 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@@ -1270,7 +1314,7 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
1270 goto out; 1314 goto out;
1271 } 1315 }
1272 1316
1273 cmd->hlid = wl->sta_hlid; 1317 cmd->hlid = wlvif->sta.hlid;
1274 1318
1275 if (key_type == KEY_WEP) 1319 if (key_type == KEY_WEP)
1276 cmd->lid_key_type = WEP_DEFAULT_LID_TYPE; 1320 cmd->lid_key_type = WEP_DEFAULT_LID_TYPE;
@@ -1321,9 +1365,10 @@ out:
1321 * TODO: merge with sta/ibss into 1 set_key function. 1365 * TODO: merge with sta/ibss into 1 set_key function.
1322 * note there are slight diffs 1366 * note there are slight diffs
1323 */ 1367 */
1324int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, 1368int wl1271_cmd_set_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1325 u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, 1369 u16 action, u8 id, u8 key_type,
1326 u16 tx_seq_16) 1370 u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
1371 u16 tx_seq_16)
1327{ 1372{
1328 struct wl1271_cmd_set_keys *cmd; 1373 struct wl1271_cmd_set_keys *cmd;
1329 int ret = 0; 1374 int ret = 0;
@@ -1333,7 +1378,7 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
1333 if (!cmd) 1378 if (!cmd)
1334 return -ENOMEM; 1379 return -ENOMEM;
1335 1380
1336 if (hlid == wl->ap_bcast_hlid) { 1381 if (hlid == wlvif->ap.bcast_hlid) {
1337 if (key_type == KEY_WEP) 1382 if (key_type == KEY_WEP)
1338 lid_type = WEP_DEFAULT_LID_TYPE; 1383 lid_type = WEP_DEFAULT_LID_TYPE;
1339 else 1384 else
@@ -1411,7 +1456,8 @@ out:
1411 return ret; 1456 return ret;
1412} 1457}
1413 1458
1414int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) 1459int wl12xx_cmd_add_peer(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1460 struct ieee80211_sta *sta, u8 hlid)
1415{ 1461{
1416 struct wl12xx_cmd_add_peer *cmd; 1462 struct wl12xx_cmd_add_peer *cmd;
1417 int i, ret; 1463 int i, ret;
@@ -1438,13 +1484,13 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
1438 else 1484 else
1439 cmd->psd_type[i] = WL1271_PSD_LEGACY; 1485 cmd->psd_type[i] = WL1271_PSD_LEGACY;
1440 1486
1441 sta_rates = sta->supp_rates[wl->band]; 1487 sta_rates = sta->supp_rates[wlvif->band];
1442 if (sta->ht_cap.ht_supported) 1488 if (sta->ht_cap.ht_supported)
1443 sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET; 1489 sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET;
1444 1490
1445 cmd->supported_rates = 1491 cmd->supported_rates =
1446 cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates, 1492 cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates,
1447 wl->band)); 1493 wlvif->band));
1448 1494
1449 wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x", 1495 wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x",
1450 cmd->supported_rates, sta->uapsd_queues); 1496 cmd->supported_rates, sta->uapsd_queues);
@@ -1584,12 +1630,13 @@ out:
1584 return ret; 1630 return ret;
1585} 1631}
1586 1632
1587static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id) 1633static int wl12xx_cmd_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif,
1634 u8 role_id)
1588{ 1635{
1589 struct wl12xx_cmd_roc *cmd; 1636 struct wl12xx_cmd_roc *cmd;
1590 int ret = 0; 1637 int ret = 0;
1591 1638
1592 wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wl->channel, role_id); 1639 wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wlvif->channel, role_id);
1593 1640
1594 if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID)) 1641 if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID))
1595 return -EINVAL; 1642 return -EINVAL;
@@ -1601,8 +1648,8 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id)
1601 } 1648 }
1602 1649
1603 cmd->role_id = role_id; 1650 cmd->role_id = role_id;
1604 cmd->channel = wl->channel; 1651 cmd->channel = wlvif->channel;
1605 switch (wl->band) { 1652 switch (wlvif->band) {
1606 case IEEE80211_BAND_2GHZ: 1653 case IEEE80211_BAND_2GHZ:
1607 cmd->band = RADIO_BAND_2_4GHZ; 1654 cmd->band = RADIO_BAND_2_4GHZ;
1608 break; 1655 break;
@@ -1610,7 +1657,7 @@ static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id)
1610 cmd->band = RADIO_BAND_5GHZ; 1657 cmd->band = RADIO_BAND_5GHZ;
1611 break; 1658 break;
1612 default: 1659 default:
1613 wl1271_error("roc - unknown band: %d", (int)wl->band); 1660 wl1271_error("roc - unknown band: %d", (int)wlvif->band);
1614 ret = -EINVAL; 1661 ret = -EINVAL;
1615 goto out_free; 1662 goto out_free;
1616 } 1663 }
@@ -1657,14 +1704,14 @@ out:
1657 return ret; 1704 return ret;
1658} 1705}
1659 1706
1660int wl12xx_roc(struct wl1271 *wl, u8 role_id) 1707int wl12xx_roc(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 role_id)
1661{ 1708{
1662 int ret = 0; 1709 int ret = 0;
1663 1710
1664 if (WARN_ON(test_bit(role_id, wl->roc_map))) 1711 if (WARN_ON(test_bit(role_id, wl->roc_map)))
1665 return 0; 1712 return 0;
1666 1713
1667 ret = wl12xx_cmd_roc(wl, role_id); 1714 ret = wl12xx_cmd_roc(wl, wlvif, role_id);
1668 if (ret < 0) 1715 if (ret < 0)
1669 goto out; 1716 goto out;
1670 1717
@@ -1753,3 +1800,50 @@ out_free:
1753out: 1800out:
1754 return ret; 1801 return ret;
1755} 1802}
1803
1804/* start dev role and roc on its channel */
1805int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
1806{
1807 int ret;
1808
1809 if (WARN_ON(!(wlvif->bss_type == BSS_TYPE_STA_BSS ||
1810 wlvif->bss_type == BSS_TYPE_IBSS)))
1811 return -EINVAL;
1812
1813 ret = wl12xx_cmd_role_start_dev(wl, wlvif);
1814 if (ret < 0)
1815 goto out;
1816
1817 ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id);
1818 if (ret < 0)
1819 goto out_stop;
1820
1821 return 0;
1822
1823out_stop:
1824 wl12xx_cmd_role_stop_dev(wl, wlvif);
1825out:
1826 return ret;
1827}
1828
1829/* croc dev hlid, and stop the role */
1830int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
1831{
1832 int ret;
1833
1834 if (WARN_ON(!(wlvif->bss_type == BSS_TYPE_STA_BSS ||
1835 wlvif->bss_type == BSS_TYPE_IBSS)))
1836 return -EINVAL;
1837
1838 if (test_bit(wlvif->dev_role_id, wl->roc_map)) {
1839 ret = wl12xx_croc(wl, wlvif->dev_role_id);
1840 if (ret < 0)
1841 goto out;
1842 }
1843
1844 ret = wl12xx_cmd_role_stop_dev(wl, wlvif);
1845 if (ret < 0)
1846 goto out;
1847out:
1848 return ret;
1849}