aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/xen/xen-pciback/passthrough.c14
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c12
-rw-r--r--drivers/xen/xen-pciback/pciback.h7
-rw-r--r--drivers/xen/xen-pciback/vpci.c14
-rw-r--r--drivers/xen/xen-pciback/xenbus.c2
5 files changed, 33 insertions, 16 deletions
diff --git a/drivers/xen/xen-pciback/passthrough.c b/drivers/xen/xen-pciback/passthrough.c
index 828dddc360df..f16a30e2a110 100644
--- a/drivers/xen/xen-pciback/passthrough.c
+++ b/drivers/xen/xen-pciback/passthrough.c
@@ -69,7 +69,7 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
69} 69}
70 70
71static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev, 71static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
72 struct pci_dev *dev) 72 struct pci_dev *dev, bool lock)
73{ 73{
74 struct passthrough_dev_data *dev_data = pdev->pci_dev_data; 74 struct passthrough_dev_data *dev_data = pdev->pci_dev_data;
75 struct pci_dev_entry *dev_entry, *t; 75 struct pci_dev_entry *dev_entry, *t;
@@ -87,8 +87,13 @@ static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
87 87
88 mutex_unlock(&dev_data->lock); 88 mutex_unlock(&dev_data->lock);
89 89
90 if (found_dev) 90 if (found_dev) {
91 if (lock)
92 device_lock(&found_dev->dev);
91 pcistub_put_pci_dev(found_dev); 93 pcistub_put_pci_dev(found_dev);
94 if (lock)
95 device_unlock(&found_dev->dev);
96 }
92} 97}
93 98
94static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev) 99static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
@@ -156,8 +161,11 @@ static void __xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
156 struct pci_dev_entry *dev_entry, *t; 161 struct pci_dev_entry *dev_entry, *t;
157 162
158 list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) { 163 list_for_each_entry_safe(dev_entry, t, &dev_data->dev_list, list) {
164 struct pci_dev *dev = dev_entry->dev;
159 list_del(&dev_entry->list); 165 list_del(&dev_entry->list);
160 pcistub_put_pci_dev(dev_entry->dev); 166 device_lock(&dev->dev);
167 pcistub_put_pci_dev(dev);
168 device_unlock(&dev->dev);
161 kfree(dev_entry); 169 kfree(dev_entry);
162 } 170 }
163 171
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 017069a455d4..9cbe1a31c1e5 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -250,6 +250,8 @@ struct pci_dev *pcistub_get_pci_dev(struct xen_pcibk_device *pdev,
250 * - 'echo BDF > unbind' with a guest still using it. See pcistub_remove 250 * - 'echo BDF > unbind' with a guest still using it. See pcistub_remove
251 * 251 *
252 * As such we have to be careful. 252 * As such we have to be careful.
253 *
254 * To make this easier, the caller has to hold the device lock.
253 */ 255 */
254void pcistub_put_pci_dev(struct pci_dev *dev) 256void pcistub_put_pci_dev(struct pci_dev *dev)
255{ 257{
@@ -276,11 +278,8 @@ void pcistub_put_pci_dev(struct pci_dev *dev)
276 /* Cleanup our device 278 /* Cleanup our device
277 * (so it's ready for the next domain) 279 * (so it's ready for the next domain)
278 */ 280 */
279 281 lockdep_assert_held(&dev->dev.mutex);
280 /* This is OK - we are running from workqueue context 282 __pci_reset_function_locked(dev);
281 * and want to inhibit the user from fiddling with 'reset'
282 */
283 pci_reset_function(dev);
284 pci_restore_state(dev); 283 pci_restore_state(dev);
285 284
286 /* This disables the device. */ 285 /* This disables the device. */
@@ -567,7 +566,8 @@ static void pcistub_remove(struct pci_dev *dev)
567 /* N.B. This ends up calling pcistub_put_pci_dev which ends up 566 /* N.B. This ends up calling pcistub_put_pci_dev which ends up
568 * doing the FLR. */ 567 * doing the FLR. */
569 xen_pcibk_release_pci_dev(found_psdev->pdev, 568 xen_pcibk_release_pci_dev(found_psdev->pdev,
570 found_psdev->dev); 569 found_psdev->dev,
570 false /* caller holds the lock. */);
571 } 571 }
572 572
573 spin_lock_irqsave(&pcistub_devices_lock, flags); 573 spin_lock_irqsave(&pcistub_devices_lock, flags);
diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h
index f72af87640e0..58e38d586f52 100644
--- a/drivers/xen/xen-pciback/pciback.h
+++ b/drivers/xen/xen-pciback/pciback.h
@@ -99,7 +99,8 @@ struct xen_pcibk_backend {
99 unsigned int *domain, unsigned int *bus, 99 unsigned int *domain, unsigned int *bus,
100 unsigned int *devfn); 100 unsigned int *devfn);
101 int (*publish)(struct xen_pcibk_device *pdev, publish_pci_root_cb cb); 101 int (*publish)(struct xen_pcibk_device *pdev, publish_pci_root_cb cb);
102 void (*release)(struct xen_pcibk_device *pdev, struct pci_dev *dev); 102 void (*release)(struct xen_pcibk_device *pdev, struct pci_dev *dev,
103 bool lock);
103 int (*add)(struct xen_pcibk_device *pdev, struct pci_dev *dev, 104 int (*add)(struct xen_pcibk_device *pdev, struct pci_dev *dev,
104 int devid, publish_pci_dev_cb publish_cb); 105 int devid, publish_pci_dev_cb publish_cb);
105 struct pci_dev *(*get)(struct xen_pcibk_device *pdev, 106 struct pci_dev *(*get)(struct xen_pcibk_device *pdev,
@@ -122,10 +123,10 @@ static inline int xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
122} 123}
123 124
124static inline void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev, 125static inline void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
125 struct pci_dev *dev) 126 struct pci_dev *dev, bool lock)
126{ 127{
127 if (xen_pcibk_backend && xen_pcibk_backend->release) 128 if (xen_pcibk_backend && xen_pcibk_backend->release)
128 return xen_pcibk_backend->release(pdev, dev); 129 return xen_pcibk_backend->release(pdev, dev, lock);
129} 130}
130 131
131static inline struct pci_dev * 132static inline struct pci_dev *
diff --git a/drivers/xen/xen-pciback/vpci.c b/drivers/xen/xen-pciback/vpci.c
index 51afff96c515..c99f8bb1c56c 100644
--- a/drivers/xen/xen-pciback/vpci.c
+++ b/drivers/xen/xen-pciback/vpci.c
@@ -145,7 +145,7 @@ out:
145} 145}
146 146
147static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev, 147static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
148 struct pci_dev *dev) 148 struct pci_dev *dev, bool lock)
149{ 149{
150 int slot; 150 int slot;
151 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; 151 struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
@@ -169,8 +169,13 @@ static void __xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
169out: 169out:
170 mutex_unlock(&vpci_dev->lock); 170 mutex_unlock(&vpci_dev->lock);
171 171
172 if (found_dev) 172 if (found_dev) {
173 if (lock)
174 device_lock(&found_dev->dev);
173 pcistub_put_pci_dev(found_dev); 175 pcistub_put_pci_dev(found_dev);
176 if (lock)
177 device_unlock(&found_dev->dev);
178 }
174} 179}
175 180
176static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev) 181static int __xen_pcibk_init_devices(struct xen_pcibk_device *pdev)
@@ -208,8 +213,11 @@ static void __xen_pcibk_release_devices(struct xen_pcibk_device *pdev)
208 struct pci_dev_entry *e, *tmp; 213 struct pci_dev_entry *e, *tmp;
209 list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot], 214 list_for_each_entry_safe(e, tmp, &vpci_dev->dev_list[slot],
210 list) { 215 list) {
216 struct pci_dev *dev = e->dev;
211 list_del(&e->list); 217 list_del(&e->list);
212 pcistub_put_pci_dev(e->dev); 218 device_lock(&dev->dev);
219 pcistub_put_pci_dev(dev);
220 device_unlock(&dev->dev);
213 kfree(e); 221 kfree(e);
214 } 222 }
215 } 223 }
diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c
index ad8d30c088fe..eeee499d4b3c 100644
--- a/drivers/xen/xen-pciback/xenbus.c
+++ b/drivers/xen/xen-pciback/xenbus.c
@@ -291,7 +291,7 @@ static int xen_pcibk_remove_device(struct xen_pcibk_device *pdev,
291 291
292 /* N.B. This ends up calling pcistub_put_pci_dev which ends up 292 /* N.B. This ends up calling pcistub_put_pci_dev which ends up
293 * doing the FLR. */ 293 * doing the FLR. */
294 xen_pcibk_release_pci_dev(pdev, dev); 294 xen_pcibk_release_pci_dev(pdev, dev, true /* use the lock. */);
295 295
296out: 296out:
297 return err; 297 return err;