Lines Matching +full:virtio +full:- +full:pci
1 // SPDX-License-Identifier: GPL-2.0
7 #include <linux/pci.h>
8 #include <linux/virtio.h>
14 #include <linux/virtio-uml.h>
20 #include "virt-pci.h"
25 /* for MSI-X we have a 32-bit payload */
59 if (!test_and_set_bit(i, dev->used_bufs)) in virtio_pcidev_get_buf()
71 if (buf == &dev->bufs[VIRTIO_PCIDEV_WRITE_BUFS]) { in virtio_pcidev_free_buf()
72 kfree(dev->extra_ptrs[VIRTIO_PCIDEV_WRITE_BUFS]); in virtio_pcidev_free_buf()
73 dev->extra_ptrs[VIRTIO_PCIDEV_WRITE_BUFS] = NULL; in virtio_pcidev_free_buf()
78 if (buf == &dev->bufs[i]) { in virtio_pcidev_free_buf()
79 kfree(dev->extra_ptrs[i]); in virtio_pcidev_free_buf()
80 dev->extra_ptrs[i] = NULL; in virtio_pcidev_free_buf()
81 WARN_ON(!test_and_clear_bit(i, dev->used_bufs)); in virtio_pcidev_free_buf()
109 return -EINVAL; in virtio_pcidev_send_cmd()
111 switch (cmd->op) { in virtio_pcidev_send_cmd()
115 /* in PCI, writes are posted, so don't wait */ in virtio_pcidev_send_cmd()
125 out && out_size <= sizeof(buf->data); in virtio_pcidev_send_cmd()
128 buf = &dev->bufs[buf_idx]; in virtio_pcidev_send_cmd()
131 if (posted && extra && extra_size > sizeof(buf) - cmd_size) { in virtio_pcidev_send_cmd()
132 dev->extra_ptrs[buf_idx] = kmemdup(extra, extra_size, in virtio_pcidev_send_cmd()
135 if (!dev->extra_ptrs[buf_idx]) { in virtio_pcidev_send_cmd()
137 return -ENOMEM; in virtio_pcidev_send_cmd()
139 extra = dev->extra_ptrs[buf_idx]; in virtio_pcidev_send_cmd()
140 } else if (extra && extra_size <= sizeof(buf) - cmd_size) { in virtio_pcidev_send_cmd()
155 sg_init_one(&in_sg, buf->data, out_size); in virtio_pcidev_send_cmd()
159 /* add to internal virtio queue */ in virtio_pcidev_send_cmd()
160 ret = virtqueue_add_sgs(dev->cmd_vq, sgs_list, in virtio_pcidev_send_cmd()
170 virtqueue_kick(dev->cmd_vq); in virtio_pcidev_send_cmd()
175 set_bit(UM_PCI_STAT_WAITING, &dev->status); in virtio_pcidev_send_cmd()
176 virtqueue_kick(dev->cmd_vq); in virtio_pcidev_send_cmd()
180 void *completed = virtqueue_get_buf(dev->cmd_vq, &len); in virtio_pcidev_send_cmd()
188 if (WARN_ONCE(virtqueue_is_broken(dev->cmd_vq) || in virtio_pcidev_send_cmd()
190 "um virt-pci delay: %d", delay_count)) { in virtio_pcidev_send_cmd()
191 ret = -EIO; in virtio_pcidev_send_cmd()
196 clear_bit(UM_PCI_STAT_WAITING, &dev->status); in virtio_pcidev_send_cmd()
199 memcpy(out, buf->data, out_size); in virtio_pcidev_send_cmd()
247 /* maximum size - we may only use parts of it */ in virtio_pcidev_cfgspace_write()
298 /* 8 is maximum size - we may only use parts of it */ in virtio_pcidev_bar_read()
339 /* maximum size - we may only use parts of it */ in virtio_pcidev_bar_write()
407 struct virtio_device *vdev = vq->vdev; in virtio_pcidev_handle_irq_message()
408 struct virtio_pcidev_device *dev = vdev->priv; in virtio_pcidev_handle_irq_message()
410 if (!dev->pdev.irq) in virtio_pcidev_handle_irq_message()
415 switch (msg->op) { in virtio_pcidev_handle_irq_message()
417 generic_handle_irq(dev->pdev.irq); in virtio_pcidev_handle_irq_message()
421 if (msg->size == sizeof(u32)) in virtio_pcidev_handle_irq_message()
422 generic_handle_irq(le32_to_cpup((void *)msg->data)); in virtio_pcidev_handle_irq_message()
424 generic_handle_irq(le16_to_cpup((void *)msg->data)); in virtio_pcidev_handle_irq_message()
427 /* nothing to do - we already woke up due to the message */ in virtio_pcidev_handle_irq_message()
430 dev_err(&vdev->dev, "unexpected virt-pci message %d\n", msg->op); in virtio_pcidev_handle_irq_message()
437 struct virtio_device *vdev = vq->vdev; in virtio_pcidev_cmd_vq_cb()
438 struct virtio_pcidev_device *dev = vdev->priv; in virtio_pcidev_cmd_vq_cb()
442 if (test_bit(UM_PCI_STAT_WAITING, &dev->status)) in virtio_pcidev_cmd_vq_cb()
472 err = virtio_find_vqs(dev->vdev, 2, vqs, vqs_info, NULL); in virtio_pcidev_init_vqs()
476 dev->cmd_vq = vqs[0]; in virtio_pcidev_init_vqs()
477 dev->irq_vq = vqs[1]; in virtio_pcidev_init_vqs()
479 virtio_device_ready(dev->vdev); in virtio_pcidev_init_vqs()
485 virtio_pcidev_irq_vq_addbuf(dev->irq_vq, msg, false); in virtio_pcidev_init_vqs()
488 virtqueue_kick(dev->irq_vq); in virtio_pcidev_init_vqs()
496 um_pci_platform_device_unregister(&dev->pdev); in __virtio_pcidev_virtio_platform_remove()
499 vdev->config->del_vqs(vdev); in __virtio_pcidev_virtio_platform_remove()
509 dev->platform = true; in virtio_pcidev_virtio_platform_probe()
515 err = um_pci_platform_device_register(&dev->pdev); in virtio_pcidev_virtio_platform_probe()
519 err = of_platform_default_populate(vdev->dev.of_node, NULL, &vdev->dev); in virtio_pcidev_virtio_platform_probe()
526 um_pci_platform_device_unregister(&dev->pdev); in virtio_pcidev_virtio_platform_probe()
529 vdev->config->del_vqs(vdev); in virtio_pcidev_virtio_platform_probe()
542 return -ENOMEM; in virtio_pcidev_virtio_probe()
544 dev->vdev = vdev; in virtio_pcidev_virtio_probe()
545 vdev->priv = dev; in virtio_pcidev_virtio_probe()
547 dev->pdev.ops = &virtio_pcidev_um_pci_ops; in virtio_pcidev_virtio_probe()
549 if (of_device_is_compatible(vdev->dev.of_node, "simple-bus")) in virtio_pcidev_virtio_probe()
556 err = um_pci_device_register(&dev->pdev); in virtio_pcidev_virtio_probe()
560 device_set_wakeup_enable(&vdev->dev, true); in virtio_pcidev_virtio_probe()
563 * In order to do suspend-resume properly, don't allow VQs in virtio_pcidev_virtio_probe()
572 vdev->config->del_vqs(vdev); in virtio_pcidev_virtio_probe()
580 struct virtio_pcidev_device *dev = vdev->priv; in virtio_pcidev_virtio_remove()
582 if (dev->platform) { in virtio_pcidev_virtio_remove()
583 of_platform_depopulate(&vdev->dev); in virtio_pcidev_virtio_remove()
588 device_set_wakeup_enable(&vdev->dev, false); in virtio_pcidev_virtio_remove()
590 um_pci_device_unregister(&dev->pdev); in virtio_pcidev_virtio_remove()
594 dev->cmd_vq = NULL; in virtio_pcidev_virtio_remove()
595 dev->irq_vq = NULL; in virtio_pcidev_virtio_remove()
596 vdev->config->del_vqs(vdev); in virtio_pcidev_virtio_remove()
605 MODULE_DEVICE_TABLE(virtio, id_table);
608 .driver.name = "virtio-pci",
617 "No virtio device ID configured for PCI - no PCI support\n")) in virtio_pcidev_init()