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; }
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; }
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); }
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; }