Lines Matching +full:virtio +full:- +full:pci

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Virtio PCI driver - common functionality for all device versions
5 * This module allows virtio devices to be used over a virtual PCI device.
24 "Force legacy mode for transitional virtio 1 devices");
33 if (vp_dev->intx_enabled) in vp_synchronize_vectors()
34 synchronize_irq(vp_dev->pci_dev->irq); in vp_synchronize_vectors()
36 for (i = 0; i < vp_dev->msix_vectors; ++i) in vp_synchronize_vectors()
37 synchronize_irq(pci_irq_vector(vp_dev->pci_dev, i)); in vp_synchronize_vectors()
45 iowrite16(vq->index, (void __iomem *)vq->priv); in vp_notify()
54 virtio_config_changed(&vp_dev->vdev); in vp_config_changed()
66 spin_lock_irqsave(&vp_dev->lock, flags); in vp_vring_interrupt()
67 list_for_each_entry(info, &vp_dev->virtqueues, node) { in vp_vring_interrupt()
68 if (vring_interrupt(irq, info->vq) == IRQ_HANDLED) in vp_vring_interrupt()
71 spin_unlock_irqrestore(&vp_dev->lock, flags); in vp_vring_interrupt()
89 isr = ioread8(vp_dev->isr); in vp_interrupt()
106 const char *name = dev_name(&vp_dev->vdev.dev); in vp_request_msix_vectors()
109 int err = -ENOMEM; in vp_request_msix_vectors()
111 vp_dev->msix_vectors = nvectors; in vp_request_msix_vectors()
113 vp_dev->msix_names = kmalloc_array(nvectors, in vp_request_msix_vectors()
114 sizeof(*vp_dev->msix_names), in vp_request_msix_vectors()
116 if (!vp_dev->msix_names) in vp_request_msix_vectors()
118 vp_dev->msix_affinity_masks in vp_request_msix_vectors()
119 = kcalloc(nvectors, sizeof(*vp_dev->msix_affinity_masks), in vp_request_msix_vectors()
121 if (!vp_dev->msix_affinity_masks) in vp_request_msix_vectors()
124 if (!alloc_cpumask_var(&vp_dev->msix_affinity_masks[i], in vp_request_msix_vectors()
130 desc->pre_vectors++; /* virtio config vector */ in vp_request_msix_vectors()
133 err = pci_alloc_irq_vectors_affinity(vp_dev->pci_dev, nvectors, in vp_request_msix_vectors()
137 vp_dev->msix_enabled = 1; in vp_request_msix_vectors()
140 v = vp_dev->msix_used_vectors; in vp_request_msix_vectors()
141 snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names, in vp_request_msix_vectors()
142 "%s-config", name); in vp_request_msix_vectors()
143 err = request_irq(pci_irq_vector(vp_dev->pci_dev, v), in vp_request_msix_vectors()
144 vp_config_changed, 0, vp_dev->msix_names[v], in vp_request_msix_vectors()
148 ++vp_dev->msix_used_vectors; in vp_request_msix_vectors()
150 v = vp_dev->config_vector(vp_dev, v); in vp_request_msix_vectors()
153 err = -EBUSY; in vp_request_msix_vectors()
159 v = vp_dev->msix_used_vectors; in vp_request_msix_vectors()
160 snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names, in vp_request_msix_vectors()
161 "%s-virtqueues", name); in vp_request_msix_vectors()
162 err = request_irq(pci_irq_vector(vp_dev->pci_dev, v), in vp_request_msix_vectors()
163 vp_vring_interrupt, 0, vp_dev->msix_names[v], in vp_request_msix_vectors()
167 ++vp_dev->msix_used_vectors; in vp_request_msix_vectors()
187 return ERR_PTR(-ENOMEM); in vp_setup_vq()
189 vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, ctx, in vp_setup_vq()
194 info->vq = vq; in vp_setup_vq()
196 spin_lock_irqsave(&vp_dev->lock, flags); in vp_setup_vq()
197 list_add(&info->node, &vp_dev->virtqueues); in vp_setup_vq()
198 spin_unlock_irqrestore(&vp_dev->lock, flags); in vp_setup_vq()
200 INIT_LIST_HEAD(&info->node); in vp_setup_vq()
203 vp_dev->vqs[index] = info; in vp_setup_vq()
213 struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); in vp_del_vq()
214 struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index]; in vp_del_vq()
218 * If it fails during re-enable reset vq. This way we won't rejoin in vp_del_vq()
219 * info->node to the queue. Prevent unexpected irqs. in vp_del_vq()
221 if (!vq->reset) { in vp_del_vq()
222 spin_lock_irqsave(&vp_dev->lock, flags); in vp_del_vq()
223 list_del(&info->node); in vp_del_vq()
224 spin_unlock_irqrestore(&vp_dev->lock, flags); in vp_del_vq()
227 vp_dev->del_vq(info); in vp_del_vq()
231 /* the config->del_vqs() implementation */
238 list_for_each_entry_safe(vq, n, &vdev->vqs, list) { in vp_del_vqs()
239 if (vp_dev->per_vq_vectors) { in vp_del_vqs()
240 int v = vp_dev->vqs[vq->index]->msix_vector; in vp_del_vqs()
243 int irq = pci_irq_vector(vp_dev->pci_dev, v); in vp_del_vqs()
251 vp_dev->per_vq_vectors = false; in vp_del_vqs()
253 if (vp_dev->intx_enabled) { in vp_del_vqs()
254 free_irq(vp_dev->pci_dev->irq, vp_dev); in vp_del_vqs()
255 vp_dev->intx_enabled = 0; in vp_del_vqs()
258 for (i = 0; i < vp_dev->msix_used_vectors; ++i) in vp_del_vqs()
259 free_irq(pci_irq_vector(vp_dev->pci_dev, i), vp_dev); in vp_del_vqs()
261 if (vp_dev->msix_affinity_masks) { in vp_del_vqs()
262 for (i = 0; i < vp_dev->msix_vectors; i++) in vp_del_vqs()
263 free_cpumask_var(vp_dev->msix_affinity_masks[i]); in vp_del_vqs()
266 if (vp_dev->msix_enabled) { in vp_del_vqs()
268 vp_dev->config_vector(vp_dev, VIRTIO_MSI_NO_VECTOR); in vp_del_vqs()
270 pci_free_irq_vectors(vp_dev->pci_dev); in vp_del_vqs()
271 vp_dev->msix_enabled = 0; in vp_del_vqs()
274 vp_dev->msix_vectors = 0; in vp_del_vqs()
275 vp_dev->msix_used_vectors = 0; in vp_del_vqs()
276 kfree(vp_dev->msix_names); in vp_del_vqs()
277 vp_dev->msix_names = NULL; in vp_del_vqs()
278 kfree(vp_dev->msix_affinity_masks); in vp_del_vqs()
279 vp_dev->msix_affinity_masks = NULL; in vp_del_vqs()
280 kfree(vp_dev->vqs); in vp_del_vqs()
281 vp_dev->vqs = NULL; in vp_del_vqs()
294 vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL); in vp_find_vqs_msix()
295 if (!vp_dev->vqs) in vp_find_vqs_msix()
296 return -ENOMEM; in vp_find_vqs_msix()
314 vp_dev->per_vq_vectors = per_vq_vectors; in vp_find_vqs_msix()
315 allocated_vectors = vp_dev->msix_used_vectors; in vp_find_vqs_msix()
324 else if (vp_dev->per_vq_vectors) in vp_find_vqs_msix()
336 if (!vp_dev->per_vq_vectors || msix_vec == VIRTIO_MSI_NO_VECTOR) in vp_find_vqs_msix()
339 /* allocate per-vq irq if available and necessary */ in vp_find_vqs_msix()
340 snprintf(vp_dev->msix_names[msix_vec], in vp_find_vqs_msix()
341 sizeof *vp_dev->msix_names, in vp_find_vqs_msix()
342 "%s-%s", in vp_find_vqs_msix()
343 dev_name(&vp_dev->vdev.dev), names[i]); in vp_find_vqs_msix()
344 err = request_irq(pci_irq_vector(vp_dev->pci_dev, msix_vec), in vp_find_vqs_msix()
346 vp_dev->msix_names[msix_vec], in vp_find_vqs_msix()
365 vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL); in vp_find_vqs_intx()
366 if (!vp_dev->vqs) in vp_find_vqs_intx()
367 return -ENOMEM; in vp_find_vqs_intx()
369 err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED, in vp_find_vqs_intx()
370 dev_name(&vdev->dev), vp_dev); in vp_find_vqs_intx()
374 vp_dev->intx_enabled = 1; in vp_find_vqs_intx()
375 vp_dev->per_vq_vectors = false; in vp_find_vqs_intx()
396 /* the config->find_vqs() implementation */
404 /* Try MSI-X with one vector per queue. */ in vp_find_vqs()
408 /* Fallback: MSI-X with one vector for config, one shared for queues. */ in vp_find_vqs()
413 if (!(to_vp_device(vdev)->pci_dev->irq)) in vp_find_vqs()
423 return pci_name(vp_dev->pci_dev); in vp_bus_name()
427 * - force the affinity for per vq vector
428 * - OR over all affinities for shared MSI
429 * - ignore the affinity request if we're using INTX
433 struct virtio_device *vdev = vq->vdev; in vp_set_vq_affinity()
435 struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index]; in vp_set_vq_affinity()
439 if (!vq->callback) in vp_set_vq_affinity()
440 return -EINVAL; in vp_set_vq_affinity()
442 if (vp_dev->msix_enabled) { in vp_set_vq_affinity()
443 mask = vp_dev->msix_affinity_masks[info->msix_vector]; in vp_set_vq_affinity()
444 irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector); in vp_set_vq_affinity()
459 if (!vp_dev->per_vq_vectors || in vp_get_vq_affinity()
460 vp_dev->vqs[index]->msix_vector == VIRTIO_MSI_NO_VECTOR) in vp_get_vq_affinity()
463 return pci_irq_get_affinity(vp_dev->pci_dev, in vp_get_vq_affinity()
464 vp_dev->vqs[index]->msix_vector); in vp_get_vq_affinity()
474 ret = virtio_device_freeze(&vp_dev->vdev); in virtio_pci_freeze()
492 return virtio_device_restore(&vp_dev->vdev); in virtio_pci_restore()
507 MODULE_DEVICE_TABLE(pci, virtio_pci_id_table);
529 return -ENOMEM; in virtio_pci_probe()
532 vp_dev->vdev.dev.parent = &pci_dev->dev; in virtio_pci_probe()
533 vp_dev->vdev.dev.release = virtio_pci_release_dev; in virtio_pci_probe()
534 vp_dev->pci_dev = pci_dev; in virtio_pci_probe()
535 INIT_LIST_HEAD(&vp_dev->virtqueues); in virtio_pci_probe()
536 spin_lock_init(&vp_dev->lock); in virtio_pci_probe()
546 if (rc == -ENODEV || rc == -ENOMEM) in virtio_pci_probe()
552 if (rc == -ENODEV) in virtio_pci_probe()
560 rc = register_virtio_device(&vp_dev->vdev); in virtio_pci_probe()
568 if (vp_dev->is_legacy) in virtio_pci_probe()
576 put_device(&vp_dev->vdev.dev); in virtio_pci_probe()
585 struct device *dev = get_device(&vp_dev->vdev.dev); in virtio_pci_remove()
588 * Device is marked broken on surprise removal so that virtio upper in virtio_pci_remove()
592 virtio_break_device(&vp_dev->vdev); in virtio_pci_remove()
596 unregister_virtio_device(&vp_dev->vdev); in virtio_pci_remove()
598 if (vp_dev->is_legacy) in virtio_pci_remove()
610 struct virtio_device *vdev = &vp_dev->vdev; in virtio_pci_sriov_configure()
613 if (!(vdev->config->get_status(vdev) & VIRTIO_CONFIG_S_DRIVER_OK)) in virtio_pci_sriov_configure()
614 return -EBUSY; in virtio_pci_sriov_configure()
617 return -EINVAL; in virtio_pci_sriov_configure()
620 return -EPERM; in virtio_pci_sriov_configure()
635 .name = "virtio-pci",
648 MODULE_DESCRIPTION("virtio-pci");