virtio_pci_legacy_dev.c (6223B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2 3#include "linux/virtio_pci.h" 4#include <linux/virtio_pci_legacy.h> 5#include <linux/module.h> 6#include <linux/pci.h> 7 8 9/* 10 * vp_legacy_probe: probe the legacy virtio pci device, note that the 11 * caller is required to enable PCI device before calling this function. 12 * @ldev: the legacy virtio-pci device 13 * 14 * Return 0 on succeed otherwise fail 15 */ 16int vp_legacy_probe(struct virtio_pci_legacy_device *ldev) 17{ 18 struct pci_dev *pci_dev = ldev->pci_dev; 19 int rc; 20 21 /* We only own devices >= 0x1000 and <= 0x103f: leave the rest. */ 22 if (pci_dev->device < 0x1000 || pci_dev->device > 0x103f) 23 return -ENODEV; 24 25 if (pci_dev->revision != VIRTIO_PCI_ABI_VERSION) 26 return -ENODEV; 27 28 rc = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(64)); 29 if (rc) { 30 rc = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32)); 31 } else { 32 /* 33 * The virtio ring base address is expressed as a 32-bit PFN, 34 * with a page size of 1 << VIRTIO_PCI_QUEUE_ADDR_SHIFT. 35 */ 36 dma_set_coherent_mask(&pci_dev->dev, 37 DMA_BIT_MASK(32 + VIRTIO_PCI_QUEUE_ADDR_SHIFT)); 38 } 39 40 if (rc) 41 dev_warn(&pci_dev->dev, "Failed to enable 64-bit or 32-bit DMA. Trying to continue, but this might not work.\n"); 42 43 rc = pci_request_region(pci_dev, 0, "virtio-pci-legacy"); 44 if (rc) 45 return rc; 46 47 ldev->ioaddr = pci_iomap(pci_dev, 0, 0); 48 if (!ldev->ioaddr) { 49 rc = -EIO; 50 goto err_iomap; 51 } 52 53 ldev->isr = ldev->ioaddr + VIRTIO_PCI_ISR; 54 55 ldev->id.vendor = pci_dev->subsystem_vendor; 56 ldev->id.device = pci_dev->subsystem_device; 57 58 return 0; 59err_iomap: 60 pci_release_region(pci_dev, 0); 61 return rc; 62} 63EXPORT_SYMBOL_GPL(vp_legacy_probe); 64 65/* 66 * vp_legacy_probe: remove and cleanup the legacy virtio pci device 67 * @ldev: the legacy virtio-pci device 68 */ 69void vp_legacy_remove(struct virtio_pci_legacy_device *ldev) 70{ 71 struct pci_dev *pci_dev = ldev->pci_dev; 72 73 pci_iounmap(pci_dev, ldev->ioaddr); 74 pci_release_region(pci_dev, 0); 75} 76EXPORT_SYMBOL_GPL(vp_legacy_remove); 77 78/* 79 * vp_legacy_get_features - get features from device 80 * @ldev: the legacy virtio-pci device 81 * 82 * Returns the features read from the device 83 */ 84u64 vp_legacy_get_features(struct virtio_pci_legacy_device *ldev) 85{ 86 87 return ioread32(ldev->ioaddr + VIRTIO_PCI_HOST_FEATURES); 88} 89EXPORT_SYMBOL_GPL(vp_legacy_get_features); 90 91/* 92 * vp_legacy_get_driver_features - get driver features from device 93 * @ldev: the legacy virtio-pci device 94 * 95 * Returns the driver features read from the device 96 */ 97u64 vp_legacy_get_driver_features(struct virtio_pci_legacy_device *ldev) 98{ 99 return ioread32(ldev->ioaddr + VIRTIO_PCI_GUEST_FEATURES); 100} 101EXPORT_SYMBOL_GPL(vp_legacy_get_driver_features); 102 103/* 104 * vp_legacy_set_features - set features to device 105 * @ldev: the legacy virtio-pci device 106 * @features: the features set to device 107 */ 108void vp_legacy_set_features(struct virtio_pci_legacy_device *ldev, 109 u32 features) 110{ 111 iowrite32(features, ldev->ioaddr + VIRTIO_PCI_GUEST_FEATURES); 112} 113EXPORT_SYMBOL_GPL(vp_legacy_set_features); 114 115/* 116 * vp_legacy_get_status - get the device status 117 * @ldev: the legacy virtio-pci device 118 * 119 * Returns the status read from device 120 */ 121u8 vp_legacy_get_status(struct virtio_pci_legacy_device *ldev) 122{ 123 return ioread8(ldev->ioaddr + VIRTIO_PCI_STATUS); 124} 125EXPORT_SYMBOL_GPL(vp_legacy_get_status); 126 127/* 128 * vp_legacy_set_status - set status to device 129 * @ldev: the legacy virtio-pci device 130 * @status: the status set to device 131 */ 132void vp_legacy_set_status(struct virtio_pci_legacy_device *ldev, 133 u8 status) 134{ 135 iowrite8(status, ldev->ioaddr + VIRTIO_PCI_STATUS); 136} 137EXPORT_SYMBOL_GPL(vp_legacy_set_status); 138 139/* 140 * vp_legacy_queue_vector - set the MSIX vector for a specific virtqueue 141 * @ldev: the legacy virtio-pci device 142 * @index: queue index 143 * @vector: the config vector 144 * 145 * Returns the config vector read from the device 146 */ 147u16 vp_legacy_queue_vector(struct virtio_pci_legacy_device *ldev, 148 u16 index, u16 vector) 149{ 150 iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL); 151 iowrite16(vector, ldev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); 152 /* Flush the write out to device */ 153 return ioread16(ldev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); 154} 155EXPORT_SYMBOL_GPL(vp_legacy_queue_vector); 156 157/* 158 * vp_legacy_config_vector - set the vector for config interrupt 159 * @ldev: the legacy virtio-pci device 160 * @vector: the config vector 161 * 162 * Returns the config vector read from the device 163 */ 164u16 vp_legacy_config_vector(struct virtio_pci_legacy_device *ldev, 165 u16 vector) 166{ 167 /* Setup the vector used for configuration events */ 168 iowrite16(vector, ldev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); 169 /* Verify we had enough resources to assign the vector */ 170 /* Will also flush the write out to device */ 171 return ioread16(ldev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); 172} 173EXPORT_SYMBOL_GPL(vp_legacy_config_vector); 174 175/* 176 * vp_legacy_set_queue_address - set the virtqueue address 177 * @ldev: the legacy virtio-pci device 178 * @index: the queue index 179 * @queue_pfn: pfn of the virtqueue 180 */ 181void vp_legacy_set_queue_address(struct virtio_pci_legacy_device *ldev, 182 u16 index, u32 queue_pfn) 183{ 184 iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL); 185 iowrite32(queue_pfn, ldev->ioaddr + VIRTIO_PCI_QUEUE_PFN); 186} 187EXPORT_SYMBOL_GPL(vp_legacy_set_queue_address); 188 189/* 190 * vp_legacy_get_queue_enable - enable a virtqueue 191 * @ldev: the legacy virtio-pci device 192 * @index: the queue index 193 * 194 * Returns whether a virtqueue is enabled or not 195 */ 196bool vp_legacy_get_queue_enable(struct virtio_pci_legacy_device *ldev, 197 u16 index) 198{ 199 iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL); 200 return ioread32(ldev->ioaddr + VIRTIO_PCI_QUEUE_PFN); 201} 202EXPORT_SYMBOL_GPL(vp_legacy_get_queue_enable); 203 204/* 205 * vp_legacy_get_queue_size - get size for a virtqueue 206 * @ldev: the legacy virtio-pci device 207 * @index: the queue index 208 * 209 * Returns the size of the virtqueue 210 */ 211u16 vp_legacy_get_queue_size(struct virtio_pci_legacy_device *ldev, 212 u16 index) 213{ 214 iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL); 215 return ioread16(ldev->ioaddr + VIRTIO_PCI_QUEUE_NUM); 216} 217EXPORT_SYMBOL_GPL(vp_legacy_get_queue_size); 218 219MODULE_VERSION("0.1"); 220MODULE_DESCRIPTION("Legacy Virtio PCI Device"); 221MODULE_AUTHOR("Wu Zongyong <wuzongyong@linux.alibaba.com>"); 222MODULE_LICENSE("GPL");