linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support
@ 2024-07-29 14:22 Sunil V L
  2024-07-29 14:22 ` [PATCH v7 01/17] arm64: PCI: Migrate ACPI related functions to pci-acpi.c Sunil V L
                   ` (16 more replies)
  0 siblings, 17 replies; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

This series adds support for the below ECR approved by ASWG.
1) MADT - https://drive.google.com/file/d/1oMGPyOD58JaPgMl1pKasT-VKsIKia7zR/view?usp=sharing

The series primarily enables irqchip drivers for RISC-V ACPI based
platforms.

The series can be broadly categorized like below. 

1) PCI ACPI related functions are migrated from arm64 to common file so
that we don't need to duplicate them for RISC-V.

2) Added support for re-ordering the probe of interrupt controllers when
IRQCHIP_ACPI_DECLARE is used.

3) To ensure probe order between interrupt controllers and devices,
implicit dependency is created similar to when _DEP is present.

4) ACPI support added in RISC-V interrupt controller drivers.

Changes since v6:
	1) Update to commit message/code comments as per feedback from Bjorn.
	2) Rebased to 6.11-rc1.

Changes since v5:
	1) Addressed feedback from Thomas.
	2) Created separate patch for refactoring DT code in IMSIC
	3) Separated a fix in riscv-intc irqchip driver and sent
	   separately. This series depends on that patch [1].
	4) Dropped serial driver patch since it depends on Andy's
	   refactoring series [2]. RISC-V patches will be sent
	   separately later once Andy series get accepted.
	5) Rebased to v6.10-rc1 which has AIA DT patches.
	6) Updated tags.

Changes since RFC v4:
	1) Removed RFC tag as the RFCv4 design looked reasonable.
	2) Dropped PCI patch needed to avoid warning when there is no MSI
	   controller. This will be sent later separately after the
	   current series.
	3) Dropped PNP handling of _DEP since there is new ACPI ID for
	   generic 16550 UART. Added the serial driver patch instead.
	4) Rebased to latest linux-next.
	5) Reordered/squashed patches in the series

Changes since RFC v3:
	1) Moved to _DEP method instead of fw_devlink.
	2) PLIC/APLIC driver probe using namespace devices.
	3) Handling PNP devices as part of clearing dependency.
	4) Rebased to latest linux-next to get AIA DT drivers.

Changes since RFC v2:
	1) Introduced fw_devlink for ACPI nodes for IRQ dependency.
	2) Dropped patches in drivers which are not required due to
	   fw_devlink support.
	3) Dropped pci_set_msi() patch and added a patch in
	   pci_create_root_bus().
	4) Updated pnp_irq() patch so that none of the actual PNP
	   drivers need to change.

Changes since RFC v1:
	1) Abandoned swnode approach as per Marc's feedback.
	2) To cope up with AIA series changes which changed irqchip driver
	   probe from core_initcall() to platform_driver, added patches
	   to support deferred probing.
	3) Rebased on top of Anup's AIA v11 and added tags.

To test the series,

1) qemu should be built using the latest master branch.

2) EDK2 should be built using the instructions at:
https://github.com/tianocore/edk2/blob/master/OvmfPkg/RiscVVirt/README.md

NOTE: One should be able to use u-boot as well as per instructions from Björn.
https://lore.kernel.org/lkml/87a5lqsrvh.fsf@all.your.base.are.belong.to.us/

3) Build Linux using this series.
Since serial driver patch is dropped, SBI_HVC console needs to be
used. Enable below configs while building the linux.
CONFIG_NONPORTABLE=y
CONFIG_HVC_RISCV_SBI=y

Run Qemu:
qemu-system-riscv64 \
 -M virt,pflash0=pflash0,pflash1=pflash1,aia=aplic-imsic \
 -m 2G -smp 8 \
 -serial mon:stdio \
 -device virtio-gpu-pci -full-screen \
 -device qemu-xhci \
 -device usb-kbd \
 -blockdev node-name=pflash0,driver=file,read-only=on,filename=RISCV_VIRT_CODE.fd \
 -blockdev node-name=pflash1,driver=file,filename=RISCV_VIRT_VARS.fd \
 -netdev user,id=net0 -device virtio-net-pci,netdev=net0 \
 -kernel arch/riscv/boot/Image \
 -initrd rootfs.cpio \
 -append "root=/dev/ram ro console=hvc0 rootwait earlycon=sbi"

To boot with APLIC only, use aia=aplic.
To boot with PLIC, remove aia= option.

This series is also available in acpi_b2_v7 branch at
https://github.com/vlsunil/linux.git

[2] - https://lore.kernel.org/lkml/20240506140308.4040735-1-andriy.shevchenko@linux.intel.com/


Sunil V L (17):
  arm64: PCI: Migrate ACPI related functions to pci-acpi.c
  ACPI: scan: Add a weak function to reorder the IRQCHIP probe
  ACPI: bus: Add acpi_riscv_init function
  ACPI: scan: Refactor dependency creation
  ACPI: scan: Add RISC-V interrupt controllers to honor list
  ACPI: scan: Define weak function to populate dependencies
  ACPI: bus: Add RINTC IRQ model for RISC-V
  ACPI: pci_link: Clear the dependencies after probe
  ACPI: RISC-V: Implement PCI related functionality
  ACPI: RISC-V: Implement function to reorder irqchip probe entries
  ACPI: RISC-V: Initialize GSI mapping structures
  ACPI: RISC-V: Implement function to add implicit dependencies
  irqchip/riscv-intc: Add ACPI support for AIA
  irqchip/riscv-imsic-state: Create separate function for DT
  irqchip/riscv-imsic: Add ACPI support
  irqchip/riscv-aplic: Add ACPI support
  irqchip/sifive-plic: Add ACPI support

 arch/arm64/kernel/pci.c                    | 191 ------------
 arch/riscv/Kconfig                         |   2 +
 arch/riscv/include/asm/irq.h               |  55 ++++
 arch/riscv/kernel/acpi.c                   |  33 +-
 drivers/acpi/bus.c                         |   4 +
 drivers/acpi/pci_link.c                    |   2 +
 drivers/acpi/riscv/Makefile                |   2 +-
 drivers/acpi/riscv/init.c                  |  14 +
 drivers/acpi/riscv/init.h                  |   4 +
 drivers/acpi/riscv/irq.c                   | 335 +++++++++++++++++++++
 drivers/acpi/scan.c                        | 103 ++++---
 drivers/irqchip/irq-riscv-aplic-direct.c   |  22 +-
 drivers/irqchip/irq-riscv-aplic-main.c     |  69 +++--
 drivers/irqchip/irq-riscv-aplic-main.h     |   1 +
 drivers/irqchip/irq-riscv-aplic-msi.c      |   9 +-
 drivers/irqchip/irq-riscv-imsic-early.c    |  64 +++-
 drivers/irqchip/irq-riscv-imsic-platform.c |  32 +-
 drivers/irqchip/irq-riscv-imsic-state.c    | 160 +++++-----
 drivers/irqchip/irq-riscv-imsic-state.h    |   2 +-
 drivers/irqchip/irq-riscv-intc.c           |  90 ++++++
 drivers/irqchip/irq-sifive-plic.c          |  94 ++++--
 drivers/pci/pci-acpi.c                     | 182 +++++++++++
 include/acpi/acpi_bus.h                    |   2 +
 include/linux/acpi.h                       |   9 +
 include/linux/irqchip/riscv-imsic.h        |   9 +
 25 files changed, 1113 insertions(+), 377 deletions(-)
 create mode 100644 drivers/acpi/riscv/init.c
 create mode 100644 drivers/acpi/riscv/init.h
 create mode 100644 drivers/acpi/riscv/irq.c

-- 
2.43.0



^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v7 01/17] arm64: PCI: Migrate ACPI related functions to pci-acpi.c
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-07-29 14:22 ` [PATCH v7 02/17] ACPI: scan: Add a weak function to reorder the IRQCHIP probe Sunil V L
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

The functions defined in arm64 for ACPI support are required
for RISC-V also. To avoid duplication, move these functions
to common location.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Acked-by: Will Deacon <will@kernel.org>
---
 arch/arm64/kernel/pci.c | 191 ----------------------------------------
 drivers/pci/pci-acpi.c  | 182 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 182 insertions(+), 191 deletions(-)

diff --git a/arch/arm64/kernel/pci.c b/arch/arm64/kernel/pci.c
index f872c57e9909..fd9a7bed83ce 100644
--- a/arch/arm64/kernel/pci.c
+++ b/arch/arm64/kernel/pci.c
@@ -6,28 +6,7 @@
  * Copyright (C) 2014 ARM Ltd.
  */
 
-#include <linux/acpi.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
 #include <linux/pci.h>
-#include <linux/pci-acpi.h>
-#include <linux/pci-ecam.h>
-#include <linux/slab.h>
-
-#ifdef CONFIG_ACPI
-/*
- * Try to assign the IRQ number when probing a new device
- */
-int pcibios_alloc_irq(struct pci_dev *dev)
-{
-	if (!acpi_disabled)
-		acpi_pci_irq_enable(dev);
-
-	return 0;
-}
-#endif
 
 /*
  * raw_pci_read/write - Platform-specific PCI config space access.
@@ -61,173 +40,3 @@ int pcibus_to_node(struct pci_bus *bus)
 EXPORT_SYMBOL(pcibus_to_node);
 
 #endif
-
-#ifdef CONFIG_ACPI
-
-struct acpi_pci_generic_root_info {
-	struct acpi_pci_root_info	common;
-	struct pci_config_window	*cfg;	/* config space mapping */
-};
-
-int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
-{
-	struct pci_config_window *cfg = bus->sysdata;
-	struct acpi_device *adev = to_acpi_device(cfg->parent);
-	struct acpi_pci_root *root = acpi_driver_data(adev);
-
-	return root->segment;
-}
-
-int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
-{
-	struct pci_config_window *cfg;
-	struct acpi_device *adev;
-	struct device *bus_dev;
-
-	if (acpi_disabled)
-		return 0;
-
-	cfg = bridge->bus->sysdata;
-
-	/*
-	 * On Hyper-V there is no corresponding ACPI device for a root bridge,
-	 * therefore ->parent is set as NULL by the driver. And set 'adev' as
-	 * NULL in this case because there is no proper ACPI device.
-	 */
-	if (!cfg->parent)
-		adev = NULL;
-	else
-		adev = to_acpi_device(cfg->parent);
-
-	bus_dev = &bridge->bus->dev;
-
-	ACPI_COMPANION_SET(&bridge->dev, adev);
-	set_dev_node(bus_dev, acpi_get_node(acpi_device_handle(adev)));
-
-	return 0;
-}
-
-static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci)
-{
-	struct resource_entry *entry, *tmp;
-	int status;
-
-	status = acpi_pci_probe_root_resources(ci);
-	resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
-		if (!(entry->res->flags & IORESOURCE_WINDOW))
-			resource_list_destroy_entry(entry);
-	}
-	return status;
-}
-
-/*
- * Lookup the bus range for the domain in MCFG, and set up config space
- * mapping.
- */
-static struct pci_config_window *
-pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
-{
-	struct device *dev = &root->device->dev;
-	struct resource *bus_res = &root->secondary;
-	u16 seg = root->segment;
-	const struct pci_ecam_ops *ecam_ops;
-	struct resource cfgres;
-	struct acpi_device *adev;
-	struct pci_config_window *cfg;
-	int ret;
-
-	ret = pci_mcfg_lookup(root, &cfgres, &ecam_ops);
-	if (ret) {
-		dev_err(dev, "%04x:%pR ECAM region not found\n", seg, bus_res);
-		return NULL;
-	}
-
-	adev = acpi_resource_consumer(&cfgres);
-	if (adev)
-		dev_info(dev, "ECAM area %pR reserved by %s\n", &cfgres,
-			 dev_name(&adev->dev));
-	else
-		dev_warn(dev, FW_BUG "ECAM area %pR not reserved in ACPI namespace\n",
-			 &cfgres);
-
-	cfg = pci_ecam_create(dev, &cfgres, bus_res, ecam_ops);
-	if (IS_ERR(cfg)) {
-		dev_err(dev, "%04x:%pR error %ld mapping ECAM\n", seg, bus_res,
-			PTR_ERR(cfg));
-		return NULL;
-	}
-
-	return cfg;
-}
-
-/* release_info: free resources allocated by init_info */
-static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci)
-{
-	struct acpi_pci_generic_root_info *ri;
-
-	ri = container_of(ci, struct acpi_pci_generic_root_info, common);
-	pci_ecam_free(ri->cfg);
-	kfree(ci->ops);
-	kfree(ri);
-}
-
-/* Interface called from ACPI code to setup PCI host controller */
-struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
-{
-	struct acpi_pci_generic_root_info *ri;
-	struct pci_bus *bus, *child;
-	struct acpi_pci_root_ops *root_ops;
-	struct pci_host_bridge *host;
-
-	ri = kzalloc(sizeof(*ri), GFP_KERNEL);
-	if (!ri)
-		return NULL;
-
-	root_ops = kzalloc(sizeof(*root_ops), GFP_KERNEL);
-	if (!root_ops) {
-		kfree(ri);
-		return NULL;
-	}
-
-	ri->cfg = pci_acpi_setup_ecam_mapping(root);
-	if (!ri->cfg) {
-		kfree(ri);
-		kfree(root_ops);
-		return NULL;
-	}
-
-	root_ops->release_info = pci_acpi_generic_release_info;
-	root_ops->prepare_resources = pci_acpi_root_prepare_resources;
-	root_ops->pci_ops = (struct pci_ops *)&ri->cfg->ops->pci_ops;
-	bus = acpi_pci_root_create(root, root_ops, &ri->common, ri->cfg);
-	if (!bus)
-		return NULL;
-
-	/* If we must preserve the resource configuration, claim now */
-	host = pci_find_host_bridge(bus);
-	if (host->preserve_config)
-		pci_bus_claim_resources(bus);
-
-	/*
-	 * Assign whatever was left unassigned. If we didn't claim above,
-	 * this will reassign everything.
-	 */
-	pci_assign_unassigned_root_bus_resources(bus);
-
-	list_for_each_entry(child, &bus->children, node)
-		pcie_bus_configure_settings(child);
-
-	return bus;
-}
-
-void pcibios_add_bus(struct pci_bus *bus)
-{
-	acpi_pci_add_bus(bus);
-}
-
-void pcibios_remove_bus(struct pci_bus *bus)
-{
-	acpi_pci_remove_bus(bus);
-}
-
-#endif
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 9cc447da9475..8ed81a373bd7 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -15,6 +15,7 @@
 #include <linux/pci_hotplug.h>
 #include <linux/module.h>
 #include <linux/pci-acpi.h>
+#include <linux/pci-ecam.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_qos.h>
 #include <linux/rwsem.h>
@@ -1541,3 +1542,184 @@ static int __init acpi_pci_init(void)
 	return 0;
 }
 arch_initcall(acpi_pci_init);
+
+#if defined(CONFIG_ARM64)
+
+/*
+ * Try to assign the IRQ number when probing a new device
+ */
+int pcibios_alloc_irq(struct pci_dev *dev)
+{
+	if (!acpi_disabled)
+		acpi_pci_irq_enable(dev);
+
+	return 0;
+}
+
+struct acpi_pci_generic_root_info {
+	struct acpi_pci_root_info	common;
+	struct pci_config_window	*cfg;	/* config space mapping */
+};
+
+int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
+{
+	struct pci_config_window *cfg = bus->sysdata;
+	struct acpi_device *adev = to_acpi_device(cfg->parent);
+	struct acpi_pci_root *root = acpi_driver_data(adev);
+
+	return root->segment;
+}
+
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	struct pci_config_window *cfg;
+	struct acpi_device *adev;
+	struct device *bus_dev;
+
+	if (acpi_disabled)
+		return 0;
+
+	cfg = bridge->bus->sysdata;
+
+	/*
+	 * On Hyper-V there is no corresponding ACPI device for a root bridge,
+	 * therefore ->parent is set as NULL by the driver. And set 'adev' as
+	 * NULL in this case because there is no proper ACPI device.
+	 */
+	if (!cfg->parent)
+		adev = NULL;
+	else
+		adev = to_acpi_device(cfg->parent);
+
+	bus_dev = &bridge->bus->dev;
+
+	ACPI_COMPANION_SET(&bridge->dev, adev);
+	set_dev_node(bus_dev, acpi_get_node(acpi_device_handle(adev)));
+
+	return 0;
+}
+
+static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci)
+{
+	struct resource_entry *entry, *tmp;
+	int status;
+
+	status = acpi_pci_probe_root_resources(ci);
+	resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
+		if (!(entry->res->flags & IORESOURCE_WINDOW))
+			resource_list_destroy_entry(entry);
+	}
+	return status;
+}
+
+/*
+ * Lookup the bus range for the domain in MCFG, and set up config space
+ * mapping.
+ */
+static struct pci_config_window *
+pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root)
+{
+	struct device *dev = &root->device->dev;
+	struct resource *bus_res = &root->secondary;
+	u16 seg = root->segment;
+	const struct pci_ecam_ops *ecam_ops;
+	struct resource cfgres;
+	struct acpi_device *adev;
+	struct pci_config_window *cfg;
+	int ret;
+
+	ret = pci_mcfg_lookup(root, &cfgres, &ecam_ops);
+	if (ret) {
+		dev_err(dev, "%04x:%pR ECAM region not found\n", seg, bus_res);
+		return NULL;
+	}
+
+	adev = acpi_resource_consumer(&cfgres);
+	if (adev)
+		dev_info(dev, "ECAM area %pR reserved by %s\n", &cfgres,
+			 dev_name(&adev->dev));
+	else
+		dev_warn(dev, FW_BUG "ECAM area %pR not reserved in ACPI namespace\n",
+			 &cfgres);
+
+	cfg = pci_ecam_create(dev, &cfgres, bus_res, ecam_ops);
+	if (IS_ERR(cfg)) {
+		dev_err(dev, "%04x:%pR error %ld mapping ECAM\n", seg, bus_res,
+			PTR_ERR(cfg));
+		return NULL;
+	}
+
+	return cfg;
+}
+
+/* release_info: free resources allocated by init_info */
+static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci)
+{
+	struct acpi_pci_generic_root_info *ri;
+
+	ri = container_of(ci, struct acpi_pci_generic_root_info, common);
+	pci_ecam_free(ri->cfg);
+	kfree(ci->ops);
+	kfree(ri);
+}
+
+/* Interface called from ACPI code to setup PCI host controller */
+struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
+{
+	struct acpi_pci_generic_root_info *ri;
+	struct pci_bus *bus, *child;
+	struct acpi_pci_root_ops *root_ops;
+	struct pci_host_bridge *host;
+
+	ri = kzalloc(sizeof(*ri), GFP_KERNEL);
+	if (!ri)
+		return NULL;
+
+	root_ops = kzalloc(sizeof(*root_ops), GFP_KERNEL);
+	if (!root_ops) {
+		kfree(ri);
+		return NULL;
+	}
+
+	ri->cfg = pci_acpi_setup_ecam_mapping(root);
+	if (!ri->cfg) {
+		kfree(ri);
+		kfree(root_ops);
+		return NULL;
+	}
+
+	root_ops->release_info = pci_acpi_generic_release_info;
+	root_ops->prepare_resources = pci_acpi_root_prepare_resources;
+	root_ops->pci_ops = (struct pci_ops *)&ri->cfg->ops->pci_ops;
+	bus = acpi_pci_root_create(root, root_ops, &ri->common, ri->cfg);
+	if (!bus)
+		return NULL;
+
+	/* If we must preserve the resource configuration, claim now */
+	host = pci_find_host_bridge(bus);
+	if (host->preserve_config)
+		pci_bus_claim_resources(bus);
+
+	/*
+	 * Assign whatever was left unassigned. If we didn't claim above,
+	 * this will reassign everything.
+	 */
+	pci_assign_unassigned_root_bus_resources(bus);
+
+	list_for_each_entry(child, &bus->children, node)
+		pcie_bus_configure_settings(child);
+
+	return bus;
+}
+
+void pcibios_add_bus(struct pci_bus *bus)
+{
+	acpi_pci_add_bus(bus);
+}
+
+void pcibios_remove_bus(struct pci_bus *bus)
+{
+	acpi_pci_remove_bus(bus);
+}
+
+#endif
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 02/17] ACPI: scan: Add a weak function to reorder the IRQCHIP probe
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
  2024-07-29 14:22 ` [PATCH v7 01/17] arm64: PCI: Migrate ACPI related functions to pci-acpi.c Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-07-31 19:41   ` Bjorn Helgaas
  2024-07-29 14:22 ` [PATCH v7 03/17] ACPI: bus: Add acpi_riscv_init function Sunil V L
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

Unlike OF framework, the irqchip probe using IRQCHIP_ACPI_DECLARE has no
order defined. Depending on the Makefile is not a good idea. So,
usually it is worked around by mandating only root interrupt controller
probed using IRQCHIP_ACPI_DECLARE and other interrupt controllers are
probed via cascade mechanism.

However, this is also not a clean solution because if there are multiple
root controllers (ex: RINTC in RISC-V which is per CPU) which need to be
probed first, then the cascade will happen for every root controller.
So, introduce a architecture specific weak function to order the probing
of the interrupt controllers which can be implemented by different
architectures as per their interrupt controller hierarchy.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 drivers/acpi/scan.c  | 3 +++
 include/linux/acpi.h | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 59771412686b..52a9dfc8e18c 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2755,6 +2755,8 @@ static int __init acpi_match_madt(union acpi_subtable_headers *header,
 	return 0;
 }
 
+void __weak arch_sort_irqchip_probe(struct acpi_probe_entry *ap_head, int nr) { }
+
 int __init __acpi_probe_device_table(struct acpi_probe_entry *ap_head, int nr)
 {
 	int count = 0;
@@ -2763,6 +2765,7 @@ int __init __acpi_probe_device_table(struct acpi_probe_entry *ap_head, int nr)
 		return 0;
 
 	mutex_lock(&acpi_probe_mutex);
+	arch_sort_irqchip_probe(ap_head, nr);
 	for (ape = ap_head; nr; ape++, nr--) {
 		if (ACPI_COMPARE_NAMESEG(ACPI_SIG_MADT, ape->id)) {
 			acpi_probe_count = 0;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 0687a442fec7..3fff86f95c2f 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -1343,6 +1343,8 @@ struct acpi_probe_entry {
 	kernel_ulong_t driver_data;
 };
 
+void arch_sort_irqchip_probe(struct acpi_probe_entry *ap_head, int nr);
+
 #define ACPI_DECLARE_PROBE_ENTRY(table, name, table_id, subtable,	\
 				 valid, data, fn)			\
 	static const struct acpi_probe_entry __acpi_probe_##name	\
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 03/17] ACPI: bus: Add acpi_riscv_init function
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
  2024-07-29 14:22 ` [PATCH v7 01/17] arm64: PCI: Migrate ACPI related functions to pci-acpi.c Sunil V L
  2024-07-29 14:22 ` [PATCH v7 02/17] ACPI: scan: Add a weak function to reorder the IRQCHIP probe Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-07-31 19:42   ` Bjorn Helgaas
  2024-07-29 14:22 ` [PATCH v7 04/17] ACPI: scan: Refactor dependency creation Sunil V L
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

Add a new function for RISC-V to do architecture specific initialization
similar to acpi_arm_init(). Some of the ACPI tables are architecture
specific and there is no reason trying to find them on other
architectures.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 drivers/acpi/bus.c          |  1 +
 drivers/acpi/riscv/Makefile |  2 +-
 drivers/acpi/riscv/init.c   | 12 ++++++++++++
 include/linux/acpi.h        |  6 ++++++
 4 files changed, 20 insertions(+), 1 deletion(-)
 create mode 100644 drivers/acpi/riscv/init.c

diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 284bc2e03580..48d277657203 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -1459,6 +1459,7 @@ static int __init acpi_init(void)
 	acpi_hest_init();
 	acpi_ghes_init();
 	acpi_arm_init();
+	acpi_riscv_init();
 	acpi_scan_init();
 	acpi_ec_init();
 	acpi_debugfs_init();
diff --git a/drivers/acpi/riscv/Makefile b/drivers/acpi/riscv/Makefile
index 86b0925f612d..877de00d1b50 100644
--- a/drivers/acpi/riscv/Makefile
+++ b/drivers/acpi/riscv/Makefile
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-y					+= rhct.o
+obj-y					+= rhct.o init.o
 obj-$(CONFIG_ACPI_PROCESSOR_IDLE)	+= cpuidle.o
 obj-$(CONFIG_ACPI_CPPC_LIB)		+= cppc.o
diff --git a/drivers/acpi/riscv/init.c b/drivers/acpi/riscv/init.c
new file mode 100644
index 000000000000..5f7571143245
--- /dev/null
+++ b/drivers/acpi/riscv/init.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023-2024, Ventana Micro Systems Inc
+ *	Author: Sunil V L <sunilvl@ventanamicro.com>
+ *
+ */
+
+#include <linux/acpi.h>
+
+void __init acpi_riscv_init(void)
+{
+}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 3fff86f95c2f..892025d873f0 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -1531,6 +1531,12 @@ void acpi_arm_init(void);
 static inline void acpi_arm_init(void) { }
 #endif
 
+#ifdef CONFIG_RISCV
+void acpi_riscv_init(void);
+#else
+static inline void acpi_riscv_init(void) { }
+#endif
+
 #ifdef CONFIG_ACPI_PCC
 void acpi_init_pcc(void);
 #else
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 04/17] ACPI: scan: Refactor dependency creation
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
                   ` (2 preceding siblings ...)
  2024-07-29 14:22 ` [PATCH v7 03/17] ACPI: bus: Add acpi_riscv_init function Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-07-29 14:22 ` [PATCH v7 05/17] ACPI: scan: Add RISC-V interrupt controllers to honor list Sunil V L
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

Some architectures like RISC-V will use implicit dependencies like GSI
map to create dependencies between interrupt controller and devices. To
support doing that, the function which creates the dependency, is
refactored bit and made public so that dependency can be added from
outside of scan.c as well.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 drivers/acpi/scan.c     | 86 ++++++++++++++++++++++-------------------
 include/acpi/acpi_bus.h |  1 +
 2 files changed, 48 insertions(+), 39 deletions(-)

diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 52a9dfc8e18c..374cae4aef78 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2013,6 +2013,49 @@ void acpi_scan_hotplug_enabled(struct acpi_hotplug_profile *hotplug, bool val)
 	mutex_unlock(&acpi_scan_lock);
 }
 
+int acpi_scan_add_dep(acpi_handle handle, struct acpi_handle_list *dep_devices)
+{
+	u32 count;
+	int i;
+
+	for (count = 0, i = 0; i < dep_devices->count; i++) {
+		struct acpi_device_info *info;
+		struct acpi_dep_data *dep;
+		bool skip, honor_dep;
+		acpi_status status;
+
+		status = acpi_get_object_info(dep_devices->handles[i], &info);
+		if (ACPI_FAILURE(status)) {
+			acpi_handle_debug(handle, "Error reading _DEP device info\n");
+			continue;
+		}
+
+		skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids);
+		honor_dep = acpi_info_matches_ids(info, acpi_honor_dep_ids);
+		kfree(info);
+
+		if (skip)
+			continue;
+
+		dep = kzalloc(sizeof(*dep), GFP_KERNEL);
+		if (!dep)
+			continue;
+
+		count++;
+
+		dep->supplier = dep_devices->handles[i];
+		dep->consumer = handle;
+		dep->honor_dep = honor_dep;
+
+		mutex_lock(&acpi_dep_list_lock);
+		list_add_tail(&dep->node, &acpi_dep_list);
+		mutex_unlock(&acpi_dep_list_lock);
+	}
+
+	acpi_handle_list_free(dep_devices);
+	return count;
+}
+
 static void acpi_scan_init_hotplug(struct acpi_device *adev)
 {
 	struct acpi_hardware_id *hwid;
@@ -2035,8 +2078,7 @@ static void acpi_scan_init_hotplug(struct acpi_device *adev)
 static u32 acpi_scan_check_dep(acpi_handle handle)
 {
 	struct acpi_handle_list dep_devices;
-	u32 count;
-	int i;
+	u32 count = 0;
 
 	/*
 	 * Check for _HID here to avoid deferring the enumeration of:
@@ -2045,48 +2087,14 @@ static u32 acpi_scan_check_dep(acpi_handle handle)
 	 * Still, checking for _HID catches more then just these cases ...
 	 */
 	if (!acpi_has_method(handle, "_DEP") || !acpi_has_method(handle, "_HID"))
-		return 0;
+		return count;
 
 	if (!acpi_evaluate_reference(handle, "_DEP", NULL, &dep_devices)) {
 		acpi_handle_debug(handle, "Failed to evaluate _DEP.\n");
-		return 0;
+		return count;
 	}
 
-	for (count = 0, i = 0; i < dep_devices.count; i++) {
-		struct acpi_device_info *info;
-		struct acpi_dep_data *dep;
-		bool skip, honor_dep;
-		acpi_status status;
-
-		status = acpi_get_object_info(dep_devices.handles[i], &info);
-		if (ACPI_FAILURE(status)) {
-			acpi_handle_debug(handle, "Error reading _DEP device info\n");
-			continue;
-		}
-
-		skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids);
-		honor_dep = acpi_info_matches_ids(info, acpi_honor_dep_ids);
-		kfree(info);
-
-		if (skip)
-			continue;
-
-		dep = kzalloc(sizeof(*dep), GFP_KERNEL);
-		if (!dep)
-			continue;
-
-		count++;
-
-		dep->supplier = dep_devices.handles[i];
-		dep->consumer = handle;
-		dep->honor_dep = honor_dep;
-
-		mutex_lock(&acpi_dep_list_lock);
-		list_add_tail(&dep->node , &acpi_dep_list);
-		mutex_unlock(&acpi_dep_list_lock);
-	}
-
-	acpi_handle_list_free(&dep_devices);
+	count += acpi_scan_add_dep(handle, &dep_devices);
 	return count;
 }
 
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 8db5bd382915..d6a4dd58e36f 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -993,6 +993,7 @@ static inline void acpi_put_acpi_dev(struct acpi_device *adev)
 
 int acpi_wait_for_acpi_ipmi(void);
 
+int acpi_scan_add_dep(acpi_handle handle, struct acpi_handle_list *dep_devices);
 #else	/* CONFIG_ACPI */
 
 static inline int register_acpi_bus_type(void *bus) { return 0; }
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 05/17] ACPI: scan: Add RISC-V interrupt controllers to honor list
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
                   ` (3 preceding siblings ...)
  2024-07-29 14:22 ` [PATCH v7 04/17] ACPI: scan: Refactor dependency creation Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-07-29 14:22 ` [PATCH v7 06/17] ACPI: scan: Define weak function to populate dependencies Sunil V L
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

RISC-V PLIC and APLIC will have dependency from devices using GSI. So, add
these devices to the honor list.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 drivers/acpi/scan.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 374cae4aef78..39b3ccae9f79 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -861,6 +861,8 @@ static const char * const acpi_honor_dep_ids[] = {
 	"INTC1095", /* IVSC (ADL) driver must be loaded to allow i2c access to camera sensors */
 	"INTC100A", /* IVSC (RPL) driver must be loaded to allow i2c access to camera sensors */
 	"INTC10CF", /* IVSC (MTL) driver must be loaded to allow i2c access to camera sensors */
+	"RSCV0001", /* RISC-V PLIC */
+	"RSCV0002", /* RISC-V APLIC */
 	NULL
 };
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 06/17] ACPI: scan: Define weak function to populate dependencies
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
                   ` (4 preceding siblings ...)
  2024-07-29 14:22 ` [PATCH v7 05/17] ACPI: scan: Add RISC-V interrupt controllers to honor list Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-07-29 14:22 ` [PATCH v7 07/17] ACPI: bus: Add RINTC IRQ model for RISC-V Sunil V L
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

Some architectures like RISC-V need to add dependencies without explicit
_DEP. Define a weak function which can be implemented by the architecture.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 drivers/acpi/scan.c     | 11 +++++++++++
 include/acpi/acpi_bus.h |  1 +
 2 files changed, 12 insertions(+)

diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 39b3ccae9f79..28a221f956d7 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2077,11 +2077,22 @@ static void acpi_scan_init_hotplug(struct acpi_device *adev)
 	}
 }
 
+u32 __weak arch_acpi_add_auto_dep(acpi_handle handle) { return 0; }
+
 static u32 acpi_scan_check_dep(acpi_handle handle)
 {
 	struct acpi_handle_list dep_devices;
 	u32 count = 0;
 
+	/*
+	 * Some architectures like RISC-V need to add dependencies for
+	 * all devices which use GSI to the interrupt controller so that
+	 * interrupt controller is probed before any of those devices.
+	 * Instead of mandating _DEP on all the devices, detect the
+	 * dependency and add automatically.
+	 */
+	count += arch_acpi_add_auto_dep(handle);
+
 	/*
 	 * Check for _HID here to avoid deferring the enumeration of:
 	 * 1. PCI devices.
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index d6a4dd58e36f..af72a5d9de99 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -994,6 +994,7 @@ static inline void acpi_put_acpi_dev(struct acpi_device *adev)
 int acpi_wait_for_acpi_ipmi(void);
 
 int acpi_scan_add_dep(acpi_handle handle, struct acpi_handle_list *dep_devices);
+u32 arch_acpi_add_auto_dep(acpi_handle handle);
 #else	/* CONFIG_ACPI */
 
 static inline int register_acpi_bus_type(void *bus) { return 0; }
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 07/17] ACPI: bus: Add RINTC IRQ model for RISC-V
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
                   ` (5 preceding siblings ...)
  2024-07-29 14:22 ` [PATCH v7 06/17] ACPI: scan: Define weak function to populate dependencies Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-07-29 14:22 ` [PATCH v7 08/17] ACPI: pci_link: Clear the dependencies after probe Sunil V L
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

Add the IRQ model for RISC-V INTC so that acpi_set_irq_model can use this
for RISC-V.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 drivers/acpi/bus.c   | 3 +++
 include/linux/acpi.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 48d277657203..16917dc3ad60 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -1203,6 +1203,9 @@ static int __init acpi_bus_init_irq(void)
 	case ACPI_IRQ_MODEL_LPIC:
 		message = "LPIC";
 		break;
+	case ACPI_IRQ_MODEL_RINTC:
+		message = "RINTC";
+		break;
 	default:
 		pr_info("Unknown interrupt routing model\n");
 		return -ENODEV;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 892025d873f0..3a21f1cf126f 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -107,6 +107,7 @@ enum acpi_irq_model_id {
 	ACPI_IRQ_MODEL_PLATFORM,
 	ACPI_IRQ_MODEL_GIC,
 	ACPI_IRQ_MODEL_LPIC,
+	ACPI_IRQ_MODEL_RINTC,
 	ACPI_IRQ_MODEL_COUNT
 };
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 08/17] ACPI: pci_link: Clear the dependencies after probe
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
                   ` (6 preceding siblings ...)
  2024-07-29 14:22 ` [PATCH v7 07/17] ACPI: bus: Add RINTC IRQ model for RISC-V Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-07-31 19:49   ` Bjorn Helgaas
                     ` (2 more replies)
  2024-07-29 14:22 ` [PATCH v7 09/17] ACPI: RISC-V: Implement PCI related functionality Sunil V L
                   ` (8 subsequent siblings)
  16 siblings, 3 replies; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

RISC-V platforms need to use dependencies between PCI host bridge, Link
devices and the interrupt controllers to ensure probe order. The
dependency is like below.

Interrupt controller <-- Link Device <-- PCI Host bridge.

If there is no dependency added between Link device and PCI Host Bridge,
then the PCI end points can get probed prior to link device, unable to
get mapping for INTx.

So, add the link device's HID to dependency honor list and also clear it
after its probe.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 drivers/acpi/pci_link.c | 2 ++
 drivers/acpi/scan.c     | 1 +
 2 files changed, 3 insertions(+)

diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index aa1038b8aec4..b727db968f33 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -748,6 +748,8 @@ static int acpi_pci_link_add(struct acpi_device *device,
 	if (result)
 		kfree(link);
 
+	acpi_dev_clear_dependencies(device);
+
 	return result < 0 ? result : 1;
 }
 
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 28a221f956d7..753539a1f26b 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -863,6 +863,7 @@ static const char * const acpi_honor_dep_ids[] = {
 	"INTC10CF", /* IVSC (MTL) driver must be loaded to allow i2c access to camera sensors */
 	"RSCV0001", /* RISC-V PLIC */
 	"RSCV0002", /* RISC-V APLIC */
+	"PNP0C0F",  /* PCI Link Device */
 	NULL
 };
 
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 09/17] ACPI: RISC-V: Implement PCI related functionality
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
                   ` (7 preceding siblings ...)
  2024-07-29 14:22 ` [PATCH v7 08/17] ACPI: pci_link: Clear the dependencies after probe Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-07-29 14:22 ` [PATCH v7 10/17] ACPI: RISC-V: Implement function to reorder irqchip probe entries Sunil V L
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

Replace the dummy implementation for PCI related functions with actual
implementation. This needs ECAM and MCFG CONFIG options to be enabled
for RISC-V.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 arch/riscv/Kconfig       |  2 ++
 arch/riscv/kernel/acpi.c | 33 +++++++++++++++------------------
 drivers/pci/pci-acpi.c   |  2 +-
 3 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 0f3cd7c3a436..a269e577284e 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -13,6 +13,7 @@ config 32BIT
 config RISCV
 	def_bool y
 	select ACPI_GENERIC_GSI if ACPI
+	select ACPI_MCFG if (ACPI && PCI)
 	select ACPI_PPTT if ACPI
 	select ACPI_REDUCED_HARDWARE_ONLY if ACPI
 	select ACPI_SPCR_TABLE if ACPI
@@ -188,6 +189,7 @@ config RISCV
 	select OF_EARLY_FLATTREE
 	select OF_IRQ
 	select PCI_DOMAINS_GENERIC if PCI
+	select PCI_ECAM if (ACPI && PCI)
 	select PCI_MSI if PCI
 	select RISCV_ALTERNATIVE if !XIP_KERNEL
 	select RISCV_APLIC
diff --git a/arch/riscv/kernel/acpi.c b/arch/riscv/kernel/acpi.c
index ba957aaca5cb..6e0d333f57e5 100644
--- a/arch/riscv/kernel/acpi.c
+++ b/arch/riscv/kernel/acpi.c
@@ -311,29 +311,26 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
 #ifdef CONFIG_PCI
 
 /*
- * These interfaces are defined just to enable building ACPI core.
- * TODO: Update it with actual implementation when external interrupt
- * controller support is added in RISC-V ACPI.
+ * raw_pci_read/write - Platform-specific PCI config space access.
  */
-int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
-		 int reg, int len, u32 *val)
+int raw_pci_read(unsigned int domain, unsigned int bus,
+		 unsigned int devfn, int reg, int len, u32 *val)
 {
-	return PCIBIOS_DEVICE_NOT_FOUND;
+	struct pci_bus *b = pci_find_bus(domain, bus);
+
+	if (!b)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	return b->ops->read(b, devfn, reg, len, val);
 }
 
-int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
-		  int reg, int len, u32 val)
+int raw_pci_write(unsigned int domain, unsigned int bus,
+		  unsigned int devfn, int reg, int len, u32 val)
 {
-	return PCIBIOS_DEVICE_NOT_FOUND;
+	struct pci_bus *b = pci_find_bus(domain, bus);
+
+	if (!b)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	return b->ops->write(b, devfn, reg, len, val);
 }
 
-int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
-{
-	return -1;
-}
-
-struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
-{
-	return NULL;
-}
 #endif	/* CONFIG_PCI */
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 8ed81a373bd7..af370628e583 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -1543,7 +1543,7 @@ static int __init acpi_pci_init(void)
 }
 arch_initcall(acpi_pci_init);
 
-#if defined(CONFIG_ARM64)
+#if defined(CONFIG_ARM64) || defined(CONFIG_RISCV)
 
 /*
  * Try to assign the IRQ number when probing a new device
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 10/17] ACPI: RISC-V: Implement function to reorder irqchip probe entries
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
                   ` (8 preceding siblings ...)
  2024-07-29 14:22 ` [PATCH v7 09/17] ACPI: RISC-V: Implement PCI related functionality Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-07-29 14:22 ` [PATCH v7 11/17] ACPI: RISC-V: Initialize GSI mapping structures Sunil V L
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

On RISC-V platforms, the RINTC structures should be probed before any
other interrupt controller structures and IMSIC before APLIC. This order
is established by using MADT sub table types which are ordered in the
incremental order from the RINTC. So, add the architecture function for
RISC-V to reorder the interrupt controller probing as per the hierarchy
like below.

  ACPI_MADT_TYPE_RINTC = 24,
  ACPI_MADT_TYPE_IMSIC = 25,
  ACPI_MADT_TYPE_APLIC = 26,
  ACPI_MADT_TYPE_PLIC = 27

This means processing all RINTC structures (in the order of appearance
in MADT), followed by IMSIC strucutre and then all APLIC/PLIC
structures.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 drivers/acpi/riscv/Makefile |  2 +-
 drivers/acpi/riscv/irq.c    | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 1 deletion(-)
 create mode 100644 drivers/acpi/riscv/irq.c

diff --git a/drivers/acpi/riscv/Makefile b/drivers/acpi/riscv/Makefile
index 877de00d1b50..a96fdf1e2cb8 100644
--- a/drivers/acpi/riscv/Makefile
+++ b/drivers/acpi/riscv/Makefile
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-y					+= rhct.o init.o
+obj-y					+= rhct.o init.o irq.o
 obj-$(CONFIG_ACPI_PROCESSOR_IDLE)	+= cpuidle.o
 obj-$(CONFIG_ACPI_CPPC_LIB)		+= cppc.o
diff --git a/drivers/acpi/riscv/irq.c b/drivers/acpi/riscv/irq.c
new file mode 100644
index 000000000000..835eb6eccd53
--- /dev/null
+++ b/drivers/acpi/riscv/irq.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023-2024, Ventana Micro Systems Inc
+ *	Author: Sunil V L <sunilvl@ventanamicro.com>
+ */
+
+#include <linux/acpi.h>
+#include <linux/sort.h>
+
+static int irqchip_cmp_func(const void *in0, const void *in1)
+{
+	struct acpi_probe_entry *elem0 = (struct acpi_probe_entry *)in0;
+	struct acpi_probe_entry *elem1 = (struct acpi_probe_entry *)in1;
+
+	return (elem0->type > elem1->type) - (elem0->type < elem1->type);
+}
+
+/*
+ * On RISC-V, RINTC structures in MADT should be probed before any other
+ * interrupt controller structures and IMSIC before APLIC. The interrupt
+ * controller subtypes in MADT of ACPI spec for RISC-V are defined in
+ * the incremental order like RINTC(24)->IMSIC(25)->APLIC(26)->PLIC(27).
+ * Hence, simply sorting the subtypes in incremental order will
+ * establish the required order.
+ */
+void arch_sort_irqchip_probe(struct acpi_probe_entry *ap_head, int nr)
+{
+	struct acpi_probe_entry *ape = ap_head;
+
+	if (nr == 1 || !ACPI_COMPARE_NAMESEG(ACPI_SIG_MADT, ape->id))
+		return;
+	sort(ape, nr, sizeof(*ape), irqchip_cmp_func, NULL);
+}
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 11/17] ACPI: RISC-V: Initialize GSI mapping structures
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
                   ` (9 preceding siblings ...)
  2024-07-29 14:22 ` [PATCH v7 10/17] ACPI: RISC-V: Implement function to reorder irqchip probe entries Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-07-29 14:22 ` [PATCH v7 12/17] ACPI: RISC-V: Implement function to add implicit dependencies Sunil V L
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

RISC-V has PLIC and APLIC in MADT as well as namespace devices.
Initialize the list of those structures using MADT and namespace devices
to create mapping between the ACPI handle and the GSI ranges. This will
be used later to add dependencies.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 arch/riscv/include/asm/irq.h |  22 ++++++
 drivers/acpi/riscv/init.c    |   2 +
 drivers/acpi/riscv/init.h    |   4 +
 drivers/acpi/riscv/irq.c     | 147 +++++++++++++++++++++++++++++++++++
 4 files changed, 175 insertions(+)
 create mode 100644 drivers/acpi/riscv/init.h

diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h
index 8e10a94430a2..44a0b128c602 100644
--- a/arch/riscv/include/asm/irq.h
+++ b/arch/riscv/include/asm/irq.h
@@ -16,4 +16,26 @@ void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void));
 
 struct fwnode_handle *riscv_get_intc_hwnode(void);
 
+#ifdef CONFIG_ACPI
+
+enum riscv_irqchip_type {
+	ACPI_RISCV_IRQCHIP_INTC		= 0x00,
+	ACPI_RISCV_IRQCHIP_IMSIC	= 0x01,
+	ACPI_RISCV_IRQCHIP_PLIC		= 0x02,
+	ACPI_RISCV_IRQCHIP_APLIC	= 0x03,
+};
+
+int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi_base,
+			    u32 *id, u32 *nr_irqs, u32 *nr_idcs);
+struct fwnode_handle *riscv_acpi_get_gsi_domain_id(u32 gsi);
+
+#else
+static inline int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi_base,
+					  u32 *id, u32 *nr_irqs, u32 *nr_idcs)
+{
+	return 0;
+}
+
+#endif /* CONFIG_ACPI */
+
 #endif /* _ASM_RISCV_IRQ_H */
diff --git a/drivers/acpi/riscv/init.c b/drivers/acpi/riscv/init.c
index 5f7571143245..22db97f7a772 100644
--- a/drivers/acpi/riscv/init.c
+++ b/drivers/acpi/riscv/init.c
@@ -6,7 +6,9 @@
  */
 
 #include <linux/acpi.h>
+#include "init.h"
 
 void __init acpi_riscv_init(void)
 {
+	riscv_acpi_init_gsi_mapping();
 }
diff --git a/drivers/acpi/riscv/init.h b/drivers/acpi/riscv/init.h
new file mode 100644
index 000000000000..0b9a07e4031f
--- /dev/null
+++ b/drivers/acpi/riscv/init.h
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include <linux/init.h>
+
+void __init riscv_acpi_init_gsi_mapping(void);
diff --git a/drivers/acpi/riscv/irq.c b/drivers/acpi/riscv/irq.c
index 835eb6eccd53..9028787c73a7 100644
--- a/drivers/acpi/riscv/irq.c
+++ b/drivers/acpi/riscv/irq.c
@@ -6,6 +6,21 @@
 
 #include <linux/acpi.h>
 #include <linux/sort.h>
+#include <linux/irq.h>
+
+#include "init.h"
+
+struct riscv_ext_intc_list {
+	acpi_handle		handle;
+	u32			gsi_base;
+	u32			nr_irqs;
+	u32			nr_idcs;
+	u32			id;
+	u32			type;
+	struct list_head	list;
+};
+
+LIST_HEAD(ext_intc_list);
 
 static int irqchip_cmp_func(const void *in0, const void *in1)
 {
@@ -31,3 +46,135 @@ void arch_sort_irqchip_probe(struct acpi_probe_entry *ap_head, int nr)
 		return;
 	sort(ape, nr, sizeof(*ape), irqchip_cmp_func, NULL);
 }
+
+static acpi_status riscv_acpi_update_gsi_handle(u32 gsi_base, acpi_handle handle)
+{
+	struct riscv_ext_intc_list *ext_intc_element;
+	struct list_head *i, *tmp;
+
+	list_for_each_safe(i, tmp, &ext_intc_list) {
+		ext_intc_element = list_entry(i, struct riscv_ext_intc_list, list);
+		if (gsi_base == ext_intc_element->gsi_base) {
+			ext_intc_element->handle = handle;
+			return AE_OK;
+		}
+	}
+
+	return AE_NOT_FOUND;
+}
+
+int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi_base,
+			    u32 *id, u32 *nr_irqs, u32 *nr_idcs)
+{
+	struct riscv_ext_intc_list *ext_intc_element;
+	struct list_head *i;
+
+	list_for_each(i, &ext_intc_list) {
+		ext_intc_element = list_entry(i, struct riscv_ext_intc_list, list);
+		if (ext_intc_element->handle == ACPI_HANDLE_FWNODE(fwnode)) {
+			*gsi_base = ext_intc_element->gsi_base;
+			*id = ext_intc_element->id;
+			*nr_irqs = ext_intc_element->nr_irqs;
+			if (nr_idcs)
+				*nr_idcs = ext_intc_element->nr_idcs;
+
+			return 0;
+		}
+	}
+
+	return -ENODEV;
+}
+
+struct fwnode_handle *riscv_acpi_get_gsi_domain_id(u32 gsi)
+{
+	struct riscv_ext_intc_list *ext_intc_element;
+	struct acpi_device *adev;
+	struct list_head *i;
+
+	list_for_each(i, &ext_intc_list) {
+		ext_intc_element = list_entry(i, struct riscv_ext_intc_list, list);
+		if (gsi >= ext_intc_element->gsi_base &&
+		    gsi < (ext_intc_element->gsi_base + ext_intc_element->nr_irqs)) {
+			adev = acpi_fetch_acpi_dev(ext_intc_element->handle);
+			if (!adev)
+				return NULL;
+
+			return acpi_fwnode_handle(adev);
+		}
+	}
+
+	return NULL;
+}
+
+static int __init riscv_acpi_register_ext_intc(u32 gsi_base, u32 nr_irqs, u32 nr_idcs,
+					       u32 id, u32 type)
+{
+	struct riscv_ext_intc_list *ext_intc_element;
+
+	ext_intc_element = kzalloc(sizeof(*ext_intc_element), GFP_KERNEL);
+	if (!ext_intc_element)
+		return -ENOMEM;
+
+	ext_intc_element->gsi_base = gsi_base;
+	ext_intc_element->nr_irqs = nr_irqs;
+	ext_intc_element->nr_idcs = nr_idcs;
+	ext_intc_element->id = id;
+	list_add_tail(&ext_intc_element->list, &ext_intc_list);
+	return 0;
+}
+
+static acpi_status __init riscv_acpi_create_gsi_map(acpi_handle handle, u32 level,
+						    void *context, void **return_value)
+{
+	acpi_status status;
+	u64 gbase;
+
+	if (!acpi_has_method(handle, "_GSB")) {
+		acpi_handle_err(handle, "_GSB method not found\n");
+		return AE_ERROR;
+	}
+
+	status = acpi_evaluate_integer(handle, "_GSB", NULL, &gbase);
+	if (ACPI_FAILURE(status)) {
+		acpi_handle_err(handle, "failed to evaluate _GSB method\n");
+		return status;
+	}
+
+	status = riscv_acpi_update_gsi_handle((u32)gbase, handle);
+	if (ACPI_FAILURE(status)) {
+		acpi_handle_err(handle, "failed to find the GSI mapping entry\n");
+		return status;
+	}
+
+	return AE_OK;
+}
+
+static int __init riscv_acpi_aplic_parse_madt(union acpi_subtable_headers *header,
+					      const unsigned long end)
+{
+	struct acpi_madt_aplic *aplic = (struct acpi_madt_aplic *)header;
+
+	return riscv_acpi_register_ext_intc(aplic->gsi_base, aplic->num_sources, aplic->num_idcs,
+					    aplic->id, ACPI_RISCV_IRQCHIP_APLIC);
+}
+
+static int __init riscv_acpi_plic_parse_madt(union acpi_subtable_headers *header,
+					     const unsigned long end)
+{
+	struct acpi_madt_plic *plic = (struct acpi_madt_plic *)header;
+
+	return riscv_acpi_register_ext_intc(plic->gsi_base, plic->num_irqs, 0,
+					    plic->id, ACPI_RISCV_IRQCHIP_PLIC);
+}
+
+void __init riscv_acpi_init_gsi_mapping(void)
+{
+	/* There can be either PLIC or APLIC */
+	if (acpi_table_parse_madt(ACPI_MADT_TYPE_PLIC, riscv_acpi_plic_parse_madt, 0) > 0) {
+		acpi_get_devices("RSCV0001", riscv_acpi_create_gsi_map, NULL, NULL);
+		return;
+	}
+
+	if (acpi_table_parse_madt(ACPI_MADT_TYPE_APLIC, riscv_acpi_aplic_parse_madt, 0) > 0)
+		acpi_get_devices("RSCV0002", riscv_acpi_create_gsi_map, NULL, NULL);
+}
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 12/17] ACPI: RISC-V: Implement function to add implicit dependencies
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
                   ` (10 preceding siblings ...)
  2024-07-29 14:22 ` [PATCH v7 11/17] ACPI: RISC-V: Initialize GSI mapping structures Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-07-29 14:22 ` [PATCH v7 13/17] irqchip/riscv-intc: Add ACPI support for AIA Sunil V L
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

RISC-V interrupt controllers for wired interrupts are platform devices
and hence their driver will be probed late. Also, APLIC which is one
such interrupt controller can not be probed early since it needs MSI
services. This needs a probing order between the interrupt controller
driver and the device drivers.

_DEP is typically used to indicate such dependencies. However, the
dependency may be already available like GSI mapping. Hence, instead of
an explicit _DEP, architecture can find the implicit dependencies and
add to the dependency list.

For RISC-V, add the dependencies for below use cases.

1) For devices which has IRQ resource, find out the interrupt controller
using GSI number map and add the dependency.

2) For PCI host bridges:
        a) If _PRT indicate PCI link devices, add dependency on the link
           device.
        b) If _PRT indicates GSI, find out the interrupt controller
           using GSI number map and add the dependency.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 drivers/acpi/riscv/irq.c | 155 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 155 insertions(+)

diff --git a/drivers/acpi/riscv/irq.c b/drivers/acpi/riscv/irq.c
index 9028787c73a7..cced960c2aef 100644
--- a/drivers/acpi/riscv/irq.c
+++ b/drivers/acpi/riscv/irq.c
@@ -20,6 +20,12 @@ struct riscv_ext_intc_list {
 	struct list_head	list;
 };
 
+struct acpi_irq_dep_ctx {
+	int		rc;
+	unsigned int	index;
+	acpi_handle	handle;
+};
+
 LIST_HEAD(ext_intc_list);
 
 static int irqchip_cmp_func(const void *in0, const void *in1)
@@ -178,3 +184,152 @@ void __init riscv_acpi_init_gsi_mapping(void)
 	if (acpi_table_parse_madt(ACPI_MADT_TYPE_APLIC, riscv_acpi_aplic_parse_madt, 0) > 0)
 		acpi_get_devices("RSCV0002", riscv_acpi_create_gsi_map, NULL, NULL);
 }
+
+static acpi_handle riscv_acpi_get_gsi_handle(u32 gsi)
+{
+	struct riscv_ext_intc_list *ext_intc_element;
+	struct list_head *i;
+
+	list_for_each(i, &ext_intc_list) {
+		ext_intc_element = list_entry(i, struct riscv_ext_intc_list, list);
+		if (gsi >= ext_intc_element->gsi_base &&
+		    gsi < (ext_intc_element->gsi_base + ext_intc_element->nr_irqs))
+			return ext_intc_element->handle;
+	}
+
+	return NULL;
+}
+
+static acpi_status riscv_acpi_irq_get_parent(struct acpi_resource *ares, void *context)
+{
+	struct acpi_irq_dep_ctx *ctx = context;
+	struct acpi_resource_irq *irq;
+	struct acpi_resource_extended_irq *eirq;
+
+	switch (ares->type) {
+	case ACPI_RESOURCE_TYPE_IRQ:
+		irq = &ares->data.irq;
+		if (ctx->index >= irq->interrupt_count) {
+			ctx->index -= irq->interrupt_count;
+			return AE_OK;
+		}
+		ctx->handle = riscv_acpi_get_gsi_handle(irq->interrupts[ctx->index]);
+		return AE_CTRL_TERMINATE;
+	case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+		eirq = &ares->data.extended_irq;
+		if (eirq->producer_consumer == ACPI_PRODUCER)
+			return AE_OK;
+
+		if (ctx->index >= eirq->interrupt_count) {
+			ctx->index -= eirq->interrupt_count;
+			return AE_OK;
+		}
+
+		/* Support GSIs only */
+		if (eirq->resource_source.string_length)
+			return AE_OK;
+
+		ctx->handle = riscv_acpi_get_gsi_handle(eirq->interrupts[ctx->index]);
+		return AE_CTRL_TERMINATE;
+	}
+
+	return AE_OK;
+}
+
+static int riscv_acpi_irq_get_dep(acpi_handle handle, unsigned int index, acpi_handle *gsi_handle)
+{
+	struct acpi_irq_dep_ctx ctx = {-EINVAL, index, NULL};
+
+	if (!gsi_handle)
+		return 0;
+
+	acpi_walk_resources(handle, METHOD_NAME__CRS, riscv_acpi_irq_get_parent, &ctx);
+	*gsi_handle = ctx.handle;
+	if (*gsi_handle)
+		return 1;
+
+	return 0;
+}
+
+static u32 riscv_acpi_add_prt_dep(acpi_handle handle)
+{
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	struct acpi_pci_routing_table *entry;
+	struct acpi_handle_list dep_devices;
+	acpi_handle gsi_handle;
+	acpi_handle link_handle;
+	acpi_status status;
+	u32 count = 0;
+
+	status = acpi_get_irq_routing_table(handle, &buffer);
+	if (ACPI_FAILURE(status)) {
+		acpi_handle_err(handle, "failed to get IRQ routing table\n");
+		kfree(buffer.pointer);
+		return 0;
+	}
+
+	entry = buffer.pointer;
+	while (entry && (entry->length > 0)) {
+		if (entry->source[0]) {
+			acpi_get_handle(handle, entry->source, &link_handle);
+			dep_devices.count = 1;
+			dep_devices.handles = kcalloc(1, sizeof(*dep_devices.handles), GFP_KERNEL);
+			if (!dep_devices.handles) {
+				acpi_handle_err(handle, "failed to allocate memory\n");
+				continue;
+			}
+
+			dep_devices.handles[0] = link_handle;
+			count += acpi_scan_add_dep(handle, &dep_devices);
+		} else {
+			gsi_handle = riscv_acpi_get_gsi_handle(entry->source_index);
+			dep_devices.count = 1;
+			dep_devices.handles = kcalloc(1, sizeof(*dep_devices.handles), GFP_KERNEL);
+			if (!dep_devices.handles) {
+				acpi_handle_err(handle, "failed to allocate memory\n");
+				continue;
+			}
+
+			dep_devices.handles[0] = gsi_handle;
+			count += acpi_scan_add_dep(handle, &dep_devices);
+		}
+
+		entry = (struct acpi_pci_routing_table *)
+			((unsigned long)entry + entry->length);
+	}
+
+	kfree(buffer.pointer);
+	return count;
+}
+
+static u32 riscv_acpi_add_irq_dep(acpi_handle handle)
+{
+	struct acpi_handle_list dep_devices;
+	acpi_handle gsi_handle;
+	u32 count = 0;
+	int i;
+
+	for (i = 0;
+	     riscv_acpi_irq_get_dep(handle, i, &gsi_handle);
+	     i++) {
+		dep_devices.count = 1;
+		dep_devices.handles = kcalloc(1, sizeof(*dep_devices.handles), GFP_KERNEL);
+		if (!dep_devices.handles) {
+			acpi_handle_err(handle, "failed to allocate memory\n");
+			continue;
+		}
+
+		dep_devices.handles[0] = gsi_handle;
+		count += acpi_scan_add_dep(handle, &dep_devices);
+	}
+
+	return count;
+}
+
+u32 arch_acpi_add_auto_dep(acpi_handle handle)
+{
+	if (acpi_has_method(handle, "_PRT"))
+		return riscv_acpi_add_prt_dep(handle);
+
+	return riscv_acpi_add_irq_dep(handle);
+}
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 13/17] irqchip/riscv-intc: Add ACPI support for AIA
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
                   ` (11 preceding siblings ...)
  2024-07-29 14:22 ` [PATCH v7 12/17] ACPI: RISC-V: Implement function to add implicit dependencies Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-08-06 15:22   ` Anup Patel
  2024-07-29 14:22 ` [PATCH v7 14/17] irqchip/riscv-imsic-state: Create separate function for DT Sunil V L
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

The RINTC subtype structure in MADT also has information about other
interrupt controllers. Save this information and provide interfaces to
retrieve them when required by corresponding drivers.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 arch/riscv/include/asm/irq.h     | 33 ++++++++++++
 drivers/irqchip/irq-riscv-intc.c | 90 ++++++++++++++++++++++++++++++++
 2 files changed, 123 insertions(+)

diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h
index 44a0b128c602..51d86f0b80d2 100644
--- a/arch/riscv/include/asm/irq.h
+++ b/arch/riscv/include/asm/irq.h
@@ -12,6 +12,8 @@
 
 #include <asm-generic/irq.h>
 
+#define INVALID_CONTEXT UINT_MAX
+
 void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void));
 
 struct fwnode_handle *riscv_get_intc_hwnode(void);
@@ -28,6 +30,11 @@ enum riscv_irqchip_type {
 int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi_base,
 			    u32 *id, u32 *nr_irqs, u32 *nr_idcs);
 struct fwnode_handle *riscv_acpi_get_gsi_domain_id(u32 gsi);
+unsigned long acpi_get_intc_index_hartid(u32 index);
+unsigned long acpi_get_ext_intc_parent_hartid(unsigned int plic_id, unsigned int ctxt_idx);
+unsigned int acpi_get_plic_nr_contexts(unsigned int plic_id);
+unsigned int acpi_get_plic_context(unsigned int plic_id, unsigned int ctxt_idx);
+int __init acpi_get_imsic_mmio_info(u32 index, struct resource *res);
 
 #else
 static inline int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi_base,
@@ -36,6 +43,32 @@ static inline int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi
 	return 0;
 }
 
+static inline unsigned long acpi_get_intc_index_hartid(u32 index)
+{
+	return INVALID_HARTID;
+}
+
+static inline unsigned long acpi_get_ext_intc_parent_hartid(unsigned int plic_id,
+							    unsigned int ctxt_idx)
+{
+	return INVALID_HARTID;
+}
+
+static inline unsigned int acpi_get_plic_nr_contexts(unsigned int plic_id)
+{
+	return INVALID_CONTEXT;
+}
+
+static inline unsigned int acpi_get_plic_context(unsigned int plic_id, unsigned int ctxt_idx)
+{
+	return INVALID_CONTEXT;
+}
+
+static inline int __init acpi_get_imsic_mmio_info(u32 index, struct resource *res)
+{
+	return 0;
+}
+
 #endif /* CONFIG_ACPI */
 
 #endif /* _ASM_RISCV_IRQ_H */
diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c
index 47f3200476da..5ddb12ce8b97 100644
--- a/drivers/irqchip/irq-riscv-intc.c
+++ b/drivers/irqchip/irq-riscv-intc.c
@@ -250,6 +250,85 @@ IRQCHIP_DECLARE(andes, "andestech,cpu-intc", riscv_intc_init);
 
 #ifdef CONFIG_ACPI
 
+struct rintc_data {
+	union {
+		u32		ext_intc_id;
+		struct {
+			u32	context_id	: 16,
+				reserved	:  8,
+				aplic_plic_id	:  8;
+		};
+	};
+	unsigned long		hart_id;
+	u64			imsic_addr;
+	u32			imsic_size;
+};
+
+static u32 nr_rintc;
+static struct rintc_data *rintc_acpi_data[NR_CPUS];
+
+#define for_each_matching_plic(_plic_id)				\
+	unsigned int _plic;						\
+									\
+	for (_plic = 0; _plic < nr_rintc; _plic++)			\
+		if (rintc_acpi_data[_plic]->aplic_plic_id != _plic_id)	\
+			continue;					\
+		else
+
+unsigned int acpi_get_plic_nr_contexts(unsigned int plic_id)
+{
+	unsigned int nctx = 0;
+
+	for_each_matching_plic(plic_id)
+		nctx++;
+
+	return nctx;
+}
+
+static struct rintc_data *get_plic_context(unsigned int plic_id, unsigned int ctxt_idx)
+{
+	unsigned int ctxt = 0;
+
+	for_each_matching_plic(plic_id) {
+		if (ctxt == ctxt_idx)
+			return rintc_acpi_data[_plic];
+
+		ctxt++;
+	}
+
+	return NULL;
+}
+
+unsigned long acpi_get_ext_intc_parent_hartid(unsigned int plic_id, unsigned int ctxt_idx)
+{
+	struct rintc_data *data = get_plic_context(plic_id, ctxt_idx);
+
+	return data ? data->hart_id : INVALID_HARTID;
+}
+
+unsigned int acpi_get_plic_context(unsigned int plic_id, unsigned int ctxt_idx)
+{
+	struct rintc_data *data = get_plic_context(plic_id, ctxt_idx);
+
+	return data ? data->context_id : INVALID_CONTEXT;
+}
+
+unsigned long acpi_get_intc_index_hartid(u32 index)
+{
+	return index >= nr_rintc ? INVALID_HARTID : rintc_acpi_data[index]->hart_id;
+}
+
+int acpi_get_imsic_mmio_info(u32 index, struct resource *res)
+{
+	if (index >= nr_rintc)
+		return -1;
+
+	res->start = rintc_acpi_data[index]->imsic_addr;
+	res->end = res->start + rintc_acpi_data[index]->imsic_size - 1;
+	res->flags = IORESOURCE_MEM;
+	return 0;
+}
+
 static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
 				       const unsigned long end)
 {
@@ -258,6 +337,15 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
 	int rc;
 
 	rintc = (struct acpi_madt_rintc *)header;
+	rintc_acpi_data[nr_rintc] = kzalloc(sizeof(*rintc_acpi_data[0]), GFP_KERNEL);
+	if (!rintc_acpi_data[nr_rintc])
+		return -ENOMEM;
+
+	rintc_acpi_data[nr_rintc]->ext_intc_id = rintc->ext_intc_id;
+	rintc_acpi_data[nr_rintc]->hart_id = rintc->hart_id;
+	rintc_acpi_data[nr_rintc]->imsic_addr = rintc->imsic_addr;
+	rintc_acpi_data[nr_rintc]->imsic_size = rintc->imsic_size;
+	nr_rintc++;
 
 	/*
 	 * The ACPI MADT will have one INTC for each CPU (or HART)
@@ -277,6 +365,8 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
 	rc = riscv_intc_init_common(fn, &riscv_intc_chip);
 	if (rc)
 		irq_domain_free_fwnode(fn);
+	else
+		acpi_set_irq_model(ACPI_IRQ_MODEL_RINTC, riscv_acpi_get_gsi_domain_id);
 
 	return rc;
 }
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 14/17] irqchip/riscv-imsic-state: Create separate function for DT
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
                   ` (12 preceding siblings ...)
  2024-07-29 14:22 ` [PATCH v7 13/17] irqchip/riscv-intc: Add ACPI support for AIA Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-08-06 15:25   ` Anup Patel
  2024-07-29 14:22 ` [PATCH v7 15/17] irqchip/riscv-imsic: Add ACPI support Sunil V L
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

While populating IMSIC global structure, many fields are initialized
using DT properties. Make the code which uses DT properties as separate
function so that it is easier to add ACPI support later. No
functionality added/changed.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 drivers/irqchip/irq-riscv-imsic-state.c | 97 ++++++++++++++-----------
 1 file changed, 55 insertions(+), 42 deletions(-)

diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
index 5479f872e62b..f9e70832863a 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.c
+++ b/drivers/irqchip/irq-riscv-imsic-state.c
@@ -510,6 +510,60 @@ static int __init imsic_matrix_init(void)
 	return 0;
 }
 
+static int __init imsic_populate_global_dt(struct fwnode_handle *fwnode,
+					   struct imsic_global_config *global,
+					   u32 *nr_parent_irqs)
+{
+	int rc;
+
+	/* Find number of guest index bits in MSI address */
+	rc = of_property_read_u32(to_of_node(fwnode), "riscv,guest-index-bits",
+				  &global->guest_index_bits);
+	if (rc)
+		global->guest_index_bits = 0;
+
+	/* Find number of HART index bits */
+	rc = of_property_read_u32(to_of_node(fwnode), "riscv,hart-index-bits",
+				  &global->hart_index_bits);
+	if (rc) {
+		/* Assume default value */
+		global->hart_index_bits = __fls(*nr_parent_irqs);
+		if (BIT(global->hart_index_bits) < *nr_parent_irqs)
+			global->hart_index_bits++;
+	}
+
+	/* Find number of group index bits */
+	rc = of_property_read_u32(to_of_node(fwnode), "riscv,group-index-bits",
+				  &global->group_index_bits);
+	if (rc)
+		global->group_index_bits = 0;
+
+	/*
+	 * Find first bit position of group index.
+	 * If not specified assumed the default APLIC-IMSIC configuration.
+	 */
+	rc = of_property_read_u32(to_of_node(fwnode), "riscv,group-index-shift",
+				  &global->group_index_shift);
+	if (rc)
+		global->group_index_shift = IMSIC_MMIO_PAGE_SHIFT * 2;
+
+	/* Find number of interrupt identities */
+	rc = of_property_read_u32(to_of_node(fwnode), "riscv,num-ids",
+				  &global->nr_ids);
+	if (rc) {
+		pr_err("%pfwP: number of interrupt identities not found\n", fwnode);
+		return rc;
+	}
+
+	/* Find number of guest interrupt identities */
+	rc = of_property_read_u32(to_of_node(fwnode), "riscv,num-guest-ids",
+				  &global->nr_guest_ids);
+	if (rc)
+		global->nr_guest_ids = global->nr_ids;
+
+	return 0;
+}
+
 static int __init imsic_get_parent_hartid(struct fwnode_handle *fwnode,
 					  u32 index, unsigned long *hartid)
 {
@@ -578,50 +632,9 @@ static int __init imsic_parse_fwnode(struct fwnode_handle *fwnode,
 		return -EINVAL;
 	}
 
-	/* Find number of guest index bits in MSI address */
-	rc = of_property_read_u32(to_of_node(fwnode), "riscv,guest-index-bits",
-				  &global->guest_index_bits);
+	rc = imsic_populate_global_dt(fwnode, global, nr_parent_irqs);
 	if (rc)
-		global->guest_index_bits = 0;
-
-	/* Find number of HART index bits */
-	rc = of_property_read_u32(to_of_node(fwnode), "riscv,hart-index-bits",
-				  &global->hart_index_bits);
-	if (rc) {
-		/* Assume default value */
-		global->hart_index_bits = __fls(*nr_parent_irqs);
-		if (BIT(global->hart_index_bits) < *nr_parent_irqs)
-			global->hart_index_bits++;
-	}
-
-	/* Find number of group index bits */
-	rc = of_property_read_u32(to_of_node(fwnode), "riscv,group-index-bits",
-				  &global->group_index_bits);
-	if (rc)
-		global->group_index_bits = 0;
-
-	/*
-	 * Find first bit position of group index.
-	 * If not specified assumed the default APLIC-IMSIC configuration.
-	 */
-	rc = of_property_read_u32(to_of_node(fwnode), "riscv,group-index-shift",
-				  &global->group_index_shift);
-	if (rc)
-		global->group_index_shift = IMSIC_MMIO_PAGE_SHIFT * 2;
-
-	/* Find number of interrupt identities */
-	rc = of_property_read_u32(to_of_node(fwnode), "riscv,num-ids",
-				  &global->nr_ids);
-	if (rc) {
-		pr_err("%pfwP: number of interrupt identities not found\n", fwnode);
 		return rc;
-	}
-
-	/* Find number of guest interrupt identities */
-	rc = of_property_read_u32(to_of_node(fwnode), "riscv,num-guest-ids",
-				  &global->nr_guest_ids);
-	if (rc)
-		global->nr_guest_ids = global->nr_ids;
 
 	/* Sanity check guest index bits */
 	i = BITS_PER_LONG - IMSIC_MMIO_PAGE_SHIFT;
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 15/17] irqchip/riscv-imsic: Add ACPI support
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
                   ` (13 preceding siblings ...)
  2024-07-29 14:22 ` [PATCH v7 14/17] irqchip/riscv-imsic-state: Create separate function for DT Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-08-06 15:30   ` Anup Patel
  2024-07-29 14:22 ` [PATCH v7 16/17] irqchip/riscv-aplic: " Sunil V L
  2024-07-29 14:22 ` [PATCH v7 17/17] irqchip/sifive-plic: " Sunil V L
  16 siblings, 1 reply; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

RISC-V IMSIC interrupt controller provides IPI and MSI support.
Currently, DT based drivers setup the IPI feature early during boot but
defer setting up the MSI functionality. However, in ACPI systems, PCI
subsystem is probed early and assume MSI controller is already setup.
Hence, both IPI and MSI features need to be initialized early itself.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 drivers/irqchip/irq-riscv-imsic-early.c    | 64 +++++++++++++++++++++-
 drivers/irqchip/irq-riscv-imsic-platform.c | 32 +++++++++--
 drivers/irqchip/irq-riscv-imsic-state.c    | 57 +++++++++++--------
 drivers/irqchip/irq-riscv-imsic-state.h    |  2 +-
 include/linux/irqchip/riscv-imsic.h        |  9 +++
 5 files changed, 134 insertions(+), 30 deletions(-)

diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c
index 4fbb37074d29..c5c2e6929a2f 100644
--- a/drivers/irqchip/irq-riscv-imsic-early.c
+++ b/drivers/irqchip/irq-riscv-imsic-early.c
@@ -5,13 +5,16 @@
  */
 
 #define pr_fmt(fmt) "riscv-imsic: " fmt
+#include <linux/acpi.h>
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irqchip.h>
 #include <linux/irqchip/chained_irq.h>
+#include <linux/irqchip/riscv-imsic.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/smp.h>
 
@@ -182,7 +185,7 @@ static int __init imsic_early_dt_init(struct device_node *node, struct device_no
 	int rc;
 
 	/* Setup IMSIC state */
-	rc = imsic_setup_state(fwnode);
+	rc = imsic_setup_state(fwnode, NULL);
 	if (rc) {
 		pr_err("%pfwP: failed to setup state (error %d)\n", fwnode, rc);
 		return rc;
@@ -199,3 +202,62 @@ static int __init imsic_early_dt_init(struct device_node *node, struct device_no
 }
 
 IRQCHIP_DECLARE(riscv_imsic, "riscv,imsics", imsic_early_dt_init);
+
+#ifdef CONFIG_ACPI
+
+static struct fwnode_handle *imsic_acpi_fwnode;
+
+struct fwnode_handle *imsic_acpi_get_fwnode(struct device *dev)
+{
+	return imsic_acpi_fwnode;
+}
+
+static int __init imsic_early_acpi_init(union acpi_subtable_headers *header,
+					const unsigned long end)
+{
+	struct acpi_madt_imsic *imsic = (struct acpi_madt_imsic *)header;
+	int rc;
+
+	imsic_acpi_fwnode = irq_domain_alloc_named_fwnode("imsic");
+	if (!imsic_acpi_fwnode) {
+		pr_err("unable to allocate IMSIC FW node\n");
+		return -ENOMEM;
+	}
+
+	/* Setup IMSIC state */
+	rc = imsic_setup_state(imsic_acpi_fwnode, imsic);
+	if (rc) {
+		pr_err("%pfwP: failed to setup state (error %d)\n", imsic_acpi_fwnode, rc);
+		return rc;
+	}
+
+	/* Do early setup of IMSIC state and IPIs */
+	rc = imsic_early_probe(imsic_acpi_fwnode);
+	if (rc) {
+		irq_domain_free_fwnode(imsic_acpi_fwnode);
+		imsic_acpi_fwnode = NULL;
+		return rc;
+	}
+
+	rc = imsic_platform_acpi_probe(imsic_acpi_fwnode);
+
+#ifdef CONFIG_PCI
+	if (!rc)
+		pci_msi_register_fwnode_provider(&imsic_acpi_get_fwnode);
+#endif
+
+	if (rc)
+		pr_err("%pfwP: failed to register IMSIC for MSI functionality (error %d)\n",
+		       imsic_acpi_fwnode, rc);
+
+	/*
+	 * Even if imsic_platform_acpi_probe() fails, the IPI part of IMSIC can
+	 * continue to work. So, no need to return failure. This is similar to
+	 * DT where IPI works but MSI probe fails for some reason.
+	 */
+	return 0;
+}
+
+IRQCHIP_ACPI_DECLARE(riscv_imsic, ACPI_MADT_TYPE_IMSIC, NULL,
+		     1, imsic_early_acpi_init);
+#endif
diff --git a/drivers/irqchip/irq-riscv-imsic-platform.c b/drivers/irqchip/irq-riscv-imsic-platform.c
index 11723a763c10..64905e6f52d7 100644
--- a/drivers/irqchip/irq-riscv-imsic-platform.c
+++ b/drivers/irqchip/irq-riscv-imsic-platform.c
@@ -5,6 +5,7 @@
  */
 
 #define pr_fmt(fmt) "riscv-imsic: " fmt
+#include <linux/acpi.h>
 #include <linux/bitmap.h>
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
@@ -348,18 +349,37 @@ int imsic_irqdomain_init(void)
 	return 0;
 }
 
-static int imsic_platform_probe(struct platform_device *pdev)
+static int imsic_platform_probe_common(struct fwnode_handle *fwnode)
 {
-	struct device *dev = &pdev->dev;
-
-	if (imsic && imsic->fwnode != dev->fwnode) {
-		dev_err(dev, "fwnode mismatch\n");
+	if (imsic && imsic->fwnode != fwnode) {
+		pr_err("%pfwP: fwnode mismatch\n", fwnode);
 		return -ENODEV;
 	}
 
 	return imsic_irqdomain_init();
 }
 
+static int imsic_platform_dt_probe(struct platform_device *pdev)
+{
+	return imsic_platform_probe_common(pdev->dev.fwnode);
+}
+
+#ifdef CONFIG_ACPI
+
+/*
+ *  On ACPI based systems, PCI enumeration happens early during boot in
+ *  acpi_scan_init(). PCI enumeration expects MSI domain setup before
+ *  it calls pci_set_msi_domain(). Hence, unlike in DT where
+ *  imsic-platform drive probe happens late during boot, ACPI based
+ *  systems need to setup the MSI domain early.
+ */
+int imsic_platform_acpi_probe(struct fwnode_handle *fwnode)
+{
+	return imsic_platform_probe_common(fwnode);
+}
+
+#endif
+
 static const struct of_device_id imsic_platform_match[] = {
 	{ .compatible = "riscv,imsics" },
 	{}
@@ -370,6 +390,6 @@ static struct platform_driver imsic_platform_driver = {
 		.name		= "riscv-imsic",
 		.of_match_table	= imsic_platform_match,
 	},
-	.probe = imsic_platform_probe,
+	.probe = imsic_platform_dt_probe,
 };
 builtin_platform_driver(imsic_platform_driver);
diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
index f9e70832863a..73faa64bffda 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.c
+++ b/drivers/irqchip/irq-riscv-imsic-state.c
@@ -5,6 +5,7 @@
  */
 
 #define pr_fmt(fmt) "riscv-imsic: " fmt
+#include <linux/acpi.h>
 #include <linux/cpu.h>
 #include <linux/bitmap.h>
 #include <linux/interrupt.h>
@@ -564,18 +565,36 @@ static int __init imsic_populate_global_dt(struct fwnode_handle *fwnode,
 	return 0;
 }
 
+static int __init imsic_populate_global_acpi(struct fwnode_handle *fwnode,
+					     struct imsic_global_config *global,
+					     u32 *nr_parent_irqs, void *opaque)
+{
+	struct acpi_madt_imsic *imsic = (struct acpi_madt_imsic *)opaque;
+
+	global->guest_index_bits = imsic->guest_index_bits;
+	global->hart_index_bits = imsic->hart_index_bits;
+	global->group_index_bits = imsic->group_index_bits;
+	global->group_index_shift = imsic->group_index_shift;
+	global->nr_ids = imsic->num_ids;
+	global->nr_guest_ids = imsic->num_guest_ids;
+	return 0;
+}
+
 static int __init imsic_get_parent_hartid(struct fwnode_handle *fwnode,
 					  u32 index, unsigned long *hartid)
 {
 	struct of_phandle_args parent;
 	int rc;
 
-	/*
-	 * Currently, only OF fwnode is supported so extend this
-	 * function for ACPI support.
-	 */
-	if (!is_of_node(fwnode))
-		return -EINVAL;
+	if (!is_of_node(fwnode)) {
+		if (hartid)
+			*hartid = acpi_get_intc_index_hartid(index);
+
+		if (!hartid || (*hartid == INVALID_HARTID))
+			return -EINVAL;
+
+		return 0;
+	}
 
 	rc = of_irq_parse_one(to_of_node(fwnode), index, &parent);
 	if (rc)
@@ -594,12 +613,8 @@ static int __init imsic_get_parent_hartid(struct fwnode_handle *fwnode,
 static int __init imsic_get_mmio_resource(struct fwnode_handle *fwnode,
 					  u32 index, struct resource *res)
 {
-	/*
-	 * Currently, only OF fwnode is supported so extend this
-	 * function for ACPI support.
-	 */
 	if (!is_of_node(fwnode))
-		return -EINVAL;
+		return acpi_get_imsic_mmio_info(index, res);
 
 	return of_address_to_resource(to_of_node(fwnode), index, res);
 }
@@ -607,20 +622,14 @@ static int __init imsic_get_mmio_resource(struct fwnode_handle *fwnode,
 static int __init imsic_parse_fwnode(struct fwnode_handle *fwnode,
 				     struct imsic_global_config *global,
 				     u32 *nr_parent_irqs,
-				     u32 *nr_mmios)
+				     u32 *nr_mmios,
+				     void *opaque)
 {
 	unsigned long hartid;
 	struct resource res;
 	int rc;
 	u32 i;
 
-	/*
-	 * Currently, only OF fwnode is supported so extend this
-	 * function for ACPI support.
-	 */
-	if (!is_of_node(fwnode))
-		return -EINVAL;
-
 	*nr_parent_irqs = 0;
 	*nr_mmios = 0;
 
@@ -632,7 +641,11 @@ static int __init imsic_parse_fwnode(struct fwnode_handle *fwnode,
 		return -EINVAL;
 	}
 
-	rc = imsic_populate_global_dt(fwnode, global, nr_parent_irqs);
+	if (is_of_node(fwnode))
+		rc = imsic_populate_global_dt(fwnode, global, nr_parent_irqs);
+	else
+		rc = imsic_populate_global_acpi(fwnode, global, nr_parent_irqs, opaque);
+
 	if (rc)
 		return rc;
 
@@ -701,7 +714,7 @@ static int __init imsic_parse_fwnode(struct fwnode_handle *fwnode,
 	return 0;
 }
 
-int __init imsic_setup_state(struct fwnode_handle *fwnode)
+int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
 {
 	u32 i, j, index, nr_parent_irqs, nr_mmios, nr_handlers = 0;
 	struct imsic_global_config *global;
@@ -742,7 +755,7 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode)
 	}
 
 	/* Parse IMSIC fwnode */
-	rc = imsic_parse_fwnode(fwnode, global, &nr_parent_irqs, &nr_mmios);
+	rc = imsic_parse_fwnode(fwnode, global, &nr_parent_irqs, &nr_mmios, opaque);
 	if (rc)
 		goto out_free_local;
 
diff --git a/drivers/irqchip/irq-riscv-imsic-state.h b/drivers/irqchip/irq-riscv-imsic-state.h
index 5ae2f69b035b..391e44280827 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.h
+++ b/drivers/irqchip/irq-riscv-imsic-state.h
@@ -102,7 +102,7 @@ void imsic_vector_debug_show_summary(struct seq_file *m, int ind);
 
 void imsic_state_online(void);
 void imsic_state_offline(void);
-int imsic_setup_state(struct fwnode_handle *fwnode);
+int imsic_setup_state(struct fwnode_handle *fwnode, void *opaque);
 int imsic_irqdomain_init(void);
 
 #endif
diff --git a/include/linux/irqchip/riscv-imsic.h b/include/linux/irqchip/riscv-imsic.h
index faf0b800b1b0..7494952c5518 100644
--- a/include/linux/irqchip/riscv-imsic.h
+++ b/include/linux/irqchip/riscv-imsic.h
@@ -8,6 +8,8 @@
 
 #include <linux/types.h>
 #include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/fwnode.h>
 #include <asm/csr.h>
 
 #define IMSIC_MMIO_PAGE_SHIFT		12
@@ -84,4 +86,11 @@ static inline const struct imsic_global_config *imsic_get_global_config(void)
 
 #endif
 
+#ifdef CONFIG_ACPI
+int imsic_platform_acpi_probe(struct fwnode_handle *fwnode);
+struct fwnode_handle *imsic_acpi_get_fwnode(struct device *dev);
+#else
+static inline struct fwnode_handle *imsic_acpi_get_fwnode(struct device *dev) { return NULL; }
+#endif
+
 #endif
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 16/17] irqchip/riscv-aplic: Add ACPI support
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
                   ` (14 preceding siblings ...)
  2024-07-29 14:22 ` [PATCH v7 15/17] irqchip/riscv-imsic: Add ACPI support Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-08-06 15:54   ` Anup Patel
  2024-07-29 14:22 ` [PATCH v7 17/17] irqchip/sifive-plic: " Sunil V L
  16 siblings, 1 reply; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

Add ACPI support in APLIC drivers. Use the mapping created early during
boot to get the details about the APLIC.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 drivers/irqchip/irq-riscv-aplic-direct.c | 22 +++++---
 drivers/irqchip/irq-riscv-aplic-main.c   | 69 ++++++++++++++++--------
 drivers/irqchip/irq-riscv-aplic-main.h   |  1 +
 drivers/irqchip/irq-riscv-aplic-msi.c    |  9 +++-
 4 files changed, 69 insertions(+), 32 deletions(-)

diff --git a/drivers/irqchip/irq-riscv-aplic-direct.c b/drivers/irqchip/irq-riscv-aplic-direct.c
index 4a3ffe856d6c..34540a0ca4da 100644
--- a/drivers/irqchip/irq-riscv-aplic-direct.c
+++ b/drivers/irqchip/irq-riscv-aplic-direct.c
@@ -4,6 +4,7 @@
  * Copyright (C) 2022 Ventana Micro Systems Inc.
  */
 
+#include <linux/acpi.h>
 #include <linux/bitfield.h>
 #include <linux/bitops.h>
 #include <linux/cpu.h>
@@ -189,17 +190,22 @@ static int aplic_direct_starting_cpu(unsigned int cpu)
 }
 
 static int aplic_direct_parse_parent_hwirq(struct device *dev, u32 index,
-					   u32 *parent_hwirq, unsigned long *parent_hartid)
+					   u32 *parent_hwirq, unsigned long *parent_hartid,
+					   struct aplic_priv *priv)
 {
 	struct of_phandle_args parent;
+	unsigned long hartid;
 	int rc;
 
-	/*
-	 * Currently, only OF fwnode is supported so extend this
-	 * function for ACPI support.
-	 */
-	if (!is_of_node(dev->fwnode))
-		return -EINVAL;
+	if (!is_of_node(dev->fwnode)) {
+		hartid = acpi_get_ext_intc_parent_hartid(priv->id, index);
+		if (hartid == INVALID_HARTID)
+			return -ENODEV;
+
+		*parent_hartid = hartid;
+		*parent_hwirq = RV_IRQ_EXT;
+		return 0;
+	}
 
 	rc = of_irq_parse_one(to_of_node(dev->fwnode), index, &parent);
 	if (rc)
@@ -237,7 +243,7 @@ int aplic_direct_setup(struct device *dev, void __iomem *regs)
 	/* Setup per-CPU IDC and target CPU mask */
 	current_cpu = get_cpu();
 	for (i = 0; i < priv->nr_idcs; i++) {
-		rc = aplic_direct_parse_parent_hwirq(dev, i, &hwirq, &hartid);
+		rc = aplic_direct_parse_parent_hwirq(dev, i, &hwirq, &hartid, priv);
 		if (rc) {
 			dev_warn(dev, "parent irq for IDC%d not found\n", i);
 			continue;
diff --git a/drivers/irqchip/irq-riscv-aplic-main.c b/drivers/irqchip/irq-riscv-aplic-main.c
index 28dd175b5764..8357c5f9921a 100644
--- a/drivers/irqchip/irq-riscv-aplic-main.c
+++ b/drivers/irqchip/irq-riscv-aplic-main.c
@@ -4,8 +4,10 @@
  * Copyright (C) 2022 Ventana Micro Systems Inc.
  */
 
+#include <linux/acpi.h>
 #include <linux/bitfield.h>
 #include <linux/irqchip/riscv-aplic.h>
+#include <linux/irqchip/riscv-imsic.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
@@ -125,39 +127,50 @@ static void aplic_init_hw_irqs(struct aplic_priv *priv)
 	writel(0, priv->regs + APLIC_DOMAINCFG);
 }
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id aplic_acpi_match[] = {
+	{ "RSCV0002", 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(acpi, aplic_acpi_match);
+
+#endif
+
 int aplic_setup_priv(struct aplic_priv *priv, struct device *dev, void __iomem *regs)
 {
 	struct device_node *np = to_of_node(dev->fwnode);
 	struct of_phandle_args parent;
 	int rc;
 
-	/*
-	 * Currently, only OF fwnode is supported so extend this
-	 * function for ACPI support.
-	 */
-	if (!np)
-		return -EINVAL;
-
 	/* Save device pointer and register base */
 	priv->dev = dev;
 	priv->regs = regs;
 
-	/* Find out number of interrupt sources */
-	rc = of_property_read_u32(np, "riscv,num-sources", &priv->nr_irqs);
-	if (rc) {
-		dev_err(dev, "failed to get number of interrupt sources\n");
-		return rc;
-	}
+	if (np) {
+		/* Find out number of interrupt sources */
+		rc = of_property_read_u32(np, "riscv,num-sources", &priv->nr_irqs);
+		if (rc) {
+			dev_err(dev, "failed to get number of interrupt sources\n");
+			return rc;
+		}
 
-	/*
-	 * Find out number of IDCs based on parent interrupts
-	 *
-	 * If "msi-parent" property is present then we ignore the
-	 * APLIC IDCs which forces the APLIC driver to use MSI mode.
-	 */
-	if (!of_property_present(np, "msi-parent")) {
-		while (!of_irq_parse_one(np, priv->nr_idcs, &parent))
-			priv->nr_idcs++;
+		/*
+		 * Find out number of IDCs based on parent interrupts
+		 *
+		 * If "msi-parent" property is present then we ignore the
+		 * APLIC IDCs which forces the APLIC driver to use MSI mode.
+		 */
+		if (!of_property_present(np, "msi-parent")) {
+			while (!of_irq_parse_one(np, priv->nr_idcs, &parent))
+				priv->nr_idcs++;
+		}
+	} else {
+		rc = riscv_acpi_get_gsi_info(dev->fwnode, &priv->gsi_base, &priv->id,
+					     &priv->nr_irqs, &priv->nr_idcs);
+		if (rc) {
+			dev_err(dev, "failed to find GSI mapping\n");
+			return rc;
+		}
 	}
 
 	/* Setup initial state APLIC interrupts */
@@ -184,7 +197,11 @@ static int aplic_probe(struct platform_device *pdev)
 	 * If msi-parent property is present then setup APLIC MSI
 	 * mode otherwise setup APLIC direct mode.
 	 */
-	msi_mode = of_property_present(to_of_node(dev->fwnode), "msi-parent");
+	if (is_of_node(dev->fwnode))
+		msi_mode = of_property_present(to_of_node(dev->fwnode), "msi-parent");
+	else
+		msi_mode = imsic_acpi_get_fwnode(NULL) ? 1 : 0;
+
 	if (msi_mode)
 		rc = aplic_msi_setup(dev, regs);
 	else
@@ -192,6 +209,11 @@ static int aplic_probe(struct platform_device *pdev)
 	if (rc)
 		dev_err(dev, "failed to setup APLIC in %s mode\n", msi_mode ? "MSI" : "direct");
 
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled)
+		acpi_dev_clear_dependencies(ACPI_COMPANION(dev));
+#endif
+
 	return rc;
 }
 
@@ -204,6 +226,7 @@ static struct platform_driver aplic_driver = {
 	.driver = {
 		.name		= "riscv-aplic",
 		.of_match_table	= aplic_match,
+		.acpi_match_table = ACPI_PTR(aplic_acpi_match),
 	},
 	.probe = aplic_probe,
 };
diff --git a/drivers/irqchip/irq-riscv-aplic-main.h b/drivers/irqchip/irq-riscv-aplic-main.h
index 4393927d8c80..9fbf45c7b4f7 100644
--- a/drivers/irqchip/irq-riscv-aplic-main.h
+++ b/drivers/irqchip/irq-riscv-aplic-main.h
@@ -28,6 +28,7 @@ struct aplic_priv {
 	u32			gsi_base;
 	u32			nr_irqs;
 	u32			nr_idcs;
+	u32			id;
 	void __iomem		*regs;
 	struct aplic_msicfg	msicfg;
 };
diff --git a/drivers/irqchip/irq-riscv-aplic-msi.c b/drivers/irqchip/irq-riscv-aplic-msi.c
index 028444af48bd..f5020241e0ed 100644
--- a/drivers/irqchip/irq-riscv-aplic-msi.c
+++ b/drivers/irqchip/irq-riscv-aplic-msi.c
@@ -157,6 +157,7 @@ static const struct msi_domain_template aplic_msi_template = {
 int aplic_msi_setup(struct device *dev, void __iomem *regs)
 {
 	const struct imsic_global_config *imsic_global;
+	struct irq_domain *msi_domain;
 	struct aplic_priv *priv;
 	struct aplic_msicfg *mc;
 	phys_addr_t pa;
@@ -239,8 +240,14 @@ int aplic_msi_setup(struct device *dev, void __iomem *regs)
 		 * IMSIC and the IMSIC MSI domains are created later through
 		 * the platform driver probing so we set it explicitly here.
 		 */
-		if (is_of_node(dev->fwnode))
+		if (is_of_node(dev->fwnode)) {
 			of_msi_configure(dev, to_of_node(dev->fwnode));
+		} else {
+			msi_domain = irq_find_matching_fwnode(imsic_acpi_get_fwnode(dev),
+							      DOMAIN_BUS_PLATFORM_MSI);
+			if (msi_domain)
+				dev_set_msi_domain(dev, msi_domain);
+		}
 	}
 
 	if (!msi_create_device_irq_domain(dev, MSI_DEFAULT_DOMAIN, &aplic_msi_template,
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v7 17/17] irqchip/sifive-plic: Add ACPI support
  2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
                   ` (15 preceding siblings ...)
  2024-07-29 14:22 ` [PATCH v7 16/17] irqchip/riscv-aplic: " Sunil V L
@ 2024-07-29 14:22 ` Sunil V L
  2024-08-06 15:59   ` Anup Patel
  16 siblings, 1 reply; 30+ messages in thread
From: Sunil V L @ 2024-07-29 14:22 UTC (permalink / raw)
  To: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci
  Cc: Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini,
	Sunil V L

Add ACPI support in PLIC driver. Use the mapping created early during
boot to get details about the PLIC.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
Co-developed-by: Haibo Xu <haibo1.xu@intel.com>
Signed-off-by: Haibo Xu <haibo1.xu@intel.com>
---
 drivers/irqchip/irq-sifive-plic.c | 94 ++++++++++++++++++++++++-------
 1 file changed, 73 insertions(+), 21 deletions(-)

diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index 9e22f7e378f5..12d60728329c 100644
--- a/drivers/irqchip/irq-sifive-plic.c
+++ b/drivers/irqchip/irq-sifive-plic.c
@@ -3,6 +3,7 @@
  * Copyright (C) 2017 SiFive
  * Copyright (C) 2018 Christoph Hellwig
  */
+#include <linux/acpi.h>
 #include <linux/cpu.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -70,6 +71,8 @@ struct plic_priv {
 	unsigned long plic_quirks;
 	unsigned int nr_irqs;
 	unsigned long *prio_save;
+	u32 gsi_base;
+	int id;
 };
 
 struct plic_handler {
@@ -324,6 +327,10 @@ static int plic_irq_domain_translate(struct irq_domain *d,
 {
 	struct plic_priv *priv = d->host_data;
 
+	/* For DT, gsi_base is always zero. */
+	if (fwspec->param[0] >= priv->gsi_base)
+		fwspec->param[0] = fwspec->param[0] - priv->gsi_base;
+
 	if (test_bit(PLIC_QUIRK_EDGE_INTERRUPT, &priv->plic_quirks))
 		return irq_domain_translate_twocell(d, fwspec, hwirq, type);
 
@@ -424,18 +431,37 @@ static const struct of_device_id plic_match[] = {
 	{}
 };
 
+#ifdef CONFIG_ACPI
+
+static const struct acpi_device_id plic_acpi_match[] = {
+	{ "RSCV0001", 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(acpi, plic_acpi_match);
+
+#endif
 static int plic_parse_nr_irqs_and_contexts(struct platform_device *pdev,
-					   u32 *nr_irqs, u32 *nr_contexts)
+					   u32 *nr_irqs, u32 *nr_contexts,
+					   u32 *gsi_base, u32 *id)
 {
 	struct device *dev = &pdev->dev;
 	int rc;
 
-	/*
-	 * Currently, only OF fwnode is supported so extend this
-	 * function for ACPI support.
-	 */
-	if (!is_of_node(dev->fwnode))
-		return -EINVAL;
+	if (!is_of_node(dev->fwnode)) {
+		rc = riscv_acpi_get_gsi_info(dev->fwnode, gsi_base, id, nr_irqs, NULL);
+		if (rc) {
+			dev_err(dev, "failed to find GSI mapping\n");
+			return rc;
+		}
+
+		*nr_contexts = acpi_get_plic_nr_contexts(*id);
+		if (WARN_ON(!*nr_contexts)) {
+			dev_err(dev, "no PLIC context available\n");
+			return -EINVAL;
+		}
+
+		return 0;
+	}
 
 	rc = of_property_read_u32(to_of_node(dev->fwnode), "riscv,ndev", nr_irqs);
 	if (rc) {
@@ -449,23 +475,29 @@ static int plic_parse_nr_irqs_and_contexts(struct platform_device *pdev,
 		return -EINVAL;
 	}
 
+	*gsi_base = 0;
+	*id = 0;
+
 	return 0;
 }
 
 static int plic_parse_context_parent(struct platform_device *pdev, u32 context,
-				     u32 *parent_hwirq, int *parent_cpu)
+				     u32 *parent_hwirq, int *parent_cpu, u32 id)
 {
 	struct device *dev = &pdev->dev;
 	struct of_phandle_args parent;
 	unsigned long hartid;
 	int rc;
 
-	/*
-	 * Currently, only OF fwnode is supported so extend this
-	 * function for ACPI support.
-	 */
-	if (!is_of_node(dev->fwnode))
-		return -EINVAL;
+	if (!is_of_node(dev->fwnode)) {
+		hartid = acpi_get_ext_intc_parent_hartid(id, context);
+		if (hartid == INVALID_HARTID)
+			return -EINVAL;
+
+		*parent_cpu = riscv_hartid_to_cpuid(hartid);
+		*parent_hwirq = RV_IRQ_EXT;
+		return 0;
+	}
 
 	rc = of_irq_parse_one(to_of_node(dev->fwnode), context, &parent);
 	if (rc)
@@ -489,6 +521,8 @@ static int plic_probe(struct platform_device *pdev)
 	u32 nr_irqs, parent_hwirq;
 	struct plic_priv *priv;
 	irq_hw_number_t hwirq;
+	int id, context_id;
+	u32 gsi_base;
 
 	if (is_of_node(dev->fwnode)) {
 		const struct of_device_id *id;
@@ -498,7 +532,7 @@ static int plic_probe(struct platform_device *pdev)
 			plic_quirks = (unsigned long)id->data;
 	}
 
-	error = plic_parse_nr_irqs_and_contexts(pdev, &nr_irqs, &nr_contexts);
+	error = plic_parse_nr_irqs_and_contexts(pdev, &nr_irqs, &nr_contexts, &gsi_base, &id);
 	if (error)
 		return error;
 
@@ -509,6 +543,8 @@ static int plic_probe(struct platform_device *pdev)
 	priv->dev = dev;
 	priv->plic_quirks = plic_quirks;
 	priv->nr_irqs = nr_irqs;
+	priv->gsi_base = gsi_base;
+	priv->id = id;
 
 	priv->regs = devm_platform_ioremap_resource(pdev, 0);
 	if (WARN_ON(!priv->regs))
@@ -519,12 +555,22 @@ static int plic_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	for (i = 0; i < nr_contexts; i++) {
-		error = plic_parse_context_parent(pdev, i, &parent_hwirq, &cpu);
+		error = plic_parse_context_parent(pdev, i, &parent_hwirq, &cpu, priv->id);
 		if (error) {
 			dev_warn(dev, "hwirq for context%d not found\n", i);
 			continue;
 		}
 
+		if (is_of_node(dev->fwnode)) {
+			context_id = i;
+		} else {
+			context_id = acpi_get_plic_context(priv->id, i);
+			if (context_id == INVALID_CONTEXT) {
+				dev_warn(dev, "invalid context id for context%d\n", i);
+				continue;
+			}
+		}
+
 		/*
 		 * Skip contexts other than external interrupts for our
 		 * privilege level.
@@ -562,10 +608,10 @@ static int plic_probe(struct platform_device *pdev)
 		cpumask_set_cpu(cpu, &priv->lmask);
 		handler->present = true;
 		handler->hart_base = priv->regs + CONTEXT_BASE +
-			i * CONTEXT_SIZE;
+			context_id * CONTEXT_SIZE;
 		raw_spin_lock_init(&handler->enable_lock);
 		handler->enable_base = priv->regs + CONTEXT_ENABLE_BASE +
-			i * CONTEXT_ENABLE_SIZE;
+			context_id * CONTEXT_ENABLE_SIZE;
 		handler->priv = priv;
 
 		handler->enable_save = devm_kcalloc(dev, DIV_ROUND_UP(nr_irqs, 32),
@@ -581,8 +627,8 @@ static int plic_probe(struct platform_device *pdev)
 		nr_handlers++;
 	}
 
-	priv->irqdomain = irq_domain_add_linear(to_of_node(dev->fwnode), nr_irqs + 1,
-						&plic_irqdomain_ops, priv);
+	priv->irqdomain = irq_domain_create_linear(dev->fwnode, nr_irqs + 1,
+						   &plic_irqdomain_ops, priv);
 	if (WARN_ON(!priv->irqdomain))
 		goto fail_cleanup_contexts;
 
@@ -619,13 +665,18 @@ static int plic_probe(struct platform_device *pdev)
 		}
 	}
 
+#ifdef CONFIG_ACPI
+	if (!acpi_disabled)
+		acpi_dev_clear_dependencies(ACPI_COMPANION(dev));
+#endif
+
 	dev_info(dev, "mapped %d interrupts with %d handlers for %d contexts.\n",
 		 nr_irqs, nr_handlers, nr_contexts);
 	return 0;
 
 fail_cleanup_contexts:
 	for (i = 0; i < nr_contexts; i++) {
-		if (plic_parse_context_parent(pdev, i, &parent_hwirq, &cpu))
+		if (plic_parse_context_parent(pdev, i, &parent_hwirq, &cpu, priv->id))
 			continue;
 		if (parent_hwirq != RV_IRQ_EXT || cpu < 0)
 			continue;
@@ -644,6 +695,7 @@ static struct platform_driver plic_driver = {
 	.driver = {
 		.name		= "riscv-plic",
 		.of_match_table	= plic_match,
+		.acpi_match_table = ACPI_PTR(plic_acpi_match),
 	},
 	.probe = plic_probe,
 };
-- 
2.43.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: [PATCH v7 02/17] ACPI: scan: Add a weak function to reorder the IRQCHIP probe
  2024-07-29 14:22 ` [PATCH v7 02/17] ACPI: scan: Add a weak function to reorder the IRQCHIP probe Sunil V L
@ 2024-07-31 19:41   ` Bjorn Helgaas
  0 siblings, 0 replies; 30+ messages in thread
From: Bjorn Helgaas @ 2024-07-31 19:41 UTC (permalink / raw)
  To: Sunil V L
  Cc: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci,
	Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini

On Mon, Jul 29, 2024 at 07:52:24PM +0530, Sunil V L wrote:
> Unlike OF framework, the irqchip probe using IRQCHIP_ACPI_DECLARE has no
> order defined. Depending on the Makefile is not a good idea. So,
> usually it is worked around by mandating only root interrupt controller
> probed using IRQCHIP_ACPI_DECLARE and other interrupt controllers are
> probed via cascade mechanism.
> 
> However, this is also not a clean solution because if there are multiple
> root controllers (ex: RINTC in RISC-V which is per CPU) which need to be
> probed first, then the cascade will happen for every root controller.
> So, introduce a architecture specific weak function to order the probing
> of the interrupt controllers which can be implemented by different
> architectures as per their interrupt controller hierarchy.

Nit: I think it's nice if the commit log and even the subject line
includes the actual *name* of the function being added.

s/a architecture/an architecture/

No need to repost for these.

> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> ---
>  drivers/acpi/scan.c  | 3 +++
>  include/linux/acpi.h | 2 ++
>  2 files changed, 5 insertions(+)
> 
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index 59771412686b..52a9dfc8e18c 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -2755,6 +2755,8 @@ static int __init acpi_match_madt(union acpi_subtable_headers *header,
>  	return 0;
>  }
>  
> +void __weak arch_sort_irqchip_probe(struct acpi_probe_entry *ap_head, int nr) { }
> +
>  int __init __acpi_probe_device_table(struct acpi_probe_entry *ap_head, int nr)
>  {
>  	int count = 0;
> @@ -2763,6 +2765,7 @@ int __init __acpi_probe_device_table(struct acpi_probe_entry *ap_head, int nr)
>  		return 0;
>  
>  	mutex_lock(&acpi_probe_mutex);
> +	arch_sort_irqchip_probe(ap_head, nr);
>  	for (ape = ap_head; nr; ape++, nr--) {
>  		if (ACPI_COMPARE_NAMESEG(ACPI_SIG_MADT, ape->id)) {
>  			acpi_probe_count = 0;
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 0687a442fec7..3fff86f95c2f 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -1343,6 +1343,8 @@ struct acpi_probe_entry {
>  	kernel_ulong_t driver_data;
>  };
>  
> +void arch_sort_irqchip_probe(struct acpi_probe_entry *ap_head, int nr);
> +
>  #define ACPI_DECLARE_PROBE_ENTRY(table, name, table_id, subtable,	\
>  				 valid, data, fn)			\
>  	static const struct acpi_probe_entry __acpi_probe_##name	\
> -- 
> 2.43.0
> 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v7 03/17] ACPI: bus: Add acpi_riscv_init function
  2024-07-29 14:22 ` [PATCH v7 03/17] ACPI: bus: Add acpi_riscv_init function Sunil V L
@ 2024-07-31 19:42   ` Bjorn Helgaas
  0 siblings, 0 replies; 30+ messages in thread
From: Bjorn Helgaas @ 2024-07-31 19:42 UTC (permalink / raw)
  To: Sunil V L
  Cc: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci,
	Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini

On Mon, Jul 29, 2024 at 07:52:25PM +0530, Sunil V L wrote:
> Add a new function for RISC-V to do architecture specific initialization
> similar to acpi_arm_init(). Some of the ACPI tables are architecture
> specific and there is no reason trying to find them on other
> architectures.

Maybe mention the RISC-V function name as well as acpi_arm_init()?

> +++ b/drivers/acpi/riscv/init.c
> @@ -0,0 +1,12 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2023-2024, Ventana Micro Systems Inc
> + *	Author: Sunil V L <sunilvl@ventanamicro.com>
> + *

Spurious blank line.

> + */


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v7 08/17] ACPI: pci_link: Clear the dependencies after probe
  2024-07-29 14:22 ` [PATCH v7 08/17] ACPI: pci_link: Clear the dependencies after probe Sunil V L
@ 2024-07-31 19:49   ` Bjorn Helgaas
  2025-12-01 13:07   ` huyuye
  2025-12-01 14:12   ` huyuye
  2 siblings, 0 replies; 30+ messages in thread
From: Bjorn Helgaas @ 2024-07-31 19:49 UTC (permalink / raw)
  To: Sunil V L
  Cc: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci,
	Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Anup Patel,
	Thomas Gleixner, Samuel Holland, Robert Moore, Conor Dooley,
	Andrew Jones, Haibo Xu, Atish Kumar Patra, Drew Fustini

On Mon, Jul 29, 2024 at 07:52:30PM +0530, Sunil V L wrote:
> RISC-V platforms need to use dependencies between PCI host bridge, Link
> devices and the interrupt controllers to ensure probe order. The
> dependency is like below.
> 
> Interrupt controller <-- Link Device <-- PCI Host bridge.
> 
> If there is no dependency added between Link device and PCI Host Bridge,
> then the PCI end points can get probed prior to link device, unable to
> get mapping for INTx.

This sentence is missing a word or something.  Maybe it's supposed to
say something like this:

  If there is no dependency between Link device and PCI Host Bridge,
  then PCI devices may be probed prior to Link devices.  If a PCI
  device is probed before its Link device, we won't be able to find
  its INTx mapping.

> So, add the link device's HID to dependency honor list and also clear it
> after its probe.

It looks like *this* patch only clears it after probe.  And the commit
log doesn't say why we need to clear the dependency.

> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> ---
>  drivers/acpi/pci_link.c | 2 ++
>  drivers/acpi/scan.c     | 1 +
>  2 files changed, 3 insertions(+)
> 
> diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
> index aa1038b8aec4..b727db968f33 100644
> --- a/drivers/acpi/pci_link.c
> +++ b/drivers/acpi/pci_link.c
> @@ -748,6 +748,8 @@ static int acpi_pci_link_add(struct acpi_device *device,
>  	if (result)
>  		kfree(link);
>  
> +	acpi_dev_clear_dependencies(device);
> +
>  	return result < 0 ? result : 1;
>  }
>  
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index 28a221f956d7..753539a1f26b 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -863,6 +863,7 @@ static const char * const acpi_honor_dep_ids[] = {
>  	"INTC10CF", /* IVSC (MTL) driver must be loaded to allow i2c access to camera sensors */
>  	"RSCV0001", /* RISC-V PLIC */
>  	"RSCV0002", /* RISC-V APLIC */
> +	"PNP0C0F",  /* PCI Link Device */
>  	NULL
>  };
>  
> -- 
> 2.43.0
> 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v7 13/17] irqchip/riscv-intc: Add ACPI support for AIA
  2024-07-29 14:22 ` [PATCH v7 13/17] irqchip/riscv-intc: Add ACPI support for AIA Sunil V L
@ 2024-08-06 15:22   ` Anup Patel
  0 siblings, 0 replies; 30+ messages in thread
From: Anup Patel @ 2024-08-06 15:22 UTC (permalink / raw)
  To: Sunil V L
  Cc: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci,
	Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Thomas Gleixner,
	Samuel Holland, Robert Moore, Conor Dooley, Andrew Jones,
	Haibo Xu, Atish Kumar Patra, Drew Fustini

On Mon, Jul 29, 2024 at 7:54 PM Sunil V L <sunilvl@ventanamicro.com> wrote:
>
> The RINTC subtype structure in MADT also has information about other
> interrupt controllers. Save this information and provide interfaces to
> retrieve them when required by corresponding drivers.
>
> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> ---
>  arch/riscv/include/asm/irq.h     | 33 ++++++++++++
>  drivers/irqchip/irq-riscv-intc.c | 90 ++++++++++++++++++++++++++++++++
>  2 files changed, 123 insertions(+)
>
> diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h
> index 44a0b128c602..51d86f0b80d2 100644
> --- a/arch/riscv/include/asm/irq.h
> +++ b/arch/riscv/include/asm/irq.h
> @@ -12,6 +12,8 @@
>
>  #include <asm-generic/irq.h>
>
> +#define INVALID_CONTEXT UINT_MAX
> +
>  void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void));
>
>  struct fwnode_handle *riscv_get_intc_hwnode(void);
> @@ -28,6 +30,11 @@ enum riscv_irqchip_type {
>  int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi_base,
>                             u32 *id, u32 *nr_irqs, u32 *nr_idcs);
>  struct fwnode_handle *riscv_acpi_get_gsi_domain_id(u32 gsi);

I suggest the below renaming to make it explicit that these are RINTC functions.

> +unsigned long acpi_get_intc_index_hartid(u32 index);

s/acpi_get_intc_index_hartid/acpi_rintc_index_to_hartid/

> +unsigned long acpi_get_ext_intc_parent_hartid(unsigned int plic_id, unsigned int ctxt_idx);

s/acpi_get_ext_intc_parent_hartid/acpi_rintc_ext_parent_to_hartid/

> +unsigned int acpi_get_plic_nr_contexts(unsigned int plic_id);

s/acpi_get_plic_nr_contexts/acpi_rintc_get_plic_nr_contexts/

> +unsigned int acpi_get_plic_context(unsigned int plic_id, unsigned int ctxt_idx);

s/acpi_get_plic_context/acpi_rintc_get_plic_context/

> +int __init acpi_get_imsic_mmio_info(u32 index, struct resource *res);

s/acpi_get_imsic_mmio_info/acpi_rintc_get_imsic_mmio_info/

>
>  #else
>  static inline int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi_base,
> @@ -36,6 +43,32 @@ static inline int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi
>         return 0;
>  }
>
> +static inline unsigned long acpi_get_intc_index_hartid(u32 index)
> +{
> +       return INVALID_HARTID;
> +}
> +
> +static inline unsigned long acpi_get_ext_intc_parent_hartid(unsigned int plic_id,
> +                                                           unsigned int ctxt_idx)
> +{
> +       return INVALID_HARTID;
> +}
> +
> +static inline unsigned int acpi_get_plic_nr_contexts(unsigned int plic_id)
> +{
> +       return INVALID_CONTEXT;
> +}
> +
> +static inline unsigned int acpi_get_plic_context(unsigned int plic_id, unsigned int ctxt_idx)
> +{
> +       return INVALID_CONTEXT;
> +}
> +
> +static inline int __init acpi_get_imsic_mmio_info(u32 index, struct resource *res)
> +{
> +       return 0;
> +}
> +
>  #endif /* CONFIG_ACPI */
>
>  #endif /* _ASM_RISCV_IRQ_H */
> diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c
> index 47f3200476da..5ddb12ce8b97 100644
> --- a/drivers/irqchip/irq-riscv-intc.c
> +++ b/drivers/irqchip/irq-riscv-intc.c
> @@ -250,6 +250,85 @@ IRQCHIP_DECLARE(andes, "andestech,cpu-intc", riscv_intc_init);
>
>  #ifdef CONFIG_ACPI
>
> +struct rintc_data {
> +       union {
> +               u32             ext_intc_id;
> +               struct {
> +                       u32     context_id      : 16,
> +                               reserved        :  8,
> +                               aplic_plic_id   :  8;
> +               };
> +       };
> +       unsigned long           hart_id;
> +       u64                     imsic_addr;
> +       u32                     imsic_size;
> +};
> +
> +static u32 nr_rintc;
> +static struct rintc_data *rintc_acpi_data[NR_CPUS];
> +
> +#define for_each_matching_plic(_plic_id)                               \
> +       unsigned int _plic;                                             \
> +                                                                       \
> +       for (_plic = 0; _plic < nr_rintc; _plic++)                      \
> +               if (rintc_acpi_data[_plic]->aplic_plic_id != _plic_id)  \
> +                       continue;                                       \
> +               else
> +
> +unsigned int acpi_get_plic_nr_contexts(unsigned int plic_id)
> +{
> +       unsigned int nctx = 0;
> +
> +       for_each_matching_plic(plic_id)
> +               nctx++;
> +
> +       return nctx;
> +}
> +
> +static struct rintc_data *get_plic_context(unsigned int plic_id, unsigned int ctxt_idx)
> +{
> +       unsigned int ctxt = 0;
> +
> +       for_each_matching_plic(plic_id) {
> +               if (ctxt == ctxt_idx)
> +                       return rintc_acpi_data[_plic];
> +
> +               ctxt++;
> +       }
> +
> +       return NULL;
> +}
> +
> +unsigned long acpi_get_ext_intc_parent_hartid(unsigned int plic_id, unsigned int ctxt_idx)
> +{
> +       struct rintc_data *data = get_plic_context(plic_id, ctxt_idx);
> +
> +       return data ? data->hart_id : INVALID_HARTID;
> +}
> +
> +unsigned int acpi_get_plic_context(unsigned int plic_id, unsigned int ctxt_idx)
> +{
> +       struct rintc_data *data = get_plic_context(plic_id, ctxt_idx);
> +
> +       return data ? data->context_id : INVALID_CONTEXT;
> +}
> +
> +unsigned long acpi_get_intc_index_hartid(u32 index)
> +{
> +       return index >= nr_rintc ? INVALID_HARTID : rintc_acpi_data[index]->hart_id;
> +}
> +
> +int acpi_get_imsic_mmio_info(u32 index, struct resource *res)
> +{
> +       if (index >= nr_rintc)
> +               return -1;
> +
> +       res->start = rintc_acpi_data[index]->imsic_addr;
> +       res->end = res->start + rintc_acpi_data[index]->imsic_size - 1;
> +       res->flags = IORESOURCE_MEM;
> +       return 0;
> +}
> +
>  static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
>                                        const unsigned long end)
>  {
> @@ -258,6 +337,15 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
>         int rc;
>
>         rintc = (struct acpi_madt_rintc *)header;
> +       rintc_acpi_data[nr_rintc] = kzalloc(sizeof(*rintc_acpi_data[0]), GFP_KERNEL);
> +       if (!rintc_acpi_data[nr_rintc])
> +               return -ENOMEM;
> +
> +       rintc_acpi_data[nr_rintc]->ext_intc_id = rintc->ext_intc_id;
> +       rintc_acpi_data[nr_rintc]->hart_id = rintc->hart_id;
> +       rintc_acpi_data[nr_rintc]->imsic_addr = rintc->imsic_addr;
> +       rintc_acpi_data[nr_rintc]->imsic_size = rintc->imsic_size;
> +       nr_rintc++;
>
>         /*
>          * The ACPI MADT will have one INTC for each CPU (or HART)
> @@ -277,6 +365,8 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
>         rc = riscv_intc_init_common(fn, &riscv_intc_chip);
>         if (rc)
>                 irq_domain_free_fwnode(fn);
> +       else
> +               acpi_set_irq_model(ACPI_IRQ_MODEL_RINTC, riscv_acpi_get_gsi_domain_id);
>
>         return rc;
>  }
> --
> 2.43.0
>

Otherwise, this looks good to me.

Reviewed-by: Anup Patel <anup@brainfault.org>

Regards,
Anup


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v7 14/17] irqchip/riscv-imsic-state: Create separate function for DT
  2024-07-29 14:22 ` [PATCH v7 14/17] irqchip/riscv-imsic-state: Create separate function for DT Sunil V L
@ 2024-08-06 15:25   ` Anup Patel
  0 siblings, 0 replies; 30+ messages in thread
From: Anup Patel @ 2024-08-06 15:25 UTC (permalink / raw)
  To: Sunil V L
  Cc: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci,
	Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Thomas Gleixner,
	Samuel Holland, Robert Moore, Conor Dooley, Andrew Jones,
	Haibo Xu, Atish Kumar Patra, Drew Fustini

On Mon, Jul 29, 2024 at 7:54 PM Sunil V L <sunilvl@ventanamicro.com> wrote:
>
> While populating IMSIC global structure, many fields are initialized
> using DT properties. Make the code which uses DT properties as separate
> function so that it is easier to add ACPI support later. No
> functionality added/changed.
>
> Suggested-by: Thomas Gleixner <tglx@linutronix.de>
> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>

LGTM.

Reviewed-by: Anup Patel <anup@brainfault.org>

Regards,
Anup

> ---
>  drivers/irqchip/irq-riscv-imsic-state.c | 97 ++++++++++++++-----------
>  1 file changed, 55 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
> index 5479f872e62b..f9e70832863a 100644
> --- a/drivers/irqchip/irq-riscv-imsic-state.c
> +++ b/drivers/irqchip/irq-riscv-imsic-state.c
> @@ -510,6 +510,60 @@ static int __init imsic_matrix_init(void)
>         return 0;
>  }
>
> +static int __init imsic_populate_global_dt(struct fwnode_handle *fwnode,
> +                                          struct imsic_global_config *global,
> +                                          u32 *nr_parent_irqs)
> +{
> +       int rc;
> +
> +       /* Find number of guest index bits in MSI address */
> +       rc = of_property_read_u32(to_of_node(fwnode), "riscv,guest-index-bits",
> +                                 &global->guest_index_bits);
> +       if (rc)
> +               global->guest_index_bits = 0;
> +
> +       /* Find number of HART index bits */
> +       rc = of_property_read_u32(to_of_node(fwnode), "riscv,hart-index-bits",
> +                                 &global->hart_index_bits);
> +       if (rc) {
> +               /* Assume default value */
> +               global->hart_index_bits = __fls(*nr_parent_irqs);
> +               if (BIT(global->hart_index_bits) < *nr_parent_irqs)
> +                       global->hart_index_bits++;
> +       }
> +
> +       /* Find number of group index bits */
> +       rc = of_property_read_u32(to_of_node(fwnode), "riscv,group-index-bits",
> +                                 &global->group_index_bits);
> +       if (rc)
> +               global->group_index_bits = 0;
> +
> +       /*
> +        * Find first bit position of group index.
> +        * If not specified assumed the default APLIC-IMSIC configuration.
> +        */
> +       rc = of_property_read_u32(to_of_node(fwnode), "riscv,group-index-shift",
> +                                 &global->group_index_shift);
> +       if (rc)
> +               global->group_index_shift = IMSIC_MMIO_PAGE_SHIFT * 2;
> +
> +       /* Find number of interrupt identities */
> +       rc = of_property_read_u32(to_of_node(fwnode), "riscv,num-ids",
> +                                 &global->nr_ids);
> +       if (rc) {
> +               pr_err("%pfwP: number of interrupt identities not found\n", fwnode);
> +               return rc;
> +       }
> +
> +       /* Find number of guest interrupt identities */
> +       rc = of_property_read_u32(to_of_node(fwnode), "riscv,num-guest-ids",
> +                                 &global->nr_guest_ids);
> +       if (rc)
> +               global->nr_guest_ids = global->nr_ids;
> +
> +       return 0;
> +}
> +
>  static int __init imsic_get_parent_hartid(struct fwnode_handle *fwnode,
>                                           u32 index, unsigned long *hartid)
>  {
> @@ -578,50 +632,9 @@ static int __init imsic_parse_fwnode(struct fwnode_handle *fwnode,
>                 return -EINVAL;
>         }
>
> -       /* Find number of guest index bits in MSI address */
> -       rc = of_property_read_u32(to_of_node(fwnode), "riscv,guest-index-bits",
> -                                 &global->guest_index_bits);
> +       rc = imsic_populate_global_dt(fwnode, global, nr_parent_irqs);
>         if (rc)
> -               global->guest_index_bits = 0;
> -
> -       /* Find number of HART index bits */
> -       rc = of_property_read_u32(to_of_node(fwnode), "riscv,hart-index-bits",
> -                                 &global->hart_index_bits);
> -       if (rc) {
> -               /* Assume default value */
> -               global->hart_index_bits = __fls(*nr_parent_irqs);
> -               if (BIT(global->hart_index_bits) < *nr_parent_irqs)
> -                       global->hart_index_bits++;
> -       }
> -
> -       /* Find number of group index bits */
> -       rc = of_property_read_u32(to_of_node(fwnode), "riscv,group-index-bits",
> -                                 &global->group_index_bits);
> -       if (rc)
> -               global->group_index_bits = 0;
> -
> -       /*
> -        * Find first bit position of group index.
> -        * If not specified assumed the default APLIC-IMSIC configuration.
> -        */
> -       rc = of_property_read_u32(to_of_node(fwnode), "riscv,group-index-shift",
> -                                 &global->group_index_shift);
> -       if (rc)
> -               global->group_index_shift = IMSIC_MMIO_PAGE_SHIFT * 2;
> -
> -       /* Find number of interrupt identities */
> -       rc = of_property_read_u32(to_of_node(fwnode), "riscv,num-ids",
> -                                 &global->nr_ids);
> -       if (rc) {
> -               pr_err("%pfwP: number of interrupt identities not found\n", fwnode);
>                 return rc;
> -       }
> -
> -       /* Find number of guest interrupt identities */
> -       rc = of_property_read_u32(to_of_node(fwnode), "riscv,num-guest-ids",
> -                                 &global->nr_guest_ids);
> -       if (rc)
> -               global->nr_guest_ids = global->nr_ids;
>
>         /* Sanity check guest index bits */
>         i = BITS_PER_LONG - IMSIC_MMIO_PAGE_SHIFT;
> --
> 2.43.0
>


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v7 15/17] irqchip/riscv-imsic: Add ACPI support
  2024-07-29 14:22 ` [PATCH v7 15/17] irqchip/riscv-imsic: Add ACPI support Sunil V L
@ 2024-08-06 15:30   ` Anup Patel
  0 siblings, 0 replies; 30+ messages in thread
From: Anup Patel @ 2024-08-06 15:30 UTC (permalink / raw)
  To: Sunil V L
  Cc: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci,
	Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Thomas Gleixner,
	Samuel Holland, Robert Moore, Conor Dooley, Andrew Jones,
	Haibo Xu, Atish Kumar Patra, Drew Fustini

On Mon, Jul 29, 2024 at 7:54 PM Sunil V L <sunilvl@ventanamicro.com> wrote:
>
> RISC-V IMSIC interrupt controller provides IPI and MSI support.
> Currently, DT based drivers setup the IPI feature early during boot but
> defer setting up the MSI functionality. However, in ACPI systems, PCI
> subsystem is probed early and assume MSI controller is already setup.
> Hence, both IPI and MSI features need to be initialized early itself.
>
> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>

LGTM.

Reviewed-by: Anup Patel <anup@brainfault.org>

Regards,
Anup


> ---
>  drivers/irqchip/irq-riscv-imsic-early.c    | 64 +++++++++++++++++++++-
>  drivers/irqchip/irq-riscv-imsic-platform.c | 32 +++++++++--
>  drivers/irqchip/irq-riscv-imsic-state.c    | 57 +++++++++++--------
>  drivers/irqchip/irq-riscv-imsic-state.h    |  2 +-
>  include/linux/irqchip/riscv-imsic.h        |  9 +++
>  5 files changed, 134 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c
> index 4fbb37074d29..c5c2e6929a2f 100644
> --- a/drivers/irqchip/irq-riscv-imsic-early.c
> +++ b/drivers/irqchip/irq-riscv-imsic-early.c
> @@ -5,13 +5,16 @@
>   */
>
>  #define pr_fmt(fmt) "riscv-imsic: " fmt
> +#include <linux/acpi.h>
>  #include <linux/cpu.h>
>  #include <linux/interrupt.h>
>  #include <linux/io.h>
>  #include <linux/irq.h>
>  #include <linux/irqchip.h>
>  #include <linux/irqchip/chained_irq.h>
> +#include <linux/irqchip/riscv-imsic.h>
>  #include <linux/module.h>
> +#include <linux/pci.h>
>  #include <linux/spinlock.h>
>  #include <linux/smp.h>
>
> @@ -182,7 +185,7 @@ static int __init imsic_early_dt_init(struct device_node *node, struct device_no
>         int rc;
>
>         /* Setup IMSIC state */
> -       rc = imsic_setup_state(fwnode);
> +       rc = imsic_setup_state(fwnode, NULL);
>         if (rc) {
>                 pr_err("%pfwP: failed to setup state (error %d)\n", fwnode, rc);
>                 return rc;
> @@ -199,3 +202,62 @@ static int __init imsic_early_dt_init(struct device_node *node, struct device_no
>  }
>
>  IRQCHIP_DECLARE(riscv_imsic, "riscv,imsics", imsic_early_dt_init);
> +
> +#ifdef CONFIG_ACPI
> +
> +static struct fwnode_handle *imsic_acpi_fwnode;
> +
> +struct fwnode_handle *imsic_acpi_get_fwnode(struct device *dev)
> +{
> +       return imsic_acpi_fwnode;
> +}
> +
> +static int __init imsic_early_acpi_init(union acpi_subtable_headers *header,
> +                                       const unsigned long end)
> +{
> +       struct acpi_madt_imsic *imsic = (struct acpi_madt_imsic *)header;
> +       int rc;
> +
> +       imsic_acpi_fwnode = irq_domain_alloc_named_fwnode("imsic");
> +       if (!imsic_acpi_fwnode) {
> +               pr_err("unable to allocate IMSIC FW node\n");
> +               return -ENOMEM;
> +       }
> +
> +       /* Setup IMSIC state */
> +       rc = imsic_setup_state(imsic_acpi_fwnode, imsic);
> +       if (rc) {
> +               pr_err("%pfwP: failed to setup state (error %d)\n", imsic_acpi_fwnode, rc);
> +               return rc;
> +       }
> +
> +       /* Do early setup of IMSIC state and IPIs */
> +       rc = imsic_early_probe(imsic_acpi_fwnode);
> +       if (rc) {
> +               irq_domain_free_fwnode(imsic_acpi_fwnode);
> +               imsic_acpi_fwnode = NULL;
> +               return rc;
> +       }
> +
> +       rc = imsic_platform_acpi_probe(imsic_acpi_fwnode);
> +
> +#ifdef CONFIG_PCI
> +       if (!rc)
> +               pci_msi_register_fwnode_provider(&imsic_acpi_get_fwnode);
> +#endif
> +
> +       if (rc)
> +               pr_err("%pfwP: failed to register IMSIC for MSI functionality (error %d)\n",
> +                      imsic_acpi_fwnode, rc);
> +
> +       /*
> +        * Even if imsic_platform_acpi_probe() fails, the IPI part of IMSIC can
> +        * continue to work. So, no need to return failure. This is similar to
> +        * DT where IPI works but MSI probe fails for some reason.
> +        */
> +       return 0;
> +}
> +
> +IRQCHIP_ACPI_DECLARE(riscv_imsic, ACPI_MADT_TYPE_IMSIC, NULL,
> +                    1, imsic_early_acpi_init);
> +#endif
> diff --git a/drivers/irqchip/irq-riscv-imsic-platform.c b/drivers/irqchip/irq-riscv-imsic-platform.c
> index 11723a763c10..64905e6f52d7 100644
> --- a/drivers/irqchip/irq-riscv-imsic-platform.c
> +++ b/drivers/irqchip/irq-riscv-imsic-platform.c
> @@ -5,6 +5,7 @@
>   */
>
>  #define pr_fmt(fmt) "riscv-imsic: " fmt
> +#include <linux/acpi.h>
>  #include <linux/bitmap.h>
>  #include <linux/cpu.h>
>  #include <linux/interrupt.h>
> @@ -348,18 +349,37 @@ int imsic_irqdomain_init(void)
>         return 0;
>  }
>
> -static int imsic_platform_probe(struct platform_device *pdev)
> +static int imsic_platform_probe_common(struct fwnode_handle *fwnode)
>  {
> -       struct device *dev = &pdev->dev;
> -
> -       if (imsic && imsic->fwnode != dev->fwnode) {
> -               dev_err(dev, "fwnode mismatch\n");
> +       if (imsic && imsic->fwnode != fwnode) {
> +               pr_err("%pfwP: fwnode mismatch\n", fwnode);
>                 return -ENODEV;
>         }
>
>         return imsic_irqdomain_init();
>  }
>
> +static int imsic_platform_dt_probe(struct platform_device *pdev)
> +{
> +       return imsic_platform_probe_common(pdev->dev.fwnode);
> +}
> +
> +#ifdef CONFIG_ACPI
> +
> +/*
> + *  On ACPI based systems, PCI enumeration happens early during boot in
> + *  acpi_scan_init(). PCI enumeration expects MSI domain setup before
> + *  it calls pci_set_msi_domain(). Hence, unlike in DT where
> + *  imsic-platform drive probe happens late during boot, ACPI based
> + *  systems need to setup the MSI domain early.
> + */
> +int imsic_platform_acpi_probe(struct fwnode_handle *fwnode)
> +{
> +       return imsic_platform_probe_common(fwnode);
> +}
> +
> +#endif
> +
>  static const struct of_device_id imsic_platform_match[] = {
>         { .compatible = "riscv,imsics" },
>         {}
> @@ -370,6 +390,6 @@ static struct platform_driver imsic_platform_driver = {
>                 .name           = "riscv-imsic",
>                 .of_match_table = imsic_platform_match,
>         },
> -       .probe = imsic_platform_probe,
> +       .probe = imsic_platform_dt_probe,
>  };
>  builtin_platform_driver(imsic_platform_driver);
> diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
> index f9e70832863a..73faa64bffda 100644
> --- a/drivers/irqchip/irq-riscv-imsic-state.c
> +++ b/drivers/irqchip/irq-riscv-imsic-state.c
> @@ -5,6 +5,7 @@
>   */
>
>  #define pr_fmt(fmt) "riscv-imsic: " fmt
> +#include <linux/acpi.h>
>  #include <linux/cpu.h>
>  #include <linux/bitmap.h>
>  #include <linux/interrupt.h>
> @@ -564,18 +565,36 @@ static int __init imsic_populate_global_dt(struct fwnode_handle *fwnode,
>         return 0;
>  }
>
> +static int __init imsic_populate_global_acpi(struct fwnode_handle *fwnode,
> +                                            struct imsic_global_config *global,
> +                                            u32 *nr_parent_irqs, void *opaque)
> +{
> +       struct acpi_madt_imsic *imsic = (struct acpi_madt_imsic *)opaque;
> +
> +       global->guest_index_bits = imsic->guest_index_bits;
> +       global->hart_index_bits = imsic->hart_index_bits;
> +       global->group_index_bits = imsic->group_index_bits;
> +       global->group_index_shift = imsic->group_index_shift;
> +       global->nr_ids = imsic->num_ids;
> +       global->nr_guest_ids = imsic->num_guest_ids;
> +       return 0;
> +}
> +
>  static int __init imsic_get_parent_hartid(struct fwnode_handle *fwnode,
>                                           u32 index, unsigned long *hartid)
>  {
>         struct of_phandle_args parent;
>         int rc;
>
> -       /*
> -        * Currently, only OF fwnode is supported so extend this
> -        * function for ACPI support.
> -        */
> -       if (!is_of_node(fwnode))
> -               return -EINVAL;
> +       if (!is_of_node(fwnode)) {
> +               if (hartid)
> +                       *hartid = acpi_get_intc_index_hartid(index);
> +
> +               if (!hartid || (*hartid == INVALID_HARTID))
> +                       return -EINVAL;
> +
> +               return 0;
> +       }
>
>         rc = of_irq_parse_one(to_of_node(fwnode), index, &parent);
>         if (rc)
> @@ -594,12 +613,8 @@ static int __init imsic_get_parent_hartid(struct fwnode_handle *fwnode,
>  static int __init imsic_get_mmio_resource(struct fwnode_handle *fwnode,
>                                           u32 index, struct resource *res)
>  {
> -       /*
> -        * Currently, only OF fwnode is supported so extend this
> -        * function for ACPI support.
> -        */
>         if (!is_of_node(fwnode))
> -               return -EINVAL;
> +               return acpi_get_imsic_mmio_info(index, res);
>
>         return of_address_to_resource(to_of_node(fwnode), index, res);
>  }
> @@ -607,20 +622,14 @@ static int __init imsic_get_mmio_resource(struct fwnode_handle *fwnode,
>  static int __init imsic_parse_fwnode(struct fwnode_handle *fwnode,
>                                      struct imsic_global_config *global,
>                                      u32 *nr_parent_irqs,
> -                                    u32 *nr_mmios)
> +                                    u32 *nr_mmios,
> +                                    void *opaque)
>  {
>         unsigned long hartid;
>         struct resource res;
>         int rc;
>         u32 i;
>
> -       /*
> -        * Currently, only OF fwnode is supported so extend this
> -        * function for ACPI support.
> -        */
> -       if (!is_of_node(fwnode))
> -               return -EINVAL;
> -
>         *nr_parent_irqs = 0;
>         *nr_mmios = 0;
>
> @@ -632,7 +641,11 @@ static int __init imsic_parse_fwnode(struct fwnode_handle *fwnode,
>                 return -EINVAL;
>         }
>
> -       rc = imsic_populate_global_dt(fwnode, global, nr_parent_irqs);
> +       if (is_of_node(fwnode))
> +               rc = imsic_populate_global_dt(fwnode, global, nr_parent_irqs);
> +       else
> +               rc = imsic_populate_global_acpi(fwnode, global, nr_parent_irqs, opaque);
> +
>         if (rc)
>                 return rc;
>
> @@ -701,7 +714,7 @@ static int __init imsic_parse_fwnode(struct fwnode_handle *fwnode,
>         return 0;
>  }
>
> -int __init imsic_setup_state(struct fwnode_handle *fwnode)
> +int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
>  {
>         u32 i, j, index, nr_parent_irqs, nr_mmios, nr_handlers = 0;
>         struct imsic_global_config *global;
> @@ -742,7 +755,7 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode)
>         }
>
>         /* Parse IMSIC fwnode */
> -       rc = imsic_parse_fwnode(fwnode, global, &nr_parent_irqs, &nr_mmios);
> +       rc = imsic_parse_fwnode(fwnode, global, &nr_parent_irqs, &nr_mmios, opaque);
>         if (rc)
>                 goto out_free_local;
>
> diff --git a/drivers/irqchip/irq-riscv-imsic-state.h b/drivers/irqchip/irq-riscv-imsic-state.h
> index 5ae2f69b035b..391e44280827 100644
> --- a/drivers/irqchip/irq-riscv-imsic-state.h
> +++ b/drivers/irqchip/irq-riscv-imsic-state.h
> @@ -102,7 +102,7 @@ void imsic_vector_debug_show_summary(struct seq_file *m, int ind);
>
>  void imsic_state_online(void);
>  void imsic_state_offline(void);
> -int imsic_setup_state(struct fwnode_handle *fwnode);
> +int imsic_setup_state(struct fwnode_handle *fwnode, void *opaque);
>  int imsic_irqdomain_init(void);
>
>  #endif
> diff --git a/include/linux/irqchip/riscv-imsic.h b/include/linux/irqchip/riscv-imsic.h
> index faf0b800b1b0..7494952c5518 100644
> --- a/include/linux/irqchip/riscv-imsic.h
> +++ b/include/linux/irqchip/riscv-imsic.h
> @@ -8,6 +8,8 @@
>
>  #include <linux/types.h>
>  #include <linux/bitops.h>
> +#include <linux/device.h>
> +#include <linux/fwnode.h>
>  #include <asm/csr.h>
>
>  #define IMSIC_MMIO_PAGE_SHIFT          12
> @@ -84,4 +86,11 @@ static inline const struct imsic_global_config *imsic_get_global_config(void)
>
>  #endif
>
> +#ifdef CONFIG_ACPI
> +int imsic_platform_acpi_probe(struct fwnode_handle *fwnode);
> +struct fwnode_handle *imsic_acpi_get_fwnode(struct device *dev);
> +#else
> +static inline struct fwnode_handle *imsic_acpi_get_fwnode(struct device *dev) { return NULL; }
> +#endif
> +
>  #endif
> --
> 2.43.0
>


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v7 16/17] irqchip/riscv-aplic: Add ACPI support
  2024-07-29 14:22 ` [PATCH v7 16/17] irqchip/riscv-aplic: " Sunil V L
@ 2024-08-06 15:54   ` Anup Patel
  0 siblings, 0 replies; 30+ messages in thread
From: Anup Patel @ 2024-08-06 15:54 UTC (permalink / raw)
  To: Sunil V L
  Cc: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci,
	Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Thomas Gleixner,
	Samuel Holland, Robert Moore, Conor Dooley, Andrew Jones,
	Haibo Xu, Atish Kumar Patra, Drew Fustini

On Mon, Jul 29, 2024 at 7:54 PM Sunil V L <sunilvl@ventanamicro.com> wrote:
>
> Add ACPI support in APLIC drivers. Use the mapping created early during
> boot to get the details about the APLIC.
>
> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> ---
>  drivers/irqchip/irq-riscv-aplic-direct.c | 22 +++++---
>  drivers/irqchip/irq-riscv-aplic-main.c   | 69 ++++++++++++++++--------
>  drivers/irqchip/irq-riscv-aplic-main.h   |  1 +
>  drivers/irqchip/irq-riscv-aplic-msi.c    |  9 +++-
>  4 files changed, 69 insertions(+), 32 deletions(-)
>
> diff --git a/drivers/irqchip/irq-riscv-aplic-direct.c b/drivers/irqchip/irq-riscv-aplic-direct.c
> index 4a3ffe856d6c..34540a0ca4da 100644
> --- a/drivers/irqchip/irq-riscv-aplic-direct.c
> +++ b/drivers/irqchip/irq-riscv-aplic-direct.c
> @@ -4,6 +4,7 @@
>   * Copyright (C) 2022 Ventana Micro Systems Inc.
>   */
>
> +#include <linux/acpi.h>
>  #include <linux/bitfield.h>
>  #include <linux/bitops.h>
>  #include <linux/cpu.h>
> @@ -189,17 +190,22 @@ static int aplic_direct_starting_cpu(unsigned int cpu)
>  }
>
>  static int aplic_direct_parse_parent_hwirq(struct device *dev, u32 index,
> -                                          u32 *parent_hwirq, unsigned long *parent_hartid)
> +                                          u32 *parent_hwirq, unsigned long *parent_hartid,
> +                                          struct aplic_priv *priv)
>  {
>         struct of_phandle_args parent;
> +       unsigned long hartid;
>         int rc;
>
> -       /*
> -        * Currently, only OF fwnode is supported so extend this
> -        * function for ACPI support.
> -        */
> -       if (!is_of_node(dev->fwnode))
> -               return -EINVAL;
> +       if (!is_of_node(dev->fwnode)) {
> +               hartid = acpi_get_ext_intc_parent_hartid(priv->id, index);
> +               if (hartid == INVALID_HARTID)
> +                       return -ENODEV;
> +
> +               *parent_hartid = hartid;
> +               *parent_hwirq = RV_IRQ_EXT;
> +               return 0;
> +       }
>
>         rc = of_irq_parse_one(to_of_node(dev->fwnode), index, &parent);
>         if (rc)
> @@ -237,7 +243,7 @@ int aplic_direct_setup(struct device *dev, void __iomem *regs)
>         /* Setup per-CPU IDC and target CPU mask */
>         current_cpu = get_cpu();
>         for (i = 0; i < priv->nr_idcs; i++) {
> -               rc = aplic_direct_parse_parent_hwirq(dev, i, &hwirq, &hartid);
> +               rc = aplic_direct_parse_parent_hwirq(dev, i, &hwirq, &hartid, priv);
>                 if (rc) {
>                         dev_warn(dev, "parent irq for IDC%d not found\n", i);
>                         continue;
> diff --git a/drivers/irqchip/irq-riscv-aplic-main.c b/drivers/irqchip/irq-riscv-aplic-main.c
> index 28dd175b5764..8357c5f9921a 100644
> --- a/drivers/irqchip/irq-riscv-aplic-main.c
> +++ b/drivers/irqchip/irq-riscv-aplic-main.c
> @@ -4,8 +4,10 @@
>   * Copyright (C) 2022 Ventana Micro Systems Inc.
>   */
>
> +#include <linux/acpi.h>
>  #include <linux/bitfield.h>
>  #include <linux/irqchip/riscv-aplic.h>
> +#include <linux/irqchip/riscv-imsic.h>
>  #include <linux/module.h>
>  #include <linux/of.h>
>  #include <linux/of_irq.h>
> @@ -125,39 +127,50 @@ static void aplic_init_hw_irqs(struct aplic_priv *priv)
>         writel(0, priv->regs + APLIC_DOMAINCFG);
>  }
>
> +#ifdef CONFIG_ACPI
> +static const struct acpi_device_id aplic_acpi_match[] = {
> +       { "RSCV0002", 0 },
> +       {}
> +};
> +MODULE_DEVICE_TABLE(acpi, aplic_acpi_match);
> +
> +#endif
> +
>  int aplic_setup_priv(struct aplic_priv *priv, struct device *dev, void __iomem *regs)
>  {
>         struct device_node *np = to_of_node(dev->fwnode);
>         struct of_phandle_args parent;
>         int rc;
>
> -       /*
> -        * Currently, only OF fwnode is supported so extend this
> -        * function for ACPI support.
> -        */
> -       if (!np)
> -               return -EINVAL;
> -
>         /* Save device pointer and register base */
>         priv->dev = dev;
>         priv->regs = regs;
>
> -       /* Find out number of interrupt sources */
> -       rc = of_property_read_u32(np, "riscv,num-sources", &priv->nr_irqs);
> -       if (rc) {
> -               dev_err(dev, "failed to get number of interrupt sources\n");
> -               return rc;
> -       }
> +       if (np) {
> +               /* Find out number of interrupt sources */
> +               rc = of_property_read_u32(np, "riscv,num-sources", &priv->nr_irqs);
> +               if (rc) {
> +                       dev_err(dev, "failed to get number of interrupt sources\n");
> +                       return rc;
> +               }
>
> -       /*
> -        * Find out number of IDCs based on parent interrupts
> -        *
> -        * If "msi-parent" property is present then we ignore the
> -        * APLIC IDCs which forces the APLIC driver to use MSI mode.
> -        */
> -       if (!of_property_present(np, "msi-parent")) {
> -               while (!of_irq_parse_one(np, priv->nr_idcs, &parent))
> -                       priv->nr_idcs++;
> +               /*
> +                * Find out number of IDCs based on parent interrupts
> +                *
> +                * If "msi-parent" property is present then we ignore the
> +                * APLIC IDCs which forces the APLIC driver to use MSI mode.
> +                */
> +               if (!of_property_present(np, "msi-parent")) {
> +                       while (!of_irq_parse_one(np, priv->nr_idcs, &parent))
> +                               priv->nr_idcs++;
> +               }
> +       } else {
> +               rc = riscv_acpi_get_gsi_info(dev->fwnode, &priv->gsi_base, &priv->id,
> +                                            &priv->nr_irqs, &priv->nr_idcs);
> +               if (rc) {
> +                       dev_err(dev, "failed to find GSI mapping\n");
> +                       return rc;
> +               }
>         }
>
>         /* Setup initial state APLIC interrupts */
> @@ -184,7 +197,11 @@ static int aplic_probe(struct platform_device *pdev)
>          * If msi-parent property is present then setup APLIC MSI
>          * mode otherwise setup APLIC direct mode.
>          */
> -       msi_mode = of_property_present(to_of_node(dev->fwnode), "msi-parent");
> +       if (is_of_node(dev->fwnode))
> +               msi_mode = of_property_present(to_of_node(dev->fwnode), "msi-parent");
> +       else
> +               msi_mode = imsic_acpi_get_fwnode(NULL) ? 1 : 0;
> +
>         if (msi_mode)
>                 rc = aplic_msi_setup(dev, regs);
>         else
> @@ -192,6 +209,11 @@ static int aplic_probe(struct platform_device *pdev)
>         if (rc)
>                 dev_err(dev, "failed to setup APLIC in %s mode\n", msi_mode ? "MSI" : "direct");
>
> +#ifdef CONFIG_ACPI
> +       if (!acpi_disabled)
> +               acpi_dev_clear_dependencies(ACPI_COMPANION(dev));
> +#endif
> +
>         return rc;
>  }
>
> @@ -204,6 +226,7 @@ static struct platform_driver aplic_driver = {
>         .driver = {
>                 .name           = "riscv-aplic",
>                 .of_match_table = aplic_match,
> +               .acpi_match_table = ACPI_PTR(aplic_acpi_match),
>         },
>         .probe = aplic_probe,
>  };
> diff --git a/drivers/irqchip/irq-riscv-aplic-main.h b/drivers/irqchip/irq-riscv-aplic-main.h
> index 4393927d8c80..9fbf45c7b4f7 100644
> --- a/drivers/irqchip/irq-riscv-aplic-main.h
> +++ b/drivers/irqchip/irq-riscv-aplic-main.h
> @@ -28,6 +28,7 @@ struct aplic_priv {
>         u32                     gsi_base;
>         u32                     nr_irqs;
>         u32                     nr_idcs;
> +       u32                     id;

This "id" is only used for ACPI so better call it "acpi_id".

>         void __iomem            *regs;
>         struct aplic_msicfg     msicfg;
>  };
> diff --git a/drivers/irqchip/irq-riscv-aplic-msi.c b/drivers/irqchip/irq-riscv-aplic-msi.c
> index 028444af48bd..f5020241e0ed 100644
> --- a/drivers/irqchip/irq-riscv-aplic-msi.c
> +++ b/drivers/irqchip/irq-riscv-aplic-msi.c
> @@ -157,6 +157,7 @@ static const struct msi_domain_template aplic_msi_template = {
>  int aplic_msi_setup(struct device *dev, void __iomem *regs)
>  {
>         const struct imsic_global_config *imsic_global;
> +       struct irq_domain *msi_domain;
>         struct aplic_priv *priv;
>         struct aplic_msicfg *mc;
>         phys_addr_t pa;
> @@ -239,8 +240,14 @@ int aplic_msi_setup(struct device *dev, void __iomem *regs)
>                  * IMSIC and the IMSIC MSI domains are created later through
>                  * the platform driver probing so we set it explicitly here.
>                  */
> -               if (is_of_node(dev->fwnode))
> +               if (is_of_node(dev->fwnode)) {
>                         of_msi_configure(dev, to_of_node(dev->fwnode));
> +               } else {
> +                       msi_domain = irq_find_matching_fwnode(imsic_acpi_get_fwnode(dev),
> +                                                             DOMAIN_BUS_PLATFORM_MSI);
> +                       if (msi_domain)
> +                               dev_set_msi_domain(dev, msi_domain);
> +               }
>         }
>
>         if (!msi_create_device_irq_domain(dev, MSI_DEFAULT_DOMAIN, &aplic_msi_template,
> --
> 2.43.0
>

Otherwise, this looks good to me.

Reviewed-by: Anup Patel <anup@brainfault.org>

Regards,
Anup


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v7 17/17] irqchip/sifive-plic: Add ACPI support
  2024-07-29 14:22 ` [PATCH v7 17/17] irqchip/sifive-plic: " Sunil V L
@ 2024-08-06 15:59   ` Anup Patel
  0 siblings, 0 replies; 30+ messages in thread
From: Anup Patel @ 2024-08-06 15:59 UTC (permalink / raw)
  To: Sunil V L
  Cc: linux-kernel, linux-arm-kernel, linux-riscv, linux-pci,
	Catalin Marinas, Will Deacon, Palmer Dabbelt, Albert Ou,
	Rafael J . Wysocki, Len Brown, Bjorn Helgaas, Thomas Gleixner,
	Samuel Holland, Robert Moore, Conor Dooley, Andrew Jones,
	Haibo Xu, Atish Kumar Patra, Drew Fustini

On Mon, Jul 29, 2024 at 7:54 PM Sunil V L <sunilvl@ventanamicro.com> wrote:
>
> Add ACPI support in PLIC driver. Use the mapping created early during
> boot to get details about the PLIC.
>
> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
> Co-developed-by: Haibo Xu <haibo1.xu@intel.com>
> Signed-off-by: Haibo Xu <haibo1.xu@intel.com>
> ---
>  drivers/irqchip/irq-sifive-plic.c | 94 ++++++++++++++++++++++++-------
>  1 file changed, 73 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
> index 9e22f7e378f5..12d60728329c 100644
> --- a/drivers/irqchip/irq-sifive-plic.c
> +++ b/drivers/irqchip/irq-sifive-plic.c
> @@ -3,6 +3,7 @@
>   * Copyright (C) 2017 SiFive
>   * Copyright (C) 2018 Christoph Hellwig
>   */
> +#include <linux/acpi.h>
>  #include <linux/cpu.h>
>  #include <linux/interrupt.h>
>  #include <linux/io.h>
> @@ -70,6 +71,8 @@ struct plic_priv {
>         unsigned long plic_quirks;
>         unsigned int nr_irqs;
>         unsigned long *prio_save;
> +       u32 gsi_base;
> +       int id;

Same as the other patch, better to call "id" as "acpi_id".

>  };
>
>  struct plic_handler {
> @@ -324,6 +327,10 @@ static int plic_irq_domain_translate(struct irq_domain *d,
>  {
>         struct plic_priv *priv = d->host_data;
>
> +       /* For DT, gsi_base is always zero. */
> +       if (fwspec->param[0] >= priv->gsi_base)
> +               fwspec->param[0] = fwspec->param[0] - priv->gsi_base;
> +
>         if (test_bit(PLIC_QUIRK_EDGE_INTERRUPT, &priv->plic_quirks))
>                 return irq_domain_translate_twocell(d, fwspec, hwirq, type);
>
> @@ -424,18 +431,37 @@ static const struct of_device_id plic_match[] = {
>         {}
>  };
>
> +#ifdef CONFIG_ACPI
> +
> +static const struct acpi_device_id plic_acpi_match[] = {
> +       { "RSCV0001", 0 },
> +       {}
> +};
> +MODULE_DEVICE_TABLE(acpi, plic_acpi_match);
> +
> +#endif
>  static int plic_parse_nr_irqs_and_contexts(struct platform_device *pdev,
> -                                          u32 *nr_irqs, u32 *nr_contexts)
> +                                          u32 *nr_irqs, u32 *nr_contexts,
> +                                          u32 *gsi_base, u32 *id)
>  {
>         struct device *dev = &pdev->dev;
>         int rc;
>
> -       /*
> -        * Currently, only OF fwnode is supported so extend this
> -        * function for ACPI support.
> -        */
> -       if (!is_of_node(dev->fwnode))
> -               return -EINVAL;
> +       if (!is_of_node(dev->fwnode)) {
> +               rc = riscv_acpi_get_gsi_info(dev->fwnode, gsi_base, id, nr_irqs, NULL);
> +               if (rc) {
> +                       dev_err(dev, "failed to find GSI mapping\n");
> +                       return rc;
> +               }
> +
> +               *nr_contexts = acpi_get_plic_nr_contexts(*id);
> +               if (WARN_ON(!*nr_contexts)) {
> +                       dev_err(dev, "no PLIC context available\n");
> +                       return -EINVAL;
> +               }
> +
> +               return 0;
> +       }
>
>         rc = of_property_read_u32(to_of_node(dev->fwnode), "riscv,ndev", nr_irqs);
>         if (rc) {
> @@ -449,23 +475,29 @@ static int plic_parse_nr_irqs_and_contexts(struct platform_device *pdev,
>                 return -EINVAL;
>         }
>
> +       *gsi_base = 0;
> +       *id = 0;
> +
>         return 0;
>  }
>
>  static int plic_parse_context_parent(struct platform_device *pdev, u32 context,
> -                                    u32 *parent_hwirq, int *parent_cpu)
> +                                    u32 *parent_hwirq, int *parent_cpu, u32 id)
>  {
>         struct device *dev = &pdev->dev;
>         struct of_phandle_args parent;
>         unsigned long hartid;
>         int rc;
>
> -       /*
> -        * Currently, only OF fwnode is supported so extend this
> -        * function for ACPI support.
> -        */
> -       if (!is_of_node(dev->fwnode))
> -               return -EINVAL;
> +       if (!is_of_node(dev->fwnode)) {
> +               hartid = acpi_get_ext_intc_parent_hartid(id, context);
> +               if (hartid == INVALID_HARTID)
> +                       return -EINVAL;
> +
> +               *parent_cpu = riscv_hartid_to_cpuid(hartid);
> +               *parent_hwirq = RV_IRQ_EXT;
> +               return 0;
> +       }
>
>         rc = of_irq_parse_one(to_of_node(dev->fwnode), context, &parent);
>         if (rc)
> @@ -489,6 +521,8 @@ static int plic_probe(struct platform_device *pdev)
>         u32 nr_irqs, parent_hwirq;
>         struct plic_priv *priv;
>         irq_hw_number_t hwirq;
> +       int id, context_id;
> +       u32 gsi_base;
>
>         if (is_of_node(dev->fwnode)) {
>                 const struct of_device_id *id;
> @@ -498,7 +532,7 @@ static int plic_probe(struct platform_device *pdev)
>                         plic_quirks = (unsigned long)id->data;
>         }
>
> -       error = plic_parse_nr_irqs_and_contexts(pdev, &nr_irqs, &nr_contexts);
> +       error = plic_parse_nr_irqs_and_contexts(pdev, &nr_irqs, &nr_contexts, &gsi_base, &id);
>         if (error)
>                 return error;
>
> @@ -509,6 +543,8 @@ static int plic_probe(struct platform_device *pdev)
>         priv->dev = dev;
>         priv->plic_quirks = plic_quirks;
>         priv->nr_irqs = nr_irqs;
> +       priv->gsi_base = gsi_base;
> +       priv->id = id;
>
>         priv->regs = devm_platform_ioremap_resource(pdev, 0);
>         if (WARN_ON(!priv->regs))
> @@ -519,12 +555,22 @@ static int plic_probe(struct platform_device *pdev)
>                 return -ENOMEM;
>
>         for (i = 0; i < nr_contexts; i++) {
> -               error = plic_parse_context_parent(pdev, i, &parent_hwirq, &cpu);
> +               error = plic_parse_context_parent(pdev, i, &parent_hwirq, &cpu, priv->id);
>                 if (error) {
>                         dev_warn(dev, "hwirq for context%d not found\n", i);
>                         continue;
>                 }
>
> +               if (is_of_node(dev->fwnode)) {
> +                       context_id = i;
> +               } else {
> +                       context_id = acpi_get_plic_context(priv->id, i);
> +                       if (context_id == INVALID_CONTEXT) {
> +                               dev_warn(dev, "invalid context id for context%d\n", i);
> +                               continue;
> +                       }
> +               }
> +
>                 /*
>                  * Skip contexts other than external interrupts for our
>                  * privilege level.
> @@ -562,10 +608,10 @@ static int plic_probe(struct platform_device *pdev)
>                 cpumask_set_cpu(cpu, &priv->lmask);
>                 handler->present = true;
>                 handler->hart_base = priv->regs + CONTEXT_BASE +
> -                       i * CONTEXT_SIZE;
> +                       context_id * CONTEXT_SIZE;
>                 raw_spin_lock_init(&handler->enable_lock);
>                 handler->enable_base = priv->regs + CONTEXT_ENABLE_BASE +
> -                       i * CONTEXT_ENABLE_SIZE;
> +                       context_id * CONTEXT_ENABLE_SIZE;
>                 handler->priv = priv;
>
>                 handler->enable_save = devm_kcalloc(dev, DIV_ROUND_UP(nr_irqs, 32),
> @@ -581,8 +627,8 @@ static int plic_probe(struct platform_device *pdev)
>                 nr_handlers++;
>         }
>
> -       priv->irqdomain = irq_domain_add_linear(to_of_node(dev->fwnode), nr_irqs + 1,
> -                                               &plic_irqdomain_ops, priv);
> +       priv->irqdomain = irq_domain_create_linear(dev->fwnode, nr_irqs + 1,
> +                                                  &plic_irqdomain_ops, priv);
>         if (WARN_ON(!priv->irqdomain))
>                 goto fail_cleanup_contexts;
>
> @@ -619,13 +665,18 @@ static int plic_probe(struct platform_device *pdev)
>                 }
>         }
>
> +#ifdef CONFIG_ACPI
> +       if (!acpi_disabled)
> +               acpi_dev_clear_dependencies(ACPI_COMPANION(dev));
> +#endif
> +
>         dev_info(dev, "mapped %d interrupts with %d handlers for %d contexts.\n",
>                  nr_irqs, nr_handlers, nr_contexts);
>         return 0;
>
>  fail_cleanup_contexts:
>         for (i = 0; i < nr_contexts; i++) {
> -               if (plic_parse_context_parent(pdev, i, &parent_hwirq, &cpu))
> +               if (plic_parse_context_parent(pdev, i, &parent_hwirq, &cpu, priv->id))
>                         continue;
>                 if (parent_hwirq != RV_IRQ_EXT || cpu < 0)
>                         continue;
> @@ -644,6 +695,7 @@ static struct platform_driver plic_driver = {
>         .driver = {
>                 .name           = "riscv-plic",
>                 .of_match_table = plic_match,
> +               .acpi_match_table = ACPI_PTR(plic_acpi_match),
>         },
>         .probe = plic_probe,
>  };
> --
> 2.43.0
>

Otherwise, this looks good to me.

Reviewed-by: Anup Patel <anup@brainfault.org>

Regards,
Anup


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re:[PATCH v7 08/17] ACPI: pci_link: Clear the dependencies after probe
  2024-07-29 14:22 ` [PATCH v7 08/17] ACPI: pci_link: Clear the dependencies after probe Sunil V L
  2024-07-31 19:49   ` Bjorn Helgaas
@ 2025-12-01 13:07   ` huyuye
  2025-12-01 13:33     ` [PATCH " Sunil V L
  2025-12-01 14:12   ` huyuye
  2 siblings, 1 reply; 30+ messages in thread
From: huyuye @ 2025-12-01 13:07 UTC (permalink / raw)
  To: sunilvl
  Cc: ajones, anup, aou, atishp, bhelgaas, catalin.marinas,
	conor.dooley, dfustini, haibo1.xu, lenb, linux-arm-kernel,
	linux-kernel, linux-pci, linux-riscv, palmer, rafael,
	robert.moore, samuel.holland, tglx, will, dai.hualiang,
	deng.weixian, guo.chang2, liu.qingtao2, wu.jiabao, lin.yongchun,
	hu.yuye, zhang.longxiang, huyuye

Hi, sunilvl

Based on the above patch, I understand that you previously resolved dependencies between Link devices and PCI Host Bridges by calling acpi_dev_clear_dependencies(device). I would like to ask: on RISC‑V platforms, if we need to manage dependencies between multiple PCI Host Bridges, could this be addressed by adding a call to acpi_dev_clear_dependencies(device) at the end of the acpi_pci_root_add enumeration function?

Initialization order dependencies can be defined via the ACPI _DEP method in the DSDT. For example, if host bridge B depends on host bridge A, bridge B should not be enumerated until bridge A is fully initialized.

Best regards,
Yuye



^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v7 08/17] ACPI: pci_link: Clear the dependencies after probe
  2025-12-01 13:07   ` huyuye
@ 2025-12-01 13:33     ` Sunil V L
  0 siblings, 0 replies; 30+ messages in thread
From: Sunil V L @ 2025-12-01 13:33 UTC (permalink / raw)
  To: huyuye
  Cc: ajones, anup, aou, atishp, bhelgaas, catalin.marinas,
	conor.dooley, dfustini, haibo1.xu, lenb, linux-arm-kernel,
	linux-kernel, linux-pci, linux-riscv, palmer, rafael,
	robert.moore, samuel.holland, tglx, will, dai.hualiang,
	deng.weixian, guo.chang2, liu.qingtao2, wu.jiabao, lin.yongchun,
	hu.yuye, zhang.longxiang

On Mon, Dec 01, 2025 at 09:07:55PM +0800, huyuye wrote:
> Hi, sunilvl
> 
> Based on the above patch, I understand that you previously resolved dependencies between Link devices and PCI Host Bridges by calling acpi_dev_clear_dependencies(device). I would like to ask: on RISC‑V platforms, if we need to manage dependencies between multiple PCI Host Bridges, could this be addressed by adding a call to acpi_dev_clear_dependencies(device) at the end of the acpi_pci_root_add enumeration function?
> 
> Initialization order dependencies can be defined via the ACPI _DEP method in the DSDT. For example, if host bridge B depends on host bridge A, bridge B should not be enumerated until bridge A is fully initialized.
> 
Yes, that should work.

Regards,
Sunil


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re:[PATCH v7 08/17] ACPI: pci_link: Clear the dependencies after probe
  2024-07-29 14:22 ` [PATCH v7 08/17] ACPI: pci_link: Clear the dependencies after probe Sunil V L
  2024-07-31 19:49   ` Bjorn Helgaas
  2025-12-01 13:07   ` huyuye
@ 2025-12-01 14:12   ` huyuye
  2025-12-02  4:28     ` [PATCH " Sunil V L
  2 siblings, 1 reply; 30+ messages in thread
From: huyuye @ 2025-12-01 14:12 UTC (permalink / raw)
  To: sunilvl
  Cc: ajones, anup, aou, atishp, bhelgaas, catalin.marinas,
	conor.dooley, dfustini, haibo1.xu, lenb, linux-arm-kernel,
	linux-kernel, linux-pci, linux-riscv, palmer, rafael,
	robert.moore, samuel.holland, tglx, will, dai.hualiang,
	deng.weixian, guo.chang2, liu.qingtao2, wu.jiabao, lin.yongchun,
	hu.yuye, zhang.longxiang, huyuye

> Hi, sunilvl

> Based on the above patch, I understand that you previously >resolved dependencies between Link devices and PCI Host Bridges by >calling acpi_dev_clear_dependencies(device). I would like to ask: >on RISC‑V platforms, if we need to manage dependencies between >multiple PCI Host Bridges, could this be addressed by adding a >call to acpi_dev_clear_dependencies(device) at the end of the >acpi_pci_root_add enumeration function?

> Initialization order dependencies can be defined via the ACPI >_DEP method in the DSDT. For example, if host bridge B depends on >host bridge A, bridge B should not be enumerated until bridge A is >fully initialized.

> Yes, that should work.
> Regards,
> Sunil

Hi,Sunil

I'm truly honored by your affirmation of my answer.Do you think this solution has a chance of being accepted into the upstream kernel? Are there any unintended side effects we may have overlooked?

Regards,
Yuye



^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v7 08/17] ACPI: pci_link: Clear the dependencies after probe
  2025-12-01 14:12   ` huyuye
@ 2025-12-02  4:28     ` Sunil V L
  0 siblings, 0 replies; 30+ messages in thread
From: Sunil V L @ 2025-12-02  4:28 UTC (permalink / raw)
  To: huyuye
  Cc: ajones, anup, aou, atishp, bhelgaas, catalin.marinas,
	conor.dooley, dfustini, haibo1.xu, lenb, linux-arm-kernel,
	linux-kernel, linux-pci, linux-riscv, palmer, rafael,
	robert.moore, samuel.holland, tglx, will, dai.hualiang,
	deng.weixian, guo.chang2, liu.qingtao2, wu.jiabao, lin.yongchun,
	hu.yuye, zhang.longxiang

On Mon, Dec 01, 2025 at 10:12:29PM +0800, huyuye wrote:
> > Hi, sunilvl
> 
> > Based on the above patch, I understand that you previously >resolved dependencies between Link devices and PCI Host Bridges by >calling acpi_dev_clear_dependencies(device). I would like to ask: >on RISC‑V platforms, if we need to manage dependencies between >multiple PCI Host Bridges, could this be addressed by adding a >call to acpi_dev_clear_dependencies(device) at the end of the >acpi_pci_root_add enumeration function?
> 
> > Initialization order dependencies can be defined via the ACPI >_DEP method in the DSDT. For example, if host bridge B depends on >host bridge A, bridge B should not be enumerated until bridge A is >fully initialized.
> 
> > Yes, that should work.
> > Regards,
> > Sunil
> 
> Hi,Sunil
> 
> I'm truly honored by your affirmation of my answer.Do you think this solution has a chance of being accepted into the upstream kernel? Are there any unintended side effects we may have overlooked?
> 
Acceptance of this solution depends on the PCI/ACPI maintainers. To help
them evaluate it, you should clearly describe why your platform requires
this dependency in the patch.

Regards
Sunil


^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2025-12-02  4:28 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-29 14:22 [PATCH v7 00/17] RISC-V: ACPI: Add external interrupt controller support Sunil V L
2024-07-29 14:22 ` [PATCH v7 01/17] arm64: PCI: Migrate ACPI related functions to pci-acpi.c Sunil V L
2024-07-29 14:22 ` [PATCH v7 02/17] ACPI: scan: Add a weak function to reorder the IRQCHIP probe Sunil V L
2024-07-31 19:41   ` Bjorn Helgaas
2024-07-29 14:22 ` [PATCH v7 03/17] ACPI: bus: Add acpi_riscv_init function Sunil V L
2024-07-31 19:42   ` Bjorn Helgaas
2024-07-29 14:22 ` [PATCH v7 04/17] ACPI: scan: Refactor dependency creation Sunil V L
2024-07-29 14:22 ` [PATCH v7 05/17] ACPI: scan: Add RISC-V interrupt controllers to honor list Sunil V L
2024-07-29 14:22 ` [PATCH v7 06/17] ACPI: scan: Define weak function to populate dependencies Sunil V L
2024-07-29 14:22 ` [PATCH v7 07/17] ACPI: bus: Add RINTC IRQ model for RISC-V Sunil V L
2024-07-29 14:22 ` [PATCH v7 08/17] ACPI: pci_link: Clear the dependencies after probe Sunil V L
2024-07-31 19:49   ` Bjorn Helgaas
2025-12-01 13:07   ` huyuye
2025-12-01 13:33     ` [PATCH " Sunil V L
2025-12-01 14:12   ` huyuye
2025-12-02  4:28     ` [PATCH " Sunil V L
2024-07-29 14:22 ` [PATCH v7 09/17] ACPI: RISC-V: Implement PCI related functionality Sunil V L
2024-07-29 14:22 ` [PATCH v7 10/17] ACPI: RISC-V: Implement function to reorder irqchip probe entries Sunil V L
2024-07-29 14:22 ` [PATCH v7 11/17] ACPI: RISC-V: Initialize GSI mapping structures Sunil V L
2024-07-29 14:22 ` [PATCH v7 12/17] ACPI: RISC-V: Implement function to add implicit dependencies Sunil V L
2024-07-29 14:22 ` [PATCH v7 13/17] irqchip/riscv-intc: Add ACPI support for AIA Sunil V L
2024-08-06 15:22   ` Anup Patel
2024-07-29 14:22 ` [PATCH v7 14/17] irqchip/riscv-imsic-state: Create separate function for DT Sunil V L
2024-08-06 15:25   ` Anup Patel
2024-07-29 14:22 ` [PATCH v7 15/17] irqchip/riscv-imsic: Add ACPI support Sunil V L
2024-08-06 15:30   ` Anup Patel
2024-07-29 14:22 ` [PATCH v7 16/17] irqchip/riscv-aplic: " Sunil V L
2024-08-06 15:54   ` Anup Patel
2024-07-29 14:22 ` [PATCH v7 17/17] irqchip/sifive-plic: " Sunil V L
2024-08-06 15:59   ` Anup Patel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).