--- /dev/null
+From bf86ba00e5c71f0b2bbce7c3a95b15b71c46334f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jan 2025 14:21:55 +0100
+Subject: bpf: Fix bpf_sk_select_reuseport() memory leak
+
+From: Michal Luczaj <mhal@rbox.co>
+
+[ Upstream commit b3af60928ab9129befa65e6df0310d27300942bf ]
+
+As pointed out in the original comment, lookup in sockmap can return a TCP
+ESTABLISHED socket. Such TCP socket may have had SO_ATTACH_REUSEPORT_EBPF
+set before it was ESTABLISHED. In other words, a non-NULL sk_reuseport_cb
+does not imply a non-refcounted socket.
+
+Drop sk's reference in both error paths.
+
+unreferenced object 0xffff888101911800 (size 2048):
+ comm "test_progs", pid 44109, jiffies 4297131437
+ hex dump (first 32 bytes):
+ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+ 80 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
+ backtrace (crc 9336483b):
+ __kmalloc_noprof+0x3bf/0x560
+ __reuseport_alloc+0x1d/0x40
+ reuseport_alloc+0xca/0x150
+ reuseport_attach_prog+0x87/0x140
+ sk_reuseport_attach_bpf+0xc8/0x100
+ sk_setsockopt+0x1181/0x1990
+ do_sock_setsockopt+0x12b/0x160
+ __sys_setsockopt+0x7b/0xc0
+ __x64_sys_setsockopt+0x1b/0x30
+ do_syscall_64+0x93/0x180
+ entry_SYSCALL_64_after_hwframe+0x76/0x7e
+
+Fixes: 64d85290d79c ("bpf: Allow bpf_map_lookup_elem for SOCKMAP and SOCKHASH")
+Signed-off-by: Michal Luczaj <mhal@rbox.co>
+Reviewed-by: Martin KaFai Lau <martin.lau@kernel.org>
+Link: https://patch.msgid.link/20250110-reuseport-memleak-v1-1-fa1ddab0adfe@rbox.co
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/filter.c | 30 ++++++++++++++++++------------
+ 1 file changed, 18 insertions(+), 12 deletions(-)
+
+diff --git a/net/core/filter.c b/net/core/filter.c
+index 54a53fae9e98f..46da488ff0703 100644
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -11263,6 +11263,7 @@ BPF_CALL_4(sk_select_reuseport, struct sk_reuseport_kern *, reuse_kern,
+ bool is_sockarray = map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY;
+ struct sock_reuseport *reuse;
+ struct sock *selected_sk;
++ int err;
+
+ selected_sk = map->ops->map_lookup_elem(map, key);
+ if (!selected_sk)
+@@ -11270,10 +11271,6 @@ BPF_CALL_4(sk_select_reuseport, struct sk_reuseport_kern *, reuse_kern,
+
+ reuse = rcu_dereference(selected_sk->sk_reuseport_cb);
+ if (!reuse) {
+- /* Lookup in sock_map can return TCP ESTABLISHED sockets. */
+- if (sk_is_refcounted(selected_sk))
+- sock_put(selected_sk);
+-
+ /* reuseport_array has only sk with non NULL sk_reuseport_cb.
+ * The only (!reuse) case here is - the sk has already been
+ * unhashed (e.g. by close()), so treat it as -ENOENT.
+@@ -11281,24 +11278,33 @@ BPF_CALL_4(sk_select_reuseport, struct sk_reuseport_kern *, reuse_kern,
+ * Other maps (e.g. sock_map) do not provide this guarantee and
+ * the sk may never be in the reuseport group to begin with.
+ */
+- return is_sockarray ? -ENOENT : -EINVAL;
++ err = is_sockarray ? -ENOENT : -EINVAL;
++ goto error;
+ }
+
+ if (unlikely(reuse->reuseport_id != reuse_kern->reuseport_id)) {
+ struct sock *sk = reuse_kern->sk;
+
+- if (sk->sk_protocol != selected_sk->sk_protocol)
+- return -EPROTOTYPE;
+- else if (sk->sk_family != selected_sk->sk_family)
+- return -EAFNOSUPPORT;
+-
+- /* Catch all. Likely bound to a different sockaddr. */
+- return -EBADFD;
++ if (sk->sk_protocol != selected_sk->sk_protocol) {
++ err = -EPROTOTYPE;
++ } else if (sk->sk_family != selected_sk->sk_family) {
++ err = -EAFNOSUPPORT;
++ } else {
++ /* Catch all. Likely bound to a different sockaddr. */
++ err = -EBADFD;
++ }
++ goto error;
+ }
+
+ reuse_kern->selected_sk = selected_sk;
+
+ return 0;
++error:
++ /* Lookup in sock_map can return TCP ESTABLISHED sockets. */
++ if (sk_is_refcounted(selected_sk))
++ sock_put(selected_sk);
++
++ return err;
+ }
+
+ static const struct bpf_func_proto sk_select_reuseport_proto = {
+--
+2.39.5
+
--- /dev/null
+From e3209b40abc256afb1bf6d333855af2f3a448e8d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Jan 2025 14:14:04 +1030
+Subject: btrfs: add the missing error handling inside get_canonical_dev_path
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit fe4de594f7a2e9bc49407de60fbd20809fad4192 ]
+
+Inside function get_canonical_dev_path(), we call d_path() to get the
+final device path.
+
+But d_path() can return error, and in that case the next strscpy() call
+will trigger an invalid memory access.
+
+Add back the missing error handling for d_path().
+
+Reported-by: Boris Burkov <boris@bur.io>
+Fixes: 7e06de7c83a7 ("btrfs: canonicalize the device path before adding it")
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/volumes.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
+index 0c4d14c59ebec..395b8b880ce78 100644
+--- a/fs/btrfs/volumes.c
++++ b/fs/btrfs/volumes.c
+@@ -797,6 +797,10 @@ static int get_canonical_dev_path(const char *dev_path, char *canonical)
+ if (ret)
+ goto out;
+ resolved_path = d_path(&path, path_buf, PATH_MAX);
++ if (IS_ERR(resolved_path)) {
++ ret = PTR_ERR(resolved_path);
++ goto out;
++ }
+ ret = strscpy(canonical, resolved_path, PATH_MAX);
+ out:
+ kfree(path_buf);
+--
+2.39.5
+
--- /dev/null
+From 81762656f37ef8ad57ec798405377b45a893ec61 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jan 2025 11:23:10 +0530
+Subject: cpufreq: Move endif to the end of Kconfig file
+
+From: Viresh Kumar <viresh.kumar@linaro.org>
+
+[ Upstream commit 7e265fc04690d449a40b413b0348b15c748cea6f ]
+
+It is possible to enable few cpufreq drivers, without the framework
+being enabled. This happened due to a bug while moving the entries
+earlier. Fix it.
+
+Fixes: 7ee1378736f0 ("cpufreq: Move CPPC configs to common Kconfig and add RISC-V")
+Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
+Reviewed-by: Pierre Gondois <pierre.gondois@arm.com>
+Reviewed-by: Sunil V L <sunilvl@ventanamicro.com>
+Reviewed-by: Sudeep Holla <sudeep.holla@arm.com>
+Link: https://patch.msgid.link/84ac7a8fa72a8fe20487bb0a350a758bce060965.1736488384.git.viresh.kumar@linaro.org
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpufreq/Kconfig | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
+index 2561b215432a8..588ab1cc6d557 100644
+--- a/drivers/cpufreq/Kconfig
++++ b/drivers/cpufreq/Kconfig
+@@ -311,8 +311,6 @@ config QORIQ_CPUFREQ
+ This adds the CPUFreq driver support for Freescale QorIQ SoCs
+ which are capable of changing the CPU's frequency dynamically.
+
+-endif
+-
+ config ACPI_CPPC_CPUFREQ
+ tristate "CPUFreq driver based on the ACPI CPPC spec"
+ depends on ACPI_PROCESSOR
+@@ -341,4 +339,6 @@ config ACPI_CPPC_CPUFREQ_FIE
+
+ If in doubt, say N.
+
++endif
++
+ endmenu
+--
+2.39.5
+
--- /dev/null
+From c81ea42a9926a06754cae3a300b94a34b8c15fd7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jan 2025 13:48:10 +0100
+Subject: cpuidle: teo: Update documentation after previous changes
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit 5a597a19a2148d1c5cd987907a60c042ab0f62d5 ]
+
+After previous changes, the description of the teo governor in the
+documentation comment does not match the code any more, so update it
+as appropriate.
+
+Fixes: 449914398083 ("cpuidle: teo: Remove recent intercepts metric")
+Fixes: 2662342079f5 ("cpuidle: teo: Gather statistics regarding whether or not to stop the tick")
+Fixes: 6da8f9ba5a87 ("cpuidle: teo: Skip tick_nohz_get_sleep_length() call in some cases")
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Reviewed-by: Christian Loehle <christian.loehle@arm.com>
+Link: https://patch.msgid.link/6120335.lOV4Wx5bFT@rjwysocki.net
+[ rjw: Corrected 3 typos found by Christian ]
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/cpuidle/governors/teo.c | 91 +++++++++++++++++----------------
+ 1 file changed, 48 insertions(+), 43 deletions(-)
+
+diff --git a/drivers/cpuidle/governors/teo.c b/drivers/cpuidle/governors/teo.c
+index f2992f92d8db8..173ddcac540ad 100644
+--- a/drivers/cpuidle/governors/teo.c
++++ b/drivers/cpuidle/governors/teo.c
+@@ -10,25 +10,27 @@
+ * DOC: teo-description
+ *
+ * The idea of this governor is based on the observation that on many systems
+- * timer events are two or more orders of magnitude more frequent than any
+- * other interrupts, so they are likely to be the most significant cause of CPU
+- * wakeups from idle states. Moreover, information about what happened in the
+- * (relatively recent) past can be used to estimate whether or not the deepest
+- * idle state with target residency within the (known) time till the closest
+- * timer event, referred to as the sleep length, is likely to be suitable for
+- * the upcoming CPU idle period and, if not, then which of the shallower idle
+- * states to choose instead of it.
++ * timer interrupts are two or more orders of magnitude more frequent than any
++ * other interrupt types, so they are likely to dominate CPU wakeup patterns.
++ * Moreover, in principle, the time when the next timer event is going to occur
++ * can be determined at the idle state selection time, although doing that may
++ * be costly, so it can be regarded as the most reliable source of information
++ * for idle state selection.
+ *
+- * Of course, non-timer wakeup sources are more important in some use cases
+- * which can be covered by taking a few most recent idle time intervals of the
+- * CPU into account. However, even in that context it is not necessary to
+- * consider idle duration values greater than the sleep length, because the
+- * closest timer will ultimately wake up the CPU anyway unless it is woken up
+- * earlier.
++ * Of course, non-timer wakeup sources are more important in some use cases,
++ * but even then it is generally unnecessary to consider idle duration values
++ * greater than the time time till the next timer event, referred as the sleep
++ * length in what follows, because the closest timer will ultimately wake up the
++ * CPU anyway unless it is woken up earlier.
+ *
+- * Thus this governor estimates whether or not the prospective idle duration of
+- * a CPU is likely to be significantly shorter than the sleep length and selects
+- * an idle state for it accordingly.
++ * However, since obtaining the sleep length may be costly, the governor first
++ * checks if it can select a shallow idle state using wakeup pattern information
++ * from recent times, in which case it can do without knowing the sleep length
++ * at all. For this purpose, it counts CPU wakeup events and looks for an idle
++ * state whose target residency has not exceeded the idle duration (measured
++ * after wakeup) in the majority of relevant recent cases. If the target
++ * residency of that state is small enough, it may be used right away and the
++ * sleep length need not be determined.
+ *
+ * The computations carried out by this governor are based on using bins whose
+ * boundaries are aligned with the target residency parameter values of the CPU
+@@ -39,7 +41,11 @@
+ * idle state 2, the third bin spans from the target residency of idle state 2
+ * up to, but not including, the target residency of idle state 3 and so on.
+ * The last bin spans from the target residency of the deepest idle state
+- * supplied by the driver to infinity.
++ * supplied by the driver to the scheduler tick period length or to infinity if
++ * the tick period length is less than the target residency of that state. In
++ * the latter case, the governor also counts events with the measured idle
++ * duration between the tick period length and the target residency of the
++ * deepest idle state.
+ *
+ * Two metrics called "hits" and "intercepts" are associated with each bin.
+ * They are updated every time before selecting an idle state for the given CPU
+@@ -49,47 +55,46 @@
+ * sleep length and the idle duration measured after CPU wakeup fall into the
+ * same bin (that is, the CPU appears to wake up "on time" relative to the sleep
+ * length). In turn, the "intercepts" metric reflects the relative frequency of
+- * situations in which the measured idle duration is so much shorter than the
+- * sleep length that the bin it falls into corresponds to an idle state
+- * shallower than the one whose bin is fallen into by the sleep length (these
+- * situations are referred to as "intercepts" below).
++ * non-timer wakeup events for which the measured idle duration falls into a bin
++ * that corresponds to an idle state shallower than the one whose bin is fallen
++ * into by the sleep length (these events are also referred to as "intercepts"
++ * below).
+ *
+ * In order to select an idle state for a CPU, the governor takes the following
+ * steps (modulo the possible latency constraint that must be taken into account
+ * too):
+ *
+- * 1. Find the deepest CPU idle state whose target residency does not exceed
+- * the current sleep length (the candidate idle state) and compute 2 sums as
+- * follows:
++ * 1. Find the deepest enabled CPU idle state (the candidate idle state) and
++ * compute 2 sums as follows:
+ *
+- * - The sum of the "hits" and "intercepts" metrics for the candidate state
+- * and all of the deeper idle states (it represents the cases in which the
+- * CPU was idle long enough to avoid being intercepted if the sleep length
+- * had been equal to the current one).
++ * - The sum of the "hits" metric for all of the idle states shallower than
++ * the candidate one (it represents the cases in which the CPU was likely
++ * woken up by a timer).
+ *
+- * - The sum of the "intercepts" metrics for all of the idle states shallower
+- * than the candidate one (it represents the cases in which the CPU was not
+- * idle long enough to avoid being intercepted if the sleep length had been
+- * equal to the current one).
++ * - The sum of the "intercepts" metric for all of the idle states shallower
++ * than the candidate one (it represents the cases in which the CPU was
++ * likely woken up by a non-timer wakeup source).
+ *
+- * 2. If the second sum is greater than the first one the CPU is likely to wake
+- * up early, so look for an alternative idle state to select.
++ * 2. If the second sum computed in step 1 is greater than a half of the sum of
++ * both metrics for the candidate state bin and all subsequent bins(if any),
++ * a shallower idle state is likely to be more suitable, so look for it.
+ *
+- * - Traverse the idle states shallower than the candidate one in the
++ * - Traverse the enabled idle states shallower than the candidate one in the
+ * descending order.
+ *
+ * - For each of them compute the sum of the "intercepts" metrics over all
+ * of the idle states between it and the candidate one (including the
+ * former and excluding the latter).
+ *
+- * - If each of these sums that needs to be taken into account (because the
+- * check related to it has indicated that the CPU is likely to wake up
+- * early) is greater than a half of the corresponding sum computed in step
+- * 1 (which means that the target residency of the state in question had
+- * not exceeded the idle duration in over a half of the relevant cases),
+- * select the given idle state instead of the candidate one.
++ * - If this sum is greater than a half of the second sum computed in step 1,
++ * use the given idle state as the new candidate one.
+ *
+- * 3. By default, select the candidate state.
++ * 3. If the current candidate state is state 0 or its target residency is short
++ * enough, return it and prevent the scheduler tick from being stopped.
++ *
++ * 4. Obtain the sleep length value and check if it is below the target
++ * residency of the current candidate state, in which case a new shallower
++ * candidate state needs to be found, so look for it.
+ */
+
+ #include <linux/cpuidle.h>
+--
+2.39.5
+
--- /dev/null
+From e118e0787c354ebc3af802df44471ad75c49840c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 5 Jan 2025 00:51:33 +0800
+Subject: drm/tests: helpers: Fix compiler warning
+
+From: Yu-Chun Lin <eleanor15x@gmail.com>
+
+[ Upstream commit b9097e4c8bf3934e4e07e6f9b88741957fef351e ]
+
+Delete one line break to make the format correct, resolving the
+following warning during a W=1 build:
+
+>> drivers/gpu/drm/tests/drm_kunit_helpers.c:324: warning: bad line: for a KUnit test
+
+Fixes: caa714f86699 ("drm/tests: helpers: Add helper for drm_display_mode_from_cea_vic()")
+Reported-by: kernel test robot <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202501032001.O6WY1VCW-lkp@intel.com/
+Reviewed-by: Kuan-Wei Chiu <visitorckw@gmail.com>
+Tested-by: Kuan-Wei Chiu <visitorckw@gmail.com>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Yu-Chun Lin <eleanor15x@gmail.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250104165134.1695864-1-eleanor15x@gmail.com
+Signed-off-by: Maxime Ripard <mripard@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/tests/drm_kunit_helpers.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c
+index 04a6b8cc62ac6..3c0b7824c0be3 100644
+--- a/drivers/gpu/drm/tests/drm_kunit_helpers.c
++++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c
+@@ -320,8 +320,7 @@ static void kunit_action_drm_mode_destroy(void *ptr)
+ }
+
+ /**
+- * drm_kunit_display_mode_from_cea_vic() - return a mode for CEA VIC
+- for a KUnit test
++ * drm_kunit_display_mode_from_cea_vic() - return a mode for CEA VIC for a KUnit test
+ * @test: The test context object
+ * @dev: DRM device
+ * @video_code: CEA VIC of the mode
+--
+2.39.5
+
--- /dev/null
+From ab48977d8c5709ea1f62a31443c1d4dab2ea87b1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 12:47:40 -0300
+Subject: drm/v3d: Ensure job pointer is set to NULL after job completion
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: MaÃra Canal <mcanal@igalia.com>
+
+[ Upstream commit e4b5ccd392b92300a2b341705cc4805681094e49 ]
+
+After a job completes, the corresponding pointer in the device must
+be set to NULL. Failing to do so triggers a warning when unloading
+the driver, as it appears the job is still active. To prevent this,
+assign the job pointer to NULL after completing the job, indicating
+the job has finished.
+
+Fixes: 14d1d1908696 ("drm/v3d: Remove the bad signaled() implementation.")
+Signed-off-by: MaÃra Canal <mcanal@igalia.com>
+Reviewed-by: Jose Maria Casanova Crespo <jmcasanova@igalia.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250113154741.67520-1-mcanal@igalia.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/v3d/v3d_irq.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c
+index 20bf33702c3c4..da203045df9be 100644
+--- a/drivers/gpu/drm/v3d/v3d_irq.c
++++ b/drivers/gpu/drm/v3d/v3d_irq.c
+@@ -108,6 +108,7 @@ v3d_irq(int irq, void *arg)
+ v3d_job_update_stats(&v3d->bin_job->base, V3D_BIN);
+ trace_v3d_bcl_irq(&v3d->drm, fence->seqno);
+ dma_fence_signal(&fence->base);
++ v3d->bin_job = NULL;
+ status = IRQ_HANDLED;
+ }
+
+@@ -118,6 +119,7 @@ v3d_irq(int irq, void *arg)
+ v3d_job_update_stats(&v3d->render_job->base, V3D_RENDER);
+ trace_v3d_rcl_irq(&v3d->drm, fence->seqno);
+ dma_fence_signal(&fence->base);
++ v3d->render_job = NULL;
+ status = IRQ_HANDLED;
+ }
+
+@@ -128,6 +130,7 @@ v3d_irq(int irq, void *arg)
+ v3d_job_update_stats(&v3d->csd_job->base, V3D_CSD);
+ trace_v3d_csd_irq(&v3d->drm, fence->seqno);
+ dma_fence_signal(&fence->base);
++ v3d->csd_job = NULL;
+ status = IRQ_HANDLED;
+ }
+
+@@ -165,6 +168,7 @@ v3d_hub_irq(int irq, void *arg)
+ v3d_job_update_stats(&v3d->tfu_job->base, V3D_TFU);
+ trace_v3d_tfu_irq(&v3d->drm, fence->seqno);
+ dma_fence_signal(&fence->base);
++ v3d->tfu_job = NULL;
+ status = IRQ_HANDLED;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From b1e88bd6bb9183213adf646a54c792be356c04ee Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jan 2025 12:53:35 -0600
+Subject: drm/vmwgfx: Add new keep_resv BO param
+
+From: Ian Forbes <ian.forbes@broadcom.com>
+
+[ Upstream commit b7d40627813799870e72729c6fc979a8a40d9ba6 ]
+
+Adds a new BO param that keeps the reservation locked after creation.
+This removes the need to re-reserve the BO after creation which is a
+waste of cycles.
+
+This also fixes a bug in vmw_prime_import_sg_table where the imported
+reservation is unlocked twice.
+
+Signed-off-by: Ian Forbes <ian.forbes@broadcom.com>
+Fixes: b32233acceff ("drm/vmwgfx: Fix prime import/export")
+Reviewed-by: Zack Rusin <zack.rusin@broadcom.com>
+Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20250110185335.15301-1-ian.forbes@broadcom.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 3 ++-
+ drivers/gpu/drm/vmwgfx/vmwgfx_bo.h | 3 ++-
+ drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 ++-----
+ drivers/gpu/drm/vmwgfx/vmwgfx_gem.c | 1 +
+ drivers/gpu/drm/vmwgfx/vmwgfx_shader.c | 7 ++-----
+ drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 5 ++---
+ 6 files changed, 11 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+index a0e433fbcba67..183cda50094cb 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+@@ -443,7 +443,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv,
+
+ if (params->pin)
+ ttm_bo_pin(&vmw_bo->tbo);
+- ttm_bo_unreserve(&vmw_bo->tbo);
++ if (!params->keep_resv)
++ ttm_bo_unreserve(&vmw_bo->tbo);
+
+ return 0;
+ }
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h
+index 43b5439ec9f76..c21ba7ff77368 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h
+@@ -56,8 +56,9 @@ struct vmw_bo_params {
+ u32 domain;
+ u32 busy_domain;
+ enum ttm_bo_type bo_type;
+- size_t size;
+ bool pin;
++ bool keep_resv;
++ size_t size;
+ struct dma_resv *resv;
+ struct sg_table *sg;
+ };
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+index 2825dd3149ed5..2e84e1029732d 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+@@ -401,7 +401,8 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
+ .busy_domain = VMW_BO_DOMAIN_SYS,
+ .bo_type = ttm_bo_type_kernel,
+ .size = PAGE_SIZE,
+- .pin = true
++ .pin = true,
++ .keep_resv = true,
+ };
+
+ /*
+@@ -413,10 +414,6 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
+ if (unlikely(ret != 0))
+ return ret;
+
+- ret = ttm_bo_reserve(&vbo->tbo, false, true, NULL);
+- BUG_ON(ret != 0);
+- vmw_bo_pin_reserved(vbo, true);
+-
+ ret = ttm_bo_kmap(&vbo->tbo, 0, 1, &map);
+ if (likely(ret == 0)) {
+ result = ttm_kmap_obj_virtual(&map, &dummy);
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c
+index b9857f37ca1ac..ed5015ced3920 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c
+@@ -206,6 +206,7 @@ struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev,
+ .bo_type = ttm_bo_type_sg,
+ .size = attach->dmabuf->size,
+ .pin = false,
++ .keep_resv = true,
+ .resv = attach->dmabuf->resv,
+ .sg = table,
+
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
+index a01ca3226d0af..7fb1c88bcc475 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
+@@ -896,7 +896,8 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv,
+ .busy_domain = VMW_BO_DOMAIN_SYS,
+ .bo_type = ttm_bo_type_device,
+ .size = size,
+- .pin = true
++ .pin = true,
++ .keep_resv = true,
+ };
+
+ if (!vmw_shader_id_ok(user_key, shader_type))
+@@ -906,10 +907,6 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv,
+ if (unlikely(ret != 0))
+ goto out;
+
+- ret = ttm_bo_reserve(&buf->tbo, false, true, NULL);
+- if (unlikely(ret != 0))
+- goto no_reserve;
+-
+ /* Map and copy shader bytecode. */
+ ret = ttm_bo_kmap(&buf->tbo, 0, PFN_UP(size), &map);
+ if (unlikely(ret != 0)) {
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
+index 621d98b376bbb..5553892d7c3e0 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c
+@@ -572,15 +572,14 @@ int vmw_bo_create_and_populate(struct vmw_private *dev_priv,
+ .busy_domain = domain,
+ .bo_type = ttm_bo_type_kernel,
+ .size = bo_size,
+- .pin = true
++ .pin = true,
++ .keep_resv = true,
+ };
+
+ ret = vmw_bo_create(dev_priv, &bo_params, &vbo);
+ if (unlikely(ret != 0))
+ return ret;
+
+- ret = ttm_bo_reserve(&vbo->tbo, false, true, NULL);
+- BUG_ON(ret != 0);
+ ret = vmw_ttm_populate(vbo->tbo.bdev, vbo->tbo.ttm, &ctx);
+ if (likely(ret == 0)) {
+ struct vmw_ttm_tt *vmw_tt =
+--
+2.39.5
+
--- /dev/null
+From f1c0d4f64ee64a22cf5f861c2714457f2ed0948e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Dec 2024 13:55:35 -0600
+Subject: drm/vmwgfx: Unreserve BO on error
+
+From: Ian Forbes <ian.forbes@broadcom.com>
+
+[ Upstream commit cb343ded122e0bf41e4b2a9f89386296451be109 ]
+
+Unlock BOs in reverse order.
+Add an acquire context so that lockdep doesn't complain.
+
+Fixes: d6667f0ddf46 ("drm/vmwgfx: Fix handling of dumb buffers")
+Signed-off-by: Ian Forbes <ian.forbes@broadcom.com>
+Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20241210195535.2074918-1-ian.forbes@broadcom.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+index 10d596cb4b402..5f99f7437ae61 100644
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+@@ -750,6 +750,7 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
+ struct vmw_plane_state *old_vps = vmw_plane_state_to_vps(old_state);
+ struct vmw_bo *old_bo = NULL;
+ struct vmw_bo *new_bo = NULL;
++ struct ww_acquire_ctx ctx;
+ s32 hotspot_x, hotspot_y;
+ int ret;
+
+@@ -769,9 +770,11 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
+ if (du->cursor_surface)
+ du->cursor_age = du->cursor_surface->snooper.age;
+
++ ww_acquire_init(&ctx, &reservation_ww_class);
++
+ if (!vmw_user_object_is_null(&old_vps->uo)) {
+ old_bo = vmw_user_object_buffer(&old_vps->uo);
+- ret = ttm_bo_reserve(&old_bo->tbo, false, false, NULL);
++ ret = ttm_bo_reserve(&old_bo->tbo, false, false, &ctx);
+ if (ret != 0)
+ return;
+ }
+@@ -779,9 +782,14 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
+ if (!vmw_user_object_is_null(&vps->uo)) {
+ new_bo = vmw_user_object_buffer(&vps->uo);
+ if (old_bo != new_bo) {
+- ret = ttm_bo_reserve(&new_bo->tbo, false, false, NULL);
+- if (ret != 0)
++ ret = ttm_bo_reserve(&new_bo->tbo, false, false, &ctx);
++ if (ret != 0) {
++ if (old_bo) {
++ ttm_bo_unreserve(&old_bo->tbo);
++ ww_acquire_fini(&ctx);
++ }
+ return;
++ }
+ } else {
+ new_bo = NULL;
+ }
+@@ -803,10 +811,12 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
+ hotspot_x, hotspot_y);
+ }
+
+- if (old_bo)
+- ttm_bo_unreserve(&old_bo->tbo);
+ if (new_bo)
+ ttm_bo_unreserve(&new_bo->tbo);
++ if (old_bo)
++ ttm_bo_unreserve(&old_bo->tbo);
++
++ ww_acquire_fini(&ctx);
+
+ du->cursor_x = new_state->crtc_x + du->set_gui_x;
+ du->cursor_y = new_state->crtc_y + du->set_gui_y;
+--
+2.39.5
+
--- /dev/null
+From 00b3a2aaa45fc436fe1712cb62b516374720ef85 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Jan 2025 20:30:57 -0800
+Subject: eth: bnxt: always recalculate features after XDP clearing, fix
+ null-deref
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit f0aa6a37a3dbb40b272df5fc6db93c114688adcd ]
+
+Recalculate features when XDP is detached.
+
+Before:
+ # ip li set dev eth0 xdp obj xdp_dummy.bpf.o sec xdp
+ # ip li set dev eth0 xdp off
+ # ethtool -k eth0 | grep gro
+ rx-gro-hw: off [requested on]
+
+After:
+ # ip li set dev eth0 xdp obj xdp_dummy.bpf.o sec xdp
+ # ip li set dev eth0 xdp off
+ # ethtool -k eth0 | grep gro
+ rx-gro-hw: on
+
+The fact that HW-GRO doesn't get re-enabled automatically is just
+a minor annoyance. The real issue is that the features will randomly
+come back during another reconfiguration which just happens to invoke
+netdev_update_features(). The driver doesn't handle reconfiguring
+two things at a time very robustly.
+
+Starting with commit 98ba1d931f61 ("bnxt_en: Fix RSS logic in
+__bnxt_reserve_rings()") we only reconfigure the RSS hash table
+if the "effective" number of Rx rings has changed. If HW-GRO is
+enabled "effective" number of rings is 2x what user sees.
+So if we are in the bad state, with HW-GRO re-enablement "pending"
+after XDP off, and we lower the rings by / 2 - the HW-GRO rings
+doing 2x and the ethtool -L doing / 2 may cancel each other out,
+and the:
+
+ if (old_rx_rings != bp->hw_resc.resv_rx_rings &&
+
+condition in __bnxt_reserve_rings() will be false.
+The RSS map won't get updated, and we'll crash with:
+
+ BUG: kernel NULL pointer dereference, address: 0000000000000168
+ RIP: 0010:__bnxt_hwrm_vnic_set_rss+0x13a/0x1a0
+ bnxt_hwrm_vnic_rss_cfg_p5+0x47/0x180
+ __bnxt_setup_vnic_p5+0x58/0x110
+ bnxt_init_nic+0xb72/0xf50
+ __bnxt_open_nic+0x40d/0xab0
+ bnxt_open_nic+0x2b/0x60
+ ethtool_set_channels+0x18c/0x1d0
+
+As we try to access a freed ring.
+
+The issue is present since XDP support was added, really, but
+prior to commit 98ba1d931f61 ("bnxt_en: Fix RSS logic in
+__bnxt_reserve_rings()") it wasn't causing major issues.
+
+Fixes: 1054aee82321 ("bnxt_en: Use NETIF_F_GRO_HW.")
+Fixes: 98ba1d931f61 ("bnxt_en: Fix RSS logic in __bnxt_reserve_rings()")
+Reviewed-by: Michael Chan <michael.chan@broadcom.com>
+Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
+Link: https://patch.msgid.link/20250109043057.2888953-1-kuba@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bnxt/bnxt.c | 25 +++++++++++++++----
+ drivers/net/ethernet/broadcom/bnxt/bnxt.h | 2 +-
+ drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c | 7 ------
+ 3 files changed, 21 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+index c255445e97f3c..603e9c968c44b 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+@@ -4558,7 +4558,7 @@ void bnxt_set_ring_params(struct bnxt *bp)
+ /* Changing allocation mode of RX rings.
+ * TODO: Update when extending xdp_rxq_info to support allocation modes.
+ */
+-int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
++static void __bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
+ {
+ struct net_device *dev = bp->dev;
+
+@@ -4579,15 +4579,30 @@ int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
+ bp->rx_skb_func = bnxt_rx_page_skb;
+ }
+ bp->rx_dir = DMA_BIDIRECTIONAL;
+- /* Disable LRO or GRO_HW */
+- netdev_update_features(dev);
+ } else {
+ dev->max_mtu = bp->max_mtu;
+ bp->flags &= ~BNXT_FLAG_RX_PAGE_MODE;
+ bp->rx_dir = DMA_FROM_DEVICE;
+ bp->rx_skb_func = bnxt_rx_skb;
+ }
+- return 0;
++}
++
++void bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
++{
++ __bnxt_set_rx_skb_mode(bp, page_mode);
++
++ if (!page_mode) {
++ int rx, tx;
++
++ bnxt_get_max_rings(bp, &rx, &tx, true);
++ if (rx > 1) {
++ bp->flags &= ~BNXT_FLAG_NO_AGG_RINGS;
++ bp->dev->hw_features |= NETIF_F_LRO;
++ }
++ }
++
++ /* Update LRO and GRO_HW availability */
++ netdev_update_features(bp->dev);
+ }
+
+ static void bnxt_free_vnic_attributes(struct bnxt *bp)
+@@ -15909,7 +15924,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ if (bp->max_fltr < BNXT_MAX_FLTR)
+ bp->max_fltr = BNXT_MAX_FLTR;
+ bnxt_init_l2_fltr_tbl(bp);
+- bnxt_set_rx_skb_mode(bp, false);
++ __bnxt_set_rx_skb_mode(bp, false);
+ bnxt_set_tpa_flags(bp);
+ bnxt_set_ring_params(bp);
+ bnxt_rdma_aux_device_init(bp);
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+index 9e05704d94450..bee645f58d0bd 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+@@ -2796,7 +2796,7 @@ void bnxt_reuse_rx_data(struct bnxt_rx_ring_info *rxr, u16 cons, void *data);
+ u32 bnxt_fw_health_readl(struct bnxt *bp, int reg_idx);
+ void bnxt_set_tpa_flags(struct bnxt *bp);
+ void bnxt_set_ring_params(struct bnxt *);
+-int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode);
++void bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode);
+ void bnxt_insert_usr_fltr(struct bnxt *bp, struct bnxt_filter_base *fltr);
+ void bnxt_del_one_usr_fltr(struct bnxt *bp, struct bnxt_filter_base *fltr);
+ int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp, unsigned long *bmap,
+diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+index f88b641533fcc..dc51dce209d5f 100644
+--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
+@@ -422,15 +422,8 @@ static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog)
+ bnxt_set_rx_skb_mode(bp, true);
+ xdp_features_set_redirect_target(dev, true);
+ } else {
+- int rx, tx;
+-
+ xdp_features_clear_redirect_target(dev);
+ bnxt_set_rx_skb_mode(bp, false);
+- bnxt_get_max_rings(bp, &rx, &tx, true);
+- if (rx > 1) {
+- bp->flags &= ~BNXT_FLAG_NO_AGG_RINGS;
+- bp->dev->hw_features |= NETIF_F_LRO;
+- }
+ }
+ bp->tx_nr_rings_xdp = tx_xdp;
+ bp->tx_nr_rings = bp->tx_nr_rings_per_tc * tc + tx_xdp;
+--
+2.39.5
+
--- /dev/null
+From 1dbe8acb4d039ee01ea2d4e95fef75cd569fbb4a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jan 2025 10:47:53 +0900
+Subject: gtp: Destroy device along with udp socket's netns dismantle.
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit eb28fd76c0a08a47b470677c6cef9dd1c60e92d1 ]
+
+gtp_newlink() links the device to a list in dev_net(dev) instead of
+src_net, where a udp tunnel socket is created.
+
+Even when src_net is removed, the device stays alive on dev_net(dev).
+Then, removing src_net triggers the splat below. [0]
+
+In this example, gtp0 is created in ns2, and the udp socket is created
+in ns1.
+
+ ip netns add ns1
+ ip netns add ns2
+ ip -n ns1 link add netns ns2 name gtp0 type gtp role sgsn
+ ip netns del ns1
+
+Let's link the device to the socket's netns instead.
+
+Now, gtp_net_exit_batch_rtnl() needs another netdev iteration to remove
+all gtp devices in the netns.
+
+[0]:
+ref_tracker: net notrefcnt@000000003d6e7d05 has 1/2 users at
+ sk_alloc (./include/net/net_namespace.h:345 net/core/sock.c:2236)
+ inet_create (net/ipv4/af_inet.c:326 net/ipv4/af_inet.c:252)
+ __sock_create (net/socket.c:1558)
+ udp_sock_create4 (net/ipv4/udp_tunnel_core.c:18)
+ gtp_create_sock (./include/net/udp_tunnel.h:59 drivers/net/gtp.c:1423)
+ gtp_create_sockets (drivers/net/gtp.c:1447)
+ gtp_newlink (drivers/net/gtp.c:1507)
+ rtnl_newlink (net/core/rtnetlink.c:3786 net/core/rtnetlink.c:3897 net/core/rtnetlink.c:4012)
+ rtnetlink_rcv_msg (net/core/rtnetlink.c:6922)
+ netlink_rcv_skb (net/netlink/af_netlink.c:2542)
+ netlink_unicast (net/netlink/af_netlink.c:1321 net/netlink/af_netlink.c:1347)
+ netlink_sendmsg (net/netlink/af_netlink.c:1891)
+ ____sys_sendmsg (net/socket.c:711 net/socket.c:726 net/socket.c:2583)
+ ___sys_sendmsg (net/socket.c:2639)
+ __sys_sendmsg (net/socket.c:2669)
+ do_syscall_64 (arch/x86/entry/common.c:52 arch/x86/entry/common.c:83)
+
+WARNING: CPU: 1 PID: 60 at lib/ref_tracker.c:179 ref_tracker_dir_exit (lib/ref_tracker.c:179)
+Modules linked in:
+CPU: 1 UID: 0 PID: 60 Comm: kworker/u16:2 Not tainted 6.13.0-rc5-00147-g4c1224501e9d #5
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014
+Workqueue: netns cleanup_net
+RIP: 0010:ref_tracker_dir_exit (lib/ref_tracker.c:179)
+Code: 00 00 00 fc ff df 4d 8b 26 49 bd 00 01 00 00 00 00 ad de 4c 39 f5 0f 85 df 00 00 00 48 8b 74 24 08 48 89 df e8 a5 cc 12 02 90 <0f> 0b 90 48 8d 6b 44 be 04 00 00 00 48 89 ef e8 80 de 67 ff 48 89
+RSP: 0018:ff11000009a07b60 EFLAGS: 00010286
+RAX: 0000000000002bd3 RBX: ff1100000f4e1aa0 RCX: 1ffffffff0e40ac6
+RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffff8423ee3c
+RBP: ff1100000f4e1af0 R08: 0000000000000001 R09: fffffbfff0e395ae
+R10: 0000000000000001 R11: 0000000000036001 R12: ff1100000f4e1af0
+R13: dead000000000100 R14: ff1100000f4e1af0 R15: dffffc0000000000
+FS: 0000000000000000(0000) GS:ff1100006ce80000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00007f9b2464bd98 CR3: 0000000005286005 CR4: 0000000000771ef0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400
+PKRU: 55555554
+Call Trace:
+ <TASK>
+ ? __warn (kernel/panic.c:748)
+ ? ref_tracker_dir_exit (lib/ref_tracker.c:179)
+ ? report_bug (lib/bug.c:201 lib/bug.c:219)
+ ? handle_bug (arch/x86/kernel/traps.c:285)
+ ? exc_invalid_op (arch/x86/kernel/traps.c:309 (discriminator 1))
+ ? asm_exc_invalid_op (./arch/x86/include/asm/idtentry.h:621)
+ ? _raw_spin_unlock_irqrestore (./arch/x86/include/asm/irqflags.h:42 ./arch/x86/include/asm/irqflags.h:97 ./arch/x86/include/asm/irqflags.h:155 ./include/linux/spinlock_api_smp.h:151 kernel/locking/spinlock.c:194)
+ ? ref_tracker_dir_exit (lib/ref_tracker.c:179)
+ ? __pfx_ref_tracker_dir_exit (lib/ref_tracker.c:158)
+ ? kfree (mm/slub.c:4613 mm/slub.c:4761)
+ net_free (net/core/net_namespace.c:476 net/core/net_namespace.c:467)
+ cleanup_net (net/core/net_namespace.c:664 (discriminator 3))
+ process_one_work (kernel/workqueue.c:3229)
+ worker_thread (kernel/workqueue.c:3304 kernel/workqueue.c:3391)
+ kthread (kernel/kthread.c:389)
+ ret_from_fork (arch/x86/kernel/process.c:147)
+ ret_from_fork_asm (arch/x86/entry/entry_64.S:257)
+ </TASK>
+
+Fixes: 459aa660eb1d ("gtp: add initial driver for datapath of GPRS Tunneling Protocol (GTP-U)")
+Reported-by: Xiao Liang <shaw.leon@gmail.com>
+Closes: https://lore.kernel.org/netdev/20250104125732.17335-1-shaw.leon@gmail.com/
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/gtp.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
+index 819ce4b756d23..47406ce990161 100644
+--- a/drivers/net/gtp.c
++++ b/drivers/net/gtp.c
+@@ -1526,7 +1526,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
+ goto out_encap;
+ }
+
+- gn = net_generic(dev_net(dev), gtp_net_id);
++ gn = net_generic(src_net, gtp_net_id);
+ list_add(>p->list, &gn->gtp_dev_list);
+ dev->priv_destructor = gtp_destructor;
+
+@@ -2487,6 +2487,11 @@ static void __net_exit gtp_net_exit_batch_rtnl(struct list_head *net_list,
+ list_for_each_entry(net, net_list, exit_list) {
+ struct gtp_net *gn = net_generic(net, gtp_net_id);
+ struct gtp_dev *gtp, *gtp_next;
++ struct net_device *dev;
++
++ for_each_netdev(net, dev)
++ if (dev->rtnl_link_ops == >p_link_ops)
++ gtp_dellink(dev, dev_to_kill);
+
+ list_for_each_entry_safe(gtp, gtp_next, &gn->gtp_dev_list, list)
+ gtp_dellink(gtp->dev, dev_to_kill);
+--
+2.39.5
+
--- /dev/null
+From 204c25494333cbe7d49f426e6860dc021be4a7d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jan 2025 10:47:52 +0900
+Subject: gtp: Use for_each_netdev_rcu() in gtp_genl_dump_pdp().
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit 46841c7053e6d25fb33e0534ef023833bf03e382 ]
+
+gtp_newlink() links the gtp device to a list in dev_net(dev).
+
+However, even after the gtp device is moved to another netns,
+it stays on the list but should be invisible.
+
+Let's use for_each_netdev_rcu() for netdev traversal in
+gtp_genl_dump_pdp().
+
+Note that gtp_dev_list is no longer used under RCU, so list
+helpers are converted to the non-RCU variant.
+
+Fixes: 459aa660eb1d ("gtp: add initial driver for datapath of GPRS Tunneling Protocol (GTP-U)")
+Reported-by: Xiao Liang <shaw.leon@gmail.com>
+Closes: https://lore.kernel.org/netdev/CABAhCOQdBL6h9M2C+kd+bGivRJ9Q72JUxW+-gur0nub_=PmFPA@mail.gmail.com/
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/gtp.c | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/gtp.c b/drivers/net/gtp.c
+index 70f981887518a..819ce4b756d23 100644
+--- a/drivers/net/gtp.c
++++ b/drivers/net/gtp.c
+@@ -1527,7 +1527,7 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
+ }
+
+ gn = net_generic(dev_net(dev), gtp_net_id);
+- list_add_rcu(>p->list, &gn->gtp_dev_list);
++ list_add(>p->list, &gn->gtp_dev_list);
+ dev->priv_destructor = gtp_destructor;
+
+ netdev_dbg(dev, "registered new GTP interface\n");
+@@ -1553,7 +1553,7 @@ static void gtp_dellink(struct net_device *dev, struct list_head *head)
+ hlist_for_each_entry_safe(pctx, next, >p->tid_hash[i], hlist_tid)
+ pdp_context_delete(pctx);
+
+- list_del_rcu(>p->list);
++ list_del(>p->list);
+ unregister_netdevice_queue(dev, head);
+ }
+
+@@ -2279,16 +2279,19 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb,
+ struct gtp_dev *last_gtp = (struct gtp_dev *)cb->args[2], *gtp;
+ int i, j, bucket = cb->args[0], skip = cb->args[1];
+ struct net *net = sock_net(skb->sk);
++ struct net_device *dev;
+ struct pdp_ctx *pctx;
+- struct gtp_net *gn;
+-
+- gn = net_generic(net, gtp_net_id);
+
+ if (cb->args[4])
+ return 0;
+
+ rcu_read_lock();
+- list_for_each_entry_rcu(gtp, &gn->gtp_dev_list, list) {
++ for_each_netdev_rcu(net, dev) {
++ if (dev->rtnl_link_ops != >p_link_ops)
++ continue;
++
++ gtp = netdev_priv(dev);
++
+ if (last_gtp && last_gtp != gtp)
+ continue;
+ else
+@@ -2483,9 +2486,9 @@ static void __net_exit gtp_net_exit_batch_rtnl(struct list_head *net_list,
+
+ list_for_each_entry(net, net_list, exit_list) {
+ struct gtp_net *gn = net_generic(net, gtp_net_id);
+- struct gtp_dev *gtp;
++ struct gtp_dev *gtp, *gtp_next;
+
+- list_for_each_entry(gtp, &gn->gtp_dev_list, list)
++ list_for_each_entry_safe(gtp, gtp_next, &gn->gtp_dev_list, list)
+ gtp_dellink(gtp->dev, dev_to_kill);
+ }
+ }
+--
+2.39.5
+
--- /dev/null
+From ff7d5ac3e7743791f9d8444534229248faf20446 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Nov 2024 13:29:16 +0100
+Subject: ice: Add correct PHY lane assignment
+
+From: Karol Kolacinski <karol.kolacinski@intel.com>
+
+[ Upstream commit 258f5f905815979f15d5151d2ea4f20d8e057fe1 ]
+
+Driver always naively assumes, that for PTP purposes, PHY lane to
+configure is corresponding to PF ID.
+
+This is not true for some port configurations, e.g.:
+- 2x50G per quad, where lanes used are 0 and 2 on each quad, but PF IDs
+ are 0 and 1
+- 100G per quad on 2 quads, where lanes used are 0 and 4, but PF IDs are
+ 0 and 1
+
+Use correct PHY lane assignment by getting and parsing port options.
+This is read from the NVM by the FW and provided to the driver with
+the indication of active port split.
+
+Remove ice_is_muxed_topo(), which is no longer needed.
+
+Fixes: 4409ea1726cb ("ice: Adjust PTP init for 2x50G E825C devices")
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Reviewed-by: Arkadiusz Kubalewski <Arkadiusz.kubalewski@intel.com>
+Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
+Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/intel/ice/ice_adminq_cmd.h | 1 +
+ drivers/net/ethernet/intel/ice/ice_common.c | 51 +++++++++++++++++++
+ drivers/net/ethernet/intel/ice/ice_common.h | 1 +
+ drivers/net/ethernet/intel/ice/ice_main.c | 6 +--
+ drivers/net/ethernet/intel/ice/ice_ptp.c | 23 ++++-----
+ drivers/net/ethernet/intel/ice/ice_ptp.h | 4 +-
+ drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 26 +---------
+ drivers/net/ethernet/intel/ice/ice_type.h | 1 -
+ 8 files changed, 68 insertions(+), 45 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
+index 79a6edd0be0ec..80f3dfd271243 100644
+--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
++++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
+@@ -1648,6 +1648,7 @@ struct ice_aqc_get_port_options_elem {
+ #define ICE_AQC_PORT_OPT_MAX_LANE_25G 5
+ #define ICE_AQC_PORT_OPT_MAX_LANE_50G 6
+ #define ICE_AQC_PORT_OPT_MAX_LANE_100G 7
++#define ICE_AQC_PORT_OPT_MAX_LANE_200G 8
+
+ u8 global_scid[2];
+ u8 phy_scid[2];
+diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
+index f1324e25b2af1..068a467de1d56 100644
+--- a/drivers/net/ethernet/intel/ice/ice_common.c
++++ b/drivers/net/ethernet/intel/ice/ice_common.c
+@@ -4074,6 +4074,57 @@ ice_aq_set_port_option(struct ice_hw *hw, u8 lport, u8 lport_valid,
+ return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
+ }
+
++/**
++ * ice_get_phy_lane_number - Get PHY lane number for current adapter
++ * @hw: pointer to the hw struct
++ *
++ * Return: PHY lane number on success, negative error code otherwise.
++ */
++int ice_get_phy_lane_number(struct ice_hw *hw)
++{
++ struct ice_aqc_get_port_options_elem *options;
++ unsigned int lport = 0;
++ unsigned int lane;
++ int err;
++
++ options = kcalloc(ICE_AQC_PORT_OPT_MAX, sizeof(*options), GFP_KERNEL);
++ if (!options)
++ return -ENOMEM;
++
++ for (lane = 0; lane < ICE_MAX_PORT_PER_PCI_DEV; lane++) {
++ u8 options_count = ICE_AQC_PORT_OPT_MAX;
++ u8 speed, active_idx, pending_idx;
++ bool active_valid, pending_valid;
++
++ err = ice_aq_get_port_options(hw, options, &options_count, lane,
++ true, &active_idx, &active_valid,
++ &pending_idx, &pending_valid);
++ if (err)
++ goto err;
++
++ if (!active_valid)
++ continue;
++
++ speed = options[active_idx].max_lane_speed;
++ /* If we don't get speed for this lane, it's unoccupied */
++ if (speed > ICE_AQC_PORT_OPT_MAX_LANE_200G)
++ continue;
++
++ if (hw->pf_id == lport) {
++ kfree(options);
++ return lane;
++ }
++
++ lport++;
++ }
++
++ /* PHY lane not found */
++ err = -ENXIO;
++err:
++ kfree(options);
++ return err;
++}
++
+ /**
+ * ice_aq_sff_eeprom
+ * @hw: pointer to the HW struct
+diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h
+index 27208a60cece5..fe6f88cfd9486 100644
+--- a/drivers/net/ethernet/intel/ice/ice_common.h
++++ b/drivers/net/ethernet/intel/ice/ice_common.h
+@@ -193,6 +193,7 @@ ice_aq_get_port_options(struct ice_hw *hw,
+ int
+ ice_aq_set_port_option(struct ice_hw *hw, u8 lport, u8 lport_valid,
+ u8 new_option);
++int ice_get_phy_lane_number(struct ice_hw *hw);
+ int
+ ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,
+ u16 mem_addr, u8 page, u8 set_page, u8 *data, u8 length,
+diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
+index 8f2e758c39427..45eefe22fb5b7 100644
+--- a/drivers/net/ethernet/intel/ice/ice_main.c
++++ b/drivers/net/ethernet/intel/ice/ice_main.c
+@@ -1144,7 +1144,7 @@ ice_link_event(struct ice_pf *pf, struct ice_port_info *pi, bool link_up,
+ if (link_up == old_link && link_speed == old_link_speed)
+ return 0;
+
+- ice_ptp_link_change(pf, pf->hw.pf_id, link_up);
++ ice_ptp_link_change(pf, link_up);
+
+ if (ice_is_dcb_active(pf)) {
+ if (test_bit(ICE_FLAG_DCB_ENA, pf->flags))
+@@ -6744,7 +6744,7 @@ 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, pf->hw.pf_id, true);
++ ice_ptp_link_change(pf, true);
+ }
+
+ /* Perform an initial read of the statistics registers now to
+@@ -7214,7 +7214,7 @@ int ice_down(struct ice_vsi *vsi)
+
+ if (vsi->netdev) {
+ vlan_err = ice_vsi_del_vlan_zero(vsi);
+- ice_ptp_link_change(vsi->back, vsi->back->hw.pf_id, false);
++ 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 0b3dd87a331c7..7c6f81beaee46 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
+@@ -1466,10 +1466,9 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port)
+ /**
+ * ice_ptp_link_change - Reconfigure PTP after link status change
+ * @pf: Board private structure
+- * @port: Port for which the PHY start is set
+ * @linkup: Link is up or down
+ */
+-void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup)
++void ice_ptp_link_change(struct ice_pf *pf, bool linkup)
+ {
+ struct ice_ptp_port *ptp_port;
+ struct ice_hw *hw = &pf->hw;
+@@ -1477,14 +1476,7 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup)
+ if (pf->ptp.state != ICE_PTP_READY)
+ return;
+
+- if (WARN_ON_ONCE(port >= hw->ptp.num_lports))
+- return;
+-
+ ptp_port = &pf->ptp.port;
+- if (ice_is_e825c(hw) && hw->ptp.is_2x50g_muxed_topo)
+- port *= 2;
+- if (WARN_ON_ONCE(ptp_port->port_num != port))
+- return;
+
+ /* Update cached link status for this port immediately */
+ ptp_port->link_up = linkup;
+@@ -3383,10 +3375,17 @@ void ice_ptp_init(struct ice_pf *pf)
+ {
+ struct ice_ptp *ptp = &pf->ptp;
+ struct ice_hw *hw = &pf->hw;
+- int err;
++ int lane_num, err;
+
+ ptp->state = ICE_PTP_INITIALIZING;
+
++ lane_num = ice_get_phy_lane_number(hw);
++ if (lane_num < 0) {
++ err = lane_num;
++ goto err_exit;
++ }
++
++ ptp->port.port_num = (u8)lane_num;
+ ice_ptp_init_hw(hw);
+
+ ice_ptp_init_tx_interrupt_mode(pf);
+@@ -3407,10 +3406,6 @@ void ice_ptp_init(struct ice_pf *pf)
+ if (err)
+ goto err_exit;
+
+- ptp->port.port_num = hw->pf_id;
+- if (ice_is_e825c(hw) && hw->ptp.is_2x50g_muxed_topo)
+- ptp->port.port_num = hw->pf_id * 2;
+-
+ err = ice_ptp_init_port(pf, &ptp->port);
+ if (err)
+ goto err_exit;
+diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h
+index 5615efc42c624..f1cfa6aa4e76b 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
+@@ -332,7 +332,7 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf,
+ enum ice_reset_req reset_type);
+ void ice_ptp_init(struct ice_pf *pf);
+ void ice_ptp_release(struct ice_pf *pf);
+-void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup);
++void ice_ptp_link_change(struct ice_pf *pf, bool linkup);
+ #else /* IS_ENABLED(CONFIG_PTP_1588_CLOCK) */
+ static inline int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr)
+ {
+@@ -380,7 +380,7 @@ static inline void ice_ptp_prepare_for_reset(struct ice_pf *pf,
+ }
+ static inline void ice_ptp_init(struct ice_pf *pf) { }
+ static inline void ice_ptp_release(struct ice_pf *pf) { }
+-static inline void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup)
++static inline void ice_ptp_link_change(struct ice_pf *pf, bool linkup)
+ {
+ }
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+index 28bd4815ebcf3..7190fde16c868 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+@@ -2698,26 +2698,6 @@ static int ice_get_phy_tx_tstamp_ready_eth56g(struct ice_hw *hw, u8 port,
+ return 0;
+ }
+
+-/**
+- * ice_is_muxed_topo - detect breakout 2x50G topology for E825C
+- * @hw: pointer to the HW struct
+- *
+- * Return: true if it's 2x50 breakout topology, false otherwise
+- */
+-static bool ice_is_muxed_topo(struct ice_hw *hw)
+-{
+- u8 link_topo;
+- bool mux;
+- u32 val;
+-
+- val = rd32(hw, GLGEN_SWITCH_MODE_CONFIG);
+- mux = FIELD_GET(GLGEN_SWITCH_MODE_CONFIG_25X4_QUAD_M, val);
+- val = rd32(hw, GLGEN_MAC_LINK_TOPO);
+- link_topo = FIELD_GET(GLGEN_MAC_LINK_TOPO_LINK_TOPO_M, val);
+-
+- return (mux && link_topo == ICE_LINK_TOPO_UP_TO_2_LINKS);
+-}
+-
+ /**
+ * ice_ptp_init_phy_e825 - initialize PHY parameters
+ * @hw: pointer to the HW struct
+@@ -2740,12 +2720,8 @@ static void ice_ptp_init_phy_e825(struct ice_hw *hw)
+
+ ice_sb_access_ena_eth56g(hw, true);
+ err = ice_read_phy_eth56g(hw, hw->pf_id, PHY_REG_REVISION, &phy_rev);
+- if (err || phy_rev != PHY_REVISION_ETH56G) {
++ if (err || phy_rev != PHY_REVISION_ETH56G)
+ ptp->phy_model = ICE_PHY_UNSUP;
+- return;
+- }
+-
+- ptp->is_2x50g_muxed_topo = ice_is_muxed_topo(hw);
+ }
+
+ /* E822 family functions
+diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
+index 479227bdff75e..609f31e0dfded 100644
+--- a/drivers/net/ethernet/intel/ice/ice_type.h
++++ b/drivers/net/ethernet/intel/ice/ice_type.h
+@@ -880,7 +880,6 @@ struct ice_ptp_hw {
+ union ice_phy_params phy;
+ u8 num_lports;
+ u8 ports_per_phy;
+- bool is_2x50g_muxed_topo;
+ };
+
+ /* Port hardware description */
+--
+2.39.5
+
--- /dev/null
+From e100d854a338dbf390b9076ddd54556f4b0da4a6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 15:09:54 +0200
+Subject: ice: Add ice_get_ctrl_ptp() wrapper to simplify the code
+
+From: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
+
+[ Upstream commit 97ed20a01f5b96e8738b53f56ae84b06953a2853 ]
+
+Add ice_get_ctrl_ptp() wrapper to simplify the PTP support code
+in the functions that do not use ctrl_pf directly.
+Add the control PF pointer to struct ice_adapter
+Rearrange fields in struct ice_adapter
+
+Signed-off-by: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Stable-dep-of: 258f5f905815 ("ice: Add correct PHY lane assignment")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_adapter.h | 5 ++++-
+ drivers/net/ethernet/intel/ice/ice_ptp.c | 12 ++++++++++++
+ 2 files changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.h b/drivers/net/ethernet/intel/ice/ice_adapter.h
+index 9d11014ec02ff..eb7cac01c2427 100644
+--- a/drivers/net/ethernet/intel/ice/ice_adapter.h
++++ b/drivers/net/ethernet/intel/ice/ice_adapter.h
+@@ -8,18 +8,21 @@
+ #include <linux/refcount_types.h>
+
+ struct pci_dev;
++struct ice_pf;
+
+ /**
+ * struct ice_adapter - PCI adapter resources shared across PFs
+ * @ptp_gltsyn_time_lock: Spinlock protecting access to the GLTSYN_TIME
+ * register of the PTP clock.
+ * @refcount: Reference count. struct ice_pf objects hold the references.
++ * @ctrl_pf: Control PF of the adapter
+ */
+ struct ice_adapter {
++ refcount_t refcount;
+ /* For access to the GLTSYN_TIME register */
+ spinlock_t ptp_gltsyn_time_lock;
+
+- refcount_t refcount;
++ struct ice_pf *ctrl_pf;
+ };
+
+ struct ice_adapter *ice_adapter_get(const struct pci_dev *pdev);
+diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
+index d534c8e571cee..2fb73ab41bc20 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
+@@ -16,6 +16,18 @@ static const struct ptp_pin_desc ice_pin_desc_e810t[] = {
+ { "U.FL2", UFL2, PTP_PF_NONE, 2, { 0, } },
+ };
+
++static struct ice_pf *ice_get_ctrl_pf(struct ice_pf *pf)
++{
++ return !pf->adapter ? NULL : pf->adapter->ctrl_pf;
++}
++
++static __maybe_unused struct ice_ptp *ice_get_ctrl_ptp(struct ice_pf *pf)
++{
++ struct ice_pf *ctrl_pf = ice_get_ctrl_pf(pf);
++
++ return !ctrl_pf ? NULL : &ctrl_pf->ptp;
++}
++
+ /**
+ * ice_get_sma_config_e810t
+ * @hw: pointer to the hw struct
+--
+2.39.5
+
--- /dev/null
+From f3367479563eb8ed8303f527e3bb82d45926221a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Nov 2024 13:29:13 +0100
+Subject: ice: Fix E825 initialization
+
+From: Karol Kolacinski <karol.kolacinski@intel.com>
+
+[ Upstream commit d79c304c76e9b30ff5527afc176b5c4f9f0374b6 ]
+
+Current implementation checks revision of all PHYs on all PFs, which is
+incorrect and may result in initialization failure. Check only the
+revision of the current PHY.
+
+Fixes: 7cab44f1c35f ("ice: Introduce ETH56G PHY model for E825C products")
+Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
+Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
+Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 22 +++++++++------------
+ 1 file changed, 9 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+index 3816e45b6ab44..f6816c2f71438 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+@@ -2664,14 +2664,15 @@ static bool ice_is_muxed_topo(struct ice_hw *hw)
+ }
+
+ /**
+- * ice_ptp_init_phy_e825c - initialize PHY parameters
++ * ice_ptp_init_phy_e825 - initialize PHY parameters
+ * @hw: pointer to the HW struct
+ */
+-static void ice_ptp_init_phy_e825c(struct ice_hw *hw)
++static void ice_ptp_init_phy_e825(struct ice_hw *hw)
+ {
+ struct ice_ptp_hw *ptp = &hw->ptp;
+ struct ice_eth56g_params *params;
+- u8 phy;
++ u32 phy_rev;
++ int err;
+
+ ptp->phy_model = ICE_PHY_ETH56G;
+ params = &ptp->phy.eth56g;
+@@ -2685,15 +2686,10 @@ static void ice_ptp_init_phy_e825c(struct ice_hw *hw)
+ ptp->num_lports = params->num_phys * ptp->ports_per_phy;
+
+ ice_sb_access_ena_eth56g(hw, true);
+- for (phy = 0; phy < params->num_phys; phy++) {
+- u32 phy_rev;
+- int err;
+-
+- err = ice_read_phy_eth56g(hw, phy, PHY_REG_REVISION, &phy_rev);
+- if (err || phy_rev != PHY_REVISION_ETH56G) {
+- ptp->phy_model = ICE_PHY_UNSUP;
+- return;
+- }
++ err = ice_read_phy_eth56g(hw, hw->pf_id, PHY_REG_REVISION, &phy_rev);
++ if (err || phy_rev != PHY_REVISION_ETH56G) {
++ ptp->phy_model = ICE_PHY_UNSUP;
++ return;
+ }
+
+ ptp->is_2x50g_muxed_topo = ice_is_muxed_topo(hw);
+@@ -5395,7 +5391,7 @@ void ice_ptp_init_hw(struct ice_hw *hw)
+ else if (ice_is_e810(hw))
+ ice_ptp_init_phy_e810(ptp);
+ else if (ice_is_e825c(hw))
+- ice_ptp_init_phy_e825c(hw);
++ ice_ptp_init_phy_e825(hw);
+ else
+ ptp->phy_model = ICE_PHY_UNSUP;
+ }
+--
+2.39.5
+
--- /dev/null
+From 3b4066672e0b53c25af72680e200f8f4964ce868 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Nov 2024 13:29:15 +0100
+Subject: ice: Fix ETH56G FC-FEC Rx offset value
+
+From: Karol Kolacinski <karol.kolacinski@intel.com>
+
+[ Upstream commit 2e60560f1ec9b722f9c6699ec5d966f1732d14dd ]
+
+Fix ETH56G FC-FEC incorrect Rx offset value by changing it from -255.96
+to -469.26 ns.
+
+Those values are derived from HW spec and reflect internal delays.
+Hex value is a fixed point representation in Q23.9 format.
+
+Fixes: 7cab44f1c35f ("ice: Introduce ETH56G PHY model for E825C products")
+Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
+Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_ptp_consts.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_consts.h b/drivers/net/ethernet/intel/ice/ice_ptp_consts.h
+index 3005dd252a102..bdb1020147d1c 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ptp_consts.h
++++ b/drivers/net/ethernet/intel/ice/ice_ptp_consts.h
+@@ -131,7 +131,7 @@ struct ice_eth56g_mac_reg_cfg eth56g_mac_cfg[NUM_ICE_ETH56G_LNK_SPD] = {
+ .rx_offset = {
+ .serdes = 0xffffeb27, /* -10.42424 */
+ .no_fec = 0xffffcccd, /* -25.6 */
+- .fc = 0xfffe0014, /* -255.96 */
++ .fc = 0xfffc557b, /* -469.26 */
+ .sfd = 0x4a4, /* 2.32 */
+ .bs_ds = 0x32 /* 0.0969697 */
+ }
+--
+2.39.5
+
--- /dev/null
+From 63a45c1b0d95af055c17c2fc2eb6f2c3d747fd31 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Nov 2024 13:29:14 +0100
+Subject: ice: Fix quad registers read on E825
+
+From: Karol Kolacinski <karol.kolacinski@intel.com>
+
+[ Upstream commit dc26548d729e5f732197d2b210fb77c745b01495 ]
+
+Quad registers are read/written incorrectly. E825 devices always use
+quad 0 address and differentiate between the PHYs by changing SBQ
+destination device (phy_0 or phy_0_peer).
+
+Add helpers for reading/writing PTP registers shared per quad and use
+correct quad address and SBQ destination device based on port.
+
+Fixes: 7cab44f1c35f ("ice: Introduce ETH56G PHY model for E825C products")
+Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
+Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
+Signed-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 219 ++++++++++++--------
+ drivers/net/ethernet/intel/ice/ice_type.h | 1 -
+ 2 files changed, 133 insertions(+), 87 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+index f6816c2f71438..64c36620a02f3 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+@@ -877,31 +877,46 @@ static void ice_ptp_exec_tmr_cmd(struct ice_hw *hw)
+ * The following functions operate on devices with the ETH 56G PHY.
+ */
+
++/**
++ * ice_ptp_get_dest_dev_e825 - get destination PHY for given port number
++ * @hw: pointer to the HW struct
++ * @port: destination port
++ *
++ * Return: destination sideband queue PHY device.
++ */
++static enum ice_sbq_msg_dev ice_ptp_get_dest_dev_e825(struct ice_hw *hw,
++ u8 port)
++{
++ /* On a single complex E825, PHY 0 is always destination device phy_0
++ * and PHY 1 is phy_0_peer.
++ */
++ if (port >= hw->ptp.ports_per_phy)
++ return eth56g_phy_1;
++ else
++ return eth56g_phy_0;
++}
++
+ /**
+ * ice_write_phy_eth56g - Write a PHY port register
+ * @hw: pointer to the HW struct
+- * @phy_idx: PHY index
++ * @port: destination port
+ * @addr: PHY register address
+ * @val: Value to write
+ *
+ * Return: 0 on success, other error codes when failed to write to PHY
+ */
+-static int ice_write_phy_eth56g(struct ice_hw *hw, u8 phy_idx, u32 addr,
+- u32 val)
++static int ice_write_phy_eth56g(struct ice_hw *hw, u8 port, u32 addr, u32 val)
+ {
+- struct ice_sbq_msg_input phy_msg;
++ struct ice_sbq_msg_input msg = {
++ .dest_dev = ice_ptp_get_dest_dev_e825(hw, port),
++ .opcode = ice_sbq_msg_wr,
++ .msg_addr_low = lower_16_bits(addr),
++ .msg_addr_high = upper_16_bits(addr),
++ .data = val
++ };
+ int err;
+
+- phy_msg.opcode = ice_sbq_msg_wr;
+-
+- phy_msg.msg_addr_low = lower_16_bits(addr);
+- phy_msg.msg_addr_high = upper_16_bits(addr);
+-
+- phy_msg.data = val;
+- phy_msg.dest_dev = hw->ptp.phy.eth56g.phy_addr[phy_idx];
+-
+- err = ice_sbq_rw_reg(hw, &phy_msg, ICE_AQ_FLAG_RD);
+-
++ err = ice_sbq_rw_reg(hw, &msg, ICE_AQ_FLAG_RD);
+ if (err)
+ ice_debug(hw, ICE_DBG_PTP, "PTP failed to send msg to phy %d\n",
+ err);
+@@ -912,41 +927,36 @@ static int ice_write_phy_eth56g(struct ice_hw *hw, u8 phy_idx, u32 addr,
+ /**
+ * ice_read_phy_eth56g - Read a PHY port register
+ * @hw: pointer to the HW struct
+- * @phy_idx: PHY index
++ * @port: destination port
+ * @addr: PHY register address
+ * @val: Value to write
+ *
+ * Return: 0 on success, other error codes when failed to read from PHY
+ */
+-static int ice_read_phy_eth56g(struct ice_hw *hw, u8 phy_idx, u32 addr,
+- u32 *val)
++static int ice_read_phy_eth56g(struct ice_hw *hw, u8 port, u32 addr, u32 *val)
+ {
+- struct ice_sbq_msg_input phy_msg;
++ struct ice_sbq_msg_input msg = {
++ .dest_dev = ice_ptp_get_dest_dev_e825(hw, port),
++ .opcode = ice_sbq_msg_rd,
++ .msg_addr_low = lower_16_bits(addr),
++ .msg_addr_high = upper_16_bits(addr)
++ };
+ int err;
+
+- phy_msg.opcode = ice_sbq_msg_rd;
+-
+- phy_msg.msg_addr_low = lower_16_bits(addr);
+- phy_msg.msg_addr_high = upper_16_bits(addr);
+-
+- phy_msg.data = 0;
+- phy_msg.dest_dev = hw->ptp.phy.eth56g.phy_addr[phy_idx];
+-
+- err = ice_sbq_rw_reg(hw, &phy_msg, ICE_AQ_FLAG_RD);
+- if (err) {
++ err = ice_sbq_rw_reg(hw, &msg, ICE_AQ_FLAG_RD);
++ if (err)
+ ice_debug(hw, ICE_DBG_PTP, "PTP failed to send msg to phy %d\n",
+ err);
+- return err;
+- }
+-
+- *val = phy_msg.data;
++ else
++ *val = msg.data;
+
+- return 0;
++ return err;
+ }
+
+ /**
+ * ice_phy_res_address_eth56g - Calculate a PHY port register address
+- * @port: Port number to be written
++ * @hw: pointer to the HW struct
++ * @lane: Lane number to be written
+ * @res_type: resource type (register/memory)
+ * @offset: Offset from PHY port register base
+ * @addr: The result address
+@@ -955,17 +965,19 @@ static int ice_read_phy_eth56g(struct ice_hw *hw, u8 phy_idx, u32 addr,
+ * * %0 - success
+ * * %EINVAL - invalid port number or resource type
+ */
+-static int ice_phy_res_address_eth56g(u8 port, enum eth56g_res_type res_type,
+- u32 offset, u32 *addr)
++static int ice_phy_res_address_eth56g(struct ice_hw *hw, u8 lane,
++ enum eth56g_res_type res_type,
++ u32 offset,
++ u32 *addr)
+ {
+- u8 lane = port % ICE_PORTS_PER_QUAD;
+- u8 phy = ICE_GET_QUAD_NUM(port);
+-
+ if (res_type >= NUM_ETH56G_PHY_RES)
+ return -EINVAL;
+
+- *addr = eth56g_phy_res[res_type].base[phy] +
++ /* Lanes 4..7 are in fact 0..3 on a second PHY */
++ lane %= hw->ptp.ports_per_phy;
++ *addr = eth56g_phy_res[res_type].base[0] +
+ lane * eth56g_phy_res[res_type].step + offset;
++
+ return 0;
+ }
+
+@@ -985,19 +997,17 @@ static int ice_phy_res_address_eth56g(u8 port, enum eth56g_res_type res_type,
+ static int ice_write_port_eth56g(struct ice_hw *hw, u8 port, u32 offset,
+ u32 val, enum eth56g_res_type res_type)
+ {
+- u8 phy_port = port % hw->ptp.ports_per_phy;
+- u8 phy_idx = port / hw->ptp.ports_per_phy;
+ u32 addr;
+ int err;
+
+ if (port >= hw->ptp.num_lports)
+ return -EINVAL;
+
+- err = ice_phy_res_address_eth56g(phy_port, res_type, offset, &addr);
++ err = ice_phy_res_address_eth56g(hw, port, res_type, offset, &addr);
+ if (err)
+ return err;
+
+- return ice_write_phy_eth56g(hw, phy_idx, addr, val);
++ return ice_write_phy_eth56g(hw, port, addr, val);
+ }
+
+ /**
+@@ -1016,19 +1026,17 @@ static int ice_write_port_eth56g(struct ice_hw *hw, u8 port, u32 offset,
+ static int ice_read_port_eth56g(struct ice_hw *hw, u8 port, u32 offset,
+ u32 *val, enum eth56g_res_type res_type)
+ {
+- u8 phy_port = port % hw->ptp.ports_per_phy;
+- u8 phy_idx = port / hw->ptp.ports_per_phy;
+ u32 addr;
+ int err;
+
+ if (port >= hw->ptp.num_lports)
+ return -EINVAL;
+
+- err = ice_phy_res_address_eth56g(phy_port, res_type, offset, &addr);
++ err = ice_phy_res_address_eth56g(hw, port, res_type, offset, &addr);
+ if (err)
+ return err;
+
+- return ice_read_phy_eth56g(hw, phy_idx, addr, val);
++ return ice_read_phy_eth56g(hw, port, addr, val);
+ }
+
+ /**
+@@ -1177,6 +1185,56 @@ static int ice_write_port_mem_eth56g(struct ice_hw *hw, u8 port, u16 offset,
+ return ice_write_port_eth56g(hw, port, offset, val, ETH56G_PHY_MEM_PTP);
+ }
+
++/**
++ * ice_write_quad_ptp_reg_eth56g - Write a PHY quad register
++ * @hw: pointer to the HW struct
++ * @offset: PHY register offset
++ * @port: Port number
++ * @val: Value to write
++ *
++ * Return:
++ * * %0 - success
++ * * %EIO - invalid port number or resource type
++ * * %other - failed to write to PHY
++ */
++static int ice_write_quad_ptp_reg_eth56g(struct ice_hw *hw, u8 port,
++ u32 offset, u32 val)
++{
++ u32 addr;
++
++ if (port >= hw->ptp.num_lports)
++ return -EIO;
++
++ addr = eth56g_phy_res[ETH56G_PHY_REG_PTP].base[0] + offset;
++
++ return ice_write_phy_eth56g(hw, port, addr, val);
++}
++
++/**
++ * ice_read_quad_ptp_reg_eth56g - Read a PHY quad register
++ * @hw: pointer to the HW struct
++ * @offset: PHY register offset
++ * @port: Port number
++ * @val: Value to read
++ *
++ * Return:
++ * * %0 - success
++ * * %EIO - invalid port number or resource type
++ * * %other - failed to read from PHY
++ */
++static int ice_read_quad_ptp_reg_eth56g(struct ice_hw *hw, u8 port,
++ u32 offset, u32 *val)
++{
++ u32 addr;
++
++ if (port >= hw->ptp.num_lports)
++ return -EIO;
++
++ addr = eth56g_phy_res[ETH56G_PHY_REG_PTP].base[0] + offset;
++
++ return ice_read_phy_eth56g(hw, port, addr, val);
++}
++
+ /**
+ * ice_is_64b_phy_reg_eth56g - Check if this is a 64bit PHY register
+ * @low_addr: the low address to check
+@@ -1896,7 +1954,6 @@ ice_phy_get_speed_eth56g(struct ice_link_status *li)
+ */
+ static int ice_phy_cfg_parpcs_eth56g(struct ice_hw *hw, u8 port)
+ {
+- u8 port_blk = port & ~(ICE_PORTS_PER_QUAD - 1);
+ u32 val;
+ int err;
+
+@@ -1911,8 +1968,8 @@ static int ice_phy_cfg_parpcs_eth56g(struct ice_hw *hw, u8 port)
+ switch (ice_phy_get_speed_eth56g(&hw->port_info->phy.link_info)) {
+ case ICE_ETH56G_LNK_SPD_1G:
+ case ICE_ETH56G_LNK_SPD_2_5G:
+- err = ice_read_ptp_reg_eth56g(hw, port_blk,
+- PHY_GPCS_CONFIG_REG0, &val);
++ err = ice_read_quad_ptp_reg_eth56g(hw, port,
++ PHY_GPCS_CONFIG_REG0, &val);
+ if (err) {
+ ice_debug(hw, ICE_DBG_PTP, "Failed to read PHY_GPCS_CONFIG_REG0, status: %d",
+ err);
+@@ -1923,8 +1980,8 @@ static int ice_phy_cfg_parpcs_eth56g(struct ice_hw *hw, u8 port)
+ val |= FIELD_PREP(PHY_GPCS_CONFIG_REG0_TX_THR_M,
+ ICE_ETH56G_NOMINAL_TX_THRESH);
+
+- err = ice_write_ptp_reg_eth56g(hw, port_blk,
+- PHY_GPCS_CONFIG_REG0, val);
++ err = ice_write_quad_ptp_reg_eth56g(hw, port,
++ PHY_GPCS_CONFIG_REG0, val);
+ if (err) {
+ ice_debug(hw, ICE_DBG_PTP, "Failed to write PHY_GPCS_CONFIG_REG0, status: %d",
+ err);
+@@ -1965,50 +2022,47 @@ static int ice_phy_cfg_parpcs_eth56g(struct ice_hw *hw, u8 port)
+ */
+ int ice_phy_cfg_ptp_1step_eth56g(struct ice_hw *hw, u8 port)
+ {
+- u8 port_blk = port & ~(ICE_PORTS_PER_QUAD - 1);
+- u8 blk_port = port & (ICE_PORTS_PER_QUAD - 1);
++ u8 quad_lane = port % ICE_PORTS_PER_QUAD;
++ u32 addr, val, peer_delay;
+ bool enable, sfd_ena;
+- u32 val, peer_delay;
+ int err;
+
+ enable = hw->ptp.phy.eth56g.onestep_ena;
+ peer_delay = hw->ptp.phy.eth56g.peer_delay;
+ sfd_ena = hw->ptp.phy.eth56g.sfd_ena;
+
+- /* PHY_PTP_1STEP_CONFIG */
+- err = ice_read_ptp_reg_eth56g(hw, port_blk, PHY_PTP_1STEP_CONFIG, &val);
++ addr = PHY_PTP_1STEP_CONFIG;
++ err = ice_read_quad_ptp_reg_eth56g(hw, port, addr, &val);
+ if (err)
+ return err;
+
+ if (enable)
+- val |= blk_port;
++ val |= BIT(quad_lane);
+ else
+- val &= ~blk_port;
++ val &= ~BIT(quad_lane);
+
+ val &= ~(PHY_PTP_1STEP_T1S_UP64_M | PHY_PTP_1STEP_T1S_DELTA_M);
+
+- err = ice_write_ptp_reg_eth56g(hw, port_blk, PHY_PTP_1STEP_CONFIG, val);
++ err = ice_write_quad_ptp_reg_eth56g(hw, port, addr, val);
+ if (err)
+ return err;
+
+- /* PHY_PTP_1STEP_PEER_DELAY */
++ addr = PHY_PTP_1STEP_PEER_DELAY(quad_lane);
+ val = FIELD_PREP(PHY_PTP_1STEP_PD_DELAY_M, peer_delay);
+ if (peer_delay)
+ val |= PHY_PTP_1STEP_PD_ADD_PD_M;
+ val |= PHY_PTP_1STEP_PD_DLY_V_M;
+- err = ice_write_ptp_reg_eth56g(hw, port_blk,
+- PHY_PTP_1STEP_PEER_DELAY(blk_port), val);
++ err = ice_write_quad_ptp_reg_eth56g(hw, port, addr, val);
+ if (err)
+ return err;
+
+ val &= ~PHY_PTP_1STEP_PD_DLY_V_M;
+- err = ice_write_ptp_reg_eth56g(hw, port_blk,
+- PHY_PTP_1STEP_PEER_DELAY(blk_port), val);
++ err = ice_write_quad_ptp_reg_eth56g(hw, port, addr, val);
+ if (err)
+ return err;
+
+- /* PHY_MAC_XIF_MODE */
+- err = ice_read_mac_reg_eth56g(hw, port, PHY_MAC_XIF_MODE, &val);
++ addr = PHY_MAC_XIF_MODE;
++ err = ice_read_mac_reg_eth56g(hw, port, addr, &val);
+ if (err)
+ return err;
+
+@@ -2028,7 +2082,7 @@ int ice_phy_cfg_ptp_1step_eth56g(struct ice_hw *hw, u8 port)
+ FIELD_PREP(PHY_MAC_XIF_TS_BIN_MODE_M, enable) |
+ FIELD_PREP(PHY_MAC_XIF_TS_SFD_ENA_M, sfd_ena);
+
+- return ice_write_mac_reg_eth56g(hw, port, PHY_MAC_XIF_MODE, val);
++ return ice_write_mac_reg_eth56g(hw, port, addr, val);
+ }
+
+ /**
+@@ -2070,21 +2124,22 @@ static u32 ice_ptp_calc_bitslip_eth56g(struct ice_hw *hw, u8 port, u32 bs,
+ bool fc, bool rs,
+ enum ice_eth56g_link_spd spd)
+ {
+- u8 port_offset = port & (ICE_PORTS_PER_QUAD - 1);
+- u8 port_blk = port & ~(ICE_PORTS_PER_QUAD - 1);
+ u32 bitslip;
+ int err;
+
+ if (!bs || rs)
+ return 0;
+
+- if (spd == ICE_ETH56G_LNK_SPD_1G || spd == ICE_ETH56G_LNK_SPD_2_5G)
++ if (spd == ICE_ETH56G_LNK_SPD_1G || spd == ICE_ETH56G_LNK_SPD_2_5G) {
+ err = ice_read_gpcs_reg_eth56g(hw, port, PHY_GPCS_BITSLIP,
+ &bitslip);
+- else
+- err = ice_read_ptp_reg_eth56g(hw, port_blk,
+- PHY_REG_SD_BIT_SLIP(port_offset),
+- &bitslip);
++ } else {
++ u8 quad_lane = port % ICE_PORTS_PER_QUAD;
++ u32 addr;
++
++ addr = PHY_REG_SD_BIT_SLIP(quad_lane);
++ err = ice_read_quad_ptp_reg_eth56g(hw, port, addr, &bitslip);
++ }
+ if (err)
+ return 0;
+
+@@ -2679,8 +2734,6 @@ static void ice_ptp_init_phy_e825(struct ice_hw *hw)
+ params->onestep_ena = false;
+ params->peer_delay = 0;
+ params->sfd_ena = false;
+- params->phy_addr[0] = eth56g_phy_0;
+- params->phy_addr[1] = eth56g_phy_1;
+ params->num_phys = 2;
+ ptp->ports_per_phy = 4;
+ ptp->num_lports = params->num_phys * ptp->ports_per_phy;
+@@ -2711,10 +2764,9 @@ static void ice_fill_phy_msg_e82x(struct ice_hw *hw,
+ struct ice_sbq_msg_input *msg, u8 port,
+ u16 offset)
+ {
+- int phy_port, phy, quadtype;
++ int phy_port, quadtype;
+
+ phy_port = port % hw->ptp.ports_per_phy;
+- phy = port / hw->ptp.ports_per_phy;
+ quadtype = ICE_GET_QUAD_NUM(port) %
+ ICE_GET_QUAD_NUM(hw->ptp.ports_per_phy);
+
+@@ -2726,12 +2778,7 @@ static void ice_fill_phy_msg_e82x(struct ice_hw *hw,
+ msg->msg_addr_high = P_Q1_H(P_4_BASE + offset, phy_port);
+ }
+
+- if (phy == 0)
+- msg->dest_dev = rmn_0;
+- else if (phy == 1)
+- msg->dest_dev = rmn_1;
+- else
+- msg->dest_dev = rmn_2;
++ msg->dest_dev = rmn_0;
+ }
+
+ /**
+diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
+index 45768796691fe..479227bdff75e 100644
+--- a/drivers/net/ethernet/intel/ice/ice_type.h
++++ b/drivers/net/ethernet/intel/ice/ice_type.h
+@@ -850,7 +850,6 @@ struct ice_mbx_data {
+
+ struct ice_eth56g_params {
+ u8 num_phys;
+- u8 phy_addr[2];
+ bool onestep_ena;
+ bool sfd_ena;
+ u32 peer_delay;
+--
+2.39.5
+
--- /dev/null
+From f893b9f439504421f64e661cc1707c39aa9cde4c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 15:09:53 +0200
+Subject: ice: Introduce ice_get_phy_model() wrapper
+
+From: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
+
+[ Upstream commit 5e0776451d89eefe66b19e010e48ece1cca07e58 ]
+
+Introduce ice_get_phy_model() to improve code readability
+
+Signed-off-by: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Stable-dep-of: 258f5f905815 ("ice: Add correct PHY lane assignment")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice.h | 5 +++++
+ drivers/net/ethernet/intel/ice/ice_ptp.c | 19 +++++++++---------
+ drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 22 ++++++++++-----------
+ 3 files changed, 25 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
+index d6f80da30decf..558cda577191d 100644
+--- a/drivers/net/ethernet/intel/ice/ice.h
++++ b/drivers/net/ethernet/intel/ice/ice.h
+@@ -1047,5 +1047,10 @@ static inline void ice_clear_rdma_cap(struct ice_pf *pf)
+ clear_bit(ICE_FLAG_RDMA_ENA, pf->flags);
+ }
+
++static inline enum ice_phy_model ice_get_phy_model(const struct ice_hw *hw)
++{
++ return hw->ptp.phy_model;
++}
++
+ extern const struct xdp_metadata_ops ice_xdp_md_ops;
+ #endif /* _ICE_H_ */
+diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
+index ef2e858f49bb0..d534c8e571cee 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
+@@ -1363,7 +1363,7 @@ ice_ptp_port_phy_stop(struct ice_ptp_port *ptp_port)
+
+ mutex_lock(&ptp_port->ps_lock);
+
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_ETH56G:
+ err = ice_stop_phy_timer_eth56g(hw, port, true);
+ break;
+@@ -1409,7 +1409,7 @@ ice_ptp_port_phy_restart(struct ice_ptp_port *ptp_port)
+
+ mutex_lock(&ptp_port->ps_lock);
+
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_ETH56G:
+ err = ice_start_phy_timer_eth56g(hw, port);
+ break;
+@@ -1480,8 +1480,7 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup)
+ /* Skip HW writes if reset is in progress */
+ if (pf->hw.reset_ongoing)
+ return;
+-
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_E810:
+ /* Do not reconfigure E810 PHY */
+ return;
+@@ -1514,7 +1513,7 @@ static int ice_ptp_cfg_phy_interrupt(struct ice_pf *pf, bool ena, u32 threshold)
+
+ ice_ptp_reset_ts_memory(hw);
+
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_ETH56G: {
+ int port;
+
+@@ -1553,7 +1552,7 @@ static int ice_ptp_cfg_phy_interrupt(struct ice_pf *pf, bool ena, u32 threshold)
+ case ICE_PHY_UNSUP:
+ default:
+ dev_warn(dev, "%s: Unexpected PHY model %d\n", __func__,
+- hw->ptp.phy_model);
++ ice_get_phy_model(hw));
+ return -EOPNOTSUPP;
+ }
+ }
+@@ -2059,7 +2058,7 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts)
+ /* For Vernier mode on E82X, we need to recalibrate after new settime.
+ * Start with marking timestamps as invalid.
+ */
+- if (hw->ptp.phy_model == ICE_PHY_E82X) {
++ if (ice_get_phy_model(hw) == ICE_PHY_E82X) {
+ err = ice_ptp_clear_phy_offset_ready_e82x(hw);
+ if (err)
+ dev_warn(ice_pf_to_dev(pf), "Failed to mark timestamps as invalid before settime\n");
+@@ -2083,7 +2082,7 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts)
+ ice_ptp_enable_all_clkout(pf);
+
+ /* Recalibrate and re-enable timestamp blocks for E822/E823 */
+- if (hw->ptp.phy_model == ICE_PHY_E82X)
++ if (ice_get_phy_model(hw) == ICE_PHY_E82X)
+ ice_ptp_restart_all_phy(pf);
+ exit:
+ if (err) {
+@@ -3209,7 +3208,7 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port)
+
+ mutex_init(&ptp_port->ps_lock);
+
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_ETH56G:
+ return ice_ptp_init_tx_eth56g(pf, &ptp_port->tx,
+ ptp_port->port_num);
+@@ -3307,7 +3306,7 @@ static void ice_ptp_remove_auxbus_device(struct ice_pf *pf)
+ */
+ static void ice_ptp_init_tx_interrupt_mode(struct ice_pf *pf)
+ {
+- switch (pf->hw.ptp.phy_model) {
++ switch (ice_get_phy_model(&pf->hw)) {
+ case ICE_PHY_E82X:
+ /* E822 based PHY has the clock owner process the interrupt
+ * for all ports.
+diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+index 64c36620a02f3..28bd4815ebcf3 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+@@ -804,7 +804,7 @@ static u32 ice_ptp_tmr_cmd_to_port_reg(struct ice_hw *hw,
+ /* Certain hardware families share the same register values for the
+ * port register and source timer register.
+ */
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_E810:
+ return ice_ptp_tmr_cmd_to_src_reg(hw, cmd) & TS_CMD_MASK_E810;
+ default:
+@@ -5461,7 +5461,7 @@ void ice_ptp_init_hw(struct ice_hw *hw)
+ static int ice_ptp_write_port_cmd(struct ice_hw *hw, u8 port,
+ enum ice_ptp_tmr_cmd cmd)
+ {
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_ETH56G:
+ return ice_ptp_write_port_cmd_eth56g(hw, port, cmd);
+ case ICE_PHY_E82X:
+@@ -5526,7 +5526,7 @@ static int ice_ptp_port_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
+ u32 port;
+
+ /* PHY models which can program all ports simultaneously */
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_E810:
+ return ice_ptp_port_cmd_e810(hw, cmd);
+ default:
+@@ -5605,7 +5605,7 @@ int ice_ptp_init_time(struct ice_hw *hw, u64 time)
+
+ /* PHY timers */
+ /* Fill Rx and Tx ports and send msg to PHY */
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_ETH56G:
+ err = ice_ptp_prep_phy_time_eth56g(hw,
+ (u32)(time & 0xFFFFFFFF));
+@@ -5651,7 +5651,7 @@ int ice_ptp_write_incval(struct ice_hw *hw, u64 incval)
+ wr32(hw, GLTSYN_SHADJ_L(tmr_idx), lower_32_bits(incval));
+ wr32(hw, GLTSYN_SHADJ_H(tmr_idx), upper_32_bits(incval));
+
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_ETH56G:
+ err = ice_ptp_prep_phy_incval_eth56g(hw, incval);
+ break;
+@@ -5720,7 +5720,7 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj)
+ wr32(hw, GLTSYN_SHADJ_L(tmr_idx), 0);
+ wr32(hw, GLTSYN_SHADJ_H(tmr_idx), adj);
+
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_ETH56G:
+ err = ice_ptp_prep_phy_adj_eth56g(hw, adj);
+ break;
+@@ -5753,7 +5753,7 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj)
+ */
+ int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp)
+ {
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_ETH56G:
+ return ice_read_ptp_tstamp_eth56g(hw, block, idx, tstamp);
+ case ICE_PHY_E810:
+@@ -5783,7 +5783,7 @@ 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)
+ {
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_ETH56G:
+ return ice_clear_ptp_tstamp_eth56g(hw, block, idx);
+ case ICE_PHY_E810:
+@@ -5846,7 +5846,7 @@ static int ice_get_pf_c827_idx(struct ice_hw *hw, u8 *idx)
+ */
+ void ice_ptp_reset_ts_memory(struct ice_hw *hw)
+ {
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_ETH56G:
+ ice_ptp_reset_ts_memory_eth56g(hw);
+ break;
+@@ -5875,7 +5875,7 @@ int ice_ptp_init_phc(struct ice_hw *hw)
+ /* Clear event err indications for auxiliary pins */
+ (void)rd32(hw, GLTSYN_STAT(src_idx));
+
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_ETH56G:
+ return ice_ptp_init_phc_eth56g(hw);
+ case ICE_PHY_E810:
+@@ -5900,7 +5900,7 @@ int ice_ptp_init_phc(struct ice_hw *hw)
+ */
+ int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready)
+ {
+- switch (hw->ptp.phy_model) {
++ switch (ice_get_phy_model(hw)) {
+ case ICE_PHY_ETH56G:
+ return ice_get_phy_tx_tstamp_ready_eth56g(hw, block,
+ tstamp_ready);
+--
+2.39.5
+
--- /dev/null
+From 13950ae904c8b1b0bb82b6f65485d3a701716110 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Aug 2024 15:09:56 +0200
+Subject: ice: Use ice_adapter for PTP shared data instead of auxdev
+
+From: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
+
+[ Upstream commit e800654e85b5b27966fc6493201f5f8cf658beb6 ]
+
+Use struct ice_adapter to hold shared PTP data and control PTP
+related actions instead of auxbus. This allows significant code
+simplification and faster access to the container fields used in
+the PTP support code.
+
+Move the PTP port list to the ice_adapter container to simplify
+the code and avoid race conditions which could occur due to the
+synchronous nature of the initialization/access and
+certain memory saving can be achieved by moving PTP data into
+the ice_adapter itself.
+
+Signed-off-by: Sergey Temerkhanov <sergey.temerkhanov@intel.com>
+Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Stable-dep-of: 258f5f905815 ("ice: Add correct PHY lane assignment")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/ice/ice_adapter.c | 6 +
+ drivers/net/ethernet/intel/ice/ice_adapter.h | 17 +++
+ drivers/net/ethernet/intel/ice/ice_ptp.c | 115 ++++++++++++-------
+ drivers/net/ethernet/intel/ice/ice_ptp.h | 5 +-
+ drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 5 +
+ 5 files changed, 105 insertions(+), 43 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.c b/drivers/net/ethernet/intel/ice/ice_adapter.c
+index ad84d8ad49a63..f3e195974a8ef 100644
+--- a/drivers/net/ethernet/intel/ice/ice_adapter.c
++++ b/drivers/net/ethernet/intel/ice/ice_adapter.c
+@@ -40,11 +40,17 @@ static struct ice_adapter *ice_adapter_new(void)
+ spin_lock_init(&adapter->ptp_gltsyn_time_lock);
+ refcount_set(&adapter->refcount, 1);
+
++ mutex_init(&adapter->ports.lock);
++ INIT_LIST_HEAD(&adapter->ports.ports);
++
+ return adapter;
+ }
+
+ static void ice_adapter_free(struct ice_adapter *adapter)
+ {
++ WARN_ON(!list_empty(&adapter->ports.ports));
++ mutex_destroy(&adapter->ports.lock);
++
+ kfree(adapter);
+ }
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_adapter.h b/drivers/net/ethernet/intel/ice/ice_adapter.h
+index eb7cac01c2427..e233225848b38 100644
+--- a/drivers/net/ethernet/intel/ice/ice_adapter.h
++++ b/drivers/net/ethernet/intel/ice/ice_adapter.h
+@@ -4,18 +4,34 @@
+ #ifndef _ICE_ADAPTER_H_
+ #define _ICE_ADAPTER_H_
+
++#include <linux/types.h>
+ #include <linux/spinlock_types.h>
+ #include <linux/refcount_types.h>
+
+ struct pci_dev;
+ struct ice_pf;
+
++/**
++ * struct ice_port_list - data used to store the list of adapter ports
++ *
++ * This structure contains data used to maintain a list of adapter ports
++ *
++ * @ports: list of ports
++ * @lock: protect access to the ports list
++ */
++struct ice_port_list {
++ struct list_head ports;
++ /* To synchronize the ports list operations */
++ struct mutex lock;
++};
++
+ /**
+ * struct ice_adapter - PCI adapter resources shared across PFs
+ * @ptp_gltsyn_time_lock: Spinlock protecting access to the GLTSYN_TIME
+ * register of the PTP clock.
+ * @refcount: Reference count. struct ice_pf objects hold the references.
+ * @ctrl_pf: Control PF of the adapter
++ * @ports: Ports list
+ */
+ struct ice_adapter {
+ refcount_t refcount;
+@@ -23,6 +39,7 @@ struct ice_adapter {
+ spinlock_t ptp_gltsyn_time_lock;
+
+ struct ice_pf *ctrl_pf;
++ struct ice_port_list ports;
+ };
+
+ struct ice_adapter *ice_adapter_get(const struct pci_dev *pdev);
+diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
+index 2fb73ab41bc20..0b3dd87a331c7 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
++++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
+@@ -21,7 +21,7 @@ static struct ice_pf *ice_get_ctrl_pf(struct ice_pf *pf)
+ return !pf->adapter ? NULL : pf->adapter->ctrl_pf;
+ }
+
+-static __maybe_unused struct ice_ptp *ice_get_ctrl_ptp(struct ice_pf *pf)
++static struct ice_ptp *ice_get_ctrl_ptp(struct ice_pf *pf)
+ {
+ struct ice_pf *ctrl_pf = ice_get_ctrl_pf(pf);
+
+@@ -812,8 +812,8 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf)
+ struct ice_ptp_port *port;
+ unsigned int i;
+
+- mutex_lock(&pf->ptp.ports_owner.lock);
+- list_for_each_entry(port, &pf->ptp.ports_owner.ports, list_member) {
++ mutex_lock(&pf->adapter->ports.lock);
++ list_for_each_entry(port, &pf->adapter->ports.ports, list_node) {
+ struct ice_ptp_tx *tx = &port->tx;
+
+ if (!tx || !tx->init)
+@@ -821,7 +821,7 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf)
+
+ ice_ptp_process_tx_tstamp(tx);
+ }
+- mutex_unlock(&pf->ptp.ports_owner.lock);
++ mutex_unlock(&pf->adapter->ports.lock);
+
+ for (i = 0; i < ICE_GET_QUAD_NUM(pf->hw.ptp.num_lports); i++) {
+ u64 tstamp_ready;
+@@ -986,7 +986,7 @@ ice_ptp_flush_all_tx_tracker(struct ice_pf *pf)
+ {
+ struct ice_ptp_port *port;
+
+- list_for_each_entry(port, &pf->ptp.ports_owner.ports, list_member)
++ list_for_each_entry(port, &pf->adapter->ports.ports, list_node)
+ ice_ptp_flush_tx_tracker(ptp_port_to_pf(port), &port->tx);
+ }
+
+@@ -1586,10 +1586,10 @@ static void ice_ptp_restart_all_phy(struct ice_pf *pf)
+ {
+ struct list_head *entry;
+
+- list_for_each(entry, &pf->ptp.ports_owner.ports) {
++ list_for_each(entry, &pf->adapter->ports.ports) {
+ struct ice_ptp_port *port = list_entry(entry,
+ struct ice_ptp_port,
+- list_member);
++ list_node);
+
+ if (port->link_up)
+ ice_ptp_port_phy_restart(port);
+@@ -2906,6 +2906,50 @@ void ice_ptp_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
+ dev_err(ice_pf_to_dev(pf), "PTP reset failed %d\n", err);
+ }
+
++static bool ice_is_primary(struct ice_hw *hw)
++{
++ return ice_is_e825c(hw) && ice_is_dual(hw) ?
++ !!(hw->dev_caps.nac_topo.mode & ICE_NAC_TOPO_PRIMARY_M) : true;
++}
++
++static int ice_ptp_setup_adapter(struct ice_pf *pf)
++{
++ if (!ice_pf_src_tmr_owned(pf) || !ice_is_primary(&pf->hw))
++ return -EPERM;
++
++ pf->adapter->ctrl_pf = pf;
++
++ return 0;
++}
++
++static int ice_ptp_setup_pf(struct ice_pf *pf)
++{
++ struct ice_ptp *ctrl_ptp = ice_get_ctrl_ptp(pf);
++ struct ice_ptp *ptp = &pf->ptp;
++
++ if (WARN_ON(!ctrl_ptp) || ice_get_phy_model(&pf->hw) == ICE_PHY_UNSUP)
++ return -ENODEV;
++
++ INIT_LIST_HEAD(&ptp->port.list_node);
++ mutex_lock(&pf->adapter->ports.lock);
++
++ list_add(&ptp->port.list_node,
++ &pf->adapter->ports.ports);
++ mutex_unlock(&pf->adapter->ports.lock);
++
++ return 0;
++}
++
++static void ice_ptp_cleanup_pf(struct ice_pf *pf)
++{
++ struct ice_ptp *ptp = &pf->ptp;
++
++ if (ice_get_phy_model(&pf->hw) != ICE_PHY_UNSUP) {
++ mutex_lock(&pf->adapter->ports.lock);
++ list_del(&ptp->port.list_node);
++ mutex_unlock(&pf->adapter->ports.lock);
++ }
++}
+ /**
+ * ice_ptp_aux_dev_to_aux_pf - Get auxiliary PF handle for the auxiliary device
+ * @aux_dev: auxiliary device to get the auxiliary PF for
+@@ -2957,9 +3001,9 @@ static int ice_ptp_auxbus_probe(struct auxiliary_device *aux_dev,
+ if (WARN_ON(!owner_pf))
+ return -ENODEV;
+
+- INIT_LIST_HEAD(&aux_pf->ptp.port.list_member);
++ INIT_LIST_HEAD(&aux_pf->ptp.port.list_node);
+ mutex_lock(&owner_pf->ptp.ports_owner.lock);
+- list_add(&aux_pf->ptp.port.list_member,
++ list_add(&aux_pf->ptp.port.list_node,
+ &owner_pf->ptp.ports_owner.ports);
+ mutex_unlock(&owner_pf->ptp.ports_owner.lock);
+
+@@ -2976,7 +3020,7 @@ static void ice_ptp_auxbus_remove(struct auxiliary_device *aux_dev)
+ struct ice_pf *aux_pf = ice_ptp_aux_dev_to_aux_pf(aux_dev);
+
+ mutex_lock(&owner_pf->ptp.ports_owner.lock);
+- list_del(&aux_pf->ptp.port.list_member);
++ list_del(&aux_pf->ptp.port.list_node);
+ mutex_unlock(&owner_pf->ptp.ports_owner.lock);
+ }
+
+@@ -3036,7 +3080,7 @@ ice_ptp_auxbus_create_id_table(struct ice_pf *pf, const char *name)
+ * ice_ptp_register_auxbus_driver - Register PTP auxiliary bus driver
+ * @pf: Board private structure
+ */
+-static int ice_ptp_register_auxbus_driver(struct ice_pf *pf)
++static int __always_unused ice_ptp_register_auxbus_driver(struct ice_pf *pf)
+ {
+ struct auxiliary_driver *aux_driver;
+ struct ice_ptp *ptp;
+@@ -3079,7 +3123,7 @@ static int ice_ptp_register_auxbus_driver(struct ice_pf *pf)
+ * ice_ptp_unregister_auxbus_driver - Unregister PTP auxiliary bus driver
+ * @pf: Board private structure
+ */
+-static void ice_ptp_unregister_auxbus_driver(struct ice_pf *pf)
++static void __always_unused ice_ptp_unregister_auxbus_driver(struct ice_pf *pf)
+ {
+ struct auxiliary_driver *aux_driver = &pf->ptp.ports_owner.aux_driver;
+
+@@ -3098,15 +3142,12 @@ static void ice_ptp_unregister_auxbus_driver(struct ice_pf *pf)
+ */
+ int ice_ptp_clock_index(struct ice_pf *pf)
+ {
+- struct auxiliary_device *aux_dev;
+- struct ice_pf *owner_pf;
++ struct ice_ptp *ctrl_ptp = ice_get_ctrl_ptp(pf);
+ struct ptp_clock *clock;
+
+- aux_dev = &pf->ptp.port.aux_dev;
+- owner_pf = ice_ptp_aux_dev_to_owner_pf(aux_dev);
+- if (!owner_pf)
++ if (!ctrl_ptp)
+ return -1;
+- clock = owner_pf->ptp.clock;
++ clock = ctrl_ptp->clock;
+
+ return clock ? ptp_clock_index(clock) : -1;
+ }
+@@ -3166,15 +3207,7 @@ static int ice_ptp_init_owner(struct ice_pf *pf)
+ if (err)
+ goto err_clk;
+
+- err = ice_ptp_register_auxbus_driver(pf);
+- if (err) {
+- dev_err(ice_pf_to_dev(pf), "Failed to register PTP auxbus driver");
+- goto err_aux;
+- }
+-
+ return 0;
+-err_aux:
+- ptp_clock_unregister(pf->ptp.clock);
+ err_clk:
+ pf->ptp.clock = NULL;
+ err_exit:
+@@ -3250,7 +3283,7 @@ static void ice_ptp_release_auxbus_device(struct device *dev)
+ * ice_ptp_create_auxbus_device - Create PTP auxiliary bus device
+ * @pf: Board private structure
+ */
+-static int ice_ptp_create_auxbus_device(struct ice_pf *pf)
++static __always_unused int ice_ptp_create_auxbus_device(struct ice_pf *pf)
+ {
+ struct auxiliary_device *aux_dev;
+ struct ice_ptp *ptp;
+@@ -3297,7 +3330,7 @@ static int ice_ptp_create_auxbus_device(struct ice_pf *pf)
+ * ice_ptp_remove_auxbus_device - Remove PTP auxiliary bus device
+ * @pf: Board private structure
+ */
+-static void ice_ptp_remove_auxbus_device(struct ice_pf *pf)
++static __always_unused void ice_ptp_remove_auxbus_device(struct ice_pf *pf)
+ {
+ struct auxiliary_device *aux_dev = &pf->ptp.port.aux_dev;
+
+@@ -3361,19 +3394,26 @@ void ice_ptp_init(struct ice_pf *pf)
+ /* If this function owns the clock hardware, it must allocate and
+ * configure the PTP clock device to represent it.
+ */
+- if (ice_pf_src_tmr_owned(pf)) {
++ if (ice_pf_src_tmr_owned(pf) && ice_is_primary(hw)) {
++ err = ice_ptp_setup_adapter(pf);
++ if (err)
++ goto err_exit;
+ err = ice_ptp_init_owner(pf);
+ if (err)
+- goto err;
++ goto err_exit;
+ }
+
++ err = ice_ptp_setup_pf(pf);
++ if (err)
++ goto err_exit;
++
+ ptp->port.port_num = hw->pf_id;
+ if (ice_is_e825c(hw) && hw->ptp.is_2x50g_muxed_topo)
+ ptp->port.port_num = hw->pf_id * 2;
+
+ err = ice_ptp_init_port(pf, &ptp->port);
+ if (err)
+- goto err;
++ goto err_exit;
+
+ /* Start the PHY timestamping block */
+ ice_ptp_reset_phy_timestamping(pf);
+@@ -3381,20 +3421,16 @@ void ice_ptp_init(struct ice_pf *pf)
+ /* Configure initial Tx interrupt settings */
+ ice_ptp_cfg_tx_interrupt(pf);
+
+- err = ice_ptp_create_auxbus_device(pf);
+- if (err)
+- goto err;
+-
+ ptp->state = ICE_PTP_READY;
+
+ err = ice_ptp_init_work(pf, ptp);
+ if (err)
+- goto err;
++ goto err_exit;
+
+ dev_info(ice_pf_to_dev(pf), "PTP init successful\n");
+ return;
+
+-err:
++err_exit:
+ /* If we registered a PTP clock, release it */
+ if (pf->ptp.clock) {
+ ptp_clock_unregister(ptp->clock);
+@@ -3421,7 +3457,7 @@ void ice_ptp_release(struct ice_pf *pf)
+ /* Disable timestamping for both Tx and Rx */
+ ice_ptp_disable_timestamp_mode(pf);
+
+- ice_ptp_remove_auxbus_device(pf);
++ ice_ptp_cleanup_pf(pf);
+
+ ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
+
+@@ -3436,9 +3472,6 @@ void ice_ptp_release(struct ice_pf *pf)
+ pf->ptp.kworker = NULL;
+ }
+
+- if (ice_pf_src_tmr_owned(pf))
+- ice_ptp_unregister_auxbus_driver(pf);
+-
+ if (!pf->ptp.clock)
+ return;
+
+diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h
+index 2db2257a0fb2f..5615efc42c624 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
++++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
+@@ -169,7 +169,7 @@ struct ice_ptp_tx {
+ * ready for PTP functionality. It is used to track the port initialization
+ * and determine when the port's PHY offset is valid.
+ *
+- * @list_member: list member structure of auxiliary device
++ * @list_node: list member structure
+ * @tx: Tx timestamp tracking for this port
+ * @aux_dev: auxiliary device associated with this port
+ * @ov_work: delayed work task for tracking when PHY offset is valid
+@@ -179,7 +179,7 @@ struct ice_ptp_tx {
+ * @port_num: the port number this structure represents
+ */
+ struct ice_ptp_port {
+- struct list_head list_member;
++ struct list_head list_node;
+ struct ice_ptp_tx tx;
+ struct auxiliary_device aux_dev;
+ struct kthread_delayed_work ov_work;
+@@ -205,6 +205,7 @@ enum ice_ptp_tx_interrupt {
+ * @ports: list of porst handled by this port owner
+ * @lock: protect access to ports list
+ */
++
+ struct ice_ptp_port_owner {
+ struct auxiliary_driver aux_driver;
+ struct list_head ports;
+diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
+index 4c8b845713442..3499062218b59 100644
+--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
++++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
+@@ -452,6 +452,11 @@ static inline u64 ice_get_base_incval(struct ice_hw *hw)
+ }
+ }
+
++static inline bool ice_is_dual(struct ice_hw *hw)
++{
++ return !!(hw->dev_caps.nac_topo.mode & ICE_NAC_TOPO_DUAL_M);
++}
++
+ #define PFTSYN_SEM_BYTES 4
+
+ #define ICE_PTP_CLOCK_INDEX_0 0x00
+--
+2.39.5
+
--- /dev/null
+From 08066a194d4b435268fe89c571c760b35b657dc9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Jan 2025 22:54:33 +0530
+Subject: net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()
+
+From: Sudheer Kumar Doredla <s-doredla@ti.com>
+
+[ Upstream commit 03d120f27d050336f7e7d21879891542c4741f81 ]
+
+CPSW ALE has 75-bit ALE entries stored across three 32-bit words.
+The cpsw_ale_get_field() and cpsw_ale_set_field() functions support
+ALE field entries spanning up to two words at the most.
+
+The cpsw_ale_get_field() and cpsw_ale_set_field() functions work as
+expected when ALE field spanned across word1 and word2, but fails when
+ALE field spanned across word2 and word3.
+
+For example, while reading the ALE field spanned across word2 and word3
+(i.e. bits 62 to 64), the word3 data shifted to an incorrect position
+due to the index becoming zero while flipping.
+The same issue occurred when setting an ALE entry.
+
+This issue has not been seen in practice but will be an issue in the future
+if the driver supports accessing ALE fields spanning word2 and word3
+
+Fix the methods to handle getting/setting fields spanning up to two words.
+
+Fixes: b685f1a58956 ("net: ethernet: ti: cpsw_ale: Fix cpsw_ale_get_field()/cpsw_ale_set_field()")
+Signed-off-by: Sudheer Kumar Doredla <s-doredla@ti.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Roger Quadros <rogerq@kernel.org>
+Reviewed-by: Siddharth Vadapalli <s-vadapalli@ti.com>
+Link: https://patch.msgid.link/20250108172433.311694-1-s-doredla@ti.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/ti/cpsw_ale.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
+index 8d02d2b214293..dc5e247ca5d1a 100644
+--- a/drivers/net/ethernet/ti/cpsw_ale.c
++++ b/drivers/net/ethernet/ti/cpsw_ale.c
+@@ -127,15 +127,15 @@ struct cpsw_ale_dev_id {
+
+ static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
+ {
+- int idx, idx2;
++ int idx, idx2, index;
+ u32 hi_val = 0;
+
+ idx = start / 32;
+ idx2 = (start + bits - 1) / 32;
+ /* Check if bits to be fetched exceed a word */
+ if (idx != idx2) {
+- idx2 = 2 - idx2; /* flip */
+- hi_val = ale_entry[idx2] << ((idx2 * 32) - start);
++ index = 2 - idx2; /* flip */
++ hi_val = ale_entry[index] << ((idx2 * 32) - start);
+ }
+ start -= idx * 32;
+ idx = 2 - idx; /* flip */
+@@ -145,16 +145,16 @@ static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
+ static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
+ u32 value)
+ {
+- int idx, idx2;
++ int idx, idx2, index;
+
+ value &= BITMASK(bits);
+ idx = start / 32;
+ idx2 = (start + bits - 1) / 32;
+ /* Check if bits to be set exceed a word */
+ if (idx != idx2) {
+- idx2 = 2 - idx2; /* flip */
+- ale_entry[idx2] &= ~(BITMASK(bits + start - (idx2 * 32)));
+- ale_entry[idx2] |= (value >> ((idx2 * 32) - start));
++ index = 2 - idx2; /* flip */
++ ale_entry[index] &= ~(BITMASK(bits + start - (idx2 * 32)));
++ ale_entry[index] |= (value >> ((idx2 * 32) - start));
+ }
+ start -= idx * 32;
+ idx = 2 - idx; /* flip */
+--
+2.39.5
+
--- /dev/null
+From 7c38868fc6519ce1066b30e5a4bda7acdb32b298 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 10:48:45 -0500
+Subject: net: fec: handle page_pool_dev_alloc_pages error
+
+From: Kevin Groeneveld <kgroeneveld@lenbrook.com>
+
+[ Upstream commit 001ba0902046cb6c352494df610718c0763e77a5 ]
+
+The fec_enet_update_cbd function calls page_pool_dev_alloc_pages but did
+not handle the case when it returned NULL. There was a WARN_ON(!new_page)
+but it would still proceed to use the NULL pointer and then crash.
+
+This case does seem somewhat rare but when the system is under memory
+pressure it can happen. One case where I can duplicate this with some
+frequency is when writing over a smbd share to a SATA HDD attached to an
+imx6q.
+
+Setting /proc/sys/vm/min_free_kbytes to higher values also seems to solve
+the problem for my test case. But it still seems wrong that the fec driver
+ignores the memory allocation error and can crash.
+
+This commit handles the allocation error by dropping the current packet.
+
+Fixes: 95698ff6177b5 ("net: fec: using page pool to manage RX buffers")
+Signed-off-by: Kevin Groeneveld <kgroeneveld@lenbrook.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Reviewed-by: Wei Fang <wei.fang@nxp.com>
+Link: https://patch.msgid.link/20250113154846.1765414-1-kgroeneveld@lenbrook.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fec_main.c | 19 ++++++++++++++-----
+ 1 file changed, 14 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
+index 9d9fcec41488e..49d1748e0c043 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -1591,19 +1591,22 @@ static void fec_enet_tx(struct net_device *ndev, int budget)
+ fec_enet_tx_queue(ndev, i, budget);
+ }
+
+-static void fec_enet_update_cbd(struct fec_enet_priv_rx_q *rxq,
++static int fec_enet_update_cbd(struct fec_enet_priv_rx_q *rxq,
+ struct bufdesc *bdp, int index)
+ {
+ struct page *new_page;
+ dma_addr_t phys_addr;
+
+ new_page = page_pool_dev_alloc_pages(rxq->page_pool);
+- WARN_ON(!new_page);
+- rxq->rx_skb_info[index].page = new_page;
++ if (unlikely(!new_page))
++ return -ENOMEM;
+
++ rxq->rx_skb_info[index].page = new_page;
+ rxq->rx_skb_info[index].offset = FEC_ENET_XDP_HEADROOM;
+ phys_addr = page_pool_get_dma_addr(new_page) + FEC_ENET_XDP_HEADROOM;
+ bdp->cbd_bufaddr = cpu_to_fec32(phys_addr);
++
++ return 0;
+ }
+
+ static u32
+@@ -1698,6 +1701,7 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
+ int cpu = smp_processor_id();
+ struct xdp_buff xdp;
+ struct page *page;
++ __fec32 cbd_bufaddr;
+ u32 sub_len = 4;
+
+ #if !defined(CONFIG_M5272)
+@@ -1766,12 +1770,17 @@ fec_enet_rx_queue(struct net_device *ndev, int budget, u16 queue_id)
+
+ index = fec_enet_get_bd_index(bdp, &rxq->bd);
+ page = rxq->rx_skb_info[index].page;
++ cbd_bufaddr = bdp->cbd_bufaddr;
++ if (fec_enet_update_cbd(rxq, bdp, index)) {
++ ndev->stats.rx_dropped++;
++ goto rx_processing_done;
++ }
++
+ dma_sync_single_for_cpu(&fep->pdev->dev,
+- fec32_to_cpu(bdp->cbd_bufaddr),
++ fec32_to_cpu(cbd_bufaddr),
+ pkt_len,
+ DMA_FROM_DEVICE);
+ prefetch(page_address(page));
+- fec_enet_update_cbd(rxq, bdp, index);
+
+ if (xdp_prog) {
+ xdp_buff_clear_frags_flag(&xdp);
+--
+2.39.5
+
--- /dev/null
+From 1cfae25c3112fee653b469824140de68e4fb7d26 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 Jan 2025 14:06:22 -0800
+Subject: net: make page_pool_ref_netmem work with net iovs
+
+From: Pavel Begunkov <asml.silence@gmail.com>
+
+[ Upstream commit cbc16bceea784210d585a42ac9f8f10ce62b300e ]
+
+page_pool_ref_netmem() should work with either netmem representation, but
+currently it casts to a page with netmem_to_page(), which will fail with
+net iovs. Use netmem_get_pp_ref_count_ref() instead.
+
+Fixes: 8ab79ed50cf1 ("page_pool: devmem support")
+Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
+Signed-off-by: David Wei <dw@davidwei.uk>
+Link: https://lore.kernel.org/20250108220644.3528845-2-dw@davidwei.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/page_pool/helpers.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/include/net/page_pool/helpers.h b/include/net/page_pool/helpers.h
+index 793e6fd78bc5c..60a5347922bec 100644
+--- a/include/net/page_pool/helpers.h
++++ b/include/net/page_pool/helpers.h
+@@ -294,7 +294,7 @@ static inline long page_pool_unref_page(struct page *page, long nr)
+
+ static inline void page_pool_ref_netmem(netmem_ref netmem)
+ {
+- atomic_long_inc(&netmem_to_page(netmem)->pp_ref_count);
++ atomic_long_inc(netmem_get_pp_ref_count_ref(netmem));
+ }
+
+ static inline void page_pool_ref_page(struct page *page)
+--
+2.39.5
+
--- /dev/null
+From c1cb7d99d032c187b2fea5a32b3c8f09741c9c58 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jan 2025 13:39:07 +0200
+Subject: net/mlx5: Clear port select structure when fail to create
+
+From: Mark Zhang <markzhang@nvidia.com>
+
+[ Upstream commit 5641e82cb55b4ecbc6366a499300917d2f3e6790 ]
+
+Clear the port select structure on error so no stale values left after
+definers are destroyed. That's because the mlx5_lag_destroy_definers()
+always try to destroy all lag definers in the tt_map, so in the flow
+below lag definers get double-destroyed and cause kernel crash:
+
+ mlx5_lag_port_sel_create()
+ mlx5_lag_create_definers()
+ mlx5_lag_create_definer() <- Failed on tt 1
+ mlx5_lag_destroy_definers() <- definers[tt=0] gets destroyed
+ mlx5_lag_port_sel_create()
+ mlx5_lag_create_definers()
+ mlx5_lag_create_definer() <- Failed on tt 0
+ mlx5_lag_destroy_definers() <- definers[tt=0] gets double-destroyed
+
+ Unable to handle kernel NULL pointer dereference at virtual address 0000000000000008
+ Mem abort info:
+ ESR = 0x0000000096000005
+ EC = 0x25: DABT (current EL), IL = 32 bits
+ SET = 0, FnV = 0
+ EA = 0, S1PTW = 0
+ FSC = 0x05: level 1 translation fault
+ Data abort info:
+ ISV = 0, ISS = 0x00000005, ISS2 = 0x00000000
+ CM = 0, WnR = 0, TnD = 0, TagAccess = 0
+ GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
+ user pgtable: 64k pages, 48-bit VAs, pgdp=0000000112ce2e00
+ [0000000000000008] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000
+ Internal error: Oops: 0000000096000005 [#1] PREEMPT SMP
+ Modules linked in: iptable_raw bonding ip_gre ip6_gre gre ip6_tunnel tunnel6 geneve ip6_udp_tunnel udp_tunnel ipip tunnel4 ip_tunnel rdma_ucm(OE) rdma_cm(OE) iw_cm(OE) ib_ipoib(OE) ib_cm(OE) ib_umad(OE) mlx5_ib(OE) ib_uverbs(OE) mlx5_fwctl(OE) fwctl(OE) mlx5_core(OE) mlxdevm(OE) ib_core(OE) mlxfw(OE) memtrack(OE) mlx_compat(OE) openvswitch nsh nf_conncount psample xt_conntrack xt_MASQUERADE nf_conntrack_netlink nfnetlink xfrm_user xfrm_algo xt_addrtype iptable_filter iptable_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 br_netfilter bridge stp llc netconsole overlay efi_pstore sch_fq_codel zram ip_tables crct10dif_ce qemu_fw_cfg fuse ipv6 crc_ccitt [last unloaded: mlx_compat(OE)]
+ CPU: 3 UID: 0 PID: 217 Comm: kworker/u53:2 Tainted: G OE 6.11.0+ #2
+ Tainted: [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
+ Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
+ Workqueue: mlx5_lag mlx5_do_bond_work [mlx5_core]
+ pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+ pc : mlx5_del_flow_rules+0x24/0x2c0 [mlx5_core]
+ lr : mlx5_lag_destroy_definer+0x54/0x100 [mlx5_core]
+ sp : ffff800085fafb00
+ x29: ffff800085fafb00 x28: ffff0000da0c8000 x27: 0000000000000000
+ x26: ffff0000da0c8000 x25: ffff0000da0c8000 x24: ffff0000da0c8000
+ x23: ffff0000c31f81a0 x22: 0400000000000000 x21: ffff0000da0c8000
+ x20: 0000000000000000 x19: 0000000000000001 x18: 0000000000000000
+ x17: 0000000000000000 x16: 0000000000000000 x15: 0000ffff8b0c9350
+ x14: 0000000000000000 x13: ffff800081390d18 x12: ffff800081dc3cc0
+ x11: 0000000000000001 x10: 0000000000000b10 x9 : ffff80007ab7304c
+ x8 : ffff0000d00711f0 x7 : 0000000000000004 x6 : 0000000000000190
+ x5 : ffff00027edb3010 x4 : 0000000000000000 x3 : 0000000000000000
+ x2 : ffff0000d39b8000 x1 : ffff0000d39b8000 x0 : 0400000000000000
+ Call trace:
+ mlx5_del_flow_rules+0x24/0x2c0 [mlx5_core]
+ mlx5_lag_destroy_definer+0x54/0x100 [mlx5_core]
+ mlx5_lag_destroy_definers+0xa0/0x108 [mlx5_core]
+ mlx5_lag_port_sel_create+0x2d4/0x6f8 [mlx5_core]
+ mlx5_activate_lag+0x60c/0x6f8 [mlx5_core]
+ mlx5_do_bond_work+0x284/0x5c8 [mlx5_core]
+ process_one_work+0x170/0x3e0
+ worker_thread+0x2d8/0x3e0
+ kthread+0x11c/0x128
+ ret_from_fork+0x10/0x20
+ Code: a9025bf5 aa0003f6 a90363f7 f90023f9 (f9400400)
+ ---[ end trace 0000000000000000 ]---
+
+Fixes: dc48516ec7d3 ("net/mlx5: Lag, add support to create definers for LAG")
+Signed-off-by: Mark Zhang <markzhang@nvidia.com>
+Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
+Reviewed-by: Mark Bloch <mbloch@nvidia.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
+index ab2717012b79b..39e80704b1c42 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
+@@ -530,7 +530,7 @@ int mlx5_lag_port_sel_create(struct mlx5_lag *ldev,
+ set_tt_map(port_sel, hash_type);
+ err = mlx5_lag_create_definers(ldev, hash_type, ports);
+ if (err)
+- return err;
++ goto clear_port_sel;
+
+ if (port_sel->tunnel) {
+ err = mlx5_lag_create_inner_ttc_table(ldev);
+@@ -549,6 +549,8 @@ int mlx5_lag_port_sel_create(struct mlx5_lag *ldev,
+ mlx5_destroy_ttc_table(port_sel->inner.ttc);
+ destroy_definers:
+ mlx5_lag_destroy_definers(ldev);
++clear_port_sel:
++ memset(port_sel, 0, sizeof(*port_sel));
+ return err;
+ }
+
+--
+2.39.5
+
--- /dev/null
+From 8ad0d10eec030a9460c1d4ca779ae6b39445d0ca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jan 2025 13:39:05 +0200
+Subject: net/mlx5: Fix a lockdep warning as part of the write combining test
+
+From: Yishai Hadas <yishaih@nvidia.com>
+
+[ Upstream commit 1b10a519a45704d4b06ebd9245b272d145752c18 ]
+
+Fix a lockdep warning [1] observed during the write combining test.
+
+The warning indicates a potential nested lock scenario that could lead
+to a deadlock.
+
+However, this is a false positive alarm because the SF lock and its
+parent lock are distinct ones.
+
+The lockdep confusion arises because the locks belong to the same object
+class (i.e., struct mlx5_core_dev).
+
+To resolve this, the code has been refactored to avoid taking both
+locks. Instead, only the parent lock is acquired.
+
+[1]
+raw_ethernet_bw/2118 is trying to acquire lock:
+[ 213.619032] ffff88811dd75e08 (&dev->wc_state_lock){+.+.}-{3:3}, at:
+ mlx5_wc_support_get+0x18c/0x210 [mlx5_core]
+[ 213.620270]
+[ 213.620270] but task is already holding lock:
+[ 213.620943] ffff88810b585e08 (&dev->wc_state_lock){+.+.}-{3:3}, at:
+ mlx5_wc_support_get+0x10c/0x210 [mlx5_core]
+[ 213.622045]
+[ 213.622045] other info that might help us debug this:
+[ 213.622778] Possible unsafe locking scenario:
+[ 213.622778]
+[ 213.623465] CPU0
+[ 213.623815] ----
+[ 213.624148] lock(&dev->wc_state_lock);
+[ 213.624615] lock(&dev->wc_state_lock);
+[ 213.625071]
+[ 213.625071] *** DEADLOCK ***
+[ 213.625071]
+[ 213.625805] May be due to missing lock nesting notation
+[ 213.625805]
+[ 213.626522] 4 locks held by raw_ethernet_bw/2118:
+[ 213.627019] #0: ffff88813f80d578 (&uverbs_dev->disassociate_srcu){.+.+}-{0:0},
+ at: ib_uverbs_ioctl+0xc4/0x170 [ib_uverbs]
+[ 213.628088] #1: ffff88810fb23930 (&file->hw_destroy_rwsem){.+.+}-{3:3},
+ at: ib_init_ucontext+0x2d/0xf0 [ib_uverbs]
+[ 213.629094] #2: ffff88810fb23878 (&file->ucontext_lock){+.+.}-{3:3},
+ at: ib_init_ucontext+0x49/0xf0 [ib_uverbs]
+[ 213.630106] #3: ffff88810b585e08 (&dev->wc_state_lock){+.+.}-{3:3},
+ at: mlx5_wc_support_get+0x10c/0x210 [mlx5_core]
+[ 213.631185]
+[ 213.631185] stack backtrace:
+[ 213.631718] CPU: 1 UID: 0 PID: 2118 Comm: raw_ethernet_bw Not tainted
+ 6.12.0-rc7_internal_net_next_mlx5_89a0ad0 #1
+[ 213.632722] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
+ rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014
+[ 213.633785] Call Trace:
+[ 213.634099]
+[ 213.634393] dump_stack_lvl+0x7e/0xc0
+[ 213.634806] print_deadlock_bug+0x278/0x3c0
+[ 213.635265] __lock_acquire+0x15f4/0x2c40
+[ 213.635712] lock_acquire+0xcd/0x2d0
+[ 213.636120] ? mlx5_wc_support_get+0x18c/0x210 [mlx5_core]
+[ 213.636722] ? mlx5_ib_enable_lb+0x24/0xa0 [mlx5_ib]
+[ 213.637277] __mutex_lock+0x81/0xda0
+[ 213.637697] ? mlx5_wc_support_get+0x18c/0x210 [mlx5_core]
+[ 213.638305] ? mlx5_wc_support_get+0x18c/0x210 [mlx5_core]
+[ 213.638902] ? rcu_read_lock_sched_held+0x3f/0x70
+[ 213.639400] ? mlx5_wc_support_get+0x18c/0x210 [mlx5_core]
+[ 213.640016] mlx5_wc_support_get+0x18c/0x210 [mlx5_core]
+[ 213.640615] set_ucontext_resp+0x68/0x2b0 [mlx5_ib]
+[ 213.641144] ? debug_mutex_init+0x33/0x40
+[ 213.641586] mlx5_ib_alloc_ucontext+0x18e/0x7b0 [mlx5_ib]
+[ 213.642145] ib_init_ucontext+0xa0/0xf0 [ib_uverbs]
+[ 213.642679] ib_uverbs_handler_UVERBS_METHOD_GET_CONTEXT+0x95/0xc0
+ [ib_uverbs]
+[ 213.643426] ? _copy_from_user+0x46/0x80
+[ 213.643878] ib_uverbs_cmd_verbs+0xa6b/0xc80 [ib_uverbs]
+[ 213.644426] ? ib_uverbs_handler_UVERBS_METHOD_INVOKE_WRITE+0x130/0x130
+ [ib_uverbs]
+[ 213.645213] ? __lock_acquire+0xa99/0x2c40
+[ 213.645675] ? lock_acquire+0xcd/0x2d0
+[ 213.646101] ? ib_uverbs_ioctl+0xc4/0x170 [ib_uverbs]
+[ 213.646625] ? reacquire_held_locks+0xcf/0x1f0
+[ 213.647102] ? do_user_addr_fault+0x45d/0x770
+[ 213.647586] ib_uverbs_ioctl+0xe0/0x170 [ib_uverbs]
+[ 213.648102] ? ib_uverbs_ioctl+0xc4/0x170 [ib_uverbs]
+[ 213.648632] __x64_sys_ioctl+0x4d3/0xaa0
+[ 213.649060] ? do_user_addr_fault+0x4a8/0x770
+[ 213.649528] do_syscall_64+0x6d/0x140
+[ 213.649947] entry_SYSCALL_64_after_hwframe+0x4b/0x53
+[ 213.650478] RIP: 0033:0x7fa179b0737b
+[ 213.650893] Code: ff ff ff 85 c0 79 9b 49 c7 c4 ff ff ff ff 5b 5d 4c
+ 89 e0 41 5c c3 66 0f 1f 84 00 00 00 00 00 f3 0f 1e fa b8
+ 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d
+ 7d 2a 0f 00 f7 d8 64 89 01 48
+[ 213.652619] RSP: 002b:00007ffd2e6d46e8 EFLAGS: 00000246 ORIG_RAX:
+ 0000000000000010
+[ 213.653390] RAX: ffffffffffffffda RBX: 00007ffd2e6d47f8 RCX:
+ 00007fa179b0737b
+[ 213.654084] RDX: 00007ffd2e6d47e0 RSI: 00000000c0181b01 RDI:
+ 0000000000000003
+[ 213.654767] RBP: 00007ffd2e6d47c0 R08: 00007fa1799be010 R09:
+ 0000000000000002
+[ 213.655453] R10: 00007ffd2e6d4960 R11: 0000000000000246 R12:
+ 00007ffd2e6d487c
+[ 213.656170] R13: 0000000000000027 R14: 0000000000000001 R15:
+ 00007ffd2e6d4f70
+
+Fixes: d98995b4bf98 ("net/mlx5: Reimplement write combining test")
+Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
+Reviewed-by: Michael Guralnik <michaelgur@nvidia.com>
+Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/wc.c | 24 ++++++++++----------
+ 1 file changed, 12 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/wc.c b/drivers/net/ethernet/mellanox/mlx5/core/wc.c
+index 1bed75eca97db..740b719e7072d 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/wc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/wc.c
+@@ -382,6 +382,7 @@ static void mlx5_core_test_wc(struct mlx5_core_dev *mdev)
+
+ bool mlx5_wc_support_get(struct mlx5_core_dev *mdev)
+ {
++ struct mutex *wc_state_lock = &mdev->wc_state_lock;
+ struct mlx5_core_dev *parent = NULL;
+
+ if (!MLX5_CAP_GEN(mdev, bf)) {
+@@ -400,32 +401,31 @@ bool mlx5_wc_support_get(struct mlx5_core_dev *mdev)
+ */
+ goto out;
+
+- mutex_lock(&mdev->wc_state_lock);
+-
+- if (mdev->wc_state != MLX5_WC_STATE_UNINITIALIZED)
+- goto unlock;
+-
+ #ifdef CONFIG_MLX5_SF
+- if (mlx5_core_is_sf(mdev))
++ if (mlx5_core_is_sf(mdev)) {
+ parent = mdev->priv.parent_mdev;
++ wc_state_lock = &parent->wc_state_lock;
++ }
+ #endif
+
+- if (parent) {
+- mutex_lock(&parent->wc_state_lock);
++ mutex_lock(wc_state_lock);
+
++ if (mdev->wc_state != MLX5_WC_STATE_UNINITIALIZED)
++ goto unlock;
++
++ if (parent) {
+ mlx5_core_test_wc(parent);
+
+ mlx5_core_dbg(mdev, "parent set wc_state=%d\n",
+ parent->wc_state);
+ mdev->wc_state = parent->wc_state;
+
+- mutex_unlock(&parent->wc_state_lock);
++ } else {
++ mlx5_core_test_wc(mdev);
+ }
+
+- mlx5_core_test_wc(mdev);
+-
+ unlock:
+- mutex_unlock(&mdev->wc_state_lock);
++ mutex_unlock(wc_state_lock);
+ out:
+ mlx5_core_dbg(mdev, "wc_state=%d\n", mdev->wc_state);
+
+--
+2.39.5
+
--- /dev/null
+From 9af9e9d637f1b404a1de562e5cd29a56f3ac597d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jan 2025 13:39:04 +0200
+Subject: net/mlx5: Fix RDMA TX steering prio
+
+From: Patrisious Haddad <phaddad@nvidia.com>
+
+[ Upstream commit c08d3e62b2e73e14da318a1d20b52d0486a28ee0 ]
+
+User added steering rules at RDMA_TX were being added to the first prio,
+which is the counters prio.
+Fix that so that they are correctly added to the BYPASS_PRIO instead.
+
+Fixes: 24670b1a3166 ("net/mlx5: Add support for RDMA TX steering")
+Signed-off-by: Patrisious Haddad <phaddad@nvidia.com>
+Reviewed-by: Mark Bloch <mbloch@nvidia.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+index 2eabfcc247c6a..0ce999706d412 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+@@ -2709,6 +2709,7 @@ struct mlx5_flow_namespace *mlx5_get_flow_namespace(struct mlx5_core_dev *dev,
+ break;
+ case MLX5_FLOW_NAMESPACE_RDMA_TX:
+ root_ns = steering->rdma_tx_root_ns;
++ prio = RDMA_TX_BYPASS_PRIO;
+ break;
+ case MLX5_FLOW_NAMESPACE_RDMA_RX_COUNTERS:
+ root_ns = steering->rdma_rx_root_ns;
+--
+2.39.5
+
--- /dev/null
+From e6450ecb8ab8d0e193a4f6d1c632f164e429fb78 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jan 2025 13:39:06 +0200
+Subject: net/mlx5: SF, Fix add port error handling
+
+From: Chris Mi <cmi@nvidia.com>
+
+[ Upstream commit 2011a2a18ef00b5b8e4b753acbe6451a8c5f2260 ]
+
+If failed to add SF, error handling doesn't delete the SF from the
+SF table. But the hw resources are deleted. So when unload driver,
+hw resources will be deleted again. Firmware will report syndrome
+0x68def3 which means "SF is not allocated can not deallocate".
+
+Fix it by delete SF from SF table if failed to add SF.
+
+Fixes: 2597ee190b4e ("net/mlx5: Call mlx5_sf_id_erase() once in mlx5_sf_dealloc()")
+Signed-off-by: Chris Mi <cmi@nvidia.com>
+Reviewed-by: Shay Drori <shayd@nvidia.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
+index a96be98be032f..b96909fbeb12d 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
+@@ -257,6 +257,7 @@ static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table,
+ return 0;
+
+ esw_err:
++ mlx5_sf_function_id_erase(table, sf);
+ mlx5_sf_free(table, sf);
+ return err;
+ }
+--
+2.39.5
+
--- /dev/null
+From 35956515527c7d8b6c6f1490e30e19ed941755fb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jan 2025 13:39:10 +0200
+Subject: net/mlx5e: Always start IPsec sequence number from 1
+
+From: Leon Romanovsky <leonro@nvidia.com>
+
+[ Upstream commit 7f95b0247764acd739d949ff247db4b76138e55a ]
+
+According to RFC4303, section "3.3.3. Sequence Number Generation",
+the first packet sent using a given SA will contain a sequence
+number of 1.
+
+This is applicable to both ESN and non-ESN mode, which was not covered
+in commit mentioned in Fixes line.
+
+Fixes: 3d42c8cc67a8 ("net/mlx5e: Ensure that IPsec sequence packet number starts from 1")
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 6 ++++++
+ .../mellanox/mlx5/core/en_accel/ipsec_offload.c | 11 ++++++++---
+ 2 files changed, 14 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+index 21857474ad83f..1baf8933a07cb 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+@@ -724,6 +724,12 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
+ /* check esn */
+ if (x->props.flags & XFRM_STATE_ESN)
+ mlx5e_ipsec_update_esn_state(sa_entry);
++ else
++ /* According to RFC4303, section "3.3.3. Sequence Number Generation",
++ * the first packet sent using a given SA will contain a sequence
++ * number of 1.
++ */
++ sa_entry->esn_state.esn = 1;
+
+ mlx5e_ipsec_build_accel_xfrm_attrs(sa_entry, &sa_entry->attrs);
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c
+index 53cfa39188cb0..820debf3fbbf2 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_offload.c
+@@ -91,8 +91,9 @@ u32 mlx5_ipsec_device_caps(struct mlx5_core_dev *mdev)
+ EXPORT_SYMBOL_GPL(mlx5_ipsec_device_caps);
+
+ static void mlx5e_ipsec_packet_setup(void *obj, u32 pdn,
+- struct mlx5_accel_esp_xfrm_attrs *attrs)
++ struct mlx5e_ipsec_sa_entry *sa_entry)
+ {
++ struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs;
+ void *aso_ctx;
+
+ aso_ctx = MLX5_ADDR_OF(ipsec_obj, obj, ipsec_aso);
+@@ -120,8 +121,12 @@ static void mlx5e_ipsec_packet_setup(void *obj, u32 pdn,
+ * active.
+ */
+ MLX5_SET(ipsec_obj, obj, aso_return_reg, MLX5_IPSEC_ASO_REG_C_4_5);
+- if (attrs->dir == XFRM_DEV_OFFLOAD_OUT)
++ if (attrs->dir == XFRM_DEV_OFFLOAD_OUT) {
+ MLX5_SET(ipsec_aso, aso_ctx, mode, MLX5_IPSEC_ASO_INC_SN);
++ if (!attrs->replay_esn.trigger)
++ MLX5_SET(ipsec_aso, aso_ctx, mode_parameter,
++ sa_entry->esn_state.esn);
++ }
+
+ if (attrs->lft.hard_packet_limit != XFRM_INF) {
+ MLX5_SET(ipsec_aso, aso_ctx, remove_flow_pkt_cnt,
+@@ -175,7 +180,7 @@ static int mlx5_create_ipsec_obj(struct mlx5e_ipsec_sa_entry *sa_entry)
+
+ res = &mdev->mlx5e_res.hw_objs;
+ if (attrs->type == XFRM_DEV_OFFLOAD_PACKET)
+- mlx5e_ipsec_packet_setup(obj, res->pdn, attrs);
++ mlx5e_ipsec_packet_setup(obj, res->pdn, sa_entry);
+
+ err = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
+ if (!err)
+--
+2.39.5
+
--- /dev/null
+From cd922d46de1ad35629a41840d55e837edafa6a7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jan 2025 13:39:08 +0200
+Subject: net/mlx5e: Fix inversion dependency warning while enabling IPsec
+ tunnel
+
+From: Leon Romanovsky <leonro@nvidia.com>
+
+[ Upstream commit 2c3688090f8a1f085230aa839cc63e4a7b977df0 ]
+
+Attempt to enable IPsec packet offload in tunnel mode in debug kernel
+generates the following kernel panic, which is happening due to two
+issues:
+1. In SA add section, the should be _bh() variant when marking SA mode.
+2. There is not needed flush_workqueue in SA delete routine. It is not
+needed as at this stage as it is removed from SADB and the running work
+will be canceled later in SA free.
+
+ =====================================================
+ WARNING: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected
+ 6.12.0+ #4 Not tainted
+ -----------------------------------------------------
+ charon/1337 [HC0[0]:SC0[4]:HE1:SE0] is trying to acquire:
+ ffff88810f365020 (&xa->xa_lock#24){+.+.}-{3:3}, at: mlx5e_xfrm_del_state+0xca/0x1e0 [mlx5_core]
+
+ and this task is already holding:
+ ffff88813e0f0d48 (&x->lock){+.-.}-{3:3}, at: xfrm_state_delete+0x16/0x30
+ which would create a new lock dependency:
+ (&x->lock){+.-.}-{3:3} -> (&xa->xa_lock#24){+.+.}-{3:3}
+
+ but this new dependency connects a SOFTIRQ-irq-safe lock:
+ (&x->lock){+.-.}-{3:3}
+
+ ... which became SOFTIRQ-irq-safe at:
+ lock_acquire+0x1be/0x520
+ _raw_spin_lock_bh+0x34/0x40
+ xfrm_timer_handler+0x91/0xd70
+ __hrtimer_run_queues+0x1dd/0xa60
+ hrtimer_run_softirq+0x146/0x2e0
+ handle_softirqs+0x266/0x860
+ irq_exit_rcu+0x115/0x1a0
+ sysvec_apic_timer_interrupt+0x6e/0x90
+ asm_sysvec_apic_timer_interrupt+0x16/0x20
+ default_idle+0x13/0x20
+ default_idle_call+0x67/0xa0
+ do_idle+0x2da/0x320
+ cpu_startup_entry+0x50/0x60
+ start_secondary+0x213/0x2a0
+ common_startup_64+0x129/0x138
+
+ to a SOFTIRQ-irq-unsafe lock:
+ (&xa->xa_lock#24){+.+.}-{3:3}
+
+ ... which became SOFTIRQ-irq-unsafe at:
+ ...
+ lock_acquire+0x1be/0x520
+ _raw_spin_lock+0x2c/0x40
+ xa_set_mark+0x70/0x110
+ mlx5e_xfrm_add_state+0xe48/0x2290 [mlx5_core]
+ xfrm_dev_state_add+0x3bb/0xd70
+ xfrm_add_sa+0x2451/0x4a90
+ xfrm_user_rcv_msg+0x493/0x880
+ netlink_rcv_skb+0x12e/0x380
+ xfrm_netlink_rcv+0x6d/0x90
+ netlink_unicast+0x42f/0x740
+ netlink_sendmsg+0x745/0xbe0
+ __sock_sendmsg+0xc5/0x190
+ __sys_sendto+0x1fe/0x2c0
+ __x64_sys_sendto+0xdc/0x1b0
+ do_syscall_64+0x6d/0x140
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+
+ other info that might help us debug this:
+
+ Possible interrupt unsafe locking scenario:
+
+ CPU0 CPU1
+ ---- ----
+ lock(&xa->xa_lock#24);
+ local_irq_disable();
+ lock(&x->lock);
+ lock(&xa->xa_lock#24);
+ <Interrupt>
+ lock(&x->lock);
+
+ *** DEADLOCK ***
+
+ 2 locks held by charon/1337:
+ #0: ffffffff87f8f858 (&net->xfrm.xfrm_cfg_mutex){+.+.}-{4:4}, at: xfrm_netlink_rcv+0x5e/0x90
+ #1: ffff88813e0f0d48 (&x->lock){+.-.}-{3:3}, at: xfrm_state_delete+0x16/0x30
+
+ the dependencies between SOFTIRQ-irq-safe lock and the holding lock:
+ -> (&x->lock){+.-.}-{3:3} ops: 29 {
+ HARDIRQ-ON-W at:
+ lock_acquire+0x1be/0x520
+ _raw_spin_lock_bh+0x34/0x40
+ xfrm_alloc_spi+0xc0/0xe60
+ xfrm_alloc_userspi+0x5f6/0xbc0
+ xfrm_user_rcv_msg+0x493/0x880
+ netlink_rcv_skb+0x12e/0x380
+ xfrm_netlink_rcv+0x6d/0x90
+ netlink_unicast+0x42f/0x740
+ netlink_sendmsg+0x745/0xbe0
+ __sock_sendmsg+0xc5/0x190
+ __sys_sendto+0x1fe/0x2c0
+ __x64_sys_sendto+0xdc/0x1b0
+ do_syscall_64+0x6d/0x140
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ IN-SOFTIRQ-W at:
+ lock_acquire+0x1be/0x520
+ _raw_spin_lock_bh+0x34/0x40
+ xfrm_timer_handler+0x91/0xd70
+ __hrtimer_run_queues+0x1dd/0xa60
+ hrtimer_run_softirq+0x146/0x2e0
+ handle_softirqs+0x266/0x860
+ irq_exit_rcu+0x115/0x1a0
+ sysvec_apic_timer_interrupt+0x6e/0x90
+ asm_sysvec_apic_timer_interrupt+0x16/0x20
+ default_idle+0x13/0x20
+ default_idle_call+0x67/0xa0
+ do_idle+0x2da/0x320
+ cpu_startup_entry+0x50/0x60
+ start_secondary+0x213/0x2a0
+ common_startup_64+0x129/0x138
+ INITIAL USE at:
+ lock_acquire+0x1be/0x520
+ _raw_spin_lock_bh+0x34/0x40
+ xfrm_alloc_spi+0xc0/0xe60
+ xfrm_alloc_userspi+0x5f6/0xbc0
+ xfrm_user_rcv_msg+0x493/0x880
+ netlink_rcv_skb+0x12e/0x380
+ xfrm_netlink_rcv+0x6d/0x90
+ netlink_unicast+0x42f/0x740
+ netlink_sendmsg+0x745/0xbe0
+ __sock_sendmsg+0xc5/0x190
+ __sys_sendto+0x1fe/0x2c0
+ __x64_sys_sendto+0xdc/0x1b0
+ do_syscall_64+0x6d/0x140
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ }
+ ... key at: [<ffffffff87f9cd20>] __key.18+0x0/0x40
+
+ the dependencies between the lock to be acquired
+ and SOFTIRQ-irq-unsafe lock:
+ -> (&xa->xa_lock#24){+.+.}-{3:3} ops: 9 {
+ HARDIRQ-ON-W at:
+ lock_acquire+0x1be/0x520
+ _raw_spin_lock_bh+0x34/0x40
+ mlx5e_xfrm_add_state+0xc5b/0x2290 [mlx5_core]
+ xfrm_dev_state_add+0x3bb/0xd70
+ xfrm_add_sa+0x2451/0x4a90
+ xfrm_user_rcv_msg+0x493/0x880
+ netlink_rcv_skb+0x12e/0x380
+ xfrm_netlink_rcv+0x6d/0x90
+ netlink_unicast+0x42f/0x740
+ netlink_sendmsg+0x745/0xbe0
+ __sock_sendmsg+0xc5/0x190
+ __sys_sendto+0x1fe/0x2c0
+ __x64_sys_sendto+0xdc/0x1b0
+ do_syscall_64+0x6d/0x140
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ SOFTIRQ-ON-W at:
+ lock_acquire+0x1be/0x520
+ _raw_spin_lock+0x2c/0x40
+ xa_set_mark+0x70/0x110
+ mlx5e_xfrm_add_state+0xe48/0x2290 [mlx5_core]
+ xfrm_dev_state_add+0x3bb/0xd70
+ xfrm_add_sa+0x2451/0x4a90
+ xfrm_user_rcv_msg+0x493/0x880
+ netlink_rcv_skb+0x12e/0x380
+ xfrm_netlink_rcv+0x6d/0x90
+ netlink_unicast+0x42f/0x740
+ netlink_sendmsg+0x745/0xbe0
+ __sock_sendmsg+0xc5/0x190
+ __sys_sendto+0x1fe/0x2c0
+ __x64_sys_sendto+0xdc/0x1b0
+ do_syscall_64+0x6d/0x140
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ INITIAL USE at:
+ lock_acquire+0x1be/0x520
+ _raw_spin_lock_bh+0x34/0x40
+ mlx5e_xfrm_add_state+0xc5b/0x2290 [mlx5_core]
+ xfrm_dev_state_add+0x3bb/0xd70
+ xfrm_add_sa+0x2451/0x4a90
+ xfrm_user_rcv_msg+0x493/0x880
+ netlink_rcv_skb+0x12e/0x380
+ xfrm_netlink_rcv+0x6d/0x90
+ netlink_unicast+0x42f/0x740
+ netlink_sendmsg+0x745/0xbe0
+ __sock_sendmsg+0xc5/0x190
+ __sys_sendto+0x1fe/0x2c0
+ __x64_sys_sendto+0xdc/0x1b0
+ do_syscall_64+0x6d/0x140
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ }
+ ... key at: [<ffffffffa078ff60>] __key.48+0x0/0xfffffffffff210a0 [mlx5_core]
+ ... acquired at:
+ __lock_acquire+0x30a0/0x5040
+ lock_acquire+0x1be/0x520
+ _raw_spin_lock_bh+0x34/0x40
+ mlx5e_xfrm_del_state+0xca/0x1e0 [mlx5_core]
+ xfrm_dev_state_delete+0x90/0x160
+ __xfrm_state_delete+0x662/0xae0
+ xfrm_state_delete+0x1e/0x30
+ xfrm_del_sa+0x1c2/0x340
+ xfrm_user_rcv_msg+0x493/0x880
+ netlink_rcv_skb+0x12e/0x380
+ xfrm_netlink_rcv+0x6d/0x90
+ netlink_unicast+0x42f/0x740
+ netlink_sendmsg+0x745/0xbe0
+ __sock_sendmsg+0xc5/0x190
+ __sys_sendto+0x1fe/0x2c0
+ __x64_sys_sendto+0xdc/0x1b0
+ do_syscall_64+0x6d/0x140
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+
+ stack backtrace:
+ CPU: 7 UID: 0 PID: 1337 Comm: charon Not tainted 6.12.0+ #4
+ Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014
+ Call Trace:
+ <TASK>
+ dump_stack_lvl+0x74/0xd0
+ check_irq_usage+0x12e8/0x1d90
+ ? print_shortest_lock_dependencies_backwards+0x1b0/0x1b0
+ ? check_chain_key+0x1bb/0x4c0
+ ? __lockdep_reset_lock+0x180/0x180
+ ? check_path.constprop.0+0x24/0x50
+ ? mark_lock+0x108/0x2fb0
+ ? print_circular_bug+0x9b0/0x9b0
+ ? mark_lock+0x108/0x2fb0
+ ? print_usage_bug.part.0+0x670/0x670
+ ? check_prev_add+0x1c4/0x2310
+ check_prev_add+0x1c4/0x2310
+ __lock_acquire+0x30a0/0x5040
+ ? lockdep_set_lock_cmp_fn+0x190/0x190
+ ? lockdep_set_lock_cmp_fn+0x190/0x190
+ lock_acquire+0x1be/0x520
+ ? mlx5e_xfrm_del_state+0xca/0x1e0 [mlx5_core]
+ ? lockdep_hardirqs_on_prepare+0x400/0x400
+ ? __xfrm_state_delete+0x5f0/0xae0
+ ? lock_downgrade+0x6b0/0x6b0
+ _raw_spin_lock_bh+0x34/0x40
+ ? mlx5e_xfrm_del_state+0xca/0x1e0 [mlx5_core]
+ mlx5e_xfrm_del_state+0xca/0x1e0 [mlx5_core]
+ xfrm_dev_state_delete+0x90/0x160
+ __xfrm_state_delete+0x662/0xae0
+ xfrm_state_delete+0x1e/0x30
+ xfrm_del_sa+0x1c2/0x340
+ ? xfrm_get_sa+0x250/0x250
+ ? check_chain_key+0x1bb/0x4c0
+ xfrm_user_rcv_msg+0x493/0x880
+ ? copy_sec_ctx+0x270/0x270
+ ? check_chain_key+0x1bb/0x4c0
+ ? lockdep_set_lock_cmp_fn+0x190/0x190
+ ? lockdep_set_lock_cmp_fn+0x190/0x190
+ netlink_rcv_skb+0x12e/0x380
+ ? copy_sec_ctx+0x270/0x270
+ ? netlink_ack+0xd90/0xd90
+ ? netlink_deliver_tap+0xcd/0xb60
+ xfrm_netlink_rcv+0x6d/0x90
+ netlink_unicast+0x42f/0x740
+ ? netlink_attachskb+0x730/0x730
+ ? lock_acquire+0x1be/0x520
+ netlink_sendmsg+0x745/0xbe0
+ ? netlink_unicast+0x740/0x740
+ ? __might_fault+0xbb/0x170
+ ? netlink_unicast+0x740/0x740
+ __sock_sendmsg+0xc5/0x190
+ ? fdget+0x163/0x1d0
+ __sys_sendto+0x1fe/0x2c0
+ ? __x64_sys_getpeername+0xb0/0xb0
+ ? do_user_addr_fault+0x856/0xe30
+ ? lock_acquire+0x1be/0x520
+ ? __task_pid_nr_ns+0x117/0x410
+ ? lock_downgrade+0x6b0/0x6b0
+ __x64_sys_sendto+0xdc/0x1b0
+ ? lockdep_hardirqs_on_prepare+0x284/0x400
+ do_syscall_64+0x6d/0x140
+ entry_SYSCALL_64_after_hwframe+0x4b/0x53
+ RIP: 0033:0x7f7d31291ba4
+ Code: 7d e8 89 4d d4 e8 4c 42 f7 ff 44 8b 4d d0 4c 8b 45 c8 89 c3 44 8b 55 d4 8b 7d e8 b8 2c 00 00 00 48 8b 55 d8 48 8b 75 e0 0f 05 <48> 3d 00 f0 ff ff 77 34 89 df 48 89 45 e8 e8 99 42 f7 ff 48 8b 45
+ RSP: 002b:00007f7d2ccd94f0 EFLAGS: 00000297 ORIG_RAX: 000000000000002c
+ RAX: ffffffffffffffda RBX: 0000000000000001 RCX: 00007f7d31291ba4
+ RDX: 0000000000000028 RSI: 00007f7d2ccd96a0 RDI: 000000000000000a
+ RBP: 00007f7d2ccd9530 R08: 00007f7d2ccd9598 R09: 000000000000000c
+ R10: 0000000000000000 R11: 0000000000000297 R12: 0000000000000028
+ R13: 00007f7d2ccd9598 R14: 00007f7d2ccd96a0 R15: 00000000000000e1
+ </TASK>
+
+Fixes: 4c24272b4e2b ("net/mlx5e: Listen to ARP events to update IPsec L2 headers in tunnel mode")
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/mellanox/mlx5/core/en_accel/ipsec.c | 16 ++++++----------
+ 1 file changed, 6 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+index ca92e518be766..21857474ad83f 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec.c
+@@ -768,9 +768,12 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
+ MLX5_IPSEC_RESCHED);
+
+ if (x->xso.type == XFRM_DEV_OFFLOAD_PACKET &&
+- x->props.mode == XFRM_MODE_TUNNEL)
+- xa_set_mark(&ipsec->sadb, sa_entry->ipsec_obj_id,
+- MLX5E_IPSEC_TUNNEL_SA);
++ x->props.mode == XFRM_MODE_TUNNEL) {
++ xa_lock_bh(&ipsec->sadb);
++ __xa_set_mark(&ipsec->sadb, sa_entry->ipsec_obj_id,
++ MLX5E_IPSEC_TUNNEL_SA);
++ xa_unlock_bh(&ipsec->sadb);
++ }
+
+ out:
+ x->xso.offload_handle = (unsigned long)sa_entry;
+@@ -797,7 +800,6 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
+ static void mlx5e_xfrm_del_state(struct xfrm_state *x)
+ {
+ struct mlx5e_ipsec_sa_entry *sa_entry = to_ipsec_sa_entry(x);
+- struct mlx5_accel_esp_xfrm_attrs *attrs = &sa_entry->attrs;
+ struct mlx5e_ipsec *ipsec = sa_entry->ipsec;
+ struct mlx5e_ipsec_sa_entry *old;
+
+@@ -806,12 +808,6 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x)
+
+ old = xa_erase_bh(&ipsec->sadb, sa_entry->ipsec_obj_id);
+ WARN_ON(old != sa_entry);
+-
+- if (attrs->mode == XFRM_MODE_TUNNEL &&
+- attrs->type == XFRM_DEV_OFFLOAD_PACKET)
+- /* Make sure that no ARP requests are running in parallel */
+- flush_workqueue(ipsec->wq);
+-
+ }
+
+ static void mlx5e_xfrm_free_state(struct xfrm_state *x)
+--
+2.39.5
+
--- /dev/null
+From 69a19552242212aee287e902b20da2a7f5444f34 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jan 2025 13:39:09 +0200
+Subject: net/mlx5e: Rely on reqid in IPsec tunnel mode
+
+From: Leon Romanovsky <leonro@nvidia.com>
+
+[ Upstream commit 25f23524dfa227959beb3b2c2c0f38e0222f4cfa ]
+
+All packet offloads SAs have reqid in it to make sure they have
+corresponding policy. While it is not strictly needed for transparent
+mode, it is extremely important in tunnel mode. In that mode, policy and
+SAs have different match criteria.
+
+Policy catches the whole subnet addresses, and SA catches the tunnel gateways
+addresses. The source address of such tunnel is not known during egress packet
+traversal in flow steering as it is added only after successful encryption.
+
+As reqid is required for packet offload and it is unique for every SA,
+we can safely rely on it only.
+
+The output below shows the configured egress policy and SA by strongswan:
+
+[leonro@vm ~]$ sudo ip x s
+src 192.169.101.2 dst 192.169.101.1
+ proto esp spi 0xc88b7652 reqid 1 mode tunnel
+ replay-window 0 flag af-unspec esn
+ aead rfc4106(gcm(aes)) 0xe406a01083986e14d116488549094710e9c57bc6 128
+ anti-replay esn context:
+ seq-hi 0x0, seq 0x0, oseq-hi 0x0, oseq 0x0
+ replay_window 1, bitmap-length 1
+ 00000000
+ crypto offload parameters: dev eth2 dir out mode packet
+
+[leonro@064 ~]$ sudo ip x p
+src 192.170.0.0/16 dst 192.170.0.0/16
+ dir out priority 383615 ptype main
+ tmpl src 192.169.101.2 dst 192.169.101.1
+ proto esp spi 0xc88b7652 reqid 1 mode tunnel
+ crypto offload parameters: dev eth2 mode packet
+
+Fixes: b3beba1fb404 ("net/mlx5e: Allow policies with reqid 0, to support IKE policy holes")
+Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
+index e51b03d4c717f..57861d34d46f8 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
+@@ -1718,23 +1718,21 @@ static int tx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry)
+ goto err_alloc;
+ }
+
+- if (attrs->family == AF_INET)
+- setup_fte_addr4(spec, &attrs->saddr.a4, &attrs->daddr.a4);
+- else
+- setup_fte_addr6(spec, attrs->saddr.a6, attrs->daddr.a6);
+-
+ setup_fte_no_frags(spec);
+ setup_fte_upper_proto_match(spec, &attrs->upspec);
+
+ switch (attrs->type) {
+ case XFRM_DEV_OFFLOAD_CRYPTO:
++ if (attrs->family == AF_INET)
++ setup_fte_addr4(spec, &attrs->saddr.a4, &attrs->daddr.a4);
++ else
++ setup_fte_addr6(spec, attrs->saddr.a6, attrs->daddr.a6);
+ setup_fte_spi(spec, attrs->spi, false);
+ setup_fte_esp(spec);
+ setup_fte_reg_a(spec);
+ break;
+ case XFRM_DEV_OFFLOAD_PACKET:
+- if (attrs->reqid)
+- setup_fte_reg_c4(spec, attrs->reqid);
++ setup_fte_reg_c4(spec, attrs->reqid);
+ err = setup_pkt_reformat(ipsec, attrs, &flow_act);
+ if (err)
+ goto err_pkt_reformat;
+--
+2.39.5
+
--- /dev/null
+From 15142367fbab4567e4d720c9799725e57555ac8f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 Jan 2025 11:37:06 +0000
+Subject: net: ravb: Fix max TX frame size for RZ/V2M
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Paul Barker <paul.barker.ct@bp.renesas.com>
+
+[ Upstream commit e7e441a4100e4bc90b52f80494a28a9667993975 ]
+
+When tx_max_frame_size was added to struct ravb_hw_info, no value was
+set in ravb_rzv2m_hw_info so the default value of zero was used.
+
+The maximum MTU is set by subtracting from tx_max_frame_size to allow
+space for headers and frame checksums. As ndev->max_mtu is unsigned,
+this subtraction wraps around leading to a ridiculously large positive
+value that is obviously incorrect.
+
+Before tx_max_frame_size was introduced, the maximum MTU was based on
+rx_max_frame_size. So, we can restore the correct maximum MTU by copying
+the rx_max_frame_size value into tx_max_frame_size for RZ/V2M.
+
+Fixes: 1d63864299ca ("net: ravb: Fix maximum TX frame size for GbEth devices")
+Signed-off-by: Paul Barker <paul.barker.ct@bp.renesas.com>
+Reviewed-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
+Link: https://patch.msgid.link/20250109113706.1409149-1-paul.barker.ct@bp.renesas.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/renesas/ravb_main.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
+index 907af4651c553..6f6b0566c65bc 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -2756,6 +2756,7 @@ static const struct ravb_hw_info ravb_rzv2m_hw_info = {
+ .net_features = NETIF_F_RXCSUM,
+ .stats_len = ARRAY_SIZE(ravb_gstrings_stats),
+ .tccr_mask = TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3,
++ .tx_max_frame_size = SZ_2K,
+ .rx_max_frame_size = SZ_2K,
+ .rx_buffer_size = SZ_2K +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)),
+--
+2.39.5
+
--- /dev/null
+From 342433c5833d7c376bc8a8c6a46405719814dc87 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 11:30:00 -0500
+Subject: net: xilinx: axienet: Fix IRQ coalescing packet count overflow
+
+From: Sean Anderson <sean.anderson@linux.dev>
+
+[ Upstream commit c17ff476f53afb30f90bb3c2af77de069c81a622 ]
+
+If coalesce_count is greater than 255 it will not fit in the register and
+will overflow. This can be reproduced by running
+
+ # ethtool -C ethX rx-frames 256
+
+which will result in a timeout of 0us instead. Fix this by checking for
+invalid values and reporting an error.
+
+Fixes: 8a3b7a252dca ("drivers/net/ethernet/xilinx: added Xilinx AXI Ethernet driver")
+Signed-off-by: Sean Anderson <sean.anderson@linux.dev>
+Reviewed-by: Shannon Nelson <shannon.nelson@amd.com>
+Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey@amd.com>
+Link: https://patch.msgid.link/20250113163001.2335235-1-sean.anderson@linux.dev
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+index 1fcbcaa85ebdb..de10a2d08c428 100644
+--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
++++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+@@ -2056,6 +2056,12 @@ axienet_ethtools_set_coalesce(struct net_device *ndev,
+ return -EBUSY;
+ }
+
++ if (ecoalesce->rx_max_coalesced_frames > 255 ||
++ ecoalesce->tx_max_coalesced_frames > 255) {
++ NL_SET_ERR_MSG(extack, "frames must be less than 256");
++ return -EINVAL;
++ }
++
+ if (ecoalesce->rx_max_coalesced_frames)
+ lp->coalesce_count_rx = ecoalesce->rx_max_coalesced_frames;
+ if (ecoalesce->rx_coalesce_usecs)
+--
+2.39.5
+
--- /dev/null
+From 2864b1203fcb0a464ff17450bbea10e524401a93 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jan 2025 08:14:36 -0800
+Subject: netdev: avoid CFI problems with sock priv helpers
+
+From: Jakub Kicinski <kuba@kernel.org>
+
+[ Upstream commit a50da36562cd62b41de9bef08edbb3e8af00f118 ]
+
+Li Li reports that casting away callback type may cause issues
+for CFI. Let's generate a small wrapper for each callback,
+to make sure compiler sees the anticipated types.
+
+Reported-by: Li Li <dualli@chromium.org>
+Link: https://lore.kernel.org/CANBPYPjQVqmzZ4J=rVQX87a9iuwmaetULwbK_5_3YWk2eGzkaA@mail.gmail.com
+Fixes: 170aafe35cb9 ("netdev: support binding dma-buf to netdevice")
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Reviewed-by: Mina Almasry <almasrymina@google.com>
+Link: https://patch.msgid.link/20250115161436.648646-1-kuba@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/netdev-genl-gen.c | 14 ++++++++++++--
+ tools/net/ynl/ynl-gen-c.py | 16 +++++++++++++---
+ 2 files changed, 25 insertions(+), 5 deletions(-)
+
+diff --git a/net/core/netdev-genl-gen.c b/net/core/netdev-genl-gen.c
+index b28424ae06d5f..8614988fc67b9 100644
+--- a/net/core/netdev-genl-gen.c
++++ b/net/core/netdev-genl-gen.c
+@@ -178,6 +178,16 @@ static const struct genl_multicast_group netdev_nl_mcgrps[] = {
+ [NETDEV_NLGRP_PAGE_POOL] = { "page-pool", },
+ };
+
++static void __netdev_nl_sock_priv_init(void *priv)
++{
++ netdev_nl_sock_priv_init(priv);
++}
++
++static void __netdev_nl_sock_priv_destroy(void *priv)
++{
++ netdev_nl_sock_priv_destroy(priv);
++}
++
+ struct genl_family netdev_nl_family __ro_after_init = {
+ .name = NETDEV_FAMILY_NAME,
+ .version = NETDEV_FAMILY_VERSION,
+@@ -189,6 +199,6 @@ struct genl_family netdev_nl_family __ro_after_init = {
+ .mcgrps = netdev_nl_mcgrps,
+ .n_mcgrps = ARRAY_SIZE(netdev_nl_mcgrps),
+ .sock_priv_size = sizeof(struct list_head),
+- .sock_priv_init = (void *)netdev_nl_sock_priv_init,
+- .sock_priv_destroy = (void *)netdev_nl_sock_priv_destroy,
++ .sock_priv_init = __netdev_nl_sock_priv_init,
++ .sock_priv_destroy = __netdev_nl_sock_priv_destroy,
+ };
+diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py
+index 717530bc9c52e..463f1394ab971 100755
+--- a/tools/net/ynl/ynl-gen-c.py
++++ b/tools/net/ynl/ynl-gen-c.py
+@@ -2361,6 +2361,17 @@ def print_kernel_family_struct_src(family, cw):
+ if not kernel_can_gen_family_struct(family):
+ return
+
++ if 'sock-priv' in family.kernel_family:
++ # Generate "trampolines" to make CFI happy
++ cw.write_func("static void", f"__{family.c_name}_nl_sock_priv_init",
++ [f"{family.c_name}_nl_sock_priv_init(priv);"],
++ ["void *priv"])
++ cw.nl()
++ cw.write_func("static void", f"__{family.c_name}_nl_sock_priv_destroy",
++ [f"{family.c_name}_nl_sock_priv_destroy(priv);"],
++ ["void *priv"])
++ cw.nl()
++
+ cw.block_start(f"struct genl_family {family.ident_name}_nl_family __ro_after_init =")
+ cw.p('.name\t\t= ' + family.fam_key + ',')
+ cw.p('.version\t= ' + family.ver_key + ',')
+@@ -2378,9 +2389,8 @@ def print_kernel_family_struct_src(family, cw):
+ cw.p(f'.n_mcgrps\t= ARRAY_SIZE({family.c_name}_nl_mcgrps),')
+ if 'sock-priv' in family.kernel_family:
+ cw.p(f'.sock_priv_size\t= sizeof({family.kernel_family["sock-priv"]}),')
+- # Force cast here, actual helpers take pointer to the real type.
+- cw.p(f'.sock_priv_init\t= (void *){family.c_name}_nl_sock_priv_init,')
+- cw.p(f'.sock_priv_destroy = (void *){family.c_name}_nl_sock_priv_destroy,')
++ cw.p(f'.sock_priv_init\t= __{family.c_name}_nl_sock_priv_init,')
++ cw.p(f'.sock_priv_destroy = __{family.c_name}_nl_sock_priv_destroy,')
+ cw.block_end(';')
+
+
+--
+2.39.5
+
--- /dev/null
+From 12894bff3f5ec9792233e44ba2bf2577320da2b0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2025 09:18:39 +0300
+Subject: nfp: bpf: prevent integer overflow in nfp_bpf_event_output()
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+[ Upstream commit 16ebb6f5b6295c9688749862a39a4889c56227f8 ]
+
+The "sizeof(struct cmsg_bpf_event) + pkt_size + data_size" math could
+potentially have an integer wrapping bug on 32bit systems. Check for
+this and return an error.
+
+Fixes: 9816dd35ecec ("nfp: bpf: perf event output helpers support")
+Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
+Link: https://patch.msgid.link/6074805b-e78d-4b8a-bf05-e929b5377c28@stanley.mountain
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/netronome/nfp/bpf/offload.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/netronome/nfp/bpf/offload.c b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
+index 9d97cd281f18e..c03558adda91e 100644
+--- a/drivers/net/ethernet/netronome/nfp/bpf/offload.c
++++ b/drivers/net/ethernet/netronome/nfp/bpf/offload.c
+@@ -458,7 +458,8 @@ int nfp_bpf_event_output(struct nfp_app_bpf *bpf, const void *data,
+ map_id_full = be64_to_cpu(cbe->map_ptr);
+ map_id = map_id_full;
+
+- if (len < sizeof(struct cmsg_bpf_event) + pkt_size + data_size)
++ if (size_add(pkt_size, data_size) > INT_MAX ||
++ len < sizeof(struct cmsg_bpf_event) + pkt_size + data_size)
+ return -EINVAL;
+ if (cbe->hdr.ver != NFP_CCM_ABI_VERSION)
+ return -EINVAL;
+--
+2.39.5
+
--- /dev/null
+From 02e5baf0f944e0762b522142b1e4f146266358e0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 Jan 2025 13:21:24 +0100
+Subject: openvswitch: fix lockup on tx to unregistering netdev with carrier
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 47e55e4b410f7d552e43011baa5be1aab4093990 ]
+
+Commit in a fixes tag attempted to fix the issue in the following
+sequence of calls:
+
+ do_output
+ -> ovs_vport_send
+ -> dev_queue_xmit
+ -> __dev_queue_xmit
+ -> netdev_core_pick_tx
+ -> skb_tx_hash
+
+When device is unregistering, the 'dev->real_num_tx_queues' goes to
+zero and the 'while (unlikely(hash >= qcount))' loop inside the
+'skb_tx_hash' becomes infinite, locking up the core forever.
+
+But unfortunately, checking just the carrier status is not enough to
+fix the issue, because some devices may still be in unregistering
+state while reporting carrier status OK.
+
+One example of such device is a net/dummy. It sets carrier ON
+on start, but it doesn't implement .ndo_stop to set the carrier off.
+And it makes sense, because dummy doesn't really have a carrier.
+Therefore, while this device is unregistering, it's still easy to hit
+the infinite loop in the skb_tx_hash() from the OVS datapath. There
+might be other drivers that do the same, but dummy by itself is
+important for the OVS ecosystem, because it is frequently used as a
+packet sink for tcpdump while debugging OVS deployments. And when the
+issue is hit, the only way to recover is to reboot.
+
+Fix that by also checking if the device is running. The running
+state is handled by the net core during unregistering, so it covers
+unregistering case better, and we don't really need to send packets
+to devices that are not running anyway.
+
+While only checking the running state might be enough, the carrier
+check is preserved. The running and the carrier states seem disjoined
+throughout the code and different drivers. And other core functions
+like __dev_direct_xmit() check both before attempting to transmit
+a packet. So, it seems safer to check both flags in OVS as well.
+
+Fixes: 066b86787fa3 ("net: openvswitch: fix race on port output")
+Reported-by: Friedrich Weber <f.weber@proxmox.com>
+Closes: https://mail.openvswitch.org/pipermail/ovs-discuss/2025-January/053423.html
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Tested-by: Friedrich Weber <f.weber@proxmox.com>
+Reviewed-by: Aaron Conole <aconole@redhat.com>
+Link: https://patch.msgid.link/20250109122225.4034688-1-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/openvswitch/actions.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
+index 16e2600146844..704c858cf2093 100644
+--- a/net/openvswitch/actions.c
++++ b/net/openvswitch/actions.c
+@@ -934,7 +934,9 @@ static void do_output(struct datapath *dp, struct sk_buff *skb, int out_port,
+ {
+ struct vport *vport = ovs_vport_rcu(dp, out_port);
+
+- if (likely(vport && netif_carrier_ok(vport->dev))) {
++ if (likely(vport &&
++ netif_running(vport->dev) &&
++ netif_carrier_ok(vport->dev))) {
+ u16 mru = OVS_CB(skb)->mru;
+ u32 cutlen = OVS_CB(skb)->cutlen;
+
+--
+2.39.5
+
--- /dev/null
+From 6880ad5a6e0826a49b0f5f191c9d7687221d3d5f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Jan 2025 10:47:54 +0900
+Subject: pfcp: Destroy device along with udp socket's netns dismantle.
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit ffc90e9ca61b0f619326a1417ff32efd6cc71ed2 ]
+
+pfcp_newlink() links the device to a list in dev_net(dev) instead
+of net, where a udp tunnel socket is created.
+
+Even when net is removed, the device stays alive on dev_net(dev).
+Then, removing net triggers the splat below. [0]
+
+In this example, pfcp0 is created in ns2, but the udp socket is
+created in ns1.
+
+ ip netns add ns1
+ ip netns add ns2
+ ip -n ns1 link add netns ns2 name pfcp0 type pfcp
+ ip netns del ns1
+
+Let's link the device to the socket's netns instead.
+
+Now, pfcp_net_exit() needs another netdev iteration to remove
+all pfcp devices in the netns.
+
+pfcp_dev_list is not used under RCU, so the list API is converted
+to the non-RCU variant.
+
+pfcp_net_exit() can be converted to .exit_batch_rtnl() in net-next.
+
+[0]:
+ref_tracker: net notrefcnt@00000000128b34dc has 1/1 users at
+ sk_alloc (./include/net/net_namespace.h:345 net/core/sock.c:2236)
+ inet_create (net/ipv4/af_inet.c:326 net/ipv4/af_inet.c:252)
+ __sock_create (net/socket.c:1558)
+ udp_sock_create4 (net/ipv4/udp_tunnel_core.c:18)
+ pfcp_create_sock (drivers/net/pfcp.c:168)
+ pfcp_newlink (drivers/net/pfcp.c:182 drivers/net/pfcp.c:197)
+ rtnl_newlink (net/core/rtnetlink.c:3786 net/core/rtnetlink.c:3897 net/core/rtnetlink.c:4012)
+ rtnetlink_rcv_msg (net/core/rtnetlink.c:6922)
+ netlink_rcv_skb (net/netlink/af_netlink.c:2542)
+ netlink_unicast (net/netlink/af_netlink.c:1321 net/netlink/af_netlink.c:1347)
+ netlink_sendmsg (net/netlink/af_netlink.c:1891)
+ ____sys_sendmsg (net/socket.c:711 net/socket.c:726 net/socket.c:2583)
+ ___sys_sendmsg (net/socket.c:2639)
+ __sys_sendmsg (net/socket.c:2669)
+ do_syscall_64 (arch/x86/entry/common.c:52 arch/x86/entry/common.c:83)
+ entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
+
+WARNING: CPU: 1 PID: 11 at lib/ref_tracker.c:179 ref_tracker_dir_exit (lib/ref_tracker.c:179)
+Modules linked in:
+CPU: 1 UID: 0 PID: 11 Comm: kworker/u16:0 Not tainted 6.13.0-rc5-00147-g4c1224501e9d #5
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014
+Workqueue: netns cleanup_net
+RIP: 0010:ref_tracker_dir_exit (lib/ref_tracker.c:179)
+Code: 00 00 00 fc ff df 4d 8b 26 49 bd 00 01 00 00 00 00 ad de 4c 39 f5 0f 85 df 00 00 00 48 8b 74 24 08 48 89 df e8 a5 cc 12 02 90 <0f> 0b 90 48 8d 6b 44 be 04 00 00 00 48 89 ef e8 80 de 67 ff 48 89
+RSP: 0018:ff11000007f3fb60 EFLAGS: 00010286
+RAX: 00000000000020ef RBX: ff1100000d6481e0 RCX: 1ffffffff0e40d82
+RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffff8423ee3c
+RBP: ff1100000d648230 R08: 0000000000000001 R09: fffffbfff0e395af
+R10: 0000000000000001 R11: 0000000000000000 R12: ff1100000d648230
+R13: dead000000000100 R14: ff1100000d648230 R15: dffffc0000000000
+FS: 0000000000000000(0000) GS:ff1100006ce80000(0000) knlGS:0000000000000000
+CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+CR2: 00005620e1363990 CR3: 000000000eeb2002 CR4: 0000000000771ef0
+DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+DR3: 0000000000000000 DR6: 00000000fffe07f0 DR7: 0000000000000400
+PKRU: 55555554
+Call Trace:
+ <TASK>
+ ? __warn (kernel/panic.c:748)
+ ? ref_tracker_dir_exit (lib/ref_tracker.c:179)
+ ? report_bug (lib/bug.c:201 lib/bug.c:219)
+ ? handle_bug (arch/x86/kernel/traps.c:285)
+ ? exc_invalid_op (arch/x86/kernel/traps.c:309 (discriminator 1))
+ ? asm_exc_invalid_op (./arch/x86/include/asm/idtentry.h:621)
+ ? _raw_spin_unlock_irqrestore (./arch/x86/include/asm/irqflags.h:42 ./arch/x86/include/asm/irqflags.h:97 ./arch/x86/include/asm/irqflags.h:155 ./include/linux/spinlock_api_smp.h:151 kernel/locking/spinlock.c:194)
+ ? ref_tracker_dir_exit (lib/ref_tracker.c:179)
+ ? __pfx_ref_tracker_dir_exit (lib/ref_tracker.c:158)
+ ? kfree (mm/slub.c:4613 mm/slub.c:4761)
+ net_free (net/core/net_namespace.c:476 net/core/net_namespace.c:467)
+ cleanup_net (net/core/net_namespace.c:664 (discriminator 3))
+ process_one_work (kernel/workqueue.c:3229)
+ worker_thread (kernel/workqueue.c:3304 kernel/workqueue.c:3391)
+ kthread (kernel/kthread.c:389)
+ ret_from_fork (arch/x86/kernel/process.c:147)
+ ret_from_fork_asm (arch/x86/entry/entry_64.S:257)
+ </TASK>
+
+Fixes: 76c8764ef36a ("pfcp: add PFCP module")
+Reported-by: Xiao Liang <shaw.leon@gmail.com>
+Closes: https://lore.kernel.org/netdev/20250104125732.17335-1-shaw.leon@gmail.com/
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/pfcp.c | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/pfcp.c b/drivers/net/pfcp.c
+index 69434fd13f961..68d0d9e92a220 100644
+--- a/drivers/net/pfcp.c
++++ b/drivers/net/pfcp.c
+@@ -206,8 +206,8 @@ static int pfcp_newlink(struct net *net, struct net_device *dev,
+ goto exit_del_pfcp_sock;
+ }
+
+- pn = net_generic(dev_net(dev), pfcp_net_id);
+- list_add_rcu(&pfcp->list, &pn->pfcp_dev_list);
++ pn = net_generic(net, pfcp_net_id);
++ list_add(&pfcp->list, &pn->pfcp_dev_list);
+
+ netdev_dbg(dev, "registered new PFCP interface\n");
+
+@@ -224,7 +224,7 @@ static void pfcp_dellink(struct net_device *dev, struct list_head *head)
+ {
+ struct pfcp_dev *pfcp = netdev_priv(dev);
+
+- list_del_rcu(&pfcp->list);
++ list_del(&pfcp->list);
+ unregister_netdevice_queue(dev, head);
+ }
+
+@@ -247,11 +247,16 @@ static int __net_init pfcp_net_init(struct net *net)
+ static void __net_exit pfcp_net_exit(struct net *net)
+ {
+ struct pfcp_net *pn = net_generic(net, pfcp_net_id);
+- struct pfcp_dev *pfcp;
++ struct pfcp_dev *pfcp, *pfcp_next;
++ struct net_device *dev;
+ LIST_HEAD(list);
+
+ rtnl_lock();
+- list_for_each_entry(pfcp, &pn->pfcp_dev_list, list)
++ for_each_netdev(net, dev)
++ if (dev->rtnl_link_ops == &pfcp_link_ops)
++ pfcp_dellink(dev, &list);
++
++ list_for_each_entry_safe(pfcp, pfcp_next, &pn->pfcp_dev_list, list)
+ pfcp_dellink(pfcp->dev, &list);
+
+ unregister_netdevice_many(&list);
+--
+2.39.5
+
--- /dev/null
+From d7478c91ea91ff3933bf837b1ad00904ddce04f7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 9 Jan 2025 11:30:39 +0300
+Subject: pktgen: Avoid out-of-bounds access in get_imix_entries
+
+From: Artem Chernyshev <artem.chernyshev@red-soft.ru>
+
+[ Upstream commit 76201b5979768500bca362871db66d77cb4c225e ]
+
+Passing a sufficient amount of imix entries leads to invalid access to the
+pkt_dev->imix_entries array because of the incorrect boundary check.
+
+UBSAN: array-index-out-of-bounds in net/core/pktgen.c:874:24
+index 20 is out of range for type 'imix_pkt [20]'
+CPU: 2 PID: 1210 Comm: bash Not tainted 6.10.0-rc1 #121
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996)
+Call Trace:
+<TASK>
+dump_stack_lvl lib/dump_stack.c:117
+__ubsan_handle_out_of_bounds lib/ubsan.c:429
+get_imix_entries net/core/pktgen.c:874
+pktgen_if_write net/core/pktgen.c:1063
+pde_write fs/proc/inode.c:334
+proc_reg_write fs/proc/inode.c:346
+vfs_write fs/read_write.c:593
+ksys_write fs/read_write.c:644
+do_syscall_64 arch/x86/entry/common.c:83
+entry_SYSCALL_64_after_hwframe arch/x86/entry/entry_64.S:130
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: 52a62f8603f9 ("pktgen: Parse internet mix (imix) input")
+Signed-off-by: Artem Chernyshev <artem.chernyshev@red-soft.ru>
+[ fp: allow to fill the array completely; minor changelog cleanup ]
+Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/pktgen.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/net/core/pktgen.c b/net/core/pktgen.c
+index 34f68ef74b8f2..b6db4910359bb 100644
+--- a/net/core/pktgen.c
++++ b/net/core/pktgen.c
+@@ -851,6 +851,9 @@ static ssize_t get_imix_entries(const char __user *buffer,
+ unsigned long weight;
+ unsigned long size;
+
++ if (pkt_dev->n_imix_entries >= MAX_IMIX_ENTRIES)
++ return -E2BIG;
++
+ len = num_arg(&buffer[i], max_digits, &size);
+ if (len < 0)
+ return len;
+@@ -880,9 +883,6 @@ static ssize_t get_imix_entries(const char __user *buffer,
+
+ i++;
+ pkt_dev->n_imix_entries++;
+-
+- if (pkt_dev->n_imix_entries > MAX_IMIX_ENTRIES)
+- return -E2BIG;
+ } while (c == ' ');
+
+ return i;
+--
+2.39.5
+
efi-zboot-limit-compression-options-to-gzip-and-zstd.patch
+net-ethernet-ti-cpsw_ale-fix-cpsw_ale_get_field.patch
+bpf-fix-bpf_sk_select_reuseport-memory-leak.patch
+eth-bnxt-always-recalculate-features-after-xdp-clear.patch
+net-ravb-fix-max-tx-frame-size-for-rz-v2m.patch
+openvswitch-fix-lockup-on-tx-to-unregistering-netdev.patch
+pktgen-avoid-out-of-bounds-access-in-get_imix_entrie.patch
+ice-fix-e825-initialization.patch
+ice-fix-quad-registers-read-on-e825.patch
+ice-fix-eth56g-fc-fec-rx-offset-value.patch
+ice-introduce-ice_get_phy_model-wrapper.patch
+ice-add-ice_get_ctrl_ptp-wrapper-to-simplify-the-cod.patch
+ice-use-ice_adapter-for-ptp-shared-data-instead-of-a.patch
+ice-add-correct-phy-lane-assignment.patch
+cpuidle-teo-update-documentation-after-previous-chan.patch
+btrfs-add-the-missing-error-handling-inside-get_cano.patch
+gtp-use-for_each_netdev_rcu-in-gtp_genl_dump_pdp.patch
+gtp-destroy-device-along-with-udp-socket-s-netns-dis.patch
+pfcp-destroy-device-along-with-udp-socket-s-netns-di.patch
+cpufreq-move-endif-to-the-end-of-kconfig-file.patch
+nfp-bpf-prevent-integer-overflow-in-nfp_bpf_event_ou.patch
+net-xilinx-axienet-fix-irq-coalescing-packet-count-o.patch
+net-fec-handle-page_pool_dev_alloc_pages-error.patch
+net-make-page_pool_ref_netmem-work-with-net-iovs.patch
+net-mlx5-fix-rdma-tx-steering-prio.patch
+net-mlx5-fix-a-lockdep-warning-as-part-of-the-write-.patch
+net-mlx5-sf-fix-add-port-error-handling.patch
+net-mlx5-clear-port-select-structure-when-fail-to-cr.patch
+net-mlx5e-fix-inversion-dependency-warning-while-ena.patch
+net-mlx5e-rely-on-reqid-in-ipsec-tunnel-mode.patch
+net-mlx5e-always-start-ipsec-sequence-number-from-1.patch
+netdev-avoid-cfi-problems-with-sock-priv-helpers.patch
+drm-tests-helpers-fix-compiler-warning.patch
+drm-vmwgfx-unreserve-bo-on-error.patch
+drm-vmwgfx-add-new-keep_resv-bo-param.patch
+drm-v3d-ensure-job-pointer-is-set-to-null-after-job-.patch