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:
parent
31ed6f21ef
commit
a44713cf0d
2 changed files with 374 additions and 1 deletions
|
@ -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
|
||||
|
|
@ -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"
|
||||
|
|
Loading…
Reference in a new issue