[PATCH 1/1] PCI/portdrv: Allow DPC if the OS controls AER natively.

Matthew W Carlis
2023-12-23T21:22:54Z

This change ensures the kernel will use DPC on a supporting device if
the kernel will also control AER on the Root Ports & RCECs.

The rules around controlling DPC/AER are somewhat clear in PCIe/ACPI
specifications. It is recommended to always link control of both to the
same entity, being the OS or system firmware. The kernel wants to be
flexible by first having a default policy, but also by providing command
line parameters to enable us all to do what we want even if it might
violate the recommendations.

The following mentioned patch brought the kernels default behavior
more in line with the specification around AER, but changed its behavior
around DPC on PCIe Downstream Switch Ports; preventing the kernel from
controlling DPC on them unless using pcie_ports=dpc-native.
* "PCI/portdrv: Allow AER service only for Root Ports & RCECs"
After this change the behavior around using DPC on PCIe switch ports
and Root Ports should be as it was before.

Signed-off-by: Matthew W Carlis <mattc@purestorage.com>
---
drivers/pci/pcie/portdrv.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c
index 14a4b89a3b83..8e023aa97672 100644
--- a/drivers/pci/pcie/portdrv.c
+++ b/drivers/pci/pcie/portdrv.c
@@ -257,12 +257,19 @@ static int get_port_device_capability(struct pci_dev *dev)
}

/*
+ * _OSC AER Control is required by the OS & requires OS to control AER,
+ * but _OSC DPC Control isn't required by the OS to control DPC; however
+ * it does require the OS to control DPC. _OSC DPC Control also requres
+ * _OSC EDR Control (Error Disconnect Recovery) (PCI Firmware - DPC ECN rev3.2)
+ * PCI_Express_Base 6.1, 6.2.11 Determination of DPC Control recommends
+ * platform fw or OS always link control of DPC to AER.
+ *
* With dpc-native, allow Linux to use DPC even if it doesn't have
* permission to use AER.
*/
if (pci_find_ext_capability(dev, PCI_EXT_CAP_ID_DPC) &&
- pci_aer_available() &&
- (pcie_ports_dpc_native || (services & PCIE_PORT_SERVICE_AER)))
+ pci_aer_available() && (pcie_ports_dpc_native ||
+ (dev->aer_cap && host->native_aer)))
services |= PCIE_PORT_SERVICE_DPC;

if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM ||
--
2.17.1