141 lines
5.0 KiB
Diff
141 lines
5.0 KiB
Diff
From a6f187f92bcc2b17821538b4a11d61764e68b091 Mon Sep 17 00:00:00 2001
|
|
From: Sascha Hauer <s.hauer@pengutronix.de>
|
|
Date: Mon, 17 Apr 2023 16:03:55 +0200
|
|
Subject: [PATCH 40/45] wifi: rtw88: usb: fix priority queue to endpoint
|
|
mapping
|
|
|
|
The RTW88 chipsets have four different priority queues in hardware. For
|
|
the USB type chipsets the packets destined for a specific priority queue
|
|
must be sent through the endpoint corresponding to the queue. This was
|
|
not fully understood when porting from the RTW88 USB out of tree driver
|
|
and thus violated.
|
|
|
|
This patch implements the qsel to endpoint mapping as in
|
|
get_usb_bulkout_id_88xx() in the downstream driver.
|
|
|
|
Without this the driver often issues "timed out to flush queue 3"
|
|
warnings and often TX stalls completely.
|
|
|
|
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
|
|
Tested-by: ValdikSS <iam@valdikss.org.ru>
|
|
Tested-by: Alexandru gagniuc <mr.nuke.me@gmail.com>
|
|
Tested-by: Larry Finger <Larry.Finger@lwfinger.net>
|
|
Cc: stable@vger.kernel.org
|
|
Reviewed-by: Ping-Ke Shih <pkshih@realtek.com>
|
|
Signed-off-by: Kalle Valo <kvalo@kernel.org>
|
|
Link: https://lore.kernel.org/r/20230417140358.2240429-2-s.hauer@pengutronix.de
|
|
---
|
|
drivers/net/wireless/realtek/rtw88/usb.c | 70 ++++++++++++++++--------
|
|
1 file changed, 47 insertions(+), 23 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/realtek/rtw88/usb.c
|
|
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
|
|
@@ -118,6 +118,22 @@ static void rtw_usb_write32(struct rtw_d
|
|
rtw_usb_write(rtwdev, addr, val, 4);
|
|
}
|
|
|
|
+static int dma_mapping_to_ep(enum rtw_dma_mapping dma_mapping)
|
|
+{
|
|
+ switch (dma_mapping) {
|
|
+ case RTW_DMA_MAPPING_HIGH:
|
|
+ return 0;
|
|
+ case RTW_DMA_MAPPING_NORMAL:
|
|
+ return 1;
|
|
+ case RTW_DMA_MAPPING_LOW:
|
|
+ return 2;
|
|
+ case RTW_DMA_MAPPING_EXTRA:
|
|
+ return 3;
|
|
+ default:
|
|
+ return -EINVAL;
|
|
+ }
|
|
+}
|
|
+
|
|
static int rtw_usb_parse(struct rtw_dev *rtwdev,
|
|
struct usb_interface *interface)
|
|
{
|
|
@@ -129,6 +145,8 @@ static int rtw_usb_parse(struct rtw_dev
|
|
int num_out_pipes = 0;
|
|
int i;
|
|
u8 num;
|
|
+ const struct rtw_chip_info *chip = rtwdev->chip;
|
|
+ const struct rtw_rqpn *rqpn;
|
|
|
|
for (i = 0; i < interface_desc->bNumEndpoints; i++) {
|
|
endpoint = &host_interface->endpoint[i].desc;
|
|
@@ -183,31 +201,34 @@ static int rtw_usb_parse(struct rtw_dev
|
|
|
|
rtwdev->hci.bulkout_num = num_out_pipes;
|
|
|
|
- switch (num_out_pipes) {
|
|
- case 4:
|
|
- case 3:
|
|
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID0] = 2;
|
|
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID1] = 2;
|
|
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID2] = 2;
|
|
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID3] = 2;
|
|
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID4] = 1;
|
|
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID5] = 1;
|
|
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID6] = 0;
|
|
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID7] = 0;
|
|
- break;
|
|
- case 2:
|
|
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID0] = 1;
|
|
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID1] = 1;
|
|
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID2] = 1;
|
|
- rtwusb->qsel_to_ep[TX_DESC_QSEL_TID3] = 1;
|
|
- break;
|
|
- case 1:
|
|
- break;
|
|
- default:
|
|
- rtw_err(rtwdev, "failed to get out_pipes(%d)\n", num_out_pipes);
|
|
+ if (num_out_pipes < 1 || num_out_pipes > 4) {
|
|
+ rtw_err(rtwdev, "invalid number of endpoints %d\n", num_out_pipes);
|
|
return -EINVAL;
|
|
}
|
|
|
|
+ rqpn = &chip->rqpn_table[num_out_pipes];
|
|
+
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID0] = dma_mapping_to_ep(rqpn->dma_map_be);
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID1] = dma_mapping_to_ep(rqpn->dma_map_bk);
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID2] = dma_mapping_to_ep(rqpn->dma_map_bk);
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID3] = dma_mapping_to_ep(rqpn->dma_map_be);
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID4] = dma_mapping_to_ep(rqpn->dma_map_vi);
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID5] = dma_mapping_to_ep(rqpn->dma_map_vi);
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID6] = dma_mapping_to_ep(rqpn->dma_map_vo);
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID7] = dma_mapping_to_ep(rqpn->dma_map_vo);
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID8] = -EINVAL;
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID9] = -EINVAL;
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID10] = -EINVAL;
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID11] = -EINVAL;
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID12] = -EINVAL;
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID13] = -EINVAL;
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID14] = -EINVAL;
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_TID15] = -EINVAL;
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_BEACON] = dma_mapping_to_ep(rqpn->dma_map_hi);
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_HIGH] = dma_mapping_to_ep(rqpn->dma_map_hi);
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_MGMT] = dma_mapping_to_ep(rqpn->dma_map_mg);
|
|
+ rtwusb->qsel_to_ep[TX_DESC_QSEL_H2C] = dma_mapping_to_ep(rqpn->dma_map_hi);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -250,7 +271,7 @@ static void rtw_usb_write_port_tx_comple
|
|
static int qsel_to_ep(struct rtw_usb *rtwusb, unsigned int qsel)
|
|
{
|
|
if (qsel >= ARRAY_SIZE(rtwusb->qsel_to_ep))
|
|
- return 0;
|
|
+ return -EINVAL;
|
|
|
|
return rtwusb->qsel_to_ep[qsel];
|
|
}
|
|
@@ -265,6 +286,9 @@ static int rtw_usb_write_port(struct rtw
|
|
int ret;
|
|
int ep = qsel_to_ep(rtwusb, qsel);
|
|
|
|
+ if (ep < 0)
|
|
+ return ep;
|
|
+
|
|
pipe = usb_sndbulkpipe(usbd, rtwusb->out_ep[ep]);
|
|
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
|
if (!urb)
|