Re: [PATCH v2 2/2] PCI/DPC: Add Error Disconnect Recover (EDR) support
On Wed, Apr 10, 2019 at 03:12:05PM -0700, sathyanarayanan kuppuswamy wrote: > On 4/10/19 11:41 AM, Bjorn Helgaas wrote: > > On Tue, Mar 19, 2019 at 01:47:29PM -0700, > > sathyanarayanan.kuppusw...@linux.intel.com wrote: > > > From: Kuppuswamy Sathyanarayanan > > > > > > > > > As per PCI firmware specification v3.2 ECN > > > (https://members.pcisig.com/wg/PCI-SIG/document/12614), when firmware > > > owns Downstream Port Containment (DPC), its expected to use the "Error > > > Disconnect Recover" (EDR) notification to alert OSPM of a DPC event and > > > if OS supports EDR, its expected to handle the software state invalidation > > > and port recovery in OS and let firmware know the recovery status via _OST > > > ACPI call. > > > > > > Since EDR is a hybrid service, DPC service shall be enabled in OS even > > > if AER is not natively enabled in OS. > > > + boolnative_dpc; > > This is going to be way too confusing with a "native_dpc" in both the > > struct pci_host_bridge and the struct dpc_dev. > Any suggestions? what about native_mode ? "native_mode" is different but doesn't contain any additional information. I haven't worked out what this new symbol actually does; if it's related to EDR, maybe that could be incorporated somehow? > > > + /* Register ACPI notifier for EDR event */ > > "Register handler for System events, one of which is the EDR event"? > In our case, we only handle EDR event. So I just explicitly mentioned it. Right. As a courtesy to the reader, I think it's worth making the comment match the code, i.e., you can't pass an event type to acpi_install_notify_handler(), so obviously the handler will be called for *all* System events. By saying "one of which is the EDR event", you give the reader a hint that the handler will have to filter out the others. The reason I noticed this is because I read "Register notifier for EDR event" and wondered to myself "Hmmm, how does this work? I don't see anything passed to acpi_install_notify_handler() that would identify an EDR event." > > > + /* > > > + * If EDR support is enabled in OS, then even if AER is not handled in > > > + * OS, DPC service can be enabled. > > > + */ > > > if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DPC) && > > > - pci_aer_available() && services & PCIE_PORT_SERVICE_AER && > > > - (pcie_ports_native || host->native_dpc)) > > > + ((IS_ENABLED(CONFIG_PCIE_EDR) && !host->native_dpc) || > > > + (pci_aer_available() && services & PCIE_PORT_SERVICE_AER && > > > + (pcie_ports_native || host->native_dpc > > Holy cow, I think I'll have to schedule an hour sometime to figure > > out what's going on here :) > Please check the previous patch in this series for details related to > host->native_dpc. Yeah, I'm just saying that conditional is starting to look pretty gnarly. Possibly there's nothing to do about it. Bjorn
Re: [PATCH v2 2/2] PCI/DPC: Add Error Disconnect Recover (EDR) support
Hi , On 4/10/19 11:41 AM, Bjorn Helgaas wrote: On Tue, Mar 19, 2019 at 01:47:29PM -0700, sathyanarayanan.kuppusw...@linux.intel.com wrote: From: Kuppuswamy Sathyanarayanan As per PCI firmware specification v3.2 ECN (https://members.pcisig.com/wg/PCI-SIG/document/12614), when firmware owns Downstream Port Containment (DPC), its expected to use the "Error Disconnect Recover" (EDR) notification to alert OSPM of a DPC event and if OS supports EDR, its expected to handle the software state invalidation and port recovery in OS and let firmware know the recovery status via _OST ACPI call. Since EDR is a hybrid service, DPC service shall be enabled in OS even if AER is not natively enabled in OS. Signed-off-by: Kuppuswamy Sathyanarayanan --- drivers/pci/pcie/Kconfig| 10 + drivers/pci/pcie/dpc.c | 326 ++-- Thanks for the review comments. I'll be looking for Keith's reviewed-by for this eventually. It looks like this could be split into some smaller patches: - Add dpc_dev.native_dpc (hopefully we can find a less confusing name) - Convert dpc_handler() to dpc_handler() + dpc_process_error() - Add EDR support Ok. I will split them in next patch set. drivers/pci/pcie/portdrv_core.c | 9 +- 3 files changed, 329 insertions(+), 16 deletions(-) diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index 5cbdbca904ac..55f65d1cbc9e 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig @@ -142,3 +142,13 @@ config PCIE_PTM This is only useful if you have devices that support PTM, but it is safe to enable even if you don't. + +config PCIE_EDR + bool "PCI Express Error Disconnect Recover support" + default n + depends on PCIE_DPC && ACPI + help + This options adds Error Disconnect Recover support as specified + in PCI firmware specification v3.2 Downstream Port Containment + Related Enhancements ECN. Enable this if you want to support hybrid + DPC model which uses both firmware and OS to implement DPC. diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index 7b77754a82de..bdf4ca8a0acb 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "portdrv.h" #include "../pci.h" @@ -20,8 +21,23 @@ struct dpc_dev { u16 cap_pos; boolrp_extensions; u8 rp_log_size; + boolnative_dpc; This is going to be way too confusing with a "native_dpc" in both the struct pci_host_bridge and the struct dpc_dev. Any suggestions? what about native_mode ? + pci_ers_result_terror_state; +#ifdef CONFIG_ACPI + struct acpi_device *adev; +#endif }; +#ifdef CONFIG_ACPI + +#define EDR_PORT_ENABLE_DSM 0x0C +#define EDR_PORT_LOCATE_DSM 0x0D + +static const guid_t pci_acpi_dsm_guid = + GUID_INIT(0xe5c937d0, 0x3553, 0x4d7a, + 0x91, 0x17, 0xea, 0x4d, 0x19, 0xc3, 0x43, 0x4d); +#endif + static const char * const rp_pio_error_string[] = { "Configuration Request received UR Completion",/* Bit Position 0 */ "Configuration Request received CA Completion",/* Bit Position 1 */ @@ -67,6 +83,9 @@ void pci_save_dpc_state(struct pci_dev *dev) if (!dpc) return; + if (!dpc->native_dpc) + return; + save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_DPC); if (!save_state) return; @@ -88,6 +107,9 @@ void pci_restore_dpc_state(struct pci_dev *dev) if (!dpc) return; + if (!dpc->native_dpc) + return; + save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_DPC); if (!save_state) return; @@ -224,10 +246,9 @@ static int dpc_get_aer_uncorrect_severity(struct pci_dev *dev, return 1; } -static irqreturn_t dpc_handler(int irq, void *context) +static void dpc_process_error(struct dpc_dev *dpc) { struct aer_err_info info; - struct dpc_dev *dpc = context; struct pci_dev *pdev = dpc->dev->port; struct device *dev = &dpc->dev->device; u16 cap = dpc->cap_pos, status, source, reason, ext_reason; @@ -261,6 +282,13 @@ static irqreturn_t dpc_handler(int irq, void *context) /* We configure DPC so it only triggers on ERR_FATAL */ pcie_do_recovery(pdev, pci_channel_io_frozen, PCIE_PORT_SERVICE_DPC); +} + +static irqreturn_t dpc_handler(int irq, void *context) +{ + struct dpc_dev *dpc = context; + + dpc_process_error(dpc); return IRQ_HANDLED; } @@ -283,6 +311,230 @@ static irqreturn_t dpc_irq(int irq, void *context) return IRQ_HANDLED; } +void dpc_error_resume(struct pci_dev *dev) Looks like this should be static? yes. I will fix it in next versi
Re: [PATCH v2 2/2] PCI/DPC: Add Error Disconnect Recover (EDR) support
On Tue, Mar 19, 2019 at 01:47:29PM -0700, sathyanarayanan.kuppusw...@linux.intel.com wrote: > From: Kuppuswamy Sathyanarayanan > > As per PCI firmware specification v3.2 ECN > (https://members.pcisig.com/wg/PCI-SIG/document/12614), when firmware > owns Downstream Port Containment (DPC), its expected to use the "Error > Disconnect Recover" (EDR) notification to alert OSPM of a DPC event and > if OS supports EDR, its expected to handle the software state invalidation > and port recovery in OS and let firmware know the recovery status via _OST > ACPI call. > > Since EDR is a hybrid service, DPC service shall be enabled in OS even > if AER is not natively enabled in OS. > > Signed-off-by: Kuppuswamy Sathyanarayanan > > --- > drivers/pci/pcie/Kconfig| 10 + > drivers/pci/pcie/dpc.c | 326 ++-- I'll be looking for Keith's reviewed-by for this eventually. It looks like this could be split into some smaller patches: - Add dpc_dev.native_dpc (hopefully we can find a less confusing name) - Convert dpc_handler() to dpc_handler() + dpc_process_error() - Add EDR support > drivers/pci/pcie/portdrv_core.c | 9 +- > 3 files changed, 329 insertions(+), 16 deletions(-) > > diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig > index 5cbdbca904ac..55f65d1cbc9e 100644 > --- a/drivers/pci/pcie/Kconfig > +++ b/drivers/pci/pcie/Kconfig > @@ -142,3 +142,13 @@ config PCIE_PTM > > This is only useful if you have devices that support PTM, but it > is safe to enable even if you don't. > + > +config PCIE_EDR > + bool "PCI Express Error Disconnect Recover support" > + default n > + depends on PCIE_DPC && ACPI > + help > + This options adds Error Disconnect Recover support as specified > + in PCI firmware specification v3.2 Downstream Port Containment > + Related Enhancements ECN. Enable this if you want to support hybrid > + DPC model which uses both firmware and OS to implement DPC. > diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c > index 7b77754a82de..bdf4ca8a0acb 100644 > --- a/drivers/pci/pcie/dpc.c > +++ b/drivers/pci/pcie/dpc.c > @@ -11,6 +11,7 @@ > #include > #include > #include > +#include > > #include "portdrv.h" > #include "../pci.h" > @@ -20,8 +21,23 @@ struct dpc_dev { > u16 cap_pos; > boolrp_extensions; > u8 rp_log_size; > + boolnative_dpc; This is going to be way too confusing with a "native_dpc" in both the struct pci_host_bridge and the struct dpc_dev. > + pci_ers_result_terror_state; > +#ifdef CONFIG_ACPI > + struct acpi_device *adev; > +#endif > }; > > +#ifdef CONFIG_ACPI > + > +#define EDR_PORT_ENABLE_DSM 0x0C > +#define EDR_PORT_LOCATE_DSM 0x0D > + > +static const guid_t pci_acpi_dsm_guid = > + GUID_INIT(0xe5c937d0, 0x3553, 0x4d7a, > + 0x91, 0x17, 0xea, 0x4d, 0x19, 0xc3, 0x43, 0x4d); > +#endif > + > static const char * const rp_pio_error_string[] = { > "Configuration Request received UR Completion", /* Bit Position 0 */ > "Configuration Request received CA Completion", /* Bit Position 1 */ > @@ -67,6 +83,9 @@ void pci_save_dpc_state(struct pci_dev *dev) > if (!dpc) > return; > > + if (!dpc->native_dpc) > + return; > + > save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_DPC); > if (!save_state) > return; > @@ -88,6 +107,9 @@ void pci_restore_dpc_state(struct pci_dev *dev) > if (!dpc) > return; > > + if (!dpc->native_dpc) > + return; > + > save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_DPC); > if (!save_state) > return; > @@ -224,10 +246,9 @@ static int dpc_get_aer_uncorrect_severity(struct pci_dev > *dev, > return 1; > } > > -static irqreturn_t dpc_handler(int irq, void *context) > +static void dpc_process_error(struct dpc_dev *dpc) > { > struct aer_err_info info; > - struct dpc_dev *dpc = context; > struct pci_dev *pdev = dpc->dev->port; > struct device *dev = &dpc->dev->device; > u16 cap = dpc->cap_pos, status, source, reason, ext_reason; > @@ -261,6 +282,13 @@ static irqreturn_t dpc_handler(int irq, void *context) > > /* We configure DPC so it only triggers on ERR_FATAL */ > pcie_do_recovery(pdev, pci_channel_io_frozen, PCIE_PORT_SERVICE_DPC); > +} > + > +static irqreturn_t dpc_handler(int irq, void *context) > +{ > + struct dpc_dev *dpc = context; > + > + dpc_process_error(dpc); > > return IRQ_HANDLED; > } > @@ -283,6 +311,230 @@ static irqreturn_t dpc_irq(int irq, void *context) > return IRQ_HANDLED; > } > > +void dpc_error_resume(struct pci_dev *dev) Looks like this should be static? > +{ > + struct dpc_dev *dpc; > + > + dpc = to_dpc_dev(de
[PATCH v2 2/2] PCI/DPC: Add Error Disconnect Recover (EDR) support
From: Kuppuswamy Sathyanarayanan As per PCI firmware specification v3.2 ECN (https://members.pcisig.com/wg/PCI-SIG/document/12614), when firmware owns Downstream Port Containment (DPC), its expected to use the "Error Disconnect Recover" (EDR) notification to alert OSPM of a DPC event and if OS supports EDR, its expected to handle the software state invalidation and port recovery in OS and let firmware know the recovery status via _OST ACPI call. Since EDR is a hybrid service, DPC service shall be enabled in OS even if AER is not natively enabled in OS. Signed-off-by: Kuppuswamy Sathyanarayanan --- drivers/pci/pcie/Kconfig| 10 + drivers/pci/pcie/dpc.c | 326 ++-- drivers/pci/pcie/portdrv_core.c | 9 +- 3 files changed, 329 insertions(+), 16 deletions(-) diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index 5cbdbca904ac..55f65d1cbc9e 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig @@ -142,3 +142,13 @@ config PCIE_PTM This is only useful if you have devices that support PTM, but it is safe to enable even if you don't. + +config PCIE_EDR + bool "PCI Express Error Disconnect Recover support" + default n + depends on PCIE_DPC && ACPI + help + This options adds Error Disconnect Recover support as specified + in PCI firmware specification v3.2 Downstream Port Containment + Related Enhancements ECN. Enable this if you want to support hybrid + DPC model which uses both firmware and OS to implement DPC. diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index 7b77754a82de..bdf4ca8a0acb 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "portdrv.h" #include "../pci.h" @@ -20,8 +21,23 @@ struct dpc_dev { u16 cap_pos; boolrp_extensions; u8 rp_log_size; + boolnative_dpc; + pci_ers_result_terror_state; +#ifdef CONFIG_ACPI + struct acpi_device *adev; +#endif }; +#ifdef CONFIG_ACPI + +#define EDR_PORT_ENABLE_DSM 0x0C +#define EDR_PORT_LOCATE_DSM 0x0D + +static const guid_t pci_acpi_dsm_guid = + GUID_INIT(0xe5c937d0, 0x3553, 0x4d7a, + 0x91, 0x17, 0xea, 0x4d, 0x19, 0xc3, 0x43, 0x4d); +#endif + static const char * const rp_pio_error_string[] = { "Configuration Request received UR Completion", /* Bit Position 0 */ "Configuration Request received CA Completion", /* Bit Position 1 */ @@ -67,6 +83,9 @@ void pci_save_dpc_state(struct pci_dev *dev) if (!dpc) return; + if (!dpc->native_dpc) + return; + save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_DPC); if (!save_state) return; @@ -88,6 +107,9 @@ void pci_restore_dpc_state(struct pci_dev *dev) if (!dpc) return; + if (!dpc->native_dpc) + return; + save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_DPC); if (!save_state) return; @@ -224,10 +246,9 @@ static int dpc_get_aer_uncorrect_severity(struct pci_dev *dev, return 1; } -static irqreturn_t dpc_handler(int irq, void *context) +static void dpc_process_error(struct dpc_dev *dpc) { struct aer_err_info info; - struct dpc_dev *dpc = context; struct pci_dev *pdev = dpc->dev->port; struct device *dev = &dpc->dev->device; u16 cap = dpc->cap_pos, status, source, reason, ext_reason; @@ -261,6 +282,13 @@ static irqreturn_t dpc_handler(int irq, void *context) /* We configure DPC so it only triggers on ERR_FATAL */ pcie_do_recovery(pdev, pci_channel_io_frozen, PCIE_PORT_SERVICE_DPC); +} + +static irqreturn_t dpc_handler(int irq, void *context) +{ + struct dpc_dev *dpc = context; + + dpc_process_error(dpc); return IRQ_HANDLED; } @@ -283,6 +311,230 @@ static irqreturn_t dpc_irq(int irq, void *context) return IRQ_HANDLED; } +void dpc_error_resume(struct pci_dev *dev) +{ + struct dpc_dev *dpc; + + dpc = to_dpc_dev(dev); + if (!dpc) + return; + + dpc->error_state = PCI_ERS_RESULT_RECOVERED; +} + +#ifdef CONFIG_ACPI + +/* + * _DSM wrapper function to enable/disable DPC port. + * @dpc : DPC device structure + * @enable: status of DPC port (0 or 1). + * + * returns 0 on success or errno on failure. + */ +static int acpi_enable_dpc_port(struct dpc_dev *dpc, bool enable) +{ + union acpi_object *obj; + int status; + union acpi_object argv4; + + /* Check whether EDR_PORT_ENABLE_DSM is supported in firmware */ + status = acpi_check_dsm(dpc->adev->handle, &pci_acpi_dsm_guid, 1, + 1 << EDR_PORT_ENABLE_DSM); + if (!statu