diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/cmd.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/cmd.c | 368 |
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 | ||
361 | int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id) | 384 | int 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 | ||
436 | static int wl12xx_allocate_link(struct wl1271 *wl, u8 *hlid) | 460 | int 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 | ||
447 | static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid) | 472 | void 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 | ||
456 | static int wl12xx_get_new_session_id(struct wl1271 *wl) | 482 | static 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 | ||
466 | int wl12xx_cmd_role_start_dev(struct wl1271 *wl) | 493 | static 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 | ||
503 | err_hlid: | 531 | err_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 | ||
509 | out_free: | 535 | out_free: |
510 | kfree(cmd); | 536 | kfree(cmd); |
@@ -513,12 +539,13 @@ out: | |||
513 | return ret; | 539 | return ret; |
514 | } | 540 | } |
515 | 541 | ||
516 | int wl12xx_cmd_role_stop_dev(struct wl1271 *wl) | 542 | static 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 | ||
550 | out_free: | 577 | out_free: |
551 | kfree(cmd); | 578 | kfree(cmd); |
@@ -554,8 +581,9 @@ out: | |||
554 | return ret; | 581 | return ret; |
555 | } | 582 | } |
556 | 583 | ||
557 | int wl12xx_cmd_role_start_sta(struct wl1271 *wl) | 584 | int 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 | ||
604 | err_hlid: | 632 | err_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 | ||
608 | out_free: | 636 | out_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 */ |
616 | int wl12xx_cmd_role_stop_sta(struct wl1271 *wl) | 644 | int 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 | ||
644 | out_free: | 672 | out_free: |
645 | kfree(cmd); | 673 | kfree(cmd); |
@@ -648,16 +676,17 @@ out: | |||
648 | return ret; | 676 | return ret; |
649 | } | 677 | } |
650 | 678 | ||
651 | int wl12xx_cmd_role_start_ap(struct wl1271 *wl) | 679 | int 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 | ||
725 | out_free_bcast: | 754 | out_free_bcast: |
726 | wl12xx_free_link(wl, &wl->ap_bcast_hlid); | 755 | wl12xx_free_link(wl, wlvif, &wlvif->ap.bcast_hlid); |
727 | 756 | ||
728 | out_free_global: | 757 | out_free_global: |
729 | wl12xx_free_link(wl, &wl->ap_global_hlid); | 758 | wl12xx_free_link(wl, wlvif, &wlvif->ap.global_hlid); |
730 | 759 | ||
731 | out_free: | 760 | out_free: |
732 | kfree(cmd); | 761 | kfree(cmd); |
@@ -735,7 +764,7 @@ out: | |||
735 | return ret; | 764 | return ret; |
736 | } | 765 | } |
737 | 766 | ||
738 | int wl12xx_cmd_role_stop_ap(struct wl1271 *wl) | 767 | int 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 | ||
762 | out_free: | 791 | out_free: |
763 | kfree(cmd); | 792 | kfree(cmd); |
@@ -766,10 +795,11 @@ out: | |||
766 | return ret; | 795 | return ret; |
767 | } | 796 | } |
768 | 797 | ||
769 | int wl12xx_cmd_role_start_ibss(struct wl1271 *wl) | 798 | int 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 | ||
819 | err_hlid: | 850 | err_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 | ||
823 | out_free: | 854 | out_free: |
824 | kfree(cmd); | 855 | kfree(cmd); |
@@ -962,7 +993,8 @@ out: | |||
962 | return ret; | 993 | return ret; |
963 | } | 994 | } |
964 | 995 | ||
965 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) | 996 | int 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 | ||
1033 | int wl1271_cmd_build_null_data(struct wl1271 *wl) | 1065 | int 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 | ||
1055 | out: | 1088 | out: |
1056 | dev_kfree_skb(skb); | 1089 | dev_kfree_skb(skb); |
@@ -1061,19 +1094,21 @@ out: | |||
1061 | 1094 | ||
1062 | } | 1095 | } |
1063 | 1096 | ||
1064 | int wl1271_cmd_build_klv_null_data(struct wl1271 *wl) | 1097 | int 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 | ||
1078 | out: | 1113 | out: |
1079 | dev_kfree_skb(skb); | 1114 | dev_kfree_skb(skb); |
@@ -1084,32 +1119,35 @@ out: | |||
1084 | 1119 | ||
1085 | } | 1120 | } |
1086 | 1121 | ||
1087 | int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) | 1122 | int 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 | ||
1099 | out: | 1136 | out: |
1100 | dev_kfree_skb(skb); | 1137 | dev_kfree_skb(skb); |
1101 | return ret; | 1138 | return ret; |
1102 | } | 1139 | } |
1103 | 1140 | ||
1104 | int wl1271_cmd_build_probe_req(struct wl1271 *wl, | 1141 | int 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 | ||
1134 | struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, | 1172 | struct 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 | ||
1162 | int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr) | 1202 | int 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 | ||
1203 | int wl1271_build_qos_null_data(struct wl1271 *wl) | 1245 | int 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 | ||
1225 | int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid) | 1268 | int 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 | ||
1256 | int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | 1299 | int 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 | */ |
1324 | int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | 1368 | int 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 | ||
1414 | int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) | 1459 | int 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 | ||
1587 | static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id) | 1633 | static 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 | ||
1660 | int wl12xx_roc(struct wl1271 *wl, u8 role_id) | 1707 | int 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: | |||
1753 | out: | 1800 | out: |
1754 | return ret; | 1801 | return ret; |
1755 | } | 1802 | } |
1803 | |||
1804 | /* start dev role and roc on its channel */ | ||
1805 | int 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 | |||
1823 | out_stop: | ||
1824 | wl12xx_cmd_role_stop_dev(wl, wlvif); | ||
1825 | out: | ||
1826 | return ret; | ||
1827 | } | ||
1828 | |||
1829 | /* croc dev hlid, and stop the role */ | ||
1830 | int 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; | ||
1847 | out: | ||
1848 | return ret; | ||
1849 | } | ||