2023-12-19 17:45:50

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 00/17] RISC-V: ACPI: Add external interrupt controller support

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) Introduced support for fw_devlink for ACPI nodes for IRQ dependency.
This helps to support deferred probe of interrupt controller drivers.

3) Modified pnp_irq() to try registering the IRQ again if it sees it in
disabled state. This solution is similar to how
platform_get_irq_optional() works for regular platform devices.

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

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

This series is based on Anup's AIA v11 series. Since Anup's AIA v11 is
not merged yet and first time introducing fw_devlink, deferred probe and
reordering support for IRQCHIP probe, this series is still kept as RFC.
Looking forward for the feedback!

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 riscv_acpi_b2_v8 branch at
https://github.com/vlsunil/qemu.git

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

3) Build Linux using this series on top of Anup's AIA v11 series.

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=ttyS0 rootwait earlycon=uart8250,mmio,0x10000000"

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

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

Based-on: [email protected]
(https://lore.kernel.org/lkml/[email protected]/)

Sunil V L (17):
arm64: PCI: Migrate ACPI related functions to pci-acpi.c
RISC-V: ACPI: Implement PCI related functionality
PCI: Make pci_create_root_bus() declare its reliance on MSI domains
ACPI: Add fw_devlink support for ACPI fwnode for IRQ dependency
ACPI: irq: Add support for deferred probe in acpi_register_gsi()
pnp.h: Reconfigure IRQ in pnp_irq() to support deferred probe
ACPI: scan.c: Add weak arch specific function to reorder the IRQCHIP
probe
ACPI: RISC-V: Implement arch function to reorder irqchip probe entries
irqchip: riscv-intc: Add ACPI support for AIA
irqchip: riscv-imsic: Add ACPI support
irqchip: riscv-aplic: Add ACPI support
irqchip: irq-sifive-plic: Add ACPI support
ACPI: bus: Add RINTC IRQ model for RISC-V
ACPI: bus: Add acpi_riscv_init function
ACPI: RISC-V: Create APLIC platform device
ACPI: RISC-V: Create PLIC platform device
irqchip: riscv-intc: Set ACPI irqmodel

arch/arm64/kernel/pci.c | 191 ---------------------
arch/riscv/Kconfig | 2 +
arch/riscv/include/asm/irq.h | 46 +++++
arch/riscv/kernel/acpi.c | 31 ++--
drivers/acpi/bus.c | 4 +
drivers/acpi/irq.c | 22 +++
drivers/acpi/property.c | 20 +++
drivers/acpi/riscv/Makefile | 2 +-
drivers/acpi/riscv/init.c | 15 ++
drivers/acpi/riscv/init.h | 6 +
drivers/acpi/riscv/irq.c | 169 ++++++++++++++++++
drivers/acpi/scan.c | 3 +
drivers/irqchip/irq-riscv-aplic-direct.c | 21 ++-
drivers/irqchip/irq-riscv-aplic-main.c | 64 ++++---
drivers/irqchip/irq-riscv-aplic-main.h | 1 +
drivers/irqchip/irq-riscv-aplic-msi.c | 9 +-
drivers/irqchip/irq-riscv-imsic-early.c | 52 +++++-
drivers/irqchip/irq-riscv-imsic-platform.c | 51 ++++--
drivers/irqchip/irq-riscv-imsic-state.c | 128 +++++++-------
drivers/irqchip/irq-riscv-imsic-state.h | 2 +-
drivers/irqchip/irq-riscv-intc.c | 96 ++++++++++-
drivers/irqchip/irq-sifive-plic.c | 76 ++++++--
drivers/pci/pci-acpi.c | 182 ++++++++++++++++++++
drivers/pci/probe.c | 1 +
drivers/pnp/pnpacpi/core.c | 7 +
include/linux/acpi.h | 18 ++
include/linux/irqchip/riscv-imsic.h | 10 ++
include/linux/pnp.h | 14 +-
28 files changed, 895 insertions(+), 348 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.39.2



2023-12-19 17:46:37

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 02/17] RISC-V: ACPI: Implement PCI related functionality

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 <[email protected]>
---
arch/riscv/Kconfig | 2 ++
arch/riscv/kernel/acpi.c | 31 ++++++++++++++-----------------
drivers/pci/pci-acpi.c | 2 +-
3 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 45c660f1219d..d939fff5b5b1 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_REDUCED_HARDWARE_ONLY if ACPI
select ARCH_DMA_DEFAULT_COHERENT
select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION
@@ -151,6 +152,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 56cb2c986c48..b7bf1678241a 100644
--- a/arch/riscv/kernel/acpi.c
+++ b/arch/riscv/kernel/acpi.c
@@ -223,29 +223,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);

-int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
- int reg, int len, u32 val)
-{
- return PCIBIOS_DEVICE_NOT_FOUND;
+ if (!b)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ return b->ops->read(b, devfn, reg, len, val);
}

-int acpi_pci_bus_find_domain_nr(struct pci_bus *bus)
+int raw_pci_write(unsigned int domain, unsigned int bus,
+ unsigned int devfn, int reg, int len, u32 val)
{
- return -1;
-}
+ struct pci_bus *b = pci_find_bus(domain, bus);

-struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
-{
- return NULL;
+ if (!b)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ return b->ops->write(b, devfn, reg, len, val);
}
+
#endif /* CONFIG_PCI */
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 58497b25d2ab..c8c3369fd69f 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -1520,7 +1520,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.39.2


2023-12-19 17:46:55

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 01/17] arm64: PCI: Migrate ACPI related functions to pci-acpi.c

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 <[email protected]>
Acked-by: Bjorn Helgaas <[email protected]>
---
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 a05350a4e49c..58497b25d2ab 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>
@@ -1518,3 +1519,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.39.2


2023-12-19 17:46:57

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 03/17] PCI: Make pci_create_root_bus() declare its reliance on MSI domains

Similar to [1], declare this dependency for PCI probe in ACPI based
flow.

This is required especially for RISC-V platforms where MSI controller
can be absent.

[1] - https://lore.kernel.org/all/[email protected]/

Signed-off-by: Sunil V L <[email protected]>
---
drivers/pci/probe.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 795534589b98..9e941cf55d87 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -3054,6 +3054,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
bridge->sysdata = sysdata;
bridge->busnr = bus;
bridge->ops = ops;
+ bridge->msi_domain = true;

error = pci_register_host_bridge(bridge);
if (error < 0)
--
2.39.2


2023-12-19 17:47:29

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 04/17] ACPI: Add fw_devlink support for ACPI fwnode for IRQ dependency

Currently ACPI doesn't support fw_devlink infrastructure which helps in
ordering the driver probe in the order of dependencies. One of the
dependency between devices in ACPI is GSI interrupt source. This
interrupt source can be another device and mentioned as part of
ResourceSource in the ASL. Or it can be indirectly determined by the GSI
mapping. In either way, adding the link for this dependency avoids
modifying all drivers to handle EPROBE_DEFER. So, add this new interface
into ACPI's fwnode handlers.

Currently, this is necessary for RISC-V architecture. So, kept the
interface functional only for RISC-V. But in future other architectures
also can enable this functionality or can be made common.

Signed-off-by: Sunil V L <[email protected]>
---
drivers/acpi/irq.c | 18 ++++++++++++++++++
drivers/acpi/property.c | 20 ++++++++++++++++++++
include/linux/acpi.h | 9 +++++++++
3 files changed, 47 insertions(+)

diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index 1687483ff319..b3409e2e2041 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -354,3 +354,21 @@ struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
host_data);
}
EXPORT_SYMBOL_GPL(acpi_irq_create_hierarchy);
+
+int acpi_get_gsi_parent_fwnode(acpi_handle handle,
+ unsigned int index,
+ struct fwnode_handle **parent)
+{
+ struct irq_fwspec fwspec;
+ unsigned long flags;
+ int rc;
+
+ fwspec.fwnode = NULL;
+ rc = acpi_irq_parse_one(handle, index, &fwspec, &flags);
+ if (rc || !fwspec.fwnode)
+ return 0;
+
+ *parent = fwspec.fwnode;
+ return 1;
+}
+EXPORT_SYMBOL_GPL(acpi_get_gsi_parent_fwnode);
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 413e4fcadcaf..88769acb13d4 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -1572,6 +1572,25 @@ static int acpi_fwnode_irq_get(const struct fwnode_handle *fwnode,
return res.start;
}

+static int acpi_fwnode_add_links(struct fwnode_handle *fwnode)
+{
+ struct fwnode_handle *parent_fwnode;
+ unsigned int i;
+
+ /* This is needed primarily for RISC-V. Other architectures can
+ * be enabled or made this generic if required.
+ */
+ if (!IS_ENABLED(CONFIG_RISCV))
+ return 0;
+
+ for (i = 0;
+ acpi_get_gsi_parent_fwnode(ACPI_HANDLE_FWNODE(fwnode), i, &parent_fwnode);
+ i++)
+ fwnode_link_add(fwnode, parent_fwnode);
+
+ return 0;
+}
+
#define DECLARE_ACPI_FWNODE_OPS(ops) \
const struct fwnode_operations ops = { \
.device_is_available = acpi_fwnode_device_is_available, \
@@ -1597,6 +1616,7 @@ static int acpi_fwnode_irq_get(const struct fwnode_handle *fwnode,
.graph_get_port_parent = acpi_fwnode_get_parent, \
.graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint, \
.irq_get = acpi_fwnode_irq_get, \
+ .add_links = acpi_fwnode_add_links, \
}; \
EXPORT_SYMBOL_GPL(ops)

diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index afd94c9b8b8a..e9a9659314f2 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -1463,12 +1463,21 @@ static inline int acpi_parse_spcr(bool enable_earlycon, bool enable_console)

#if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI)
int acpi_irq_get(acpi_handle handle, unsigned int index, struct resource *res);
+int acpi_get_gsi_parent_fwnode(acpi_handle handle, unsigned int index,
+ struct fwnode_handle **parent);
#else
static inline
int acpi_irq_get(acpi_handle handle, unsigned int index, struct resource *res)
{
return -EINVAL;
}
+
+static inline
+int acpi_get_gsi_parent_fwnode(acpi_handle handle, unsigned int index,
+ struct fwnode_handle **parent)
+{
+ return 0;
+}
#endif

#ifdef CONFIG_ACPI_LPIT
--
2.39.2


2023-12-19 17:47:44

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 05/17] ACPI: irq: Add support for deferred probe in acpi_register_gsi()

The chip which provides the GSI support may not be initialized at the
time of acpi_register_gsi(). Return -EPROBE_DEFER to support deferred
probing similar to acpi_irq_get().

This is required to support ResourceSource as supported by ACPI spec for
Interrupt resource.

Signed-off-by: Sunil V L <[email protected]>
---
drivers/acpi/irq.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index b3409e2e2041..c4605fdcda77 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -52,6 +52,7 @@ EXPORT_SYMBOL_GPL(acpi_gsi_to_irq);
*
* Returns: a valid linux IRQ number on success
* -EINVAL on failure
+ * -EPROBE_DEFER if irqdomain not created yet
*/
int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
int polarity)
@@ -65,6 +66,9 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger,
return -EINVAL;
}

+ if (!irq_find_matching_fwnode(fwspec.fwnode, DOMAIN_BUS_ANY))
+ return -EPROBE_DEFER;
+
fwspec.param[0] = gsi;
fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
fwspec.param_count = 2;
--
2.39.2


2023-12-19 17:48:02

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 06/17] pnp.h: Reconfigure IRQ in pnp_irq() to support deferred probe

PNP devices add the IRQ resources to PNP data structure early during
boot from ACPI resource structure. As part of this, the Interrupt
resource (GSI) are registered and appropriate linux IRQ is saved
directly in PNP data structure while creating PNP devices. But at this
time, the interrupt controller for the GSI (either via GSI vector
mapping or via ResourceSource in Interrupt()) may not be probed and
initialized. Hence, the IRQ number in PNP data structure may not be the
linux IRQ number. When the actual driver for the PNP device get probed,
it will get incorrect linux IRQ number.

Fix this issue similar to how platform devices handle this. Basically,
while creating PNP devices, the hwirq number is saved in PNP device and
marked as disabled since acpi_register_gsi() would have failed. When the
actual driver calls pnp_irq(), get the linux IRQ number again if the IRQ
is disabled.

Signed-off-by: Sunil V L <[email protected]>
---
drivers/pnp/pnpacpi/core.c | 7 +++++++
include/linux/pnp.h | 14 ++++++++++++--
2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 6ab272c84b7b..239355977d4c 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -326,3 +326,10 @@ static int __init pnpacpi_setup(char *str)
}

__setup("pnpacpi=", pnpacpi_setup);
+
+void pnpacpi_reconfigure_irq(struct pnp_dev *dev, unsigned int index, struct resource *res)
+{
+ if (has_acpi_companion(&dev->dev))
+ acpi_irq_get(ACPI_HANDLE(&dev->dev), index, res);
+}
+EXPORT_SYMBOL(pnpacpi_reconfigure_irq);
diff --git a/include/linux/pnp.h b/include/linux/pnp.h
index c2a7cfbca713..8753eb4275b0 100644
--- a/include/linux/pnp.h
+++ b/include/linux/pnp.h
@@ -26,6 +26,7 @@ struct pnp_dev;
#ifdef CONFIG_PNP
struct resource *pnp_get_resource(struct pnp_dev *dev, unsigned long type,
unsigned int num);
+
#else
static inline struct resource *pnp_get_resource(struct pnp_dev *dev,
unsigned long type, unsigned int num)
@@ -146,13 +147,22 @@ static inline resource_size_t pnp_mem_len(struct pnp_dev *dev,
return 0;
}

+#ifdef CONFIG_PNPACPI
+void pnpacpi_reconfigure_irq(struct pnp_dev *dev, unsigned int index, struct resource *res);
+#endif

-static inline resource_size_t pnp_irq(struct pnp_dev *dev, unsigned int bar)
+static inline int pnp_irq(struct pnp_dev *dev, unsigned int bar)
{
struct resource *res = pnp_get_resource(dev, IORESOURCE_IRQ, bar);

- if (pnp_resource_valid(res))
+ if (pnp_resource_valid(res)) {
+#ifdef CONFIG_PNPACPI
+ if (!pnp_resource_enabled(res))
+ pnpacpi_reconfigure_irq(dev, bar, res);
+#endif
return res->start;
+ }
+
return -1;
}

--
2.39.2


2023-12-19 17:48:24

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 07/17] ACPI: scan.c: Add weak arch specific function to reorder the IRQCHIP probe

Unlike OF framework, the irqchip probe using IRQCHIP_ACPI_DECLARE has no
order defined. Depending on the driver 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 <[email protected]>
---
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 691d4b7686ee..87f4baebd497 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2685,6 +2685,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;
@@ -2693,6 +2695,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 e9a9659314f2..ae045e14126b 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -1338,6 +1338,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.39.2


2023-12-19 17:48:45

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 08/17] ACPI: RISC-V: Implement arch function to reorder irqchip probe entries

ACPI MADT entries for interrupt controllers don't have a way to describe
the hierarchy. However, the hierarchy is known to the architecture and
on RISC-V platforms, the MADT sub table types are ordered in the
incremental order from the root controller which is RINTC. So, add
architecture function for RISC-V to reorder the interrupt controller
probing as per the hierarchy as below.

RINTC->IMSIC->APLIC->PLIC

Signed-off-by: Sunil V L <[email protected]>
---
drivers/acpi/riscv/Makefile | 2 +-
drivers/acpi/riscv/irq.c | 32 ++++++++++++++++++++++++++++++++
2 files changed, 33 insertions(+), 1 deletion(-)
create mode 100644 drivers/acpi/riscv/irq.c

diff --git a/drivers/acpi/riscv/Makefile b/drivers/acpi/riscv/Makefile
index 8b3b126e0b94..f80b3da230e9 100644
--- a/drivers/acpi/riscv/Makefile
+++ b/drivers/acpi/riscv/Makefile
@@ -1,2 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-y += rhct.o
+obj-y += rhct.o irq.o
diff --git a/drivers/acpi/riscv/irq.c b/drivers/acpi/riscv/irq.c
new file mode 100644
index 000000000000..36e0525b3235
--- /dev/null
+++ b/drivers/acpi/riscv/irq.c
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023, Ventana Micro Systems Inc
+ * Author: Sunil V L <[email protected]>
+ *
+ */
+
+#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);
+}
+
+/*
+ * RISC-V irqchips in MADT of ACPI spec are defined in the same order how
+ * they should be probed. Since IRQCHIP_ACPI_DECLARE doesn't define any
+ * order, this arch function will reorder the probe functions as per the
+ * required order for the architecture.
+ */
+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.39.2


2023-12-19 17:49:20

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 09/17] irqchip: riscv-intc: Add ACPI support for AIA

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 <[email protected]>
---
arch/riscv/include/asm/irq.h | 45 +++++++++++++++
drivers/irqchip/irq-riscv-intc.c | 95 +++++++++++++++++++++++++++++++-
2 files changed, 139 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h
index 8e10a94430a2..232314e5f007 100644
--- a/arch/riscv/include/asm/irq.h
+++ b/arch/riscv/include/asm/irq.h
@@ -12,8 +12,53 @@

#include <asm-generic/irq.h>

+#ifdef CONFIG_ACPI
+
+/*
+ * The ext_intc_id format is as follows:
+ * Bits [31:24] APLIC/PLIC ID
+ * Bits [15:0] APLIC IDC ID / PLIC S-Mode Context ID for this hart
+ */
+#define APLIC_PLIC_ID(x) ((x) >> 24)
+#define IDC_CONTEXT_ID(x) ((x) & 0x0000ffff)
+
+int __init acpi_get_intc_index_hartid(u32 index, unsigned long *hartid);
+int acpi_get_ext_intc_parent_hartid(u8 id, u32 idx, unsigned long *hartid);
+void acpi_get_plic_nr_contexts(u8 id, int *nr_contexts);
+int acpi_get_plic_context(u8 id, u32 idx, int *context_id);
+int __init acpi_get_imsic_mmio_info(u32 index, struct resource *res);
+
+#else
+static inline struct fwnode_handle *ext_entc_get_gsi_domain_id(u32 gsi)
+{
+ return NULL;
+}
+
+static inline int __init acpi_get_intc_index_hartid(u32 index, unsigned long *hartid)
+{
+ return -EINVAL;
+}
+
+static inline int acpi_get_ext_intc_parent_hartid(u8 id, u32 idx, unsigned long *hartid)
+{
+ return -EINVAL;
+}
+
+static inline void acpi_get_plic_nr_contexts(u8 id, int *nr_contexts) { }
+static inline int acpi_get_plic_context(u8 id, u32 idx, int *context_id)
+{
+ return -EINVAL;
+}
+
+static inline int __init acpi_get_imsic_mmio_info(u32 index, struct resource *res)
+{
+ return -EINVAL;
+}
+#endif
+
void riscv_set_intc_hwnode_fn(struct fwnode_handle *(*fn)(void));

struct fwnode_handle *riscv_get_intc_hwnode(void);
+int acpi_imsic_probe(struct fwnode_handle *parent);

#endif /* _ASM_RISCV_IRQ_H */
diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c
index bab536bbaf2c..24bbc5bfc30f 100644
--- a/drivers/irqchip/irq-riscv-intc.c
+++ b/drivers/irqchip/irq-riscv-intc.c
@@ -195,13 +195,100 @@ IRQCHIP_DECLARE(riscv, "riscv,cpu-intc", riscv_intc_init);

#ifdef CONFIG_ACPI

+struct rintc_data {
+ u32 ext_intc_id;
+ unsigned long hart_id;
+ u64 imsic_addr;
+ u32 imsic_size;
+};
+
+static u32 nr_rintc;
+static struct rintc_data *rintc_acpi_data[NR_CPUS];
+
+int acpi_get_intc_index_hartid(u32 index, unsigned long *hartid)
+{
+ if (index >= nr_rintc)
+ return -1;
+
+ *hartid = rintc_acpi_data[index]->hart_id;
+ return 0;
+}
+
+int acpi_get_ext_intc_parent_hartid(u8 id, u32 idx, unsigned long *hartid)
+{
+ int i, j = 0;
+
+ for (i = 0; i < nr_rintc; i++) {
+ if (APLIC_PLIC_ID(rintc_acpi_data[i]->ext_intc_id) == id) {
+ if (idx == j) {
+ *hartid = rintc_acpi_data[i]->hart_id;
+ return 0;
+ }
+ j++;
+ }
+ }
+
+ return -1;
+}
+
+void acpi_get_plic_nr_contexts(u8 id, int *nr_contexts)
+{
+ int i, j = 0;
+
+ for (i = 0; i < nr_rintc; i++) {
+ if (APLIC_PLIC_ID(rintc_acpi_data[i]->ext_intc_id) == id)
+ j++;
+ }
+
+ *nr_contexts = j;
+}
+
+int acpi_get_plic_context(u8 id, u32 idx, int *context_id)
+{
+ int i, j = 0;
+
+ for (i = 0; i < nr_rintc; i++) {
+ if (APLIC_PLIC_ID(rintc_acpi_data[i]->ext_intc_id) == id) {
+ if (idx == j) {
+ *context_id = IDC_CONTEXT_ID(rintc_acpi_data[i]->ext_intc_id);
+ return 0;
+ }
+
+ j++;
+ }
+ }
+
+ return -1;
+}
+
+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)
{
struct fwnode_handle *fn;
struct acpi_madt_rintc *rintc;
+ 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)
@@ -218,7 +305,13 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
return -ENOMEM;
}

- return riscv_intc_init_common(fn);
+ rc = riscv_intc_init_common(fn);
+ if (rc) {
+ irq_domain_free_fwnode(fn);
+ return rc;
+ }
+
+ return 0;
}

IRQCHIP_ACPI_DECLARE(riscv_intc, ACPI_MADT_TYPE_RINTC, NULL,
--
2.39.2


2023-12-19 17:49:51

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 10/17] irqchip: riscv-imsic: Add ACPI support

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
scan happens early during boot and PCI subsystem expects MSI controller
is already setup. Hence, in case of ACPI, both IPI and MSI features
are initialized early itself.

Signed-off-by: Sunil V L <[email protected]>
---
drivers/irqchip/irq-riscv-imsic-early.c | 52 ++++++++-
drivers/irqchip/irq-riscv-imsic-platform.c | 51 +++++---
drivers/irqchip/irq-riscv-imsic-state.c | 128 ++++++++++-----------
drivers/irqchip/irq-riscv-imsic-state.h | 2 +-
include/linux/irqchip/riscv-imsic.h | 10 ++
5 files changed, 160 insertions(+), 83 deletions(-)

diff --git a/drivers/irqchip/irq-riscv-imsic-early.c b/drivers/irqchip/irq-riscv-imsic-early.c
index 23f689ff5807..866e97559e4c 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>

@@ -216,7 +219,7 @@ static int __init imsic_early_dt_init(struct device_node *node,
struct fwnode_handle *fwnode = &node->fwnode;

/* 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);
@@ -233,3 +236,50 @@ static int __init imsic_early_dt_init(struct device_node *node,
return 0;
}
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, (void *)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)
+ 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
+
+ return rc;
+}
+
+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 cdb659401199..f905340d24e6 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>
@@ -308,43 +309,47 @@ static int imsic_irq_domains_init(struct fwnode_handle *fwnode)
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;
struct imsic_global_config *global;
int rc;

if (!imsic) {
- dev_err(dev, "early driver not probed\n");
+ pr_err("%pfwP: early driver not probed\n", fwnode);
return -ENODEV;
}

if (imsic->base_domain) {
- dev_err(dev, "irq domain already created\n");
+ pr_err("%pfwP: irq domain already created\n", fwnode);
return -ENODEV;
}

global = &imsic->global;

/* Initialize IRQ and MSI domains */
- rc = imsic_irq_domains_init(dev->fwnode);
+ rc = imsic_irq_domains_init(fwnode);
if (rc) {
- dev_err(dev, "failed to initialize IRQ and MSI domains\n");
+ pr_err("%pfwP: failed to initialize IRQ and MSI domains\n", fwnode);
return rc;
}

- dev_info(dev, " hart-index-bits: %d, guest-index-bits: %d\n",
- global->hart_index_bits, global->guest_index_bits);
- dev_info(dev, " group-index-bits: %d, group-index-shift: %d\n",
- global->group_index_bits, global->group_index_shift);
- dev_info(dev, " per-CPU IDs %d at base PPN %pa\n",
- global->nr_ids, &global->base_addr);
- dev_info(dev, " total %d interrupts available\n",
- imsic->nr_hwirqs);
+ pr_info("%pfwP: hart-index-bits: %d, guest-index-bits: %d\n", fwnode,
+ global->hart_index_bits, global->guest_index_bits);
+ pr_info("%pfwP: group-index-bits: %d, group-index-shift: %d\n", fwnode,
+ global->group_index_bits, global->group_index_shift);
+ pr_info("%pfwP: per-CPU IDs %d at base PPN %pa\n", fwnode,
+ global->nr_ids, &global->base_addr);
+ pr_info("%pfwP: total %d interrupts available\n", fwnode,
+ imsic->nr_hwirqs);

return 0;
}

+static int imsic_platform_dt_probe(struct platform_device *pdev)
+{
+ return imsic_platform_probe_common(pdev->dev.fwnode);
+}
+
static const struct of_device_id imsic_platform_match[] = {
{ .compatible = "riscv,imsics" },
{}
@@ -355,6 +360,22 @@ 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);
+
+#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
diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
index 54465e47851c..b842c499df0a 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>
@@ -593,12 +594,8 @@ static int __init imsic_get_parent_hartid(struct fwnode_handle *fwnode,
int rc;
struct of_phandle_args parent;

- /*
- * Currently, only OF fwnode is supported so extend this
- * function for ACPI support.
- */
if (!is_of_node(fwnode))
- return -EINVAL;
+ return acpi_get_intc_index_hartid(index, hartid);

rc = of_irq_parse_one(to_of_node(fwnode), index, &parent);
if (rc)
@@ -617,12 +614,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);
}
@@ -630,20 +623,15 @@ 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)
{
+ struct acpi_madt_imsic *imsic = (struct acpi_madt_imsic *)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;

@@ -656,58 +644,66 @@ 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);
- if (rc)
- global->guest_index_bits = 0;
+ if (is_of_node(fwnode)) {
+ /* 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 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 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 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 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;
+ } else {
+ 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;
}

- /* 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;
if (i < global->guest_index_bits) {
@@ -775,7 +771,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)
{
int rc, cpu;
phys_addr_t base_addr;
@@ -817,7 +813,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 8d209e77432e..ee1f52891e89 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.h
+++ b/drivers/irqchip/irq-riscv-imsic-state.h
@@ -105,6 +105,6 @@ void imsic_vector_debug_show_summary(struct seq_file *m, int ind);
int imsic_hwirqs_alloc(unsigned int order);
void imsic_hwirqs_free(unsigned int base_hwirq, unsigned int order);

-int imsic_setup_state(struct fwnode_handle *fwnode);
+int imsic_setup_state(struct fwnode_handle *fwnode, void *opaque);

#endif
diff --git a/include/linux/irqchip/riscv-imsic.h b/include/linux/irqchip/riscv-imsic.h
index cbb7bcd0e4dd..c112e5559d88 100644
--- a/include/linux/irqchip/riscv-imsic.h
+++ b/include/linux/irqchip/riscv-imsic.h
@@ -84,4 +84,14 @@ 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.39.2


2023-12-19 17:50:19

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 11/17] irqchip: riscv-aplic: Add ACPI support

Add ACPI support in APLIC drivers. In ACPI, IO devices use Global System
Interrupts (GSI) which is a flat space split across multiple APLICs.

Signed-off-by: Sunil V L <[email protected]>
---
arch/riscv/include/asm/irq.h | 6 +++
drivers/irqchip/irq-riscv-aplic-direct.c | 21 +++++---
drivers/irqchip/irq-riscv-aplic-main.c | 64 ++++++++++++++----------
drivers/irqchip/irq-riscv-aplic-main.h | 1 +
drivers/irqchip/irq-riscv-aplic-msi.c | 9 +++-
5 files changed, 66 insertions(+), 35 deletions(-)

diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h
index 232314e5f007..df59192a157d 100644
--- a/arch/riscv/include/asm/irq.h
+++ b/arch/riscv/include/asm/irq.h
@@ -22,6 +22,12 @@
#define APLIC_PLIC_ID(x) ((x) >> 24)
#define IDC_CONTEXT_ID(x) ((x) & 0x0000ffff)

+#ifdef CONFIG_RISCV_APLIC
+struct fwnode_handle *aplic_get_gsi_domain_id(u32 gsi);
+#else
+static inline struct fwnode_handle *aplic_get_gsi_domain_id(u32 gsi) { return NULL; }
+#endif
+
int __init acpi_get_intc_index_hartid(u32 index, unsigned long *hartid);
int acpi_get_ext_intc_parent_hartid(u8 id, u32 idx, unsigned long *hartid);
void acpi_get_plic_nr_contexts(u8 id, int *nr_contexts);
diff --git a/drivers/irqchip/irq-riscv-aplic-direct.c b/drivers/irqchip/irq-riscv-aplic-direct.c
index 9ed2666bfb5e..3e7a7e092120 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/bitops.h>
#include <linux/cpu.h>
#include <linux/interrupt.h>
@@ -14,6 +15,7 @@
#include <linux/of_address.h>
#include <linux/printk.h>
#include <linux/smp.h>
+#include <asm/acpi.h>

#include "irq-riscv-aplic-main.h"

@@ -203,17 +205,20 @@ 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)
+ unsigned long *parent_hartid,
+ struct aplic_priv *priv)
{
struct of_phandle_args parent;
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 = acpi_get_ext_intc_parent_hartid(priv->id, index, parent_hartid);
+ if (rc)
+ return rc;
+
+ *parent_hwirq = RV_IRQ_EXT;
+ return 0;
+ }

rc = of_irq_parse_one(to_of_node(dev->fwnode), index, &parent);
if (rc)
@@ -251,7 +256,7 @@ int aplic_direct_setup(struct device *dev, void __iomem *regs)

/* Setup per-CPU IDC and target CPU mask */
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 d1b342b66551..31434b3ff690 100644
--- a/drivers/irqchip/irq-riscv-aplic-main.c
+++ b/drivers/irqchip/irq-riscv-aplic-main.c
@@ -4,12 +4,15 @@
* Copyright (C) 2022 Ventana Micro Systems Inc.
*/

+#include <linux/acpi.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/printk.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/irqchip/riscv-aplic.h>
+#include <linux/irqchip/riscv-imsic.h>
+#include <asm/acpi.h>

#include "irq-riscv-aplic-main.h"

@@ -137,38 +140,44 @@ int aplic_setup_priv(struct aplic_priv *priv, struct device *dev,
void __iomem *regs)
{
struct of_phandle_args parent;
+ struct acpi_madt_aplic *aplic;
int rc;

- /*
- * Currently, only OF fwnode is supported so extend this
- * function for ACPI support.
- */
- if (!is_of_node(dev->fwnode))
- 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(to_of_node(dev->fwnode),
- "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(to_of_node(dev->fwnode), "msi-parent")) {
- while (!of_irq_parse_one(to_of_node(dev->fwnode),
- priv->nr_idcs, &parent))
- priv->nr_idcs++;
+ if (is_of_node(dev->fwnode)) {
+ /* Find out number of interrupt sources */
+ rc = of_property_read_u32(to_of_node(dev->fwnode),
+ "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(to_of_node(dev->fwnode), "msi-parent")) {
+ while (!of_irq_parse_one(to_of_node(dev->fwnode),
+ priv->nr_idcs, &parent))
+ priv->nr_idcs++;
+ }
+ } else {
+ aplic = *(struct acpi_madt_aplic **)dev_get_platdata(dev);
+ if (!aplic) {
+ dev_err(dev, "APLIC platform data is NULL!\n");
+ return -1;
+ }
+ priv->gsi_base = aplic->gsi_base;
+ priv->nr_irqs = aplic->num_sources;
+ priv->nr_idcs = aplic->num_idcs;
+ priv->id = aplic->id;
}

/* Setup initial state APLIC interrupts */
@@ -204,6 +213,9 @@ static int aplic_probe(struct platform_device *pdev)
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
diff --git a/drivers/irqchip/irq-riscv-aplic-main.h b/drivers/irqchip/irq-riscv-aplic-main.h
index 78267ec58098..dc022e89bc97 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 086d00e0429e..03a8ac6554c4 100644
--- a/drivers/irqchip/irq-riscv-aplic-msi.c
+++ b/drivers/irqchip/irq-riscv-aplic-msi.c
@@ -178,6 +178,7 @@ static void aplic_msi_write_msg(struct msi_desc *desc, struct msi_msg *msg)
int aplic_msi_setup(struct device *dev, void __iomem *regs)
{
const struct imsic_global_config *imsic_global;
+ struct irq_domain *msi_domain;
struct irq_domain *irqdomain;
struct aplic_priv *priv;
struct aplic_msicfg *mc;
@@ -261,8 +262,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);
+ }
}

/* Create irq domain instance for the APLIC MSI-mode */
--
2.39.2


2023-12-19 17:51:14

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 13/17] ACPI: bus: Add RINTC IRQ model for RISC-V

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 <[email protected]>
---
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 a4aa53b7e2bb..9eace6c7042e 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -1158,6 +1158,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 ae045e14126b..b6766bded765 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -95,6 +95,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.39.2


2023-12-19 17:51:53

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 15/17] ACPI: RISC-V: Create APLIC platform device

Since APLIC needs to be a platform device, probe the MADT and create
platform devices for each APLIC in the system.

Signed-off-by: Sunil V L <[email protected]>
---
drivers/acpi/riscv/init.c | 2 +
drivers/acpi/riscv/init.h | 5 ++
drivers/acpi/riscv/irq.c | 118 ++++++++++++++++++++++++++++++++++++++
3 files changed, 125 insertions(+)
create mode 100644 drivers/acpi/riscv/init.h

diff --git a/drivers/acpi/riscv/init.c b/drivers/acpi/riscv/init.c
index b5807bbdb171..e7eff7ab1474 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_aplic_platform_init();
}
diff --git a/drivers/acpi/riscv/init.h b/drivers/acpi/riscv/init.h
new file mode 100644
index 000000000000..17bcf0baaadb
--- /dev/null
+++ b/drivers/acpi/riscv/init.h
@@ -0,0 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include <linux/init.h>
+
+void __init riscv_acpi_imsic_platform_init(void);
+void __init riscv_acpi_aplic_platform_init(void);
diff --git a/drivers/acpi/riscv/irq.c b/drivers/acpi/riscv/irq.c
index 36e0525b3235..d08a851ab6dc 100644
--- a/drivers/acpi/riscv/irq.c
+++ b/drivers/acpi/riscv/irq.c
@@ -6,7 +6,36 @@
*/

#include <linux/acpi.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/platform_device.h>
#include <linux/sort.h>
+#include "init.h"
+
+static LIST_HEAD(ext_intc_list);
+
+struct ext_intc_fwnode_list {
+ struct fwnode_handle *fwnode;
+ u32 gsi_base;
+ u32 nr_irqs;
+ struct list_head list;
+};
+
+struct fwnode_handle *ext_entc_get_gsi_domain_id(u32 gsi)
+{
+ struct ext_intc_fwnode_list *ext_intc_element;
+ struct list_head *i, *tmp;
+
+ /* Find the External Interrupt controller that manages this GSI. */
+ list_for_each_safe(i, tmp, &ext_intc_list) {
+ ext_intc_element = list_entry(i, struct ext_intc_fwnode_list, list);
+ if (gsi >= ext_intc_element->gsi_base &&
+ gsi < (ext_intc_element->gsi_base + ext_intc_element->nr_irqs))
+ return ext_intc_element->fwnode;
+ }
+
+ return NULL;
+}

static int irqchip_cmp_func(const void *in0, const void *in1)
{
@@ -30,3 +59,92 @@ void arch_sort_irqchip_probe(struct acpi_probe_entry *ap_head, int nr)
return;
sort(ape, nr, sizeof(*ape), irqchip_cmp_func, NULL);
}
+
+static int __init irqchip_add_platform_device(char *irqchip_name, u32 irqchip_id,
+ resource_size_t iomem_res_start,
+ resource_size_t iomem_res_size,
+ u32 gsi_base,
+ u32 nr_irqs,
+ union acpi_subtable_headers *header)
+{
+ struct ext_intc_fwnode_list *ext_intc_element;
+ struct platform_device *pdev;
+ struct fwnode_handle *fn;
+ struct resource *res;
+ int ret;
+
+ fn = irq_domain_alloc_named_id_fwnode(irqchip_name, irqchip_id);
+ if (!fn)
+ return -ENOMEM;
+
+ pdev = platform_device_alloc(irqchip_name, irqchip_id);
+ if (!pdev) {
+ irq_domain_free_fwnode(fn);
+ return -ENOMEM;
+ }
+
+ res = kcalloc(1, sizeof(*res), GFP_KERNEL);
+ if (!res) {
+ irq_domain_free_fwnode(fn);
+ platform_device_put(pdev);
+ return -ENOMEM;
+ }
+
+ ext_intc_element = kcalloc(1, sizeof(*ext_intc_element), GFP_KERNEL);
+ if (!ext_intc_element)
+ return -ENOMEM;
+
+ ext_intc_element->fwnode = fn;
+ ext_intc_element->gsi_base = gsi_base;
+ ext_intc_element->nr_irqs = nr_irqs;
+ list_add_tail(&ext_intc_element->list, &ext_intc_list);
+
+ res->start = iomem_res_start;
+ res->end = res->start + iomem_res_size - 1;
+ res->flags = IORESOURCE_MEM;
+ ret = platform_device_add_resources(pdev, res, 1);
+ /*
+ * Resources are duplicated in platform_device_add_resources,
+ * free their allocated memory
+ */
+ kfree(res);
+
+ /*
+ * Add copy of aplic pointer so that platform driver get aplic details.
+ */
+ ret = platform_device_add_data(pdev, &header, sizeof(header));
+ if (ret) {
+ irq_domain_free_fwnode(fn);
+ platform_device_put(pdev);
+ return ret;
+ }
+
+ pdev->dev.fwnode = fn;
+ ret = platform_device_add(pdev);
+ if (ret) {
+ irq_domain_free_fwnode(fn);
+ platform_device_put(pdev);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __init aplic_parse_madt(union acpi_subtable_headers *header,
+ const unsigned long end)
+{
+ struct acpi_madt_aplic *aplic = (struct acpi_madt_aplic *)header;
+
+ return irqchip_add_platform_device("riscv-aplic",
+ aplic->id,
+ aplic->base_addr,
+ aplic->size,
+ aplic->gsi_base,
+ aplic->num_sources,
+ header);
+}
+
+void __init riscv_acpi_aplic_platform_init(void)
+{
+ acpi_table_parse_madt(ACPI_MADT_TYPE_APLIC, aplic_parse_madt, 0);
+}
--
2.39.2


2023-12-19 17:52:11

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 12/17] irqchip: irq-sifive-plic: Add ACPI support

Add ACPI support in PLIC driver. In ACPI, IO devices use Global System
Interrupts (GSI) which is a flat space split across multiple PLICs.

Signed-off-by: Sunil V L <[email protected]>
Co-developed-by: Haibo Xu <[email protected]>
Signed-off-by: Haibo Xu <[email protected]>
---
arch/riscv/include/asm/irq.h | 6 +++
drivers/irqchip/irq-sifive-plic.c | 76 +++++++++++++++++++++++--------
2 files changed, 64 insertions(+), 18 deletions(-)

diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h
index df59192a157d..7b14f3ebe242 100644
--- a/arch/riscv/include/asm/irq.h
+++ b/arch/riscv/include/asm/irq.h
@@ -28,6 +28,12 @@ struct fwnode_handle *aplic_get_gsi_domain_id(u32 gsi);
static inline struct fwnode_handle *aplic_get_gsi_domain_id(u32 gsi) { return NULL; }
#endif

+#ifdef CONFIG_SIFIVE_PLIC
+struct fwnode_handle *plic_get_gsi_domain_id(u32 gsi);
+#else
+static inline struct fwnode_handle *plic_get_gsi_domain_id(u32 gsi) { return NULL; }
+#endif
+
int __init acpi_get_intc_index_hartid(u32 index, unsigned long *hartid);
int acpi_get_ext_intc_parent_hartid(u8 id, u32 idx, unsigned long *hartid);
void acpi_get_plic_nr_contexts(u8 id, int *nr_contexts);
diff --git a/drivers/irqchip/irq-sifive-plic.c b/drivers/irqchip/irq-sifive-plic.c
index c8f8a8cdcce1..d4c355ffa628 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 {
@@ -316,6 +319,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);

@@ -417,17 +424,31 @@ static const struct of_device_id plic_match[] = {
};

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;
+ struct acpi_madt_plic *plic;
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)) {
+ plic = *(struct acpi_madt_plic **)dev_get_platdata(dev);
+ if (!plic) {
+ dev_err(dev, "PLIC platform data is NULL!\n");
+ return -EINVAL;
+ }
+
+ *nr_irqs = plic->num_irqs;
+ acpi_get_plic_nr_contexts(plic->id, nr_contexts);
+ if (WARN_ON(!*nr_contexts)) {
+ dev_err(dev, "no PLIC context available\n");
+ return -EINVAL;
+ }
+
+ *gsi_base = plic->gsi_base;
+ *id = plic->id;
+ return 0;
+ }

rc = of_property_read_u32(to_of_node(dev->fwnode),
"riscv,ndev", nr_irqs);
@@ -442,23 +463,28 @@ 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_hwirq(struct platform_device *pdev,
- u32 context, u32 *parent_hwirq,
+ u32 context, u32 id, u32 *parent_hwirq,
unsigned long *parent_hartid)
{
struct device *dev = &pdev->dev;
struct of_phandle_args parent;
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 = acpi_get_ext_intc_parent_hartid(id, context, parent_hartid);
+ if (rc)
+ return rc;
+
+ *parent_hwirq = RV_IRQ_EXT;
+ return 0;
+ }

rc = of_irq_parse_one(to_of_node(dev->fwnode), context, &parent);
if (rc)
@@ -483,7 +509,9 @@ static int plic_probe(struct platform_device *pdev)
struct plic_priv *priv;
irq_hw_number_t hwirq;
struct resource *res;
+ int id, context_id;
bool cpuhp_setup;
+ u32 gsi_base;

if (is_of_node(dev->fwnode)) {
const struct of_device_id *id;
@@ -510,19 +538,21 @@ static int plic_probe(struct platform_device *pdev)
return -EIO;
}

- rc = plic_parse_nr_irqs_and_contexts(pdev, &nr_irqs, &nr_contexts);
+ rc = plic_parse_nr_irqs_and_contexts(pdev, &nr_irqs, &nr_contexts, &gsi_base, &id);
if (rc) {
dev_err(dev, "failed to parse irqs and contexts\n");
return rc;
}
priv->nr_irqs = nr_irqs;
+ priv->gsi_base = gsi_base;
+ priv->id = id;

priv->prio_save = devm_bitmap_zalloc(dev, nr_irqs, GFP_KERNEL);
if (!priv->prio_save)
return -ENOMEM;

for (i = 0; i < nr_contexts; i++) {
- rc = plic_parse_context_parent_hwirq(pdev, i,
+ rc = plic_parse_context_parent_hwirq(pdev, i, priv->id,
&parent_hwirq, &hartid);
if (rc) {
dev_warn(dev, "hwirq for context%d not found\n", i);
@@ -574,13 +604,23 @@ static int plic_probe(struct platform_device *pdev)
goto done;
}

+ if (is_of_node(dev->fwnode)) {
+ context_id = i;
+ } else {
+ rc = acpi_get_plic_context(priv->id, i, &context_id);
+ if (rc) {
+ dev_warn(dev, "invalid context id for context%d\n", i);
+ continue;
+ }
+ }
+
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,
--
2.39.2


2023-12-19 17:52:31

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 14/17] ACPI: bus: Add acpi_riscv_init function

Add a new function for RISC-V to do any architecture specific
initialization. This function will be used to create platform devices
like APLIC, PLIC, RISC-V IOMMU etc. This is similar to acpi_arm_init().

Signed-off-by: Sunil V L <[email protected]>
---
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 9eace6c7042e..f7ac0caf04cf 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -1417,6 +1417,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 f80b3da230e9..c4d679b1359e 100644
--- a/drivers/acpi/riscv/Makefile
+++ b/drivers/acpi/riscv/Makefile
@@ -1,2 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
-obj-y += rhct.o irq.o
+obj-y += rhct.o irq.o init.o
diff --git a/drivers/acpi/riscv/init.c b/drivers/acpi/riscv/init.c
new file mode 100644
index 000000000000..b5807bbdb171
--- /dev/null
+++ b/drivers/acpi/riscv/init.c
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2023, Ventana Micro Systems Inc
+ * Author: Sunil V L <[email protected]>
+ *
+ */
+
+#include <linux/acpi.h>
+
+void __init acpi_riscv_init(void)
+{
+}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index b6766bded765..60dc1f1e9351 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -1536,6 +1536,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.39.2


2023-12-19 17:52:58

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 17/17] irqchip: riscv-intc: Set ACPI irqmodel

INTC being the root interrupt controller, set the ACPI irqmodel with
callback function to get the GSI domain id.

Signed-off-by: Sunil V L <[email protected]>
---
arch/riscv/include/asm/irq.h | 13 +------------
drivers/irqchip/irq-riscv-intc.c | 1 +
2 files changed, 2 insertions(+), 12 deletions(-)

diff --git a/arch/riscv/include/asm/irq.h b/arch/riscv/include/asm/irq.h
index 7b14f3ebe242..9c2bdf4bd880 100644
--- a/arch/riscv/include/asm/irq.h
+++ b/arch/riscv/include/asm/irq.h
@@ -22,18 +22,7 @@
#define APLIC_PLIC_ID(x) ((x) >> 24)
#define IDC_CONTEXT_ID(x) ((x) & 0x0000ffff)

-#ifdef CONFIG_RISCV_APLIC
-struct fwnode_handle *aplic_get_gsi_domain_id(u32 gsi);
-#else
-static inline struct fwnode_handle *aplic_get_gsi_domain_id(u32 gsi) { return NULL; }
-#endif
-
-#ifdef CONFIG_SIFIVE_PLIC
-struct fwnode_handle *plic_get_gsi_domain_id(u32 gsi);
-#else
-static inline struct fwnode_handle *plic_get_gsi_domain_id(u32 gsi) { return NULL; }
-#endif
-
+struct fwnode_handle *ext_entc_get_gsi_domain_id(u32 gsi);
int __init acpi_get_intc_index_hartid(u32 index, unsigned long *hartid);
int acpi_get_ext_intc_parent_hartid(u8 id, u32 idx, unsigned long *hartid);
void acpi_get_plic_nr_contexts(u8 id, int *nr_contexts);
diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c
index 24bbc5bfc30f..bddfe47df27b 100644
--- a/drivers/irqchip/irq-riscv-intc.c
+++ b/drivers/irqchip/irq-riscv-intc.c
@@ -311,6 +311,7 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
return rc;
}

+ acpi_set_irq_model(ACPI_IRQ_MODEL_RINTC, ext_entc_get_gsi_domain_id);
return 0;
}

--
2.39.2


2023-12-19 17:54:21

by Sunil V L

[permalink] [raw]
Subject: [RFC PATCH v3 16/17] ACPI: RISC-V: Create PLIC platform device

Since PLIC needs to be a platform device, probe the MADT and create
platform devices for each PLIC in the system.

Signed-off-by: Sunil V L <[email protected]>
---
drivers/acpi/riscv/init.c | 1 +
drivers/acpi/riscv/init.h | 1 +
drivers/acpi/riscv/irq.c | 19 +++++++++++++++++++
3 files changed, 21 insertions(+)

diff --git a/drivers/acpi/riscv/init.c b/drivers/acpi/riscv/init.c
index e7eff7ab1474..c6fd4097e8ae 100644
--- a/drivers/acpi/riscv/init.c
+++ b/drivers/acpi/riscv/init.c
@@ -11,4 +11,5 @@
void __init acpi_riscv_init(void)
{
riscv_acpi_aplic_platform_init();
+ riscv_acpi_plic_platform_init();
}
diff --git a/drivers/acpi/riscv/init.h b/drivers/acpi/riscv/init.h
index 17bcf0baaadb..b4b305d83b3a 100644
--- a/drivers/acpi/riscv/init.h
+++ b/drivers/acpi/riscv/init.h
@@ -3,3 +3,4 @@

void __init riscv_acpi_imsic_platform_init(void);
void __init riscv_acpi_aplic_platform_init(void);
+void __init riscv_acpi_plic_platform_init(void);
diff --git a/drivers/acpi/riscv/irq.c b/drivers/acpi/riscv/irq.c
index d08a851ab6dc..f14ea43b0178 100644
--- a/drivers/acpi/riscv/irq.c
+++ b/drivers/acpi/riscv/irq.c
@@ -148,3 +148,22 @@ void __init riscv_acpi_aplic_platform_init(void)
{
acpi_table_parse_madt(ACPI_MADT_TYPE_APLIC, aplic_parse_madt, 0);
}
+
+static int __init plic_parse_madt(union acpi_subtable_headers *header,
+ const unsigned long end)
+{
+ struct acpi_madt_plic *plic = (struct acpi_madt_plic *)header;
+
+ return irqchip_add_platform_device("riscv-plic",
+ plic->id,
+ plic->base_addr,
+ plic->size,
+ plic->gsi_base,
+ plic->num_irqs,
+ header);
+}
+
+void __init riscv_acpi_plic_platform_init(void)
+{
+ acpi_table_parse_madt(ACPI_MADT_TYPE_PLIC, plic_parse_madt, 0);
+}
--
2.39.2


2023-12-19 17:54:25

by Rafael J. Wysocki

[permalink] [raw]
Subject: Re: [RFC PATCH v3 00/17] RISC-V: ACPI: Add external interrupt controller support

On Tue, Dec 19, 2023 at 6:45 PM Sunil V L <[email protected]> wrote:
>
> 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) Introduced support for fw_devlink for ACPI nodes for IRQ dependency.
> This helps to support deferred probe of interrupt controller drivers.
>
> 3) Modified pnp_irq() to try registering the IRQ again if it sees it in
> disabled state. This solution is similar to how
> platform_get_irq_optional() works for regular platform devices.
>
> 4) Added support for re-ordering the probe of interrupt controllers when
> IRQCHIP_ACPI_DECLARE is used.
>
> 5) ACPI support added in RISC-V interrupt controller drivers.
>
> This series is based on Anup's AIA v11 series. Since Anup's AIA v11 is
> not merged yet and first time introducing fw_devlink, deferred probe and
> reordering support for IRQCHIP probe, this series is still kept as RFC.
> Looking forward for the feedback!
>
> 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 riscv_acpi_b2_v8 branch at
> https://github.com/vlsunil/qemu.git
>
> 2) EDK2 should be built using the instructions at:
> https://github.com/tianocore/edk2/blob/master/OvmfPkg/RiscVVirt/README.md
>
> 3) Build Linux using this series on top of Anup's AIA v11 series.
>
> 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=ttyS0 rootwait earlycon=uart8250,mmio,0x10000000"
>
> To boot with APLIC only, use aia=aplic.
> To boot with PLIC, remove aia= option.
>
> This series is also available in acpi_b2_v3_riscv_aia_v11 branch at
> https://github.com/vlsunil/linux.git
>
> Based-on: [email protected]
> (https://lore.kernel.org/lkml/[email protected]/)
>
> Sunil V L (17):
> arm64: PCI: Migrate ACPI related functions to pci-acpi.c
> RISC-V: ACPI: Implement PCI related functionality
> PCI: Make pci_create_root_bus() declare its reliance on MSI domains
> ACPI: Add fw_devlink support for ACPI fwnode for IRQ dependency
> ACPI: irq: Add support for deferred probe in acpi_register_gsi()
> pnp.h: Reconfigure IRQ in pnp_irq() to support deferred probe
> ACPI: scan.c: Add weak arch specific function to reorder the IRQCHIP
> probe
> ACPI: RISC-V: Implement arch function to reorder irqchip probe entries
> irqchip: riscv-intc: Add ACPI support for AIA
> irqchip: riscv-imsic: Add ACPI support
> irqchip: riscv-aplic: Add ACPI support
> irqchip: irq-sifive-plic: Add ACPI support
> ACPI: bus: Add RINTC IRQ model for RISC-V
> ACPI: bus: Add acpi_riscv_init function
> ACPI: RISC-V: Create APLIC platform device
> ACPI: RISC-V: Create PLIC platform device
> irqchip: riscv-intc: Set ACPI irqmodel

JFYI, I have no capacity to provide any feedback on this till 6.8-rc1 is out.

Thanks!

2023-12-20 03:50:07

by Sunil V L

[permalink] [raw]
Subject: Re: [RFC PATCH v3 00/17] RISC-V: ACPI: Add external interrupt controller support

On Tue, Dec 19, 2023 at 06:50:19PM +0100, Rafael J. Wysocki wrote:
> On Tue, Dec 19, 2023 at 6:45 PM Sunil V L <[email protected]> wrote:
> >
> > 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) Introduced support for fw_devlink for ACPI nodes for IRQ dependency.
> > This helps to support deferred probe of interrupt controller drivers.
> >
> > 3) Modified pnp_irq() to try registering the IRQ again if it sees it in
> > disabled state. This solution is similar to how
> > platform_get_irq_optional() works for regular platform devices.
> >
> > 4) Added support for re-ordering the probe of interrupt controllers when
> > IRQCHIP_ACPI_DECLARE is used.
> >
> > 5) ACPI support added in RISC-V interrupt controller drivers.
> >
> > This series is based on Anup's AIA v11 series. Since Anup's AIA v11 is
> > not merged yet and first time introducing fw_devlink, deferred probe and
> > reordering support for IRQCHIP probe, this series is still kept as RFC.
> > Looking forward for the feedback!
> >
> > 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 riscv_acpi_b2_v8 branch at
> > https://github.com/vlsunil/qemu.git
> >
> > 2) EDK2 should be built using the instructions at:
> > https://github.com/tianocore/edk2/blob/master/OvmfPkg/RiscVVirt/README.md
> >
> > 3) Build Linux using this series on top of Anup's AIA v11 series.
> >
> > 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=ttyS0 rootwait earlycon=uart8250,mmio,0x10000000"
> >
> > To boot with APLIC only, use aia=aplic.
> > To boot with PLIC, remove aia= option.
> >
> > This series is also available in acpi_b2_v3_riscv_aia_v11 branch at
> > https://github.com/vlsunil/linux.git
> >
> > Based-on: [email protected]
> > (https://lore.kernel.org/lkml/[email protected]/)
> >
> > Sunil V L (17):
> > arm64: PCI: Migrate ACPI related functions to pci-acpi.c
> > RISC-V: ACPI: Implement PCI related functionality
> > PCI: Make pci_create_root_bus() declare its reliance on MSI domains
> > ACPI: Add fw_devlink support for ACPI fwnode for IRQ dependency
> > ACPI: irq: Add support for deferred probe in acpi_register_gsi()
> > pnp.h: Reconfigure IRQ in pnp_irq() to support deferred probe
> > ACPI: scan.c: Add weak arch specific function to reorder the IRQCHIP
> > probe
> > ACPI: RISC-V: Implement arch function to reorder irqchip probe entries
> > irqchip: riscv-intc: Add ACPI support for AIA
> > irqchip: riscv-imsic: Add ACPI support
> > irqchip: riscv-aplic: Add ACPI support
> > irqchip: irq-sifive-plic: Add ACPI support
> > ACPI: bus: Add RINTC IRQ model for RISC-V
> > ACPI: bus: Add acpi_riscv_init function
> > ACPI: RISC-V: Create APLIC platform device
> > ACPI: RISC-V: Create PLIC platform device
> > irqchip: riscv-intc: Set ACPI irqmodel
>
> JFYI, I have no capacity to provide any feedback on this till 6.8-rc1 is out.
>
No worries!. I will wait for your feedback.

Thanks!
Sunil

2023-12-26 23:56:20

by Bjorn Helgaas

[permalink] [raw]
Subject: Re: [RFC PATCH v3 03/17] PCI: Make pci_create_root_bus() declare its reliance on MSI domains

On Tue, Dec 19, 2023 at 11:15:12PM +0530, Sunil V L wrote:
> Similar to [1], declare this dependency for PCI probe in ACPI based
> flow.

It would be better to refer to this as 9ec37efb8783 ("PCI/MSI: Make
pci_host_common_probe() declare its reliance on MSI domains") instead
of a link to the mailing list archives.

The git SHA1 is part of the git repo, and git can tell us where that
SHA1 is included. The lore URL is external and doesn't say anything
about what happened to the patch.

> This is required especially for RISC-V platforms where MSI controller
> can be absent.
>
> [1] - https://lore.kernel.org/all/[email protected]/

2023-12-28 13:09:06

by Sunil V L

[permalink] [raw]
Subject: Re: [RFC PATCH v3 03/17] PCI: Make pci_create_root_bus() declare its reliance on MSI domains

On Tue, Dec 26, 2023 at 05:56:02PM -0600, Bjorn Helgaas wrote:
> On Tue, Dec 19, 2023 at 11:15:12PM +0530, Sunil V L wrote:
> > Similar to [1], declare this dependency for PCI probe in ACPI based
> > flow.
>
> It would be better to refer to this as 9ec37efb8783 ("PCI/MSI: Make
> pci_host_common_probe() declare its reliance on MSI domains") instead
> of a link to the mailing list archives.
>
> The git SHA1 is part of the git repo, and git can tell us where that
> SHA1 is included. The lore URL is external and doesn't say anything
> about what happened to the patch.
>
Yes!. Let me update in next version. Thanks!

> > This is required especially for RISC-V platforms where MSI controller
> > can be absent.
> >
> > [1] - https://lore.kernel.org/all/[email protected]/

2024-01-30 06:02:59

by Sunil V L

[permalink] [raw]
Subject: Re: [RFC PATCH v3 00/17] RISC-V: ACPI: Add external interrupt controller support

On Tue, Dec 19, 2023 at 06:50:19PM +0100, Rafael J. Wysocki wrote:
> On Tue, Dec 19, 2023 at 6:45 PM Sunil V L <[email protected]> wrote:
> >
> > 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) Introduced support for fw_devlink for ACPI nodes for IRQ dependency.
> > This helps to support deferred probe of interrupt controller drivers.
> >
> > 3) Modified pnp_irq() to try registering the IRQ again if it sees it in
> > disabled state. This solution is similar to how
> > platform_get_irq_optional() works for regular platform devices.
> >
> > 4) Added support for re-ordering the probe of interrupt controllers when
> > IRQCHIP_ACPI_DECLARE is used.
> >
> > 5) ACPI support added in RISC-V interrupt controller drivers.
> >
> > This series is based on Anup's AIA v11 series. Since Anup's AIA v11 is
> > not merged yet and first time introducing fw_devlink, deferred probe and
> > reordering support for IRQCHIP probe, this series is still kept as RFC.
> > Looking forward for the feedback!
> >
> > 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 riscv_acpi_b2_v8 branch at
> > https://github.com/vlsunil/qemu.git
> >
> > 2) EDK2 should be built using the instructions at:
> > https://github.com/tianocore/edk2/blob/master/OvmfPkg/RiscVVirt/README.md
> >
> > 3) Build Linux using this series on top of Anup's AIA v11 series.
> >
> > 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=ttyS0 rootwait earlycon=uart8250,mmio,0x10000000"
> >
> > To boot with APLIC only, use aia=aplic.
> > To boot with PLIC, remove aia= option.
> >
> > This series is also available in acpi_b2_v3_riscv_aia_v11 branch at
> > https://github.com/vlsunil/linux.git
> >
> > Based-on: [email protected]
> > (https://lore.kernel.org/lkml/[email protected]/)
> >
> > Sunil V L (17):
> > arm64: PCI: Migrate ACPI related functions to pci-acpi.c
> > RISC-V: ACPI: Implement PCI related functionality
> > PCI: Make pci_create_root_bus() declare its reliance on MSI domains
> > ACPI: Add fw_devlink support for ACPI fwnode for IRQ dependency
> > ACPI: irq: Add support for deferred probe in acpi_register_gsi()
> > pnp.h: Reconfigure IRQ in pnp_irq() to support deferred probe
> > ACPI: scan.c: Add weak arch specific function to reorder the IRQCHIP
> > probe
> > ACPI: RISC-V: Implement arch function to reorder irqchip probe entries
> > irqchip: riscv-intc: Add ACPI support for AIA
> > irqchip: riscv-imsic: Add ACPI support
> > irqchip: riscv-aplic: Add ACPI support
> > irqchip: irq-sifive-plic: Add ACPI support
> > ACPI: bus: Add RINTC IRQ model for RISC-V
> > ACPI: bus: Add acpi_riscv_init function
> > ACPI: RISC-V: Create APLIC platform device
> > ACPI: RISC-V: Create PLIC platform device
> > irqchip: riscv-intc: Set ACPI irqmodel
>
> JFYI, I have no capacity to provide any feedback on this till 6.8-rc1 is out.
>
Hi Rafael,

Gentle ping.

Could you please provide feedback on the series? Patches 4, 5, 6, 7 and
8 are bit critical IMO. So, I really look forward for your and other
ACPI experts!.

Thanks!
Sunil

2024-02-01 18:14:46

by Rafael J. Wysocki

[permalink] [raw]
Subject: Re: [RFC PATCH v3 00/17] RISC-V: ACPI: Add external interrupt controller support

On Tue, Jan 30, 2024 at 7:02 AM Sunil V L <[email protected]> wrote:
>
> On Tue, Dec 19, 2023 at 06:50:19PM +0100, Rafael J. Wysocki wrote:
> > On Tue, Dec 19, 2023 at 6:45 PM Sunil V L <sunilvl@ventanamicrocom> wrote:
> > >
> > > 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) Introduced support for fw_devlink for ACPI nodes for IRQ dependency.
> > > This helps to support deferred probe of interrupt controller drivers.
> > >
> > > 3) Modified pnp_irq() to try registering the IRQ again if it sees it in
> > > disabled state. This solution is similar to how
> > > platform_get_irq_optional() works for regular platform devices.
> > >
> > > 4) Added support for re-ordering the probe of interrupt controllers when
> > > IRQCHIP_ACPI_DECLARE is used.
> > >
> > > 5) ACPI support added in RISC-V interrupt controller drivers.
> > >
> > > This series is based on Anup's AIA v11 series. Since Anup's AIA v11 is
> > > not merged yet and first time introducing fw_devlink, deferred probe and
> > > reordering support for IRQCHIP probe, this series is still kept as RFC.
> > > Looking forward for the feedback!
> > >
> > > 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 riscv_acpi_b2_v8 branch at
> > > https://github.com/vlsunil/qemu.git
> > >
> > > 2) EDK2 should be built using the instructions at:
> > > https://github.com/tianocore/edk2/blob/master/OvmfPkg/RiscVVirt/README.md
> > >
> > > 3) Build Linux using this series on top of Anup's AIA v11 series.
> > >
> > > 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=ttyS0 rootwait earlycon=uart8250,mmio,0x10000000"
> > >
> > > To boot with APLIC only, use aia=aplic.
> > > To boot with PLIC, remove aia= option.
> > >
> > > This series is also available in acpi_b2_v3_riscv_aia_v11 branch at
> > > https://github.com/vlsunil/linux.git
> > >
> > > Based-on: [email protected]
> > > (https://lore.kernel.org/lkml/[email protected]/)
> > >
> > > Sunil V L (17):
> > > arm64: PCI: Migrate ACPI related functions to pci-acpi.c
> > > RISC-V: ACPI: Implement PCI related functionality
> > > PCI: Make pci_create_root_bus() declare its reliance on MSI domains
> > > ACPI: Add fw_devlink support for ACPI fwnode for IRQ dependency
> > > ACPI: irq: Add support for deferred probe in acpi_register_gsi()
> > > pnp.h: Reconfigure IRQ in pnp_irq() to support deferred probe
> > > ACPI: scan.c: Add weak arch specific function to reorder the IRQCHIP
> > > probe
> > > ACPI: RISC-V: Implement arch function to reorder irqchip probe entries
> > > irqchip: riscv-intc: Add ACPI support for AIA
> > > irqchip: riscv-imsic: Add ACPI support
> > > irqchip: riscv-aplic: Add ACPI support
> > > irqchip: irq-sifive-plic: Add ACPI support
> > > ACPI: bus: Add RINTC IRQ model for RISC-V
> > > ACPI: bus: Add acpi_riscv_init function
> > > ACPI: RISC-V: Create APLIC platform device
> > > ACPI: RISC-V: Create PLIC platform device
> > > irqchip: riscv-intc: Set ACPI irqmodel
> >
> > JFYI, I have no capacity to provide any feedback on this till 6.8-rc1 is out.
> >
> Hi Rafael,
>
> Gentle ping.
>
> Could you please provide feedback on the series? Patches 4, 5, 6, 7 and
> 8 are bit critical IMO. So, I really look forward for your and other
> ACPI experts!.

There was quite a bit of discussion on patch [6/21] and it still seems
relevant to me.

ACPI actually has a way to at least indicate what the probe ordering
should be which is _DEP.

The current handling of _DEP in the kernel may not be covering this
particular use case, but I would rather extend it (if necessary)
instead of doing all of the -EPROBE_DEFER dance which seems fragile to
me.

Thanks!

2024-02-02 12:17:43

by Sunil V L

[permalink] [raw]
Subject: Re: [RFC PATCH v3 00/17] RISC-V: ACPI: Add external interrupt controller support

On Thu, Feb 01, 2024 at 07:10:28PM +0100, Rafael J. Wysocki wrote:
> On Tue, Jan 30, 2024 at 7:02 AM Sunil V L <[email protected]> wrote:
> >
> > On Tue, Dec 19, 2023 at 06:50:19PM +0100, Rafael J. Wysocki wrote:
> > > On Tue, Dec 19, 2023 at 6:45 PM Sunil V L <[email protected]> wrote:
> > > >
> > > > 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) Introduced support for fw_devlink for ACPI nodes for IRQ dependency.
> > > > This helps to support deferred probe of interrupt controller drivers.
> > > >
> > > > 3) Modified pnp_irq() to try registering the IRQ again if it sees it in
> > > > disabled state. This solution is similar to how
> > > > platform_get_irq_optional() works for regular platform devices.
> > > >
> > > > 4) Added support for re-ordering the probe of interrupt controllers when
> > > > IRQCHIP_ACPI_DECLARE is used.
> > > >
> > > > 5) ACPI support added in RISC-V interrupt controller drivers.
> > > >
> > > > This series is based on Anup's AIA v11 series. Since Anup's AIA v11 is
> > > > not merged yet and first time introducing fw_devlink, deferred probe and
> > > > reordering support for IRQCHIP probe, this series is still kept as RFC.
> > > > Looking forward for the feedback!
> > > >
> > > > 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 riscv_acpi_b2_v8 branch at
> > > > https://github.com/vlsunil/qemu.git
> > > >
> > > > 2) EDK2 should be built using the instructions at:
> > > > https://github.com/tianocore/edk2/blob/master/OvmfPkg/RiscVVirt/README.md
> > > >
> > > > 3) Build Linux using this series on top of Anup's AIA v11 series.
> > > >
> > > > 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=ttyS0 rootwait earlycon=uart8250,mmio,0x10000000"
> > > >
> > > > To boot with APLIC only, use aia=aplic.
> > > > To boot with PLIC, remove aia= option.
> > > >
> > > > This series is also available in acpi_b2_v3_riscv_aia_v11 branch at
> > > > https://github.com/vlsunil/linux.git
> > > >
> > > > Based-on: [email protected]
> > > > (https://lore.kernel.org/lkml/[email protected]/)
> > > >
> > > > Sunil V L (17):
> > > > arm64: PCI: Migrate ACPI related functions to pci-acpi.c
> > > > RISC-V: ACPI: Implement PCI related functionality
> > > > PCI: Make pci_create_root_bus() declare its reliance on MSI domains
> > > > ACPI: Add fw_devlink support for ACPI fwnode for IRQ dependency
> > > > ACPI: irq: Add support for deferred probe in acpi_register_gsi()
> > > > pnp.h: Reconfigure IRQ in pnp_irq() to support deferred probe
> > > > ACPI: scan.c: Add weak arch specific function to reorder the IRQCHIP
> > > > probe
> > > > ACPI: RISC-V: Implement arch function to reorder irqchip probe entries
> > > > irqchip: riscv-intc: Add ACPI support for AIA
> > > > irqchip: riscv-imsic: Add ACPI support
> > > > irqchip: riscv-aplic: Add ACPI support
> > > > irqchip: irq-sifive-plic: Add ACPI support
> > > > ACPI: bus: Add RINTC IRQ model for RISC-V
> > > > ACPI: bus: Add acpi_riscv_init function
> > > > ACPI: RISC-V: Create APLIC platform device
> > > > ACPI: RISC-V: Create PLIC platform device
> > > > irqchip: riscv-intc: Set ACPI irqmodel
> > >
> > > JFYI, I have no capacity to provide any feedback on this till 6.8-rc1 is out.
> > >
> > Hi Rafael,
> >
> > Gentle ping.
> >
> > Could you please provide feedback on the series? Patches 4, 5, 6, 7 and
> > 8 are bit critical IMO. So, I really look forward for your and other
> > ACPI experts!.
>
> There was quite a bit of discussion on patch [6/21] and it still seems
> relevant to me.
>
> ACPI actually has a way to at least indicate what the probe ordering
> should be which is _DEP.
>
> The current handling of _DEP in the kernel may not be covering this
> particular use case, but I would rather extend it (if necessary)
> instead of doing all of the -EPROBE_DEFER dance which seems fragile to
> me.
>
Hi Rafael,

Appreciate your help to look at the patches. Thank you very much!.

I am not very sure whether you looked into patches in the v3 of the
series. Because, unlike in v2, v3 doesn't need changing all drivers to
handle EPROBE_DEFER. In v3, it creates fw_devlink for the dependency as
suggested by Marc. Please take a look at PATCH 4/17.

For the IRQ dependency, I think adding _DEP is not required. The
"Extended Interrupt Descriptor" supports ResourceSource to
indicate the dependency. Or GSI mapping can indicate the source. This is
already handled in acpi_irq_parse_one_cb(). PATCH 4 uses this
information to create links between producer and consumer so that DD
framework probes the driver in the required order.

As you know, PNP devices are enumerated in a different way. I don't know
why it was done like this. But pnpacpi_init() is called via
fs_initcall() and acpi_dev_resource_interrupt() called from
pnpacpi_allocated_resource() doesn't handle the ResourceSource
dependency. It caches the information in PNP data structure and expects
the IRQ mapping to be available. Even if we add support to
handle extended interrupt descriptor, it is not going to help. Hence, I
had to add PATCH 5/17 and PATCH 6/17. Again, the change is mainly in
pnp_irq() now and hence it doesn't need changing all drivers.

Thanks,
Sunil

2024-03-04 10:31:48

by Sunil V L

[permalink] [raw]
Subject: Re: [RFC PATCH v3 00/17] RISC-V: ACPI: Add external interrupt controller support

On Fri, Feb 02, 2024 at 05:47:16PM +0530, Sunil V L wrote:
> On Thu, Feb 01, 2024 at 07:10:28PM +0100, Rafael J. Wysocki wrote:
> > On Tue, Jan 30, 2024 at 7:02 AM Sunil V L <[email protected]> wrote:
> > >
> > > On Tue, Dec 19, 2023 at 06:50:19PM +0100, Rafael J. Wysocki wrote:
> > > > On Tue, Dec 19, 2023 at 6:45 PM Sunil V L <[email protected]> wrote:
> > > > >
> > > > > 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) Introduced support for fw_devlink for ACPI nodes for IRQ dependency.
> > > > > This helps to support deferred probe of interrupt controller drivers.
> > > > >
> > > > > 3) Modified pnp_irq() to try registering the IRQ again if it sees it in
> > > > > disabled state. This solution is similar to how
> > > > > platform_get_irq_optional() works for regular platform devices.
> > > > >
> > > > > 4) Added support for re-ordering the probe of interrupt controllers when
> > > > > IRQCHIP_ACPI_DECLARE is used.
> > > > >
> > > > > 5) ACPI support added in RISC-V interrupt controller drivers.
> > > > >
> > > > > This series is based on Anup's AIA v11 series. Since Anup's AIA v11 is
> > > > > not merged yet and first time introducing fw_devlink, deferred probe and
> > > > > reordering support for IRQCHIP probe, this series is still kept as RFC.
> > > > > Looking forward for the feedback!
> > > > >
> > > > > 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 riscv_acpi_b2_v8 branch at
> > > > > https://github.com/vlsunil/qemu.git
> > > > >
> > > > > 2) EDK2 should be built using the instructions at:
> > > > > https://github.com/tianocore/edk2/blob/master/OvmfPkg/RiscVVirt/README.md
> > > > >
> > > > > 3) Build Linux using this series on top of Anup's AIA v11 series.
> > > > >
> > > > > 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=ttyS0 rootwait earlycon=uart8250,mmio,0x10000000"
> > > > >
> > > > > To boot with APLIC only, use aia=aplic.
> > > > > To boot with PLIC, remove aia= option.
> > > > >
> > > > > This series is also available in acpi_b2_v3_riscv_aia_v11 branch at
> > > > > https://github.com/vlsunil/linux.git
> > > > >
> > > > > Based-on: [email protected]
> > > > > (https://lore.kernel.org/lkml/[email protected]/)
> > > > >
> > > > > Sunil V L (17):
> > > > > arm64: PCI: Migrate ACPI related functions to pci-acpi.c
> > > > > RISC-V: ACPI: Implement PCI related functionality
> > > > > PCI: Make pci_create_root_bus() declare its reliance on MSI domains
> > > > > ACPI: Add fw_devlink support for ACPI fwnode for IRQ dependency
> > > > > ACPI: irq: Add support for deferred probe in acpi_register_gsi()
> > > > > pnp.h: Reconfigure IRQ in pnp_irq() to support deferred probe
> > > > > ACPI: scan.c: Add weak arch specific function to reorder the IRQCHIP
> > > > > probe
> > > > > ACPI: RISC-V: Implement arch function to reorder irqchip probe entries
> > > > > irqchip: riscv-intc: Add ACPI support for AIA
> > > > > irqchip: riscv-imsic: Add ACPI support
> > > > > irqchip: riscv-aplic: Add ACPI support
> > > > > irqchip: irq-sifive-plic: Add ACPI support
> > > > > ACPI: bus: Add RINTC IRQ model for RISC-V
> > > > > ACPI: bus: Add acpi_riscv_init function
> > > > > ACPI: RISC-V: Create APLIC platform device
> > > > > ACPI: RISC-V: Create PLIC platform device
> > > > > irqchip: riscv-intc: Set ACPI irqmodel
> > > >
> > > > JFYI, I have no capacity to provide any feedback on this till 6.8-rc1 is out.
> > > >
> > > Hi Rafael,
> > >
> > > Gentle ping.
> > >
> > > Could you please provide feedback on the series? Patches 4, 5, 6, 7 and
> > > 8 are bit critical IMO. So, I really look forward for your and other
> > > ACPI experts!.
> >
> > There was quite a bit of discussion on patch [6/21] and it still seems
> > relevant to me.
> >
> > ACPI actually has a way to at least indicate what the probe ordering
> > should be which is _DEP.
> >
> > The current handling of _DEP in the kernel may not be covering this
> > particular use case, but I would rather extend it (if necessary)
> > instead of doing all of the -EPROBE_DEFER dance which seems fragile to
> > me.
> >
> Hi Rafael,
>
> Appreciate your help to look at the patches. Thank you very much!.
>
> I am not very sure whether you looked into patches in the v3 of the
> series. Because, unlike in v2, v3 doesn't need changing all drivers to
> handle EPROBE_DEFER. In v3, it creates fw_devlink for the dependency as
> suggested by Marc. Please take a look at PATCH 4/17.
>
> For the IRQ dependency, I think adding _DEP is not required. The
> "Extended Interrupt Descriptor" supports ResourceSource to
> indicate the dependency. Or GSI mapping can indicate the source. This is
> already handled in acpi_irq_parse_one_cb(). PATCH 4 uses this
> information to create links between producer and consumer so that DD
> framework probes the driver in the required order.
>
> As you know, PNP devices are enumerated in a different way. I don't know
> why it was done like this. But pnpacpi_init() is called via
> fs_initcall() and acpi_dev_resource_interrupt() called from
> pnpacpi_allocated_resource() doesn't handle the ResourceSource
> dependency. It caches the information in PNP data structure and expects
> the IRQ mapping to be available. Even if we add support to
> handle extended interrupt descriptor, it is not going to help. Hence, I
> had to add PATCH 5/17 and PATCH 6/17. Again, the change is mainly in
> pnp_irq() now and hence it doesn't need changing all drivers.
>
Hi Rafael,

Any further feedback on this? Do you see any issues with fw_devlink and
pnp_irq() changes for the interrupt controller dependency?

BTW, I explored the _DEP option you mentioned. But I think the current
approach would probably be better with lesser impact than _DEP. Below are
my findings.

1) When PNP device like PNP0501 (16550A UART) has _DEP, it does not get
created in the first pass (as expected) but they won't get created even
after the supplier clears the dependency. This is because
acpi_pnp_attach() returns success without calling pnpacpi_add_device()
when acpi_scan_clear_dep_fn() calls acpi_bus_attach(). Either
acpi_pnp_attach() needs to be modified or pnpacpi_add_device()
should be called as part of clearing the dependency. I may be wrong but
I think modifying pnp_irq() would probably affect only RISC-V than any
of the approaches above.

2) _DEP doesn't support PCI devices. When we have PCI link devices
(PNP0C0F) in the _PRT, the PCI driver probe as part of PCI scan can happen
prior to link device probe since link device will have dependency on the
interrupt controller which may not be probed yet. This will cause issue
to the PCI device driver init because _PRT says there is link device for
legacy PCI interrupt routing but the link driver is not probed yet.

3) _DEP needs namespace interrupt controllers. We would like to avoid
adding namespace devices also along with MADT.

Please let me know your thoughts.

Thanks,
Sunil

2024-04-15 15:16:24

by Sunil V L

[permalink] [raw]
Subject: Re: [RFC PATCH v3 00/17] RISC-V: ACPI: Add external interrupt controller support

On Thu, Feb 01, 2024 at 07:10:28PM +0100, Rafael J. Wysocki wrote:
> On Tue, Jan 30, 2024 at 7:02 AM Sunil V L <[email protected]> wrote:
> >
> > On Tue, Dec 19, 2023 at 06:50:19PM +0100, Rafael J. Wysocki wrote:
> > > On Tue, Dec 19, 2023 at 6:45 PM Sunil V L <[email protected]> wrote:
> > > >
> > > > 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) Introduced support for fw_devlink for ACPI nodes for IRQ dependency.
> > > > This helps to support deferred probe of interrupt controller drivers.
> > > >
> > > > 3) Modified pnp_irq() to try registering the IRQ again if it sees it in
> > > > disabled state. This solution is similar to how
> > > > platform_get_irq_optional() works for regular platform devices.
> > > >
> > > > 4) Added support for re-ordering the probe of interrupt controllers when
> > > > IRQCHIP_ACPI_DECLARE is used.
> > > >
> > > > 5) ACPI support added in RISC-V interrupt controller drivers.
> > > >
> > > > This series is based on Anup's AIA v11 series. Since Anup's AIA v11 is
> > > > not merged yet and first time introducing fw_devlink, deferred probe and
> > > > reordering support for IRQCHIP probe, this series is still kept as RFC.
> > > > Looking forward for the feedback!
> > > >
> > > > 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 riscv_acpi_b2_v8 branch at
> > > > https://github.com/vlsunil/qemu.git
> > > >
> > > > 2) EDK2 should be built using the instructions at:
> > > > https://github.com/tianocore/edk2/blob/master/OvmfPkg/RiscVVirt/README.md
> > > >
> > > > 3) Build Linux using this series on top of Anup's AIA v11 series.
> > > >
> > > > 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=ttyS0 rootwait earlycon=uart8250,mmio,0x10000000"
> > > >
> > > > To boot with APLIC only, use aia=aplic.
> > > > To boot with PLIC, remove aia= option.
> > > >
> > > > This series is also available in acpi_b2_v3_riscv_aia_v11 branch at
> > > > https://github.com/vlsunil/linux.git
> > > >
> > > > Based-on: [email protected]
> > > > (https://lore.kernel.org/lkml/[email protected]/)
> > > >
> > > > Sunil V L (17):
> > > > arm64: PCI: Migrate ACPI related functions to pci-acpi.c
> > > > RISC-V: ACPI: Implement PCI related functionality
> > > > PCI: Make pci_create_root_bus() declare its reliance on MSI domains
> > > > ACPI: Add fw_devlink support for ACPI fwnode for IRQ dependency
> > > > ACPI: irq: Add support for deferred probe in acpi_register_gsi()
> > > > pnp.h: Reconfigure IRQ in pnp_irq() to support deferred probe
> > > > ACPI: scan.c: Add weak arch specific function to reorder the IRQCHIP
> > > > probe
> > > > ACPI: RISC-V: Implement arch function to reorder irqchip probe entries
> > > > irqchip: riscv-intc: Add ACPI support for AIA
> > > > irqchip: riscv-imsic: Add ACPI support
> > > > irqchip: riscv-aplic: Add ACPI support
> > > > irqchip: irq-sifive-plic: Add ACPI support
> > > > ACPI: bus: Add RINTC IRQ model for RISC-V
> > > > ACPI: bus: Add acpi_riscv_init function
> > > > ACPI: RISC-V: Create APLIC platform device
> > > > ACPI: RISC-V: Create PLIC platform device
> > > > irqchip: riscv-intc: Set ACPI irqmodel
> > >
> > > JFYI, I have no capacity to provide any feedback on this till 6.8-rc1 is out.
> > >
> > Hi Rafael,
> >
> > Gentle ping.
> >
> > Could you please provide feedback on the series? Patches 4, 5, 6, 7 and
> > 8 are bit critical IMO. So, I really look forward for your and other
> > ACPI experts!.
>
> There was quite a bit of discussion on patch [6/21] and it still seems
> relevant to me.
>
> ACPI actually has a way to at least indicate what the probe ordering
> should be which is _DEP.
>
> The current handling of _DEP in the kernel may not be covering this
> particular use case, but I would rather extend it (if necessary)
> instead of doing all of the -EPROBE_DEFER dance which seems fragile to
> me.
>
Hi Rafael,

I found that _DEP is better than fw_devlink for ACPI since it works
during scan itself. For ex: the way PCI host bridges are scanned in
ACPI, PNP device handling. While some hacky solution could be done like
I did in v3 (pnp_irq() changes), _DEP way seems much better.

So, we decided to go with your suggested approach and defined namespace
devices for PLIC and APLIC required to create dependency mechanism.
However, there are concerns that every device will have to add _DEP now
and whether it is intended for this use case. Also, actually the
dependency is already available in the form of GSI number mapping.
Hence, instead of explicit dependency, we would like to create implicit
dependency. So, I will send RFC v4 series with those changes. Please
help us with feedback. If you could provide quick high level go/no-go,
that will help us a lot since we need to finalize the spec whether to
mandate _DEP or not.

I request you to provide some high level feedback in the RFC v4 I am
going to send.

1) Creation of implicit dependency.
2) Handling PNP devices as part of clearing dependency
3) IRQCHIP probing reordering when there are multiple irqchips.

Thanks,
Sunil

2024-04-15 15:19:17

by Rafael J. Wysocki

[permalink] [raw]
Subject: Re: [RFC PATCH v3 00/17] RISC-V: ACPI: Add external interrupt controller support

Hi,

[cut]

> >
> Hi Rafael,
>
> I found that _DEP is better than fw_devlink for ACPI since it works
> during scan itself. For ex: the way PCI host bridges are scanned in
> ACPI, PNP device handling. While some hacky solution could be done like
> I did in v3 (pnp_irq() changes), _DEP way seems much better.
>
> So, we decided to go with your suggested approach and defined namespace
> devices for PLIC and APLIC required to create dependency mechanism.
> However, there are concerns that every device will have to add _DEP now
> and whether it is intended for this use case. Also, actually the
> dependency is already available in the form of GSI number mapping.
> Hence, instead of explicit dependency, we would like to create implicit
> dependency. So, I will send RFC v4 series with those changes. Please
> help us with feedback. If you could provide quick high level go/no-go,
> that will help us a lot since we need to finalize the spec whether to
> mandate _DEP or not.
>
> I request you to provide some high level feedback in the RFC v4 I am
> going to send.

I will, thank you!