From: Sasha Levin Date: Sun, 7 Apr 2024 12:53:27 +0000 (-0400) Subject: Fixes for 6.1 X-Git-Tag: v5.15.154~77 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f95a9ab81986ed1032289772b38de73621f024ec;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.1 Signed-off-by: Sasha Levin --- diff --git a/queue-6.1/drivers-net-convert-to-boolean-for-the-mac_managed_p.patch b/queue-6.1/drivers-net-convert-to-boolean-for-the-mac_managed_p.patch new file mode 100644 index 00000000000..4f2b8ab5809 --- /dev/null +++ b/queue-6.1/drivers-net-convert-to-boolean-for-the-mac_managed_p.patch @@ -0,0 +1,70 @@ +From d8e1f8dc1c6bd22dbfea05913f621b6c2ad25d25 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Oct 2022 21:45:02 +0300 +Subject: drivers: net: convert to boolean for the mac_managed_pm flag + +From: Denis Kirjanov + +[ Upstream commit eca485d22165695587bed02d8b9d0f7f44246c4a ] + +Signed-off-by: Dennis Kirjanov +Signed-off-by: David S. Miller +Stable-dep-of: cbc17e7802f5 ("net: fec: Set mac_managed_pm during probe") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/drm-amd-add-concept-of-running-prepare_suspend-seque.patch b/queue-6.1/drm-amd-add-concept-of-running-prepare_suspend-seque.patch new file mode 100644 index 00000000000..aca440477ea --- /dev/null +++ b/queue-6.1/drm-amd-add-concept-of-running-prepare_suspend-seque.patch @@ -0,0 +1,73 @@ +From d9f0c27fff66d90c0edf6393f2f6656e7341b3bc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Mario Limonciello +Signed-off-by: Alex Deucher +Stable-dep-of: ca299b4512d4 ("drm/amd: Flush GFXOFF requests in prepare stage") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/drm-amd-evict-resources-during-pm-ops-prepare-callba.patch b/queue-6.1/drm-amd-evict-resources-during-pm-ops-prepare-callba.patch new file mode 100644 index 00000000000..e4d235e1437 --- /dev/null +++ b/queue-6.1/drm-amd-evict-resources-during-pm-ops-prepare-callba.patch @@ -0,0 +1,128 @@ +From 61797b71db6c7d8b2870088dad97ed8e3e24e990 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Alex Deucher +Signed-off-by: Mario Limonciello +Signed-off-by: Alex Deucher +Stable-dep-of: ca299b4512d4 ("drm/amd: Flush GFXOFF requests in prepare stage") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/drm-amd-flush-gfxoff-requests-in-prepare-stage.patch b/queue-6.1/drm-amd-flush-gfxoff-requests-in-prepare-stage.patch new file mode 100644 index 00000000000..2753e6f1e42 --- /dev/null +++ b/queue-6.1/drm-amd-flush-gfxoff-requests-in-prepare-stage.patch @@ -0,0 +1,47 @@ +From c8707e59797200d6575e5c35577921d51447ce05 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Mar 2024 13:32:21 -0500 +Subject: drm/amd: Flush GFXOFF requests in prepare stage + +From: Mario Limonciello + +[ 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: # 6.1.y: 5095d5418193 ("drm/amd: Evict resources during PM ops prepare() callback") +Cc: # 6.1.y: cb11ca3233aa ("drm/amd: Add concept of running prepare_suspend() sequence for IP blocks") +Cc: # 6.1.y: 2ceec37b0e3d ("drm/amd: Add missing kernel doc for prepare_suspend()") +Cc: # 6.1.y: 3a9626c816db ("drm/amd: Stop evicting resources on APUs in suspend") +Cc: # 6.6.y: 5095d5418193 ("drm/amd: Evict resources during PM ops prepare() callback") +Cc: # 6.6.y: cb11ca3233aa ("drm/amd: Add concept of running prepare_suspend() sequence for IP blocks") +Cc: # 6.6.y: 2ceec37b0e3d ("drm/amd: Add missing kernel doc for prepare_suspend()") +Cc: # 6.6.y: 3a9626c816db ("drm/amd: Stop evicting resources on APUs in suspend") +Cc: # 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 +Signed-off-by: Mario Limonciello +Signed-off-by: Alex Deucher +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/i40e-enforce-software-interrupt-during-busy-poll-exi.patch b/queue-6.1/i40e-enforce-software-interrupt-during-busy-poll-exi.patch new file mode 100644 index 00000000000..6b9251a6660 --- /dev/null +++ b/queue-6.1/i40e-enforce-software-interrupt-during-busy-poll-exi.patch @@ -0,0 +1,320 @@ +From 75a6070e88c129ef8d0364d8fdf13f47e279f99d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 16 Mar 2024 12:38:29 +0100 +Subject: i40e: Enforce software interrupt during busy-poll exit + +From: Ivan Vecera + +[ 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: ---> 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: ---> 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: ---> 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: ---> observation = 12.277 + +Fixes: 0bcd952feec7 ("ethernet/intel: consolidate NAPI and NAPI exit") +Reported-by: Hugo Ferreira +Reviewed-by: Michal Schmidt +Signed-off-by: Ivan Vecera +Reviewed-by: Jesse Brandeburg +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/i40e-remove-_t-suffix-from-enum-type-names.patch b/queue-6.1/i40e-remove-_t-suffix-from-enum-type-names.patch new file mode 100644 index 00000000000..a9cf316f470 --- /dev/null +++ b/queue-6.1/i40e-remove-_t-suffix-from-enum-type-names.patch @@ -0,0 +1,105 @@ +From 1bfd61e386535c404d2148ff89ec029a4ded9e33 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Nov 2023 15:10:24 -0800 +Subject: i40e: Remove _t suffix from enum type names + +From: Ivan Vecera + +[ 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 +Reviewed-by: Jacob Keller +Tested-by: Pucha Himasekhar Reddy (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Link: https://lore.kernel.org/r/20231113231047.548659-6-anthony.l.nguyen@intel.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: ea558de7238b ("i40e: Enforce software interrupt during busy-poll exit") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/i40e-store-the-irq-number-in-i40e_q_vector.patch b/queue-6.1/i40e-store-the-irq-number-in-i40e_q_vector.patch new file mode 100644 index 00000000000..d9bd04f781b --- /dev/null +++ b/queue-6.1/i40e-store-the-irq-number-in-i40e_q_vector.patch @@ -0,0 +1,51 @@ +From 6960c854a016fde9484ad00407bf3cbf91b7b4b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 7 Oct 2022 14:38:40 -0700 +Subject: i40e: Store the irq number in i40e_q_vector + +From: Joe Damato + +[ 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 +Acked-by: Jesse Brandeburg +Acked-by: Sridhar Samudrala +Tested-by: Gurucharan (A Contingent worker at Intel) +Signed-off-by: Tony Nguyen +Stable-dep-of: ea558de7238b ("i40e: Enforce software interrupt during busy-poll exit") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/kvm-svm-add-support-for-allowing-zero-sev-asids.patch b/queue-6.1/kvm-svm-add-support-for-allowing-zero-sev-asids.patch new file mode 100644 index 00000000000..d64c1fc767f --- /dev/null +++ b/queue-6.1/kvm-svm-add-support-for-allowing-zero-sev-asids.patch @@ -0,0 +1,102 @@ +From 0ab1837687c5503e2cb43ec4dfacde6e12f0ff20 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Jan 2024 15:56:08 -0800 +Subject: KVM: SVM: Add support for allowing zero SEV ASIDs + +From: Ashish Kalra + +[ 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 +Signed-off-by: Ashish Kalra +Cc: stable@vger.kernel.org +Acked-by: Tom Lendacky +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 +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/kvm-svm-enhance-info-printk-s-in-sev-init.patch b/queue-6.1/kvm-svm-enhance-info-printk-s-in-sev-init.patch new file mode 100644 index 00000000000..e555dc6a62a --- /dev/null +++ b/queue-6.1/kvm-svm-enhance-info-printk-s-in-sev-init.patch @@ -0,0 +1,78 @@ +From 6688ee674bc40eb0df66195e870205542c8ae100 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Cc: Paolo Bonzini +Cc: Stéphane Graber +Cc: kvm@vger.kernel.org +Cc: linux-kernel@vger.kernel.org +Suggested-by: Sean Christopherson +Signed-off-by: Alexander Mikhalitsyn +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 +Stable-dep-of: 0aa6b90ef9d7 ("KVM: SVM: Add support for allowing zero SEV ASIDs") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/kvm-svm-use-unsigned-integers-when-dealing-with-asid.patch b/queue-6.1/kvm-svm-use-unsigned-integers-when-dealing-with-asid.patch new file mode 100644 index 00000000000..c2c391e500f --- /dev/null +++ b/queue-6.1/kvm-svm-use-unsigned-integers-when-dealing-with-asid.patch @@ -0,0 +1,139 @@ +From 4de3c77867712cd4c5bf01f4913c88334c967cad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 31 Jan 2024 15:56:07 -0800 +Subject: KVM: SVM: Use unsigned integers when dealing with ASIDs + +From: Sean Christopherson + +[ 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 +Link: https://lore.kernel.org/r/20240131235609.4161407-3-seanjc@google.com +Signed-off-by: Sean Christopherson +Stable-dep-of: 0aa6b90ef9d7 ("KVM: SVM: Add support for allowing zero SEV ASIDs") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/kvm-svm-warn-but-continue-if-misc_cg_set_capacity-fa.patch b/queue-6.1/kvm-svm-warn-but-continue-if-misc_cg_set_capacity-fa.patch new file mode 100644 index 00000000000..9fe4e8d498e --- /dev/null +++ b/queue-6.1/kvm-svm-warn-but-continue-if-misc_cg_set_capacity-fa.patch @@ -0,0 +1,58 @@ +From b438e2cec334ebdf9dc1fef6d41f786d3053c5d5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Jun 2023 17:44:49 -0700 +Subject: KVM: SVM: WARN, but continue, if misc_cg_set_capacity() fails + +From: Sean Christopherson + +[ 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 +Link: https://lore.kernel.org/r/20230607004449.1421131-1-seanjc@google.com +Signed-off-by: Sean Christopherson +Stable-dep-of: 0aa6b90ef9d7 ("KVM: SVM: Add support for allowing zero SEV ASIDs") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/net-fec-set-mac_managed_pm-during-probe.patch b/queue-6.1/net-fec-set-mac_managed_pm-during-probe.patch new file mode 100644 index 00000000000..3d92d112b67 --- /dev/null +++ b/queue-6.1/net-fec-set-mac_managed_pm-during-probe.patch @@ -0,0 +1,95 @@ +From c9e8094de8b24a39c40f9b2f6cdae887b0046d8c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Mar 2024 15:59:29 +0000 +Subject: net: fec: Set mac_managed_pm during probe + +From: Wei Fang + +[ 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 +[jernberg: commit message] +Signed-off-by: John Ernberg +Link: https://lore.kernel.org/r/20240328155909.59613-2-john.ernberg@actia.se +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/net-ravb-always-process-tx-descriptor-ring.patch b/queue-6.1/net-ravb-always-process-tx-descriptor-ring.patch new file mode 100644 index 00000000000..f2a90e282f5 --- /dev/null +++ b/queue-6.1/net-ravb-always-process-tx-descriptor-ring.patch @@ -0,0 +1,55 @@ +From 130e144c7f600c23b60ed01e49410904868bd328 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Apr 2024 15:53:04 +0100 +Subject: net: ravb: Always process TX descriptor ring + +From: Paul Barker + +[ 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 +Reviewed-by: Sergey Shtylyov +Link: https://lore.kernel.org/r/20240402145305.82148-1-paul.barker.ct@bp.renesas.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/net-ravb-always-update-error-counters.patch b/queue-6.1/net-ravb-always-update-error-counters.patch new file mode 100644 index 00000000000..f1d7720fc87 --- /dev/null +++ b/queue-6.1/net-ravb-always-update-error-counters.patch @@ -0,0 +1,66 @@ +From f50634c0af9e573394705a99f46742dc1b386207 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 2 Apr 2024 15:53:05 +0100 +Subject: net: ravb: Always update error counters + +From: Paul Barker + +[ 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 +Reviewed-by: Sergey Shtylyov +Link: https://lore.kernel.org/r/20240402145305.82148-2-paul.barker.ct@bp.renesas.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/net-ravb-let-ip-specific-receive-function-to-interro.patch b/queue-6.1/net-ravb-let-ip-specific-receive-function-to-interro.patch new file mode 100644 index 00000000000..735fa497831 --- /dev/null +++ b/queue-6.1/net-ravb-let-ip-specific-receive-function-to-interro.patch @@ -0,0 +1,63 @@ +From b3ee9b253e4c29c2fb2ffdb5d591403d0697103a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 2 Feb 2024 10:41:22 +0200 +Subject: net: ravb: Let IP-specific receive function to interrogate + descriptors + +From: Claudiu Beznea + +[ 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 +Reviewed-by: Sergey Shtylyov +Signed-off-by: Paolo Abeni +Stable-dep-of: 596a4254915f ("net: ravb: Always process TX descriptor ring") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/r8169-prepare-rtl_hw_aspm_clkreq_enable-for-usage-in.patch b/queue-6.1/r8169-prepare-rtl_hw_aspm_clkreq_enable-for-usage-in.patch new file mode 100644 index 00000000000..d57b1190c16 --- /dev/null +++ b/queue-6.1/r8169-prepare-rtl_hw_aspm_clkreq_enable-for-usage-in.patch @@ -0,0 +1,54 @@ +From aac32c3b37669481d53069d54398c839f1eb544c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Simon Horman +Tested-by: Kai-Heng Feng +Tested-by: Holger Hoffstätte +Signed-off-by: Heiner Kallweit +Signed-off-by: David S. Miller +Stable-dep-of: 5e864d90b208 ("r8169: skip DASH fw status checks when DASH is disabled") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/r8169-use-spinlock-to-protect-access-to-registers-co.patch b/queue-6.1/r8169-use-spinlock-to-protect-access-to-registers-co.patch new file mode 100644 index 00000000000..c6eeb0950ec --- /dev/null +++ b/queue-6.1/r8169-use-spinlock-to-protect-access-to-registers-co.patch @@ -0,0 +1,165 @@ +From f88bf35af7012b24e193c8e665309a8e5a4ac105 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Tested-by: Kai-Heng Feng +Tested-by: Holger Hoffstätte +Signed-off-by: Heiner Kallweit +Signed-off-by: David S. Miller +Stable-dep-of: 5e864d90b208 ("r8169: skip DASH fw status checks when DASH is disabled") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/r8169-use-spinlock-to-protect-mac-ocp-register-acces.patch b/queue-6.1/r8169-use-spinlock-to-protect-mac-ocp-register-acces.patch new file mode 100644 index 00000000000..7bd1676513f --- /dev/null +++ b/queue-6.1/r8169-use-spinlock-to-protect-mac-ocp-register-acces.patch @@ -0,0 +1,112 @@ +From f161a3b464b4ff8bf2f390e15c65540029c519d8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Tested-by: Kai-Heng Feng +Tested-by: Holger Hoffstätte +Signed-off-by: Heiner Kallweit +Signed-off-by: David S. Miller +Stable-dep-of: 5e864d90b208 ("r8169: skip DASH fw status checks when DASH is disabled") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/series b/queue-6.1/series index 32d3b6fb549..367b374d5fa 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -66,3 +66,23 @@ octeontx2-pf-check-negative-error-code-in-otx2_open.patch 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 diff --git a/queue-6.1/tcp-fix-bind-regression-for-v6-only-wildcard-and-v4-.patch b/queue-6.1/tcp-fix-bind-regression-for-v6-only-wildcard-and-v4-.patch new file mode 100644 index 00000000000..f6ee190d6f6 --- /dev/null +++ b/queue-6.1/tcp-fix-bind-regression-for-v6-only-wildcard-and-v4-.patch @@ -0,0 +1,99 @@ +From 961f27c6b980bd03433c02a3b405cc917c093f0f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: Kuniyuki Iwashima +Link: https://lore.kernel.org/r/20240326204251.51301-3-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.1/usb-typec-ucsi-check-for-notifications-after-init.patch b/queue-6.1/usb-typec-ucsi-check-for-notifications-after-init.patch new file mode 100644 index 00000000000..9ec7eea3291 --- /dev/null +++ b/queue-6.1/usb-typec-ucsi-check-for-notifications-after-init.patch @@ -0,0 +1,70 @@ +From ca61215561a0947476576f8ee06c0dca69b25884 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Mar 2024 08:39:23 +0100 +Subject: usb: typec: ucsi: Check for notifications after init + +From: Christian A. Ehrhardt + +[ 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 +Reviewed-by: Heikki Krogerus +Tested-by: Neil Armstrong # on SM8550-QRD +Link: https://lore.kernel.org/r/20240320073927.1641788-3-lk@c--e.de +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 +