a44713cf0d
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
371 lines
11 KiB
Diff
371 lines
11 KiB
Diff
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
|
|
|