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");
34 return index == vp_dev->admin_vq.vq_index;
43 if (vp_dev->intx_enabled)
44 synchronize_irq(vp_dev->pci_dev->irq);
46 for (i = 0; i < vp_dev->msix_vectors; ++i)
47 synchronize_irq(pci_irq_vector(vp_dev->pci_dev, i));
55 iowrite16(vq->index, (void __iomem *)vq->priv);
66 spin_lock_irqsave(&vp_dev->lock, flags);
67 list_for_each_entry(info, &vp_dev->slow_virtqueues, node)
68 vring_interrupt(irq, info->vq);
69 spin_unlock_irqrestore(&vp_dev->lock, flags);
77 virtio_config_changed(&vp_dev->vdev);
90 spin_lock_irqsave(&vp_dev->lock, flags);
91 list_for_each_entry(info, &vp_dev->virtqueues, node) {
92 if (vring_interrupt(irq, info->vq) == IRQ_HANDLED)
95 spin_unlock_irqrestore(&vp_dev->lock, flags);
113 isr = ioread8(vp_dev->isr);
130 const char *name = dev_name(&vp_dev->vdev.dev);
133 int err = -ENOMEM;
135 vp_dev->msix_vectors = nvectors;
137 vp_dev->msix_names = kmalloc_array(nvectors,
138 sizeof(*vp_dev->msix_names),
140 if (!vp_dev->msix_names)
142 vp_dev->msix_affinity_masks
143 = kcalloc(nvectors, sizeof(*vp_dev->msix_affinity_masks),
145 if (!vp_dev->msix_affinity_masks)
148 if (!alloc_cpumask_var(&vp_dev->msix_affinity_masks[i],
157 desc->pre_vectors++; /* virtio config vector */
160 err = pci_alloc_irq_vectors_affinity(vp_dev->pci_dev, nvectors,
164 vp_dev->msix_enabled = 1;
167 v = vp_dev->msix_used_vectors;
168 snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names,
169 "%s-config", name);
170 err = request_irq(pci_irq_vector(vp_dev->pci_dev, v),
171 vp_config_changed, 0, vp_dev->msix_names[v],
175 ++vp_dev->msix_used_vectors;
177 v = vp_dev->config_vector(vp_dev, v);
180 err = -EBUSY;
186 v = vp_dev->msix_used_vectors;
187 snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names,
188 "%s-virtqueues", name);
189 err = request_irq(pci_irq_vector(vp_dev->pci_dev, v),
190 vp_vring_interrupt, 0, vp_dev->msix_names[v],
194 ++vp_dev->msix_used_vectors;
220 return ERR_PTR(-ENOMEM);
222 vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, ctx,
227 info->vq = vq;
229 spin_lock_irqsave(&vp_dev->lock, flags);
231 list_add(&info->node, &vp_dev->virtqueues);
233 list_add(&info->node, &vp_dev->slow_virtqueues);
234 spin_unlock_irqrestore(&vp_dev->lock, flags);
236 INIT_LIST_HEAD(&info->node);
249 struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
253 * If it fails during re-enable reset vq. This way we won't rejoin
254 * info->node to the queue. Prevent unexpected irqs.
256 if (!vq->reset) {
257 spin_lock_irqsave(&vp_dev->lock, flags);
258 list_del(&info->node);
259 spin_unlock_irqrestore(&vp_dev->lock, flags);
262 vp_dev->del_vq(info);
266 /* the config->del_vqs() implementation */
274 list_for_each_entry_safe(vq, n, &vdev->vqs, list) {
275 info = vp_is_avq(vdev, vq->index) ? vp_dev->admin_vq.info :
276 vp_dev->vqs[vq->index];
278 if (vp_dev->per_vq_vectors) {
279 int v = info->msix_vector;
282 int irq = pci_irq_vector(vp_dev->pci_dev, v);
290 vp_dev->per_vq_vectors = false;
292 if (vp_dev->intx_enabled) {
293 free_irq(vp_dev->pci_dev->irq, vp_dev);
294 vp_dev->intx_enabled = 0;
297 for (i = 0; i < vp_dev->msix_used_vectors; ++i)
298 free_irq(pci_irq_vector(vp_dev->pci_dev, i), vp_dev);
300 if (vp_dev->msix_affinity_masks) {
301 for (i = 0; i < vp_dev->msix_vectors; i++)
302 free_cpumask_var(vp_dev->msix_affinity_masks[i]);
305 if (vp_dev->msix_enabled) {
307 vp_dev->config_vector(vp_dev, VIRTIO_MSI_NO_VECTOR);
309 pci_free_irq_vectors(vp_dev->pci_dev);
310 vp_dev->msix_enabled = 0;
313 vp_dev->msix_vectors = 0;
314 vp_dev->msix_used_vectors = 0;
315 kfree(vp_dev->msix_names);
316 vp_dev->msix_names = NULL;
317 kfree(vp_dev->msix_affinity_masks);
318 vp_dev->msix_affinity_masks = NULL;
319 kfree(vp_dev->vqs);
320 vp_dev->vqs = NULL;
362 /* allocate per-vq irq if available and necessary */
363 snprintf(vp_dev->msix_names[msix_vec], sizeof(*vp_dev->msix_names),
364 "%s-%s", dev_name(&vp_dev->vdev.dev), name);
365 err = request_irq(pci_irq_vector(vp_dev->pci_dev, msix_vec),
367 vp_dev->msix_names[msix_vec], vq);
383 struct virtio_pci_admin_vq *avq = &vp_dev->admin_vq;
390 vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
391 if (!vp_dev->vqs)
392 return -ENOMEM;
394 if (vp_dev->avq_index) {
395 err = vp_dev->avq_index(vdev, &avq->vq_index, &avq_num);
407 if (vqi->name && vqi->callback)
421 vp_dev->per_vq_vectors = per_vq_vectors;
422 allocated_vectors = vp_dev->msix_used_vectors;
425 if (!vqi->name) {
429 vqs[i] = vp_find_one_vq_msix(vdev, queue_idx++, vqi->callback,
430 vqi->name, vqi->ctx, false,
432 &vp_dev->vqs[i]);
441 sprintf(avq->name, "avq.%u", avq->vq_index);
442 vq = vp_find_one_vq_msix(vdev, avq->vq_index, vp_modern_avq_done,
443 avq->name, false, true, &allocated_vectors,
444 vector_policy, &vp_dev->admin_vq.info);
462 struct virtio_pci_admin_vq *avq = &vp_dev->admin_vq;
467 vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
468 if (!vp_dev->vqs)
469 return -ENOMEM;
471 if (vp_dev->avq_index) {
472 err = vp_dev->avq_index(vdev, &avq->vq_index, &avq_num);
477 err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, IRQF_SHARED,
478 dev_name(&vdev->dev), vp_dev);
482 vp_dev->intx_enabled = 1;
483 vp_dev->per_vq_vectors = false;
487 if (!vqi->name) {
491 vqs[i] = vp_setup_vq(vdev, queue_idx++, vqi->callback,
492 vqi->name, vqi->ctx,
493 VIRTIO_MSI_NO_VECTOR, &vp_dev->vqs[i]);
502 sprintf(avq->name, "avq.%u", avq->vq_index);
503 vq = vp_setup_vq(vdev, queue_idx++, vp_modern_avq_done, avq->name,
505 &vp_dev->admin_vq.info);
517 /* the config->find_vqs() implementation */
524 /* Try MSI-X with one vector per queue. */
529 /* Fallback: MSI-X with one shared vector for config and
536 /* Fallback: MSI-X with one vector for config, one shared for queues. */
542 if (!(to_vp_device(vdev)->pci_dev->irq))
552 return pci_name(vp_dev->pci_dev);
556 * - force the affinity for per vq vector
557 * - OR over all affinities for shared MSI
558 * - ignore the affinity request if we're using INTX
562 struct virtio_device *vdev = vq->vdev;
564 struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index];
568 if (!vq->callback)
569 return -EINVAL;
571 if (vp_dev->msix_enabled) {
572 mask = vp_dev->msix_affinity_masks[info->msix_vector];
573 irq = pci_irq_vector(vp_dev->pci_dev, info->msix_vector);
588 if (!vp_dev->per_vq_vectors ||
589 vp_dev->vqs[index]->msix_vector == VIRTIO_MSI_NO_VECTOR ||
590 vp_is_slow_path_vector(vp_dev->vqs[index]->msix_vector))
593 return pci_irq_get_affinity(vp_dev->pci_dev,
594 vp_dev->vqs[index]->msix_vector);
604 ret = virtio_device_freeze(&vp_dev->vdev);
622 return virtio_device_restore(&vp_dev->vdev);
630 if (!pci_dev->pm_cap)
633 pci_read_config_word(pci_dev, pci_dev->pm_cap + PCI_PM_CTRL, &pmcsr);
669 MODULE_DEVICE_TABLE(pci, virtio_pci_id_table);
691 return -ENOMEM;
694 vp_dev->vdev.dev.parent = &pci_dev->dev;
695 vp_dev->vdev.dev.release = virtio_pci_release_dev;
696 vp_dev->pci_dev = pci_dev;
697 INIT_LIST_HEAD(&vp_dev->virtqueues);
698 INIT_LIST_HEAD(&vp_dev->slow_virtqueues);
699 spin_lock_init(&vp_dev->lock);
709 if (rc == -ENODEV || rc == -ENOMEM)
715 if (rc == -ENODEV)
723 rc = register_virtio_device(&vp_dev->vdev);
731 if (vp_dev->is_legacy)
739 put_device(&vp_dev->vdev.dev);
748 struct device *dev = get_device(&vp_dev->vdev.dev);
751 * Device is marked broken on surprise removal so that virtio upper
755 virtio_break_device(&vp_dev->vdev);
759 unregister_virtio_device(&vp_dev->vdev);
761 if (vp_dev->is_legacy)
773 struct virtio_device *vdev = &vp_dev->vdev;
776 if (!(vdev->config->get_status(vdev) & VIRTIO_CONFIG_S_DRIVER_OK))
777 return -EBUSY;
780 return -EINVAL;
783 return -EPERM;
802 ret = virtio_device_reset_prepare(&vp_dev->vdev);
804 if (ret != -EOPNOTSUPP)
805 dev_warn(&pci_dev->dev, "Reset prepare failure: %d",
825 ret = virtio_device_reset_done(&vp_dev->vdev);
828 if (ret && ret != -EOPNOTSUPP)
829 dev_warn(&pci_dev->dev, "Reset done failure: %d", ret);
838 .name = "virtio-pci",
857 return &pf_vp_dev->vdev;
863 MODULE_DESCRIPTION("virtio-pci");