Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* uio_pci_generic - generic UIO driver for PCI 2.3 devices
0003  *
0004  * Copyright (C) 2009 Red Hat, Inc.
0005  * Author: Michael S. Tsirkin <mst@redhat.com>
0006  *
0007  * Since the driver does not declare any device ids, you must allocate
0008  * id and bind the device to the driver yourself.  For example:
0009  *
0010  * # echo "8086 10f5" > /sys/bus/pci/drivers/uio_pci_generic/new_id
0011  * # echo -n 0000:00:19.0 > /sys/bus/pci/drivers/e1000e/unbind
0012  * # echo -n 0000:00:19.0 > /sys/bus/pci/drivers/uio_pci_generic/bind
0013  * # ls -l /sys/bus/pci/devices/0000:00:19.0/driver
0014  * .../0000:00:19.0/driver -> ../../../bus/pci/drivers/uio_pci_generic
0015  *
0016  * Driver won't bind to devices which do not support the Interrupt Disable Bit
0017  * in the command register. All devices compliant to PCI 2.3 (circa 2002) and
0018  * all compliant PCI Express devices should support this bit.
0019  */
0020 
0021 #include <linux/device.h>
0022 #include <linux/module.h>
0023 #include <linux/pci.h>
0024 #include <linux/slab.h>
0025 #include <linux/uio_driver.h>
0026 
0027 #define DRIVER_VERSION  "0.01.0"
0028 #define DRIVER_AUTHOR   "Michael S. Tsirkin <mst@redhat.com>"
0029 #define DRIVER_DESC "Generic UIO driver for PCI 2.3 devices"
0030 
0031 struct uio_pci_generic_dev {
0032     struct uio_info info;
0033     struct pci_dev *pdev;
0034 };
0035 
0036 static inline struct uio_pci_generic_dev *
0037 to_uio_pci_generic_dev(struct uio_info *info)
0038 {
0039     return container_of(info, struct uio_pci_generic_dev, info);
0040 }
0041 
0042 static int release(struct uio_info *info, struct inode *inode)
0043 {
0044     struct uio_pci_generic_dev *gdev = to_uio_pci_generic_dev(info);
0045 
0046     /*
0047      * This driver is insecure when used with devices doing DMA, but some
0048      * people (mis)use it with such devices.
0049      * Let's at least make sure DMA isn't left enabled after the userspace
0050      * driver closes the fd.
0051      * Note that there's a non-zero chance doing this will wedge the device
0052      * at least until reset.
0053      */
0054     pci_clear_master(gdev->pdev);
0055     return 0;
0056 }
0057 
0058 /* Interrupt handler. Read/modify/write the command register to disable
0059  * the interrupt. */
0060 static irqreturn_t irqhandler(int irq, struct uio_info *info)
0061 {
0062     struct uio_pci_generic_dev *gdev = to_uio_pci_generic_dev(info);
0063 
0064     if (!pci_check_and_mask_intx(gdev->pdev))
0065         return IRQ_NONE;
0066 
0067     /* UIO core will signal the user process. */
0068     return IRQ_HANDLED;
0069 }
0070 
0071 static int probe(struct pci_dev *pdev,
0072                const struct pci_device_id *id)
0073 {
0074     struct uio_pci_generic_dev *gdev;
0075     struct uio_mem *uiomem;
0076     int err;
0077     int i;
0078 
0079     err = pcim_enable_device(pdev);
0080     if (err) {
0081         dev_err(&pdev->dev, "%s: pci_enable_device failed: %d\n",
0082             __func__, err);
0083         return err;
0084     }
0085 
0086     if (pdev->irq && !pci_intx_mask_supported(pdev))
0087         return -ENODEV;
0088 
0089     gdev = devm_kzalloc(&pdev->dev, sizeof(struct uio_pci_generic_dev), GFP_KERNEL);
0090     if (!gdev)
0091         return -ENOMEM;
0092 
0093     gdev->info.name = "uio_pci_generic";
0094     gdev->info.version = DRIVER_VERSION;
0095     gdev->info.release = release;
0096     gdev->pdev = pdev;
0097     if (pdev->irq && (pdev->irq != IRQ_NOTCONNECTED)) {
0098         gdev->info.irq = pdev->irq;
0099         gdev->info.irq_flags = IRQF_SHARED;
0100         gdev->info.handler = irqhandler;
0101     } else {
0102         dev_warn(&pdev->dev, "No IRQ assigned to device: "
0103              "no support for interrupts?\n");
0104     }
0105 
0106     uiomem = &gdev->info.mem[0];
0107     for (i = 0; i < MAX_UIO_MAPS; ++i) {
0108         struct resource *r = &pdev->resource[i];
0109 
0110         if (r->flags != (IORESOURCE_SIZEALIGN | IORESOURCE_MEM))
0111             continue;
0112 
0113         if (uiomem >= &gdev->info.mem[MAX_UIO_MAPS]) {
0114             dev_warn(
0115                 &pdev->dev,
0116                 "device has more than " __stringify(
0117                     MAX_UIO_MAPS) " I/O memory resources.\n");
0118             break;
0119         }
0120 
0121         uiomem->memtype = UIO_MEM_PHYS;
0122         uiomem->addr = r->start & PAGE_MASK;
0123         uiomem->offs = r->start & ~PAGE_MASK;
0124         uiomem->size =
0125             (uiomem->offs + resource_size(r) + PAGE_SIZE - 1) &
0126             PAGE_MASK;
0127         uiomem->name = r->name;
0128         ++uiomem;
0129     }
0130 
0131     while (uiomem < &gdev->info.mem[MAX_UIO_MAPS]) {
0132         uiomem->size = 0;
0133         ++uiomem;
0134     }
0135 
0136     return devm_uio_register_device(&pdev->dev, &gdev->info);
0137 }
0138 
0139 static struct pci_driver uio_pci_driver = {
0140     .name = "uio_pci_generic",
0141     .id_table = NULL, /* only dynamic id's */
0142     .probe = probe,
0143 };
0144 
0145 module_pci_driver(uio_pci_driver);
0146 MODULE_VERSION(DRIVER_VERSION);
0147 MODULE_LICENSE("GPL v2");
0148 MODULE_AUTHOR(DRIVER_AUTHOR);
0149 MODULE_DESCRIPTION(DRIVER_DESC);