diff options
Diffstat (limited to 'drivers/net/wireless/ti')
-rw-r--r-- | drivers/net/wireless/ti/wl12xx/main.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wl18xx/main.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/conf.h | 14 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/main.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/tx.c | 124 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/wlcore.h | 3 |
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 | ||
682 | enum { | 694 | enum { |
@@ -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 | ||
470 | static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl, | 470 | static 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 | ||
498 | static struct sk_buff *wl12xx_lnk_skb_dequeue(struct wl1271 *wl, | 494 | static 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 | ||
525 | static struct sk_buff *wl12xx_vif_skb_dequeue(struct wl1271 *wl, | 515 | static 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 | |||
528 | static 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 | |||
546 | static 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 | /* | 633 | next: |
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 | ||
667 | out: | ||
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 | ||