diff options
Diffstat (limited to 'drivers/xen/xen-pciback')
| -rw-r--r-- | drivers/xen/xen-pciback/pci_stub.c | 59 | ||||
| -rw-r--r-- | drivers/xen/xen-pciback/pciback_ops.c | 3 | 
2 files changed, 46 insertions, 16 deletions
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 9204126f156..a2278ba7fb2 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -17,6 +17,7 @@  #include <xen/events.h>  #include <asm/xen/pci.h>  #include <asm/xen/hypervisor.h> +#include <xen/interface/physdev.h>  #include "pciback.h"  #include "conf_space.h"  #include "conf_space_quirks.h" @@ -85,37 +86,52 @@ static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev)  static void pcistub_device_release(struct kref *kref)  {  	struct pcistub_device *psdev; +	struct pci_dev *dev;  	struct xen_pcibk_dev_data *dev_data;  	psdev = container_of(kref, struct pcistub_device, kref); -	dev_data = pci_get_drvdata(psdev->dev); +	dev = psdev->dev; +	dev_data = pci_get_drvdata(dev); -	dev_dbg(&psdev->dev->dev, "pcistub_device_release\n"); +	dev_dbg(&dev->dev, "pcistub_device_release\n"); -	xen_unregister_device_domain_owner(psdev->dev); +	xen_unregister_device_domain_owner(dev);  	/* Call the reset function which does not take lock as this  	 * is called from "unbind" which takes a device_lock mutex.  	 */ -	__pci_reset_function_locked(psdev->dev); -	if (pci_load_and_free_saved_state(psdev->dev, -					  &dev_data->pci_saved_state)) { -		dev_dbg(&psdev->dev->dev, "Could not reload PCI state\n"); -	} else -		pci_restore_state(psdev->dev); +	__pci_reset_function_locked(dev); +	if (pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state)) +		dev_dbg(&dev->dev, "Could not reload PCI state\n"); +	else +		pci_restore_state(dev); + +	if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) { +		struct physdev_pci_device ppdev = { +			.seg = pci_domain_nr(dev->bus), +			.bus = dev->bus->number, +			.devfn = dev->devfn +		}; +		int err = HYPERVISOR_physdev_op(PHYSDEVOP_release_msix, +						&ppdev); + +		if (err) +			dev_warn(&dev->dev, "MSI-X release failed (%d)\n", +				 err); +	}  	/* Disable the device */ -	xen_pcibk_reset_device(psdev->dev); +	xen_pcibk_reset_device(dev);  	kfree(dev_data); -	pci_set_drvdata(psdev->dev, NULL); +	pci_set_drvdata(dev, NULL);  	/* Clean-up the device */ -	xen_pcibk_config_free_dyn_fields(psdev->dev); -	xen_pcibk_config_free_dev(psdev->dev); +	xen_pcibk_config_free_dyn_fields(dev); +	xen_pcibk_config_free_dev(dev); -	psdev->dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED; -	pci_dev_put(psdev->dev); +	dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED; +	pci_dev_put(dev);  	kfree(psdev);  } @@ -355,6 +371,19 @@ static int pcistub_init_device(struct pci_dev *dev)  	if (err)  		goto config_release; +	if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) { +		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) +			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); diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index 37c1f825f51..b98cf0c3572 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c @@ -113,7 +113,8 @@ void xen_pcibk_reset_device(struct pci_dev *dev)  		if (dev->msi_enabled)  			pci_disable_msi(dev);  #endif -		pci_disable_device(dev); +		if (pci_is_enabled(dev)) +			pci_disable_device(dev);  		pci_write_config_word(dev, PCI_COMMAND, 0);  |