* Re: [PATCH net v2] ipv6: addrconf: skip ERRDAD transition when address already DEAD
From: Sabrina Dubroca @ 2026-04-22 10:43 UTC (permalink / raw)
To: Linmao Li
Cc: davem, dsahern, edumazet, kuba, pabeni, horms, netdev,
linux-kernel
In-Reply-To: <20260421075033.1110816-1-lilinmao@kylinos.cn>
2026-04-21, 15:50:33 +0800, Linmao Li wrote:
> addrconf_dad_end() transitions ifp->state from DAD to POSTDAD under
> ifp->lock and releases the lock. addrconf_dad_failure() takes
> ifp->lock again with the spin_lock_bh() following the
> net_info_ratelimited() duplicate-address log. A concurrent
> ipv6_del_addr() can acquire the lock in that window, set ifp->state
> to DEAD and run list_del_rcu(&ifp->if_list).
You're pretty much saying that the ifp->state check we did in
addrconf_dad_end before dropping the lock is not valid, so it seems we
should just skip that separate check since it's not doing anything
useful, and move it under the "main" lock we acquire after the
net_info_ratelimited(). There would still be a problem with "we
dropped the lock in the STABLE_PRIVACY block", which your patch
handles.
> addrconf_dad_failure() then overwrites DEAD with ERRDAD at errdad:
> and schedules a new dad_work. The work calls ipv6_del_addr() again,
> hitting the already-poisoned list entry:
>
> general protection fault: 0000 [#1] SMP NOPTI
> CPU: 4 PID: 217 Comm: kworker/4:1
> Workqueue: ipv6_addrconf addrconf_dad_work
> RIP: 0010:ipv6_del_addr+0xe9/0x280
> RAX: dead000000000122
> Call Trace:
> addrconf_dad_stop+0x113/0x140
> addrconf_dad_work+0x28c/0x430
> process_one_work+0x1eb/0x3b0
> worker_thread+0x4d/0x400
> kthread+0x104/0x140
> ret_from_fork+0x35/0x40
>
> Bail out at errdad: when ifp->state is already DEAD. The existing
> in6_ifa_put() releases the reference taken for this invocation.
Mentioning "the existing in6_ifa_put()" is a bit confusing since
you're adding a separate unlock/put/return path.
--
Sabrina
^ permalink raw reply
* Re: Bug#1130336: [regression] Network failure beyond first connection after 69894e5b4c5e ("netfilter: nft_connlimit: update the count if add was skipped")
From: Fernando Fernandez Mancera @ 2026-04-22 10:32 UTC (permalink / raw)
To: Thorsten Leemhuis, Alejandro Oliván Alvarez,
Salvatore Bonaccorso, 1130336
Cc: Florian Westphal, Pablo Neira Ayuso, Phil Sutter, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
netfilter-devel, coreteam, netdev, linux-kernel, regressions,
stable
In-Reply-To: <0b8607c8-2d29-4fca-961a-b7a677e968a1@leemhuis.info>
On 4/22/26 11:18 AM, Thorsten Leemhuis wrote:
> Lo! Top-posting on purpose to make this easy to process.
>
> What happened to this regression? It looks a bit like things stalled and
> fell through the cracks. Or Fernando, did you post a patch like you
> mentioned? I looked for one referring the commit or the reporter, but
> could not find anything -- but maybe I missed it.
>
Yes, it stalled and fell through the cracks. Let me prepare a fix as I
mentioned.
Thanks for the reminder Thorsten!
> Ciao, Thorsten
>
> On 3/19/26 09:59, Fernando Fernandez Mancera wrote:
>> On 3/19/26 9:44 AM, Alejandro Oliván Alvarez wrote:
>>> Hi folks.
>>>
>>> On Wed, 2026-03-18 at 13:49 +0100, Salvatore Bonaccorso wrote:
>>>> Hi Alejandro,
>>>>
>>>> On Sun, Mar 15, 2026 at 02:09:33AM +0100, Fernando Fernandez Mancera
>>>> wrote:
>>>>> On 3/14/26 8:25 PM, Florian Westphal wrote:
>>>>>> Fernando Fernandez Mancera <fmancera@suse.de> wrote:
>>>>>>> On 3/14/26 5:13 PM, Fernando Fernandez Mancera wrote:
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> On 3/14/26 3:03 PM, Salvatore Bonaccorso wrote:
>>>>>>>>> Control: forwarded -1
>>>>>>>>> https://lore.kernel.org/
>>>>>>>>> regressions/177349610461.3071718.4083978280323144323@eldama
>>>>>>>>> r.lan
>>>>>>>>> Control: tags -1 + upstream
>>>>>>>>>
>>>>>>>>> Hi
>>>>>>>>>
>>>>>>>>> In Debian, in https://bugs.debian.org/1130336, Alejandro
>>>>>>>>> reported that
>>>>>>>>> after updates including 69894e5b4c5e ("netfilter:
>>>>>>>>> nft_connlimit:
>>>>>>>>> update the count if add was skipped"), when the following
>>>>>>>>> rule is set
>>>>>>>>>
>>>>>>>>> iptables -A INPUT -p tcp -m
>>>>>>>>> connlimit --connlimit-above 111 -j
>>>>>>>>> REJECT --reject-with tcp-reset
>>>>>>>>>
>>>>>>>>> connections get stuck accordingly, it can be easily
>>>>>>>>> reproduced by:
>>>>>>>>>
>>>>>>>>> # iptables -A INPUT -p tcp -m connlimit
>>>>>>>>> --connlimit-above 111 -j REJECT
>>>>>>>>> --reject-with tcp-reset
>>>>>>>>> # nft list ruleset
>>>>>>>>> # Warning: table ip filter is managed by iptables-nft, do
>>>>>>>>> not touch!
>>>>>>>>> table ip filter {
>>>>>>>>> chain INPUT {
>>>>>>>>> type filter hook input priority filter;
>>>>>>>>> policy accept;
>>>>>>>>> ip protocol tcp xt
>>>>>>>>> match "connlimit" counter packets 0
>>>>>>>>> bytes 0 reject with tcp reset
>>>>>>>>> }
>>>>>>>>> }
>>>>>>>>> # wget -O /dev/null
>>>>>>>>> https://git.kernel.org/torvalds/t/linux-7.0-
>>>>>>>>> rc3.tar.gz
>>>>>>>>> --2026-03-14 14:53:51--
>>>>>>>>> https://git.kernel.org/torvalds/t/linux-7.0-
>>>>>>>>> rc3.tar.gz
>>>>>>>>> Resolving git.kernel.org
>>>>>>>>> (git.kernel.org)... 172.105.64.184,
>>>>>>>>> 2a01:7e01:e001:937:0:1991:8:25
>>>>>>>>> Connecting to git.kernel.org
>>>>>>>>> (git.kernel.org)|172.105.64.184|:443...
>>>>>>>>> connected.
>>>>>>>>> HTTP request sent, awaiting response... 301 Moved
>>>>>>>>> Permanently
>>>>>>>>> Location:
>>>>>>>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/
>>>>>>>>> linux.git/snapshot/linux-7.0-rc3.tar.gz
>>>>>>>>> [following]
>>>>>>>>> --2026-03-14 14:53:51--
>>>>>>>>> https://git.kernel.org/pub/scm/linux/kernel/ git/torvalds/l
>>>>>>>>> inux.git/snapshot/linux-7.0-rc3.tar.gz
>>>>>>>>> Reusing existing connection to git.kernel.org:443.
>>>>>>>>> HTTP request sent, awaiting response... 200 OK
>>>>>>>>> Length: unspecified [application/x-gzip]
>>>>>>>>> Saving to: ‘/dev/null’
>>>>>>>>>
>>>>>>>>> /dev/null [
>>>>>>>>> <=> ] 248.03M
>>>>>>>>> 51.9MB/s in 5.0s
>>>>>>>>>
>>>>>>>>> 2026-03-14 14:53:56 (49.3 MB/s) - ‘/dev/null’ saved
>>>>>>>>> [260080129]
>>>>>>>>>
>>>>>>>>> # wget -O /dev/null
>>>>>>>>> https://git.kernel.org/torvalds/t/linux-7.0-
>>>>>>>>> rc3.tar.gz
>>>>>>>>> --2026-03-14 14:53:58--
>>>>>>>>> https://git.kernel.org/torvalds/t/linux-7.0-
>>>>>>>>> rc3.tar.gz
>>>>>>>>> Resolving git.kernel.org
>>>>>>>>> (git.kernel.org)... 172.105.64.184,
>>>>>>>>> 2a01:7e01:e001:937:0:1991:8:25
>>>>>>>>> Connecting to git.kernel.org
>>>>>>>>> (git.kernel.org)|172.105.64.184|:443...
>>>>>>>>> failed: Connection timed out.
>>>>>>>>> Connecting to git.kernel.org
>>>>>>>>> (git.kernel.org)|
>>>>>>>>> 2a01:7e01:e001:937:0:1991:8:25|:443...
>>>>>>>>> failed: Network is unreachable.
>>>>>>>>>
>>>>>>>>> Before the 69894e5b4c5e ("netfilter: nft_connlimit: update
>>>>>>>>> the count
>>>>>>>>> if add was skipped") commit this worked.
>>>>>>>>>
>>>>>>>>
>>>>>>>> Thanks for the report. I have reproduced
>>>>>>>> this on upstream kernel. I am working on it.
>>>>>>>>
>>>>>>>
>>>>>>> This is what is happening:
>>>>>>>
>>>>>>> 1. The first connection is established and
>>>>>>> tracked, all good. When it finishes, it goes to
>>>>>>> TIME_WAIT state
>>>>>>> 2. The second connection is established, ct is
>>>>>>> confirmed since the beginning, skipping the
>>>>>>> tracking and calling a GC.
>>>>>>> 3. The previously tracked connection is cleaned
>>>>>>> up during GC as TIME_WAIT is considered closed.
>>>>>>
>>>>>> This is stupid. The fix is to add --syn or use
>>>>>> OUTPUT. Its not even clear to me what the user wants to achive
>>>>>> with this rule.
>>>>>>
>>>>>
>>>>> Yes, the ruleset shown does not make sense. Having said this, it
>>>>> could
>>>>> affect to a soft-limit scenario as the one described on the blamed
>>>>> commit..
>>>>
>>>> Alejandro, can you describe what you would like to achieve with the
>>>> specific rule?
>>>>
>>>> Regards,
>>>> Salvatore
>>>
>>> The intended use of that rule was to prevent (limit) a single host from
>>> establishing too many TCP connections to given host (Denial of
>>> Service... particularly on streaming servers).
>>>
>>> I learnt about it in several IPtables guides/howtos (maaaany years
>>> ago!), and never was an issue on itself.
>>> Was it stupid? ... possibly... It 'seemed' to work, or, at least, when
>>> checking iptables -L -v one could see packet counter for the rule
>>> catching some traffic, without ever noticing it being troublesome, so,
>>> at the very least it 'didn't hurt', and, since DoS ever happened over
>>> the years...well, I tended to think it was indeed working the way I
>>> read it did.
>>>
>>> Certainly, I never (the authors of those guides at their time indeed)
>>> though about the possibility of just target the TCP syn.
>>> I have given a try to adding the --syn option to the rule to see the
>>> difference, and well, it is way less disruptive that way, but it still
>>> breaks things (I saw postfix queues hanging, for instance).
>>>
>>
>> The current problem with the ruleset is that it mixes both, incoming and
>> outgoing connections. This should probably use --syn flag so it targets
>> connections established against your host only.
>>
>> Anyway, I am sending a patch fixing this as it makes sense to do it IMO.
>> We just want to understand what is the real use-case and how the ruleset
>> can be improved.
>>
>> In addition, I would recommend you to transition to nftables because it
>> would be ideal for your use-case. With nftables it would be easy to
>> combine this with sets and probably quota expression to limit the usage.
>>
>> What is wrong with the current ruleset? (Even before the blammed
>> commit), if you reach the connlimit limit **ALL** TCP connections will
>> be rejected (including legit ones), I do not think that is what you want
>> to achieve.
>>
>> Thanks,
>> Fernando.
>>
>>> So, I have but screwed the idea of using connlimit anymore anyways.
>>> Sorry for the noise. Lesson learned.
>>>
>>> Cheers!
>>
>>
>
>
^ permalink raw reply
* Re: [PATCH] dt-bindings: Fix phandle-array constraints, again
From: Krzysztof Kozlowski @ 2026-04-22 10:22 UTC (permalink / raw)
To: Rob Herring (Arm)
Cc: Maarten Lankhorst, Maxime Ripard, Krzysztof Kozlowski,
Conor Dooley, Ulf Hansson, Stephan Gerhold, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Johannes Berg, Jeff Johnson, Bjorn Helgaas, Lorenzo Pieralisi,
Krzysztof Wilczyński, Manivannan Sadhasivam, Bjorn Andersson,
Mathieu Poirier, Sylwester Nawrocki, Mark Brown, Maxime Coquelin,
Greg Kroah-Hartman, Yang Xiwen, Alex Elder, Chaitanya Chundru,
Sibi Sankar, Rao Mandadapu, Patrice Chotard, Xu Yang, Peng Fan,
Thomas Zimmermann, devicetree, linux-kernel, linux-mmc,
linux-arm-msm, netdev, linux-wireless, ath10k, ath11k, linux-pci,
linux-remoteproc, linux-sound, linux-spi, linux-usb
In-Reply-To: <20260421195836.1547469-1-robh@kernel.org>
On Tue, Apr 21, 2026 at 02:55:25PM -0500, Rob Herring (Arm) wrote:
> diff --git a/Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml b/Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml
> index b30544410d09..e47e1e09300a 100644
> --- a/Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml
> +++ b/Documentation/devicetree/bindings/net/qcom,bam-dmux.yaml
> @@ -42,7 +42,13 @@ properties:
> description: State bits used by the AP to signal the modem.
> items:
> - description: Power control
> + items:
> + - description: Phandle to ???
> + - description: ???
> - description: Power control acknowledgment
> + items:
> + - description: Phandle to ???
> + - description: ???
>
Here and in all cases except qcom,msm8916-mss-pil:
- description: Phandle to the Shared Memory Point 2 Point device
handling the communication with a remote processor
- description: Single bit index to toggle in the value sent to
the remote processor
maximum: 32
...
> diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,msm8916-mss-pil.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,msm8916-mss-pil.yaml
> index c179b560572b..3c614cb7ce88 100644
> --- a/Documentation/devicetree/bindings/remoteproc/qcom,msm8916-mss-pil.yaml
> +++ b/Documentation/devicetree/bindings/remoteproc/qcom,msm8916-mss-pil.yaml
> @@ -104,6 +104,9 @@ properties:
> description: States used by the AP to signal the Hexagon core
> items:
> - description: Stop modem
> + items:
> + - description: Phandle to ???
> + - description: ???
- description: Phandle to the Shared Memory Point 2 Point or Shared
Memory Manager device handling the communication with a remote
processor
- description: Single bit index to toggle in the value sent to
the remote processor
maximum: 32
Best regards,
Krzysztof
^ permalink raw reply
* [PATCH] NFC: trf7970a: Ignore antenna noise when checking for RF field
From: Paul Geurts @ 2026-04-22 10:09 UTC (permalink / raw)
To: mgreer, sameo, linux-wireless, netdev, linux-kernel
Cc: martijn.de.gouw, Paul Geurts
The main channel Received Signal Strength Indicator (RSSI) measurement
is used to determine whether an RF field is present or not. RSSI != 0
is interpreted as an RF Field is present. This does not take RF noise
and measurement inaccuracy into account, and results in false positives
in the field.
Define a noise level and make sure the RF field is only interpreted as
present when the RSSI is above the noise level.
Fixes: 851ee3cbf850 ("NFC: trf7970a: Don't turn on RF if there is already an RF field")
Signed-off-by: Paul Geurts <paul.geurts@prodrive-technologies.com>
---
drivers/nfc/trf7970a.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c
index d17c701c7888..08c27bb438b5 100644
--- a/drivers/nfc/trf7970a.c
+++ b/drivers/nfc/trf7970a.c
@@ -317,6 +317,7 @@
#define TRF7970A_RSSI_OSC_STATUS_RSSI_MASK (BIT(2) | BIT(1) | BIT(0))
#define TRF7970A_RSSI_OSC_STATUS_RSSI_X_MASK (BIT(5) | BIT(4) | BIT(3))
#define TRF7970A_RSSI_OSC_STATUS_RSSI_OSC_OK BIT(6)
+#define TRF7970A_RSSI_OSC_STATUS_RSSI_NOISE_LEVEL 1
#define TRF7970A_SPECIAL_FCN_REG1_COL_7_6 BIT(0)
#define TRF7970A_SPECIAL_FCN_REG1_14_ANTICOLL BIT(1)
@@ -1300,7 +1301,7 @@ static int trf7970a_is_rf_field(struct trf7970a *trf, bool *is_rf_field)
if (ret)
return ret;
- if (rssi & TRF7970A_RSSI_OSC_STATUS_RSSI_MASK)
+ if ((rssi & TRF7970A_RSSI_OSC_STATUS_RSSI_MASK) > TRF7970A_RSSI_OSC_STATUS_RSSI_NOISE_LEVEL)
*is_rf_field = true;
else
*is_rf_field = false;
--
2.39.2
^ permalink raw reply related
* [RFC PATCH net-next 2/5] net: wangxun: add Tx timeout process
From: Jiawen Wu @ 2026-04-22 9:56 UTC (permalink / raw)
To: netdev
Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
Simon Horman, Kees Cook, Larysa Zaremba, Breno Leitao, Joe Damato,
Jacob Keller, Fabio Baltieri, Jiawen Wu
In-Reply-To: <20260422095617.27080-1-jiawenwu@trustnetic.com>
Implement .ndo_tx_timeout to handle Tx side timeout event. When Tx
timeout event occur, it will triger driver into reset process.
The WX_HANG_CHECK_ARMED bit is set to indicate a potential hang. It will
be cleared if a pause frame is received to remove false hang detection
due to 802.3 frames.
Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
drivers/net/ethernet/wangxun/libwx/Makefile | 2 +-
drivers/net/ethernet/wangxun/libwx/wx_err.c | 125 ++++++++++++++++++
drivers/net/ethernet/wangxun/libwx/wx_err.h | 14 ++
drivers/net/ethernet/wangxun/libwx/wx_hw.c | 17 ++-
drivers/net/ethernet/wangxun/libwx/wx_lib.c | 37 ++++++
drivers/net/ethernet/wangxun/libwx/wx_lib.h | 1 +
drivers/net/ethernet/wangxun/libwx/wx_type.h | 12 +-
drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 4 +
.../net/ethernet/wangxun/txgbe/txgbe_main.c | 4 +
9 files changed, 211 insertions(+), 5 deletions(-)
create mode 100644 drivers/net/ethernet/wangxun/libwx/wx_err.c
create mode 100644 drivers/net/ethernet/wangxun/libwx/wx_err.h
diff --git a/drivers/net/ethernet/wangxun/libwx/Makefile b/drivers/net/ethernet/wangxun/libwx/Makefile
index a71b0ad77de3..c8724bb129aa 100644
--- a/drivers/net/ethernet/wangxun/libwx/Makefile
+++ b/drivers/net/ethernet/wangxun/libwx/Makefile
@@ -4,5 +4,5 @@
obj-$(CONFIG_LIBWX) += libwx.o
-libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o wx_ptp.o wx_mbx.o wx_sriov.o
+libwx-objs := wx_hw.o wx_lib.o wx_ethtool.o wx_ptp.o wx_mbx.o wx_sriov.o wx_err.o
libwx-objs += wx_vf.o wx_vf_lib.o wx_vf_common.o
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_err.c b/drivers/net/ethernet/wangxun/libwx/wx_err.c
new file mode 100644
index 000000000000..42e00f0bd8da
--- /dev/null
+++ b/drivers/net/ethernet/wangxun/libwx/wx_err.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2015 - 2026 Beijing WangXun Technology Co., Ltd. */
+
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+
+#include "wx_type.h"
+#include "wx_lib.h"
+#include "wx_err.h"
+
+static void wx_reset_subtask(struct wx *wx)
+{
+ if (!test_bit(WX_FLAG_NEED_PF_RESET, wx->flags))
+ return;
+
+ rtnl_lock();
+
+ if (!netif_running(wx->netdev) ||
+ test_bit(WX_STATE_RESETTING, wx->state))
+ return;
+
+ wx_warn(wx, "Reset adapter.\n");
+
+ if (test_and_clear_bit(WX_FLAG_NEED_PF_RESET, wx->flags)) {
+ if (wx->do_reset)
+ wx->do_reset(wx->netdev);
+ }
+
+ rtnl_unlock();
+}
+
+/*
+ * wx_check_tx_hang_subtask - check for hung queues and dropped interrupts
+ * @wx - pointer to the device wx structure
+ *
+ * This function serves two purposes. First it strobes the interrupt lines
+ * in order to make certain interrupts are occurring. Secondly it sets the
+ * bits needed to check for TX hangs. As a result we should immediately
+ * determine if a hang has occurred.
+ */
+static void wx_check_tx_hang_subtask(struct wx *wx)
+{
+ int i;
+
+ /* If we're down or resetting, just bail */
+ if (!netif_running(wx->netdev) ||
+ test_bit(WX_STATE_RESETTING, wx->state))
+ return;
+
+ /* Force detection of hung controller */
+ if (netif_carrier_ok(wx->netdev)) {
+ for (i = 0; i < wx->num_tx_queues; i++)
+ set_bit(WX_TX_DETECT_HANG, wx->tx_ring[i]->state);
+ }
+}
+
+void wx_handle_errors_subtask(struct wx *wx)
+{
+ wx_reset_subtask(wx);
+ wx_check_tx_hang_subtask(wx);
+}
+EXPORT_SYMBOL(wx_handle_errors_subtask);
+
+static void wx_tx_timeout_reset(struct wx *wx)
+{
+ if (!netif_running(wx->netdev))
+ return;
+
+ set_bit(WX_FLAG_NEED_PF_RESET, wx->flags);
+ wx_warn(wx, "initiating reset due to tx timeout\n");
+ wx_service_event_schedule(wx);
+}
+
+void wx_tx_timeout(struct net_device *netdev, unsigned int txqueue)
+{
+ struct wx *wx = netdev_priv(netdev);
+ u32 head, tail;
+ int i;
+
+ for (i = 0; i < wx->num_tx_queues; i++) {
+ struct wx_ring *tx_ring = wx->tx_ring[i];
+
+ if (test_bit(WX_TX_DETECT_HANG, tx_ring->state) &&
+ wx_check_tx_hang(tx_ring))
+ wx_warn(wx, "Real tx hang detected on queue %d\n", i);
+
+ head = rd32(wx, WX_PX_TR_RP(tx_ring->reg_idx));
+ tail = rd32(wx, WX_PX_TR_WP(tx_ring->reg_idx));
+ wx_warn(wx,
+ "tx ring %d next_to_use is %d, next_to_clean is %d\n",
+ i, tx_ring->next_to_use,
+ tx_ring->next_to_clean);
+ wx_warn(wx, "tx ring %d hw rp is 0x%x, wp is 0x%x\n",
+ i, head, tail);
+ }
+
+ wx_tx_timeout_reset(wx);
+}
+EXPORT_SYMBOL(wx_tx_timeout);
+
+void wx_handle_tx_hang(struct wx_ring *tx_ring, unsigned int next)
+{
+ struct wx *wx = netdev_priv(tx_ring->netdev);
+
+ wx_warn(wx, "Detected Tx Unit Hang\n"
+ " Tx Queue <%d>\n"
+ " TDH, TDT <%x>, <%x>\n"
+ " next_to_use <%x>\n"
+ " next_to_clean <%x>\n"
+ "tx_buffer_info[next_to_clean]\n"
+ " time_stamp <%lx>\n"
+ " jiffies <%lx>\n",
+ tx_ring->queue_index,
+ rd32(wx, WX_PX_TR_RP(tx_ring->reg_idx)),
+ rd32(wx, WX_PX_TR_WP(tx_ring->reg_idx)),
+ tx_ring->next_to_use, next,
+ tx_ring->tx_buffer_info[next].time_stamp, jiffies);
+
+ netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index);
+
+ wx_warn(wx, "tx hang detected on queue %d, resetting adapter\n",
+ tx_ring->queue_index);
+
+ wx_tx_timeout_reset(wx);
+}
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_err.h b/drivers/net/ethernet/wangxun/libwx/wx_err.h
new file mode 100644
index 000000000000..e317e6c8d928
--- /dev/null
+++ b/drivers/net/ethernet/wangxun/libwx/wx_err.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * WangXun Gigabit PCI Express Linux driver
+ * Copyright (c) 2015 - 2026 Beijing WangXun Technology Co., Ltd.
+ */
+
+#ifndef _WX_ERR_H_
+#define _WX_ERR_H_
+
+void wx_handle_errors_subtask(struct wx *wx);
+void wx_tx_timeout(struct net_device *netdev, unsigned int txqueue);
+void wx_handle_tx_hang(struct wx_ring *tx_ring, unsigned int next);
+
+#endif /* _WX_ERR_H_ */
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index d3772d01e00b..401dc7eb1137 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -1932,6 +1932,7 @@ static void wx_configure_tx_ring(struct wx *wx,
else
ring->atr_sample_rate = 0;
+ bitmap_zero(ring->state, WX_RING_STATE_NBITS);
/* reinitialize tx_buffer_info */
memset(ring->tx_buffer_info, 0,
sizeof(struct wx_tx_buffer) * ring->count);
@@ -2847,16 +2848,26 @@ EXPORT_SYMBOL(wx_fc_enable);
static void wx_update_xoff_rx_lfc(struct wx *wx)
{
struct wx_hw_stats *hwstats = &wx->stats;
+ u64 data;
+ int i;
if (wx->fc.mode != wx_fc_full &&
wx->fc.mode != wx_fc_rx_pause)
return;
if (wx->mac.type >= wx_mac_aml)
- hwstats->lxoffrxc += rd32_wrap(wx, WX_MAC_LXOFFRXC_AML,
- &wx->last_stats.lxoffrxc);
+ data = rd32_wrap(wx, WX_MAC_LXOFFRXC_AML,
+ &wx->last_stats.lxoffrxc);
else
- hwstats->lxoffrxc += rd64(wx, WX_MAC_LXOFFRXC);
+ data = rd64(wx, WX_MAC_LXOFFRXC);
+ hwstats->lxoffrxc += data;
+
+ /* refill credits (no tx hang) if we received xoff */
+ if (!data)
+ return;
+
+ for (i = 0; i < wx->num_tx_queues; i++)
+ clear_bit(WX_HANG_CHECK_ARMED, wx->tx_ring[i]->state);
}
/**
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
index 746623fa59b4..9e6167b43f75 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
@@ -14,6 +14,7 @@
#include "wx_type.h"
#include "wx_lib.h"
+#include "wx_err.h"
#include "wx_ptp.h"
#include "wx_hw.h"
#include "wx_vf_lib.h"
@@ -742,6 +743,36 @@ static struct netdev_queue *wx_txring_txq(const struct wx_ring *ring)
return netdev_get_tx_queue(ring->netdev, ring->queue_index);
}
+static u32 wx_get_tx_pending(struct wx_ring *ring)
+{
+ unsigned int head, tail;
+
+ head = ring->next_to_clean;
+ tail = ring->next_to_use;
+
+ return ((head <= tail) ? tail : tail + ring->count) - head;
+}
+
+bool wx_check_tx_hang(struct wx_ring *ring)
+{
+ u32 tx_done_old = ring->tx_stats.tx_done_old;
+ u32 tx_pending = wx_get_tx_pending(ring);
+ u32 tx_done = ring->stats.packets;
+
+ clear_bit(WX_TX_DETECT_HANG, ring->state);
+
+ if (tx_done_old == tx_done && tx_pending)
+ /* make sure it is true for two checks in a row */
+ return test_and_set_bit(WX_HANG_CHECK_ARMED, ring->state);
+
+ /* update completed stats and continue */
+ ring->tx_stats.tx_done_old = tx_done;
+ /* reset the countdown */
+ clear_bit(WX_HANG_CHECK_ARMED, ring->state);
+
+ return false;
+}
+
/**
* wx_clean_tx_irq - Reclaim resources after transmit completes
* @q_vector: structure containing interrupt and ring information
@@ -866,6 +897,12 @@ static bool wx_clean_tx_irq(struct wx_q_vector *q_vector,
netdev_tx_completed_queue(wx_txring_txq(tx_ring),
total_packets, total_bytes);
+ if (test_bit(WX_TX_DETECT_HANG, tx_ring->state) &&
+ wx_check_tx_hang(tx_ring)) {
+ wx_handle_tx_hang(tx_ring, i);
+ return true;
+ }
+
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
if (unlikely(total_packets && netif_carrier_ok(tx_ring->netdev) &&
(wx_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD))) {
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.h b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
index aed6ea8cf0d6..e373cd7f05d3 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h
@@ -10,6 +10,7 @@
struct wx_dec_ptype wx_decode_ptype(const u8 ptype);
void wx_alloc_rx_buffers(struct wx_ring *rx_ring, u16 cleaned_count);
u16 wx_desc_unused(struct wx_ring *ring);
+bool wx_check_tx_hang(struct wx_ring *ring);
netdev_tx_t wx_xmit_frame(struct sk_buff *skb,
struct net_device *netdev);
void wx_napi_enable_all(struct wx *wx);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 0da5565ee4ff..f65c2d7bae39 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -1039,6 +1039,7 @@ struct wx_queue_stats {
struct wx_tx_queue_stats {
u64 restart_queue;
u64 tx_busy;
+ u32 tx_done_old;
};
struct wx_rx_queue_stats {
@@ -1054,6 +1055,12 @@ struct wx_rx_queue_stats {
#define wx_for_each_ring(posm, headm) \
for (posm = (headm).ring; posm; posm = posm->next)
+enum wx_ring_state {
+ WX_TX_DETECT_HANG,
+ WX_HANG_CHECK_ARMED,
+ WX_RING_STATE_NBITS
+};
+
struct wx_ring_container {
struct wx_ring *ring; /* pointer to linked list of rings */
unsigned int total_bytes; /* total bytes processed this int */
@@ -1073,6 +1080,7 @@ struct wx_ring {
struct wx_tx_buffer *tx_buffer_info;
struct wx_rx_buffer *rx_buffer_info;
};
+ DECLARE_BITMAP(state, WX_RING_STATE_NBITS);
u8 __iomem *tail;
dma_addr_t dma; /* phys. address of descriptor ring */
dma_addr_t headwb_dma;
@@ -1273,6 +1281,7 @@ enum wx_pf_flags {
WX_FLAG_NEED_DO_RESET,
WX_FLAG_RX_MERGE_ENABLED,
WX_FLAG_TXHEAD_WB_ENABLED,
+ WX_FLAG_NEED_PF_RESET,
WX_PF_FLAGS_NBITS /* must be last */
};
@@ -1503,7 +1512,8 @@ rd32_wrap(struct wx *wx, u32 reg, u32 *last)
#define wx_err(wx, fmt, arg...) \
dev_err(&(wx)->pdev->dev, fmt, ##arg)
-
+#define wx_warn(wx, fmt, arg...) \
+ dev_warn(&(wx)->pdev->dev, fmt, ##arg)
#define wx_dbg(wx, fmt, arg...) \
dev_dbg(&(wx)->pdev->dev, fmt, ##arg)
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index bd905e267575..e9561996b970 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -14,6 +14,7 @@
#include "../libwx/wx_type.h"
#include "../libwx/wx_hw.h"
#include "../libwx/wx_lib.h"
+#include "../libwx/wx_err.h"
#include "../libwx/wx_ptp.h"
#include "../libwx/wx_mbx.h"
#include "../libwx/wx_sriov.h"
@@ -147,6 +148,7 @@ static void ngbe_service_task(struct work_struct *work)
{
struct wx *wx = container_of(work, struct wx, service_task);
+ wx_handle_errors_subtask(wx);
wx_update_stats(wx);
wx_service_event_complete(wx);
@@ -642,6 +644,7 @@ static const struct net_device_ops ngbe_netdev_ops = {
.ndo_stop = ngbe_close,
.ndo_change_mtu = wx_change_mtu,
.ndo_start_xmit = wx_xmit_frame,
+ .ndo_tx_timeout = wx_tx_timeout,
.ndo_set_rx_mode = wx_set_rx_mode,
.ndo_set_features = wx_set_features,
.ndo_fix_features = wx_fix_features,
@@ -731,6 +734,7 @@ static int ngbe_probe(struct pci_dev *pdev,
wx->driver_name = ngbe_driver_name;
ngbe_set_ethtool_ops(netdev);
netdev->netdev_ops = &ngbe_netdev_ops;
+ netdev->watchdog_timeo = 5 * HZ;
netdev->features = NETIF_F_SG | NETIF_F_IP_CSUM |
NETIF_F_TSO | NETIF_F_TSO6 |
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index ec32a5f422f2..b13c48507374 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -14,6 +14,7 @@
#include "../libwx/wx_type.h"
#include "../libwx/wx_lib.h"
+#include "../libwx/wx_err.h"
#include "../libwx/wx_ptp.h"
#include "../libwx/wx_hw.h"
#include "../libwx/wx_mbx.h"
@@ -128,6 +129,7 @@ static void txgbe_service_task(struct work_struct *work)
{
struct wx *wx = container_of(work, struct wx, service_task);
+ wx_handle_errors_subtask(wx);
txgbe_module_detection_subtask(wx);
txgbe_link_config_subtask(wx);
wx_update_stats(wx);
@@ -659,6 +661,7 @@ static const struct net_device_ops txgbe_netdev_ops = {
.ndo_stop = txgbe_close,
.ndo_change_mtu = wx_change_mtu,
.ndo_start_xmit = wx_xmit_frame,
+ .ndo_tx_timeout = wx_tx_timeout,
.ndo_set_rx_mode = wx_set_rx_mode,
.ndo_set_features = wx_set_features,
.ndo_fix_features = wx_fix_features,
@@ -750,6 +753,7 @@ static int txgbe_probe(struct pci_dev *pdev,
wx->driver_name = txgbe_driver_name;
txgbe_set_ethtool_ops(netdev);
netdev->netdev_ops = &txgbe_netdev_ops;
+ netdev->watchdog_timeo = 5 * HZ;
netdev->udp_tunnel_nic_info = &txgbe_udp_tunnels;
/* setup the private structure */
--
2.51.0
^ permalink raw reply related
* [RFC PATCH net-next 4/5] net: wangxun: extract the close_suspend sequence
From: Jiawen Wu @ 2026-04-22 9:56 UTC (permalink / raw)
To: netdev
Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
Simon Horman, Kees Cook, Larysa Zaremba, Breno Leitao, Joe Damato,
Jacob Keller, Fabio Baltieri, Jiawen Wu
In-Reply-To: <20260422095617.27080-1-jiawenwu@trustnetic.com>
Refactor the .ndo_close implementation by extracting the necessary
hardware shutdown sequence into a dedicated close_suspend function.
This is for later implementation of PCIe error callback function in
libwx.
Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
drivers/net/ethernet/wangxun/libwx/wx_type.h | 1 +
drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 18 +++++++++++++-----
drivers/net/ethernet/wangxun/ngbe/ngbe_type.h | 1 +
.../net/ethernet/wangxun/txgbe/txgbe_main.c | 13 +++++++------
.../net/ethernet/wangxun/txgbe/txgbe_type.h | 1 +
5 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 671ac0a19dee..4b72835ddec1 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -1403,6 +1403,7 @@ struct wx {
void (*configure_fdir)(struct wx *wx);
int (*setup_tc)(struct net_device *netdev, u8 tc);
void (*do_reset)(struct net_device *netdev, bool reinit);
+ void (*close_suspend)(struct wx *wx);
int (*ptp_setup_sdp)(struct wx *wx);
void (*set_num_queues)(struct wx *wx);
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index ec14dd47cd42..bd6c0c9c51ba 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -135,6 +135,7 @@ static int ngbe_sw_init(struct wx *wx)
wx->mbx.size = WX_VXMAILBOX_SIZE;
wx->setup_tc = ngbe_setup_tc;
wx->do_reset = ngbe_do_reset;
+ wx->close_suspend = ngbe_close_suspend;
set_bit(0, &wx->fwd_bitmask);
return 0;
@@ -510,6 +511,16 @@ void ngbe_up(struct wx *wx)
ngbe_up_complete(wx);
}
+void ngbe_close_suspend(struct wx *wx)
+{
+ wx_ptp_suspend(wx);
+ ngbe_down(wx);
+ wx_free_irq(wx);
+ wx_free_isb_resources(wx);
+ wx_free_resources(wx);
+ phylink_disconnect_phy(wx->phylink);
+}
+
/**
* ngbe_close - Disables a network interface
* @netdev: network interface device structure
@@ -526,11 +537,8 @@ static int ngbe_close(struct net_device *netdev)
struct wx *wx = netdev_priv(netdev);
wx_ptp_stop(wx);
- ngbe_down(wx);
- wx_free_irq(wx);
- wx_free_isb_resources(wx);
- wx_free_resources(wx);
- phylink_disconnect_phy(wx->phylink);
+ if (netif_device_present(netdev))
+ ngbe_close_suspend(wx);
wx_control_hw(wx, false);
return 0;
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
index c9233dc7ae50..eb5c92edae06 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
@@ -126,5 +126,6 @@ void ngbe_down(struct wx *wx);
void ngbe_up(struct wx *wx);
int ngbe_setup_tc(struct net_device *dev, u8 tc);
void ngbe_do_reset(struct net_device *netdev, bool reinit);
+void ngbe_close_suspend(struct wx *wx);
#endif /* _NGBE_TYPE_H_ */
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index f6050775af71..20969dd7d47a 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -415,6 +415,7 @@ static int txgbe_sw_init(struct wx *wx)
wx->setup_tc = txgbe_setup_tc;
wx->do_reset = txgbe_do_reset;
+ wx->close_suspend = txgbe_close_suspend;
set_bit(0, &wx->fwd_bitmask);
switch (wx->mac.type) {
@@ -503,10 +504,12 @@ static int txgbe_open(struct net_device *netdev)
* This function should contain the necessary work common to both suspending
* and closing of the device.
*/
-static void txgbe_close_suspend(struct wx *wx)
+void txgbe_close_suspend(struct wx *wx)
{
wx_ptp_suspend(wx);
- txgbe_disable_device(wx);
+ txgbe_down(wx);
+ wx_free_irq(wx);
+ txgbe_free_misc_irq(wx->priv);
wx_free_resources(wx);
}
@@ -526,10 +529,8 @@ static int txgbe_close(struct net_device *netdev)
struct wx *wx = netdev_priv(netdev);
wx_ptp_stop(wx);
- txgbe_down(wx);
- wx_free_irq(wx);
- txgbe_free_misc_irq(wx->priv);
- wx_free_resources(wx);
+ if (netif_device_present(netdev))
+ txgbe_close_suspend(wx);
txgbe_fdir_filter_exit(wx);
wx_control_hw(wx, false);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
index 1e373f7fd9b5..cd50ff1ef2ed 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
@@ -314,6 +314,7 @@ void txgbe_down(struct wx *wx);
void txgbe_up(struct wx *wx);
int txgbe_setup_tc(struct net_device *dev, u8 tc);
void txgbe_do_reset(struct net_device *netdev, bool reinit);
+void txgbe_close_suspend(struct wx *wx);
#define TXGBE_LINK_SPEED_UNKNOWN 0
#define TXGBE_LINK_SPEED_10GB_FULL 4
--
2.51.0
^ permalink raw reply related
* [RFC PATCH net-next 3/5] net: wangxun: add reinit parameter to wx->do_reset callback
From: Jiawen Wu @ 2026-04-22 9:56 UTC (permalink / raw)
To: netdev
Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
Simon Horman, Kees Cook, Larysa Zaremba, Breno Leitao, Joe Damato,
Jacob Keller, Fabio Baltieri, Jiawen Wu
In-Reply-To: <20260422095617.27080-1-jiawenwu@trustnetic.com>
To implement a simple hardware reset without tearing down the network
interface state, introduce a boolean 'reinit' parameter to wx->do_reset
callback.
Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
drivers/net/ethernet/wangxun/libwx/wx_err.c | 2 +-
drivers/net/ethernet/wangxun/libwx/wx_ethtool.c | 2 +-
drivers/net/ethernet/wangxun/libwx/wx_lib.c | 4 ++--
drivers/net/ethernet/wangxun/libwx/wx_type.h | 2 +-
drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 4 ++--
drivers/net/ethernet/wangxun/ngbe/ngbe_type.h | 2 +-
drivers/net/ethernet/wangxun/txgbe/txgbe_main.c | 4 ++--
drivers/net/ethernet/wangxun/txgbe/txgbe_type.h | 2 +-
8 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_err.c b/drivers/net/ethernet/wangxun/libwx/wx_err.c
index 42e00f0bd8da..e7c9dcb148b5 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_err.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_err.c
@@ -23,7 +23,7 @@ static void wx_reset_subtask(struct wx *wx)
if (test_and_clear_bit(WX_FLAG_NEED_PF_RESET, wx->flags)) {
if (wx->do_reset)
- wx->do_reset(wx->netdev);
+ wx->do_reset(wx->netdev, true);
}
rtnl_unlock();
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
index 5df971aca9e3..d1356ff5d69b 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_ethtool.c
@@ -395,7 +395,7 @@ static void wx_update_rsc(struct wx *wx)
/* reset the device to apply the new RSC setting */
if (need_reset && wx->do_reset)
- wx->do_reset(netdev);
+ wx->do_reset(netdev, true);
}
int wx_set_coalesce(struct net_device *netdev,
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
index 9e6167b43f75..3216dee778be 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
@@ -3146,7 +3146,7 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features)
netdev->features = features;
if (changed & NETIF_F_HW_VLAN_CTAG_RX && wx->do_reset)
- wx->do_reset(netdev);
+ wx->do_reset(netdev, true);
else if (changed & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER))
wx_set_rx_mode(netdev);
@@ -3196,7 +3196,7 @@ int wx_set_features(struct net_device *netdev, netdev_features_t features)
out:
if (need_reset && wx->do_reset)
- wx->do_reset(netdev);
+ wx->do_reset(netdev, true);
return 0;
}
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index f65c2d7bae39..671ac0a19dee 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -1402,7 +1402,7 @@ struct wx {
void (*atr)(struct wx_ring *ring, struct wx_tx_buffer *first, u8 ptype);
void (*configure_fdir)(struct wx *wx);
int (*setup_tc)(struct net_device *netdev, u8 tc);
- void (*do_reset)(struct net_device *netdev);
+ void (*do_reset)(struct net_device *netdev, bool reinit);
int (*ptp_setup_sdp)(struct wx *wx);
void (*set_num_queues)(struct wx *wx);
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index e9561996b970..ec14dd47cd42 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -629,11 +629,11 @@ static void ngbe_reinit_locked(struct wx *wx)
mutex_unlock(&wx->reset_lock);
}
-void ngbe_do_reset(struct net_device *netdev)
+void ngbe_do_reset(struct net_device *netdev, bool reinit)
{
struct wx *wx = netdev_priv(netdev);
- if (netif_running(netdev))
+ if (netif_running(netdev) && reinit)
ngbe_reinit_locked(wx);
else
ngbe_reset(wx);
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
index 4f648f272c08..c9233dc7ae50 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
@@ -125,6 +125,6 @@ extern char ngbe_driver_name[];
void ngbe_down(struct wx *wx);
void ngbe_up(struct wx *wx);
int ngbe_setup_tc(struct net_device *dev, u8 tc);
-void ngbe_do_reset(struct net_device *netdev);
+void ngbe_do_reset(struct net_device *netdev, bool reinit);
#endif /* _NGBE_TYPE_H_ */
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index b13c48507374..f6050775af71 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -613,11 +613,11 @@ static void txgbe_reinit_locked(struct wx *wx)
mutex_unlock(&wx->reset_lock);
}
-void txgbe_do_reset(struct net_device *netdev)
+void txgbe_do_reset(struct net_device *netdev, bool reinit)
{
struct wx *wx = netdev_priv(netdev);
- if (netif_running(netdev))
+ if (netif_running(netdev) && reinit)
txgbe_reinit_locked(wx);
else
txgbe_reset(wx);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
index 6b05f32b4a01..1e373f7fd9b5 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
@@ -313,7 +313,7 @@ extern char txgbe_driver_name[];
void txgbe_down(struct wx *wx);
void txgbe_up(struct wx *wx);
int txgbe_setup_tc(struct net_device *dev, u8 tc);
-void txgbe_do_reset(struct net_device *netdev);
+void txgbe_do_reset(struct net_device *netdev, bool reinit);
#define TXGBE_LINK_SPEED_UNKNOWN 0
#define TXGBE_LINK_SPEED_10GB_FULL 4
--
2.51.0
^ permalink raw reply related
* [RFC PATCH net-next 5/5] net: wangxun: implement pci_error_handlers ops
From: Jiawen Wu @ 2026-04-22 9:56 UTC (permalink / raw)
To: netdev
Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
Simon Horman, Kees Cook, Larysa Zaremba, Breno Leitao, Joe Damato,
Jacob Keller, Fabio Baltieri, Jiawen Wu
In-Reply-To: <20260422095617.27080-1-jiawenwu@trustnetic.com>
Support AER driver to handle the PCIe errors.
Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
drivers/net/ethernet/wangxun/libwx/wx_err.c | 107 ++++++++++++++++++
drivers/net/ethernet/wangxun/libwx/wx_err.h | 2 +
drivers/net/ethernet/wangxun/libwx/wx_type.h | 1 +
drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 9 +-
.../net/ethernet/wangxun/txgbe/txgbe_main.c | 5 +-
5 files changed, 121 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_err.c b/drivers/net/ethernet/wangxun/libwx/wx_err.c
index e7c9dcb148b5..1aefae402c8e 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_err.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_err.c
@@ -3,11 +3,118 @@
#include <linux/netdevice.h>
#include <linux/pci.h>
+#include <linux/aer.h>
#include "wx_type.h"
#include "wx_lib.h"
#include "wx_err.h"
+/**
+ * wx_io_error_detected - called when PCI error is detected
+ * @pdev: Pointer to PCI device
+ * @state: The current pci connection state
+ *
+ * Return: pci_ers_result_t.
+ *
+ * This function is called after a PCI bus error affecting
+ * this device has been detected.
+ */
+static pci_ers_result_t wx_io_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct wx *wx = pci_get_drvdata(pdev);
+ struct net_device *netdev;
+
+ netdev = wx->netdev;
+ if (!netif_device_present(netdev))
+ return PCI_ERS_RESULT_DISCONNECT;
+
+ rtnl_lock();
+ netif_device_detach(netdev);
+
+ if (netif_running(netdev))
+ wx->close_suspend(wx);
+
+ if (state == pci_channel_io_perm_failure) {
+ rtnl_unlock();
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+
+ if (!test_and_set_bit(WX_STATE_DISABLED, wx->state))
+ pci_disable_device(pdev);
+ rtnl_unlock();
+
+ /* Request a slot reset. */
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+/**
+ * wx_io_slot_reset - called after the pci bus has been reset.
+ * @pdev: Pointer to PCI device
+ *
+ * Return: pci_ers_result_t.
+ *
+ * Restart the card from scratch, as if from a cold-boot.
+ */
+static pci_ers_result_t wx_io_slot_reset(struct pci_dev *pdev)
+{
+ struct wx *wx = pci_get_drvdata(pdev);
+ pci_ers_result_t result;
+
+ if (pci_enable_device_mem(pdev)) {
+ wx_err(wx, "Cannot re-enable PCI device after reset.\n");
+ result = PCI_ERS_RESULT_DISCONNECT;
+ } else {
+ /* make all bar access done before reset. */
+ smp_mb__before_atomic();
+ clear_bit(WX_STATE_DISABLED, wx->state);
+ pci_set_master(pdev);
+ pci_restore_state(pdev);
+ pci_wake_from_d3(pdev, false);
+
+ wx->do_reset(wx->netdev, false);
+ result = PCI_ERS_RESULT_RECOVERED;
+ }
+
+ pci_aer_clear_nonfatal_status(pdev);
+
+ return result;
+}
+
+/**
+ * wx_io_resume - called when traffic can start flowing again.
+ * @pdev: Pointer to PCI device
+ *
+ * This callback is called when the error recovery driver tells us that
+ * its OK to resume normal operation.
+ */
+static void wx_io_resume(struct pci_dev *pdev)
+{
+ struct wx *wx = pci_get_drvdata(pdev);
+ struct net_device *netdev;
+ int err;
+
+ netdev = wx->netdev;
+ rtnl_lock();
+ if (netif_running(netdev)) {
+ err = netdev->netdev_ops->ndo_open(netdev);
+ if (err) {
+ wx_err(wx, "Failed to open netdev after reset\n");
+ goto out;
+ }
+ }
+ netif_device_attach(netdev);
+out:
+ rtnl_unlock();
+}
+
+const struct pci_error_handlers wx_err_handler = {
+ .error_detected = wx_io_error_detected,
+ .slot_reset = wx_io_slot_reset,
+ .resume = wx_io_resume,
+};
+EXPORT_SYMBOL(wx_err_handler);
+
static void wx_reset_subtask(struct wx *wx)
{
if (!test_bit(WX_FLAG_NEED_PF_RESET, wx->flags))
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_err.h b/drivers/net/ethernet/wangxun/libwx/wx_err.h
index e317e6c8d928..8b1a7863b5b1 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_err.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_err.h
@@ -7,6 +7,8 @@
#ifndef _WX_ERR_H_
#define _WX_ERR_H_
+extern const struct pci_error_handlers wx_err_handler;
+
void wx_handle_errors_subtask(struct wx *wx);
void wx_tx_timeout(struct net_device *netdev, unsigned int txqueue);
void wx_handle_tx_hang(struct wx_ring *tx_ring, unsigned int next);
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h
index 4b72835ddec1..81e12609d3fa 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_type.h
+++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h
@@ -1215,6 +1215,7 @@ enum wx_state {
WX_STATE_PTP_RUNNING,
WX_STATE_PTP_TX_IN_PROGRESS,
WX_STATE_SERVICE_SCHED,
+ WX_STATE_DISABLED,
WX_STATE_NBITS /* must be last */
};
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index bd6c0c9c51ba..a174605d1105 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -570,7 +570,8 @@ static void ngbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake)
*enable_wake = !!wufc;
wx_control_hw(wx, false);
- pci_disable_device(pdev);
+ if (!test_and_set_bit(WX_STATE_DISABLED, wx->state))
+ pci_disable_device(pdev);
}
static void ngbe_shutdown(struct pci_dev *pdev)
@@ -856,6 +857,7 @@ static int ngbe_probe(struct pci_dev *pdev,
goto err_register;
pci_set_drvdata(pdev, wx);
+ pci_save_state(pdev);
return 0;
@@ -907,7 +909,8 @@ static void ngbe_remove(struct pci_dev *pdev)
kfree(wx->mac_table);
wx_clear_interrupt_scheme(wx);
- pci_disable_device(pdev);
+ if (!test_and_set_bit(WX_STATE_DISABLED, wx->state))
+ pci_disable_device(pdev);
}
static int ngbe_suspend(struct pci_dev *pdev, pm_message_t state)
@@ -934,6 +937,7 @@ static int ngbe_resume(struct pci_dev *pdev)
wx_err(wx, "Cannot enable PCI device from suspend\n");
return err;
}
+ clear_bit(WX_STATE_DISABLED, wx->state);
pci_set_master(pdev);
device_wakeup_disable(&pdev->dev);
@@ -958,6 +962,7 @@ static struct pci_driver ngbe_driver = {
.resume = ngbe_resume,
.shutdown = ngbe_shutdown,
.sriov_configure = wx_pci_sriov_configure,
+ .err_handler = &wx_err_handler,
};
module_pci_driver(ngbe_driver);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
index 20969dd7d47a..56e8482c1896 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c
@@ -899,6 +899,7 @@ static int txgbe_probe(struct pci_dev *pdev,
goto err_remove_phy;
pci_set_drvdata(pdev, wx);
+ pci_save_state(pdev);
netif_tx_stop_all_queues(netdev);
@@ -969,7 +970,8 @@ static void txgbe_remove(struct pci_dev *pdev)
kfree(wx->mac_table);
wx_clear_interrupt_scheme(wx);
- pci_disable_device(pdev);
+ if (!test_and_set_bit(WX_STATE_DISABLED, wx->state))
+ pci_disable_device(pdev);
}
static struct pci_driver txgbe_driver = {
@@ -979,6 +981,7 @@ static struct pci_driver txgbe_driver = {
.remove = txgbe_remove,
.shutdown = txgbe_shutdown,
.sriov_configure = wx_pci_sriov_configure,
+ .err_handler = &wx_err_handler,
};
module_pci_driver(txgbe_driver);
--
2.51.0
^ permalink raw reply related
* [RFC PATCH net-next 1/5] net: ngbe: implement libwx reset ops
From: Jiawen Wu @ 2026-04-22 9:56 UTC (permalink / raw)
To: netdev
Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
Simon Horman, Kees Cook, Larysa Zaremba, Breno Leitao, Joe Damato,
Jacob Keller, Fabio Baltieri, Jiawen Wu
In-Reply-To: <20260422095617.27080-1-jiawenwu@trustnetic.com>
Implement wx->do_reset() for library module calling.
Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
---
.../net/ethernet/wangxun/ngbe/ngbe_ethtool.c | 1 -
drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 37 ++++++++++++++++++-
drivers/net/ethernet/wangxun/ngbe/ngbe_type.h | 1 +
3 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
index b2e191982803..1960f7154151 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_ethtool.c
@@ -59,7 +59,6 @@ static int ngbe_set_ringparam(struct net_device *netdev,
wx_set_ring(wx, new_tx_count, new_rx_count, temp_ring);
kvfree(temp_ring);
- wx_configure(wx);
ngbe_up(wx);
clear_reset:
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
index d8e3827a8b1f..bd905e267575 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
@@ -133,6 +133,7 @@ static int ngbe_sw_init(struct wx *wx)
wx->mbx.size = WX_VXMAILBOX_SIZE;
wx->setup_tc = ngbe_setup_tc;
+ wx->do_reset = ngbe_do_reset;
set_bit(0, &wx->fwd_bitmask);
return 0;
@@ -422,7 +423,7 @@ void ngbe_down(struct wx *wx)
wx_clean_all_rx_rings(wx);
}
-void ngbe_up(struct wx *wx)
+static void ngbe_up_complete(struct wx *wx)
{
wx_configure_vectors(wx);
@@ -488,7 +489,7 @@ static int ngbe_open(struct net_device *netdev)
wx_ptp_init(wx);
- ngbe_up(wx);
+ ngbe_up_complete(wx);
return 0;
err_dis_phy:
@@ -501,6 +502,12 @@ static int ngbe_open(struct net_device *netdev)
return err;
}
+void ngbe_up(struct wx *wx)
+{
+ wx_configure(wx);
+ ngbe_up_complete(wx);
+}
+
/**
* ngbe_close - Disables a network interface
* @netdev: network interface device structure
@@ -588,6 +595,8 @@ int ngbe_setup_tc(struct net_device *dev, u8 tc)
*/
if (netif_running(dev))
ngbe_close(dev);
+ else
+ ngbe_reset(wx);
wx_clear_interrupt_scheme(wx);
@@ -604,6 +613,30 @@ int ngbe_setup_tc(struct net_device *dev, u8 tc)
return 0;
}
+static void ngbe_reinit_locked(struct wx *wx)
+{
+ netif_trans_update(wx->netdev);
+
+ mutex_lock(&wx->reset_lock);
+ set_bit(WX_STATE_RESETTING, wx->state);
+
+ ngbe_down(wx);
+ ngbe_up(wx);
+
+ clear_bit(WX_STATE_RESETTING, wx->state);
+ mutex_unlock(&wx->reset_lock);
+}
+
+void ngbe_do_reset(struct net_device *netdev)
+{
+ struct wx *wx = netdev_priv(netdev);
+
+ if (netif_running(netdev))
+ ngbe_reinit_locked(wx);
+ else
+ ngbe_reset(wx);
+}
+
static const struct net_device_ops ngbe_netdev_ops = {
.ndo_open = ngbe_open,
.ndo_stop = ngbe_close,
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
index 7077a0da4c98..4f648f272c08 100644
--- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
+++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
@@ -125,5 +125,6 @@ extern char ngbe_driver_name[];
void ngbe_down(struct wx *wx);
void ngbe_up(struct wx *wx);
int ngbe_setup_tc(struct net_device *dev, u8 tc);
+void ngbe_do_reset(struct net_device *netdev);
#endif /* _NGBE_TYPE_H_ */
--
2.51.0
^ permalink raw reply related
* [RFC PATCH net-next 0/5] net: wangxun: timeout and error
From: Jiawen Wu @ 2026-04-22 9:56 UTC (permalink / raw)
To: netdev
Cc: Mengyuan Lou, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Richard Cochran, Russell King,
Simon Horman, Kees Cook, Larysa Zaremba, Breno Leitao, Joe Damato,
Jacob Keller, Fabio Baltieri, Jiawen Wu
This series is a split of the previous series:
https://lore.kernel.org/all/20260326021406.30444-1-jiawenwu@trustnetic.com
It is about adding the Tx timeout process and pci_error_handlers.
The changes from the last full patch set V6:
- Add 'else' handling in ngbe_do_reset().
- Acquire rtnl_lock() before checking netif_running() in
wx_reset_subtask().
- Use test_and_clear_bit() instead of test_bit()…clear_bit() to avoid
losing another reset request.
- Change ‘u64 tx_done_old’ to ‘u32’ to avoid data race between
dev_watchdog and NAPI polling.
- Check the return value of ndo_open() in wx_io_resume().
- Drop pci_save_state().
Jiawen Wu (5):
net: ngbe: implement libwx reset ops
net: wangxun: add Tx timeout process
net: wangxun: add reinit parameter to wx->do_reset callback
net: wangxun: extract the close_suspend sequence
net: wangxun: implement pci_error_handlers ops
drivers/net/ethernet/wangxun/libwx/Makefile | 2 +-
drivers/net/ethernet/wangxun/libwx/wx_err.c | 232 ++++++++++++++++++
drivers/net/ethernet/wangxun/libwx/wx_err.h | 16 ++
.../net/ethernet/wangxun/libwx/wx_ethtool.c | 2 +-
drivers/net/ethernet/wangxun/libwx/wx_hw.c | 17 +-
drivers/net/ethernet/wangxun/libwx/wx_lib.c | 41 +++-
drivers/net/ethernet/wangxun/libwx/wx_lib.h | 1 +
drivers/net/ethernet/wangxun/libwx/wx_type.h | 16 +-
.../net/ethernet/wangxun/ngbe/ngbe_ethtool.c | 1 -
drivers/net/ethernet/wangxun/ngbe/ngbe_main.c | 68 ++++-
drivers/net/ethernet/wangxun/ngbe/ngbe_type.h | 2 +
.../net/ethernet/wangxun/txgbe/txgbe_main.c | 26 +-
.../net/ethernet/wangxun/txgbe/txgbe_type.h | 3 +-
13 files changed, 398 insertions(+), 29 deletions(-)
create mode 100644 drivers/net/ethernet/wangxun/libwx/wx_err.c
create mode 100644 drivers/net/ethernet/wangxun/libwx/wx_err.h
--
2.51.0
^ permalink raw reply
* Re: [PATCH net v3 1/1] net: hsr: limit node table growth
From: Felix Maurer @ 2026-04-22 9:45 UTC (permalink / raw)
To: Sebastian Andrzej Siewior
Cc: Ren Wei, netdev, davem, edumazet, kuba, pabeni, horms, kees,
kexinsun, luka.gejak, Arvid.Brodin, m-karicheri2, yuantan098,
yifanwucs, tomapufckgml, bird, xuyuqiabc, royenheart
In-Reply-To: <20260422085242.3TkVbXc2@linutronix.de>
On Wed, Apr 22, 2026 at 10:52:42AM +0200, Sebastian Andrzej Siewior wrote:
> On 2026-04-22 10:31:39 [+0200], Felix Maurer wrote:
> > On Tue, Apr 21, 2026 at 10:50:01PM +0800, Ren Wei wrote:
> > > diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c
> > > index d09875b33588..8a5a2a54a81f 100644
> > > --- a/net/hsr/hsr_framereg.c
> > > +++ b/net/hsr/hsr_framereg.c
> > > @@ -189,6 +195,7 @@ static struct hsr_node *hsr_add_node(struct hsr_priv *hsr,
> > > enum hsr_port_type rx_port)
> > > {
> > > struct hsr_node *new_node, *node = NULL;
> > > + unsigned int node_count = 0;
> > > unsigned long now;
> > > size_t block_sz;
> > > int i;
> > > @@ -226,20 +233,31 @@ static struct hsr_node *hsr_add_node(struct hsr_priv *hsr,
> > > spin_lock_bh(&hsr->list_lock);
> > > list_for_each_entry_rcu(node, node_db, mac_list,
> > > lockdep_is_held(&hsr->list_lock)) {
> > > + node_count++;
> >
> > I'm not sure if this on-the-fly node counting is the best solution here.
> > My concern is that it comes quite late in the process, i.e., after we
> > already allocated a bunch of memory, etc. As we are discussing a
> > scenario where a lot of entries are created, maybe we shouldn't even
> > allocate a new_node if the table is already full? For example by storing
> > the node_count in hsr_priv and checking it early in the function?
>
> The node is allocated upfront. Then it iterates here and we only end up
> counting through the full list if there is no match. This is under a
> lock so "many clients" are serialized. If we allocate the node later
> then we need to do it under the lock.
>
> I don't think the node count exceeds 100 in production. So having a
> counter which is incremented while adding to the list and decremented
> while removing items from the list would optimize the "worst case". So
> instead traversing the list with 1000 we would just give up.
The counter is what I had in mind. I agree that allocating under the
lock isn't what we want.
I'd argue counting through the whole list is the normal case.
hsr_add_node() is only called after the node table has been searched
already (without the lock). Here we go through the whole list again
under the lock to prevent TOCTOU-type situations.
I agree that, overall, it would be optimizing the worst case, but I
think it may be worth it to prevent the memory allocations and walking
the whole list. But I'd go along with the (current) on-the-fly counting
as well.
Thanks,
Felix
^ permalink raw reply
* Re: [PATCH net] hv_sock: Return -EIO for malformed/short packets
From: Stefano Garzarella @ 2026-04-22 9:40 UTC (permalink / raw)
To: Dexuan Cui
Cc: kys, haiyangz, wei.liu, longli, davem, edumazet, kuba, pabeni,
horms, niuxuewei.nxw, linux-hyperv, virtualization, netdev,
linux-kernel, stable
In-Reply-To: <20260421174931.1152238-1-decui@microsoft.com>
On Tue, Apr 21, 2026 at 10:49:31AM -0700, Dexuan Cui wrote:
>Commit f63152958994 fixes a regression, however it fails to report an
>error for malformed/short packets -- normally we should never see such
>packets, but let's report an error for them just in case.
>
>Fixes: f63152958994 ("hv_sock: Report EOF instead of -EIO for FIN")
>Cc: stable@vger.kernel.org
>Signed-off-by: Dexuan Cui <decui@microsoft.com>
>---
>
>Commit f63152958994 is currently only in net.git's master branch.
>
> net/vmw_vsock/hyperv_transport.c | 29 +++++++++++++++++++----------
> 1 file changed, 19 insertions(+), 10 deletions(-)
>
>diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c
>index 76e78c83fdbc..8faaa14bccda 100644
>--- a/net/vmw_vsock/hyperv_transport.c
>+++ b/net/vmw_vsock/hyperv_transport.c
>@@ -704,18 +704,27 @@ static s64 hvs_stream_has_data(struct vsock_sock *vsk)
> if (hvs->recv_desc) {
> /* Here hvs->recv_data_len is 0, so hvs->recv_desc must
> * be NULL unless it points to the 0-byte-payload FIN
>- * packet: see hvs_update_recv_data().
>+ * packet or a malformed/short packet: see
>+ * hvs_update_recv_data().
> *
>- * Here all the payload has been dequeued, but
>- * hvs_channel_readable_payload() still returns 1,
>- * because the VMBus ringbuffer's read_index is not
>- * updated for the FIN packet: hvs_stream_dequeue() ->
>- * hv_pkt_iter_next() updates the cached priv_read_index
>- * but has no opportunity to update the read_index in
>- * hv_pkt_iter_close() as hvs_stream_has_data() returns
>- * 0 for the FIN packet, so it won't get dequeued.
>+ * If hvs->recv_desc points to the FIN packet, here all
>+ * the payload has been dequeued and the peer_shutdown
>+ * flag is set, but hvs_channel_readable_payload() still
>+ * returns 1, because the VMBus ringbuffer's read_index
>+ * is not updated for the FIN packet:
>+ * hvs_stream_dequeue() -> hv_pkt_iter_next() updates
>+ * the cached priv_read_index but has no opportunity to
>+ * update the read_index in hv_pkt_iter_close() as
>+ * hvs_stream_has_data() returns 0 for the FIN packet,
>+ * so it won't get dequeued.
>+ *
>+ * In case hvs->recv_desc points to a malformed/short
>+ * packet, return -EIO.
> */
>- return 0;
>+ if (hvs->vsk->peer_shutdown & SEND_SHUTDOWN)
We can access `vsk` directly, I mean `vsk->peer_shutdown`.
>+ return 0;
>+ else
nit: we usually avoid the `else` if the other branch returns early, and
maybe have the error returned first, so it's more clear when reading the
comment on top. I mean something like this:
if (!(vsk->peer_shutdown & SEND_SHUTDOWN))
return -EIO;
return 0;
BTW, not a strong opinion on that.
The rest, LGTM!
Thanks,
Stefano
^ permalink raw reply
* [PATCH] net: atheros: atl1e: use atomic functions with memory barriers for next_to_clean
From: Gui-Dong Han @ 2026-04-22 9:37 UTC (permalink / raw)
To: Chris Snook
Cc: Andrew Lunn, David S . Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, netdev, linux-kernel, baijiaju1990, Gui-Dong Han
next_to_clean synchronizes Tx ring cleanup in atl1e_clean_tx_irq()
with slot reuse in atl1e_tpd_avail().
atomic_set() and atomic_read() do not provide ordering. Without memory
barriers, out-of-order execution can lead to concurrency bugs on weak
memory architectures like ARM. For example, this can let the transmit
path reuse a slot before tx_buffer->skb = NULL is visible and trigger
the BUG_ON() in atl1e_tx_map(). This is a constructed scenario, and
there might be other undiscovered, potentially more harmful bugs caused
by this lack of ordering.
Use atomic_set_release() and atomic_read_acquire() for next_to_clean.
Fixes: a6a5325239c2 ("atl1e: Atheros L1E Gigabit Ethernet driver")
Signed-off-by: Gui-Dong Han <hanguidong02@gmail.com>
---
Found by auditing atomic operations used for synchronization.
A similar fix can be found in 6df8e84aa6b5.
Do not change atl1e_init_ring_ptrs(). Its atomic_set() runs during
bring-up before NAPI and interrupts are enabled, so it is not a runtime
publication point between Tx cleanup and Tx submission.
In my opinion, implementing ad-hoc lockless algorithms directly within
individual drivers is highly error-prone. To avoid these subtle memory
ordering and barrier bugs, drivers should rely on established, well-tested
kernel libraries like kfifo to handle this type of concurrency.
---
drivers/net/ethernet/atheros/atl1e/atl1e_main.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
index 40290028580b..4ac8d4786820 100644
--- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
+++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c
@@ -1232,7 +1232,7 @@ static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter)
struct atl1e_tx_ring *tx_ring = &adapter->tx_ring;
struct atl1e_tx_buffer *tx_buffer = NULL;
u16 hw_next_to_clean = AT_READ_REGW(&adapter->hw, REG_TPD_CONS_IDX);
- u16 next_to_clean = atomic_read(&tx_ring->next_to_clean);
+ u16 next_to_clean = atomic_read_acquire(&tx_ring->next_to_clean);
while (next_to_clean != hw_next_to_clean) {
tx_buffer = &tx_ring->tx_buffer[next_to_clean];
@@ -1259,7 +1259,7 @@ static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter)
next_to_clean = 0;
}
- atomic_set(&tx_ring->next_to_clean, next_to_clean);
+ atomic_set_release(&tx_ring->next_to_clean, next_to_clean);
if (netif_queue_stopped(adapter->netdev) &&
netif_carrier_ok(adapter->netdev)) {
@@ -1562,7 +1562,7 @@ static inline u16 atl1e_tpd_avail(struct atl1e_adapter *adapter)
u16 next_to_use = 0;
u16 next_to_clean = 0;
- next_to_clean = atomic_read(&tx_ring->next_to_clean);
+ next_to_clean = atomic_read_acquire(&tx_ring->next_to_clean);
next_to_use = tx_ring->next_to_use;
return (u16)(next_to_clean > next_to_use) ?
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 08/23] arm64: topology: Use RCU to protect access to HK_TYPE_TICK cpumask
From: Chen Ridong @ 2026-04-22 9:34 UTC (permalink / raw)
To: Waiman Long, Tejun Heo, Johannes Weiner, Michal Koutný,
Jonathan Corbet, Shuah Khan, Catalin Marinas, Will Deacon,
K. Y. Srinivasan, Haiyang Zhang, Wei Liu, Dexuan Cui, Long Li,
Guenter Roeck, Frederic Weisbecker, Paul E. McKenney,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng,
Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers,
Lai Jiangshan, Zqiang, Anna-Maria Behnsen, Ingo Molnar,
Thomas Gleixner, Peter Zijlstra, Juri Lelli, Vincent Guittot,
Dietmar Eggemann, Ben Segall, Mel Gorman, Valentin Schneider,
K Prateek Nayak, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman
Cc: cgroups, linux-doc, linux-kernel, linux-arm-kernel, linux-hyperv,
linux-hwmon, rcu, netdev, linux-kselftest, Costa Shulyupin,
Qiliang Yuan
In-Reply-To: <20260421030351.281436-9-longman@redhat.com>
On 2026/4/21 11:03, Waiman Long wrote:
> As the HK_TYPE_TICK cpumask is going to be changeable at run time, we
> need to use RCU to protect access to the cpumask to prevent it from
> going away in the middle of the operation.
>
> Signed-off-by: Waiman Long <longman@redhat.com>
> ---
> arch/arm64/kernel/topology.c | 17 ++++++++++++++---
> 1 file changed, 14 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
> index b32f13358fbb..48f150801689 100644
> --- a/arch/arm64/kernel/topology.c
> +++ b/arch/arm64/kernel/topology.c
> @@ -173,6 +173,7 @@ void arch_cpu_idle_enter(void)
> if (!amu_fie_cpu_supported(cpu))
> return;
>
> + guard(rcu)();
> /* Kick in AMU update but only if one has not happened already */
> if (housekeeping_cpu(cpu, HK_TYPE_TICK) &&
> time_is_before_jiffies(per_cpu(cpu_amu_samples.last_scale_update, cpu)))
> @@ -187,11 +188,16 @@ int arch_freq_get_on_cpu(int cpu)
> unsigned int start_cpu = cpu;
> unsigned long last_update;
> unsigned int freq = 0;
> + bool hk_cpu;
> u64 scale;
>
> if (!amu_fie_cpu_supported(cpu) || !arch_scale_freq_ref(cpu))
> return -EOPNOTSUPP;
>
> + scoped_guard(rcu) {
> + hk_cpu = housekeeping_cpu(cpu, HK_TYPE_TICK);
> + }
> +
Should we put this into a while loop, since cpu might be changed to ref_cpu?
> while (1) {
>
> amu_sample = per_cpu_ptr(&cpu_amu_samples, cpu);
> @@ -204,16 +210,21 @@ int arch_freq_get_on_cpu(int cpu)
> * (and thus freq scale), if available, for given policy: this boils
> * down to identifying an active cpu within the same freq domain, if any.
> */
> - if (!housekeeping_cpu(cpu, HK_TYPE_TICK) ||
> + if (!hk_cpu ||
> time_is_before_jiffies(last_update + msecs_to_jiffies(AMU_SAMPLE_EXP_MS))) {
> struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
> + bool hk_intersects;
> int ref_cpu;
>
> if (!policy)
> return -EINVAL;
>
> - if (!cpumask_intersects(policy->related_cpus,
> - housekeeping_cpumask(HK_TYPE_TICK))) {
> + scoped_guard(rcu) {
> + hk_intersects = cpumask_intersects(policy->related_cpus,
> + housekeeping_cpumask(HK_TYPE_TICK));
> + }
> +
> + if (!hk_intersects) {
> cpufreq_cpu_put(policy);
> return -EOPNOTSUPP;
> }
--
Best regards,
Ridong
^ permalink raw reply
* Re: [PATCH net 00/18] Remove a number of ISA and PCMCIA Ethernet drivers
From: Daniel Palmer @ 2026-04-22 9:33 UTC (permalink / raw)
To: David Laight
Cc: Andrew Lunn, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Jonathan Corbet,
Shuah Khan, linux-kernel, netdev, linux-doc
In-Reply-To: <20260422101316.0efdcf24@pumpkin>
Hi David,
On Wed, 22 Apr 2026 at 18:13, David Laight <david.laight.linux@gmail.com> wrote:
> Is marking them EXPERT or BROKEN enough?
> (Or a similar new option.)
I think EXPERT gives the wrong impression that they are difficult to
use and BROKEN makes it seem like they don't work.
NEEDSHOBBIES or LIVINGINTHEPAST ?
Seriously though, I think we should have something to mark stuff in
MAINTAINERS and elsewhere that is in the kernel but only because a few
people are having fun with it.
^ permalink raw reply
* Re: [PATCH net 1/2] net/mlx5e: psp: Fix invalid access on PSP dev registration fail
From: Cosmin Ratiu @ 2026-04-22 9:25 UTC (permalink / raw)
To: kuba@kernel.org
Cc: Boris Pismenny, willemdebruijn.kernel@gmail.com,
andrew+netdev@lunn.ch, daniel.zahka@gmail.com,
davem@davemloft.net, leon@kernel.org,
linux-kernel@vger.kernel.org, edumazet@google.com,
linux-rdma@vger.kernel.org, Rahul Rameshbabu, Raed Salem,
Dragos Tatulea, kees@kernel.org, Mark Bloch, pabeni@redhat.com,
Tariq Toukan, Saeed Mahameed, netdev@vger.kernel.org,
Gal Pressman
In-Reply-To: <20260421113210.4f6a8eb6@kernel.org>
On Tue, 2026-04-21 at 11:32 -0700, Jakub Kicinski wrote:
> On Tue, 21 Apr 2026 17:34:32 +0000 Cosmin Ratiu wrote:
> > > No, the normal thing to do is to propagate errors.
> > > If you want to diverge from that _you_ should have a reason,
> > > a better reason than a vague "kernel can fail".
> > > I'd prefer for the driver to fail in an obvious way.
> > > Which will be immediately spotted by the operator, not 2 weeks
> > > later when 10% of the fleet is upgraded already.
> > > The only exception I'd make is to keep devlink registered in
> > > case the fix is to flash a different FW.
> >
> > In this case, PSP not working would be spotted on the next PSP dev-
> > get
> > op which produces zilch instead of working devices.
>
> When you have X vendors times Y device generations times Z FW
> versions
> in your fleet dev-get returning nothing is not a failure. It just
> means
> you're running on a machine that's not capable. Best you can do to
> spot a buggy kernel is to notice that the fraction of PSP traffic is
> decreasing over time. After significant portion of the fleet is
> already
> on the bad kernel.
>
> > But I understand what you want. You'd like the netdevice to either
> > be
> > fully initialized with all supported+configured protocols or fail
> > the
> > open operation. No intermediate/partial states. This is a non-
> > trivial
> > refactor for mlx5, because mlx5_nic_enable() returns nothing.
> > Refactoring seems possible though, its only caller is
> > mlx5e_attach_netdev(), which returns errors. It's certainly not
> > something that should be done for a net fix though.
> >
> > I have a series pending for net-next where the PSP configuration is
> > hooked to mlx5e_psp_set_config(). I will look into implementing
> > what
> > you propose there and propagate errors.
> >
> > Meanwhile, do you want to take these fixes (1 and 2) or maybe just
> > 2
> > for net or not?
>
> Can you call mlx5e_psp_cleanup() when register fails for now?
Done for the next version, currently undergoing testing.
Cosmin.
^ permalink raw reply
* Re: [PATCH net 0/4] Intel Wired LAN Driver Updates 2026-04-20 (ice)
From: Simon Horman @ 2026-04-22 9:23 UTC (permalink / raw)
To: Jacob Keller
Cc: Przemek Kitszel, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev, Grzegorz Nitka,
Aleksandr Loktionov, Petr Oros, Sunitha Mekala, Timothy Miskell
In-Reply-To: <20260420-jk-iwl-net-2026-04-20-ptp-e825c-phy-interrupt-fixes-v1-0-bc2240f42251@intel.com>
On Mon, Apr 20, 2026 at 05:51:24PM -0700, Jacob Keller wrote:
> Since this is a set of related fixes for just the ice driver, Jake provides
> the following description for the series:
Thanks for the excellent cover letter and patch descriptions.
Reviewed-by: Simon Horman <horms@kernel.org>
For completeness:
* I have looked over the AI generated review of patch 2/4 by Sashiko.
You may wish to too. But I do not believe that feedback warrants
holding up this series. Actually, I am skeptical those issues
should be addressed at all.
* I have also looked over the AI generated review based on Chris Mason's
review prompts which is available at https://netdev-ai.bots.linux.dev
(if only it had a name!). It flags an potentially incorrect Fixes tag in
patch 4/4. However, the cover letter for the patch explains the
choice of Fixes tag, effectively rebutting the analysis generated by AI
(I guess it didn't take the commit message sufficiently into account.)
^ permalink raw reply
* Re: [PATCH] dt-bindings: Fix phandle-array constraints, again
From: Krzysztof Kozlowski @ 2026-04-22 9:19 UTC (permalink / raw)
To: Rob Herring (Arm)
Cc: Maarten Lankhorst, Maxime Ripard, Krzysztof Kozlowski,
Conor Dooley, Ulf Hansson, Stephan Gerhold, Andrew Lunn,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Johannes Berg, Jeff Johnson, Bjorn Helgaas, Lorenzo Pieralisi,
Krzysztof Wilczyński, Manivannan Sadhasivam, Bjorn Andersson,
Mathieu Poirier, Sylwester Nawrocki, Mark Brown, Maxime Coquelin,
Greg Kroah-Hartman, Yang Xiwen, Alex Elder, Chaitanya Chundru,
Sibi Sankar, Rao Mandadapu, Patrice Chotard, Xu Yang, Peng Fan,
Thomas Zimmermann, devicetree, linux-kernel, linux-mmc,
linux-arm-msm, netdev, linux-wireless, ath10k, ath11k, linux-pci,
linux-remoteproc, linux-sound, linux-spi, linux-usb
In-Reply-To: <20260421195836.1547469-1-robh@kernel.org>
On Tue, Apr 21, 2026 at 02:55:25PM -0500, Rob Herring (Arm) wrote:
> The unfortunately named 'phandle-array' property type is really a matrix
> with phandle and fixed arg cells entries. A matrix property should have 2
> levels of items constraints.
>
> Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
> ---
> Can someone from QCom provide some descriptions for 'qcom,smem-states'
> properties.
Working on it...
Best regards,
Krzysztof
^ permalink raw reply
* Re: Bug#1130336: [regression] Network failure beyond first connection after 69894e5b4c5e ("netfilter: nft_connlimit: update the count if add was skipped")
From: Thorsten Leemhuis @ 2026-04-22 9:18 UTC (permalink / raw)
To: Fernando Fernandez Mancera, Alejandro Oliván Alvarez,
Salvatore Bonaccorso, 1130336
Cc: Florian Westphal, Pablo Neira Ayuso, Phil Sutter, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
netfilter-devel, coreteam, netdev, linux-kernel, regressions,
stable
In-Reply-To: <8788e351-553f-48da-a6e6-ce082adacb8d@suse.de>
Lo! Top-posting on purpose to make this easy to process.
What happened to this regression? It looks a bit like things stalled and
fell through the cracks. Or Fernando, did you post a patch like you
mentioned? I looked for one referring the commit or the reporter, but
could not find anything -- but maybe I missed it.
Ciao, Thorsten
On 3/19/26 09:59, Fernando Fernandez Mancera wrote:
> On 3/19/26 9:44 AM, Alejandro Oliván Alvarez wrote:
>> Hi folks.
>>
>> On Wed, 2026-03-18 at 13:49 +0100, Salvatore Bonaccorso wrote:
>>> Hi Alejandro,
>>>
>>> On Sun, Mar 15, 2026 at 02:09:33AM +0100, Fernando Fernandez Mancera
>>> wrote:
>>>> On 3/14/26 8:25 PM, Florian Westphal wrote:
>>>>> Fernando Fernandez Mancera <fmancera@suse.de> wrote:
>>>>>> On 3/14/26 5:13 PM, Fernando Fernandez Mancera wrote:
>>>>>>> Hi,
>>>>>>>
>>>>>>> On 3/14/26 3:03 PM, Salvatore Bonaccorso wrote:
>>>>>>>> Control: forwarded -1
>>>>>>>> https://lore.kernel.org/
>>>>>>>> regressions/177349610461.3071718.4083978280323144323@eldama
>>>>>>>> r.lan
>>>>>>>> Control: tags -1 + upstream
>>>>>>>>
>>>>>>>> Hi
>>>>>>>>
>>>>>>>> In Debian, in https://bugs.debian.org/1130336, Alejandro
>>>>>>>> reported that
>>>>>>>> after updates including 69894e5b4c5e ("netfilter:
>>>>>>>> nft_connlimit:
>>>>>>>> update the count if add was skipped"), when the following
>>>>>>>> rule is set
>>>>>>>>
>>>>>>>> iptables -A INPUT -p tcp -m
>>>>>>>> connlimit --connlimit-above 111 -j
>>>>>>>> REJECT --reject-with tcp-reset
>>>>>>>>
>>>>>>>> connections get stuck accordingly, it can be easily
>>>>>>>> reproduced by:
>>>>>>>>
>>>>>>>> # iptables -A INPUT -p tcp -m connlimit
>>>>>>>> --connlimit-above 111 -j REJECT
>>>>>>>> --reject-with tcp-reset
>>>>>>>> # nft list ruleset
>>>>>>>> # Warning: table ip filter is managed by iptables-nft, do
>>>>>>>> not touch!
>>>>>>>> table ip filter {
>>>>>>>> chain INPUT {
>>>>>>>> type filter hook input priority filter;
>>>>>>>> policy accept;
>>>>>>>> ip protocol tcp xt
>>>>>>>> match "connlimit" counter packets 0
>>>>>>>> bytes 0 reject with tcp reset
>>>>>>>> }
>>>>>>>> }
>>>>>>>> # wget -O /dev/null
>>>>>>>> https://git.kernel.org/torvalds/t/linux-7.0-
>>>>>>>> rc3.tar.gz
>>>>>>>> --2026-03-14 14:53:51--
>>>>>>>> https://git.kernel.org/torvalds/t/linux-7.0-
>>>>>>>> rc3.tar.gz
>>>>>>>> Resolving git.kernel.org
>>>>>>>> (git.kernel.org)... 172.105.64.184,
>>>>>>>> 2a01:7e01:e001:937:0:1991:8:25
>>>>>>>> Connecting to git.kernel.org
>>>>>>>> (git.kernel.org)|172.105.64.184|:443...
>>>>>>>> connected.
>>>>>>>> HTTP request sent, awaiting response... 301 Moved
>>>>>>>> Permanently
>>>>>>>> Location:
>>>>>>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/
>>>>>>>> linux.git/snapshot/linux-7.0-rc3.tar.gz
>>>>>>>> [following]
>>>>>>>> --2026-03-14 14:53:51--
>>>>>>>> https://git.kernel.org/pub/scm/linux/kernel/ git/torvalds/l
>>>>>>>> inux.git/snapshot/linux-7.0-rc3.tar.gz
>>>>>>>> Reusing existing connection to git.kernel.org:443.
>>>>>>>> HTTP request sent, awaiting response... 200 OK
>>>>>>>> Length: unspecified [application/x-gzip]
>>>>>>>> Saving to: ‘/dev/null’
>>>>>>>>
>>>>>>>> /dev/null [
>>>>>>>> <=> ] 248.03M
>>>>>>>> 51.9MB/s in 5.0s
>>>>>>>>
>>>>>>>> 2026-03-14 14:53:56 (49.3 MB/s) - ‘/dev/null’ saved
>>>>>>>> [260080129]
>>>>>>>>
>>>>>>>> # wget -O /dev/null
>>>>>>>> https://git.kernel.org/torvalds/t/linux-7.0-
>>>>>>>> rc3.tar.gz
>>>>>>>> --2026-03-14 14:53:58--
>>>>>>>> https://git.kernel.org/torvalds/t/linux-7.0-
>>>>>>>> rc3.tar.gz
>>>>>>>> Resolving git.kernel.org
>>>>>>>> (git.kernel.org)... 172.105.64.184,
>>>>>>>> 2a01:7e01:e001:937:0:1991:8:25
>>>>>>>> Connecting to git.kernel.org
>>>>>>>> (git.kernel.org)|172.105.64.184|:443...
>>>>>>>> failed: Connection timed out.
>>>>>>>> Connecting to git.kernel.org
>>>>>>>> (git.kernel.org)|
>>>>>>>> 2a01:7e01:e001:937:0:1991:8:25|:443...
>>>>>>>> failed: Network is unreachable.
>>>>>>>>
>>>>>>>> Before the 69894e5b4c5e ("netfilter: nft_connlimit: update
>>>>>>>> the count
>>>>>>>> if add was skipped") commit this worked.
>>>>>>>>
>>>>>>>
>>>>>>> Thanks for the report. I have reproduced
>>>>>>> this on upstream kernel. I am working on it.
>>>>>>>
>>>>>>
>>>>>> This is what is happening:
>>>>>>
>>>>>> 1. The first connection is established and
>>>>>> tracked, all good. When it finishes, it goes to
>>>>>> TIME_WAIT state
>>>>>> 2. The second connection is established, ct is
>>>>>> confirmed since the beginning, skipping the
>>>>>> tracking and calling a GC.
>>>>>> 3. The previously tracked connection is cleaned
>>>>>> up during GC as TIME_WAIT is considered closed.
>>>>>
>>>>> This is stupid. The fix is to add --syn or use
>>>>> OUTPUT. Its not even clear to me what the user wants to achive
>>>>> with this rule.
>>>>>
>>>>
>>>> Yes, the ruleset shown does not make sense. Having said this, it
>>>> could
>>>> affect to a soft-limit scenario as the one described on the blamed
>>>> commit..
>>>
>>> Alejandro, can you describe what you would like to achieve with the
>>> specific rule?
>>>
>>> Regards,
>>> Salvatore
>>
>> The intended use of that rule was to prevent (limit) a single host from
>> establishing too many TCP connections to given host (Denial of
>> Service... particularly on streaming servers).
>>
>> I learnt about it in several IPtables guides/howtos (maaaany years
>> ago!), and never was an issue on itself.
>> Was it stupid? ... possibly... It 'seemed' to work, or, at least, when
>> checking iptables -L -v one could see packet counter for the rule
>> catching some traffic, without ever noticing it being troublesome, so,
>> at the very least it 'didn't hurt', and, since DoS ever happened over
>> the years...well, I tended to think it was indeed working the way I
>> read it did.
>>
>> Certainly, I never (the authors of those guides at their time indeed)
>> though about the possibility of just target the TCP syn.
>> I have given a try to adding the --syn option to the rule to see the
>> difference, and well, it is way less disruptive that way, but it still
>> breaks things (I saw postfix queues hanging, for instance).
>>
>
> The current problem with the ruleset is that it mixes both, incoming and
> outgoing connections. This should probably use --syn flag so it targets
> connections established against your host only.
>
> Anyway, I am sending a patch fixing this as it makes sense to do it IMO.
> We just want to understand what is the real use-case and how the ruleset
> can be improved.
>
> In addition, I would recommend you to transition to nftables because it
> would be ideal for your use-case. With nftables it would be easy to
> combine this with sets and probably quota expression to limit the usage.
>
> What is wrong with the current ruleset? (Even before the blammed
> commit), if you reach the connlimit limit **ALL** TCP connections will
> be rejected (including legit ones), I do not think that is what you want
> to achieve.
>
> Thanks,
> Fernando.
>
>> So, I have but screwed the idea of using connlimit anymore anyways.
>> Sorry for the noise. Lesson learned.
>>
>> Cheers!
>
>
^ permalink raw reply
* Re: [PATCH net 00/18] Remove a number of ISA and PCMCIA Ethernet drivers
From: David Laight @ 2026-04-22 9:13 UTC (permalink / raw)
To: Daniel Palmer
Cc: Andrew Lunn, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Jonathan Corbet,
Shuah Khan, linux-kernel, netdev, linux-doc
In-Reply-To: <CAFr9PXn1ixyhD42OswoyGZ=W-O-oZygUGpRNm2dcAuYBNgtmQw@mail.gmail.com>
On Wed, 22 Apr 2026 07:03:19 +0900
Daniel Palmer <daniel@0x0f.com> wrote:
...
> Maybe we could add a special thing in the maintainers for "this is
> code only crazy people use" and have a rule to ignore untested AI
> generated patches for it? :)
Is marking them EXPERT or BROKEN enough?
(Or a similar new option.)
David
^ permalink raw reply
* [syzbot] Monthly net report (Apr 2026)
From: syzbot @ 2026-04-22 9:08 UTC (permalink / raw)
To: linux-kernel, netdev, syzkaller-bugs
Hello net maintainers/developers,
This is a 31-day syzbot report for the net subsystem.
All related reports/information can be found at:
https://syzkaller.appspot.com/upstream/s/net
During the period, 9 new issues were detected and 5 were fixed.
In total, 94 issues are still open and 1720 have already been fixed.
Some of the still happening issues:
Ref Crashes Repro Title
<1> 8561 Yes KMSAN: uninit-value in eth_type_trans (2)
https://syzkaller.appspot.com/bug?extid=0901d0cc75c3d716a3a3
<2> 3513 Yes INFO: task hung in linkwatch_event (4)
https://syzkaller.appspot.com/bug?extid=2ba2d70f288cf61174e4
<3> 3170 Yes INFO: task hung in synchronize_rcu (4)
https://syzkaller.appspot.com/bug?extid=222aa26d0a5dbc2e84fe
<4> 2914 Yes WARNING in rcu_check_gp_start_stall
https://syzkaller.appspot.com/bug?extid=111bc509cd9740d7e4aa
<5> 2111 Yes KMSAN: uninit-value in bpf_prog_run_generic_xdp
https://syzkaller.appspot.com/bug?extid=0e6ddb1ef80986bdfe64
<6> 2008 Yes INFO: task hung in del_device_store
https://syzkaller.appspot.com/bug?extid=6d10ecc8a97cc10639f9
<7> 1675 Yes INFO: task hung in addrconf_dad_work (5)
https://syzkaller.appspot.com/bug?extid=82ccd564344eeaa5427d
<8> 1312 Yes possible deadlock in hsr_dev_xmit (2)
https://syzkaller.appspot.com/bug?extid=fbf74291c3b7e753b481
<9> 663 Yes INFO: task hung in tun_chr_close (5)
https://syzkaller.appspot.com/bug?extid=b0ae8f1abf7d891e0426
<10> 632 Yes INFO: rcu detected stall in tc_modify_qdisc
https://syzkaller.appspot.com/bug?extid=9f78d5c664a8c33f4cce
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
To disable reminders for individual bugs, reply with the following command:
#syz set <Ref> no-reminders
To change bug's subsystems, reply with:
#syz set <Ref> subsystems: new-subsystem
You may send multiple commands in a single email message.
^ permalink raw reply
* Re: [PATCH net 1/1] net: nsh: handle nested NSH headers during GSO
From: Jiri Benc @ 2026-04-22 8:52 UTC (permalink / raw)
To: Ren Wei
Cc: netdev, davem, edumazet, kuba, pabeni, horms, yuantan098,
yifanwucs, tomapufckgml, bird, lx24, caoruide123
In-Reply-To: <6112cce99b4e3571444a616d0fb19e91e2fcca72.1776597598.git.caoruide123@gmail.com>
On Mon, 20 Apr 2026 11:31:32 +0800, Ren Wei wrote:
> Handle nested NSH headers iteratively in a single nsh_gso_segment()
> invocation. Unwrap consecutive NSH headers until the first non-NSH payload
> is reached, including the case where the next redispatch target is reached
> through ETH_P_TEB, segment that payload once, and then restore the full
> outer encapsulation on each output segment.
This looks fragile. If there's ever another protocol with similar logic
added, we'll be in the same situation. (And obviously, unrolling the
recursion for any combination of protocols doesn't scale well.)
What about using a mechanism similar to dev_xmit_recursion to limit the
depth and returning EINVAL if we exceed the limit? I think it's fine to
drop the packet in this pathological case.
We might even just use dev_xmit_recursion directly, since it can be
argued that such nested NSH headers are in fact nested tunnels.
Jiri
^ permalink raw reply
* Re: [PATCH net v3 1/1] net: hsr: limit node table growth
From: Sebastian Andrzej Siewior @ 2026-04-22 8:52 UTC (permalink / raw)
To: Felix Maurer
Cc: Ren Wei, netdev, davem, edumazet, kuba, pabeni, horms, kees,
kexinsun, luka.gejak, Arvid.Brodin, m-karicheri2, yuantan098,
yifanwucs, tomapufckgml, bird, xuyuqiabc, royenheart
In-Reply-To: <aeiHa7rzmSqzMIaJ@thinkpad>
On 2026-04-22 10:31:39 [+0200], Felix Maurer wrote:
> On Tue, Apr 21, 2026 at 10:50:01PM +0800, Ren Wei wrote:
> > diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c
> > index d09875b33588..8a5a2a54a81f 100644
> > --- a/net/hsr/hsr_framereg.c
> > +++ b/net/hsr/hsr_framereg.c
> > @@ -189,6 +195,7 @@ static struct hsr_node *hsr_add_node(struct hsr_priv *hsr,
> > enum hsr_port_type rx_port)
> > {
> > struct hsr_node *new_node, *node = NULL;
> > + unsigned int node_count = 0;
> > unsigned long now;
> > size_t block_sz;
> > int i;
> > @@ -226,20 +233,31 @@ static struct hsr_node *hsr_add_node(struct hsr_priv *hsr,
> > spin_lock_bh(&hsr->list_lock);
> > list_for_each_entry_rcu(node, node_db, mac_list,
> > lockdep_is_held(&hsr->list_lock)) {
> > + node_count++;
>
> I'm not sure if this on-the-fly node counting is the best solution here.
> My concern is that it comes quite late in the process, i.e., after we
> already allocated a bunch of memory, etc. As we are discussing a
> scenario where a lot of entries are created, maybe we shouldn't even
> allocate a new_node if the table is already full? For example by storing
> the node_count in hsr_priv and checking it early in the function?
The node is allocated upfront. Then it iterates here and we only end up
counting through the full list if there is no match. This is under a
lock so "many clients" are serialized. If we allocate the node later
then we need to do it under the lock.
I don't think the node count exceeds 100 in production. So having a
counter which is incremented while adding to the list and decremented
while removing items from the list would optimize the "worst case". So
instead traversing the list with 1000 we would just give up.
The "oom block" works regardless. This does not affect the common case
where we have far less nodes.
> > if (ether_addr_equal(node->macaddress_A, addr))
> > - goto out;
> > + goto out_found;
> > if (ether_addr_equal(node->macaddress_B, addr))
> > - goto out;
> > + goto out_found;
> > }
> > +
> > + if (hsr_node_table_size && node_count >= hsr_node_table_size)
> > + goto out_drop;
>
> I think it would be good to somehow make this situation transparent to
> the user, so they can react if this an undesired behavior (for example,
> because they simply have a large network and need a large node table).
netdev_warn_once() probably.
> > list_add_tail_rcu(&new_node->mac_list, node_db);
> > spin_unlock_bh(&hsr->list_lock);
> > return new_node;
> > -out:
> > +out_found:
> > spin_unlock_bh(&hsr->list_lock);
> > + xa_destroy(&new_node->seq_blocks);
> > kfree(new_node->block_buf);
> > -free:
> > kfree(new_node);
> > return node;
> > +out_drop:
> > + spin_unlock_bh(&hsr->list_lock);
> > + xa_destroy(&new_node->seq_blocks);
> > + kfree(new_node->block_buf);
> > +free:
> > + kfree(new_node);
> > + return NULL;
> > }
>
> The two cleanup paths are almost the same now. We usually attempt to
> keep them unified to make sure that we do the correct cleanup steps in
> all situations. So please keep them unified here as well.
>
> Thanks,
> Felix
Sebastian
^ permalink raw reply
* [PATCH net-next] Documentation: net/smc: correct old value of smcr_max_recv_wr
From: Mahanta Jambigi @ 2026-04-22 8:51 UTC (permalink / raw)
To: andrew+netdev, davem, edumazet, kuba, pabeni, alibuda, dust.li,
sidraya, wenjia
Cc: pasic, horms, tonylu, guwen, netdev, linux-s390, Mahanta Jambigi
The smc-sysctl.rst documentation incorrectly stated that the previous
hardcoded maximum number of WR buffers on the receive path (smcr_max_recv_wr)
was 16. The correct historical value used before the introduction of the sysctl
control was 48. Update the documentation to reflect the accurate default value.
Fixes: aef3cdb47bbb net/smc: make wr buffer count configurable
Reviewed-by: Halil Pasic <pasic@linux.ibm.com>
Reviewed-by: Sidraya Jayagond <sidraya@linux.ibm.com>
Signed-off-by: Mahanta Jambigi <mjambigi@linux.ibm.com>
---
Documentation/networking/smc-sysctl.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/networking/smc-sysctl.rst b/Documentation/networking/smc-sysctl.rst
index 904a910f198e..279d15e61899 100644
--- a/Documentation/networking/smc-sysctl.rst
+++ b/Documentation/networking/smc-sysctl.rst
@@ -100,14 +100,14 @@ smcr_max_recv_wr - INTEGER
depending on the workload it can be a bottleneck in a sense that threads
have to wait for work request buffers to become available. Before the
introduction of this control the maximal number of work request buffers
- available on the receive path used to be hard coded to 16. With this control
+ available on the receive path used to be hard coded to 48. With this control
it becomes configurable. The acceptable range is between 2 and 2048.
Please be aware that all the buffers need to be allocated as a physically
continuous array in which each element is a single buffer and has the size
of SMC_WR_BUF_SIZE (48) bytes. If the allocation fails, we keep retrying
with half of the buffer count until it is ether successful or (unlikely)
- we dip below the old hard coded value which is 16 where we give up much
+ we dip below the old hard coded value which is 48 where we give up much
like before having this control.
Default: 48
--
2.51.0
^ permalink raw reply related
* RE: [PATCH v2 1/1] tipc: fix double-free in tipc_buf_append()
From: Tung Quang Nguyen @ 2026-04-22 8:47 UTC (permalink / raw)
To: Lee Jones
Cc: tipc-discussion@lists.sourceforge.net, Jon Maloy, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, Ying Xue,
netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <20260421124528.162996-1-lee@kernel.org>
>Subject: [PATCH v2 1/1] tipc: fix double-free in tipc_buf_append()
>
>tipc_msg_validate() can potentially reallocate the skb it is validating, freeing
>the old one. In tipc_buf_append(), it was being called with a pointer to a local
>variable which was a copy of the caller's skb pointer.
>
>If the skb was reallocated and validation subsequently failed, the error
>handling path would free the original skb pointer, which had already been
>freed, leading to double-free.
>
>Fix this by checking if head now points to a newly allocated reassembled skb.
>If it does, reassign *headbuf for later freeing operations.
>
>Fixes: d618d09a68e4 ("tipc: enforce valid ratio between skb truesize and
>contents")
>Suggested-by: Tung Nguyen <tung.quang.nguyen@est.tech>
>Signed-off-by: Lee Jones <lee@kernel.org>
>---
>1v => v2: Keep the passed pointer type the same, but reassign on-change
>
> net/tipc/msg.c | 14 +++++++++++++-
> 1 file changed, 13 insertions(+), 1 deletion(-)
>
>diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 76284fc538eb..b0bba0feef56
>100644
>--- a/net/tipc/msg.c
>+++ b/net/tipc/msg.c
>@@ -177,8 +177,20 @@ int tipc_buf_append(struct sk_buff **headbuf, struct
>sk_buff **buf)
>
> if (fragid == LAST_FRAGMENT) {
> TIPC_SKB_CB(head)->validated = 0;
>- if (unlikely(!tipc_msg_validate(&head)))
>+
>+ /* If the reassembled skb has been freed in
>+ * tipc_msg_validate() because of an invalid truesize,
>+ * then head will point to a newly allocated reassembled
>+ * skb, while *headbuf points to freed reassembled skb.
>+ * In such cases, correct *headbuf for freeing the newly
>+ * allocated reassembled skb later.
>+ */
>+ if (unlikely(!tipc_msg_validate(&head))) {
>+ if (head != *headbuf)
>+ *headbuf = head;
> goto err;
>+ }
>+
> *buf = head;
> TIPC_SKB_CB(head)->tail = NULL;
> *headbuf = NULL;
>--
>2.54.0.rc1.555.g9c883467ad-goog
Reviewed-by: Tung Nguyen <tung.quang.nguyen@est.tech>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox