summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851bu.c1
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852au.c1
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852bu.c1
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852cu.c1
-rw-r--r--drivers/net/wireless/realtek/rtw89/usb.c84
-rw-r--r--drivers/net/wireless/realtek/rtw89/usb.h12
6 files changed, 87 insertions, 13 deletions
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851bu.c b/drivers/net/wireless/realtek/rtw89/rtw8851bu.c
index 959d62aefdd8..6a8d31544314 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851bu.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851bu.c
@@ -15,6 +15,7 @@ static const struct rtw89_usb_info rtw8851b_usb_info = {
.usb3_mac_npi_config_intf_0 = R_AX_USB3_MAC_NPI_CONFIG_INTF_0,
.usb_endpoint_0 = R_AX_USB_ENDPOINT_0,
.usb_endpoint_2 = R_AX_USB_ENDPOINT_2,
+ .rx_agg_alignment = 8,
.bulkout_id = {
[RTW89_DMA_ACH0] = 3,
[RTW89_DMA_ACH1] = 4,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852au.c b/drivers/net/wireless/realtek/rtw89/rtw8852au.c
index ccdbcc178c2a..4cced4619b7d 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852au.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852au.c
@@ -15,6 +15,7 @@ static const struct rtw89_usb_info rtw8852a_usb_info = {
.usb3_mac_npi_config_intf_0 = R_AX_USB3_MAC_NPI_CONFIG_INTF_0,
.usb_endpoint_0 = R_AX_USB_ENDPOINT_0,
.usb_endpoint_2 = R_AX_USB_ENDPOINT_2,
+ .rx_agg_alignment = 8,
.bulkout_id = {
[RTW89_DMA_ACH0] = 3,
[RTW89_DMA_ACH2] = 5,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bu.c b/drivers/net/wireless/realtek/rtw89/rtw8852bu.c
index 84cd3ec971f9..37111fed276f 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bu.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bu.c
@@ -15,6 +15,7 @@ static const struct rtw89_usb_info rtw8852b_usb_info = {
.usb3_mac_npi_config_intf_0 = R_AX_USB3_MAC_NPI_CONFIG_INTF_0,
.usb_endpoint_0 = R_AX_USB_ENDPOINT_0,
.usb_endpoint_2 = R_AX_USB_ENDPOINT_2,
+ .rx_agg_alignment = 8,
.bulkout_id = {
[RTW89_DMA_ACH0] = 3,
[RTW89_DMA_ACH1] = 4,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c
index 3b9825c92a0d..0c5aebaed873 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c
@@ -15,6 +15,7 @@ static const struct rtw89_usb_info rtw8852c_usb_info = {
.usb3_mac_npi_config_intf_0 = R_AX_USB3_MAC_NPI_CONFIG_INTF_0_V1,
.usb_endpoint_0 = R_AX_USB_ENDPOINT_0_V1,
.usb_endpoint_2 = R_AX_USB_ENDPOINT_2_V1,
+ .rx_agg_alignment = 8,
.bulkout_id = {
[RTW89_DMA_ACH0] = 3,
[RTW89_DMA_ACH2] = 5,
diff --git a/drivers/net/wireless/realtek/rtw89/usb.c b/drivers/net/wireless/realtek/rtw89/usb.c
index 64f0c0ec5ed4..581b8c05f930 100644
--- a/drivers/net/wireless/realtek/rtw89/usb.c
+++ b/drivers/net/wireless/realtek/rtw89/usb.c
@@ -408,11 +408,14 @@ static int rtw89_usb_ops_tx_write(struct rtw89_dev *rtwdev,
static void rtw89_usb_rx_handler(struct work_struct *work)
{
struct rtw89_usb *rtwusb = container_of(work, struct rtw89_usb, rx_work);
+ const struct rtw89_usb_info *info = rtwusb->info;
struct rtw89_dev *rtwdev = rtwusb->rtwdev;
struct rtw89_rx_desc_info desc_info;
+ s32 aligned_offset, remaining;
struct sk_buff *rx_skb;
struct sk_buff *skb;
u32 pkt_offset;
+ u8 *pkt_ptr;
int limit;
for (limit = 0; limit < 200; limit++) {
@@ -425,23 +428,38 @@ static void rtw89_usb_rx_handler(struct work_struct *work)
goto free_or_reuse;
}
- memset(&desc_info, 0, sizeof(desc_info));
- rtw89_chip_query_rxdesc(rtwdev, &desc_info, rx_skb->data, 0);
+ pkt_ptr = rx_skb->data;
+ remaining = rx_skb->len;
- skb = rtw89_alloc_skb_for_rx(rtwdev, desc_info.pkt_size);
- if (!skb) {
- rtw89_debug(rtwdev, RTW89_DBG_HCI,
- "failed to allocate RX skb of size %u\n",
- desc_info.pkt_size);
- goto free_or_reuse;
- }
+ do {
+ memset(&desc_info, 0, sizeof(desc_info));
+ rtw89_chip_query_rxdesc(rtwdev, &desc_info, pkt_ptr, 0);
- pkt_offset = desc_info.offset + desc_info.rxd_len;
+ pkt_offset = desc_info.offset + desc_info.rxd_len;
+ if (remaining < (pkt_offset + desc_info.pkt_size)) {
+ rtw89_debug(rtwdev, RTW89_DBG_HCI,
+ "Failed to get remaining RX pkt %u > %u\n",
+ pkt_offset + desc_info.pkt_size, remaining);
+ goto free_or_reuse;
+ }
- skb_put_data(skb, rx_skb->data + pkt_offset,
- desc_info.pkt_size);
+ skb = rtw89_alloc_skb_for_rx(rtwdev, desc_info.pkt_size);
+ if (!skb) {
+ rtw89_debug(rtwdev, RTW89_DBG_HCI,
+ "failed to allocate RX skb of size %u\n",
+ desc_info.pkt_size);
+ goto free_or_reuse;
+ }
+
+ skb_put_data(skb, pkt_ptr + pkt_offset, desc_info.pkt_size);
+ rtw89_core_rx(rtwdev, &desc_info, skb);
- rtw89_core_rx(rtwdev, &desc_info, skb);
+ /* next frame */
+ pkt_offset += desc_info.pkt_size;
+ aligned_offset = ALIGN(pkt_offset, info->rx_agg_alignment);
+ pkt_ptr += aligned_offset;
+ remaining -= aligned_offset;
+ } while (remaining > 0);
free_or_reuse:
if (skb_queue_len(&rtwusb->rx_free_queue) >= RTW89_USB_RX_SKB_NUM)
@@ -745,6 +763,44 @@ static int rtw89_usb_ops_mac_pre_deinit(struct rtw89_dev *rtwdev)
return 0; /* Nothing to do. */
}
+static void rtw89_usb_rx_agg_cfg_v1(struct rtw89_dev *rtwdev)
+{
+ const u32 rxagg_0 = FIELD_PREP_CONST(B_AX_RXAGG_0_EN, 1) |
+ FIELD_PREP_CONST(B_AX_RXAGG_0_NUM_TH, 0) |
+ FIELD_PREP_CONST(B_AX_RXAGG_0_TIME_32US_TH, 32) |
+ FIELD_PREP_CONST(B_AX_RXAGG_0_BUF_SZ_4K, 5);
+
+ rtw89_write32(rtwdev, R_AX_RXAGG_0, rxagg_0);
+}
+
+static void rtw89_usb_rx_agg_cfg_v2(struct rtw89_dev *rtwdev)
+{
+ const u32 rxagg_0 = FIELD_PREP_CONST(B_AX_RXAGG_0_EN, 1) |
+ FIELD_PREP_CONST(B_AX_RXAGG_0_NUM_TH, 255) |
+ FIELD_PREP_CONST(B_AX_RXAGG_0_TIME_32US_TH, 32) |
+ FIELD_PREP_CONST(B_AX_RXAGG_0_BUF_SZ_1K, 20);
+
+ rtw89_write32(rtwdev, R_AX_RXAGG_0_V1, rxagg_0);
+ rtw89_write32(rtwdev, R_AX_RXAGG_1_V1, 0x1F);
+}
+
+static void rtw89_usb_rx_agg_cfg(struct rtw89_dev *rtwdev)
+{
+ switch (rtwdev->chip->chip_id) {
+ case RTL8851B:
+ case RTL8852A:
+ case RTL8852B:
+ rtw89_usb_rx_agg_cfg_v1(rtwdev);
+ break;
+ case RTL8852C:
+ rtw89_usb_rx_agg_cfg_v2(rtwdev);
+ break;
+ default:
+ rtw89_warn(rtwdev, "%s: USB RX agg not support\n", __func__);
+ return;
+ }
+}
+
static int rtw89_usb_ops_mac_post_init(struct rtw89_dev *rtwdev)
{
struct rtw89_usb *rtwusb = rtw89_usb_priv(rtwdev);
@@ -773,6 +829,8 @@ static int rtw89_usb_ops_mac_post_init(struct rtw89_dev *rtwdev)
rtw89_write8(rtwdev, info->usb_endpoint_2 + 1, NUMP);
}
+ rtw89_usb_rx_agg_cfg(rtwdev);
+
return 0;
}
diff --git a/drivers/net/wireless/realtek/rtw89/usb.h b/drivers/net/wireless/realtek/rtw89/usb.h
index 203ec8e993e9..3d17e514e346 100644
--- a/drivers/net/wireless/realtek/rtw89/usb.h
+++ b/drivers/net/wireless/realtek/rtw89/usb.h
@@ -20,6 +20,17 @@
#define RTW89_MAX_ENDPOINT_NUM 9
#define RTW89_MAX_BULKOUT_NUM 7
+#define R_AX_RXAGG_0_V1 0x6000
+#define B_AX_RXAGG_0_EN BIT(31)
+#define B_AX_RXAGG_0_NUM_TH GENMASK(23, 16)
+#define B_AX_RXAGG_0_TIME_32US_TH GENMASK(15, 8)
+#define B_AX_RXAGG_0_BUF_SZ_1K GENMASK(7, 0)
+
+#define R_AX_RXAGG_1_V1 0x6004
+
+#define R_AX_RXAGG_0 0x8900
+#define B_AX_RXAGG_0_BUF_SZ_4K GENMASK(7, 0)
+
struct rtw89_usb_info {
u32 usb_host_request_2;
u32 usb_wlan0_1;
@@ -27,6 +38,7 @@ struct rtw89_usb_info {
u32 usb3_mac_npi_config_intf_0;
u32 usb_endpoint_0;
u32 usb_endpoint_2;
+ u8 rx_agg_alignment;
u8 bulkout_id[RTW89_DMA_CH_NUM];
};