Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 18 additions & 8 deletions drivers/of/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,19 +704,22 @@ static int of_check_msi_parent(struct device_node *dev_node, struct device_node
/**
* of_msi_xlate - map a MSI ID and find relevant MSI controller node
* @dev: device for which the mapping is to be done.
* @msi_np: Pointer to target MSI controller node
* @msi_np: Pointer to target MSI controller node, or NULL if the caller
* only needs the translated ID without receiving the controller node.
* If non-NULL and pointing to a non-NULL node, only entries targeting
* that node will be matched. If non-NULL and pointing to NULL, it will
* receive the first matching target node with a reference held.
* @id_in: Device ID.
*
* Walk up the device hierarchy looking for devices with a "msi-map"
* or "msi-parent" property. If found, apply the mapping to @id_in.
* If @msi_np points to a non-NULL device node pointer, only entries targeting
* that node will be matched; if it points to a NULL value, it will receive the
* device node of the first matching target phandle, with a reference held.
*
* Returns: The mapped MSI id.
*/
u32 of_msi_xlate(struct device *dev, struct device_node **msi_np, u32 id_in)
{
struct device_node *local_np = NULL;
struct device_node **np = msi_np ?: &local_np;
struct device *parent_dev;
u32 id_out = id_in;

Expand All @@ -727,17 +730,24 @@ u32 of_msi_xlate(struct device *dev, struct device_node **msi_np, u32 id_in)
for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) {
struct of_phandle_args msi_spec = {};

if (!of_map_msi_id(parent_dev->of_node, id_in, *msi_np, &msi_spec)) {
if (!of_map_msi_id(parent_dev->of_node, id_in, *np, &msi_spec)) {
/*
* Pass-through result: no msi-map on this node (or no
* matching entry). Keep walking up the hierarchy.
*/
if (!msi_spec.np)
continue;
id_out = msi_spec.args[0];
if (!*msi_np)
*msi_np = msi_spec.np;
if (!*np)
*np = msi_spec.np;
else
of_node_put(msi_spec.np);
break;
}
if (!of_check_msi_parent(parent_dev->of_node, msi_np))
if (!of_check_msi_parent(parent_dev->of_node, np))
break;
}
of_node_put(local_np);
return id_out;
}
EXPORT_SYMBOL_GPL(of_msi_xlate);
Expand Down