diff options
Diffstat (limited to 'drivers/xen/xen-pciback/pci_stub.c')
-rw-r--r-- | drivers/xen/xen-pciback/pci_stub.c | 59 |
1 files changed, 44 insertions, 15 deletions
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 9204126f1560..a2278ba7fb27 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <xen/events.h> | 17 | #include <xen/events.h> |
18 | #include <asm/xen/pci.h> | 18 | #include <asm/xen/pci.h> |
19 | #include <asm/xen/hypervisor.h> | 19 | #include <asm/xen/hypervisor.h> |
20 | #include <xen/interface/physdev.h> | ||
20 | #include "pciback.h" | 21 | #include "pciback.h" |
21 | #include "conf_space.h" | 22 | #include "conf_space.h" |
22 | #include "conf_space_quirks.h" | 23 | #include "conf_space_quirks.h" |
@@ -85,37 +86,52 @@ static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev) | |||
85 | static void pcistub_device_release(struct kref *kref) | 86 | static void pcistub_device_release(struct kref *kref) |
86 | { | 87 | { |
87 | struct pcistub_device *psdev; | 88 | struct pcistub_device *psdev; |
89 | struct pci_dev *dev; | ||
88 | struct xen_pcibk_dev_data *dev_data; | 90 | struct xen_pcibk_dev_data *dev_data; |
89 | 91 | ||
90 | psdev = container_of(kref, struct pcistub_device, kref); | 92 | psdev = container_of(kref, struct pcistub_device, kref); |
91 | dev_data = pci_get_drvdata(psdev->dev); | 93 | dev = psdev->dev; |
94 | dev_data = pci_get_drvdata(dev); | ||
92 | 95 | ||
93 | dev_dbg(&psdev->dev->dev, "pcistub_device_release\n"); | 96 | dev_dbg(&dev->dev, "pcistub_device_release\n"); |
94 | 97 | ||
95 | xen_unregister_device_domain_owner(psdev->dev); | 98 | xen_unregister_device_domain_owner(dev); |
96 | 99 | ||
97 | /* Call the reset function which does not take lock as this | 100 | /* Call the reset function which does not take lock as this |
98 | * is called from "unbind" which takes a device_lock mutex. | 101 | * is called from "unbind" which takes a device_lock mutex. |
99 | */ | 102 | */ |
100 | __pci_reset_function_locked(psdev->dev); | 103 | __pci_reset_function_locked(dev); |
101 | if (pci_load_and_free_saved_state(psdev->dev, | 104 | if (pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state)) |
102 | &dev_data->pci_saved_state)) { | 105 | dev_dbg(&dev->dev, "Could not reload PCI state\n"); |
103 | dev_dbg(&psdev->dev->dev, "Could not reload PCI state\n"); | 106 | else |
104 | } else | 107 | pci_restore_state(dev); |
105 | pci_restore_state(psdev->dev); | 108 | |
109 | if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) { | ||
110 | struct physdev_pci_device ppdev = { | ||
111 | .seg = pci_domain_nr(dev->bus), | ||
112 | .bus = dev->bus->number, | ||
113 | .devfn = dev->devfn | ||
114 | }; | ||
115 | int err = HYPERVISOR_physdev_op(PHYSDEVOP_release_msix, | ||
116 | &ppdev); | ||
117 | |||
118 | if (err) | ||
119 | dev_warn(&dev->dev, "MSI-X release failed (%d)\n", | ||
120 | err); | ||
121 | } | ||
106 | 122 | ||
107 | /* Disable the device */ | 123 | /* Disable the device */ |
108 | xen_pcibk_reset_device(psdev->dev); | 124 | xen_pcibk_reset_device(dev); |
109 | 125 | ||
110 | kfree(dev_data); | 126 | kfree(dev_data); |
111 | pci_set_drvdata(psdev->dev, NULL); | 127 | pci_set_drvdata(dev, NULL); |
112 | 128 | ||
113 | /* Clean-up the device */ | 129 | /* Clean-up the device */ |
114 | xen_pcibk_config_free_dyn_fields(psdev->dev); | 130 | xen_pcibk_config_free_dyn_fields(dev); |
115 | xen_pcibk_config_free_dev(psdev->dev); | 131 | xen_pcibk_config_free_dev(dev); |
116 | 132 | ||
117 | psdev->dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED; | 133 | dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED; |
118 | pci_dev_put(psdev->dev); | 134 | pci_dev_put(dev); |
119 | 135 | ||
120 | kfree(psdev); | 136 | kfree(psdev); |
121 | } | 137 | } |
@@ -355,6 +371,19 @@ static int pcistub_init_device(struct pci_dev *dev) | |||
355 | if (err) | 371 | if (err) |
356 | goto config_release; | 372 | goto config_release; |
357 | 373 | ||
374 | if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) { | ||
375 | struct physdev_pci_device ppdev = { | ||
376 | .seg = pci_domain_nr(dev->bus), | ||
377 | .bus = dev->bus->number, | ||
378 | .devfn = dev->devfn | ||
379 | }; | ||
380 | |||
381 | err = HYPERVISOR_physdev_op(PHYSDEVOP_prepare_msix, &ppdev); | ||
382 | if (err) | ||
383 | dev_err(&dev->dev, "MSI-X preparation failed (%d)\n", | ||
384 | err); | ||
385 | } | ||
386 | |||
358 | /* We need the device active to save the state. */ | 387 | /* We need the device active to save the state. */ |
359 | dev_dbg(&dev->dev, "save state of device\n"); | 388 | dev_dbg(&dev->dev, "save state of device\n"); |
360 | pci_save_state(dev); | 389 | pci_save_state(dev); |