Netdev List
 help / color / mirror / Atom feed
* RE: [Intel-wired-lan] [PATCH iwl-net v2] ice: suppress DPLL errors during reset recovery
From: Rinitha, SX @ 2026-07-20 10:29 UTC (permalink / raw)
  To: Korba, Przemyslaw, intel-wired-lan@lists.osuosl.org
  Cc: netdev@vger.kernel.org, Nguyen, Anthony L, Kitszel, Przemyslaw,
	Loktionov, Aleksandr, Kubalewski, Arkadiusz, horms@kernel.org,
	Korba, Przemyslaw
In-Reply-To: <20260520115213.10864-2-przemyslaw.korba@intel.com>

> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf Of Przemyslaw Korba
> Sent: 20 May 2026 17:20
> To: intel-wired-lan@lists.osuosl.org
> Cc: netdev@vger.kernel.org; Nguyen, Anthony L <anthony.l.nguyen@intel.com>; Kitszel, Przemyslaw <przemyslaw.kitszel@intel.com>; Loktionov, Aleksandr <aleksandr.loktionov@intel.com>; Kubalewski, Arkadiusz <arkadiusz.kubalewski@intel.com>; horms@kernel.org; Korba, Przemyslaw <przemyslaw.korba@intel.com>
> Subject: [Intel-wired-lan] [PATCH iwl-net v2] ice: suppress DPLL errors during reset recovery
>
>During reset recovery, the admin queue returns EBUSY which is expected behavior. However, the DPLL subsystem was logging these as errors and incrementing the error counter, potentially leading to unnecessary warnings and even disabling the DPLL periodic worker if the threshold was reached.
>
> Suppress error logging and error counter increments when the admin queue returns EBUSY, as this is expected during reset recovery and not a real failure condition.
>
> test case:
> - ethtool --reset eth3 irq-shared dma-shared filter-shared offload-shared mac-shared phy-shared ram-shared
> - observe if dmesg EBUSY errors are gone
>
> Fixes: d7999f5ea64b ("ice: implement dpll interface to control cgu")
> Signed-off-by: Przemyslaw Korba <przemyslaw.korba@intel.com>
> ---
> v2:
> add missing EBUSY check in ice_dpll_pps_update_phase_offsets()
> v1:
> https://lore.kernel.org/intel-wired-lan/20260520105311.5336-1-przemyslaw.korba@intel.com/T/#u
> ---
> drivers/net/ethernet/intel/ice/ice_dpll.c | 19 ++++++++++++-------
> 1 file changed, 12 insertions(+), 7 deletions(-)
>

Tested-by: Rinitha S <sx.rinitha@intel.com> (A Contingent worker at Intel)

^ permalink raw reply

* Re: [PATCH net v2] net: erspan: set lltx to avoid sch_direct_xmit deadlock
From: Zhou, Yun @ 2026-07-20 10:32 UTC (permalink / raw)
  To: Ido Schimmel, edumazet
  Cc: dsahern, davem, kuba, pabeni, horms, netdev, linux-kernel
In-Reply-To: <20260720075352.GA2233846@shredder>



On 7/20/26 15:53, Ido Schimmel wrote:
> CAUTION: This email comes from a non Wind River email account!
> Do not click links or open attachments unless you recognize the sender and know the content is safe.
> 
> On Mon, Jul 13, 2026 at 11:14:35PM +0800, Yun Zhou wrote:
>> erspan_xmit() re-enters the network stack via ip_tunnel_xmit(), causing
>> nested acquisition of _xmit_lock on the underlay device while already
>> holding the ERSPAN device's _xmit_lock. Both are ARPHRD_ETHER and share
>> the same lockdep class, creating an ABBA deadlock:
>>
>>    sch_direct_xmit [lock erspan] -> erspan_xmit -> ip_tunnel_xmit ->
>>    ip_output -> __dev_queue_xmit -> sch_direct_xmit [lock underlay]
>>
>> Set dev->lltx = true so HARD_TX_LOCK() skips the spinlock for ERSPAN.
>> This is safe as erspan_xmit() has no shared mutable state: o_seqno is
>> atomic, stats use atomic_long_inc, and dst_cache is per-CPU. GRETAP,
>> the sibling device with identical xmit structure, already sets lltx.
> 
> erspan_xmit() (unlike gre_tap_xmit()) is performing non-atomic
> __clear_bit() on shared tunnel flags and KCSAN will probably flag it.
> 
> Eric had a patch [1] that changes erspan_xmit() to use a private copy of
> these flags. I think it's better to wait for Eric's patch to be merged
> before setting lltx.
> 
> Eric, can you please submit v2 of your patch to net?
> 
> Also, doesn't ip6erspan suffer from the same problem? Please try to
> reproduce and fix.
> 

The following command sequence can reproduce the problem:

ip link set lo up

ip addr add fd00:a::1/128 dev lo
ip addr add fd00:b::1/128 dev lo

ip link add ip6erspan_dev type ip6erspan \
     local fd00:a::1 remote fd00:a::2 \
     seq key 1 erspan_ver 1 erspan 1
ip link set ip6erspan_dev up

ip link add ip6gretap_dev type ip6gretap \
     local fd00:b::1 remote fd00:b::2 seq
ip link set ip6gretap_dev up

ip -6 route add fd00:a::2/128 dev ip6gretap_dev
ip -6 route add fd00:b::2/128 dev ip6erspan_dev

ip -6 neigh add fd00:a::2 lladdr 00:11:22:33:44:55 dev ip6gretap_dev
ip -6 neigh add fd00:b::2 lladdr 00:11:22:33:44:66 dev ip6erspan_dev

^ permalink raw reply

* Re: [PATCH RESEND v1 net] ptp: netc: explicitly clear TMR_OFF during initialization
From: Breno Leitao @ 2026-07-20 10:36 UTC (permalink / raw)
  To: wei.fang
  Cc: richardcochran, xiaoning.wang, andrew+netdev, davem, edumazet,
	kuba, pabeni, Frank.Li, vadim.fedorenko, wei.fang, imx, netdev,
	linux-kernel
In-Reply-To: <20260720012508.23227-1-wei.fang@oss.nxp.com>

On Mon, Jul 20, 2026 at 09:25:08AM +0800, wei.fang@oss.nxp.com wrote:
> From: Clark Wang <xiaoning.wang@nxp.com>
> 
> The NETC timer does not support function level reset, so TMR_OFF_L/H
> registers are not cleared by pcie_flr(). If TMR_OFF was set to a
> non-zero value in a previous binding, it will persist across driver
> rebind and cause inaccurate PTP time.
> 
> There is also a hardware issue: after a warm reset or soft reset,
> TMR_OFF_L/H registers appear to be cleared to zero, but the timer clock
> domain internally retains the stale value. When the timer is re-enabled,
> TMR_CUR_TIME continues to track the old offset until TMR_OFF is written
> explicitly. This can cause incorrect PTP timestamps and even PTP clock
> synchronization failures.
> 
> Per the recommendation from the IP team, explicitly write 0 to TMR_OFF
> in netc_timer_init() to flush the internally cached value and ensure
> TMR_CUR_TIME follows the freshly initialized counter.
> 
> Fixes: 87a201d59963 ("ptp: netc: add NETC V4 Timer PTP driver support")
> Signed-off-by: Clark Wang <xiaoning.wang@nxp.com>
> Signed-off-by: Wei Fang <wei.fang@nxp.com>
> Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>

Reviewed-by: Breno Leitao <leitao@debian.org>

^ permalink raw reply

* Re: [PATCH] net: mana: cap HWC init max message size to HW_CHANNEL_MAX_REQUEST_SIZE
From: Simon Horman @ 2026-07-20 10:40 UTC (permalink / raw)
  To: michael.bommarito
  Cc: Simon Horman, haiyangz, decui, longli, kys, wei.liu,
	andrew+netdev, kuba, pabeni, netdev, linux-hyperv, linux-kernel,
	stable
In-Reply-To: <20260711150628.2914205-1-michael.bommarito@gmail.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
https://sashiko.dev/#/patchset/20260711150628.2914205-1-michael.bommarito@gmail.com?part=1
---
--- Patch [1]: [PATCH] net: mana: cap HWC init max message size to HW_CHANNEL_MAX_REQUEST_SIZE ---
commit ea80048daa839e9f12f06618139e15fddebc0ac5
Author: Michael Bommarito <michael.bommarito@gmail.com>

net: mana: cap HWC init max message size to HW_CHANNEL_MAX_REQUEST_SIZE

The commit adds bounds checking for max message size during HWC initialization.
It claims this prevents an out-of-bounds DMA buffer write in
mana_hwc_alloc_dma_buf().

>    mana_hwc_init_event_handler() in hw_channel.c stores device-advertised
>    HWC_INIT_DATA_MAX_REQUEST and HWC_INIT_DATA_MAX_RESPONSE values
>    without bounds checking. mana_hwc_alloc_dma_buf() later computes the
>    DMA buffer size as MANA_PAGE_ALIGN(q_depth * max_msg_size) in 32-bit
>    arithmetic. A malicious device returning a large max_msg_size causes
>    the product to wrap, allocating a small buffer while laying out
>    q_depth request slots at the unwrapped stride, placing slots outside
>    the allocation.

[Severity: Medium]
Is this description accurate?

The modified variables (hwc->hwc_init_max_req_msg_size and
hwc->hwc_init_max_resp_msg_size) appear to be dead code that do not affect
memory allocation. mana_hwc_alloc_dma_buf() is invoked before the event
handler runs (via mana_hwc_init_queues()) using hardcoded sizes (4096),
not the hardware-provided ones.

> diff --git a/drivers/net/ethernet/microsoft/mana/hw_channel.c b/drivers/net/ethernet/microsoft/mana/hw_channel.c
> index e3c24d50dad07..94594fba112f9 100644
> --- a/drivers/net/ethernet/microsoft/mana/hw_channel.c
> +++ b/drivers/net/ethernet/microsoft/mana/hw_channel.c
> @@ -150,10 +150,14 @@ static void mana_hwc_init_event_handler(void *ctx, struct gdma_queue *q_self,
>  			break;
>  
>  		case HWC_INIT_DATA_MAX_REQUEST:
> +			if (val == 0 || val > HW_CHANNEL_MAX_REQUEST_SIZE)
> +				val = HW_CHANNEL_MAX_REQUEST_SIZE;
>  			hwc->hwc_init_max_req_msg_size = val;
>  			break;
>  
>  		case HWC_INIT_DATA_MAX_RESPONSE:
> +			if (val == 0 || val > HW_CHANNEL_MAX_REQUEST_SIZE)
> +				val = HW_CHANNEL_MAX_REQUEST_SIZE;

[Severity: Low]
Does this incorrectly clamp HWC_INIT_DATA_MAX_RESPONSE using
HW_CHANNEL_MAX_REQUEST_SIZE instead of HW_CHANNEL_MAX_RESPONSE_SIZE?

>  			hwc->hwc_init_max_resp_msg_size = val;
>  			break;
>  

[Severity: High]
This is a pre-existing issue, but is it possible for a malicious device
to trigger an out-of-bounds MMIO write via an unchecked doorbell index?

Earlier in mana_hwc_init_event_handler():

	case GDMA_EQE_HWC_INIT_EQ_ID_DB:
		eq_db.as_uint32 = event->details[0];
		hwc->cq->gdma_eq->id = eq_db.eq_id;
		gd->doorbell = eq_db.doorbell;

When the driver posts WQEs and rings the doorbell via mana_gd_ring_doorbell():

drivers/net/ethernet/microsoft/mana/gdma_main.c:mana_gd_ring_doorbell() {
    ...
    void __iomem *addr = gc->db_page_base + gc->db_page_size * db_index;
    ...
    writeq(e.as_uint64, addr);
    ...
}

If eq_db.doorbell is excessively large, could it calculate a memory-mapped
address that exceeds gc->bar0_size, resulting in an out-of-bounds writeq()
that corrupts adjacent mappings?


[Severity: High]
This is a pre-existing issue, but does the unchecked max_num_cqs value
allow a malicious device to exhaust system memory?

Later in mana_hwc_init_event_handler():

		case HWC_INIT_DATA_MAX_NUM_CQS:
			gd->gdma_context->max_num_cqs = val;
			break;

This unbounded max_num_cqs value is later used for memory allocation:

drivers/net/ethernet/microsoft/mana/hw_channel.c:mana_hwc_establish_channel() {
    ...
	gc->cq_table = vcalloc(gc->max_num_cqs, sizeof(struct gdma_queue *));
    ...
}

If max_num_cqs is an exceptionally large 32-bit value (e.g., 0x1FFFFFFF),
could vcalloc() attempt to allocate multiple gigabytes of memory and cause a
host-level denial of service?

^ permalink raw reply

* Re: [PATCH net 2/7] selftests: openvswitch: add config file
From: Matthieu Baerts @ 2026-07-17  9:39 UTC (permalink / raw)
  To: Aaron Conole
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Shuah Khan, netdev, linux-kselftest, linux-kernel,
	Eelco Chaudron, Ilya Maximets, dev
In-Reply-To: <f7tldbar9gp.fsf@redhat.com>

Hi Aaron,

Thank you for the review!

On 16/07/2026 22:00, Aaron Conole wrote:
> Aaron Conole <aconole@redhat.com> writes:
>> "Matthieu Baerts (NGI0)" <matttbe@kernel.org> writes:
>>
>>> The kselftests doc mentions that a config file should be present "if a
>>> test needs specific kernel config options enabled". This selftest
>>> requires some kernel config, but no config file was provided.
>>>
>>> We could say that a sub-target could use the parent's config file, but
>>> the kselftests doc doesn't mention anything about that. Plus the
>>> net/openvswitch target is the only net target without a config file.
>>
>> We've been operating on that assumption from the openvswitch side, but
>> it's true that isn't explicitly documented anywhere, and I guess it
>> isn't officially supported in the kselftest framework.  I guess we'll
>> need to keep updating this config as we add tests for things like SCTP,
>> and others, and maybe that's a good thing like we can add a comment
>> describing which tests take which configs.
>>
>> The downside is for most of the OVS testing we use the NIPA scripts
>> and those 'inherit' the parent config, so it would be a change on our
>> side from the development standpoint (but probably something we should
>> have been doing from the beginning).
>>
>> That said, would it be worth also exploring the 'cascading
>> configuration' support?  It seems like a useful feature, but maybe it
>> should be a separate discussion.  I ask because of how OVS interacts
>> with the networking stack as an 'alternative bridge' so-to-speak, I do
>> worry about having to duplicate lots of configurations between the two
>> as we expand the test coverage on OVS side.

It is not clear to me what you are using on your side, but I guess it
should be doable to modify some scripts to merge this new config file
and the net one in your case.

>>> Here is a new config file, which is a trimmed version of the net one,
>>> with hopefully the minimal required kconfig on top of 'make defconfig'.
>>
>> Should this also remove the OVS configs from the upper level since there
>> shouldn't be OVS tests executing there (ie: CONFIG_OPENVSWITCH*)?
> 
> Actually, forget this part.  The P-MTU tests in pmtu.sh use ovs to
> create a datapath through OVS.  So these configurations need to stay at
> the top level as well.

Indeed. I don't know these tests well, but maybe this P-MTU selftest
should move to the net/openvswitch target?

Cheers,
Matt

^ permalink raw reply

* Re: [PATCH net 2/7] selftests: openvswitch: add config file
From: Matthieu Baerts @ 2026-07-17  9:39 UTC (permalink / raw)
  To: Eelco Chaudron
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Shuah Khan, netdev, linux-kselftest, linux-kernel,
	Aaron Conole, Ilya Maximets, dev
In-Reply-To: <454FC9EC-8F3C-4999-BE7B-91EADC392EF7@redhat.com>

Hi Eelco,

Thank you for the review!

On 16/07/2026 10:15, Eelco Chaudron wrote:
> On 10 Jul 2026, at 20:04, Matthieu Baerts (NGI0) wrote:
> 
>> The kselftests doc mentions that a config file should be present "if a
>> test needs specific kernel config options enabled". This selftest
>> requires some kernel config, but no config file was provided.
>>
>> We could say that a sub-target could use the parent's config file, but
>> the kselftests doc doesn't mention anything about that. Plus the
>> net/openvswitch target is the only net target without a config file.
>>
>> Here is a new config file, which is a trimmed version of the net one,
>> with hopefully the minimal required kconfig on top of 'make defconfig'.
>>
>> The Fixes tag points to the introduction of the net/openvswitch target,
>> just to help validating this target on stable kernels.
>>
>> Fixes: 25f16c873fb1 ("selftests: add openvswitch selftest suite")
>> Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
> 
> Thanks for adding this Matthieu.
> 
> The changes look good to me, and I've tested the configuration and
> it works fine. Note that the config cannot be used for the OVS
> make-kernel test as it's missing some modules. But that's fine for
> the purpose of this kselftest suite.
> 
> Do note that when adding new tests to the openvswitch kselftest
> suite, they should be validated against this config, as the upstream
> CI uses the net config, which has more modules enabled.

Indeed. I'm currently doing some modifications for this CI, and this
behaviour might change in the future to use new config file for this
net/openvswitch target.

Cheers,
Matt

^ permalink raw reply

* Re: [PATCH net v5 0/2] amt: fix use-after-free of the skb head across pulls
From: Simon Horman @ 2026-07-20 11:06 UTC (permalink / raw)
  To: Michael Bommarito
  Cc: Taehee Yoo, Andrew Lunn, David S . Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, netdev, linux-kernel
In-Reply-To: <20260711151934.2955226-1-michael.bommarito@gmail.com>

On Sat, Jul 11, 2026 at 11:19:32AM -0400, Michael Bommarito wrote:
> Several AMT receive and transmit paths cache a pointer into the skb head
> and then call a helper that can reallocate that head before the cached
> pointer is used again, so the later access reads or writes freed memory.
> 
> Patch 1 walks every AMT path and, for each pointer used after a
> reallocating call, either snapshots the value before the first pull or
> re-derives the pointer after the last one.
> 
> Patch 2 is a smaller, separable hardening change: the three handlers
> that rewrite the ethernet header do so in place without making the head
> private, which corrupts a cloned skb (for example one held by a packet
> tap).  It adds skb_cow_head() before the rewrite, split out so the
> use-after-free fix is not held up by discussion of the clone case.
> 
> Both patches build cleanly (x86_64, CONFIG_AMT, W=1) and are
> checkpatch --strict clean.
> 
> Changes since v4:
>  - amt_update_handler(): also snapshot amtmu->nonce and
>    amtmu->response_mac before iptunnel_pull_header(), which can
>    reallocate the head for a GSO cloned skb; the tunnel-match loop read
>    both fields through the stale amtmu.  This is the same class as the
>    query handler's response_mac snapshot and was the one remaining site
>    the v4 fix missed.
>  - Remove the explanatory comments added in v4; the reason for each
>    snapshot/re-derive is described in the commit message instead.
>  - Order the local variable declarations longest-to-shortest in the
>    handlers that gained locals (amt_membership_query_handler and
>    amt_update_handler).
> 
> v4: https://lore.kernel.org/all/20260707193243.3448201-1-michael.bommarito@gmail.com/
> v3: https://lore.kernel.org/all/20260626111917.802243-1-michael.bommarito@gmail.com/
> v2: https://lore.kernel.org/all/20260617123443.3586930-1-michael.bommarito@gmail.com/

For the series:

Reviewed-by: Simon Horman <horms@kernel.org>

FTR, I believe the issues flagged in the AI-generated review of this patch
should not block it's progress. Rather, you may wish to consider then in
the context of possible follow-up.


^ permalink raw reply

* [PATCH net v2] net: stmmac: dwmac4: mask interrupts when stopping DMA in suspend
From: Luis Lang @ 2026-07-20 11:15 UTC (permalink / raw)
  To: netdev
  Cc: Luis Lang, Andrew Lunn, Maxime Chevallier, Andrew Lunn,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Maxime Coquelin, Alexandre Torgue, Russell King (Oracle),
	Oleksij Rempel, Ovidiu Panait, Rohan G Thomas,
	moderated list:ARM/STM32 ARCHITECTURE,
	moderated list:ARM/STM32 ARCHITECTURE, open list

Since commit 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU
interrupts"), suspending causes an interrupt storm from the RPS
interrupt.
Fix this by adding a deinit_chan() op to stmmac_dma_ops, which
masks all default dma channel interrupts. This is called from
stmmac_stop_all_dma(), so interrupts don't trigger while suspending.

Fixes: 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts")
Suggested-by: Andrew Lunn <andrew@lunn.ch>
Suggested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Signed-off-by: Luis Lang <luis.la@mail.de>
---
 .../net/ethernet/stmicro/stmmac/dwmac4_dma.c  | 24 +++++++++++++++++++
 drivers/net/ethernet/stmicro/stmmac/hwif.h    |  4 ++++
 .../net/ethernet/stmicro/stmmac/stmmac_main.c |  4 ++++
 3 files changed, 32 insertions(+)

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
index 829a23bdad01..23ffe1adcd0d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
@@ -106,6 +106,17 @@ static void dwmac4_dma_init_channel(struct stmmac_priv *priv,
 	       ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
 }
 
+static void dwmac4_dma_deinit_channel(struct stmmac_priv *priv,
+				      void __iomem *ioaddr, u32 chan)
+{
+	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
+	u32 value;
+
+	value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
+	value &= ~DMA_CHAN_INTR_DEFAULT_MASK;
+	writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
+}
+
 static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
 				      void __iomem *ioaddr,
 				      struct stmmac_dma_cfg *dma_cfg, u32 chan)
@@ -125,6 +136,17 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv,
 	       ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
 }
 
+static void dwmac410_dma_deinit_channel(struct stmmac_priv *priv,
+					void __iomem *ioaddr, u32 chan)
+{
+	const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs;
+	u32 value;
+
+	value = readl(ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
+	value &= ~DMA_CHAN_INTR_DEFAULT_MASK_4_10;
+	writel(value, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan));
+}
+
 static void dwmac4_dma_init(void __iomem *ioaddr,
 			    struct stmmac_dma_cfg *dma_cfg)
 {
@@ -548,6 +570,7 @@ const struct stmmac_dma_ops dwmac4_dma_ops = {
 	.reset = dwmac4_dma_reset,
 	.init = dwmac4_dma_init,
 	.init_chan = dwmac4_dma_init_channel,
+	.deinit_chan = dwmac4_dma_deinit_channel,
 	.init_rx_chan = dwmac4_dma_init_rx_chan,
 	.init_tx_chan = dwmac4_dma_init_tx_chan,
 	.axi = dwmac4_dma_axi,
@@ -577,6 +600,7 @@ const struct stmmac_dma_ops dwmac410_dma_ops = {
 	.reset = dwmac4_dma_reset,
 	.init = dwmac4_dma_init,
 	.init_chan = dwmac410_dma_init_channel,
+	.deinit_chan = dwmac410_dma_deinit_channel,
 	.init_rx_chan = dwmac4_dma_init_rx_chan,
 	.init_tx_chan = dwmac4_dma_init_tx_chan,
 	.axi = dwmac4_dma_axi,
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index e6317b94fff7..04dafec021b4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -170,6 +170,8 @@ struct stmmac_dma_ops {
 	void (*init)(void __iomem *ioaddr, struct stmmac_dma_cfg *dma_cfg);
 	void (*init_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
 			  struct stmmac_dma_cfg *dma_cfg, u32 chan);
+	void (*deinit_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
+			    u32 chan);
 	void (*init_rx_chan)(struct stmmac_priv *priv, void __iomem *ioaddr,
 			     struct stmmac_dma_cfg *dma_cfg,
 			     dma_addr_t phy, u32 chan);
@@ -235,6 +237,8 @@ struct stmmac_dma_ops {
 	stmmac_do_void_callback(__priv, dma, init, __args)
 #define stmmac_init_chan(__priv, __args...) \
 	stmmac_do_void_callback(__priv, dma, init_chan, __priv, __args)
+#define stmmac_deinit_chan(__priv, __args...) \
+	stmmac_do_void_callback(__priv, dma, deinit_chan, __priv, __args)
 #define stmmac_init_rx_chan(__priv, __args...) \
 	stmmac_do_void_callback(__priv, dma, init_rx_chan, __priv, __args)
 #define stmmac_init_tx_chan(__priv, __args...) \
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 2a0d7eff88d3..af29a50ddb89 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2560,6 +2560,7 @@ static void stmmac_stop_all_dma(struct stmmac_priv *priv)
 {
 	u8 rx_channels_count = priv->plat->rx_queues_to_use;
 	u8 tx_channels_count = priv->plat->tx_queues_to_use;
+	u8 dma_csr_ch = max(rx_channels_count, tx_channels_count);
 	u8 chan;
 
 	for (chan = 0; chan < rx_channels_count; chan++)
@@ -2567,6 +2568,9 @@ static void stmmac_stop_all_dma(struct stmmac_priv *priv)
 
 	for (chan = 0; chan < tx_channels_count; chan++)
 		stmmac_stop_tx_dma(priv, chan);
+
+	for (chan = 0; chan < dma_csr_ch; chan++)
+		stmmac_deinit_chan(priv, priv->ioaddr, chan);
 }
 
 /**
-- 
2.55.0


^ permalink raw reply related

* [PATCH net v2] net: airoha: fix ETS channel derivation in airoha_tc_setup_qdisc_ets()
From: Lorenzo Bianconi @ 2026-07-20 11:22 UTC (permalink / raw)
  To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Lorenzo Bianconi
  Cc: linux-arm-kernel, linux-mediatek, netdev, Simon Horman

Derive the hardware QoS channel from opt->parent instead of opt->handle
in airoha_tc_setup_qdisc_ets(). The ETS qdisc handle is either
user-specified or auto-allocated by qdisc_alloc_handle() and bears no
relation to the HTB leaf classid that identifies the hardware channel.
HTB derives the channel from TC_H_MIN(opt->classid), and ETS is always
attached as a child of an HTB leaf, so its opt->parent matches that
classid. Using opt->handle instead can cause two ETS qdiscs on different
HTB leaves to collide on the same hardware channel, corrupting scheduler
configuration and stats.

Fixes: 20bf7d07c956 ("net: airoha: Add sched ETS offload support")
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
Changes in v2:
- Rebase on top of net main branch
- Link to v1: https://lore.kernel.org/r/20260704-airoha-ets-handle-fix-v1-1-42516b3549a1@kernel.org
---
 drivers/net/ethernet/airoha/airoha_eth.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c
index 59001fd4b6f7..fac2aaefffff 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.c
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
@@ -2504,8 +2504,7 @@ static int airoha_tc_setup_qdisc_ets(struct net_device *dev,
 	if (opt->parent == TC_H_ROOT)
 		return -EINVAL;
 
-	channel = TC_H_MAJ(opt->handle) >> 16;
-	channel = channel % AIROHA_NUM_QOS_CHANNELS;
+	channel = TC_H_MIN(opt->parent) % AIROHA_NUM_QOS_CHANNELS;
 
 	switch (opt->command) {
 	case TC_ETS_REPLACE:

---
base-commit: e13caf1c26587434f0b768193100440939c0fb91
change-id: 20260704-airoha-ets-handle-fix-6c166de3d396

Best regards,
-- 
Lorenzo Bianconi <lorenzo@kernel.org>


^ permalink raw reply related

* Re: [PATCH] net: stmmac: dwmac4: mask interrupts before stopping DMA in suspend
From: luis.la @ 2026-07-20 11:24 UTC (permalink / raw)
  To: Maxime Chevallier, netdev
  Cc: Andrew Lunn, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
	Russell King (Oracle), Ovidiu Panait, Oleksij Rempel,
	Rohan G Thomas, moderated list:ARM/STM32 ARCHITECTURE,
	moderated list:ARM/STM32 ARCHITECTURE, open list
In-Reply-To: <5cc0d788-c78d-40f2-998f-235d40f567f2@bootlin.com>

Hi Maxime,
> This is almost perfect for a new submission, only 2 things to improve :
> 
>  - you're missing the tree name in the patch subject. As this is a fix, it should be :
> 
>    [PATCH net] net: stmmac: dwmac4: mask interrupts before stopping DMA in suspend
> 
>    you can find instructions for this in the doc Andrew linked :
> 
>    https://www.kernel.org/doc/html/latest/process/maintainer-netdev.html
> 
>  - When submitting a patch, do so in a dedicated thread, and not in reply to
>    other threads.
> 
> You should send a V2 addressing the tree name in the patch subject.

Thanks for the feedback, I addressed these changes and sent a v2 patch.

> Sashiko noted something on the patch :
> 
>   https://sashiko.dev/#/patchset/20260718152802.83553-1-luis.la%40mail.de
> 
> It looks to me that sashiko is just wrong there though, I can't make sense
> of what it is saying.

This seems to be because strictly speaking the title of the commit was wrong,
the interrupts don't get deactivated before stopping dma.
I changed it, but only read after that it is discouraged to change the Subject, sorry...
I hope the patch now meets the requirements,
Luis


^ permalink raw reply

* Re: [PATCH net 2/2] selftests: ptp: add a regression test for the frequency adjustment overflow
From: Simon Horman @ 2026-07-20 11:28 UTC (permalink / raw)
  To: deepshah146
  Cc: Simon Horman, netdev, richardcochran, davem, kuba, pabeni,
	edumazet, andrew+netdev, linux-kernel, shuah, linux-kselftest
In-Reply-To: <20260712040922.6403-3-deepshah146@gmail.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
https://sashiko.dev/#/patchset/20260712040922.6403-3-deepshah146@gmail.com?part=2
---
--- Patch [2]: [PATCH net 2/2] selftests: ptp: add a regression test for the frequency adjustment overflow ---
commit be5629a2612f961645c213deea88db61fa06f083
Author: Deep Shah <deepshah146@gmail.com>

selftests: ptp: add a regression test for the frequency adjustment overflow
    
This commit adds a regression test that crafts a struct timex.freq directly
to verify if an overflowing frequency adjustment is correctly rejected by
ptp_clock_adjtime() with -ERANGE.

> diff --git a/tools/testing/selftests/ptp/ptp_freq_overflow.c b/tools/testing/selftests/ptp/ptp_freq_overflow.c
> new file mode 100644
> index 0000000000000..342b22689f679
> --- /dev/null
> +++ b/tools/testing/selftests/ptp/ptp_freq_overflow.c
[ ... ]
> +
> +#define FD_TO_CLOCKID(fd)	((~(clockid_t)(fd) << 3) | 3)

[Severity: Medium]
Does this macro left-shift a negative signed integer?

Casting fd (a positive integer) to clockid_t (a signed 32-bit int), applying
bitwise NOT, and left-shifting it by 3 yields a negative integer. Left-shifting
a negative signed integer invokes undefined behavior in ISO C, which will
trigger a runtime error if tests are run with Undefined Behavior Sanitizer
(UBSan) enabled.

Could the inverted value be cast to an unsigned integer prior to the shift,
similar to how it is handled in testptp.c?

[ ... ]
> +	/*
> +	 * (1 + 147573952589676412) * 125 == 2^64 + 9, which overflows s64 in
> +	 * scaled_ppm_to_ppb() and wraps the result to a ppb of 0.  A kernel
> +	 * that does not detect the overflow lets this absurd frequency past
> +	 * the max_adj check; a fixed kernel rejects it with -ERANGE.
> +	 */
> +	tx.modes = ADJ_FREQUENCY;
> +	tx.freq = 147573952589676412LL;

[Severity: Low]
Will this assignment cause a -Woverflow compiler warning on 32-bit
architectures?

On 32-bit platforms where tx.freq is a 32-bit long (without _TIME_BITS=64),
assigning this 64-bit literal exceeds the maximum value of the signed integer
type. Although a runtime check prevents execution, the compiler still parses
the assignment and emits a -Woverflow warning during the build.

> +
> +	ret = clock_adjtime(clkid, &tx);

[Severity: Medium]
Does this test permanently disrupt the hardware clock frequency on vulnerable
kernels without restoring it?

If the kernel does not have the overflow fix, clock_adjtime() will bypass
the max_adj check and push the corrupted frequency downstream to the driver
via ops->adjfine(). Because the test exits immediately after verifying the
error code, the original frequency is never restored, leaving time
synchronization corrupted until a reboot or manual reset.

Should the test read the initial dialed_frequency and restore it at the
end of the test?

> +	ksft_test_result(ret < 0 && errno == ERANGE,
> +			 "overflowing frequency adjustment is rejected (ret=%d errno=%d)\n",
> +			 ret, ret < 0 ? errno : 0);

[Severity: Medium]
Will this test incorrectly fail if the PTP clock is in free-running mode?

If virtual clocks are active on the selected PTP device, ptp_clock_freerun()
returns true and the kernel explicitly returns -EBUSY before evaluating the
frequency overflow logic. Since the test expects -ERANGE, receiving -EBUSY
will cause the KSFT assertion to fail.

Should -EBUSY be accounted for as a valid condition to gracefully skip
the test?

> +
> +	close(fd);
> +	ksft_finished();
> +}

^ permalink raw reply

* Re: [PATCH net 1/1] packet: synchronize pressure clearing with ring reconfiguration
From: Willem de Bruijn @ 2026-07-20 11:31 UTC (permalink / raw)
  To: Ren Wei, netdev
  Cc: willemdebruijn.kernel, davem, edumazet, pabeni, horms, vega,
	xizh2024, enjou1224z
In-Reply-To: <24f7311aed0c9ff06b8ea982647b82bf543ec369.1784454542.git.xizh2024@lzu.edu.cn>

Ren Wei wrote:
> From: Zihan Xi <xizh2024@lzu.edu.cn>
> 
> packet_set_ring() updates the RX ring state under sk_receive_queue.lock,
> but publishes the tpacket receive mode through po->prot_hook.func after
> releasing that lock. packet_poll() and packet_recvmsg() can therefore run
> the pressure clearing path after the ring has been cleared while still
> seeing tpacket_rcv, causing __packet_rcv_has_room() to dereference stale
> or NULL ring storage.
> 
> Serialize pressure clearing with RX ring reconfiguration and update the
> receive hook while holding the same queue lock when changing the RX ring.
> This keeps the receive hook decision consistent with the ring state used
> by the tpacket room checks.

Thanks for the report and proposed fix.

Ideally we can avoid taking sk_receive_queue.lock an extra time in
packet_recvmsg.

packet_rcv_try_clear_pressure only accesses the ring if flag
PACKET_SOCK_PRESSURE is set. One option may be to clear that in
packet_set_ring, after detaching the socket (and thus after any input
could set it again) and before swapping prot_hook.func (with a barrier
to guarantee that). E.g.,:

@@ -4528,6 +4528,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
        WRITE_ONCE(po->num, 0);
        if (was_running)
                __unregister_prot_hook(sk, false);
+       packet_sock_flag_set(po, PACKET_SOCK_PRESSURE, false);
 
        spin_unlock(&po->bind_lock);


> Fixes: 2ccdbaa6d55b ("packet: rollover lock contention avoidance")
> Cc: stable@vger.kernel.org
> Reported-by: Vega <vega@nebusec.ai>
> Assisted-by: Codex:gpt-5.4
> Signed-off-by: Zihan Xi <xizh2024@lzu.edu.cn>
> Reviewed-by: Ren Wei <enjou1224z@gmail.com>
> ---
>  net/packet/af_packet.c | 18 ++++++++++++++----
>  1 file changed, 14 insertions(+), 4 deletions(-)
> 
> diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
> index 8e6f3a734ba0..b369f44b4065 100644
> --- a/net/packet/af_packet.c
> +++ b/net/packet/af_packet.c
> @@ -1315,13 +1315,22 @@ static int packet_rcv_has_room(struct packet_sock *po, struct sk_buff *skb)
>  	return ret;
>  }
>  
> -static void packet_rcv_try_clear_pressure(struct packet_sock *po)
> +static void __packet_rcv_try_clear_pressure(struct packet_sock *po)
>  {
>  	if (packet_sock_flag(po, PACKET_SOCK_PRESSURE) &&
>  	    __packet_rcv_has_room(po, NULL) == ROOM_NORMAL)
>  		packet_sock_flag_set(po, PACKET_SOCK_PRESSURE, false);
>  }
>  
> +static void packet_rcv_try_clear_pressure(struct packet_sock *po)
> +{
> +	struct sock *sk = &po->sk;
> +
> +	spin_lock_bh(&sk->sk_receive_queue.lock);
> +	__packet_rcv_try_clear_pressure(po);
> +	spin_unlock_bh(&sk->sk_receive_queue.lock);
> +}
> +
>  static void packet_sock_destruct(struct sock *sk)
>  {
>  	skb_queue_purge(&sk->sk_error_queue);
> @@ -4304,7 +4313,7 @@ static __poll_t packet_poll(struct file *file, struct socket *sock,
>  			TP_STATUS_KERNEL))
>  			mask |= EPOLLIN | EPOLLRDNORM;
>  	}
> -	packet_rcv_try_clear_pressure(po);
> +	__packet_rcv_try_clear_pressure(po);
>  	spin_unlock_bh(&sk->sk_receive_queue.lock);
>  	spin_lock_bh(&sk->sk_write_queue.lock);
>  	if (po->tx_ring.pg_vec) {
> @@ -4544,14 +4553,15 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
>  		rb->frame_max = (req->tp_frame_nr - 1);
>  		rb->head = 0;
>  		rb->frame_size = req->tp_frame_size;
> +		if (!tx_ring)
> +			po->prot_hook.func = po->rx_ring.pg_vec ?
> +						tpacket_rcv : packet_rcv;
>  		spin_unlock_bh(&rb_queue->lock);
>  
>  		swap(rb->pg_vec_order, order);
>  		swap(rb->pg_vec_len, req->tp_block_nr);
>  
>  		rb->pg_vec_pages = req->tp_block_size/PAGE_SIZE;
> -		po->prot_hook.func = (po->rx_ring.pg_vec) ?
> -						tpacket_rcv : packet_rcv;
>  		skb_queue_purge(rb_queue);
>  		if (atomic_long_read(&po->mapped))
>  			pr_err("packet_mmap: vma is busy: %ld\n",
> -- 
> 2.43.0



^ permalink raw reply

* Re: [PATCH iwl-next v2 1/2] i40e: move ATR sample rate from ring to PF level
From: mohammad heib @ 2026-07-20 11:36 UTC (permalink / raw)
  To: Simon Horman
  Cc: intel-wired-lan, netdev, jiri, davem, edumazet, kuba, pabeni,
	corbet, anthony.l.nguyen, przemyslaw.kitszel, andrew+netdev
In-Reply-To: <20260708143601.1491656-1-horms@kernel.org>

Hi Simon
Thank you for the review.

On 7/8/26 5:36 PM, Simon Horman wrote:
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> Full review at: https://sashiko.dev
> ---
> i40e: move ATR sample rate from ring to PF level
> 
> This commit moves the ATR sample rate configuration from the per-ring level
> to the PF level. It initializes the sample rate globally during software init
> and updates the fast path to reference the PF structure.
> 
>> diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
>> index a04683004a567..4d4d4b07a0f3a 100644
>> --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
>> +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
> [ ... ]
>> @@ -3454,12 +3454,7 @@ static int i40e_configure_tx_ring(struct i40e_ring *ring)
>>   		ring->xsk_pool = i40e_xsk_pool(ring);
>>   
>>   	/* some ATR related tx ring init */
>> -	if (test_bit(I40E_FLAG_FD_ATR_ENA, vsi->back->flags)) {
>> -		ring->atr_sample_rate = I40E_DEFAULT_ATR_SAMPLE_RATE;
>> -		ring->atr_count = 0;
>> -	} else {
>> -		ring->atr_sample_rate = 0;
>> -	}
>> +	ring->atr_count = 0;
> 
> [Severity: High]
> Does removing this per-ring initialization remove the protection against
> dynamic ethtool flag toggles?
> 
> Previously, if the ring was configured while Flow Director ATR was disabled,
> the ring's sample rate was cached to 0 in i40e_configure_tx_ring(). This
> prevented descriptor injection even if the PF flag was later toggled on
> without a ring reset.
> 

The per-ring zeroing of atr_sample_rate was redundant. i40e_atr() 
already checks I40E_FLAG_FD_ATR_ENA before it ever looks at atr_sample_rate:

  /* make sure ATR is enabled */
   if (!test_bit(I40E_FLAG_FD_ATR_ENA, pf->flags))
       return;

   if (test_bit(__I40E_FD_ATR_AUTO_DISABLED, pf->state))
       return;

   /* if sampling is disabled do nothing */
   if (!pf->atr_sample_rate)
       return;


When ATR is disabled via ethtool private flags, the function bails out 
at the I40E_FLAG_FD_ATR_ENA check regardless of what atr_sample_rate is 
set to. The flag check is the real protection the per-ring sample rate 
cache was never the thing providing protection against dynamic toggling.


> [ ... ]
>> diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
>> index 894f2d06d39d0..b36e0fc9b31d2 100644
>> --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
>> +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
> [ ... ]
>> @@ -2879,7 +2879,7 @@ static void i40e_atr(struct i40e_ring *tx_ring, struct sk_buff *skb,
>>   		return;
>>   
>>   	/* if sampling is disabled do nothing */
>> -	if (!tx_ring->atr_sample_rate)
>> +	if (!pf->atr_sample_rate)
>>   		return;
> 
> [Severity: High]
> Can this global check lead to a hardware Malicious Driver Detection (MDD)
> event if ethtool flags are modified dynamically?
> 
> If an administrator performs the following sequence:
> 
> 1. Disables flow-director-atr via ethtool.
> 2. Disables ntuple (which resets the ring and sets tx_ctx.fd_ena = 0).
> 3. Re-enables flow-director-atr.
> 
> The final step does not trigger a ring reset, so fd_ena remains 0 in the
> hardware queue context.
> 
> However, I40E_FLAG_FD_ATR_ENA is now true, and pf->atr_sample_rate is
> globally set to a non-zero value.
> 
> Will i40e_atr() now proceed and inject FDIR descriptors into a TX queue
> that is not configured for FDIR?
> 
> If so, does this cause the hardware to trigger an MDD event and hang the
> TX queue?
> 
The scenario you described was already broken before this patch, walking 
through the old code with the same sequence:

   1. Disable ATR — flag cleared, __I40E_FD_ATR_AUTO_DISABLED set
   2. Disable ntuple — ring reset happens, i40e_configure_tx_ring() runs 
with ATR off, so ring->atr_sample_rate = 0 and fd_ena = 0
   3. Re-enable ATR — flag set, no ring reset

In the old code, ring->atr_sample_rate is stuck at 0 from step 2, so 
i40e_atr() bails out at the sample rate check. That avoids the fd_ena 
problem, but ATR is also silently non-functional
   — the user re-enabled it but it doesn't actually work until something 
triggers a ring reset.

This patch changes how that failure looks, instead of silently doing 
nothing, pf->atr_sample_rate is non-zero so i40e_atr() would proceed 
but the root cause is the same:
toggling ATR via ethtool private flags doesn't trigger a ring reset, so 
fd_ena can be stale.

Properly fixing this would mean triggering a reset when ATR is 
re-enabled. The reset calls i40e_configure_tx_ring(), which re-evaluates 
fd_ena based on the current flag state so fd_ena would be set to 1 since 
I40E_FLAG_FD_ATR_ENA is now on.

What do you think about addressing this as a follow-up patch on top of 
this series? Since it's a pre-existing issue, it feels like it belongs 
as a separate fix rather than being mixed into this refactor.



^ permalink raw reply

* Re: [PATCH 3/3] usb: typec: Use %pe to print error pointers
From: Badhri Jagan Sridharan @ 2026-07-20 11:38 UTC (permalink / raw)
  To: Subasri S
  Cc: Peter Chen, Greg Kroah-Hartman, Frank Li, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, Duncan Sands,
	Chas Williams, Minas Harutyunyan, Hans de Goede, Heikki Krogerus,
	linux-usb, imx, linux-arm-kernel, linux-kernel, linux-atm-general,
	netdev
In-Reply-To: <20260719-usb-ptr_err_patchset-v1-3-85f7f2e4fefb@gmail.com>

On Sun, Jul 19, 2026 at 5:56 AM Subasri S <subasris1210@gmail.com> wrote:
>
> Use the %pe format specifier instead of %ld with PTR_ERR() for printing
> error pointers in various typec drivers. This prints symbolic
> error names (e.g.-ENOMEM) instead of errno numbers (e.g. -12),
> making error logs more readable.
>
> This patch fixes coccinelle reported warnings:
> ./typec/tcpm/tcpm.c:4799:60-67: WARNING: Consider using %pe to print PTR_ERR()
> ./typec/mux/pi3usb30532.c:143:3-10: WARNING: Consider using %pe to print PTR_ERR()
> ./typec/mux/pi3usb30532.c:155:3-10: WARNING: Consider using %pe to print PTR_ERR()
> ./typec/wusb3801.c:281:5-12: WARNING: Consider using %pe to print PTR_ERR()
>
> Compile tested only.
>
> Signed-off-by: Subasri S <subasris1210@gmail.com>

Reviewed-by: Badhri Jagan Sridharan <badhri@google.com>
> ---
>  drivers/usb/typec/mux/pi3usb30532.c | 8 ++++----
>  drivers/usb/typec/tcpm/tcpm.c       | 2 +-
>  drivers/usb/typec/wusb3801.c        | 4 ++--
>  3 files changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/usb/typec/mux/pi3usb30532.c b/drivers/usb/typec/mux/pi3usb30532.c
> index 985683fe49e9..a2357a28ecf4 100644
> --- a/drivers/usb/typec/mux/pi3usb30532.c
> +++ b/drivers/usb/typec/mux/pi3usb30532.c
> @@ -139,8 +139,8 @@ static int pi3usb30532_probe(struct i2c_client *client)
>
>         pi->sw = typec_switch_register(dev, &sw_desc);
>         if (IS_ERR(pi->sw)) {
> -               dev_err(dev, "Error registering typec switch: %ld\n",
> -                       PTR_ERR(pi->sw));
> +               dev_err(dev, "Error registering typec switch: %pe\n",
> +                       pi->sw);
>                 return PTR_ERR(pi->sw);
>         }
>
> @@ -151,8 +151,8 @@ static int pi3usb30532_probe(struct i2c_client *client)
>         pi->mux = typec_mux_register(dev, &mux_desc);
>         if (IS_ERR(pi->mux)) {
>                 typec_switch_unregister(pi->sw);
> -               dev_err(dev, "Error registering typec mux: %ld\n",
> -                       PTR_ERR(pi->mux));
> +               dev_err(dev, "Error registering typec mux: %pe\n",
> +                       pi->mux);
>                 return PTR_ERR(pi->mux);
>         }
>
> diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
> index 89eec20a2064..ad10470ea73b 100644
> --- a/drivers/usb/typec/tcpm/tcpm.c
> +++ b/drivers/usb/typec/tcpm/tcpm.c
> @@ -4796,7 +4796,7 @@ static void tcpm_typec_connect(struct tcpm_port *port)
>                         port->partner_desc.accessory = TYPEC_ACCESSORY_NONE;
>                 partner = typec_register_partner(port->typec_port, &port->partner_desc);
>                 if (IS_ERR(partner)) {
> -                       dev_err(port->dev, "Failed to register partner (%ld)\n", PTR_ERR(partner));
> +                       dev_err(port->dev, "Failed to register partner (%pe)\n", partner);
>                         return;
>                 }
>
> diff --git a/drivers/usb/typec/wusb3801.c b/drivers/usb/typec/wusb3801.c
> index 6062875fb04a..86d13ab41670 100644
> --- a/drivers/usb/typec/wusb3801.c
> +++ b/drivers/usb/typec/wusb3801.c
> @@ -277,8 +277,8 @@ static void wusb3801_hw_update(struct wusb3801 *wusb3801)
>                 if (partner_type != WUSB3801_STAT_PARTNER_STANDBY) {
>                         wusb3801->partner = typec_register_partner(port, &desc);
>                         if (IS_ERR(wusb3801->partner))
> -                               dev_err(dev, "Failed to register partner: %ld\n",
> -                                       PTR_ERR(wusb3801->partner));
> +                               dev_err(dev, "Failed to register partner: %pe\n",
> +                                       wusb3801->partner);
>                 }
>
>                 data_role = pwr_role == TYPEC_SOURCE ? TYPEC_HOST : TYPEC_DEVICE;
>
> --
> 2.43.0
>

^ permalink raw reply

* Re: [PATCH RFC net-next 3/6] bpf: Allow skb extensions to survive packet scrubbing
From: Jakub Sitnicki @ 2026-07-20 11:39 UTC (permalink / raw)
  To: Jason Xing
  Cc: Stanislav Fomichev, Daniel Borkmann, John Fastabend, netdev, bpf,
	kernel-team, Jakub Kicinski, Kuniyuki Iwashima
In-Reply-To: <CAL+tcoBPv2_yMZrrvgNT7kkL9tCmAfUZmsr7+0qYukRmYJb6gQ@mail.gmail.com>

On Fri, Jul 17, 2026 at 07:30 PM +02, Jason Xing wrote:
> On Thu, Jul 16, 2026 at 5:06 PM Jason Xing <kerneljasonxing@gmail.com> wrote:
>>
>> On Thu, Jul 16, 2026 at 3:00 PM Jakub Sitnicki <jakub@cloudflare.com> wrote:
>> >
>> > On Thu, Jul 16, 2026 at 05:11 AM -07, Stanislav Fomichev wrote:
>> > > On 07/14, Jakub Sitnicki wrote:
>> > >> skb_scrub_packet() drops all skb extensions unconditionally via
>> > >> skb_ext_reset(). It runs on tunnel encap/decap (ip_tunnel_rcv,
>> > >> vxlan_rcv, etc.) and cross-netns forwarding (dev_forward_skb).
>> > >>
>> > >> This makes it impossible for a BPF program to pass metadata via
>> > >> bpf_skb_ext through a tunnel or across a netns boundary. The extension
>> > >> is always lost at the scrub point.
>> > >>
>> > >> Introduce skb_ext_scrub() which consults each active extension before
>> > >> discarding it. Extensions that request preservation are kept while the
>> > >> rest are torn down. When the extension slab is shared with clones, COW
>> > >> ensures isolation. Replace the skb_ext_reset() call in
>> > >> skb_scrub_packet() with skb_ext_scrub().
>> > >>
>> > >> Expose the opt-in mechanism to BPF via the BPF_SKB_EXT_F_NO_SCRUB flag
>> > >> for bpf_dynptr_from_skb_ext(). A program that sets this flag when
>> > >> creating the extension signals that its metadata should survive
>> > >> scrubbing.
>> > >>
>> > >> Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
>> > >> ---
>> > >>  include/linux/bpf.h      |  1 +
>> > >>  include/linux/skbuff.h   |  2 ++
>> > >>  include/uapi/linux/bpf.h |  3 +-
>> > >>  net/core/filter.c        | 11 +++++--
>> > >>  net/core/skbuff.c        | 82 ++++++++++++++++++++++++++++++++++++++++++------
>> > >>  net/ipv4/udp.c           |  2 +-
>> > >>  6 files changed, 86 insertions(+), 15 deletions(-)
>> > >>
>> > >> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
>> > >> index 6b918a5b61bf..a46ca53c5b27 100644
>> > >> --- a/include/linux/bpf.h
>> > >> +++ b/include/linux/bpf.h
>> > >> @@ -4214,6 +4214,7 @@ static inline int bpf_map_check_op_flags(struct bpf_map *map, u64 flags, u64 all
>> > >>  #ifdef CONFIG_BPF_SKB_EXT
>> > >>
>> > >>  struct bpf_skb_ext {
>> > >> +    u64 flags;
>> > >>      u8 buf[CONFIG_BPF_SKB_EXT_SIZE] __aligned(8);
>> > >>  };
>> > >>
>> > >> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
>> > >> index 584d8440d352..66afa5489007 100644
>> > >> --- a/include/linux/skbuff.h
>> > >> +++ b/include/linux/skbuff.h
>> > >> @@ -5063,6 +5063,7 @@ void *__skb_ext_set(struct sk_buff *skb, enum skb_ext_id id,
>> > >>  void *skb_ext_add(struct sk_buff *skb, enum skb_ext_id id);
>> > >>  void __skb_ext_del(struct sk_buff *skb, enum skb_ext_id id);
>> > >>  void __skb_ext_put(struct skb_ext *ext);
>> > >> +void skb_ext_scrub(struct sk_buff *skb);
>> > >>
>> > >>  static inline void skb_ext_put(struct sk_buff *skb)
>> > >>  {
>> > >> @@ -5132,6 +5133,7 @@ static inline bool skb_has_extensions(struct sk_buff *skb)
>> > >>  static inline void __skb_ext_put(struct skb_ext *ext) {}
>> > >>  static inline void skb_ext_put(struct sk_buff *skb) {}
>> > >>  static inline void skb_ext_reset(struct sk_buff *skb) {}
>> > >> +static inline void skb_ext_scrub(struct sk_buff *skb) {}
>> > >>  static inline void skb_ext_del(struct sk_buff *skb, int unused) {}
>> > >>  static inline void __skb_ext_copy(struct sk_buff *d, const struct sk_buff *s) {}
>> > >>  static inline void skb_ext_copy(struct sk_buff *dst, const struct sk_buff *s) {}
>> > >> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
>> > >> index 3eee4467422d..02da170205de 100644
>> > >> --- a/include/uapi/linux/bpf.h
>> > >> +++ b/include/uapi/linux/bpf.h
>> > >> @@ -7734,7 +7734,8 @@ struct bpf_insn_array_value {
>> > >>
>> > >>  /* Flags to control bpf_dynptr_from_skb_ext() behavior. */
>> > >>  enum {
>> > >> -    BPF_SKB_EXT_F_CREATE = (1ULL << 0),
>> > >> +    BPF_SKB_EXT_F_CREATE    = (1ULL << 0),
>> > >> +    BPF_SKB_EXT_F_NO_SCRUB  = (1ULL << 1),
>> > >
>> > > Do I understand correctly that you do prefer the NO_SCRUB mode? Any reason
>> > > we need to have scrub mode? If it's all produced/consumed by bpf, maybe
>> > > we can just carry this data unconditionally instead of having a SCRUB/NO_SCRUB
>> > > option?
>
> After giving it more thought, I vote for only no_scrub mode because I
> don't see any reason why we still use scrub mode. But it's just my
> opinion.
>
> My question is if we in the future really need the scrub mode, it's
> still possible to add this option, right?

Sorry for the delayed response. Took some time off after the conference.

I will make the bpf skb ext contents survive skb scrubbing in v1.

It seems to suit everyone we've heard from and it is consistent with the
existing bpf_redirect_peer behavior wrt xdp/skb metadata.

^ permalink raw reply

* Re: [PATCH net] nfc: llcp: Fix raw socket local ref leak on rebind
From: Simon Horman @ 2026-07-20 11:41 UTC (permalink / raw)
  To: shuangpeng.kernel
  Cc: Simon Horman, david, davem, edumazet, kuba, pabeni, sameo,
	oe-linux-nfc, netdev, linux-kernel, stable
In-Reply-To: <20260713012111.4066423-1-shuangpeng.kernel@gmail.com>

This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260713012111.4066423-1-shuangpeng.kernel@gmail.com?part=1
---
Now I have enough context to produce the report.

commit 569ae381cd8b4adedc1a30fa7c6777d518fb2eb7
Author: Shuangpeng Bai <shuangpeng.kernel@gmail.com>
Subject: nfc: llcp: Fix raw socket local ref leak on rebind

This patch fixes a leak of the nfc_llcp_local reference owned by raw
LLCP sockets when the bound NFC device is unregistered and the socket
is subsequently rebound. It drops any stale llcp_sock->local before
storing the new reference obtained from nfc_llcp_find_local().

> diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
> index feab29fc62f4..0c00cdaabbc6 100644
> --- a/net/nfc/llcp_sock.c
> +++ b/net/nfc/llcp_sock.c
> @@ -152,6 +152,7 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr_unsized *addr
>  	struct sock *sk = sock->sk;
>  	struct nfc_llcp_sock *llcp_sock = nfc_llcp_sock(sk);
>  	struct nfc_llcp_local *local;
> +	struct nfc_llcp_local *old_local;
>  	struct nfc_dev *dev;
>  	struct sockaddr_nfc_llcp llcp_addr;
>  	int len, ret = 0;
> @@ -185,6 +186,11 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr_unsized *addr
>  		goto put_dev;
>  	}
>  
> +	old_local = llcp_sock->local;
> +	llcp_sock->local = NULL;
> +	llcp_sock->dev = NULL;
> +	nfc_llcp_local_put(old_local);
> +
>  	llcp_sock->dev = dev;
>  	llcp_sock->local = local;
>  	llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;

[High]
Does the same rebind leak exist on the non-raw path in llcp_sock_bind()?

nfc_llcp_socket_release() walks local->sockets first and, for every
non-raw socket, sets sk_state to LLCP_CLOSED and calls sk_del_node_init(),
but does not touch llcp_sock->local:

net/nfc/llcp_core.c:nfc_llcp_socket_release() {
    ...
    sk_for_each_safe(sk, tmp, &local->sockets.head) {
        llcp_sock = nfc_llcp_sock(sk);
        ...
        sk->sk_state = LLCP_CLOSED;
        sk->sk_state_change(sk);
        bh_unlock_sock(sk);
        sk_del_node_init(sk);
    }
    ...
    /* If we still have a device, we keep the RAW sockets alive */
    if (device == true)
        return;
    ...
}

That path is reachable for non-raw sockets from nfc_llcp_mac_is_down()
(which calls nfc_llcp_socket_release(local, true, 0)) while the nfc_dev
is still around, so a userspace rebind of a SOCK_STREAM/SOCK_DGRAM LLCP
socket that is now in LLCP_CLOSED with a stale llcp_sock->local passes
the gate and reaches:

net/nfc/llcp_sock.c:llcp_sock_bind() {
    ...
    if (sk->sk_state != LLCP_CLOSED) {
        ret = -EBADFD;
        goto error;
    }
    ...
    local = nfc_llcp_find_local(dev);
    ...
    llcp_sock->dev = dev;
    llcp_sock->local = local;
    ...
    llcp_sock->service_name = kmemdup(llcp_addr.service_name,
                                      llcp_sock->service_name_len,
                                      GFP_KERNEL);
    ...
}

Would this overwrite of llcp_sock->local leak the previous reference
returned by the earlier nfc_llcp_find_local(), together with the nfc_dev
ref that nfc_llcp_local_get() holds via local->dev, in the same way as
the raw path this patch is fixing?

As a secondary consequence in the same window, the unconditional
llcp_sock->service_name = kmemdup(...) reassignment appears to overwrite
the previous kmemdup allocation without a kfree(), and
llcp_sock->reserved_ssap continues to reference an SSAP that was reserved
on the earlier local.

Would it make sense to extend the same "drop old_local before overwriting"
pattern to llcp_sock_bind() so both bind paths are covered by the fix?

^ permalink raw reply

* Re: [PATCH net] e1000e: Fix out-of-bounds MMIO access by validating BAR0 size
From: Pu Lehui @ 2026-07-20 11:56 UTC (permalink / raw)
  To: Breno Leitao
  Cc: Tony Nguyen, Przemek Kitszel, Andrew Lunn, David S. Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, netdev, linux-kernel
In-Reply-To: <al3uh7OU2OtkEkSY@gmail.com>


On 2026/7/20 17:47, Breno Leitao wrote:
> On Wed, Jul 15, 2026 at 03:58:50AM +0000, Pu Lehui wrote:
>> +/* Minimum MMIO (BAR0) len, the largest offset is lower than 64K */
> 
> Why "the largest" in this case?

Hi Breno,

Thanks for pointing that out. I meant the maximum register offset 
accessed by the driver.

IIUC, common e1000e NIC usually have a 128K BAR0. But since I'm not 100% 
sure if older NIC might be smaller, I picked 64K as a safe lower limit 
because it covers the largest register offset used in the driver's 
codebase. If my assumption here is off, I'd really appreciate any 
corrections!

And for this comment, how about the follow?
/* Minimum MMIO (BAR0) length to safely cover the maximum register 
offset accessed by the driver */


^ permalink raw reply

* [PATCH iwl-net 0/4] ice: fix PTP timestamp handling issues
From: Przemyslaw Korba @ 2026-07-20 12:01 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: netdev, anthony.l.nguyen, przemyslaw.kitszel, aleksandr.loktionov,
	arkadiusz.kubalewski, konstantin.ilichev

This series fixes several PTP timestamp handling issues in the ice
driver that manifest during link state transitions on E82x devices.
Together, these issues can cause Tx timestamp timeouts, ptp4l service
disruptions, and on PREEMPT_RT kernels, a system livelock requiring a
hard reboot.

The root cause is a set of race conditions in the PTP link change path.
When taking the link down (ice_down) or bringing it up
(ice_up_complete), the PTP recalibration and cleanup were not properly
synchronized with actual physical link transitions. This allowed Tx
timestamp requests to be queued against uncalibrated or stopped PHY
hardware, producing orphaned timestamp ready bits in the PHY registers.

On E82x, the PHY will not generate a new timestamp interrupt until all
outstanding ready bits have been read. Orphaned bits — set for slots
with no matching software tracker entry — are never read, permanently
blocking new timestamp interrupts. The existing periodic work detects
this symptom and re-triggers the interrupt, but without clearing the
stale bits, this creates an infinite trigger loop. On PREEMPT_RT
kernels, the resulting interrupt storm causes RCU stalls and eventually
a full system livelock.

Arkadiusz Kubalewski (1):
  ice: call PTP link change only from link events

Jacob Keller (1):
  ice: clear unexpected Tx timestamp ready bits to prevent stuck PHY

Karol Kolacinski (2):
  ice: keep Tx timestamps disabled until offset calibration completes
  ice: cancel E82x offset verification work during reset preparation

 drivers/net/ethernet/intel/ice/ice_main.c   |   3 +-
 drivers/net/ethernet/intel/ice/ice_ptp.c    | 155 +++++++++++++++++---
 drivers/net/ethernet/intel/ice/ice_ptp_hw.c |  89 +++++++++--
 drivers/net/ethernet/intel/ice/ice_ptp_hw.h |   1 +
 drivers/net/ethernet/intel/ice/ice_type.h   |   7 +
 5 files changed, 219 insertions(+), 36 deletions(-)

-- 
2.43.0

^ permalink raw reply

* [PATCH iwl-net 1/4] ice: keep Tx timestamps disabled until offset calibration completes
From: Przemyslaw Korba @ 2026-07-20 12:01 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: netdev, anthony.l.nguyen, przemyslaw.kitszel, aleksandr.loktionov,
	arkadiusz.kubalewski, konstantin.ilichev, Przemyslaw Korba
In-Reply-To: <20260720120151.2675206-1-przemyslaw.korba@intel.com>

From: Karol Kolacinski <karol.kolacinski@intel.com>

Do not clear the tx.calibrating flag immediately after starting the PHY
timer in ice_ptp_port_phy_restart(). Instead, keep Tx timestamps
disabled until the offset verification work (ice_ptp_wait_for_offsets)
has confirmed that both Tx and Rx PHY offsets are properly configured.

Previously, tx.calibrating was set to true, then immediately back to
false right after ice_start_phy_timer_e82x() returned. This allowed Tx
timestamp requests to be served during the window where offset
verification was still pending. Timestamps produced during this window
use uncalibrated PHY offsets and can produce incorrect values.

When ptp4l receives incorrect timestamps, it may reject them and wait
for the next sync interval (typically 1-2 seconds), compounding delays
during link cycling. This contributes to the time transmitter port
becoming unresponsive after repeated link down/up cycles.

Move the tx.calibrating = false to ice_ptp_wait_for_offsets(), after
both Tx and Rx offset configuration has completed successfully. This
ensures that Tx timestamps are only reported with properly calibrated
PHY offsets.

If ice_start_phy_timer_e82x() fails, restore calibrating to false on
the error path to prevent permanently disabling Tx timestamps when
ov_work is never queued.

Log a debug message while offset calibration is still pending, including
the specific Tx/Rx error codes to aid debugging stalled calibration.
This path is expected on every routine link-up: ov_work is first queued
with no delay and the vernier offset cannot be computed until at least
one packet has been transmitted, so the first several invocations
normally land here. Use dev_dbg() rather than a rate-limited warning to
avoid emitting KERN_WARNING on every link-up during normal operation.
Log a debug message when calibration completes successfully.

Fixes: 3a7496234d17 ("ice: implement basic E822 PTP support")
Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Signed-off-by: Przemyslaw Korba <przemyslaw.korba@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_ptp.c | 36 ++++++++++++++++++++----
 1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 6984fe5bf033..1aa440b0639f 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -1149,6 +1149,7 @@ static int ice_ptp_check_tx_fifo(struct ice_ptp_port *port)
 static void ice_ptp_wait_for_offsets(struct kthread_work *work)
 {
 	struct ice_ptp_port *port;
+	unsigned long flags;
 	struct ice_pf *pf;
 	struct ice_hw *hw;
 	int tx_err;
@@ -1171,12 +1172,28 @@ static void ice_ptp_wait_for_offsets(struct kthread_work *work)
 		tx_err = ice_phy_cfg_tx_offset_e82x(hw, port->port_num);
 	rx_err = ice_phy_cfg_rx_offset_e82x(hw, port->port_num);
 	if (tx_err || rx_err) {
-		/* Tx and/or Rx offset not yet configured, try again later */
+		/* Tx and/or Rx offset not yet configured, try again later.
+		 * This is expected during normal link-up: the vernier offset
+		 * calibration cannot complete until at least one packet has
+		 * been transmitted, so the first retries routinely land here.
+		 */
+		dev_dbg(ice_pf_to_dev(pf),
+			"PTP offset not yet valid for port %u (tx_err=%d rx_err=%d)\n",
+			port->port_num, tx_err, rx_err);
 		kthread_queue_delayed_work(pf->ptp.kworker,
 					   &port->ov_work,
 					   msecs_to_jiffies(100));
 		return;
 	}
+
+	/* Tx and Rx offsets are now configured, enable Tx timestamps */
+	spin_lock_irqsave(&port->tx.lock, flags);
+	port->tx.calibrating = false;
+	spin_unlock_irqrestore(&port->tx.lock, flags);
+
+	dev_dbg(ice_pf_to_dev(pf),
+		"PTP offset valid for port %u, Tx timestamps enabled\n",
+		port->port_num);
 }
 
 /**
@@ -1259,13 +1276,20 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port)
 
 		/* Start the PHY timer in Vernier mode */
 		err = ice_start_phy_timer_e82x(hw, port);
-		if (err)
+		if (err) {
+			spin_lock_irqsave(&ptp_port->tx.lock, flags);
+			ptp_port->tx.calibrating = false;
+			spin_unlock_irqrestore(&ptp_port->tx.lock, flags);
 			break;
+		}
 
-		/* Enable Tx timestamps right away */
-		spin_lock_irqsave(&ptp_port->tx.lock, flags);
-		ptp_port->tx.calibrating = false;
-		spin_unlock_irqrestore(&ptp_port->tx.lock, flags);
+		/* Do not clear calibrating flag here. Tx timestamps remain
+		 * disabled until ice_ptp_wait_for_offsets() has verified
+		 * that the Tx and Rx offset calibration has completed.
+		 * Clearing it here would allow Tx timestamps to be reported
+		 * before the PHY offset registers are configured, leading
+		 * to incorrect timestamp values.
+		 */
 
 		kthread_queue_delayed_work(pf->ptp.kworker, &ptp_port->ov_work,
 					   0);
-- 
2.43.0


^ permalink raw reply related

* [PATCH iwl-net 2/4] ice: clear unexpected Tx timestamp ready bits to prevent stuck PHY
From: Przemyslaw Korba @ 2026-07-20 12:01 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: netdev, anthony.l.nguyen, przemyslaw.kitszel, aleksandr.loktionov,
	arkadiusz.kubalewski, konstantin.ilichev, Grzegorz Nitka,
	Przemyslaw Korba
In-Reply-To: <20260720120151.2675206-1-przemyslaw.korba@intel.com>

From: Jacob Keller <jacob.e.keller@intel.com>

Clear orphaned timestamp ready bits left in the PHY when a packet is
timestamped just as the link goes down. The driver clears its software
in_use bits during link-down cleanup, but the PHY has already latched
the timestamp, so on the next link-up a stale ready bit from the
previous link cycle remains set with no matching in_use entry.

The PHY timestamp interrupt logic will not generate a new interrupt
until ALL outstanding ready bits have been read. ice_ptp_process_tx_
tstamp() only iterates slots set in the software in_use bitmap, so it
never reads these orphaned slots. The result is a permanent interrupt
deadlock:

1. The PHY has ready bits set for slots with no in_use tracker entry
2. The driver never reads those slots because in_use is clear
3. The PHY refuses to generate new timestamp interrupts
4. All future Tx timestamps permanently fail
5. Only a power-on reset can recover the device

Clear these stale ready bits on link-up, in ice_ptp_link_change(),
before any new timestamp requests arrive, scoped to the affected port
only so timestamps still pending on other ports are left untouched. For
every affected MAC the clearing iterates the not-in_use slots with
for_each_clear_bit(), so a pending software request is never discarded
and tx->lock need not be held across the PHY access:

  - E810 is skipped (guarded by tx->has_ready_bitmap) because
    ice_get_phy_tx_tstamp_ready_e810() returns an all-ones bitmap rather
    than a real ready status.
  - E830 and E825/eth56g read the real Tx timestamp ready bitmap and
    clear only the slots the PHY actually latched, via
    ice_clear_phy_tstamp(). If the ready bitmap cannot be read, the
    clear is skipped and a rate-limited warning is logged.

On every MAC the ready bit is cleared by reading the slot's timestamp
memory; the orphaned bits linger only because the normal processing path
never reads those not-in_use slots. The link-up recovery clears them by
reading the timestamp memory via ice_clear_phy_tstamp():

  - E830: add ice_clear_phy_tstamp_e830(), which reads the
    PRTTSYN_TXTIME_H/L registers to clear the entry, and add an
    ICE_MAC_E830 case to the ice_clear_phy_tstamp() dispatch.
  - eth56g: ice_clear_ptp_tstamp_eth56g() reads the timestamp memory
    location, which per the PHY spec is the operation that clears the
    entry's valid bit and its corresponding (read-only) ts_memory_status
    bit. The ts_memory_status registers cannot be written to clear a
    bit, so only reading the timestamp memory has any effect.

The new for_each_clear_bit() loop runs from the service task via link
events. During device removal, tx->in_use is freed before the service
task is stopped. Fix by stopping the service task at the start of
ice_unload(), before ice_ptp_release() frees tx->in_use.

Reviewed-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Signed-off-by: Przemyslaw Korba <przemyslaw.korba@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_main.c   |  1 +
 drivers/net/ethernet/intel/ice/ice_ptp.c    | 72 +++++++++++++++--
 drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 89 +++++++++++++++++----
 drivers/net/ethernet/intel/ice/ice_ptp_hw.h |  1 +
 drivers/net/ethernet/intel/ice/ice_type.h   |  7 ++
 5 files changed, 149 insertions(+), 21 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index e3d3810c791f..231d533309cb 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5169,6 +5169,7 @@ void ice_unload(struct ice_pf *pf)
 
 	devl_assert_locked(priv_to_devlink(pf));
 
+	ice_service_task_stop(pf);
 	ice_unplug_aux_dev(pf);
 	ice_deinit_rdma(pf);
 	ice_deinit_features(pf);
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 1aa440b0639f..9d9d9958fe5c 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -1372,15 +1372,73 @@ void ice_ptp_link_change(struct ice_pf *pf, bool linkup)
 	switch (hw->mac_type) {
 	case ICE_MAC_E810:
 	case ICE_MAC_E830:
-		/* Do not reconfigure E810 or E830 PHY */
+	case ICE_MAC_GENERIC_3K_E825:
+		/* Do not reconfigure E810 or E830 PHY, but on link-up clear
+		 * any stale timestamp ready bits left over from a previous
+		 * link cycle. The PHY may have latched timestamps for packets
+		 * in flight when the link went down; these must be cleared
+		 * before new timestamp requests arrive.
+		 *
+		 * E810 does not have a real ready bitmap
+		 * (ice_get_phy_tx_tstamp_ready_e810 returns all-ones), so
+		 * skip clearing on E810 to avoid unnecessary sideband queue
+		 * operations for every not-in-use slot on each link-up.
+		 */
+		if (linkup && ptp_port->tx.has_ready_bitmap) {
+			struct ice_ptp_tx *tx = &ptp_port->tx;
+			u64 tstamp_ready;
+			int i;
+
+			if (ice_get_phy_tx_tstamp_ready(hw, tx->block,
+							&tstamp_ready)) {
+				dev_warn_ratelimited(ice_pf_to_dev(pf),
+						     "PTP failed to read Tx timestamp ready bitmap on link-up; stale PHY timestamps may remain and stall Tx timestamping\n");
+			} else {
+				/* Only clear stale ready bits for slots that
+				 * have no in-flight software request. Iterating
+				 * the not-in-use slots skips any concurrent
+				 * ice_ptp_request_ts() allocation without
+				 * holding tx->lock across the PHY access. E830
+				 * and E825 reach this clear; E810 is filtered
+				 * out above by has_ready_bitmap.
+				 */
+				for_each_clear_bit(i, tx->in_use, tx->len) {
+					u8 phy_idx = i + tx->offset;
+
+					if (tstamp_ready & BIT_ULL(phy_idx))
+						ice_clear_phy_tstamp(hw,
+								     tx->block,
+								     phy_idx);
+				}
+			}
+		}
+
+		/* E810 and E830 need no further PHY reconfiguration */
+		if (hw->mac_type != ICE_MAC_GENERIC_3K_E825)
+			return;
+
+		/* E825 recovers its Tx path by soft resetting the PHY
+		 * timestamp block and restarting the port, but only on
+		 * link-up. The reset is a three-step register toggle; if it
+		 * fails partway through, the port can be left held in reset,
+		 * and programming a PHY that is stuck in reset via
+		 * ice_ptp_port_phy_restart() would leave Tx timestamping
+		 * permanently broken. So warn and skip the restart on
+		 * failure; the sequence is retried on the next link-up event.
+		 */
+		if (!linkup)
+			return;
+
+		if (ice_ptp_phy_soft_reset_eth56g(hw, ptp_port->port_num))
+			dev_warn(ice_pf_to_dev(pf),
+				 "PTP failed to soft reset PHY port %u on link-up; skipping restart, Tx timestamping may be stuck, try toggle a link to recover\n",
+				 ptp_port->port_num);
+		else
+			ice_ptp_port_phy_restart(ptp_port);
 		return;
 	case ICE_MAC_GENERIC:
 		ice_ptp_port_phy_restart(ptp_port);
 		return;
-	case ICE_MAC_GENERIC_3K_E825:
-		if (linkup)
-			ice_ptp_port_phy_restart(ptp_port);
-		return;
 	default:
 		dev_warn(ice_pf_to_dev(pf), "%s: Unknown PHY type\n", __func__);
 	}
@@ -3380,6 +3438,7 @@ void ice_ptp_init(struct ice_pf *pf)
 
 	ptp->state = ICE_PTP_INITIALIZING;
 
+	mutex_init(&hw->ptp.tx_tstamp_lock);
 	if (hw->lane_num < 0) {
 		err = hw->lane_num;
 		goto err_exit;
@@ -3443,6 +3502,7 @@ void ice_ptp_init(struct ice_pf *pf)
 
 	ice_ptp_cleanup_adapter(pf);
 err_exit:
+	mutex_destroy(&hw->ptp.tx_tstamp_lock);
 	/* If we registered a PTP clock, release it */
 	if (pf->ptp.clock) {
 		ptp_clock_unregister(ptp->clock);
@@ -3469,6 +3529,7 @@ void ice_ptp_release(struct ice_pf *pf)
 
 	if (pf->ptp.state != ICE_PTP_READY) {
 		mutex_destroy(&pf->ptp.port.ps_lock);
+		mutex_destroy(&pf->hw.ptp.tx_tstamp_lock);
 		ice_ptp_cleanup_pf(pf);
 		ice_ptp_cleanup_adapter(pf);
 		if (pf->ptp.clock) {
@@ -3495,6 +3556,7 @@ void ice_ptp_release(struct ice_pf *pf)
 
 	ice_ptp_port_phy_stop(&pf->ptp.port);
 	mutex_destroy(&pf->ptp.port.ps_lock);
+	mutex_destroy(&pf->hw.ptp.tx_tstamp_lock);
 	if (pf->ptp.kworker) {
 		kthread_destroy_worker(pf->ptp.kworker);
 		pf->ptp.kworker = NULL;
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
index a1970a887c38..b23b68cd18ee 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
@@ -1160,11 +1160,15 @@ static int ice_read_ptp_tstamp_eth56g(struct ice_hw *hw, u8 port, u8 idx,
  *
  * To directly clear the contents of the timestamp block entirely, discarding
  * all timestamp data at once, software should instead use
- * ice_ptp_reset_ts_memory_quad_eth56g().
+ * ice_ptp_reset_ts_memory_eth56g().
  *
  * This function should only be called on an idx whose bit is set according to
  * ice_get_phy_tx_tstamp_ready().
  *
+ * Serialized against ice_ptp_clear_tx_memory_status_eth56g() via
+ * tx_tstamp_lock so the two paths do not interleave their reads of the same
+ * port's Tx timestamp memory.
+ *
  * Return:
  * * %0     - success
  * * %other - failed to write to PHY
@@ -1175,25 +1179,62 @@ static int ice_clear_ptp_tstamp_eth56g(struct ice_hw *hw, u8 port, u8 idx)
 	u16 lo_addr;
 	int err;
 
-	/* Read the timestamp register to ensure the timestamp status bit is
-	 * cleared.
+	lo_addr = (u16)PHY_TSTAMP_L(idx);
+
+	mutex_lock(&hw->ptp.tx_tstamp_lock);
+
+	/* Per the PHY spec, reading the timestamp memory location is what
+	 * clears the entry's valid bit and its corresponding (read-only)
+	 * ts_memory_status bit. This clears only this index, leaving any
+	 * other in-flight timestamps on the port untouched.
 	 */
 	err = ice_read_ptp_tstamp_eth56g(hw, port, idx, &unused_tstamp);
-	if (err) {
+	if (err)
 		ice_debug(hw, ICE_DBG_PTP, "Failed to read the PHY timestamp register for port %u, idx %u, err %d\n",
 			  port, idx, err);
-	}
-
-	lo_addr = (u16)PHY_TSTAMP_L(idx);
 
 	err = ice_write_port_mem_eth56g(hw, port, lo_addr, 0);
-	if (err) {
+	if (err)
 		ice_debug(hw, ICE_DBG_PTP, "Failed to clear low PTP timestamp register for port %u, idx %u, err %d\n",
 			  port, idx, err);
-		return err;
+
+	mutex_unlock(&hw->ptp.tx_tstamp_lock);
+
+	return err;
+}
+
+/**
+ * ice_ptp_clear_tx_memory_status_eth56g - Reset one port's Tx timestamp memory
+ * @hw: pointer to the HW struct
+ * @port: port number to clear
+ *
+ * Fully reset a single PHY port's Tx timestamp memory. Per the PHY spec, the
+ * only way to clear a timestamp valid bit (and its read-only ts_memory_status
+ * bit) is to read the timestamp memory location, so read every entry for the
+ * port (two 32-bit reads each). This discards all timestamp data on the port,
+ * so it must only be used for a full reset; callers that must preserve
+ * in-flight timestamps clear individual indices via ice_clear_phy_tstamp().
+ *
+ * Holds tx_tstamp_lock so this full-port sweep does not interleave with the
+ * per-index reads in ice_clear_ptp_tstamp_eth56g() on the same port.
+ *
+ * Return: 0 on success, negative error code on failure to read the PHY.
+ */
+int ice_ptp_clear_tx_memory_status_eth56g(struct ice_hw *hw, u8 port)
+{
+	u64 unused_tstamp;
+	int err = 0;
+	u8 idx;
+
+	mutex_lock(&hw->ptp.tx_tstamp_lock);
+	for (idx = 0; idx < INDEX_PER_PORT; idx++) {
+		err = ice_read_ptp_tstamp_eth56g(hw, port, idx, &unused_tstamp);
+		if (err)
+			break;
 	}
+	mutex_unlock(&hw->ptp.tx_tstamp_lock);
 
-	return 0;
+	return err;
 }
 
 /**
@@ -1204,12 +1245,8 @@ static void ice_ptp_reset_ts_memory_eth56g(struct ice_hw *hw)
 {
 	unsigned int port;
 
-	for (port = 0; port < hw->ptp.num_lports; port++) {
-		ice_write_ptp_reg_eth56g(hw, port, PHY_REG_TX_MEMORY_STATUS_L,
-					 0);
-		ice_write_ptp_reg_eth56g(hw, port, PHY_REG_TX_MEMORY_STATUS_U,
-					 0);
-	}
+	for (port = 0; port < hw->ptp.num_lports; port++)
+		ice_ptp_clear_tx_memory_status_eth56g(hw, port);
 }
 
 /**
@@ -5277,6 +5314,23 @@ static void ice_read_phy_tstamp_e830(const struct ice_hw *hw, u8 idx,
 		  FIELD_PREP(PHY_EXT_40B_LOW_M, lo);
 }
 
+/**
+ * ice_clear_phy_tstamp_e830 - Clear a timestamp from the E830 PHY
+ * @hw: pointer to the HW struct
+ * @idx: the timestamp index to clear
+ *
+ * Clear the valid bit for the given timestamp index in the Tx memory (TS_MEM).
+ * On E830 devices the PRTMAC_TS_TX_MEM_VALID_L/H registers are read-only
+ * mirrors of the per-entry TX_VALID bits and cannot be written. The actual
+ * TS_MEM entry's TX_VALID bit is cleared by reading the corresponding
+ * PRTTSYN_TXTIME_L/H registers (read-to-clear).
+ */
+static void ice_clear_phy_tstamp_e830(const struct ice_hw *hw, u8 idx)
+{
+	rd32(hw, E830_PRTTSYN_TXTIME_H(idx));
+	rd32(hw, E830_PRTTSYN_TXTIME_L(idx));
+}
+
 /**
  * ice_get_phy_tx_tstamp_ready_e830 - Read Tx memory status register
  * @hw: pointer to the HW struct
@@ -5772,6 +5826,9 @@ int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx)
 	switch (hw->mac_type) {
 	case ICE_MAC_E810:
 		return ice_clear_phy_tstamp_e810(hw, block, idx);
+	case ICE_MAC_E830:
+		ice_clear_phy_tstamp_e830(hw, idx);
+		return 0;
 	case ICE_MAC_GENERIC:
 		return ice_clear_phy_tstamp_e82x(hw, block, idx);
 	case ICE_MAC_GENERIC_3K_E825:
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
index 16b1988e993d..b003e0aae8b1 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
@@ -304,6 +304,7 @@ int ice_ptp_clear_phy_offset_ready_e82x(struct ice_hw *hw);
 int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp);
 int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx);
 void ice_ptp_reset_ts_memory(struct ice_hw *hw);
+int ice_ptp_clear_tx_memory_status_eth56g(struct ice_hw *hw, u8 port);
 int ice_ptp_init_phc(struct ice_hw *hw);
 void ice_ptp_init_hw(struct ice_hw *hw);
 int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready);
diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
index 710c519d670d..d8c73fcafc25 100644
--- a/drivers/net/ethernet/intel/ice/ice_type.h
+++ b/drivers/net/ethernet/intel/ice/ice_type.h
@@ -888,6 +888,13 @@ enum ice_global_link_topo {
 
 struct ice_ptp_hw {
 	union ice_phy_params phy;
+	/* Serializes eth56g Tx timestamp-memory reads (the per-index
+	 * timestamp entries, not the TX_MEMORY_STATUS registers). Reading an
+	 * entry auto-clears its ts_memory_status bit as a side effect, so the
+	 * per-index and full-port clear paths must not interleave on the same
+	 * port or a bit could re-latch the interrupt.
+	 */
+	struct mutex tx_tstamp_lock;
 	u8 num_lports;
 	u8 ports_per_phy;
 };
-- 
2.43.0


^ permalink raw reply related

* [PATCH iwl-net 3/4] ice: cancel E82x offset verification work during reset preparation
From: Przemyslaw Korba @ 2026-07-20 12:01 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: netdev, anthony.l.nguyen, przemyslaw.kitszel, aleksandr.loktionov,
	arkadiusz.kubalewski, konstantin.ilichev, Przemyslaw Korba
In-Reply-To: <20260720120151.2675206-1-przemyslaw.korba@intel.com>

From: Karol Kolacinski <karol.kolacinski@intel.com>

Cancel the offset verification delayed work (ov_work) during PTP reset
preparation to prevent it from running concurrently with the reset
sequence.

Without this, ice_ptp_wait_for_offsets() can execute during a reset,
find that ice_is_reset_in_progress() is true, and re-queue itself in a
tight loop. Meanwhile, the reset path in ice_ptp_rebuild_owner() calls
ice_ptp_port_phy_restart(), which starts a new ov_work. This results in
two ov_work instances running simultaneously, racing over the PHY offset
registers and the calibrating flag.

Cancel ov_work in ice_ptp_prepare_for_reset() alongside the existing
cancellation of the Tx tracker. The comment in the existing code already
documents that ov_work interference during reset is a concern but only
cancels it during ice_ptp_release().

Fixes: 4809671015a1 ("ice: Fix E810 PTP reset flow")
Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Signed-off-by: Przemyslaw Korba <przemyslaw.korba@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_ptp.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 9d9d9958fe5c..e0be88024ac3 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -3042,6 +3042,14 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
 	if (reset_type == ICE_RESET_PFR)
 		return;
 
+	/* Cancel the offset verification work for E82x before releasing the
+	 * Tx tracker. If ov_work is running during reset, it may issue
+	 * sideband queue commands that will fail or timeout, and may
+	 * reference state that is being torn down.
+	 */
+	if (hw->mac_type == ICE_MAC_GENERIC)
+		kthread_cancel_delayed_work_sync(&ptp->port.ov_work);
+
 	if (ice_pf_src_tmr_owned(pf) && hw->mac_type == ICE_MAC_GENERIC_3K_E825)
 		ice_ptp_prepare_rebuild_sec(pf, false, reset_type);
 
-- 
2.43.0


^ permalink raw reply related

* [PATCH iwl-net 4/4] ice: call PTP link change only from link events
From: Przemyslaw Korba @ 2026-07-20 12:01 UTC (permalink / raw)
  To: intel-wired-lan
  Cc: netdev, anthony.l.nguyen, przemyslaw.kitszel, aleksandr.loktionov,
	arkadiusz.kubalewski, konstantin.ilichev, Przemyslaw Korba
In-Reply-To: <20260720120151.2675206-1-przemyslaw.korba@intel.com>

From: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>

Remove redundant ice_ptp_link_change() calls from ice_up_complete() and
ice_down(). These duplicate the call already made from
ice_handle_link_event(), creating three problems:

1. Double initialization on link-up: ice_handle_link_event() calls
   ice_ptp_link_change(true), then ice_up_complete() calls it again.
   The second call re-enters ice_ptp_port_phy_restart(), re-setting the
   calibrating flag and restarting the PHY timer while the first
   invocation's offset verification work (ov_work) may still be running.

2. Premature cleanup on administrative down: ice_down() calls
   ice_ptp_link_change(false) during ifconfig down or reset preparation,
   even when the physical link is still up. This clears timestamp state
   unnecessarily and can interfere with ongoing PTP operations.

3. Ordering dependency: ice_down()/ice_up_complete() are called during
   reset sequences where PTP may not be fully initialized, creating
   edge cases with partially configured state.

The link event handler is the correct and sufficient place to drive PTP
link state changes, as it reflects actual physical link transitions.

Add the link_up to be set within ice_ptp_init(..), it is required to
have actual state of link_up flag on driver load.

Fixes: 6b1ff5d39228 ("ice: always call ice_ptp_link_change and make it void")
Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com>
Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Signed-off-by: Przemyslaw Korba <przemyslaw.korba@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_main.c |  2 --
 drivers/net/ethernet/intel/ice/ice_ptp.c  | 39 +++++++++++++++++++----
 2 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 231d533309cb..8c25c1604949 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -6782,7 +6782,6 @@ static int ice_up_complete(struct ice_vsi *vsi)
 		ice_print_link_msg(vsi, true);
 		netif_tx_start_all_queues(vsi->netdev);
 		netif_carrier_on(vsi->netdev);
-		ice_ptp_link_change(pf, true);
 	}
 
 	/* Perform an initial read of the statistics registers now to
@@ -7310,7 +7309,6 @@ int ice_down(struct ice_vsi *vsi)
 
 	if (vsi->netdev) {
 		vlan_err = ice_vsi_del_vlan_zero(vsi);
-		ice_ptp_link_change(vsi->back, false);
 		netif_carrier_off(vsi->netdev);
 		netif_tx_disable(vsi->netdev);
 	}
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index e0be88024ac3..e1c8bc5fafc1 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -3343,9 +3343,13 @@ static int ice_ptp_init_owner(struct ice_pf *pf)
 }
 
 /**
- * ice_ptp_init_work - Initialize PTP work threads
+ * ice_ptp_init_work - Initialize the PTP kworker
  * @pf: Board private structure
  * @ptp: PF PTP structure
+ *
+ * Allocate the kworker and initialize the periodic work function. The
+ * periodic work is not queued here; the caller starts it once the PTP
+ * state is ICE_PTP_READY.
  */
 static int ice_ptp_init_work(struct ice_pf *pf, struct ice_ptp *ptp)
 {
@@ -3364,9 +3368,6 @@ static int ice_ptp_init_work(struct ice_pf *pf, struct ice_ptp *ptp)
 
 	ptp->kworker = kworker;
 
-	/* Start periodic work going */
-	kthread_queue_delayed_work(ptp->kworker, &ptp->work, 0);
-
 	return 0;
 }
 
@@ -3489,6 +3490,29 @@ void ice_ptp_init(struct ice_pf *pf)
 	if (err)
 		goto err_clean_pf;
 
+	/* Seed the cached PTP link state from the current PHY link status
+	 * before starting the PHY timestamping block. On a fresh load the
+	 * port structure is zeroed (link_up == false); if the link is
+	 * already up at probe (for example after a PXE boot) no link-change
+	 * edge will follow, and ice_ptp_link_change() is edge-driven, so the
+	 * flag would stay stale. Seeding it here also lets
+	 * ice_ptp_reset_phy_timestamping() make the correct start/stop
+	 * decision instead of stopping the PHY timer on an already-up link.
+	 */
+	if (pf->hw.port_info)
+		ptp->port.link_up =
+			!!(pf->hw.port_info->phy.link_info.link_info &
+			ICE_AQ_LINK_UP);
+
+	/* Create the PTP kworker before (re)starting the PHY, because the
+	 * E82x restart path queues offset verification work on it, and
+	 * before ICE_PTP_READY is set, so a concurrent link event cannot
+	 * reach ice_ptp_port_phy_restart() while the kworker is still NULL.
+	 */
+	err = ice_ptp_init_work(pf, ptp);
+	if (err)
+		goto err_exit;
+
 	/* Start the PHY timestamping block */
 	ice_ptp_reset_phy_timestamping(pf);
 
@@ -3497,9 +3521,10 @@ void ice_ptp_init(struct ice_pf *pf)
 
 	ptp->state = ICE_PTP_READY;
 
-	err = ice_ptp_init_work(pf, ptp);
-	if (err)
-		goto err_exit;
+	/* Start periodic work only after the state is READY; the worker
+	 * returns without rescheduling while the state is not READY.
+	 */
+	kthread_queue_delayed_work(ptp->kworker, &ptp->work, 0);
 
 	dev_info(ice_pf_to_dev(pf), "PTP init successful\n");
 	return;
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH] phy: fsl-lynx-10g: propagate PCVT enable errors
From: Breno Leitao @ 2026-07-20 12:14 UTC (permalink / raw)
  To: kr494167
  Cc: ioana.ciornei, vladimir.oltean, vkoul, neil.armstrong, netdev,
	linux-phy, linux-kernel
In-Reply-To: <20260720101906.80584-1-kr494167@gmail.com>

On Mon, Jul 20, 2026 at 03:49:06PM +0530, kr494167@gmail.com wrote:
> Propagate the error and leave the previous lane mode intact so the caller
> can handle the failed reconfiguration.

Do you need to undo these operations that were done to the lane earlier?

        lynx_10g_lane_change_proto_conf(lane, lane_mode);
        lynx_10g_lane_remap_pll(lane, lane_mode);

--breno

^ permalink raw reply

* Re: [PATCH] phy: fsl-lynx-10g: propagate PCVT enable errors
From: Vladimir Oltean @ 2026-07-20 12:16 UTC (permalink / raw)
  To: kr494167
  Cc: ioana.ciornei, vkoul, neil.armstrong, netdev, linux-phy,
	linux-kernel
In-Reply-To: <20260720101906.80584-1-kr494167@gmail.com>

Hi Surendra,

On Mon, Jul 20, 2026 at 03:49:06PM +0530, kr494167@gmail.com wrote:
> From: surendra <kr494167@gmail.com>
> 
> lynx_10g_set_mode() currently ignores failures from
> lynx_10g_lane_enable_pcvt(). It then updates the lane mode and reports
> success even though the protocol converter may remain disabled.
> 
> Propagate the error and leave the previous lane mode intact so the caller
> can handle the failed reconfiguration.
> 
> Signed-off-by: surendra <kr494167@gmail.com>
> ---
>  drivers/phy/freescale/phy-fsl-lynx-10g.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/phy/freescale/phy-fsl-lynx-10g.c b/drivers/phy/freescale/phy-fsl-lynx-10g.c
> index 38def160ef1a..9740b08700c4 100644
> --- a/drivers/phy/freescale/phy-fsl-lynx-10g.c
> +++ b/drivers/phy/freescale/phy-fsl-lynx-10g.c
> @@ -1231,7 +1231,9 @@ static int lynx_10g_set_mode(struct phy *phy, enum phy_mode mode, int submode)
> 
>         lynx_10g_lane_change_proto_conf(lane, lane_mode);
>         lynx_10g_lane_remap_pll(lane, lane_mode);
> -       WARN_ON(lynx_10g_lane_enable_pcvt(lane, lane_mode));
> +       err = lynx_10g_lane_enable_pcvt(lane, lane_mode);
> +       if (err)
> +               goto out;
> 
>         lane->mode = lane_mode;
> 
> --
> 2.55.0
>

Thank you for the patch, however you are fixing a situation which will
never occur.

Assume lynx_10g_lane_enable_pcvt(lane, lane_mode) will fail.
It means one of the following functions inside of it returned a negative
return code:
- lynx_pcvt_rmw(lane, mode, ...)
- lynx_pccr_write(lane, mode, ...)

Let's take them one by one.

lynx_pcvt_rmw() fails if priv->info->get_pcvt_offset(lane->id, mode)
returns negative.

lynx_pccr_write() fails if priv->info->get_pccr(mode, lane->id, ...)
returns negative.

Had any of these two functions returned a negative error code, the
execution would not have reached the lynx_10g_lane_enable_pcvt() stage!

The following code path:
lynx_10g_set_mode()
-> lynx_10g_validate()
   -> lynx_phy_mode_to_lane_mode()
      -> lynx_lane_supports_mode()
         -> priv->info->lane_supports_mode() // this is provided for lynx-28g
            OR
         -> lynx_lane_supports_mode_default() // all lynx-10g instances use this
            -> checks priv->info->get_pccr() and
               priv->info->get_pcvt_offset()

already fails much earlier if priv->info->get_pccr() or
priv->info->get_pcvt_offset() return negative (i.e. we don't know how to
handle the requested protocol).

The suggested placement of your error handling is extremely late anyway.
lynx_10g_lane_change_proto_conf() and lynx_10g_lane_remap_pll() have
already been executed, so the lane is reconfigured for the new protocol
and remapped to the new PLL. The "goto out" label doesn't undo that.
This is why I am reluctant to agree with your proposed change - it
doesn't make the code any more correct, it just complicates the handling
and actually makes that impossible case handled *incorrectly* (on
phy_set_mode_ext() failure, you don't expect the PHY to be configured
half way).

It would be very strange to proceed thus far if we didn't first make
sure that the protocol we are switching to is fully supported.

This is why the code has the WARN_ON(). The function _can_ fail, but we
don't need to check more than once for failures on the same mode with
the same protocol, since they are time-invariant.

^ permalink raw reply

* Re: [PATCH net] ipv4: require matching source address for route hint reuse
From: Ido Schimmel @ 2026-07-20 12:16 UTC (permalink / raw)
  To: Yizhou Zhao, pabeni
  Cc: netdev, David Ahern, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Simon Horman, linux-kernel,
	Yuxiang Yang, Ao Wang, Xuewei Feng, Qi Li, Ke Xu, stable
In-Reply-To: <20260714122618.21698-1-zhaoyz24@mails.tsinghua.edu.cn>

On Tue, Jul 14, 2026 at 08:26:17PM +0800, Yizhou Zhao wrote:
> IPv4 list receive can reuse a route from the previous skb in the same
> receive batch. The current eligibility check only compares the destination
> address and TOS before calling ip_route_use_hint().
> 
> For forwarded routes, ip_route_use_hint() skips fib_validate_source()
> unless the hinted route is local. This means a packet with a different
> source address can reuse a forwarding dst created for an earlier packet
> and avoid source validation such as strict rp_filter.

I'm not sure why we are skipping source validation for non-local routes.

The comment above ip_route_use_hint() says "Implements all the
saddr-related checks as ip_route_input_slow()". I agree that
ip_route_input_slow() only does source validation for RTN_LOCAL, but for
RTN_UNICAST it is calling ip_mkroute_input(), which eventually calls
fib_validate_source().

Paolo, WDYT about always performing source validation [1]?

> 
> In a KASAN QEMU router with strict rp_filter on the ingress device, a 

Why mention KASAN? How is it related to this bug / patch?

> bad-only burst was dropped entirely, however, a paired valid/bad burst 
> with the same destination/TOS made all of the bad packets pass rp_filter.
> 
> Require the source address to match before reusing the hint. Packets from
> the same source/destination/TOS still take the fast path; packets whose
> source changes go through the normal route lookup and source validation
> path.

I agree that it fixes the problem, but we will always pay the
performance penalty, even when rp_filter is disabled. According to
commit 02b24941619f ("ipv4: use dst hint for ipv4 list receive"), there
is still a performance gain when we perform the source validation
per-packet.

[1]
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 3f3de5164d6e..89338111793b 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2194,6 +2194,7 @@ ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	struct rtable *rt = skb_rtable(hint);
 	struct net *net = dev_net(dev);
 	u32 tag = 0;
+	int oif = 0;
 
 	if (!in_dev)
 		return reason;
@@ -2214,14 +2215,13 @@ ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	}
 
 	if (!(rt->rt_flags & RTCF_LOCAL))
-		goto skip_validate_source;
+		oif = dst_dev_rcu(&rt->dst)->ifindex;
 
-	reason = fib_validate_source_reason(skb, saddr, daddr, dscp, 0, dev,
+	reason = fib_validate_source_reason(skb, saddr, daddr, dscp, oif, dev,
 					    in_dev, &tag);
 	if (reason)
 		goto martian_source;
 
-skip_validate_source:
 	skb_dst_copy(skb, hint);
 	return SKB_NOT_DROPPED_YET;

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox