From nobody Thu Sep 24 20:37:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A13044F551; Mon, 21 Sep 2026 07:59:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789977592; cv=none; b=cOnUsoWufLthYEGLFHkB4zh5uJw6ofjQ8SFMJfV4LCrK2VVVdkT8lDv4z1ezP6OpzcMTHY2LVtkq/e+j3Jb0E10CJ1sOzcITlE5QhWGi7Auy4rd4awkqJP+iDT9GGVnOfkWJiPNtVlE4U5i40Ka7Dx/eqfRkn5X9IpVpZRmrLs4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789977592; c=relaxed/simple; bh=O4jHspC2Q+PMYWXP+lpP2UpLmRNt60AedDGYqXHhhl4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=GLV/96Vls6eveL8peJDHlx1/9ggjN6aCzuSgKVA03jLUlI5gE8bG+8D5uNrZ+pAMrulaIwpL3ACcaLO/WIDCU2tDp4X0vVVk6K2v8KpAZs5AZG5ASraTw0wJ+J/K2crEUsKcR/YJN9Fl9btBYBdgQ9jLqzUihVFIfAwBCSkwwF8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LBgnuMQs; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LBgnuMQs" Received: by smtp.kernel.org (Postfix) with ESMTPS id EF210C2BCB3; Mon, 21 Sep 2026 07:59:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1789977592; bh=O4jHspC2Q+PMYWXP+lpP2UpLmRNt60AedDGYqXHhhl4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=LBgnuMQsAzLLB/Fa5zvJODl+9O631ItyZ1sxQx+vhSRT5clmjiq3tyh6keinfqZOA 8gHg71YOR/q59TUVOLEUuFG95U5LaZYqqFF8uJYorESH+A8dJhfRcxc+R1OUaNm0uZ srf0emKgpGJAx0ejyzyOBNcNgeZK0vOMQJNTZZ4YxoCkU82iz3eNANDjmyMWJybEDF D9Xmxl67YVQWPHaT7JH2jhA3HioIzlbj8JBMtNfl5O7Iko90VjNVZaoefBxlMVgQVh 8xNoVG4PwCN52DcdKO4vslos/7u8zyH0IaokkpX7teBR7Oh8DWrqvD0MuyfWHo+cKO vigGEdlC5qn3A== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id CD9DDC982ED; Mon, 21 Sep 2026 07:59:51 +0000 (UTC) From: Kim Wooseok via B4 Relay Date: Mon, 21 Sep 2026 16:59:49 +0900 Subject: [PATCH rtw-next v4 1/3] wifi: rtl8xxxu: free RX skb when URB submission fails Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260921-codex-rtl-rx-v3-submit-v4-1-eeb09fe8f791@khu.ac.kr> References: <20260921-codex-rtl-rx-v3-submit-v4-0-eeb09fe8f791@khu.ac.kr> In-Reply-To: <20260921-codex-rtl-rx-v3-submit-v4-0-eeb09fe8f791@khu.ac.kr> To: linux-wireless@vger.kernel.org Cc: Ping-Ke Shih , Jes Sorensen , Kalle Valo , linux-kernel@vger.kernel.org, Kim Wooseok <5mghybrid@khu.ac.kr> X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1789977589; l=2896; i=5mghybrid@khu.ac.kr; s=kernel-20260913; h=from:subject:message-id; bh=v2NnvT75DMsgHtN+8TES4Q5i+B5ih9gWoiLYF9i+R38=; b=8VMd7dtyT9w2+wCwgxaWS7lmbTf3Jcojdxl9HFw1fB9/z0tlJHw+a1Gp9GFWtfFNhEeMK/24t jHa6yTvjSOlCFmP+edgBVICKA41LCt173JmUnYh0I14cmb17awTb/Li X-Developer-Key: i=5mghybrid@khu.ac.kr; a=ed25519; pk=1az/6lC8Tmd6BcvyarPc8FWoSxsV/WRr5NLs1v+kjlE= X-Endpoint-Received: by B4 Relay for 5mghybrid@khu.ac.kr/kernel-20260913 with auth_id=1028 X-Original-From: Kim Wooseok <5mghybrid@khu.ac.kr> Reply-To: 5mghybrid@khu.ac.kr From: Kim Wooseok <5mghybrid@khu.ac.kr> When usb_submit_urb() fails, rtl8xxxu_submit_rx_urb() unanchors the URB but leaves the newly allocated skb in urb.context. For ENOMEM/EAGAIN, the RX worker puts the request back on the pending list. The next submission allocates another skb and overwrites that pointer, leaking the previous buffer. Stopping before the retry also leaks it, because pending-list cleanup frees only the URB. Free the skb and clear urb.context in rtl8xxxu_submit_rx_urb() when submission fails. This keeps buffer allocation and failure cleanup in the same function, so a request returned for retry or teardown no longer owns an skb. Remove the corresponding cleanup from start and the RX worker; they only need to decide whether to retry or free the URB. Fixes: 26f1fad29ad9 ("New driver: rtl8xxxu (mac80211)") Reviewed-by: Ping-Ke Shih Assisted-by: GPT-6 Astra Signed-off-by: Kim Wooseok <5mghybrid@khu.ac.kr> --- drivers/net/wireless/realtek/rtl8xxxu/core.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wir= eless/realtek/rtl8xxxu/core.c index bddbd0990de72..795a5ec2f8cd4 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c @@ -5864,7 +5864,6 @@ static void rtl8xxxu_rx_urb_work(struct work_struct *= work) struct rtl8xxxu_priv *priv; struct rtl8xxxu_rx_urb *rx_urb, *tmp; struct list_head local; - struct sk_buff *skb; unsigned long flags; int ret; =20 @@ -5896,8 +5895,6 @@ static void rtl8xxxu_rx_urb_work(struct work_struct *= work) default: dev_warn(&priv->udev->dev, "failed to requeue urb with error %i\n", ret); - skb =3D (struct sk_buff *)rx_urb->urb.context; - dev_kfree_skb(skb); usb_free_urb(&rx_urb->urb); } } @@ -6596,8 +6593,11 @@ static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_pr= iv *priv, skb_size, rtl8xxxu_rx_complete, skb); usb_anchor_urb(&rx_urb->urb, &priv->rx_anchor); ret =3D usb_submit_urb(&rx_urb->urb, GFP_ATOMIC); - if (ret) + if (ret) { usb_unanchor_urb(&rx_urb->urb); + dev_kfree_skb(skb); + rx_urb->urb.context =3D NULL; + } return ret; } =20 @@ -7410,7 +7410,6 @@ static int rtl8xxxu_start(struct ieee80211_hw *hw) struct rtl8xxxu_priv *priv =3D hw->priv; struct rtl8xxxu_rx_urb *rx_urb; struct rtl8xxxu_tx_urb *tx_urb; - struct sk_buff *skb; unsigned long flags; int ret, i; =20 @@ -7461,13 +7460,8 @@ static int rtl8xxxu_start(struct ieee80211_hw *hw) rx_urb->hw =3D hw; =20 ret =3D rtl8xxxu_submit_rx_urb(priv, rx_urb); - if (ret) { - if (ret !=3D -ENOMEM) { - skb =3D (struct sk_buff *)rx_urb->urb.context; - dev_kfree_skb(skb); - } + if (ret) rtl8xxxu_queue_rx_urb(priv, rx_urb); - } } =20 schedule_delayed_work(&priv->ra_watchdog, 2 * HZ); --=20 2.53.0 From nobody Thu Sep 24 20:37:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4C5D844F552; Mon, 21 Sep 2026 07:59:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789977592; cv=none; b=t1mdX92VGnGEbElfF3yBxHFV5DcI16fUJPekG4cw/41Q+3FV7mQfZTwXBXu8NN6EowHL5TM1kac5XHo7/oM0V8AyYS/X80aSYUNmwp2LInwGNge6Nb9Jgy3IE86eDOGyNSxW69ldia8p+dMJX8/x4LDCokkt/h+n6/iUcmvbOeA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789977592; c=relaxed/simple; bh=etVa3vvxQb0DqOYjNEk8LqD09ZYI1Oe/HMz9BJjINjM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=RaNtNRKJxFnLL4SaxkOBbN/3eTmJ9rpo3TQmPssTASOIfzDjf679jqbXIKLm1BM5OR9IB+4LadHGB8XxgHlBHmpGYsq4xFTRLwzK4mHvBB+GBjGsZ4hDG5yzV10aGzadpL/WQ7Yf4hVMYcvIf51kpt2zY2lWiSAsVldKWzCEx08= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ypimg5Sz; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ypimg5Sz" Received: by smtp.kernel.org (Postfix) with ESMTPS id 0AE58C2BCFC; Mon, 21 Sep 2026 07:59:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1789977592; bh=etVa3vvxQb0DqOYjNEk8LqD09ZYI1Oe/HMz9BJjINjM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Ypimg5Szn5B70rFkfvVBjBrIOUqXnAsnboydy2+9gyHbuJj/C7nuEJgVqSwmkxnfe FATdgOjhEWTnf7pv5aJf5kYlQJta4sTn+3Svme2+4v2inu4SVqwC43DsIkbNV3bPKc TSXfTFif5M3XOSoiBEg4Du9FsWIBiHviShP6LEBy7dxad1GuRLIAjSPgk9/Qdp3eQM XcmRQ1ESsG3ZzCSvDSqUALRmuHtXN3dG61K27p4oqA9I9eGs+W2vNhb5X5x3nhZtIa sb+c7Mru10dvG1K3RQVkkQ3Dc8zT9DJ1lhOUKxFUUA0SiKeYckEK/DQ79PiLNgSmA6 7xCDPOhqEck8w== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id E1844C982E1; Mon, 21 Sep 2026 07:59:51 +0000 (UTC) From: Kim Wooseok via B4 Relay Date: Mon, 21 Sep 2026 16:59:50 +0900 Subject: [PATCH rtw-next v4 2/3] wifi: rtl8xxxu: unwind incomplete receive startup Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260921-codex-rtl-rx-v3-submit-v4-2-eeb09fe8f791@khu.ac.kr> References: <20260921-codex-rtl-rx-v3-submit-v4-0-eeb09fe8f791@khu.ac.kr> In-Reply-To: <20260921-codex-rtl-rx-v3-submit-v4-0-eeb09fe8f791@khu.ac.kr> To: linux-wireless@vger.kernel.org Cc: Ping-Ke Shih , Jes Sorensen , Kalle Valo , linux-kernel@vger.kernel.org, Kim Wooseok <5mghybrid@khu.ac.kr> X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1789977589; l=6740; i=5mghybrid@khu.ac.kr; s=kernel-20260913; h=from:subject:message-id; bh=YdHeSuY+PK9w5uA/U1vQIeOMy/apsNeEOgCqC4q9uno=; b=qWXJ6SjSrLw3RDOl8pjWS/UBbFZNJaWmE4j4Aicjm2P0T4MWtaGXcGT1BL9G5Ol2GjQdwv4wv WVbbikfAv+JBMOYn6wXoWSqYkOVKVvrYQ+C7InGQvcNPGW8ho0LKfwx X-Developer-Key: i=5mghybrid@khu.ac.kr; a=ed25519; pk=1az/6lC8Tmd6BcvyarPc8FWoSxsV/WRr5NLs1v+kjlE= X-Endpoint-Received: by B4 Relay for 5mghybrid@khu.ac.kr/kernel-20260913 with auth_id=1028 X-Original-From: Kim Wooseok <5mghybrid@khu.ac.kr> Reply-To: 5mghybrid@khu.ac.kr From: Kim Wooseok <5mghybrid@khu.ac.kr> rtl8xxxu_start() allocates and submits RX URBs one at a time. If a later allocation fails, the error path frees the TX pool but leaves earlier RX requests active. A partial TX or RX allocation failure can also leave ret at zero, so start reports success despite the incomplete setup. Allocate the RX pool before submitting any of it, and return ENOMEM whenever a pool allocation fails. Pass start errors through rtl8xxxu_stop(), including interrupt URB submission failures, so the existing stop path cancels work and releases both active requests and partially allocated pools. Share the submission loop with the RX worker. Both callers keep requests that fail with ENOMEM/EAGAIN. For a fatal error during startup, free the rest of the unsubmitted batch and return the error so start can unwind. In the worker, free only the failed request and continue with the rest of the batch. Keep the allocation loop in a small helper so the setup and error paths in start remain easy to follow. On an RTL8192EU, I exercised every error exit in rtl8xxxu_start() except interrupt-URB allocation and submission failures, which this adapter does not use. Fixes: 26f1fad29ad9 ("New driver: rtl8xxxu (mac80211)") Assisted-by: GPT-6 Astra Reviewed-by: Ping-Ke Shih Signed-off-by: Kim Wooseok <5mghybrid@khu.ac.kr> --- drivers/net/wireless/realtek/rtl8xxxu/core.c | 96 ++++++++++++++++--------= ---- 1 file changed, 54 insertions(+), 42 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wir= eless/realtek/rtl8xxxu/core.c index 795a5ec2f8cd4..5cd6498cc47f2 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c @@ -58,6 +58,7 @@ MODULE_PARM_DESC(dma_agg_pages, "Set DMA aggregation page= s (range 1-127, 0 to di #define RTL8XXXU_TX_URB_LOW_WATER 25 #define RTL8XXXU_TX_URB_HIGH_WATER 32 =20 +static void rtl8xxxu_stop(struct ieee80211_hw *hw, bool suspend); static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv, struct rtl8xxxu_rx_urb *rx_urb); =20 @@ -5832,6 +5833,28 @@ static void rtl8xxxu_free_rx_resources(struct rtl8xx= xu_priv *priv) spin_unlock_irqrestore(&priv->rx_urb_lock, flags); } =20 +static int rtl8xxxu_alloc_rx_urbs(struct rtl8xxxu_priv *priv) +{ + struct rtl8xxxu_rx_urb *rx_urb; + int i; + + /* No RX work is active until the complete pool has been allocated. */ + for (i =3D 0; i < RTL8XXXU_RX_URBS; i++) { + rx_urb =3D kmalloc_obj(struct rtl8xxxu_rx_urb); + if (!rx_urb) + return -ENOMEM; + + usb_init_urb(&rx_urb->urb); + INIT_LIST_HEAD(&rx_urb->list); + rx_urb->hw =3D priv->hw; + + list_add_tail(&rx_urb->list, &priv->rx_urb_pending_list); + priv->rx_urb_pending_count++; + } + + return 0; +} + static void rtl8xxxu_queue_rx_urb(struct rtl8xxxu_priv *priv, struct rtl8xxxu_rx_urb *rx_urb) { @@ -5859,32 +5882,21 @@ static void rtl8xxxu_queue_rx_urb(struct rtl8xxxu_p= riv *priv, spin_unlock_irqrestore(&priv->rx_urb_lock, flags); } =20 -static void rtl8xxxu_rx_urb_work(struct work_struct *work) +static int rtl8xxxu_submit_rx_urbs(struct rtl8xxxu_priv *priv, bool startu= p) { - struct rtl8xxxu_priv *priv; struct rtl8xxxu_rx_urb *rx_urb, *tmp; - struct list_head local; unsigned long flags; + LIST_HEAD(local); int ret; =20 - priv =3D container_of(work, struct rtl8xxxu_priv, rx_urb_wq); - INIT_LIST_HEAD(&local); - spin_lock_irqsave(&priv->rx_urb_lock, flags); - list_splice_init(&priv->rx_urb_pending_list, &local); priv->rx_urb_pending_count =3D 0; - spin_unlock_irqrestore(&priv->rx_urb_lock, flags); =20 list_for_each_entry_safe(rx_urb, tmp, &local, list) { list_del_init(&rx_urb->list); ret =3D rtl8xxxu_submit_rx_urb(priv, rx_urb); - /* - * If out of memory or temporary error, put it back on the - * queue and try again. Otherwise the device is dead/gone - * and we should drop it. - */ switch (ret) { case 0: break; @@ -5893,11 +5905,29 @@ static void rtl8xxxu_rx_urb_work(struct work_struct= *work) rtl8xxxu_queue_rx_urb(priv, rx_urb); break; default: + usb_free_urb(&rx_urb->urb); + if (startup) + goto free_remaining; dev_warn(&priv->udev->dev, "failed to requeue urb with error %i\n", ret); - usb_free_urb(&rx_urb->urb); } } + + return 0; + +free_remaining: + list_for_each_entry_safe(rx_urb, tmp, &local, list) { + list_del(&rx_urb->list); + usb_free_urb(&rx_urb->urb); + } + return ret; +} + +static void rtl8xxxu_rx_urb_work(struct work_struct *work) +{ + struct rtl8xxxu_priv *priv =3D container_of(work, struct rtl8xxxu_priv, r= x_urb_wq); + + rtl8xxxu_submit_rx_urbs(priv, false); } =20 /* @@ -7408,7 +7438,6 @@ static void rtl8xxxu_watchdog_callback(struct work_st= ruct *work) static int rtl8xxxu_start(struct ieee80211_hw *hw) { struct rtl8xxxu_priv *priv =3D hw->priv; - struct rtl8xxxu_rx_urb *rx_urb; struct rtl8xxxu_tx_urb *tx_urb; unsigned long flags; int ret, i; @@ -7423,14 +7452,13 @@ static int rtl8xxxu_start(struct ieee80211_hw *hw) if (priv->usb_interrupts) { ret =3D rtl8xxxu_submit_int_urb(hw); if (ret) - goto exit; + goto error_out; } =20 for (i =3D 0; i < RTL8XXXU_TX_URBS; i++) { tx_urb =3D kmalloc_obj(struct rtl8xxxu_tx_urb); if (!tx_urb) { - if (!i) - ret =3D -ENOMEM; + ret =3D -ENOMEM; =20 goto error_out; } @@ -7441,31 +7469,21 @@ static int rtl8xxxu_start(struct ieee80211_hw *hw) priv->tx_urb_free_count++; } =20 + ret =3D rtl8xxxu_alloc_rx_urbs(priv); + if (ret) + goto error_out; + priv->tx_stopped =3D false; =20 spin_lock_irqsave(&priv->rx_urb_lock, flags); priv->shutdown =3D false; spin_unlock_irqrestore(&priv->rx_urb_lock, flags); =20 - for (i =3D 0; i < RTL8XXXU_RX_URBS; i++) { - rx_urb =3D kmalloc_obj(struct rtl8xxxu_rx_urb); - if (!rx_urb) { - if (!i) - ret =3D -ENOMEM; - - goto error_out; - } - usb_init_urb(&rx_urb->urb); - INIT_LIST_HEAD(&rx_urb->list); - rx_urb->hw =3D hw; - - ret =3D rtl8xxxu_submit_rx_urb(priv, rx_urb); - if (ret) - rtl8xxxu_queue_rx_urb(priv, rx_urb); - } + ret =3D rtl8xxxu_submit_rx_urbs(priv, true); + if (ret) + goto error_out; =20 schedule_delayed_work(&priv->ra_watchdog, 2 * HZ); -exit: /* * Accept all data and mgmt frames */ @@ -7478,13 +7496,7 @@ static int rtl8xxxu_start(struct ieee80211_hw *hw) return ret; =20 error_out: - rtl8xxxu_free_tx_resources(priv); - /* - * Disable all data and mgmt frames - */ - rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0x0000); - rtl8xxxu_write16(priv, REG_RXFLTMAP0, 0x0000); - + rtl8xxxu_stop(hw, false); return ret; } =20 --=20 2.53.0 From nobody Thu Sep 24 20:37:27 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 49EE244F54F; Mon, 21 Sep 2026 07:59:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789977592; cv=none; b=GeF6kUX6DJSL80iMO5dPpxnXR/mM0f2qYa1OiPrY64nvyLI/Kpt8y+tE7KcXvZoiciseX9+NcnFBMrm/EmMew7Iy+mUwet96sbLVIMF23anyImp8Eg+Wcuz73dXEqXf7IHhEAiKqHW7uoSl3qINNNh+FLaKjtrYnUJXX3mUYDw0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789977592; c=relaxed/simple; bh=YzeRJI+k51HfWcyQp+4KPivjBZtcOJ98l1A4EKDeL6o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cdWSEr1vsjb6fx6oxfVsT7gSzDf/OorEhtgFt1t2DqBuUPVPVNaiLdUaL0NbOI5IRtRxMZ1E6YScz2JAiF1KHkV5+/d7Lh4rMFVvl5e9x5mCAUi5gQY7F/HX32BUuDC+X/pne1C2PK5wr8MU3g1MFMazDn1WehheJrFcBMYxCWk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KaH6Mfln; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="KaH6Mfln" Received: by smtp.kernel.org (Postfix) with ESMTPS id 177B8C2BCFD; Mon, 21 Sep 2026 07:59:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1789977592; bh=YzeRJI+k51HfWcyQp+4KPivjBZtcOJ98l1A4EKDeL6o=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=KaH6MflnuvLkAnFTDDAdcXjYv2Qj3/cZvmAg/J5vb1G2yix4mYhM1QqwwpYn9U3ZK WIFD35oGeKllX3L/XDfIjZocAoQQQ0so9nl7fcbFnYW8CpDHKzpA9SzU9nDMNN1RHi MtYG8i2bw2/kTq57ixhO2XYjjPTm4JR+wBTZH71JFIPBByjDNAYxv0rrkzUFDl21Ml LVSiDrFABVykhcetuCi38AIszf/XVodi6C9pXwi6yIuEO7wQ/VV9z5Nu+cR5GVPzGv b18ZZmApZMc2Cqb5xM+g0b5BDBlhXs02GFz0OP+bHqwpX42rQM8rPd7LweB1Ualo6C jzzm3AvExBcDw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id F2FE1C982F6; Mon, 21 Sep 2026 07:59:51 +0000 (UTC) From: Kim Wooseok via B4 Relay Date: Mon, 21 Sep 2026 16:59:51 +0900 Subject: [PATCH rtw-next v4 3/3] wifi: rtl8xxxu: preserve RX requests across recoverable transfer errors Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260921-codex-rtl-rx-v3-submit-v4-3-eeb09fe8f791@khu.ac.kr> References: <20260921-codex-rtl-rx-v3-submit-v4-0-eeb09fe8f791@khu.ac.kr> In-Reply-To: <20260921-codex-rtl-rx-v3-submit-v4-0-eeb09fe8f791@khu.ac.kr> To: linux-wireless@vger.kernel.org Cc: Ping-Ke Shih , Jes Sorensen , Kalle Valo , linux-kernel@vger.kernel.org, Kim Wooseok <5mghybrid@khu.ac.kr> X-Mailer: b4 0.16.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1789977589; l=6556; i=5mghybrid@khu.ac.kr; s=kernel-20260913; h=from:subject:message-id; bh=s5LeAHyjThLc6mAtyZ76vXgD5nPgBRiYvXbrCmu0990=; b=YObtkdvOMk+XG1WWAVnXkHgOmGgdoUHXvEkcPBMAUaJMcqBe2K2HJdatthNn8lrllh7AB6Cx6 dkFEgSu1Ca6C8FvlVTohaqf6UYgrL//bDqu+AUq8e5WL7nkaiUDVAhw X-Developer-Key: i=5mghybrid@khu.ac.kr; a=ed25519; pk=1az/6lC8Tmd6BcvyarPc8FWoSxsV/WRr5NLs1v+kjlE= X-Endpoint-Received: by B4 Relay for 5mghybrid@khu.ac.kr/kernel-20260913 with auth_id=1028 X-Original-From: Kim Wooseok <5mghybrid@khu.ac.kr> Reply-To: 5mghybrid@khu.ac.kr From: Kim Wooseok <5mghybrid@khu.ac.kr> rtl8xxxu resubmits completed RX requests when more than eight URBs are waiting on the pending list. It starts with 32 URBs, but frees them on completion errors. After enough errors, the remaining pool can no longer reach the submission threshold. Reception then stays stopped even after the errors end. Temporary submission failures can leave a small batch waiting with no further work scheduled, too. Keep the URB when a completion reports EPROTO, EILSEQ, ETIME, EOVERFLOW, ECOMM or ENOSR. Free its receive buffer and return the request to the same pending list used by normal completions. ENOMEM/EAGAIN from startup or worker submission uses this path as well, so a submission failure cannot strand a request during recovery. Use one delayed work item to submit the pending requests. An error queues a retry after 100 ms without moving an existing reservation back. If a normal completion takes the pending count above eight, mod_delayed_work(..., 0) brings the work forward. This limits repeated retries when reception is not progressing, while allowing normal traffic to replenish the pool promptly. The 100 ms delay is therefore not a minimum wait for each failed URB. Keep the shutdown check, queue insertion and scheduling under the RX lock. Stop sets shutdown under that lock, cancels the delayed work synchronously, then drains active and pending requests. Cancellation and device removal continue to free their URBs. Fixes: 26f1fad29ad9 ("New driver: rtl8xxxu (mac80211)") Assisted-by: GPT-6 Astra Signed-off-by: Kim Wooseok <5mghybrid@khu.ac.kr> Reviewed-by: Ping-Ke Shih --- drivers/net/wireless/realtek/rtl8xxxu/core.c | 46 +++++++++++++++-----= ---- drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h | 2 +- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wir= eless/realtek/rtl8xxxu/core.c index 5cd6498cc47f2..3d0c22db30a80 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c @@ -54,6 +54,7 @@ MODULE_PARM_DESC(dma_agg_pages, "Set DMA aggregation page= s (range 1-127, 0 to di #define USB_VENDOR_ID_REALTEK 0x0bda #define RTL8XXXU_RX_URBS 32 #define RTL8XXXU_RX_URB_PENDING_WATER 8 +#define RTL8XXXU_RX_URB_RETRY_DELAY_MS 100 #define RTL8XXXU_TX_URBS 64 #define RTL8XXXU_TX_URB_LOW_WATER 25 #define RTL8XXXU_TX_URB_HIGH_WATER 32 @@ -5856,9 +5857,8 @@ static int rtl8xxxu_alloc_rx_urbs(struct rtl8xxxu_pri= v *priv) } =20 static void rtl8xxxu_queue_rx_urb(struct rtl8xxxu_priv *priv, - struct rtl8xxxu_rx_urb *rx_urb) + struct rtl8xxxu_rx_urb *rx_urb, bool defer_schedule) { - struct sk_buff *skb; unsigned long flags; =20 spin_lock_irqsave(&priv->rx_urb_lock, flags); @@ -5866,16 +5866,13 @@ static void rtl8xxxu_queue_rx_urb(struct rtl8xxxu_p= riv *priv, if (!priv->shutdown) { list_add_tail(&rx_urb->list, &priv->rx_urb_pending_list); priv->rx_urb_pending_count++; - /* - * Arm the worker under rx_urb_lock so this is atomic with the - * shutdown check: moving it out of the lock would let a - * completion arm the work after rtl8xxxu_stop() canceled it. - */ - if (priv->rx_urb_pending_count > RTL8XXXU_RX_URB_PENDING_WATER) - schedule_work(&priv->rx_urb_wq); + /* Serialize scheduling with the shutdown check and cancellation. */ + if (defer_schedule) + schedule_delayed_work(&priv->rx_urb_wq, + msecs_to_jiffies(RTL8XXXU_RX_URB_RETRY_DELAY_MS)); + else if (priv->rx_urb_pending_count > RTL8XXXU_RX_URB_PENDING_WATER) + mod_delayed_work(system_percpu_wq, &priv->rx_urb_wq, 0); } else { - skb =3D (struct sk_buff *)rx_urb->urb.context; - dev_kfree_skb_irq(skb); usb_free_urb(&rx_urb->urb); } =20 @@ -5902,7 +5899,7 @@ static int rtl8xxxu_submit_rx_urbs(struct rtl8xxxu_pr= iv *priv, bool startup) break; case -ENOMEM: case -EAGAIN: - rtl8xxxu_queue_rx_urb(priv, rx_urb); + rtl8xxxu_queue_rx_urb(priv, rx_urb, true); break; default: usb_free_urb(&rx_urb->urb); @@ -5925,7 +5922,8 @@ static int rtl8xxxu_submit_rx_urbs(struct rtl8xxxu_pr= iv *priv, bool startup) =20 static void rtl8xxxu_rx_urb_work(struct work_struct *work) { - struct rtl8xxxu_priv *priv =3D container_of(work, struct rtl8xxxu_priv, r= x_urb_wq); + struct rtl8xxxu_priv *priv =3D container_of(to_delayed_work(work), + struct rtl8xxxu_priv, rx_urb_wq); =20 rtl8xxxu_submit_rx_urbs(priv, false); } @@ -6585,10 +6583,24 @@ static void rtl8xxxu_rx_complete(struct urb *urb) =20 skb =3D NULL; rx_urb->urb.context =3D NULL; - rtl8xxxu_queue_rx_urb(priv, rx_urb); + rtl8xxxu_queue_rx_urb(priv, rx_urb, false); } else { dev_dbg(dev, "%s: status %i\n", __func__, urb->status); - goto cleanup; + + switch (urb->status) { + case -EPROTO: + case -EILSEQ: + case -ETIME: + case -EOVERFLOW: + case -ECOMM: + case -ENOSR: + dev_kfree_skb(skb); + urb->context =3D NULL; + rtl8xxxu_queue_rx_urb(priv, rx_urb, true); + return; + default: + goto cleanup; + } } return; =20 @@ -7519,7 +7531,7 @@ static void rtl8xxxu_stop(struct ieee80211_hw *hw, bo= ol suspend) * it drained via rtl8xxxu_submit_rx_urb(), so a worker still running * after the kill could submit a URB that escapes it. */ - cancel_work_sync(&priv->rx_urb_wq); + cancel_delayed_work_sync(&priv->rx_urb_wq); =20 usb_kill_anchored_urbs(&priv->rx_anchor); usb_kill_anchored_urbs(&priv->tx_anchor); @@ -7832,7 +7844,7 @@ static int rtl8xxxu_probe(struct usb_interface *inter= face, spin_lock_init(&priv->tx_urb_lock); INIT_LIST_HEAD(&priv->rx_urb_pending_list); spin_lock_init(&priv->rx_urb_lock); - INIT_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work); + INIT_DELAYED_WORK(&priv->rx_urb_wq, rtl8xxxu_rx_urb_work); INIT_DELAYED_WORK(&priv->ra_watchdog, rtl8xxxu_watchdog_callback); INIT_DELAYED_WORK(&priv->update_beacon_work, rtl8xxxu_update_beacon_work_= callback); skb_queue_head_init(&priv->c2hcmd_queue); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net= /wireless/realtek/rtl8xxxu/rtl8xxxu.h index eeb18eb0e4c0f..c6953051d9c40 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -1809,7 +1809,7 @@ struct rtl8xxxu_priv { struct list_head rx_urb_pending_list; int rx_urb_pending_count; bool shutdown; - struct work_struct rx_urb_wq; + struct delayed_work rx_urb_wq; =20 u8 mac_addr[ETH_ALEN]; char chip_name[8]; --=20 2.53.0