From a44713cf0dd28e27092ad718d9e69e5680aab962 Mon Sep 17 00:00:00 2001 From: Clayton Craft Date: Fri, 19 Mar 2021 12:22:32 -0700 Subject: [PATCH] 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 --- ...ean-up-loop-in-the-interrupt-handler.patch | 371 ++++++++++++++++++ .../community/linux-purism-librem5/APKBUILD | 4 +- 2 files changed, 374 insertions(+), 1 deletion(-) create mode 100644 device/community/linux-purism-librem5/0003-Revert-redpine-Clean-up-loop-in-the-interrupt-handler.patch diff --git a/device/community/linux-purism-librem5/0003-Revert-redpine-Clean-up-loop-in-the-interrupt-handler.patch b/device/community/linux-purism-librem5/0003-Revert-redpine-Clean-up-loop-in-the-interrupt-handler.patch new file mode 100644 index 000000000..3553e4cd0 --- /dev/null +++ b/device/community/linux-purism-librem5/0003-Revert-redpine-Clean-up-loop-in-the-interrupt-handler.patch @@ -0,0 +1,371 @@ +From 9fcc84f60f496a70d5e0245c7f507d7f2dc5a8e0 Mon Sep 17 00:00:00 2001 +From: Sebastian Krzyszkowiak +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 +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 + diff --git a/device/community/linux-purism-librem5/APKBUILD b/device/community/linux-purism-librem5/APKBUILD index 151ddf1fc..afa39004f 100644 --- a/device/community/linux-purism-librem5/APKBUILD +++ b/device/community/linux-purism-librem5/APKBUILD @@ -2,7 +2,7 @@ # Maintainer: Clayton Craft pkgname=linux-purism-librem5 pkgver=5.11.4 -pkgrel=1 +pkgrel=2 _purismrel=1 # . _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"