aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorEliad Peller <eliad@wizery.com>2011-10-05 05:56:05 -0400
committerLuciano Coelho <coelho@ti.com>2011-10-07 01:33:46 -0400
commitc7ffb902cca655e4d6bdda4156407008573bb214 (patch)
treed5dc1af5d2fd29a59d45fe6dcde61c58c3aa9503 /drivers
parentd0802abdf9c60b1dadb097e806022f3449b0cc6b (diff)
wl12xx: move ap_hlid_map into wlvif.ap
Add wlvif->links_map bitmap to represent all the links allocated for this vif. AP vif also has a sta_hlid_map bitmap, which represents the links stations connected to it (sta_hlid_bitmap is a subset of wlvif->links_map, which itself is a subset of the global wl->links_map) Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: Luciano Coelho <coelho@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/wl12xx/cmd.c34
-rw-r--r--drivers/net/wireless/wl12xx/cmd.h3
-rw-r--r--drivers/net/wireless/wl12xx/debugfs.c1
-rw-r--r--drivers/net/wireless/wl12xx/event.c15
-rw-r--r--drivers/net/wireless/wl12xx/event.h3
-rw-r--r--drivers/net/wireless/wl12xx/main.c92
-rw-r--r--drivers/net/wireless/wl12xx/tx.c35
-rw-r--r--drivers/net/wireless/wl12xx/tx.h2
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h24
9 files changed, 92 insertions, 117 deletions
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 68375ffb4123..102a8a5371e4 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -434,23 +434,25 @@ out:
434 return ret; 434 return ret;
435} 435}
436 436
437static int wl12xx_allocate_link(struct wl1271 *wl, u8 *hlid) 437int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
438{ 438{
439 u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS); 439 u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS);
440 if (link >= WL12XX_MAX_LINKS) 440 if (link >= WL12XX_MAX_LINKS)
441 return -EBUSY; 441 return -EBUSY;
442 442
443 __set_bit(link, wl->links_map); 443 __set_bit(link, wl->links_map);
444 __set_bit(link, wlvif->links_map);
444 *hlid = link; 445 *hlid = link;
445 return 0; 446 return 0;
446} 447}
447 448
448static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid) 449void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid)
449{ 450{
450 if (*hlid == WL12XX_INVALID_LINK_ID) 451 if (*hlid == WL12XX_INVALID_LINK_ID)
451 return; 452 return;
452 453
453 __clear_bit(*hlid, wl->links_map); 454 __clear_bit(*hlid, wl->links_map);
455 __clear_bit(*hlid, wlvif->links_map);
454 *hlid = WL12XX_INVALID_LINK_ID; 456 *hlid = WL12XX_INVALID_LINK_ID;
455} 457}
456 458
@@ -484,7 +486,7 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
484 cmd->channel = wl->channel; 486 cmd->channel = wl->channel;
485 487
486 if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) { 488 if (wlvif->dev_hlid == WL12XX_INVALID_LINK_ID) {
487 ret = wl12xx_allocate_link(wl, &wlvif->dev_hlid); 489 ret = wl12xx_allocate_link(wl, wlvif, &wlvif->dev_hlid);
488 if (ret) 490 if (ret)
489 goto out_free; 491 goto out_free;
490 } 492 }
@@ -504,7 +506,7 @@ int wl12xx_cmd_role_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
504 506
505err_hlid: 507err_hlid:
506 /* clear links on error */ 508 /* clear links on error */
507 wl12xx_free_link(wl, &wlvif->dev_hlid); 509 wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid);
508 510
509out_free: 511out_free:
510 kfree(cmd); 512 kfree(cmd);
@@ -545,7 +547,7 @@ int wl12xx_cmd_role_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif)
545 goto out_free; 547 goto out_free;
546 } 548 }
547 549
548 wl12xx_free_link(wl, &wlvif->dev_hlid); 550 wl12xx_free_link(wl, wlvif, &wlvif->dev_hlid);
549 551
550out_free: 552out_free:
551 kfree(cmd); 553 kfree(cmd);
@@ -581,7 +583,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
581 cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); 583 cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set);
582 584
583 if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { 585 if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) {
584 ret = wl12xx_allocate_link(wl, &wlvif->sta.hlid); 586 ret = wl12xx_allocate_link(wl, wlvif, &wlvif->sta.hlid);
585 if (ret) 587 if (ret)
586 goto out_free; 588 goto out_free;
587 } 589 }
@@ -604,7 +606,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
604 606
605err_hlid: 607err_hlid:
606 /* clear links on error. */ 608 /* clear links on error. */
607 wl12xx_free_link(wl, &wlvif->sta.hlid); 609 wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid);
608 610
609out_free: 611out_free:
610 kfree(cmd); 612 kfree(cmd);
@@ -640,7 +642,7 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
640 goto out_free; 642 goto out_free;
641 } 643 }
642 644
643 wl12xx_free_link(wl, &wlvif->sta.hlid); 645 wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid);
644 646
645out_free: 647out_free:
646 kfree(cmd); 648 kfree(cmd);
@@ -670,11 +672,11 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
670 goto out; 672 goto out;
671 } 673 }
672 674
673 ret = wl12xx_allocate_link(wl, &wlvif->ap.global_hlid); 675 ret = wl12xx_allocate_link(wl, wlvif, &wlvif->ap.global_hlid);
674 if (ret < 0) 676 if (ret < 0)
675 goto out_free; 677 goto out_free;
676 678
677 ret = wl12xx_allocate_link(wl, &wlvif->ap.bcast_hlid); 679 ret = wl12xx_allocate_link(wl, wlvif, &wlvif->ap.bcast_hlid);
678 if (ret < 0) 680 if (ret < 0)
679 goto out_free_global; 681 goto out_free_global;
680 682
@@ -724,10 +726,10 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
724 goto out_free; 726 goto out_free;
725 727
726out_free_bcast: 728out_free_bcast:
727 wl12xx_free_link(wl, &wlvif->ap.bcast_hlid); 729 wl12xx_free_link(wl, wlvif, &wlvif->ap.bcast_hlid);
728 730
729out_free_global: 731out_free_global:
730 wl12xx_free_link(wl, &wlvif->ap.global_hlid); 732 wl12xx_free_link(wl, wlvif, &wlvif->ap.global_hlid);
731 733
732out_free: 734out_free:
733 kfree(cmd); 735 kfree(cmd);
@@ -757,8 +759,8 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)
757 goto out_free; 759 goto out_free;
758 } 760 }
759 761
760 wl12xx_free_link(wl, &wlvif->ap.bcast_hlid); 762 wl12xx_free_link(wl, wlvif, &wlvif->ap.bcast_hlid);
761 wl12xx_free_link(wl, &wlvif->ap.global_hlid); 763 wl12xx_free_link(wl, wlvif, &wlvif->ap.global_hlid);
762 764
763out_free: 765out_free:
764 kfree(cmd); 766 kfree(cmd);
@@ -796,7 +798,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif)
796 cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set); 798 cmd->sta.local_rates = cpu_to_le32(wlvif->rate_set);
797 799
798 if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) { 800 if (wlvif->sta.hlid == WL12XX_INVALID_LINK_ID) {
799 ret = wl12xx_allocate_link(wl, &wlvif->sta.hlid); 801 ret = wl12xx_allocate_link(wl, wlvif, &wlvif->sta.hlid);
800 if (ret) 802 if (ret)
801 goto out_free; 803 goto out_free;
802 } 804 }
@@ -821,7 +823,7 @@ int wl12xx_cmd_role_start_ibss(struct wl1271 *wl, struct wl12xx_vif *wlvif)
821 823
822err_hlid: 824err_hlid:
823 /* clear links on error. */ 825 /* clear links on error. */
824 wl12xx_free_link(wl, &wlvif->sta.hlid); 826 wl12xx_free_link(wl, wlvif, &wlvif->sta.hlid);
825 827
826out_free: 828out_free:
827 kfree(cmd); 829 kfree(cmd);
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 9624828b76e8..d2670d379b75 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -89,6 +89,9 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
89int wl12xx_cmd_channel_switch(struct wl1271 *wl, 89int wl12xx_cmd_channel_switch(struct wl1271 *wl,
90 struct ieee80211_channel_switch *ch_switch); 90 struct ieee80211_channel_switch *ch_switch);
91int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl); 91int wl12xx_cmd_stop_channel_switch(struct wl1271 *wl);
92int wl12xx_allocate_link(struct wl1271 *wl, struct wl12xx_vif *wlvif,
93 u8 *hlid);
94void wl12xx_free_link(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 *hlid);
92 95
93enum wl1271_commands { 96enum wl1271_commands {
94 CMD_INTERROGATE = 1, /*use this to read information elements*/ 97 CMD_INTERROGATE = 1, /*use this to read information elements*/
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index ee42a43d6a66..f0398d037d4d 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -355,7 +355,6 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
355 DRIVER_STATE_PRINT_INT(sg_enabled); 355 DRIVER_STATE_PRINT_INT(sg_enabled);
356 DRIVER_STATE_PRINT_INT(enable_11a); 356 DRIVER_STATE_PRINT_INT(enable_11a);
357 DRIVER_STATE_PRINT_INT(noise); 357 DRIVER_STATE_PRINT_INT(noise);
358 DRIVER_STATE_PRINT_LHEX(ap_hlid_map[0]);
359 DRIVER_STATE_PRINT_INT(last_tx_hlid); 358 DRIVER_STATE_PRINT_INT(last_tx_hlid);
360 DRIVER_STATE_PRINT_HEX(ap_fw_ps_map); 359 DRIVER_STATE_PRINT_HEX(ap_fw_ps_map);
361 DRIVER_STATE_PRINT_LHEX(ap_ps_map); 360 DRIVER_STATE_PRINT_LHEX(ap_ps_map);
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index 8c31274228ea..486c8ee0101a 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -189,11 +189,12 @@ static void wl1271_stop_ba_event(struct wl1271 *wl, struct wl12xx_vif *wlvif)
189 ieee80211_stop_rx_ba_session(wl->vif, wlvif->sta.ba_rx_bitmap, 189 ieee80211_stop_rx_ba_session(wl->vif, wlvif->sta.ba_rx_bitmap,
190 wl->vif->bss_conf.bssid); 190 wl->vif->bss_conf.bssid);
191 } else { 191 } else {
192 int i; 192 u8 hlid;
193 struct wl1271_link *lnk; 193 struct wl1271_link *lnk;
194 for (i = WL1271_AP_STA_HLID_START; i < AP_MAX_LINKS; i++) { 194 for_each_set_bit(hlid, wlvif->ap.sta_hlid_map,
195 lnk = &wl->links[i]; 195 WL12XX_MAX_LINKS) {
196 if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap) 196 lnk = &wl->links[hlid];
197 if (!lnk->ba_bitmap)
197 continue; 198 continue;
198 199
199 ieee80211_stop_rx_ba_session(wl->vif, 200 ieee80211_stop_rx_ba_session(wl->vif,
@@ -355,10 +356,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
355 const u8 *addr; 356 const u8 *addr;
356 int h; 357 int h;
357 358
358 for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS); 359 for_each_set_bit(h, &sta_bitmap, WL12XX_MAX_LINKS) {
359 h < AP_MAX_LINKS; 360 if (!test_bit(h, wlvif->ap.sta_hlid_map))
360 h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) {
361 if (!wl1271_is_active_sta(wl, h))
362 continue; 361 continue;
363 362
364 addr = wl->links[h].addr; 363 addr = wl->links[h].addr;
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h
index 49c1a0ede5b1..1d878ba47bf4 100644
--- a/drivers/net/wireless/wl12xx/event.h
+++ b/drivers/net/wireless/wl12xx/event.h
@@ -132,7 +132,4 @@ void wl1271_event_mbox_config(struct wl1271 *wl);
132int wl1271_event_handle(struct wl1271 *wl, u8 mbox); 132int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
133void wl1271_pspoll_work(struct work_struct *work); 133void wl1271_pspoll_work(struct work_struct *work);
134 134
135/* Functions from main.c */
136bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid);
137
138#endif 135#endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 984dae881a8d..f712f0fb50be 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -778,10 +778,6 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
778{ 778{
779 bool fw_ps, single_sta; 779 bool fw_ps, single_sta;
780 780
781 /* only regulate station links */
782 if (hlid < WL1271_AP_STA_HLID_START)
783 return;
784
785 fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); 781 fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
786 single_sta = (wl->active_sta_count == 1); 782 single_sta = (wl->active_sta_count == 1);
787 783
@@ -801,21 +797,11 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
801 wl1271_ps_link_start(wl, hlid, true); 797 wl1271_ps_link_start(wl, hlid, true);
802} 798}
803 799
804bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
805{
806 int id;
807
808 /* global/broadcast "stations" are always active */
809 if (hlid < WL1271_AP_STA_HLID_START)
810 return true;
811
812 id = hlid - WL1271_AP_STA_HLID_START;
813 return test_bit(id, wl->ap_hlid_map);
814}
815
816static void wl12xx_irq_update_links_status(struct wl1271 *wl, 800static void wl12xx_irq_update_links_status(struct wl1271 *wl,
801 struct wl12xx_vif *wlvif,
817 struct wl12xx_fw_status *status) 802 struct wl12xx_fw_status *status)
818{ 803{
804 struct wl1271_link *lnk;
819 u32 cur_fw_ps_map; 805 u32 cur_fw_ps_map;
820 u8 hlid, cnt; 806 u8 hlid, cnt;
821 807
@@ -831,19 +817,14 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
831 wl->ap_fw_ps_map = cur_fw_ps_map; 817 wl->ap_fw_ps_map = cur_fw_ps_map;
832 } 818 }
833 819
834 for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) { 820 for_each_set_bit(hlid, wlvif->ap.sta_hlid_map, WL12XX_MAX_LINKS) {
835 if (!wl1271_is_active_sta(wl, hlid)) 821 lnk = &wl->links[hlid];
836 continue; 822 cnt = status->tx_lnk_free_pkts[hlid] - lnk->prev_freed_pkts;
837
838 cnt = status->tx_lnk_free_pkts[hlid] -
839 wl->links[hlid].prev_freed_pkts;
840 823
841 wl->links[hlid].prev_freed_pkts = 824 lnk->prev_freed_pkts = status->tx_lnk_free_pkts[hlid];
842 status->tx_lnk_free_pkts[hlid]; 825 lnk->allocated_pkts -= cnt;
843 wl->links[hlid].allocated_pkts -= cnt;
844 826
845 wl12xx_irq_ps_regulate_link(wl, hlid, 827 wl12xx_irq_ps_regulate_link(wl, hlid, lnk->allocated_pkts);
846 wl->links[hlid].allocated_pkts);
847 } 828 }
848} 829}
849 830
@@ -907,7 +888,7 @@ static void wl12xx_fw_status(struct wl1271 *wl,
907 888
908 /* for AP update num of allocated TX blocks per link and ps status */ 889 /* for AP update num of allocated TX blocks per link and ps status */
909 if (wlvif->bss_type == BSS_TYPE_AP_BSS) 890 if (wlvif->bss_type == BSS_TYPE_AP_BSS)
910 wl12xx_irq_update_links_status(wl, status); 891 wl12xx_irq_update_links_status(wl, wlvif, status);
911 892
912 /* update the host-chipset time offset */ 893 /* update the host-chipset time offset */
913 getnstimeofday(&ts); 894 getnstimeofday(&ts);
@@ -1505,7 +1486,7 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
1505 1486
1506 /* queue the packet */ 1487 /* queue the packet */
1507 if (wlvif->bss_type == BSS_TYPE_AP_BSS) { 1488 if (wlvif->bss_type == BSS_TYPE_AP_BSS) {
1508 if (!wl1271_is_active_sta(wl, hlid)) { 1489 if (!test_bit(hlid, wlvif->links_map)) {
1509 wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d", 1490 wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d",
1510 hlid, q); 1491 hlid, q);
1511 dev_kfree_skb(skb); 1492 dev_kfree_skb(skb);
@@ -2152,7 +2133,7 @@ deinit:
2152 wl->vif = NULL; 2133 wl->vif = NULL;
2153 wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; 2134 wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
2154 wl1271_free_ap_keys(wl); 2135 wl1271_free_ap_keys(wl);
2155 memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); 2136 memset(wlvif->ap.sta_hlid_map, 0, sizeof(wlvif->ap.sta_hlid_map));
2156 wl->ap_fw_ps_map = 0; 2137 wl->ap_fw_ps_map = 0;
2157 wl->ap_ps_map = 0; 2138 wl->ap_ps_map = 0;
2158 wl->sched_scanning = false; 2139 wl->sched_scanning = false;
@@ -3946,43 +3927,44 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx,
3946} 3927}
3947 3928
3948static int wl1271_allocate_sta(struct wl1271 *wl, 3929static int wl1271_allocate_sta(struct wl1271 *wl,
3949 struct ieee80211_sta *sta, 3930 struct wl12xx_vif *wlvif,
3950 u8 *hlid) 3931 struct ieee80211_sta *sta)
3951{ 3932{
3952 struct wl1271_station *wl_sta; 3933 struct wl1271_station *wl_sta;
3953 int id; 3934 int ret;
3954 3935
3955 id = find_first_zero_bit(wl->ap_hlid_map, AP_MAX_STATIONS); 3936
3956 if (id >= AP_MAX_STATIONS) { 3937 if (wl->active_sta_count >= AP_MAX_STATIONS) {
3957 wl1271_warning("could not allocate HLID - too much stations"); 3938 wl1271_warning("could not allocate HLID - too much stations");
3958 return -EBUSY; 3939 return -EBUSY;
3959 } 3940 }
3960 3941
3961 wl_sta = (struct wl1271_station *)sta->drv_priv; 3942 wl_sta = (struct wl1271_station *)sta->drv_priv;
3962 set_bit(id, wl->ap_hlid_map); 3943 ret = wl12xx_allocate_link(wl, wlvif, &wl_sta->hlid);
3963 wl_sta->hlid = WL1271_AP_STA_HLID_START + id; 3944 if (ret < 0) {
3964 *hlid = wl_sta->hlid; 3945 wl1271_warning("could not allocate HLID - too many links");
3946 return -EBUSY;
3947 }
3948
3949 set_bit(wl_sta->hlid, wlvif->ap.sta_hlid_map);
3965 memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN); 3950 memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN);
3966 wl->active_sta_count++; 3951 wl->active_sta_count++;
3967 return 0; 3952 return 0;
3968} 3953}
3969 3954
3970void wl1271_free_sta(struct wl1271 *wl, u8 hlid) 3955/* TODO: change wl1271_tx_reset(), so we can get sta as param */
3956void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid)
3971{ 3957{
3972 int id = hlid - WL1271_AP_STA_HLID_START; 3958 if (!test_bit(hlid, wlvif->ap.sta_hlid_map))
3973
3974 if (hlid < WL1271_AP_STA_HLID_START)
3975 return; 3959 return;
3976 3960
3977 if (!test_bit(id, wl->ap_hlid_map)) 3961 clear_bit(hlid, wlvif->ap.sta_hlid_map);
3978 return;
3979
3980 clear_bit(id, wl->ap_hlid_map);
3981 memset(wl->links[hlid].addr, 0, ETH_ALEN); 3962 memset(wl->links[hlid].addr, 0, ETH_ALEN);
3982 wl->links[hlid].ba_bitmap = 0; 3963 wl->links[hlid].ba_bitmap = 0;
3983 wl1271_tx_reset_link_queues(wl, hlid); 3964 wl1271_tx_reset_link_queues(wl, hlid);
3984 __clear_bit(hlid, &wl->ap_ps_map); 3965 __clear_bit(hlid, &wl->ap_ps_map);
3985 __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); 3966 __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
3967 wl12xx_free_link(wl, wlvif, &hlid);
3986 wl->active_sta_count--; 3968 wl->active_sta_count--;
3987} 3969}
3988 3970
@@ -3992,6 +3974,7 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
3992{ 3974{
3993 struct wl1271 *wl = hw->priv; 3975 struct wl1271 *wl = hw->priv;
3994 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); 3976 struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
3977 struct wl1271_station *wl_sta;
3995 int ret = 0; 3978 int ret = 0;
3996 u8 hlid; 3979 u8 hlid;
3997 3980
@@ -4005,10 +3988,13 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
4005 3988
4006 wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid); 3989 wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid);
4007 3990
4008 ret = wl1271_allocate_sta(wl, sta, &hlid); 3991 ret = wl1271_allocate_sta(wl, wlvif, sta);
4009 if (ret < 0) 3992 if (ret < 0)
4010 goto out; 3993 goto out;
4011 3994
3995 wl_sta = (struct wl1271_station *)sta->drv_priv;
3996 hlid = wl_sta->hlid;
3997
4012 ret = wl1271_ps_elp_wakeup(wl); 3998 ret = wl1271_ps_elp_wakeup(wl);
4013 if (ret < 0) 3999 if (ret < 0)
4014 goto out_free_sta; 4000 goto out_free_sta;
@@ -4030,7 +4016,7 @@ out_sleep:
4030 4016
4031out_free_sta: 4017out_free_sta:
4032 if (ret < 0) 4018 if (ret < 0)
4033 wl1271_free_sta(wl, hlid); 4019 wl1271_free_sta(wl, wlvif, hlid);
4034 4020
4035out: 4021out:
4036 mutex_unlock(&wl->mutex); 4022 mutex_unlock(&wl->mutex);
@@ -4057,8 +4043,8 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
4057 wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid); 4043 wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid);
4058 4044
4059 wl_sta = (struct wl1271_station *)sta->drv_priv; 4045 wl_sta = (struct wl1271_station *)sta->drv_priv;
4060 id = wl_sta->hlid - WL1271_AP_STA_HLID_START; 4046 id = wl_sta->hlid;
4061 if (WARN_ON(!test_bit(id, wl->ap_hlid_map))) 4047 if (WARN_ON(!test_bit(id, wlvif->ap.sta_hlid_map)))
4062 goto out; 4048 goto out;
4063 4049
4064 ret = wl1271_ps_elp_wakeup(wl); 4050 ret = wl1271_ps_elp_wakeup(wl);
@@ -4069,7 +4055,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
4069 if (ret < 0) 4055 if (ret < 0)
4070 goto out_sleep; 4056 goto out_sleep;
4071 4057
4072 wl1271_free_sta(wl, wl_sta->hlid); 4058 wl1271_free_sta(wl, wlvif, wl_sta->hlid);
4073 4059
4074out_sleep: 4060out_sleep:
4075 wl1271_ps_elp_sleep(wl); 4061 wl1271_ps_elp_sleep(wl);
@@ -4841,7 +4827,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
4841 int i, j, ret; 4827 int i, j, ret;
4842 unsigned int order; 4828 unsigned int order;
4843 4829
4844 BUILD_BUG_ON(AP_MAX_LINKS > WL12XX_MAX_LINKS); 4830 BUILD_BUG_ON(AP_MAX_STATIONS > WL12XX_MAX_LINKS);
4845 4831
4846 hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); 4832 hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
4847 if (!hw) { 4833 if (!hw) {
@@ -4869,7 +4855,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
4869 skb_queue_head_init(&wl->tx_queue[i]); 4855 skb_queue_head_init(&wl->tx_queue[i]);
4870 4856
4871 for (i = 0; i < NUM_TX_QUEUES; i++) 4857 for (i = 0; i < NUM_TX_QUEUES; i++)
4872 for (j = 0; j < AP_MAX_LINKS; j++) 4858 for (j = 0; j < WL12XX_MAX_LINKS; j++)
4873 skb_queue_head_init(&wl->links[j].tx_queue[i]); 4859 skb_queue_head_init(&wl->links[j].tx_queue[i]);
4874 4860
4875 skb_queue_head_init(&wl->deferred_rx_queue); 4861 skb_queue_head_init(&wl->deferred_rx_queue);
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 6ce61635f3bd..1b3d8e3f35a8 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -125,18 +125,16 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
125 wl1271_acx_set_inconnection_sta(wl, hdr->addr1); 125 wl1271_acx_set_inconnection_sta(wl, hdr->addr1);
126} 126}
127 127
128static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid) 128static void wl1271_tx_regulate_link(struct wl1271 *wl,
129 struct wl12xx_vif *wlvif,
130 u8 hlid)
129{ 131{
130 bool fw_ps, single_sta; 132 bool fw_ps, single_sta;
131 u8 tx_pkts; 133 u8 tx_pkts;
132 134
133 /* only regulate station links */ 135 if (WARN_ON(!test_bit(hlid, wlvif->links_map)))
134 if (hlid < WL1271_AP_STA_HLID_START)
135 return; 136 return;
136 137
137 if (WARN_ON(!wl1271_is_active_sta(wl, hlid)))
138 return;
139
140 fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); 138 fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
141 tx_pkts = wl->links[hlid].allocated_pkts; 139 tx_pkts = wl->links[hlid].allocated_pkts;
142 single_sta = (wl->active_sta_count == 1); 140 single_sta = (wl->active_sta_count == 1);
@@ -266,7 +264,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct ieee80211_vif *vif,
266 wl->tx_allocated_pkts[ac]++; 264 wl->tx_allocated_pkts[ac]++;
267 265
268 if (wlvif->bss_type == BSS_TYPE_AP_BSS && 266 if (wlvif->bss_type == BSS_TYPE_AP_BSS &&
269 hlid >= WL1271_AP_STA_HLID_START) 267 test_bit(hlid, wlvif->ap.sta_hlid_map))
270 wl->links[hlid].allocated_pkts++; 268 wl->links[hlid].allocated_pkts++;
271 269
272 ret = 0; 270 ret = 0;
@@ -445,7 +443,7 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
445 443
446 if (wlvif->bss_type == BSS_TYPE_AP_BSS && !is_dummy) { 444 if (wlvif->bss_type == BSS_TYPE_AP_BSS && !is_dummy) {
447 wl1271_tx_ap_update_inconnection_sta(wl, skb); 445 wl1271_tx_ap_update_inconnection_sta(wl, skb);
448 wl1271_tx_regulate_link(wl, hlid); 446 wl1271_tx_regulate_link(wl, wlvif, hlid);
449 } 447 }
450 448
451 /* 449 /*
@@ -563,7 +561,8 @@ out:
563 return skb; 561 return skb;
564} 562}
565 563
566static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl) 564static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl,
565 struct wl12xx_vif *wlvif)
567{ 566{
568 struct sk_buff *skb = NULL; 567 struct sk_buff *skb = NULL;
569 unsigned long flags; 568 unsigned long flags;
@@ -571,15 +570,14 @@ static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
571 struct sk_buff_head *queue; 570 struct sk_buff_head *queue;
572 571
573 /* start from the link after the last one */ 572 /* start from the link after the last one */
574 start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS; 573 start_hlid = (wl->last_tx_hlid + 1) % WL12XX_MAX_LINKS;
575 574
576 /* dequeue according to AC, round robin on each link */ 575 /* dequeue according to AC, round robin on each link */
577 for (i = 0; i < AP_MAX_LINKS; i++) { 576 for (i = 0; i < WL12XX_MAX_LINKS; i++) {
578 h = (start_hlid + i) % AP_MAX_LINKS; 577 h = (start_hlid + i) % WL12XX_MAX_LINKS;
579 578
580 /* only consider connected stations */ 579 /* only consider connected stations */
581 if (h >= WL1271_AP_STA_HLID_START && 580 if (!test_bit(h, wlvif->links_map))
582 !test_bit(h - WL1271_AP_STA_HLID_START, wl->ap_hlid_map))
583 continue; 581 continue;
584 582
585 queue = wl1271_select_queue(wl, wl->links[h].tx_queue); 583 queue = wl1271_select_queue(wl, wl->links[h].tx_queue);
@@ -611,7 +609,7 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl,
611 struct sk_buff *skb = NULL; 609 struct sk_buff *skb = NULL;
612 610
613 if (wlvif->bss_type == BSS_TYPE_AP_BSS) 611 if (wlvif->bss_type == BSS_TYPE_AP_BSS)
614 skb = wl1271_ap_skb_dequeue(wl); 612 skb = wl1271_ap_skb_dequeue(wl, wlvif);
615 else 613 else
616 skb = wl1271_sta_skb_dequeue(wl); 614 skb = wl1271_sta_skb_dequeue(wl);
617 615
@@ -643,7 +641,8 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct ieee80211_vif *vif,
643 skb_queue_head(&wl->links[hlid].tx_queue[q], skb); 641 skb_queue_head(&wl->links[hlid].tx_queue[q], skb);
644 642
645 /* make sure we dequeue the same packet next time */ 643 /* make sure we dequeue the same packet next time */
646 wl->last_tx_hlid = (hlid + AP_MAX_LINKS - 1) % AP_MAX_LINKS; 644 wl->last_tx_hlid = (hlid + WL12XX_MAX_LINKS - 1) %
645 WL12XX_MAX_LINKS;
647 } else { 646 } else {
648 skb_queue_head(&wl->tx_queue[q], skb); 647 skb_queue_head(&wl->tx_queue[q], skb);
649 } 648 }
@@ -918,8 +917,8 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
918 917
919 /* TX failure */ 918 /* TX failure */
920 if (wlvif->bss_type == BSS_TYPE_AP_BSS) { 919 if (wlvif->bss_type == BSS_TYPE_AP_BSS) {
921 for (i = 0; i < AP_MAX_LINKS; i++) { 920 for (i = 0; i < WL12XX_MAX_LINKS; i++) {
922 wl1271_free_sta(wl, i); 921 wl1271_free_sta(wl, wlvif, i);
923 wl1271_tx_reset_link_queues(wl, i); 922 wl1271_tx_reset_link_queues(wl, i);
924 wl->links[i].allocated_pkts = 0; 923 wl->links[i].allocated_pkts = 0;
925 wl->links[i].prev_freed_pkts = 0; 924 wl->links[i].prev_freed_pkts = 0;
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 0964c9335316..add4402d7931 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -219,6 +219,6 @@ void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
219bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb); 219bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb);
220 220
221/* from main.c */ 221/* from main.c */
222void wl1271_free_sta(struct wl1271 *wl, u8 hlid); 222void wl1271_free_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif, u8 hlid);
223 223
224#endif 224#endif
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index fcc779147c1c..5fd3c262bc5f 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -146,12 +146,6 @@ extern u32 wl12xx_debug_level;
146#define WL12XX_SYSTEM_HLID 0 146#define WL12XX_SYSTEM_HLID 0
147 147
148/* 148/*
149 * TODO: we currently don't support multirole. remove
150 * this constant from the code when we do.
151 */
152#define WL1271_AP_STA_HLID_START 3
153
154/*
155 * When in AP-mode, we allow (at least) this number of packets 149 * When in AP-mode, we allow (at least) this number of packets
156 * to be transmitted to FW for a STA in PS-mode. Only when packets are 150 * to be transmitted to FW for a STA in PS-mode. Only when packets are
157 * present in the FW buffers it will wake the sleeping STA. We want to put 151 * present in the FW buffers it will wake the sleeping STA. We want to put
@@ -236,13 +230,6 @@ struct wl1271_stats {
236 230
237#define AP_MAX_STATIONS 8 231#define AP_MAX_STATIONS 8
238 232
239/* Broadcast and Global links + system link + links to stations */
240/*
241 * TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all
242 * the places that use this.
243 */
244#define AP_MAX_LINKS (AP_MAX_STATIONS + WL1271_AP_STA_HLID_START)
245
246/* FW status registers */ 233/* FW status registers */
247struct wl12xx_fw_status { 234struct wl12xx_fw_status {
248 __le32 intr; 235 __le32 intr;
@@ -537,9 +524,6 @@ struct wl1271 {
537 /* Most recently reported noise in dBm */ 524 /* Most recently reported noise in dBm */
538 s8 noise; 525 s8 noise;
539 526
540 /* map for HLIDs of associated stations - when operating in AP mode */
541 unsigned long ap_hlid_map[BITS_TO_LONGS(AP_MAX_STATIONS)];
542
543 /* recoreded keys for AP-mode - set here before AP startup */ 527 /* recoreded keys for AP-mode - set here before AP startup */
544 struct wl1271_ap_key *recorded_ap_keys[MAX_NUM_KEYS]; 528 struct wl1271_ap_key *recorded_ap_keys[MAX_NUM_KEYS];
545 529
@@ -559,7 +543,7 @@ struct wl1271 {
559 * AP-mode - links indexed by HLID. The global and broadcast links 543 * AP-mode - links indexed by HLID. The global and broadcast links
560 * are always active. 544 * are always active.
561 */ 545 */
562 struct wl1271_link links[AP_MAX_LINKS]; 546 struct wl1271_link links[WL12XX_MAX_LINKS];
563 547
564 /* the hlid of the link where the last transmitted skb came from */ 548 /* the hlid of the link where the last transmitted skb came from */
565 int last_tx_hlid; 549 int last_tx_hlid;
@@ -605,9 +589,15 @@ struct wl12xx_vif {
605 struct { 589 struct {
606 u8 global_hlid; 590 u8 global_hlid;
607 u8 bcast_hlid; 591 u8 bcast_hlid;
592
593 /* HLIDs bitmap of associated stations */
594 unsigned long sta_hlid_map[BITS_TO_LONGS(
595 WL12XX_MAX_LINKS)];
608 } ap; 596 } ap;
609 }; 597 };
610 598
599 unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
600
611 u8 ssid[IEEE80211_MAX_SSID_LEN + 1]; 601 u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
612 u8 ssid_len; 602 u8 ssid_len;
613 603