PCI/EDR: Align EDR_PORT_LOCATE_DSM with PCI Firmware r3.3
authorKuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Wed, 8 May 2024 19:31:38 +0000 (14:31 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 8 May 2024 20:08:39 +0000 (15:08 -0500)
The "Downstream Port Containment related Enhancements" ECN of Jan 28, 2019
(document 12888 below), defined the EDR_PORT_LOCATE_DSM function with
Revision ID 5 with a return value encoding (Bits 2:0 = Function, Bits 7:3 =
Device, Bits 15:8 = Bus).  When the ECN was integrated into PCI Firmware
r3.3, sec 4.6.13, Bit 31 was added to indicate success or failure.

Check Bit 31 for failure in acpi_dpc_port_get().

Link: https://lore.kernel.org/r/20240501022543.1626025-1-sathyanarayanan.kuppuswamy@linux.intel.com
Link: https://members.pcisig.com/wg/PCI-SIG/document/12888
Fixes: ac1c8e35a326 ("PCI/DPC: Add Error Disconnect Recover (EDR) support")
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
[bhelgaas: split into two patches, update commit log]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Satish Thatchanamurthy <Satish.Thatchanamurt@Dell.com> # one platform
drivers/pci/pcie/edr.c

index fa085677c91de1521023ab7a8cdc8780e1ac0bfc..e86298dbbcff602adb210378ceb033ae0ff155d5 100644 (file)
@@ -80,8 +80,9 @@ static struct pci_dev *acpi_dpc_port_get(struct pci_dev *pdev)
        u16 port;
 
        /*
-        * Behavior when calling unsupported _DSM functions is undefined,
-        * so check whether EDR_PORT_DPC_ENABLE_DSM is supported.
+        * If EDR_PORT_LOCATE_DSM is not implemented under the target of
+        * EDR, the target is the port that experienced the containment
+        * event (PCI Firmware r3.3, sec 4.6.13).
         */
        if (!acpi_check_dsm(adev->handle, &pci_acpi_dsm_guid, 5,
                            1ULL << EDR_PORT_LOCATE_DSM))
@@ -98,6 +99,16 @@ static struct pci_dev *acpi_dpc_port_get(struct pci_dev *pdev)
                return NULL;
        }
 
+       /*
+        * Bit 31 represents the success/failure of the operation. If bit
+        * 31 is set, the operation failed.
+        */
+       if (obj->integer.value & BIT(31)) {
+               ACPI_FREE(obj);
+               pci_err(pdev, "Locate Port _DSM failed\n");
+               return NULL;
+       }
+
        /*
         * Firmware returns DPC port BDF details in following format:
         *      15:8 = bus