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