static int um_pci_init()

in drivers/virt-pci.c [855:935]


static int um_pci_init(void)
{
	int err, i;

	WARN_ON(logic_iomem_add_region(&virt_cfgspace_resource,
				       &um_pci_cfgspace_ops));
	WARN_ON(logic_iomem_add_region(&virt_iomem_resource,
				       &um_pci_iomem_ops));

	if (WARN(CONFIG_UML_PCI_OVER_VIRTIO_DEVICE_ID < 0,
		 "No virtio device ID configured for PCI - no PCI support\n"))
		return 0;

	um_pci_msg_bufs = alloc_percpu(struct um_pci_message_buffer);
	if (!um_pci_msg_bufs)
		return -ENOMEM;

	bridge = pci_alloc_host_bridge(0);
	if (!bridge) {
		err = -ENOMEM;
		goto free;
	}

	um_pci_fwnode = irq_domain_alloc_named_fwnode("um-pci");
	if (!um_pci_fwnode) {
		err = -ENOMEM;
		goto free;
	}

	um_pci_inner_domain = __irq_domain_add(um_pci_fwnode, MAX_MSI_VECTORS,
					       MAX_MSI_VECTORS, 0,
					       &um_pci_inner_domain_ops, NULL);
	if (!um_pci_inner_domain) {
		err = -ENOMEM;
		goto free;
	}

	um_pci_msi_domain = pci_msi_create_irq_domain(um_pci_fwnode,
						      &um_pci_msi_domain_info,
						      um_pci_inner_domain);
	if (!um_pci_msi_domain) {
		err = -ENOMEM;
		goto free;
	}

	pci_add_resource(&bridge->windows, &virt_iomem_resource);
	pci_add_resource(&bridge->windows, &busn_resource);
	bridge->ops = &um_pci_ops;
	bridge->map_irq = um_pci_map_irq;

	for (i = 0; i < MAX_DEVICES; i++) {
		resource_size_t start;

		start = virt_cfgspace_resource.start + i * CFG_SPACE_SIZE;
		um_pci_devices[i].iomem = ioremap(start, CFG_SPACE_SIZE);
		if (WARN(!um_pci_devices[i].iomem, "failed to map %d\n", i)) {
			err = -ENOMEM;
			goto free;
		}
	}

	err = pci_host_probe(bridge);
	if (err)
		goto free;

	err = register_virtio_driver(&um_pci_virtio_driver);
	if (err)
		goto free;
	return 0;
free:
	if (um_pci_inner_domain)
		irq_domain_remove(um_pci_inner_domain);
	if (um_pci_fwnode)
		irq_domain_free_fwnode(um_pci_fwnode);
	if (bridge) {
		pci_free_resource_list(&bridge->windows);
		pci_free_host_bridge(bridge);
	}
	free_percpu(um_pci_msg_bufs);
	return err;
}