drivers/irqchip/irq-gic-its-msi-parent.c

Source file repositories/reference/linux-study-clean/drivers/irqchip/irq-gic-its-msi-parent.c

File Facts

System
Linux kernel
Corpus path
drivers/irqchip/irq-gic-its-msi-parent.c
Extension
.c
Size
9517 bytes
Lines
340
Domain
Driver Families
Bucket
drivers/irqchip
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (np == irq_domain_get_of_node(domain)) {
			u32 args;

			if (WARN_ON(of_phandle_iterator_args(&it, &args, 1) != 1))
				ret = -EINVAL;

			if (!ret && pa)
				ret = its_translate_frame_address(of_fwnode_handle(it.node), pa);

			if (!ret)
				*dev_id = args;

			of_node_put(it.node);
			return ret;
		}
	}

	ret = of_map_msi_id(dev->of_node, dev->id, &msi_ctrl, &msi_spec);
	if (!ret)
		*dev_id = msi_spec.args[0];
	of_node_put(msi_spec.np);
	return ret;
}

static int its_pmsi_prepare(struct irq_domain *domain, struct device *dev,
			    int nvec, msi_alloc_info_t *info)
{
	struct msi_domain_info *msi_info;
	u32 dev_id;
	int ret = 0;

	if (dev_is_fsl_mc(dev))
		dev_id = fsl_mc_get_msi_id(dev);
	else if (dev->of_node)
		ret = of_pmsi_get_msi_info(domain->parent, dev, &dev_id, NULL);
	else
		ret = iort_pmsi_get_msi_info(dev, &dev_id, NULL);
	if (ret)
		return ret;

	/* ITS specific DeviceID, as the core ITS ignores dev. */
	info->scratchpad[0].ul = dev_id;

	/* Allocate at least 32 MSIs, and always as a power of 2 */
	nvec = max_t(int, 32, roundup_pow_of_two(nvec));

	msi_info = msi_get_domain_info(domain->parent);
	return msi_info->ops->msi_prepare(domain->parent,
					  dev, nvec, info);
}

static int its_v5_pmsi_prepare(struct irq_domain *domain, struct device *dev,
			       int nvec, msi_alloc_info_t *info)
{
	struct msi_domain_info *msi_info;
	phys_addr_t pa;
	u32 dev_id;
	int ret;

	if (dev->of_node)
		ret = of_pmsi_get_msi_info(domain->parent, dev, &dev_id, &pa);
	else
		ret = iort_pmsi_get_msi_info(dev, &dev_id, &pa);
	if (ret)
		return ret;

	/* ITS specific DeviceID */
	info->scratchpad[0].ul = dev_id;
	/* ITS translate frame physical address */
	info->scratchpad[1].ul = pa;

	/* Allocate always as a power of 2 */
	nvec = roundup_pow_of_two(nvec);

	msi_info = msi_get_domain_info(domain->parent);
	return msi_info->ops->msi_prepare(domain->parent, dev, nvec, info);
}

static void its_msi_teardown(struct irq_domain *domain, msi_alloc_info_t *info)
{
	struct msi_domain_info *msi_info;

	msi_info = msi_get_domain_info(domain->parent);
	msi_info->ops->msi_teardown(domain->parent, info);
}

static bool its_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
				  struct irq_domain *real_parent, struct msi_domain_info *info)
{
	if (!msi_lib_init_dev_msi_info(dev, domain, real_parent, info))

Annotation

Implementation Notes