brintos

brintos / linux-shallow public Read only

0
0
Text · 6.1 KiB · 677d1f6 Raw
223 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2 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 the11 * caller is required to enable PCI device before calling this function.12 * @ldev: the legacy virtio-pci device13 *14 * Return 0 on succeed otherwise fail15 */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 device67 * @ldev: the legacy virtio-pci device68 */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 device80 * @ldev: the legacy virtio-pci device81 *82 * Returns the features read from the device83 */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 device93 * @ldev: the legacy virtio-pci device94 *95 * Returns the driver features read from the device96 */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 device105 * @ldev: the legacy virtio-pci device106 * @features: the features set to device107 */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 status117 * @ldev: the legacy virtio-pci device118 *119 * Returns the status read from device120 */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 device129 * @ldev: the legacy virtio-pci device130 * @status: the status set to device131 */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 virtqueue141 * @ldev: the legacy virtio-pci device142 * @index: queue index143 * @vector: the config vector144 *145 * Returns the config vector read from the device146 */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 interrupt159 * @ldev: the legacy virtio-pci device160 * @vector: the config vector161 *162 * Returns the config vector read from the device163 */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 address177 * @ldev: the legacy virtio-pci device178 * @index: the queue index179 * @queue_pfn: pfn of the virtqueue180 */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 virtqueue191 * @ldev: the legacy virtio-pci device192 * @index: the queue index193 *194 * Returns whether a virtqueue is enabled or not195 */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 virtqueue206 * @ldev: the legacy virtio-pci device207 * @index: the queue index208 *209 * Returns the size of the virtqueue210 */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");223