cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

irq.c (20551B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 *  Derived from arch/i386/kernel/irq.c
      4 *    Copyright (C) 1992 Linus Torvalds
      5 *  Adapted from arch/i386 by Gary Thomas
      6 *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
      7 *  Updated and modified by Cort Dougan <cort@fsmlabs.com>
      8 *    Copyright (C) 1996-2001 Cort Dougan
      9 *  Adapted for Power Macintosh by Paul Mackerras
     10 *    Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
     11 *
     12 * This file contains the code used to make IRQ descriptions in the
     13 * device tree to actual irq numbers on an interrupt controller
     14 * driver.
     15 */
     16
     17#define pr_fmt(fmt)	"OF: " fmt
     18
     19#include <linux/device.h>
     20#include <linux/errno.h>
     21#include <linux/list.h>
     22#include <linux/module.h>
     23#include <linux/of.h>
     24#include <linux/of_irq.h>
     25#include <linux/string.h>
     26#include <linux/slab.h>
     27
     28/**
     29 * irq_of_parse_and_map - Parse and map an interrupt into linux virq space
     30 * @dev: Device node of the device whose interrupt is to be mapped
     31 * @index: Index of the interrupt to map
     32 *
     33 * This function is a wrapper that chains of_irq_parse_one() and
     34 * irq_create_of_mapping() to make things easier to callers
     35 */
     36unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
     37{
     38	struct of_phandle_args oirq;
     39
     40	if (of_irq_parse_one(dev, index, &oirq))
     41		return 0;
     42
     43	return irq_create_of_mapping(&oirq);
     44}
     45EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
     46
     47/**
     48 * of_irq_find_parent - Given a device node, find its interrupt parent node
     49 * @child: pointer to device node
     50 *
     51 * Return: A pointer to the interrupt parent node, or NULL if the interrupt
     52 * parent could not be determined.
     53 */
     54struct device_node *of_irq_find_parent(struct device_node *child)
     55{
     56	struct device_node *p;
     57	phandle parent;
     58
     59	if (!of_node_get(child))
     60		return NULL;
     61
     62	do {
     63		if (of_property_read_u32(child, "interrupt-parent", &parent)) {
     64			p = of_get_parent(child);
     65		} else	{
     66			if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
     67				p = of_node_get(of_irq_dflt_pic);
     68			else
     69				p = of_find_node_by_phandle(parent);
     70		}
     71		of_node_put(child);
     72		child = p;
     73	} while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL);
     74
     75	return p;
     76}
     77EXPORT_SYMBOL_GPL(of_irq_find_parent);
     78
     79/*
     80 * These interrupt controllers abuse interrupt-map for unspeakable
     81 * reasons and rely on the core code to *ignore* it (the drivers do
     82 * their own parsing of the property).
     83 *
     84 * If you think of adding to the list for something *new*, think
     85 * again. There is a high chance that you will be sent back to the
     86 * drawing board.
     87 */
     88static const char * const of_irq_imap_abusers[] = {
     89	"CBEA,platform-spider-pic",
     90	"sti,platform-spider-pic",
     91	"realtek,rtl-intc",
     92	"fsl,ls1021a-extirq",
     93	"fsl,ls1043a-extirq",
     94	"fsl,ls1088a-extirq",
     95	"renesas,rza1-irqc",
     96	NULL,
     97};
     98
     99/**
    100 * of_irq_parse_raw - Low level interrupt tree parsing
    101 * @addr:	address specifier (start of "reg" property of the device) in be32 format
    102 * @out_irq:	structure of_phandle_args updated by this function
    103 *
    104 * This function is a low-level interrupt tree walking function. It
    105 * can be used to do a partial walk with synthetized reg and interrupts
    106 * properties, for example when resolving PCI interrupts when no device
    107 * node exist for the parent. It takes an interrupt specifier structure as
    108 * input, walks the tree looking for any interrupt-map properties, translates
    109 * the specifier for each map, and then returns the translated map.
    110 *
    111 * Return: 0 on success and a negative number on error
    112 */
    113int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq)
    114{
    115	struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL;
    116	__be32 initial_match_array[MAX_PHANDLE_ARGS];
    117	const __be32 *match_array = initial_match_array;
    118	const __be32 *tmp, *imap, *imask, dummy_imask[] = { [0 ... MAX_PHANDLE_ARGS] = cpu_to_be32(~0) };
    119	u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0;
    120	int imaplen, match, i, rc = -EINVAL;
    121
    122#ifdef DEBUG
    123	of_print_phandle_args("of_irq_parse_raw: ", out_irq);
    124#endif
    125
    126	ipar = of_node_get(out_irq->np);
    127
    128	/* First get the #interrupt-cells property of the current cursor
    129	 * that tells us how to interpret the passed-in intspec. If there
    130	 * is none, we are nice and just walk up the tree
    131	 */
    132	do {
    133		if (!of_property_read_u32(ipar, "#interrupt-cells", &intsize))
    134			break;
    135		tnode = ipar;
    136		ipar = of_irq_find_parent(ipar);
    137		of_node_put(tnode);
    138	} while (ipar);
    139	if (ipar == NULL) {
    140		pr_debug(" -> no parent found !\n");
    141		goto fail;
    142	}
    143
    144	pr_debug("of_irq_parse_raw: ipar=%pOF, size=%d\n", ipar, intsize);
    145
    146	if (out_irq->args_count != intsize)
    147		goto fail;
    148
    149	/* Look for this #address-cells. We have to implement the old linux
    150	 * trick of looking for the parent here as some device-trees rely on it
    151	 */
    152	old = of_node_get(ipar);
    153	do {
    154		tmp = of_get_property(old, "#address-cells", NULL);
    155		tnode = of_get_parent(old);
    156		of_node_put(old);
    157		old = tnode;
    158	} while (old && tmp == NULL);
    159	of_node_put(old);
    160	old = NULL;
    161	addrsize = (tmp == NULL) ? 2 : be32_to_cpu(*tmp);
    162
    163	pr_debug(" -> addrsize=%d\n", addrsize);
    164
    165	/* Range check so that the temporary buffer doesn't overflow */
    166	if (WARN_ON(addrsize + intsize > MAX_PHANDLE_ARGS)) {
    167		rc = -EFAULT;
    168		goto fail;
    169	}
    170
    171	/* Precalculate the match array - this simplifies match loop */
    172	for (i = 0; i < addrsize; i++)
    173		initial_match_array[i] = addr ? addr[i] : 0;
    174	for (i = 0; i < intsize; i++)
    175		initial_match_array[addrsize + i] = cpu_to_be32(out_irq->args[i]);
    176
    177	/* Now start the actual "proper" walk of the interrupt tree */
    178	while (ipar != NULL) {
    179		/*
    180		 * Now check if cursor is an interrupt-controller and
    181		 * if it is then we are done, unless there is an
    182		 * interrupt-map which takes precedence except on one
    183		 * of these broken platforms that want to parse
    184		 * interrupt-map themselves for $reason.
    185		 */
    186		bool intc = of_property_read_bool(ipar, "interrupt-controller");
    187
    188		imap = of_get_property(ipar, "interrupt-map", &imaplen);
    189		if (intc &&
    190		    (!imap || of_device_compatible_match(ipar, of_irq_imap_abusers))) {
    191			pr_debug(" -> got it !\n");
    192			return 0;
    193		}
    194
    195		/*
    196		 * interrupt-map parsing does not work without a reg
    197		 * property when #address-cells != 0
    198		 */
    199		if (addrsize && !addr) {
    200			pr_debug(" -> no reg passed in when needed !\n");
    201			goto fail;
    202		}
    203
    204		/* No interrupt map, check for an interrupt parent */
    205		if (imap == NULL) {
    206			pr_debug(" -> no map, getting parent\n");
    207			newpar = of_irq_find_parent(ipar);
    208			goto skiplevel;
    209		}
    210		imaplen /= sizeof(u32);
    211
    212		/* Look for a mask */
    213		imask = of_get_property(ipar, "interrupt-map-mask", NULL);
    214		if (!imask)
    215			imask = dummy_imask;
    216
    217		/* Parse interrupt-map */
    218		match = 0;
    219		while (imaplen > (addrsize + intsize + 1) && !match) {
    220			/* Compare specifiers */
    221			match = 1;
    222			for (i = 0; i < (addrsize + intsize); i++, imaplen--)
    223				match &= !((match_array[i] ^ *imap++) & imask[i]);
    224
    225			pr_debug(" -> match=%d (imaplen=%d)\n", match, imaplen);
    226
    227			/* Get the interrupt parent */
    228			if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
    229				newpar = of_node_get(of_irq_dflt_pic);
    230			else
    231				newpar = of_find_node_by_phandle(be32_to_cpup(imap));
    232			imap++;
    233			--imaplen;
    234
    235			/* Check if not found */
    236			if (newpar == NULL) {
    237				pr_debug(" -> imap parent not found !\n");
    238				goto fail;
    239			}
    240
    241			if (!of_device_is_available(newpar))
    242				match = 0;
    243
    244			/* Get #interrupt-cells and #address-cells of new
    245			 * parent
    246			 */
    247			if (of_property_read_u32(newpar, "#interrupt-cells",
    248						 &newintsize)) {
    249				pr_debug(" -> parent lacks #interrupt-cells!\n");
    250				goto fail;
    251			}
    252			if (of_property_read_u32(newpar, "#address-cells",
    253						 &newaddrsize))
    254				newaddrsize = 0;
    255
    256			pr_debug(" -> newintsize=%d, newaddrsize=%d\n",
    257			    newintsize, newaddrsize);
    258
    259			/* Check for malformed properties */
    260			if (WARN_ON(newaddrsize + newintsize > MAX_PHANDLE_ARGS)
    261			    || (imaplen < (newaddrsize + newintsize))) {
    262				rc = -EFAULT;
    263				goto fail;
    264			}
    265
    266			imap += newaddrsize + newintsize;
    267			imaplen -= newaddrsize + newintsize;
    268
    269			pr_debug(" -> imaplen=%d\n", imaplen);
    270		}
    271		if (!match) {
    272			if (intc) {
    273				/*
    274				 * The PASEMI Nemo is a known offender, so
    275				 * let's only warn for anyone else.
    276				 */
    277				WARN(!IS_ENABLED(CONFIG_PPC_PASEMI),
    278				     "%pOF interrupt-map failed, using interrupt-controller\n",
    279				     ipar);
    280				return 0;
    281			}
    282
    283			goto fail;
    284		}
    285
    286		/*
    287		 * Successfully parsed an interrupt-map translation; copy new
    288		 * interrupt specifier into the out_irq structure
    289		 */
    290		match_array = imap - newaddrsize - newintsize;
    291		for (i = 0; i < newintsize; i++)
    292			out_irq->args[i] = be32_to_cpup(imap - newintsize + i);
    293		out_irq->args_count = intsize = newintsize;
    294		addrsize = newaddrsize;
    295
    296		if (ipar == newpar) {
    297			pr_debug("%pOF interrupt-map entry to self\n", ipar);
    298			return 0;
    299		}
    300
    301	skiplevel:
    302		/* Iterate again with new parent */
    303		out_irq->np = newpar;
    304		pr_debug(" -> new parent: %pOF\n", newpar);
    305		of_node_put(ipar);
    306		ipar = newpar;
    307		newpar = NULL;
    308	}
    309	rc = -ENOENT; /* No interrupt-map found */
    310
    311 fail:
    312	of_node_put(ipar);
    313	of_node_put(newpar);
    314
    315	return rc;
    316}
    317EXPORT_SYMBOL_GPL(of_irq_parse_raw);
    318
    319/**
    320 * of_irq_parse_one - Resolve an interrupt for a device
    321 * @device: the device whose interrupt is to be resolved
    322 * @index: index of the interrupt to resolve
    323 * @out_irq: structure of_phandle_args filled by this function
    324 *
    325 * This function resolves an interrupt for a node by walking the interrupt tree,
    326 * finding which interrupt controller node it is attached to, and returning the
    327 * interrupt specifier that can be used to retrieve a Linux IRQ number.
    328 */
    329int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq)
    330{
    331	struct device_node *p;
    332	const __be32 *addr;
    333	u32 intsize;
    334	int i, res;
    335
    336	pr_debug("of_irq_parse_one: dev=%pOF, index=%d\n", device, index);
    337
    338	/* OldWorld mac stuff is "special", handle out of line */
    339	if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
    340		return of_irq_parse_oldworld(device, index, out_irq);
    341
    342	/* Get the reg property (if any) */
    343	addr = of_get_property(device, "reg", NULL);
    344
    345	/* Try the new-style interrupts-extended first */
    346	res = of_parse_phandle_with_args(device, "interrupts-extended",
    347					"#interrupt-cells", index, out_irq);
    348	if (!res)
    349		return of_irq_parse_raw(addr, out_irq);
    350
    351	/* Look for the interrupt parent. */
    352	p = of_irq_find_parent(device);
    353	if (p == NULL)
    354		return -EINVAL;
    355
    356	/* Get size of interrupt specifier */
    357	if (of_property_read_u32(p, "#interrupt-cells", &intsize)) {
    358		res = -EINVAL;
    359		goto out;
    360	}
    361
    362	pr_debug(" parent=%pOF, intsize=%d\n", p, intsize);
    363
    364	/* Copy intspec into irq structure */
    365	out_irq->np = p;
    366	out_irq->args_count = intsize;
    367	for (i = 0; i < intsize; i++) {
    368		res = of_property_read_u32_index(device, "interrupts",
    369						 (index * intsize) + i,
    370						 out_irq->args + i);
    371		if (res)
    372			goto out;
    373	}
    374
    375	pr_debug(" intspec=%d\n", *out_irq->args);
    376
    377
    378	/* Check if there are any interrupt-map translations to process */
    379	res = of_irq_parse_raw(addr, out_irq);
    380 out:
    381	of_node_put(p);
    382	return res;
    383}
    384EXPORT_SYMBOL_GPL(of_irq_parse_one);
    385
    386/**
    387 * of_irq_to_resource - Decode a node's IRQ and return it as a resource
    388 * @dev: pointer to device tree node
    389 * @index: zero-based index of the irq
    390 * @r: pointer to resource structure to return result into.
    391 */
    392int of_irq_to_resource(struct device_node *dev, int index, struct resource *r)
    393{
    394	int irq = of_irq_get(dev, index);
    395
    396	if (irq < 0)
    397		return irq;
    398
    399	/* Only dereference the resource if both the
    400	 * resource and the irq are valid. */
    401	if (r && irq) {
    402		const char *name = NULL;
    403
    404		memset(r, 0, sizeof(*r));
    405		/*
    406		 * Get optional "interrupt-names" property to add a name
    407		 * to the resource.
    408		 */
    409		of_property_read_string_index(dev, "interrupt-names", index,
    410					      &name);
    411
    412		r->start = r->end = irq;
    413		r->flags = IORESOURCE_IRQ | irqd_get_trigger_type(irq_get_irq_data(irq));
    414		r->name = name ? name : of_node_full_name(dev);
    415	}
    416
    417	return irq;
    418}
    419EXPORT_SYMBOL_GPL(of_irq_to_resource);
    420
    421/**
    422 * of_irq_get - Decode a node's IRQ and return it as a Linux IRQ number
    423 * @dev: pointer to device tree node
    424 * @index: zero-based index of the IRQ
    425 *
    426 * Return: Linux IRQ number on success, or 0 on the IRQ mapping failure, or
    427 * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
    428 * of any other failure.
    429 */
    430int of_irq_get(struct device_node *dev, int index)
    431{
    432	int rc;
    433	struct of_phandle_args oirq;
    434	struct irq_domain *domain;
    435
    436	rc = of_irq_parse_one(dev, index, &oirq);
    437	if (rc)
    438		return rc;
    439
    440	domain = irq_find_host(oirq.np);
    441	if (!domain)
    442		return -EPROBE_DEFER;
    443
    444	return irq_create_of_mapping(&oirq);
    445}
    446EXPORT_SYMBOL_GPL(of_irq_get);
    447
    448/**
    449 * of_irq_get_byname - Decode a node's IRQ and return it as a Linux IRQ number
    450 * @dev: pointer to device tree node
    451 * @name: IRQ name
    452 *
    453 * Return: Linux IRQ number on success, or 0 on the IRQ mapping failure, or
    454 * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case
    455 * of any other failure.
    456 */
    457int of_irq_get_byname(struct device_node *dev, const char *name)
    458{
    459	int index;
    460
    461	if (unlikely(!name))
    462		return -EINVAL;
    463
    464	index = of_property_match_string(dev, "interrupt-names", name);
    465	if (index < 0)
    466		return index;
    467
    468	return of_irq_get(dev, index);
    469}
    470EXPORT_SYMBOL_GPL(of_irq_get_byname);
    471
    472/**
    473 * of_irq_count - Count the number of IRQs a node uses
    474 * @dev: pointer to device tree node
    475 */
    476int of_irq_count(struct device_node *dev)
    477{
    478	struct of_phandle_args irq;
    479	int nr = 0;
    480
    481	while (of_irq_parse_one(dev, nr, &irq) == 0)
    482		nr++;
    483
    484	return nr;
    485}
    486
    487/**
    488 * of_irq_to_resource_table - Fill in resource table with node's IRQ info
    489 * @dev: pointer to device tree node
    490 * @res: array of resources to fill in
    491 * @nr_irqs: the number of IRQs (and upper bound for num of @res elements)
    492 *
    493 * Return: The size of the filled in table (up to @nr_irqs).
    494 */
    495int of_irq_to_resource_table(struct device_node *dev, struct resource *res,
    496		int nr_irqs)
    497{
    498	int i;
    499
    500	for (i = 0; i < nr_irqs; i++, res++)
    501		if (of_irq_to_resource(dev, i, res) <= 0)
    502			break;
    503
    504	return i;
    505}
    506EXPORT_SYMBOL_GPL(of_irq_to_resource_table);
    507
    508struct of_intc_desc {
    509	struct list_head	list;
    510	of_irq_init_cb_t	irq_init_cb;
    511	struct device_node	*dev;
    512	struct device_node	*interrupt_parent;
    513};
    514
    515/**
    516 * of_irq_init - Scan and init matching interrupt controllers in DT
    517 * @matches: 0 terminated array of nodes to match and init function to call
    518 *
    519 * This function scans the device tree for matching interrupt controller nodes,
    520 * and calls their initialization functions in order with parents first.
    521 */
    522void __init of_irq_init(const struct of_device_id *matches)
    523{
    524	const struct of_device_id *match;
    525	struct device_node *np, *parent = NULL;
    526	struct of_intc_desc *desc, *temp_desc;
    527	struct list_head intc_desc_list, intc_parent_list;
    528
    529	INIT_LIST_HEAD(&intc_desc_list);
    530	INIT_LIST_HEAD(&intc_parent_list);
    531
    532	for_each_matching_node_and_match(np, matches, &match) {
    533		if (!of_property_read_bool(np, "interrupt-controller") ||
    534				!of_device_is_available(np))
    535			continue;
    536
    537		if (WARN(!match->data, "of_irq_init: no init function for %s\n",
    538			 match->compatible))
    539			continue;
    540
    541		/*
    542		 * Here, we allocate and populate an of_intc_desc with the node
    543		 * pointer, interrupt-parent device_node etc.
    544		 */
    545		desc = kzalloc(sizeof(*desc), GFP_KERNEL);
    546		if (!desc) {
    547			of_node_put(np);
    548			goto err;
    549		}
    550
    551		desc->irq_init_cb = match->data;
    552		desc->dev = of_node_get(np);
    553		/*
    554		 * interrupts-extended can reference multiple parent domains.
    555		 * Arbitrarily pick the first one; assume any other parents
    556		 * are the same distance away from the root irq controller.
    557		 */
    558		desc->interrupt_parent = of_parse_phandle(np, "interrupts-extended", 0);
    559		if (!desc->interrupt_parent)
    560			desc->interrupt_parent = of_irq_find_parent(np);
    561		if (desc->interrupt_parent == np) {
    562			of_node_put(desc->interrupt_parent);
    563			desc->interrupt_parent = NULL;
    564		}
    565		list_add_tail(&desc->list, &intc_desc_list);
    566	}
    567
    568	/*
    569	 * The root irq controller is the one without an interrupt-parent.
    570	 * That one goes first, followed by the controllers that reference it,
    571	 * followed by the ones that reference the 2nd level controllers, etc.
    572	 */
    573	while (!list_empty(&intc_desc_list)) {
    574		/*
    575		 * Process all controllers with the current 'parent'.
    576		 * First pass will be looking for NULL as the parent.
    577		 * The assumption is that NULL parent means a root controller.
    578		 */
    579		list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
    580			int ret;
    581
    582			if (desc->interrupt_parent != parent)
    583				continue;
    584
    585			list_del(&desc->list);
    586
    587			of_node_set_flag(desc->dev, OF_POPULATED);
    588
    589			pr_debug("of_irq_init: init %pOF (%p), parent %p\n",
    590				 desc->dev,
    591				 desc->dev, desc->interrupt_parent);
    592			ret = desc->irq_init_cb(desc->dev,
    593						desc->interrupt_parent);
    594			if (ret) {
    595				of_node_clear_flag(desc->dev, OF_POPULATED);
    596				kfree(desc);
    597				continue;
    598			}
    599
    600			/*
    601			 * This one is now set up; add it to the parent list so
    602			 * its children can get processed in a subsequent pass.
    603			 */
    604			list_add_tail(&desc->list, &intc_parent_list);
    605		}
    606
    607		/* Get the next pending parent that might have children */
    608		desc = list_first_entry_or_null(&intc_parent_list,
    609						typeof(*desc), list);
    610		if (!desc) {
    611			pr_err("of_irq_init: children remain, but no parents\n");
    612			break;
    613		}
    614		list_del(&desc->list);
    615		parent = desc->dev;
    616		kfree(desc);
    617	}
    618
    619	list_for_each_entry_safe(desc, temp_desc, &intc_parent_list, list) {
    620		list_del(&desc->list);
    621		kfree(desc);
    622	}
    623err:
    624	list_for_each_entry_safe(desc, temp_desc, &intc_desc_list, list) {
    625		list_del(&desc->list);
    626		of_node_put(desc->dev);
    627		kfree(desc);
    628	}
    629}
    630
    631static u32 __of_msi_map_id(struct device *dev, struct device_node **np,
    632			    u32 id_in)
    633{
    634	struct device *parent_dev;
    635	u32 id_out = id_in;
    636
    637	/*
    638	 * Walk up the device parent links looking for one with a
    639	 * "msi-map" property.
    640	 */
    641	for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent)
    642		if (!of_map_id(parent_dev->of_node, id_in, "msi-map",
    643				"msi-map-mask", np, &id_out))
    644			break;
    645	return id_out;
    646}
    647
    648/**
    649 * of_msi_map_id - Map a MSI ID for a device.
    650 * @dev: device for which the mapping is to be done.
    651 * @msi_np: device node of the expected msi controller.
    652 * @id_in: unmapped MSI ID for the device.
    653 *
    654 * Walk up the device hierarchy looking for devices with a "msi-map"
    655 * property.  If found, apply the mapping to @id_in.
    656 *
    657 * Return: The mapped MSI ID.
    658 */
    659u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in)
    660{
    661	return __of_msi_map_id(dev, &msi_np, id_in);
    662}
    663
    664/**
    665 * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain
    666 * @dev: device for which the mapping is to be done.
    667 * @id: Device ID.
    668 * @bus_token: Bus token
    669 *
    670 * Walk up the device hierarchy looking for devices with a "msi-map"
    671 * property.
    672 *
    673 * Returns: the MSI domain for this device (or NULL on failure)
    674 */
    675struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 id,
    676						u32 bus_token)
    677{
    678	struct device_node *np = NULL;
    679
    680	__of_msi_map_id(dev, &np, id);
    681	return irq_find_matching_host(np, bus_token);
    682}
    683
    684/**
    685 * of_msi_get_domain - Use msi-parent to find the relevant MSI domain
    686 * @dev: device for which the domain is requested
    687 * @np: device node for @dev
    688 * @token: bus type for this domain
    689 *
    690 * Parse the msi-parent property (both the simple and the complex
    691 * versions), and returns the corresponding MSI domain.
    692 *
    693 * Returns: the MSI domain for this device (or NULL on failure).
    694 */
    695struct irq_domain *of_msi_get_domain(struct device *dev,
    696				     struct device_node *np,
    697				     enum irq_domain_bus_token token)
    698{
    699	struct device_node *msi_np;
    700	struct irq_domain *d;
    701
    702	/* Check for a single msi-parent property */
    703	msi_np = of_parse_phandle(np, "msi-parent", 0);
    704	if (msi_np && !of_property_read_bool(msi_np, "#msi-cells")) {
    705		d = irq_find_matching_host(msi_np, token);
    706		if (!d)
    707			of_node_put(msi_np);
    708		return d;
    709	}
    710
    711	if (token == DOMAIN_BUS_PLATFORM_MSI) {
    712		/* Check for the complex msi-parent version */
    713		struct of_phandle_args args;
    714		int index = 0;
    715
    716		while (!of_parse_phandle_with_args(np, "msi-parent",
    717						   "#msi-cells",
    718						   index, &args)) {
    719			d = irq_find_matching_host(args.np, token);
    720			if (d)
    721				return d;
    722
    723			of_node_put(args.np);
    724			index++;
    725		}
    726	}
    727
    728	return NULL;
    729}
    730
    731/**
    732 * of_msi_configure - Set the msi_domain field of a device
    733 * @dev: device structure to associate with an MSI irq domain
    734 * @np: device node for that device
    735 */
    736void of_msi_configure(struct device *dev, struct device_node *np)
    737{
    738	dev_set_msi_domain(dev,
    739			   of_msi_get_domain(dev, np, DOMAIN_BUS_PLATFORM_MSI));
    740}
    741EXPORT_SYMBOL_GPL(of_msi_configure);