diff options
| -rw-r--r-- | arch/x86/include/asm/xen/hypercall.h | 4 | ||||
| -rw-r--r-- | drivers/xen/fallback.c | 3 | ||||
| -rw-r--r-- | drivers/xen/xen-pciback/pci_stub.c | 59 | ||||
| -rw-r--r-- | include/xen/interface/physdev.h | 6 |
4 files changed, 54 insertions, 18 deletions
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h index c20d1ce62dc6..e709884d0ef9 100644 --- a/arch/x86/include/asm/xen/hypercall.h +++ b/arch/x86/include/asm/xen/hypercall.h | |||
| @@ -382,14 +382,14 @@ HYPERVISOR_console_io(int cmd, int count, char *str) | |||
| 382 | return _hypercall3(int, console_io, cmd, count, str); | 382 | return _hypercall3(int, console_io, cmd, count, str); |
| 383 | } | 383 | } |
| 384 | 384 | ||
| 385 | extern int __must_check HYPERVISOR_physdev_op_compat(int, void *); | 385 | extern int __must_check xen_physdev_op_compat(int, void *); |
| 386 | 386 | ||
| 387 | static inline int | 387 | static inline int |
| 388 | HYPERVISOR_physdev_op(int cmd, void *arg) | 388 | HYPERVISOR_physdev_op(int cmd, void *arg) |
| 389 | { | 389 | { |
| 390 | int rc = _hypercall2(int, physdev_op, cmd, arg); | 390 | int rc = _hypercall2(int, physdev_op, cmd, arg); |
| 391 | if (unlikely(rc == -ENOSYS)) | 391 | if (unlikely(rc == -ENOSYS)) |
| 392 | rc = HYPERVISOR_physdev_op_compat(cmd, arg); | 392 | rc = xen_physdev_op_compat(cmd, arg); |
| 393 | return rc; | 393 | return rc; |
| 394 | } | 394 | } |
| 395 | 395 | ||
diff --git a/drivers/xen/fallback.c b/drivers/xen/fallback.c index 0ef7c4d40f86..b04fb64c5a91 100644 --- a/drivers/xen/fallback.c +++ b/drivers/xen/fallback.c | |||
| @@ -44,7 +44,7 @@ int xen_event_channel_op_compat(int cmd, void *arg) | |||
| 44 | } | 44 | } |
| 45 | EXPORT_SYMBOL_GPL(xen_event_channel_op_compat); | 45 | EXPORT_SYMBOL_GPL(xen_event_channel_op_compat); |
| 46 | 46 | ||
| 47 | int HYPERVISOR_physdev_op_compat(int cmd, void *arg) | 47 | int xen_physdev_op_compat(int cmd, void *arg) |
| 48 | { | 48 | { |
| 49 | struct physdev_op op; | 49 | struct physdev_op op; |
| 50 | int rc; | 50 | int rc; |
| @@ -78,3 +78,4 @@ int HYPERVISOR_physdev_op_compat(int cmd, void *arg) | |||
| 78 | 78 | ||
| 79 | return rc; | 79 | return rc; |
| 80 | } | 80 | } |
| 81 | EXPORT_SYMBOL_GPL(xen_physdev_op_compat); | ||
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); |
diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h index 1844d31f4552..7000bb1f6e96 100644 --- a/include/xen/interface/physdev.h +++ b/include/xen/interface/physdev.h | |||
| @@ -251,6 +251,12 @@ struct physdev_pci_device_add { | |||
| 251 | 251 | ||
| 252 | #define PHYSDEVOP_pci_device_remove 26 | 252 | #define PHYSDEVOP_pci_device_remove 26 |
| 253 | #define PHYSDEVOP_restore_msi_ext 27 | 253 | #define PHYSDEVOP_restore_msi_ext 27 |
| 254 | /* | ||
| 255 | * Dom0 should use these two to announce MMIO resources assigned to | ||
| 256 | * MSI-X capable devices won't (prepare) or may (release) change. | ||
| 257 | */ | ||
| 258 | #define PHYSDEVOP_prepare_msix 30 | ||
| 259 | #define PHYSDEVOP_release_msix 31 | ||
| 254 | struct physdev_pci_device { | 260 | struct physdev_pci_device { |
| 255 | /* IN */ | 261 | /* IN */ |
| 256 | uint16_t seg; | 262 | uint16_t seg; |
