linux-purism-librem5: add patch to fix wifi performance regression (MR 2043)

This patch fixes a fairly severe performance regression with wifi on the
L5 (something like 20x improvement in performance with this patch)

[ci:skip-build] Already build successfully in CI
This commit is contained in:
Clayton Craft 2021-03-19 12:22:32 -07:00
parent 31ed6f21ef
commit a44713cf0d
No known key found for this signature in database
GPG key ID: 7A3461CA187CEA54
2 changed files with 374 additions and 1 deletions

View file

@ -0,0 +1,371 @@
From 9fcc84f60f496a70d5e0245c7f507d7f2dc5a8e0 Mon Sep 17 00:00:00 2001
From: Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>
Date: Fri, 19 Mar 2021 06:31:20 +0100
Subject: [PATCH 1/2] Revert "redpine: Clean up loop in the interrupt handler"
This reverts commit d0ce5dd74f882d903a28cf4000e0fc4416c75ec3.
---
.../net/wireless/redpine/rsi_91x_sdio_ops.c | 123 +++++++++---------
1 file changed, 61 insertions(+), 62 deletions(-)
diff --git a/drivers/net/wireless/redpine/rsi_91x_sdio_ops.c b/drivers/net/wireless/redpine/rsi_91x_sdio_ops.c
index 7170cb02cb8b..b8e42ef157bf 100644
--- a/drivers/net/wireless/redpine/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/redpine/rsi_91x_sdio_ops.c
@@ -333,74 +333,73 @@ static void rsi_rx_handler(struct rsi_hw *adapter)
__func__, isr_status, (1 << MSDU_PKT_PENDING),
(1 << FW_ASSERT_IND));
- if (isr_status & BIT(PKT_BUFF_AVAILABLE)) {
- status = rsi_sdio_check_buffer_status(adapter, 0);
- if (status < 0)
- redpine_dbg(ERR_ZONE,
- "%s: Failed to check buffer status\n",
- __func__);
- rsi_sdio_ack_intr(common->priv,
- (1 << PKT_BUFF_AVAILABLE));
- rsi_set_event(&common->tx_thread.event);
-
- redpine_dbg(ISR_ZONE,
- "%s: Buffer full/available\n",
- __func__);
- dev->buff_status_updated = 1;
-
- isr_status &= ~BIT(PKT_BUFF_AVAILABLE);
- }
-
- if (isr_status & BIT(FW_ASSERT_IND)) {
- redpine_dbg(ERR_ZONE,
- "%s: ==> FIRMWARE Assert <==\n",
- __func__);
- status = rsi_sdio_read_register(common->priv,
- SDIO_FW_STATUS_REG,
- &fw_status);
- if (status) {
- redpine_dbg(ERR_ZONE,
- "%s: Failed to read f/w reg\n",
- __func__);
- } else {
- redpine_dbg(ERR_ZONE,
- "%s: Firmware Status is 0x%x\n",
- __func__, fw_status);
+ do {
+ RSI_GET_SDIO_INTERRUPT_TYPE(isr_status, isr_type);
+
+ switch (isr_type) {
+ case BUFFER_AVAILABLE:
+ status = rsi_sdio_check_buffer_status(adapter, 0);
+ if (status < 0)
+ redpine_dbg(ERR_ZONE,
+ "%s: Failed to check buffer status\n",
+ __func__);
rsi_sdio_ack_intr(common->priv,
- (1 << FW_ASSERT_IND));
- }
-
- common->fsm_state = FSM_CARD_NOT_READY;
+ (1 << PKT_BUFF_AVAILABLE));
+ rsi_set_event(&common->tx_thread.event);
- isr_status &= ~BIT(FW_ASSERT_IND);
- }
-
- if (isr_status & BIT(MSDU_PKT_PENDING)) {
- redpine_dbg(ISR_ZONE, "Pkt pending interrupt\n");
- dev->rx_info.total_sdio_msdu_pending_intr++;
+ redpine_dbg(ISR_ZONE,
+ "%s: Buffer full/available\n",
+ __func__);
+ dev->buff_status_updated = 1;
+ break;
- status = rsi_process_pkt(common);
- if (status) {
+ case FIRMWARE_ASSERT_IND:
redpine_dbg(ERR_ZONE,
- "%s: Failed to read pkt\n",
+ "%s: ==> FIRMWARE Assert <==\n",
__func__);
- mutex_unlock(&common->rx_lock);
- common->rx_in_prog = false;
- return;
+ status = rsi_sdio_read_register(common->priv,
+ SDIO_FW_STATUS_REG,
+ &fw_status);
+ if (status) {
+ redpine_dbg(ERR_ZONE,
+ "%s: Failed to read f/w reg\n",
+ __func__);
+ } else {
+ redpine_dbg(ERR_ZONE,
+ "%s: Firmware Status is 0x%x\n",
+ __func__, fw_status);
+ rsi_sdio_ack_intr(common->priv,
+ (1 << FW_ASSERT_IND));
+ }
+
+ common->fsm_state = FSM_CARD_NOT_READY;
+ break;
+
+ case MSDU_PACKET_PENDING:
+ redpine_dbg(ISR_ZONE, "Pkt pending interrupt\n");
+ dev->rx_info.total_sdio_msdu_pending_intr++;
+
+ status = rsi_process_pkt(common);
+ if (status) {
+ redpine_dbg(ERR_ZONE,
+ "%s: Failed to read pkt\n",
+ __func__);
+ mutex_unlock(&common->rx_lock);
+ common->rx_in_prog = false;
+ return;
+ }
+ break;
+ default:
+ rsi_sdio_ack_intr(common->priv, isr_status);
+ dev->rx_info.total_sdio_unknown_intr++;
+ isr_status = 0;
+ redpine_dbg(ISR_ZONE,
+ "Unknown Interrupt %x\n",
+ isr_status);
+ break;
}
-
- isr_status &= ~BIT(MSDU_PKT_PENDING);
- }
-
- if (isr_status) {
- rsi_sdio_ack_intr(common->priv, isr_status);
- dev->rx_info.total_sdio_unknown_intr++;
- isr_status = 0;
- redpine_dbg(ISR_ZONE,
- "Unknown Interrupt %x\n",
- isr_status);
- }
-
+ isr_status ^= BIT(isr_type - 1);
+ } while (isr_status);
mutex_unlock(&common->rx_lock);
} while (1);
common->rx_in_prog = false;
--
GitLab
From 11085503196282fb799a82526d87c0286859f18d Mon Sep 17 00:00:00 2001
From: Sebastian Krzyszkowiak <sebastian.krzyszkowiak@puri.sm>
Date: Fri, 19 Mar 2021 06:31:26 +0100
Subject: [PATCH 2/2] Revert "redpine: Move card interrupt handling to RX
thread"
This reverts commit 73e357c5a9cf52d300941d286d42bd8d61fd7847.
---
drivers/net/wireless/redpine/rsi_91x_sdio.c | 7 +-
.../net/wireless/redpine/rsi_91x_sdio_ops.c | 76 +++++++++++++++----
drivers/net/wireless/redpine/rsi_sdio.h | 9 ++-
3 files changed, 76 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/redpine/rsi_91x_sdio.c b/drivers/net/wireless/redpine/rsi_91x_sdio.c
index dc6559bb2462..827a5c47654b 100644
--- a/drivers/net/wireless/redpine/rsi_91x_sdio.c
+++ b/drivers/net/wireless/redpine/rsi_91x_sdio.c
@@ -177,7 +177,9 @@ static void rsi_handle_interrupt(struct sdio_func *function)
if (adapter->priv->fsm_state == FSM_FW_NOT_LOADED)
return;
- rsi_set_event(&dev->rx_thread.event);
+ dev->sdio_irq_task = current;
+ rsi_interrupt_handler(adapter);
+ dev->sdio_irq_task = NULL;
}
static void rsi_gspi_init(struct rsi_hw *adapter)
@@ -1191,6 +1193,7 @@ static int rsi_init_sdio_interface(struct rsi_hw *adapter,
sdio_release_host(pfunction);
adapter->determine_event_timeout = rsi_sdio_determine_event_timeout;
+ adapter->process_isr_hci = rsi_interrupt_handler;
adapter->check_intr_status_reg = rsi_read_intr_status_reg;
#ifdef CONFIG_REDPINE_DEBUGFS
@@ -1292,6 +1295,8 @@ static int rsi_probe(struct sdio_func *pfunction,
redpine_dbg(ERR_ZONE, "%s: Unable to init rx thrd\n", __func__);
goto fail_kill_thread;
}
+ skb_queue_head_init(&sdev->rx_q.head);
+ sdev->rx_q.num_rx_pkts = 0;
/*Receive buffer for handling RX interrupts in case of memory full*/
sdev->temp_rcv_buf = kzalloc((RCV_BUFF_LEN *4), GFP_KERNEL);
diff --git a/drivers/net/wireless/redpine/rsi_91x_sdio_ops.c b/drivers/net/wireless/redpine/rsi_91x_sdio_ops.c
index b8e42ef157bf..f67b9f66f879 100644
--- a/drivers/net/wireless/redpine/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/redpine/rsi_91x_sdio_ops.c
@@ -74,26 +74,49 @@ int rsi_sdio_master_access_msword(struct rsi_hw *adapter,
return status;
}
-static void rsi_rx_handler(struct rsi_hw *adapter);
-
void rsi_sdio_rx_thread(struct rsi_common *common)
{
struct rsi_hw *adapter = common->priv;
struct rsi_91x_sdiodev *sdev = adapter->rsi_dev;
+ struct sk_buff *skb;
int status;
+ bool done = false;
do {
- status = rsi_wait_event(&sdev->rx_thread.event,
+ status = rsi_wait_event(&sdev->rx_thread.event,
EVENT_WAIT_FOREVER);
if (status < 0)
break;
- rsi_reset_event(&sdev->rx_thread.event);
- rsi_rx_handler(adapter);
+ if (atomic_read(&sdev->rx_thread.thread_done))
+ break;
- } while (!atomic_read(&sdev->rx_thread.thread_done));
+ while (true) {
+ skb = skb_dequeue(&sdev->rx_q.head);
+ if (!skb)
+ break;
+ status = redpine_read_pkt(common, skb->data, skb->len);
+ if (status) {
+ redpine_dbg(ERR_ZONE, "Failed to read the packet\n");
+ dev_kfree_skb(skb);
+ return;
+ }
+ dev_kfree_skb(skb);
+ if (sdev->rx_q.num_rx_pkts > 0)
+ sdev->rx_q.num_rx_pkts--;
+
+ if (atomic_read(&sdev->rx_thread.thread_done)) {
+ done = true;
+ break;
+ }
+ }
+ rsi_reset_event(&sdev->rx_thread.event);
+ if (done)
+ break;
+ } while (1);
redpine_dbg(INFO_ZONE, "%s: Terminated SDIO RX thread\n", __func__);
+ skb_queue_purge(&sdev->rx_q.head);
atomic_inc(&sdev->rx_thread.thread_done);
complete_and_exit(&sdev->rx_thread.completion, 0);
}
@@ -115,6 +138,7 @@ static int rsi_process_pkt(struct rsi_common *common)
int status = 0;
u8 value = 0;
u8 protocol = 0, unaggr_pkt = 0;
+ struct sk_buff *skb;
#define COEX_PKT 0
@@ -155,18 +179,41 @@ static int rsi_process_pkt(struct rsi_common *common)
unaggr_pkt = 1;
rcv_pkt_len = (num_blks * 256);
+ if (dev->rx_q.num_rx_pkts >= RSI_SDIO_MAX_RX_PKTS)
+ {
+ redpine_dbg(ISR_ZONE, "%s,%d: Reached MAX RX_Q size,"
+ "dropping the packet\n",__func__,__LINE__);
+ goto DROP_PKT;
+ }
+
+ skb = dev_alloc_skb(rcv_pkt_len);
+
+ if (!skb)
+ {
+ redpine_dbg(ERR_ZONE, "%s,%d: Failed to allocate rx packet buffer,"
+ "dropping packet\n",__func__,__LINE__);
+ goto DROP_PKT;
+ }
- status = rsi_sdio_host_intf_read_pkt(adapter, dev->pktbuffer, rcv_pkt_len);
+ skb_put(skb, rcv_pkt_len);
+ status = rsi_sdio_host_intf_read_pkt(adapter, skb->data, skb->len);
if (status) {
redpine_dbg(ERR_ZONE, "%s,%d: Failed to read packet from card\n",
__func__,__LINE__);
+ dev_kfree_skb(skb);
return status;
}
- status = redpine_read_pkt(common, dev->pktbuffer, rcv_pkt_len);
- if (status) {
- redpine_dbg(ERR_ZONE, "Failed to read the packet\n");
- return status;
- }
+ skb_queue_tail(&dev->rx_q.head, skb);
+ dev->rx_q.num_rx_pkts++;
+ rsi_set_event(&dev->rx_thread.event);
+ return 0;
+DROP_PKT:
+ status = rsi_sdio_host_intf_read_pkt(adapter, dev->temp_rcv_buf, rcv_pkt_len);
+ if (status)
+ redpine_dbg(ERR_ZONE, "%s,%d: Failed to read packet from card\n",
+ __func__,__LINE__);
+
+ rsi_set_event(&dev->rx_thread.event);
return 0;
}
@@ -273,17 +320,18 @@ int rsi_read_intr_status_reg(struct rsi_hw *adapter)
}
/**
- * rsi_rx_handler() - This function read and process SDIO interrupts.
+ * rsi_interrupt_handler() - This function read and process SDIO interrupts.
* @adapter: Pointer to the adapter structure.
*
* Return: None.
*/
-static void rsi_rx_handler(struct rsi_hw *adapter)
+void rsi_interrupt_handler(struct rsi_hw *adapter)
{
struct rsi_common *common = adapter->priv;
struct rsi_91x_sdiodev *dev =
(struct rsi_91x_sdiodev *)adapter->rsi_dev;
int status;
+ enum sdio_interrupt_type isr_type;
u8 isr_status = 0;
u8 fw_status = 0;
diff --git a/drivers/net/wireless/redpine/rsi_sdio.h b/drivers/net/wireless/redpine/rsi_sdio.h
index 26ea697f91e4..bc22f75184fb 100644
--- a/drivers/net/wireless/redpine/rsi_sdio.h
+++ b/drivers/net/wireless/redpine/rsi_sdio.h
@@ -133,6 +133,12 @@ struct receive_info {
u32 buf_available_counter;
};
+#define RSI_SDIO_MAX_RX_PKTS 100
+struct rsi_sdio_rx_q {
+ u8 num_rx_pkts;
+ struct sk_buff_head head;
+};
+
struct rsi_91x_sdiodev {
struct sdio_func *pfunction;
struct task_struct *sdio_irq_task;
@@ -145,12 +151,13 @@ struct rsi_91x_sdiodev {
u32 tx_blk_size;
u8 write_fail;
u8 buff_status_updated;
+ struct rsi_sdio_rx_q rx_q;
struct rsi_thread rx_thread;
u8 *temp_rcv_buf;
- u8 pktbuffer[8192] __aligned(4);
};
void redpine_gpio_init(struct rsi_common *common);
+void rsi_interrupt_handler(struct rsi_hw *adapter);
int rsi_init_sdio_slave_regs(struct rsi_hw *adapter);
int rsi_sdio_device_init(struct rsi_common *common);
int rsi_sdio_read_register(struct rsi_hw *adapter, u32 addr, u8 *data);
--
GitLab

View file

@ -2,7 +2,7 @@
# Maintainer: Clayton Craft <clayton@craftyguy.net>
pkgname=linux-purism-librem5
pkgver=5.11.4
pkgrel=1
pkgrel=2
_purismrel=1
# <kernel ver>.<purism kernel release>
_purismver=${pkgver}pureos$_purismrel
@ -35,6 +35,7 @@ source="
8f11380ec32912370b8ae9134a0387a6f18862f7.patch
0001-Revert-arm64-dts-librem5-Drop-separte-DP-device-tree.patch
0002-bq25890_charger-enter-ship-mode-on-power-off.patch
0003-Revert-redpine-Clean-up-loop-in-the-interrupt-handler.patch
$_config
"
builddir="$srcdir/$_repository-pureos-$_purismver"
@ -77,4 +78,5 @@ sha512sums="d2e0f49403413f581aee6e47e021cb04fc003fbf821349c188a0c6a57561ba702c32
9870bff4b187188b519b23264c2634ee4232011fed6d2f66a7b4971db354ac3dffa0e1552bd0dc953c66ec622e18ce8899fdbcfba94f60867fc5004d6da96753 8f11380ec32912370b8ae9134a0387a6f18862f7.patch
5baae99010bde62e253fdd56f21ba096c217ba2ab9c367c80b34bc0f445a79a8fb8b5d14682f71ad6061d73c81fc16a608f4be037d792978dbbaf74267844260 0001-Revert-arm64-dts-librem5-Drop-separte-DP-device-tree.patch
1a12f74895b0fc710792e3881f23754a8eb92d25b11a2751db007a1b08f72729043d1e824096c97dc795b8e33300274887b428997ddaacf4b61f52ef3bd78ce5 0002-bq25890_charger-enter-ship-mode-on-power-off.patch
00286a7ea3d3167150eca1025f271bb76e05d8a47c481879b1322ec9e88250c365b1b0ddcc8140ccc9b8f6138ffec843f184645c0c7d4ff11f75c988f5c4945c 0003-Revert-redpine-Clean-up-loop-in-the-interrupt-handler.patch
d27cc078f49563fa935d104846017c9ba28e859d5231d202c68b6438e25f381747206fe0be86d323bd50dc457e67b02a52eb60a845c35bd33d7f2367893781d2 config-purism-librem5.aarch64"