static int pcistub_init_device()

in xen-pciback/pci_stub.c [359:444]


static int pcistub_init_device(struct pci_dev *dev)
{
	struct xen_pcibk_dev_data *dev_data;
	int err = 0;

	dev_dbg(&dev->dev, "initializing...\n");

	/* The PCI backend is not intended to be a module (or to work with
	 * removable PCI devices (yet). If it were, xen_pcibk_config_free()
	 * would need to be called somewhere to free the memory allocated
	 * here and then to call kfree(pci_get_drvdata(psdev->dev)).
	 */
	dev_data = kzalloc(sizeof(*dev_data) +  strlen(DRV_NAME "[]")
				+ strlen(pci_name(dev)) + 1, GFP_KERNEL);
	if (!dev_data) {
		err = -ENOMEM;
		goto out;
	}
	pci_set_drvdata(dev, dev_data);

	/*
	 * Setup name for fake IRQ handler. It will only be enabled
	 * once the device is turned on by the guest.
	 */
	sprintf(dev_data->irq_name, DRV_NAME "[%s]", pci_name(dev));

	dev_dbg(&dev->dev, "initializing config\n");

	init_waitqueue_head(&xen_pcibk_aer_wait_queue);
	err = xen_pcibk_config_init_dev(dev);
	if (err)
		goto out;

	/* HACK: Force device (& ACPI) to determine what IRQ it's on - we
	 * must do this here because pcibios_enable_device may specify
	 * the pci device's true irq (and possibly its other resources)
	 * if they differ from what's in the configuration space.
	 * This makes the assumption that the device's resources won't
	 * change after this point (otherwise this code may break!)
	 */
	dev_dbg(&dev->dev, "enabling device\n");
	err = pci_enable_device(dev);
	if (err)
		goto config_release;

	if (dev->msix_cap) {
		struct physdev_pci_device ppdev = {
			.seg = pci_domain_nr(dev->bus),
			.bus = dev->bus->number,
			.devfn = dev->devfn
		};

		err = HYPERVISOR_physdev_op(PHYSDEVOP_prepare_msix, &ppdev);
		if (err && err != -ENOSYS)
			dev_err(&dev->dev, "MSI-X preparation failed (%d)\n",
				err);
	}

	/* We need the device active to save the state. */
	dev_dbg(&dev->dev, "save state of device\n");
	pci_save_state(dev);
	dev_data->pci_saved_state = pci_store_saved_state(dev);
	if (!dev_data->pci_saved_state)
		dev_err(&dev->dev, "Could not store PCI conf saved state!\n");
	else {
		dev_dbg(&dev->dev, "resetting (FLR, D3, etc) the device\n");
		__pci_reset_function_locked(dev);
		pci_restore_state(dev);
	}
	/* Now disable the device (this also ensures some private device
	 * data is setup before we export)
	 */
	dev_dbg(&dev->dev, "reset device\n");
	xen_pcibk_reset_device(dev);

	pci_set_dev_assigned(dev);
	return 0;

config_release:
	xen_pcibk_config_free_dev(dev);

out:
	pci_set_drvdata(dev, NULL);
	kfree(dev_data);
	return err;
}