]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/virtio/virtio_pci_common.c
virtio: allow drivers to request IRQ affinity when creating VQs
[karo-tx-linux.git] / drivers / virtio / virtio_pci_common.c
1 /*
2  * Virtio PCI driver - common functionality for all device versions
3  *
4  * This module allows virtio devices to be used over a virtual PCI device.
5  * This can be used with QEMU based VMMs like KVM or Xen.
6  *
7  * Copyright IBM Corp. 2007
8  * Copyright Red Hat, Inc. 2014
9  *
10  * Authors:
11  *  Anthony Liguori  <aliguori@us.ibm.com>
12  *  Rusty Russell <rusty@rustcorp.com.au>
13  *  Michael S. Tsirkin <mst@redhat.com>
14  *
15  * This work is licensed under the terms of the GNU GPL, version 2 or later.
16  * See the COPYING file in the top-level directory.
17  *
18  */
19
20 #include "virtio_pci_common.h"
21
22 static bool force_legacy = false;
23
24 #if IS_ENABLED(CONFIG_VIRTIO_PCI_LEGACY)
25 module_param(force_legacy, bool, 0444);
26 MODULE_PARM_DESC(force_legacy,
27                  "Force legacy mode for transitional virtio 1 devices");
28 #endif
29
30 /* wait for pending irq handlers */
31 void vp_synchronize_vectors(struct virtio_device *vdev)
32 {
33         struct virtio_pci_device *vp_dev = to_vp_device(vdev);
34         int i;
35
36         synchronize_irq(pci_irq_vector(vp_dev->pci_dev, 0));
37         for (i = 1; i < vp_dev->msix_vectors; i++)
38                 synchronize_irq(pci_irq_vector(vp_dev->pci_dev, i));
39 }
40
41 /* the notify function used when creating a virt queue */
42 bool vp_notify(struct virtqueue *vq)
43 {
44         /* we write the queue's selector into the notification register to
45          * signal the other end */
46         iowrite16(vq->index, (void __iomem *)vq->priv);
47         return true;
48 }
49
50 /* Handle a configuration change: Tell driver if it wants to know. */
51 static irqreturn_t vp_config_changed(int irq, void *opaque)
52 {
53         struct virtio_pci_device *vp_dev = opaque;
54
55         virtio_config_changed(&vp_dev->vdev);
56         return IRQ_HANDLED;
57 }
58
59 /* Notify all virtqueues on an interrupt. */
60 static irqreturn_t vp_vring_interrupt(int irq, void *opaque)
61 {
62         struct virtio_pci_device *vp_dev = opaque;
63         irqreturn_t ret = IRQ_NONE;
64         struct virtqueue *vq;
65
66         list_for_each_entry(vq, &vp_dev->vdev.vqs, list) {
67                 if (vq->callback && vring_interrupt(irq, vq) == IRQ_HANDLED)
68                         ret = IRQ_HANDLED;
69         }
70
71         return ret;
72 }
73
74 /* A small wrapper to also acknowledge the interrupt when it's handled.
75  * I really need an EIO hook for the vring so I can ack the interrupt once we
76  * know that we'll be handling the IRQ but before we invoke the callback since
77  * the callback may notify the host which results in the host attempting to
78  * raise an interrupt that we would then mask once we acknowledged the
79  * interrupt. */
80 static irqreturn_t vp_interrupt(int irq, void *opaque)
81 {
82         struct virtio_pci_device *vp_dev = opaque;
83         u8 isr;
84
85         /* reading the ISR has the effect of also clearing it so it's very
86          * important to save off the value. */
87         isr = ioread8(vp_dev->isr);
88
89         /* It's definitely not us if the ISR was not high */
90         if (!isr)
91                 return IRQ_NONE;
92
93         /* Configuration change?  Tell driver if it wants to know. */
94         if (isr & VIRTIO_PCI_ISR_CONFIG)
95                 vp_config_changed(irq, opaque);
96
97         return vp_vring_interrupt(irq, opaque);
98 }
99
100 static void vp_remove_vqs(struct virtio_device *vdev)
101 {
102         struct virtio_pci_device *vp_dev = to_vp_device(vdev);
103         struct virtqueue *vq, *n;
104
105         list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
106                 if (vp_dev->msix_vector_map) {
107                         int v = vp_dev->msix_vector_map[vq->index];
108
109                         if (v != VIRTIO_MSI_NO_VECTOR)
110                                 free_irq(pci_irq_vector(vp_dev->pci_dev, v),
111                                         vq);
112                 }
113                 vp_dev->del_vq(vq);
114         }
115 }
116
117 /* the config->del_vqs() implementation */
118 void vp_del_vqs(struct virtio_device *vdev)
119 {
120         struct virtio_pci_device *vp_dev = to_vp_device(vdev);
121         int i;
122
123         if (WARN_ON_ONCE(list_empty_careful(&vdev->vqs)))
124                 return;
125
126         vp_remove_vqs(vdev);
127
128         if (vp_dev->pci_dev->msix_enabled) {
129                 for (i = 0; i < vp_dev->msix_vectors; i++)
130                         free_cpumask_var(vp_dev->msix_affinity_masks[i]);
131
132                 /* Disable the vector used for configuration */
133                 vp_dev->config_vector(vp_dev, VIRTIO_MSI_NO_VECTOR);
134
135                 kfree(vp_dev->msix_affinity_masks);
136                 kfree(vp_dev->msix_names);
137                 kfree(vp_dev->msix_vector_map);
138         }
139
140         free_irq(pci_irq_vector(vp_dev->pci_dev, 0), vp_dev);
141         pci_free_irq_vectors(vp_dev->pci_dev);
142 }
143
144 static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
145                 struct virtqueue *vqs[], vq_callback_t *callbacks[],
146                 const char * const names[], struct irq_affinity *desc)
147 {
148         struct virtio_pci_device *vp_dev = to_vp_device(vdev);
149         const char *name = dev_name(&vp_dev->vdev.dev);
150         int i, err = -ENOMEM, allocated_vectors, nvectors;
151         unsigned flags = PCI_IRQ_MSIX;
152         bool shared = false;
153         u16 msix_vec;
154
155         if (desc) {
156                 flags |= PCI_IRQ_AFFINITY;
157                 desc->pre_vectors++; /* virtio config vector */
158         }
159
160         nvectors = 1;
161         for (i = 0; i < nvqs; i++)
162                 if (callbacks[i])
163                         nvectors++;
164
165         /* Try one vector per queue first. */
166         err = pci_alloc_irq_vectors_affinity(vp_dev->pci_dev, nvectors,
167                         nvectors, flags, desc);
168         if (err < 0) {
169                 /* Fallback to one vector for config, one shared for queues. */
170                 shared = true;
171                 err = pci_alloc_irq_vectors(vp_dev->pci_dev, 2, 2,
172                                 PCI_IRQ_MSIX);
173                 if (err < 0)
174                         return err;
175         }
176         if (err < 0)
177                 return err;
178
179         vp_dev->msix_vectors = nvectors;
180         vp_dev->msix_names = kmalloc_array(nvectors,
181                         sizeof(*vp_dev->msix_names), GFP_KERNEL);
182         if (!vp_dev->msix_names)
183                 goto out_free_irq_vectors;
184
185         vp_dev->msix_affinity_masks = kcalloc(nvectors,
186                         sizeof(*vp_dev->msix_affinity_masks), GFP_KERNEL);
187         if (!vp_dev->msix_affinity_masks)
188                 goto out_free_msix_names;
189
190         for (i = 0; i < nvectors; ++i) {
191                 if (!alloc_cpumask_var(&vp_dev->msix_affinity_masks[i],
192                                 GFP_KERNEL))
193                         goto out_free_msix_affinity_masks;
194         }
195
196         /* Set the vector used for configuration */
197         snprintf(vp_dev->msix_names[0], sizeof(*vp_dev->msix_names),
198                  "%s-config", name);
199         err = request_irq(pci_irq_vector(vp_dev->pci_dev, 0), vp_config_changed,
200                         0, vp_dev->msix_names[0], vp_dev);
201         if (err)
202                 goto out_free_msix_affinity_masks;
203
204         /* Verify we had enough resources to assign the vector */
205         if (vp_dev->config_vector(vp_dev, 0) == VIRTIO_MSI_NO_VECTOR) {
206                 err = -EBUSY;
207                 goto out_free_config_irq;
208         }
209
210         vp_dev->msix_vector_map = kmalloc_array(nvqs,
211                         sizeof(*vp_dev->msix_vector_map), GFP_KERNEL);
212         if (!vp_dev->msix_vector_map)
213                 goto out_disable_config_irq;
214
215         allocated_vectors = 1; /* vector 0 is the config interrupt */
216         for (i = 0; i < nvqs; ++i) {
217                 if (!names[i]) {
218                         vqs[i] = NULL;
219                         continue;
220                 }
221
222                 if (callbacks[i])
223                         msix_vec = allocated_vectors;
224                 else
225                         msix_vec = VIRTIO_MSI_NO_VECTOR;
226
227                 vqs[i] = vp_dev->setup_vq(vp_dev, i, callbacks[i], names[i],
228                                 msix_vec);
229                 if (IS_ERR(vqs[i])) {
230                         err = PTR_ERR(vqs[i]);
231                         goto out_remove_vqs;
232                 }
233
234                 if (msix_vec == VIRTIO_MSI_NO_VECTOR) {
235                         vp_dev->msix_vector_map[i] = VIRTIO_MSI_NO_VECTOR;
236                         continue;
237                 }
238
239                 snprintf(vp_dev->msix_names[i + 1],
240                          sizeof(*vp_dev->msix_names), "%s-%s",
241                          dev_name(&vp_dev->vdev.dev), names[i]);
242                 err = request_irq(pci_irq_vector(vp_dev->pci_dev, msix_vec),
243                                   vring_interrupt, IRQF_SHARED,
244                                   vp_dev->msix_names[i + 1], vqs[i]);
245                 if (err) {
246                         /* don't free this irq on error */
247                         vp_dev->msix_vector_map[i] = VIRTIO_MSI_NO_VECTOR;
248                         goto out_remove_vqs;
249                 }
250                 vp_dev->msix_vector_map[i] = msix_vec;
251
252                 /*
253                  * Use a different vector for each queue if they are available,
254                  * else share the same vector for all VQs.
255                  */
256                 if (!shared)
257                         allocated_vectors++;
258         }
259
260         return 0;
261
262 out_remove_vqs:
263         vp_remove_vqs(vdev);
264         kfree(vp_dev->msix_vector_map);
265 out_disable_config_irq:
266         vp_dev->config_vector(vp_dev, VIRTIO_MSI_NO_VECTOR);
267 out_free_config_irq:
268         free_irq(pci_irq_vector(vp_dev->pci_dev, 0), vp_dev);
269 out_free_msix_affinity_masks:
270         for (i = 0; i < nvectors; i++) {
271                 if (vp_dev->msix_affinity_masks[i])
272                         free_cpumask_var(vp_dev->msix_affinity_masks[i]);
273         }
274         kfree(vp_dev->msix_affinity_masks);
275 out_free_msix_names:
276         kfree(vp_dev->msix_names);
277 out_free_irq_vectors:
278         pci_free_irq_vectors(vp_dev->pci_dev);
279         return err;
280 }
281
282 static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
283                 struct virtqueue *vqs[], vq_callback_t *callbacks[],
284                 const char * const names[])
285 {
286         struct virtio_pci_device *vp_dev = to_vp_device(vdev);
287         int i, err;
288
289         err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED,
290                         dev_name(&vdev->dev), vp_dev);
291         if (err)
292                 return err;
293
294         for (i = 0; i < nvqs; ++i) {
295                 if (!names[i]) {
296                         vqs[i] = NULL;
297                         continue;
298                 }
299                 vqs[i] = vp_dev->setup_vq(vp_dev, i, callbacks[i], names[i],
300                                 VIRTIO_MSI_NO_VECTOR);
301                 if (IS_ERR(vqs[i])) {
302                         err = PTR_ERR(vqs[i]);
303                         goto out_remove_vqs;
304                 }
305         }
306
307         return 0;
308
309 out_remove_vqs:
310         vp_remove_vqs(vdev);
311         free_irq(pci_irq_vector(vp_dev->pci_dev, 0), vp_dev);
312         return err;
313 }
314
315 /* the config->find_vqs() implementation */
316 int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
317                 struct virtqueue *vqs[], vq_callback_t *callbacks[],
318                 const char * const names[], struct irq_affinity *desc)
319 {
320         int err;
321
322         err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, desc);
323         if (!err)
324                 return 0;
325         return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names);
326 }
327
328 const char *vp_bus_name(struct virtio_device *vdev)
329 {
330         struct virtio_pci_device *vp_dev = to_vp_device(vdev);
331
332         return pci_name(vp_dev->pci_dev);
333 }
334
335 /* Setup the affinity for a virtqueue:
336  * - force the affinity for per vq vector
337  * - OR over all affinities for shared MSI
338  * - ignore the affinity request if we're using INTX
339  */
340 int vp_set_vq_affinity(struct virtqueue *vq, int cpu)
341 {
342         struct virtio_device *vdev = vq->vdev;
343         struct virtio_pci_device *vp_dev = to_vp_device(vdev);
344
345         if (!vq->callback)
346                 return -EINVAL;
347
348         if (vp_dev->pci_dev->msix_enabled) {
349                 int vec = vp_dev->msix_vector_map[vq->index];
350                 struct cpumask *mask = vp_dev->msix_affinity_masks[vec];
351                 unsigned int irq = pci_irq_vector(vp_dev->pci_dev, vec);
352
353                 if (cpu == -1)
354                         irq_set_affinity_hint(irq, NULL);
355                 else {
356                         cpumask_clear(mask);
357                         cpumask_set_cpu(cpu, mask);
358                         irq_set_affinity_hint(irq, mask);
359                 }
360         }
361         return 0;
362 }
363
364 #ifdef CONFIG_PM_SLEEP
365 static int virtio_pci_freeze(struct device *dev)
366 {
367         struct pci_dev *pci_dev = to_pci_dev(dev);
368         struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
369         int ret;
370
371         ret = virtio_device_freeze(&vp_dev->vdev);
372
373         if (!ret)
374                 pci_disable_device(pci_dev);
375         return ret;
376 }
377
378 static int virtio_pci_restore(struct device *dev)
379 {
380         struct pci_dev *pci_dev = to_pci_dev(dev);
381         struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
382         int ret;
383
384         ret = pci_enable_device(pci_dev);
385         if (ret)
386                 return ret;
387
388         pci_set_master(pci_dev);
389         return virtio_device_restore(&vp_dev->vdev);
390 }
391
392 static const struct dev_pm_ops virtio_pci_pm_ops = {
393         SET_SYSTEM_SLEEP_PM_OPS(virtio_pci_freeze, virtio_pci_restore)
394 };
395 #endif
396
397
398 /* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */
399 static const struct pci_device_id virtio_pci_id_table[] = {
400         { PCI_DEVICE(PCI_VENDOR_ID_REDHAT_QUMRANET, PCI_ANY_ID) },
401         { 0 }
402 };
403
404 MODULE_DEVICE_TABLE(pci, virtio_pci_id_table);
405
406 static void virtio_pci_release_dev(struct device *_d)
407 {
408         struct virtio_device *vdev = dev_to_virtio(_d);
409         struct virtio_pci_device *vp_dev = to_vp_device(vdev);
410
411         /* As struct device is a kobject, it's not safe to
412          * free the memory (including the reference counter itself)
413          * until it's release callback. */
414         kfree(vp_dev);
415 }
416
417 static int virtio_pci_probe(struct pci_dev *pci_dev,
418                             const struct pci_device_id *id)
419 {
420         struct virtio_pci_device *vp_dev;
421         int rc;
422
423         /* allocate our structure and fill it out */
424         vp_dev = kzalloc(sizeof(struct virtio_pci_device), GFP_KERNEL);
425         if (!vp_dev)
426                 return -ENOMEM;
427
428         pci_set_drvdata(pci_dev, vp_dev);
429         vp_dev->vdev.dev.parent = &pci_dev->dev;
430         vp_dev->vdev.dev.release = virtio_pci_release_dev;
431         vp_dev->pci_dev = pci_dev;
432
433         /* enable the device */
434         rc = pci_enable_device(pci_dev);
435         if (rc)
436                 goto err_enable_device;
437
438         if (force_legacy) {
439                 rc = virtio_pci_legacy_probe(vp_dev);
440                 /* Also try modern mode if we can't map BAR0 (no IO space). */
441                 if (rc == -ENODEV || rc == -ENOMEM)
442                         rc = virtio_pci_modern_probe(vp_dev);
443                 if (rc)
444                         goto err_probe;
445         } else {
446                 rc = virtio_pci_modern_probe(vp_dev);
447                 if (rc == -ENODEV)
448                         rc = virtio_pci_legacy_probe(vp_dev);
449                 if (rc)
450                         goto err_probe;
451         }
452
453         pci_set_master(pci_dev);
454
455         rc = register_virtio_device(&vp_dev->vdev);
456         if (rc)
457                 goto err_register;
458
459         return 0;
460
461 err_register:
462         if (vp_dev->ioaddr)
463              virtio_pci_legacy_remove(vp_dev);
464         else
465              virtio_pci_modern_remove(vp_dev);
466 err_probe:
467         pci_disable_device(pci_dev);
468 err_enable_device:
469         kfree(vp_dev);
470         return rc;
471 }
472
473 static void virtio_pci_remove(struct pci_dev *pci_dev)
474 {
475         struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
476         struct device *dev = get_device(&vp_dev->vdev.dev);
477
478         unregister_virtio_device(&vp_dev->vdev);
479
480         if (vp_dev->ioaddr)
481                 virtio_pci_legacy_remove(vp_dev);
482         else
483                 virtio_pci_modern_remove(vp_dev);
484
485         pci_disable_device(pci_dev);
486         put_device(dev);
487 }
488
489 static struct pci_driver virtio_pci_driver = {
490         .name           = "virtio-pci",
491         .id_table       = virtio_pci_id_table,
492         .probe          = virtio_pci_probe,
493         .remove         = virtio_pci_remove,
494 #ifdef CONFIG_PM_SLEEP
495         .driver.pm      = &virtio_pci_pm_ops,
496 #endif
497 };
498
499 module_pci_driver(virtio_pci_driver);
500
501 MODULE_AUTHOR("Anthony Liguori <aliguori@us.ibm.com>");
502 MODULE_DESCRIPTION("virtio-pci");
503 MODULE_LICENSE("GPL");
504 MODULE_VERSION("1");