Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 
0003 #include "linux/virtio_pci.h"
0004 #include <linux/virtio_pci_legacy.h>
0005 #include <linux/module.h>
0006 #include <linux/pci.h>
0007 
0008 
0009 /*
0010  * vp_legacy_probe: probe the legacy virtio pci device, note that the
0011  * caller is required to enable PCI device before calling this function.
0012  * @ldev: the legacy virtio-pci device
0013  *
0014  * Return 0 on succeed otherwise fail
0015  */
0016 int vp_legacy_probe(struct virtio_pci_legacy_device *ldev)
0017 {
0018     struct pci_dev *pci_dev = ldev->pci_dev;
0019     int rc;
0020 
0021     /* We only own devices >= 0x1000 and <= 0x103f: leave the rest. */
0022     if (pci_dev->device < 0x1000 || pci_dev->device > 0x103f)
0023         return -ENODEV;
0024 
0025     if (pci_dev->revision != VIRTIO_PCI_ABI_VERSION)
0026         return -ENODEV;
0027 
0028     rc = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(64));
0029     if (rc) {
0030         rc = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32));
0031     } else {
0032         /*
0033          * The virtio ring base address is expressed as a 32-bit PFN,
0034          * with a page size of 1 << VIRTIO_PCI_QUEUE_ADDR_SHIFT.
0035          */
0036         dma_set_coherent_mask(&pci_dev->dev,
0037                 DMA_BIT_MASK(32 + VIRTIO_PCI_QUEUE_ADDR_SHIFT));
0038     }
0039 
0040     if (rc)
0041         dev_warn(&pci_dev->dev, "Failed to enable 64-bit or 32-bit DMA.  Trying to continue, but this might not work.\n");
0042 
0043     rc = pci_request_region(pci_dev, 0, "virtio-pci-legacy");
0044     if (rc)
0045         return rc;
0046 
0047     ldev->ioaddr = pci_iomap(pci_dev, 0, 0);
0048     if (!ldev->ioaddr) {
0049         rc = -EIO;
0050         goto err_iomap;
0051     }
0052 
0053     ldev->isr = ldev->ioaddr + VIRTIO_PCI_ISR;
0054 
0055     ldev->id.vendor = pci_dev->subsystem_vendor;
0056     ldev->id.device = pci_dev->subsystem_device;
0057 
0058     return 0;
0059 err_iomap:
0060     pci_release_region(pci_dev, 0);
0061     return rc;
0062 }
0063 EXPORT_SYMBOL_GPL(vp_legacy_probe);
0064 
0065 /*
0066  * vp_legacy_probe: remove and cleanup the legacy virtio pci device
0067  * @ldev: the legacy virtio-pci device
0068  */
0069 void vp_legacy_remove(struct virtio_pci_legacy_device *ldev)
0070 {
0071     struct pci_dev *pci_dev = ldev->pci_dev;
0072 
0073     pci_iounmap(pci_dev, ldev->ioaddr);
0074     pci_release_region(pci_dev, 0);
0075 }
0076 EXPORT_SYMBOL_GPL(vp_legacy_remove);
0077 
0078 /*
0079  * vp_legacy_get_features - get features from device
0080  * @ldev: the legacy virtio-pci device
0081  *
0082  * Returns the features read from the device
0083  */
0084 u64 vp_legacy_get_features(struct virtio_pci_legacy_device *ldev)
0085 {
0086 
0087     return ioread32(ldev->ioaddr + VIRTIO_PCI_HOST_FEATURES);
0088 }
0089 EXPORT_SYMBOL_GPL(vp_legacy_get_features);
0090 
0091 /*
0092  * vp_legacy_get_driver_features - get driver features from device
0093  * @ldev: the legacy virtio-pci device
0094  *
0095  * Returns the driver features read from the device
0096  */
0097 u64 vp_legacy_get_driver_features(struct virtio_pci_legacy_device *ldev)
0098 {
0099     return ioread32(ldev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
0100 }
0101 EXPORT_SYMBOL_GPL(vp_legacy_get_driver_features);
0102 
0103 /*
0104  * vp_legacy_set_features - set features to device
0105  * @ldev: the legacy virtio-pci device
0106  * @features: the features set to device
0107  */
0108 void vp_legacy_set_features(struct virtio_pci_legacy_device *ldev,
0109                 u32 features)
0110 {
0111     iowrite32(features, ldev->ioaddr + VIRTIO_PCI_GUEST_FEATURES);
0112 }
0113 EXPORT_SYMBOL_GPL(vp_legacy_set_features);
0114 
0115 /*
0116  * vp_legacy_get_status - get the device status
0117  * @ldev: the legacy virtio-pci device
0118  *
0119  * Returns the status read from device
0120  */
0121 u8 vp_legacy_get_status(struct virtio_pci_legacy_device *ldev)
0122 {
0123     return ioread8(ldev->ioaddr + VIRTIO_PCI_STATUS);
0124 }
0125 EXPORT_SYMBOL_GPL(vp_legacy_get_status);
0126 
0127 /*
0128  * vp_legacy_set_status - set status to device
0129  * @ldev: the legacy virtio-pci device
0130  * @status: the status set to device
0131  */
0132 void vp_legacy_set_status(struct virtio_pci_legacy_device *ldev,
0133                  u8 status)
0134 {
0135     iowrite8(status, ldev->ioaddr + VIRTIO_PCI_STATUS);
0136 }
0137 EXPORT_SYMBOL_GPL(vp_legacy_set_status);
0138 
0139 /*
0140  * vp_legacy_queue_vector - set the MSIX vector for a specific virtqueue
0141  * @ldev: the legacy virtio-pci device
0142  * @index: queue index
0143  * @vector: the config vector
0144  *
0145  * Returns the config vector read from the device
0146  */
0147 u16 vp_legacy_queue_vector(struct virtio_pci_legacy_device *ldev,
0148                u16 index, u16 vector)
0149 {
0150     iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
0151     iowrite16(vector, ldev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR);
0152     /* Flush the write out to device */
0153     return ioread16(ldev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR);
0154 }
0155 EXPORT_SYMBOL_GPL(vp_legacy_queue_vector);
0156 
0157 /*
0158  * vp_legacy_config_vector - set the vector for config interrupt
0159  * @ldev: the legacy virtio-pci device
0160  * @vector: the config vector
0161  *
0162  * Returns the config vector read from the device
0163  */
0164 u16 vp_legacy_config_vector(struct virtio_pci_legacy_device *ldev,
0165                 u16 vector)
0166 {
0167     /* Setup the vector used for configuration events */
0168     iowrite16(vector, ldev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
0169     /* Verify we had enough resources to assign the vector */
0170     /* Will also flush the write out to device */
0171     return ioread16(ldev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR);
0172 }
0173 EXPORT_SYMBOL_GPL(vp_legacy_config_vector);
0174 
0175 /*
0176  * vp_legacy_set_queue_address - set the virtqueue address
0177  * @ldev: the legacy virtio-pci device
0178  * @index: the queue index
0179  * @queue_pfn: pfn of the virtqueue
0180  */
0181 void vp_legacy_set_queue_address(struct virtio_pci_legacy_device *ldev,
0182                  u16 index, u32 queue_pfn)
0183 {
0184     iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
0185     iowrite32(queue_pfn, ldev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
0186 }
0187 EXPORT_SYMBOL_GPL(vp_legacy_set_queue_address);
0188 
0189 /*
0190  * vp_legacy_get_queue_enable - enable a virtqueue
0191  * @ldev: the legacy virtio-pci device
0192  * @index: the queue index
0193  *
0194  * Returns whether a virtqueue is enabled or not
0195  */
0196 bool vp_legacy_get_queue_enable(struct virtio_pci_legacy_device *ldev,
0197                 u16 index)
0198 {
0199     iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
0200     return ioread32(ldev->ioaddr + VIRTIO_PCI_QUEUE_PFN);
0201 }
0202 EXPORT_SYMBOL_GPL(vp_legacy_get_queue_enable);
0203 
0204 /*
0205  * vp_legacy_get_queue_size - get size for a virtqueue
0206  * @ldev: the legacy virtio-pci device
0207  * @index: the queue index
0208  *
0209  * Returns the size of the virtqueue
0210  */
0211 u16 vp_legacy_get_queue_size(struct virtio_pci_legacy_device *ldev,
0212                  u16 index)
0213 {
0214     iowrite16(index, ldev->ioaddr + VIRTIO_PCI_QUEUE_SEL);
0215     return ioread16(ldev->ioaddr + VIRTIO_PCI_QUEUE_NUM);
0216 }
0217 EXPORT_SYMBOL_GPL(vp_legacy_get_queue_size);
0218 
0219 MODULE_VERSION("0.1");
0220 MODULE_DESCRIPTION("Legacy Virtio PCI Device");
0221 MODULE_AUTHOR("Wu Zongyong <wuzongyong@linux.alibaba.com>");
0222 MODULE_LICENSE("GPL");