diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/main.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/main.c | 1966 |
1 files changed, 1136 insertions, 830 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 884f82b63219..c3058419e227 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -32,8 +32,10 @@ | |||
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <linux/wl12xx.h> | 33 | #include <linux/wl12xx.h> |
34 | #include <linux/sched.h> | 34 | #include <linux/sched.h> |
35 | #include <linux/interrupt.h> | ||
35 | 36 | ||
36 | #include "wl12xx.h" | 37 | #include "wl12xx.h" |
38 | #include "debug.h" | ||
37 | #include "wl12xx_80211.h" | 39 | #include "wl12xx_80211.h" |
38 | #include "reg.h" | 40 | #include "reg.h" |
39 | #include "io.h" | 41 | #include "io.h" |
@@ -377,42 +379,30 @@ static char *fwlog_param; | |||
377 | static bool bug_on_recovery; | 379 | static bool bug_on_recovery; |
378 | 380 | ||
379 | static void __wl1271_op_remove_interface(struct wl1271 *wl, | 381 | static void __wl1271_op_remove_interface(struct wl1271 *wl, |
382 | struct ieee80211_vif *vif, | ||
380 | bool reset_tx_queues); | 383 | bool reset_tx_queues); |
381 | static void wl1271_free_ap_keys(struct wl1271 *wl); | 384 | static void wl1271_op_stop(struct ieee80211_hw *hw); |
382 | 385 | static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif); | |
383 | |||
384 | static void wl1271_device_release(struct device *dev) | ||
385 | { | ||
386 | |||
387 | } | ||
388 | |||
389 | static struct platform_device wl1271_device = { | ||
390 | .name = "wl1271", | ||
391 | .id = -1, | ||
392 | |||
393 | /* device model insists to have a release function */ | ||
394 | .dev = { | ||
395 | .release = wl1271_device_release, | ||
396 | }, | ||
397 | }; | ||
398 | 386 | ||
399 | static DEFINE_MUTEX(wl_list_mutex); | 387 | static DEFINE_MUTEX(wl_list_mutex); |
400 | static LIST_HEAD(wl_list); | 388 | static LIST_HEAD(wl_list); |
401 | 389 | ||
402 | static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate) | 390 | static int wl1271_check_operstate(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
391 | unsigned char operstate) | ||
403 | { | 392 | { |
404 | int ret; | 393 | int ret; |
394 | |||
405 | if (operstate != IF_OPER_UP) | 395 | if (operstate != IF_OPER_UP) |
406 | return 0; | 396 | return 0; |
407 | 397 | ||
408 | if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) | 398 | if (test_and_set_bit(WLVIF_FLAG_STA_STATE_SENT, &wlvif->flags)) |
409 | return 0; | 399 | return 0; |
410 | 400 | ||
411 | ret = wl12xx_cmd_set_peer_state(wl, wl->sta_hlid); | 401 | ret = wl12xx_cmd_set_peer_state(wl, wlvif->sta.hlid); |
412 | if (ret < 0) | 402 | if (ret < 0) |
413 | return ret; | 403 | return ret; |
414 | 404 | ||
415 | wl12xx_croc(wl, wl->role_id); | 405 | wl12xx_croc(wl, wlvif->role_id); |
416 | 406 | ||
417 | wl1271_info("Association completed."); | 407 | wl1271_info("Association completed."); |
418 | return 0; | 408 | return 0; |
@@ -426,6 +416,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, | |||
426 | struct ieee80211_hw *hw; | 416 | struct ieee80211_hw *hw; |
427 | struct wl1271 *wl; | 417 | struct wl1271 *wl; |
428 | struct wl1271 *wl_temp; | 418 | struct wl1271 *wl_temp; |
419 | struct wl12xx_vif *wlvif; | ||
429 | int ret = 0; | 420 | int ret = 0; |
430 | 421 | ||
431 | /* Check that this notification is for us. */ | 422 | /* Check that this notification is for us. */ |
@@ -459,17 +450,18 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what, | |||
459 | if (wl->state == WL1271_STATE_OFF) | 450 | if (wl->state == WL1271_STATE_OFF) |
460 | goto out; | 451 | goto out; |
461 | 452 | ||
462 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 453 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
463 | goto out; | 454 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) |
464 | 455 | continue; | |
465 | ret = wl1271_ps_elp_wakeup(wl); | ||
466 | if (ret < 0) | ||
467 | goto out; | ||
468 | 456 | ||
469 | wl1271_check_operstate(wl, dev->operstate); | 457 | ret = wl1271_ps_elp_wakeup(wl); |
458 | if (ret < 0) | ||
459 | goto out; | ||
470 | 460 | ||
471 | wl1271_ps_elp_sleep(wl); | 461 | wl1271_check_operstate(wl, wlvif, dev->operstate); |
472 | 462 | ||
463 | wl1271_ps_elp_sleep(wl); | ||
464 | } | ||
473 | out: | 465 | out: |
474 | mutex_unlock(&wl->mutex); | 466 | mutex_unlock(&wl->mutex); |
475 | 467 | ||
@@ -498,19 +490,20 @@ static int wl1271_reg_notify(struct wiphy *wiphy, | |||
498 | return 0; | 490 | return 0; |
499 | } | 491 | } |
500 | 492 | ||
501 | static int wl1271_set_rx_streaming(struct wl1271 *wl, bool enable) | 493 | static int wl1271_set_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
494 | bool enable) | ||
502 | { | 495 | { |
503 | int ret = 0; | 496 | int ret = 0; |
504 | 497 | ||
505 | /* we should hold wl->mutex */ | 498 | /* we should hold wl->mutex */ |
506 | ret = wl1271_acx_ps_rx_streaming(wl, enable); | 499 | ret = wl1271_acx_ps_rx_streaming(wl, wlvif, enable); |
507 | if (ret < 0) | 500 | if (ret < 0) |
508 | goto out; | 501 | goto out; |
509 | 502 | ||
510 | if (enable) | 503 | if (enable) |
511 | set_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags); | 504 | set_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags); |
512 | else | 505 | else |
513 | clear_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags); | 506 | clear_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags); |
514 | out: | 507 | out: |
515 | return ret; | 508 | return ret; |
516 | } | 509 | } |
@@ -519,25 +512,25 @@ out: | |||
519 | * this function is being called when the rx_streaming interval | 512 | * this function is being called when the rx_streaming interval |
520 | * has beed changed or rx_streaming should be disabled | 513 | * has beed changed or rx_streaming should be disabled |
521 | */ | 514 | */ |
522 | int wl1271_recalc_rx_streaming(struct wl1271 *wl) | 515 | int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
523 | { | 516 | { |
524 | int ret = 0; | 517 | int ret = 0; |
525 | int period = wl->conf.rx_streaming.interval; | 518 | int period = wl->conf.rx_streaming.interval; |
526 | 519 | ||
527 | /* don't reconfigure if rx_streaming is disabled */ | 520 | /* don't reconfigure if rx_streaming is disabled */ |
528 | if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) | 521 | if (!test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags)) |
529 | goto out; | 522 | goto out; |
530 | 523 | ||
531 | /* reconfigure/disable according to new streaming_period */ | 524 | /* reconfigure/disable according to new streaming_period */ |
532 | if (period && | 525 | if (period && |
533 | test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) && | 526 | test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) && |
534 | (wl->conf.rx_streaming.always || | 527 | (wl->conf.rx_streaming.always || |
535 | test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) | 528 | test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) |
536 | ret = wl1271_set_rx_streaming(wl, true); | 529 | ret = wl1271_set_rx_streaming(wl, wlvif, true); |
537 | else { | 530 | else { |
538 | ret = wl1271_set_rx_streaming(wl, false); | 531 | ret = wl1271_set_rx_streaming(wl, wlvif, false); |
539 | /* don't cancel_work_sync since we might deadlock */ | 532 | /* don't cancel_work_sync since we might deadlock */ |
540 | del_timer_sync(&wl->rx_streaming_timer); | 533 | del_timer_sync(&wlvif->rx_streaming_timer); |
541 | } | 534 | } |
542 | out: | 535 | out: |
543 | return ret; | 536 | return ret; |
@@ -546,13 +539,14 @@ out: | |||
546 | static void wl1271_rx_streaming_enable_work(struct work_struct *work) | 539 | static void wl1271_rx_streaming_enable_work(struct work_struct *work) |
547 | { | 540 | { |
548 | int ret; | 541 | int ret; |
549 | struct wl1271 *wl = | 542 | struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif, |
550 | container_of(work, struct wl1271, rx_streaming_enable_work); | 543 | rx_streaming_enable_work); |
544 | struct wl1271 *wl = wlvif->wl; | ||
551 | 545 | ||
552 | mutex_lock(&wl->mutex); | 546 | mutex_lock(&wl->mutex); |
553 | 547 | ||
554 | if (test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags) || | 548 | if (test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags) || |
555 | !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || | 549 | !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || |
556 | (!wl->conf.rx_streaming.always && | 550 | (!wl->conf.rx_streaming.always && |
557 | !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) | 551 | !test_bit(WL1271_FLAG_SOFT_GEMINI, &wl->flags))) |
558 | goto out; | 552 | goto out; |
@@ -564,12 +558,12 @@ static void wl1271_rx_streaming_enable_work(struct work_struct *work) | |||
564 | if (ret < 0) | 558 | if (ret < 0) |
565 | goto out; | 559 | goto out; |
566 | 560 | ||
567 | ret = wl1271_set_rx_streaming(wl, true); | 561 | ret = wl1271_set_rx_streaming(wl, wlvif, true); |
568 | if (ret < 0) | 562 | if (ret < 0) |
569 | goto out_sleep; | 563 | goto out_sleep; |
570 | 564 | ||
571 | /* stop it after some time of inactivity */ | 565 | /* stop it after some time of inactivity */ |
572 | mod_timer(&wl->rx_streaming_timer, | 566 | mod_timer(&wlvif->rx_streaming_timer, |
573 | jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration)); | 567 | jiffies + msecs_to_jiffies(wl->conf.rx_streaming.duration)); |
574 | 568 | ||
575 | out_sleep: | 569 | out_sleep: |
@@ -581,19 +575,20 @@ out: | |||
581 | static void wl1271_rx_streaming_disable_work(struct work_struct *work) | 575 | static void wl1271_rx_streaming_disable_work(struct work_struct *work) |
582 | { | 576 | { |
583 | int ret; | 577 | int ret; |
584 | struct wl1271 *wl = | 578 | struct wl12xx_vif *wlvif = container_of(work, struct wl12xx_vif, |
585 | container_of(work, struct wl1271, rx_streaming_disable_work); | 579 | rx_streaming_disable_work); |
580 | struct wl1271 *wl = wlvif->wl; | ||
586 | 581 | ||
587 | mutex_lock(&wl->mutex); | 582 | mutex_lock(&wl->mutex); |
588 | 583 | ||
589 | if (!test_bit(WL1271_FLAG_RX_STREAMING_STARTED, &wl->flags)) | 584 | if (!test_bit(WLVIF_FLAG_RX_STREAMING_STARTED, &wlvif->flags)) |
590 | goto out; | 585 | goto out; |
591 | 586 | ||
592 | ret = wl1271_ps_elp_wakeup(wl); | 587 | ret = wl1271_ps_elp_wakeup(wl); |
593 | if (ret < 0) | 588 | if (ret < 0) |
594 | goto out; | 589 | goto out; |
595 | 590 | ||
596 | ret = wl1271_set_rx_streaming(wl, false); | 591 | ret = wl1271_set_rx_streaming(wl, wlvif, false); |
597 | if (ret) | 592 | if (ret) |
598 | goto out_sleep; | 593 | goto out_sleep; |
599 | 594 | ||
@@ -605,8 +600,9 @@ out: | |||
605 | 600 | ||
606 | static void wl1271_rx_streaming_timer(unsigned long data) | 601 | static void wl1271_rx_streaming_timer(unsigned long data) |
607 | { | 602 | { |
608 | struct wl1271 *wl = (struct wl1271 *)data; | 603 | struct wl12xx_vif *wlvif = (struct wl12xx_vif *)data; |
609 | ieee80211_queue_work(wl->hw, &wl->rx_streaming_disable_work); | 604 | struct wl1271 *wl = wlvif->wl; |
605 | ieee80211_queue_work(wl->hw, &wlvif->rx_streaming_disable_work); | ||
610 | } | 606 | } |
611 | 607 | ||
612 | static void wl1271_conf_init(struct wl1271 *wl) | 608 | static void wl1271_conf_init(struct wl1271 *wl) |
@@ -645,9 +641,7 @@ static void wl1271_conf_init(struct wl1271 *wl) | |||
645 | 641 | ||
646 | static int wl1271_plt_init(struct wl1271 *wl) | 642 | static int wl1271_plt_init(struct wl1271 *wl) |
647 | { | 643 | { |
648 | struct conf_tx_ac_category *conf_ac; | 644 | int ret; |
649 | struct conf_tx_tid *conf_tid; | ||
650 | int ret, i; | ||
651 | 645 | ||
652 | if (wl->chip.id == CHIP_ID_1283_PG20) | 646 | if (wl->chip.id == CHIP_ID_1283_PG20) |
653 | ret = wl128x_cmd_general_parms(wl); | 647 | ret = wl128x_cmd_general_parms(wl); |
@@ -676,74 +670,14 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
676 | if (ret < 0) | 670 | if (ret < 0) |
677 | return ret; | 671 | return ret; |
678 | 672 | ||
679 | ret = wl1271_sta_init_templates_config(wl); | ||
680 | if (ret < 0) | ||
681 | return ret; | ||
682 | |||
683 | ret = wl1271_acx_init_mem_config(wl); | 673 | ret = wl1271_acx_init_mem_config(wl); |
684 | if (ret < 0) | 674 | if (ret < 0) |
685 | return ret; | 675 | return ret; |
686 | 676 | ||
687 | /* PHY layer config */ | ||
688 | ret = wl1271_init_phy_config(wl); | ||
689 | if (ret < 0) | ||
690 | goto out_free_memmap; | ||
691 | |||
692 | ret = wl1271_acx_dco_itrim_params(wl); | ||
693 | if (ret < 0) | ||
694 | goto out_free_memmap; | ||
695 | |||
696 | /* Initialize connection monitoring thresholds */ | ||
697 | ret = wl1271_acx_conn_monit_params(wl, false); | ||
698 | if (ret < 0) | ||
699 | goto out_free_memmap; | ||
700 | |||
701 | /* Bluetooth WLAN coexistence */ | ||
702 | ret = wl1271_init_pta(wl); | ||
703 | if (ret < 0) | ||
704 | goto out_free_memmap; | ||
705 | |||
706 | /* FM WLAN coexistence */ | ||
707 | ret = wl1271_acx_fm_coex(wl); | ||
708 | if (ret < 0) | ||
709 | goto out_free_memmap; | ||
710 | |||
711 | /* Energy detection */ | ||
712 | ret = wl1271_init_energy_detection(wl); | ||
713 | if (ret < 0) | ||
714 | goto out_free_memmap; | ||
715 | |||
716 | ret = wl12xx_acx_mem_cfg(wl); | 677 | ret = wl12xx_acx_mem_cfg(wl); |
717 | if (ret < 0) | 678 | if (ret < 0) |
718 | goto out_free_memmap; | 679 | goto out_free_memmap; |
719 | 680 | ||
720 | /* Default fragmentation threshold */ | ||
721 | ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); | ||
722 | if (ret < 0) | ||
723 | goto out_free_memmap; | ||
724 | |||
725 | /* Default TID/AC configuration */ | ||
726 | BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count); | ||
727 | for (i = 0; i < wl->conf.tx.tid_conf_count; i++) { | ||
728 | conf_ac = &wl->conf.tx.ac_conf[i]; | ||
729 | ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min, | ||
730 | conf_ac->cw_max, conf_ac->aifsn, | ||
731 | conf_ac->tx_op_limit); | ||
732 | if (ret < 0) | ||
733 | goto out_free_memmap; | ||
734 | |||
735 | conf_tid = &wl->conf.tx.tid_conf[i]; | ||
736 | ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id, | ||
737 | conf_tid->channel_type, | ||
738 | conf_tid->tsid, | ||
739 | conf_tid->ps_scheme, | ||
740 | conf_tid->ack_policy, | ||
741 | conf_tid->apsd_conf[0], | ||
742 | conf_tid->apsd_conf[1]); | ||
743 | if (ret < 0) | ||
744 | goto out_free_memmap; | ||
745 | } | ||
746 | |||
747 | /* Enable data path */ | 681 | /* Enable data path */ |
748 | ret = wl1271_cmd_data_path(wl, 1); | 682 | ret = wl1271_cmd_data_path(wl, 1); |
749 | if (ret < 0) | 683 | if (ret < 0) |
@@ -768,14 +702,12 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
768 | return ret; | 702 | return ret; |
769 | } | 703 | } |
770 | 704 | ||
771 | static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) | 705 | static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, |
706 | struct wl12xx_vif *wlvif, | ||
707 | u8 hlid, u8 tx_pkts) | ||
772 | { | 708 | { |
773 | bool fw_ps, single_sta; | 709 | bool fw_ps, single_sta; |
774 | 710 | ||
775 | /* only regulate station links */ | ||
776 | if (hlid < WL1271_AP_STA_HLID_START) | ||
777 | return; | ||
778 | |||
779 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 711 | fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
780 | single_sta = (wl->active_sta_count == 1); | 712 | single_sta = (wl->active_sta_count == 1); |
781 | 713 | ||
@@ -784,7 +716,7 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) | |||
784 | * packets in FW or if the STA is awake. | 716 | * packets in FW or if the STA is awake. |
785 | */ | 717 | */ |
786 | if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS) | 718 | if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS) |
787 | wl1271_ps_link_end(wl, hlid); | 719 | wl12xx_ps_link_end(wl, wlvif, hlid); |
788 | 720 | ||
789 | /* | 721 | /* |
790 | * Start high-level PS if the STA is asleep with enough blocks in FW. | 722 | * Start high-level PS if the STA is asleep with enough blocks in FW. |
@@ -792,24 +724,14 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts) | |||
792 | * case FW-memory congestion is not a problem. | 724 | * case FW-memory congestion is not a problem. |
793 | */ | 725 | */ |
794 | else if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) | 726 | else if (!single_sta && fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS) |
795 | wl1271_ps_link_start(wl, hlid, true); | 727 | wl12xx_ps_link_start(wl, wlvif, hlid, true); |
796 | } | ||
797 | |||
798 | bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) | ||
799 | { | ||
800 | int id; | ||
801 | |||
802 | /* global/broadcast "stations" are always active */ | ||
803 | if (hlid < WL1271_AP_STA_HLID_START) | ||
804 | return true; | ||
805 | |||
806 | id = hlid - WL1271_AP_STA_HLID_START; | ||
807 | return test_bit(id, wl->ap_hlid_map); | ||
808 | } | 728 | } |
809 | 729 | ||
810 | static void wl12xx_irq_update_links_status(struct wl1271 *wl, | 730 | static void wl12xx_irq_update_links_status(struct wl1271 *wl, |
731 | struct wl12xx_vif *wlvif, | ||
811 | struct wl12xx_fw_status *status) | 732 | struct wl12xx_fw_status *status) |
812 | { | 733 | { |
734 | struct wl1271_link *lnk; | ||
813 | u32 cur_fw_ps_map; | 735 | u32 cur_fw_ps_map; |
814 | u8 hlid, cnt; | 736 | u8 hlid, cnt; |
815 | 737 | ||
@@ -825,25 +747,22 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, | |||
825 | wl->ap_fw_ps_map = cur_fw_ps_map; | 747 | wl->ap_fw_ps_map = cur_fw_ps_map; |
826 | } | 748 | } |
827 | 749 | ||
828 | for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) { | 750 | for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, WL12XX_MAX_LINKS) { |
829 | if (!wl1271_is_active_sta(wl, hlid)) | 751 | lnk = &wl->links[hlid]; |
830 | continue; | 752 | cnt = status->tx_lnk_free_pkts[hlid] - lnk->prev_freed_pkts; |
831 | |||
832 | cnt = status->tx_lnk_free_pkts[hlid] - | ||
833 | wl->links[hlid].prev_freed_pkts; | ||
834 | 753 | ||
835 | wl->links[hlid].prev_freed_pkts = | 754 | lnk->prev_freed_pkts = status->tx_lnk_free_pkts[hlid]; |
836 | status->tx_lnk_free_pkts[hlid]; | 755 | lnk->allocated_pkts -= cnt; |
837 | wl->links[hlid].allocated_pkts -= cnt; | ||
838 | 756 | ||
839 | wl12xx_irq_ps_regulate_link(wl, hlid, | 757 | wl12xx_irq_ps_regulate_link(wl, wlvif, hlid, |
840 | wl->links[hlid].allocated_pkts); | 758 | lnk->allocated_pkts); |
841 | } | 759 | } |
842 | } | 760 | } |
843 | 761 | ||
844 | static void wl12xx_fw_status(struct wl1271 *wl, | 762 | static void wl12xx_fw_status(struct wl1271 *wl, |
845 | struct wl12xx_fw_status *status) | 763 | struct wl12xx_fw_status *status) |
846 | { | 764 | { |
765 | struct wl12xx_vif *wlvif; | ||
847 | struct timespec ts; | 766 | struct timespec ts; |
848 | u32 old_tx_blk_count = wl->tx_blocks_available; | 767 | u32 old_tx_blk_count = wl->tx_blocks_available; |
849 | int avail, freed_blocks; | 768 | int avail, freed_blocks; |
@@ -898,8 +817,9 @@ static void wl12xx_fw_status(struct wl1271 *wl, | |||
898 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); | 817 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); |
899 | 818 | ||
900 | /* for AP update num of allocated TX blocks per link and ps status */ | 819 | /* for AP update num of allocated TX blocks per link and ps status */ |
901 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 820 | wl12xx_for_each_wlvif_ap(wl, wlvif) { |
902 | wl12xx_irq_update_links_status(wl, status); | 821 | wl12xx_irq_update_links_status(wl, wlvif, status); |
822 | } | ||
903 | 823 | ||
904 | /* update the host-chipset time offset */ | 824 | /* update the host-chipset time offset */ |
905 | getnstimeofday(&ts); | 825 | getnstimeofday(&ts); |
@@ -932,7 +852,7 @@ static void wl1271_netstack_work(struct work_struct *work) | |||
932 | 852 | ||
933 | #define WL1271_IRQ_MAX_LOOPS 256 | 853 | #define WL1271_IRQ_MAX_LOOPS 256 |
934 | 854 | ||
935 | irqreturn_t wl1271_irq(int irq, void *cookie) | 855 | static irqreturn_t wl1271_irq(int irq, void *cookie) |
936 | { | 856 | { |
937 | int ret; | 857 | int ret; |
938 | u32 intr; | 858 | u32 intr; |
@@ -1054,7 +974,6 @@ out: | |||
1054 | 974 | ||
1055 | return IRQ_HANDLED; | 975 | return IRQ_HANDLED; |
1056 | } | 976 | } |
1057 | EXPORT_SYMBOL_GPL(wl1271_irq); | ||
1058 | 977 | ||
1059 | static int wl1271_fetch_firmware(struct wl1271 *wl) | 978 | static int wl1271_fetch_firmware(struct wl1271 *wl) |
1060 | { | 979 | { |
@@ -1069,10 +988,10 @@ static int wl1271_fetch_firmware(struct wl1271 *wl) | |||
1069 | 988 | ||
1070 | wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name); | 989 | wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name); |
1071 | 990 | ||
1072 | ret = request_firmware(&fw, fw_name, wl1271_wl_to_dev(wl)); | 991 | ret = request_firmware(&fw, fw_name, wl->dev); |
1073 | 992 | ||
1074 | if (ret < 0) { | 993 | if (ret < 0) { |
1075 | wl1271_error("could not get firmware: %d", ret); | 994 | wl1271_error("could not get firmware %s: %d", fw_name, ret); |
1076 | return ret; | 995 | return ret; |
1077 | } | 996 | } |
1078 | 997 | ||
@@ -1107,10 +1026,11 @@ static int wl1271_fetch_nvs(struct wl1271 *wl) | |||
1107 | const struct firmware *fw; | 1026 | const struct firmware *fw; |
1108 | int ret; | 1027 | int ret; |
1109 | 1028 | ||
1110 | ret = request_firmware(&fw, WL12XX_NVS_NAME, wl1271_wl_to_dev(wl)); | 1029 | ret = request_firmware(&fw, WL12XX_NVS_NAME, wl->dev); |
1111 | 1030 | ||
1112 | if (ret < 0) { | 1031 | if (ret < 0) { |
1113 | wl1271_error("could not get nvs file: %d", ret); | 1032 | wl1271_error("could not get nvs file %s: %d", WL12XX_NVS_NAME, |
1033 | ret); | ||
1114 | return ret; | 1034 | return ret; |
1115 | } | 1035 | } |
1116 | 1036 | ||
@@ -1217,11 +1137,13 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
1217 | { | 1137 | { |
1218 | struct wl1271 *wl = | 1138 | struct wl1271 *wl = |
1219 | container_of(work, struct wl1271, recovery_work); | 1139 | container_of(work, struct wl1271, recovery_work); |
1140 | struct wl12xx_vif *wlvif; | ||
1141 | struct ieee80211_vif *vif; | ||
1220 | 1142 | ||
1221 | mutex_lock(&wl->mutex); | 1143 | mutex_lock(&wl->mutex); |
1222 | 1144 | ||
1223 | if (wl->state != WL1271_STATE_ON) | 1145 | if (wl->state != WL1271_STATE_ON) |
1224 | goto out; | 1146 | goto out_unlock; |
1225 | 1147 | ||
1226 | /* Avoid a recursive recovery */ | 1148 | /* Avoid a recursive recovery */ |
1227 | set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); | 1149 | set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); |
@@ -1238,9 +1160,12 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
1238 | * in the firmware during recovery. This doens't hurt if the network is | 1160 | * in the firmware during recovery. This doens't hurt if the network is |
1239 | * not encrypted. | 1161 | * not encrypted. |
1240 | */ | 1162 | */ |
1241 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || | 1163 | wl12xx_for_each_wlvif(wl, wlvif) { |
1242 | test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) | 1164 | if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) || |
1243 | wl->tx_security_seq += WL1271_TX_SQN_POST_RECOVERY_PADDING; | 1165 | test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) |
1166 | wlvif->tx_security_seq += | ||
1167 | WL1271_TX_SQN_POST_RECOVERY_PADDING; | ||
1168 | } | ||
1244 | 1169 | ||
1245 | /* Prevent spurious TX during FW restart */ | 1170 | /* Prevent spurious TX during FW restart */ |
1246 | ieee80211_stop_queues(wl->hw); | 1171 | ieee80211_stop_queues(wl->hw); |
@@ -1251,7 +1176,14 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
1251 | } | 1176 | } |
1252 | 1177 | ||
1253 | /* reboot the chipset */ | 1178 | /* reboot the chipset */ |
1254 | __wl1271_op_remove_interface(wl, false); | 1179 | while (!list_empty(&wl->wlvif_list)) { |
1180 | wlvif = list_first_entry(&wl->wlvif_list, | ||
1181 | struct wl12xx_vif, list); | ||
1182 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
1183 | __wl1271_op_remove_interface(wl, vif, false); | ||
1184 | } | ||
1185 | mutex_unlock(&wl->mutex); | ||
1186 | wl1271_op_stop(wl->hw); | ||
1255 | 1187 | ||
1256 | clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); | 1188 | clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); |
1257 | 1189 | ||
@@ -1262,8 +1194,8 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
1262 | * to restart the HW. | 1194 | * to restart the HW. |
1263 | */ | 1195 | */ |
1264 | ieee80211_wake_queues(wl->hw); | 1196 | ieee80211_wake_queues(wl->hw); |
1265 | 1197 | return; | |
1266 | out: | 1198 | out_unlock: |
1267 | mutex_unlock(&wl->mutex); | 1199 | mutex_unlock(&wl->mutex); |
1268 | } | 1200 | } |
1269 | 1201 | ||
@@ -1318,7 +1250,16 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
1318 | /* 0. read chip id from CHIP_ID */ | 1250 | /* 0. read chip id from CHIP_ID */ |
1319 | wl->chip.id = wl1271_read32(wl, CHIP_ID_B); | 1251 | wl->chip.id = wl1271_read32(wl, CHIP_ID_B); |
1320 | 1252 | ||
1321 | /* 1. check if chip id is valid */ | 1253 | /* |
1254 | * For wl127x based devices we could use the default block | ||
1255 | * size (512 bytes), but due to a bug in the sdio driver, we | ||
1256 | * need to set it explicitly after the chip is powered on. To | ||
1257 | * simplify the code and since the performance impact is | ||
1258 | * negligible, we use the same block size for all different | ||
1259 | * chip types. | ||
1260 | */ | ||
1261 | if (!wl1271_set_block_size(wl)) | ||
1262 | wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT; | ||
1322 | 1263 | ||
1323 | switch (wl->chip.id) { | 1264 | switch (wl->chip.id) { |
1324 | case CHIP_ID_1271_PG10: | 1265 | case CHIP_ID_1271_PG10: |
@@ -1328,7 +1269,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
1328 | ret = wl1271_setup(wl); | 1269 | ret = wl1271_setup(wl); |
1329 | if (ret < 0) | 1270 | if (ret < 0) |
1330 | goto out; | 1271 | goto out; |
1272 | wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT; | ||
1331 | break; | 1273 | break; |
1274 | |||
1332 | case CHIP_ID_1271_PG20: | 1275 | case CHIP_ID_1271_PG20: |
1333 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | 1276 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", |
1334 | wl->chip.id); | 1277 | wl->chip.id); |
@@ -1336,7 +1279,9 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
1336 | ret = wl1271_setup(wl); | 1279 | ret = wl1271_setup(wl); |
1337 | if (ret < 0) | 1280 | if (ret < 0) |
1338 | goto out; | 1281 | goto out; |
1282 | wl->quirks |= WL12XX_QUIRK_NO_BLOCKSIZE_ALIGNMENT; | ||
1339 | break; | 1283 | break; |
1284 | |||
1340 | case CHIP_ID_1283_PG20: | 1285 | case CHIP_ID_1283_PG20: |
1341 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)", | 1286 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1283 PG20)", |
1342 | wl->chip.id); | 1287 | wl->chip.id); |
@@ -1344,9 +1289,6 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
1344 | ret = wl1271_setup(wl); | 1289 | ret = wl1271_setup(wl); |
1345 | if (ret < 0) | 1290 | if (ret < 0) |
1346 | goto out; | 1291 | goto out; |
1347 | |||
1348 | if (wl1271_set_block_size(wl)) | ||
1349 | wl->quirks |= WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT; | ||
1350 | break; | 1292 | break; |
1351 | case CHIP_ID_1283_PG10: | 1293 | case CHIP_ID_1283_PG10: |
1352 | default: | 1294 | default: |
@@ -1389,8 +1331,6 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
1389 | goto out; | 1331 | goto out; |
1390 | } | 1332 | } |
1391 | 1333 | ||
1392 | wl->bss_type = BSS_TYPE_STA_BSS; | ||
1393 | |||
1394 | while (retries) { | 1334 | while (retries) { |
1395 | retries--; | 1335 | retries--; |
1396 | ret = wl1271_chip_wakeup(wl); | 1336 | ret = wl1271_chip_wakeup(wl); |
@@ -1482,33 +1422,34 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
1482 | static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 1422 | static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
1483 | { | 1423 | { |
1484 | struct wl1271 *wl = hw->priv; | 1424 | struct wl1271 *wl = hw->priv; |
1425 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
1426 | struct ieee80211_vif *vif = info->control.vif; | ||
1427 | struct wl12xx_vif *wlvif = NULL; | ||
1485 | unsigned long flags; | 1428 | unsigned long flags; |
1486 | int q, mapping; | 1429 | int q, mapping; |
1487 | u8 hlid = 0; | 1430 | u8 hlid; |
1431 | |||
1432 | if (vif) | ||
1433 | wlvif = wl12xx_vif_to_data(vif); | ||
1488 | 1434 | ||
1489 | mapping = skb_get_queue_mapping(skb); | 1435 | mapping = skb_get_queue_mapping(skb); |
1490 | q = wl1271_tx_get_queue(mapping); | 1436 | q = wl1271_tx_get_queue(mapping); |
1491 | 1437 | ||
1492 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 1438 | hlid = wl12xx_tx_get_hlid(wl, wlvif, skb); |
1493 | hlid = wl12xx_tx_get_hlid_ap(wl, skb); | ||
1494 | 1439 | ||
1495 | spin_lock_irqsave(&wl->wl_lock, flags); | 1440 | spin_lock_irqsave(&wl->wl_lock, flags); |
1496 | 1441 | ||
1497 | /* queue the packet */ | 1442 | /* queue the packet */ |
1498 | if (wl->bss_type == BSS_TYPE_AP_BSS) { | 1443 | if (hlid == WL12XX_INVALID_LINK_ID || |
1499 | if (!wl1271_is_active_sta(wl, hlid)) { | 1444 | (wlvif && !test_bit(hlid, wlvif->links_map))) { |
1500 | wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", | 1445 | wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", hlid, q); |
1501 | hlid, q); | 1446 | ieee80211_free_txskb(hw, skb); |
1502 | dev_kfree_skb(skb); | 1447 | goto out; |
1503 | goto out; | ||
1504 | } | ||
1505 | |||
1506 | wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q); | ||
1507 | skb_queue_tail(&wl->links[hlid].tx_queue[q], skb); | ||
1508 | } else { | ||
1509 | skb_queue_tail(&wl->tx_queue[q], skb); | ||
1510 | } | 1448 | } |
1511 | 1449 | ||
1450 | wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q); | ||
1451 | skb_queue_tail(&wl->links[hlid].tx_queue[q], skb); | ||
1452 | |||
1512 | wl->tx_queue_count[q]++; | 1453 | wl->tx_queue_count[q]++; |
1513 | 1454 | ||
1514 | /* | 1455 | /* |
@@ -1609,13 +1550,14 @@ static struct notifier_block wl1271_dev_notifier = { | |||
1609 | }; | 1550 | }; |
1610 | 1551 | ||
1611 | #ifdef CONFIG_PM | 1552 | #ifdef CONFIG_PM |
1612 | static int wl1271_configure_suspend_sta(struct wl1271 *wl) | 1553 | static int wl1271_configure_suspend_sta(struct wl1271 *wl, |
1554 | struct wl12xx_vif *wlvif) | ||
1613 | { | 1555 | { |
1614 | int ret = 0; | 1556 | int ret = 0; |
1615 | 1557 | ||
1616 | mutex_lock(&wl->mutex); | 1558 | mutex_lock(&wl->mutex); |
1617 | 1559 | ||
1618 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 1560 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) |
1619 | goto out_unlock; | 1561 | goto out_unlock; |
1620 | 1562 | ||
1621 | ret = wl1271_ps_elp_wakeup(wl); | 1563 | ret = wl1271_ps_elp_wakeup(wl); |
@@ -1623,12 +1565,12 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl) | |||
1623 | goto out_unlock; | 1565 | goto out_unlock; |
1624 | 1566 | ||
1625 | /* enter psm if needed*/ | 1567 | /* enter psm if needed*/ |
1626 | if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 1568 | if (!test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { |
1627 | DECLARE_COMPLETION_ONSTACK(compl); | 1569 | DECLARE_COMPLETION_ONSTACK(compl); |
1628 | 1570 | ||
1629 | wl->ps_compl = &compl; | 1571 | wlvif->ps_compl = &compl; |
1630 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 1572 | ret = wl1271_ps_set_mode(wl, wlvif, STATION_POWER_SAVE_MODE, |
1631 | wl->basic_rate, true); | 1573 | wlvif->basic_rate, true); |
1632 | if (ret < 0) | 1574 | if (ret < 0) |
1633 | goto out_sleep; | 1575 | goto out_sleep; |
1634 | 1576 | ||
@@ -1638,42 +1580,43 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl) | |||
1638 | 1580 | ||
1639 | ret = wait_for_completion_timeout( | 1581 | ret = wait_for_completion_timeout( |
1640 | &compl, msecs_to_jiffies(WL1271_PS_COMPLETE_TIMEOUT)); | 1582 | &compl, msecs_to_jiffies(WL1271_PS_COMPLETE_TIMEOUT)); |
1583 | |||
1584 | mutex_lock(&wl->mutex); | ||
1641 | if (ret <= 0) { | 1585 | if (ret <= 0) { |
1642 | wl1271_warning("couldn't enter ps mode!"); | 1586 | wl1271_warning("couldn't enter ps mode!"); |
1643 | ret = -EBUSY; | 1587 | ret = -EBUSY; |
1644 | goto out; | 1588 | goto out_cleanup; |
1645 | } | 1589 | } |
1646 | 1590 | ||
1647 | /* take mutex again, and wakeup */ | ||
1648 | mutex_lock(&wl->mutex); | ||
1649 | |||
1650 | ret = wl1271_ps_elp_wakeup(wl); | 1591 | ret = wl1271_ps_elp_wakeup(wl); |
1651 | if (ret < 0) | 1592 | if (ret < 0) |
1652 | goto out_unlock; | 1593 | goto out_cleanup; |
1653 | } | 1594 | } |
1654 | out_sleep: | 1595 | out_sleep: |
1655 | wl1271_ps_elp_sleep(wl); | 1596 | wl1271_ps_elp_sleep(wl); |
1597 | out_cleanup: | ||
1598 | wlvif->ps_compl = NULL; | ||
1656 | out_unlock: | 1599 | out_unlock: |
1657 | mutex_unlock(&wl->mutex); | 1600 | mutex_unlock(&wl->mutex); |
1658 | out: | ||
1659 | return ret; | 1601 | return ret; |
1660 | 1602 | ||
1661 | } | 1603 | } |
1662 | 1604 | ||
1663 | static int wl1271_configure_suspend_ap(struct wl1271 *wl) | 1605 | static int wl1271_configure_suspend_ap(struct wl1271 *wl, |
1606 | struct wl12xx_vif *wlvif) | ||
1664 | { | 1607 | { |
1665 | int ret = 0; | 1608 | int ret = 0; |
1666 | 1609 | ||
1667 | mutex_lock(&wl->mutex); | 1610 | mutex_lock(&wl->mutex); |
1668 | 1611 | ||
1669 | if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) | 1612 | if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) |
1670 | goto out_unlock; | 1613 | goto out_unlock; |
1671 | 1614 | ||
1672 | ret = wl1271_ps_elp_wakeup(wl); | 1615 | ret = wl1271_ps_elp_wakeup(wl); |
1673 | if (ret < 0) | 1616 | if (ret < 0) |
1674 | goto out_unlock; | 1617 | goto out_unlock; |
1675 | 1618 | ||
1676 | ret = wl1271_acx_beacon_filter_opt(wl, true); | 1619 | ret = wl1271_acx_beacon_filter_opt(wl, wlvif, true); |
1677 | 1620 | ||
1678 | wl1271_ps_elp_sleep(wl); | 1621 | wl1271_ps_elp_sleep(wl); |
1679 | out_unlock: | 1622 | out_unlock: |
@@ -1682,20 +1625,22 @@ out_unlock: | |||
1682 | 1625 | ||
1683 | } | 1626 | } |
1684 | 1627 | ||
1685 | static int wl1271_configure_suspend(struct wl1271 *wl) | 1628 | static int wl1271_configure_suspend(struct wl1271 *wl, |
1629 | struct wl12xx_vif *wlvif) | ||
1686 | { | 1630 | { |
1687 | if (wl->bss_type == BSS_TYPE_STA_BSS) | 1631 | if (wlvif->bss_type == BSS_TYPE_STA_BSS) |
1688 | return wl1271_configure_suspend_sta(wl); | 1632 | return wl1271_configure_suspend_sta(wl, wlvif); |
1689 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 1633 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) |
1690 | return wl1271_configure_suspend_ap(wl); | 1634 | return wl1271_configure_suspend_ap(wl, wlvif); |
1691 | return 0; | 1635 | return 0; |
1692 | } | 1636 | } |
1693 | 1637 | ||
1694 | static void wl1271_configure_resume(struct wl1271 *wl) | 1638 | static void wl1271_configure_resume(struct wl1271 *wl, |
1639 | struct wl12xx_vif *wlvif) | ||
1695 | { | 1640 | { |
1696 | int ret; | 1641 | int ret; |
1697 | bool is_sta = wl->bss_type == BSS_TYPE_STA_BSS; | 1642 | bool is_sta = wlvif->bss_type == BSS_TYPE_STA_BSS; |
1698 | bool is_ap = wl->bss_type == BSS_TYPE_AP_BSS; | 1643 | bool is_ap = wlvif->bss_type == BSS_TYPE_AP_BSS; |
1699 | 1644 | ||
1700 | if (!is_sta && !is_ap) | 1645 | if (!is_sta && !is_ap) |
1701 | return; | 1646 | return; |
@@ -1707,11 +1652,11 @@ static void wl1271_configure_resume(struct wl1271 *wl) | |||
1707 | 1652 | ||
1708 | if (is_sta) { | 1653 | if (is_sta) { |
1709 | /* exit psm if it wasn't configured */ | 1654 | /* exit psm if it wasn't configured */ |
1710 | if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) | 1655 | if (!test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) |
1711 | wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | 1656 | wl1271_ps_set_mode(wl, wlvif, STATION_ACTIVE_MODE, |
1712 | wl->basic_rate, true); | 1657 | wlvif->basic_rate, true); |
1713 | } else if (is_ap) { | 1658 | } else if (is_ap) { |
1714 | wl1271_acx_beacon_filter_opt(wl, false); | 1659 | wl1271_acx_beacon_filter_opt(wl, wlvif, false); |
1715 | } | 1660 | } |
1716 | 1661 | ||
1717 | wl1271_ps_elp_sleep(wl); | 1662 | wl1271_ps_elp_sleep(wl); |
@@ -1723,16 +1668,19 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
1723 | struct cfg80211_wowlan *wow) | 1668 | struct cfg80211_wowlan *wow) |
1724 | { | 1669 | { |
1725 | struct wl1271 *wl = hw->priv; | 1670 | struct wl1271 *wl = hw->priv; |
1671 | struct wl12xx_vif *wlvif; | ||
1726 | int ret; | 1672 | int ret; |
1727 | 1673 | ||
1728 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); | 1674 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); |
1729 | WARN_ON(!wow || !wow->any); | 1675 | WARN_ON(!wow || !wow->any); |
1730 | 1676 | ||
1731 | wl->wow_enabled = true; | 1677 | wl->wow_enabled = true; |
1732 | ret = wl1271_configure_suspend(wl); | 1678 | wl12xx_for_each_wlvif(wl, wlvif) { |
1733 | if (ret < 0) { | 1679 | ret = wl1271_configure_suspend(wl, wlvif); |
1734 | wl1271_warning("couldn't prepare device to suspend"); | 1680 | if (ret < 0) { |
1735 | return ret; | 1681 | wl1271_warning("couldn't prepare device to suspend"); |
1682 | return ret; | ||
1683 | } | ||
1736 | } | 1684 | } |
1737 | /* flush any remaining work */ | 1685 | /* flush any remaining work */ |
1738 | wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); | 1686 | wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); |
@@ -1751,7 +1699,9 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
1751 | 1699 | ||
1752 | wl1271_enable_interrupts(wl); | 1700 | wl1271_enable_interrupts(wl); |
1753 | flush_work(&wl->tx_work); | 1701 | flush_work(&wl->tx_work); |
1754 | flush_delayed_work(&wl->pspoll_work); | 1702 | wl12xx_for_each_wlvif(wl, wlvif) { |
1703 | flush_delayed_work(&wlvif->pspoll_work); | ||
1704 | } | ||
1755 | flush_delayed_work(&wl->elp_work); | 1705 | flush_delayed_work(&wl->elp_work); |
1756 | 1706 | ||
1757 | return 0; | 1707 | return 0; |
@@ -1760,6 +1710,7 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
1760 | static int wl1271_op_resume(struct ieee80211_hw *hw) | 1710 | static int wl1271_op_resume(struct ieee80211_hw *hw) |
1761 | { | 1711 | { |
1762 | struct wl1271 *wl = hw->priv; | 1712 | struct wl1271 *wl = hw->priv; |
1713 | struct wl12xx_vif *wlvif; | ||
1763 | unsigned long flags; | 1714 | unsigned long flags; |
1764 | bool run_irq_work = false; | 1715 | bool run_irq_work = false; |
1765 | 1716 | ||
@@ -1783,7 +1734,9 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) | |||
1783 | wl1271_irq(0, wl); | 1734 | wl1271_irq(0, wl); |
1784 | wl1271_enable_interrupts(wl); | 1735 | wl1271_enable_interrupts(wl); |
1785 | } | 1736 | } |
1786 | wl1271_configure_resume(wl); | 1737 | wl12xx_for_each_wlvif(wl, wlvif) { |
1738 | wl1271_configure_resume(wl, wlvif); | ||
1739 | } | ||
1787 | wl->wow_enabled = false; | 1740 | wl->wow_enabled = false; |
1788 | 1741 | ||
1789 | return 0; | 1742 | return 0; |
@@ -1810,20 +1763,119 @@ static int wl1271_op_start(struct ieee80211_hw *hw) | |||
1810 | 1763 | ||
1811 | static void wl1271_op_stop(struct ieee80211_hw *hw) | 1764 | static void wl1271_op_stop(struct ieee80211_hw *hw) |
1812 | { | 1765 | { |
1766 | struct wl1271 *wl = hw->priv; | ||
1767 | int i; | ||
1768 | |||
1813 | wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); | 1769 | wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); |
1770 | |||
1771 | mutex_lock(&wl->mutex); | ||
1772 | if (wl->state == WL1271_STATE_OFF) { | ||
1773 | mutex_unlock(&wl->mutex); | ||
1774 | return; | ||
1775 | } | ||
1776 | /* | ||
1777 | * this must be before the cancel_work calls below, so that the work | ||
1778 | * functions don't perform further work. | ||
1779 | */ | ||
1780 | wl->state = WL1271_STATE_OFF; | ||
1781 | mutex_unlock(&wl->mutex); | ||
1782 | |||
1783 | mutex_lock(&wl_list_mutex); | ||
1784 | list_del(&wl->list); | ||
1785 | mutex_unlock(&wl_list_mutex); | ||
1786 | |||
1787 | wl1271_disable_interrupts(wl); | ||
1788 | wl1271_flush_deferred_work(wl); | ||
1789 | cancel_delayed_work_sync(&wl->scan_complete_work); | ||
1790 | cancel_work_sync(&wl->netstack_work); | ||
1791 | cancel_work_sync(&wl->tx_work); | ||
1792 | cancel_delayed_work_sync(&wl->elp_work); | ||
1793 | |||
1794 | /* let's notify MAC80211 about the remaining pending TX frames */ | ||
1795 | wl12xx_tx_reset(wl, true); | ||
1796 | mutex_lock(&wl->mutex); | ||
1797 | |||
1798 | wl1271_power_off(wl); | ||
1799 | |||
1800 | wl->band = IEEE80211_BAND_2GHZ; | ||
1801 | |||
1802 | wl->rx_counter = 0; | ||
1803 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | ||
1804 | wl->tx_blocks_available = 0; | ||
1805 | wl->tx_allocated_blocks = 0; | ||
1806 | wl->tx_results_count = 0; | ||
1807 | wl->tx_packets_count = 0; | ||
1808 | wl->time_offset = 0; | ||
1809 | wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; | ||
1810 | wl->ap_fw_ps_map = 0; | ||
1811 | wl->ap_ps_map = 0; | ||
1812 | wl->sched_scanning = false; | ||
1813 | memset(wl->roles_map, 0, sizeof(wl->roles_map)); | ||
1814 | memset(wl->links_map, 0, sizeof(wl->links_map)); | ||
1815 | memset(wl->roc_map, 0, sizeof(wl->roc_map)); | ||
1816 | wl->active_sta_count = 0; | ||
1817 | |||
1818 | /* The system link is always allocated */ | ||
1819 | __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); | ||
1820 | |||
1821 | /* | ||
1822 | * this is performed after the cancel_work calls and the associated | ||
1823 | * mutex_lock, so that wl1271_op_add_interface does not accidentally | ||
1824 | * get executed before all these vars have been reset. | ||
1825 | */ | ||
1826 | wl->flags = 0; | ||
1827 | |||
1828 | wl->tx_blocks_freed = 0; | ||
1829 | |||
1830 | for (i = 0; i < NUM_TX_QUEUES; i++) { | ||
1831 | wl->tx_pkts_freed[i] = 0; | ||
1832 | wl->tx_allocated_pkts[i] = 0; | ||
1833 | } | ||
1834 | |||
1835 | wl1271_debugfs_reset(wl); | ||
1836 | |||
1837 | kfree(wl->fw_status); | ||
1838 | wl->fw_status = NULL; | ||
1839 | kfree(wl->tx_res_if); | ||
1840 | wl->tx_res_if = NULL; | ||
1841 | kfree(wl->target_mem_map); | ||
1842 | wl->target_mem_map = NULL; | ||
1843 | |||
1844 | mutex_unlock(&wl->mutex); | ||
1845 | } | ||
1846 | |||
1847 | static int wl12xx_allocate_rate_policy(struct wl1271 *wl, u8 *idx) | ||
1848 | { | ||
1849 | u8 policy = find_first_zero_bit(wl->rate_policies_map, | ||
1850 | WL12XX_MAX_RATE_POLICIES); | ||
1851 | if (policy >= WL12XX_MAX_RATE_POLICIES) | ||
1852 | return -EBUSY; | ||
1853 | |||
1854 | __set_bit(policy, wl->rate_policies_map); | ||
1855 | *idx = policy; | ||
1856 | return 0; | ||
1857 | } | ||
1858 | |||
1859 | static void wl12xx_free_rate_policy(struct wl1271 *wl, u8 *idx) | ||
1860 | { | ||
1861 | if (WARN_ON(*idx >= WL12XX_MAX_RATE_POLICIES)) | ||
1862 | return; | ||
1863 | |||
1864 | __clear_bit(*idx, wl->rate_policies_map); | ||
1865 | *idx = WL12XX_MAX_RATE_POLICIES; | ||
1814 | } | 1866 | } |
1815 | 1867 | ||
1816 | static u8 wl12xx_get_role_type(struct wl1271 *wl) | 1868 | static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
1817 | { | 1869 | { |
1818 | switch (wl->bss_type) { | 1870 | switch (wlvif->bss_type) { |
1819 | case BSS_TYPE_AP_BSS: | 1871 | case BSS_TYPE_AP_BSS: |
1820 | if (wl->p2p) | 1872 | if (wlvif->p2p) |
1821 | return WL1271_ROLE_P2P_GO; | 1873 | return WL1271_ROLE_P2P_GO; |
1822 | else | 1874 | else |
1823 | return WL1271_ROLE_AP; | 1875 | return WL1271_ROLE_AP; |
1824 | 1876 | ||
1825 | case BSS_TYPE_STA_BSS: | 1877 | case BSS_TYPE_STA_BSS: |
1826 | if (wl->p2p) | 1878 | if (wlvif->p2p) |
1827 | return WL1271_ROLE_P2P_CL; | 1879 | return WL1271_ROLE_P2P_CL; |
1828 | else | 1880 | else |
1829 | return WL1271_ROLE_STA; | 1881 | return WL1271_ROLE_STA; |
@@ -1832,78 +1884,95 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl) | |||
1832 | return WL1271_ROLE_IBSS; | 1884 | return WL1271_ROLE_IBSS; |
1833 | 1885 | ||
1834 | default: | 1886 | default: |
1835 | wl1271_error("invalid bss_type: %d", wl->bss_type); | 1887 | wl1271_error("invalid bss_type: %d", wlvif->bss_type); |
1836 | } | 1888 | } |
1837 | return WL12XX_INVALID_ROLE_TYPE; | 1889 | return WL12XX_INVALID_ROLE_TYPE; |
1838 | } | 1890 | } |
1839 | 1891 | ||
1840 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | 1892 | static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) |
1841 | struct ieee80211_vif *vif) | ||
1842 | { | 1893 | { |
1843 | struct wl1271 *wl = hw->priv; | 1894 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
1844 | struct wiphy *wiphy = hw->wiphy; | 1895 | int i; |
1845 | int retries = WL1271_BOOT_RETRIES; | ||
1846 | int ret = 0; | ||
1847 | u8 role_type; | ||
1848 | bool booted = false; | ||
1849 | |||
1850 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | ||
1851 | ieee80211_vif_type_p2p(vif), vif->addr); | ||
1852 | |||
1853 | mutex_lock(&wl->mutex); | ||
1854 | if (wl->vif) { | ||
1855 | wl1271_debug(DEBUG_MAC80211, | ||
1856 | "multiple vifs are not supported yet"); | ||
1857 | ret = -EBUSY; | ||
1858 | goto out; | ||
1859 | } | ||
1860 | 1896 | ||
1861 | /* | 1897 | /* clear everything but the persistent data */ |
1862 | * in some very corner case HW recovery scenarios its possible to | 1898 | memset(wlvif, 0, offsetof(struct wl12xx_vif, persistent)); |
1863 | * get here before __wl1271_op_remove_interface is complete, so | ||
1864 | * opt out if that is the case. | ||
1865 | */ | ||
1866 | if (test_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags)) { | ||
1867 | ret = -EBUSY; | ||
1868 | goto out; | ||
1869 | } | ||
1870 | 1899 | ||
1871 | switch (ieee80211_vif_type_p2p(vif)) { | 1900 | switch (ieee80211_vif_type_p2p(vif)) { |
1872 | case NL80211_IFTYPE_P2P_CLIENT: | 1901 | case NL80211_IFTYPE_P2P_CLIENT: |
1873 | wl->p2p = 1; | 1902 | wlvif->p2p = 1; |
1874 | /* fall-through */ | 1903 | /* fall-through */ |
1875 | case NL80211_IFTYPE_STATION: | 1904 | case NL80211_IFTYPE_STATION: |
1876 | wl->bss_type = BSS_TYPE_STA_BSS; | 1905 | wlvif->bss_type = BSS_TYPE_STA_BSS; |
1877 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
1878 | break; | 1906 | break; |
1879 | case NL80211_IFTYPE_ADHOC: | 1907 | case NL80211_IFTYPE_ADHOC: |
1880 | wl->bss_type = BSS_TYPE_IBSS; | 1908 | wlvif->bss_type = BSS_TYPE_IBSS; |
1881 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
1882 | break; | 1909 | break; |
1883 | case NL80211_IFTYPE_P2P_GO: | 1910 | case NL80211_IFTYPE_P2P_GO: |
1884 | wl->p2p = 1; | 1911 | wlvif->p2p = 1; |
1885 | /* fall-through */ | 1912 | /* fall-through */ |
1886 | case NL80211_IFTYPE_AP: | 1913 | case NL80211_IFTYPE_AP: |
1887 | wl->bss_type = BSS_TYPE_AP_BSS; | 1914 | wlvif->bss_type = BSS_TYPE_AP_BSS; |
1888 | break; | 1915 | break; |
1889 | default: | 1916 | default: |
1890 | ret = -EOPNOTSUPP; | 1917 | wlvif->bss_type = MAX_BSS_TYPE; |
1891 | goto out; | 1918 | return -EOPNOTSUPP; |
1892 | } | 1919 | } |
1893 | 1920 | ||
1894 | role_type = wl12xx_get_role_type(wl); | 1921 | wlvif->role_id = WL12XX_INVALID_ROLE_ID; |
1895 | if (role_type == WL12XX_INVALID_ROLE_TYPE) { | 1922 | wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; |
1896 | ret = -EINVAL; | 1923 | wlvif->dev_hlid = WL12XX_INVALID_LINK_ID; |
1897 | goto out; | 1924 | |
1925 | if (wlvif->bss_type == BSS_TYPE_STA_BSS || | ||
1926 | wlvif->bss_type == BSS_TYPE_IBSS) { | ||
1927 | /* init sta/ibss data */ | ||
1928 | wlvif->sta.hlid = WL12XX_INVALID_LINK_ID; | ||
1929 | wl12xx_allocate_rate_policy(wl, &wlvif->sta.basic_rate_idx); | ||
1930 | wl12xx_allocate_rate_policy(wl, &wlvif->sta.ap_rate_idx); | ||
1931 | wl12xx_allocate_rate_policy(wl, &wlvif->sta.p2p_rate_idx); | ||
1932 | } else { | ||
1933 | /* init ap data */ | ||
1934 | wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; | ||
1935 | wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; | ||
1936 | wl12xx_allocate_rate_policy(wl, &wlvif->ap.mgmt_rate_idx); | ||
1937 | wl12xx_allocate_rate_policy(wl, &wlvif->ap.bcast_rate_idx); | ||
1938 | for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++) | ||
1939 | wl12xx_allocate_rate_policy(wl, | ||
1940 | &wlvif->ap.ucast_rate_idx[i]); | ||
1898 | } | 1941 | } |
1899 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); | ||
1900 | 1942 | ||
1901 | if (wl->state != WL1271_STATE_OFF) { | 1943 | wlvif->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; |
1902 | wl1271_error("cannot start because not in off state: %d", | 1944 | wlvif->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; |
1903 | wl->state); | 1945 | wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; |
1904 | ret = -EBUSY; | 1946 | wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; |
1905 | goto out; | 1947 | wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; |
1906 | } | 1948 | wlvif->beacon_int = WL1271_DEFAULT_BEACON_INT; |
1949 | |||
1950 | /* | ||
1951 | * mac80211 configures some values globally, while we treat them | ||
1952 | * per-interface. thus, on init, we have to copy them from wl | ||
1953 | */ | ||
1954 | wlvif->band = wl->band; | ||
1955 | wlvif->channel = wl->channel; | ||
1956 | wlvif->power_level = wl->power_level; | ||
1957 | |||
1958 | INIT_WORK(&wlvif->rx_streaming_enable_work, | ||
1959 | wl1271_rx_streaming_enable_work); | ||
1960 | INIT_WORK(&wlvif->rx_streaming_disable_work, | ||
1961 | wl1271_rx_streaming_disable_work); | ||
1962 | INIT_DELAYED_WORK(&wlvif->pspoll_work, wl1271_pspoll_work); | ||
1963 | INIT_LIST_HEAD(&wlvif->list); | ||
1964 | |||
1965 | setup_timer(&wlvif->rx_streaming_timer, wl1271_rx_streaming_timer, | ||
1966 | (unsigned long) wlvif); | ||
1967 | return 0; | ||
1968 | } | ||
1969 | |||
1970 | static bool wl12xx_init_fw(struct wl1271 *wl) | ||
1971 | { | ||
1972 | int retries = WL1271_BOOT_RETRIES; | ||
1973 | bool booted = false; | ||
1974 | struct wiphy *wiphy = wl->hw->wiphy; | ||
1975 | int ret; | ||
1907 | 1976 | ||
1908 | while (retries) { | 1977 | while (retries) { |
1909 | retries--; | 1978 | retries--; |
@@ -1915,25 +1984,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
1915 | if (ret < 0) | 1984 | if (ret < 0) |
1916 | goto power_off; | 1985 | goto power_off; |
1917 | 1986 | ||
1918 | if (wl->bss_type == BSS_TYPE_STA_BSS || | ||
1919 | wl->bss_type == BSS_TYPE_IBSS) { | ||
1920 | /* | ||
1921 | * The device role is a special role used for | ||
1922 | * rx and tx frames prior to association (as | ||
1923 | * the STA role can get packets only from | ||
1924 | * its associated bssid) | ||
1925 | */ | ||
1926 | ret = wl12xx_cmd_role_enable(wl, | ||
1927 | WL1271_ROLE_DEVICE, | ||
1928 | &wl->dev_role_id); | ||
1929 | if (ret < 0) | ||
1930 | goto irq_disable; | ||
1931 | } | ||
1932 | |||
1933 | ret = wl12xx_cmd_role_enable(wl, role_type, &wl->role_id); | ||
1934 | if (ret < 0) | ||
1935 | goto irq_disable; | ||
1936 | |||
1937 | ret = wl1271_hw_init(wl); | 1987 | ret = wl1271_hw_init(wl); |
1938 | if (ret < 0) | 1988 | if (ret < 0) |
1939 | goto irq_disable; | 1989 | goto irq_disable; |
@@ -1964,9 +2014,6 @@ power_off: | |||
1964 | goto out; | 2014 | goto out; |
1965 | } | 2015 | } |
1966 | 2016 | ||
1967 | wl->vif = vif; | ||
1968 | wl->state = WL1271_STATE_ON; | ||
1969 | set_bit(WL1271_FLAG_IF_INITIALIZED, &wl->flags); | ||
1970 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); | 2017 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str); |
1971 | 2018 | ||
1972 | /* update hw/fw version info in wiphy struct */ | 2019 | /* update hw/fw version info in wiphy struct */ |
@@ -1984,7 +2031,110 @@ power_off: | |||
1984 | wl1271_debug(DEBUG_MAC80211, "11a is %ssupported", | 2031 | wl1271_debug(DEBUG_MAC80211, "11a is %ssupported", |
1985 | wl->enable_11a ? "" : "not "); | 2032 | wl->enable_11a ? "" : "not "); |
1986 | 2033 | ||
2034 | wl->state = WL1271_STATE_ON; | ||
1987 | out: | 2035 | out: |
2036 | return booted; | ||
2037 | } | ||
2038 | |||
2039 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | ||
2040 | struct ieee80211_vif *vif) | ||
2041 | { | ||
2042 | struct wl1271 *wl = hw->priv; | ||
2043 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
2044 | int ret = 0; | ||
2045 | u8 role_type; | ||
2046 | bool booted = false; | ||
2047 | |||
2048 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | ||
2049 | ieee80211_vif_type_p2p(vif), vif->addr); | ||
2050 | |||
2051 | mutex_lock(&wl->mutex); | ||
2052 | ret = wl1271_ps_elp_wakeup(wl); | ||
2053 | if (ret < 0) | ||
2054 | goto out_unlock; | ||
2055 | |||
2056 | if (wl->vif) { | ||
2057 | wl1271_debug(DEBUG_MAC80211, | ||
2058 | "multiple vifs are not supported yet"); | ||
2059 | ret = -EBUSY; | ||
2060 | goto out; | ||
2061 | } | ||
2062 | |||
2063 | /* | ||
2064 | * in some very corner case HW recovery scenarios its possible to | ||
2065 | * get here before __wl1271_op_remove_interface is complete, so | ||
2066 | * opt out if that is the case. | ||
2067 | */ | ||
2068 | if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags) || | ||
2069 | test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) { | ||
2070 | ret = -EBUSY; | ||
2071 | goto out; | ||
2072 | } | ||
2073 | |||
2074 | ret = wl12xx_init_vif_data(wl, vif); | ||
2075 | if (ret < 0) | ||
2076 | goto out; | ||
2077 | |||
2078 | wlvif->wl = wl; | ||
2079 | role_type = wl12xx_get_role_type(wl, wlvif); | ||
2080 | if (role_type == WL12XX_INVALID_ROLE_TYPE) { | ||
2081 | ret = -EINVAL; | ||
2082 | goto out; | ||
2083 | } | ||
2084 | |||
2085 | /* | ||
2086 | * TODO: after the nvs issue will be solved, move this block | ||
2087 | * to start(), and make sure here the driver is ON. | ||
2088 | */ | ||
2089 | if (wl->state == WL1271_STATE_OFF) { | ||
2090 | /* | ||
2091 | * we still need this in order to configure the fw | ||
2092 | * while uploading the nvs | ||
2093 | */ | ||
2094 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); | ||
2095 | |||
2096 | booted = wl12xx_init_fw(wl); | ||
2097 | if (!booted) { | ||
2098 | ret = -EINVAL; | ||
2099 | goto out; | ||
2100 | } | ||
2101 | } | ||
2102 | |||
2103 | if (wlvif->bss_type == BSS_TYPE_STA_BSS || | ||
2104 | wlvif->bss_type == BSS_TYPE_IBSS) { | ||
2105 | /* | ||
2106 | * The device role is a special role used for | ||
2107 | * rx and tx frames prior to association (as | ||
2108 | * the STA role can get packets only from | ||
2109 | * its associated bssid) | ||
2110 | */ | ||
2111 | ret = wl12xx_cmd_role_enable(wl, vif->addr, | ||
2112 | WL1271_ROLE_DEVICE, | ||
2113 | &wlvif->dev_role_id); | ||
2114 | if (ret < 0) | ||
2115 | goto out; | ||
2116 | } | ||
2117 | |||
2118 | ret = wl12xx_cmd_role_enable(wl, vif->addr, | ||
2119 | role_type, &wlvif->role_id); | ||
2120 | if (ret < 0) | ||
2121 | goto out; | ||
2122 | |||
2123 | ret = wl1271_init_vif_specific(wl, vif); | ||
2124 | if (ret < 0) | ||
2125 | goto out; | ||
2126 | |||
2127 | wl->vif = vif; | ||
2128 | list_add(&wlvif->list, &wl->wlvif_list); | ||
2129 | set_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags); | ||
2130 | |||
2131 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) | ||
2132 | wl->ap_count++; | ||
2133 | else | ||
2134 | wl->sta_count++; | ||
2135 | out: | ||
2136 | wl1271_ps_elp_sleep(wl); | ||
2137 | out_unlock: | ||
1988 | mutex_unlock(&wl->mutex); | 2138 | mutex_unlock(&wl->mutex); |
1989 | 2139 | ||
1990 | mutex_lock(&wl_list_mutex); | 2140 | mutex_lock(&wl_list_mutex); |
@@ -1996,29 +2146,34 @@ out: | |||
1996 | } | 2146 | } |
1997 | 2147 | ||
1998 | static void __wl1271_op_remove_interface(struct wl1271 *wl, | 2148 | static void __wl1271_op_remove_interface(struct wl1271 *wl, |
2149 | struct ieee80211_vif *vif, | ||
1999 | bool reset_tx_queues) | 2150 | bool reset_tx_queues) |
2000 | { | 2151 | { |
2001 | int ret, i; | 2152 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
2153 | int i, ret; | ||
2002 | 2154 | ||
2003 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | 2155 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); |
2004 | 2156 | ||
2157 | if (!test_and_clear_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) | ||
2158 | return; | ||
2159 | |||
2160 | wl->vif = NULL; | ||
2161 | |||
2005 | /* because of hardware recovery, we may get here twice */ | 2162 | /* because of hardware recovery, we may get here twice */ |
2006 | if (wl->state != WL1271_STATE_ON) | 2163 | if (wl->state != WL1271_STATE_ON) |
2007 | return; | 2164 | return; |
2008 | 2165 | ||
2009 | wl1271_info("down"); | 2166 | wl1271_info("down"); |
2010 | 2167 | ||
2011 | mutex_lock(&wl_list_mutex); | ||
2012 | list_del(&wl->list); | ||
2013 | mutex_unlock(&wl_list_mutex); | ||
2014 | |||
2015 | /* enable dyn ps just in case (if left on due to fw crash etc) */ | 2168 | /* enable dyn ps just in case (if left on due to fw crash etc) */ |
2016 | if (wl->bss_type == BSS_TYPE_STA_BSS) | 2169 | if (wlvif->bss_type == BSS_TYPE_STA_BSS) |
2017 | ieee80211_enable_dyn_ps(wl->vif); | 2170 | ieee80211_enable_dyn_ps(vif); |
2018 | 2171 | ||
2019 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE) { | 2172 | if (wl->scan.state != WL1271_SCAN_STATE_IDLE && |
2173 | wl->scan_vif == vif) { | ||
2020 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | 2174 | wl->scan.state = WL1271_SCAN_STATE_IDLE; |
2021 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); | 2175 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); |
2176 | wl->scan_vif = NULL; | ||
2022 | wl->scan.req = NULL; | 2177 | wl->scan.req = NULL; |
2023 | ieee80211_scan_completed(wl->hw, true); | 2178 | ieee80211_scan_completed(wl->hw, true); |
2024 | } | 2179 | } |
@@ -2029,13 +2184,13 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, | |||
2029 | if (ret < 0) | 2184 | if (ret < 0) |
2030 | goto deinit; | 2185 | goto deinit; |
2031 | 2186 | ||
2032 | if (wl->bss_type == BSS_TYPE_STA_BSS) { | 2187 | if (wlvif->bss_type == BSS_TYPE_STA_BSS) { |
2033 | ret = wl12xx_cmd_role_disable(wl, &wl->dev_role_id); | 2188 | ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); |
2034 | if (ret < 0) | 2189 | if (ret < 0) |
2035 | goto deinit; | 2190 | goto deinit; |
2036 | } | 2191 | } |
2037 | 2192 | ||
2038 | ret = wl12xx_cmd_role_disable(wl, &wl->role_id); | 2193 | ret = wl12xx_cmd_role_disable(wl, &wlvif->role_id); |
2039 | if (ret < 0) | 2194 | if (ret < 0) |
2040 | goto deinit; | 2195 | goto deinit; |
2041 | 2196 | ||
@@ -2043,120 +2198,82 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, | |||
2043 | } | 2198 | } |
2044 | deinit: | 2199 | deinit: |
2045 | /* clear all hlids (except system_hlid) */ | 2200 | /* clear all hlids (except system_hlid) */ |
2046 | wl->sta_hlid = WL12XX_INVALID_LINK_ID; | 2201 | wlvif->dev_hlid = WL12XX_INVALID_LINK_ID; |
2047 | wl->dev_hlid = WL12XX_INVALID_LINK_ID; | 2202 | |
2048 | wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; | 2203 | if (wlvif->bss_type == BSS_TYPE_STA_BSS || |
2049 | wl->ap_global_hlid = WL12XX_INVALID_LINK_ID; | 2204 | wlvif->bss_type == BSS_TYPE_IBSS) { |
2205 | wlvif->sta.hlid = WL12XX_INVALID_LINK_ID; | ||
2206 | wl12xx_free_rate_policy(wl, &wlvif->sta.basic_rate_idx); | ||
2207 | wl12xx_free_rate_policy(wl, &wlvif->sta.ap_rate_idx); | ||
2208 | wl12xx_free_rate_policy(wl, &wlvif->sta.p2p_rate_idx); | ||
2209 | } else { | ||
2210 | wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; | ||
2211 | wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; | ||
2212 | wl12xx_free_rate_policy(wl, &wlvif->ap.mgmt_rate_idx); | ||
2213 | wl12xx_free_rate_policy(wl, &wlvif->ap.bcast_rate_idx); | ||
2214 | for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++) | ||
2215 | wl12xx_free_rate_policy(wl, | ||
2216 | &wlvif->ap.ucast_rate_idx[i]); | ||
2217 | } | ||
2050 | 2218 | ||
2051 | /* | 2219 | wl12xx_tx_reset_wlvif(wl, wlvif); |
2052 | * this must be before the cancel_work calls below, so that the work | 2220 | wl1271_free_ap_keys(wl, wlvif); |
2053 | * functions don't perform further work. | 2221 | if (wl->last_wlvif == wlvif) |
2054 | */ | 2222 | wl->last_wlvif = NULL; |
2055 | wl->state = WL1271_STATE_OFF; | 2223 | list_del(&wlvif->list); |
2224 | memset(wlvif->ap.sta_hlid_map, 0, sizeof(wlvif->ap.sta_hlid_map)); | ||
2225 | wlvif->role_id = WL12XX_INVALID_ROLE_ID; | ||
2226 | wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; | ||
2227 | |||
2228 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) | ||
2229 | wl->ap_count--; | ||
2230 | else | ||
2231 | wl->sta_count--; | ||
2056 | 2232 | ||
2057 | mutex_unlock(&wl->mutex); | 2233 | mutex_unlock(&wl->mutex); |
2058 | 2234 | del_timer_sync(&wlvif->rx_streaming_timer); | |
2059 | wl1271_disable_interrupts(wl); | 2235 | cancel_work_sync(&wlvif->rx_streaming_enable_work); |
2060 | wl1271_flush_deferred_work(wl); | 2236 | cancel_work_sync(&wlvif->rx_streaming_disable_work); |
2061 | cancel_delayed_work_sync(&wl->scan_complete_work); | 2237 | cancel_delayed_work_sync(&wlvif->pspoll_work); |
2062 | cancel_work_sync(&wl->netstack_work); | ||
2063 | cancel_work_sync(&wl->tx_work); | ||
2064 | del_timer_sync(&wl->rx_streaming_timer); | ||
2065 | cancel_work_sync(&wl->rx_streaming_enable_work); | ||
2066 | cancel_work_sync(&wl->rx_streaming_disable_work); | ||
2067 | cancel_delayed_work_sync(&wl->pspoll_work); | ||
2068 | cancel_delayed_work_sync(&wl->elp_work); | ||
2069 | 2238 | ||
2070 | mutex_lock(&wl->mutex); | 2239 | mutex_lock(&wl->mutex); |
2071 | |||
2072 | /* let's notify MAC80211 about the remaining pending TX frames */ | ||
2073 | wl1271_tx_reset(wl, reset_tx_queues); | ||
2074 | wl1271_power_off(wl); | ||
2075 | |||
2076 | memset(wl->bssid, 0, ETH_ALEN); | ||
2077 | memset(wl->ssid, 0, IEEE80211_MAX_SSID_LEN + 1); | ||
2078 | wl->ssid_len = 0; | ||
2079 | wl->bss_type = MAX_BSS_TYPE; | ||
2080 | wl->set_bss_type = MAX_BSS_TYPE; | ||
2081 | wl->p2p = 0; | ||
2082 | wl->band = IEEE80211_BAND_2GHZ; | ||
2083 | |||
2084 | wl->rx_counter = 0; | ||
2085 | wl->psm_entry_retry = 0; | ||
2086 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | ||
2087 | wl->tx_blocks_available = 0; | ||
2088 | wl->tx_allocated_blocks = 0; | ||
2089 | wl->tx_results_count = 0; | ||
2090 | wl->tx_packets_count = 0; | ||
2091 | wl->time_offset = 0; | ||
2092 | wl->session_counter = 0; | ||
2093 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | ||
2094 | wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; | ||
2095 | wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; | ||
2096 | wl->vif = NULL; | ||
2097 | wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; | ||
2098 | wl1271_free_ap_keys(wl); | ||
2099 | memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); | ||
2100 | wl->ap_fw_ps_map = 0; | ||
2101 | wl->ap_ps_map = 0; | ||
2102 | wl->sched_scanning = false; | ||
2103 | wl->role_id = WL12XX_INVALID_ROLE_ID; | ||
2104 | wl->dev_role_id = WL12XX_INVALID_ROLE_ID; | ||
2105 | memset(wl->roles_map, 0, sizeof(wl->roles_map)); | ||
2106 | memset(wl->links_map, 0, sizeof(wl->links_map)); | ||
2107 | memset(wl->roc_map, 0, sizeof(wl->roc_map)); | ||
2108 | wl->active_sta_count = 0; | ||
2109 | |||
2110 | /* The system link is always allocated */ | ||
2111 | __set_bit(WL12XX_SYSTEM_HLID, wl->links_map); | ||
2112 | |||
2113 | /* | ||
2114 | * this is performed after the cancel_work calls and the associated | ||
2115 | * mutex_lock, so that wl1271_op_add_interface does not accidentally | ||
2116 | * get executed before all these vars have been reset. | ||
2117 | */ | ||
2118 | wl->flags = 0; | ||
2119 | |||
2120 | wl->tx_blocks_freed = 0; | ||
2121 | |||
2122 | for (i = 0; i < NUM_TX_QUEUES; i++) { | ||
2123 | wl->tx_pkts_freed[i] = 0; | ||
2124 | wl->tx_allocated_pkts[i] = 0; | ||
2125 | } | ||
2126 | |||
2127 | wl1271_debugfs_reset(wl); | ||
2128 | |||
2129 | kfree(wl->fw_status); | ||
2130 | wl->fw_status = NULL; | ||
2131 | kfree(wl->tx_res_if); | ||
2132 | wl->tx_res_if = NULL; | ||
2133 | kfree(wl->target_mem_map); | ||
2134 | wl->target_mem_map = NULL; | ||
2135 | } | 2240 | } |
2136 | 2241 | ||
2137 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | 2242 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, |
2138 | struct ieee80211_vif *vif) | 2243 | struct ieee80211_vif *vif) |
2139 | { | 2244 | { |
2140 | struct wl1271 *wl = hw->priv; | 2245 | struct wl1271 *wl = hw->priv; |
2246 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
2247 | struct wl12xx_vif *iter; | ||
2141 | 2248 | ||
2142 | mutex_lock(&wl->mutex); | 2249 | mutex_lock(&wl->mutex); |
2250 | |||
2251 | if (wl->state == WL1271_STATE_OFF || | ||
2252 | !test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) | ||
2253 | goto out; | ||
2254 | |||
2143 | /* | 2255 | /* |
2144 | * wl->vif can be null here if someone shuts down the interface | 2256 | * wl->vif can be null here if someone shuts down the interface |
2145 | * just when hardware recovery has been started. | 2257 | * just when hardware recovery has been started. |
2146 | */ | 2258 | */ |
2147 | if (wl->vif) { | 2259 | wl12xx_for_each_wlvif(wl, iter) { |
2148 | WARN_ON(wl->vif != vif); | 2260 | if (iter != wlvif) |
2149 | __wl1271_op_remove_interface(wl, true); | 2261 | continue; |
2150 | } | ||
2151 | 2262 | ||
2263 | __wl1271_op_remove_interface(wl, vif, true); | ||
2264 | break; | ||
2265 | } | ||
2266 | WARN_ON(iter != wlvif); | ||
2267 | out: | ||
2152 | mutex_unlock(&wl->mutex); | 2268 | mutex_unlock(&wl->mutex); |
2153 | cancel_work_sync(&wl->recovery_work); | 2269 | cancel_work_sync(&wl->recovery_work); |
2154 | } | 2270 | } |
2155 | 2271 | ||
2156 | static int wl1271_join(struct wl1271 *wl, bool set_assoc) | 2272 | static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
2273 | bool set_assoc) | ||
2157 | { | 2274 | { |
2158 | int ret; | 2275 | int ret; |
2159 | bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); | 2276 | bool is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); |
2160 | 2277 | ||
2161 | /* | 2278 | /* |
2162 | * One of the side effects of the JOIN command is that is clears | 2279 | * One of the side effects of the JOIN command is that is clears |
@@ -2167,20 +2284,20 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc) | |||
2167 | * Keep the below message for now, unless it starts bothering | 2284 | * Keep the below message for now, unless it starts bothering |
2168 | * users who really like to roam a lot :) | 2285 | * users who really like to roam a lot :) |
2169 | */ | 2286 | */ |
2170 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 2287 | if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) |
2171 | wl1271_info("JOIN while associated."); | 2288 | wl1271_info("JOIN while associated."); |
2172 | 2289 | ||
2173 | if (set_assoc) | 2290 | if (set_assoc) |
2174 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | 2291 | set_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags); |
2175 | 2292 | ||
2176 | if (is_ibss) | 2293 | if (is_ibss) |
2177 | ret = wl12xx_cmd_role_start_ibss(wl); | 2294 | ret = wl12xx_cmd_role_start_ibss(wl, wlvif); |
2178 | else | 2295 | else |
2179 | ret = wl12xx_cmd_role_start_sta(wl); | 2296 | ret = wl12xx_cmd_role_start_sta(wl, wlvif); |
2180 | if (ret < 0) | 2297 | if (ret < 0) |
2181 | goto out; | 2298 | goto out; |
2182 | 2299 | ||
2183 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 2300 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) |
2184 | goto out; | 2301 | goto out; |
2185 | 2302 | ||
2186 | /* | 2303 | /* |
@@ -2189,19 +2306,20 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc) | |||
2189 | * the join. The acx_aid starts the keep-alive process, and the order | 2306 | * the join. The acx_aid starts the keep-alive process, and the order |
2190 | * of the commands below is relevant. | 2307 | * of the commands below is relevant. |
2191 | */ | 2308 | */ |
2192 | ret = wl1271_acx_keep_alive_mode(wl, true); | 2309 | ret = wl1271_acx_keep_alive_mode(wl, wlvif, true); |
2193 | if (ret < 0) | 2310 | if (ret < 0) |
2194 | goto out; | 2311 | goto out; |
2195 | 2312 | ||
2196 | ret = wl1271_acx_aid(wl, wl->aid); | 2313 | ret = wl1271_acx_aid(wl, wlvif, wlvif->aid); |
2197 | if (ret < 0) | 2314 | if (ret < 0) |
2198 | goto out; | 2315 | goto out; |
2199 | 2316 | ||
2200 | ret = wl1271_cmd_build_klv_null_data(wl); | 2317 | ret = wl12xx_cmd_build_klv_null_data(wl, wlvif); |
2201 | if (ret < 0) | 2318 | if (ret < 0) |
2202 | goto out; | 2319 | goto out; |
2203 | 2320 | ||
2204 | ret = wl1271_acx_keep_alive_config(wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | 2321 | ret = wl1271_acx_keep_alive_config(wl, wlvif, |
2322 | CMD_TEMPL_KLV_IDX_NULL_DATA, | ||
2205 | ACX_KEEP_ALIVE_TPL_VALID); | 2323 | ACX_KEEP_ALIVE_TPL_VALID); |
2206 | if (ret < 0) | 2324 | if (ret < 0) |
2207 | goto out; | 2325 | goto out; |
@@ -2210,34 +2328,34 @@ out: | |||
2210 | return ret; | 2328 | return ret; |
2211 | } | 2329 | } |
2212 | 2330 | ||
2213 | static int wl1271_unjoin(struct wl1271 *wl) | 2331 | static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
2214 | { | 2332 | { |
2215 | int ret; | 2333 | int ret; |
2216 | 2334 | ||
2217 | if (test_and_clear_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags)) { | 2335 | if (test_and_clear_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags)) { |
2336 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | ||
2337 | |||
2218 | wl12xx_cmd_stop_channel_switch(wl); | 2338 | wl12xx_cmd_stop_channel_switch(wl); |
2219 | ieee80211_chswitch_done(wl->vif, false); | 2339 | ieee80211_chswitch_done(vif, false); |
2220 | } | 2340 | } |
2221 | 2341 | ||
2222 | /* to stop listening to a channel, we disconnect */ | 2342 | /* to stop listening to a channel, we disconnect */ |
2223 | ret = wl12xx_cmd_role_stop_sta(wl); | 2343 | ret = wl12xx_cmd_role_stop_sta(wl, wlvif); |
2224 | if (ret < 0) | 2344 | if (ret < 0) |
2225 | goto out; | 2345 | goto out; |
2226 | 2346 | ||
2227 | memset(wl->bssid, 0, ETH_ALEN); | ||
2228 | |||
2229 | /* reset TX security counters on a clean disconnect */ | 2347 | /* reset TX security counters on a clean disconnect */ |
2230 | wl->tx_security_last_seq_lsb = 0; | 2348 | wlvif->tx_security_last_seq_lsb = 0; |
2231 | wl->tx_security_seq = 0; | 2349 | wlvif->tx_security_seq = 0; |
2232 | 2350 | ||
2233 | out: | 2351 | out: |
2234 | return ret; | 2352 | return ret; |
2235 | } | 2353 | } |
2236 | 2354 | ||
2237 | static void wl1271_set_band_rate(struct wl1271 *wl) | 2355 | static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
2238 | { | 2356 | { |
2239 | wl->basic_rate_set = wl->bitrate_masks[wl->band]; | 2357 | wlvif->basic_rate_set = wlvif->bitrate_masks[wlvif->band]; |
2240 | wl->rate_set = wl->basic_rate_set; | 2358 | wlvif->rate_set = wlvif->basic_rate_set; |
2241 | } | 2359 | } |
2242 | 2360 | ||
2243 | static bool wl12xx_is_roc(struct wl1271 *wl) | 2361 | static bool wl12xx_is_roc(struct wl1271 *wl) |
@@ -2251,27 +2369,25 @@ static bool wl12xx_is_roc(struct wl1271 *wl) | |||
2251 | return true; | 2369 | return true; |
2252 | } | 2370 | } |
2253 | 2371 | ||
2254 | static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) | 2372 | static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
2373 | bool idle) | ||
2255 | { | 2374 | { |
2256 | int ret; | 2375 | int ret; |
2257 | 2376 | ||
2258 | if (idle) { | 2377 | if (idle) { |
2259 | /* no need to croc if we weren't busy (e.g. during boot) */ | 2378 | /* no need to croc if we weren't busy (e.g. during boot) */ |
2260 | if (wl12xx_is_roc(wl)) { | 2379 | if (wl12xx_is_roc(wl)) { |
2261 | ret = wl12xx_croc(wl, wl->dev_role_id); | 2380 | ret = wl12xx_stop_dev(wl, wlvif); |
2262 | if (ret < 0) | ||
2263 | goto out; | ||
2264 | |||
2265 | ret = wl12xx_cmd_role_stop_dev(wl); | ||
2266 | if (ret < 0) | 2381 | if (ret < 0) |
2267 | goto out; | 2382 | goto out; |
2268 | } | 2383 | } |
2269 | wl->rate_set = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); | 2384 | wlvif->rate_set = |
2270 | ret = wl1271_acx_sta_rate_policies(wl); | 2385 | wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); |
2386 | ret = wl1271_acx_sta_rate_policies(wl, wlvif); | ||
2271 | if (ret < 0) | 2387 | if (ret < 0) |
2272 | goto out; | 2388 | goto out; |
2273 | ret = wl1271_acx_keep_alive_config( | 2389 | ret = wl1271_acx_keep_alive_config( |
2274 | wl, CMD_TEMPL_KLV_IDX_NULL_DATA, | 2390 | wl, wlvif, CMD_TEMPL_KLV_IDX_NULL_DATA, |
2275 | ACX_KEEP_ALIVE_TPL_INVALID); | 2391 | ACX_KEEP_ALIVE_TPL_INVALID); |
2276 | if (ret < 0) | 2392 | if (ret < 0) |
2277 | goto out; | 2393 | goto out; |
@@ -2283,11 +2399,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) | |||
2283 | ieee80211_sched_scan_stopped(wl->hw); | 2399 | ieee80211_sched_scan_stopped(wl->hw); |
2284 | } | 2400 | } |
2285 | 2401 | ||
2286 | ret = wl12xx_cmd_role_start_dev(wl); | 2402 | ret = wl12xx_start_dev(wl, wlvif); |
2287 | if (ret < 0) | ||
2288 | goto out; | ||
2289 | |||
2290 | ret = wl12xx_roc(wl, wl->dev_role_id); | ||
2291 | if (ret < 0) | 2403 | if (ret < 0) |
2292 | goto out; | 2404 | goto out; |
2293 | clear_bit(WL1271_FLAG_IDLE, &wl->flags); | 2405 | clear_bit(WL1271_FLAG_IDLE, &wl->flags); |
@@ -2297,61 +2409,22 @@ out: | |||
2297 | return ret; | 2409 | return ret; |
2298 | } | 2410 | } |
2299 | 2411 | ||
2300 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | 2412 | static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
2413 | struct ieee80211_conf *conf, u32 changed) | ||
2301 | { | 2414 | { |
2302 | struct wl1271 *wl = hw->priv; | 2415 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); |
2303 | struct ieee80211_conf *conf = &hw->conf; | 2416 | int channel, ret; |
2304 | int channel, ret = 0; | ||
2305 | bool is_ap; | ||
2306 | 2417 | ||
2307 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); | 2418 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); |
2308 | 2419 | ||
2309 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s" | ||
2310 | " changed 0x%x", | ||
2311 | channel, | ||
2312 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", | ||
2313 | conf->power_level, | ||
2314 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use", | ||
2315 | changed); | ||
2316 | |||
2317 | /* | ||
2318 | * mac80211 will go to idle nearly immediately after transmitting some | ||
2319 | * frames, such as the deauth. To make sure those frames reach the air, | ||
2320 | * wait here until the TX queue is fully flushed. | ||
2321 | */ | ||
2322 | if ((changed & IEEE80211_CONF_CHANGE_IDLE) && | ||
2323 | (conf->flags & IEEE80211_CONF_IDLE)) | ||
2324 | wl1271_tx_flush(wl); | ||
2325 | |||
2326 | mutex_lock(&wl->mutex); | ||
2327 | |||
2328 | if (unlikely(wl->state == WL1271_STATE_OFF)) { | ||
2329 | /* we support configuring the channel and band while off */ | ||
2330 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL)) { | ||
2331 | wl->band = conf->channel->band; | ||
2332 | wl->channel = channel; | ||
2333 | } | ||
2334 | |||
2335 | if ((changed & IEEE80211_CONF_CHANGE_POWER)) | ||
2336 | wl->power_level = conf->power_level; | ||
2337 | |||
2338 | goto out; | ||
2339 | } | ||
2340 | |||
2341 | is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | ||
2342 | |||
2343 | ret = wl1271_ps_elp_wakeup(wl); | ||
2344 | if (ret < 0) | ||
2345 | goto out; | ||
2346 | |||
2347 | /* if the channel changes while joined, join again */ | 2420 | /* if the channel changes while joined, join again */ |
2348 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL && | 2421 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL && |
2349 | ((wl->band != conf->channel->band) || | 2422 | ((wlvif->band != conf->channel->band) || |
2350 | (wl->channel != channel))) { | 2423 | (wlvif->channel != channel))) { |
2351 | /* send all pending packets */ | 2424 | /* send all pending packets */ |
2352 | wl1271_tx_work_locked(wl); | 2425 | wl1271_tx_work_locked(wl); |
2353 | wl->band = conf->channel->band; | 2426 | wlvif->band = conf->channel->band; |
2354 | wl->channel = channel; | 2427 | wlvif->channel = channel; |
2355 | 2428 | ||
2356 | if (!is_ap) { | 2429 | if (!is_ap) { |
2357 | /* | 2430 | /* |
@@ -2360,24 +2433,27 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
2360 | * possible rate for the band as a fixed rate for | 2433 | * possible rate for the band as a fixed rate for |
2361 | * association frames and other control messages. | 2434 | * association frames and other control messages. |
2362 | */ | 2435 | */ |
2363 | if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 2436 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) |
2364 | wl1271_set_band_rate(wl); | 2437 | wl1271_set_band_rate(wl, wlvif); |
2365 | 2438 | ||
2366 | wl->basic_rate = | 2439 | wlvif->basic_rate = |
2367 | wl1271_tx_min_rate_get(wl, wl->basic_rate_set); | 2440 | wl1271_tx_min_rate_get(wl, |
2368 | ret = wl1271_acx_sta_rate_policies(wl); | 2441 | wlvif->basic_rate_set); |
2442 | ret = wl1271_acx_sta_rate_policies(wl, wlvif); | ||
2369 | if (ret < 0) | 2443 | if (ret < 0) |
2370 | wl1271_warning("rate policy for channel " | 2444 | wl1271_warning("rate policy for channel " |
2371 | "failed %d", ret); | 2445 | "failed %d", ret); |
2372 | 2446 | ||
2373 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | 2447 | if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, |
2448 | &wlvif->flags)) { | ||
2374 | if (wl12xx_is_roc(wl)) { | 2449 | if (wl12xx_is_roc(wl)) { |
2375 | /* roaming */ | 2450 | /* roaming */ |
2376 | ret = wl12xx_croc(wl, wl->dev_role_id); | 2451 | ret = wl12xx_croc(wl, |
2452 | wlvif->dev_role_id); | ||
2377 | if (ret < 0) | 2453 | if (ret < 0) |
2378 | goto out_sleep; | 2454 | return ret; |
2379 | } | 2455 | } |
2380 | ret = wl1271_join(wl, false); | 2456 | ret = wl1271_join(wl, wlvif, false); |
2381 | if (ret < 0) | 2457 | if (ret < 0) |
2382 | wl1271_warning("cmd join on channel " | 2458 | wl1271_warning("cmd join on channel " |
2383 | "failed %d", ret); | 2459 | "failed %d", ret); |
@@ -2389,64 +2465,112 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
2389 | */ | 2465 | */ |
2390 | if (wl12xx_is_roc(wl) && | 2466 | if (wl12xx_is_roc(wl) && |
2391 | !(conf->flags & IEEE80211_CONF_IDLE)) { | 2467 | !(conf->flags & IEEE80211_CONF_IDLE)) { |
2392 | ret = wl12xx_croc(wl, wl->dev_role_id); | 2468 | ret = wl12xx_stop_dev(wl, wlvif); |
2393 | if (ret < 0) | 2469 | if (ret < 0) |
2394 | goto out_sleep; | 2470 | return ret; |
2395 | 2471 | ||
2396 | ret = wl12xx_roc(wl, wl->dev_role_id); | 2472 | ret = wl12xx_start_dev(wl, wlvif); |
2397 | if (ret < 0) | 2473 | if (ret < 0) |
2398 | wl1271_warning("roc failed %d", | 2474 | return ret; |
2399 | ret); | ||
2400 | } | 2475 | } |
2401 | } | 2476 | } |
2402 | } | 2477 | } |
2403 | } | 2478 | } |
2404 | 2479 | ||
2405 | if (changed & IEEE80211_CONF_CHANGE_IDLE && !is_ap) { | ||
2406 | ret = wl1271_sta_handle_idle(wl, | ||
2407 | conf->flags & IEEE80211_CONF_IDLE); | ||
2408 | if (ret < 0) | ||
2409 | wl1271_warning("idle mode change failed %d", ret); | ||
2410 | } | ||
2411 | |||
2412 | /* | 2480 | /* |
2413 | * if mac80211 changes the PSM mode, make sure the mode is not | 2481 | * if mac80211 changes the PSM mode, make sure the mode is not |
2414 | * incorrectly changed after the pspoll failure active window. | 2482 | * incorrectly changed after the pspoll failure active window. |
2415 | */ | 2483 | */ |
2416 | if (changed & IEEE80211_CONF_CHANGE_PS) | 2484 | if (changed & IEEE80211_CONF_CHANGE_PS) |
2417 | clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags); | 2485 | clear_bit(WLVIF_FLAG_PSPOLL_FAILURE, &wlvif->flags); |
2418 | 2486 | ||
2419 | if (conf->flags & IEEE80211_CONF_PS && | 2487 | if (conf->flags & IEEE80211_CONF_PS && |
2420 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 2488 | !test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) { |
2421 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 2489 | set_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags); |
2422 | 2490 | ||
2423 | /* | 2491 | /* |
2424 | * We enter PSM only if we're already associated. | 2492 | * We enter PSM only if we're already associated. |
2425 | * If we're not, we'll enter it when joining an SSID, | 2493 | * If we're not, we'll enter it when joining an SSID, |
2426 | * through the bss_info_changed() hook. | 2494 | * through the bss_info_changed() hook. |
2427 | */ | 2495 | */ |
2428 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | 2496 | if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { |
2429 | wl1271_debug(DEBUG_PSM, "psm enabled"); | 2497 | wl1271_debug(DEBUG_PSM, "psm enabled"); |
2430 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | 2498 | ret = wl1271_ps_set_mode(wl, wlvif, |
2431 | wl->basic_rate, true); | 2499 | STATION_POWER_SAVE_MODE, |
2500 | wlvif->basic_rate, true); | ||
2432 | } | 2501 | } |
2433 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 2502 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
2434 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | 2503 | test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags)) { |
2435 | wl1271_debug(DEBUG_PSM, "psm disabled"); | 2504 | wl1271_debug(DEBUG_PSM, "psm disabled"); |
2436 | 2505 | ||
2437 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | 2506 | clear_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags); |
2438 | 2507 | ||
2439 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) | 2508 | if (test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) |
2440 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | 2509 | ret = wl1271_ps_set_mode(wl, wlvif, |
2441 | wl->basic_rate, true); | 2510 | STATION_ACTIVE_MODE, |
2511 | wlvif->basic_rate, true); | ||
2442 | } | 2512 | } |
2443 | 2513 | ||
2444 | if (conf->power_level != wl->power_level) { | 2514 | if (conf->power_level != wlvif->power_level) { |
2445 | ret = wl1271_acx_tx_power(wl, conf->power_level); | 2515 | ret = wl1271_acx_tx_power(wl, wlvif, conf->power_level); |
2446 | if (ret < 0) | 2516 | if (ret < 0) |
2447 | goto out_sleep; | 2517 | return ret; |
2518 | |||
2519 | wlvif->power_level = conf->power_level; | ||
2520 | } | ||
2521 | |||
2522 | return 0; | ||
2523 | } | ||
2524 | |||
2525 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | ||
2526 | { | ||
2527 | struct wl1271 *wl = hw->priv; | ||
2528 | struct wl12xx_vif *wlvif; | ||
2529 | struct ieee80211_conf *conf = &hw->conf; | ||
2530 | int channel, ret = 0; | ||
2531 | |||
2532 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); | ||
2533 | |||
2534 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s" | ||
2535 | " changed 0x%x", | ||
2536 | channel, | ||
2537 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", | ||
2538 | conf->power_level, | ||
2539 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use", | ||
2540 | changed); | ||
2541 | |||
2542 | /* | ||
2543 | * mac80211 will go to idle nearly immediately after transmitting some | ||
2544 | * frames, such as the deauth. To make sure those frames reach the air, | ||
2545 | * wait here until the TX queue is fully flushed. | ||
2546 | */ | ||
2547 | if ((changed & IEEE80211_CONF_CHANGE_IDLE) && | ||
2548 | (conf->flags & IEEE80211_CONF_IDLE)) | ||
2549 | wl1271_tx_flush(wl); | ||
2550 | |||
2551 | mutex_lock(&wl->mutex); | ||
2552 | |||
2553 | /* we support configuring the channel and band even while off */ | ||
2554 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
2555 | wl->band = conf->channel->band; | ||
2556 | wl->channel = channel; | ||
2557 | } | ||
2448 | 2558 | ||
2559 | if (changed & IEEE80211_CONF_CHANGE_POWER) | ||
2449 | wl->power_level = conf->power_level; | 2560 | wl->power_level = conf->power_level; |
2561 | |||
2562 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
2563 | goto out; | ||
2564 | |||
2565 | ret = wl1271_ps_elp_wakeup(wl); | ||
2566 | if (ret < 0) | ||
2567 | goto out; | ||
2568 | |||
2569 | /* configure each interface */ | ||
2570 | wl12xx_for_each_wlvif(wl, wlvif) { | ||
2571 | ret = wl12xx_config_vif(wl, wlvif, conf, changed); | ||
2572 | if (ret < 0) | ||
2573 | goto out_sleep; | ||
2450 | } | 2574 | } |
2451 | 2575 | ||
2452 | out_sleep: | 2576 | out_sleep: |
@@ -2509,6 +2633,8 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
2509 | { | 2633 | { |
2510 | struct wl1271_filter_params *fp = (void *)(unsigned long)multicast; | 2634 | struct wl1271_filter_params *fp = (void *)(unsigned long)multicast; |
2511 | struct wl1271 *wl = hw->priv; | 2635 | struct wl1271 *wl = hw->priv; |
2636 | struct wl12xx_vif *wlvif; | ||
2637 | |||
2512 | int ret; | 2638 | int ret; |
2513 | 2639 | ||
2514 | wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter changed %x" | 2640 | wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter changed %x" |
@@ -2526,15 +2652,20 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | |||
2526 | if (ret < 0) | 2652 | if (ret < 0) |
2527 | goto out; | 2653 | goto out; |
2528 | 2654 | ||
2529 | if (wl->bss_type != BSS_TYPE_AP_BSS) { | 2655 | wl12xx_for_each_wlvif(wl, wlvif) { |
2530 | if (*total & FIF_ALLMULTI) | 2656 | if (wlvif->bss_type != BSS_TYPE_AP_BSS) { |
2531 | ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0); | 2657 | if (*total & FIF_ALLMULTI) |
2532 | else if (fp) | 2658 | ret = wl1271_acx_group_address_tbl(wl, wlvif, |
2533 | ret = wl1271_acx_group_address_tbl(wl, fp->enabled, | 2659 | false, |
2534 | fp->mc_list, | 2660 | NULL, 0); |
2535 | fp->mc_list_length); | 2661 | else if (fp) |
2536 | if (ret < 0) | 2662 | ret = wl1271_acx_group_address_tbl(wl, wlvif, |
2537 | goto out_sleep; | 2663 | fp->enabled, |
2664 | fp->mc_list, | ||
2665 | fp->mc_list_length); | ||
2666 | if (ret < 0) | ||
2667 | goto out_sleep; | ||
2668 | } | ||
2538 | } | 2669 | } |
2539 | 2670 | ||
2540 | /* | 2671 | /* |
@@ -2551,9 +2682,10 @@ out: | |||
2551 | kfree(fp); | 2682 | kfree(fp); |
2552 | } | 2683 | } |
2553 | 2684 | ||
2554 | static int wl1271_record_ap_key(struct wl1271 *wl, u8 id, u8 key_type, | 2685 | static int wl1271_record_ap_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
2555 | u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32, | 2686 | u8 id, u8 key_type, u8 key_size, |
2556 | u16 tx_seq_16) | 2687 | const u8 *key, u8 hlid, u32 tx_seq_32, |
2688 | u16 tx_seq_16) | ||
2557 | { | 2689 | { |
2558 | struct wl1271_ap_key *ap_key; | 2690 | struct wl1271_ap_key *ap_key; |
2559 | int i; | 2691 | int i; |
@@ -2568,10 +2700,10 @@ static int wl1271_record_ap_key(struct wl1271 *wl, u8 id, u8 key_type, | |||
2568 | * an existing key. | 2700 | * an existing key. |
2569 | */ | 2701 | */ |
2570 | for (i = 0; i < MAX_NUM_KEYS; i++) { | 2702 | for (i = 0; i < MAX_NUM_KEYS; i++) { |
2571 | if (wl->recorded_ap_keys[i] == NULL) | 2703 | if (wlvif->ap.recorded_keys[i] == NULL) |
2572 | break; | 2704 | break; |
2573 | 2705 | ||
2574 | if (wl->recorded_ap_keys[i]->id == id) { | 2706 | if (wlvif->ap.recorded_keys[i]->id == id) { |
2575 | wl1271_warning("trying to record key replacement"); | 2707 | wl1271_warning("trying to record key replacement"); |
2576 | return -EINVAL; | 2708 | return -EINVAL; |
2577 | } | 2709 | } |
@@ -2592,21 +2724,21 @@ static int wl1271_record_ap_key(struct wl1271 *wl, u8 id, u8 key_type, | |||
2592 | ap_key->tx_seq_32 = tx_seq_32; | 2724 | ap_key->tx_seq_32 = tx_seq_32; |
2593 | ap_key->tx_seq_16 = tx_seq_16; | 2725 | ap_key->tx_seq_16 = tx_seq_16; |
2594 | 2726 | ||
2595 | wl->recorded_ap_keys[i] = ap_key; | 2727 | wlvif->ap.recorded_keys[i] = ap_key; |
2596 | return 0; | 2728 | return 0; |
2597 | } | 2729 | } |
2598 | 2730 | ||
2599 | static void wl1271_free_ap_keys(struct wl1271 *wl) | 2731 | static void wl1271_free_ap_keys(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
2600 | { | 2732 | { |
2601 | int i; | 2733 | int i; |
2602 | 2734 | ||
2603 | for (i = 0; i < MAX_NUM_KEYS; i++) { | 2735 | for (i = 0; i < MAX_NUM_KEYS; i++) { |
2604 | kfree(wl->recorded_ap_keys[i]); | 2736 | kfree(wlvif->ap.recorded_keys[i]); |
2605 | wl->recorded_ap_keys[i] = NULL; | 2737 | wlvif->ap.recorded_keys[i] = NULL; |
2606 | } | 2738 | } |
2607 | } | 2739 | } |
2608 | 2740 | ||
2609 | static int wl1271_ap_init_hwenc(struct wl1271 *wl) | 2741 | static int wl1271_ap_init_hwenc(struct wl1271 *wl, struct wl12xx_vif *wlvif) |
2610 | { | 2742 | { |
2611 | int i, ret = 0; | 2743 | int i, ret = 0; |
2612 | struct wl1271_ap_key *key; | 2744 | struct wl1271_ap_key *key; |
@@ -2614,15 +2746,15 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl) | |||
2614 | 2746 | ||
2615 | for (i = 0; i < MAX_NUM_KEYS; i++) { | 2747 | for (i = 0; i < MAX_NUM_KEYS; i++) { |
2616 | u8 hlid; | 2748 | u8 hlid; |
2617 | if (wl->recorded_ap_keys[i] == NULL) | 2749 | if (wlvif->ap.recorded_keys[i] == NULL) |
2618 | break; | 2750 | break; |
2619 | 2751 | ||
2620 | key = wl->recorded_ap_keys[i]; | 2752 | key = wlvif->ap.recorded_keys[i]; |
2621 | hlid = key->hlid; | 2753 | hlid = key->hlid; |
2622 | if (hlid == WL12XX_INVALID_LINK_ID) | 2754 | if (hlid == WL12XX_INVALID_LINK_ID) |
2623 | hlid = wl->ap_bcast_hlid; | 2755 | hlid = wlvif->ap.bcast_hlid; |
2624 | 2756 | ||
2625 | ret = wl1271_cmd_set_ap_key(wl, KEY_ADD_OR_REPLACE, | 2757 | ret = wl1271_cmd_set_ap_key(wl, wlvif, KEY_ADD_OR_REPLACE, |
2626 | key->id, key->key_type, | 2758 | key->id, key->key_type, |
2627 | key->key_size, key->key, | 2759 | key->key_size, key->key, |
2628 | hlid, key->tx_seq_32, | 2760 | hlid, key->tx_seq_32, |
@@ -2635,23 +2767,24 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl) | |||
2635 | } | 2767 | } |
2636 | 2768 | ||
2637 | if (wep_key_added) { | 2769 | if (wep_key_added) { |
2638 | ret = wl12xx_cmd_set_default_wep_key(wl, wl->default_key, | 2770 | ret = wl12xx_cmd_set_default_wep_key(wl, wlvif->default_key, |
2639 | wl->ap_bcast_hlid); | 2771 | wlvif->ap.bcast_hlid); |
2640 | if (ret < 0) | 2772 | if (ret < 0) |
2641 | goto out; | 2773 | goto out; |
2642 | } | 2774 | } |
2643 | 2775 | ||
2644 | out: | 2776 | out: |
2645 | wl1271_free_ap_keys(wl); | 2777 | wl1271_free_ap_keys(wl, wlvif); |
2646 | return ret; | 2778 | return ret; |
2647 | } | 2779 | } |
2648 | 2780 | ||
2649 | static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | 2781 | static int wl1271_set_key(struct wl1271 *wl, struct wl12xx_vif *wlvif, |
2782 | u16 action, u8 id, u8 key_type, | ||
2650 | u8 key_size, const u8 *key, u32 tx_seq_32, | 2783 | u8 key_size, const u8 *key, u32 tx_seq_32, |
2651 | u16 tx_seq_16, struct ieee80211_sta *sta) | 2784 | u16 tx_seq_16, struct ieee80211_sta *sta) |
2652 | { | 2785 | { |
2653 | int ret; | 2786 | int ret; |
2654 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | 2787 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); |
2655 | 2788 | ||
2656 | if (is_ap) { | 2789 | if (is_ap) { |
2657 | struct wl1271_station *wl_sta; | 2790 | struct wl1271_station *wl_sta; |
@@ -2661,10 +2794,10 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | |||
2661 | wl_sta = (struct wl1271_station *)sta->drv_priv; | 2794 | wl_sta = (struct wl1271_station *)sta->drv_priv; |
2662 | hlid = wl_sta->hlid; | 2795 | hlid = wl_sta->hlid; |
2663 | } else { | 2796 | } else { |
2664 | hlid = wl->ap_bcast_hlid; | 2797 | hlid = wlvif->ap.bcast_hlid; |
2665 | } | 2798 | } |
2666 | 2799 | ||
2667 | if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { | 2800 | if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) { |
2668 | /* | 2801 | /* |
2669 | * We do not support removing keys after AP shutdown. | 2802 | * We do not support removing keys after AP shutdown. |
2670 | * Pretend we do to make mac80211 happy. | 2803 | * Pretend we do to make mac80211 happy. |
@@ -2672,12 +2805,12 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | |||
2672 | if (action != KEY_ADD_OR_REPLACE) | 2805 | if (action != KEY_ADD_OR_REPLACE) |
2673 | return 0; | 2806 | return 0; |
2674 | 2807 | ||
2675 | ret = wl1271_record_ap_key(wl, id, | 2808 | ret = wl1271_record_ap_key(wl, wlvif, id, |
2676 | key_type, key_size, | 2809 | key_type, key_size, |
2677 | key, hlid, tx_seq_32, | 2810 | key, hlid, tx_seq_32, |
2678 | tx_seq_16); | 2811 | tx_seq_16); |
2679 | } else { | 2812 | } else { |
2680 | ret = wl1271_cmd_set_ap_key(wl, action, | 2813 | ret = wl1271_cmd_set_ap_key(wl, wlvif, action, |
2681 | id, key_type, key_size, | 2814 | id, key_type, key_size, |
2682 | key, hlid, tx_seq_32, | 2815 | key, hlid, tx_seq_32, |
2683 | tx_seq_16); | 2816 | tx_seq_16); |
@@ -2718,10 +2851,10 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | |||
2718 | 2851 | ||
2719 | /* don't remove key if hlid was already deleted */ | 2852 | /* don't remove key if hlid was already deleted */ |
2720 | if (action == KEY_REMOVE && | 2853 | if (action == KEY_REMOVE && |
2721 | wl->sta_hlid == WL12XX_INVALID_LINK_ID) | 2854 | wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) |
2722 | return 0; | 2855 | return 0; |
2723 | 2856 | ||
2724 | ret = wl1271_cmd_set_sta_key(wl, action, | 2857 | ret = wl1271_cmd_set_sta_key(wl, wlvif, action, |
2725 | id, key_type, key_size, | 2858 | id, key_type, key_size, |
2726 | key, addr, tx_seq_32, | 2859 | key, addr, tx_seq_32, |
2727 | tx_seq_16); | 2860 | tx_seq_16); |
@@ -2731,8 +2864,8 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, | |||
2731 | /* the default WEP key needs to be configured at least once */ | 2864 | /* the default WEP key needs to be configured at least once */ |
2732 | if (key_type == KEY_WEP) { | 2865 | if (key_type == KEY_WEP) { |
2733 | ret = wl12xx_cmd_set_default_wep_key(wl, | 2866 | ret = wl12xx_cmd_set_default_wep_key(wl, |
2734 | wl->default_key, | 2867 | wlvif->default_key, |
2735 | wl->sta_hlid); | 2868 | wlvif->sta.hlid); |
2736 | if (ret < 0) | 2869 | if (ret < 0) |
2737 | return ret; | 2870 | return ret; |
2738 | } | 2871 | } |
@@ -2747,6 +2880,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2747 | struct ieee80211_key_conf *key_conf) | 2880 | struct ieee80211_key_conf *key_conf) |
2748 | { | 2881 | { |
2749 | struct wl1271 *wl = hw->priv; | 2882 | struct wl1271 *wl = hw->priv; |
2883 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
2750 | int ret; | 2884 | int ret; |
2751 | u32 tx_seq_32 = 0; | 2885 | u32 tx_seq_32 = 0; |
2752 | u16 tx_seq_16 = 0; | 2886 | u16 tx_seq_16 = 0; |
@@ -2782,20 +2916,20 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2782 | key_type = KEY_TKIP; | 2916 | key_type = KEY_TKIP; |
2783 | 2917 | ||
2784 | key_conf->hw_key_idx = key_conf->keyidx; | 2918 | key_conf->hw_key_idx = key_conf->keyidx; |
2785 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); | 2919 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); |
2786 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | 2920 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); |
2787 | break; | 2921 | break; |
2788 | case WLAN_CIPHER_SUITE_CCMP: | 2922 | case WLAN_CIPHER_SUITE_CCMP: |
2789 | key_type = KEY_AES; | 2923 | key_type = KEY_AES; |
2790 | 2924 | ||
2791 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 2925 | key_conf->flags |= IEEE80211_KEY_FLAG_PUT_IV_SPACE; |
2792 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); | 2926 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); |
2793 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | 2927 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); |
2794 | break; | 2928 | break; |
2795 | case WL1271_CIPHER_SUITE_GEM: | 2929 | case WL1271_CIPHER_SUITE_GEM: |
2796 | key_type = KEY_GEM; | 2930 | key_type = KEY_GEM; |
2797 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); | 2931 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wlvif->tx_security_seq); |
2798 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | 2932 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wlvif->tx_security_seq); |
2799 | break; | 2933 | break; |
2800 | default: | 2934 | default: |
2801 | wl1271_error("Unknown key algo 0x%x", key_conf->cipher); | 2935 | wl1271_error("Unknown key algo 0x%x", key_conf->cipher); |
@@ -2806,7 +2940,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2806 | 2940 | ||
2807 | switch (cmd) { | 2941 | switch (cmd) { |
2808 | case SET_KEY: | 2942 | case SET_KEY: |
2809 | ret = wl1271_set_key(wl, KEY_ADD_OR_REPLACE, | 2943 | ret = wl1271_set_key(wl, wlvif, KEY_ADD_OR_REPLACE, |
2810 | key_conf->keyidx, key_type, | 2944 | key_conf->keyidx, key_type, |
2811 | key_conf->keylen, key_conf->key, | 2945 | key_conf->keylen, key_conf->key, |
2812 | tx_seq_32, tx_seq_16, sta); | 2946 | tx_seq_32, tx_seq_16, sta); |
@@ -2817,7 +2951,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2817 | break; | 2951 | break; |
2818 | 2952 | ||
2819 | case DISABLE_KEY: | 2953 | case DISABLE_KEY: |
2820 | ret = wl1271_set_key(wl, KEY_REMOVE, | 2954 | ret = wl1271_set_key(wl, wlvif, KEY_REMOVE, |
2821 | key_conf->keyidx, key_type, | 2955 | key_conf->keyidx, key_type, |
2822 | key_conf->keylen, key_conf->key, | 2956 | key_conf->keylen, key_conf->key, |
2823 | 0, 0, sta); | 2957 | 0, 0, sta); |
@@ -2847,6 +2981,8 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
2847 | struct cfg80211_scan_request *req) | 2981 | struct cfg80211_scan_request *req) |
2848 | { | 2982 | { |
2849 | struct wl1271 *wl = hw->priv; | 2983 | struct wl1271 *wl = hw->priv; |
2984 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
2985 | |||
2850 | int ret; | 2986 | int ret; |
2851 | u8 *ssid = NULL; | 2987 | u8 *ssid = NULL; |
2852 | size_t len = 0; | 2988 | size_t len = 0; |
@@ -2876,16 +3012,15 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, | |||
2876 | 3012 | ||
2877 | /* cancel ROC before scanning */ | 3013 | /* cancel ROC before scanning */ |
2878 | if (wl12xx_is_roc(wl)) { | 3014 | if (wl12xx_is_roc(wl)) { |
2879 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { | 3015 | if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { |
2880 | /* don't allow scanning right now */ | 3016 | /* don't allow scanning right now */ |
2881 | ret = -EBUSY; | 3017 | ret = -EBUSY; |
2882 | goto out_sleep; | 3018 | goto out_sleep; |
2883 | } | 3019 | } |
2884 | wl12xx_croc(wl, wl->dev_role_id); | 3020 | wl12xx_stop_dev(wl, wlvif); |
2885 | wl12xx_cmd_role_stop_dev(wl); | ||
2886 | } | 3021 | } |
2887 | 3022 | ||
2888 | ret = wl1271_scan(hw->priv, ssid, len, req); | 3023 | ret = wl1271_scan(hw->priv, vif, ssid, len, req); |
2889 | out_sleep: | 3024 | out_sleep: |
2890 | wl1271_ps_elp_sleep(wl); | 3025 | wl1271_ps_elp_sleep(wl); |
2891 | out: | 3026 | out: |
@@ -2921,6 +3056,7 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw, | |||
2921 | } | 3056 | } |
2922 | wl->scan.state = WL1271_SCAN_STATE_IDLE; | 3057 | wl->scan.state = WL1271_SCAN_STATE_IDLE; |
2923 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); | 3058 | memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch)); |
3059 | wl->scan_vif = NULL; | ||
2924 | wl->scan.req = NULL; | 3060 | wl->scan.req = NULL; |
2925 | ieee80211_scan_completed(wl->hw, true); | 3061 | ieee80211_scan_completed(wl->hw, true); |
2926 | 3062 | ||
@@ -2938,6 +3074,7 @@ static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, | |||
2938 | struct ieee80211_sched_scan_ies *ies) | 3074 | struct ieee80211_sched_scan_ies *ies) |
2939 | { | 3075 | { |
2940 | struct wl1271 *wl = hw->priv; | 3076 | struct wl1271 *wl = hw->priv; |
3077 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
2941 | int ret; | 3078 | int ret; |
2942 | 3079 | ||
2943 | wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_start"); | 3080 | wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_start"); |
@@ -2948,11 +3085,11 @@ static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, | |||
2948 | if (ret < 0) | 3085 | if (ret < 0) |
2949 | goto out; | 3086 | goto out; |
2950 | 3087 | ||
2951 | ret = wl1271_scan_sched_scan_config(wl, req, ies); | 3088 | ret = wl1271_scan_sched_scan_config(wl, wlvif, req, ies); |
2952 | if (ret < 0) | 3089 | if (ret < 0) |
2953 | goto out_sleep; | 3090 | goto out_sleep; |
2954 | 3091 | ||
2955 | ret = wl1271_scan_sched_scan_start(wl); | 3092 | ret = wl1271_scan_sched_scan_start(wl, wlvif); |
2956 | if (ret < 0) | 3093 | if (ret < 0) |
2957 | goto out_sleep; | 3094 | goto out_sleep; |
2958 | 3095 | ||
@@ -3017,6 +3154,7 @@ out: | |||
3017 | static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 3154 | static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
3018 | { | 3155 | { |
3019 | struct wl1271 *wl = hw->priv; | 3156 | struct wl1271 *wl = hw->priv; |
3157 | struct wl12xx_vif *wlvif; | ||
3020 | int ret = 0; | 3158 | int ret = 0; |
3021 | 3159 | ||
3022 | mutex_lock(&wl->mutex); | 3160 | mutex_lock(&wl->mutex); |
@@ -3030,10 +3168,11 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | |||
3030 | if (ret < 0) | 3168 | if (ret < 0) |
3031 | goto out; | 3169 | goto out; |
3032 | 3170 | ||
3033 | ret = wl1271_acx_rts_threshold(wl, value); | 3171 | wl12xx_for_each_wlvif(wl, wlvif) { |
3034 | if (ret < 0) | 3172 | ret = wl1271_acx_rts_threshold(wl, wlvif, value); |
3035 | wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret); | 3173 | if (ret < 0) |
3036 | 3174 | wl1271_warning("set rts threshold failed: %d", ret); | |
3175 | } | ||
3037 | wl1271_ps_elp_sleep(wl); | 3176 | wl1271_ps_elp_sleep(wl); |
3038 | 3177 | ||
3039 | out: | 3178 | out: |
@@ -3042,9 +3181,10 @@ out: | |||
3042 | return ret; | 3181 | return ret; |
3043 | } | 3182 | } |
3044 | 3183 | ||
3045 | static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, | 3184 | static int wl1271_ssid_set(struct ieee80211_vif *vif, struct sk_buff *skb, |
3046 | int offset) | 3185 | int offset) |
3047 | { | 3186 | { |
3187 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
3048 | u8 ssid_len; | 3188 | u8 ssid_len; |
3049 | const u8 *ptr = cfg80211_find_ie(WLAN_EID_SSID, skb->data + offset, | 3189 | const u8 *ptr = cfg80211_find_ie(WLAN_EID_SSID, skb->data + offset, |
3050 | skb->len - offset); | 3190 | skb->len - offset); |
@@ -3060,8 +3200,8 @@ static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, | |||
3060 | return -EINVAL; | 3200 | return -EINVAL; |
3061 | } | 3201 | } |
3062 | 3202 | ||
3063 | wl->ssid_len = ssid_len; | 3203 | wlvif->ssid_len = ssid_len; |
3064 | memcpy(wl->ssid, ptr+2, ssid_len); | 3204 | memcpy(wlvif->ssid, ptr+2, ssid_len); |
3065 | return 0; | 3205 | return 0; |
3066 | } | 3206 | } |
3067 | 3207 | ||
@@ -3096,18 +3236,40 @@ static void wl12xx_remove_vendor_ie(struct sk_buff *skb, | |||
3096 | skb_trim(skb, skb->len - len); | 3236 | skb_trim(skb, skb->len - len); |
3097 | } | 3237 | } |
3098 | 3238 | ||
3099 | static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, | 3239 | static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, u32 rates, |
3100 | u8 *probe_rsp_data, | 3240 | struct ieee80211_vif *vif) |
3101 | size_t probe_rsp_len, | ||
3102 | u32 rates) | ||
3103 | { | 3241 | { |
3104 | struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf; | 3242 | struct sk_buff *skb; |
3243 | int ret; | ||
3244 | |||
3245 | skb = ieee80211_proberesp_get(wl->hw, vif); | ||
3246 | if (!skb) | ||
3247 | return -EOPNOTSUPP; | ||
3248 | |||
3249 | ret = wl1271_cmd_template_set(wl, | ||
3250 | CMD_TEMPL_AP_PROBE_RESPONSE, | ||
3251 | skb->data, | ||
3252 | skb->len, 0, | ||
3253 | rates); | ||
3254 | |||
3255 | dev_kfree_skb(skb); | ||
3256 | return ret; | ||
3257 | } | ||
3258 | |||
3259 | static int wl1271_ap_set_probe_resp_tmpl_legacy(struct wl1271 *wl, | ||
3260 | struct ieee80211_vif *vif, | ||
3261 | u8 *probe_rsp_data, | ||
3262 | size_t probe_rsp_len, | ||
3263 | u32 rates) | ||
3264 | { | ||
3265 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
3266 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
3105 | u8 probe_rsp_templ[WL1271_CMD_TEMPL_MAX_SIZE]; | 3267 | u8 probe_rsp_templ[WL1271_CMD_TEMPL_MAX_SIZE]; |
3106 | int ssid_ie_offset, ie_offset, templ_len; | 3268 | int ssid_ie_offset, ie_offset, templ_len; |
3107 | const u8 *ptr; | 3269 | const u8 *ptr; |
3108 | 3270 | ||
3109 | /* no need to change probe response if the SSID is set correctly */ | 3271 | /* no need to change probe response if the SSID is set correctly */ |
3110 | if (wl->ssid_len > 0) | 3272 | if (wlvif->ssid_len > 0) |
3111 | return wl1271_cmd_template_set(wl, | 3273 | return wl1271_cmd_template_set(wl, |
3112 | CMD_TEMPL_AP_PROBE_RESPONSE, | 3274 | CMD_TEMPL_AP_PROBE_RESPONSE, |
3113 | probe_rsp_data, | 3275 | probe_rsp_data, |
@@ -3153,16 +3315,18 @@ static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl, | |||
3153 | } | 3315 | } |
3154 | 3316 | ||
3155 | static int wl1271_bss_erp_info_changed(struct wl1271 *wl, | 3317 | static int wl1271_bss_erp_info_changed(struct wl1271 *wl, |
3318 | struct ieee80211_vif *vif, | ||
3156 | struct ieee80211_bss_conf *bss_conf, | 3319 | struct ieee80211_bss_conf *bss_conf, |
3157 | u32 changed) | 3320 | u32 changed) |
3158 | { | 3321 | { |
3322 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
3159 | int ret = 0; | 3323 | int ret = 0; |
3160 | 3324 | ||
3161 | if (changed & BSS_CHANGED_ERP_SLOT) { | 3325 | if (changed & BSS_CHANGED_ERP_SLOT) { |
3162 | if (bss_conf->use_short_slot) | 3326 | if (bss_conf->use_short_slot) |
3163 | ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT); | 3327 | ret = wl1271_acx_slot(wl, wlvif, SLOT_TIME_SHORT); |
3164 | else | 3328 | else |
3165 | ret = wl1271_acx_slot(wl, SLOT_TIME_LONG); | 3329 | ret = wl1271_acx_slot(wl, wlvif, SLOT_TIME_LONG); |
3166 | if (ret < 0) { | 3330 | if (ret < 0) { |
3167 | wl1271_warning("Set slot time failed %d", ret); | 3331 | wl1271_warning("Set slot time failed %d", ret); |
3168 | goto out; | 3332 | goto out; |
@@ -3171,16 +3335,18 @@ static int wl1271_bss_erp_info_changed(struct wl1271 *wl, | |||
3171 | 3335 | ||
3172 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | 3336 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
3173 | if (bss_conf->use_short_preamble) | 3337 | if (bss_conf->use_short_preamble) |
3174 | wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT); | 3338 | wl1271_acx_set_preamble(wl, wlvif, ACX_PREAMBLE_SHORT); |
3175 | else | 3339 | else |
3176 | wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG); | 3340 | wl1271_acx_set_preamble(wl, wlvif, ACX_PREAMBLE_LONG); |
3177 | } | 3341 | } |
3178 | 3342 | ||
3179 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | 3343 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { |
3180 | if (bss_conf->use_cts_prot) | 3344 | if (bss_conf->use_cts_prot) |
3181 | ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE); | 3345 | ret = wl1271_acx_cts_protect(wl, wlvif, |
3346 | CTSPROTECT_ENABLE); | ||
3182 | else | 3347 | else |
3183 | ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE); | 3348 | ret = wl1271_acx_cts_protect(wl, wlvif, |
3349 | CTSPROTECT_DISABLE); | ||
3184 | if (ret < 0) { | 3350 | if (ret < 0) { |
3185 | wl1271_warning("Set ctsprotect failed %d", ret); | 3351 | wl1271_warning("Set ctsprotect failed %d", ret); |
3186 | goto out; | 3352 | goto out; |
@@ -3196,14 +3362,23 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3196 | struct ieee80211_bss_conf *bss_conf, | 3362 | struct ieee80211_bss_conf *bss_conf, |
3197 | u32 changed) | 3363 | u32 changed) |
3198 | { | 3364 | { |
3199 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | 3365 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
3366 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); | ||
3200 | int ret = 0; | 3367 | int ret = 0; |
3201 | 3368 | ||
3202 | if ((changed & BSS_CHANGED_BEACON_INT)) { | 3369 | if ((changed & BSS_CHANGED_BEACON_INT)) { |
3203 | wl1271_debug(DEBUG_MASTER, "beacon interval updated: %d", | 3370 | wl1271_debug(DEBUG_MASTER, "beacon interval updated: %d", |
3204 | bss_conf->beacon_int); | 3371 | bss_conf->beacon_int); |
3205 | 3372 | ||
3206 | wl->beacon_int = bss_conf->beacon_int; | 3373 | wlvif->beacon_int = bss_conf->beacon_int; |
3374 | } | ||
3375 | |||
3376 | if ((changed & BSS_CHANGED_AP_PROBE_RESP) && is_ap) { | ||
3377 | u32 rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); | ||
3378 | if (!wl1271_ap_set_probe_resp_tmpl(wl, rate, vif)) { | ||
3379 | wl1271_debug(DEBUG_AP, "probe response updated"); | ||
3380 | set_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags); | ||
3381 | } | ||
3207 | } | 3382 | } |
3208 | 3383 | ||
3209 | if ((changed & BSS_CHANGED_BEACON)) { | 3384 | if ((changed & BSS_CHANGED_BEACON)) { |
@@ -3214,17 +3389,19 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3214 | struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); | 3389 | struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); |
3215 | u16 tmpl_id; | 3390 | u16 tmpl_id; |
3216 | 3391 | ||
3217 | if (!beacon) | 3392 | if (!beacon) { |
3393 | ret = -EINVAL; | ||
3218 | goto out; | 3394 | goto out; |
3395 | } | ||
3219 | 3396 | ||
3220 | wl1271_debug(DEBUG_MASTER, "beacon updated"); | 3397 | wl1271_debug(DEBUG_MASTER, "beacon updated"); |
3221 | 3398 | ||
3222 | ret = wl1271_ssid_set(wl, beacon, ieoffset); | 3399 | ret = wl1271_ssid_set(vif, beacon, ieoffset); |
3223 | if (ret < 0) { | 3400 | if (ret < 0) { |
3224 | dev_kfree_skb(beacon); | 3401 | dev_kfree_skb(beacon); |
3225 | goto out; | 3402 | goto out; |
3226 | } | 3403 | } |
3227 | min_rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set); | 3404 | min_rate = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); |
3228 | tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : | 3405 | tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : |
3229 | CMD_TEMPL_BEACON; | 3406 | CMD_TEMPL_BEACON; |
3230 | ret = wl1271_cmd_template_set(wl, tmpl_id, | 3407 | ret = wl1271_cmd_template_set(wl, tmpl_id, |
@@ -3236,6 +3413,13 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3236 | goto out; | 3413 | goto out; |
3237 | } | 3414 | } |
3238 | 3415 | ||
3416 | /* | ||
3417 | * In case we already have a probe-resp beacon set explicitly | ||
3418 | * by usermode, don't use the beacon data. | ||
3419 | */ | ||
3420 | if (test_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, &wlvif->flags)) | ||
3421 | goto end_bcn; | ||
3422 | |||
3239 | /* remove TIM ie from probe response */ | 3423 | /* remove TIM ie from probe response */ |
3240 | wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset); | 3424 | wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset); |
3241 | 3425 | ||
@@ -3254,7 +3438,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3254 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 3438 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
3255 | IEEE80211_STYPE_PROBE_RESP); | 3439 | IEEE80211_STYPE_PROBE_RESP); |
3256 | if (is_ap) | 3440 | if (is_ap) |
3257 | ret = wl1271_ap_set_probe_resp_tmpl(wl, | 3441 | ret = wl1271_ap_set_probe_resp_tmpl_legacy(wl, vif, |
3258 | beacon->data, | 3442 | beacon->data, |
3259 | beacon->len, | 3443 | beacon->len, |
3260 | min_rate); | 3444 | min_rate); |
@@ -3264,12 +3448,15 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, | |||
3264 | beacon->data, | 3448 | beacon->data, |
3265 | beacon->len, 0, | 3449 | beacon->len, 0, |
3266 | min_rate); | 3450 | min_rate); |
3451 | end_bcn: | ||
3267 | dev_kfree_skb(beacon); | 3452 | dev_kfree_skb(beacon); |
3268 | if (ret < 0) | 3453 | if (ret < 0) |
3269 | goto out; | 3454 | goto out; |
3270 | } | 3455 | } |
3271 | 3456 | ||
3272 | out: | 3457 | out: |
3458 | if (ret != 0) | ||
3459 | wl1271_error("beacon info change failed: %d", ret); | ||
3273 | return ret; | 3460 | return ret; |
3274 | } | 3461 | } |
3275 | 3462 | ||
@@ -3279,23 +3466,24 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
3279 | struct ieee80211_bss_conf *bss_conf, | 3466 | struct ieee80211_bss_conf *bss_conf, |
3280 | u32 changed) | 3467 | u32 changed) |
3281 | { | 3468 | { |
3469 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
3282 | int ret = 0; | 3470 | int ret = 0; |
3283 | 3471 | ||
3284 | if ((changed & BSS_CHANGED_BASIC_RATES)) { | 3472 | if ((changed & BSS_CHANGED_BASIC_RATES)) { |
3285 | u32 rates = bss_conf->basic_rates; | 3473 | u32 rates = bss_conf->basic_rates; |
3286 | 3474 | ||
3287 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, | 3475 | wlvif->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates, |
3288 | wl->band); | 3476 | wlvif->band); |
3289 | wl->basic_rate = wl1271_tx_min_rate_get(wl, | 3477 | wlvif->basic_rate = wl1271_tx_min_rate_get(wl, |
3290 | wl->basic_rate_set); | 3478 | wlvif->basic_rate_set); |
3291 | 3479 | ||
3292 | ret = wl1271_init_ap_rates(wl); | 3480 | ret = wl1271_init_ap_rates(wl, wlvif); |
3293 | if (ret < 0) { | 3481 | if (ret < 0) { |
3294 | wl1271_error("AP rate policy change failed %d", ret); | 3482 | wl1271_error("AP rate policy change failed %d", ret); |
3295 | goto out; | 3483 | goto out; |
3296 | } | 3484 | } |
3297 | 3485 | ||
3298 | ret = wl1271_ap_init_templates(wl); | 3486 | ret = wl1271_ap_init_templates(wl, vif); |
3299 | if (ret < 0) | 3487 | if (ret < 0) |
3300 | goto out; | 3488 | goto out; |
3301 | } | 3489 | } |
@@ -3306,38 +3494,40 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
3306 | 3494 | ||
3307 | if ((changed & BSS_CHANGED_BEACON_ENABLED)) { | 3495 | if ((changed & BSS_CHANGED_BEACON_ENABLED)) { |
3308 | if (bss_conf->enable_beacon) { | 3496 | if (bss_conf->enable_beacon) { |
3309 | if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { | 3497 | if (!test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) { |
3310 | ret = wl12xx_cmd_role_start_ap(wl); | 3498 | ret = wl12xx_cmd_role_start_ap(wl, wlvif); |
3311 | if (ret < 0) | 3499 | if (ret < 0) |
3312 | goto out; | 3500 | goto out; |
3313 | 3501 | ||
3314 | ret = wl1271_ap_init_hwenc(wl); | 3502 | ret = wl1271_ap_init_hwenc(wl, wlvif); |
3315 | if (ret < 0) | 3503 | if (ret < 0) |
3316 | goto out; | 3504 | goto out; |
3317 | 3505 | ||
3318 | set_bit(WL1271_FLAG_AP_STARTED, &wl->flags); | 3506 | set_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags); |
3319 | wl1271_debug(DEBUG_AP, "started AP"); | 3507 | wl1271_debug(DEBUG_AP, "started AP"); |
3320 | } | 3508 | } |
3321 | } else { | 3509 | } else { |
3322 | if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) { | 3510 | if (test_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags)) { |
3323 | ret = wl12xx_cmd_role_stop_ap(wl); | 3511 | ret = wl12xx_cmd_role_stop_ap(wl, wlvif); |
3324 | if (ret < 0) | 3512 | if (ret < 0) |
3325 | goto out; | 3513 | goto out; |
3326 | 3514 | ||
3327 | clear_bit(WL1271_FLAG_AP_STARTED, &wl->flags); | 3515 | clear_bit(WLVIF_FLAG_AP_STARTED, &wlvif->flags); |
3516 | clear_bit(WLVIF_FLAG_AP_PROBE_RESP_SET, | ||
3517 | &wlvif->flags); | ||
3328 | wl1271_debug(DEBUG_AP, "stopped AP"); | 3518 | wl1271_debug(DEBUG_AP, "stopped AP"); |
3329 | } | 3519 | } |
3330 | } | 3520 | } |
3331 | } | 3521 | } |
3332 | 3522 | ||
3333 | ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); | 3523 | ret = wl1271_bss_erp_info_changed(wl, vif, bss_conf, changed); |
3334 | if (ret < 0) | 3524 | if (ret < 0) |
3335 | goto out; | 3525 | goto out; |
3336 | 3526 | ||
3337 | /* Handle HT information change */ | 3527 | /* Handle HT information change */ |
3338 | if ((changed & BSS_CHANGED_HT) && | 3528 | if ((changed & BSS_CHANGED_HT) && |
3339 | (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { | 3529 | (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { |
3340 | ret = wl1271_acx_set_ht_information(wl, | 3530 | ret = wl1271_acx_set_ht_information(wl, wlvif, |
3341 | bss_conf->ht_operation_mode); | 3531 | bss_conf->ht_operation_mode); |
3342 | if (ret < 0) { | 3532 | if (ret < 0) { |
3343 | wl1271_warning("Set ht information failed %d", ret); | 3533 | wl1271_warning("Set ht information failed %d", ret); |
@@ -3355,8 +3545,9 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
3355 | struct ieee80211_bss_conf *bss_conf, | 3545 | struct ieee80211_bss_conf *bss_conf, |
3356 | u32 changed) | 3546 | u32 changed) |
3357 | { | 3547 | { |
3548 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
3358 | bool do_join = false, set_assoc = false; | 3549 | bool do_join = false, set_assoc = false; |
3359 | bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS); | 3550 | bool is_ibss = (wlvif->bss_type == BSS_TYPE_IBSS); |
3360 | bool ibss_joined = false; | 3551 | bool ibss_joined = false; |
3361 | u32 sta_rate_set = 0; | 3552 | u32 sta_rate_set = 0; |
3362 | int ret; | 3553 | int ret; |
@@ -3373,14 +3564,13 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
3373 | 3564 | ||
3374 | if (changed & BSS_CHANGED_IBSS) { | 3565 | if (changed & BSS_CHANGED_IBSS) { |
3375 | if (bss_conf->ibss_joined) { | 3566 | if (bss_conf->ibss_joined) { |
3376 | set_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags); | 3567 | set_bit(WLVIF_FLAG_IBSS_JOINED, &wlvif->flags); |
3377 | ibss_joined = true; | 3568 | ibss_joined = true; |
3378 | } else { | 3569 | } else { |
3379 | if (test_and_clear_bit(WL1271_FLAG_IBSS_JOINED, | 3570 | if (test_and_clear_bit(WLVIF_FLAG_IBSS_JOINED, |
3380 | &wl->flags)) { | 3571 | &wlvif->flags)) { |
3381 | wl1271_unjoin(wl); | 3572 | wl1271_unjoin(wl, wlvif); |
3382 | wl12xx_cmd_role_start_dev(wl); | 3573 | wl12xx_start_dev(wl, wlvif); |
3383 | wl12xx_roc(wl, wl->dev_role_id); | ||
3384 | } | 3574 | } |
3385 | } | 3575 | } |
3386 | } | 3576 | } |
@@ -3396,46 +3586,40 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
3396 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", | 3586 | wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s", |
3397 | bss_conf->enable_beacon ? "enabled" : "disabled"); | 3587 | bss_conf->enable_beacon ? "enabled" : "disabled"); |
3398 | 3588 | ||
3399 | if (bss_conf->enable_beacon) | ||
3400 | wl->set_bss_type = BSS_TYPE_IBSS; | ||
3401 | else | ||
3402 | wl->set_bss_type = BSS_TYPE_STA_BSS; | ||
3403 | do_join = true; | 3589 | do_join = true; |
3404 | } | 3590 | } |
3405 | 3591 | ||
3592 | if (changed & BSS_CHANGED_IDLE) { | ||
3593 | ret = wl1271_sta_handle_idle(wl, wlvif, bss_conf->idle); | ||
3594 | if (ret < 0) | ||
3595 | wl1271_warning("idle mode change failed %d", ret); | ||
3596 | } | ||
3597 | |||
3406 | if ((changed & BSS_CHANGED_CQM)) { | 3598 | if ((changed & BSS_CHANGED_CQM)) { |
3407 | bool enable = false; | 3599 | bool enable = false; |
3408 | if (bss_conf->cqm_rssi_thold) | 3600 | if (bss_conf->cqm_rssi_thold) |
3409 | enable = true; | 3601 | enable = true; |
3410 | ret = wl1271_acx_rssi_snr_trigger(wl, enable, | 3602 | ret = wl1271_acx_rssi_snr_trigger(wl, wlvif, enable, |
3411 | bss_conf->cqm_rssi_thold, | 3603 | bss_conf->cqm_rssi_thold, |
3412 | bss_conf->cqm_rssi_hyst); | 3604 | bss_conf->cqm_rssi_hyst); |
3413 | if (ret < 0) | 3605 | if (ret < 0) |
3414 | goto out; | 3606 | goto out; |
3415 | wl->rssi_thold = bss_conf->cqm_rssi_thold; | 3607 | wlvif->rssi_thold = bss_conf->cqm_rssi_thold; |
3416 | } | 3608 | } |
3417 | 3609 | ||
3418 | if ((changed & BSS_CHANGED_BSSID) && | 3610 | if (changed & BSS_CHANGED_BSSID) |
3419 | /* | 3611 | if (!is_zero_ether_addr(bss_conf->bssid)) { |
3420 | * Now we know the correct bssid, so we send a new join command | 3612 | ret = wl12xx_cmd_build_null_data(wl, wlvif); |
3421 | * and enable the BSSID filter | ||
3422 | */ | ||
3423 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | ||
3424 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | ||
3425 | |||
3426 | if (!is_zero_ether_addr(wl->bssid)) { | ||
3427 | ret = wl1271_cmd_build_null_data(wl); | ||
3428 | if (ret < 0) | 3613 | if (ret < 0) |
3429 | goto out; | 3614 | goto out; |
3430 | 3615 | ||
3431 | ret = wl1271_build_qos_null_data(wl); | 3616 | ret = wl1271_build_qos_null_data(wl, vif); |
3432 | if (ret < 0) | 3617 | if (ret < 0) |
3433 | goto out; | 3618 | goto out; |
3434 | 3619 | ||
3435 | /* Need to update the BSSID (for filtering etc) */ | 3620 | /* Need to update the BSSID (for filtering etc) */ |
3436 | do_join = true; | 3621 | do_join = true; |
3437 | } | 3622 | } |
3438 | } | ||
3439 | 3623 | ||
3440 | if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) { | 3624 | if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) { |
3441 | rcu_read_lock(); | 3625 | rcu_read_lock(); |
@@ -3459,26 +3643,28 @@ sta_not_found: | |||
3459 | if (bss_conf->assoc) { | 3643 | if (bss_conf->assoc) { |
3460 | u32 rates; | 3644 | u32 rates; |
3461 | int ieoffset; | 3645 | int ieoffset; |
3462 | wl->aid = bss_conf->aid; | 3646 | wlvif->aid = bss_conf->aid; |
3463 | set_assoc = true; | 3647 | set_assoc = true; |
3464 | 3648 | ||
3465 | wl->ps_poll_failures = 0; | 3649 | wlvif->ps_poll_failures = 0; |
3466 | 3650 | ||
3467 | /* | 3651 | /* |
3468 | * use basic rates from AP, and determine lowest rate | 3652 | * use basic rates from AP, and determine lowest rate |
3469 | * to use with control frames. | 3653 | * to use with control frames. |
3470 | */ | 3654 | */ |
3471 | rates = bss_conf->basic_rates; | 3655 | rates = bss_conf->basic_rates; |
3472 | wl->basic_rate_set = | 3656 | wlvif->basic_rate_set = |
3473 | wl1271_tx_enabled_rates_get(wl, rates, | 3657 | wl1271_tx_enabled_rates_get(wl, rates, |
3474 | wl->band); | 3658 | wlvif->band); |
3475 | wl->basic_rate = | 3659 | wlvif->basic_rate = |
3476 | wl1271_tx_min_rate_get(wl, wl->basic_rate_set); | 3660 | wl1271_tx_min_rate_get(wl, |
3661 | wlvif->basic_rate_set); | ||
3477 | if (sta_rate_set) | 3662 | if (sta_rate_set) |
3478 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, | 3663 | wlvif->rate_set = |
3664 | wl1271_tx_enabled_rates_get(wl, | ||
3479 | sta_rate_set, | 3665 | sta_rate_set, |
3480 | wl->band); | 3666 | wlvif->band); |
3481 | ret = wl1271_acx_sta_rate_policies(wl); | 3667 | ret = wl1271_acx_sta_rate_policies(wl, wlvif); |
3482 | if (ret < 0) | 3668 | if (ret < 0) |
3483 | goto out; | 3669 | goto out; |
3484 | 3670 | ||
@@ -3488,53 +3674,56 @@ sta_not_found: | |||
3488 | * updates it by itself when the first beacon is | 3674 | * updates it by itself when the first beacon is |
3489 | * received after a join. | 3675 | * received after a join. |
3490 | */ | 3676 | */ |
3491 | ret = wl1271_cmd_build_ps_poll(wl, wl->aid); | 3677 | ret = wl1271_cmd_build_ps_poll(wl, wlvif, wlvif->aid); |
3492 | if (ret < 0) | 3678 | if (ret < 0) |
3493 | goto out; | 3679 | goto out; |
3494 | 3680 | ||
3495 | /* | 3681 | /* |
3496 | * Get a template for hardware connection maintenance | 3682 | * Get a template for hardware connection maintenance |
3497 | */ | 3683 | */ |
3498 | dev_kfree_skb(wl->probereq); | 3684 | dev_kfree_skb(wlvif->probereq); |
3499 | wl->probereq = wl1271_cmd_build_ap_probe_req(wl, NULL); | 3685 | wlvif->probereq = wl1271_cmd_build_ap_probe_req(wl, |
3686 | wlvif, | ||
3687 | NULL); | ||
3500 | ieoffset = offsetof(struct ieee80211_mgmt, | 3688 | ieoffset = offsetof(struct ieee80211_mgmt, |
3501 | u.probe_req.variable); | 3689 | u.probe_req.variable); |
3502 | wl1271_ssid_set(wl, wl->probereq, ieoffset); | 3690 | wl1271_ssid_set(vif, wlvif->probereq, ieoffset); |
3503 | 3691 | ||
3504 | /* enable the connection monitoring feature */ | 3692 | /* enable the connection monitoring feature */ |
3505 | ret = wl1271_acx_conn_monit_params(wl, true); | 3693 | ret = wl1271_acx_conn_monit_params(wl, wlvif, true); |
3506 | if (ret < 0) | 3694 | if (ret < 0) |
3507 | goto out; | 3695 | goto out; |
3508 | } else { | 3696 | } else { |
3509 | /* use defaults when not associated */ | 3697 | /* use defaults when not associated */ |
3510 | bool was_assoc = | 3698 | bool was_assoc = |
3511 | !!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED, | 3699 | !!test_and_clear_bit(WLVIF_FLAG_STA_ASSOCIATED, |
3512 | &wl->flags); | 3700 | &wlvif->flags); |
3513 | bool was_ifup = | 3701 | bool was_ifup = |
3514 | !!test_and_clear_bit(WL1271_FLAG_STA_STATE_SENT, | 3702 | !!test_and_clear_bit(WLVIF_FLAG_STA_STATE_SENT, |
3515 | &wl->flags); | 3703 | &wlvif->flags); |
3516 | wl->aid = 0; | 3704 | wlvif->aid = 0; |
3517 | 3705 | ||
3518 | /* free probe-request template */ | 3706 | /* free probe-request template */ |
3519 | dev_kfree_skb(wl->probereq); | 3707 | dev_kfree_skb(wlvif->probereq); |
3520 | wl->probereq = NULL; | 3708 | wlvif->probereq = NULL; |
3521 | 3709 | ||
3522 | /* re-enable dynamic ps - just in case */ | 3710 | /* re-enable dynamic ps - just in case */ |
3523 | ieee80211_enable_dyn_ps(wl->vif); | 3711 | ieee80211_enable_dyn_ps(vif); |
3524 | 3712 | ||
3525 | /* revert back to minimum rates for the current band */ | 3713 | /* revert back to minimum rates for the current band */ |
3526 | wl1271_set_band_rate(wl); | 3714 | wl1271_set_band_rate(wl, wlvif); |
3527 | wl->basic_rate = | 3715 | wlvif->basic_rate = |
3528 | wl1271_tx_min_rate_get(wl, wl->basic_rate_set); | 3716 | wl1271_tx_min_rate_get(wl, |
3529 | ret = wl1271_acx_sta_rate_policies(wl); | 3717 | wlvif->basic_rate_set); |
3718 | ret = wl1271_acx_sta_rate_policies(wl, wlvif); | ||
3530 | if (ret < 0) | 3719 | if (ret < 0) |
3531 | goto out; | 3720 | goto out; |
3532 | 3721 | ||
3533 | /* disable connection monitor features */ | 3722 | /* disable connection monitor features */ |
3534 | ret = wl1271_acx_conn_monit_params(wl, false); | 3723 | ret = wl1271_acx_conn_monit_params(wl, wlvif, false); |
3535 | 3724 | ||
3536 | /* Disable the keep-alive feature */ | 3725 | /* Disable the keep-alive feature */ |
3537 | ret = wl1271_acx_keep_alive_mode(wl, false); | 3726 | ret = wl1271_acx_keep_alive_mode(wl, wlvif, false); |
3538 | if (ret < 0) | 3727 | if (ret < 0) |
3539 | goto out; | 3728 | goto out; |
3540 | 3729 | ||
@@ -3546,7 +3735,7 @@ sta_not_found: | |||
3546 | * no IF_OPER_UP notification. | 3735 | * no IF_OPER_UP notification. |
3547 | */ | 3736 | */ |
3548 | if (!was_ifup) { | 3737 | if (!was_ifup) { |
3549 | ret = wl12xx_croc(wl, wl->role_id); | 3738 | ret = wl12xx_croc(wl, wlvif->role_id); |
3550 | if (ret < 0) | 3739 | if (ret < 0) |
3551 | goto out; | 3740 | goto out; |
3552 | } | 3741 | } |
@@ -3555,17 +3744,16 @@ sta_not_found: | |||
3555 | * roaming on the same channel. until we will | 3744 | * roaming on the same channel. until we will |
3556 | * have a better flow...) | 3745 | * have a better flow...) |
3557 | */ | 3746 | */ |
3558 | if (test_bit(wl->dev_role_id, wl->roc_map)) { | 3747 | if (test_bit(wlvif->dev_role_id, wl->roc_map)) { |
3559 | ret = wl12xx_croc(wl, wl->dev_role_id); | 3748 | ret = wl12xx_croc(wl, |
3749 | wlvif->dev_role_id); | ||
3560 | if (ret < 0) | 3750 | if (ret < 0) |
3561 | goto out; | 3751 | goto out; |
3562 | } | 3752 | } |
3563 | 3753 | ||
3564 | wl1271_unjoin(wl); | 3754 | wl1271_unjoin(wl, wlvif); |
3565 | if (!(conf_flags & IEEE80211_CONF_IDLE)) { | 3755 | if (!(conf_flags & IEEE80211_CONF_IDLE)) |
3566 | wl12xx_cmd_role_start_dev(wl); | 3756 | wl12xx_start_dev(wl, wlvif); |
3567 | wl12xx_roc(wl, wl->dev_role_id); | ||
3568 | } | ||
3569 | } | 3757 | } |
3570 | } | 3758 | } |
3571 | } | 3759 | } |
@@ -3576,27 +3764,28 @@ sta_not_found: | |||
3576 | 3764 | ||
3577 | if (bss_conf->ibss_joined) { | 3765 | if (bss_conf->ibss_joined) { |
3578 | u32 rates = bss_conf->basic_rates; | 3766 | u32 rates = bss_conf->basic_rates; |
3579 | wl->basic_rate_set = | 3767 | wlvif->basic_rate_set = |
3580 | wl1271_tx_enabled_rates_get(wl, rates, | 3768 | wl1271_tx_enabled_rates_get(wl, rates, |
3581 | wl->band); | 3769 | wlvif->band); |
3582 | wl->basic_rate = | 3770 | wlvif->basic_rate = |
3583 | wl1271_tx_min_rate_get(wl, wl->basic_rate_set); | 3771 | wl1271_tx_min_rate_get(wl, |
3772 | wlvif->basic_rate_set); | ||
3584 | 3773 | ||
3585 | /* by default, use 11b + OFDM rates */ | 3774 | /* by default, use 11b + OFDM rates */ |
3586 | wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; | 3775 | wlvif->rate_set = CONF_TX_IBSS_DEFAULT_RATES; |
3587 | ret = wl1271_acx_sta_rate_policies(wl); | 3776 | ret = wl1271_acx_sta_rate_policies(wl, wlvif); |
3588 | if (ret < 0) | 3777 | if (ret < 0) |
3589 | goto out; | 3778 | goto out; |
3590 | } | 3779 | } |
3591 | } | 3780 | } |
3592 | 3781 | ||
3593 | ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); | 3782 | ret = wl1271_bss_erp_info_changed(wl, vif, bss_conf, changed); |
3594 | if (ret < 0) | 3783 | if (ret < 0) |
3595 | goto out; | 3784 | goto out; |
3596 | 3785 | ||
3597 | if (changed & BSS_CHANGED_ARP_FILTER) { | 3786 | if (changed & BSS_CHANGED_ARP_FILTER) { |
3598 | __be32 addr = bss_conf->arp_addr_list[0]; | 3787 | __be32 addr = bss_conf->arp_addr_list[0]; |
3599 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); | 3788 | WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS); |
3600 | 3789 | ||
3601 | if (bss_conf->arp_addr_cnt == 1 && | 3790 | if (bss_conf->arp_addr_cnt == 1 && |
3602 | bss_conf->arp_filter_enabled) { | 3791 | bss_conf->arp_filter_enabled) { |
@@ -3606,24 +3795,24 @@ sta_not_found: | |||
3606 | * isn't being set (when sending), so we have to | 3795 | * isn't being set (when sending), so we have to |
3607 | * reconfigure the template upon every ip change. | 3796 | * reconfigure the template upon every ip change. |
3608 | */ | 3797 | */ |
3609 | ret = wl1271_cmd_build_arp_rsp(wl, addr); | 3798 | ret = wl1271_cmd_build_arp_rsp(wl, wlvif, addr); |
3610 | if (ret < 0) { | 3799 | if (ret < 0) { |
3611 | wl1271_warning("build arp rsp failed: %d", ret); | 3800 | wl1271_warning("build arp rsp failed: %d", ret); |
3612 | goto out; | 3801 | goto out; |
3613 | } | 3802 | } |
3614 | 3803 | ||
3615 | ret = wl1271_acx_arp_ip_filter(wl, | 3804 | ret = wl1271_acx_arp_ip_filter(wl, wlvif, |
3616 | ACX_ARP_FILTER_ARP_FILTERING, | 3805 | ACX_ARP_FILTER_ARP_FILTERING, |
3617 | addr); | 3806 | addr); |
3618 | } else | 3807 | } else |
3619 | ret = wl1271_acx_arp_ip_filter(wl, 0, addr); | 3808 | ret = wl1271_acx_arp_ip_filter(wl, wlvif, 0, addr); |
3620 | 3809 | ||
3621 | if (ret < 0) | 3810 | if (ret < 0) |
3622 | goto out; | 3811 | goto out; |
3623 | } | 3812 | } |
3624 | 3813 | ||
3625 | if (do_join) { | 3814 | if (do_join) { |
3626 | ret = wl1271_join(wl, set_assoc); | 3815 | ret = wl1271_join(wl, wlvif, set_assoc); |
3627 | if (ret < 0) { | 3816 | if (ret < 0) { |
3628 | wl1271_warning("cmd join failed %d", ret); | 3817 | wl1271_warning("cmd join failed %d", ret); |
3629 | goto out; | 3818 | goto out; |
@@ -3631,35 +3820,31 @@ sta_not_found: | |||
3631 | 3820 | ||
3632 | /* ROC until connected (after EAPOL exchange) */ | 3821 | /* ROC until connected (after EAPOL exchange) */ |
3633 | if (!is_ibss) { | 3822 | if (!is_ibss) { |
3634 | ret = wl12xx_roc(wl, wl->role_id); | 3823 | ret = wl12xx_roc(wl, wlvif, wlvif->role_id); |
3635 | if (ret < 0) | 3824 | if (ret < 0) |
3636 | goto out; | 3825 | goto out; |
3637 | 3826 | ||
3638 | wl1271_check_operstate(wl, | 3827 | wl1271_check_operstate(wl, wlvif, |
3639 | ieee80211_get_operstate(vif)); | 3828 | ieee80211_get_operstate(vif)); |
3640 | } | 3829 | } |
3641 | /* | 3830 | /* |
3642 | * stop device role if started (we might already be in | 3831 | * stop device role if started (we might already be in |
3643 | * STA role). TODO: make it better. | 3832 | * STA role). TODO: make it better. |
3644 | */ | 3833 | */ |
3645 | if (wl->dev_role_id != WL12XX_INVALID_ROLE_ID) { | 3834 | if (wlvif->dev_role_id != WL12XX_INVALID_ROLE_ID) { |
3646 | ret = wl12xx_croc(wl, wl->dev_role_id); | 3835 | ret = wl12xx_stop_dev(wl, wlvif); |
3647 | if (ret < 0) | ||
3648 | goto out; | ||
3649 | |||
3650 | ret = wl12xx_cmd_role_stop_dev(wl); | ||
3651 | if (ret < 0) | 3836 | if (ret < 0) |
3652 | goto out; | 3837 | goto out; |
3653 | } | 3838 | } |
3654 | 3839 | ||
3655 | /* If we want to go in PSM but we're not there yet */ | 3840 | /* If we want to go in PSM but we're not there yet */ |
3656 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && | 3841 | if (test_bit(WLVIF_FLAG_PSM_REQUESTED, &wlvif->flags) && |
3657 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { | 3842 | !test_bit(WLVIF_FLAG_PSM, &wlvif->flags)) { |
3658 | enum wl1271_cmd_ps_mode mode; | 3843 | enum wl1271_cmd_ps_mode mode; |
3659 | 3844 | ||
3660 | mode = STATION_POWER_SAVE_MODE; | 3845 | mode = STATION_POWER_SAVE_MODE; |
3661 | ret = wl1271_ps_set_mode(wl, mode, | 3846 | ret = wl1271_ps_set_mode(wl, wlvif, mode, |
3662 | wl->basic_rate, | 3847 | wlvif->basic_rate, |
3663 | true); | 3848 | true); |
3664 | if (ret < 0) | 3849 | if (ret < 0) |
3665 | goto out; | 3850 | goto out; |
@@ -3673,7 +3858,7 @@ sta_not_found: | |||
3673 | ret = wl1271_acx_set_ht_capabilities(wl, | 3858 | ret = wl1271_acx_set_ht_capabilities(wl, |
3674 | &sta_ht_cap, | 3859 | &sta_ht_cap, |
3675 | true, | 3860 | true, |
3676 | wl->sta_hlid); | 3861 | wlvif->sta.hlid); |
3677 | if (ret < 0) { | 3862 | if (ret < 0) { |
3678 | wl1271_warning("Set ht cap true failed %d", | 3863 | wl1271_warning("Set ht cap true failed %d", |
3679 | ret); | 3864 | ret); |
@@ -3685,7 +3870,7 @@ sta_not_found: | |||
3685 | ret = wl1271_acx_set_ht_capabilities(wl, | 3870 | ret = wl1271_acx_set_ht_capabilities(wl, |
3686 | &sta_ht_cap, | 3871 | &sta_ht_cap, |
3687 | false, | 3872 | false, |
3688 | wl->sta_hlid); | 3873 | wlvif->sta.hlid); |
3689 | if (ret < 0) { | 3874 | if (ret < 0) { |
3690 | wl1271_warning("Set ht cap false failed %d", | 3875 | wl1271_warning("Set ht cap false failed %d", |
3691 | ret); | 3876 | ret); |
@@ -3697,7 +3882,7 @@ sta_not_found: | |||
3697 | /* Handle HT information change. Done after join. */ | 3882 | /* Handle HT information change. Done after join. */ |
3698 | if ((changed & BSS_CHANGED_HT) && | 3883 | if ((changed & BSS_CHANGED_HT) && |
3699 | (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { | 3884 | (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { |
3700 | ret = wl1271_acx_set_ht_information(wl, | 3885 | ret = wl1271_acx_set_ht_information(wl, wlvif, |
3701 | bss_conf->ht_operation_mode); | 3886 | bss_conf->ht_operation_mode); |
3702 | if (ret < 0) { | 3887 | if (ret < 0) { |
3703 | wl1271_warning("Set ht information failed %d", ret); | 3888 | wl1271_warning("Set ht information failed %d", ret); |
@@ -3715,7 +3900,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
3715 | u32 changed) | 3900 | u32 changed) |
3716 | { | 3901 | { |
3717 | struct wl1271 *wl = hw->priv; | 3902 | struct wl1271 *wl = hw->priv; |
3718 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | 3903 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
3904 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); | ||
3719 | int ret; | 3905 | int ret; |
3720 | 3906 | ||
3721 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x", | 3907 | wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x", |
@@ -3726,6 +3912,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
3726 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 3912 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
3727 | goto out; | 3913 | goto out; |
3728 | 3914 | ||
3915 | if (unlikely(!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags))) | ||
3916 | goto out; | ||
3917 | |||
3729 | ret = wl1271_ps_elp_wakeup(wl); | 3918 | ret = wl1271_ps_elp_wakeup(wl); |
3730 | if (ret < 0) | 3919 | if (ret < 0) |
3731 | goto out; | 3920 | goto out; |
@@ -3746,6 +3935,7 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, | |||
3746 | const struct ieee80211_tx_queue_params *params) | 3935 | const struct ieee80211_tx_queue_params *params) |
3747 | { | 3936 | { |
3748 | struct wl1271 *wl = hw->priv; | 3937 | struct wl1271 *wl = hw->priv; |
3938 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
3749 | u8 ps_scheme; | 3939 | u8 ps_scheme; |
3750 | int ret = 0; | 3940 | int ret = 0; |
3751 | 3941 | ||
@@ -3792,13 +3982,13 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, | |||
3792 | * the txop is confed in units of 32us by the mac80211, | 3982 | * the txop is confed in units of 32us by the mac80211, |
3793 | * we need us | 3983 | * we need us |
3794 | */ | 3984 | */ |
3795 | ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue), | 3985 | ret = wl1271_acx_ac_cfg(wl, wlvif, wl1271_tx_get_queue(queue), |
3796 | params->cw_min, params->cw_max, | 3986 | params->cw_min, params->cw_max, |
3797 | params->aifs, params->txop << 5); | 3987 | params->aifs, params->txop << 5); |
3798 | if (ret < 0) | 3988 | if (ret < 0) |
3799 | goto out_sleep; | 3989 | goto out_sleep; |
3800 | 3990 | ||
3801 | ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue), | 3991 | ret = wl1271_acx_tid_cfg(wl, wlvif, wl1271_tx_get_queue(queue), |
3802 | CONF_CHANNEL_TYPE_EDCF, | 3992 | CONF_CHANNEL_TYPE_EDCF, |
3803 | wl1271_tx_get_queue(queue), | 3993 | wl1271_tx_get_queue(queue), |
3804 | ps_scheme, CONF_ACK_POLICY_LEGACY, | 3994 | ps_scheme, CONF_ACK_POLICY_LEGACY, |
@@ -3861,43 +4051,43 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx, | |||
3861 | } | 4051 | } |
3862 | 4052 | ||
3863 | static int wl1271_allocate_sta(struct wl1271 *wl, | 4053 | static int wl1271_allocate_sta(struct wl1271 *wl, |
3864 | struct ieee80211_sta *sta, | 4054 | struct wl12xx_vif *wlvif, |
3865 | u8 *hlid) | 4055 | struct ieee80211_sta *sta) |
3866 | { | 4056 | { |
3867 | struct wl1271_station *wl_sta; | 4057 | struct wl1271_station *wl_sta; |
3868 | int id; | 4058 | int ret; |
4059 | |||
3869 | 4060 | ||
3870 | id = find_first_zero_bit(wl->ap_hlid_map, AP_MAX_STATIONS); | 4061 | if (wl->active_sta_count >= AP_MAX_STATIONS) { |
3871 | if (id >= AP_MAX_STATIONS) { | ||
3872 | wl1271_warning("could not allocate HLID - too much stations"); | 4062 | wl1271_warning("could not allocate HLID - too much stations"); |
3873 | return -EBUSY; | 4063 | return -EBUSY; |
3874 | } | 4064 | } |
3875 | 4065 | ||
3876 | wl_sta = (struct wl1271_station *)sta->drv_priv; | 4066 | wl_sta = (struct wl1271_station *)sta->drv_priv; |
3877 | set_bit(id, wl->ap_hlid_map); | 4067 | ret = wl12xx_allocate_link(wl, wlvif, &wl_sta->hlid); |
3878 | wl_sta->hlid = WL1271_AP_STA_HLID_START + id; | 4068 | if (ret < 0) { |
3879 | *hlid = wl_sta->hlid; | 4069 | wl1271_warning("could not allocate HLID - too many links"); |
4070 | return -EBUSY; | ||
4071 | } | ||
4072 | |||
4073 | set_bit(wl_sta->hlid, wlvif->ap.sta_hlid_map); | ||
3880 | memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); | 4074 | memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); |
3881 | wl->active_sta_count++; | 4075 | wl->active_sta_count++; |
3882 | return 0; | 4076 | return 0; |
3883 | } | 4077 | } |
3884 | 4078 | ||
3885 | void wl1271_free_sta(struct wl1271 *wl, u8 hlid) | 4079 | void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid) |
3886 | { | 4080 | { |
3887 | int id = hlid - WL1271_AP_STA_HLID_START; | 4081 | if (!test_bit(hlid, wlvif->ap.sta_hlid_map)) |
3888 | |||
3889 | if (hlid < WL1271_AP_STA_HLID_START) | ||
3890 | return; | 4082 | return; |
3891 | 4083 | ||
3892 | if (!test_bit(id, wl->ap_hlid_map)) | 4084 | clear_bit(hlid, wlvif->ap.sta_hlid_map); |
3893 | return; | ||
3894 | |||
3895 | clear_bit(id, wl->ap_hlid_map); | ||
3896 | memset(wl->links[hlid].addr, 0, ETH_ALEN); | 4085 | memset(wl->links[hlid].addr, 0, ETH_ALEN); |
3897 | wl->links[hlid].ba_bitmap = 0; | 4086 | wl->links[hlid].ba_bitmap = 0; |
3898 | wl1271_tx_reset_link_queues(wl, hlid); | 4087 | wl1271_tx_reset_link_queues(wl, hlid); |
3899 | __clear_bit(hlid, &wl->ap_ps_map); | 4088 | __clear_bit(hlid, &wl->ap_ps_map); |
3900 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 4089 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
4090 | wl12xx_free_link(wl, wlvif, &hlid); | ||
3901 | wl->active_sta_count--; | 4091 | wl->active_sta_count--; |
3902 | } | 4092 | } |
3903 | 4093 | ||
@@ -3906,6 +4096,8 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, | |||
3906 | struct ieee80211_sta *sta) | 4096 | struct ieee80211_sta *sta) |
3907 | { | 4097 | { |
3908 | struct wl1271 *wl = hw->priv; | 4098 | struct wl1271 *wl = hw->priv; |
4099 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
4100 | struct wl1271_station *wl_sta; | ||
3909 | int ret = 0; | 4101 | int ret = 0; |
3910 | u8 hlid; | 4102 | u8 hlid; |
3911 | 4103 | ||
@@ -3914,20 +4106,23 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw, | |||
3914 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 4106 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
3915 | goto out; | 4107 | goto out; |
3916 | 4108 | ||
3917 | if (wl->bss_type != BSS_TYPE_AP_BSS) | 4109 | if (wlvif->bss_type != BSS_TYPE_AP_BSS) |
3918 | goto out; | 4110 | goto out; |
3919 | 4111 | ||
3920 | wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid); | 4112 | wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid); |
3921 | 4113 | ||
3922 | ret = wl1271_allocate_sta(wl, sta, &hlid); | 4114 | ret = wl1271_allocate_sta(wl, wlvif, sta); |
3923 | if (ret < 0) | 4115 | if (ret < 0) |
3924 | goto out; | 4116 | goto out; |
3925 | 4117 | ||
4118 | wl_sta = (struct wl1271_station *)sta->drv_priv; | ||
4119 | hlid = wl_sta->hlid; | ||
4120 | |||
3926 | ret = wl1271_ps_elp_wakeup(wl); | 4121 | ret = wl1271_ps_elp_wakeup(wl); |
3927 | if (ret < 0) | 4122 | if (ret < 0) |
3928 | goto out_free_sta; | 4123 | goto out_free_sta; |
3929 | 4124 | ||
3930 | ret = wl12xx_cmd_add_peer(wl, sta, hlid); | 4125 | ret = wl12xx_cmd_add_peer(wl, wlvif, sta, hlid); |
3931 | if (ret < 0) | 4126 | if (ret < 0) |
3932 | goto out_sleep; | 4127 | goto out_sleep; |
3933 | 4128 | ||
@@ -3944,7 +4139,7 @@ out_sleep: | |||
3944 | 4139 | ||
3945 | out_free_sta: | 4140 | out_free_sta: |
3946 | if (ret < 0) | 4141 | if (ret < 0) |
3947 | wl1271_free_sta(wl, hlid); | 4142 | wl1271_free_sta(wl, wlvif, hlid); |
3948 | 4143 | ||
3949 | out: | 4144 | out: |
3950 | mutex_unlock(&wl->mutex); | 4145 | mutex_unlock(&wl->mutex); |
@@ -3956,6 +4151,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw, | |||
3956 | struct ieee80211_sta *sta) | 4151 | struct ieee80211_sta *sta) |
3957 | { | 4152 | { |
3958 | struct wl1271 *wl = hw->priv; | 4153 | struct wl1271 *wl = hw->priv; |
4154 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
3959 | struct wl1271_station *wl_sta; | 4155 | struct wl1271_station *wl_sta; |
3960 | int ret = 0, id; | 4156 | int ret = 0, id; |
3961 | 4157 | ||
@@ -3964,14 +4160,14 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw, | |||
3964 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 4160 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
3965 | goto out; | 4161 | goto out; |
3966 | 4162 | ||
3967 | if (wl->bss_type != BSS_TYPE_AP_BSS) | 4163 | if (wlvif->bss_type != BSS_TYPE_AP_BSS) |
3968 | goto out; | 4164 | goto out; |
3969 | 4165 | ||
3970 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid); | 4166 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid); |
3971 | 4167 | ||
3972 | wl_sta = (struct wl1271_station *)sta->drv_priv; | 4168 | wl_sta = (struct wl1271_station *)sta->drv_priv; |
3973 | id = wl_sta->hlid - WL1271_AP_STA_HLID_START; | 4169 | id = wl_sta->hlid; |
3974 | if (WARN_ON(!test_bit(id, wl->ap_hlid_map))) | 4170 | if (WARN_ON(!test_bit(id, wlvif->ap.sta_hlid_map))) |
3975 | goto out; | 4171 | goto out; |
3976 | 4172 | ||
3977 | ret = wl1271_ps_elp_wakeup(wl); | 4173 | ret = wl1271_ps_elp_wakeup(wl); |
@@ -3982,7 +4178,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw, | |||
3982 | if (ret < 0) | 4178 | if (ret < 0) |
3983 | goto out_sleep; | 4179 | goto out_sleep; |
3984 | 4180 | ||
3985 | wl1271_free_sta(wl, wl_sta->hlid); | 4181 | wl1271_free_sta(wl, wlvif, wl_sta->hlid); |
3986 | 4182 | ||
3987 | out_sleep: | 4183 | out_sleep: |
3988 | wl1271_ps_elp_sleep(wl); | 4184 | wl1271_ps_elp_sleep(wl); |
@@ -3999,6 +4195,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, | |||
3999 | u8 buf_size) | 4195 | u8 buf_size) |
4000 | { | 4196 | { |
4001 | struct wl1271 *wl = hw->priv; | 4197 | struct wl1271 *wl = hw->priv; |
4198 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
4002 | int ret; | 4199 | int ret; |
4003 | u8 hlid, *ba_bitmap; | 4200 | u8 hlid, *ba_bitmap; |
4004 | 4201 | ||
@@ -4016,10 +4213,10 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, | |||
4016 | goto out; | 4213 | goto out; |
4017 | } | 4214 | } |
4018 | 4215 | ||
4019 | if (wl->bss_type == BSS_TYPE_STA_BSS) { | 4216 | if (wlvif->bss_type == BSS_TYPE_STA_BSS) { |
4020 | hlid = wl->sta_hlid; | 4217 | hlid = wlvif->sta.hlid; |
4021 | ba_bitmap = &wl->ba_rx_bitmap; | 4218 | ba_bitmap = &wlvif->sta.ba_rx_bitmap; |
4022 | } else if (wl->bss_type == BSS_TYPE_AP_BSS) { | 4219 | } else if (wlvif->bss_type == BSS_TYPE_AP_BSS) { |
4023 | struct wl1271_station *wl_sta; | 4220 | struct wl1271_station *wl_sta; |
4024 | 4221 | ||
4025 | wl_sta = (struct wl1271_station *)sta->drv_priv; | 4222 | wl_sta = (struct wl1271_station *)sta->drv_priv; |
@@ -4039,7 +4236,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, | |||
4039 | 4236 | ||
4040 | switch (action) { | 4237 | switch (action) { |
4041 | case IEEE80211_AMPDU_RX_START: | 4238 | case IEEE80211_AMPDU_RX_START: |
4042 | if (!wl->ba_support || !wl->ba_allowed) { | 4239 | if (!wlvif->ba_support || !wlvif->ba_allowed) { |
4043 | ret = -ENOTSUPP; | 4240 | ret = -ENOTSUPP; |
4044 | break; | 4241 | break; |
4045 | } | 4242 | } |
@@ -4108,8 +4305,9 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw, | |||
4108 | struct ieee80211_vif *vif, | 4305 | struct ieee80211_vif *vif, |
4109 | const struct cfg80211_bitrate_mask *mask) | 4306 | const struct cfg80211_bitrate_mask *mask) |
4110 | { | 4307 | { |
4308 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | ||
4111 | struct wl1271 *wl = hw->priv; | 4309 | struct wl1271 *wl = hw->priv; |
4112 | int i; | 4310 | int i, ret = 0; |
4113 | 4311 | ||
4114 | wl1271_debug(DEBUG_MAC80211, "mac80211 set_bitrate_mask 0x%x 0x%x", | 4312 | wl1271_debug(DEBUG_MAC80211, "mac80211 set_bitrate_mask 0x%x 0x%x", |
4115 | mask->control[NL80211_BAND_2GHZ].legacy, | 4313 | mask->control[NL80211_BAND_2GHZ].legacy, |
@@ -4118,19 +4316,39 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw, | |||
4118 | mutex_lock(&wl->mutex); | 4316 | mutex_lock(&wl->mutex); |
4119 | 4317 | ||
4120 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | 4318 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) |
4121 | wl->bitrate_masks[i] = | 4319 | wlvif->bitrate_masks[i] = |
4122 | wl1271_tx_enabled_rates_get(wl, | 4320 | wl1271_tx_enabled_rates_get(wl, |
4123 | mask->control[i].legacy, | 4321 | mask->control[i].legacy, |
4124 | i); | 4322 | i); |
4323 | |||
4324 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
4325 | goto out; | ||
4326 | |||
4327 | if (wlvif->bss_type == BSS_TYPE_STA_BSS && | ||
4328 | !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { | ||
4329 | |||
4330 | ret = wl1271_ps_elp_wakeup(wl); | ||
4331 | if (ret < 0) | ||
4332 | goto out; | ||
4333 | |||
4334 | wl1271_set_band_rate(wl, wlvif); | ||
4335 | wlvif->basic_rate = | ||
4336 | wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); | ||
4337 | ret = wl1271_acx_sta_rate_policies(wl, wlvif); | ||
4338 | |||
4339 | wl1271_ps_elp_sleep(wl); | ||
4340 | } | ||
4341 | out: | ||
4125 | mutex_unlock(&wl->mutex); | 4342 | mutex_unlock(&wl->mutex); |
4126 | 4343 | ||
4127 | return 0; | 4344 | return ret; |
4128 | } | 4345 | } |
4129 | 4346 | ||
4130 | static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, | 4347 | static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, |
4131 | struct ieee80211_channel_switch *ch_switch) | 4348 | struct ieee80211_channel_switch *ch_switch) |
4132 | { | 4349 | { |
4133 | struct wl1271 *wl = hw->priv; | 4350 | struct wl1271 *wl = hw->priv; |
4351 | struct wl12xx_vif *wlvif; | ||
4134 | int ret; | 4352 | int ret; |
4135 | 4353 | ||
4136 | wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch"); | 4354 | wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch"); |
@@ -4138,19 +4356,24 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, | |||
4138 | mutex_lock(&wl->mutex); | 4356 | mutex_lock(&wl->mutex); |
4139 | 4357 | ||
4140 | if (unlikely(wl->state == WL1271_STATE_OFF)) { | 4358 | if (unlikely(wl->state == WL1271_STATE_OFF)) { |
4141 | mutex_unlock(&wl->mutex); | 4359 | wl12xx_for_each_wlvif_sta(wl, wlvif) { |
4142 | ieee80211_chswitch_done(wl->vif, false); | 4360 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); |
4143 | return; | 4361 | ieee80211_chswitch_done(vif, false); |
4362 | } | ||
4363 | goto out; | ||
4144 | } | 4364 | } |
4145 | 4365 | ||
4146 | ret = wl1271_ps_elp_wakeup(wl); | 4366 | ret = wl1271_ps_elp_wakeup(wl); |
4147 | if (ret < 0) | 4367 | if (ret < 0) |
4148 | goto out; | 4368 | goto out; |
4149 | 4369 | ||
4150 | ret = wl12xx_cmd_channel_switch(wl, ch_switch); | 4370 | /* TODO: change mac80211 to pass vif as param */ |
4371 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
4372 | ret = wl12xx_cmd_channel_switch(wl, ch_switch); | ||
4151 | 4373 | ||
4152 | if (!ret) | 4374 | if (!ret) |
4153 | set_bit(WL1271_FLAG_CS_PROGRESS, &wl->flags); | 4375 | set_bit(WLVIF_FLAG_CS_PROGRESS, &wlvif->flags); |
4376 | } | ||
4154 | 4377 | ||
4155 | wl1271_ps_elp_sleep(wl); | 4378 | wl1271_ps_elp_sleep(wl); |
4156 | 4379 | ||
@@ -4170,10 +4393,6 @@ static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) | |||
4170 | 4393 | ||
4171 | /* packets are considered pending if in the TX queue or the FW */ | 4394 | /* packets are considered pending if in the TX queue or the FW */ |
4172 | ret = (wl1271_tx_total_queue_count(wl) > 0) || (wl->tx_frames_cnt > 0); | 4395 | ret = (wl1271_tx_total_queue_count(wl) > 0) || (wl->tx_frames_cnt > 0); |
4173 | |||
4174 | /* the above is appropriate for STA mode for PS purposes */ | ||
4175 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); | ||
4176 | |||
4177 | out: | 4396 | out: |
4178 | mutex_unlock(&wl->mutex); | 4397 | mutex_unlock(&wl->mutex); |
4179 | 4398 | ||
@@ -4604,7 +4823,7 @@ static struct bin_attribute fwlog_attr = { | |||
4604 | .read = wl1271_sysfs_read_fwlog, | 4823 | .read = wl1271_sysfs_read_fwlog, |
4605 | }; | 4824 | }; |
4606 | 4825 | ||
4607 | int wl1271_register_hw(struct wl1271 *wl) | 4826 | static int wl1271_register_hw(struct wl1271 *wl) |
4608 | { | 4827 | { |
4609 | int ret; | 4828 | int ret; |
4610 | 4829 | ||
@@ -4645,9 +4864,8 @@ int wl1271_register_hw(struct wl1271 *wl) | |||
4645 | 4864 | ||
4646 | return 0; | 4865 | return 0; |
4647 | } | 4866 | } |
4648 | EXPORT_SYMBOL_GPL(wl1271_register_hw); | ||
4649 | 4867 | ||
4650 | void wl1271_unregister_hw(struct wl1271 *wl) | 4868 | static void wl1271_unregister_hw(struct wl1271 *wl) |
4651 | { | 4869 | { |
4652 | if (wl->state == WL1271_STATE_PLT) | 4870 | if (wl->state == WL1271_STATE_PLT) |
4653 | __wl1271_plt_stop(wl); | 4871 | __wl1271_plt_stop(wl); |
@@ -4657,9 +4875,8 @@ void wl1271_unregister_hw(struct wl1271 *wl) | |||
4657 | wl->mac80211_registered = false; | 4875 | wl->mac80211_registered = false; |
4658 | 4876 | ||
4659 | } | 4877 | } |
4660 | EXPORT_SYMBOL_GPL(wl1271_unregister_hw); | ||
4661 | 4878 | ||
4662 | int wl1271_init_ieee80211(struct wl1271 *wl) | 4879 | static int wl1271_init_ieee80211(struct wl1271 *wl) |
4663 | { | 4880 | { |
4664 | static const u32 cipher_suites[] = { | 4881 | static const u32 cipher_suites[] = { |
4665 | WLAN_CIPHER_SUITE_WEP40, | 4882 | WLAN_CIPHER_SUITE_WEP40, |
@@ -4736,27 +4953,33 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
4736 | 4953 | ||
4737 | wl->hw->wiphy->reg_notifier = wl1271_reg_notify; | 4954 | wl->hw->wiphy->reg_notifier = wl1271_reg_notify; |
4738 | 4955 | ||
4739 | SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl)); | 4956 | /* the FW answers probe-requests in AP-mode */ |
4957 | wl->hw->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | ||
4958 | wl->hw->wiphy->probe_resp_offload = | ||
4959 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | ||
4960 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | ||
4961 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; | ||
4962 | |||
4963 | SET_IEEE80211_DEV(wl->hw, wl->dev); | ||
4740 | 4964 | ||
4741 | wl->hw->sta_data_size = sizeof(struct wl1271_station); | 4965 | wl->hw->sta_data_size = sizeof(struct wl1271_station); |
4966 | wl->hw->vif_data_size = sizeof(struct wl12xx_vif); | ||
4742 | 4967 | ||
4743 | wl->hw->max_rx_aggregation_subframes = 8; | 4968 | wl->hw->max_rx_aggregation_subframes = 8; |
4744 | 4969 | ||
4745 | return 0; | 4970 | return 0; |
4746 | } | 4971 | } |
4747 | EXPORT_SYMBOL_GPL(wl1271_init_ieee80211); | ||
4748 | 4972 | ||
4749 | #define WL1271_DEFAULT_CHANNEL 0 | 4973 | #define WL1271_DEFAULT_CHANNEL 0 |
4750 | 4974 | ||
4751 | struct ieee80211_hw *wl1271_alloc_hw(void) | 4975 | static struct ieee80211_hw *wl1271_alloc_hw(void) |
4752 | { | 4976 | { |
4753 | struct ieee80211_hw *hw; | 4977 | struct ieee80211_hw *hw; |
4754 | struct platform_device *plat_dev = NULL; | ||
4755 | struct wl1271 *wl; | 4978 | struct wl1271 *wl; |
4756 | int i, j, ret; | 4979 | int i, j, ret; |
4757 | unsigned int order; | 4980 | unsigned int order; |
4758 | 4981 | ||
4759 | BUILD_BUG_ON(AP_MAX_LINKS > WL12XX_MAX_LINKS); | 4982 | BUILD_BUG_ON(AP_MAX_STATIONS > WL12XX_MAX_LINKS); |
4760 | 4983 | ||
4761 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); | 4984 | hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); |
4762 | if (!hw) { | 4985 | if (!hw) { |
@@ -4765,41 +4988,26 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
4765 | goto err_hw_alloc; | 4988 | goto err_hw_alloc; |
4766 | } | 4989 | } |
4767 | 4990 | ||
4768 | plat_dev = kmemdup(&wl1271_device, sizeof(wl1271_device), GFP_KERNEL); | ||
4769 | if (!plat_dev) { | ||
4770 | wl1271_error("could not allocate platform_device"); | ||
4771 | ret = -ENOMEM; | ||
4772 | goto err_plat_alloc; | ||
4773 | } | ||
4774 | |||
4775 | wl = hw->priv; | 4991 | wl = hw->priv; |
4776 | memset(wl, 0, sizeof(*wl)); | 4992 | memset(wl, 0, sizeof(*wl)); |
4777 | 4993 | ||
4778 | INIT_LIST_HEAD(&wl->list); | 4994 | INIT_LIST_HEAD(&wl->list); |
4995 | INIT_LIST_HEAD(&wl->wlvif_list); | ||
4779 | 4996 | ||
4780 | wl->hw = hw; | 4997 | wl->hw = hw; |
4781 | wl->plat_dev = plat_dev; | ||
4782 | |||
4783 | for (i = 0; i < NUM_TX_QUEUES; i++) | ||
4784 | skb_queue_head_init(&wl->tx_queue[i]); | ||
4785 | 4998 | ||
4786 | for (i = 0; i < NUM_TX_QUEUES; i++) | 4999 | for (i = 0; i < NUM_TX_QUEUES; i++) |
4787 | for (j = 0; j < AP_MAX_LINKS; j++) | 5000 | for (j = 0; j < WL12XX_MAX_LINKS; j++) |
4788 | skb_queue_head_init(&wl->links[j].tx_queue[i]); | 5001 | skb_queue_head_init(&wl->links[j].tx_queue[i]); |
4789 | 5002 | ||
4790 | skb_queue_head_init(&wl->deferred_rx_queue); | 5003 | skb_queue_head_init(&wl->deferred_rx_queue); |
4791 | skb_queue_head_init(&wl->deferred_tx_queue); | 5004 | skb_queue_head_init(&wl->deferred_tx_queue); |
4792 | 5005 | ||
4793 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 5006 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
4794 | INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); | ||
4795 | INIT_WORK(&wl->netstack_work, wl1271_netstack_work); | 5007 | INIT_WORK(&wl->netstack_work, wl1271_netstack_work); |
4796 | INIT_WORK(&wl->tx_work, wl1271_tx_work); | 5008 | INIT_WORK(&wl->tx_work, wl1271_tx_work); |
4797 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); | 5009 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); |
4798 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); | 5010 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); |
4799 | INIT_WORK(&wl->rx_streaming_enable_work, | ||
4800 | wl1271_rx_streaming_enable_work); | ||
4801 | INIT_WORK(&wl->rx_streaming_disable_work, | ||
4802 | wl1271_rx_streaming_disable_work); | ||
4803 | 5011 | ||
4804 | wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); | 5012 | wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); |
4805 | if (!wl->freezable_wq) { | 5013 | if (!wl->freezable_wq) { |
@@ -4808,41 +5016,21 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
4808 | } | 5016 | } |
4809 | 5017 | ||
4810 | wl->channel = WL1271_DEFAULT_CHANNEL; | 5018 | wl->channel = WL1271_DEFAULT_CHANNEL; |
4811 | wl->beacon_int = WL1271_DEFAULT_BEACON_INT; | ||
4812 | wl->default_key = 0; | ||
4813 | wl->rx_counter = 0; | 5019 | wl->rx_counter = 0; |
4814 | wl->psm_entry_retry = 0; | ||
4815 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 5020 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
4816 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; | ||
4817 | wl->basic_rate = CONF_TX_RATE_MASK_BASIC; | ||
4818 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | ||
4819 | wl->band = IEEE80211_BAND_2GHZ; | 5021 | wl->band = IEEE80211_BAND_2GHZ; |
4820 | wl->vif = NULL; | 5022 | wl->vif = NULL; |
4821 | wl->flags = 0; | 5023 | wl->flags = 0; |
4822 | wl->sg_enabled = true; | 5024 | wl->sg_enabled = true; |
4823 | wl->hw_pg_ver = -1; | 5025 | wl->hw_pg_ver = -1; |
4824 | wl->bss_type = MAX_BSS_TYPE; | ||
4825 | wl->set_bss_type = MAX_BSS_TYPE; | ||
4826 | wl->last_tx_hlid = 0; | ||
4827 | wl->ap_ps_map = 0; | 5026 | wl->ap_ps_map = 0; |
4828 | wl->ap_fw_ps_map = 0; | 5027 | wl->ap_fw_ps_map = 0; |
4829 | wl->quirks = 0; | 5028 | wl->quirks = 0; |
4830 | wl->platform_quirks = 0; | 5029 | wl->platform_quirks = 0; |
4831 | wl->sched_scanning = false; | 5030 | wl->sched_scanning = false; |
4832 | wl->tx_security_seq = 0; | ||
4833 | wl->tx_security_last_seq_lsb = 0; | ||
4834 | wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; | 5031 | wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; |
4835 | wl->role_id = WL12XX_INVALID_ROLE_ID; | ||
4836 | wl->system_hlid = WL12XX_SYSTEM_HLID; | 5032 | wl->system_hlid = WL12XX_SYSTEM_HLID; |
4837 | wl->sta_hlid = WL12XX_INVALID_LINK_ID; | ||
4838 | wl->dev_role_id = WL12XX_INVALID_ROLE_ID; | ||
4839 | wl->dev_hlid = WL12XX_INVALID_LINK_ID; | ||
4840 | wl->session_counter = 0; | ||
4841 | wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID; | ||
4842 | wl->ap_global_hlid = WL12XX_INVALID_LINK_ID; | ||
4843 | wl->active_sta_count = 0; | 5033 | wl->active_sta_count = 0; |
4844 | setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer, | ||
4845 | (unsigned long) wl); | ||
4846 | wl->fwlog_size = 0; | 5034 | wl->fwlog_size = 0; |
4847 | init_waitqueue_head(&wl->fwlog_waitq); | 5035 | init_waitqueue_head(&wl->fwlog_waitq); |
4848 | 5036 | ||
@@ -4860,8 +5048,6 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
4860 | 5048 | ||
4861 | /* Apply default driver configuration. */ | 5049 | /* Apply default driver configuration. */ |
4862 | wl1271_conf_init(wl); | 5050 | wl1271_conf_init(wl); |
4863 | wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate; | ||
4864 | wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5; | ||
4865 | 5051 | ||
4866 | order = get_order(WL1271_AGGR_BUFFER_SIZE); | 5052 | order = get_order(WL1271_AGGR_BUFFER_SIZE); |
4867 | wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); | 5053 | wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); |
@@ -4883,49 +5069,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
4883 | goto err_dummy_packet; | 5069 | goto err_dummy_packet; |
4884 | } | 5070 | } |
4885 | 5071 | ||
4886 | /* Register platform device */ | ||
4887 | ret = platform_device_register(wl->plat_dev); | ||
4888 | if (ret) { | ||
4889 | wl1271_error("couldn't register platform device"); | ||
4890 | goto err_fwlog; | ||
4891 | } | ||
4892 | dev_set_drvdata(&wl->plat_dev->dev, wl); | ||
4893 | |||
4894 | /* Create sysfs file to control bt coex state */ | ||
4895 | ret = device_create_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); | ||
4896 | if (ret < 0) { | ||
4897 | wl1271_error("failed to create sysfs file bt_coex_state"); | ||
4898 | goto err_platform; | ||
4899 | } | ||
4900 | |||
4901 | /* Create sysfs file to get HW PG version */ | ||
4902 | ret = device_create_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); | ||
4903 | if (ret < 0) { | ||
4904 | wl1271_error("failed to create sysfs file hw_pg_ver"); | ||
4905 | goto err_bt_coex_state; | ||
4906 | } | ||
4907 | |||
4908 | /* Create sysfs file for the FW log */ | ||
4909 | ret = device_create_bin_file(&wl->plat_dev->dev, &fwlog_attr); | ||
4910 | if (ret < 0) { | ||
4911 | wl1271_error("failed to create sysfs file fwlog"); | ||
4912 | goto err_hw_pg_ver; | ||
4913 | } | ||
4914 | |||
4915 | return hw; | 5072 | return hw; |
4916 | 5073 | ||
4917 | err_hw_pg_ver: | ||
4918 | device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); | ||
4919 | |||
4920 | err_bt_coex_state: | ||
4921 | device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); | ||
4922 | |||
4923 | err_platform: | ||
4924 | platform_device_unregister(wl->plat_dev); | ||
4925 | |||
4926 | err_fwlog: | ||
4927 | free_page((unsigned long)wl->fwlog); | ||
4928 | |||
4929 | err_dummy_packet: | 5074 | err_dummy_packet: |
4930 | dev_kfree_skb(wl->dummy_packet); | 5075 | dev_kfree_skb(wl->dummy_packet); |
4931 | 5076 | ||
@@ -4937,18 +5082,14 @@ err_wq: | |||
4937 | 5082 | ||
4938 | err_hw: | 5083 | err_hw: |
4939 | wl1271_debugfs_exit(wl); | 5084 | wl1271_debugfs_exit(wl); |
4940 | kfree(plat_dev); | ||
4941 | |||
4942 | err_plat_alloc: | ||
4943 | ieee80211_free_hw(hw); | 5085 | ieee80211_free_hw(hw); |
4944 | 5086 | ||
4945 | err_hw_alloc: | 5087 | err_hw_alloc: |
4946 | 5088 | ||
4947 | return ERR_PTR(ret); | 5089 | return ERR_PTR(ret); |
4948 | } | 5090 | } |
4949 | EXPORT_SYMBOL_GPL(wl1271_alloc_hw); | ||
4950 | 5091 | ||
4951 | int wl1271_free_hw(struct wl1271 *wl) | 5092 | static int wl1271_free_hw(struct wl1271 *wl) |
4952 | { | 5093 | { |
4953 | /* Unblock any fwlog readers */ | 5094 | /* Unblock any fwlog readers */ |
4954 | mutex_lock(&wl->mutex); | 5095 | mutex_lock(&wl->mutex); |
@@ -4956,17 +5097,15 @@ int wl1271_free_hw(struct wl1271 *wl) | |||
4956 | wake_up_interruptible_all(&wl->fwlog_waitq); | 5097 | wake_up_interruptible_all(&wl->fwlog_waitq); |
4957 | mutex_unlock(&wl->mutex); | 5098 | mutex_unlock(&wl->mutex); |
4958 | 5099 | ||
4959 | device_remove_bin_file(&wl->plat_dev->dev, &fwlog_attr); | 5100 | device_remove_bin_file(wl->dev, &fwlog_attr); |
4960 | 5101 | ||
4961 | device_remove_file(&wl->plat_dev->dev, &dev_attr_hw_pg_ver); | 5102 | device_remove_file(wl->dev, &dev_attr_hw_pg_ver); |
4962 | 5103 | ||
4963 | device_remove_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state); | 5104 | device_remove_file(wl->dev, &dev_attr_bt_coex_state); |
4964 | platform_device_unregister(wl->plat_dev); | ||
4965 | free_page((unsigned long)wl->fwlog); | 5105 | free_page((unsigned long)wl->fwlog); |
4966 | dev_kfree_skb(wl->dummy_packet); | 5106 | dev_kfree_skb(wl->dummy_packet); |
4967 | free_pages((unsigned long)wl->aggr_buf, | 5107 | free_pages((unsigned long)wl->aggr_buf, |
4968 | get_order(WL1271_AGGR_BUFFER_SIZE)); | 5108 | get_order(WL1271_AGGR_BUFFER_SIZE)); |
4969 | kfree(wl->plat_dev); | ||
4970 | 5109 | ||
4971 | wl1271_debugfs_exit(wl); | 5110 | wl1271_debugfs_exit(wl); |
4972 | 5111 | ||
@@ -4983,7 +5122,174 @@ int wl1271_free_hw(struct wl1271 *wl) | |||
4983 | 5122 | ||
4984 | return 0; | 5123 | return 0; |
4985 | } | 5124 | } |
4986 | EXPORT_SYMBOL_GPL(wl1271_free_hw); | 5125 | |
5126 | static irqreturn_t wl12xx_hardirq(int irq, void *cookie) | ||
5127 | { | ||
5128 | struct wl1271 *wl = cookie; | ||
5129 | unsigned long flags; | ||
5130 | |||
5131 | wl1271_debug(DEBUG_IRQ, "IRQ"); | ||
5132 | |||
5133 | /* complete the ELP completion */ | ||
5134 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
5135 | set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); | ||
5136 | if (wl->elp_compl) { | ||
5137 | complete(wl->elp_compl); | ||
5138 | wl->elp_compl = NULL; | ||
5139 | } | ||
5140 | |||
5141 | if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) { | ||
5142 | /* don't enqueue a work right now. mark it as pending */ | ||
5143 | set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags); | ||
5144 | wl1271_debug(DEBUG_IRQ, "should not enqueue work"); | ||
5145 | disable_irq_nosync(wl->irq); | ||
5146 | pm_wakeup_event(wl->dev, 0); | ||
5147 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
5148 | return IRQ_HANDLED; | ||
5149 | } | ||
5150 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
5151 | |||
5152 | return IRQ_WAKE_THREAD; | ||
5153 | } | ||
5154 | |||
5155 | static int __devinit wl12xx_probe(struct platform_device *pdev) | ||
5156 | { | ||
5157 | struct wl12xx_platform_data *pdata = pdev->dev.platform_data; | ||
5158 | struct ieee80211_hw *hw; | ||
5159 | struct wl1271 *wl; | ||
5160 | unsigned long irqflags; | ||
5161 | int ret = -ENODEV; | ||
5162 | |||
5163 | hw = wl1271_alloc_hw(); | ||
5164 | if (IS_ERR(hw)) { | ||
5165 | wl1271_error("can't allocate hw"); | ||
5166 | ret = PTR_ERR(hw); | ||
5167 | goto out; | ||
5168 | } | ||
5169 | |||
5170 | wl = hw->priv; | ||
5171 | wl->irq = platform_get_irq(pdev, 0); | ||
5172 | wl->ref_clock = pdata->board_ref_clock; | ||
5173 | wl->tcxo_clock = pdata->board_tcxo_clock; | ||
5174 | wl->platform_quirks = pdata->platform_quirks; | ||
5175 | wl->set_power = pdata->set_power; | ||
5176 | wl->dev = &pdev->dev; | ||
5177 | wl->if_ops = pdata->ops; | ||
5178 | |||
5179 | platform_set_drvdata(pdev, wl); | ||
5180 | |||
5181 | if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) | ||
5182 | irqflags = IRQF_TRIGGER_RISING; | ||
5183 | else | ||
5184 | irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; | ||
5185 | |||
5186 | ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wl1271_irq, | ||
5187 | irqflags, | ||
5188 | pdev->name, wl); | ||
5189 | if (ret < 0) { | ||
5190 | wl1271_error("request_irq() failed: %d", ret); | ||
5191 | goto out_free_hw; | ||
5192 | } | ||
5193 | |||
5194 | ret = enable_irq_wake(wl->irq); | ||
5195 | if (!ret) { | ||
5196 | wl->irq_wake_enabled = true; | ||
5197 | device_init_wakeup(wl->dev, 1); | ||
5198 | if (pdata->pwr_in_suspend) | ||
5199 | hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; | ||
5200 | |||
5201 | } | ||
5202 | disable_irq(wl->irq); | ||
5203 | |||
5204 | ret = wl1271_init_ieee80211(wl); | ||
5205 | if (ret) | ||
5206 | goto out_irq; | ||
5207 | |||
5208 | ret = wl1271_register_hw(wl); | ||
5209 | if (ret) | ||
5210 | goto out_irq; | ||
5211 | |||
5212 | /* Create sysfs file to control bt coex state */ | ||
5213 | ret = device_create_file(wl->dev, &dev_attr_bt_coex_state); | ||
5214 | if (ret < 0) { | ||
5215 | wl1271_error("failed to create sysfs file bt_coex_state"); | ||
5216 | goto out_irq; | ||
5217 | } | ||
5218 | |||
5219 | /* Create sysfs file to get HW PG version */ | ||
5220 | ret = device_create_file(wl->dev, &dev_attr_hw_pg_ver); | ||
5221 | if (ret < 0) { | ||
5222 | wl1271_error("failed to create sysfs file hw_pg_ver"); | ||
5223 | goto out_bt_coex_state; | ||
5224 | } | ||
5225 | |||
5226 | /* Create sysfs file for the FW log */ | ||
5227 | ret = device_create_bin_file(wl->dev, &fwlog_attr); | ||
5228 | if (ret < 0) { | ||
5229 | wl1271_error("failed to create sysfs file fwlog"); | ||
5230 | goto out_hw_pg_ver; | ||
5231 | } | ||
5232 | |||
5233 | return 0; | ||
5234 | |||
5235 | out_hw_pg_ver: | ||
5236 | device_remove_file(wl->dev, &dev_attr_hw_pg_ver); | ||
5237 | |||
5238 | out_bt_coex_state: | ||
5239 | device_remove_file(wl->dev, &dev_attr_bt_coex_state); | ||
5240 | |||
5241 | out_irq: | ||
5242 | free_irq(wl->irq, wl); | ||
5243 | |||
5244 | out_free_hw: | ||
5245 | wl1271_free_hw(wl); | ||
5246 | |||
5247 | out: | ||
5248 | return ret; | ||
5249 | } | ||
5250 | |||
5251 | static int __devexit wl12xx_remove(struct platform_device *pdev) | ||
5252 | { | ||
5253 | struct wl1271 *wl = platform_get_drvdata(pdev); | ||
5254 | |||
5255 | if (wl->irq_wake_enabled) { | ||
5256 | device_init_wakeup(wl->dev, 0); | ||
5257 | disable_irq_wake(wl->irq); | ||
5258 | } | ||
5259 | wl1271_unregister_hw(wl); | ||
5260 | free_irq(wl->irq, wl); | ||
5261 | wl1271_free_hw(wl); | ||
5262 | |||
5263 | return 0; | ||
5264 | } | ||
5265 | |||
5266 | static const struct platform_device_id wl12xx_id_table[] __devinitconst = { | ||
5267 | { "wl12xx", 0 }, | ||
5268 | { } /* Terminating Entry */ | ||
5269 | }; | ||
5270 | MODULE_DEVICE_TABLE(platform, wl12xx_id_table); | ||
5271 | |||
5272 | static struct platform_driver wl12xx_driver = { | ||
5273 | .probe = wl12xx_probe, | ||
5274 | .remove = __devexit_p(wl12xx_remove), | ||
5275 | .id_table = wl12xx_id_table, | ||
5276 | .driver = { | ||
5277 | .name = "wl12xx_driver", | ||
5278 | .owner = THIS_MODULE, | ||
5279 | } | ||
5280 | }; | ||
5281 | |||
5282 | static int __init wl12xx_init(void) | ||
5283 | { | ||
5284 | return platform_driver_register(&wl12xx_driver); | ||
5285 | } | ||
5286 | module_init(wl12xx_init); | ||
5287 | |||
5288 | static void __exit wl12xx_exit(void) | ||
5289 | { | ||
5290 | platform_driver_unregister(&wl12xx_driver); | ||
5291 | } | ||
5292 | module_exit(wl12xx_exit); | ||
4987 | 5293 | ||
4988 | u32 wl12xx_debug_level = DEBUG_NONE; | 5294 | u32 wl12xx_debug_level = DEBUG_NONE; |
4989 | EXPORT_SYMBOL_GPL(wl12xx_debug_level); | 5295 | EXPORT_SYMBOL_GPL(wl12xx_debug_level); |