All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
@ 2020-11-17 13:42 ` Chen Baozi
  0 siblings, 0 replies; 22+ messages in thread
From: Chen Baozi @ 2020-11-17 13:42 UTC (permalink / raw)
  To: Ard Biesheuvel, Hanjun Guo, Marc Zyngier, Bjorn Helgaas
  Cc: linux-acpi, linux-pci, linux-arm-kernel, linux-kernel, Lorenzo Pieralisi

Some PCIe designs require software to do extra acknowledgements for
legacy INTx interrupts. If the driver is written only for device tree,
things are simple. In that case, a new driver can be written under
driver/pci/controller/ with a DT node of PCIe host written like:

  pcie {
    ...
    interrupt-map = <0 0 0  1  &pcie_intc 0>,
                    <0 0 0  2  &pcie_intc 1>,
                    <0 0 0  3  &pcie_intc 2>,
                    <0 0 0  4  &pcie_intc 3>;

    pcie_intc: legacy-interrupt-controller {
      interrupt-controller;
      #interrupt-cells = <1>;
      interrupt-parent = <&gic>;
      interrupts = <0 226 4>;
    };
  };

Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
UniPhier PCIe controller at the moment. Essentially, those designs are
supported by inserting an extra interrupt controller between PCIe host
and GIC and parse the topology in a DT-based PCI controller driver.
As we turn to ACPI, All the PCIe hosts are described the same ID of
"PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
to make this kind of PCI INTx work under ACPI.

Therefore, we introduce an stacked IRQ domain support to PCI interrupt
link for ACPI. With this support, we can populate the ResourceSource
to refer to a device object that describes an interrupt controller.
That would allow us to refer to a dedicated driver which implements
the logic needed to manage the interrupt state. With this patch,
those PCI interrupt links can be supported by describing the INTx
in ACPI table as the following example:

  Device (IXIU) {
    ...
  }

  Device(LINKA) {
    Name(_HID, EISAID("PNP0C0F"))
    Name(_PRS, ResourceTemplate(){
      Interrupt(ResourceProducer, Level, ActiveHigh, Exclusive, 0, "\\SB.IXIU")
        { 60 }
    })
    ...
  }

  Device(PCI0) {
    ...
    Name(_PRT, Package{
      Package{ 0x0000FFFF, 0, LINKA, 0 }
      ...
    })
  }

Signed-off-by: Chen Baozi <chenbaozi@phytium.com.cn>
---
 drivers/acpi/irq.c          | 22 +++++++++++++++++++++-
 drivers/acpi/pci_irq.c      |  6 ++++--
 drivers/acpi/pci_link.c     | 17 +++++++++++++++--
 include/acpi/acpi_drivers.h |  2 +-
 include/linux/acpi.h        |  4 ++++
 5 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index e209081d644b..e78a44815c44 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -81,6 +81,25 @@ void acpi_unregister_gsi(u32 gsi)
 }
 EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
 
+int acpi_register_irq(struct device *dev, u32 irq, int trigger,
+		      int polarity, struct fwnode_handle *domain_id)
+{
+	struct irq_fwspec fwspec;
+
+	if (WARN_ON(!domain_id)) {
+		pr_warn("GSI: No registered irqchip, giving up\n");
+		return -EINVAL;
+	}
+
+	fwspec.fwnode = domain_id;
+	fwspec.param[0] = irq;
+	fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
+	fwspec.param_count = 2;
+
+	return irq_create_fwspec_mapping(&fwspec);
+}
+EXPORT_SYMBOL_GPL(acpi_register_irq);
+
 /**
  * acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ resource source.
  * @source: acpi_resource_source to use for the lookup.
@@ -92,7 +111,7 @@ EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
  * Return:
  * The referenced device fwhandle or NULL on failure
  */
-static struct fwnode_handle *
+struct fwnode_handle *
 acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
 {
 	struct fwnode_handle *result;
@@ -115,6 +134,7 @@ acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
 	acpi_bus_put_acpi_device(device);
 	return result;
 }
+EXPORT_SYMBOL_GPL(acpi_get_irq_source_fwhandle);
 
 /*
  * Context for the resource walk used to lookup IRQ resources.
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 14ee631cb7cf..19296d70c95c 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -410,6 +410,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 	char *link = NULL;
 	char link_desc[16];
 	int rc;
+	struct fwnode_handle *irq_domain;
 
 	pin = dev->pin;
 	if (!pin) {
@@ -438,7 +439,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 			gsi = acpi_pci_link_allocate_irq(entry->link,
 							 entry->index,
 							 &triggering, &polarity,
-							 &link);
+							 &link,
+							 &irq_domain);
 		else
 			gsi = entry->index;
 	} else
@@ -462,7 +464,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 		return 0;
 	}
 
-	rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
+	rc = acpi_register_irq(&dev->dev, gsi, triggering, polarity, irq_domain);
 	if (rc < 0) {
 		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
 			 pin_name(pin));
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index fb4c5632a232..219a644d739a 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -59,6 +59,7 @@ struct acpi_pci_link_irq {
 	u8 resource_type;
 	u8 possible_count;
 	u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
+	struct acpi_resource_source resource_source;
 	u8 initialized:1;
 	u8 reserved:7;
 };
@@ -120,6 +121,8 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
 		{
 			struct acpi_resource_extended_irq *p =
 			    &resource->data.extended_irq;
+			struct acpi_resource_source *rs =
+			    &link->irq.resource_source;
 			if (!p || !p->interrupt_count) {
 				printk(KERN_WARNING PREFIX
 					      "Blank _PRS EXT IRQ resource\n");
@@ -140,6 +143,12 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
 			link->irq.triggering = p->triggering;
 			link->irq.polarity = p->polarity;
 			link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
+			if (p->resource_source.string_length) {
+				rs->index = p->resource_source.index;
+				rs->string_length = p->resource_source.string_length;
+				rs->string_ptr = kmalloc(rs->string_length, GFP_KERNEL);
+				strcpy(rs->string_ptr, p->resource_source.string_ptr);
+			}
 			break;
 		}
 	default:
@@ -326,7 +335,8 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
 			resource->res.data.extended_irq.shareable = ACPI_SHARED;
 		resource->res.data.extended_irq.interrupt_count = 1;
 		resource->res.data.extended_irq.interrupts[0] = irq;
-		/* ignore resource_source, it's optional */
+		resource->res.data.extended_irq.resource_source =
+			link->irq.resource_source;
 		break;
 	default:
 		printk(KERN_ERR PREFIX "Invalid Resource_type %d\n", link->irq.resource_type);
@@ -612,7 +622,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
  * failure: return -1
  */
 int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
-			       int *polarity, char **name)
+			       int *polarity, char **name, struct fwnode_handle **irq_domain)
 {
 	int result;
 	struct acpi_device *device;
@@ -656,6 +666,9 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
 		*polarity = link->irq.polarity;
 	if (name)
 		*name = acpi_device_bid(link->device);
+	if (irq_domain)
+		*irq_domain = acpi_get_irq_source_fwhandle(&link->irq.resource_source);
+
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 			  "Link %s is referenced\n",
 			  acpi_device_bid(link->device)));
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index 5eb175933a5b..6ff1ea76d476 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -68,7 +68,7 @@
 
 int acpi_irq_penalty_init(void);
 int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
-			       int *polarity, char **name);
+			       int *polarity, char **name, struct fwnode_handle **irq_domain);
 int acpi_pci_link_free_irq(acpi_handle handle);
 
 /* ACPI PCI Device Binding (pci_bind.c) */
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 39263c6b52e1..5f1d7d3192fb 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -324,6 +324,8 @@ extern int sbf_port;
 extern unsigned long acpi_realmode_flags;
 
 int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
+int acpi_register_irq(struct device *dev, u32 gsi, int trigger,
+		      int polarity, struct fwnode_handle *domain_id);
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
 
@@ -336,6 +338,8 @@ struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
 					     const struct irq_domain_ops *ops,
 					     void *host_data);
 
+struct fwnode_handle *acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source);
+
 #ifdef CONFIG_X86_IO_APIC
 extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
 #else
-- 
2.28.0


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

* [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
@ 2020-11-17 13:42 ` Chen Baozi
  0 siblings, 0 replies; 22+ messages in thread
From: Chen Baozi @ 2020-11-17 13:42 UTC (permalink / raw)
  To: Ard Biesheuvel, Hanjun Guo, Marc Zyngier, Bjorn Helgaas
  Cc: linux-acpi, Lorenzo Pieralisi, linux-kernel, linux-arm-kernel, linux-pci

Some PCIe designs require software to do extra acknowledgements for
legacy INTx interrupts. If the driver is written only for device tree,
things are simple. In that case, a new driver can be written under
driver/pci/controller/ with a DT node of PCIe host written like:

  pcie {
    ...
    interrupt-map = <0 0 0  1  &pcie_intc 0>,
                    <0 0 0  2  &pcie_intc 1>,
                    <0 0 0  3  &pcie_intc 2>,
                    <0 0 0  4  &pcie_intc 3>;

    pcie_intc: legacy-interrupt-controller {
      interrupt-controller;
      #interrupt-cells = <1>;
      interrupt-parent = <&gic>;
      interrupts = <0 226 4>;
    };
  };

Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
UniPhier PCIe controller at the moment. Essentially, those designs are
supported by inserting an extra interrupt controller between PCIe host
and GIC and parse the topology in a DT-based PCI controller driver.
As we turn to ACPI, All the PCIe hosts are described the same ID of
"PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
to make this kind of PCI INTx work under ACPI.

Therefore, we introduce an stacked IRQ domain support to PCI interrupt
link for ACPI. With this support, we can populate the ResourceSource
to refer to a device object that describes an interrupt controller.
That would allow us to refer to a dedicated driver which implements
the logic needed to manage the interrupt state. With this patch,
those PCI interrupt links can be supported by describing the INTx
in ACPI table as the following example:

  Device (IXIU) {
    ...
  }

  Device(LINKA) {
    Name(_HID, EISAID("PNP0C0F"))
    Name(_PRS, ResourceTemplate(){
      Interrupt(ResourceProducer, Level, ActiveHigh, Exclusive, 0, "\\SB.IXIU")
        { 60 }
    })
    ...
  }

  Device(PCI0) {
    ...
    Name(_PRT, Package{
      Package{ 0x0000FFFF, 0, LINKA, 0 }
      ...
    })
  }

Signed-off-by: Chen Baozi <chenbaozi@phytium.com.cn>
---
 drivers/acpi/irq.c          | 22 +++++++++++++++++++++-
 drivers/acpi/pci_irq.c      |  6 ++++--
 drivers/acpi/pci_link.c     | 17 +++++++++++++++--
 include/acpi/acpi_drivers.h |  2 +-
 include/linux/acpi.h        |  4 ++++
 5 files changed, 45 insertions(+), 6 deletions(-)

diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index e209081d644b..e78a44815c44 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -81,6 +81,25 @@ void acpi_unregister_gsi(u32 gsi)
 }
 EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
 
+int acpi_register_irq(struct device *dev, u32 irq, int trigger,
+		      int polarity, struct fwnode_handle *domain_id)
+{
+	struct irq_fwspec fwspec;
+
+	if (WARN_ON(!domain_id)) {
+		pr_warn("GSI: No registered irqchip, giving up\n");
+		return -EINVAL;
+	}
+
+	fwspec.fwnode = domain_id;
+	fwspec.param[0] = irq;
+	fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
+	fwspec.param_count = 2;
+
+	return irq_create_fwspec_mapping(&fwspec);
+}
+EXPORT_SYMBOL_GPL(acpi_register_irq);
+
 /**
  * acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ resource source.
  * @source: acpi_resource_source to use for the lookup.
@@ -92,7 +111,7 @@ EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
  * Return:
  * The referenced device fwhandle or NULL on failure
  */
-static struct fwnode_handle *
+struct fwnode_handle *
 acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
 {
 	struct fwnode_handle *result;
@@ -115,6 +134,7 @@ acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
 	acpi_bus_put_acpi_device(device);
 	return result;
 }
+EXPORT_SYMBOL_GPL(acpi_get_irq_source_fwhandle);
 
 /*
  * Context for the resource walk used to lookup IRQ resources.
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 14ee631cb7cf..19296d70c95c 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -410,6 +410,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 	char *link = NULL;
 	char link_desc[16];
 	int rc;
+	struct fwnode_handle *irq_domain;
 
 	pin = dev->pin;
 	if (!pin) {
@@ -438,7 +439,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 			gsi = acpi_pci_link_allocate_irq(entry->link,
 							 entry->index,
 							 &triggering, &polarity,
-							 &link);
+							 &link,
+							 &irq_domain);
 		else
 			gsi = entry->index;
 	} else
@@ -462,7 +464,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
 		return 0;
 	}
 
-	rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
+	rc = acpi_register_irq(&dev->dev, gsi, triggering, polarity, irq_domain);
 	if (rc < 0) {
 		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
 			 pin_name(pin));
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
index fb4c5632a232..219a644d739a 100644
--- a/drivers/acpi/pci_link.c
+++ b/drivers/acpi/pci_link.c
@@ -59,6 +59,7 @@ struct acpi_pci_link_irq {
 	u8 resource_type;
 	u8 possible_count;
 	u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
+	struct acpi_resource_source resource_source;
 	u8 initialized:1;
 	u8 reserved:7;
 };
@@ -120,6 +121,8 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
 		{
 			struct acpi_resource_extended_irq *p =
 			    &resource->data.extended_irq;
+			struct acpi_resource_source *rs =
+			    &link->irq.resource_source;
 			if (!p || !p->interrupt_count) {
 				printk(KERN_WARNING PREFIX
 					      "Blank _PRS EXT IRQ resource\n");
@@ -140,6 +143,12 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
 			link->irq.triggering = p->triggering;
 			link->irq.polarity = p->polarity;
 			link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
+			if (p->resource_source.string_length) {
+				rs->index = p->resource_source.index;
+				rs->string_length = p->resource_source.string_length;
+				rs->string_ptr = kmalloc(rs->string_length, GFP_KERNEL);
+				strcpy(rs->string_ptr, p->resource_source.string_ptr);
+			}
 			break;
 		}
 	default:
@@ -326,7 +335,8 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
 			resource->res.data.extended_irq.shareable = ACPI_SHARED;
 		resource->res.data.extended_irq.interrupt_count = 1;
 		resource->res.data.extended_irq.interrupts[0] = irq;
-		/* ignore resource_source, it's optional */
+		resource->res.data.extended_irq.resource_source =
+			link->irq.resource_source;
 		break;
 	default:
 		printk(KERN_ERR PREFIX "Invalid Resource_type %d\n", link->irq.resource_type);
@@ -612,7 +622,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
  * failure: return -1
  */
 int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
-			       int *polarity, char **name)
+			       int *polarity, char **name, struct fwnode_handle **irq_domain)
 {
 	int result;
 	struct acpi_device *device;
@@ -656,6 +666,9 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
 		*polarity = link->irq.polarity;
 	if (name)
 		*name = acpi_device_bid(link->device);
+	if (irq_domain)
+		*irq_domain = acpi_get_irq_source_fwhandle(&link->irq.resource_source);
+
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 			  "Link %s is referenced\n",
 			  acpi_device_bid(link->device)));
diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
index 5eb175933a5b..6ff1ea76d476 100644
--- a/include/acpi/acpi_drivers.h
+++ b/include/acpi/acpi_drivers.h
@@ -68,7 +68,7 @@
 
 int acpi_irq_penalty_init(void);
 int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
-			       int *polarity, char **name);
+			       int *polarity, char **name, struct fwnode_handle **irq_domain);
 int acpi_pci_link_free_irq(acpi_handle handle);
 
 /* ACPI PCI Device Binding (pci_bind.c) */
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 39263c6b52e1..5f1d7d3192fb 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -324,6 +324,8 @@ extern int sbf_port;
 extern unsigned long acpi_realmode_flags;
 
 int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
+int acpi_register_irq(struct device *dev, u32 gsi, int trigger,
+		      int polarity, struct fwnode_handle *domain_id);
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
 
@@ -336,6 +338,8 @@ struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
 					     const struct irq_domain_ops *ops,
 					     void *host_data);
 
+struct fwnode_handle *acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source);
+
 #ifdef CONFIG_X86_IO_APIC
 extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
 #else
-- 
2.28.0


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
  2020-11-17 13:42 ` Chen Baozi
@ 2020-11-17 18:57   ` Bjorn Helgaas
  -1 siblings, 0 replies; 22+ messages in thread
From: Bjorn Helgaas @ 2020-11-17 18:57 UTC (permalink / raw)
  To: Chen Baozi
  Cc: Ard Biesheuvel, Hanjun Guo, Marc Zyngier, Bjorn Helgaas,
	linux-acpi, linux-pci, linux-arm-kernel, linux-kernel,
	Lorenzo Pieralisi

Nit: please don't just make up random styles for the subject.  Run
"git log --oneline" on the file and/or the directory and try to follow
the existing convention.  Using random styles adds noise to the
system.

On Tue, Nov 17, 2020 at 09:42:14PM +0800, Chen Baozi wrote:
> Some PCIe designs require software to do extra acknowledgements for
> legacy INTx interrupts. If the driver is written only for device tree,
> things are simple. In that case, a new driver can be written under
> driver/pci/controller/ with a DT node of PCIe host written like:
> 
>   pcie {
>     ...
>     interrupt-map = <0 0 0  1  &pcie_intc 0>,
>                     <0 0 0  2  &pcie_intc 1>,
>                     <0 0 0  3  &pcie_intc 2>,
>                     <0 0 0  4  &pcie_intc 3>;
> 
>     pcie_intc: legacy-interrupt-controller {
>       interrupt-controller;
>       #interrupt-cells = <1>;
>       interrupt-parent = <&gic>;
>       interrupts = <0 226 4>;
>     };
>   };
> 
> Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
> UniPhier PCIe controller at the moment. Essentially, those designs are
> supported by inserting an extra interrupt controller between PCIe host
> and GIC and parse the topology in a DT-based PCI controller driver.

If I understand correctly, we previously ignored the Resource Source
field of an Extended Interrupt Descriptor in the _PRS method of
PNP0C0F PCI Interrupt Link devices, and this patch adds support for
it.

If that's true, this has nothing to do with DT, other than DT being
another way to describe the same topology, and the above details
really aren't relevant to this patch.

> As we turn to ACPI, All the PCIe hosts are described the same ID of
> "PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
> to make this kind of PCI INTx work under ACPI.

s/All the PCIe/all the PCIe/

But this paragraph should probably just go away in favor of something
about implementing Resource Source support.

> Therefore, we introduce an stacked IRQ domain support to PCI interrupt
> link for ACPI. With this support, we can populate the ResourceSource
> to refer to a device object that describes an interrupt controller.
> That would allow us to refer to a dedicated driver which implements
> the logic needed to manage the interrupt state. With this patch,
> those PCI interrupt links can be supported by describing the INTx
> in ACPI table as the following example:

"Stacked IRQ domain" sounds like a detail of how you're implementing
support for the Resource Source field for PCI Interrupt Links.

I don't know what the dedicated driver refers to.  This *should* be
all generic code the follows the ACPI spec (which is pretty sketchy in
this area).  But I assume that there's no special driver needed for
devices like \SB.IXIU, and the logic associated with the interrupt
controller is in the AML associated with IXIU.  It would probably be
useful to mention the relevant methods in the IXIU methods in the
example below.

From ACPI v6.3, Table 6-200, it looks like this patch should include
changes to acpi_bus_osc_support() to advertise "Interrupt
ResourceSource support".

>   Device (IXIU) {
>     ...
>   }
> 
>   Device(LINKA) {
>     Name(_HID, EISAID("PNP0C0F"))
>     Name(_PRS, ResourceTemplate(){
>       Interrupt(ResourceProducer, Level, ActiveHigh, Exclusive, 0, "\\SB.IXIU")
>         { 60 }
>     })
>     ...
>   }
> 
>   Device(PCI0) {
>     ...
>     Name(_PRT, Package{
>       Package{ 0x0000FFFF, 0, LINKA, 0 }
>       ...
>     })
>   }
> 
> Signed-off-by: Chen Baozi <chenbaozi@phytium.com.cn>
> ---
>  drivers/acpi/irq.c          | 22 +++++++++++++++++++++-
>  drivers/acpi/pci_irq.c      |  6 ++++--
>  drivers/acpi/pci_link.c     | 17 +++++++++++++++--
>  include/acpi/acpi_drivers.h |  2 +-
>  include/linux/acpi.h        |  4 ++++
>  5 files changed, 45 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
> index e209081d644b..e78a44815c44 100644
> --- a/drivers/acpi/irq.c
> +++ b/drivers/acpi/irq.c
> @@ -81,6 +81,25 @@ void acpi_unregister_gsi(u32 gsi)
>  }
>  EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
>  
> +int acpi_register_irq(struct device *dev, u32 irq, int trigger,
> +		      int polarity, struct fwnode_handle *domain_id)
> +{
> +	struct irq_fwspec fwspec;
> +
> +	if (WARN_ON(!domain_id)) {
> +		pr_warn("GSI: No registered irqchip, giving up\n");

This message could contain more information, e.g., by using
dev_warn(), including the irq value, etc.

> +		return -EINVAL;
> +	}
> +
> +	fwspec.fwnode = domain_id;
> +	fwspec.param[0] = irq;
> +	fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
> +	fwspec.param_count = 2;
> +
> +	return irq_create_fwspec_mapping(&fwspec);
> +}
> +EXPORT_SYMBOL_GPL(acpi_register_irq);

Why does this need to be exported?  You only call it from
acpi_pci_irq_enable(), which cannot be a module.

>  /**
>   * acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ resource source.
>   * @source: acpi_resource_source to use for the lookup.
> @@ -92,7 +111,7 @@ EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
>   * Return:
>   * The referenced device fwhandle or NULL on failure
>   */
> -static struct fwnode_handle *
> +struct fwnode_handle *
>  acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
>  {
>  	struct fwnode_handle *result;
> @@ -115,6 +134,7 @@ acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
>  	acpi_bus_put_acpi_device(device);
>  	return result;
>  }
> +EXPORT_SYMBOL_GPL(acpi_get_irq_source_fwhandle);

This doesn't look like it needs to be exported either.

>  /*
>   * Context for the resource walk used to lookup IRQ resources.
> diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
> index 14ee631cb7cf..19296d70c95c 100644
> --- a/drivers/acpi/pci_irq.c
> +++ b/drivers/acpi/pci_irq.c
> @@ -410,6 +410,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  	char *link = NULL;
>  	char link_desc[16];
>  	int rc;
> +	struct fwnode_handle *irq_domain;
>  
>  	pin = dev->pin;
>  	if (!pin) {
> @@ -438,7 +439,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  			gsi = acpi_pci_link_allocate_irq(entry->link,
>  							 entry->index,
>  							 &triggering, &polarity,
> -							 &link);
> +							 &link,
> +							 &irq_domain);
>  		else
>  			gsi = entry->index;
>  	} else
> @@ -462,7 +464,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  		return 0;
>  	}
>  
> -	rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
> +	rc = acpi_register_irq(&dev->dev, gsi, triggering, polarity, irq_domain);
>  	if (rc < 0) {
>  		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
>  			 pin_name(pin));
> diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
> index fb4c5632a232..219a644d739a 100644
> --- a/drivers/acpi/pci_link.c
> +++ b/drivers/acpi/pci_link.c
> @@ -59,6 +59,7 @@ struct acpi_pci_link_irq {
>  	u8 resource_type;
>  	u8 possible_count;
>  	u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
> +	struct acpi_resource_source resource_source;
>  	u8 initialized:1;
>  	u8 reserved:7;
>  };
> @@ -120,6 +121,8 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
>  		{
>  			struct acpi_resource_extended_irq *p =
>  			    &resource->data.extended_irq;
> +			struct acpi_resource_source *rs =
> +			    &link->irq.resource_source;
>  			if (!p || !p->interrupt_count) {
>  				printk(KERN_WARNING PREFIX
>  					      "Blank _PRS EXT IRQ resource\n");
> @@ -140,6 +143,12 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
>  			link->irq.triggering = p->triggering;
>  			link->irq.polarity = p->polarity;
>  			link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
> +			if (p->resource_source.string_length) {
> +				rs->index = p->resource_source.index;
> +				rs->string_length = p->resource_source.string_length;
> +				rs->string_ptr = kmalloc(rs->string_length, GFP_KERNEL);
> +				strcpy(rs->string_ptr, p->resource_source.string_ptr);
> +			}
>  			break;
>  		}
>  	default:
> @@ -326,7 +335,8 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
>  			resource->res.data.extended_irq.shareable = ACPI_SHARED;
>  		resource->res.data.extended_irq.interrupt_count = 1;
>  		resource->res.data.extended_irq.interrupts[0] = irq;
> -		/* ignore resource_source, it's optional */
> +		resource->res.data.extended_irq.resource_source =
> +			link->irq.resource_source;
>  		break;
>  	default:
>  		printk(KERN_ERR PREFIX "Invalid Resource_type %d\n", link->irq.resource_type);
> @@ -612,7 +622,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
>   * failure: return -1
>   */
>  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
> -			       int *polarity, char **name)
> +			       int *polarity, char **name, struct fwnode_handle **irq_domain)
>  {
>  	int result;
>  	struct acpi_device *device;
> @@ -656,6 +666,9 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
>  		*polarity = link->irq.polarity;
>  	if (name)
>  		*name = acpi_device_bid(link->device);
> +	if (irq_domain)
> +		*irq_domain = acpi_get_irq_source_fwhandle(&link->irq.resource_source);
> +
>  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
>  			  "Link %s is referenced\n",
>  			  acpi_device_bid(link->device)));
> diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
> index 5eb175933a5b..6ff1ea76d476 100644
> --- a/include/acpi/acpi_drivers.h
> +++ b/include/acpi/acpi_drivers.h
> @@ -68,7 +68,7 @@
>  
>  int acpi_irq_penalty_init(void);
>  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
> -			       int *polarity, char **name);
> +			       int *polarity, char **name, struct fwnode_handle **irq_domain);
>  int acpi_pci_link_free_irq(acpi_handle handle);
>  
>  /* ACPI PCI Device Binding (pci_bind.c) */
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 39263c6b52e1..5f1d7d3192fb 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -324,6 +324,8 @@ extern int sbf_port;
>  extern unsigned long acpi_realmode_flags;
>  
>  int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
> +int acpi_register_irq(struct device *dev, u32 gsi, int trigger,
> +		      int polarity, struct fwnode_handle *domain_id);

It looks like this declaration should be in drivers/acpi/internal.h,
since it's only used inside drivers/acpi/.

>  int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
>  int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
>  
> @@ -336,6 +338,8 @@ struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
>  					     const struct irq_domain_ops *ops,
>  					     void *host_data);
>  
> +struct fwnode_handle *acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source);
> +
>  #ifdef CONFIG_X86_IO_APIC
>  extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
>  #else
> -- 
> 2.28.0
> 

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
@ 2020-11-17 18:57   ` Bjorn Helgaas
  0 siblings, 0 replies; 22+ messages in thread
From: Bjorn Helgaas @ 2020-11-17 18:57 UTC (permalink / raw)
  To: Chen Baozi
  Cc: Lorenzo Pieralisi, Marc Zyngier, Hanjun Guo, linux-kernel,
	linux-acpi, linux-pci, Bjorn Helgaas, Ard Biesheuvel,
	linux-arm-kernel

Nit: please don't just make up random styles for the subject.  Run
"git log --oneline" on the file and/or the directory and try to follow
the existing convention.  Using random styles adds noise to the
system.

On Tue, Nov 17, 2020 at 09:42:14PM +0800, Chen Baozi wrote:
> Some PCIe designs require software to do extra acknowledgements for
> legacy INTx interrupts. If the driver is written only for device tree,
> things are simple. In that case, a new driver can be written under
> driver/pci/controller/ with a DT node of PCIe host written like:
> 
>   pcie {
>     ...
>     interrupt-map = <0 0 0  1  &pcie_intc 0>,
>                     <0 0 0  2  &pcie_intc 1>,
>                     <0 0 0  3  &pcie_intc 2>,
>                     <0 0 0  4  &pcie_intc 3>;
> 
>     pcie_intc: legacy-interrupt-controller {
>       interrupt-controller;
>       #interrupt-cells = <1>;
>       interrupt-parent = <&gic>;
>       interrupts = <0 226 4>;
>     };
>   };
> 
> Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
> UniPhier PCIe controller at the moment. Essentially, those designs are
> supported by inserting an extra interrupt controller between PCIe host
> and GIC and parse the topology in a DT-based PCI controller driver.

If I understand correctly, we previously ignored the Resource Source
field of an Extended Interrupt Descriptor in the _PRS method of
PNP0C0F PCI Interrupt Link devices, and this patch adds support for
it.

If that's true, this has nothing to do with DT, other than DT being
another way to describe the same topology, and the above details
really aren't relevant to this patch.

> As we turn to ACPI, All the PCIe hosts are described the same ID of
> "PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
> to make this kind of PCI INTx work under ACPI.

s/All the PCIe/all the PCIe/

But this paragraph should probably just go away in favor of something
about implementing Resource Source support.

> Therefore, we introduce an stacked IRQ domain support to PCI interrupt
> link for ACPI. With this support, we can populate the ResourceSource
> to refer to a device object that describes an interrupt controller.
> That would allow us to refer to a dedicated driver which implements
> the logic needed to manage the interrupt state. With this patch,
> those PCI interrupt links can be supported by describing the INTx
> in ACPI table as the following example:

"Stacked IRQ domain" sounds like a detail of how you're implementing
support for the Resource Source field for PCI Interrupt Links.

I don't know what the dedicated driver refers to.  This *should* be
all generic code the follows the ACPI spec (which is pretty sketchy in
this area).  But I assume that there's no special driver needed for
devices like \SB.IXIU, and the logic associated with the interrupt
controller is in the AML associated with IXIU.  It would probably be
useful to mention the relevant methods in the IXIU methods in the
example below.

From ACPI v6.3, Table 6-200, it looks like this patch should include
changes to acpi_bus_osc_support() to advertise "Interrupt
ResourceSource support".

>   Device (IXIU) {
>     ...
>   }
> 
>   Device(LINKA) {
>     Name(_HID, EISAID("PNP0C0F"))
>     Name(_PRS, ResourceTemplate(){
>       Interrupt(ResourceProducer, Level, ActiveHigh, Exclusive, 0, "\\SB.IXIU")
>         { 60 }
>     })
>     ...
>   }
> 
>   Device(PCI0) {
>     ...
>     Name(_PRT, Package{
>       Package{ 0x0000FFFF, 0, LINKA, 0 }
>       ...
>     })
>   }
> 
> Signed-off-by: Chen Baozi <chenbaozi@phytium.com.cn>
> ---
>  drivers/acpi/irq.c          | 22 +++++++++++++++++++++-
>  drivers/acpi/pci_irq.c      |  6 ++++--
>  drivers/acpi/pci_link.c     | 17 +++++++++++++++--
>  include/acpi/acpi_drivers.h |  2 +-
>  include/linux/acpi.h        |  4 ++++
>  5 files changed, 45 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
> index e209081d644b..e78a44815c44 100644
> --- a/drivers/acpi/irq.c
> +++ b/drivers/acpi/irq.c
> @@ -81,6 +81,25 @@ void acpi_unregister_gsi(u32 gsi)
>  }
>  EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
>  
> +int acpi_register_irq(struct device *dev, u32 irq, int trigger,
> +		      int polarity, struct fwnode_handle *domain_id)
> +{
> +	struct irq_fwspec fwspec;
> +
> +	if (WARN_ON(!domain_id)) {
> +		pr_warn("GSI: No registered irqchip, giving up\n");

This message could contain more information, e.g., by using
dev_warn(), including the irq value, etc.

> +		return -EINVAL;
> +	}
> +
> +	fwspec.fwnode = domain_id;
> +	fwspec.param[0] = irq;
> +	fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
> +	fwspec.param_count = 2;
> +
> +	return irq_create_fwspec_mapping(&fwspec);
> +}
> +EXPORT_SYMBOL_GPL(acpi_register_irq);

Why does this need to be exported?  You only call it from
acpi_pci_irq_enable(), which cannot be a module.

>  /**
>   * acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ resource source.
>   * @source: acpi_resource_source to use for the lookup.
> @@ -92,7 +111,7 @@ EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
>   * Return:
>   * The referenced device fwhandle or NULL on failure
>   */
> -static struct fwnode_handle *
> +struct fwnode_handle *
>  acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
>  {
>  	struct fwnode_handle *result;
> @@ -115,6 +134,7 @@ acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
>  	acpi_bus_put_acpi_device(device);
>  	return result;
>  }
> +EXPORT_SYMBOL_GPL(acpi_get_irq_source_fwhandle);

This doesn't look like it needs to be exported either.

>  /*
>   * Context for the resource walk used to lookup IRQ resources.
> diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
> index 14ee631cb7cf..19296d70c95c 100644
> --- a/drivers/acpi/pci_irq.c
> +++ b/drivers/acpi/pci_irq.c
> @@ -410,6 +410,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  	char *link = NULL;
>  	char link_desc[16];
>  	int rc;
> +	struct fwnode_handle *irq_domain;
>  
>  	pin = dev->pin;
>  	if (!pin) {
> @@ -438,7 +439,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  			gsi = acpi_pci_link_allocate_irq(entry->link,
>  							 entry->index,
>  							 &triggering, &polarity,
> -							 &link);
> +							 &link,
> +							 &irq_domain);
>  		else
>  			gsi = entry->index;
>  	} else
> @@ -462,7 +464,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  		return 0;
>  	}
>  
> -	rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
> +	rc = acpi_register_irq(&dev->dev, gsi, triggering, polarity, irq_domain);
>  	if (rc < 0) {
>  		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
>  			 pin_name(pin));
> diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
> index fb4c5632a232..219a644d739a 100644
> --- a/drivers/acpi/pci_link.c
> +++ b/drivers/acpi/pci_link.c
> @@ -59,6 +59,7 @@ struct acpi_pci_link_irq {
>  	u8 resource_type;
>  	u8 possible_count;
>  	u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
> +	struct acpi_resource_source resource_source;
>  	u8 initialized:1;
>  	u8 reserved:7;
>  };
> @@ -120,6 +121,8 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
>  		{
>  			struct acpi_resource_extended_irq *p =
>  			    &resource->data.extended_irq;
> +			struct acpi_resource_source *rs =
> +			    &link->irq.resource_source;
>  			if (!p || !p->interrupt_count) {
>  				printk(KERN_WARNING PREFIX
>  					      "Blank _PRS EXT IRQ resource\n");
> @@ -140,6 +143,12 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
>  			link->irq.triggering = p->triggering;
>  			link->irq.polarity = p->polarity;
>  			link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
> +			if (p->resource_source.string_length) {
> +				rs->index = p->resource_source.index;
> +				rs->string_length = p->resource_source.string_length;
> +				rs->string_ptr = kmalloc(rs->string_length, GFP_KERNEL);
> +				strcpy(rs->string_ptr, p->resource_source.string_ptr);
> +			}
>  			break;
>  		}
>  	default:
> @@ -326,7 +335,8 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
>  			resource->res.data.extended_irq.shareable = ACPI_SHARED;
>  		resource->res.data.extended_irq.interrupt_count = 1;
>  		resource->res.data.extended_irq.interrupts[0] = irq;
> -		/* ignore resource_source, it's optional */
> +		resource->res.data.extended_irq.resource_source =
> +			link->irq.resource_source;
>  		break;
>  	default:
>  		printk(KERN_ERR PREFIX "Invalid Resource_type %d\n", link->irq.resource_type);
> @@ -612,7 +622,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
>   * failure: return -1
>   */
>  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
> -			       int *polarity, char **name)
> +			       int *polarity, char **name, struct fwnode_handle **irq_domain)
>  {
>  	int result;
>  	struct acpi_device *device;
> @@ -656,6 +666,9 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
>  		*polarity = link->irq.polarity;
>  	if (name)
>  		*name = acpi_device_bid(link->device);
> +	if (irq_domain)
> +		*irq_domain = acpi_get_irq_source_fwhandle(&link->irq.resource_source);
> +
>  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
>  			  "Link %s is referenced\n",
>  			  acpi_device_bid(link->device)));
> diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
> index 5eb175933a5b..6ff1ea76d476 100644
> --- a/include/acpi/acpi_drivers.h
> +++ b/include/acpi/acpi_drivers.h
> @@ -68,7 +68,7 @@
>  
>  int acpi_irq_penalty_init(void);
>  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
> -			       int *polarity, char **name);
> +			       int *polarity, char **name, struct fwnode_handle **irq_domain);
>  int acpi_pci_link_free_irq(acpi_handle handle);
>  
>  /* ACPI PCI Device Binding (pci_bind.c) */
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 39263c6b52e1..5f1d7d3192fb 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -324,6 +324,8 @@ extern int sbf_port;
>  extern unsigned long acpi_realmode_flags;
>  
>  int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
> +int acpi_register_irq(struct device *dev, u32 gsi, int trigger,
> +		      int polarity, struct fwnode_handle *domain_id);

It looks like this declaration should be in drivers/acpi/internal.h,
since it's only used inside drivers/acpi/.

>  int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
>  int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
>  
> @@ -336,6 +338,8 @@ struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
>  					     const struct irq_domain_ops *ops,
>  					     void *host_data);
>  
> +struct fwnode_handle *acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source);
> +
>  #ifdef CONFIG_X86_IO_APIC
>  extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
>  #else
> -- 
> 2.28.0
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
  2020-11-17 13:42 ` Chen Baozi
  (?)
  (?)
@ 2020-11-17 20:01 ` kernel test robot
  -1 siblings, 0 replies; 22+ messages in thread
From: kernel test robot @ 2020-11-17 20:01 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 3652 bytes --]

Hi Chen,

[FYI, it's a private test report for your RFC patch.]
[auto build test ERROR on pm/linux-next]
[also build test ERROR on pci/next v5.10-rc4 next-20201117]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Chen-Baozi/acpi-irq-Add-stacked-IRQ-domain-support-to-PCI-interrupt-link/20201117-214552
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
config: i386-randconfig-r036-20201117 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/76f0a22bc937647cd1ee87ee48b2caf44e72030a
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Chen-Baozi/acpi-irq-Add-stacked-IRQ-domain-support-to-PCI-interrupt-link/20201117-214552
        git checkout 76f0a22bc937647cd1ee87ee48b2caf44e72030a
        # save the attached .config to linux build tree
        make W=1 ARCH=i386 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   ld: drivers/acpi/pci_link.o: in function `acpi_pci_link_allocate_irq':
>> drivers/acpi/pci_link.c:670: undefined reference to `acpi_get_irq_source_fwhandle'
   ld: drivers/acpi/pci_irq.o: in function `acpi_pci_irq_enable':
>> drivers/acpi/pci_irq.c:467: undefined reference to `acpi_register_irq'

vim +670 drivers/acpi/pci_link.c

   618	
   619	/*
   620	 * acpi_pci_link_allocate_irq
   621	 * success: return IRQ >= 0
   622	 * failure: return -1
   623	 */
   624	int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
   625				       int *polarity, char **name, struct fwnode_handle **irq_domain)
   626	{
   627		int result;
   628		struct acpi_device *device;
   629		struct acpi_pci_link *link;
   630	
   631		result = acpi_bus_get_device(handle, &device);
   632		if (result) {
   633			printk(KERN_ERR PREFIX "Invalid link device\n");
   634			return -1;
   635		}
   636	
   637		link = acpi_driver_data(device);
   638		if (!link) {
   639			printk(KERN_ERR PREFIX "Invalid link context\n");
   640			return -1;
   641		}
   642	
   643		/* TBD: Support multiple index (IRQ) entries per Link Device */
   644		if (index) {
   645			printk(KERN_ERR PREFIX "Invalid index %d\n", index);
   646			return -1;
   647		}
   648	
   649		mutex_lock(&acpi_link_lock);
   650		if (acpi_pci_link_allocate(link)) {
   651			mutex_unlock(&acpi_link_lock);
   652			return -1;
   653		}
   654	
   655		if (!link->irq.active) {
   656			mutex_unlock(&acpi_link_lock);
   657			printk(KERN_ERR PREFIX "Link active IRQ is 0!\n");
   658			return -1;
   659		}
   660		link->refcnt++;
   661		mutex_unlock(&acpi_link_lock);
   662	
   663		if (triggering)
   664			*triggering = link->irq.triggering;
   665		if (polarity)
   666			*polarity = link->irq.polarity;
   667		if (name)
   668			*name = acpi_device_bid(link->device);
   669		if (irq_domain)
 > 670			*irq_domain = acpi_get_irq_source_fwhandle(&link->irq.resource_source);
   671	
   672		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
   673				  "Link %s is referenced\n",
   674				  acpi_device_bid(link->device)));
   675		return link->irq.active;
   676	}
   677	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 34709 bytes --]

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
  2020-11-17 13:42 ` Chen Baozi
@ 2020-11-18  9:27   ` Marc Zyngier
  -1 siblings, 0 replies; 22+ messages in thread
From: Marc Zyngier @ 2020-11-18  9:27 UTC (permalink / raw)
  To: Chen Baozi
  Cc: Ard Biesheuvel, Hanjun Guo, Bjorn Helgaas, linux-acpi, linux-pci,
	linux-arm-kernel, linux-kernel, Lorenzo Pieralisi

Hi Chen,

On top of Bjorn's comments:

On 2020-11-17 13:42, Chen Baozi wrote:
> Some PCIe designs require software to do extra acknowledgements for
> legacy INTx interrupts. If the driver is written only for device tree,
> things are simple. In that case, a new driver can be written under
> driver/pci/controller/ with a DT node of PCIe host written like:
> 
>   pcie {
>     ...
>     interrupt-map = <0 0 0  1  &pcie_intc 0>,
>                     <0 0 0  2  &pcie_intc 1>,
>                     <0 0 0  3  &pcie_intc 2>,
>                     <0 0 0  4  &pcie_intc 3>;
> 
>     pcie_intc: legacy-interrupt-controller {
>       interrupt-controller;
>       #interrupt-cells = <1>;
>       interrupt-parent = <&gic>;
>       interrupts = <0 226 4>;
>     };
>   };
> 
> Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
> UniPhier PCIe controller at the moment. Essentially, those designs are
> supported by inserting an extra interrupt controller between PCIe host
> and GIC and parse the topology in a DT-based PCI controller driver.
> As we turn to ACPI, All the PCIe hosts are described the same ID of
> "PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
> to make this kind of PCI INTx work under ACPI.
> 
> Therefore, we introduce an stacked IRQ domain support to PCI interrupt
> link for ACPI. With this support, we can populate the ResourceSource
> to refer to a device object that describes an interrupt controller.
> That would allow us to refer to a dedicated driver which implements
> the logic needed to manage the interrupt state. With this patch,
> those PCI interrupt links can be supported by describing the INTx
> in ACPI table as the following example:
> 
>   Device (IXIU) {
>     ...
>   }
> 
>   Device(LINKA) {
>     Name(_HID, EISAID("PNP0C0F"))
>     Name(_PRS, ResourceTemplate(){
>       Interrupt(ResourceProducer, Level, ActiveHigh, Exclusive, 0, 
> "\\SB.IXIU")
>         { 60 }
>     })
>     ...
>   }
> 
>   Device(PCI0) {
>     ...
>     Name(_PRT, Package{
>       Package{ 0x0000FFFF, 0, LINKA, 0 }
>       ...
>     })
>   }
> 
> Signed-off-by: Chen Baozi <chenbaozi@phytium.com.cn>
> ---
>  drivers/acpi/irq.c          | 22 +++++++++++++++++++++-
>  drivers/acpi/pci_irq.c      |  6 ++++--
>  drivers/acpi/pci_link.c     | 17 +++++++++++++++--
>  include/acpi/acpi_drivers.h |  2 +-
>  include/linux/acpi.h        |  4 ++++
>  5 files changed, 45 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
> index e209081d644b..e78a44815c44 100644
> --- a/drivers/acpi/irq.c
> +++ b/drivers/acpi/irq.c
> @@ -81,6 +81,25 @@ void acpi_unregister_gsi(u32 gsi)
>  }
>  EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
> 
> +int acpi_register_irq(struct device *dev, u32 irq, int trigger,
> +		      int polarity, struct fwnode_handle *domain_id)
> +{
> +	struct irq_fwspec fwspec;
> +
> +	if (WARN_ON(!domain_id)) {
> +		pr_warn("GSI: No registered irqchip, giving up\n");

A fwnode_handle is not an irqchip. It's just an opaque identifier
for a HW block. Furthermore, there is no need to have both a WARN_ON()
and a pr_warn(). Please pick one.

I'd also suggest you rename domain_id to fwnode, which is the commonly
used idiom (yes, I know about the unfortunate precedent in 
acpi_register_gsi()).

> +		return -EINVAL;
> +	}
> +
> +	fwspec.fwnode = domain_id;
> +	fwspec.param[0] = irq;
> +	fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
> +	fwspec.param_count = 2;
> +
> +	return irq_create_fwspec_mapping(&fwspec);
> +}
> +EXPORT_SYMBOL_GPL(acpi_register_irq);

By the way, this is almost an exact duplicate of acpi_register_gsi().
You definitely want to make this code common.

> +
>  /**
>   * acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ 
> resource source.
>   * @source: acpi_resource_source to use for the lookup.
> @@ -92,7 +111,7 @@ EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
>   * Return:
>   * The referenced device fwhandle or NULL on failure
>   */
> -static struct fwnode_handle *
> +struct fwnode_handle *
>  acpi_get_irq_source_fwhandle(const struct acpi_resource_source 
> *source)
>  {
>  	struct fwnode_handle *result;
> @@ -115,6 +134,7 @@ acpi_get_irq_source_fwhandle(const struct
> acpi_resource_source *source)
>  	acpi_bus_put_acpi_device(device);
>  	return result;
>  }
> +EXPORT_SYMBOL_GPL(acpi_get_irq_source_fwhandle);
> 
>  /*
>   * Context for the resource walk used to lookup IRQ resources.
> diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
> index 14ee631cb7cf..19296d70c95c 100644
> --- a/drivers/acpi/pci_irq.c
> +++ b/drivers/acpi/pci_irq.c
> @@ -410,6 +410,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  	char *link = NULL;
>  	char link_desc[16];
>  	int rc;
> +	struct fwnode_handle *irq_domain;

fwnode_handle is most definitely not an IRQ domain.

> 
>  	pin = dev->pin;
>  	if (!pin) {
> @@ -438,7 +439,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  			gsi = acpi_pci_link_allocate_irq(entry->link,
>  							 entry->index,
>  							 &triggering, &polarity,
> -							 &link);
> +							 &link,
> +							 &irq_domain);
>  		else
>  			gsi = entry->index;
>  	} else
> @@ -462,7 +464,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  		return 0;
>  	}
> 
> -	rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
> +	rc = acpi_register_irq(&dev->dev, gsi, triggering, polarity, 
> irq_domain);
>  	if (rc < 0) {
>  		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
>  			 pin_name(pin));
> diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
> index fb4c5632a232..219a644d739a 100644
> --- a/drivers/acpi/pci_link.c
> +++ b/drivers/acpi/pci_link.c
> @@ -59,6 +59,7 @@ struct acpi_pci_link_irq {
>  	u8 resource_type;
>  	u8 possible_count;
>  	u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
> +	struct acpi_resource_source resource_source;
>  	u8 initialized:1;
>  	u8 reserved:7;
>  };
> @@ -120,6 +121,8 @@ static acpi_status
> acpi_pci_link_check_possible(struct acpi_resource *resource,
>  		{
>  			struct acpi_resource_extended_irq *p =
>  			    &resource->data.extended_irq;
> +			struct acpi_resource_source *rs =
> +			    &link->irq.resource_source;
>  			if (!p || !p->interrupt_count) {
>  				printk(KERN_WARNING PREFIX
>  					      "Blank _PRS EXT IRQ resource\n");
> @@ -140,6 +143,12 @@ static acpi_status
> acpi_pci_link_check_possible(struct acpi_resource *resource,
>  			link->irq.triggering = p->triggering;
>  			link->irq.polarity = p->polarity;
>  			link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
> +			if (p->resource_source.string_length) {
> +				rs->index = p->resource_source.index;
> +				rs->string_length = p->resource_source.string_length;
> +				rs->string_ptr = kmalloc(rs->string_length, GFP_KERNEL);
> +				strcpy(rs->string_ptr, p->resource_source.string_ptr);

We have kstrdup() for this kind of things, as using rs->string_length to 
allocate
the buffer and strcpy() to copy it feels... dangerous.

> +			}
>  			break;
>  		}
>  	default:
> @@ -326,7 +335,8 @@ static int acpi_pci_link_set(struct acpi_pci_link
> *link, int irq)
>  			resource->res.data.extended_irq.shareable = ACPI_SHARED;
>  		resource->res.data.extended_irq.interrupt_count = 1;
>  		resource->res.data.extended_irq.interrupts[0] = irq;
> -		/* ignore resource_source, it's optional */
> +		resource->res.data.extended_irq.resource_source =
> +			link->irq.resource_source;
>  		break;
>  	default:
>  		printk(KERN_ERR PREFIX "Invalid Resource_type %d\n",
> link->irq.resource_type);
> @@ -612,7 +622,7 @@ static int acpi_pci_link_allocate(struct
> acpi_pci_link *link)
>   * failure: return -1
>   */
>  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int 
> *triggering,
> -			       int *polarity, char **name)
> +			       int *polarity, char **name, struct fwnode_handle 
> **irq_domain)

Same remark about the naming.

>  {
>  	int result;
>  	struct acpi_device *device;
> @@ -656,6 +666,9 @@ int acpi_pci_link_allocate_irq(acpi_handle handle,
> int index, int *triggering,
>  		*polarity = link->irq.polarity;
>  	if (name)
>  		*name = acpi_device_bid(link->device);
> +	if (irq_domain)
> +		*irq_domain = 
> acpi_get_irq_source_fwhandle(&link->irq.resource_source);
> +
>  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
>  			  "Link %s is referenced\n",
>  			  acpi_device_bid(link->device)));
> diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
> index 5eb175933a5b..6ff1ea76d476 100644
> --- a/include/acpi/acpi_drivers.h
> +++ b/include/acpi/acpi_drivers.h
> @@ -68,7 +68,7 @@
> 
>  int acpi_irq_penalty_init(void);
>  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int 
> *triggering,
> -			       int *polarity, char **name);
> +			       int *polarity, char **name, struct fwnode_handle 
> **irq_domain);
>  int acpi_pci_link_free_irq(acpi_handle handle);
> 
>  /* ACPI PCI Device Binding (pci_bind.c) */
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 39263c6b52e1..5f1d7d3192fb 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -324,6 +324,8 @@ extern int sbf_port;
>  extern unsigned long acpi_realmode_flags;
> 
>  int acpi_register_gsi (struct device *dev, u32 gsi, int triggering,
> int polarity);
> +int acpi_register_irq(struct device *dev, u32 gsi, int trigger,
> +		      int polarity, struct fwnode_handle *domain_id);
>  int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
>  int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
> 
> @@ -336,6 +338,8 @@ struct irq_domain
> *acpi_irq_create_hierarchy(unsigned int flags,
>  					     const struct irq_domain_ops *ops,
>  					     void *host_data);
> 
> +struct fwnode_handle *acpi_get_irq_source_fwhandle(const struct
> acpi_resource_source *source);
> +
>  #ifdef CONFIG_X86_IO_APIC
>  extern int acpi_get_override_irq(u32 gsi, int *trigger, int 
> *polarity);
>  #else

Thanks,

         M.
-- 
Jazz is not dead. It just smells funny...

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
@ 2020-11-18  9:27   ` Marc Zyngier
  0 siblings, 0 replies; 22+ messages in thread
From: Marc Zyngier @ 2020-11-18  9:27 UTC (permalink / raw)
  To: Chen Baozi
  Cc: Lorenzo Pieralisi, linux-pci, linux-kernel, linux-acpi,
	Hanjun Guo, Bjorn Helgaas, Ard Biesheuvel, linux-arm-kernel

Hi Chen,

On top of Bjorn's comments:

On 2020-11-17 13:42, Chen Baozi wrote:
> Some PCIe designs require software to do extra acknowledgements for
> legacy INTx interrupts. If the driver is written only for device tree,
> things are simple. In that case, a new driver can be written under
> driver/pci/controller/ with a DT node of PCIe host written like:
> 
>   pcie {
>     ...
>     interrupt-map = <0 0 0  1  &pcie_intc 0>,
>                     <0 0 0  2  &pcie_intc 1>,
>                     <0 0 0  3  &pcie_intc 2>,
>                     <0 0 0  4  &pcie_intc 3>;
> 
>     pcie_intc: legacy-interrupt-controller {
>       interrupt-controller;
>       #interrupt-cells = <1>;
>       interrupt-parent = <&gic>;
>       interrupts = <0 226 4>;
>     };
>   };
> 
> Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
> UniPhier PCIe controller at the moment. Essentially, those designs are
> supported by inserting an extra interrupt controller between PCIe host
> and GIC and parse the topology in a DT-based PCI controller driver.
> As we turn to ACPI, All the PCIe hosts are described the same ID of
> "PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
> to make this kind of PCI INTx work under ACPI.
> 
> Therefore, we introduce an stacked IRQ domain support to PCI interrupt
> link for ACPI. With this support, we can populate the ResourceSource
> to refer to a device object that describes an interrupt controller.
> That would allow us to refer to a dedicated driver which implements
> the logic needed to manage the interrupt state. With this patch,
> those PCI interrupt links can be supported by describing the INTx
> in ACPI table as the following example:
> 
>   Device (IXIU) {
>     ...
>   }
> 
>   Device(LINKA) {
>     Name(_HID, EISAID("PNP0C0F"))
>     Name(_PRS, ResourceTemplate(){
>       Interrupt(ResourceProducer, Level, ActiveHigh, Exclusive, 0, 
> "\\SB.IXIU")
>         { 60 }
>     })
>     ...
>   }
> 
>   Device(PCI0) {
>     ...
>     Name(_PRT, Package{
>       Package{ 0x0000FFFF, 0, LINKA, 0 }
>       ...
>     })
>   }
> 
> Signed-off-by: Chen Baozi <chenbaozi@phytium.com.cn>
> ---
>  drivers/acpi/irq.c          | 22 +++++++++++++++++++++-
>  drivers/acpi/pci_irq.c      |  6 ++++--
>  drivers/acpi/pci_link.c     | 17 +++++++++++++++--
>  include/acpi/acpi_drivers.h |  2 +-
>  include/linux/acpi.h        |  4 ++++
>  5 files changed, 45 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
> index e209081d644b..e78a44815c44 100644
> --- a/drivers/acpi/irq.c
> +++ b/drivers/acpi/irq.c
> @@ -81,6 +81,25 @@ void acpi_unregister_gsi(u32 gsi)
>  }
>  EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
> 
> +int acpi_register_irq(struct device *dev, u32 irq, int trigger,
> +		      int polarity, struct fwnode_handle *domain_id)
> +{
> +	struct irq_fwspec fwspec;
> +
> +	if (WARN_ON(!domain_id)) {
> +		pr_warn("GSI: No registered irqchip, giving up\n");

A fwnode_handle is not an irqchip. It's just an opaque identifier
for a HW block. Furthermore, there is no need to have both a WARN_ON()
and a pr_warn(). Please pick one.

I'd also suggest you rename domain_id to fwnode, which is the commonly
used idiom (yes, I know about the unfortunate precedent in 
acpi_register_gsi()).

> +		return -EINVAL;
> +	}
> +
> +	fwspec.fwnode = domain_id;
> +	fwspec.param[0] = irq;
> +	fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
> +	fwspec.param_count = 2;
> +
> +	return irq_create_fwspec_mapping(&fwspec);
> +}
> +EXPORT_SYMBOL_GPL(acpi_register_irq);

By the way, this is almost an exact duplicate of acpi_register_gsi().
You definitely want to make this code common.

> +
>  /**
>   * acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ 
> resource source.
>   * @source: acpi_resource_source to use for the lookup.
> @@ -92,7 +111,7 @@ EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
>   * Return:
>   * The referenced device fwhandle or NULL on failure
>   */
> -static struct fwnode_handle *
> +struct fwnode_handle *
>  acpi_get_irq_source_fwhandle(const struct acpi_resource_source 
> *source)
>  {
>  	struct fwnode_handle *result;
> @@ -115,6 +134,7 @@ acpi_get_irq_source_fwhandle(const struct
> acpi_resource_source *source)
>  	acpi_bus_put_acpi_device(device);
>  	return result;
>  }
> +EXPORT_SYMBOL_GPL(acpi_get_irq_source_fwhandle);
> 
>  /*
>   * Context for the resource walk used to lookup IRQ resources.
> diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
> index 14ee631cb7cf..19296d70c95c 100644
> --- a/drivers/acpi/pci_irq.c
> +++ b/drivers/acpi/pci_irq.c
> @@ -410,6 +410,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  	char *link = NULL;
>  	char link_desc[16];
>  	int rc;
> +	struct fwnode_handle *irq_domain;

fwnode_handle is most definitely not an IRQ domain.

> 
>  	pin = dev->pin;
>  	if (!pin) {
> @@ -438,7 +439,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  			gsi = acpi_pci_link_allocate_irq(entry->link,
>  							 entry->index,
>  							 &triggering, &polarity,
> -							 &link);
> +							 &link,
> +							 &irq_domain);
>  		else
>  			gsi = entry->index;
>  	} else
> @@ -462,7 +464,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  		return 0;
>  	}
> 
> -	rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
> +	rc = acpi_register_irq(&dev->dev, gsi, triggering, polarity, 
> irq_domain);
>  	if (rc < 0) {
>  		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
>  			 pin_name(pin));
> diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
> index fb4c5632a232..219a644d739a 100644
> --- a/drivers/acpi/pci_link.c
> +++ b/drivers/acpi/pci_link.c
> @@ -59,6 +59,7 @@ struct acpi_pci_link_irq {
>  	u8 resource_type;
>  	u8 possible_count;
>  	u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
> +	struct acpi_resource_source resource_source;
>  	u8 initialized:1;
>  	u8 reserved:7;
>  };
> @@ -120,6 +121,8 @@ static acpi_status
> acpi_pci_link_check_possible(struct acpi_resource *resource,
>  		{
>  			struct acpi_resource_extended_irq *p =
>  			    &resource->data.extended_irq;
> +			struct acpi_resource_source *rs =
> +			    &link->irq.resource_source;
>  			if (!p || !p->interrupt_count) {
>  				printk(KERN_WARNING PREFIX
>  					      "Blank _PRS EXT IRQ resource\n");
> @@ -140,6 +143,12 @@ static acpi_status
> acpi_pci_link_check_possible(struct acpi_resource *resource,
>  			link->irq.triggering = p->triggering;
>  			link->irq.polarity = p->polarity;
>  			link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
> +			if (p->resource_source.string_length) {
> +				rs->index = p->resource_source.index;
> +				rs->string_length = p->resource_source.string_length;
> +				rs->string_ptr = kmalloc(rs->string_length, GFP_KERNEL);
> +				strcpy(rs->string_ptr, p->resource_source.string_ptr);

We have kstrdup() for this kind of things, as using rs->string_length to 
allocate
the buffer and strcpy() to copy it feels... dangerous.

> +			}
>  			break;
>  		}
>  	default:
> @@ -326,7 +335,8 @@ static int acpi_pci_link_set(struct acpi_pci_link
> *link, int irq)
>  			resource->res.data.extended_irq.shareable = ACPI_SHARED;
>  		resource->res.data.extended_irq.interrupt_count = 1;
>  		resource->res.data.extended_irq.interrupts[0] = irq;
> -		/* ignore resource_source, it's optional */
> +		resource->res.data.extended_irq.resource_source =
> +			link->irq.resource_source;
>  		break;
>  	default:
>  		printk(KERN_ERR PREFIX "Invalid Resource_type %d\n",
> link->irq.resource_type);
> @@ -612,7 +622,7 @@ static int acpi_pci_link_allocate(struct
> acpi_pci_link *link)
>   * failure: return -1
>   */
>  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int 
> *triggering,
> -			       int *polarity, char **name)
> +			       int *polarity, char **name, struct fwnode_handle 
> **irq_domain)

Same remark about the naming.

>  {
>  	int result;
>  	struct acpi_device *device;
> @@ -656,6 +666,9 @@ int acpi_pci_link_allocate_irq(acpi_handle handle,
> int index, int *triggering,
>  		*polarity = link->irq.polarity;
>  	if (name)
>  		*name = acpi_device_bid(link->device);
> +	if (irq_domain)
> +		*irq_domain = 
> acpi_get_irq_source_fwhandle(&link->irq.resource_source);
> +
>  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
>  			  "Link %s is referenced\n",
>  			  acpi_device_bid(link->device)));
> diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
> index 5eb175933a5b..6ff1ea76d476 100644
> --- a/include/acpi/acpi_drivers.h
> +++ b/include/acpi/acpi_drivers.h
> @@ -68,7 +68,7 @@
> 
>  int acpi_irq_penalty_init(void);
>  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int 
> *triggering,
> -			       int *polarity, char **name);
> +			       int *polarity, char **name, struct fwnode_handle 
> **irq_domain);
>  int acpi_pci_link_free_irq(acpi_handle handle);
> 
>  /* ACPI PCI Device Binding (pci_bind.c) */
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 39263c6b52e1..5f1d7d3192fb 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -324,6 +324,8 @@ extern int sbf_port;
>  extern unsigned long acpi_realmode_flags;
> 
>  int acpi_register_gsi (struct device *dev, u32 gsi, int triggering,
> int polarity);
> +int acpi_register_irq(struct device *dev, u32 gsi, int trigger,
> +		      int polarity, struct fwnode_handle *domain_id);
>  int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
>  int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
> 
> @@ -336,6 +338,8 @@ struct irq_domain
> *acpi_irq_create_hierarchy(unsigned int flags,
>  					     const struct irq_domain_ops *ops,
>  					     void *host_data);
> 
> +struct fwnode_handle *acpi_get_irq_source_fwhandle(const struct
> acpi_resource_source *source);
> +
>  #ifdef CONFIG_X86_IO_APIC
>  extern int acpi_get_override_irq(u32 gsi, int *trigger, int 
> *polarity);
>  #else

Thanks,

         M.
-- 
Jazz is not dead. It just smells funny...

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
  2020-11-17 13:42 ` Chen Baozi
@ 2020-11-18  9:51   ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 22+ messages in thread
From: Lorenzo Pieralisi @ 2020-11-18  9:51 UTC (permalink / raw)
  To: Chen Baozi
  Cc: Ard Biesheuvel, Hanjun Guo, Marc Zyngier, Bjorn Helgaas,
	linux-acpi, linux-pci, linux-arm-kernel, linux-kernel

On Tue, Nov 17, 2020 at 09:42:14PM +0800, Chen Baozi wrote:
> Some PCIe designs require software to do extra acknowledgements for
> legacy INTx interrupts. If the driver is written only for device tree,
> things are simple. In that case, a new driver can be written under
> driver/pci/controller/ with a DT node of PCIe host written like:
> 
>   pcie {
>     ...
>     interrupt-map = <0 0 0  1  &pcie_intc 0>,
>                     <0 0 0  2  &pcie_intc 1>,
>                     <0 0 0  3  &pcie_intc 2>,
>                     <0 0 0  4  &pcie_intc 3>;
> 
>     pcie_intc: legacy-interrupt-controller {
>       interrupt-controller;
>       #interrupt-cells = <1>;
>       interrupt-parent = <&gic>;
>       interrupts = <0 226 4>;
>     };
>   };
> 
> Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
> UniPhier PCIe controller at the moment. Essentially, those designs are
> supported by inserting an extra interrupt controller between PCIe host
> and GIC and parse the topology in a DT-based PCI controller driver.
> As we turn to ACPI, All the PCIe hosts are described the same ID of
> "PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
> to make this kind of PCI INTx work under ACPI.

In this respect this patch is a minor detail. The major detail is how
those host controllers are going to probe and initialize with ACPI and I
am against merging this patch stand alone with no user before
understanding what you really want to do with those host controller
drivers in the ACPI world.

Side note, there is ongoing work for a generic interrupt MUX:

https://bugzilla.tianocore.org/show_bug.cgi?id=2995

If we ever come to support those MUXes with ACPI that must be a
starting point, the binding above can be your first "user".

I still have reservations about bootstrapping the host controllers
you mentioned in platforms with no firmware support whatsoever for
PCI initialization (eg address decoders, link bring-up, etc. - the
ACPI host bridge model relies on FW to carry out that initialization)
with ACPI - I would like to see the whole picture first.

Lorenzo

> Therefore, we introduce an stacked IRQ domain support to PCI interrupt
> link for ACPI. With this support, we can populate the ResourceSource
> to refer to a device object that describes an interrupt controller.
> That would allow us to refer to a dedicated driver which implements
> the logic needed to manage the interrupt state. With this patch,
> those PCI interrupt links can be supported by describing the INTx
> in ACPI table as the following example:
> 
>   Device (IXIU) {
>     ...
>   }
> 
>   Device(LINKA) {
>     Name(_HID, EISAID("PNP0C0F"))
>     Name(_PRS, ResourceTemplate(){
>       Interrupt(ResourceProducer, Level, ActiveHigh, Exclusive, 0, "\\SB.IXIU")
>         { 60 }
>     })
>     ...
>   }
> 
>   Device(PCI0) {
>     ...
>     Name(_PRT, Package{
>       Package{ 0x0000FFFF, 0, LINKA, 0 }
>       ...
>     })
>   }
> 
> Signed-off-by: Chen Baozi <chenbaozi@phytium.com.cn>
> ---
>  drivers/acpi/irq.c          | 22 +++++++++++++++++++++-
>  drivers/acpi/pci_irq.c      |  6 ++++--
>  drivers/acpi/pci_link.c     | 17 +++++++++++++++--
>  include/acpi/acpi_drivers.h |  2 +-
>  include/linux/acpi.h        |  4 ++++
>  5 files changed, 45 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
> index e209081d644b..e78a44815c44 100644
> --- a/drivers/acpi/irq.c
> +++ b/drivers/acpi/irq.c
> @@ -81,6 +81,25 @@ void acpi_unregister_gsi(u32 gsi)
>  }
>  EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
>  
> +int acpi_register_irq(struct device *dev, u32 irq, int trigger,
> +		      int polarity, struct fwnode_handle *domain_id)
> +{
> +	struct irq_fwspec fwspec;
> +
> +	if (WARN_ON(!domain_id)) {
> +		pr_warn("GSI: No registered irqchip, giving up\n");
> +		return -EINVAL;
> +	}
> +
> +	fwspec.fwnode = domain_id;
> +	fwspec.param[0] = irq;
> +	fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
> +	fwspec.param_count = 2;
> +
> +	return irq_create_fwspec_mapping(&fwspec);
> +}
> +EXPORT_SYMBOL_GPL(acpi_register_irq);
> +
>  /**
>   * acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ resource source.
>   * @source: acpi_resource_source to use for the lookup.
> @@ -92,7 +111,7 @@ EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
>   * Return:
>   * The referenced device fwhandle or NULL on failure
>   */
> -static struct fwnode_handle *
> +struct fwnode_handle *
>  acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
>  {
>  	struct fwnode_handle *result;
> @@ -115,6 +134,7 @@ acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
>  	acpi_bus_put_acpi_device(device);
>  	return result;
>  }
> +EXPORT_SYMBOL_GPL(acpi_get_irq_source_fwhandle);
>  
>  /*
>   * Context for the resource walk used to lookup IRQ resources.
> diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
> index 14ee631cb7cf..19296d70c95c 100644
> --- a/drivers/acpi/pci_irq.c
> +++ b/drivers/acpi/pci_irq.c
> @@ -410,6 +410,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  	char *link = NULL;
>  	char link_desc[16];
>  	int rc;
> +	struct fwnode_handle *irq_domain;
>  
>  	pin = dev->pin;
>  	if (!pin) {
> @@ -438,7 +439,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  			gsi = acpi_pci_link_allocate_irq(entry->link,
>  							 entry->index,
>  							 &triggering, &polarity,
> -							 &link);
> +							 &link,
> +							 &irq_domain);
>  		else
>  			gsi = entry->index;
>  	} else
> @@ -462,7 +464,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  		return 0;
>  	}
>  
> -	rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
> +	rc = acpi_register_irq(&dev->dev, gsi, triggering, polarity, irq_domain);
>  	if (rc < 0) {
>  		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
>  			 pin_name(pin));
> diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
> index fb4c5632a232..219a644d739a 100644
> --- a/drivers/acpi/pci_link.c
> +++ b/drivers/acpi/pci_link.c
> @@ -59,6 +59,7 @@ struct acpi_pci_link_irq {
>  	u8 resource_type;
>  	u8 possible_count;
>  	u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
> +	struct acpi_resource_source resource_source;
>  	u8 initialized:1;
>  	u8 reserved:7;
>  };
> @@ -120,6 +121,8 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
>  		{
>  			struct acpi_resource_extended_irq *p =
>  			    &resource->data.extended_irq;
> +			struct acpi_resource_source *rs =
> +			    &link->irq.resource_source;
>  			if (!p || !p->interrupt_count) {
>  				printk(KERN_WARNING PREFIX
>  					      "Blank _PRS EXT IRQ resource\n");
> @@ -140,6 +143,12 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
>  			link->irq.triggering = p->triggering;
>  			link->irq.polarity = p->polarity;
>  			link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
> +			if (p->resource_source.string_length) {
> +				rs->index = p->resource_source.index;
> +				rs->string_length = p->resource_source.string_length;
> +				rs->string_ptr = kmalloc(rs->string_length, GFP_KERNEL);
> +				strcpy(rs->string_ptr, p->resource_source.string_ptr);
> +			}
>  			break;
>  		}
>  	default:
> @@ -326,7 +335,8 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
>  			resource->res.data.extended_irq.shareable = ACPI_SHARED;
>  		resource->res.data.extended_irq.interrupt_count = 1;
>  		resource->res.data.extended_irq.interrupts[0] = irq;
> -		/* ignore resource_source, it's optional */
> +		resource->res.data.extended_irq.resource_source =
> +			link->irq.resource_source;
>  		break;
>  	default:
>  		printk(KERN_ERR PREFIX "Invalid Resource_type %d\n", link->irq.resource_type);
> @@ -612,7 +622,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
>   * failure: return -1
>   */
>  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
> -			       int *polarity, char **name)
> +			       int *polarity, char **name, struct fwnode_handle **irq_domain)
>  {
>  	int result;
>  	struct acpi_device *device;
> @@ -656,6 +666,9 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
>  		*polarity = link->irq.polarity;
>  	if (name)
>  		*name = acpi_device_bid(link->device);
> +	if (irq_domain)
> +		*irq_domain = acpi_get_irq_source_fwhandle(&link->irq.resource_source);
> +
>  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
>  			  "Link %s is referenced\n",
>  			  acpi_device_bid(link->device)));
> diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
> index 5eb175933a5b..6ff1ea76d476 100644
> --- a/include/acpi/acpi_drivers.h
> +++ b/include/acpi/acpi_drivers.h
> @@ -68,7 +68,7 @@
>  
>  int acpi_irq_penalty_init(void);
>  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
> -			       int *polarity, char **name);
> +			       int *polarity, char **name, struct fwnode_handle **irq_domain);
>  int acpi_pci_link_free_irq(acpi_handle handle);
>  
>  /* ACPI PCI Device Binding (pci_bind.c) */
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 39263c6b52e1..5f1d7d3192fb 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -324,6 +324,8 @@ extern int sbf_port;
>  extern unsigned long acpi_realmode_flags;
>  
>  int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
> +int acpi_register_irq(struct device *dev, u32 gsi, int trigger,
> +		      int polarity, struct fwnode_handle *domain_id);
>  int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
>  int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
>  
> @@ -336,6 +338,8 @@ struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
>  					     const struct irq_domain_ops *ops,
>  					     void *host_data);
>  
> +struct fwnode_handle *acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source);
> +
>  #ifdef CONFIG_X86_IO_APIC
>  extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
>  #else
> -- 
> 2.28.0
> 

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
@ 2020-11-18  9:51   ` Lorenzo Pieralisi
  0 siblings, 0 replies; 22+ messages in thread
From: Lorenzo Pieralisi @ 2020-11-18  9:51 UTC (permalink / raw)
  To: Chen Baozi
  Cc: Marc Zyngier, Hanjun Guo, linux-kernel, linux-acpi, linux-pci,
	Bjorn Helgaas, Ard Biesheuvel, linux-arm-kernel

On Tue, Nov 17, 2020 at 09:42:14PM +0800, Chen Baozi wrote:
> Some PCIe designs require software to do extra acknowledgements for
> legacy INTx interrupts. If the driver is written only for device tree,
> things are simple. In that case, a new driver can be written under
> driver/pci/controller/ with a DT node of PCIe host written like:
> 
>   pcie {
>     ...
>     interrupt-map = <0 0 0  1  &pcie_intc 0>,
>                     <0 0 0  2  &pcie_intc 1>,
>                     <0 0 0  3  &pcie_intc 2>,
>                     <0 0 0  4  &pcie_intc 3>;
> 
>     pcie_intc: legacy-interrupt-controller {
>       interrupt-controller;
>       #interrupt-cells = <1>;
>       interrupt-parent = <&gic>;
>       interrupts = <0 226 4>;
>     };
>   };
> 
> Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
> UniPhier PCIe controller at the moment. Essentially, those designs are
> supported by inserting an extra interrupt controller between PCIe host
> and GIC and parse the topology in a DT-based PCI controller driver.
> As we turn to ACPI, All the PCIe hosts are described the same ID of
> "PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
> to make this kind of PCI INTx work under ACPI.

In this respect this patch is a minor detail. The major detail is how
those host controllers are going to probe and initialize with ACPI and I
am against merging this patch stand alone with no user before
understanding what you really want to do with those host controller
drivers in the ACPI world.

Side note, there is ongoing work for a generic interrupt MUX:

https://bugzilla.tianocore.org/show_bug.cgi?id=2995

If we ever come to support those MUXes with ACPI that must be a
starting point, the binding above can be your first "user".

I still have reservations about bootstrapping the host controllers
you mentioned in platforms with no firmware support whatsoever for
PCI initialization (eg address decoders, link bring-up, etc. - the
ACPI host bridge model relies on FW to carry out that initialization)
with ACPI - I would like to see the whole picture first.

Lorenzo

> Therefore, we introduce an stacked IRQ domain support to PCI interrupt
> link for ACPI. With this support, we can populate the ResourceSource
> to refer to a device object that describes an interrupt controller.
> That would allow us to refer to a dedicated driver which implements
> the logic needed to manage the interrupt state. With this patch,
> those PCI interrupt links can be supported by describing the INTx
> in ACPI table as the following example:
> 
>   Device (IXIU) {
>     ...
>   }
> 
>   Device(LINKA) {
>     Name(_HID, EISAID("PNP0C0F"))
>     Name(_PRS, ResourceTemplate(){
>       Interrupt(ResourceProducer, Level, ActiveHigh, Exclusive, 0, "\\SB.IXIU")
>         { 60 }
>     })
>     ...
>   }
> 
>   Device(PCI0) {
>     ...
>     Name(_PRT, Package{
>       Package{ 0x0000FFFF, 0, LINKA, 0 }
>       ...
>     })
>   }
> 
> Signed-off-by: Chen Baozi <chenbaozi@phytium.com.cn>
> ---
>  drivers/acpi/irq.c          | 22 +++++++++++++++++++++-
>  drivers/acpi/pci_irq.c      |  6 ++++--
>  drivers/acpi/pci_link.c     | 17 +++++++++++++++--
>  include/acpi/acpi_drivers.h |  2 +-
>  include/linux/acpi.h        |  4 ++++
>  5 files changed, 45 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
> index e209081d644b..e78a44815c44 100644
> --- a/drivers/acpi/irq.c
> +++ b/drivers/acpi/irq.c
> @@ -81,6 +81,25 @@ void acpi_unregister_gsi(u32 gsi)
>  }
>  EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
>  
> +int acpi_register_irq(struct device *dev, u32 irq, int trigger,
> +		      int polarity, struct fwnode_handle *domain_id)
> +{
> +	struct irq_fwspec fwspec;
> +
> +	if (WARN_ON(!domain_id)) {
> +		pr_warn("GSI: No registered irqchip, giving up\n");
> +		return -EINVAL;
> +	}
> +
> +	fwspec.fwnode = domain_id;
> +	fwspec.param[0] = irq;
> +	fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
> +	fwspec.param_count = 2;
> +
> +	return irq_create_fwspec_mapping(&fwspec);
> +}
> +EXPORT_SYMBOL_GPL(acpi_register_irq);
> +
>  /**
>   * acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ resource source.
>   * @source: acpi_resource_source to use for the lookup.
> @@ -92,7 +111,7 @@ EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
>   * Return:
>   * The referenced device fwhandle or NULL on failure
>   */
> -static struct fwnode_handle *
> +struct fwnode_handle *
>  acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
>  {
>  	struct fwnode_handle *result;
> @@ -115,6 +134,7 @@ acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
>  	acpi_bus_put_acpi_device(device);
>  	return result;
>  }
> +EXPORT_SYMBOL_GPL(acpi_get_irq_source_fwhandle);
>  
>  /*
>   * Context for the resource walk used to lookup IRQ resources.
> diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
> index 14ee631cb7cf..19296d70c95c 100644
> --- a/drivers/acpi/pci_irq.c
> +++ b/drivers/acpi/pci_irq.c
> @@ -410,6 +410,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  	char *link = NULL;
>  	char link_desc[16];
>  	int rc;
> +	struct fwnode_handle *irq_domain;
>  
>  	pin = dev->pin;
>  	if (!pin) {
> @@ -438,7 +439,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  			gsi = acpi_pci_link_allocate_irq(entry->link,
>  							 entry->index,
>  							 &triggering, &polarity,
> -							 &link);
> +							 &link,
> +							 &irq_domain);
>  		else
>  			gsi = entry->index;
>  	} else
> @@ -462,7 +464,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>  		return 0;
>  	}
>  
> -	rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
> +	rc = acpi_register_irq(&dev->dev, gsi, triggering, polarity, irq_domain);
>  	if (rc < 0) {
>  		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
>  			 pin_name(pin));
> diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
> index fb4c5632a232..219a644d739a 100644
> --- a/drivers/acpi/pci_link.c
> +++ b/drivers/acpi/pci_link.c
> @@ -59,6 +59,7 @@ struct acpi_pci_link_irq {
>  	u8 resource_type;
>  	u8 possible_count;
>  	u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
> +	struct acpi_resource_source resource_source;
>  	u8 initialized:1;
>  	u8 reserved:7;
>  };
> @@ -120,6 +121,8 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
>  		{
>  			struct acpi_resource_extended_irq *p =
>  			    &resource->data.extended_irq;
> +			struct acpi_resource_source *rs =
> +			    &link->irq.resource_source;
>  			if (!p || !p->interrupt_count) {
>  				printk(KERN_WARNING PREFIX
>  					      "Blank _PRS EXT IRQ resource\n");
> @@ -140,6 +143,12 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
>  			link->irq.triggering = p->triggering;
>  			link->irq.polarity = p->polarity;
>  			link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
> +			if (p->resource_source.string_length) {
> +				rs->index = p->resource_source.index;
> +				rs->string_length = p->resource_source.string_length;
> +				rs->string_ptr = kmalloc(rs->string_length, GFP_KERNEL);
> +				strcpy(rs->string_ptr, p->resource_source.string_ptr);
> +			}
>  			break;
>  		}
>  	default:
> @@ -326,7 +335,8 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
>  			resource->res.data.extended_irq.shareable = ACPI_SHARED;
>  		resource->res.data.extended_irq.interrupt_count = 1;
>  		resource->res.data.extended_irq.interrupts[0] = irq;
> -		/* ignore resource_source, it's optional */
> +		resource->res.data.extended_irq.resource_source =
> +			link->irq.resource_source;
>  		break;
>  	default:
>  		printk(KERN_ERR PREFIX "Invalid Resource_type %d\n", link->irq.resource_type);
> @@ -612,7 +622,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
>   * failure: return -1
>   */
>  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
> -			       int *polarity, char **name)
> +			       int *polarity, char **name, struct fwnode_handle **irq_domain)
>  {
>  	int result;
>  	struct acpi_device *device;
> @@ -656,6 +666,9 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
>  		*polarity = link->irq.polarity;
>  	if (name)
>  		*name = acpi_device_bid(link->device);
> +	if (irq_domain)
> +		*irq_domain = acpi_get_irq_source_fwhandle(&link->irq.resource_source);
> +
>  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
>  			  "Link %s is referenced\n",
>  			  acpi_device_bid(link->device)));
> diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
> index 5eb175933a5b..6ff1ea76d476 100644
> --- a/include/acpi/acpi_drivers.h
> +++ b/include/acpi/acpi_drivers.h
> @@ -68,7 +68,7 @@
>  
>  int acpi_irq_penalty_init(void);
>  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
> -			       int *polarity, char **name);
> +			       int *polarity, char **name, struct fwnode_handle **irq_domain);
>  int acpi_pci_link_free_irq(acpi_handle handle);
>  
>  /* ACPI PCI Device Binding (pci_bind.c) */
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 39263c6b52e1..5f1d7d3192fb 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -324,6 +324,8 @@ extern int sbf_port;
>  extern unsigned long acpi_realmode_flags;
>  
>  int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
> +int acpi_register_irq(struct device *dev, u32 gsi, int trigger,
> +		      int polarity, struct fwnode_handle *domain_id);
>  int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
>  int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
>  
> @@ -336,6 +338,8 @@ struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
>  					     const struct irq_domain_ops *ops,
>  					     void *host_data);
>  
> +struct fwnode_handle *acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source);
> +
>  #ifdef CONFIG_X86_IO_APIC
>  extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
>  #else
> -- 
> 2.28.0
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
  2020-11-17 18:57   ` Bjorn Helgaas
@ 2020-11-18 10:37     ` Chen Baozi
  -1 siblings, 0 replies; 22+ messages in thread
From: Chen Baozi @ 2020-11-18 10:37 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Ard Biesheuvel, Guohanjun, Marc Zyngier, Bjorn Helgaas,
	linux-acpi, linux-pci, linux-arm-kernel, linux-kernel,
	Lorenzo Pieralisi

Hi Bjorn,

Thanks for reviewing. I’ll try to fix all existing issues and send a new
version later.

> On Nov 18, 2020, at 2:57 AM, Bjorn Helgaas <helgaas@kernel.org> wrote:
> 
> Nit: please don't just make up random styles for the subject.  Run
> "git log --oneline" on the file and/or the directory and try to follow
> the existing convention.  Using random styles adds noise to the
> system.
> 
> On Tue, Nov 17, 2020 at 09:42:14PM +0800, Chen Baozi wrote:
>> 
>> Therefore, we introduce an stacked IRQ domain support to PCI interrupt
>> link for ACPI. With this support, we can populate the ResourceSource
>> to refer to a device object that describes an interrupt controller.
>> That would allow us to refer to a dedicated driver which implements
>> the logic needed to manage the interrupt state. With this patch,
>> those PCI interrupt links can be supported by describing the INTx
>> in ACPI table as the following example:
> 
> "Stacked IRQ domain" sounds like a detail of how you're implementing
> support for the Resource Source field for PCI Interrupt Links.
> 
> I don't know what the dedicated driver refers to.  This *should* be
> all generic code the follows the ACPI spec (which is pretty sketchy in
> this area).  But I assume that there's no special driver needed for
> devices like \SB.IXIU, and the logic associated with the interrupt
> controller is in the AML associated with IXIU.  It would probably be
> useful to mention the relevant methods in the IXIU methods in the
> example below.
> 
> From ACPI v6.3, Table 6-200, it looks like this patch should include
> changes to acpi_bus_osc_support() to advertise "Interrupt
> ResourceSource support".

According to my understanding, does it mean to add something like:

+       capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_INTR_RS_SUPPORT;

and check whether the platform supports usage of ResourceSource after
acpi_run_osc() returns successfully:

+		osc_sb_intr_rs_support_confirmed =
+			capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_INTR_RS_SUPPORT;

with this bool value, we can then determine if we would ignore the
ResourceSource field later.

Or we just advertise this capability from the OS side without introducing
the ‘osc_sb_intr_rs_support_confirmed’?

I am not certain about it because:

1) If we strictly flow the spec, which says “the platform will indicate to
OS whether ... If not set, the OS may choose to ignore the ResourceSource
parameter in the extended interrupt descirptor”, this means this capability
can be used to determine whether we would ignore to parse the field later.

2) On the other hand, Since the ResourceSource has already been used to
create hierarchical domain for platform device (introduced by 621dc2fdcea1)
and previous driver does not check this capability, I am not sure whether
it would break the existing platforms. 

Fix me if I am wrong.

Cheers,

Chen Baozi.



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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
@ 2020-11-18 10:37     ` Chen Baozi
  0 siblings, 0 replies; 22+ messages in thread
From: Chen Baozi @ 2020-11-18 10:37 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Lorenzo Pieralisi, Marc Zyngier, Guohanjun, linux-kernel,
	linux-acpi, linux-pci, Bjorn Helgaas, Ard Biesheuvel,
	linux-arm-kernel

Hi Bjorn,

Thanks for reviewing. I’ll try to fix all existing issues and send a new
version later.

> On Nov 18, 2020, at 2:57 AM, Bjorn Helgaas <helgaas@kernel.org> wrote:
> 
> Nit: please don't just make up random styles for the subject.  Run
> "git log --oneline" on the file and/or the directory and try to follow
> the existing convention.  Using random styles adds noise to the
> system.
> 
> On Tue, Nov 17, 2020 at 09:42:14PM +0800, Chen Baozi wrote:
>> 
>> Therefore, we introduce an stacked IRQ domain support to PCI interrupt
>> link for ACPI. With this support, we can populate the ResourceSource
>> to refer to a device object that describes an interrupt controller.
>> That would allow us to refer to a dedicated driver which implements
>> the logic needed to manage the interrupt state. With this patch,
>> those PCI interrupt links can be supported by describing the INTx
>> in ACPI table as the following example:
> 
> "Stacked IRQ domain" sounds like a detail of how you're implementing
> support for the Resource Source field for PCI Interrupt Links.
> 
> I don't know what the dedicated driver refers to.  This *should* be
> all generic code the follows the ACPI spec (which is pretty sketchy in
> this area).  But I assume that there's no special driver needed for
> devices like \SB.IXIU, and the logic associated with the interrupt
> controller is in the AML associated with IXIU.  It would probably be
> useful to mention the relevant methods in the IXIU methods in the
> example below.
> 
> From ACPI v6.3, Table 6-200, it looks like this patch should include
> changes to acpi_bus_osc_support() to advertise "Interrupt
> ResourceSource support".

According to my understanding, does it mean to add something like:

+       capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_INTR_RS_SUPPORT;

and check whether the platform supports usage of ResourceSource after
acpi_run_osc() returns successfully:

+		osc_sb_intr_rs_support_confirmed =
+			capbuf_ret[OSC_SUPPORT_DWORD] & OSC_SB_INTR_RS_SUPPORT;

with this bool value, we can then determine if we would ignore the
ResourceSource field later.

Or we just advertise this capability from the OS side without introducing
the ‘osc_sb_intr_rs_support_confirmed’?

I am not certain about it because:

1) If we strictly flow the spec, which says “the platform will indicate to
OS whether ... If not set, the OS may choose to ignore the ResourceSource
parameter in the extended interrupt descirptor”, this means this capability
can be used to determine whether we would ignore to parse the field later.

2) On the other hand, Since the ResourceSource has already been used to
create hierarchical domain for platform device (introduced by 621dc2fdcea1)
and previous driver does not check this capability, I am not sure whether
it would break the existing platforms. 

Fix me if I am wrong.

Cheers,

Chen Baozi.



_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
  2020-11-18  9:27   ` Marc Zyngier
@ 2020-11-18 13:36     ` Chen Baozi
  -1 siblings, 0 replies; 22+ messages in thread
From: Chen Baozi @ 2020-11-18 13:36 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Lorenzo Pieralisi, linux-pci, linux-kernel, linux-acpi,
	Guohanjun, Bjorn Helgaas, Ard Biesheuvel, linux-arm-kernel

Hi Marc,

> On Nov 18, 2020, at 5:27 PM, Marc Zyngier <maz@kernel.org> wrote:
> 
> Hi Chen,
> 
> On top of Bjorn's comments:
> 
> On 2020-11-17 13:42, Chen Baozi wrote:
>> 
>> ---
>> drivers/acpi/irq.c          | 22 +++++++++++++++++++++-
>> drivers/acpi/pci_irq.c      |  6 ++++--
>> drivers/acpi/pci_link.c     | 17 +++++++++++++++--
>> include/acpi/acpi_drivers.h |  2 +-
>> include/linux/acpi.h        |  4 ++++
>> 5 files changed, 45 insertions(+), 6 deletions(-)
>> diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
>> index e209081d644b..e78a44815c44 100644
>> --- a/drivers/acpi/irq.c
>> +++ b/drivers/acpi/irq.c
>> @@ -81,6 +81,25 @@ void acpi_unregister_gsi(u32 gsi)
>> }
>> EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
>> +int acpi_register_irq(struct device *dev, u32 irq, int trigger,
>> +		      int polarity, struct fwnode_handle *domain_id)
>> +{
>> +	struct irq_fwspec fwspec;
>> +
>> +	if (WARN_ON(!domain_id)) {
>> +		pr_warn("GSI: No registered irqchip, giving up\n");
> 
> A fwnode_handle is not an irqchip. It's just an opaque identifier
> for a HW block. Furthermore, there is no need to have both a WARN_ON()
> and a pr_warn(). Please pick one.
> 
> I'd also suggest you rename domain_id to fwnode, which is the commonly
> used idiom (yes, I know about the unfortunate precedent in acpi_register_gsi()).
> 
>> +		return -EINVAL;
>> +	}
>> +
>> +	fwspec.fwnode = domain_id;
>> +	fwspec.param[0] = irq;
>> +	fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
>> +	fwspec.param_count = 2;
>> +
>> +	return irq_create_fwspec_mapping(&fwspec);
>> +}
>> +EXPORT_SYMBOL_GPL(acpi_register_irq);
> 
> By the way, this is almost an exact duplicate of acpi_register_gsi().
> You definitely want to make this code common.
> 
>> @@ -115,6 +134,7 @@ acpi_get_irq_source_fwhandle(const struct
>> acpi_resource_source *source)
>> 	acpi_bus_put_acpi_device(device);
>> 	return result;
>> }
>> +EXPORT_SYMBOL_GPL(acpi_get_irq_source_fwhandle);
>> /*
>>  * Context for the resource walk used to lookup IRQ resources.
>> diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
>> index 14ee631cb7cf..19296d70c95c 100644
>> --- a/drivers/acpi/pci_irq.c
>> +++ b/drivers/acpi/pci_irq.c
>> @@ -410,6 +410,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>> 	char *link = NULL;
>> 	char link_desc[16];
>> 	int rc;
>> +	struct fwnode_handle *irq_domain;
> 
> fwnode_handle is most definitely not an IRQ domain.
> 
>> @@ -140,6 +143,12 @@ static acpi_status
>> acpi_pci_link_check_possible(struct acpi_resource *resource,
>> 			link->irq.triggering = p->triggering;
>> 			link->irq.polarity = p->polarity;
>> 			link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
>> +			if (p->resource_source.string_length) {
>> +				rs->index = p->resource_source.index;
>> +				rs->string_length = p->resource_source.string_length;
>> +				rs->string_ptr = kmalloc(rs->string_length, GFP_KERNEL);
>> +				strcpy(rs->string_ptr, p->resource_source.string_ptr);
> 
> We have kstrdup() for this kind of things, as using rs->string_length to allocate
> the buffer and strcpy() to copy it feels... dangerous.
> 
>> +			}
>> 			break;
>> 		}
>> 	default:
>> @@ -612,7 +622,7 @@ static int acpi_pci_link_allocate(struct
>> acpi_pci_link *link)
>>  * failure: return -1
>>  */
>> int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
>> -			       int *polarity, char **name)
>> +			       int *polarity, char **name, struct fwnode_handle **irq_domain)
> 
> Same remark about the naming.

Thanks. It is very helpful. I’ll fix it in next version.

Baozi.


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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
@ 2020-11-18 13:36     ` Chen Baozi
  0 siblings, 0 replies; 22+ messages in thread
From: Chen Baozi @ 2020-11-18 13:36 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Lorenzo Pieralisi, linux-pci, linux-kernel, linux-acpi,
	Guohanjun, Bjorn Helgaas, Ard Biesheuvel, linux-arm-kernel

Hi Marc,

> On Nov 18, 2020, at 5:27 PM, Marc Zyngier <maz@kernel.org> wrote:
> 
> Hi Chen,
> 
> On top of Bjorn's comments:
> 
> On 2020-11-17 13:42, Chen Baozi wrote:
>> 
>> ---
>> drivers/acpi/irq.c          | 22 +++++++++++++++++++++-
>> drivers/acpi/pci_irq.c      |  6 ++++--
>> drivers/acpi/pci_link.c     | 17 +++++++++++++++--
>> include/acpi/acpi_drivers.h |  2 +-
>> include/linux/acpi.h        |  4 ++++
>> 5 files changed, 45 insertions(+), 6 deletions(-)
>> diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
>> index e209081d644b..e78a44815c44 100644
>> --- a/drivers/acpi/irq.c
>> +++ b/drivers/acpi/irq.c
>> @@ -81,6 +81,25 @@ void acpi_unregister_gsi(u32 gsi)
>> }
>> EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
>> +int acpi_register_irq(struct device *dev, u32 irq, int trigger,
>> +		      int polarity, struct fwnode_handle *domain_id)
>> +{
>> +	struct irq_fwspec fwspec;
>> +
>> +	if (WARN_ON(!domain_id)) {
>> +		pr_warn("GSI: No registered irqchip, giving up\n");
> 
> A fwnode_handle is not an irqchip. It's just an opaque identifier
> for a HW block. Furthermore, there is no need to have both a WARN_ON()
> and a pr_warn(). Please pick one.
> 
> I'd also suggest you rename domain_id to fwnode, which is the commonly
> used idiom (yes, I know about the unfortunate precedent in acpi_register_gsi()).
> 
>> +		return -EINVAL;
>> +	}
>> +
>> +	fwspec.fwnode = domain_id;
>> +	fwspec.param[0] = irq;
>> +	fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
>> +	fwspec.param_count = 2;
>> +
>> +	return irq_create_fwspec_mapping(&fwspec);
>> +}
>> +EXPORT_SYMBOL_GPL(acpi_register_irq);
> 
> By the way, this is almost an exact duplicate of acpi_register_gsi().
> You definitely want to make this code common.
> 
>> @@ -115,6 +134,7 @@ acpi_get_irq_source_fwhandle(const struct
>> acpi_resource_source *source)
>> 	acpi_bus_put_acpi_device(device);
>> 	return result;
>> }
>> +EXPORT_SYMBOL_GPL(acpi_get_irq_source_fwhandle);
>> /*
>>  * Context for the resource walk used to lookup IRQ resources.
>> diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
>> index 14ee631cb7cf..19296d70c95c 100644
>> --- a/drivers/acpi/pci_irq.c
>> +++ b/drivers/acpi/pci_irq.c
>> @@ -410,6 +410,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
>> 	char *link = NULL;
>> 	char link_desc[16];
>> 	int rc;
>> +	struct fwnode_handle *irq_domain;
> 
> fwnode_handle is most definitely not an IRQ domain.
> 
>> @@ -140,6 +143,12 @@ static acpi_status
>> acpi_pci_link_check_possible(struct acpi_resource *resource,
>> 			link->irq.triggering = p->triggering;
>> 			link->irq.polarity = p->polarity;
>> 			link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
>> +			if (p->resource_source.string_length) {
>> +				rs->index = p->resource_source.index;
>> +				rs->string_length = p->resource_source.string_length;
>> +				rs->string_ptr = kmalloc(rs->string_length, GFP_KERNEL);
>> +				strcpy(rs->string_ptr, p->resource_source.string_ptr);
> 
> We have kstrdup() for this kind of things, as using rs->string_length to allocate
> the buffer and strcpy() to copy it feels... dangerous.
> 
>> +			}
>> 			break;
>> 		}
>> 	default:
>> @@ -612,7 +622,7 @@ static int acpi_pci_link_allocate(struct
>> acpi_pci_link *link)
>>  * failure: return -1
>>  */
>> int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
>> -			       int *polarity, char **name)
>> +			       int *polarity, char **name, struct fwnode_handle **irq_domain)
> 
> Same remark about the naming.

Thanks. It is very helpful. I’ll fix it in next version.

Baozi.


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
  2020-11-17 18:57   ` Bjorn Helgaas
@ 2020-11-18 13:45     ` Ard Biesheuvel
  -1 siblings, 0 replies; 22+ messages in thread
From: Ard Biesheuvel @ 2020-11-18 13:45 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Chen Baozi, Hanjun Guo, Marc Zyngier, Bjorn Helgaas,
	ACPI Devel Maling List, PCI, Linux ARM,
	Linux Kernel Mailing List, Lorenzo Pieralisi

On Tue, 17 Nov 2020 at 19:57, Bjorn Helgaas <helgaas@kernel.org> wrote:
>
> Nit: please don't just make up random styles for the subject.  Run
> "git log --oneline" on the file and/or the directory and try to follow
> the existing convention.  Using random styles adds noise to the
> system.
>
> On Tue, Nov 17, 2020 at 09:42:14PM +0800, Chen Baozi wrote:
> > Some PCIe designs require software to do extra acknowledgements for
> > legacy INTx interrupts. If the driver is written only for device tree,
> > things are simple. In that case, a new driver can be written under
> > driver/pci/controller/ with a DT node of PCIe host written like:
> >
> >   pcie {
> >     ...
> >     interrupt-map = <0 0 0  1  &pcie_intc 0>,
> >                     <0 0 0  2  &pcie_intc 1>,
> >                     <0 0 0  3  &pcie_intc 2>,
> >                     <0 0 0  4  &pcie_intc 3>;
> >
> >     pcie_intc: legacy-interrupt-controller {
> >       interrupt-controller;
> >       #interrupt-cells = <1>;
> >       interrupt-parent = <&gic>;
> >       interrupts = <0 226 4>;
> >     };
> >   };
> >
> > Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
> > UniPhier PCIe controller at the moment. Essentially, those designs are
> > supported by inserting an extra interrupt controller between PCIe host
> > and GIC and parse the topology in a DT-based PCI controller driver.
>
> If I understand correctly, we previously ignored the Resource Source
> field of an Extended Interrupt Descriptor in the _PRS method of
> PNP0C0F PCI Interrupt Link devices, and this patch adds support for
> it.
>
> If that's true, this has nothing to do with DT, other than DT being
> another way to describe the same topology, and the above details
> really aren't relevant to this patch.
>
> > As we turn to ACPI, All the PCIe hosts are described the same ID of
> > "PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
> > to make this kind of PCI INTx work under ACPI.
>
> s/All the PCIe/all the PCIe/
>
> But this paragraph should probably just go away in favor of something
> about implementing Resource Source support.
>
> > Therefore, we introduce an stacked IRQ domain support to PCI interrupt
> > link for ACPI. With this support, we can populate the ResourceSource
> > to refer to a device object that describes an interrupt controller.
> > That would allow us to refer to a dedicated driver which implements
> > the logic needed to manage the interrupt state. With this patch,
> > those PCI interrupt links can be supported by describing the INTx
> > in ACPI table as the following example:
>
> "Stacked IRQ domain" sounds like a detail of how you're implementing
> support for the Resource Source field for PCI Interrupt Links.
>
> I don't know what the dedicated driver refers to.  This *should* be
> all generic code the follows the ACPI spec (which is pretty sketchy in
> this area).  But I assume that there's no special driver needed for
> devices like \SB.IXIU, and the logic associated with the interrupt
> controller is in the AML associated with IXIU.  It would probably be
> useful to mention the relevant methods in the IXIU methods in the
> example below.
>

As I understand it, the intent is to provide a driver for \SB.IXIU
that acknowledges the legacy INTx interrupts in a SoC specific way,
and I don't see how AML could be involved here.

That also explains why the routines are exported to modules - the IXIU
driver could be modularized.


> From ACPI v6.3, Table 6-200, it looks like this patch should include
> changes to acpi_bus_osc_support() to advertise "Interrupt
> ResourceSource support".
>

I assume this covers all uses of ResourceSource, right? Not only in
the context if PCIe legacy interrupts?

> >   Device (IXIU) {
> >     ...
> >   }
> >
> >   Device(LINKA) {
> >     Name(_HID, EISAID("PNP0C0F"))
> >     Name(_PRS, ResourceTemplate(){
> >       Interrupt(ResourceProducer, Level, ActiveHigh, Exclusive, 0, "\\SB.IXIU")
> >         { 60 }
> >     })
> >     ...
> >   }
> >
> >   Device(PCI0) {
> >     ...
> >     Name(_PRT, Package{
> >       Package{ 0x0000FFFF, 0, LINKA, 0 }
> >       ...
> >     })
> >   }
> >
> > Signed-off-by: Chen Baozi <chenbaozi@phytium.com.cn>
> > ---
> >  drivers/acpi/irq.c          | 22 +++++++++++++++++++++-
> >  drivers/acpi/pci_irq.c      |  6 ++++--
> >  drivers/acpi/pci_link.c     | 17 +++++++++++++++--
> >  include/acpi/acpi_drivers.h |  2 +-
> >  include/linux/acpi.h        |  4 ++++
> >  5 files changed, 45 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
> > index e209081d644b..e78a44815c44 100644
> > --- a/drivers/acpi/irq.c
> > +++ b/drivers/acpi/irq.c
> > @@ -81,6 +81,25 @@ void acpi_unregister_gsi(u32 gsi)
> >  }
> >  EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
> >
> > +int acpi_register_irq(struct device *dev, u32 irq, int trigger,
> > +                   int polarity, struct fwnode_handle *domain_id)
> > +{
> > +     struct irq_fwspec fwspec;
> > +
> > +     if (WARN_ON(!domain_id)) {
> > +             pr_warn("GSI: No registered irqchip, giving up\n");
>
> This message could contain more information, e.g., by using
> dev_warn(), including the irq value, etc.
>
> > +             return -EINVAL;
> > +     }
> > +
> > +     fwspec.fwnode = domain_id;
> > +     fwspec.param[0] = irq;
> > +     fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
> > +     fwspec.param_count = 2;
> > +
> > +     return irq_create_fwspec_mapping(&fwspec);
> > +}
> > +EXPORT_SYMBOL_GPL(acpi_register_irq);
>
> Why does this need to be exported?  You only call it from
> acpi_pci_irq_enable(), which cannot be a module.
>
> >  /**
> >   * acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ resource source.
> >   * @source: acpi_resource_source to use for the lookup.
> > @@ -92,7 +111,7 @@ EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
> >   * Return:
> >   * The referenced device fwhandle or NULL on failure
> >   */
> > -static struct fwnode_handle *
> > +struct fwnode_handle *
> >  acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
> >  {
> >       struct fwnode_handle *result;
> > @@ -115,6 +134,7 @@ acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
> >       acpi_bus_put_acpi_device(device);
> >       return result;
> >  }
> > +EXPORT_SYMBOL_GPL(acpi_get_irq_source_fwhandle);
>
> This doesn't look like it needs to be exported either.
>
> >  /*
> >   * Context for the resource walk used to lookup IRQ resources.
> > diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
> > index 14ee631cb7cf..19296d70c95c 100644
> > --- a/drivers/acpi/pci_irq.c
> > +++ b/drivers/acpi/pci_irq.c
> > @@ -410,6 +410,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
> >       char *link = NULL;
> >       char link_desc[16];
> >       int rc;
> > +     struct fwnode_handle *irq_domain;
> >
> >       pin = dev->pin;
> >       if (!pin) {
> > @@ -438,7 +439,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
> >                       gsi = acpi_pci_link_allocate_irq(entry->link,
> >                                                        entry->index,
> >                                                        &triggering, &polarity,
> > -                                                      &link);
> > +                                                      &link,
> > +                                                      &irq_domain);
> >               else
> >                       gsi = entry->index;
> >       } else
> > @@ -462,7 +464,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
> >               return 0;
> >       }
> >
> > -     rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
> > +     rc = acpi_register_irq(&dev->dev, gsi, triggering, polarity, irq_domain);
> >       if (rc < 0) {
> >               dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
> >                        pin_name(pin));
> > diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
> > index fb4c5632a232..219a644d739a 100644
> > --- a/drivers/acpi/pci_link.c
> > +++ b/drivers/acpi/pci_link.c
> > @@ -59,6 +59,7 @@ struct acpi_pci_link_irq {
> >       u8 resource_type;
> >       u8 possible_count;
> >       u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
> > +     struct acpi_resource_source resource_source;
> >       u8 initialized:1;
> >       u8 reserved:7;
> >  };
> > @@ -120,6 +121,8 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
> >               {
> >                       struct acpi_resource_extended_irq *p =
> >                           &resource->data.extended_irq;
> > +                     struct acpi_resource_source *rs =
> > +                         &link->irq.resource_source;
> >                       if (!p || !p->interrupt_count) {
> >                               printk(KERN_WARNING PREFIX
> >                                             "Blank _PRS EXT IRQ resource\n");
> > @@ -140,6 +143,12 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
> >                       link->irq.triggering = p->triggering;
> >                       link->irq.polarity = p->polarity;
> >                       link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
> > +                     if (p->resource_source.string_length) {
> > +                             rs->index = p->resource_source.index;
> > +                             rs->string_length = p->resource_source.string_length;
> > +                             rs->string_ptr = kmalloc(rs->string_length, GFP_KERNEL);
> > +                             strcpy(rs->string_ptr, p->resource_source.string_ptr);
> > +                     }
> >                       break;
> >               }
> >       default:
> > @@ -326,7 +335,8 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
> >                       resource->res.data.extended_irq.shareable = ACPI_SHARED;
> >               resource->res.data.extended_irq.interrupt_count = 1;
> >               resource->res.data.extended_irq.interrupts[0] = irq;
> > -             /* ignore resource_source, it's optional */
> > +             resource->res.data.extended_irq.resource_source =
> > +                     link->irq.resource_source;
> >               break;
> >       default:
> >               printk(KERN_ERR PREFIX "Invalid Resource_type %d\n", link->irq.resource_type);
> > @@ -612,7 +622,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
> >   * failure: return -1
> >   */
> >  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
> > -                            int *polarity, char **name)
> > +                            int *polarity, char **name, struct fwnode_handle **irq_domain)
> >  {
> >       int result;
> >       struct acpi_device *device;
> > @@ -656,6 +666,9 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
> >               *polarity = link->irq.polarity;
> >       if (name)
> >               *name = acpi_device_bid(link->device);
> > +     if (irq_domain)
> > +             *irq_domain = acpi_get_irq_source_fwhandle(&link->irq.resource_source);
> > +
> >       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
> >                         "Link %s is referenced\n",
> >                         acpi_device_bid(link->device)));
> > diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
> > index 5eb175933a5b..6ff1ea76d476 100644
> > --- a/include/acpi/acpi_drivers.h
> > +++ b/include/acpi/acpi_drivers.h
> > @@ -68,7 +68,7 @@
> >
> >  int acpi_irq_penalty_init(void);
> >  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
> > -                            int *polarity, char **name);
> > +                            int *polarity, char **name, struct fwnode_handle **irq_domain);
> >  int acpi_pci_link_free_irq(acpi_handle handle);
> >
> >  /* ACPI PCI Device Binding (pci_bind.c) */
> > diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> > index 39263c6b52e1..5f1d7d3192fb 100644
> > --- a/include/linux/acpi.h
> > +++ b/include/linux/acpi.h
> > @@ -324,6 +324,8 @@ extern int sbf_port;
> >  extern unsigned long acpi_realmode_flags;
> >
> >  int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
> > +int acpi_register_irq(struct device *dev, u32 gsi, int trigger,
> > +                   int polarity, struct fwnode_handle *domain_id);
>
> It looks like this declaration should be in drivers/acpi/internal.h,
> since it's only used inside drivers/acpi/.
>
> >  int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
> >  int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
> >
> > @@ -336,6 +338,8 @@ struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
> >                                            const struct irq_domain_ops *ops,
> >                                            void *host_data);
> >
> > +struct fwnode_handle *acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source);
> > +
> >  #ifdef CONFIG_X86_IO_APIC
> >  extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
> >  #else
> > --
> > 2.28.0
> >

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
@ 2020-11-18 13:45     ` Ard Biesheuvel
  0 siblings, 0 replies; 22+ messages in thread
From: Ard Biesheuvel @ 2020-11-18 13:45 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Lorenzo Pieralisi, Marc Zyngier, PCI, Linux Kernel Mailing List,
	ACPI Devel Maling List, Hanjun Guo, Bjorn Helgaas, Linux ARM,
	Chen Baozi

On Tue, 17 Nov 2020 at 19:57, Bjorn Helgaas <helgaas@kernel.org> wrote:
>
> Nit: please don't just make up random styles for the subject.  Run
> "git log --oneline" on the file and/or the directory and try to follow
> the existing convention.  Using random styles adds noise to the
> system.
>
> On Tue, Nov 17, 2020 at 09:42:14PM +0800, Chen Baozi wrote:
> > Some PCIe designs require software to do extra acknowledgements for
> > legacy INTx interrupts. If the driver is written only for device tree,
> > things are simple. In that case, a new driver can be written under
> > driver/pci/controller/ with a DT node of PCIe host written like:
> >
> >   pcie {
> >     ...
> >     interrupt-map = <0 0 0  1  &pcie_intc 0>,
> >                     <0 0 0  2  &pcie_intc 1>,
> >                     <0 0 0  3  &pcie_intc 2>,
> >                     <0 0 0  4  &pcie_intc 3>;
> >
> >     pcie_intc: legacy-interrupt-controller {
> >       interrupt-controller;
> >       #interrupt-cells = <1>;
> >       interrupt-parent = <&gic>;
> >       interrupts = <0 226 4>;
> >     };
> >   };
> >
> > Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
> > UniPhier PCIe controller at the moment. Essentially, those designs are
> > supported by inserting an extra interrupt controller between PCIe host
> > and GIC and parse the topology in a DT-based PCI controller driver.
>
> If I understand correctly, we previously ignored the Resource Source
> field of an Extended Interrupt Descriptor in the _PRS method of
> PNP0C0F PCI Interrupt Link devices, and this patch adds support for
> it.
>
> If that's true, this has nothing to do with DT, other than DT being
> another way to describe the same topology, and the above details
> really aren't relevant to this patch.
>
> > As we turn to ACPI, All the PCIe hosts are described the same ID of
> > "PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
> > to make this kind of PCI INTx work under ACPI.
>
> s/All the PCIe/all the PCIe/
>
> But this paragraph should probably just go away in favor of something
> about implementing Resource Source support.
>
> > Therefore, we introduce an stacked IRQ domain support to PCI interrupt
> > link for ACPI. With this support, we can populate the ResourceSource
> > to refer to a device object that describes an interrupt controller.
> > That would allow us to refer to a dedicated driver which implements
> > the logic needed to manage the interrupt state. With this patch,
> > those PCI interrupt links can be supported by describing the INTx
> > in ACPI table as the following example:
>
> "Stacked IRQ domain" sounds like a detail of how you're implementing
> support for the Resource Source field for PCI Interrupt Links.
>
> I don't know what the dedicated driver refers to.  This *should* be
> all generic code the follows the ACPI spec (which is pretty sketchy in
> this area).  But I assume that there's no special driver needed for
> devices like \SB.IXIU, and the logic associated with the interrupt
> controller is in the AML associated with IXIU.  It would probably be
> useful to mention the relevant methods in the IXIU methods in the
> example below.
>

As I understand it, the intent is to provide a driver for \SB.IXIU
that acknowledges the legacy INTx interrupts in a SoC specific way,
and I don't see how AML could be involved here.

That also explains why the routines are exported to modules - the IXIU
driver could be modularized.


> From ACPI v6.3, Table 6-200, it looks like this patch should include
> changes to acpi_bus_osc_support() to advertise "Interrupt
> ResourceSource support".
>

I assume this covers all uses of ResourceSource, right? Not only in
the context if PCIe legacy interrupts?

> >   Device (IXIU) {
> >     ...
> >   }
> >
> >   Device(LINKA) {
> >     Name(_HID, EISAID("PNP0C0F"))
> >     Name(_PRS, ResourceTemplate(){
> >       Interrupt(ResourceProducer, Level, ActiveHigh, Exclusive, 0, "\\SB.IXIU")
> >         { 60 }
> >     })
> >     ...
> >   }
> >
> >   Device(PCI0) {
> >     ...
> >     Name(_PRT, Package{
> >       Package{ 0x0000FFFF, 0, LINKA, 0 }
> >       ...
> >     })
> >   }
> >
> > Signed-off-by: Chen Baozi <chenbaozi@phytium.com.cn>
> > ---
> >  drivers/acpi/irq.c          | 22 +++++++++++++++++++++-
> >  drivers/acpi/pci_irq.c      |  6 ++++--
> >  drivers/acpi/pci_link.c     | 17 +++++++++++++++--
> >  include/acpi/acpi_drivers.h |  2 +-
> >  include/linux/acpi.h        |  4 ++++
> >  5 files changed, 45 insertions(+), 6 deletions(-)
> >
> > diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
> > index e209081d644b..e78a44815c44 100644
> > --- a/drivers/acpi/irq.c
> > +++ b/drivers/acpi/irq.c
> > @@ -81,6 +81,25 @@ void acpi_unregister_gsi(u32 gsi)
> >  }
> >  EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
> >
> > +int acpi_register_irq(struct device *dev, u32 irq, int trigger,
> > +                   int polarity, struct fwnode_handle *domain_id)
> > +{
> > +     struct irq_fwspec fwspec;
> > +
> > +     if (WARN_ON(!domain_id)) {
> > +             pr_warn("GSI: No registered irqchip, giving up\n");
>
> This message could contain more information, e.g., by using
> dev_warn(), including the irq value, etc.
>
> > +             return -EINVAL;
> > +     }
> > +
> > +     fwspec.fwnode = domain_id;
> > +     fwspec.param[0] = irq;
> > +     fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
> > +     fwspec.param_count = 2;
> > +
> > +     return irq_create_fwspec_mapping(&fwspec);
> > +}
> > +EXPORT_SYMBOL_GPL(acpi_register_irq);
>
> Why does this need to be exported?  You only call it from
> acpi_pci_irq_enable(), which cannot be a module.
>
> >  /**
> >   * acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ resource source.
> >   * @source: acpi_resource_source to use for the lookup.
> > @@ -92,7 +111,7 @@ EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
> >   * Return:
> >   * The referenced device fwhandle or NULL on failure
> >   */
> > -static struct fwnode_handle *
> > +struct fwnode_handle *
> >  acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
> >  {
> >       struct fwnode_handle *result;
> > @@ -115,6 +134,7 @@ acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source)
> >       acpi_bus_put_acpi_device(device);
> >       return result;
> >  }
> > +EXPORT_SYMBOL_GPL(acpi_get_irq_source_fwhandle);
>
> This doesn't look like it needs to be exported either.
>
> >  /*
> >   * Context for the resource walk used to lookup IRQ resources.
> > diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
> > index 14ee631cb7cf..19296d70c95c 100644
> > --- a/drivers/acpi/pci_irq.c
> > +++ b/drivers/acpi/pci_irq.c
> > @@ -410,6 +410,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
> >       char *link = NULL;
> >       char link_desc[16];
> >       int rc;
> > +     struct fwnode_handle *irq_domain;
> >
> >       pin = dev->pin;
> >       if (!pin) {
> > @@ -438,7 +439,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
> >                       gsi = acpi_pci_link_allocate_irq(entry->link,
> >                                                        entry->index,
> >                                                        &triggering, &polarity,
> > -                                                      &link);
> > +                                                      &link,
> > +                                                      &irq_domain);
> >               else
> >                       gsi = entry->index;
> >       } else
> > @@ -462,7 +464,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
> >               return 0;
> >       }
> >
> > -     rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity);
> > +     rc = acpi_register_irq(&dev->dev, gsi, triggering, polarity, irq_domain);
> >       if (rc < 0) {
> >               dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
> >                        pin_name(pin));
> > diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c
> > index fb4c5632a232..219a644d739a 100644
> > --- a/drivers/acpi/pci_link.c
> > +++ b/drivers/acpi/pci_link.c
> > @@ -59,6 +59,7 @@ struct acpi_pci_link_irq {
> >       u8 resource_type;
> >       u8 possible_count;
> >       u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
> > +     struct acpi_resource_source resource_source;
> >       u8 initialized:1;
> >       u8 reserved:7;
> >  };
> > @@ -120,6 +121,8 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
> >               {
> >                       struct acpi_resource_extended_irq *p =
> >                           &resource->data.extended_irq;
> > +                     struct acpi_resource_source *rs =
> > +                         &link->irq.resource_source;
> >                       if (!p || !p->interrupt_count) {
> >                               printk(KERN_WARNING PREFIX
> >                                             "Blank _PRS EXT IRQ resource\n");
> > @@ -140,6 +143,12 @@ static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource,
> >                       link->irq.triggering = p->triggering;
> >                       link->irq.polarity = p->polarity;
> >                       link->irq.resource_type = ACPI_RESOURCE_TYPE_EXTENDED_IRQ;
> > +                     if (p->resource_source.string_length) {
> > +                             rs->index = p->resource_source.index;
> > +                             rs->string_length = p->resource_source.string_length;
> > +                             rs->string_ptr = kmalloc(rs->string_length, GFP_KERNEL);
> > +                             strcpy(rs->string_ptr, p->resource_source.string_ptr);
> > +                     }
> >                       break;
> >               }
> >       default:
> > @@ -326,7 +335,8 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq)
> >                       resource->res.data.extended_irq.shareable = ACPI_SHARED;
> >               resource->res.data.extended_irq.interrupt_count = 1;
> >               resource->res.data.extended_irq.interrupts[0] = irq;
> > -             /* ignore resource_source, it's optional */
> > +             resource->res.data.extended_irq.resource_source =
> > +                     link->irq.resource_source;
> >               break;
> >       default:
> >               printk(KERN_ERR PREFIX "Invalid Resource_type %d\n", link->irq.resource_type);
> > @@ -612,7 +622,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link)
> >   * failure: return -1
> >   */
> >  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
> > -                            int *polarity, char **name)
> > +                            int *polarity, char **name, struct fwnode_handle **irq_domain)
> >  {
> >       int result;
> >       struct acpi_device *device;
> > @@ -656,6 +666,9 @@ int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
> >               *polarity = link->irq.polarity;
> >       if (name)
> >               *name = acpi_device_bid(link->device);
> > +     if (irq_domain)
> > +             *irq_domain = acpi_get_irq_source_fwhandle(&link->irq.resource_source);
> > +
> >       ACPI_DEBUG_PRINT((ACPI_DB_INFO,
> >                         "Link %s is referenced\n",
> >                         acpi_device_bid(link->device)));
> > diff --git a/include/acpi/acpi_drivers.h b/include/acpi/acpi_drivers.h
> > index 5eb175933a5b..6ff1ea76d476 100644
> > --- a/include/acpi/acpi_drivers.h
> > +++ b/include/acpi/acpi_drivers.h
> > @@ -68,7 +68,7 @@
> >
> >  int acpi_irq_penalty_init(void);
> >  int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering,
> > -                            int *polarity, char **name);
> > +                            int *polarity, char **name, struct fwnode_handle **irq_domain);
> >  int acpi_pci_link_free_irq(acpi_handle handle);
> >
> >  /* ACPI PCI Device Binding (pci_bind.c) */
> > diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> > index 39263c6b52e1..5f1d7d3192fb 100644
> > --- a/include/linux/acpi.h
> > +++ b/include/linux/acpi.h
> > @@ -324,6 +324,8 @@ extern int sbf_port;
> >  extern unsigned long acpi_realmode_flags;
> >
> >  int acpi_register_gsi (struct device *dev, u32 gsi, int triggering, int polarity);
> > +int acpi_register_irq(struct device *dev, u32 gsi, int trigger,
> > +                   int polarity, struct fwnode_handle *domain_id);
>
> It looks like this declaration should be in drivers/acpi/internal.h,
> since it's only used inside drivers/acpi/.
>
> >  int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
> >  int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
> >
> > @@ -336,6 +338,8 @@ struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
> >                                            const struct irq_domain_ops *ops,
> >                                            void *host_data);
> >
> > +struct fwnode_handle *acpi_get_irq_source_fwhandle(const struct acpi_resource_source *source);
> > +
> >  #ifdef CONFIG_X86_IO_APIC
> >  extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
> >  #else
> > --
> > 2.28.0
> >

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
  2020-11-18 13:45     ` Ard Biesheuvel
@ 2020-11-18 13:50       ` Rafael J. Wysocki
  -1 siblings, 0 replies; 22+ messages in thread
From: Rafael J. Wysocki @ 2020-11-18 13:50 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Bjorn Helgaas, Chen Baozi, Hanjun Guo, Marc Zyngier,
	Bjorn Helgaas, ACPI Devel Maling List, PCI, Linux ARM,
	Linux Kernel Mailing List, Lorenzo Pieralisi

On Wed, Nov 18, 2020 at 2:46 PM Ard Biesheuvel <ardb@kernel.org> wrote:
>
> On Tue, 17 Nov 2020 at 19:57, Bjorn Helgaas <helgaas@kernel.org> wrote:
> >
> > Nit: please don't just make up random styles for the subject.  Run
> > "git log --oneline" on the file and/or the directory and try to follow
> > the existing convention.  Using random styles adds noise to the
> > system.
> >
> > On Tue, Nov 17, 2020 at 09:42:14PM +0800, Chen Baozi wrote:
> > > Some PCIe designs require software to do extra acknowledgements for
> > > legacy INTx interrupts. If the driver is written only for device tree,
> > > things are simple. In that case, a new driver can be written under
> > > driver/pci/controller/ with a DT node of PCIe host written like:
> > >
> > >   pcie {
> > >     ...
> > >     interrupt-map = <0 0 0  1  &pcie_intc 0>,
> > >                     <0 0 0  2  &pcie_intc 1>,
> > >                     <0 0 0  3  &pcie_intc 2>,
> > >                     <0 0 0  4  &pcie_intc 3>;
> > >
> > >     pcie_intc: legacy-interrupt-controller {
> > >       interrupt-controller;
> > >       #interrupt-cells = <1>;
> > >       interrupt-parent = <&gic>;
> > >       interrupts = <0 226 4>;
> > >     };
> > >   };
> > >
> > > Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
> > > UniPhier PCIe controller at the moment. Essentially, those designs are
> > > supported by inserting an extra interrupt controller between PCIe host
> > > and GIC and parse the topology in a DT-based PCI controller driver.
> >
> > If I understand correctly, we previously ignored the Resource Source
> > field of an Extended Interrupt Descriptor in the _PRS method of
> > PNP0C0F PCI Interrupt Link devices, and this patch adds support for
> > it.
> >
> > If that's true, this has nothing to do with DT, other than DT being
> > another way to describe the same topology, and the above details
> > really aren't relevant to this patch.
> >
> > > As we turn to ACPI, All the PCIe hosts are described the same ID of
> > > "PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
> > > to make this kind of PCI INTx work under ACPI.
> >
> > s/All the PCIe/all the PCIe/
> >
> > But this paragraph should probably just go away in favor of something
> > about implementing Resource Source support.
> >
> > > Therefore, we introduce an stacked IRQ domain support to PCI interrupt
> > > link for ACPI. With this support, we can populate the ResourceSource
> > > to refer to a device object that describes an interrupt controller.
> > > That would allow us to refer to a dedicated driver which implements
> > > the logic needed to manage the interrupt state. With this patch,
> > > those PCI interrupt links can be supported by describing the INTx
> > > in ACPI table as the following example:
> >
> > "Stacked IRQ domain" sounds like a detail of how you're implementing
> > support for the Resource Source field for PCI Interrupt Links.
> >
> > I don't know what the dedicated driver refers to.  This *should* be
> > all generic code the follows the ACPI spec (which is pretty sketchy in
> > this area).  But I assume that there's no special driver needed for
> > devices like \SB.IXIU, and the logic associated with the interrupt
> > controller is in the AML associated with IXIU.  It would probably be
> > useful to mention the relevant methods in the IXIU methods in the
> > example below.
> >
>
> As I understand it, the intent is to provide a driver for \SB.IXIU
> that acknowledges the legacy INTx interrupts in a SoC specific way,
> and I don't see how AML could be involved here.
>
> That also explains why the routines are exported to modules - the IXIU
> driver could be modularized.

OK, but every new symbol export requires an in-the-tree user or the
patch is basically not applicable.

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
@ 2020-11-18 13:50       ` Rafael J. Wysocki
  0 siblings, 0 replies; 22+ messages in thread
From: Rafael J. Wysocki @ 2020-11-18 13:50 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Lorenzo Pieralisi, Marc Zyngier, PCI, Linux Kernel Mailing List,
	ACPI Devel Maling List, Bjorn Helgaas, Hanjun Guo, Bjorn Helgaas,
	Linux ARM, Chen Baozi

On Wed, Nov 18, 2020 at 2:46 PM Ard Biesheuvel <ardb@kernel.org> wrote:
>
> On Tue, 17 Nov 2020 at 19:57, Bjorn Helgaas <helgaas@kernel.org> wrote:
> >
> > Nit: please don't just make up random styles for the subject.  Run
> > "git log --oneline" on the file and/or the directory and try to follow
> > the existing convention.  Using random styles adds noise to the
> > system.
> >
> > On Tue, Nov 17, 2020 at 09:42:14PM +0800, Chen Baozi wrote:
> > > Some PCIe designs require software to do extra acknowledgements for
> > > legacy INTx interrupts. If the driver is written only for device tree,
> > > things are simple. In that case, a new driver can be written under
> > > driver/pci/controller/ with a DT node of PCIe host written like:
> > >
> > >   pcie {
> > >     ...
> > >     interrupt-map = <0 0 0  1  &pcie_intc 0>,
> > >                     <0 0 0  2  &pcie_intc 1>,
> > >                     <0 0 0  3  &pcie_intc 2>,
> > >                     <0 0 0  4  &pcie_intc 3>;
> > >
> > >     pcie_intc: legacy-interrupt-controller {
> > >       interrupt-controller;
> > >       #interrupt-cells = <1>;
> > >       interrupt-parent = <&gic>;
> > >       interrupts = <0 226 4>;
> > >     };
> > >   };
> > >
> > > Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
> > > UniPhier PCIe controller at the moment. Essentially, those designs are
> > > supported by inserting an extra interrupt controller between PCIe host
> > > and GIC and parse the topology in a DT-based PCI controller driver.
> >
> > If I understand correctly, we previously ignored the Resource Source
> > field of an Extended Interrupt Descriptor in the _PRS method of
> > PNP0C0F PCI Interrupt Link devices, and this patch adds support for
> > it.
> >
> > If that's true, this has nothing to do with DT, other than DT being
> > another way to describe the same topology, and the above details
> > really aren't relevant to this patch.
> >
> > > As we turn to ACPI, All the PCIe hosts are described the same ID of
> > > "PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
> > > to make this kind of PCI INTx work under ACPI.
> >
> > s/All the PCIe/all the PCIe/
> >
> > But this paragraph should probably just go away in favor of something
> > about implementing Resource Source support.
> >
> > > Therefore, we introduce an stacked IRQ domain support to PCI interrupt
> > > link for ACPI. With this support, we can populate the ResourceSource
> > > to refer to a device object that describes an interrupt controller.
> > > That would allow us to refer to a dedicated driver which implements
> > > the logic needed to manage the interrupt state. With this patch,
> > > those PCI interrupt links can be supported by describing the INTx
> > > in ACPI table as the following example:
> >
> > "Stacked IRQ domain" sounds like a detail of how you're implementing
> > support for the Resource Source field for PCI Interrupt Links.
> >
> > I don't know what the dedicated driver refers to.  This *should* be
> > all generic code the follows the ACPI spec (which is pretty sketchy in
> > this area).  But I assume that there's no special driver needed for
> > devices like \SB.IXIU, and the logic associated with the interrupt
> > controller is in the AML associated with IXIU.  It would probably be
> > useful to mention the relevant methods in the IXIU methods in the
> > example below.
> >
>
> As I understand it, the intent is to provide a driver for \SB.IXIU
> that acknowledges the legacy INTx interrupts in a SoC specific way,
> and I don't see how AML could be involved here.
>
> That also explains why the routines are exported to modules - the IXIU
> driver could be modularized.

OK, but every new symbol export requires an in-the-tree user or the
patch is basically not applicable.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
  2020-11-18  9:51   ` Lorenzo Pieralisi
@ 2020-11-18 14:05     ` Chen Baozi
  -1 siblings, 0 replies; 22+ messages in thread
From: Chen Baozi @ 2020-11-18 14:05 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: Marc Zyngier, Guohanjun, linux-kernel, linux-acpi, linux-pci,
	Bjorn Helgaas, Ard Biesheuvel, linux-arm-kernel

Hi Lorenzo,

> On Nov 18, 2020, at 5:51 PM, Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> wrote:
> 
> On Tue, Nov 17, 2020 at 09:42:14PM +0800, Chen Baozi wrote:
>> Some PCIe designs require software to do extra acknowledgements for
>> legacy INTx interrupts. If the driver is written only for device tree,
>> things are simple. In that case, a new driver can be written under
>> driver/pci/controller/ with a DT node of PCIe host written like:
>> 
>>  pcie {
>>    ...
>>    interrupt-map = <0 0 0  1  &pcie_intc 0>,
>>                    <0 0 0  2  &pcie_intc 1>,
>>                    <0 0 0  3  &pcie_intc 2>,
>>                    <0 0 0  4  &pcie_intc 3>;
>> 
>>    pcie_intc: legacy-interrupt-controller {
>>      interrupt-controller;
>>      #interrupt-cells = <1>;
>>      interrupt-parent = <&gic>;
>>      interrupts = <0 226 4>;
>>    };
>>  };
>> 
>> Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
>> UniPhier PCIe controller at the moment. Essentially, those designs are
>> supported by inserting an extra interrupt controller between PCIe host
>> and GIC and parse the topology in a DT-based PCI controller driver.
>> As we turn to ACPI, All the PCIe hosts are described the same ID of
>> "PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
>> to make this kind of PCI INTx work under ACPI.
> 
> In this respect this patch is a minor detail. The major detail is how
> those host controllers are going to probe and initialize with ACPI and I
> am against merging this patch stand alone with no user before
> understanding what you really want to do with those host controller
> drivers in the ACPI world.
> 
> Side note, there is ongoing work for a generic interrupt MUX:
> 
> https://bugzilla.tianocore.org/show_bug.cgi?id=2995
> 
> If we ever come to support those MUXes with ACPI that must be a
> starting point, the binding above can be your first "user".
> 
> I still have reservations about bootstrapping the host controllers
> you mentioned in platforms with no firmware support whatsoever for
> PCI initialization (eg address decoders, link bring-up, etc. - the
> ACPI host bridge model relies on FW to carry out that initialization)
> with ACPI - I would like to see the whole picture first.

Frankly, I’m also waiting for my first “user” to be announced at the moment,
so that I can make the whole picture clearer. And it is why I mark this
patch as an RFC. 

Yes. I admit it is a little weird to add another interrupt controller
between the GIC and INTx device. But if it is not only about
initialization but also about hooking into the INTx processing (e.g.,
introduce an extra ack operation...), it seems we cannot only rely
on FW. I have looked for a FW solution without introducing a new
driver later but failed... I’m happy to be fixed if there is a pure
FW solution.

Thanks.

Baozi.


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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
@ 2020-11-18 14:05     ` Chen Baozi
  0 siblings, 0 replies; 22+ messages in thread
From: Chen Baozi @ 2020-11-18 14:05 UTC (permalink / raw)
  To: Lorenzo Pieralisi
  Cc: linux-pci, Guohanjun, linux-kernel, linux-acpi, Marc Zyngier,
	Bjorn Helgaas, Ard Biesheuvel, linux-arm-kernel

Hi Lorenzo,

> On Nov 18, 2020, at 5:51 PM, Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> wrote:
> 
> On Tue, Nov 17, 2020 at 09:42:14PM +0800, Chen Baozi wrote:
>> Some PCIe designs require software to do extra acknowledgements for
>> legacy INTx interrupts. If the driver is written only for device tree,
>> things are simple. In that case, a new driver can be written under
>> driver/pci/controller/ with a DT node of PCIe host written like:
>> 
>>  pcie {
>>    ...
>>    interrupt-map = <0 0 0  1  &pcie_intc 0>,
>>                    <0 0 0  2  &pcie_intc 1>,
>>                    <0 0 0  3  &pcie_intc 2>,
>>                    <0 0 0  4  &pcie_intc 3>;
>> 
>>    pcie_intc: legacy-interrupt-controller {
>>      interrupt-controller;
>>      #interrupt-cells = <1>;
>>      interrupt-parent = <&gic>;
>>      interrupts = <0 226 4>;
>>    };
>>  };
>> 
>> Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
>> UniPhier PCIe controller at the moment. Essentially, those designs are
>> supported by inserting an extra interrupt controller between PCIe host
>> and GIC and parse the topology in a DT-based PCI controller driver.
>> As we turn to ACPI, All the PCIe hosts are described the same ID of
>> "PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
>> to make this kind of PCI INTx work under ACPI.
> 
> In this respect this patch is a minor detail. The major detail is how
> those host controllers are going to probe and initialize with ACPI and I
> am against merging this patch stand alone with no user before
> understanding what you really want to do with those host controller
> drivers in the ACPI world.
> 
> Side note, there is ongoing work for a generic interrupt MUX:
> 
> https://bugzilla.tianocore.org/show_bug.cgi?id=2995
> 
> If we ever come to support those MUXes with ACPI that must be a
> starting point, the binding above can be your first "user".
> 
> I still have reservations about bootstrapping the host controllers
> you mentioned in platforms with no firmware support whatsoever for
> PCI initialization (eg address decoders, link bring-up, etc. - the
> ACPI host bridge model relies on FW to carry out that initialization)
> with ACPI - I would like to see the whole picture first.

Frankly, I’m also waiting for my first “user” to be announced at the moment,
so that I can make the whole picture clearer. And it is why I mark this
patch as an RFC. 

Yes. I admit it is a little weird to add another interrupt controller
between the GIC and INTx device. But if it is not only about
initialization but also about hooking into the INTx processing (e.g.,
introduce an extra ack operation...), it seems we cannot only rely
on FW. I have looked for a FW solution without introducing a new
driver later but failed... I’m happy to be fixed if there is a pure
FW solution.

Thanks.

Baozi.


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
  2020-11-18 14:05     ` Chen Baozi
@ 2020-11-19 10:37       ` Lorenzo Pieralisi
  -1 siblings, 0 replies; 22+ messages in thread
From: Lorenzo Pieralisi @ 2020-11-19 10:37 UTC (permalink / raw)
  To: Chen Baozi
  Cc: Marc Zyngier, Guohanjun, linux-kernel, linux-acpi, linux-pci,
	Bjorn Helgaas, Ard Biesheuvel, linux-arm-kernel

On Wed, Nov 18, 2020 at 10:05:29PM +0800, Chen Baozi wrote:
> Hi Lorenzo,
> 
> > On Nov 18, 2020, at 5:51 PM, Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> wrote:
> > 
> > On Tue, Nov 17, 2020 at 09:42:14PM +0800, Chen Baozi wrote:
> >> Some PCIe designs require software to do extra acknowledgements for
> >> legacy INTx interrupts. If the driver is written only for device tree,
> >> things are simple. In that case, a new driver can be written under
> >> driver/pci/controller/ with a DT node of PCIe host written like:
> >> 
> >>  pcie {
> >>    ...
> >>    interrupt-map = <0 0 0  1  &pcie_intc 0>,
> >>                    <0 0 0  2  &pcie_intc 1>,
> >>                    <0 0 0  3  &pcie_intc 2>,
> >>                    <0 0 0  4  &pcie_intc 3>;
> >> 
> >>    pcie_intc: legacy-interrupt-controller {
> >>      interrupt-controller;
> >>      #interrupt-cells = <1>;
> >>      interrupt-parent = <&gic>;
> >>      interrupts = <0 226 4>;
> >>    };
> >>  };
> >> 
> >> Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
> >> UniPhier PCIe controller at the moment. Essentially, those designs are
> >> supported by inserting an extra interrupt controller between PCIe host
> >> and GIC and parse the topology in a DT-based PCI controller driver.
> >> As we turn to ACPI, All the PCIe hosts are described the same ID of
> >> "PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
> >> to make this kind of PCI INTx work under ACPI.
> > 
> > In this respect this patch is a minor detail. The major detail is how
> > those host controllers are going to probe and initialize with ACPI and I
> > am against merging this patch stand alone with no user before
> > understanding what you really want to do with those host controller
> > drivers in the ACPI world.
> > 
> > Side note, there is ongoing work for a generic interrupt MUX:
> > 
> > https://bugzilla.tianocore.org/show_bug.cgi?id=2995
> > 
> > If we ever come to support those MUXes with ACPI that must be a
> > starting point, the binding above can be your first "user".
> > 
> > I still have reservations about bootstrapping the host controllers
> > you mentioned in platforms with no firmware support whatsoever for
> > PCI initialization (eg address decoders, link bring-up, etc. - the
> > ACPI host bridge model relies on FW to carry out that initialization)
> > with ACPI - I would like to see the whole picture first.
> 
> Frankly, I’m also waiting for my first “user” to be announced at the
> moment, so that I can make the whole picture clearer. And it is why I
> mark this patch as an RFC. 

AFAIK none of the host controllers requiring this IRQ muxing is shipped
with a firmware stack that can bootstrap them with ACPI.

That's why I think this patch is a thought exercise, there is not much
to talk about.

> Yes. I admit it is a little weird to add another interrupt controller
> between the GIC and INTx device. But if it is not only about
> initialization but also about hooking into the INTx processing (e.g.,
> introduce an extra ack operation...), it seems we cannot only rely
> on FW. I have looked for a FW solution without introducing a new
> driver later but failed... I’m happy to be fixed if there is a pure
> FW solution.

I did not say that to solve the INTX muxing we can use FW. I said that
to probe the host controllers that require this muxing there must be
firmware in place (to allow probing them with ACPI) before we look at
solving the PCI INTX muxing issue.

We should not solve issues that don't exist ;-)

Thanks,
Lorenzo

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
@ 2020-11-19 10:37       ` Lorenzo Pieralisi
  0 siblings, 0 replies; 22+ messages in thread
From: Lorenzo Pieralisi @ 2020-11-19 10:37 UTC (permalink / raw)
  To: Chen Baozi
  Cc: linux-pci, Guohanjun, linux-kernel, linux-acpi, Marc Zyngier,
	Bjorn Helgaas, Ard Biesheuvel, linux-arm-kernel

On Wed, Nov 18, 2020 at 10:05:29PM +0800, Chen Baozi wrote:
> Hi Lorenzo,
> 
> > On Nov 18, 2020, at 5:51 PM, Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> wrote:
> > 
> > On Tue, Nov 17, 2020 at 09:42:14PM +0800, Chen Baozi wrote:
> >> Some PCIe designs require software to do extra acknowledgements for
> >> legacy INTx interrupts. If the driver is written only for device tree,
> >> things are simple. In that case, a new driver can be written under
> >> driver/pci/controller/ with a DT node of PCIe host written like:
> >> 
> >>  pcie {
> >>    ...
> >>    interrupt-map = <0 0 0  1  &pcie_intc 0>,
> >>                    <0 0 0  2  &pcie_intc 1>,
> >>                    <0 0 0  3  &pcie_intc 2>,
> >>                    <0 0 0  4  &pcie_intc 3>;
> >> 
> >>    pcie_intc: legacy-interrupt-controller {
> >>      interrupt-controller;
> >>      #interrupt-cells = <1>;
> >>      interrupt-parent = <&gic>;
> >>      interrupts = <0 226 4>;
> >>    };
> >>  };
> >> 
> >> Similar designs can be found on Aardvark, MediaTek Gen2 and Socionext
> >> UniPhier PCIe controller at the moment. Essentially, those designs are
> >> supported by inserting an extra interrupt controller between PCIe host
> >> and GIC and parse the topology in a DT-based PCI controller driver.
> >> As we turn to ACPI, All the PCIe hosts are described the same ID of
> >> "PNP0A03" and share driver/acpi/pci_root.c. It comes to be a problem
> >> to make this kind of PCI INTx work under ACPI.
> > 
> > In this respect this patch is a minor detail. The major detail is how
> > those host controllers are going to probe and initialize with ACPI and I
> > am against merging this patch stand alone with no user before
> > understanding what you really want to do with those host controller
> > drivers in the ACPI world.
> > 
> > Side note, there is ongoing work for a generic interrupt MUX:
> > 
> > https://bugzilla.tianocore.org/show_bug.cgi?id=2995
> > 
> > If we ever come to support those MUXes with ACPI that must be a
> > starting point, the binding above can be your first "user".
> > 
> > I still have reservations about bootstrapping the host controllers
> > you mentioned in platforms with no firmware support whatsoever for
> > PCI initialization (eg address decoders, link bring-up, etc. - the
> > ACPI host bridge model relies on FW to carry out that initialization)
> > with ACPI - I would like to see the whole picture first.
> 
> Frankly, I’m also waiting for my first “user” to be announced at the
> moment, so that I can make the whole picture clearer. And it is why I
> mark this patch as an RFC. 

AFAIK none of the host controllers requiring this IRQ muxing is shipped
with a firmware stack that can bootstrap them with ACPI.

That's why I think this patch is a thought exercise, there is not much
to talk about.

> Yes. I admit it is a little weird to add another interrupt controller
> between the GIC and INTx device. But if it is not only about
> initialization but also about hooking into the INTx processing (e.g.,
> introduce an extra ack operation...), it seems we cannot only rely
> on FW. I have looked for a FW solution without introducing a new
> driver later but failed... I’m happy to be fixed if there is a pure
> FW solution.

I did not say that to solve the INTX muxing we can use FW. I said that
to probe the host controllers that require this muxing there must be
firmware in place (to allow probing them with ACPI) before we look at
solving the PCI INTX muxing issue.

We should not solve issues that don't exist ;-)

Thanks,
Lorenzo

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link
@ 2020-11-18 16:22 kernel test robot
  0 siblings, 0 replies; 22+ messages in thread
From: kernel test robot @ 2020-11-18 16:22 UTC (permalink / raw)
  To: kbuild

[-- Attachment #1: Type: text/plain, Size: 8704 bytes --]

CC: kbuild-all(a)lists.01.org
In-Reply-To: <20201117134214.970-1-chenbaozi@phytium.com.cn>
References: <20201117134214.970-1-chenbaozi@phytium.com.cn>
TO: Chen Baozi <chenbaozi@phytium.com.cn>

Hi Chen,

[FYI, it's a private test report for your RFC patch.]
[auto build test WARNING on pm/linux-next]
[also build test WARNING on pci/next v5.10-rc4 next-20201118]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Chen-Baozi/acpi-irq-Add-stacked-IRQ-domain-support-to-PCI-interrupt-link/20201117-214552
base:   https://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git linux-next
:::::: branch date: 27 hours ago
:::::: commit date: 27 hours ago
config: x86_64-randconfig-m001-20201118 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-15) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

smatch warnings:
drivers/acpi/pci_irq.c:467 acpi_pci_irq_enable() error: uninitialized symbol 'irq_domain'.

vim +/irq_domain +467 drivers/acpi/pci_irq.c

e237a5518425155 Chen Fan          2016-02-15  394  
4be44fcd3bf648b Len Brown         2005-08-05  395  int acpi_pci_irq_enable(struct pci_dev *dev)
^1da177e4c3f415 Linus Torvalds    2005-04-16  396  {
beba8a643d7f774 Bjorn Helgaas     2008-12-08  397  	struct acpi_prt_entry *entry;
3f0f3c27be19d39 Bjorn Helgaas     2008-12-08  398  	int gsi;
3f0f3c27be19d39 Bjorn Helgaas     2008-12-08  399  	u8 pin;
50eca3eb89d73d9 Bob Moore         2005-09-30  400  	int triggering = ACPI_LEVEL_SENSITIVE;
10b68700add43d0 Lorenzo Pieralisi 2016-09-05  401  	/*
10b68700add43d0 Lorenzo Pieralisi 2016-09-05  402  	 * On ARM systems with the GIC interrupt model, level interrupts
10b68700add43d0 Lorenzo Pieralisi 2016-09-05  403  	 * are always polarity high by specification; PCI legacy
10b68700add43d0 Lorenzo Pieralisi 2016-09-05  404  	 * IRQs lines are inverted before reaching the interrupt
10b68700add43d0 Lorenzo Pieralisi 2016-09-05  405  	 * controller and must therefore be considered active high
10b68700add43d0 Lorenzo Pieralisi 2016-09-05  406  	 * as default.
10b68700add43d0 Lorenzo Pieralisi 2016-09-05  407  	 */
10b68700add43d0 Lorenzo Pieralisi 2016-09-05  408  	int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ?
10b68700add43d0 Lorenzo Pieralisi 2016-09-05  409  				      ACPI_ACTIVE_HIGH : ACPI_ACTIVE_LOW;
^1da177e4c3f415 Linus Torvalds    2005-04-16  410  	char *link = NULL;
c83642d5123225a Bjorn Helgaas     2008-06-27  411  	char link_desc[16];
349f0d5640c18db Kenji Kaneshige   2005-07-28  412  	int rc;
76f0a22bc937647 Chen Baozi        2020-11-17  413  	struct fwnode_handle *irq_domain;
^1da177e4c3f415 Linus Torvalds    2005-04-16  414  
8015a01486a0f78 Kristen Accardi   2005-11-02  415  	pin = dev->pin;
^1da177e4c3f415 Linus Torvalds    2005-04-16  416  	if (!pin) {
4be44fcd3bf648b Len Brown         2005-08-05  417  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd3bf648b Len Brown         2005-08-05  418  				  "No interrupt pin configured for device %s\n",
4be44fcd3bf648b Len Brown         2005-08-05  419  				  pci_name(dev)));
d550d98d3317378 Patrick Mochel    2006-06-27  420  		return 0;
^1da177e4c3f415 Linus Torvalds    2005-04-16  421  	}
^1da177e4c3f415 Linus Torvalds    2005-04-16  422  
67b4eab91caf2ad Bjorn Helgaas     2016-02-17  423  	if (dev->irq_managed && dev->irq > 0)
cffe0a2b5a34c95 Jiang Liu         2014-10-27  424  		return 0;
cffe0a2b5a34c95 Jiang Liu         2014-10-27  425  
beba8a643d7f774 Bjorn Helgaas     2008-12-08  426  	entry = acpi_pci_irq_lookup(dev, pin);
5697b7ca406b4ee Bjorn Helgaas     2008-12-08  427  	if (!entry) {
^1da177e4c3f415 Linus Torvalds    2005-04-16  428  		/*
5697b7ca406b4ee Bjorn Helgaas     2008-12-08  429  		 * IDE legacy mode controller IRQs are magic. Why do compat
5697b7ca406b4ee Bjorn Helgaas     2008-12-08  430  		 * extensions always make such a nasty mess.
^1da177e4c3f415 Linus Torvalds    2005-04-16  431  		 */
5697b7ca406b4ee Bjorn Helgaas     2008-12-08  432  		if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE &&
5697b7ca406b4ee Bjorn Helgaas     2008-12-08  433  				(dev->class & 0x05) == 0)
5697b7ca406b4ee Bjorn Helgaas     2008-12-08  434  			return 0;
5697b7ca406b4ee Bjorn Helgaas     2008-12-08  435  	}
beba8a643d7f774 Bjorn Helgaas     2008-12-08  436  
74f82af1eda39c2 Bjorn Helgaas     2008-12-08  437  	if (entry) {
74f82af1eda39c2 Bjorn Helgaas     2008-12-08  438  		if (entry->link)
74f82af1eda39c2 Bjorn Helgaas     2008-12-08  439  			gsi = acpi_pci_link_allocate_irq(entry->link,
74f82af1eda39c2 Bjorn Helgaas     2008-12-08  440  							 entry->index,
74f82af1eda39c2 Bjorn Helgaas     2008-12-08  441  							 &triggering, &polarity,
76f0a22bc937647 Chen Baozi        2020-11-17  442  							 &link,
76f0a22bc937647 Chen Baozi        2020-11-17  443  							 &irq_domain);
beba8a643d7f774 Bjorn Helgaas     2008-12-08  444  		else
74f82af1eda39c2 Bjorn Helgaas     2008-12-08  445  			gsi = entry->index;
74f82af1eda39c2 Bjorn Helgaas     2008-12-08  446  	} else
beba8a643d7f774 Bjorn Helgaas     2008-12-08  447  		gsi = -1;
^1da177e4c3f415 Linus Torvalds    2005-04-16  448  
e237a5518425155 Chen Fan          2016-02-15  449  	if (gsi < 0) {
^1da177e4c3f415 Linus Torvalds    2005-04-16  450  		/*
^1da177e4c3f415 Linus Torvalds    2005-04-16  451  		 * No IRQ known to the ACPI subsystem - maybe the BIOS /
^1da177e4c3f415 Linus Torvalds    2005-04-16  452  		 * driver reported one, then use it. Exit in any case.
^1da177e4c3f415 Linus Torvalds    2005-04-16  453  		 */
29b49958cf73b43 Wenwen Wang       2019-08-20  454  		if (!acpi_pci_irq_valid(dev, pin)) {
29b49958cf73b43 Wenwen Wang       2019-08-20  455  			kfree(entry);
e237a5518425155 Chen Fan          2016-02-15  456  			return 0;
29b49958cf73b43 Wenwen Wang       2019-08-20  457  		}
e237a5518425155 Chen Fan          2016-02-15  458  
c1aaae673f68448 Tomasz Nowicki    2014-02-20  459  		if (acpi_isa_register_gsi(dev))
66fd3835ac9a374 Joe Perches       2012-11-21  460  			dev_warn(&dev->dev, "PCI INT %c: no GSI\n",
66fd3835ac9a374 Joe Perches       2012-11-21  461  				 pin_name(pin));
181380b702eee1a Yinghai Lu        2013-02-16  462  
b685f3b1744061a Tomasz Nowicki    2014-02-10  463  		kfree(entry);
66fd3835ac9a374 Joe Perches       2012-11-21  464  		return 0;
^1da177e4c3f415 Linus Torvalds    2005-04-16  465  	}
^1da177e4c3f415 Linus Torvalds    2005-04-16  466  
76f0a22bc937647 Chen Baozi        2020-11-17 @467  	rc = acpi_register_irq(&dev->dev, gsi, triggering, polarity, irq_domain);
349f0d5640c18db Kenji Kaneshige   2005-07-28  468  	if (rc < 0) {
c83642d5123225a Bjorn Helgaas     2008-06-27  469  		dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n",
cf68b80b0e0cbc6 Bjorn Helgaas     2008-12-08  470  			 pin_name(pin));
181380b702eee1a Yinghai Lu        2013-02-16  471  		kfree(entry);
d550d98d3317378 Patrick Mochel    2006-06-27  472  		return rc;
349f0d5640c18db Kenji Kaneshige   2005-07-28  473  	}
67b4eab91caf2ad Bjorn Helgaas     2016-02-17  474  	dev->irq = rc;
67b4eab91caf2ad Bjorn Helgaas     2016-02-17  475  	dev->irq_managed = 1;
^1da177e4c3f415 Linus Torvalds    2005-04-16  476  
^1da177e4c3f415 Linus Torvalds    2005-04-16  477  	if (link)
c83642d5123225a Bjorn Helgaas     2008-06-27  478  		snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
c83642d5123225a Bjorn Helgaas     2008-06-27  479  	else
c83642d5123225a Bjorn Helgaas     2008-06-27  480  		link_desc[0] = '\0';
^1da177e4c3f415 Linus Torvalds    2005-04-16  481  
85b8582d7ca5160 Vincent Palatin   2011-12-05  482  	dev_dbg(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n",
cf68b80b0e0cbc6 Bjorn Helgaas     2008-12-08  483  		pin_name(pin), link_desc, gsi,
50eca3eb89d73d9 Bob Moore         2005-09-30  484  		(triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
50eca3eb89d73d9 Bob Moore         2005-09-30  485  		(polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
^1da177e4c3f415 Linus Torvalds    2005-04-16  486  
181380b702eee1a Yinghai Lu        2013-02-16  487  	kfree(entry);
d550d98d3317378 Patrick Mochel    2006-06-27  488  	return 0;
^1da177e4c3f415 Linus Torvalds    2005-04-16  489  }
^1da177e4c3f415 Linus Torvalds    2005-04-16  490  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 33186 bytes --]

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

end of thread, other threads:[~2020-11-19 10:38 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-17 13:42 [RFC PATCH V2] acpi/irq: Add stacked IRQ domain support to PCI interrupt link Chen Baozi
2020-11-17 13:42 ` Chen Baozi
2020-11-17 18:57 ` Bjorn Helgaas
2020-11-17 18:57   ` Bjorn Helgaas
2020-11-18 10:37   ` Chen Baozi
2020-11-18 10:37     ` Chen Baozi
2020-11-18 13:45   ` Ard Biesheuvel
2020-11-18 13:45     ` Ard Biesheuvel
2020-11-18 13:50     ` Rafael J. Wysocki
2020-11-18 13:50       ` Rafael J. Wysocki
2020-11-17 20:01 ` kernel test robot
2020-11-18  9:27 ` Marc Zyngier
2020-11-18  9:27   ` Marc Zyngier
2020-11-18 13:36   ` Chen Baozi
2020-11-18 13:36     ` Chen Baozi
2020-11-18  9:51 ` Lorenzo Pieralisi
2020-11-18  9:51   ` Lorenzo Pieralisi
2020-11-18 14:05   ` Chen Baozi
2020-11-18 14:05     ` Chen Baozi
2020-11-19 10:37     ` Lorenzo Pieralisi
2020-11-19 10:37       ` Lorenzo Pieralisi
2020-11-18 16:22 kernel test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.