Add Error Disconnect Recover (EDR) support.
Subsystems (4)
cover Add Error Disconnect Recover (EDR) support.
From: Kuppuswamy Sathyanarayanan <[email protected]>
This patchset adds support for following features:
1. Error Disconnect Recover (EDR) support.
2. _OSC based negotiation support for DPC.
You can find EDR spec in the following link.
https://members.pcisig.com/wg/PCI-SIG/document/12614
Kuppuswamy Sathyanarayanan (3):
PCI/ACPI: Add _OSC based negotiation support for DPC
ACPI: Add Error Disconnect Recover (EDR) ACPI notifier support PCI/DPC: Add Error Disconnect Recover (EDR) support
drivers/acpi/acpica/utdecode.c | 3 +- drivers/acpi/bus.c | 5 +- drivers/acpi/pci_root.c | 6 + drivers/pci/pcie/Kconfig | 10 + drivers/pci/pcie/dpc.c | 326 ++++++++++++++++++++++++++++++-- drivers/pci/pcie/portdrv_core.c | 8 +- drivers/pci/probe.c | 1 + include/acpi/actypes.h | 3 +- include/linux/acpi.h | 3 +- include/linux/pci.h | 1 + 10 files changed, 347 insertions(+), 19 deletions(-)
Signature · 1 line
2.20.1
PATCH 1/3 PCI/ACPI: Add _OSC based negotiation support for DPC
From: Kuppuswamy Sathyanarayanan <[email protected]>
As per PCI Firmware Specification, r3.2 ECN
(https://members.pcisig.com/wg/PCI-SIG/document/12614), OS can use bit 7 of _OSC Control Field to negotiate control over Downstream Port Containment (DPC) configuration of PCIe port.
After _OSC negotiation, firmware will Set this bit to grant OS control over PCIe DPC configuration and Clear it if this feature was requested and denied, or was not requested.
--- drivers/acpi/pci_root.c | 6 ++++++ drivers/pci/pcie/portdrv_core.c | 3 ++- drivers/pci/probe.c | 1 + include/linux/acpi.h | 3 ++- include/linux/pci.h | 1 + 5 files changed, 12 insertions(+), 2 deletions(-)
drivers/acpi/pci_root.c +6 -0
@@ -154,6 +154,7 @@ static struct pci_osc_bit_struct pci_osc_control_bit[] = { { OSC_PCI_EXPRESS_AER_CONTROL, "AER" }, { OSC_PCI_EXPRESS_CAPABILITY_CONTROL, "PCIeCapability" }, { OSC_PCI_EXPRESS_LTR_CONTROL, "LTR" }, + { OSC_PCI_EXPRESS_DPC_CONTROL, "DPC" }, }; static void decode_osc_bits(struct acpi_pci_root *root, char *msg, u32 word,
@@ -499,6 +500,9 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, control |=OSC_PCI_EXPRESS_AER_CONTROL ; } +if (IS_ENABLED (CONFIG_PCIE_DPC )) + control |=OSC_PCI_EXPRESS_DPC_CONTROL ; + requested = control; status =acpi_pci_osc_control_set (handle, &control,OSC_PCI_EXPRESS_CAPABILITY_CONTROL );
@@ -927,6 +931,8 @@ struct pci_bus *acpi_pci_root_create(struct acpi_pci_root *root, host_bridge->native_pme =0 ;if (!(root->osc_control_set &OSC_PCI_EXPRESS_LTR_CONTROL )) host_bridge->native_ltr =0 ; +if (!(root->osc_control_set &OSC_PCI_EXPRESS_DPC_CONTROL )) + host_bridge->native_dpc =0 ;pci_scan_child_bus (bus); pci_set_host_bridge_release(host_bridge, acpi_pci_root_release_info,
drivers/pci/pcie/portdrv_core.c +2 -1
@@ -247,7 +247,8 @@ static int get_port_device_capability(struct pci_dev *dev) }if (pci_find_ext_capability (dev,PCI_EXT_CAP_ID_DPC ) && -pci_aer_available () && services &PCIE_PORT_SERVICE_AER ) +pci_aer_available () && services &PCIE_PORT_SERVICE_AER && + (pcie_ports_native || host->native_dpc)) services |=PCIE_PORT_SERVICE_DPC ;return services;
drivers/pci/probe.c +1 -0
@@ -557,6 +557,7 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv) bridge->native_shpc_hotplug =1 ; bridge->native_pme =1 ; bridge->native_ltr =1 ; + bridge->native_dpc =1 ;return bridge; }
include/linux/acpi.h +2 -1
@@ -517,7 +517,8 @@ extern bool osc_pc_lpi_support_confirmed;#define OSC_PCI_EXPRESS_AER_CONTROL 0x00000008#define OSC_PCI_EXPRESS_CAPABILITY_CONTROL 0x00000010#define OSC_PCI_EXPRESS_LTR_CONTROL 0x00000020 -#define OSC_PCI_CONTROL_MASKS 0x0000003f +#define OSC_PCI_EXPRESS_DPC_CONTROL 0x00000080 +#define OSC_PCI_CONTROL_MASKS 0x000000ff#define ACPI_GSB_ACCESS_ATTRIB_QUICK 0x00000002#define ACPI_GSB_ACCESS_ATTRIB_SEND_RCV 0x00000004
include/linux/pci.h +1 -0
@@ -499,6 +499,7 @@ struct pci_host_bridge { unsigned int native_shpc_hotplug:1; /* OS may use SHPC hotplug */ unsigned int native_pme:1; /* OS may use PCIe PME */ unsigned int native_ltr:1; /* OS may use PCIe LTR */ + unsigned int native_dpc:1; /* OS may use PCIe DPC *//* Resource alignment requirements */ resource_size_t (*align_resource)(struct pci_dev *dev, const struct resource *res,
Signature · 1 line
2.20.1
PATCH 2/3 ACPI: Add Error Disconnect Recover (EDR) ACPI notifier support
In reply to [email protected]From: Kuppuswamy Sathyanarayanan <[email protected]>
As per ACPI spec r6.3, sec 6.3.5, Error Disconnect Recover notification can be used to notify OSPM of asynchronous removal of devices for error containment purposes. OSPM can use this notification to invalidate software states of disconnected child devices in the bus and also optionally can attempt recover the child devices.
--- drivers/acpi/acpica/utdecode.c | 3 ++- drivers/acpi/bus.c | 5 ++++- include/acpi/actypes.h | 3 ++- 3 files changed, 8 insertions(+), 3 deletions(-)
drivers/acpi/acpica/utdecode.c +2 -1
@@ -431,7 +431,8 @@ static const char *acpi_gbl_generic_notify[ACPI_GENERIC_NOTIFY_MAX + 1] = {/* Reserved in ACPI 6.0 */ /* 0D */ "System Resource Affinity Update" ,/* 0E */ "Heterogeneous Memory Attributes Update" -/* ACPI 6.2 */ + /* 0F */ "Error Disconnect Recover", + /* ACPI 6.3 */ }; static const char *acpi_gbl_device_notify[5] = {
drivers/acpi/bus.c +4 -1
@@ -397,7 +397,10 @@ static void acpi_bus_notify(acpi_handle handle, u32 type, void *data)case ACPI_NOTIFY_POWER_FAULT :acpi_handle_err (handle,"Device has suffered a power fault\n" );break ; - +case ACPI_NOTIFY_ERROR_DISCONNECT : +acpi_handle_debug (handle, +"ACPI_NOTIFY_ERROR_DISCONNECT event\n" ); +break ;default :acpi_handle_debug (handle,"Unknown event type 0x%x\n" , type);break ;
include/acpi/actypes.h +2 -1
@@ -617,8 +617,9 @@ typedef u64 acpi_integer;#define ACPI_NOTIFY_SHUTDOWN_REQUEST (u8) 0x0C#define ACPI_NOTIFY_AFFINITY_UPDATE (u8) 0x0D#define ACPI_NOTIFY_MEMORY_UPDATE (u8) 0x0E +#define ACPI_NOTIFY_ERROR_DISCONNECT (u8) 0x0F -#define ACPI_GENERIC_NOTIFY_MAX 0x0E +#define ACPI_GENERIC_NOTIFY_MAX 0x0F#define ACPI_SPECIFIC_NOTIFY_MAX 0x84/*
Signature · 1 line
2.20.1
PATCH 3/3 PCI/DPC: Add Error Disconnect Recover (EDR) support
In reply to [email protected]From: Kuppuswamy Sathyanarayanan <[email protected]>
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.
--- 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(-)
drivers/pci/pcie/Kconfig +10 -0
@@ -143,3 +143,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.
drivers/pci/pcie/dpc.c +312 -14
405 lines not on this page · raw message
drivers/pci/pcie/portdrv_core.c +7 -2
@@ -246,9 +246,14 @@ static int get_port_device_capability(struct pci_dev *dev)pcie_pme_interrupt_enable (dev, false); } +/* +* 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)))) services |=PCIE_PORT_SERVICE_DPC ;return services;
Signature · 1 line
2.20.1