[PATCH v2 7/7] irqchip/gic-v5: Add ACPI IWB probing

Lorenzo Pieralisi posted 7 patches 1 month, 3 weeks ago
There is a newer version of this series
[PATCH v2 7/7] irqchip/gic-v5: Add ACPI IWB probing
Posted by Lorenzo Pieralisi 1 month, 3 weeks ago
To probe an IWB in an ACPI based system it is required:

- to implement the IORT functions handling the IWB IORT node and create
  functions to retrieve IWB firmware information
- to augment the driver to match the DSDT ACPI "ARMH0003" device and
  retrieve the IWB wire and trigger mask from the GSI interrupt descriptor
  in the IWB msi_domain_ops.msi_translate() function

Make the required driver changes to enable IWB probing in ACPI systems.

The GICv5 GSI format requires special handling for IWB routed IRQs.

Add IWB GSI detection to the top level driver gic_v5_get_gsi_domain_id()
function so that the correct IRQ domain for a GSI can be detected by
parsing the GSI and check whether it is an IWB-backed IRQ or not.

Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Hanjun Guo <guohanjun@huawei.com>
Cc: Sudeep Holla <sudeep.holla@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
---
 drivers/acpi/arm64/iort.c          | 95 ++++++++++++++++++++++++++++++++------
 drivers/irqchip/irq-gic-v5-iwb.c   | 42 +++++++++++++----
 drivers/irqchip/irq-gic-v5.c       |  4 ++
 include/linux/acpi_iort.h          |  1 +
 include/linux/irqchip/arm-gic-v5.h |  6 +++
 5 files changed, 123 insertions(+), 25 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 17dbe66da804..4b0b753db738 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -264,39 +264,47 @@ static acpi_status iort_match_node_callback(struct acpi_iort_node *node,
 	struct device *dev = context;
 	acpi_status status = AE_NOT_FOUND;
 
-	if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT) {
+	if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT ||
+	    node->type == ACPI_IORT_NODE_IWB) {
 		struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
-		struct acpi_device *adev;
 		struct acpi_iort_named_component *ncomp;
-		struct device *nc_dev = dev;
+		struct acpi_iort_iwb *iwb;
+		struct device *cdev = dev;
+		struct acpi_device *adev;
+		const char *device_name;
 
 		/*
 		 * Walk the device tree to find a device with an
 		 * ACPI companion; there is no point in scanning
-		 * IORT for a device matching a named component if
+		 * IORT for a device matching a named component or IWB if
 		 * the device does not have an ACPI companion to
 		 * start with.
 		 */
 		do {
-			adev = ACPI_COMPANION(nc_dev);
+			adev = ACPI_COMPANION(cdev);
 			if (adev)
 				break;
 
-			nc_dev = nc_dev->parent;
-		} while (nc_dev);
+			cdev = cdev->parent;
+		} while (cdev);
 
 		if (!adev)
 			goto out;
 
 		status = acpi_get_name(adev->handle, ACPI_FULL_PATHNAME, &buf);
 		if (ACPI_FAILURE(status)) {
-			dev_warn(nc_dev, "Can't get device full path name\n");
+			dev_warn(cdev, "Can't get device full path name\n");
 			goto out;
 		}
 
-		ncomp = (struct acpi_iort_named_component *)node->node_data;
-		status = !strcmp(ncomp->device_name, buf.pointer) ?
-							AE_OK : AE_NOT_FOUND;
+		if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT) {
+			ncomp = (struct acpi_iort_named_component *)node->node_data;
+			device_name = ncomp->device_name;
+		} else {
+			iwb = (struct acpi_iort_iwb *)node->node_data;
+			device_name = iwb->device_name;
+		}
+		status = !strcmp(device_name, buf.pointer) ?  AE_OK : AE_NOT_FOUND;
 		acpi_os_free(buf.pointer);
 	} else if (node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX) {
 		struct acpi_iort_root_complex *pci_rc;
@@ -317,12 +325,28 @@ static acpi_status iort_match_node_callback(struct acpi_iort_node *node,
 	return status;
 }
 
+static acpi_status iort_match_iwb_callback(struct acpi_iort_node *node, void *context)
+{
+	acpi_status status = AE_NOT_FOUND;
+	u32 *id = context;
+
+	if (node->type == ACPI_IORT_NODE_IWB) {
+		struct acpi_iort_iwb *iwb;
+
+		iwb = (struct acpi_iort_iwb *)node->node_data;
+		status = iwb->iwb_index == *id ? AE_OK : AE_NOT_FOUND;
+	}
+
+	return status;
+}
+
 static int iort_id_map(struct acpi_iort_id_mapping *map, u8 type, u32 rid_in,
 		       u32 *rid_out, bool check_overlap)
 {
 	/* Single mapping does not care for input id */
 	if (map->flags & ACPI_IORT_ID_SINGLE_MAPPING) {
 		if (type == ACPI_IORT_NODE_NAMED_COMPONENT ||
+		    type == ACPI_IORT_NODE_IWB		   ||
 		    type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX) {
 			*rid_out = map->output_base;
 			return 0;
@@ -392,6 +416,7 @@ static struct acpi_iort_node *iort_node_get_id(struct acpi_iort_node *node,
 
 	if (map->flags & ACPI_IORT_ID_SINGLE_MAPPING) {
 		if (node->type == ACPI_IORT_NODE_NAMED_COMPONENT ||
+		    node->type == ACPI_IORT_NODE_IWB ||
 		    node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX ||
 		    node->type == ACPI_IORT_NODE_SMMU_V3 ||
 		    node->type == ACPI_IORT_NODE_PMCG) {
@@ -562,9 +587,14 @@ static struct acpi_iort_node *iort_find_dev_node(struct device *dev)
 			return node;
 		/*
 		 * if not, then it should be a platform device defined in
-		 * DSDT/SSDT (with Named Component node in IORT)
+		 * DSDT/SSDT (with Named Component node in IORT) or an
+		 * IWB device in the DSDT/SSDT.
 		 */
-		return iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
+		node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
+				      iort_match_node_callback, dev);
+		if (node)
+			return node;
+		return iort_scan_node(ACPI_IORT_NODE_IWB,
 				      iort_match_node_callback, dev);
 	}
 
@@ -756,6 +786,35 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
 	return irq_find_matching_fwnode(handle, bus_token);
 }
 
+struct fwnode_handle *iort_iwb_handle(u32 iwb_id)
+{
+	struct fwnode_handle *fwnode;
+	struct acpi_iort_node *node;
+	struct acpi_device *device;
+	struct acpi_iort_iwb *iwb;
+	acpi_status status;
+	acpi_handle handle;
+
+	/* find its associated IWB node */
+	node = iort_scan_node(ACPI_IORT_NODE_IWB, iort_match_iwb_callback, &iwb_id);
+	if (!node)
+		return NULL;
+
+	iwb = (struct acpi_iort_iwb *)node->node_data;
+	status = acpi_get_handle(NULL, iwb->device_name, &handle);
+	if (ACPI_FAILURE(status))
+		return NULL;
+
+	device = acpi_get_acpi_dev(handle);
+	if (!device)
+		return NULL;
+
+	fwnode = acpi_fwnode_handle(device);
+	acpi_put_acpi_dev(device);
+
+	return fwnode;
+}
+
 static void iort_set_device_domain(struct device *dev,
 				   struct acpi_iort_node *node)
 {
@@ -816,8 +875,14 @@ static struct irq_domain *iort_get_platform_device_domain(struct device *dev)
 	/* find its associated iort node */
 	node = iort_scan_node(ACPI_IORT_NODE_NAMED_COMPONENT,
 			      iort_match_node_callback, dev);
-	if (!node)
-		return NULL;
+	if (!node) {
+		/* find its associated iort node */
+		node = iort_scan_node(ACPI_IORT_NODE_IWB,
+				      iort_match_node_callback, dev);
+
+		if (!node)
+			return NULL;
+	}
 
 	/* then find its msi parent node */
 	for (i = 0; i < node->mapping_count; i++) {
diff --git a/drivers/irqchip/irq-gic-v5-iwb.c b/drivers/irqchip/irq-gic-v5-iwb.c
index ad9fdc14d1c6..c7d5fd34d053 100644
--- a/drivers/irqchip/irq-gic-v5-iwb.c
+++ b/drivers/irqchip/irq-gic-v5-iwb.c
@@ -4,6 +4,7 @@
  */
 #define pr_fmt(fmt)	"GICv5 IWB: " fmt
 
+#include <linux/acpi.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/msi.h>
@@ -136,18 +137,31 @@ static int gicv5_iwb_irq_domain_translate(struct irq_domain *d, struct irq_fwspe
 					  irq_hw_number_t *hwirq,
 					  unsigned int *type)
 {
-	if (!is_of_node(fwspec->fwnode))
-		return -EINVAL;
+	if (is_of_node(fwspec->fwnode)) {
 
-	if (fwspec->param_count < 2)
-		return -EINVAL;
+		if (fwspec->param_count < 2)
+			return -EINVAL;
 
-	/*
-	 * param[0] is be the wire
-	 * param[1] is the interrupt type
-	 */
-	*hwirq = fwspec->param[0];
-	*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
+		/*
+		 * param[0] is be the wire
+		 * param[1] is the interrupt type
+		 */
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
+	}
+
+	if (is_acpi_device_node(fwspec->fwnode)) {
+
+		if (fwspec->param_count < 2)
+			return -EINVAL;
+
+		/*
+		 * Extract the wire from param[0]
+		 * param[1] is the interrupt type
+		 */
+		*hwirq = FIELD_GET(GICV5_GSI_IWB_WIRE, fwspec->param[0]);
+		*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
+	}
 
 	return 0;
 }
@@ -265,10 +279,18 @@ static const struct of_device_id gicv5_iwb_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, gicv5_iwb_of_match);
 
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id iwb_acpi_match[] = {
+	{ "ARMH0003", 0 },
+	{}
+};
+#endif
+
 static struct platform_driver gicv5_iwb_platform_driver = {
 	.driver = {
 		.name			= "GICv5 IWB",
 		.of_match_table		= gicv5_iwb_of_match,
+		.acpi_match_table	= ACPI_PTR(iwb_acpi_match),
 		.suppress_bind_attrs	= true,
 	},
 	.probe				= gicv5_iwb_device_probe,
diff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c
index 23fd551c4347..da867dd2e77d 100644
--- a/drivers/irqchip/irq-gic-v5.c
+++ b/drivers/irqchip/irq-gic-v5.c
@@ -5,6 +5,7 @@
 
 #define pr_fmt(fmt)	"GICv5: " fmt
 
+#include <linux/acpi_iort.h>
 #include <linux/cpuhotplug.h>
 #include <linux/idr.h>
 #include <linux/irqdomain.h>
@@ -1187,6 +1188,9 @@ static struct fwnode_handle *gsi_domain_handle;
 
 static struct fwnode_handle *gic_v5_get_gsi_domain_id(u32 gsi)
 {
+	if (FIELD_GET(GICV5_GSI_IC_TYPE, gsi) == GICV5_GSI_IWB_TYPE)
+		return iort_iwb_handle(FIELD_GET(GICV5_GSI_IWB_FRAME_ID, gsi));
+
 	return gsi_domain_handle;
 }
 
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 2d22268677a9..17bb3374f4ca 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -27,6 +27,7 @@ int iort_register_domain_token(int trans_id, phys_addr_t base,
 			       struct fwnode_handle *fw_node);
 void iort_deregister_domain_token(int trans_id);
 struct fwnode_handle *iort_find_domain_token(int trans_id);
+struct fwnode_handle *iort_iwb_handle(u32 iwb_id);
 
 #ifdef CONFIG_ACPI_IORT
 u32 iort_msi_map_id(struct device *dev, u32 id);
diff --git a/include/linux/irqchip/arm-gic-v5.h b/include/linux/irqchip/arm-gic-v5.h
index 334b6986435c..3da1ad80fc9d 100644
--- a/include/linux/irqchip/arm-gic-v5.h
+++ b/include/linux/irqchip/arm-gic-v5.h
@@ -265,6 +265,12 @@
 
 #define GICV5_IWB_WENABLE_STATUSR_IDLE		BIT(0)
 
+#define GICV5_GSI_IC_TYPE			GENMASK(31, 29)
+#define GICV5_GSI_IWB_TYPE			0x7
+
+#define GICV5_GSI_IWB_FRAME_ID			GENMASK(28, 16)
+#define GICV5_GSI_IWB_WIRE			GENMASK(15, 0)
+
 /*
  * Global Data structures and functions
  */

-- 
2.50.1
Re: [PATCH v2 7/7] irqchip/gic-v5: Add ACPI IWB probing
Posted by Jonathan Cameron 1 month ago
On Thu, 18 Dec 2025 11:14:33 +0100
Lorenzo Pieralisi <lpieralisi@kernel.org> wrote:

> To probe an IWB in an ACPI based system it is required:
> 
> - to implement the IORT functions handling the IWB IORT node and create
>   functions to retrieve IWB firmware information
> - to augment the driver to match the DSDT ACPI "ARMH0003" device and
>   retrieve the IWB wire and trigger mask from the GSI interrupt descriptor
>   in the IWB msi_domain_ops.msi_translate() function
> 
> Make the required driver changes to enable IWB probing in ACPI systems.
> 
> The GICv5 GSI format requires special handling for IWB routed IRQs.
> 
> Add IWB GSI detection to the top level driver gic_v5_get_gsi_domain_id()
> function so that the correct IRQ domain for a GSI can be detected by
> parsing the GSI and check whether it is an IWB-backed IRQ or not.
> 
> Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Hanjun Guo <guohanjun@huawei.com>
> Cc: Sudeep Holla <sudeep.holla@arm.com>
> Cc: Marc Zyngier <maz@kernel.org>
A couple of trivial comments inline. Overall this series looks in a good
state to me.
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>

> ---
>  drivers/acpi/arm64/iort.c          | 95 ++++++++++++++++++++++++++++++++------
>  drivers/irqchip/irq-gic-v5-iwb.c   | 42 +++++++++++++----
>  drivers/irqchip/irq-gic-v5.c       |  4 ++
>  include/linux/acpi_iort.h          |  1 +
>  include/linux/irqchip/arm-gic-v5.h |  6 +++
>  5 files changed, 123 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> index 17dbe66da804..4b0b753db738 100644
> --- a/drivers/acpi/arm64/iort.c
> +++ b/drivers/acpi/arm64/iort.c

> @@ -317,12 +325,28 @@ static acpi_status iort_match_node_callback(struct acpi_iort_node *node,
>  	return status;
>  }
>  
> +static acpi_status iort_match_iwb_callback(struct acpi_iort_node *node, void *context)
> +{
> +	acpi_status status = AE_NOT_FOUND;
> +	u32 *id = context;
> +
> +	if (node->type == ACPI_IORT_NODE_IWB) {
> +		struct acpi_iort_iwb *iwb;
> +
> +		iwb = (struct acpi_iort_iwb *)node->node_data;
> +		status = iwb->iwb_index == *id ? AE_OK : AE_NOT_FOUND;
> +	}
> +
> +	return status;
Simpler flow with a quick exclusion of wrong nodes.
	if (node->type != ACPI_IORT_NODE_IWB)
		return AE_NOT_FOUND;
	....
	iwb = ...
	
Also not sure I'd use a ternary here given it's only slightly more code
as more readable.
	if (iwb->iwb_index != *id)
		return AE_NOT_FOUND;

	return AE_OK;

> +}


> diff --git a/drivers/irqchip/irq-gic-v5-iwb.c b/drivers/irqchip/irq-gic-v5-iwb.c
> index ad9fdc14d1c6..c7d5fd34d053 100644
> --- a/drivers/irqchip/irq-gic-v5-iwb.c
> +++ b/drivers/irqchip/irq-gic-v5-iwb.c
> @@ -4,6 +4,7 @@
>   */
>  #define pr_fmt(fmt)	"GICv5 IWB: " fmt
>  
> +#include <linux/acpi.h>
>  #include <linux/init.h>
>  #include <linux/kernel.h>
>  #include <linux/msi.h>
> @@ -136,18 +137,31 @@ static int gicv5_iwb_irq_domain_translate(struct irq_domain *d, struct irq_fwspe
>  					  irq_hw_number_t *hwirq,
>  					  unsigned int *type)
>  {
> -	if (!is_of_node(fwspec->fwnode))
> -		return -EINVAL;
> +	if (is_of_node(fwspec->fwnode)) {
>  
> -	if (fwspec->param_count < 2)
> -		return -EINVAL;
> +		if (fwspec->param_count < 2)
> +			return -EINVAL;
>  
> -	/*
> -	 * param[0] is be the wire
> -	 * param[1] is the interrupt type
> -	 */
> -	*hwirq = fwspec->param[0];
> -	*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
> +		/*
> +		 * param[0] is be the wire
> +		 * param[1] is the interrupt type
> +		 */
> +		*hwirq = fwspec->param[0];
> +		*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;

As below, FIELD_GET() would improve reviewability a little.


> +	}
> +
> +	if (is_acpi_device_node(fwspec->fwnode)) {
> +
> +		if (fwspec->param_count < 2)
> +			return -EINVAL;
> +
> +		/*
> +		 * Extract the wire from param[0]
> +		 * param[1] is the interrupt type
> +		 */
> +		*hwirq = FIELD_GET(GICV5_GSI_IWB_WIRE, fwspec->param[0]);
> +		*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;

I'd prefer this FIELD_GET() for this as well so there is no need to
go sanity check that it is the lowest bits.

> +	}
>  
>  	return 0;
Re: [PATCH v2 7/7] irqchip/gic-v5: Add ACPI IWB probing
Posted by Lorenzo Pieralisi 1 month ago
On Mon, Jan 05, 2026 at 03:35:21PM +0000, Jonathan Cameron wrote:
> On Thu, 18 Dec 2025 11:14:33 +0100
> Lorenzo Pieralisi <lpieralisi@kernel.org> wrote:
> 
> > To probe an IWB in an ACPI based system it is required:
> > 
> > - to implement the IORT functions handling the IWB IORT node and create
> >   functions to retrieve IWB firmware information
> > - to augment the driver to match the DSDT ACPI "ARMH0003" device and
> >   retrieve the IWB wire and trigger mask from the GSI interrupt descriptor
> >   in the IWB msi_domain_ops.msi_translate() function
> > 
> > Make the required driver changes to enable IWB probing in ACPI systems.
> > 
> > The GICv5 GSI format requires special handling for IWB routed IRQs.
> > 
> > Add IWB GSI detection to the top level driver gic_v5_get_gsi_domain_id()
> > function so that the correct IRQ domain for a GSI can be detected by
> > parsing the GSI and check whether it is an IWB-backed IRQ or not.
> > 
> > Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
> > Cc: Thomas Gleixner <tglx@linutronix.de>
> > Cc: Hanjun Guo <guohanjun@huawei.com>
> > Cc: Sudeep Holla <sudeep.holla@arm.com>
> > Cc: Marc Zyngier <maz@kernel.org>
> A couple of trivial comments inline. Overall this series looks in a good
> state to me.
> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
> 
> > ---
> >  drivers/acpi/arm64/iort.c          | 95 ++++++++++++++++++++++++++++++++------
> >  drivers/irqchip/irq-gic-v5-iwb.c   | 42 +++++++++++++----
> >  drivers/irqchip/irq-gic-v5.c       |  4 ++
> >  include/linux/acpi_iort.h          |  1 +
> >  include/linux/irqchip/arm-gic-v5.h |  6 +++
> >  5 files changed, 123 insertions(+), 25 deletions(-)
> > 
> > diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
> > index 17dbe66da804..4b0b753db738 100644
> > --- a/drivers/acpi/arm64/iort.c
> > +++ b/drivers/acpi/arm64/iort.c
> 
> > @@ -317,12 +325,28 @@ static acpi_status iort_match_node_callback(struct acpi_iort_node *node,
> >  	return status;
> >  }
> >  
> > +static acpi_status iort_match_iwb_callback(struct acpi_iort_node *node, void *context)
> > +{
> > +	acpi_status status = AE_NOT_FOUND;
> > +	u32 *id = context;
> > +
> > +	if (node->type == ACPI_IORT_NODE_IWB) {
> > +		struct acpi_iort_iwb *iwb;
> > +
> > +		iwb = (struct acpi_iort_iwb *)node->node_data;
> > +		status = iwb->iwb_index == *id ? AE_OK : AE_NOT_FOUND;
> > +	}
> > +
> > +	return status;
> Simpler flow with a quick exclusion of wrong nodes.
> 	if (node->type != ACPI_IORT_NODE_IWB)
> 		return AE_NOT_FOUND;
> 	....
> 	iwb = ...
> 	
> Also not sure I'd use a ternary here given it's only slightly more code
> as more readable.
> 	if (iwb->iwb_index != *id)
> 		return AE_NOT_FOUND;
> 
> 	return AE_OK;

Updated.

> > +}
> 
> 
> > diff --git a/drivers/irqchip/irq-gic-v5-iwb.c b/drivers/irqchip/irq-gic-v5-iwb.c
> > index ad9fdc14d1c6..c7d5fd34d053 100644
> > --- a/drivers/irqchip/irq-gic-v5-iwb.c
> > +++ b/drivers/irqchip/irq-gic-v5-iwb.c
> > @@ -4,6 +4,7 @@
> >   */
> >  #define pr_fmt(fmt)	"GICv5 IWB: " fmt
> >  
> > +#include <linux/acpi.h>
> >  #include <linux/init.h>
> >  #include <linux/kernel.h>
> >  #include <linux/msi.h>
> > @@ -136,18 +137,31 @@ static int gicv5_iwb_irq_domain_translate(struct irq_domain *d, struct irq_fwspe
> >  					  irq_hw_number_t *hwirq,
> >  					  unsigned int *type)
> >  {
> > -	if (!is_of_node(fwspec->fwnode))
> > -		return -EINVAL;
> > +	if (is_of_node(fwspec->fwnode)) {
> >  
> > -	if (fwspec->param_count < 2)
> > -		return -EINVAL;
> > +		if (fwspec->param_count < 2)
> > +			return -EINVAL;
> >  
> > -	/*
> > -	 * param[0] is be the wire
> > -	 * param[1] is the interrupt type
> > -	 */
> > -	*hwirq = fwspec->param[0];
> > -	*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
> > +		/*
> > +		 * param[0] is be the wire
> > +		 * param[1] is the interrupt type
> > +		 */
> > +		*hwirq = fwspec->param[0];
> > +		*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
> 
> As below, FIELD_GET() would improve reviewability a little.
> 
> 
> > +	}
> > +
> > +	if (is_acpi_device_node(fwspec->fwnode)) {
> > +
> > +		if (fwspec->param_count < 2)
> > +			return -EINVAL;
> > +
> > +		/*
> > +		 * Extract the wire from param[0]
> > +		 * param[1] is the interrupt type
> > +		 */
> > +		*hwirq = FIELD_GET(GICV5_GSI_IWB_WIRE, fwspec->param[0]);
> > +		*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
> 
> I'd prefer this FIELD_GET() for this as well so there is no need to
> go sanity check that it is the lowest bits.

It is a common pattern in the kernel, that's why I am not convinced that
changing just this instance would improve much.

Thanks,
Lorenzo

> 
> > +	}
> >  
> >  	return 0;