From: Sasha Levin Date: Thu, 4 Mar 2021 20:46:02 +0000 (-0500) Subject: Fixes for 4.19 X-Git-Tag: v4.4.260~35 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=b36ea1a1e10d30f139a526d3091718b714932c45;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 4.19 Signed-off-by: Sasha Levin --- diff --git a/queue-4.19/rsi-fix-tx-eapol-packet-handling-against-iwlwifi-ap.patch b/queue-4.19/rsi-fix-tx-eapol-packet-handling-against-iwlwifi-ap.patch new file mode 100644 index 00000000000..35c2e5c65d9 --- /dev/null +++ b/queue-4.19/rsi-fix-tx-eapol-packet-handling-against-iwlwifi-ap.patch @@ -0,0 +1,71 @@ +From 43d6c53a2a36a75a30f366accc91f846900f9cab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 15 Oct 2020 13:16:16 +0200 +Subject: rsi: Fix TX EAPOL packet handling against iwlwifi AP + +From: Marek Vasut + +[ Upstream commit 65277100caa2f2c62b6f3c4648b90d6f0435f3bc ] + +In case RSI9116 SDIO WiFi operates in STA mode against Intel 9260 in AP mode, +the association fails. The former is using wpa_supplicant during association, +the later is set up using hostapd: + +iwl$ cat hostapd.conf +interface=wlp1s0 +ssid=test +country_code=DE +hw_mode=g +channel=1 +wpa=2 +wpa_passphrase=test +wpa_key_mgmt=WPA-PSK +iwl$ hostapd -d hostapd.conf + +rsi$ wpa_supplicant -i wlan0 -c <(wpa_passphrase test test) + +The problem is that the TX EAPOL data descriptor RSI_DESC_REQUIRE_CFM_TO_HOST +flag and extended descriptor EAPOL4_CONFIRM frame type are not set in case the +AP is iwlwifi, because in that case the TX EAPOL packet is 2 bytes shorter. + +The downstream vendor driver has this change in place already [1], however +there is no explanation for it, neither is there any commit history from which +such explanation could be obtained. + +[1] https://github.com/SiliconLabs/RS911X-nLink-OSD/blob/master/rsi/rsi_91x_hal.c#L238 + +Signed-off-by: Marek Vasut +Cc: Angus Ainslie +Cc: David S. Miller +Cc: Jakub Kicinski +Cc: Kalle Valo +Cc: Lee Jones +Cc: Martin Kepplinger +Cc: Sebastian Krzyszkowiak +Cc: Siva Rebbagondla +Cc: linux-wireless@vger.kernel.org +Cc: netdev@vger.kernel.org +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20201015111616.429220-1-marex@denx.de +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/rsi/rsi_91x_hal.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c +index a7b341e95e76..0da95777f1c1 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_hal.c ++++ b/drivers/net/wireless/rsi/rsi_91x_hal.c +@@ -238,7 +238,8 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb) + rsi_set_len_qno(&data_desc->len_qno, + (skb->len - FRAME_DESC_SZ), + RSI_WIFI_MGMT_Q); +- if ((skb->len - header_size) == EAPOL4_PACKET_LEN) { ++ if (((skb->len - header_size) == EAPOL4_PACKET_LEN) || ++ ((skb->len - header_size) == EAPOL4_PACKET_LEN - 2)) { + data_desc->misc_flags |= + RSI_DESC_REQUIRE_CFM_TO_HOST; + xtend_desc->confirm_frame_type = EAPOL4_CONFIRM; +-- +2.30.1 + diff --git a/queue-4.19/rsi-move-card-interrupt-handling-to-rx-thread.patch b/queue-4.19/rsi-move-card-interrupt-handling-to-rx-thread.patch new file mode 100644 index 00000000000..7794d2208b3 --- /dev/null +++ b/queue-4.19/rsi-move-card-interrupt-handling-to-rx-thread.patch @@ -0,0 +1,217 @@ +From 8cbb540a0c4817bc2d069378f2a127153f4c9c50 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Nov 2020 19:09:40 +0100 +Subject: rsi: Move card interrupt handling to RX thread + +From: Marek Vasut + +[ Upstream commit 287431463e786766e05e4dc26d0a11d5f8ac8815 ] + +The interrupt handling of the RS911x is particularly heavy. For each RX +packet, the card does three SDIO transactions, one to read interrupt +status register, one to RX buffer length, one to read the RX packet(s). +This translates to ~330 uS per one cycle of interrupt handler. In case +there is more incoming traffic, this will be more. + +The drivers/mmc/core/sdio_irq.c has the following comment, quote "Just +like traditional hard IRQ handlers, we expect SDIO IRQ handlers to be +quick and to the point, so that the holding of the host lock does not +cover too much work that doesn't require that lock to be held." + +The RS911x interrupt handler does not fit that. This patch therefore +changes it such that the entire IRQ handler is moved to the RX thread +instead, and the interrupt handler only wakes the RX thread. + +This is OK, because the interrupt handler only does things which can +also be done in the RX thread, that is, it checks for firmware loading +error(s), it checks buffer status, it checks whether a packet arrived +and if so, reads out the packet and passes it to network stack. + +Moreover, this change permits removal of a code which allocated an +skbuff only to get 4-byte-aligned buffer, read up to 8kiB of data +into the skbuff, queue this skbuff into local private queue, then in +RX thread, this buffer is dequeued, the data in the skbuff as passed +to the RSI driver core, and the skbuff is deallocated. All this is +replaced by directly calling the RSI driver core with local buffer. + +Signed-off-by: Marek Vasut +Cc: Angus Ainslie +Cc: David S. Miller +Cc: Jakub Kicinski +Cc: Kalle Valo +Cc: Lee Jones +Cc: Martin Kepplinger +Cc: Sebastian Krzyszkowiak +Cc: Siva Rebbagondla +Cc: linux-wireless@vger.kernel.org +Cc: netdev@vger.kernel.org +Tested-by: Martin Kepplinger +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20201103180941.443528-1-marex@denx.de +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/rsi/rsi_91x_sdio.c | 6 +-- + drivers/net/wireless/rsi/rsi_91x_sdio_ops.c | 52 ++++++--------------- + drivers/net/wireless/rsi/rsi_sdio.h | 8 +--- + 3 files changed, 15 insertions(+), 51 deletions(-) + +diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c +index 81cc1044532d..f76a360cf1e3 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c ++++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c +@@ -153,9 +153,7 @@ static void rsi_handle_interrupt(struct sdio_func *function) + if (adapter->priv->fsm_state == FSM_FW_NOT_LOADED) + return; + +- dev->sdio_irq_task = current; +- rsi_interrupt_handler(adapter); +- dev->sdio_irq_task = NULL; ++ rsi_set_event(&dev->rx_thread.event); + } + + /** +@@ -973,8 +971,6 @@ static int rsi_probe(struct sdio_func *pfunction, + rsi_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; + + sdio_claim_host(pfunction); + if (sdio_claim_irq(pfunction, rsi_handle_interrupt)) { +diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c +index 612c211e21a1..d66ae2f57314 100644 +--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c ++++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c +@@ -60,39 +60,20 @@ int rsi_sdio_master_access_msword(struct rsi_hw *adapter, u16 ms_word) + 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; + + do { + rsi_wait_event(&sdev->rx_thread.event, EVENT_WAIT_FOREVER); + rsi_reset_event(&sdev->rx_thread.event); ++ rsi_rx_handler(adapter); ++ } while (!atomic_read(&sdev->rx_thread.thread_done)); + +- while (true) { +- if (atomic_read(&sdev->rx_thread.thread_done)) +- goto out; +- +- skb = skb_dequeue(&sdev->rx_q.head); +- if (!skb) +- break; +- if (sdev->rx_q.num_rx_pkts > 0) +- sdev->rx_q.num_rx_pkts--; +- status = rsi_read_pkt(common, skb->data, skb->len); +- if (status) { +- rsi_dbg(ERR_ZONE, "Failed to read the packet\n"); +- dev_kfree_skb(skb); +- break; +- } +- dev_kfree_skb(skb); +- } +- } while (1); +- +-out: + rsi_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); + } +@@ -113,10 +94,6 @@ static int rsi_process_pkt(struct rsi_common *common) + u32 rcv_pkt_len = 0; + int status = 0; + u8 value = 0; +- struct sk_buff *skb; +- +- if (dev->rx_q.num_rx_pkts >= RSI_MAX_RX_PKTS) +- return 0; + + num_blks = ((adapter->interrupt_status & 1) | + ((adapter->interrupt_status >> RECV_NUM_BLOCKS) << 1)); +@@ -144,22 +121,19 @@ static int rsi_process_pkt(struct rsi_common *common) + + rcv_pkt_len = (num_blks * 256); + +- skb = dev_alloc_skb(rcv_pkt_len); +- if (!skb) +- return -ENOMEM; +- +- status = rsi_sdio_host_intf_read_pkt(adapter, skb->data, rcv_pkt_len); ++ status = rsi_sdio_host_intf_read_pkt(adapter, dev->pktbuffer, ++ rcv_pkt_len); + if (status) { + rsi_dbg(ERR_ZONE, "%s: Failed to read packet from card\n", + __func__); +- dev_kfree_skb(skb); + return status; + } +- skb_put(skb, rcv_pkt_len); +- skb_queue_tail(&dev->rx_q.head, skb); +- dev->rx_q.num_rx_pkts++; + +- rsi_set_event(&dev->rx_thread.event); ++ status = rsi_read_pkt(common, dev->pktbuffer, rcv_pkt_len); ++ if (status) { ++ rsi_dbg(ERR_ZONE, "Failed to read the packet\n"); ++ return status; ++ } + + return 0; + } +@@ -251,12 +225,12 @@ int rsi_init_sdio_slave_regs(struct rsi_hw *adapter) + } + + /** +- * rsi_interrupt_handler() - This function read and process SDIO interrupts. ++ * rsi_rx_handler() - Read and process SDIO interrupts. + * @adapter: Pointer to the adapter structure. + * + * Return: None. + */ +-void rsi_interrupt_handler(struct rsi_hw *adapter) ++static void rsi_rx_handler(struct rsi_hw *adapter) + { + struct rsi_common *common = adapter->priv; + struct rsi_91x_sdiodev *dev = +diff --git a/drivers/net/wireless/rsi/rsi_sdio.h b/drivers/net/wireless/rsi/rsi_sdio.h +index 66dcd2ec9051..fd11f16fc74f 100644 +--- a/drivers/net/wireless/rsi/rsi_sdio.h ++++ b/drivers/net/wireless/rsi/rsi_sdio.h +@@ -110,11 +110,6 @@ struct receive_info { + u32 buf_available_counter; + }; + +-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; +@@ -127,11 +122,10 @@ struct rsi_91x_sdiodev { + u16 tx_blk_size; + u8 write_fail; + bool buff_status_updated; +- struct rsi_sdio_rx_q rx_q; + struct rsi_thread rx_thread; ++ u8 pktbuffer[8192] __aligned(4); + }; + +-void rsi_interrupt_handler(struct rsi_hw *adapter); + int rsi_init_sdio_slave_regs(struct rsi_hw *adapter); + int rsi_sdio_read_register(struct rsi_hw *adapter, u32 addr, u8 *data); + int rsi_sdio_host_intf_read_pkt(struct rsi_hw *adapter, u8 *pkt, u32 length); +-- +2.30.1 + diff --git a/queue-4.19/series b/queue-4.19/series index 38d7c8442cc..7d7ecec7b71 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -16,3 +16,5 @@ net-fix-up-truesize-of-cloned-skb-in-skb_prepare_for_shift.patch mm-hugetlb.c-fix-unnecessary-address-expansion-of-pmd-sharing.patch net-bridge-use-switchdev-for-port-flags-set-through-sysfs-too.patch dt-bindings-net-btusb-dt-fix-s-interrupt-name-interrupt-names.patch +rsi-fix-tx-eapol-packet-handling-against-iwlwifi-ap.patch +rsi-move-card-interrupt-handling-to-rx-thread.patch