Skip to content

Commit 9d1c58c

Browse files
committed
genirq/msi: Optionally use dev->fwnode for device domain
To support wire to MSI domains via the MSI infrastructure it is required to use the firmware node of the device which implements this for creating the MSI domain. Otherwise the existing firmware match mechanisms to find the correct irqdomain for a wired interrupt which is connected to a wire to MSI bridge would fail. This cannot be used for the general case because not all devices provide firmware nodes and all regular per device MSI domains are directly associated to the device and have not be searched for. Signed-off-by: Thomas Gleixner <[email protected]> Signed-off-by: Anup Patel <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 2d566a4 commit 9d1c58c

File tree

2 files changed

+18
-4
lines changed

2 files changed

+18
-4
lines changed

include/linux/msi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,8 @@ enum {
552552
MSI_FLAG_ALLOC_SIMPLE_MSI_DESCS = (1 << 5),
553553
/* Free MSI descriptors */
554554
MSI_FLAG_FREE_MSI_DESCS = (1 << 6),
555+
/* Use dev->fwnode for MSI device domain creation */
556+
MSI_FLAG_USE_DEV_FWNODE = (1 << 7),
555557

556558
/* Mask for the generic functionality */
557559
MSI_GENERIC_FLAGS_MASK = GENMASK(15, 0),

kernel/irq/msi.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -960,9 +960,9 @@ bool msi_create_device_irq_domain(struct device *dev, unsigned int domid,
960960
void *chip_data)
961961
{
962962
struct irq_domain *domain, *parent = dev->msi.domain;
963-
const struct msi_parent_ops *pops;
963+
struct fwnode_handle *fwnode, *fwnalloced = NULL;
964964
struct msi_domain_template *bundle;
965-
struct fwnode_handle *fwnode;
965+
const struct msi_parent_ops *pops;
966966

967967
if (!irq_domain_is_msi_parent(parent))
968968
return false;
@@ -985,7 +985,19 @@ bool msi_create_device_irq_domain(struct device *dev, unsigned int domid,
985985
pops->prefix ? : "", bundle->chip.name, dev_name(dev));
986986
bundle->chip.name = bundle->name;
987987

988-
fwnode = irq_domain_alloc_named_fwnode(bundle->name);
988+
/*
989+
* Using the device firmware node is required for wire to MSI
990+
* device domains so that the existing firmware results in a domain
991+
* match.
992+
* All other device domains like PCI/MSI use the named firmware
993+
* node as they are not guaranteed to have a fwnode. They are never
994+
* looked up and always handled in the context of the device.
995+
*/
996+
if (bundle->info.flags & MSI_FLAG_USE_DEV_FWNODE)
997+
fwnode = dev->fwnode;
998+
else
999+
fwnode = fwnalloced = irq_domain_alloc_named_fwnode(bundle->name);
1000+
9891001
if (!fwnode)
9901002
goto free_bundle;
9911003

@@ -1012,7 +1024,7 @@ bool msi_create_device_irq_domain(struct device *dev, unsigned int domid,
10121024
fail:
10131025
msi_unlock_descs(dev);
10141026
free_fwnode:
1015-
irq_domain_free_fwnode(fwnode);
1027+
irq_domain_free_fwnode(fwnalloced);
10161028
free_bundle:
10171029
kfree(bundle);
10181030
return false;

0 commit comments

Comments
 (0)