aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/wl12xx/main.c')
-rw-r--r--drivers/net/wireless/wl12xx/main.c151
1 files changed, 119 insertions, 32 deletions
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 61dea73f5fd..947491a1d9c 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -482,6 +482,10 @@ static int wl1271_plt_init(struct wl1271 *wl)
482 if (ret < 0) 482 if (ret < 0)
483 goto out_free_memmap; 483 goto out_free_memmap;
484 484
485 ret = wl1271_acx_sta_mem_cfg(wl);
486 if (ret < 0)
487 goto out_free_memmap;
488
485 /* Default fragmentation threshold */ 489 /* Default fragmentation threshold */
486 ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); 490 ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold);
487 if (ret < 0) 491 if (ret < 0)
@@ -533,6 +537,57 @@ static int wl1271_plt_init(struct wl1271 *wl)
533 return ret; 537 return ret;
534} 538}
535 539
540static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks)
541{
542 bool fw_ps;
543
544 /* only regulate station links */
545 if (hlid < WL1271_AP_STA_HLID_START)
546 return;
547
548 fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
549
550 /*
551 * Wake up from high level PS if the STA is asleep with too little
552 * blocks in FW or if the STA is awake.
553 */
554 if (!fw_ps || tx_blks < WL1271_PS_STA_MAX_BLOCKS)
555 wl1271_ps_link_end(wl, hlid);
556
557 /* Start high-level PS if the STA is asleep with enough blocks in FW */
558 else if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
559 wl1271_ps_link_start(wl, hlid, true);
560}
561
562static void wl1271_irq_update_links_status(struct wl1271 *wl,
563 struct wl1271_fw_ap_status *status)
564{
565 u32 cur_fw_ps_map;
566 u8 hlid;
567
568 cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap);
569 if (wl->ap_fw_ps_map != cur_fw_ps_map) {
570 wl1271_debug(DEBUG_PSM,
571 "link ps prev 0x%x cur 0x%x changed 0x%x",
572 wl->ap_fw_ps_map, cur_fw_ps_map,
573 wl->ap_fw_ps_map ^ cur_fw_ps_map);
574
575 wl->ap_fw_ps_map = cur_fw_ps_map;
576 }
577
578 for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) {
579 u8 cnt = status->tx_lnk_free_blks[hlid] -
580 wl->links[hlid].prev_freed_blks;
581
582 wl->links[hlid].prev_freed_blks =
583 status->tx_lnk_free_blks[hlid];
584 wl->links[hlid].allocated_blks -= cnt;
585
586 wl1271_irq_ps_regulate_link(wl, hlid,
587 wl->links[hlid].allocated_blks);
588 }
589}
590
536static void wl1271_fw_status(struct wl1271 *wl, 591static void wl1271_fw_status(struct wl1271 *wl,
537 struct wl1271_fw_full_status *full_status) 592 struct wl1271_fw_full_status *full_status)
538{ 593{
@@ -570,6 +625,10 @@ static void wl1271_fw_status(struct wl1271 *wl,
570 if (total) 625 if (total)
571 clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); 626 clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
572 627
628 /* for AP update num of allocated TX blocks per link and ps status */
629 if (wl->bss_type == BSS_TYPE_AP_BSS)
630 wl1271_irq_update_links_status(wl, &full_status->ap);
631
573 /* update the host-chipset time offset */ 632 /* update the host-chipset time offset */
574 getnstimeofday(&ts); 633 getnstimeofday(&ts);
575 wl->time_offset = (timespec_to_ns(&ts) >> 10) - 634 wl->time_offset = (timespec_to_ns(&ts) >> 10) -
@@ -975,19 +1034,37 @@ int wl1271_plt_stop(struct wl1271 *wl)
975 return ret; 1034 return ret;
976} 1035}
977 1036
978static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) 1037static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
979{ 1038{
980 struct wl1271 *wl = hw->priv; 1039 struct wl1271 *wl = hw->priv;
981 unsigned long flags; 1040 unsigned long flags;
982 int q; 1041 int q;
1042 u8 hlid = 0;
983 1043
984 spin_lock_irqsave(&wl->wl_lock, flags); 1044 spin_lock_irqsave(&wl->wl_lock, flags);
985 wl->tx_queue_count++; 1045 wl->tx_queue_count++;
1046
1047 /*
1048 * The workqueue is slow to process the tx_queue and we need stop
1049 * the queue here, otherwise the queue will get too long.
1050 */
1051 if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
1052 wl1271_debug(DEBUG_TX, "op_tx: stopping queues");
1053 ieee80211_stop_queues(wl->hw);
1054 set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
1055 }
1056
986 spin_unlock_irqrestore(&wl->wl_lock, flags); 1057 spin_unlock_irqrestore(&wl->wl_lock, flags);
987 1058
988 /* queue the packet */ 1059 /* queue the packet */
989 q = wl1271_tx_get_queue(skb_get_queue_mapping(skb)); 1060 q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
990 skb_queue_tail(&wl->tx_queue[q], skb); 1061 if (wl->bss_type == BSS_TYPE_AP_BSS) {
1062 hlid = wl1271_tx_get_hlid(skb);
1063 wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q);
1064 skb_queue_tail(&wl->links[hlid].tx_queue[q], skb);
1065 } else {
1066 skb_queue_tail(&wl->tx_queue[q], skb);
1067 }
991 1068
992 /* 1069 /*
993 * The chip specific setup must run before the first TX packet - 1070 * The chip specific setup must run before the first TX packet -
@@ -996,21 +1073,6 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
996 1073
997 if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) 1074 if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags))
998 ieee80211_queue_work(wl->hw, &wl->tx_work); 1075 ieee80211_queue_work(wl->hw, &wl->tx_work);
999
1000 /*
1001 * The workqueue is slow to process the tx_queue and we need stop
1002 * the queue here, otherwise the queue will get too long.
1003 */
1004 if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
1005 wl1271_debug(DEBUG_TX, "op_tx: stopping queues");
1006
1007 spin_lock_irqsave(&wl->wl_lock, flags);
1008 ieee80211_stop_queues(wl->hw);
1009 set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
1010 spin_unlock_irqrestore(&wl->wl_lock, flags);
1011 }
1012
1013 return NETDEV_TX_OK;
1014} 1076}
1015 1077
1016static struct notifier_block wl1271_dev_notifier = { 1078static struct notifier_block wl1271_dev_notifier = {
@@ -1221,6 +1283,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
1221 wl->filters = 0; 1283 wl->filters = 0;
1222 wl1271_free_ap_keys(wl); 1284 wl1271_free_ap_keys(wl);
1223 memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); 1285 memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
1286 wl->ap_fw_ps_map = 0;
1287 wl->ap_ps_map = 0;
1224 1288
1225 for (i = 0; i < NUM_TX_QUEUES; i++) 1289 for (i = 0; i < NUM_TX_QUEUES; i++)
1226 wl->tx_blocks_freed[i] = 0; 1290 wl->tx_blocks_freed[i] = 0;
@@ -2218,6 +2282,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
2218 u32 sta_rate_set = 0; 2282 u32 sta_rate_set = 0;
2219 int ret; 2283 int ret;
2220 struct ieee80211_sta *sta; 2284 struct ieee80211_sta *sta;
2285 bool sta_exists = false;
2286 struct ieee80211_sta_ht_cap sta_ht_cap;
2221 2287
2222 if (is_ibss) { 2288 if (is_ibss) {
2223 ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, 2289 ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf,
@@ -2289,16 +2355,20 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
2289 if (sta->ht_cap.ht_supported) 2355 if (sta->ht_cap.ht_supported)
2290 sta_rate_set |= 2356 sta_rate_set |=
2291 (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET); 2357 (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET);
2358 sta_ht_cap = sta->ht_cap;
2359 sta_exists = true;
2360 }
2361 rcu_read_unlock();
2292 2362
2363 if (sta_exists) {
2293 /* handle new association with HT and HT information change */ 2364 /* handle new association with HT and HT information change */
2294 if ((changed & BSS_CHANGED_HT) && 2365 if ((changed & BSS_CHANGED_HT) &&
2295 (bss_conf->channel_type != NL80211_CHAN_NO_HT)) { 2366 (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
2296 ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, 2367 ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
2297 true); 2368 true);
2298 if (ret < 0) { 2369 if (ret < 0) {
2299 wl1271_warning("Set ht cap true failed %d", 2370 wl1271_warning("Set ht cap true failed %d",
2300 ret); 2371 ret);
2301 rcu_read_unlock();
2302 goto out; 2372 goto out;
2303 } 2373 }
2304 ret = wl1271_acx_set_ht_information(wl, 2374 ret = wl1271_acx_set_ht_information(wl,
@@ -2306,23 +2376,20 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
2306 if (ret < 0) { 2376 if (ret < 0) {
2307 wl1271_warning("Set ht information failed %d", 2377 wl1271_warning("Set ht information failed %d",
2308 ret); 2378 ret);
2309 rcu_read_unlock();
2310 goto out; 2379 goto out;
2311 } 2380 }
2312 } 2381 }
2313 /* handle new association without HT and disassociation */ 2382 /* handle new association without HT and disassociation */
2314 else if (changed & BSS_CHANGED_ASSOC) { 2383 else if (changed & BSS_CHANGED_ASSOC) {
2315 ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, 2384 ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
2316 false); 2385 false);
2317 if (ret < 0) { 2386 if (ret < 0) {
2318 wl1271_warning("Set ht cap false failed %d", 2387 wl1271_warning("Set ht cap false failed %d",
2319 ret); 2388 ret);
2320 rcu_read_unlock();
2321 goto out; 2389 goto out;
2322 } 2390 }
2323 } 2391 }
2324 } 2392 }
2325 rcu_read_unlock();
2326 2393
2327 if ((changed & BSS_CHANGED_ASSOC)) { 2394 if ((changed & BSS_CHANGED_ASSOC)) {
2328 if (bss_conf->assoc) { 2395 if (bss_conf->assoc) {
@@ -2612,7 +2679,7 @@ static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx,
2612 return 0; 2679 return 0;
2613} 2680}
2614 2681
2615static int wl1271_allocate_hlid(struct wl1271 *wl, 2682static int wl1271_allocate_sta(struct wl1271 *wl,
2616 struct ieee80211_sta *sta, 2683 struct ieee80211_sta *sta,
2617 u8 *hlid) 2684 u8 *hlid)
2618{ 2685{
@@ -2626,18 +2693,25 @@ static int wl1271_allocate_hlid(struct wl1271 *wl,
2626 } 2693 }
2627 2694
2628 wl_sta = (struct wl1271_station *)sta->drv_priv; 2695 wl_sta = (struct wl1271_station *)sta->drv_priv;
2629
2630 __set_bit(id, wl->ap_hlid_map); 2696 __set_bit(id, wl->ap_hlid_map);
2631 wl_sta->hlid = WL1271_AP_STA_HLID_START + id; 2697 wl_sta->hlid = WL1271_AP_STA_HLID_START + id;
2632 *hlid = wl_sta->hlid; 2698 *hlid = wl_sta->hlid;
2699 memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN);
2633 return 0; 2700 return 0;
2634} 2701}
2635 2702
2636static void wl1271_free_hlid(struct wl1271 *wl, u8 hlid) 2703static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
2637{ 2704{
2638 int id = hlid - WL1271_AP_STA_HLID_START; 2705 int id = hlid - WL1271_AP_STA_HLID_START;
2639 2706
2707 if (WARN_ON(!test_bit(id, wl->ap_hlid_map)))
2708 return;
2709
2640 __clear_bit(id, wl->ap_hlid_map); 2710 __clear_bit(id, wl->ap_hlid_map);
2711 memset(wl->links[hlid].addr, 0, ETH_ALEN);
2712 wl1271_tx_reset_link_queues(wl, hlid);
2713 __clear_bit(hlid, &wl->ap_ps_map);
2714 __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
2641} 2715}
2642 2716
2643static int wl1271_op_sta_add(struct ieee80211_hw *hw, 2717static int wl1271_op_sta_add(struct ieee80211_hw *hw,
@@ -2658,13 +2732,13 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
2658 2732
2659 wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid); 2733 wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid);
2660 2734
2661 ret = wl1271_allocate_hlid(wl, sta, &hlid); 2735 ret = wl1271_allocate_sta(wl, sta, &hlid);
2662 if (ret < 0) 2736 if (ret < 0)
2663 goto out; 2737 goto out;
2664 2738
2665 ret = wl1271_ps_elp_wakeup(wl, false); 2739 ret = wl1271_ps_elp_wakeup(wl, false);
2666 if (ret < 0) 2740 if (ret < 0)
2667 goto out; 2741 goto out_free_sta;
2668 2742
2669 ret = wl1271_cmd_add_sta(wl, sta, hlid); 2743 ret = wl1271_cmd_add_sta(wl, sta, hlid);
2670 if (ret < 0) 2744 if (ret < 0)
@@ -2673,6 +2747,10 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
2673out_sleep: 2747out_sleep:
2674 wl1271_ps_elp_sleep(wl); 2748 wl1271_ps_elp_sleep(wl);
2675 2749
2750out_free_sta:
2751 if (ret < 0)
2752 wl1271_free_sta(wl, hlid);
2753
2676out: 2754out:
2677 mutex_unlock(&wl->mutex); 2755 mutex_unlock(&wl->mutex);
2678 return ret; 2756 return ret;
@@ -2709,7 +2787,7 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
2709 if (ret < 0) 2787 if (ret < 0)
2710 goto out_sleep; 2788 goto out_sleep;
2711 2789
2712 wl1271_free_hlid(wl, wl_sta->hlid); 2790 wl1271_free_sta(wl, wl_sta->hlid);
2713 2791
2714out_sleep: 2792out_sleep:
2715 wl1271_ps_elp_sleep(wl); 2793 wl1271_ps_elp_sleep(wl);
@@ -3212,7 +3290,9 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
3212 IEEE80211_HW_SUPPORTS_UAPSD | 3290 IEEE80211_HW_SUPPORTS_UAPSD |
3213 IEEE80211_HW_HAS_RATE_CONTROL | 3291 IEEE80211_HW_HAS_RATE_CONTROL |
3214 IEEE80211_HW_CONNECTION_MONITOR | 3292 IEEE80211_HW_CONNECTION_MONITOR |
3215 IEEE80211_HW_SUPPORTS_CQM_RSSI; 3293 IEEE80211_HW_SUPPORTS_CQM_RSSI |
3294 IEEE80211_HW_REPORTS_TX_ACK_STATUS |
3295 IEEE80211_HW_AP_LINK_PS;
3216 3296
3217 wl->hw->wiphy->cipher_suites = cipher_suites; 3297 wl->hw->wiphy->cipher_suites = cipher_suites;
3218 wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); 3298 wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
@@ -3264,7 +3344,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
3264 struct ieee80211_hw *hw; 3344 struct ieee80211_hw *hw;
3265 struct platform_device *plat_dev = NULL; 3345 struct platform_device *plat_dev = NULL;
3266 struct wl1271 *wl; 3346 struct wl1271 *wl;
3267 int i, ret; 3347 int i, j, ret;
3268 unsigned int order; 3348 unsigned int order;
3269 3349
3270 hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); 3350 hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
@@ -3292,6 +3372,10 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
3292 for (i = 0; i < NUM_TX_QUEUES; i++) 3372 for (i = 0; i < NUM_TX_QUEUES; i++)
3293 skb_queue_head_init(&wl->tx_queue[i]); 3373 skb_queue_head_init(&wl->tx_queue[i]);
3294 3374
3375 for (i = 0; i < NUM_TX_QUEUES; i++)
3376 for (j = 0; j < AP_MAX_LINKS; j++)
3377 skb_queue_head_init(&wl->links[j].tx_queue[i]);
3378
3295 INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); 3379 INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
3296 INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work); 3380 INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work);
3297 INIT_WORK(&wl->irq_work, wl1271_irq_work); 3381 INIT_WORK(&wl->irq_work, wl1271_irq_work);
@@ -3317,6 +3401,9 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
3317 wl->bss_type = MAX_BSS_TYPE; 3401 wl->bss_type = MAX_BSS_TYPE;
3318 wl->set_bss_type = MAX_BSS_TYPE; 3402 wl->set_bss_type = MAX_BSS_TYPE;
3319 wl->fw_bss_type = MAX_BSS_TYPE; 3403 wl->fw_bss_type = MAX_BSS_TYPE;
3404 wl->last_tx_hlid = 0;
3405 wl->ap_ps_map = 0;
3406 wl->ap_fw_ps_map = 0;
3320 3407
3321 memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); 3408 memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
3322 for (i = 0; i < ACX_TX_DESCRIPTORS; i++) 3409 for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
@@ -3412,5 +3499,5 @@ module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR);
3412MODULE_PARM_DESC(debug_level, "wl12xx debugging level"); 3499MODULE_PARM_DESC(debug_level, "wl12xx debugging level");
3413 3500
3414MODULE_LICENSE("GPL"); 3501MODULE_LICENSE("GPL");
3415MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>"); 3502MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
3416MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>"); 3503MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");