Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtw88: flush hardware tx queues

Sometimes mac80211 will ask us to flush the hardware queues.
To flush them, first we need to get the corresponding priority queues
from the RQPN mapping table.

Then we can check the available pages are equal to the originally
reserved pages, which means the hardware has returned all of the pages
it used to transmit.

Note that now we only check for 100 ms for the priority queue, but
sometimes if we have a lot of traffic (ex. 100Mbps up), some of the
packets could be dropped.

Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>

authored by

Yan-Hsuan Chuang and committed by
Kalle Valo
1131ad7f 127eef1d

+105 -1
+88
drivers/net/wireless/realtek/rtw88/mac.c
··· 719 719 return ret; 720 720 } 721 721 722 + static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues) 723 + { 724 + struct rtw_rqpn *rqpn = rtwdev->fifo.rqpn; 725 + u32 prio_queues = 0; 726 + 727 + if (queues & BIT(IEEE80211_AC_VO)) 728 + prio_queues |= BIT(rqpn->dma_map_vo); 729 + if (queues & BIT(IEEE80211_AC_VI)) 730 + prio_queues |= BIT(rqpn->dma_map_vi); 731 + if (queues & BIT(IEEE80211_AC_BE)) 732 + prio_queues |= BIT(rqpn->dma_map_be); 733 + if (queues & BIT(IEEE80211_AC_BK)) 734 + prio_queues |= BIT(rqpn->dma_map_bk); 735 + 736 + return prio_queues; 737 + } 738 + 739 + static void __rtw_mac_flush_prio_queue(struct rtw_dev *rtwdev, 740 + u32 prio_queue, bool drop) 741 + { 742 + u32 addr; 743 + u16 avail_page, rsvd_page; 744 + int i; 745 + 746 + switch (prio_queue) { 747 + case RTW_DMA_MAPPING_EXTRA: 748 + addr = REG_FIFOPAGE_INFO_4; 749 + break; 750 + case RTW_DMA_MAPPING_LOW: 751 + addr = REG_FIFOPAGE_INFO_2; 752 + break; 753 + case RTW_DMA_MAPPING_NORMAL: 754 + addr = REG_FIFOPAGE_INFO_3; 755 + break; 756 + case RTW_DMA_MAPPING_HIGH: 757 + addr = REG_FIFOPAGE_INFO_1; 758 + break; 759 + default: 760 + return; 761 + } 762 + 763 + /* check if all of the reserved pages are available for 100 msecs */ 764 + for (i = 0; i < 5; i++) { 765 + rsvd_page = rtw_read16(rtwdev, addr); 766 + avail_page = rtw_read16(rtwdev, addr + 2); 767 + if (rsvd_page == avail_page) 768 + return; 769 + 770 + msleep(20); 771 + } 772 + 773 + /* priority queue is still not empty, throw a warning, 774 + * 775 + * Note that if we want to flush the tx queue when having a lot of 776 + * traffic (ex, 100Mbps up), some of the packets could be dropped. 777 + * And it requires like ~2secs to flush the full priority queue. 778 + */ 779 + if (!drop) 780 + rtw_warn(rtwdev, "timed out to flush queue %d\n", prio_queue); 781 + } 782 + 783 + static void rtw_mac_flush_prio_queues(struct rtw_dev *rtwdev, 784 + u32 prio_queues, bool drop) 785 + { 786 + u32 q; 787 + 788 + for (q = 0; q < RTW_DMA_MAPPING_MAX; q++) 789 + if (prio_queues & BIT(q)) 790 + __rtw_mac_flush_prio_queue(rtwdev, q, drop); 791 + } 792 + 793 + void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop) 794 + { 795 + u32 prio_queues = 0; 796 + 797 + /* If all of the hardware queues are requested to flush, 798 + * or the priority queues are not mapped yet, 799 + * flush all of the priority queues 800 + */ 801 + if (queues == BIT(rtwdev->hw->queues) - 1 || !rtwdev->fifo.rqpn) 802 + prio_queues = BIT(RTW_DMA_MAPPING_MAX) - 1; 803 + else 804 + prio_queues = get_priority_queues(rtwdev, queues); 805 + 806 + rtw_mac_flush_prio_queues(rtwdev, prio_queues, drop); 807 + } 808 + 722 809 static int txdma_queue_mapping(struct rtw_dev *rtwdev) 723 810 { 724 811 struct rtw_chip_info *chip = rtwdev->chip; ··· 830 743 return -EINVAL; 831 744 } 832 745 746 + rtwdev->fifo.rqpn = rqpn; 833 747 txdma_pq_map |= BIT_TXDMA_HIQ_MAP(rqpn->dma_map_hi); 834 748 txdma_pq_map |= BIT_TXDMA_MGQ_MAP(rqpn->dma_map_mg); 835 749 txdma_pq_map |= BIT_TXDMA_BKQ_MAP(rqpn->dma_map_bk);
+1
drivers/net/wireless/realtek/rtw88/mac.h
··· 31 31 void rtw_mac_power_off(struct rtw_dev *rtwdev); 32 32 int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw); 33 33 int rtw_mac_init(struct rtw_dev *rtwdev); 34 + void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop); 34 35 35 36 #endif
+14
drivers/net/wireless/realtek/rtw88/mac80211.c
··· 589 589 sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); 590 590 } 591 591 592 + static void rtw_ops_flush(struct ieee80211_hw *hw, 593 + struct ieee80211_vif *vif, 594 + u32 queues, bool drop) 595 + { 596 + struct rtw_dev *rtwdev = hw->priv; 597 + 598 + mutex_lock(&rtwdev->mutex); 599 + rtw_leave_lps_deep(rtwdev); 600 + 601 + rtw_mac_flush_queues(rtwdev, queues, drop); 602 + mutex_unlock(&rtwdev->mutex); 603 + } 604 + 592 605 const struct ieee80211_ops rtw_ops = { 593 606 .tx = rtw_ops_tx, 594 607 .wake_tx_queue = rtw_ops_wake_tx_queue, ··· 621 608 .mgd_prepare_tx = rtw_ops_mgd_prepare_tx, 622 609 .set_rts_threshold = rtw_ops_set_rts_threshold, 623 610 .sta_statistics = rtw_ops_sta_statistics, 611 + .flush = rtw_ops_flush, 624 612 }; 625 613 EXPORT_SYMBOL(rtw_ops);
+2 -1
drivers/net/wireless/realtek/rtw88/main.h
··· 780 780 RTW_DMA_MAPPING_NORMAL = 2, 781 781 RTW_DMA_MAPPING_HIGH = 3, 782 782 783 + RTW_DMA_MAPPING_MAX, 783 784 RTW_DMA_MAPPING_UNDEF, 784 785 }; 785 786 ··· 1287 1286 u16 rsvd_cpu_instr_addr; 1288 1287 u16 rsvd_fw_txbuf_addr; 1289 1288 u16 rsvd_csibuf_addr; 1290 - enum rtw_dma_mapping pq_map[RTW_PQ_MAP_NUM]; 1289 + struct rtw_rqpn *rqpn; 1291 1290 }; 1292 1291 1293 1292 struct rtw_fw_state {