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 goto err_iomap; 50 51 ldev->isr = ldev->ioaddr + VIRTIO_PCI_ISR; 52 53 ldev->id.vendor = pci_dev->subsystem_vendor; 54 ldev->id.device = pci_dev->subsystem_device; 55 56 return 0; 57 err_iomap: 58 pci_release_region(pci_dev, 0); 59 return rc; 60 } 61 EXPORT_SYMBOL_GPL(vp_legacy_probe); 62 63 /* 64 * vp_legacy_probe: remove and cleanup the legacy virtio pci device 65 * @ldev: the legacy virtio-pci device 66 */ 67 void vp_legacy_remove(struct virtio_pci_legacy_device *ldev) 68 { 69 struct pci_dev *pci_dev = ldev->pci_dev; 70 71 pci_iounmap(pci_dev, ldev->ioaddr); 72 pci_release_region(pci_dev, 0); 73 } 74 EXPORT_SYMBOL_GPL(vp_legacy_remove); 75 76 /* 77 * vp_legacy_get_features - get features from device 78 * @ldev: the legacy virtio-pci device 79 * 80 * Returns the features read from the device 81 */ 82 u64 vp_legacy_get_features(struct virtio_pci_legacy_device *ldev) 83 { 84 85 return ioread32(ldev->ioaddr + VIRTIO_PCI_HOST_FEATURES); 86 } 87 EXPORT_SYMBOL_GPL(vp_legacy_get_features); 88 89 /* 90 * vp_legacy_get_driver_features - get driver features from device 91 * @ldev: the legacy virtio-pci device 92 * 93 * Returns the driver features read from the device 94 */ 95 u64 vp_legacy_get_driver_features(struct virtio_pci_legacy_device *ldev) 96 { 97 return ioread32(ldev->ioaddr + VIRTIO_PCI_GUEST_FEATURES); 98 } 99 EXPORT_SYMBOL_GPL(vp_legacy_get_driver_features); 100 101 /* 102 * vp_legacy_set_features - set features to device 103 * @ldev: the legacy virtio-pci device 104 * @features: the features set to device 105 */ 106 void vp_legacy_set_features(struct virtio_pci_legacy_device *ldev, 107 u32 features) 108 { 109 iowrite32(features, ldev->ioaddr + VIRTIO_PCI_GUEST_FEATURES); 110 } 111 EXPORT_SYMBOL_GPL(vp_legacy_set_features); 112 113 /* 114 * vp_legacy_get_status - get the device status 115 * @ldev: the legacy virtio-pci device 116 * 117 * Returns the status read from device 118 */ 119 u8 vp_legacy_get_status(struct virtio_pci_legacy_device *ldev) 120 { 121 return ioread8(ldev->ioaddr + VIRTIO_PCI_STATUS); 122 } 123 EXPORT_SYMBOL_GPL(vp_legacy_get_status); 124 125 /* 126 * vp_legacy_set_status - set status to device 127 * @ldev: the legacy virtio-pci device 128 * @status: the status set to device 129 */ 130 void vp_legacy_set_status(struct virtio_pci_legacy_device *ldev, 131 u8 status) 132 { 133 iowrite8(status, ldev->ioaddr + VIRTIO_PCI_STATUS); 134 } 135 EXPORT_SYMBOL_GPL(vp_legacy_set_status); 136 137 /* 138 * vp_legacy_queue_vector - set the MSIX vector for a specific virtqueue 139 * @ldev: the legacy virtio-pci device 140 * @index: queue index 141 * @vector: the config vector 142 * 143 * Returns the config vector read from the device 144 */ 145 u16 vp_legacy_queue_vector(struct virtio_pci_legacy_device *ldev, 146 u16 index, u16 vector) 147 { 148 iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL); 149 iowrite16(vector, ldev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); 150 /* Flush the write out to device */ 151 return ioread16(ldev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); 152 } 153 EXPORT_SYMBOL_GPL(vp_legacy_queue_vector); 154 155 /* 156 * vp_legacy_config_vector - set the vector for config interrupt 157 * @ldev: the legacy virtio-pci device 158 * @vector: the config vector 159 * 160 * Returns the config vector read from the device 161 */ 162 u16 vp_legacy_config_vector(struct virtio_pci_legacy_device *ldev, 163 u16 vector) 164 { 165 /* Setup the vector used for configuration events */ 166 iowrite16(vector, ldev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); 167 /* Verify we had enough resources to assign the vector */ 168 /* Will also flush the write out to device */ 169 return ioread16(ldev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); 170 } 171 EXPORT_SYMBOL_GPL(vp_legacy_config_vector); 172 173 /* 174 * vp_legacy_set_queue_address - set the virtqueue address 175 * @ldev: the legacy virtio-pci device 176 * @index: the queue index 177 * @queue_pfn: pfn of the virtqueue 178 */ 179 void vp_legacy_set_queue_address(struct virtio_pci_legacy_device *ldev, 180 u16 index, u32 queue_pfn) 181 { 182 iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL); 183 iowrite32(queue_pfn, ldev->ioaddr + VIRTIO_PCI_QUEUE_PFN); 184 } 185 EXPORT_SYMBOL_GPL(vp_legacy_set_queue_address); 186 187 /* 188 * vp_legacy_get_queue_enable - enable a virtqueue 189 * @ldev: the legacy virtio-pci device 190 * @index: the queue index 191 * 192 * Returns whether a virtqueue is enabled or not 193 */ 194 bool vp_legacy_get_queue_enable(struct virtio_pci_legacy_device *ldev, 195 u16 index) 196 { 197 iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL); 198 return ioread32(ldev->ioaddr + VIRTIO_PCI_QUEUE_PFN); 199 } 200 EXPORT_SYMBOL_GPL(vp_legacy_get_queue_enable); 201 202 /* 203 * vp_legacy_get_queue_size - get size for a virtqueue 204 * @ldev: the legacy virtio-pci device 205 * @index: the queue index 206 * 207 * Returns the size of the virtqueue 208 */ 209 u16 vp_legacy_get_queue_size(struct virtio_pci_legacy_device *ldev, 210 u16 index) 211 { 212 iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL); 213 return ioread16(ldev->ioaddr + VIRTIO_PCI_QUEUE_NUM); 214 } 215 EXPORT_SYMBOL_GPL(vp_legacy_get_queue_size); 216 217 MODULE_VERSION("0.1"); 218 MODULE_DESCRIPTION("Legacy Virtio PCI Device"); 219 MODULE_AUTHOR("Wu Zongyong <wuzongyong@linux.alibaba.com>"); 220 MODULE_LICENSE("GPL"); 221