138eb4a29SMichael S. Tsirkin /* 2a90fdce9SMichael S. Tsirkin * Virtio PCI driver - legacy device support 338eb4a29SMichael S. Tsirkin * 438eb4a29SMichael S. Tsirkin * This module allows virtio devices to be used over a virtual PCI device. 538eb4a29SMichael S. Tsirkin * This can be used with QEMU based VMMs like KVM or Xen. 638eb4a29SMichael S. Tsirkin * 738eb4a29SMichael S. Tsirkin * Copyright IBM Corp. 2007 8a90fdce9SMichael S. Tsirkin * Copyright Red Hat, Inc. 2014 938eb4a29SMichael S. Tsirkin * 1038eb4a29SMichael S. Tsirkin * Authors: 1138eb4a29SMichael S. Tsirkin * Anthony Liguori <aliguori@us.ibm.com> 12a90fdce9SMichael S. Tsirkin * Rusty Russell <rusty@rustcorp.com.au> 13a90fdce9SMichael S. Tsirkin * Michael S. Tsirkin <mst@redhat.com> 1438eb4a29SMichael S. Tsirkin * 1538eb4a29SMichael S. Tsirkin * This work is licensed under the terms of the GNU GPL, version 2 or later. 1638eb4a29SMichael S. Tsirkin * See the COPYING file in the top-level directory. 1738eb4a29SMichael S. Tsirkin * 1838eb4a29SMichael S. Tsirkin */ 1938eb4a29SMichael S. Tsirkin 205f4c9760SMichael S. Tsirkin #include "virtio_pci_common.h" 2138eb4a29SMichael S. Tsirkin 2238eb4a29SMichael S. Tsirkin /* virtio config->get_features() implementation */ 2338eb4a29SMichael S. Tsirkin static u64 vp_get_features(struct virtio_device *vdev) 2438eb4a29SMichael S. Tsirkin { 2538eb4a29SMichael S. Tsirkin struct virtio_pci_device *vp_dev = to_vp_device(vdev); 2638eb4a29SMichael S. Tsirkin 2738eb4a29SMichael S. Tsirkin /* When someone needs more than 32 feature bits, we'll need to 2838eb4a29SMichael S. Tsirkin * steal a bit to indicate that the rest are somewhere else. */ 2938eb4a29SMichael S. Tsirkin return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES); 3038eb4a29SMichael S. Tsirkin } 3138eb4a29SMichael S. Tsirkin 3238eb4a29SMichael S. Tsirkin /* virtio config->finalize_features() implementation */ 3338eb4a29SMichael S. Tsirkin static int vp_finalize_features(struct virtio_device *vdev) 3438eb4a29SMichael S. Tsirkin { 3538eb4a29SMichael S. Tsirkin struct virtio_pci_device *vp_dev = to_vp_device(vdev); 3638eb4a29SMichael S. Tsirkin 3738eb4a29SMichael S. Tsirkin /* Give virtio_ring a chance to accept features. */ 3838eb4a29SMichael S. Tsirkin vring_transport_features(vdev); 3938eb4a29SMichael S. Tsirkin 4038eb4a29SMichael S. Tsirkin /* Make sure we don't have any features > 32 bits! */ 4138eb4a29SMichael S. Tsirkin BUG_ON((u32)vdev->features != vdev->features); 4238eb4a29SMichael S. Tsirkin 4338eb4a29SMichael S. Tsirkin /* We only support 32 feature bits. */ 4438eb4a29SMichael S. Tsirkin iowrite32(vdev->features, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES); 4538eb4a29SMichael S. Tsirkin 4638eb4a29SMichael S. Tsirkin return 0; 4738eb4a29SMichael S. Tsirkin } 4838eb4a29SMichael S. Tsirkin 4938eb4a29SMichael S. Tsirkin /* virtio config->get() implementation */ 5038eb4a29SMichael S. Tsirkin static void vp_get(struct virtio_device *vdev, unsigned offset, 5138eb4a29SMichael S. Tsirkin void *buf, unsigned len) 5238eb4a29SMichael S. Tsirkin { 5338eb4a29SMichael S. Tsirkin struct virtio_pci_device *vp_dev = to_vp_device(vdev); 5438eb4a29SMichael S. Tsirkin void __iomem *ioaddr = vp_dev->ioaddr + 5538eb4a29SMichael S. Tsirkin VIRTIO_PCI_CONFIG(vp_dev) + offset; 5638eb4a29SMichael S. Tsirkin u8 *ptr = buf; 5738eb4a29SMichael S. Tsirkin int i; 5838eb4a29SMichael S. Tsirkin 5938eb4a29SMichael S. Tsirkin for (i = 0; i < len; i++) 6038eb4a29SMichael S. Tsirkin ptr[i] = ioread8(ioaddr + i); 6138eb4a29SMichael S. Tsirkin } 6238eb4a29SMichael S. Tsirkin 6338eb4a29SMichael S. Tsirkin /* the config->set() implementation. it's symmetric to the config->get() 6438eb4a29SMichael S. Tsirkin * implementation */ 6538eb4a29SMichael S. Tsirkin static void vp_set(struct virtio_device *vdev, unsigned offset, 6638eb4a29SMichael S. Tsirkin const void *buf, unsigned len) 6738eb4a29SMichael S. Tsirkin { 6838eb4a29SMichael S. Tsirkin struct virtio_pci_device *vp_dev = to_vp_device(vdev); 6938eb4a29SMichael S. Tsirkin void __iomem *ioaddr = vp_dev->ioaddr + 7038eb4a29SMichael S. Tsirkin VIRTIO_PCI_CONFIG(vp_dev) + offset; 7138eb4a29SMichael S. Tsirkin const u8 *ptr = buf; 7238eb4a29SMichael S. Tsirkin int i; 7338eb4a29SMichael S. Tsirkin 7438eb4a29SMichael S. Tsirkin for (i = 0; i < len; i++) 7538eb4a29SMichael S. Tsirkin iowrite8(ptr[i], ioaddr + i); 7638eb4a29SMichael S. Tsirkin } 7738eb4a29SMichael S. Tsirkin 7838eb4a29SMichael S. Tsirkin /* config->{get,set}_status() implementations */ 7938eb4a29SMichael S. Tsirkin static u8 vp_get_status(struct virtio_device *vdev) 8038eb4a29SMichael S. Tsirkin { 8138eb4a29SMichael S. Tsirkin struct virtio_pci_device *vp_dev = to_vp_device(vdev); 8238eb4a29SMichael S. Tsirkin return ioread8(vp_dev->ioaddr + VIRTIO_PCI_STATUS); 8338eb4a29SMichael S. Tsirkin } 8438eb4a29SMichael S. Tsirkin 8538eb4a29SMichael S. Tsirkin static void vp_set_status(struct virtio_device *vdev, u8 status) 8638eb4a29SMichael S. Tsirkin { 8738eb4a29SMichael S. Tsirkin struct virtio_pci_device *vp_dev = to_vp_device(vdev); 8838eb4a29SMichael S. Tsirkin /* We should never be setting status to 0. */ 8938eb4a29SMichael S. Tsirkin BUG_ON(status == 0); 9038eb4a29SMichael S. Tsirkin iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS); 9138eb4a29SMichael S. Tsirkin } 9238eb4a29SMichael S. Tsirkin 9338eb4a29SMichael S. Tsirkin static void vp_reset(struct virtio_device *vdev) 9438eb4a29SMichael S. Tsirkin { 9538eb4a29SMichael S. Tsirkin struct virtio_pci_device *vp_dev = to_vp_device(vdev); 9638eb4a29SMichael S. Tsirkin /* 0 status means a reset. */ 9738eb4a29SMichael S. Tsirkin iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS); 9838eb4a29SMichael S. Tsirkin /* Flush out the status write, and flush in device writes, 9938eb4a29SMichael S. Tsirkin * including MSi-X interrupts, if any. */ 10038eb4a29SMichael S. Tsirkin ioread8(vp_dev->ioaddr + VIRTIO_PCI_STATUS); 10138eb4a29SMichael S. Tsirkin /* Flush pending VQ/configuration callbacks. */ 10238eb4a29SMichael S. Tsirkin vp_synchronize_vectors(vdev); 10338eb4a29SMichael S. Tsirkin } 10438eb4a29SMichael S. Tsirkin 10538eb4a29SMichael S. Tsirkin static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector) 10638eb4a29SMichael S. Tsirkin { 10738eb4a29SMichael S. Tsirkin /* Setup the vector used for configuration events */ 10838eb4a29SMichael S. Tsirkin iowrite16(vector, vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); 10938eb4a29SMichael S. Tsirkin /* Verify we had enough resources to assign the vector */ 11038eb4a29SMichael S. Tsirkin /* Will also flush the write out to device */ 11138eb4a29SMichael S. Tsirkin return ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); 11238eb4a29SMichael S. Tsirkin } 11338eb4a29SMichael S. Tsirkin 11438eb4a29SMichael S. Tsirkin static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, 11538eb4a29SMichael S. Tsirkin struct virtio_pci_vq_info *info, 11638eb4a29SMichael S. Tsirkin unsigned index, 11738eb4a29SMichael S. Tsirkin void (*callback)(struct virtqueue *vq), 11838eb4a29SMichael S. Tsirkin const char *name, 11938eb4a29SMichael S. Tsirkin u16 msix_vec) 12038eb4a29SMichael S. Tsirkin { 12138eb4a29SMichael S. Tsirkin struct virtqueue *vq; 12238eb4a29SMichael S. Tsirkin u16 num; 12338eb4a29SMichael S. Tsirkin int err; 12438eb4a29SMichael S. Tsirkin 12538eb4a29SMichael S. Tsirkin /* Select the queue we're interested in */ 12638eb4a29SMichael S. Tsirkin iowrite16(index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); 12738eb4a29SMichael S. Tsirkin 12838eb4a29SMichael S. Tsirkin /* Check if queue is either not available or already active. */ 12938eb4a29SMichael S. Tsirkin num = ioread16(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NUM); 13038eb4a29SMichael S. Tsirkin if (!num || ioread32(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN)) 13138eb4a29SMichael S. Tsirkin return ERR_PTR(-ENOENT); 13238eb4a29SMichael S. Tsirkin 13338eb4a29SMichael S. Tsirkin info->msix_vector = msix_vec; 13438eb4a29SMichael S. Tsirkin 1357a5589b2SAndy Lutomirski /* create the vring */ 1367a5589b2SAndy Lutomirski vq = vring_create_virtqueue(index, num, 1377a5589b2SAndy Lutomirski VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev, 1387a5589b2SAndy Lutomirski true, false, vp_notify, callback, name); 1397a5589b2SAndy Lutomirski if (!vq) 14038eb4a29SMichael S. Tsirkin return ERR_PTR(-ENOMEM); 14138eb4a29SMichael S. Tsirkin 14238eb4a29SMichael S. Tsirkin /* activate the queue */ 1437a5589b2SAndy Lutomirski iowrite32(virtqueue_get_desc_addr(vq) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT, 14438eb4a29SMichael S. Tsirkin vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); 14538eb4a29SMichael S. Tsirkin 14638eb4a29SMichael S. Tsirkin vq->priv = (void __force *)vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY; 14738eb4a29SMichael S. Tsirkin 14838eb4a29SMichael S. Tsirkin if (msix_vec != VIRTIO_MSI_NO_VECTOR) { 14938eb4a29SMichael S. Tsirkin iowrite16(msix_vec, vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); 15038eb4a29SMichael S. Tsirkin msix_vec = ioread16(vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); 15138eb4a29SMichael S. Tsirkin if (msix_vec == VIRTIO_MSI_NO_VECTOR) { 15238eb4a29SMichael S. Tsirkin err = -EBUSY; 1537a5589b2SAndy Lutomirski goto out_deactivate; 15438eb4a29SMichael S. Tsirkin } 15538eb4a29SMichael S. Tsirkin } 15638eb4a29SMichael S. Tsirkin 15738eb4a29SMichael S. Tsirkin return vq; 15838eb4a29SMichael S. Tsirkin 1597a5589b2SAndy Lutomirski out_deactivate: 16038eb4a29SMichael S. Tsirkin iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); 1617a5589b2SAndy Lutomirski vring_del_virtqueue(vq); 16238eb4a29SMichael S. Tsirkin return ERR_PTR(err); 16338eb4a29SMichael S. Tsirkin } 16438eb4a29SMichael S. Tsirkin 16538eb4a29SMichael S. Tsirkin static void del_vq(struct virtio_pci_vq_info *info) 16638eb4a29SMichael S. Tsirkin { 16738eb4a29SMichael S. Tsirkin struct virtqueue *vq = info->vq; 16838eb4a29SMichael S. Tsirkin struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); 16938eb4a29SMichael S. Tsirkin 17038eb4a29SMichael S. Tsirkin iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); 17138eb4a29SMichael S. Tsirkin 17238eb4a29SMichael S. Tsirkin if (vp_dev->msix_enabled) { 17338eb4a29SMichael S. Tsirkin iowrite16(VIRTIO_MSI_NO_VECTOR, 17438eb4a29SMichael S. Tsirkin vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); 17538eb4a29SMichael S. Tsirkin /* Flush the write out to device */ 17638eb4a29SMichael S. Tsirkin ioread8(vp_dev->ioaddr + VIRTIO_PCI_ISR); 17738eb4a29SMichael S. Tsirkin } 17838eb4a29SMichael S. Tsirkin 17938eb4a29SMichael S. Tsirkin /* Select and deactivate the queue */ 18038eb4a29SMichael S. Tsirkin iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); 18138eb4a29SMichael S. Tsirkin 1827a5589b2SAndy Lutomirski vring_del_virtqueue(vq); 18338eb4a29SMichael S. Tsirkin } 18438eb4a29SMichael S. Tsirkin 18538eb4a29SMichael S. Tsirkin static const struct virtio_config_ops virtio_pci_config_ops = { 18638eb4a29SMichael S. Tsirkin .get = vp_get, 18738eb4a29SMichael S. Tsirkin .set = vp_set, 18838eb4a29SMichael S. Tsirkin .get_status = vp_get_status, 18938eb4a29SMichael S. Tsirkin .set_status = vp_set_status, 19038eb4a29SMichael S. Tsirkin .reset = vp_reset, 19138eb4a29SMichael S. Tsirkin .find_vqs = vp_find_vqs, 19238eb4a29SMichael S. Tsirkin .del_vqs = vp_del_vqs, 19338eb4a29SMichael S. Tsirkin .get_features = vp_get_features, 19438eb4a29SMichael S. Tsirkin .finalize_features = vp_finalize_features, 19538eb4a29SMichael S. Tsirkin .bus_name = vp_bus_name, 19638eb4a29SMichael S. Tsirkin .set_vq_affinity = vp_set_vq_affinity, 19738eb4a29SMichael S. Tsirkin }; 19838eb4a29SMichael S. Tsirkin 19938eb4a29SMichael S. Tsirkin /* the PCI probing function */ 200ff31d2e2SMichael S. Tsirkin int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev) 20138eb4a29SMichael S. Tsirkin { 202ff31d2e2SMichael S. Tsirkin struct pci_dev *pci_dev = vp_dev->pci_dev; 20359a5b0f7SGerd Hoffmann int rc; 20438eb4a29SMichael S. Tsirkin 20538eb4a29SMichael S. Tsirkin /* We only own devices >= 0x1000 and <= 0x103f: leave the rest. */ 20638eb4a29SMichael S. Tsirkin if (pci_dev->device < 0x1000 || pci_dev->device > 0x103f) 20738eb4a29SMichael S. Tsirkin return -ENODEV; 20838eb4a29SMichael S. Tsirkin 20938eb4a29SMichael S. Tsirkin if (pci_dev->revision != VIRTIO_PCI_ABI_VERSION) { 21038eb4a29SMichael S. Tsirkin printk(KERN_ERR "virtio_pci: expected ABI version %d, got %d\n", 21138eb4a29SMichael S. Tsirkin VIRTIO_PCI_ABI_VERSION, pci_dev->revision); 21238eb4a29SMichael S. Tsirkin return -ENODEV; 21338eb4a29SMichael S. Tsirkin } 21438eb4a29SMichael S. Tsirkin 2157a5589b2SAndy Lutomirski rc = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(64)); 2167a5589b2SAndy Lutomirski if (rc) 2177a5589b2SAndy Lutomirski rc = dma_set_mask_and_coherent(&pci_dev->dev, 2187a5589b2SAndy Lutomirski DMA_BIT_MASK(32)); 2197a5589b2SAndy Lutomirski if (rc) 2207a5589b2SAndy Lutomirski dev_warn(&pci_dev->dev, "Failed to enable 64-bit or 32-bit DMA. Trying to continue, but this might not work.\n"); 2217a5589b2SAndy Lutomirski 22259a5b0f7SGerd Hoffmann rc = pci_request_region(pci_dev, 0, "virtio-pci-legacy"); 22359a5b0f7SGerd Hoffmann if (rc) 22459a5b0f7SGerd Hoffmann return rc; 22559a5b0f7SGerd Hoffmann 22659a5b0f7SGerd Hoffmann rc = -ENOMEM; 227ff31d2e2SMichael S. Tsirkin vp_dev->ioaddr = pci_iomap(pci_dev, 0, 0); 228ff31d2e2SMichael S. Tsirkin if (!vp_dev->ioaddr) 22959a5b0f7SGerd Hoffmann goto err_iomap; 23038eb4a29SMichael S. Tsirkin 23138eb4a29SMichael S. Tsirkin vp_dev->isr = vp_dev->ioaddr + VIRTIO_PCI_ISR; 23238eb4a29SMichael S. Tsirkin 23338eb4a29SMichael S. Tsirkin /* we use the subsystem vendor/device id as the virtio vendor/device 23438eb4a29SMichael S. Tsirkin * id. this allows us to use the same PCI vendor/device id for all 23538eb4a29SMichael S. Tsirkin * virtio devices and to identify the particular virtio driver by 23638eb4a29SMichael S. Tsirkin * the subsystem ids */ 23738eb4a29SMichael S. Tsirkin vp_dev->vdev.id.vendor = pci_dev->subsystem_vendor; 23838eb4a29SMichael S. Tsirkin vp_dev->vdev.id.device = pci_dev->subsystem_device; 23938eb4a29SMichael S. Tsirkin 240ff31d2e2SMichael S. Tsirkin vp_dev->vdev.config = &virtio_pci_config_ops; 241ff31d2e2SMichael S. Tsirkin 24238eb4a29SMichael S. Tsirkin vp_dev->config_vector = vp_config_vector; 24338eb4a29SMichael S. Tsirkin vp_dev->setup_vq = setup_vq; 24438eb4a29SMichael S. Tsirkin vp_dev->del_vq = del_vq; 24538eb4a29SMichael S. Tsirkin 24638eb4a29SMichael S. Tsirkin return 0; 24759a5b0f7SGerd Hoffmann 24859a5b0f7SGerd Hoffmann err_iomap: 24959a5b0f7SGerd Hoffmann pci_release_region(pci_dev, 0); 25059a5b0f7SGerd Hoffmann return rc; 25138eb4a29SMichael S. Tsirkin } 25238eb4a29SMichael S. Tsirkin 253ff31d2e2SMichael S. Tsirkin void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev) 25438eb4a29SMichael S. Tsirkin { 255ff31d2e2SMichael S. Tsirkin struct pci_dev *pci_dev = vp_dev->pci_dev; 25638eb4a29SMichael S. Tsirkin 25738eb4a29SMichael S. Tsirkin pci_iounmap(pci_dev, vp_dev->ioaddr); 25859a5b0f7SGerd Hoffmann pci_release_region(pci_dev, 0); 25938eb4a29SMichael S. Tsirkin } 260