aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/xen/hypercall.h4
-rw-r--r--drivers/xen/fallback.c3
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c59
-rw-r--r--include/xen/interface/physdev.h6
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
385extern int __must_check HYPERVISOR_physdev_op_compat(int, void *); 385extern int __must_check xen_physdev_op_compat(int, void *);
386 386
387static inline int 387static inline int
388HYPERVISOR_physdev_op(int cmd, void *arg) 388HYPERVISOR_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}
45EXPORT_SYMBOL_GPL(xen_event_channel_op_compat); 45EXPORT_SYMBOL_GPL(xen_event_channel_op_compat);
46 46
47int HYPERVISOR_physdev_op_compat(int cmd, void *arg) 47int 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}
81EXPORT_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)
85static void pcistub_device_release(struct kref *kref) 86static 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
254struct physdev_pci_device { 260struct physdev_pci_device {
255 /* IN */ 261 /* IN */
256 uint16_t seg; 262 uint16_t seg;