Skip to content

Commit 2e590d6

Browse files
committed
Merge tag 'devicetree-fixes-for-6.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux
Pull devicetree fixes from Rob Herring: - Fix handling of GICv5 ITS MSI properties on platforms with 'msi-parent' as well as a of_node refcounting fix. This is also preparation for further refactoring in 6.19 to use common DT parsing of MSI properties. * tag 'devicetree-fixes-for-6.18-2' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux: of/irq: Export of_msi_xlate() for module usage of/irq: Fix OF node refcount in of_msi_get_domain() of/irq: Add msi-parent check to of_msi_xlate()
2 parents 9b9b6e7 + 7209ff3 commit 2e590d6

File tree

1 file changed

+40
-4
lines changed

1 file changed

+40
-4
lines changed

drivers/of/irq.c

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -671,14 +671,44 @@ void __init of_irq_init(const struct of_device_id *matches)
671671
}
672672
}
673673

674+
static int of_check_msi_parent(struct device_node *dev_node, struct device_node **msi_node)
675+
{
676+
struct of_phandle_args msi_spec;
677+
int ret;
678+
679+
/*
680+
* An msi-parent phandle with a missing or == 0 #msi-cells
681+
* property identifies a 1:1 ID translation mapping.
682+
*
683+
* Set the msi controller node if the firmware matches this
684+
* condition.
685+
*/
686+
ret = of_parse_phandle_with_optional_args(dev_node, "msi-parent", "#msi-cells",
687+
0, &msi_spec);
688+
if (ret)
689+
return ret;
690+
691+
if ((*msi_node && *msi_node != msi_spec.np) || msi_spec.args_count != 0)
692+
ret = -EINVAL;
693+
694+
if (!ret) {
695+
/* Return with a node reference held */
696+
*msi_node = msi_spec.np;
697+
return 0;
698+
}
699+
of_node_put(msi_spec.np);
700+
701+
return ret;
702+
}
703+
674704
/**
675705
* of_msi_xlate - map a MSI ID and find relevant MSI controller node
676706
* @dev: device for which the mapping is to be done.
677707
* @msi_np: Pointer to target MSI controller node
678708
* @id_in: Device ID.
679709
*
680710
* Walk up the device hierarchy looking for devices with a "msi-map"
681-
* property. If found, apply the mapping to @id_in.
711+
* or "msi-parent" property. If found, apply the mapping to @id_in.
682712
* If @msi_np points to a non-NULL device node pointer, only entries targeting
683713
* that node will be matched; if it points to a NULL value, it will receive the
684714
* device node of the first matching target phandle, with a reference held.
@@ -692,14 +722,18 @@ u32 of_msi_xlate(struct device *dev, struct device_node **msi_np, u32 id_in)
692722

693723
/*
694724
* Walk up the device parent links looking for one with a
695-
* "msi-map" property.
725+
* "msi-map" or an "msi-parent" property.
696726
*/
697-
for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent)
727+
for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) {
698728
if (!of_map_id(parent_dev->of_node, id_in, "msi-map",
699729
"msi-map-mask", msi_np, &id_out))
700730
break;
731+
if (!of_check_msi_parent(parent_dev->of_node, msi_np))
732+
break;
733+
}
701734
return id_out;
702735
}
736+
EXPORT_SYMBOL_GPL(of_msi_xlate);
703737

704738
/**
705739
* of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain
@@ -741,8 +775,10 @@ struct irq_domain *of_msi_get_domain(struct device *dev,
741775

742776
of_for_each_phandle(&it, err, np, "msi-parent", "#msi-cells", 0) {
743777
d = irq_find_matching_host(it.node, token);
744-
if (d)
778+
if (d) {
779+
of_node_put(it.node);
745780
return d;
781+
}
746782
}
747783

748784
return NULL;

0 commit comments

Comments
 (0)