aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ti
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ti')
-rw-r--r--drivers/net/wireless/ti/wl12xx/main.c2
-rw-r--r--drivers/net/wireless/ti/wl18xx/main.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/conf.h14
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c4
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.c124
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore.h3
6 files changed, 112 insertions, 37 deletions
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index d22b52f90d42..64dffafa35fb 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -210,6 +210,8 @@ static struct wlcore_conf wl12xx_conf = {
210 .tmpl_short_retry_limit = 10, 210 .tmpl_short_retry_limit = 10,
211 .tmpl_long_retry_limit = 10, 211 .tmpl_long_retry_limit = 10,
212 .tx_watchdog_timeout = 5000, 212 .tx_watchdog_timeout = 5000,
213 .slow_link_thold = 3,
214 .fast_link_thold = 10,
213 }, 215 },
214 .conn = { 216 .conn = {
215 .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, 217 .wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index f6c2bac9f640..a5119d3d5e70 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -337,6 +337,8 @@ static struct wlcore_conf wl18xx_conf = {
337 .tmpl_short_retry_limit = 10, 337 .tmpl_short_retry_limit = 10,
338 .tmpl_long_retry_limit = 10, 338 .tmpl_long_retry_limit = 10,
339 .tx_watchdog_timeout = 5000, 339 .tx_watchdog_timeout = 5000,
340 .slow_link_thold = 3,
341 .fast_link_thold = 30,
340 }, 342 },
341 .conn = { 343 .conn = {
342 .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, 344 .wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h
index 1bd831c9e843..552ac8182475 100644
--- a/drivers/net/wireless/ti/wlcore/conf.h
+++ b/drivers/net/wireless/ti/wlcore/conf.h
@@ -677,6 +677,18 @@ struct conf_tx_settings {
677 677
678 /* Time in ms for Tx watchdog timer to expire */ 678 /* Time in ms for Tx watchdog timer to expire */
679 u32 tx_watchdog_timeout; 679 u32 tx_watchdog_timeout;
680
681 /*
682 * when a slow link has this much packets pending, it becomes a low
683 * priority link, scheduling-wise
684 */
685 u8 slow_link_thold;
686
687 /*
688 * when a fast link has this much packets pending, it becomes a low
689 * priority link, scheduling-wise
690 */
691 u8 fast_link_thold;
680} __packed; 692} __packed;
681 693
682enum { 694enum {
@@ -1281,7 +1293,7 @@ struct conf_recovery_settings {
1281 * version, the two LSB are the lower driver's private conf 1293 * version, the two LSB are the lower driver's private conf
1282 * version. 1294 * version.
1283 */ 1295 */
1284#define WLCORE_CONF_VERSION (0x0004 << 16) 1296#define WLCORE_CONF_VERSION (0x0005 << 16)
1285#define WLCORE_CONF_MASK 0xffff0000 1297#define WLCORE_CONF_MASK 0xffff0000
1286#define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \ 1298#define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \
1287 sizeof(struct wlcore_conf)) 1299 sizeof(struct wlcore_conf))
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 33a9559f4d84..486b7fa0259c 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -362,8 +362,6 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl,
362 u32 cur_fw_ps_map; 362 u32 cur_fw_ps_map;
363 u8 hlid; 363 u8 hlid;
364 364
365 /* TODO: also use link_fast_bitmap here */
366
367 cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap); 365 cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap);
368 if (wl->ap_fw_ps_map != cur_fw_ps_map) { 366 if (wl->ap_fw_ps_map != cur_fw_ps_map) {
369 wl1271_debug(DEBUG_PSM, 367 wl1271_debug(DEBUG_PSM,
@@ -479,6 +477,8 @@ static int wlcore_fw_status(struct wl1271 *wl,
479 wl->time_offset = (timespec_to_ns(&ts) >> 10) - 477 wl->time_offset = (timespec_to_ns(&ts) >> 10) -
480 (s64)le32_to_cpu(status_2->fw_localtime); 478 (s64)le32_to_cpu(status_2->fw_localtime);
481 479
480 wl->fw_fast_lnk_map = le32_to_cpu(status_2->link_fast_bitmap);
481
482 return 0; 482 return 0;
483} 483}
484 484
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index 076983b05b4d..fbda3cbca7e7 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -467,8 +467,7 @@ void wl1271_handle_tx_low_watermark(struct wl1271 *wl)
467 } 467 }
468} 468}
469 469
470static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl, 470static int wlcore_select_ac(struct wl1271 *wl)
471 struct sk_buff_head *queues)
472{ 471{
473 int i, q = -1, ac; 472 int i, q = -1, ac;
474 u32 min_pkts = 0xffffffff; 473 u32 min_pkts = 0xffffffff;
@@ -482,33 +481,24 @@ static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl,
482 */ 481 */
483 for (i = 0; i < NUM_TX_QUEUES; i++) { 482 for (i = 0; i < NUM_TX_QUEUES; i++) {
484 ac = wl1271_tx_get_queue(i); 483 ac = wl1271_tx_get_queue(i);
485 if (!skb_queue_empty(&queues[ac]) && 484 if (wl->tx_queue_count[ac] &&
486 (wl->tx_allocated_pkts[ac] < min_pkts)) { 485 wl->tx_allocated_pkts[ac] < min_pkts) {
487 q = ac; 486 q = ac;
488 min_pkts = wl->tx_allocated_pkts[q]; 487 min_pkts = wl->tx_allocated_pkts[q];
489 } 488 }
490 } 489 }
491 490
492 if (q == -1) 491 return q;
493 return NULL;
494
495 return &queues[q];
496} 492}
497 493
498static struct sk_buff *wl12xx_lnk_skb_dequeue(struct wl1271 *wl, 494static struct sk_buff *wlcore_lnk_dequeue(struct wl1271 *wl,
499 struct wl1271_link *lnk) 495 struct wl1271_link *lnk, u8 q)
500{ 496{
501 struct sk_buff *skb; 497 struct sk_buff *skb;
502 unsigned long flags; 498 unsigned long flags;
503 struct sk_buff_head *queue;
504 499
505 queue = wl1271_select_queue(wl, lnk->tx_queue); 500 skb = skb_dequeue(&lnk->tx_queue[q]);
506 if (!queue)
507 return NULL;
508
509 skb = skb_dequeue(queue);
510 if (skb) { 501 if (skb) {
511 int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
512 spin_lock_irqsave(&wl->wl_lock, flags); 502 spin_lock_irqsave(&wl->wl_lock, flags);
513 WARN_ON_ONCE(wl->tx_queue_count[q] <= 0); 503 WARN_ON_ONCE(wl->tx_queue_count[q] <= 0);
514 wl->tx_queue_count[q]--; 504 wl->tx_queue_count[q]--;
@@ -522,9 +512,41 @@ static struct sk_buff *wl12xx_lnk_skb_dequeue(struct wl1271 *wl,
522 return skb; 512 return skb;
523} 513}
524 514
525static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl, 515static bool wlcore_lnk_high_prio(struct wl1271 *wl, u8 hlid,
526 struct wl12xx_vif *wlvif, 516 struct wl1271_link *lnk)
527 u8 *hlid) 517{
518 u8 thold;
519
520 if (test_bit(hlid, (unsigned long *)&wl->fw_fast_lnk_map))
521 thold = wl->conf.tx.fast_link_thold;
522 else
523 thold = wl->conf.tx.slow_link_thold;
524
525 return lnk->allocated_pkts < thold;
526}
527
528static struct sk_buff *wlcore_lnk_dequeue_high_prio(struct wl1271 *wl,
529 u8 hlid, u8 ac,
530 u8 *low_prio_hlid)
531{
532 struct wl1271_link *lnk = &wl->links[hlid];
533
534 if (!wlcore_lnk_high_prio(wl, hlid, lnk)) {
535 if (*low_prio_hlid == WL12XX_INVALID_LINK_ID &&
536 !skb_queue_empty(&lnk->tx_queue[ac]))
537 /* we found the first non-empty low priority queue */
538 *low_prio_hlid = hlid;
539
540 return NULL;
541 }
542
543 return wlcore_lnk_dequeue(wl, lnk, ac);
544}
545
546static struct sk_buff *wlcore_vif_dequeue_high_prio(struct wl1271 *wl,
547 struct wl12xx_vif *wlvif,
548 u8 ac, u8 *hlid,
549 u8 *low_prio_hlid)
528{ 550{
529 struct sk_buff *skb = NULL; 551 struct sk_buff *skb = NULL;
530 int i, h, start_hlid; 552 int i, h, start_hlid;
@@ -540,7 +562,8 @@ static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl,
540 if (!test_bit(h, wlvif->links_map)) 562 if (!test_bit(h, wlvif->links_map))
541 continue; 563 continue;
542 564
543 skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[h]); 565 skb = wlcore_lnk_dequeue_high_prio(wl, h, ac,
566 low_prio_hlid);
544 if (!skb) 567 if (!skb)
545 continue; 568 continue;
546 569
@@ -560,42 +583,74 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl, u8 *hlid)
560 unsigned long flags; 583 unsigned long flags;
561 struct wl12xx_vif *wlvif = wl->last_wlvif; 584 struct wl12xx_vif *wlvif = wl->last_wlvif;
562 struct sk_buff *skb = NULL; 585 struct sk_buff *skb = NULL;
586 int ac;
587 u8 low_prio_hlid = WL12XX_INVALID_LINK_ID;
588
589 ac = wlcore_select_ac(wl);
590 if (ac < 0)
591 goto out;
563 592
564 /* continue from last wlvif (round robin) */ 593 /* continue from last wlvif (round robin) */
565 if (wlvif) { 594 if (wlvif) {
566 wl12xx_for_each_wlvif_continue(wl, wlvif) { 595 wl12xx_for_each_wlvif_continue(wl, wlvif) {
567 skb = wl12xx_vif_skb_dequeue(wl, wlvif, hlid); 596 if (!wlvif->tx_queue_count[ac])
568 if (skb) { 597 continue;
569 wl->last_wlvif = wlvif; 598
570 break; 599 skb = wlcore_vif_dequeue_high_prio(wl, wlvif, ac, hlid,
571 } 600 &low_prio_hlid);
601 if (!skb)
602 continue;
603
604 wl->last_wlvif = wlvif;
605 break;
572 } 606 }
573 } 607 }
574 608
575 /* dequeue from the system HLID before the restarting wlvif list */ 609 /* dequeue from the system HLID before the restarting wlvif list */
576 if (!skb) { 610 if (!skb) {
577 skb = wl12xx_lnk_skb_dequeue(wl, &wl->links[wl->system_hlid]); 611 skb = wlcore_lnk_dequeue_high_prio(wl, wl->system_hlid,
578 *hlid = wl->system_hlid; 612 ac, &low_prio_hlid);
613 if (skb) {
614 *hlid = wl->system_hlid;
615 wl->last_wlvif = NULL;
616 }
579 } 617 }
580 618
581 /* do a new pass over the wlvif list */ 619 /* Do a new pass over the wlvif list. But no need to continue
620 * after last_wlvif. The previous pass should have found it. */
582 if (!skb) { 621 if (!skb) {
583 wl12xx_for_each_wlvif(wl, wlvif) { 622 wl12xx_for_each_wlvif(wl, wlvif) {
584 skb = wl12xx_vif_skb_dequeue(wl, wlvif, hlid); 623 if (!wlvif->tx_queue_count[ac])
624 goto next;
625
626 skb = wlcore_vif_dequeue_high_prio(wl, wlvif, ac, hlid,
627 &low_prio_hlid);
585 if (skb) { 628 if (skb) {
586 wl->last_wlvif = wlvif; 629 wl->last_wlvif = wlvif;
587 break; 630 break;
588 } 631 }
589 632
590 /* 633next:
591 * No need to continue after last_wlvif. The previous
592 * pass should have found it.
593 */
594 if (wlvif == wl->last_wlvif) 634 if (wlvif == wl->last_wlvif)
595 break; 635 break;
596 } 636 }
597 } 637 }
598 638
639 /* no high priority skbs found - but maybe a low priority one? */
640 if (!skb && low_prio_hlid != WL12XX_INVALID_LINK_ID) {
641 struct wl1271_link *lnk = &wl->links[low_prio_hlid];
642 skb = wlcore_lnk_dequeue(wl, lnk, ac);
643
644 WARN_ON(!skb); /* we checked this before */
645 *hlid = low_prio_hlid;
646
647 /* ensure proper round robin in the vif/link levels */
648 wl->last_wlvif = lnk->wlvif;
649 if (lnk->wlvif)
650 lnk->wlvif->last_tx_hlid = low_prio_hlid;
651
652 }
653
599 if (!skb && 654 if (!skb &&
600 test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) { 655 test_and_clear_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags)) {
601 int q; 656 int q;
@@ -609,6 +664,7 @@ static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl, u8 *hlid)
609 spin_unlock_irqrestore(&wl->wl_lock, flags); 664 spin_unlock_irqrestore(&wl->wl_lock, flags);
610 } 665 }
611 666
667out:
612 return skb; 668 return skb;
613} 669}
614 670
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 8703ae976081..e8245f36a67e 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -361,6 +361,9 @@ struct wl1271 {
361 */ 361 */
362 struct wl1271_link links[WL12XX_MAX_LINKS]; 362 struct wl1271_link links[WL12XX_MAX_LINKS];
363 363
364 /* Fast/slow links bitmap according to FW */
365 u32 fw_fast_lnk_map;
366
364 /* AP-mode - a bitmap of links currently in PS mode according to FW */ 367 /* AP-mode - a bitmap of links currently in PS mode according to FW */
365 u32 ap_fw_ps_map; 368 u32 ap_fw_ps_map;
366 369