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 */ 16 int 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; 59 err_iomap: 60 pci_release_region(pci_dev, 0); 61 return rc; 62 } 63 EXPORT_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 */ 69 void 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 } 76 EXPORT_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 */ 84 u64 vp_legacy_get_features(struct virtio_pci_legacy_device *ldev) 85 { 86 87 return ioread32(ldev->ioaddr + VIRTIO_PCI_HOST_FEATURES); 88 } 89 EXPORT_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 */ 97 u64 vp_legacy_get_driver_features(struct virtio_pci_legacy_device *ldev) 98 { 99 return ioread32(ldev->ioaddr + VIRTIO_PCI_GUEST_FEATURES); 100 } 101 EXPORT_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 */ 108 void vp_legacy_set_features(struct virtio_pci_legacy_device *ldev, 109 u32 features) 110 { 111 iowrite32(features, ldev->ioaddr + VIRTIO_PCI_GUEST_FEATURES); 112 } 113 EXPORT_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 */ 121 u8 vp_legacy_get_status(struct virtio_pci_legacy_device *ldev) 122 { 123 return ioread8(ldev->ioaddr + VIRTIO_PCI_STATUS); 124 } 125 EXPORT_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 */ 132 void vp_legacy_set_status(struct virtio_pci_legacy_device *ldev, 133 u8 status) 134 { 135 iowrite8(status, ldev->ioaddr + VIRTIO_PCI_STATUS); 136 } 137 EXPORT_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 */ 147 u16 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 } 155 EXPORT_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 */ 164 u16 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 } 173 EXPORT_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 */ 181 void 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 } 187 EXPORT_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 */ 196 bool 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 } 202 EXPORT_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 */ 211 u16 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 } 217 EXPORT_SYMBOL_GPL(vp_legacy_get_queue_size); 218 219 MODULE_VERSION("0.1"); 220 MODULE_DESCRIPTION("Legacy Virtio PCI Device"); 221 MODULE_AUTHOR("Wu Zongyong <wuzongyong@linux.alibaba.com>"); 222 MODULE_LICENSE("GPL"); 223