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

rtw88: kick off TX packets once for higher efficiency

Driver used to kick off every TX packets, that will waste some
time while we can do better to kick off the TX packets once after
they are all prepared to be transmitted.

For PCI, it uses DMA engine to transfer the SKBs to the device,
and the transition of the state of the DMA engine could be a cost.
Driver can save some time to kick off multiple SKBs once so that
the DMA engine will have only one transition.

So, split rtw_hci_ops::tx() to rtw_hci_ops::tx_write() and
rtw_hci_ops::tx_kick_off() to explicitly kick the SKBs off after
they are written to the prepared buffer. For packets come from
ieee80211_ops::tx(), write one and then kick it off immediately.
For packets queued in TX queue, which come from
ieee80211_ops::wake_tx_queue(), we can dequeue them, write them
to the buffer, and then kick them off together.

Signed-off-by: Yan-Hsuan Chuang <yhchuang@realtek.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200312080852.16684-6-yhchuang@realtek.com

authored by

Yan-Hsuan Chuang and committed by
Kalle Valo
aaab5d0e a5697a65

+135 -55
+13 -7
drivers/net/wireless/realtek/rtw88/hci.h
··· 7 7 8 8 /* ops for PCI, USB and SDIO */ 9 9 struct rtw_hci_ops { 10 - int (*tx)(struct rtw_dev *rtwdev, 11 - struct rtw_tx_pkt_info *pkt_info, 12 - struct sk_buff *skb); 10 + int (*tx_write)(struct rtw_dev *rtwdev, 11 + struct rtw_tx_pkt_info *pkt_info, 12 + struct sk_buff *skb); 13 + void (*tx_kick_off)(struct rtw_dev *rtwdev); 13 14 int (*setup)(struct rtw_dev *rtwdev); 14 15 int (*start)(struct rtw_dev *rtwdev); 15 16 void (*stop)(struct rtw_dev *rtwdev); ··· 29 28 void (*write32)(struct rtw_dev *rtwdev, u32 addr, u32 val); 30 29 }; 31 30 32 - static inline int rtw_hci_tx(struct rtw_dev *rtwdev, 33 - struct rtw_tx_pkt_info *pkt_info, 34 - struct sk_buff *skb) 31 + static inline int rtw_hci_tx_write(struct rtw_dev *rtwdev, 32 + struct rtw_tx_pkt_info *pkt_info, 33 + struct sk_buff *skb) 35 34 { 36 - return rtwdev->hci.ops->tx(rtwdev, pkt_info, skb); 35 + return rtwdev->hci.ops->tx_write(rtwdev, pkt_info, skb); 36 + } 37 + 38 + static inline void rtw_hci_tx_kick_off(struct rtw_dev *rtwdev) 39 + { 40 + return rtwdev->hci.ops->tx_kick_off(rtwdev); 37 41 } 38 42 39 43 static inline int rtw_hci_setup(struct rtw_dev *rtwdev)
+66 -24
drivers/net/wireless/realtek/rtw88/pci.c
··· 691 691 rtwpci->rx_tag = (rtwpci->rx_tag + 1) % RX_TAG_MAX; 692 692 } 693 693 694 - static int rtw_pci_xmit(struct rtw_dev *rtwdev, 695 - struct rtw_tx_pkt_info *pkt_info, 696 - struct sk_buff *skb, u8 queue) 694 + static void rtw_pci_tx_kick_off_queue(struct rtw_dev *rtwdev, u8 queue) 695 + { 696 + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 697 + struct rtw_pci_tx_ring *ring; 698 + u32 bd_idx; 699 + 700 + ring = &rtwpci->tx_rings[queue]; 701 + bd_idx = rtw_pci_tx_queue_idx_addr[queue]; 702 + 703 + spin_lock_bh(&rtwpci->irq_lock); 704 + rtw_pci_deep_ps_leave(rtwdev); 705 + rtw_write16(rtwdev, bd_idx, ring->r.wp & TRX_BD_IDX_MASK); 706 + spin_unlock_bh(&rtwpci->irq_lock); 707 + } 708 + 709 + static void rtw_pci_tx_kick_off(struct rtw_dev *rtwdev) 710 + { 711 + struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 712 + u8 queue; 713 + 714 + for (queue = 0; queue < RTK_MAX_TX_QUEUE_NUM; queue++) 715 + if (test_and_clear_bit(queue, rtwpci->tx_queued)) 716 + rtw_pci_tx_kick_off_queue(rtwdev, queue); 717 + } 718 + 719 + static int rtw_pci_tx_write_data(struct rtw_dev *rtwdev, 720 + struct rtw_tx_pkt_info *pkt_info, 721 + struct sk_buff *skb, u8 queue) 697 722 { 698 723 struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 699 724 struct rtw_chip_info *chip = rtwdev->chip; ··· 731 706 u32 psb_len; 732 707 u8 *pkt_desc; 733 708 struct rtw_pci_tx_buffer_desc *buf_desc; 734 - u32 bd_idx; 735 709 736 710 ring = &rtwpci->tx_rings[queue]; 737 711 ··· 769 745 770 746 spin_lock_bh(&rtwpci->irq_lock); 771 747 772 - rtw_pci_deep_ps_leave(rtwdev); 773 748 skb_queue_tail(&ring->queue, skb); 774 749 775 - /* kick off tx queue */ 776 - if (queue != RTW_TX_QUEUE_BCN) { 777 - if (++ring->r.wp >= ring->r.len) 778 - ring->r.wp = 0; 779 - bd_idx = rtw_pci_tx_queue_idx_addr[queue]; 780 - rtw_write16(rtwdev, bd_idx, ring->r.wp & TRX_BD_IDX_MASK); 781 - } else { 782 - u32 reg_bcn_work; 750 + if (queue == RTW_TX_QUEUE_BCN) 751 + goto out_unlock; 783 752 784 - reg_bcn_work = rtw_read8(rtwdev, RTK_PCI_TXBD_BCN_WORK); 785 - reg_bcn_work |= BIT_PCI_BCNQ_FLAG; 786 - rtw_write8(rtwdev, RTK_PCI_TXBD_BCN_WORK, reg_bcn_work); 787 - } 753 + /* update write-index, and kick it off later */ 754 + set_bit(queue, rtwpci->tx_queued); 755 + if (++ring->r.wp >= ring->r.len) 756 + ring->r.wp = 0; 757 + 758 + out_unlock: 788 759 spin_unlock_bh(&rtwpci->irq_lock); 789 760 790 761 return 0; ··· 790 771 { 791 772 struct sk_buff *skb; 792 773 struct rtw_tx_pkt_info pkt_info = {0}; 774 + u8 reg_bcn_work; 775 + int ret; 793 776 794 777 skb = rtw_tx_write_data_rsvd_page_get(rtwdev, &pkt_info, buf, size); 795 778 if (!skb) 796 779 return -ENOMEM; 797 780 798 - return rtw_pci_xmit(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_BCN); 781 + ret = rtw_pci_tx_write_data(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_BCN); 782 + if (ret) { 783 + rtw_err(rtwdev, "failed to write rsvd page data\n"); 784 + return ret; 785 + } 786 + 787 + /* reserved pages go through beacon queue */ 788 + reg_bcn_work = rtw_read8(rtwdev, RTK_PCI_TXBD_BCN_WORK); 789 + reg_bcn_work |= BIT_PCI_BCNQ_FLAG; 790 + rtw_write8(rtwdev, RTK_PCI_TXBD_BCN_WORK, reg_bcn_work); 791 + 792 + return 0; 799 793 } 800 794 801 795 static int rtw_pci_write_data_h2c(struct rtw_dev *rtwdev, u8 *buf, u32 size) 802 796 { 803 797 struct sk_buff *skb; 804 798 struct rtw_tx_pkt_info pkt_info = {0}; 799 + int ret; 805 800 806 801 skb = rtw_tx_write_data_h2c_get(rtwdev, &pkt_info, buf, size); 807 802 if (!skb) 808 803 return -ENOMEM; 809 804 810 - return rtw_pci_xmit(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_H2C); 805 + ret = rtw_pci_tx_write_data(rtwdev, &pkt_info, skb, RTW_TX_QUEUE_H2C); 806 + if (ret) { 807 + rtw_err(rtwdev, "failed to write h2c data\n"); 808 + return ret; 809 + } 810 + 811 + rtw_pci_tx_kick_off_queue(rtwdev, RTW_TX_QUEUE_H2C); 812 + 813 + return 0; 811 814 } 812 815 813 - static int rtw_pci_tx(struct rtw_dev *rtwdev, 814 - struct rtw_tx_pkt_info *pkt_info, 815 - struct sk_buff *skb) 816 + static int rtw_pci_tx_write(struct rtw_dev *rtwdev, 817 + struct rtw_tx_pkt_info *pkt_info, 818 + struct sk_buff *skb) 816 819 { 817 820 struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv; 818 821 struct rtw_pci_tx_ring *ring; 819 822 u8 queue = rtw_hw_queue_mapping(skb); 820 823 int ret; 821 824 822 - ret = rtw_pci_xmit(rtwdev, pkt_info, skb, queue); 825 + ret = rtw_pci_tx_write_data(rtwdev, pkt_info, skb, queue); 823 826 if (ret) 824 827 return ret; 825 828 ··· 1415 1374 } 1416 1375 1417 1376 static struct rtw_hci_ops rtw_pci_ops = { 1418 - .tx = rtw_pci_tx, 1377 + .tx_write = rtw_pci_tx_write, 1378 + .tx_kick_off = rtw_pci_tx_kick_off, 1419 1379 .setup = rtw_pci_setup, 1420 1380 .start = rtw_pci_start, 1421 1381 .stop = rtw_pci_stop,
+1
drivers/net/wireless/realtek/rtw88/pci.h
··· 208 208 bool irq_enabled; 209 209 210 210 u16 rx_tag; 211 + DECLARE_BITMAP(tx_queued, RTK_MAX_TX_QUEUE_NUM); 211 212 struct rtw_pci_tx_ring tx_rings[RTK_MAX_TX_QUEUE_NUM]; 212 213 struct rtw_pci_rx_ring rx_rings[RTK_MAX_RX_QUEUE_NUM]; 213 214 u16 link_ctrl;
+54 -23
drivers/net/wireless/realtek/rtw88/tx.c
··· 221 221 222 222 static void rtw_tx_mgmt_pkt_info_update(struct rtw_dev *rtwdev, 223 223 struct rtw_tx_pkt_info *pkt_info, 224 - struct ieee80211_tx_control *control, 224 + struct ieee80211_sta *sta, 225 225 struct sk_buff *skb) 226 226 { 227 227 pkt_info->use_rate = true; ··· 231 231 232 232 static void rtw_tx_data_pkt_info_update(struct rtw_dev *rtwdev, 233 233 struct rtw_tx_pkt_info *pkt_info, 234 - struct ieee80211_tx_control *control, 234 + struct ieee80211_sta *sta, 235 235 struct sk_buff *skb) 236 236 { 237 - struct ieee80211_sta *sta = control->sta; 238 237 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 239 238 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 240 239 struct rtw_sta_info *si; ··· 292 293 293 294 void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev, 294 295 struct rtw_tx_pkt_info *pkt_info, 295 - struct ieee80211_tx_control *control, 296 + struct ieee80211_sta *sta, 296 297 struct sk_buff *skb) 297 298 { 298 299 struct rtw_chip_info *chip = rtwdev->chip; ··· 304 305 u8 sec_type = 0; 305 306 bool bmc; 306 307 307 - if (control->sta) { 308 - si = (struct rtw_sta_info *)control->sta->drv_priv; 308 + if (sta) { 309 + si = (struct rtw_sta_info *)sta->drv_priv; 309 310 vif = si->vif; 310 311 } 311 312 312 313 if (ieee80211_is_mgmt(fc) || ieee80211_is_nullfunc(fc)) 313 - rtw_tx_mgmt_pkt_info_update(rtwdev, pkt_info, control, skb); 314 + rtw_tx_mgmt_pkt_info_update(rtwdev, pkt_info, sta, skb); 314 315 else if (ieee80211_is_data(fc)) 315 - rtw_tx_data_pkt_info_update(rtwdev, pkt_info, control, skb); 316 + rtw_tx_data_pkt_info_update(rtwdev, pkt_info, sta, skb); 316 317 317 318 if (info->control.hw_key) { 318 319 struct ieee80211_key_conf *key = info->control.hw_key; ··· 426 427 struct sk_buff *skb) 427 428 { 428 429 struct rtw_tx_pkt_info pkt_info = {0}; 430 + int ret; 429 431 430 - rtw_tx_pkt_info_update(rtwdev, &pkt_info, control, skb); 431 - if (rtw_hci_tx(rtwdev, &pkt_info, skb)) 432 + rtw_tx_pkt_info_update(rtwdev, &pkt_info, control->sta, skb); 433 + ret = rtw_hci_tx_write(rtwdev, &pkt_info, skb); 434 + if (ret) { 435 + rtw_err(rtwdev, "failed to write TX skb to HCI\n"); 432 436 goto out; 437 + } 438 + 439 + rtw_hci_tx_kick_off(rtwdev); 433 440 434 441 return; 435 442 ··· 475 470 ieee80211_queue_work(rtwdev->hw, &rtwdev->ba_work); 476 471 } 477 472 478 - static bool rtw_txq_dequeue(struct rtw_dev *rtwdev, 479 - struct rtw_txq *rtwtxq) 473 + static int rtw_txq_push_skb(struct rtw_dev *rtwdev, 474 + struct rtw_txq *rtwtxq, 475 + struct sk_buff *skb) 480 476 { 481 477 struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq); 482 - struct ieee80211_tx_control control; 478 + struct rtw_tx_pkt_info pkt_info = {0}; 479 + int ret; 480 + 481 + rtw_txq_check_agg(rtwdev, rtwtxq, skb); 482 + 483 + rtw_tx_pkt_info_update(rtwdev, &pkt_info, txq->sta, skb); 484 + ret = rtw_hci_tx_write(rtwdev, &pkt_info, skb); 485 + if (ret) { 486 + rtw_err(rtwdev, "failed to write TX skb to HCI\n"); 487 + return ret; 488 + } 489 + rtwtxq->last_push = jiffies; 490 + 491 + return 0; 492 + } 493 + 494 + static struct sk_buff *rtw_txq_dequeue(struct rtw_dev *rtwdev, 495 + struct rtw_txq *rtwtxq) 496 + { 497 + struct ieee80211_txq *txq = rtwtxq_to_txq(rtwtxq); 483 498 struct sk_buff *skb; 484 499 485 500 skb = ieee80211_tx_dequeue(rtwdev->hw, txq); 486 501 if (!skb) 487 - return false; 502 + return NULL; 488 503 489 - rtw_txq_check_agg(rtwdev, rtwtxq, skb); 490 - 491 - control.sta = txq->sta; 492 - rtw_tx(rtwdev, &control, skb); 493 - rtwtxq->last_push = jiffies; 494 - 495 - return true; 504 + return skb; 496 505 } 497 506 498 507 static void rtw_txq_push(struct rtw_dev *rtwdev, 499 508 struct rtw_txq *rtwtxq, 500 509 unsigned long frames) 501 510 { 511 + struct sk_buff *skb; 512 + int ret; 502 513 int i; 503 514 504 515 rcu_read_lock(); 505 516 506 - for (i = 0; i < frames; i++) 507 - if (!rtw_txq_dequeue(rtwdev, rtwtxq)) 517 + for (i = 0; i < frames; i++) { 518 + skb = rtw_txq_dequeue(rtwdev, rtwtxq); 519 + if (!skb) 508 520 break; 521 + 522 + ret = rtw_txq_push_skb(rtwdev, rtwtxq, skb); 523 + if (ret) { 524 + rtw_err(rtwdev, "failed to pusk skb, ret %d\n", ret); 525 + break; 526 + } 527 + } 509 528 510 529 rcu_read_unlock(); 511 530 } ··· 551 522 552 523 list_del_init(&rtwtxq->list); 553 524 } 525 + 526 + rtw_hci_tx_kick_off(rtwdev); 554 527 555 528 spin_unlock_bh(&rtwdev->txq_lock); 556 529 }
+1 -1
drivers/net/wireless/realtek/rtw88/tx.h
··· 85 85 void rtw_tx_tasklet(unsigned long data); 86 86 void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev, 87 87 struct rtw_tx_pkt_info *pkt_info, 88 - struct ieee80211_tx_control *control, 88 + struct ieee80211_sta *sta, 89 89 struct sk_buff *skb); 90 90 void rtw_tx_fill_tx_desc(struct rtw_tx_pkt_info *pkt_info, struct sk_buff *skb); 91 91 void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn);