aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2017-04-04 14:44:44 -0400
committerMichael S. Tsirkin <mst@redhat.com>2017-04-10 17:29:59 -0400
commit0a9b3f47da5b8a2c4bf4f2f2199761f49ac0a54e (patch)
treece81a903abb42f7d92d5e1a8929d3ced8c388d69
parent0b0f9dc52ed0333fa52a9314b53d0b2b248b821d (diff)
Revert "virtio_pci: remove struct virtio_pci_vq_info"
This reverts commit 5c34d002dcc7a6dd665a19d098b4f4cd5501ba1a. Conflicts: drivers/virtio/virtio_pci_common.c The cleanup seems to be one of the changes that broke hybernation for some users. We are still not sure why but revert helps. This reverts the cleanup changes but keeps the affinity support. Tested-by: Mike Galbraith <efault@gmx.de> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--drivers/virtio/virtio_pci_common.c128
-rw-r--r--drivers/virtio/virtio_pci_common.h25
-rw-r--r--drivers/virtio/virtio_pci_legacy.c6
-rw-r--r--drivers/virtio/virtio_pci_modern.c6
4 files changed, 122 insertions, 43 deletions
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index d99029d3892e..e41bff3ec79b 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -62,13 +62,16 @@ static irqreturn_t vp_config_changed(int irq, void *opaque)
62static irqreturn_t vp_vring_interrupt(int irq, void *opaque) 62static irqreturn_t vp_vring_interrupt(int irq, void *opaque)
63{ 63{
64 struct virtio_pci_device *vp_dev = opaque; 64 struct virtio_pci_device *vp_dev = opaque;
65 struct virtio_pci_vq_info *info;
65 irqreturn_t ret = IRQ_NONE; 66 irqreturn_t ret = IRQ_NONE;
66 struct virtqueue *vq; 67 unsigned long flags;
67 68
68 list_for_each_entry(vq, &vp_dev->vdev.vqs, list) { 69 spin_lock_irqsave(&vp_dev->lock, flags);
69 if (vq->callback && vring_interrupt(irq, vq) == IRQ_HANDLED) 70 list_for_each_entry(info, &vp_dev->virtqueues, node) {
71 if (vring_interrupt(irq, info->vq) == IRQ_HANDLED)
70 ret = IRQ_HANDLED; 72 ret = IRQ_HANDLED;
71 } 73 }
74 spin_unlock_irqrestore(&vp_dev->lock, flags);
72 75
73 return ret; 76 return ret;
74} 77}
@@ -166,6 +169,56 @@ error:
166 return err; 169 return err;
167} 170}
168 171
172static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index,
173 void (*callback)(struct virtqueue *vq),
174 const char *name,
175 u16 msix_vec)
176{
177 struct virtio_pci_device *vp_dev = to_vp_device(vdev);
178 struct virtio_pci_vq_info *info = kmalloc(sizeof *info, GFP_KERNEL);
179 struct virtqueue *vq;
180 unsigned long flags;
181
182 /* fill out our structure that represents an active queue */
183 if (!info)
184 return ERR_PTR(-ENOMEM);
185
186 vq = vp_dev->setup_vq(vp_dev, info, index, callback, name,
187 msix_vec);
188 if (IS_ERR(vq))
189 goto out_info;
190
191 info->vq = vq;
192 if (callback) {
193 spin_lock_irqsave(&vp_dev->lock, flags);
194 list_add(&info->node, &vp_dev->virtqueues);
195 spin_unlock_irqrestore(&vp_dev->lock, flags);
196 } else {
197 INIT_LIST_HEAD(&info->node);
198 }
199
200 vp_dev->vqs[index] = info;
201 return vq;
202
203out_info:
204 kfree(info);
205 return vq;
206}
207
208static void vp_del_vq(struct virtqueue *vq)
209{
210 struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
211 struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
212 unsigned long flags;
213
214 spin_lock_irqsave(&vp_dev->lock, flags);
215 list_del(&info->node);
216 spin_unlock_irqrestore(&vp_dev->lock, flags);
217
218 vp_dev->del_vq(info);
219 kfree(info);
220}
221
169/* the config->del_vqs() implementation */ 222/* the config->del_vqs() implementation */
170void vp_del_vqs(struct virtio_device *vdev) 223void vp_del_vqs(struct virtio_device *vdev)
171{ 224{
@@ -174,15 +227,16 @@ void vp_del_vqs(struct virtio_device *vdev)
174 int i; 227 int i;
175 228
176 list_for_each_entry_safe(vq, n, &vdev->vqs, list) { 229 list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
177 if (vp_dev->msix_vector_map) { 230 if (vp_dev->per_vq_vectors) {
178 int v = vp_dev->msix_vector_map[vq->index]; 231 int v = vp_dev->vqs[vq->index]->msix_vector;
179 232
180 if (v != VIRTIO_MSI_NO_VECTOR) 233 if (v != VIRTIO_MSI_NO_VECTOR)
181 free_irq(pci_irq_vector(vp_dev->pci_dev, v), 234 free_irq(pci_irq_vector(vp_dev->pci_dev, v),
182 vq); 235 vq);
183 } 236 }
184 vp_dev->del_vq(vq); 237 vp_del_vq(vq);
185 } 238 }
239 vp_dev->per_vq_vectors = false;
186 240
187 if (vp_dev->intx_enabled) { 241 if (vp_dev->intx_enabled) {
188 free_irq(vp_dev->pci_dev->irq, vp_dev); 242 free_irq(vp_dev->pci_dev->irq, vp_dev);
@@ -210,8 +264,8 @@ void vp_del_vqs(struct virtio_device *vdev)
210 vp_dev->msix_names = NULL; 264 vp_dev->msix_names = NULL;
211 kfree(vp_dev->msix_affinity_masks); 265 kfree(vp_dev->msix_affinity_masks);
212 vp_dev->msix_affinity_masks = NULL; 266 vp_dev->msix_affinity_masks = NULL;
213 kfree(vp_dev->msix_vector_map); 267 kfree(vp_dev->vqs);
214 vp_dev->msix_vector_map = NULL; 268 vp_dev->vqs = NULL;
215} 269}
216 270
217static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs, 271static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
@@ -223,6 +277,10 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
223 u16 msix_vec; 277 u16 msix_vec;
224 int i, err, nvectors, allocated_vectors; 278 int i, err, nvectors, allocated_vectors;
225 279
280 vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
281 if (!vp_dev->vqs)
282 return -ENOMEM;
283
226 if (per_vq_vectors) { 284 if (per_vq_vectors) {
227 /* Best option: one for change interrupt, one per vq. */ 285 /* Best option: one for change interrupt, one per vq. */
228 nvectors = 1; 286 nvectors = 1;
@@ -239,13 +297,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
239 if (err) 297 if (err)
240 goto error_find; 298 goto error_find;
241 299
242 if (per_vq_vectors) { 300 vp_dev->per_vq_vectors = per_vq_vectors;
243 vp_dev->msix_vector_map = kmalloc_array(nvqs,
244 sizeof(*vp_dev->msix_vector_map), GFP_KERNEL);
245 if (!vp_dev->msix_vector_map)
246 goto error_find;
247 }
248
249 allocated_vectors = vp_dev->msix_used_vectors; 301 allocated_vectors = vp_dev->msix_used_vectors;
250 for (i = 0; i < nvqs; ++i) { 302 for (i = 0; i < nvqs; ++i) {
251 if (!names[i]) { 303 if (!names[i]) {
@@ -255,24 +307,19 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
255 307
256 if (!callbacks[i]) 308 if (!callbacks[i])
257 msix_vec = VIRTIO_MSI_NO_VECTOR; 309 msix_vec = VIRTIO_MSI_NO_VECTOR;
258 else if (per_vq_vectors) 310 else if (vp_dev->per_vq_vectors)
259 msix_vec = allocated_vectors++; 311 msix_vec = allocated_vectors++;
260 else 312 else
261 msix_vec = VP_MSIX_VQ_VECTOR; 313 msix_vec = VP_MSIX_VQ_VECTOR;
262 vqs[i] = vp_dev->setup_vq(vp_dev, i, callbacks[i], names[i], 314 vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i],
263 msix_vec); 315 msix_vec);
264 if (IS_ERR(vqs[i])) { 316 if (IS_ERR(vqs[i])) {
265 err = PTR_ERR(vqs[i]); 317 err = PTR_ERR(vqs[i]);
266 goto error_find; 318 goto error_find;
267 } 319 }
268 320
269 if (!per_vq_vectors) 321 if (!vp_dev->per_vq_vectors || msix_vec == VIRTIO_MSI_NO_VECTOR)
270 continue;
271
272 if (msix_vec == VIRTIO_MSI_NO_VECTOR) {
273 vp_dev->msix_vector_map[i] = VIRTIO_MSI_NO_VECTOR;
274 continue; 322 continue;
275 }
276 323
277 /* allocate per-vq irq if available and necessary */ 324 /* allocate per-vq irq if available and necessary */
278 snprintf(vp_dev->msix_names[msix_vec], 325 snprintf(vp_dev->msix_names[msix_vec],
@@ -283,12 +330,8 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
283 vring_interrupt, 0, 330 vring_interrupt, 0,
284 vp_dev->msix_names[msix_vec], 331 vp_dev->msix_names[msix_vec],
285 vqs[i]); 332 vqs[i]);
286 if (err) { 333 if (err)
287 /* don't free this irq on error */
288 vp_dev->msix_vector_map[i] = VIRTIO_MSI_NO_VECTOR;
289 goto error_find; 334 goto error_find;
290 }
291 vp_dev->msix_vector_map[i] = msix_vec;
292 } 335 }
293 return 0; 336 return 0;
294 337
@@ -304,19 +347,24 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
304 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 347 struct virtio_pci_device *vp_dev = to_vp_device(vdev);
305 int i, err; 348 int i, err;
306 349
350 vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
351 if (!vp_dev->vqs)
352 return -ENOMEM;
353
307 err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED, 354 err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED,
308 dev_name(&vdev->dev), vp_dev); 355 dev_name(&vdev->dev), vp_dev);
309 if (err) 356 if (err)
310 goto out_del_vqs; 357 goto out_del_vqs;
311 358
312 vp_dev->intx_enabled = 1; 359 vp_dev->intx_enabled = 1;
360 vp_dev->per_vq_vectors = false;
313 for (i = 0; i < nvqs; ++i) { 361 for (i = 0; i < nvqs; ++i) {
314 if (!names[i]) { 362 if (!names[i]) {
315 vqs[i] = NULL; 363 vqs[i] = NULL;
316 continue; 364 continue;
317 } 365 }
318 vqs[i] = vp_dev->setup_vq(vp_dev, i, callbacks[i], names[i], 366 vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i],
319 VIRTIO_MSI_NO_VECTOR); 367 VIRTIO_MSI_NO_VECTOR);
320 if (IS_ERR(vqs[i])) { 368 if (IS_ERR(vqs[i])) {
321 err = PTR_ERR(vqs[i]); 369 err = PTR_ERR(vqs[i]);
322 goto out_del_vqs; 370 goto out_del_vqs;
@@ -364,15 +412,16 @@ int vp_set_vq_affinity(struct virtqueue *vq, int cpu)
364{ 412{
365 struct virtio_device *vdev = vq->vdev; 413 struct virtio_device *vdev = vq->vdev;
366 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 414 struct virtio_pci_device *vp_dev = to_vp_device(vdev);
415 struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
416 struct cpumask *mask;
417 unsigned int irq;
367 418
368 if (!vq->callback) 419 if (!vq->callback)
369 return -EINVAL; 420 return -EINVAL;
370 421
371 if (vp_dev->msix_enabled) { 422 if (vp_dev->msix_enabled) {
372 int vec = vp_dev->msix_vector_map[vq->index]; 423 mask = vp_dev->msix_affinity_masks[info->msix_vector];
373 struct cpumask *mask = vp_dev->msix_affinity_masks[vec]; 424 irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
374 unsigned int irq = pci_irq_vector(vp_dev->pci_dev, vec);
375
376 if (cpu == -1) 425 if (cpu == -1)
377 irq_set_affinity_hint(irq, NULL); 426 irq_set_affinity_hint(irq, NULL);
378 else { 427 else {
@@ -387,12 +436,13 @@ int vp_set_vq_affinity(struct virtqueue *vq, int cpu)
387const struct cpumask *vp_get_vq_affinity(struct virtio_device *vdev, int index) 436const struct cpumask *vp_get_vq_affinity(struct virtio_device *vdev, int index)
388{ 437{
389 struct virtio_pci_device *vp_dev = to_vp_device(vdev); 438 struct virtio_pci_device *vp_dev = to_vp_device(vdev);
390 unsigned int *map = vp_dev->msix_vector_map;
391 439
392 if (!map || map[index] == VIRTIO_MSI_NO_VECTOR) 440 if (!vp_dev->per_vq_vectors ||
441 vp_dev->vqs[index]->msix_vector == VIRTIO_MSI_NO_VECTOR)
393 return NULL; 442 return NULL;
394 443
395 return pci_irq_get_affinity(vp_dev->pci_dev, map[index]); 444 return pci_irq_get_affinity(vp_dev->pci_dev,
445 vp_dev->vqs[index]->msix_vector);
396} 446}
397 447
398#ifdef CONFIG_PM_SLEEP 448#ifdef CONFIG_PM_SLEEP
@@ -463,6 +513,8 @@ static int virtio_pci_probe(struct pci_dev *pci_dev,
463 vp_dev->vdev.dev.parent = &pci_dev->dev; 513 vp_dev->vdev.dev.parent = &pci_dev->dev;
464 vp_dev->vdev.dev.release = virtio_pci_release_dev; 514 vp_dev->vdev.dev.release = virtio_pci_release_dev;
465 vp_dev->pci_dev = pci_dev; 515 vp_dev->pci_dev = pci_dev;
516 INIT_LIST_HEAD(&vp_dev->virtqueues);
517 spin_lock_init(&vp_dev->lock);
466 518
467 /* enable the device */ 519 /* enable the device */
468 rc = pci_enable_device(pci_dev); 520 rc = pci_enable_device(pci_dev);
diff --git a/drivers/virtio/virtio_pci_common.h b/drivers/virtio/virtio_pci_common.h
index 3cdabba8415e..e96334aec1e0 100644
--- a/drivers/virtio/virtio_pci_common.h
+++ b/drivers/virtio/virtio_pci_common.h
@@ -31,6 +31,17 @@
31#include <linux/highmem.h> 31#include <linux/highmem.h>
32#include <linux/spinlock.h> 32#include <linux/spinlock.h>
33 33
34struct virtio_pci_vq_info {
35 /* the actual virtqueue */
36 struct virtqueue *vq;
37
38 /* the list node for the virtqueues list */
39 struct list_head node;
40
41 /* MSI-X vector (or none) */
42 unsigned msix_vector;
43};
44
34/* Our device structure */ 45/* Our device structure */
35struct virtio_pci_device { 46struct virtio_pci_device {
36 struct virtio_device vdev; 47 struct virtio_device vdev;
@@ -64,6 +75,13 @@ struct virtio_pci_device {
64 /* the IO mapping for the PCI config space */ 75 /* the IO mapping for the PCI config space */
65 void __iomem *ioaddr; 76 void __iomem *ioaddr;
66 77
78 /* a list of queues so we can dispatch IRQs */
79 spinlock_t lock;
80 struct list_head virtqueues;
81
82 /* array of all queues for house-keeping */
83 struct virtio_pci_vq_info **vqs;
84
67 /* MSI-X support */ 85 /* MSI-X support */
68 int msix_enabled; 86 int msix_enabled;
69 int intx_enabled; 87 int intx_enabled;
@@ -76,15 +94,16 @@ struct virtio_pci_device {
76 /* Vectors allocated, excluding per-vq vectors if any */ 94 /* Vectors allocated, excluding per-vq vectors if any */
77 unsigned msix_used_vectors; 95 unsigned msix_used_vectors;
78 96
79 /* Map of per-VQ MSI-X vectors, may be NULL */ 97 /* Whether we have vector per vq */
80 unsigned *msix_vector_map; 98 bool per_vq_vectors;
81 99
82 struct virtqueue *(*setup_vq)(struct virtio_pci_device *vp_dev, 100 struct virtqueue *(*setup_vq)(struct virtio_pci_device *vp_dev,
101 struct virtio_pci_vq_info *info,
83 unsigned idx, 102 unsigned idx,
84 void (*callback)(struct virtqueue *vq), 103 void (*callback)(struct virtqueue *vq),
85 const char *name, 104 const char *name,
86 u16 msix_vec); 105 u16 msix_vec);
87 void (*del_vq)(struct virtqueue *vq); 106 void (*del_vq)(struct virtio_pci_vq_info *info);
88 107
89 u16 (*config_vector)(struct virtio_pci_device *vp_dev, u16 vector); 108 u16 (*config_vector)(struct virtio_pci_device *vp_dev, u16 vector);
90}; 109};
diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c
index 5dd01f09608b..4bfa48fb1324 100644
--- a/drivers/virtio/virtio_pci_legacy.c
+++ b/drivers/virtio/virtio_pci_legacy.c
@@ -112,6 +112,7 @@ static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
112} 112}
113 113
114static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, 114static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
115 struct virtio_pci_vq_info *info,
115 unsigned index, 116 unsigned index,
116 void (*callback)(struct virtqueue *vq), 117 void (*callback)(struct virtqueue *vq),
117 const char *name, 118 const char *name,
@@ -129,6 +130,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
129 if (!num || ioread32(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN)) 130 if (!num || ioread32(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN))
130 return ERR_PTR(-ENOENT); 131 return ERR_PTR(-ENOENT);
131 132
133 info->msix_vector = msix_vec;
134
132 /* create the vring */ 135 /* create the vring */
133 vq = vring_create_virtqueue(index, num, 136 vq = vring_create_virtqueue(index, num,
134 VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev, 137 VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev,
@@ -159,8 +162,9 @@ out_deactivate:
159 return ERR_PTR(err); 162 return ERR_PTR(err);
160} 163}
161 164
162static void del_vq(struct virtqueue *vq) 165static void del_vq(struct virtio_pci_vq_info *info)
163{ 166{
167 struct virtqueue *vq = info->vq;
164 struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); 168 struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
165 169
166 iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); 170 iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 7ce36daccc31..8978f109d2d7 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -293,6 +293,7 @@ static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector)
293} 293}
294 294
295static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, 295static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
296 struct virtio_pci_vq_info *info,
296 unsigned index, 297 unsigned index,
297 void (*callback)(struct virtqueue *vq), 298 void (*callback)(struct virtqueue *vq),
298 const char *name, 299 const char *name,
@@ -322,6 +323,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
322 /* get offset of notification word for this vq */ 323 /* get offset of notification word for this vq */
323 off = vp_ioread16(&cfg->queue_notify_off); 324 off = vp_ioread16(&cfg->queue_notify_off);
324 325
326 info->msix_vector = msix_vec;
327
325 /* create the vring */ 328 /* create the vring */
326 vq = vring_create_virtqueue(index, num, 329 vq = vring_create_virtqueue(index, num,
327 SMP_CACHE_BYTES, &vp_dev->vdev, 330 SMP_CACHE_BYTES, &vp_dev->vdev,
@@ -405,8 +408,9 @@ static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
405 return 0; 408 return 0;
406} 409}
407 410
408static void del_vq(struct virtqueue *vq) 411static void del_vq(struct virtio_pci_vq_info *info)
409{ 412{
413 struct virtqueue *vq = info->vq;
410 struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); 414 struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
411 415
412 vp_iowrite16(vq->index, &vp_dev->common->queue_select); 416 vp_iowrite16(vq->index, &vp_dev->common->queue_select);