static int __init its_pci_msi_init(void)
{
	struct device_node *np;
	struct irq_domain *parent;

	for (np = of_find_matching_node(NULL, its_device_id); np;
	     np = of_find_matching_node(np, its_device_id)) {
		if (!of_property_read_bool(np, "msi-controller"))
			continue;

		parent = irq_find_matching_host(np, DOMAIN_BUS_NEXUS);
		if (!parent || !msi_get_domain_info(parent)) {
			pr_err("%s: unable to locate ITS domain\n",
			       np->full_name);
			continue;
		}

		if (!pci_msi_create_irq_domain(np, &its_pci_msi_domain_info,
					       parent)) {
			pr_err("%s: unable to create PCI domain\n",
			       np->full_name);
			continue;
		}

		pr_info("PCI/MSI: %s domain created\n", np->full_name);
	}

	return 0;
}
Exemple #2
0
void arch_init_msi_domain(struct irq_domain *parent)
{
	if (disable_apic)
		return;

	msi_default_domain = pci_msi_create_irq_domain(NULL,
					&pci_msi_domain_info, parent);
	if (!msi_default_domain)
		pr_warn("failed to initialize irqdomain for MSI/MSI-x.\n");
}
static int __init its_pci_msi_init_one(struct fwnode_handle *handle,
				       const char *name)
{
	struct irq_domain *parent;

	parent = irq_find_matching_fwnode(handle, DOMAIN_BUS_NEXUS);
	if (!parent || !msi_get_domain_info(parent)) {
		pr_err("%s: Unable to locate ITS domain\n", name);
		return -ENXIO;
	}

	if (!pci_msi_create_irq_domain(handle, &its_pci_msi_domain_info,
				       parent)) {
		pr_err("%s: Unable to create PCI domain\n", name);
		return -ENOMEM;
	}

	return 0;
}
Exemple #4
0
struct irq_domain *arch_create_msi_irq_domain(struct irq_domain *parent)
{
	return pci_msi_create_irq_domain(NULL, &pci_msi_ir_domain_info, parent);
}
Exemple #5
0
static int __init gicv2m_init_one(struct device_node *node,
				  struct irq_domain *parent)
{
	int ret;
	struct v2m_data *v2m;
	struct irq_domain *inner_domain, *pci_domain, *plat_domain;

	v2m = kzalloc(sizeof(struct v2m_data), GFP_KERNEL);
	if (!v2m) {
		pr_err("Failed to allocate struct v2m_data.\n");
		return -ENOMEM;
	}

	ret = of_address_to_resource(node, 0, &v2m->res);
	if (ret) {
		pr_err("Failed to allocate v2m resource.\n");
		goto err_free_v2m;
	}

	v2m->base = ioremap(v2m->res.start, resource_size(&v2m->res));
	if (!v2m->base) {
		pr_err("Failed to map GICv2m resource\n");
		ret = -ENOMEM;
		goto err_free_v2m;
	}

	if (!of_property_read_u32(node, "arm,msi-base-spi", &v2m->spi_start) &&
	    !of_property_read_u32(node, "arm,msi-num-spis", &v2m->nr_spis)) {
		pr_info("Overriding V2M MSI_TYPER (base:%u, num:%u)\n",
			v2m->spi_start, v2m->nr_spis);
	} else {
		u32 typer = readl_relaxed(v2m->base + V2M_MSI_TYPER);

		v2m->spi_start = V2M_MSI_TYPER_BASE_SPI(typer);
		v2m->nr_spis = V2M_MSI_TYPER_NUM_SPI(typer);
	}

	if (!is_msi_spi_valid(v2m->spi_start, v2m->nr_spis)) {
		ret = -EINVAL;
		goto err_iounmap;
	}

	v2m->bm = kzalloc(sizeof(long) * BITS_TO_LONGS(v2m->nr_spis),
			  GFP_KERNEL);
	if (!v2m->bm) {
		ret = -ENOMEM;
		goto err_iounmap;
	}

	inner_domain = irq_domain_add_tree(node, &gicv2m_domain_ops, v2m);
	if (!inner_domain) {
		pr_err("Failed to create GICv2m domain\n");
		ret = -ENOMEM;
		goto err_free_bm;
	}

	inner_domain->bus_token = DOMAIN_BUS_NEXUS;
	inner_domain->parent = parent;
	pci_domain = pci_msi_create_irq_domain(node, &gicv2m_msi_domain_info,
					       inner_domain);
	plat_domain = platform_msi_create_irq_domain(node,
						     &gicv2m_pmsi_domain_info,
						     inner_domain);
	if (!pci_domain || !plat_domain) {
		pr_err("Failed to create MSI domains\n");
		ret = -ENOMEM;
		goto err_free_domains;
	}

	spin_lock_init(&v2m->msi_cnt_lock);

	pr_info("Node %s: range[%#lx:%#lx], SPI[%d:%d]\n", node->name,
		(unsigned long)v2m->res.start, (unsigned long)v2m->res.end,
		v2m->spi_start, (v2m->spi_start + v2m->nr_spis));

	return 0;

err_free_domains:
	if (plat_domain)
		irq_domain_remove(plat_domain);
	if (pci_domain)
		irq_domain_remove(pci_domain);
	if (inner_domain)
		irq_domain_remove(inner_domain);
err_free_bm:
	kfree(v2m->bm);
err_iounmap:
	iounmap(v2m->base);
err_free_v2m:
	kfree(v2m);
	return ret;
}