* Re:
@ 2011-12-13 2:58 Matt Shaw
0 siblings, 0 replies; 13+ messages in thread
From: Matt Shaw @ 2011-12-13 2:58 UTC (permalink / raw)
To: doshoes1990
https://docs.google.com/document/d/1-MgXERW0_TNnd0VK2caXYhDXtT58z1DJ0laAmJaj=
rEs/edit
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re:
2012-10-30 17:42 ` Yinghai Lu
@ 2012-11-02 0:17 ` Rafael J. Wysocki
2012-11-05 22:27 ` Re: Bjorn Helgaas
2012-11-06 5:03 ` Taku Izumi
1 sibling, 1 reply; 13+ messages in thread
From: Rafael J. Wysocki @ 2012-11-02 0:17 UTC (permalink / raw)
To: Yinghai Lu
Cc: Bjorn Helgaas, Len Brown, Taku Izumi, Jiang Liu, linux-pci,
linux-acpi
Hi,
On Tuesday, October 30, 2012 10:42:37 AM Yinghai Lu wrote:
> Subject: [PATCH resend 0/8] PCI, ACPI, x86: pci root bus hotplug support resources assign and remove path
>
> 1. add support for assign resource for hot add path.
> 2. stop and remove root bus during acpi root remove.
>
>
> could get from
> git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-root-bus-hotplug
>
> Yinghai Lu (8):
> PCI: Separate out pci_assign_unassigned_bus_resources()
> PCI: Move pci_rescan_bus() back to probe.c
> PCI: Move out pci_enable_bridges out of assign_unsigned_bus_res
> PCI, ACPI: assign unassigned resource for hot add root bus
> PCI: Add pci_stop/remove_root_bus()
> PCI, ACPI: Make acpi_pci_root_remove stop/remove pci root bus
> PCI, ACPI: delete root bus prt during hot remove path
> PCI, ACPI: remove acpi_root_driver in reserse order
>
> drivers/acpi/pci_root.c | 21 ++++++++++++++++++++-
> drivers/pci/probe.c | 22 ++++++++++++++++++++++
> drivers/pci/remove.c | 36 ++++++++++++++++++++++++++++++++++++
> drivers/pci/setup-bus.c | 22 +---------------------
> include/linux/pci.h | 3 +++
> 5 files changed, 82 insertions(+), 22 deletions(-)
Please feel free to add
Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
to the ACPI-related patches in this series.
Thanks,
Rafael
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re:
2012-11-02 0:17 ` Rafael J. Wysocki
@ 2012-11-05 22:27 ` Bjorn Helgaas
2012-11-05 22:49 ` Re: Yinghai Lu
0 siblings, 1 reply; 13+ messages in thread
From: Bjorn Helgaas @ 2012-11-05 22:27 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Yinghai Lu, Len Brown, Taku Izumi, Jiang Liu, linux-pci,
linux-acpi
On Thu, Nov 1, 2012 at 6:17 PM, Rafael J. Wysocki <rjw@sisk.pl> wrote:
> Hi,
>
> On Tuesday, October 30, 2012 10:42:37 AM Yinghai Lu wrote:
>> Subject: [PATCH resend 0/8] PCI, ACPI, x86: pci root bus hotplug support resources assign and remove path
>>
>> 1. add support for assign resource for hot add path.
>> 2. stop and remove root bus during acpi root remove.
>>
>>
>> could get from
>> git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-root-bus-hotplug
>>
>> Yinghai Lu (8):
>> PCI: Separate out pci_assign_unassigned_bus_resources()
>> PCI: Move pci_rescan_bus() back to probe.c
>> PCI: Move out pci_enable_bridges out of assign_unsigned_bus_res
>> PCI, ACPI: assign unassigned resource for hot add root bus
>> PCI: Add pci_stop/remove_root_bus()
>> PCI, ACPI: Make acpi_pci_root_remove stop/remove pci root bus
>> PCI, ACPI: delete root bus prt during hot remove path
>> PCI, ACPI: remove acpi_root_driver in reserse order
>>
>> drivers/acpi/pci_root.c | 21 ++++++++++++++++++++-
>> drivers/pci/probe.c | 22 ++++++++++++++++++++++
>> drivers/pci/remove.c | 36 ++++++++++++++++++++++++++++++++++++
>> drivers/pci/setup-bus.c | 22 +---------------------
>> include/linux/pci.h | 3 +++
>> 5 files changed, 82 insertions(+), 22 deletions(-)
>
> Please feel free to add
>
> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> to the ACPI-related patches in this series.
I applied these to my pci/yinghai-for-pci-root-bus-hotplug branch as
v3.8 material. They should appear in "next" tomorrow. Thanks!
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re:
2012-11-05 22:27 ` Re: Bjorn Helgaas
@ 2012-11-05 22:49 ` Yinghai Lu
0 siblings, 0 replies; 13+ messages in thread
From: Yinghai Lu @ 2012-11-05 22:49 UTC (permalink / raw)
To: Bjorn Helgaas
Cc: Rafael J. Wysocki, Len Brown, Taku Izumi, Jiang Liu, linux-pci,
linux-acpi
On Mon, Nov 5, 2012 at 2:27 PM, Bjorn Helgaas <bhelgaas@google.com> wrote:
> I applied these to my pci/yinghai-for-pci-root-bus-hotplug branch as
> v3.8 material. They should appear in "next" tomorrow. Thanks!
Thanks...
please check batch 2 at
https://patchwork.kernel.org/patch/1693211/
Yinghai
^ permalink raw reply [flat|nested] 13+ messages in thread
* RE:
2012-10-30 17:42 ` Yinghai Lu
2012-11-02 0:17 ` Rafael J. Wysocki
@ 2012-11-06 5:03 ` Taku Izumi
1 sibling, 0 replies; 13+ messages in thread
From: Taku Izumi @ 2012-11-06 5:03 UTC (permalink / raw)
To: 'Yinghai Lu'
Cc: linux-pci, linux-acpi, 'Bjorn Helgaas',
'Len Brown', 'Jiang Liu'
Reviewed and tested by Taku Izumi <izumi.taku@jp.fujitsu.com>
> -----Original Message-----
> From: linux-pci-owner@vger.kernel.org [mailto:linux-pci-owner@vger.kernel.org] On Behalf Of Yinghai Lu
> Sent: Wednesday, October 31, 2012 2:43 AM
> To: Bjorn Helgaas; Len Brown; Taku Izumi; Jiang Liu
> Cc: linux-pci@vger.kernel.org; linux-acpi@vger.kernel.org; Yinghai Lu
> Subject:
>
> Subject: [PATCH resend 0/8] PCI, ACPI, x86: pci root bus hotplug support resources assign and remove path
>
> 1. add support for assign resource for hot add path.
> 2. stop and remove root bus during acpi root remove.
>
>
> could get from
> git://git.kernel.org/pub/scm/linux/kernel/git/yinghai/linux-yinghai.git for-pci-root-bus-hotplug
>
> Yinghai Lu (8):
> PCI: Separate out pci_assign_unassigned_bus_resources()
> PCI: Move pci_rescan_bus() back to probe.c
> PCI: Move out pci_enable_bridges out of assign_unsigned_bus_res
> PCI, ACPI: assign unassigned resource for hot add root bus
> PCI: Add pci_stop/remove_root_bus()
> PCI, ACPI: Make acpi_pci_root_remove stop/remove pci root bus
> PCI, ACPI: delete root bus prt during hot remove path
> PCI, ACPI: remove acpi_root_driver in reserse order
>
> drivers/acpi/pci_root.c | 21 ++++++++++++++++++++-
> drivers/pci/probe.c | 22 ++++++++++++++++++++++
> drivers/pci/remove.c | 36 ++++++++++++++++++++++++++++++++++++
> drivers/pci/setup-bus.c | 22 +---------------------
> include/linux/pci.h | 3 +++
> 5 files changed, 82 insertions(+), 22 deletions(-)
>
> --
> 1.7.7
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re:
2025-05-09 17:38 Shawn Anastasio
@ 2025-05-10 19:50 ` Trilok Soni
0 siblings, 0 replies; 13+ messages in thread
From: Trilok Soni @ 2025-05-10 19:50 UTC (permalink / raw)
To: Shawn Anastasio, linux-pci, Lukas Wunner,
Krishna Chaitanya Chundru
Cc: Bjorn Helgaas, Lorenzo Pieralisi, Krzysztof Wilczyński,
Manivannan Sadhasivam, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, chaitanya chundru, Bjorn Andersson, Konrad Dybcio,
cros-qcom-dts-watchers, Jingoo Han, Bartosz Golaszewski,
quic_vbadigan, amitk, devicetree, linux-kernel, linux-arm-msm,
jorge.ramirez, Dmitry Baryshkov, Timothy Pearson
On 5/9/2025 10:38 AM, Shawn Anastasio wrote:
> From: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
>
> Date: Sat, 12 Apr 2025 07:19:56 +0530
> Subject: [PATCH v6] PCI: PCI: Add pcie_link_is_active() to determine if the
> PCIe link is active
I don't understand this patch and it doesn't have any subject in email. Please fix.
>
> Introduce a common API to check if the PCIe link is active, replacing
> duplicate code in multiple locations.
>
> Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com>
> Signed-off-by: Shawn Anastasio <sanastasio@raptorengineering.com>
> ---
> This is an updated patch pulled from Krishna's v5 series:
> https://patchwork.kernel.org/project/linux-pci/list/?series=952665
>
> The following changes to Krishna's v5 were made by me:
> - Revert pcie_link_is_active return type back to int per Lukas' review
> comments
> - Handle non-zero error returns at call site of the new function in
> pci.c/pci_bridge_wait_for_secondary_bus
>
> drivers/pci/hotplug/pciehp.h | 1 -
> drivers/pci/hotplug/pciehp_ctrl.c | 2 +-
> drivers/pci/hotplug/pciehp_hpc.c | 33 +++----------------------------
> drivers/pci/pci.c | 26 +++++++++++++++++++++---
> include/linux/pci.h | 4 ++++
> 5 files changed, 31 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
> index 273dd8c66f4e..acef728530e3 100644
> --- a/drivers/pci/hotplug/pciehp.h
> +++ b/drivers/pci/hotplug/pciehp.h
> @@ -186,7 +186,6 @@ int pciehp_query_power_fault(struct controller *ctrl);
> int pciehp_card_present(struct controller *ctrl);
> int pciehp_card_present_or_link_active(struct controller *ctrl);
> int pciehp_check_link_status(struct controller *ctrl);
> -int pciehp_check_link_active(struct controller *ctrl);
> void pciehp_release_ctrl(struct controller *ctrl);
>
> int pciehp_sysfs_enable_slot(struct hotplug_slot *hotplug_slot);
> diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
> index d603a7aa7483..4bb58ba1c766 100644
> --- a/drivers/pci/hotplug/pciehp_ctrl.c
> +++ b/drivers/pci/hotplug/pciehp_ctrl.c
> @@ -260,7 +260,7 @@ void pciehp_handle_presence_or_link_change(struct controller *ctrl, u32 events)
> /* Turn the slot on if it's occupied or link is up */
> mutex_lock(&ctrl->state_lock);
> present = pciehp_card_present(ctrl);
> - link_active = pciehp_check_link_active(ctrl);
> + link_active = pcie_link_is_active(ctrl->pcie->port);
> if (present <= 0 && link_active <= 0) {
> if (ctrl->state == BLINKINGON_STATE) {
> ctrl->state = OFF_STATE;
> diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
> index 8a09fb6083e2..278bc21d531d 100644
> --- a/drivers/pci/hotplug/pciehp_hpc.c
> +++ b/drivers/pci/hotplug/pciehp_hpc.c
> @@ -221,33 +221,6 @@ static void pcie_write_cmd_nowait(struct controller *ctrl, u16 cmd, u16 mask)
> pcie_do_write_cmd(ctrl, cmd, mask, false);
> }
>
> -/**
> - * pciehp_check_link_active() - Is the link active
> - * @ctrl: PCIe hotplug controller
> - *
> - * Check whether the downstream link is currently active. Note it is
> - * possible that the card is removed immediately after this so the
> - * caller may need to take it into account.
> - *
> - * If the hotplug controller itself is not available anymore returns
> - * %-ENODEV.
> - */
> -int pciehp_check_link_active(struct controller *ctrl)
> -{
> - struct pci_dev *pdev = ctrl_dev(ctrl);
> - u16 lnk_status;
> - int ret;
> -
> - ret = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);
> - if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status))
> - return -ENODEV;
> -
> - ret = !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);
> - ctrl_dbg(ctrl, "%s: lnk_status = %x\n", __func__, lnk_status);
> -
> - return ret;
> -}
> -
> static bool pci_bus_check_dev(struct pci_bus *bus, int devfn)
> {
> u32 l;
> @@ -467,7 +440,7 @@ int pciehp_card_present_or_link_active(struct controller *ctrl)
> if (ret)
> return ret;
>
> - return pciehp_check_link_active(ctrl);
> + return pcie_link_is_active(ctrl_dev(ctrl));
> }
>
> int pciehp_query_power_fault(struct controller *ctrl)
> @@ -584,7 +557,7 @@ static void pciehp_ignore_dpc_link_change(struct controller *ctrl,
> * Synthesize it to ensure that it is acted on.
> */
> down_read_nested(&ctrl->reset_lock, ctrl->depth);
> - if (!pciehp_check_link_active(ctrl))
> + if (!pcie_link_is_active(ctrl_dev(ctrl)))
> pciehp_request(ctrl, PCI_EXP_SLTSTA_DLLSC);
> up_read(&ctrl->reset_lock);
> }
> @@ -884,7 +857,7 @@ int pciehp_slot_reset(struct pcie_device *dev)
> pcie_capability_write_word(dev->port, PCI_EXP_SLTSTA,
> PCI_EXP_SLTSTA_DLLSC);
>
> - if (!pciehp_check_link_active(ctrl))
> + if (!pcie_link_is_active(ctrl_dev(ctrl)))
> pciehp_request(ctrl, PCI_EXP_SLTSTA_DLLSC);
>
> return 0;
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index e77d5b53c0ce..3bb8354b14bf 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -4926,7 +4926,6 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type)
> return 0;
>
> if (pcie_get_speed_cap(dev) <= PCIE_SPEED_5_0GT) {
> - u16 status;
>
> pci_dbg(dev, "waiting %d ms for downstream link\n", delay);
> msleep(delay);
> @@ -4942,8 +4941,7 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type)
> if (!dev->link_active_reporting)
> return -ENOTTY;
>
> - pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &status);
> - if (!(status & PCI_EXP_LNKSTA_DLLLA))
> + if (pcie_link_is_active(dev) <= 0)
> return -ENOTTY;
>
> return pci_dev_wait(child, reset_type,
> @@ -6247,6 +6245,28 @@ void pcie_print_link_status(struct pci_dev *dev)
> }
> EXPORT_SYMBOL(pcie_print_link_status);
>
> +/**
> + * pcie_link_is_active() - Checks if the link is active or not
> + * @pdev: PCI device to query
> + *
> + * Check whether the link is active or not.
> + *
> + * Return: link state, or -ENODEV if the config read failes.
> + */
> +int pcie_link_is_active(struct pci_dev *pdev)
> +{
> + u16 lnk_status;
> + int ret;
> +
> + ret = pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnk_status);
> + if (ret == PCIBIOS_DEVICE_NOT_FOUND || PCI_POSSIBLE_ERROR(lnk_status))
> + return -ENODEV;
> +
> + pci_dbg(pdev, "lnk_status = %x\n", lnk_status);
> + return !!(lnk_status & PCI_EXP_LNKSTA_DLLLA);
> +}
> +EXPORT_SYMBOL(pcie_link_is_active);
> +
> /**
> * pci_select_bars - Make BAR mask from the type of resource
> * @dev: the PCI device for which BAR mask is made
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 51e2bd6405cd..a79a9919320c 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1945,6 +1945,7 @@ pci_release_mem_regions(struct pci_dev *pdev)
> pci_select_bars(pdev, IORESOURCE_MEM));
> }
>
> +int pcie_link_is_active(struct pci_dev *dev);
> #else /* CONFIG_PCI is not enabled */
>
> static inline void pci_set_flags(int flags) { }
> @@ -2093,6 +2094,9 @@ pci_alloc_irq_vectors(struct pci_dev *dev, unsigned int min_vecs,
> {
> return -ENOSPC;
> }
> +
> +static inline bool pcie_link_is_active(struct pci_dev *dev)
> +{ return false; }
> #endif /* CONFIG_PCI */
>
> /* Include architecture-dependent settings and functions */
> --
> 2.30.2
>
>
--
---Trilok Soni
^ permalink raw reply [flat|nested] 13+ messages in thread
* (no subject)
@ 2026-04-28 18:24 Fabio M. De Francesco
2026-04-28 18:24 ` [PATCH 1/2] PCI/CXL: Allow PM Init to complete on cxl_bus reset if ACS SV enabled Fabio M. De Francesco
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: Fabio M. De Francesco @ 2026-04-28 18:24 UTC (permalink / raw)
To: linux-cxl
Cc: Davidlohr Bueso, Jonathan Cameron, Dave Jiang, Alison Schofield,
Vishal Verma, Ira Weiny, Dan Williams, Bjorn Helgaas,
linux-kernel, linux-pci, Fabio M. De Francesco
Subject: [PATCH 0/2] PCI/CXL: Recover CXL Downstream Ports from PM Init failure
CXL r4.0 sec 8.1.5.1 Implementation Note describes a scenario in which a
Secondary Bus Reset, a Link Down, or Downstream Port Containment on a
CXL Downstream Port prevents Port PM Init from completing when ACS
Source Validation is enabled on the Downstream Port. The spec states
that another SBR alone does not recover the port and describes a
software recovery sequence.
Patch 1 extends cxl_reset_bus_function(), the helper backing the cxl_bus
PCI/CXL reset method exposed to userspace via sysfs. It saves, clears,
and restores ACS Source Validation and Bus Master Enable on the CXL
Downstream Port around the SBR it issues. This keeps the userspace
cxl_bus reset path from leaving the port unable to complete PM Init.
Patch 2 adds a recovery pass during CXL enumeration. For each CXL
Downstream Port in a memdev's ancestry, the CXL core checks whether PM
Init has completed. If it has not, regardless of what caused the
failure, it invokes cxl_reset_bus_function() on the child below the port
in the hope of restoring the port to a usable state. CXL enumeration
re-runs after events that tear down and re-probe the memdev, including
DPC, AER, and Link Down, so those paths reach this recovery.
This small series is developed from an old RFC v3:
https://lore.kernel.org/linux-cxl/20260330193347.25072-1-fabio.m.de.francesco@linux.intel.com/
Fabio M. De Francesco (2):
PCI/CXL: Allow PM Init to complete on cxl_bus reset if ACS SV enabled
cxl/core: Recover from PM Init failure via cxl_reset_bus_function()
drivers/cxl/core/pci.c | 30 ++++++++++++++++++++
drivers/cxl/core/port.c | 22 +++++++++++++++
drivers/cxl/cxlpci.h | 3 ++
drivers/pci/pci.c | 52 ++++++++++++++++++++++++++++++++++-
include/linux/pci.h | 1 +
include/uapi/linux/pci_regs.h | 2 ++
6 files changed, 109 insertions(+), 1 deletion(-)
--
2.53.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/2] PCI/CXL: Allow PM Init to complete on cxl_bus reset if ACS SV enabled
2026-04-28 18:24 Fabio M. De Francesco
@ 2026-04-28 18:24 ` Fabio M. De Francesco
2026-05-01 18:36 ` Dave Jiang
2026-04-28 18:24 ` [PATCH 2/2] cxl/core: Recover from PM Init failure via cxl_reset_bus_function() Fabio M. De Francesco
2026-05-01 22:01 ` Dave Jiang
2 siblings, 1 reply; 13+ messages in thread
From: Fabio M. De Francesco @ 2026-04-28 18:24 UTC (permalink / raw)
To: linux-cxl
Cc: Davidlohr Bueso, Jonathan Cameron, Dave Jiang, Alison Schofield,
Vishal Verma, Ira Weiny, Dan Williams, Bjorn Helgaas,
linux-kernel, linux-pci, Fabio M. De Francesco
CXL r4.0 sec 8.1.5.1 Implementation Note describes a scenario in which
issuing a Secondary Bus Reset on a CXL Downstream Port leaves the
Port Power Management Initialization Complete bit unset when the PCIe
Access Control Service (ACS) Source Validation bit (SV) is enabled on
the Downstream Port. The spec states that another SBR alone will not
facilitate recovery and shows a software recovery sequence.
Implement the sequence by extending cxl_reset_bus_function() to save,
clear, and restore ACS SV and Bus Master Enable (BME) on the Downstream
Port around the SBR with the use of helpers.
The wait inside pci_bridge_secondary_bus_reset() covers the 100 ms
referenced by the spec. The helpers return when ACS SV is not enabled on
the Downstream Port.
Signed-off-by: Fabio M. De Francesco <fabio.m.de.francesco@linux.intel.com>
---
drivers/pci/pci.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 49 insertions(+)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 8f7cfcc00090..047d3b4508a5 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4930,10 +4930,55 @@ static int pci_reset_bus_function(struct pci_dev *dev, bool probe)
return rc;
}
+static void cxl_disable_acs_sv_bme(struct pci_dev *bridge, u16 *saved_cmd,
+ u16 *saved_acs_ctrl)
+{
+ if (!bridge->acs_cap)
+ return;
+
+ pci_read_config_word(bridge, bridge->acs_cap + PCI_ACS_CTRL,
+ saved_acs_ctrl);
+ if (!(*saved_acs_ctrl & PCI_ACS_SV))
+ return;
+
+ pci_read_config_word(bridge, PCI_COMMAND, saved_cmd);
+ if (*saved_cmd & PCI_COMMAND_MASTER)
+ pci_clear_master(bridge);
+
+ pci_write_config_word(bridge, bridge->acs_cap + PCI_ACS_CTRL,
+ *saved_acs_ctrl & ~PCI_ACS_SV);
+}
+
+static void cxl_restore_acs_sv_bme(struct pci_dev *bridge, u16 saved_cmd,
+ u16 saved_acs_ctrl)
+{
+ if (!bridge->acs_cap || !(saved_acs_ctrl & PCI_ACS_SV))
+ return;
+
+ pci_write_config_word(bridge, bridge->acs_cap + PCI_ACS_CTRL,
+ saved_acs_ctrl);
+ if (saved_cmd & PCI_COMMAND_MASTER)
+ pci_set_master(bridge);
+}
+
+/**
+ * cxl_reset_bus_function - SBR for a child of a CXL downstream port
+ * @dev: child device whose upstream bridge is a CXL downstream port
+ * @probe: if true, only check whether the reset is supported
+ *
+ * Issues an SBR on @dev's parent bus. Temporarily sets the CXL Port
+ * DVSEC Unmask SBR bit across the reset. When ACS Source Validation
+ * is enabled on the bridge, also temporarily clears Bus Master Enable
+ * and ACS Source Validation, per CXL r4.0 sec 8.1.5.1.
+ *
+ * Return: 0 on success, -ENOTTY if the reset cannot be issued, or an
+ * errno from the reset path.
+ */
static int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
{
struct pci_dev *bridge;
u16 dvsec, reg, val;
+ u16 saved_cmd = 0, saved_acs_ctrl = 0;
int rc;
bridge = pci_upstream_bridge(dev);
@@ -4957,6 +5002,8 @@ static int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
return rc;
}
+ cxl_disable_acs_sv_bme(bridge, &saved_cmd, &saved_acs_ctrl);
+
if (reg & PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR) {
val = reg;
} else {
@@ -4971,6 +5018,8 @@ static int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
pci_write_config_word(bridge, dvsec + PCI_DVSEC_CXL_PORT_CTL,
reg);
+ cxl_restore_acs_sv_bme(bridge, saved_cmd, saved_acs_ctrl);
+
pci_dev_reset_iommu_done(dev);
return rc;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/2] cxl/core: Recover from PM Init failure via cxl_reset_bus_function()
2026-04-28 18:24 Fabio M. De Francesco
2026-04-28 18:24 ` [PATCH 1/2] PCI/CXL: Allow PM Init to complete on cxl_bus reset if ACS SV enabled Fabio M. De Francesco
@ 2026-04-28 18:24 ` Fabio M. De Francesco
2026-05-01 21:59 ` Dave Jiang
2026-05-06 5:54 ` Alison Schofield
2026-05-01 22:01 ` Dave Jiang
2 siblings, 2 replies; 13+ messages in thread
From: Fabio M. De Francesco @ 2026-04-28 18:24 UTC (permalink / raw)
To: linux-cxl
Cc: Davidlohr Bueso, Jonathan Cameron, Dave Jiang, Alison Schofield,
Vishal Verma, Ira Weiny, Dan Williams, Bjorn Helgaas,
linux-kernel, linux-pci, Fabio M. De Francesco
CXL r4.0 sec 8.1.5.1 Implementation Note describes a scenario in which a
Secondary Bus Reset, a Link Down, or Downstream Port Containment on a
CXL Downstream Port prevents Port PM Init from completing when ACS
Source Validation is enabled.
During CXL enumeration, for each CXL Downstream Port in a memdev's
ancestry, check whether PM Init has completed. If it has not, invoke
cxl_reset_bus_function() which is exported for use by CXL.
Signed-off-by: Fabio M. De Francesco <fabio.m.de.francesco@linux.intel.com>
---
drivers/cxl/core/pci.c | 30 ++++++++++++++++++++++++++++++
drivers/cxl/core/port.c | 22 ++++++++++++++++++++++
drivers/cxl/cxlpci.h | 3 +++
drivers/pci/pci.c | 3 ++-
include/linux/pci.h | 1 +
include/uapi/linux/pci_regs.h | 2 ++
6 files changed, 60 insertions(+), 1 deletion(-)
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index d1f487b3d809..de6a317df650 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -926,3 +926,33 @@ int cxl_port_get_possible_dports(struct cxl_port *port)
return ctx.count;
}
+
+/**
+ * cxl_port_pm_init_is_complete - check the downstream port's PM Init Complete
+ * @pdev: downstream port
+ *
+ * Read the Port Power Management Initialization Complete bit in the
+ * Downstream Port's CXL DVSEC Port Extended Status register.
+ *
+ * Return: false only when the bit is observably clear. Return true when PM
+ * init is complete, when @pdev is not a CXL port (no Port DVSEC), or when
+ * the status register cannot be read.
+ */
+bool cxl_port_pm_init_is_complete(struct pci_dev *pdev)
+{
+ u16 status;
+ u16 dvsec;
+ int rc;
+
+ dvsec = pci_find_dvsec_capability(pdev, PCI_VENDOR_ID_CXL,
+ PCI_DVSEC_CXL_PORT);
+ if (!dvsec)
+ return true;
+
+ rc = pci_read_config_word(pdev, dvsec + PCI_DVSEC_CXL_PORT_EXT_STATUS,
+ &status);
+ if (rc || PCI_POSSIBLE_ERROR(status))
+ return true;
+
+ return !!FIELD_GET(PCI_DVSEC_CXL_PORT_EXT_STATUS_PM_INIT_COMP, status);
+}
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index c5aacd7054f1..a91841855d3b 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -1825,6 +1825,28 @@ int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd)
if (is_cxl_host_bridge(dport_dev))
return 0;
+ /*
+ * Check the downstream port's PM init status, and if it has
+ * failed retry PM init according to CXL Spec. 4.0 Sect. 8.1.5.1
+ * - Implementation Note
+ */
+ if (dev_is_pci(dport_dev) && dev_is_pci(iter->parent)) {
+ struct pci_dev *dport_pdev = to_pci_dev(dport_dev);
+
+ if (!cxl_port_pm_init_is_complete(dport_pdev)) {
+ dev_dbg(&cxlmd->dev,
+ "PM init failed for %s, retrying PM init\n",
+ dev_name(dport_dev));
+
+ cxl_reset_bus_function(to_pci_dev(iter->parent), false);
+
+ if (!cxl_port_pm_init_is_complete(dport_pdev))
+ dev_dbg(&cxlmd->dev,
+ "PM init failed retry for %s\n",
+ dev_name(dport_dev));
+ }
+ }
+
uport_dev = dport_dev->parent;
if (!uport_dev) {
dev_warn(dev, "at %s no parent for dport: %s\n",
diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h
index b826eb53cf7b..c66ff2ce82a3 100644
--- a/drivers/cxl/cxlpci.h
+++ b/drivers/cxl/cxlpci.h
@@ -114,4 +114,7 @@ static inline void devm_cxl_port_ras_setup(struct cxl_port *port)
int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
struct cxl_register_map *map);
+
+bool cxl_port_pm_init_is_complete(struct pci_dev *pdev);
+
#endif /* __CXL_PCI_H__ */
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 047d3b4508a5..ae30da22daf4 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -4974,7 +4974,7 @@ static void cxl_restore_acs_sv_bme(struct pci_dev *bridge, u16 saved_cmd,
* Return: 0 on success, -ENOTTY if the reset cannot be issued, or an
* errno from the reset path.
*/
-static int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
+int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
{
struct pci_dev *bridge;
u16 dvsec, reg, val;
@@ -5023,6 +5023,7 @@ static int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
pci_dev_reset_iommu_done(dev);
return rc;
}
+EXPORT_SYMBOL_NS_GPL(cxl_reset_bus_function, "CXL");
void pci_dev_lock(struct pci_dev *dev)
{
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 2c4454583c11..1fb1360d41e8 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1477,6 +1477,7 @@ int pci_probe_reset_slot(struct pci_slot *slot);
int pci_probe_reset_bus(struct pci_bus *bus);
int pci_reset_bus(struct pci_dev *dev);
void pci_reset_secondary_bus(struct pci_dev *dev);
+int cxl_reset_bus_function(struct pci_dev *dev, bool probe);
void pcibios_reset_secondary_bus(struct pci_dev *dev);
void pci_update_resource(struct pci_dev *dev, int resno);
int __must_check pci_assign_resource(struct pci_dev *dev, int i);
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index 14f634ab9350..7e2579f89041 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -1369,6 +1369,8 @@
/* CXL r4.0, 8.1.5: Extensions DVSEC for Ports */
#define PCI_DVSEC_CXL_PORT 3
+#define PCI_DVSEC_CXL_PORT_EXT_STATUS 0x0A
+#define PCI_DVSEC_CXL_PORT_EXT_STATUS_PM_INIT_COMP _BITUL(0)
#define PCI_DVSEC_CXL_PORT_CTL 0x0c
#define PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR 0x00000001
--
2.53.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 1/2] PCI/CXL: Allow PM Init to complete on cxl_bus reset if ACS SV enabled
2026-04-28 18:24 ` [PATCH 1/2] PCI/CXL: Allow PM Init to complete on cxl_bus reset if ACS SV enabled Fabio M. De Francesco
@ 2026-05-01 18:36 ` Dave Jiang
0 siblings, 0 replies; 13+ messages in thread
From: Dave Jiang @ 2026-05-01 18:36 UTC (permalink / raw)
To: Fabio M. De Francesco, linux-cxl
Cc: Davidlohr Bueso, Alison Schofield, Vishal Verma, Ira Weiny,
Bjorn Helgaas, linux-kernel, linux-pci, Jonathan Cameron,
Dan Williams
On 4/28/26 11:24 AM, Fabio M. De Francesco wrote:
> CXL r4.0 sec 8.1.5.1 Implementation Note describes a scenario in which
> issuing a Secondary Bus Reset on a CXL Downstream Port leaves the
> Port Power Management Initialization Complete bit unset when the PCIe
> Access Control Service (ACS) Source Validation bit (SV) is enabled on
> the Downstream Port. The spec states that another SBR alone will not
> facilitate recovery and shows a software recovery sequence.
>
> Implement the sequence by extending cxl_reset_bus_function() to save,
> clear, and restore ACS SV and Bus Master Enable (BME) on the Downstream
> Port around the SBR with the use of helpers.
>
> The wait inside pci_bridge_secondary_bus_reset() covers the 100 ms
> referenced by the spec. The helpers return when ACS SV is not enabled on
> the Downstream Port.
>
> Signed-off-by: Fabio M. De Francesco <fabio.m.de.francesco@linux.intel.com>
> ---
> drivers/pci/pci.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 49 insertions(+)
>
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 8f7cfcc00090..047d3b4508a5 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -4930,10 +4930,55 @@ static int pci_reset_bus_function(struct pci_dev *dev, bool probe)
> return rc;
> }
>
> +static void cxl_disable_acs_sv_bme(struct pci_dev *bridge, u16 *saved_cmd,
> + u16 *saved_acs_ctrl)
Maybe you can call this 'cxl_bus_reset_prep' and the restore one 'cxl_bus_reset_done'?
> +{
Should you return int and check if the two ptr passed in are valid?
> + if (!bridge->acs_cap)
> + return;
Returning here and the output parameters are not set. That is a problem when you try to restore with invalid values. Maybe -EOPNOTSUPP needs to be returned. Errno from this function should prevent the restore from being called.
> +
> + pci_read_config_word(bridge, bridge->acs_cap + PCI_ACS_CTRL,
> + saved_acs_ctrl);
> + if (!(*saved_acs_ctrl & PCI_ACS_SV))
> + return;
What is the caller suppose to do if PCI_ACS_SV is not set? Should you skip restore later?
> +
> + pci_read_config_word(bridge, PCI_COMMAND, saved_cmd);
> + if (*saved_cmd & PCI_COMMAND_MASTER)
If all you care is master bit enabled, maybe just write back a bool 'master_en'.
> + pci_clear_master(bridge);
> +
> + pci_write_config_word(bridge, bridge->acs_cap + PCI_ACS_CTRL,
> + *saved_acs_ctrl & ~PCI_ACS_SV);
> +}
> +
> +static void cxl_restore_acs_sv_bme(struct pci_dev *bridge, u16 saved_cmd,
> + u16 saved_acs_ctrl)
static void cxl_bus_reset_done(struct pci_dev *bridge, bool master_en, u16 acs_ctrl)
saved_ has no relevance to the function itself.
Come to think of it, why not create a local struct and pass that in as parameter for prep and done functions? That way in the future if there are other stuff that needs to be done, this can be more versatile.
struct cxl_reset_ctx {
u16 acs_ctrl;
bool master_en;
bool acs_restore;
};
This way you can also set 'acs_restore' on completion of the prep function. And in the done function, you can check and return early if it's not set. That takes away the messiness of returning errno in the prep function and then needing to determine if you need to call the prep function or not.
DJ
> +{
> + if (!bridge->acs_cap || !(saved_acs_ctrl & PCI_ACS_SV))
> + return;
> +
> + pci_write_config_word(bridge, bridge->acs_cap + PCI_ACS_CTRL,
> + saved_acs_ctrl);
> + if (saved_cmd & PCI_COMMAND_MASTER)
> + pci_set_master(bridge);
> +}
> +
> +/**
> + * cxl_reset_bus_function - SBR for a child of a CXL downstream port
> + * @dev: child device whose upstream bridge is a CXL downstream port
> + * @probe: if true, only check whether the reset is supported
> + *
> + * Issues an SBR on @dev's parent bus. Temporarily sets the CXL Port
> + * DVSEC Unmask SBR bit across the reset. When ACS Source Validation
> + * is enabled on the bridge, also temporarily clears Bus Master Enable
> + * and ACS Source Validation, per CXL r4.0 sec 8.1.5.1.
> + *
> + * Return: 0 on success, -ENOTTY if the reset cannot be issued, or an
> + * errno from the reset path.
> + */
> static int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
> {
> struct pci_dev *bridge;
> u16 dvsec, reg, val;
> + u16 saved_cmd = 0, saved_acs_ctrl = 0;
> int rc;
>
> bridge = pci_upstream_bridge(dev);
> @@ -4957,6 +5002,8 @@ static int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
> return rc;
> }
>
> + cxl_disable_acs_sv_bme(bridge, &saved_cmd, &saved_acs_ctrl);
> +
> if (reg & PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR) {
> val = reg;
> } else {
> @@ -4971,6 +5018,8 @@ static int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
> pci_write_config_word(bridge, dvsec + PCI_DVSEC_CXL_PORT_CTL,
> reg);
>
> + cxl_restore_acs_sv_bme(bridge, saved_cmd, saved_acs_ctrl);
> +
> pci_dev_reset_iommu_done(dev);
> return rc;
> }
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] cxl/core: Recover from PM Init failure via cxl_reset_bus_function()
2026-04-28 18:24 ` [PATCH 2/2] cxl/core: Recover from PM Init failure via cxl_reset_bus_function() Fabio M. De Francesco
@ 2026-05-01 21:59 ` Dave Jiang
2026-05-06 5:54 ` Alison Schofield
1 sibling, 0 replies; 13+ messages in thread
From: Dave Jiang @ 2026-05-01 21:59 UTC (permalink / raw)
To: Fabio M. De Francesco, linux-cxl
Cc: Davidlohr Bueso, Jonathan Cameron, Alison Schofield, Vishal Verma,
Ira Weiny, Dan Williams, Bjorn Helgaas, linux-kernel, linux-pci
On 4/28/26 11:24 AM, Fabio M. De Francesco wrote:
> CXL r4.0 sec 8.1.5.1 Implementation Note describes a scenario in which a
> Secondary Bus Reset, a Link Down, or Downstream Port Containment on a
> CXL Downstream Port prevents Port PM Init from completing when ACS
> Source Validation is enabled.
>
> During CXL enumeration, for each CXL Downstream Port in a memdev's
> ancestry, check whether PM Init has completed. If it has not, invoke
> cxl_reset_bus_function() which is exported for use by CXL.
>
> Signed-off-by: Fabio M. De Francesco <fabio.m.de.francesco@linux.intel.com>
> ---
> drivers/cxl/core/pci.c | 30 ++++++++++++++++++++++++++++++
> drivers/cxl/core/port.c | 22 ++++++++++++++++++++++
> drivers/cxl/cxlpci.h | 3 +++
> drivers/pci/pci.c | 3 ++-
> include/linux/pci.h | 1 +
> include/uapi/linux/pci_regs.h | 2 ++
> 6 files changed, 60 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index d1f487b3d809..de6a317df650 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -926,3 +926,33 @@ int cxl_port_get_possible_dports(struct cxl_port *port)
>
> return ctx.count;
> }
> +
> +/**
> + * cxl_port_pm_init_is_complete - check the downstream port's PM Init Complete
> + * @pdev: downstream port
> + *
> + * Read the Port Power Management Initialization Complete bit in the
> + * Downstream Port's CXL DVSEC Port Extended Status register.
> + *
> + * Return: false only when the bit is observably clear. Return true when PM
> + * init is complete, when @pdev is not a CXL port (no Port DVSEC), or when
> + * the status register cannot be read.
> + */
> +bool cxl_port_pm_init_is_complete(struct pci_dev *pdev)
> +{
> + u16 status;
> + u16 dvsec;
> + int rc;
> +
> + dvsec = pci_find_dvsec_capability(pdev, PCI_VENDOR_ID_CXL,
> + PCI_DVSEC_CXL_PORT);
> + if (!dvsec)
> + return true;
> +
> + rc = pci_read_config_word(pdev, dvsec + PCI_DVSEC_CXL_PORT_EXT_STATUS,
> + &status);
> + if (rc || PCI_POSSIBLE_ERROR(status))
> + return true;
> +
> + return !!FIELD_GET(PCI_DVSEC_CXL_PORT_EXT_STATUS_PM_INIT_COMP, status);
> +}
> diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
> index c5aacd7054f1..a91841855d3b 100644
> --- a/drivers/cxl/core/port.c
> +++ b/drivers/cxl/core/port.c
> @@ -1825,6 +1825,28 @@ int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd)
> if (is_cxl_host_bridge(dport_dev))
> return 0;
>
> + /*
> + * Check the downstream port's PM init status, and if it has
> + * failed retry PM init according to CXL Spec. 4.0 Sect. 8.1.5.1
> + * - Implementation Note
> + */
> + if (dev_is_pci(dport_dev) && dev_is_pci(iter->parent)) {
> + struct pci_dev *dport_pdev = to_pci_dev(dport_dev);
> +
> + if (!cxl_port_pm_init_is_complete(dport_pdev)) {
> + dev_dbg(&cxlmd->dev,
> + "PM init failed for %s, retrying PM init\n",
> + dev_name(dport_dev));
> +
> + cxl_reset_bus_function(to_pci_dev(iter->parent), false);
> +
> + if (!cxl_port_pm_init_is_complete(dport_pdev))
> + dev_dbg(&cxlmd->dev,
> + "PM init failed retry for %s\n",
> + dev_name(dport_dev));
> + }
> + }
Make this a helper function and move it to core/pci.c. Also pass 'struct device' and not 'struct pci_dev' to that function.
I do wonder if you reset it here, maybe you need to restart enumeration from the endpoint instead of just continuing as if nothing happened.
DJ
> +
> uport_dev = dport_dev->parent;
> if (!uport_dev) {
> dev_warn(dev, "at %s no parent for dport: %s\n",
> diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h
> index b826eb53cf7b..c66ff2ce82a3 100644
> --- a/drivers/cxl/cxlpci.h
> +++ b/drivers/cxl/cxlpci.h
> @@ -114,4 +114,7 @@ static inline void devm_cxl_port_ras_setup(struct cxl_port *port)
>
> int cxl_pci_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
> struct cxl_register_map *map);
> +
> +bool cxl_port_pm_init_is_complete(struct pci_dev *pdev);
> +
> #endif /* __CXL_PCI_H__ */
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 047d3b4508a5..ae30da22daf4 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -4974,7 +4974,7 @@ static void cxl_restore_acs_sv_bme(struct pci_dev *bridge, u16 saved_cmd,
> * Return: 0 on success, -ENOTTY if the reset cannot be issued, or an
> * errno from the reset path.
> */
> -static int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
> +int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
> {
> struct pci_dev *bridge;
> u16 dvsec, reg, val;
> @@ -5023,6 +5023,7 @@ static int cxl_reset_bus_function(struct pci_dev *dev, bool probe)
> pci_dev_reset_iommu_done(dev);
> return rc;
> }
> +EXPORT_SYMBOL_NS_GPL(cxl_reset_bus_function, "CXL");
>
> void pci_dev_lock(struct pci_dev *dev)
> {
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 2c4454583c11..1fb1360d41e8 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -1477,6 +1477,7 @@ int pci_probe_reset_slot(struct pci_slot *slot);
> int pci_probe_reset_bus(struct pci_bus *bus);
> int pci_reset_bus(struct pci_dev *dev);
> void pci_reset_secondary_bus(struct pci_dev *dev);
> +int cxl_reset_bus_function(struct pci_dev *dev, bool probe);
> void pcibios_reset_secondary_bus(struct pci_dev *dev);
> void pci_update_resource(struct pci_dev *dev, int resno);
> int __must_check pci_assign_resource(struct pci_dev *dev, int i);
> diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
> index 14f634ab9350..7e2579f89041 100644
> --- a/include/uapi/linux/pci_regs.h
> +++ b/include/uapi/linux/pci_regs.h
> @@ -1369,6 +1369,8 @@
>
> /* CXL r4.0, 8.1.5: Extensions DVSEC for Ports */
> #define PCI_DVSEC_CXL_PORT 3
> +#define PCI_DVSEC_CXL_PORT_EXT_STATUS 0x0A
> +#define PCI_DVSEC_CXL_PORT_EXT_STATUS_PM_INIT_COMP _BITUL(0)
> #define PCI_DVSEC_CXL_PORT_CTL 0x0c
> #define PCI_DVSEC_CXL_PORT_CTL_UNMASK_SBR 0x00000001
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re:
2026-04-28 18:24 Fabio M. De Francesco
2026-04-28 18:24 ` [PATCH 1/2] PCI/CXL: Allow PM Init to complete on cxl_bus reset if ACS SV enabled Fabio M. De Francesco
2026-04-28 18:24 ` [PATCH 2/2] cxl/core: Recover from PM Init failure via cxl_reset_bus_function() Fabio M. De Francesco
@ 2026-05-01 22:01 ` Dave Jiang
2 siblings, 0 replies; 13+ messages in thread
From: Dave Jiang @ 2026-05-01 22:01 UTC (permalink / raw)
To: Fabio M. De Francesco, linux-cxl
Cc: Davidlohr Bueso, Jonathan Cameron, Alison Schofield, Vishal Verma,
Ira Weiny, Dan Williams, Bjorn Helgaas, linux-kernel, linux-pci
On 4/28/26 11:24 AM, Fabio M. De Francesco wrote:
> Subject: [PATCH 0/2] PCI/CXL: Recover CXL Downstream Ports from PM Init failure
>
> CXL r4.0 sec 8.1.5.1 Implementation Note describes a scenario in which a
> Secondary Bus Reset, a Link Down, or Downstream Port Containment on a
I'm not sure if this series covers a Link Down event (i.e. hotplug). As I recall, cxl_reset_bus_function() only happens via sysfs trigger.
DJ
> CXL Downstream Port prevents Port PM Init from completing when ACS
> Source Validation is enabled on the Downstream Port. The spec states
> that another SBR alone does not recover the port and describes a
> software recovery sequence.
>
> Patch 1 extends cxl_reset_bus_function(), the helper backing the cxl_bus
> PCI/CXL reset method exposed to userspace via sysfs. It saves, clears,
> and restores ACS Source Validation and Bus Master Enable on the CXL
> Downstream Port around the SBR it issues. This keeps the userspace
> cxl_bus reset path from leaving the port unable to complete PM Init.
>
> Patch 2 adds a recovery pass during CXL enumeration. For each CXL
> Downstream Port in a memdev's ancestry, the CXL core checks whether PM
> Init has completed. If it has not, regardless of what caused the
> failure, it invokes cxl_reset_bus_function() on the child below the port
> in the hope of restoring the port to a usable state. CXL enumeration
> re-runs after events that tear down and re-probe the memdev, including
> DPC, AER, and Link Down, so those paths reach this recovery.
>
> This small series is developed from an old RFC v3:
> https://lore.kernel.org/linux-cxl/20260330193347.25072-1-fabio.m.de.francesco@linux.intel.com/
>
> Fabio M. De Francesco (2):
> PCI/CXL: Allow PM Init to complete on cxl_bus reset if ACS SV enabled
> cxl/core: Recover from PM Init failure via cxl_reset_bus_function()
>
> drivers/cxl/core/pci.c | 30 ++++++++++++++++++++
> drivers/cxl/core/port.c | 22 +++++++++++++++
> drivers/cxl/cxlpci.h | 3 ++
> drivers/pci/pci.c | 52 ++++++++++++++++++++++++++++++++++-
> include/linux/pci.h | 1 +
> include/uapi/linux/pci_regs.h | 2 ++
> 6 files changed, 109 insertions(+), 1 deletion(-)
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 2/2] cxl/core: Recover from PM Init failure via cxl_reset_bus_function()
2026-04-28 18:24 ` [PATCH 2/2] cxl/core: Recover from PM Init failure via cxl_reset_bus_function() Fabio M. De Francesco
2026-05-01 21:59 ` Dave Jiang
@ 2026-05-06 5:54 ` Alison Schofield
1 sibling, 0 replies; 13+ messages in thread
From: Alison Schofield @ 2026-05-06 5:54 UTC (permalink / raw)
To: Fabio M. De Francesco
Cc: linux-cxl, Davidlohr Bueso, Jonathan Cameron, Dave Jiang,
Vishal Verma, Ira Weiny, Dan Williams, Bjorn Helgaas,
linux-kernel, linux-pci
On Tue, Apr 28, 2026 at 08:24:35PM +0200, Fabio M. De Francesco wrote:
> CXL r4.0 sec 8.1.5.1 Implementation Note describes a scenario in which a
> Secondary Bus Reset, a Link Down, or Downstream Port Containment on a
> CXL Downstream Port prevents Port PM Init from completing when ACS
> Source Validation is enabled.
>
> During CXL enumeration, for each CXL Downstream Port in a memdev's
> ancestry, check whether PM Init has completed. If it has not, invoke
> cxl_reset_bus_function() which is exported for use by CXL.
Hi Fabio, Not a full review yet, but that !! caught my eye, so...
>
> Signed-off-by: Fabio M. De Francesco <fabio.m.de.francesco@linux.intel.com>
> ---
> drivers/cxl/core/pci.c | 30 ++++++++++++++++++++++++++++++
> drivers/cxl/core/port.c | 22 ++++++++++++++++++++++
> drivers/cxl/cxlpci.h | 3 +++
> drivers/pci/pci.c | 3 ++-
> include/linux/pci.h | 1 +
> include/uapi/linux/pci_regs.h | 2 ++
> 6 files changed, 60 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
> index d1f487b3d809..de6a317df650 100644
> --- a/drivers/cxl/core/pci.c
> +++ b/drivers/cxl/core/pci.c
> @@ -926,3 +926,33 @@ int cxl_port_get_possible_dports(struct cxl_port *port)
>
> return ctx.count;
> }
> +
> +/**
> + * cxl_port_pm_init_is_complete - check the downstream port's PM Init Complete
> + * @pdev: downstream port
> + *
> + * Read the Port Power Management Initialization Complete bit in the
> + * Downstream Port's CXL DVSEC Port Extended Status register.
> + *
> + * Return: false only when the bit is observably clear. Return true when PM
> + * init is complete, when @pdev is not a CXL port (no Port DVSEC), or when
> + * the status register cannot be read.
> + */
> +bool cxl_port_pm_init_is_complete(struct pci_dev *pdev)
> +{
> + u16 status;
> + u16 dvsec;
> + int rc;
> +
> + dvsec = pci_find_dvsec_capability(pdev, PCI_VENDOR_ID_CXL,
> + PCI_DVSEC_CXL_PORT);
> + if (!dvsec)
> + return true;
> +
> + rc = pci_read_config_word(pdev, dvsec + PCI_DVSEC_CXL_PORT_EXT_STATUS,
> + &status);
> + if (rc || PCI_POSSIBLE_ERROR(status))
> + return true;
> +
> + return !!FIELD_GET(PCI_DVSEC_CXL_PORT_EXT_STATUS_PM_INIT_COMP, status);
> +}
The !! seems unnecessary here since this is already a single bit FIELD_GET(),
ie. result is 0 or 1.
I also wouldn't mind this being extra reader friendly like below,
but I'm happy if you just get rid of the !!
bool complete;
complete = FIELD_GET(....);
return complete;
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-05-06 5:54 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-28 18:24 Fabio M. De Francesco
2026-04-28 18:24 ` [PATCH 1/2] PCI/CXL: Allow PM Init to complete on cxl_bus reset if ACS SV enabled Fabio M. De Francesco
2026-05-01 18:36 ` Dave Jiang
2026-04-28 18:24 ` [PATCH 2/2] cxl/core: Recover from PM Init failure via cxl_reset_bus_function() Fabio M. De Francesco
2026-05-01 21:59 ` Dave Jiang
2026-05-06 5:54 ` Alison Schofield
2026-05-01 22:01 ` Dave Jiang
-- strict thread matches above, loose matches on Subject: below --
2025-05-09 17:38 Shawn Anastasio
2025-05-10 19:50 ` Trilok Soni
2012-10-30 4:02 [PATCH v3 7/8] ACPI, PCI: add hostbridge removal function Bjorn Helgaas
2012-10-30 17:42 ` Yinghai Lu
2012-11-02 0:17 ` Rafael J. Wysocki
2012-11-05 22:27 ` Re: Bjorn Helgaas
2012-11-05 22:49 ` Re: Yinghai Lu
2012-11-06 5:03 ` Taku Izumi
2011-12-13 2:58 Matt Shaw
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox