[PATCH v2] arm64: PCI: Add quirk for Qualcomm WoA devices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Commit 8fd4391ee717 ("arm64: PCI: Exclude ACPI "consumer" resources from
host bridge windows") introduced a check to remove host bridge register
resources for all arm64 platforms, with the assumption that the PNP0A03
_CRS resources would always be host bridge registers and never as windows
on arm64 platforms.

The assumption stands true until Qualcomm WoA (Windows on ARM) devices
emerge.  These devices describe host bridge windows in PNP0A03 _CRS
resources instead.  For example, the Microsoft Surface Pro X has host
bridges defined as

    Name (_HID, EisaId ("PNP0A08") /* PCI Express Bus */)  // _HID: Hardware ID
    Name (_CID, EisaId ("PNP0A03") /* PCI Bus */)  // _CID: Compatible ID

    Method (_CRS, 0, NotSerialized)  // _CRS: Current Resource Settings
    {
        Name (RBUF, ResourceTemplate ()
        {
            Memory32Fixed (ReadWrite,
                0x60200000,         // Address Base
                0x01DF0000,         // Address Length
                )
            WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
                0x0000,             // Granularity
                0x0000,             // Range Minimum
                0x0001,             // Range Maximum
                0x0000,             // Translation Offset
                0x0002,             // Length
                ,, )
        })
        Return (RBUF) /* \_SB_.PCI0._CRS.RBUF */
    }

The Memory32Fixed holds a host bridge window, but it's not properly
defined as a "producer" resource.  Consequently the resource gets
removed by kernel, and the BAR allocation fails later on:

    [ 0.150731] pci 0002:00:00.0: BAR 14: no space for [mem size 0x00100000]
    [ 0.150744] pci 0002:00:00.0: BAR 14: failed to assign [mem size 0x00100000]
    [ 0.150758] pci 0002:01:00.0: BAR 0: no space for [mem size 0x00004000 64bit]
    [ 0.150769] pci 0002:01:00.0: BAR 0: failed to assign [mem size 0x00004000 64bit]

This eventually prevents the PCIe NVME drive from being accessible.

Add a quirk for these devices to avoid the resource being removed.

Signed-off-by: Shawn Guo <shawn.guo@xxxxxxxxxx>
---
Changes for v2:
- Match devices using PPTT instead of DSDT to avoid maintenance burden.
  Hope this is an acceptable compromise.
- Add const delaration to qcom_platlist[].

v1 link:
https://lore.kernel.org/lkml/20230227021221.17980-1-shawn.guo@xxxxxxxxxx/

 arch/arm64/kernel/pci.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
index 2276689b5411..2ff2f3befa76 100644
--- a/arch/arm64/kernel/pci.c
+++ b/arch/arm64/kernel/pci.c
@@ -109,16 +109,44 @@ int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
 	return 0;
 }
 
+#define QCOM_PCI_QUIRK "Host bridge windows in PNP0A03 _CRS"
+
+/*
+ * Ideally DSDT (Differentiated System Description Table) should be used to
+ * match the platforms, as the quirk is in there. But devices from different
+ * manufacturers usually have different oem_id and oem_table_id in DSDT,
+ * so matching DSDT makes the list a maintenance burden.  As a compromise,
+ * PPTT (Processor Properties Topology Table) is used instead to work
+ * around this quirk for the most Qualcomm WoA (Windows on ARM) devices.
+ */
+static const struct acpi_platform_list qcom_platlist[] = {
+	{ "QCOM  ", "QCOMEDK2", 0, ACPI_SIG_PPTT, all_versions, QCOM_PCI_QUIRK },
+	{ }
+};
+
 static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci)
 {
 	struct resource_entry *entry, *tmp;
 	int status;
+	int idx;
 
 	status = acpi_pci_probe_root_resources(ci);
+
+	/*
+	 * Instead of describing host bridge registers in PNP0A03 _CRS
+	 * resources, Qualcomm WoA devices describe host bridge windows in
+	 * there.  We do not want to destroy the resources on these platforms.
+	 */
+	idx = acpi_match_platform_list(qcom_platlist);
+	if (idx >= 0)
+		goto done;
+
 	resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
 		if (!(entry->res->flags & IORESOURCE_WINDOW))
 			resource_list_destroy_entry(entry);
 	}
+
+done:
 	return status;
 }
 
-- 
2.17.1




[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux