--- /dev/null
+From d8e1f8dc1c6bd22dbfea05913f621b6c2ad25d25 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 27 Oct 2022 21:45:02 +0300
+Subject: drivers: net: convert to boolean for the mac_managed_pm flag
+
+From: Denis Kirjanov <dkirjanov@suse.de>
+
+[ Upstream commit eca485d22165695587bed02d8b9d0f7f44246c4a ]
+
+Signed-off-by: Dennis Kirjanov <dkirjanov@suse.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: cbc17e7802f5 ("net: fec: Set mac_managed_pm during probe")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fec_main.c | 2 +-
+ drivers/net/ethernet/realtek/r8169_main.c | 2 +-
+ drivers/net/usb/asix_devices.c | 4 ++--
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
+index 97d12c7eea772..51eb30c20c7cf 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -2236,7 +2236,7 @@ static int fec_enet_mii_probe(struct net_device *ndev)
+ fep->link = 0;
+ fep->full_duplex = 0;
+
+- phy_dev->mac_managed_pm = 1;
++ phy_dev->mac_managed_pm = true;
+
+ phy_attached_info(phy_dev);
+
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index 256630f57ffe1..6e3417712e402 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -5148,7 +5148,7 @@ static int r8169_mdio_register(struct rtl8169_private *tp)
+ return -EUNATCH;
+ }
+
+- tp->phydev->mac_managed_pm = 1;
++ tp->phydev->mac_managed_pm = true;
+
+ phy_support_asym_pause(tp->phydev);
+
+diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c
+index 6eacbf17f1c0c..34cd568b27f19 100644
+--- a/drivers/net/usb/asix_devices.c
++++ b/drivers/net/usb/asix_devices.c
+@@ -714,7 +714,7 @@ static int ax88772_init_phy(struct usbnet *dev)
+ }
+
+ phy_suspend(priv->phydev);
+- priv->phydev->mac_managed_pm = 1;
++ priv->phydev->mac_managed_pm = true;
+
+ phy_attached_info(priv->phydev);
+
+@@ -734,7 +734,7 @@ static int ax88772_init_phy(struct usbnet *dev)
+ return -ENODEV;
+ }
+
+- priv->phydev_int->mac_managed_pm = 1;
++ priv->phydev_int->mac_managed_pm = true;
+ phy_suspend(priv->phydev_int);
+
+ return 0;
+--
+2.43.0
+
--- /dev/null
+From d9f0c27fff66d90c0edf6393f2f6656e7341b3bc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Oct 2023 13:50:21 -0500
+Subject: drm/amd: Add concept of running prepare_suspend() sequence for IP
+ blocks
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit cb11ca3233aa3303dc11dca25977d2e7f24be00f ]
+
+If any IP blocks allocate memory during their hw_fini() sequence
+this can cause the suspend to fail under memory pressure. Introduce
+a new phase that IP blocks can use to allocate memory before suspend
+starts so that it can potentially be evicted into swap instead.
+
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: ca299b4512d4 ("drm/amd: Flush GFXOFF requests in prepare stage")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 12 +++++++++++-
+ drivers/gpu/drm/amd/include/amd_shared.h | 1 +
+ 2 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+index 902a446cc4d38..77e35b919b064 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -4180,7 +4180,7 @@ static int amdgpu_device_evict_resources(struct amdgpu_device *adev)
+ int amdgpu_device_prepare(struct drm_device *dev)
+ {
+ struct amdgpu_device *adev = drm_to_adev(dev);
+- int r;
++ int i, r;
+
+ if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
+ return 0;
+@@ -4190,6 +4190,16 @@ int amdgpu_device_prepare(struct drm_device *dev)
+ if (r)
+ return r;
+
++ for (i = 0; i < adev->num_ip_blocks; i++) {
++ if (!adev->ip_blocks[i].status.valid)
++ continue;
++ if (!adev->ip_blocks[i].version->funcs->prepare_suspend)
++ continue;
++ r = adev->ip_blocks[i].version->funcs->prepare_suspend((void *)adev);
++ if (r)
++ return r;
++ }
++
+ return 0;
+ }
+
+diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h
+index f175e65b853a0..34467427c9f97 100644
+--- a/drivers/gpu/drm/amd/include/amd_shared.h
++++ b/drivers/gpu/drm/amd/include/amd_shared.h
+@@ -294,6 +294,7 @@ struct amd_ip_funcs {
+ int (*hw_init)(void *handle);
+ int (*hw_fini)(void *handle);
+ void (*late_fini)(void *handle);
++ int (*prepare_suspend)(void *handle);
+ int (*suspend)(void *handle);
+ int (*resume)(void *handle);
+ bool (*is_idle)(void *handle);
+--
+2.43.0
+
--- /dev/null
+From 61797b71db6c7d8b2870088dad97ed8e3e24e990 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Oct 2023 13:50:20 -0500
+Subject: drm/amd: Evict resources during PM ops prepare() callback
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit 5095d5418193eb2748c7d8553c7150b8f1c44696 ]
+
+Linux PM core has a prepare() callback run before suspend.
+
+If the system is under high memory pressure, the resources may need
+to be evicted into swap instead. If the storage backing for swap
+is offlined during the suspend() step then such a call may fail.
+
+So move this step into prepare() to move evict majority of
+resources and update all non-pmops callers to call the same callback.
+
+Link: https://gitlab.freedesktop.org/drm/amd/-/issues/2362
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: ca299b4512d4 ("drm/amd: Flush GFXOFF requests in prepare stage")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 +
+ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 26 ++++++++++++++++++++++
+ drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 10 ++++++---
+ 3 files changed, 34 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+index e636c7850f777..dd22d2559720c 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+@@ -1342,6 +1342,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
+ void amdgpu_driver_release_kms(struct drm_device *dev);
+
+ int amdgpu_device_ip_suspend(struct amdgpu_device *adev);
++int amdgpu_device_prepare(struct drm_device *dev);
+ int amdgpu_device_suspend(struct drm_device *dev, bool fbcon);
+ int amdgpu_device_resume(struct drm_device *dev, bool fbcon);
+ u32 amdgpu_get_vblank_counter_kms(struct drm_crtc *crtc);
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+index 6a4749c0c5a58..902a446cc4d38 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -1639,6 +1639,7 @@ static void amdgpu_switcheroo_set_state(struct pci_dev *pdev,
+ } else {
+ pr_info("switched off\n");
+ dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;
++ amdgpu_device_prepare(dev);
+ amdgpu_device_suspend(dev, true);
+ amdgpu_device_cache_pci_state(pdev);
+ /* Shut down the device */
+@@ -4167,6 +4168,31 @@ static int amdgpu_device_evict_resources(struct amdgpu_device *adev)
+ /*
+ * Suspend & resume.
+ */
++/**
++ * amdgpu_device_prepare - prepare for device suspend
++ *
++ * @dev: drm dev pointer
++ *
++ * Prepare to put the hw in the suspend state (all asics).
++ * Returns 0 for success or an error on failure.
++ * Called at driver suspend.
++ */
++int amdgpu_device_prepare(struct drm_device *dev)
++{
++ struct amdgpu_device *adev = drm_to_adev(dev);
++ int r;
++
++ if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
++ return 0;
++
++ /* Evict the majority of BOs before starting suspend sequence */
++ r = amdgpu_device_evict_resources(adev);
++ if (r)
++ return r;
++
++ return 0;
++}
++
+ /**
+ * amdgpu_device_suspend - initiate device suspend
+ *
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+index f24c3a20e901d..9a5416331f02e 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+@@ -2391,8 +2391,9 @@ static int amdgpu_pmops_prepare(struct device *dev)
+ /* Return a positive number here so
+ * DPM_FLAG_SMART_SUSPEND works properly
+ */
+- if (amdgpu_device_supports_boco(drm_dev))
+- return pm_runtime_suspended(dev);
++ if (amdgpu_device_supports_boco(drm_dev) &&
++ pm_runtime_suspended(dev))
++ return 1;
+
+ /* if we will not support s3 or s2i for the device
+ * then skip suspend
+@@ -2401,7 +2402,7 @@ static int amdgpu_pmops_prepare(struct device *dev)
+ !amdgpu_acpi_is_s3_active(adev))
+ return 1;
+
+- return 0;
++ return amdgpu_device_prepare(drm_dev);
+ }
+
+ static void amdgpu_pmops_complete(struct device *dev)
+@@ -2600,6 +2601,9 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
+ if (amdgpu_device_supports_boco(drm_dev))
+ adev->mp1_state = PP_MP1_STATE_UNLOAD;
+
++ ret = amdgpu_device_prepare(drm_dev);
++ if (ret)
++ return ret;
+ ret = amdgpu_device_suspend(drm_dev, false);
+ if (ret) {
+ adev->in_runpm = false;
+--
+2.43.0
+
--- /dev/null
+From c8707e59797200d6575e5c35577921d51447ce05 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Mar 2024 13:32:21 -0500
+Subject: drm/amd: Flush GFXOFF requests in prepare stage
+
+From: Mario Limonciello <mario.limonciello@amd.com>
+
+[ Upstream commit ca299b4512d4b4f516732a48ce9aa19d91f4473e ]
+
+If the system hasn't entered GFXOFF when suspend starts it can cause
+hangs accessing GC and RLC during the suspend stage.
+
+Cc: <stable@vger.kernel.org> # 6.1.y: 5095d5418193 ("drm/amd: Evict resources during PM ops prepare() callback")
+Cc: <stable@vger.kernel.org> # 6.1.y: cb11ca3233aa ("drm/amd: Add concept of running prepare_suspend() sequence for IP blocks")
+Cc: <stable@vger.kernel.org> # 6.1.y: 2ceec37b0e3d ("drm/amd: Add missing kernel doc for prepare_suspend()")
+Cc: <stable@vger.kernel.org> # 6.1.y: 3a9626c816db ("drm/amd: Stop evicting resources on APUs in suspend")
+Cc: <stable@vger.kernel.org> # 6.6.y: 5095d5418193 ("drm/amd: Evict resources during PM ops prepare() callback")
+Cc: <stable@vger.kernel.org> # 6.6.y: cb11ca3233aa ("drm/amd: Add concept of running prepare_suspend() sequence for IP blocks")
+Cc: <stable@vger.kernel.org> # 6.6.y: 2ceec37b0e3d ("drm/amd: Add missing kernel doc for prepare_suspend()")
+Cc: <stable@vger.kernel.org> # 6.6.y: 3a9626c816db ("drm/amd: Stop evicting resources on APUs in suspend")
+Cc: <stable@vger.kernel.org> # 6.1+
+Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3132
+Fixes: ab4750332dbe ("drm/amdgpu/sdma5.2: add begin/end_use ring callbacks")
+Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+index 77e35b919b064..b11690a816e73 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+@@ -4190,6 +4190,8 @@ int amdgpu_device_prepare(struct drm_device *dev)
+ if (r)
+ return r;
+
++ flush_delayed_work(&adev->gfx.gfx_off_delay_work);
++
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+ if (!adev->ip_blocks[i].status.valid)
+ continue;
+--
+2.43.0
+
--- /dev/null
+From 75a6070e88c129ef8d0364d8fdf13f47e279f99d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 16 Mar 2024 12:38:29 +0100
+Subject: i40e: Enforce software interrupt during busy-poll exit
+
+From: Ivan Vecera <ivecera@redhat.com>
+
+[ Upstream commit ea558de7238bb12c3435c47f0631e9d17bf4a09f ]
+
+As for ice bug fixed by commit b7306b42beaf ("ice: manage interrupts
+during poll exit") followed by commit 23be7075b318 ("ice: fix software
+generating extra interrupts") I'm seeing the similar issue also with
+i40e driver.
+
+In certain situation when busy-loop is enabled together with adaptive
+coalescing, the driver occasionally misses that there are outstanding
+descriptors to clean when exiting busy poll.
+
+Try to catch the remaining work by triggering a software interrupt
+when exiting busy poll. No extra interrupts will be generated when
+busy polling is not used.
+
+The issue was found when running sockperf ping-pong tcp test with
+adaptive coalescing and busy poll enabled (50 as value busy_pool
+and busy_read sysctl knobs) and results in huge latency spikes
+with more than 100000us.
+
+The fix is inspired from the ice driver and do the following:
+1) During napi poll exit in case of busy-poll (napo_complete_done()
+ returns false) this is recorded to q_vector that we were in busy
+ loop.
+2) Extends i40e_buildreg_itr() to be able to add an enforced software
+ interrupt into built value
+2) In i40e_update_enable_itr() enforces a software interrupt trigger
+ if we are exiting busy poll to catch any pending clean-ups
+3) Reuses unused 3rd ITR (interrupt throttle) index and set it to
+ 20K interrupts per second to limit the number of these sw interrupts.
+
+Test results
+============
+Prior:
+[root@dell-per640-07 net]# sockperf ping-pong -i 10.9.9.1 --tcp -m 1000 --mps=max -t 120
+sockperf: == version #3.10-no.git ==
+sockperf[CLIENT] send on:sockperf: using recvfrom() to block on socket(s)
+
+[ 0] IP = 10.9.9.1 PORT = 11111 # TCP
+sockperf: Warmup stage (sending a few dummy messages)...
+sockperf: Starting test...
+sockperf: Test end (interrupted by timer)
+sockperf: Test ended
+sockperf: [Total Run] RunTime=119.999 sec; Warm up time=400 msec; SentMessages=2438563; ReceivedMessages=2438562
+sockperf: ========= Printing statistics for Server No: 0
+sockperf: [Valid Duration] RunTime=119.549 sec; SentMessages=2429473; ReceivedMessages=2429473
+sockperf: ====> avg-latency=24.571 (std-dev=93.297, mean-ad=4.904, median-ad=1.510, siqr=1.063, cv=3.797, std-error=0.060, 99.0% ci=[24.417, 24.725])
+sockperf: # dropped messages = 0; # duplicated messages = 0; # out-of-order messages = 0
+sockperf: Summary: Latency is 24.571 usec
+sockperf: Total 2429473 observations; each percentile contains 24294.73 observations
+sockperf: ---> <MAX> observation = 103294.331
+sockperf: ---> percentile 99.999 = 45.633
+sockperf: ---> percentile 99.990 = 37.013
+sockperf: ---> percentile 99.900 = 35.910
+sockperf: ---> percentile 99.000 = 33.390
+sockperf: ---> percentile 90.000 = 28.626
+sockperf: ---> percentile 75.000 = 27.741
+sockperf: ---> percentile 50.000 = 26.743
+sockperf: ---> percentile 25.000 = 25.614
+sockperf: ---> <MIN> observation = 12.220
+
+After:
+[root@dell-per640-07 net]# sockperf ping-pong -i 10.9.9.1 --tcp -m 1000 --mps=max -t 120
+sockperf: == version #3.10-no.git ==
+sockperf[CLIENT] send on:sockperf: using recvfrom() to block on socket(s)
+
+[ 0] IP = 10.9.9.1 PORT = 11111 # TCP
+sockperf: Warmup stage (sending a few dummy messages)...
+sockperf: Starting test...
+sockperf: Test end (interrupted by timer)
+sockperf: Test ended
+sockperf: [Total Run] RunTime=119.999 sec; Warm up time=400 msec; SentMessages=2400055; ReceivedMessages=2400054
+sockperf: ========= Printing statistics for Server No: 0
+sockperf: [Valid Duration] RunTime=119.549 sec; SentMessages=2391186; ReceivedMessages=2391186
+sockperf: ====> avg-latency=24.965 (std-dev=5.934, mean-ad=4.642, median-ad=1.485, siqr=1.067, cv=0.238, std-error=0.004, 99.0% ci=[24.955, 24.975])
+sockperf: # dropped messages = 0; # duplicated messages = 0; # out-of-order messages = 0
+sockperf: Summary: Latency is 24.965 usec
+sockperf: Total 2391186 observations; each percentile contains 23911.86 observations
+sockperf: ---> <MAX> observation = 195.841
+sockperf: ---> percentile 99.999 = 45.026
+sockperf: ---> percentile 99.990 = 39.009
+sockperf: ---> percentile 99.900 = 35.922
+sockperf: ---> percentile 99.000 = 33.482
+sockperf: ---> percentile 90.000 = 28.902
+sockperf: ---> percentile 75.000 = 27.821
+sockperf: ---> percentile 50.000 = 26.860
+sockperf: ---> percentile 25.000 = 25.685
+sockperf: ---> <MIN> observation = 12.277
+
+Fixes: 0bcd952feec7 ("ethernet/intel: consolidate NAPI and NAPI exit")
+Reported-by: Hugo Ferreira <hferreir@redhat.com>
+Reviewed-by: Michal Schmidt <mschmidt@redhat.com>
+Signed-off-by: Ivan Vecera <ivecera@redhat.com>
+Reviewed-by: Jesse Brandeburg <jesse.brandeburg@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/i40e/i40e.h | 1 +
+ drivers/net/ethernet/intel/i40e/i40e_main.c | 6 ++
+ .../net/ethernet/intel/i40e/i40e_register.h | 3 +
+ drivers/net/ethernet/intel/i40e/i40e_txrx.c | 82 ++++++++++++++-----
+ drivers/net/ethernet/intel/i40e/i40e_txrx.h | 1 +
+ 5 files changed, 72 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
+index 35862dedd59b5..5293fc00938cf 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e.h
++++ b/drivers/net/ethernet/intel/i40e/i40e.h
+@@ -992,6 +992,7 @@ struct i40e_q_vector {
+ struct rcu_head rcu; /* to avoid race with update stats on free */
+ char name[I40E_INT_NAME_STR_LEN];
+ bool arm_wb_state;
++ bool in_busy_poll;
+ int irq_num; /* IRQ assigned to this q_vector */
+ } ____cacheline_internodealigned_in_smp;
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
+index ee0d7c29e8f17..a9db1ed74d3fc 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
+@@ -3891,6 +3891,12 @@ static void i40e_vsi_configure_msix(struct i40e_vsi *vsi)
+ q_vector->tx.target_itr >> 1);
+ q_vector->tx.current_itr = q_vector->tx.target_itr;
+
++ /* Set ITR for software interrupts triggered after exiting
++ * busy-loop polling.
++ */
++ wr32(hw, I40E_PFINT_ITRN(I40E_SW_ITR, vector - 1),
++ I40E_ITR_20K);
++
+ wr32(hw, I40E_PFINT_RATEN(vector - 1),
+ i40e_intrl_usec_to_reg(vsi->int_rate_limit));
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_register.h b/drivers/net/ethernet/intel/i40e/i40e_register.h
+index 7339003aa17cd..694cb3e45c1ec 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_register.h
++++ b/drivers/net/ethernet/intel/i40e/i40e_register.h
+@@ -328,8 +328,11 @@
+ #define I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT 3
+ #define I40E_PFINT_DYN_CTLN_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT)
+ #define I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT 5
++#define I40E_PFINT_DYN_CTLN_INTERVAL_MASK I40E_MASK(0xFFF, I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT)
+ #define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT 24
+ #define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK I40E_MASK(0x1, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_SHIFT)
++#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT 25
++#define I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK I40E_MASK(0x3, I40E_PFINT_DYN_CTLN_SW_ITR_INDX_SHIFT)
+ #define I40E_PFINT_ICR0 0x00038780 /* Reset: CORER */
+ #define I40E_PFINT_ICR0_INTEVENT_SHIFT 0
+ #define I40E_PFINT_ICR0_INTEVENT_MASK I40E_MASK(0x1, I40E_PFINT_ICR0_INTEVENT_SHIFT)
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+index 94cf82668efaa..3d83fccf742b1 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c
+@@ -2571,7 +2571,22 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
+ return failure ? budget : (int)total_rx_packets;
+ }
+
+-static inline u32 i40e_buildreg_itr(const int type, u16 itr)
++/**
++ * i40e_buildreg_itr - build a value for writing to I40E_PFINT_DYN_CTLN register
++ * @itr_idx: interrupt throttling index
++ * @interval: interrupt throttling interval value in usecs
++ * @force_swint: force software interrupt
++ *
++ * The function builds a value for I40E_PFINT_DYN_CTLN register that
++ * is used to update interrupt throttling interval for specified ITR index
++ * and optionally enforces a software interrupt. If the @itr_idx is equal
++ * to I40E_ITR_NONE then no interval change is applied and only @force_swint
++ * parameter is taken into account. If the interval change and enforced
++ * software interrupt are not requested then the built value just enables
++ * appropriate vector interrupt.
++ **/
++static u32 i40e_buildreg_itr(enum i40e_dyn_idx itr_idx, u16 interval,
++ bool force_swint)
+ {
+ u32 val;
+
+@@ -2585,23 +2600,33 @@ static inline u32 i40e_buildreg_itr(const int type, u16 itr)
+ * an event in the PBA anyway so we need to rely on the automask
+ * to hold pending events for us until the interrupt is re-enabled
+ *
+- * The itr value is reported in microseconds, and the register
+- * value is recorded in 2 microsecond units. For this reason we
+- * only need to shift by the interval shift - 1 instead of the
+- * full value.
++ * We have to shift the given value as it is reported in microseconds
++ * and the register value is recorded in 2 microsecond units.
+ */
+- itr &= I40E_ITR_MASK;
++ interval >>= 1;
+
++ /* 1. Enable vector interrupt
++ * 2. Update the interval for the specified ITR index
++ * (I40E_ITR_NONE in the register is used to indicate that
++ * no interval update is requested)
++ */
+ val = I40E_PFINT_DYN_CTLN_INTENA_MASK |
+- (type << I40E_PFINT_DYN_CTLN_ITR_INDX_SHIFT) |
+- (itr << (I40E_PFINT_DYN_CTLN_INTERVAL_SHIFT - 1));
++ FIELD_PREP(I40E_PFINT_DYN_CTLN_ITR_INDX_MASK, itr_idx) |
++ FIELD_PREP(I40E_PFINT_DYN_CTLN_INTERVAL_MASK, interval);
++
++ /* 3. Enforce software interrupt trigger if requested
++ * (These software interrupts rate is limited by ITR2 that is
++ * set to 20K interrupts per second)
++ */
++ if (force_swint)
++ val |= I40E_PFINT_DYN_CTLN_SWINT_TRIG_MASK |
++ I40E_PFINT_DYN_CTLN_SW_ITR_INDX_ENA_MASK |
++ FIELD_PREP(I40E_PFINT_DYN_CTLN_SW_ITR_INDX_MASK,
++ I40E_SW_ITR);
+
+ return val;
+ }
+
+-/* a small macro to shorten up some long lines */
+-#define INTREG I40E_PFINT_DYN_CTLN
+-
+ /* The act of updating the ITR will cause it to immediately trigger. In order
+ * to prevent this from throwing off adaptive update statistics we defer the
+ * update so that it can only happen so often. So after either Tx or Rx are
+@@ -2620,8 +2645,10 @@ static inline u32 i40e_buildreg_itr(const int type, u16 itr)
+ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
+ struct i40e_q_vector *q_vector)
+ {
++ enum i40e_dyn_idx itr_idx = I40E_ITR_NONE;
+ struct i40e_hw *hw = &vsi->back->hw;
+- u32 intval;
++ u16 interval = 0;
++ u32 itr_val;
+
+ /* If we don't have MSIX, then we only need to re-enable icr0 */
+ if (!(vsi->back->flags & I40E_FLAG_MSIX_ENABLED)) {
+@@ -2643,8 +2670,8 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
+ */
+ if (q_vector->rx.target_itr < q_vector->rx.current_itr) {
+ /* Rx ITR needs to be reduced, this is highest priority */
+- intval = i40e_buildreg_itr(I40E_RX_ITR,
+- q_vector->rx.target_itr);
++ itr_idx = I40E_RX_ITR;
++ interval = q_vector->rx.target_itr;
+ q_vector->rx.current_itr = q_vector->rx.target_itr;
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
+ } else if ((q_vector->tx.target_itr < q_vector->tx.current_itr) ||
+@@ -2653,25 +2680,36 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
+ /* Tx ITR needs to be reduced, this is second priority
+ * Tx ITR needs to be increased more than Rx, fourth priority
+ */
+- intval = i40e_buildreg_itr(I40E_TX_ITR,
+- q_vector->tx.target_itr);
++ itr_idx = I40E_TX_ITR;
++ interval = q_vector->tx.target_itr;
+ q_vector->tx.current_itr = q_vector->tx.target_itr;
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
+ } else if (q_vector->rx.current_itr != q_vector->rx.target_itr) {
+ /* Rx ITR needs to be increased, third priority */
+- intval = i40e_buildreg_itr(I40E_RX_ITR,
+- q_vector->rx.target_itr);
++ itr_idx = I40E_RX_ITR;
++ interval = q_vector->rx.target_itr;
+ q_vector->rx.current_itr = q_vector->rx.target_itr;
+ q_vector->itr_countdown = ITR_COUNTDOWN_START;
+ } else {
+ /* No ITR update, lowest priority */
+- intval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
+ if (q_vector->itr_countdown)
+ q_vector->itr_countdown--;
+ }
+
+- if (!test_bit(__I40E_VSI_DOWN, vsi->state))
+- wr32(hw, INTREG(q_vector->reg_idx), intval);
++ /* Do not update interrupt control register if VSI is down */
++ if (test_bit(__I40E_VSI_DOWN, vsi->state))
++ return;
++
++ /* Update ITR interval if necessary and enforce software interrupt
++ * if we are exiting busy poll.
++ */
++ if (q_vector->in_busy_poll) {
++ itr_val = i40e_buildreg_itr(itr_idx, interval, true);
++ q_vector->in_busy_poll = false;
++ } else {
++ itr_val = i40e_buildreg_itr(itr_idx, interval, false);
++ }
++ wr32(hw, I40E_PFINT_DYN_CTLN(q_vector->reg_idx), itr_val);
+ }
+
+ /**
+@@ -2778,6 +2816,8 @@ int i40e_napi_poll(struct napi_struct *napi, int budget)
+ */
+ if (likely(napi_complete_done(napi, work_done)))
+ i40e_update_enable_itr(vsi, q_vector);
++ else
++ q_vector->in_busy_poll = true;
+
+ return min(work_done, budget - 1);
+ }
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+index 602ddd956245e..6e567d343e031 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h
++++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+@@ -67,6 +67,7 @@ enum i40e_dyn_idx {
+ /* these are indexes into ITRN registers */
+ #define I40E_RX_ITR I40E_IDX_ITR0
+ #define I40E_TX_ITR I40E_IDX_ITR1
++#define I40E_SW_ITR I40E_IDX_ITR2
+
+ /* Supported RSS offloads */
+ #define I40E_DEFAULT_RSS_HENA ( \
+--
+2.43.0
+
--- /dev/null
+From 1bfd61e386535c404d2148ff89ec029a4ded9e33 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Nov 2023 15:10:24 -0800
+Subject: i40e: Remove _t suffix from enum type names
+
+From: Ivan Vecera <ivecera@redhat.com>
+
+[ Upstream commit addca9175e5f74cf29e8ad918c38c09b8663b5b8 ]
+
+Enum type names should not be suffixed by '_t'. Either to use
+'typedef enum name name_t' to so plain 'name_t var' instead of
+'enum name_t var'.
+
+Signed-off-by: Ivan Vecera <ivecera@redhat.com>
+Reviewed-by: Jacob Keller <jacob.e.keller@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>
+Link: https://lore.kernel.org/r/20231113231047.548659-6-anthony.l.nguyen@intel.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: ea558de7238b ("i40e: Enforce software interrupt during busy-poll exit")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/i40e/i40e.h | 4 ++--
+ drivers/net/ethernet/intel/i40e/i40e_ptp.c | 6 +++---
+ drivers/net/ethernet/intel/i40e/i40e_txrx.h | 4 ++--
+ 3 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
+index 59c4e9d642980..35862dedd59b5 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e.h
++++ b/drivers/net/ethernet/intel/i40e/i40e.h
+@@ -108,7 +108,7 @@
+ #define I40E_MAX_BW_INACTIVE_ACCUM 4 /* accumulate 4 credits max */
+
+ /* driver state flags */
+-enum i40e_state_t {
++enum i40e_state {
+ __I40E_TESTING,
+ __I40E_CONFIG_BUSY,
+ __I40E_CONFIG_DONE,
+@@ -156,7 +156,7 @@ enum i40e_state_t {
+ BIT_ULL(__I40E_PF_RESET_AND_REBUILD_REQUESTED)
+
+ /* VSI state flags */
+-enum i40e_vsi_state_t {
++enum i40e_vsi_state {
+ __I40E_VSI_DOWN,
+ __I40E_VSI_NEEDS_RESTART,
+ __I40E_VSI_SYNCING_FILTERS,
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
+index 97a9efe7b713e..5f2555848a69e 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c
+@@ -34,7 +34,7 @@ enum i40e_ptp_pin {
+ GPIO_4
+ };
+
+-enum i40e_can_set_pins_t {
++enum i40e_can_set_pins {
+ CANT_DO_PINS = -1,
+ CAN_SET_PINS,
+ CAN_DO_PINS
+@@ -192,7 +192,7 @@ static bool i40e_is_ptp_pin_dev(struct i40e_hw *hw)
+ * return CAN_DO_PINS if pins can be manipulated within a NIC or
+ * return CANT_DO_PINS otherwise.
+ **/
+-static enum i40e_can_set_pins_t i40e_can_set_pins(struct i40e_pf *pf)
++static enum i40e_can_set_pins i40e_can_set_pins(struct i40e_pf *pf)
+ {
+ if (!i40e_is_ptp_pin_dev(&pf->hw)) {
+ dev_warn(&pf->pdev->dev,
+@@ -1081,7 +1081,7 @@ static void i40e_ptp_set_pins_hw(struct i40e_pf *pf)
+ static int i40e_ptp_set_pins(struct i40e_pf *pf,
+ struct i40e_ptp_pins_settings *pins)
+ {
+- enum i40e_can_set_pins_t pin_caps = i40e_can_set_pins(pf);
++ enum i40e_can_set_pins pin_caps = i40e_can_set_pins(pf);
+ int i = 0;
+
+ if (pin_caps == CANT_DO_PINS)
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.h b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+index 768290dc6f48b..602ddd956245e 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.h
++++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.h
+@@ -57,7 +57,7 @@ static inline u16 i40e_intrl_usec_to_reg(int intrl)
+ * mentioning ITR_INDX, ITR_NONE cannot be used as an index 'n' into any
+ * register but instead is a special value meaning "don't update" ITR0/1/2.
+ */
+-enum i40e_dyn_idx_t {
++enum i40e_dyn_idx {
+ I40E_IDX_ITR0 = 0,
+ I40E_IDX_ITR1 = 1,
+ I40E_IDX_ITR2 = 2,
+@@ -304,7 +304,7 @@ struct i40e_rx_queue_stats {
+ u64 page_busy_count;
+ };
+
+-enum i40e_ring_state_t {
++enum i40e_ring_state {
+ __I40E_TX_FDIR_INIT_DONE,
+ __I40E_TX_XPS_INIT_DONE,
+ __I40E_RING_STATE_NBITS /* must be last */
+--
+2.43.0
+
--- /dev/null
+From 6960c854a016fde9484ad00407bf3cbf91b7b4b4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 7 Oct 2022 14:38:40 -0700
+Subject: i40e: Store the irq number in i40e_q_vector
+
+From: Joe Damato <jdamato@fastly.com>
+
+[ Upstream commit 6b85a4f39ff7177b2428d4deab1151a31754e391 ]
+
+Make it easy to figure out the IRQ number for a particular i40e_q_vector by
+storing the assigned IRQ in the structure itself.
+
+Signed-off-by: Joe Damato <jdamato@fastly.com>
+Acked-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
+Acked-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
+Tested-by: Gurucharan <gurucharanx.g@intel.com> (A Contingent worker at Intel)
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Stable-dep-of: ea558de7238b ("i40e: Enforce software interrupt during busy-poll exit")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/intel/i40e/i40e.h | 1 +
+ drivers/net/ethernet/intel/i40e/i40e_main.c | 1 +
+ 2 files changed, 2 insertions(+)
+
+diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
+index 7d4cc4eafd59e..59c4e9d642980 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e.h
++++ b/drivers/net/ethernet/intel/i40e/i40e.h
+@@ -992,6 +992,7 @@ struct i40e_q_vector {
+ struct rcu_head rcu; /* to avoid race with update stats on free */
+ char name[I40E_INT_NAME_STR_LEN];
+ bool arm_wb_state;
++ int irq_num; /* IRQ assigned to this q_vector */
+ } ____cacheline_internodealigned_in_smp;
+
+ /* lan device */
+diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
+index 5be56db1dafda..ee0d7c29e8f17 100644
+--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
+@@ -4145,6 +4145,7 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
+ }
+
+ /* register for affinity change notifications */
++ q_vector->irq_num = irq_num;
+ q_vector->affinity_notify.notify = i40e_irq_affinity_notify;
+ q_vector->affinity_notify.release = i40e_irq_affinity_release;
+ irq_set_affinity_notifier(irq_num, &q_vector->affinity_notify);
+--
+2.43.0
+
--- /dev/null
+From 0ab1837687c5503e2cb43ec4dfacde6e12f0ff20 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jan 2024 15:56:08 -0800
+Subject: KVM: SVM: Add support for allowing zero SEV ASIDs
+
+From: Ashish Kalra <ashish.kalra@amd.com>
+
+[ Upstream commit 0aa6b90ef9d75b4bd7b6d106d85f2a3437697f91 ]
+
+Some BIOSes allow the end user to set the minimum SEV ASID value
+(CPUID 0x8000001F_EDX) to be greater than the maximum number of
+encrypted guests, or maximum SEV ASID value (CPUID 0x8000001F_ECX)
+in order to dedicate all the SEV ASIDs to SEV-ES or SEV-SNP.
+
+The SEV support, as coded, does not handle the case where the minimum
+SEV ASID value can be greater than the maximum SEV ASID value.
+As a result, the following confusing message is issued:
+
+[ 30.715724] kvm_amd: SEV enabled (ASIDs 1007 - 1006)
+
+Fix the support to properly handle this case.
+
+Fixes: 916391a2d1dc ("KVM: SVM: Add support for SEV-ES capability in KVM")
+Suggested-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
+Cc: stable@vger.kernel.org
+Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
+Link: https://lore.kernel.org/r/20240104190520.62510-1-Ashish.Kalra@amd.com
+Link: https://lore.kernel.org/r/20240131235609.4161407-4-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/svm/sev.c | 29 +++++++++++++++++++----------
+ 1 file changed, 19 insertions(+), 10 deletions(-)
+
+diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
+index 9e50eaf967f22..d8e192ad59538 100644
+--- a/arch/x86/kvm/svm/sev.c
++++ b/arch/x86/kvm/svm/sev.c
+@@ -136,10 +136,21 @@ static void sev_misc_cg_uncharge(struct kvm_sev_info *sev)
+
+ static int sev_asid_new(struct kvm_sev_info *sev)
+ {
+- unsigned int asid, min_asid, max_asid;
++ /*
++ * SEV-enabled guests must use asid from min_sev_asid to max_sev_asid.
++ * SEV-ES-enabled guest can use from 1 to min_sev_asid - 1.
++ * Note: min ASID can end up larger than the max if basic SEV support is
++ * effectively disabled by disallowing use of ASIDs for SEV guests.
++ */
++ unsigned int min_asid = sev->es_active ? 1 : min_sev_asid;
++ unsigned int max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid;
++ unsigned int asid;
+ bool retry = true;
+ int ret;
+
++ if (min_asid > max_asid)
++ return -ENOTTY;
++
+ WARN_ON(sev->misc_cg);
+ sev->misc_cg = get_current_misc_cg();
+ ret = sev_misc_cg_try_charge(sev);
+@@ -151,12 +162,6 @@ static int sev_asid_new(struct kvm_sev_info *sev)
+
+ mutex_lock(&sev_bitmap_lock);
+
+- /*
+- * SEV-enabled guests must use asid from min_sev_asid to max_sev_asid.
+- * SEV-ES-enabled guest can use from 1 to min_sev_asid - 1.
+- */
+- min_asid = sev->es_active ? 1 : min_sev_asid;
+- max_asid = sev->es_active ? min_sev_asid - 1 : max_sev_asid;
+ again:
+ asid = find_next_zero_bit(sev_asid_bitmap, max_asid + 1, min_asid);
+ if (asid > max_asid) {
+@@ -2215,8 +2220,10 @@ void __init sev_hardware_setup(void)
+ goto out;
+ }
+
+- sev_asid_count = max_sev_asid - min_sev_asid + 1;
+- WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count));
++ if (min_sev_asid <= max_sev_asid) {
++ sev_asid_count = max_sev_asid - min_sev_asid + 1;
++ WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count));
++ }
+ sev_supported = true;
+
+ /* SEV-ES support requested? */
+@@ -2247,7 +2254,9 @@ void __init sev_hardware_setup(void)
+ out:
+ if (boot_cpu_has(X86_FEATURE_SEV))
+ pr_info("SEV %s (ASIDs %u - %u)\n",
+- sev_supported ? "enabled" : "disabled",
++ sev_supported ? min_sev_asid <= max_sev_asid ? "enabled" :
++ "unusable" :
++ "disabled",
+ min_sev_asid, max_sev_asid);
+ if (boot_cpu_has(X86_FEATURE_SEV_ES))
+ pr_info("SEV-ES %s (ASIDs %u - %u)\n",
+--
+2.43.0
+
--- /dev/null
+From 6688ee674bc40eb0df66195e870205542c8ae100 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 22 May 2023 18:12:48 +0200
+Subject: KVM: SVM: enhance info printk's in SEV init
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
+
+[ Upstream commit 6d1bc9754b04075d938b47cf7f7800814b8911a7 ]
+
+Let's print available ASID ranges for SEV/SEV-ES guests.
+This information can be useful for system administrator
+to debug if SEV/SEV-ES fails to enable.
+
+There are a few reasons.
+SEV:
+- NPT is disabled (module parameter)
+- CPU lacks some features (sev, decodeassists)
+- Maximum SEV ASID is 0
+
+SEV-ES:
+- mmio_caching is disabled (module parameter)
+- CPU lacks sev_es feature
+- Minimum SEV ASID value is 1 (can be adjusted in BIOS/UEFI)
+
+Cc: Sean Christopherson <seanjc@google.com>
+Cc: Paolo Bonzini <pbonzini@redhat.com>
+Cc: Stéphane Graber <stgraber@ubuntu.com>
+Cc: kvm@vger.kernel.org
+Cc: linux-kernel@vger.kernel.org
+Suggested-by: Sean Christopherson <seanjc@google.com>
+Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
+Link: https://lore.kernel.org/r/20230522161249.800829-3-aleksandr.mikhalitsyn@canonical.com
+[sean: print '0' for min SEV-ES ASID if there are no available ASIDs]
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Stable-dep-of: 0aa6b90ef9d7 ("KVM: SVM: Add support for allowing zero SEV ASIDs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/svm/sev.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
+index 3dc0ee1fe9db9..1fe9257d87b2d 100644
+--- a/arch/x86/kvm/svm/sev.c
++++ b/arch/x86/kvm/svm/sev.c
+@@ -2217,7 +2217,6 @@ void __init sev_hardware_setup(void)
+ if (misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count))
+ goto out;
+
+- pr_info("SEV supported: %u ASIDs\n", sev_asid_count);
+ sev_supported = true;
+
+ /* SEV-ES support requested? */
+@@ -2245,10 +2244,18 @@ void __init sev_hardware_setup(void)
+ if (misc_cg_set_capacity(MISC_CG_RES_SEV_ES, sev_es_asid_count))
+ goto out;
+
+- pr_info("SEV-ES supported: %u ASIDs\n", sev_es_asid_count);
+ sev_es_supported = true;
+
+ out:
++ if (boot_cpu_has(X86_FEATURE_SEV))
++ pr_info("SEV %s (ASIDs %u - %u)\n",
++ sev_supported ? "enabled" : "disabled",
++ min_sev_asid, max_sev_asid);
++ if (boot_cpu_has(X86_FEATURE_SEV_ES))
++ pr_info("SEV-ES %s (ASIDs %u - %u)\n",
++ sev_es_supported ? "enabled" : "disabled",
++ min_sev_asid > 1 ? 1 : 0, min_sev_asid - 1);
++
+ sev_enabled = sev_supported;
+ sev_es_enabled = sev_es_supported;
+ #endif
+--
+2.43.0
+
--- /dev/null
+From 4de3c77867712cd4c5bf01f4913c88334c967cad Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 31 Jan 2024 15:56:07 -0800
+Subject: KVM: SVM: Use unsigned integers when dealing with ASIDs
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit 466eec4a22a76c462781bf6d45cb02cbedf21a61 ]
+
+Convert all local ASID variables and parameters throughout the SEV code
+from signed integers to unsigned integers. As ASIDs are fundamentally
+unsigned values, and the global min/max variables are appropriately
+unsigned integers, too.
+
+Functionally, this is a glorified nop as KVM guarantees min_sev_asid is
+non-zero, and no CPU supports -1u as the _only_ asid, i.e. the signed vs.
+unsigned goof won't cause problems in practice.
+
+Opportunistically use sev_get_asid() in sev_flush_encrypted_page() instead
+of open coding an equivalent.
+
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Link: https://lore.kernel.org/r/20240131235609.4161407-3-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Stable-dep-of: 0aa6b90ef9d7 ("KVM: SVM: Add support for allowing zero SEV ASIDs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/svm/sev.c | 18 ++++++++++--------
+ arch/x86/kvm/trace.h | 10 +++++-----
+ 2 files changed, 15 insertions(+), 13 deletions(-)
+
+diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
+index 0316fdf5040f7..9e50eaf967f22 100644
+--- a/arch/x86/kvm/svm/sev.c
++++ b/arch/x86/kvm/svm/sev.c
+@@ -76,9 +76,10 @@ struct enc_region {
+ };
+
+ /* Called with the sev_bitmap_lock held, or on shutdown */
+-static int sev_flush_asids(int min_asid, int max_asid)
++static int sev_flush_asids(unsigned int min_asid, unsigned int max_asid)
+ {
+- int ret, asid, error = 0;
++ int ret, error = 0;
++ unsigned int asid;
+
+ /* Check if there are any ASIDs to reclaim before performing a flush */
+ asid = find_next_bit(sev_reclaim_asid_bitmap, nr_asids, min_asid);
+@@ -108,7 +109,7 @@ static inline bool is_mirroring_enc_context(struct kvm *kvm)
+ }
+
+ /* Must be called with the sev_bitmap_lock held */
+-static bool __sev_recycle_asids(int min_asid, int max_asid)
++static bool __sev_recycle_asids(unsigned int min_asid, unsigned int max_asid)
+ {
+ if (sev_flush_asids(min_asid, max_asid))
+ return false;
+@@ -135,8 +136,9 @@ static void sev_misc_cg_uncharge(struct kvm_sev_info *sev)
+
+ static int sev_asid_new(struct kvm_sev_info *sev)
+ {
+- int asid, min_asid, max_asid, ret;
++ unsigned int asid, min_asid, max_asid;
+ bool retry = true;
++ int ret;
+
+ WARN_ON(sev->misc_cg);
+ sev->misc_cg = get_current_misc_cg();
+@@ -179,7 +181,7 @@ static int sev_asid_new(struct kvm_sev_info *sev)
+ return ret;
+ }
+
+-static int sev_get_asid(struct kvm *kvm)
++static unsigned int sev_get_asid(struct kvm *kvm)
+ {
+ struct kvm_sev_info *sev = &to_kvm_svm(kvm)->sev_info;
+
+@@ -276,8 +278,8 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
+
+ static int sev_bind_asid(struct kvm *kvm, unsigned int handle, int *error)
+ {
++ unsigned int asid = sev_get_asid(kvm);
+ struct sev_data_activate activate;
+- int asid = sev_get_asid(kvm);
+ int ret;
+
+ /* activate ASID on the given handle */
+@@ -2290,7 +2292,7 @@ int sev_cpu_init(struct svm_cpu_data *sd)
+ */
+ static void sev_flush_encrypted_page(struct kvm_vcpu *vcpu, void *va)
+ {
+- int asid = to_kvm_svm(vcpu->kvm)->sev_info.asid;
++ unsigned int asid = sev_get_asid(vcpu->kvm);
+
+ /*
+ * Note! The address must be a kernel address, as regular page walk
+@@ -2611,7 +2613,7 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm)
+ void pre_sev_run(struct vcpu_svm *svm, int cpu)
+ {
+ struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
+- int asid = sev_get_asid(svm->vcpu.kvm);
++ unsigned int asid = sev_get_asid(svm->vcpu.kvm);
+
+ /* Assign the asid allocated with this SEV guest */
+ svm->asid = asid;
+diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
+index bc25589ad5886..6c1dcf44c4fa3 100644
+--- a/arch/x86/kvm/trace.h
++++ b/arch/x86/kvm/trace.h
+@@ -729,13 +729,13 @@ TRACE_EVENT(kvm_nested_intr_vmexit,
+ * Tracepoint for nested #vmexit because of interrupt pending
+ */
+ TRACE_EVENT(kvm_invlpga,
+- TP_PROTO(__u64 rip, int asid, u64 address),
++ TP_PROTO(__u64 rip, unsigned int asid, u64 address),
+ TP_ARGS(rip, asid, address),
+
+ TP_STRUCT__entry(
+- __field( __u64, rip )
+- __field( int, asid )
+- __field( __u64, address )
++ __field( __u64, rip )
++ __field( unsigned int, asid )
++ __field( __u64, address )
+ ),
+
+ TP_fast_assign(
+@@ -744,7 +744,7 @@ TRACE_EVENT(kvm_invlpga,
+ __entry->address = address;
+ ),
+
+- TP_printk("rip: 0x%016llx asid: %d address: 0x%016llx",
++ TP_printk("rip: 0x%016llx asid: %u address: 0x%016llx",
+ __entry->rip, __entry->asid, __entry->address)
+ );
+
+--
+2.43.0
+
--- /dev/null
+From b438e2cec334ebdf9dc1fef6d41f786d3053c5d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Jun 2023 17:44:49 -0700
+Subject: KVM: SVM: WARN, but continue, if misc_cg_set_capacity() fails
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit 106ed2cad9f7bd803bd31a18fe7a9219b077bf95 ]
+
+WARN and continue if misc_cg_set_capacity() fails, as the only scenario
+in which it can fail is if the specified resource is invalid, which should
+never happen when CONFIG_KVM_AMD_SEV=y. Deliberately not bailing "fixes"
+a theoretical bug where KVM would leak the ASID bitmaps on failure, which
+again can't happen.
+
+If the impossible should happen, the end result is effectively the same
+with respect to SEV and SEV-ES (they are unusable), while continuing on
+has the advantage of letting KVM load, i.e. userspace can still run
+non-SEV guests.
+
+Reported-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
+Link: https://lore.kernel.org/r/20230607004449.1421131-1-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Stable-dep-of: 0aa6b90ef9d7 ("KVM: SVM: Add support for allowing zero SEV ASIDs")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/svm/sev.c | 8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
+index 1fe9257d87b2d..0316fdf5040f7 100644
+--- a/arch/x86/kvm/svm/sev.c
++++ b/arch/x86/kvm/svm/sev.c
+@@ -2214,9 +2214,7 @@ void __init sev_hardware_setup(void)
+ }
+
+ sev_asid_count = max_sev_asid - min_sev_asid + 1;
+- if (misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count))
+- goto out;
+-
++ WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV, sev_asid_count));
+ sev_supported = true;
+
+ /* SEV-ES support requested? */
+@@ -2241,9 +2239,7 @@ void __init sev_hardware_setup(void)
+ goto out;
+
+ sev_es_asid_count = min_sev_asid - 1;
+- if (misc_cg_set_capacity(MISC_CG_RES_SEV_ES, sev_es_asid_count))
+- goto out;
+-
++ WARN_ON_ONCE(misc_cg_set_capacity(MISC_CG_RES_SEV_ES, sev_es_asid_count));
+ sev_es_supported = true;
+
+ out:
+--
+2.43.0
+
--- /dev/null
+From c9e8094de8b24a39c40f9b2f6cdae887b0046d8c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Mar 2024 15:59:29 +0000
+Subject: net: fec: Set mac_managed_pm during probe
+
+From: Wei Fang <wei.fang@nxp.com>
+
+[ Upstream commit cbc17e7802f5de37c7c262204baadfad3f7f99e5 ]
+
+Setting mac_managed_pm during interface up is too late.
+
+In situations where the link is not brought up yet and the system suspends
+the regular PHY power management will run. Since the FEC ETHEREN control
+bit is cleared (automatically) on suspend the controller is off in resume.
+When the regular PHY power management resume path runs in this context it
+will write to the MII_DATA register but nothing will be transmitted on the
+MDIO bus.
+
+This can be observed by the following log:
+
+ fec 5b040000.ethernet eth0: MDIO read timeout
+ Microchip LAN87xx T1 5b040000.ethernet-1:04: PM: dpm_run_callback(): mdio_bus_phy_resume+0x0/0xc8 returns -110
+ Microchip LAN87xx T1 5b040000.ethernet-1:04: PM: failed to resume: error -110
+
+The data written will however remain in the MII_DATA register.
+
+When the link later is set to administrative up it will trigger a call to
+fec_restart() which will restore the MII_SPEED register. This triggers the
+quirk explained in f166f890c8f0 ("net: ethernet: fec: Replace interrupt
+driven MDIO with polled IO") causing an extra MII_EVENT.
+
+This extra event desynchronizes all the MDIO register reads, causing them
+to complete too early. Leading all reads to read as 0 because
+fec_enet_mdio_wait() returns too early.
+
+When a Microchip LAN8700R PHY is connected to the FEC, the 0 reads causes
+the PHY to be initialized incorrectly and the PHY will not transmit any
+ethernet signal in this state. It cannot be brought out of this state
+without a power cycle of the PHY.
+
+Fixes: 557d5dc83f68 ("net: fec: use mac-managed PHY PM")
+Closes: https://lore.kernel.org/netdev/1f45bdbe-eab1-4e59-8f24-add177590d27@actia.se/
+Signed-off-by: Wei Fang <wei.fang@nxp.com>
+[jernberg: commit message]
+Signed-off-by: John Ernberg <john.ernberg@actia.se>
+Link: https://lore.kernel.org/r/20240328155909.59613-2-john.ernberg@actia.se
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fec_main.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
+index 51eb30c20c7cf..ebff14b0837d9 100644
+--- a/drivers/net/ethernet/freescale/fec_main.c
++++ b/drivers/net/ethernet/freescale/fec_main.c
+@@ -2236,8 +2236,6 @@ static int fec_enet_mii_probe(struct net_device *ndev)
+ fep->link = 0;
+ fep->full_duplex = 0;
+
+- phy_dev->mac_managed_pm = true;
+-
+ phy_attached_info(phy_dev);
+
+ return 0;
+@@ -2249,10 +2247,12 @@ static int fec_enet_mii_init(struct platform_device *pdev)
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct fec_enet_private *fep = netdev_priv(ndev);
+ bool suppress_preamble = false;
++ struct phy_device *phydev;
+ struct device_node *node;
+ int err = -ENXIO;
+ u32 mii_speed, holdtime;
+ u32 bus_freq;
++ int addr;
+
+ /*
+ * The i.MX28 dual fec interfaces are not equal.
+@@ -2362,6 +2362,13 @@ static int fec_enet_mii_init(struct platform_device *pdev)
+ goto err_out_free_mdiobus;
+ of_node_put(node);
+
++ /* find all the PHY devices on the bus and set mac_managed_pm to true */
++ for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
++ phydev = mdiobus_get_phy(fep->mii_bus, addr);
++ if (phydev)
++ phydev->mac_managed_pm = true;
++ }
++
+ mii_cnt++;
+
+ /* save fec0 mii_bus */
+--
+2.43.0
+
--- /dev/null
+From 130e144c7f600c23b60ed01e49410904868bd328 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Apr 2024 15:53:04 +0100
+Subject: net: ravb: Always process TX descriptor ring
+
+From: Paul Barker <paul.barker.ct@bp.renesas.com>
+
+[ Upstream commit 596a4254915f94c927217fe09c33a6828f33fb25 ]
+
+The TX queue should be serviced each time the poll function is called,
+even if the full RX work budget has been consumed. This prevents
+starvation of the TX queue when RX bandwidth usage is high.
+
+Fixes: c156633f1353 ("Renesas Ethernet AVB driver proper")
+Signed-off-by: Paul Barker <paul.barker.ct@bp.renesas.com>
+Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
+Link: https://lore.kernel.org/r/20240402145305.82148-1-paul.barker.ct@bp.renesas.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/renesas/ravb_main.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
+index 36e2718c564ac..b11cc365d19e3 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -1294,12 +1294,12 @@ static int ravb_poll(struct napi_struct *napi, int budget)
+ int q = napi - priv->napi;
+ int mask = BIT(q);
+ int quota = budget;
++ bool unmask;
+
+ /* Processing RX Descriptor Ring */
+ /* Clear RX interrupt */
+ ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0);
+- if (ravb_rx(ndev, "a, q))
+- goto out;
++ unmask = !ravb_rx(ndev, "a, q);
+
+ /* Processing TX Descriptor Ring */
+ spin_lock_irqsave(&priv->lock, flags);
+@@ -1309,6 +1309,9 @@ static int ravb_poll(struct napi_struct *napi, int budget)
+ netif_wake_subqueue(ndev, q);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
++ if (!unmask)
++ goto out;
++
+ napi_complete(napi);
+
+ /* Re-enable RX/TX interrupts */
+--
+2.43.0
+
--- /dev/null
+From f50634c0af9e573394705a99f46742dc1b386207 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Apr 2024 15:53:05 +0100
+Subject: net: ravb: Always update error counters
+
+From: Paul Barker <paul.barker.ct@bp.renesas.com>
+
+[ Upstream commit 101b76418d7163240bc74a7e06867dca0e51183e ]
+
+The error statistics should be updated each time the poll function is
+called, even if the full RX work budget has been consumed. This prevents
+the counts from becoming stuck when RX bandwidth usage is high.
+
+This also ensures that error counters are not updated after we've
+re-enabled interrupts as that could result in a race condition.
+
+Also drop an unnecessary space.
+
+Fixes: c156633f1353 ("Renesas Ethernet AVB driver proper")
+Signed-off-by: Paul Barker <paul.barker.ct@bp.renesas.com>
+Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
+Link: https://lore.kernel.org/r/20240402145305.82148-2-paul.barker.ct@bp.renesas.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/renesas/ravb_main.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
+index b11cc365d19e3..756ac4a07f60b 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -1309,6 +1309,15 @@ static int ravb_poll(struct napi_struct *napi, int budget)
+ netif_wake_subqueue(ndev, q);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
++ /* Receive error message handling */
++ priv->rx_over_errors = priv->stats[RAVB_BE].rx_over_errors;
++ if (info->nc_queues)
++ priv->rx_over_errors += priv->stats[RAVB_NC].rx_over_errors;
++ if (priv->rx_over_errors != ndev->stats.rx_over_errors)
++ ndev->stats.rx_over_errors = priv->rx_over_errors;
++ if (priv->rx_fifo_errors != ndev->stats.rx_fifo_errors)
++ ndev->stats.rx_fifo_errors = priv->rx_fifo_errors;
++
+ if (!unmask)
+ goto out;
+
+@@ -1325,14 +1334,6 @@ static int ravb_poll(struct napi_struct *napi, int budget)
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+- /* Receive error message handling */
+- priv->rx_over_errors = priv->stats[RAVB_BE].rx_over_errors;
+- if (info->nc_queues)
+- priv->rx_over_errors += priv->stats[RAVB_NC].rx_over_errors;
+- if (priv->rx_over_errors != ndev->stats.rx_over_errors)
+- ndev->stats.rx_over_errors = priv->rx_over_errors;
+- if (priv->rx_fifo_errors != ndev->stats.rx_fifo_errors)
+- ndev->stats.rx_fifo_errors = priv->rx_fifo_errors;
+ out:
+ return budget - quota;
+ }
+--
+2.43.0
+
--- /dev/null
+From b3ee9b253e4c29c2fb2ffdb5d591403d0697103a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 2 Feb 2024 10:41:22 +0200
+Subject: net: ravb: Let IP-specific receive function to interrogate
+ descriptors
+
+From: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+[ Upstream commit 2b993bfdb47b3aaafd8fe9cd5038b5e297b18ee1 ]
+
+ravb_poll() initial code used to interrogate the first descriptor of the
+RX queue in case gPTP is false to determine if ravb_rx() should be called.
+This is done for non-gPTP IPs. For gPTP IPs the driver PTP-specific
+information was used to determine if receive function should be called. As
+every IP has its own receive function that interrogates the RX descriptors
+list in the same way the ravb_poll() was doing there is no need to double
+check this in ravb_poll(). Removing the code from ravb_poll() leads to a
+cleaner code.
+
+Signed-off-by: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+Reviewed-by: Sergey Shtylyov <s.shtylyov@omp.ru>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: 596a4254915f ("net: ravb: Always process TX descriptor ring")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/renesas/ravb_main.c | 13 ++-----------
+ 1 file changed, 2 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
+index e7b70006261f7..36e2718c564ac 100644
+--- a/drivers/net/ethernet/renesas/ravb_main.c
++++ b/drivers/net/ethernet/renesas/ravb_main.c
+@@ -1290,25 +1290,16 @@ static int ravb_poll(struct napi_struct *napi, int budget)
+ struct net_device *ndev = napi->dev;
+ struct ravb_private *priv = netdev_priv(ndev);
+ const struct ravb_hw_info *info = priv->info;
+- bool gptp = info->gptp || info->ccc_gac;
+- struct ravb_rx_desc *desc;
+ unsigned long flags;
+ int q = napi - priv->napi;
+ int mask = BIT(q);
+ int quota = budget;
+- unsigned int entry;
+
+- if (!gptp) {
+- entry = priv->cur_rx[q] % priv->num_rx_ring[q];
+- desc = &priv->gbeth_rx_ring[entry];
+- }
+ /* Processing RX Descriptor Ring */
+ /* Clear RX interrupt */
+ ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0);
+- if (gptp || desc->die_dt != DT_FEMPTY) {
+- if (ravb_rx(ndev, "a, q))
+- goto out;
+- }
++ if (ravb_rx(ndev, "a, q))
++ goto out;
+
+ /* Processing TX Descriptor Ring */
+ spin_lock_irqsave(&priv->lock, flags);
+--
+2.43.0
+
--- /dev/null
+From aac32c3b37669481d53069d54398c839f1eb544c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Mar 2023 22:25:49 +0100
+Subject: r8169: prepare rtl_hw_aspm_clkreq_enable for usage in atomic context
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit 49ef7d846d4bd77b0b9f1f801fc765b004690a07 ]
+
+Bail out if the function is used with chip versions that don't support
+ASPM configuration. In addition remove the delay, it tuned out that
+it's not needed, also vendor driver r8125 doesn't have it.
+
+Suggested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Tested-by: Holger Hoffstätte <holger@applied-asynchrony.com>
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 5e864d90b208 ("r8169: skip DASH fw status checks when DASH is disabled")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index 4a1710b2726ce..256630f57ffe1 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -2772,6 +2772,9 @@ static void rtl_disable_exit_l1(struct rtl8169_private *tp)
+
+ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
+ {
++ if (tp->mac_version < RTL_GIGA_MAC_VER_32)
++ return;
++
+ /* Don't enable ASPM in the chip if OS can't control ASPM */
+ if (enable && tp->aspm_manageable) {
+ rtl_mod_config5(tp, 0, ASPM_en);
+@@ -2801,8 +2804,6 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
+ rtl_mod_config2(tp, ClkReqEn, 0);
+ rtl_mod_config5(tp, ASPM_en, 0);
+ }
+-
+- udelay(10);
+ }
+
+ static void rtl_set_fifo_size(struct rtl8169_private *tp, u16 rx_stat,
+--
+2.43.0
+
--- /dev/null
+From f88bf35af7012b24e193c8e665309a8e5a4ac105 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Mar 2023 22:24:00 +0100
+Subject: r8169: use spinlock to protect access to registers Config2 and
+ Config5
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit 6bc6c4e6893ee79a9862c61d1635e7da6d5a3333 ]
+
+For disabling ASPM during NAPI poll we'll have to access both registers
+in atomic context. Use a spinlock to protect access.
+
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Tested-by: Holger Hoffstätte <holger@applied-asynchrony.com>
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 5e864d90b208 ("r8169: skip DASH fw status checks when DASH is disabled")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 47 ++++++++++++++++++-----
+ 1 file changed, 37 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index c7dd0eb94817f..4a1710b2726ce 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -615,6 +615,7 @@ struct rtl8169_private {
+ struct work_struct work;
+ } wk;
+
++ spinlock_t config25_lock;
+ spinlock_t mac_ocp_lock;
+
+ unsigned supports_gmii:1;
+@@ -680,6 +681,28 @@ static void rtl_pci_commit(struct rtl8169_private *tp)
+ RTL_R8(tp, ChipCmd);
+ }
+
++static void rtl_mod_config2(struct rtl8169_private *tp, u8 clear, u8 set)
++{
++ unsigned long flags;
++ u8 val;
++
++ spin_lock_irqsave(&tp->config25_lock, flags);
++ val = RTL_R8(tp, Config2);
++ RTL_W8(tp, Config2, (val & ~clear) | set);
++ spin_unlock_irqrestore(&tp->config25_lock, flags);
++}
++
++static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set)
++{
++ unsigned long flags;
++ u8 val;
++
++ spin_lock_irqsave(&tp->config25_lock, flags);
++ val = RTL_R8(tp, Config5);
++ RTL_W8(tp, Config5, (val & ~clear) | set);
++ spin_unlock_irqrestore(&tp->config25_lock, flags);
++}
++
+ static bool rtl_is_8125(struct rtl8169_private *tp)
+ {
+ return tp->mac_version >= RTL_GIGA_MAC_VER_61;
+@@ -1401,6 +1424,7 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
+ { WAKE_MAGIC, Config3, MagicPacket }
+ };
+ unsigned int i, tmp = ARRAY_SIZE(cfg);
++ unsigned long flags;
+ u8 options;
+
+ rtl_unlock_config_regs(tp);
+@@ -1419,12 +1443,14 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
+ r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0);
+ }
+
++ spin_lock_irqsave(&tp->config25_lock, flags);
+ for (i = 0; i < tmp; i++) {
+ options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask;
+ if (wolopts & cfg[i].opt)
+ options |= cfg[i].mask;
+ RTL_W8(tp, cfg[i].reg, options);
+ }
++ spin_unlock_irqrestore(&tp->config25_lock, flags);
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
+@@ -1436,10 +1462,10 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
+ case RTL_GIGA_MAC_VER_34:
+ case RTL_GIGA_MAC_VER_37:
+ case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_63:
+- options = RTL_R8(tp, Config2) & ~PME_SIGNAL;
+ if (wolopts)
+- options |= PME_SIGNAL;
+- RTL_W8(tp, Config2, options);
++ rtl_mod_config2(tp, 0, PME_SIGNAL);
++ else
++ rtl_mod_config2(tp, PME_SIGNAL, 0);
+ break;
+ default:
+ break;
+@@ -2748,8 +2774,8 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
+ {
+ /* Don't enable ASPM in the chip if OS can't control ASPM */
+ if (enable && tp->aspm_manageable) {
+- RTL_W8(tp, Config5, RTL_R8(tp, Config5) | ASPM_en);
+- RTL_W8(tp, Config2, RTL_R8(tp, Config2) | ClkReqEn);
++ rtl_mod_config5(tp, 0, ASPM_en);
++ rtl_mod_config2(tp, 0, ClkReqEn);
+
+ switch (tp->mac_version) {
+ case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
+@@ -2772,8 +2798,8 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
+ break;
+ }
+
+- RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
+- RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
++ rtl_mod_config2(tp, ClkReqEn, 0);
++ rtl_mod_config5(tp, ASPM_en, 0);
+ }
+
+ udelay(10);
+@@ -2934,7 +2960,7 @@ static void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
+ RTL_W32(tp, MISC, RTL_R32(tp, MISC) | TXPLA_RST);
+ RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~TXPLA_RST);
+
+- RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
++ rtl_mod_config5(tp, Spi_en, 0);
+ }
+
+ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
+@@ -2967,7 +2993,7 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
+
+ RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
+ RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN);
+- RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
++ rtl_mod_config5(tp, Spi_en, 0);
+
+ rtl_hw_aspm_clkreq_enable(tp, true);
+ }
+@@ -2990,7 +3016,7 @@ static void rtl_hw_start_8168f(struct rtl8169_private *tp)
+ RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
+ RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
+ RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN);
+- RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
++ rtl_mod_config5(tp, Spi_en, 0);
+
+ rtl8168_config_eee_mac(tp);
+ }
+@@ -5259,6 +5285,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ tp->eee_adv = -1;
+ tp->ocp_base = OCP_STD_PHY_BASE;
+
++ spin_lock_init(&tp->config25_lock);
+ spin_lock_init(&tp->mac_ocp_lock);
+
+ dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
+--
+2.43.0
+
--- /dev/null
+From f161a3b464b4ff8bf2f390e15c65540029c519d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Mar 2023 22:23:15 +0100
+Subject: r8169: use spinlock to protect mac ocp register access
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit 91c8643578a21e435c412ffbe902bb4b4773e262 ]
+
+For disabling ASPM during NAPI poll we'll have to access mac ocp
+registers in atomic context. This could result in races because
+a mac ocp read consists of a write to register OCPDR, followed
+by a read from the same register. Therefore add a spinlock to
+protect access to mac ocp registers.
+
+Reviewed-by: Simon Horman <simon.horman@corigine.com>
+Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Tested-by: Holger Hoffstätte <holger@applied-asynchrony.com>
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 5e864d90b208 ("r8169: skip DASH fw status checks when DASH is disabled")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 37 ++++++++++++++++++++---
+ 1 file changed, 33 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index 3dbcb311dcbf2..c7dd0eb94817f 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -615,6 +615,8 @@ struct rtl8169_private {
+ struct work_struct work;
+ } wk;
+
++ spinlock_t mac_ocp_lock;
++
+ unsigned supports_gmii:1;
+ unsigned aspm_manageable:1;
+ unsigned dash_enabled:1;
+@@ -850,7 +852,7 @@ static int r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
+ (RTL_R32(tp, GPHY_OCP) & 0xffff) : -ETIMEDOUT;
+ }
+
+-static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
++static void __r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
+ {
+ if (rtl_ocp_reg_failure(reg))
+ return;
+@@ -858,7 +860,16 @@ static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
+ RTL_W32(tp, OCPDR, OCPAR_FLAG | (reg << 15) | data);
+ }
+
+-static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
++static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&tp->mac_ocp_lock, flags);
++ __r8168_mac_ocp_write(tp, reg, data);
++ spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
++}
++
++static u16 __r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
+ {
+ if (rtl_ocp_reg_failure(reg))
+ return 0;
+@@ -868,12 +879,28 @@ static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
+ return RTL_R32(tp, OCPDR);
+ }
+
++static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
++{
++ unsigned long flags;
++ u16 val;
++
++ spin_lock_irqsave(&tp->mac_ocp_lock, flags);
++ val = __r8168_mac_ocp_read(tp, reg);
++ spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
++
++ return val;
++}
++
+ static void r8168_mac_ocp_modify(struct rtl8169_private *tp, u32 reg, u16 mask,
+ u16 set)
+ {
+- u16 data = r8168_mac_ocp_read(tp, reg);
++ unsigned long flags;
++ u16 data;
+
+- r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
++ spin_lock_irqsave(&tp->mac_ocp_lock, flags);
++ data = __r8168_mac_ocp_read(tp, reg);
++ __r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
++ spin_unlock_irqrestore(&tp->mac_ocp_lock, flags);
+ }
+
+ /* Work around a hw issue with RTL8168g PHY, the quirk disables
+@@ -5232,6 +5259,8 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ tp->eee_adv = -1;
+ tp->ocp_base = OCP_STD_PHY_BASE;
+
++ spin_lock_init(&tp->mac_ocp_lock);
++
+ dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev,
+ struct pcpu_sw_netstats);
+ if (!dev->tstats)
+--
+2.43.0
+
octeontx2-af-add-array-index-check.patch
i40e-fix-i40e_count_filters-to-count-only-active-new-filters.patch
i40e-fix-vf-may-be-used-uninitialized-in-this-function-warning.patch
+usb-typec-ucsi-check-for-notifications-after-init.patch
+drm-amd-evict-resources-during-pm-ops-prepare-callba.patch
+drm-amd-add-concept-of-running-prepare_suspend-seque.patch
+drm-amd-flush-gfxoff-requests-in-prepare-stage.patch
+i40e-store-the-irq-number-in-i40e_q_vector.patch
+i40e-remove-_t-suffix-from-enum-type-names.patch
+i40e-enforce-software-interrupt-during-busy-poll-exi.patch
+r8169-use-spinlock-to-protect-mac-ocp-register-acces.patch
+r8169-use-spinlock-to-protect-access-to-registers-co.patch
+r8169-prepare-rtl_hw_aspm_clkreq_enable-for-usage-in.patch
+tcp-fix-bind-regression-for-v6-only-wildcard-and-v4-.patch
+drivers-net-convert-to-boolean-for-the-mac_managed_p.patch
+net-fec-set-mac_managed_pm-during-probe.patch
+net-ravb-let-ip-specific-receive-function-to-interro.patch
+net-ravb-always-process-tx-descriptor-ring.patch
+net-ravb-always-update-error-counters.patch
+kvm-svm-enhance-info-printk-s-in-sev-init.patch
+kvm-svm-warn-but-continue-if-misc_cg_set_capacity-fa.patch
+kvm-svm-use-unsigned-integers-when-dealing-with-asid.patch
+kvm-svm-add-support-for-allowing-zero-sev-asids.patch
--- /dev/null
+From 961f27c6b980bd03433c02a3b405cc917c093f0f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Mar 2024 13:42:45 -0700
+Subject: tcp: Fix bind() regression for v6-only wildcard and v4(-mapped-v6)
+ non-wildcard addresses.
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit d91ef1e1b55f730bee8ce286b02b7bdccbc42973 ]
+
+Jianguo Wu reported another bind() regression introduced by bhash2.
+
+Calling bind() for the following 3 addresses on the same port, the
+3rd one should fail but now succeeds.
+
+ 1. 0.0.0.0 or ::ffff:0.0.0.0
+ 2. [::] w/ IPV6_V6ONLY
+ 3. IPv4 non-wildcard address or v4-mapped-v6 non-wildcard address
+
+The first two bind() create tb2 like this:
+
+ bhash2 -> tb2(:: w/ IPV6_V6ONLY) -> tb2(0.0.0.0)
+
+The 3rd bind() will match with the IPv6 only wildcard address bucket
+in inet_bind2_bucket_match_addr_any(), however, no conflicting socket
+exists in the bucket. So, inet_bhash2_conflict() will returns false,
+and thus, inet_bhash2_addr_any_conflict() returns false consequently.
+
+As a result, the 3rd bind() bypasses conflict check, which should be
+done against the IPv4 wildcard address bucket.
+
+So, in inet_bhash2_addr_any_conflict(), we must iterate over all buckets.
+
+Note that we cannot add ipv6_only flag for inet_bind2_bucket as it
+would confuse the following patetrn.
+
+ 1. [::] w/ SO_REUSE{ADDR,PORT} and IPV6_V6ONLY
+ 2. [::] w/ SO_REUSE{ADDR,PORT}
+ 3. IPv4 non-wildcard address or v4-mapped-v6 non-wildcard address
+
+The first bind() would create a bucket with ipv6_only flag true,
+the second bind() would add the [::] socket into the same bucket,
+and the third bind() could succeed based on the wrong assumption
+that ipv6_only bucket would not conflict with v4(-mapped-v6) address.
+
+Fixes: 28044fc1d495 ("net: Add a bhash2 table hashed by port and address")
+Diagnosed-by: Jianguo Wu <wujianguo106@163.com>
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Link: https://lore.kernel.org/r/20240326204251.51301-3-kuniyu@amazon.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/inet_connection_sock.c | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
+index f7832d4253820..8407098a59391 100644
+--- a/net/ipv4/inet_connection_sock.c
++++ b/net/ipv4/inet_connection_sock.c
+@@ -289,6 +289,7 @@ static bool inet_bhash2_addr_any_conflict(const struct sock *sk, int port, int l
+ struct sock_reuseport *reuseport_cb;
+ struct inet_bind_hashbucket *head2;
+ struct inet_bind2_bucket *tb2;
++ bool conflict = false;
+ bool reuseport_cb_ok;
+
+ rcu_read_lock();
+@@ -301,18 +302,20 @@ static bool inet_bhash2_addr_any_conflict(const struct sock *sk, int port, int l
+
+ spin_lock(&head2->lock);
+
+- inet_bind_bucket_for_each(tb2, &head2->chain)
+- if (inet_bind2_bucket_match_addr_any(tb2, net, port, l3mdev, sk))
+- break;
++ inet_bind_bucket_for_each(tb2, &head2->chain) {
++ if (!inet_bind2_bucket_match_addr_any(tb2, net, port, l3mdev, sk))
++ continue;
+
+- if (tb2 && inet_bhash2_conflict(sk, tb2, uid, relax, reuseport_cb_ok,
+- reuseport_ok)) {
+- spin_unlock(&head2->lock);
+- return true;
++ if (!inet_bhash2_conflict(sk, tb2, uid, relax, reuseport_cb_ok, reuseport_ok))
++ continue;
++
++ conflict = true;
++ break;
+ }
+
+ spin_unlock(&head2->lock);
+- return false;
++
++ return conflict;
+ }
+
+ /*
+--
+2.43.0
+
--- /dev/null
+From ca61215561a0947476576f8ee06c0dca69b25884 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 20 Mar 2024 08:39:23 +0100
+Subject: usb: typec: ucsi: Check for notifications after init
+
+From: Christian A. Ehrhardt <lk@c--e.de>
+
+[ Upstream commit 808a8b9e0b87bbc72bcc1f7ddfe5d04746e7ce56 ]
+
+The completion notification for the final SET_NOTIFICATION_ENABLE
+command during initialization can include a connector change
+notification. However, at the time this completion notification is
+processed, the ucsi struct is not ready to handle this notification.
+As a result the notification is ignored and the controller
+never sends an interrupt again.
+
+Re-check CCI for a pending connector state change after
+initialization is complete. Adjust the corresponding debug
+message accordingly.
+
+Fixes: 71a1fa0df2a3 ("usb: typec: ucsi: Store the notification mask")
+Cc: stable@vger.kernel.org
+Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Tested-by: Neil Armstrong <neil.armstrong@linaro.org> # on SM8550-QRD
+Link: https://lore.kernel.org/r/20240320073927.1641788-3-lk@c--e.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/typec/ucsi/ucsi.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
+index 98f335cbbcdea..1fd4aaf348047 100644
+--- a/drivers/usb/typec/ucsi/ucsi.c
++++ b/drivers/usb/typec/ucsi/ucsi.c
+@@ -855,7 +855,7 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num)
+ struct ucsi_connector *con = &ucsi->connector[num - 1];
+
+ if (!(ucsi->ntfy & UCSI_ENABLE_NTFY_CONNECTOR_CHANGE)) {
+- dev_dbg(ucsi->dev, "Bogus connector change event\n");
++ dev_dbg(ucsi->dev, "Early connector change event\n");
+ return;
+ }
+
+@@ -1248,6 +1248,7 @@ static int ucsi_init(struct ucsi *ucsi)
+ {
+ struct ucsi_connector *con, *connector;
+ u64 command, ntfy;
++ u32 cci;
+ int ret;
+ int i;
+
+@@ -1300,6 +1301,13 @@ static int ucsi_init(struct ucsi *ucsi)
+
+ ucsi->connector = connector;
+ ucsi->ntfy = ntfy;
++
++ ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci));
++ if (ret)
++ return ret;
++ if (UCSI_CCI_CONNECTOR(READ_ONCE(cci)))
++ ucsi_connector_change(ucsi, cci);
++
+ return 0;
+
+ err_unregister:
+--
+2.43.0
+