From 407799f8792cb1cc8b3beedee2418df2b53f14fb Mon Sep 17 00:00:00 2001
From: Jincheng Li <jincheng.li@intel.com>
Date: Fri, 10 May 2024 16:09:15 +0800
Subject: soc/intel/xeon_sp: Report PCIe integrated end points under DRHD

In case of a PCH-less platform, no DRHD_INCLUDE_PCI_ALL flags are
used, all PCIe integrated end points should be explicitly listed
under the DRHD they are affiliated to. Otherwise, the device MSI
setting could fail.

TESTED = Build and boot on intel/beechnutcity CRB

In CentOS Stream (5.14.0-479.el9.x86_64) 9 5.14.0-479.el9.x86_64,
without the changes, below failure logs will occur,

[    6.908347] ------------[ cut here ]------------
[    6.908353] WARNING: CPU: 0 PID: 8 at drivers/pci/msi/msi.h:121 pci_msi_setup_msi_irqs+0x27/0x40
[    6.908374] Modules linked in:
[    6.908379] CPU: 0 PID: 8 Comm: kworker/0:0 Not tainted 5.14.0-479.el9.x86_64 #1
[    6.908385] Hardware name: Intel Beechnut City CRB/Beechnut City CRB, BIOS c1e9362c93be-dirty 09/25/2024
[    6.908389] Workqueue: events work_for_cpu_fn
[    6.908401] RIP: 0010:pci_msi_setup_msi_irqs+0x27/0x40
[    6.908411] Code: 90 90 90 0f 1f 44 00 00 48 8b 87 00 03 00 00 89 f2 48 85 c0 74 14 f6 40 28 01 74 0e 48 81 c7 c8 00 00 00 31 f6 e9 19 de ac ff <0f> 0b b8 ed ff ff ff c3 cc cc cc cc 66 66 2e 0f 1f 84 00 00 00 00
[    6.908417] RSP: 0000:ffffac47c0137c80 EFLAGS: 00010246
[    6.908423] RAX: 0000000000000000 RBX: ffff9a0a874e2000 RCX: 000000000000009c
[    6.908428] RDX: 0000000000000001 RSI: 0000000000000001 RDI: ffff9a0a874e2000
[    6.908433] RBP: 0000000000000000 R08: 0000000000000004 R09: 0000000000000001
[    6.908437] R10: ffff9a0a8adcb258 R11: 0000000000000000 R12: 0000000000000001
[    6.908440] R13: 0000000000000001 R14: ffff9a0a8738be00 R15: ffff9a0a874e20c8
[    6.908443] FS:  0000000000000000(0000) GS:ffff9a0ded000000(0000) knlGS:0000000000000000
[    6.908448] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[    6.908451] CR2: ffff9a11fffff000 CR3: 00000003cd410001 CR4: 0000000000770ef0
[    6.908455] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[    6.908457] DR3: 0000000000000000 DR6: 00000000ffff07f0 DR7: 0000000000000400
[    6.908460] PKRU: 55555554
[    6.908462] Call Trace:
[    6.908465]  <TASK>
[    6.908470]  ? show_trace_log_lvl+0x1c4/0x2df
[    6.908484]  ? show_trace_log_lvl+0x1c4/0x2df
[    6.908492]  ? msi_capability_init+0x193/0x280
[    6.908501]  ? pci_msi_setup_msi_irqs+0x27/0x40
[    6.908509]  ? __warn+0x7e/0xd0
[    6.908519]  ? pci_msi_setup_msi_irqs+0x27/0x40
[    6.908527]  ? report_bug+0x100/0x140
[    6.908537]  ? handle_bug+0x3c/0x70
[    6.908545]  ? exc_invalid_op+0x14/0x70
[    6.908551]  ? asm_exc_invalid_op+0x16/0x20
[    6.908561]  ? pci_msi_setup_msi_irqs+0x27/0x40
[    6.908569]  msi_capability_init+0x193/0x280
[    6.908577]  __pci_enable_msi_range+0x1a3/0x230
[    6.908586]  pci_alloc_irq_vectors_affinity+0xc3/0x110
[    6.908594]  pcie_port_enable_irq_vec+0x3f/0x250
[    6.908604]  ? __pci_set_master+0x31/0xd0
[    6.908614]  pcie_portdrv_probe+0xdf/0x300
[    6.908620]  local_pci_probe+0x4c/0xa0
[    6.908627]  work_for_cpu_fn+0x13/0x20
[    6.908635]  process_one_work+0x194/0x380
[    6.908643]  worker_thread+0x2fe/0x410
[    6.908649]  ? __pfx_worker_thread+0x10/0x10
[    6.908655]  kthread+0xdd/0x100
[    6.908665]  ? __pfx_kthread+0x10/0x10
[    6.908673]  ret_from_fork+0x29/0x50
[    6.908686]  </TASK>
[    6.908688] ---[ end trace 0000000000000000 ]---

Change-Id: Ib015b002f2c077f50d48c046513504bdbd5b35aa
Signed-off-by: Jincheng Li <jincheng.li@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/84315
Reviewed-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
---
 src/soc/intel/xeon_sp/uncore_acpi.c | 90 ++++++++++++++-----------------------
 1 file changed, 34 insertions(+), 56 deletions(-)

(limited to 'src/soc/intel/xeon_sp')

diff --git a/src/soc/intel/xeon_sp/uncore_acpi.c b/src/soc/intel/xeon_sp/uncore_acpi.c
index baffdd0e96..fc283ee50d 100644
--- a/src/soc/intel/xeon_sp/uncore_acpi.c
+++ b/src/soc/intel/xeon_sp/uncore_acpi.c
@@ -266,22 +266,22 @@ static unsigned long acpi_create_drhd(unsigned long current, struct device *iomm
 	printk(BIOS_SPEW, "%s socket: %d, stack: %d, bus: 0x%x, pcie_seg: 0x%x, reg_base: 0x%x\n",
 		__func__, socket, stack, bus, pcie_seg, reg_base);
 
-	// Add DRHD Hardware Unit
+	/*
+	 * Add DRHD Hardware Unit
+	 * For IBL platforms, domain0 is not PCH stack and not recommended to set
+	 * DRHD_INCLUDE_PCI_ALL
+	 */
 
-	if (is_dev_on_domain0(iommu)) {
-		printk(BIOS_DEBUG, "[Hardware Unit Definition] Flags: 0x%x, PCI Segment Number: 0x%x, "
-			"Register Base Address: 0x%x\n",
-			DRHD_INCLUDE_PCI_ALL, pcie_seg, reg_base);
-		current += acpi_create_dmar_drhd(current, DRHD_INCLUDE_PCI_ALL,
-			pcie_seg, reg_base, vtd_probe_bar_size(iommu));
-	} else {
-		printk(BIOS_DEBUG, "[Hardware Unit Definition] Flags: 0x%x, PCI Segment Number: 0x%x, "
-			"Register Base Address: 0x%x\n", 0, pcie_seg, reg_base);
-		current += acpi_create_dmar_drhd(current, 0, pcie_seg, reg_base,
-			vtd_probe_bar_size(iommu));
-	}
+	uint8_t flags = ((!CONFIG(SOC_INTEL_COMMON_IBL_BASE)) && is_dev_on_domain0(iommu)) ?
+			DRHD_INCLUDE_PCI_ALL : 0;
 
-	// Add PCH IOAPIC
+	printk(BIOS_DEBUG, "[Hardware Unit Definition] Flags: 0x%x, PCI Segment Number: 0x%x, "
+		"Register Base Address: 0x%x\n",
+		flags, pcie_seg, reg_base);
+	current += acpi_create_dmar_drhd(current, flags,
+		pcie_seg, reg_base, vtd_probe_bar_size(iommu));
+
+	// Add IOAPIC
 	if (is_dev_on_domain0(iommu)) {
 		union p2sb_bdf ioapic_bdf = soc_get_ioapic_bdf();
 		printk(BIOS_DEBUG, "    [IOAPIC Device] Enumeration ID: 0x%x, PCI Bus Number: 0x%x, "
@@ -291,7 +291,7 @@ static unsigned long acpi_create_drhd(unsigned long current, struct device *iomm
 				IO_APIC_ADDR, ioapic_bdf.bus, ioapic_bdf.dev, ioapic_bdf.fn);
 	}
 
-/* SPR has no per stack IOAPIC or CBDMA devices */
+/* SPR and later SoCs have no per stack IOAPIC */
 #if CONFIG(SOC_INTEL_SKYLAKE_SP) || CONFIG(SOC_INTEL_COOPERLAKE_SP)
 	uint32_t enum_id;
 	// Add IOAPIC entry
@@ -300,21 +300,10 @@ static unsigned long acpi_create_drhd(unsigned long current, struct device *iomm
 		"PCI Path: 0x%x, 0x%x\n", enum_id, bus, APIC_DEV_NUM, APIC_FUNC_NUM);
 	current += acpi_create_dmar_ds_ioapic(current, enum_id, bus,
 		APIC_DEV_NUM, APIC_FUNC_NUM);
-
-	// Add CBDMA devices for CSTACK
-	if (socket != 0 && stack == CSTACK) {
-		for (int cbdma_func_id = 0; cbdma_func_id < 8; ++cbdma_func_id) {
-			printk(BIOS_DEBUG, "    [PCI Endpoint Device] "
-				"PCI Bus Number: 0x%x, PCI Path: 0x%x, 0x%x\n",
-				bus, CBDMA_DEV_NUM, cbdma_func_id);
-			current += acpi_create_dmar_ds_pci(current,
-				bus, CBDMA_DEV_NUM, cbdma_func_id);
-		}
-	}
 #endif
 
-	// Add PCIe Ports
-	if (!is_dev_on_domain0(iommu)) {
+	if (flags != DRHD_INCLUDE_PCI_ALL) {
+		// Add PCIe Ports
 		const struct device *domain = dev_get_domain(iommu);
 		struct device *dev = NULL;
 		while ((dev = dev_bus_each_child(domain->downstream, dev)))
@@ -323,35 +312,24 @@ static unsigned long acpi_create_drhd(unsigned long current, struct device *iomm
 				acpi_create_dmar_ds_pci_br_for_port(
 				current, dev, pcie_seg, false, NULL);
 
-#if CONFIG(SOC_INTEL_SKYLAKE_SP) || CONFIG(SOC_INTEL_COOPERLAKE_SP)
-		// Add VMD
-		if (hob->PlatformData.VMDStackEnable[socket][stack] &&
-			stack >= PSTACK0 && stack <= PSTACK2) {
-			printk(BIOS_DEBUG, "    [PCI Endpoint Device] "
-				"PCI Bus Number: 0x%x, PCI Path: 0x%x, 0x%x\n",
-				 bus, VMD_DEV_NUM, VMD_FUNC_NUM);
-			current += acpi_create_dmar_ds_pci(current,
-				bus, VMD_DEV_NUM, VMD_FUNC_NUM);
-		}
-#endif
-	}
-
-	// Add IOAT End Points (with memory resources. We don't report every End Point device.)
-	if (CONFIG(HAVE_IOAT_DOMAINS) && is_dev_on_ioat_domain(iommu)) {
-		struct device *dev = NULL;
+		// Add PCIe end points
+		dev = NULL;
 		while ((dev = dev_find_all_devices_on_stack(socket, stack,
-			XEONSP_VENDOR_MAX, XEONSP_DEVICE_MAX, dev)))
-			/* This may also require a check for IORESOURCE_PREFETCH,
-			 * but that would not include the FPU (4942/0) */
-			if ((dev->resource_list->flags &
-				(IORESOURCE_MEM | IORESOURCE_PCI64 | IORESOURCE_ASSIGNED)) ==
-				(IORESOURCE_MEM | IORESOURCE_PCI64 | IORESOURCE_ASSIGNED)) {
-				const uint32_t b = dev->upstream->secondary;
-				const uint32_t d = PCI_SLOT(dev->path.pci.devfn);
-				const uint32_t f = PCI_FUNC(dev->path.pci.devfn);
-				printk(BIOS_DEBUG, "    [PCIE Endpoint Device] %s\n", dev_path(dev));
-				current += acpi_create_dmar_ds_pci(current, b, d, f);
-			}
+			XEONSP_VENDOR_MAX, XEONSP_DEVICE_MAX, dev))) {
+			const uint32_t b = dev->upstream->secondary;
+			const uint32_t d = PCI_SLOT(dev->path.pci.devfn);
+			const uint32_t f = PCI_FUNC(dev->path.pci.devfn);
+			struct device *upstream_dev = dev->upstream->dev;
+
+			if (is_pci_bridge(dev))
+				continue;
+
+			if (upstream_dev->path.type != DEVICE_PATH_DOMAIN)
+				continue;
+
+			printk(BIOS_DEBUG, "    [PCIE Endpoint Device] %s\n", dev_path(dev));
+			current += acpi_create_dmar_ds_pci(current, b, d, f);
+		}
 	}
 
 	// Add HPET
-- 
cgit v1.2.3