Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
0002 /*
0003  * Copyright 2013-2016 Freescale Semiconductor Inc.
0004  * Copyright 2016-2017,2019-2020 NXP
0005  */
0006 
0007 #include <linux/device.h>
0008 #include <linux/iommu.h>
0009 #include <linux/module.h>
0010 #include <linux/mutex.h>
0011 #include <linux/slab.h>
0012 #include <linux/types.h>
0013 #include <linux/vfio.h>
0014 #include <linux/fsl/mc.h>
0015 #include <linux/delay.h>
0016 #include <linux/io-64-nonatomic-hi-lo.h>
0017 
0018 #include "vfio_fsl_mc_private.h"
0019 
0020 static struct fsl_mc_driver vfio_fsl_mc_driver;
0021 
0022 static int vfio_fsl_mc_open_device(struct vfio_device *core_vdev)
0023 {
0024     struct vfio_fsl_mc_device *vdev =
0025         container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
0026     struct fsl_mc_device *mc_dev = vdev->mc_dev;
0027     int count = mc_dev->obj_desc.region_count;
0028     int i;
0029 
0030     vdev->regions = kcalloc(count, sizeof(struct vfio_fsl_mc_region),
0031                 GFP_KERNEL);
0032     if (!vdev->regions)
0033         return -ENOMEM;
0034 
0035     for (i = 0; i < count; i++) {
0036         struct resource *res = &mc_dev->regions[i];
0037         int no_mmap = is_fsl_mc_bus_dprc(mc_dev);
0038 
0039         vdev->regions[i].addr = res->start;
0040         vdev->regions[i].size = resource_size(res);
0041         vdev->regions[i].type = mc_dev->regions[i].flags & IORESOURCE_BITS;
0042         /*
0043          * Only regions addressed with PAGE granularity may be
0044          * MMAPed securely.
0045          */
0046         if (!no_mmap && !(vdev->regions[i].addr & ~PAGE_MASK) &&
0047                 !(vdev->regions[i].size & ~PAGE_MASK))
0048             vdev->regions[i].flags |=
0049                     VFIO_REGION_INFO_FLAG_MMAP;
0050         vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ;
0051         if (!(mc_dev->regions[i].flags & IORESOURCE_READONLY))
0052             vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_WRITE;
0053     }
0054 
0055     return 0;
0056 }
0057 
0058 static void vfio_fsl_mc_regions_cleanup(struct vfio_fsl_mc_device *vdev)
0059 {
0060     struct fsl_mc_device *mc_dev = vdev->mc_dev;
0061     int i;
0062 
0063     for (i = 0; i < mc_dev->obj_desc.region_count; i++)
0064         iounmap(vdev->regions[i].ioaddr);
0065     kfree(vdev->regions);
0066 }
0067 
0068 static int vfio_fsl_mc_reset_device(struct vfio_fsl_mc_device *vdev)
0069 {
0070     struct fsl_mc_device *mc_dev = vdev->mc_dev;
0071     int ret = 0;
0072 
0073     if (is_fsl_mc_bus_dprc(vdev->mc_dev)) {
0074         return dprc_reset_container(mc_dev->mc_io, 0,
0075                     mc_dev->mc_handle,
0076                     mc_dev->obj_desc.id,
0077                     DPRC_RESET_OPTION_NON_RECURSIVE);
0078     } else {
0079         u16 token;
0080 
0081         ret = fsl_mc_obj_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
0082                       mc_dev->obj_desc.type,
0083                       &token);
0084         if (ret)
0085             goto out;
0086         ret = fsl_mc_obj_reset(mc_dev->mc_io, 0, token);
0087         if (ret) {
0088             fsl_mc_obj_close(mc_dev->mc_io, 0, token);
0089             goto out;
0090         }
0091         ret = fsl_mc_obj_close(mc_dev->mc_io, 0, token);
0092     }
0093 out:
0094     return ret;
0095 }
0096 
0097 static void vfio_fsl_mc_close_device(struct vfio_device *core_vdev)
0098 {
0099     struct vfio_fsl_mc_device *vdev =
0100         container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
0101     struct fsl_mc_device *mc_dev = vdev->mc_dev;
0102     struct device *cont_dev = fsl_mc_cont_dev(&mc_dev->dev);
0103     struct fsl_mc_device *mc_cont = to_fsl_mc_device(cont_dev);
0104     int ret;
0105 
0106     vfio_fsl_mc_regions_cleanup(vdev);
0107 
0108     /* reset the device before cleaning up the interrupts */
0109     ret = vfio_fsl_mc_reset_device(vdev);
0110 
0111     if (WARN_ON(ret))
0112         dev_warn(&mc_cont->dev,
0113              "VFIO_FLS_MC: reset device has failed (%d)\n", ret);
0114 
0115     vfio_fsl_mc_irqs_cleanup(vdev);
0116 
0117     fsl_mc_cleanup_irq_pool(mc_cont);
0118 }
0119 
0120 static long vfio_fsl_mc_ioctl(struct vfio_device *core_vdev,
0121                   unsigned int cmd, unsigned long arg)
0122 {
0123     unsigned long minsz;
0124     struct vfio_fsl_mc_device *vdev =
0125         container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
0126     struct fsl_mc_device *mc_dev = vdev->mc_dev;
0127 
0128     switch (cmd) {
0129     case VFIO_DEVICE_GET_INFO:
0130     {
0131         struct vfio_device_info info;
0132 
0133         minsz = offsetofend(struct vfio_device_info, num_irqs);
0134 
0135         if (copy_from_user(&info, (void __user *)arg, minsz))
0136             return -EFAULT;
0137 
0138         if (info.argsz < minsz)
0139             return -EINVAL;
0140 
0141         info.flags = VFIO_DEVICE_FLAGS_FSL_MC;
0142 
0143         if (is_fsl_mc_bus_dprc(mc_dev))
0144             info.flags |= VFIO_DEVICE_FLAGS_RESET;
0145 
0146         info.num_regions = mc_dev->obj_desc.region_count;
0147         info.num_irqs = mc_dev->obj_desc.irq_count;
0148 
0149         return copy_to_user((void __user *)arg, &info, minsz) ?
0150             -EFAULT : 0;
0151     }
0152     case VFIO_DEVICE_GET_REGION_INFO:
0153     {
0154         struct vfio_region_info info;
0155 
0156         minsz = offsetofend(struct vfio_region_info, offset);
0157 
0158         if (copy_from_user(&info, (void __user *)arg, minsz))
0159             return -EFAULT;
0160 
0161         if (info.argsz < minsz)
0162             return -EINVAL;
0163 
0164         if (info.index >= mc_dev->obj_desc.region_count)
0165             return -EINVAL;
0166 
0167         /* map offset to the physical address  */
0168         info.offset = VFIO_FSL_MC_INDEX_TO_OFFSET(info.index);
0169         info.size = vdev->regions[info.index].size;
0170         info.flags = vdev->regions[info.index].flags;
0171 
0172         if (copy_to_user((void __user *)arg, &info, minsz))
0173             return -EFAULT;
0174         return 0;
0175     }
0176     case VFIO_DEVICE_GET_IRQ_INFO:
0177     {
0178         struct vfio_irq_info info;
0179 
0180         minsz = offsetofend(struct vfio_irq_info, count);
0181         if (copy_from_user(&info, (void __user *)arg, minsz))
0182             return -EFAULT;
0183 
0184         if (info.argsz < minsz)
0185             return -EINVAL;
0186 
0187         if (info.index >= mc_dev->obj_desc.irq_count)
0188             return -EINVAL;
0189 
0190         info.flags = VFIO_IRQ_INFO_EVENTFD;
0191         info.count = 1;
0192 
0193         if (copy_to_user((void __user *)arg, &info, minsz))
0194             return -EFAULT;
0195         return 0;
0196     }
0197     case VFIO_DEVICE_SET_IRQS:
0198     {
0199         struct vfio_irq_set hdr;
0200         u8 *data = NULL;
0201         int ret = 0;
0202         size_t data_size = 0;
0203 
0204         minsz = offsetofend(struct vfio_irq_set, count);
0205 
0206         if (copy_from_user(&hdr, (void __user *)arg, minsz))
0207             return -EFAULT;
0208 
0209         ret = vfio_set_irqs_validate_and_prepare(&hdr, mc_dev->obj_desc.irq_count,
0210                     mc_dev->obj_desc.irq_count, &data_size);
0211         if (ret)
0212             return ret;
0213 
0214         if (data_size) {
0215             data = memdup_user((void __user *)(arg + minsz),
0216                    data_size);
0217             if (IS_ERR(data))
0218                 return PTR_ERR(data);
0219         }
0220 
0221         mutex_lock(&vdev->igate);
0222         ret = vfio_fsl_mc_set_irqs_ioctl(vdev, hdr.flags,
0223                          hdr.index, hdr.start,
0224                          hdr.count, data);
0225         mutex_unlock(&vdev->igate);
0226         kfree(data);
0227 
0228         return ret;
0229     }
0230     case VFIO_DEVICE_RESET:
0231     {
0232         return vfio_fsl_mc_reset_device(vdev);
0233 
0234     }
0235     default:
0236         return -ENOTTY;
0237     }
0238 }
0239 
0240 static ssize_t vfio_fsl_mc_read(struct vfio_device *core_vdev, char __user *buf,
0241                 size_t count, loff_t *ppos)
0242 {
0243     struct vfio_fsl_mc_device *vdev =
0244         container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
0245     unsigned int index = VFIO_FSL_MC_OFFSET_TO_INDEX(*ppos);
0246     loff_t off = *ppos & VFIO_FSL_MC_OFFSET_MASK;
0247     struct fsl_mc_device *mc_dev = vdev->mc_dev;
0248     struct vfio_fsl_mc_region *region;
0249     u64 data[8];
0250     int i;
0251 
0252     if (index >= mc_dev->obj_desc.region_count)
0253         return -EINVAL;
0254 
0255     region = &vdev->regions[index];
0256 
0257     if (!(region->flags & VFIO_REGION_INFO_FLAG_READ))
0258         return -EINVAL;
0259 
0260     if (!region->ioaddr) {
0261         region->ioaddr = ioremap(region->addr, region->size);
0262         if (!region->ioaddr)
0263             return -ENOMEM;
0264     }
0265 
0266     if (count != 64 || off != 0)
0267         return -EINVAL;
0268 
0269     for (i = 7; i >= 0; i--)
0270         data[i] = readq(region->ioaddr + i * sizeof(uint64_t));
0271 
0272     if (copy_to_user(buf, data, 64))
0273         return -EFAULT;
0274 
0275     return count;
0276 }
0277 
0278 #define MC_CMD_COMPLETION_TIMEOUT_MS    5000
0279 #define MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS    500
0280 
0281 static int vfio_fsl_mc_send_command(void __iomem *ioaddr, uint64_t *cmd_data)
0282 {
0283     int i;
0284     enum mc_cmd_status status;
0285     unsigned long timeout_usecs = MC_CMD_COMPLETION_TIMEOUT_MS * 1000;
0286 
0287     /* Write at command parameter into portal */
0288     for (i = 7; i >= 1; i--)
0289         writeq_relaxed(cmd_data[i], ioaddr + i * sizeof(uint64_t));
0290 
0291     /* Write command header in the end */
0292     writeq(cmd_data[0], ioaddr);
0293 
0294     /* Wait for response before returning to user-space
0295      * This can be optimized in future to even prepare response
0296      * before returning to user-space and avoid read ioctl.
0297      */
0298     for (;;) {
0299         u64 header;
0300         struct mc_cmd_header *resp_hdr;
0301 
0302         header = cpu_to_le64(readq_relaxed(ioaddr));
0303 
0304         resp_hdr = (struct mc_cmd_header *)&header;
0305         status = (enum mc_cmd_status)resp_hdr->status;
0306         if (status != MC_CMD_STATUS_READY)
0307             break;
0308 
0309         udelay(MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS);
0310         timeout_usecs -= MC_CMD_COMPLETION_POLLING_MAX_SLEEP_USECS;
0311         if (timeout_usecs == 0)
0312             return -ETIMEDOUT;
0313     }
0314 
0315     return 0;
0316 }
0317 
0318 static ssize_t vfio_fsl_mc_write(struct vfio_device *core_vdev,
0319                  const char __user *buf, size_t count,
0320                  loff_t *ppos)
0321 {
0322     struct vfio_fsl_mc_device *vdev =
0323         container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
0324     unsigned int index = VFIO_FSL_MC_OFFSET_TO_INDEX(*ppos);
0325     loff_t off = *ppos & VFIO_FSL_MC_OFFSET_MASK;
0326     struct fsl_mc_device *mc_dev = vdev->mc_dev;
0327     struct vfio_fsl_mc_region *region;
0328     u64 data[8];
0329     int ret;
0330 
0331     if (index >= mc_dev->obj_desc.region_count)
0332         return -EINVAL;
0333 
0334     region = &vdev->regions[index];
0335 
0336     if (!(region->flags & VFIO_REGION_INFO_FLAG_WRITE))
0337         return -EINVAL;
0338 
0339     if (!region->ioaddr) {
0340         region->ioaddr = ioremap(region->addr, region->size);
0341         if (!region->ioaddr)
0342             return -ENOMEM;
0343     }
0344 
0345     if (count != 64 || off != 0)
0346         return -EINVAL;
0347 
0348     if (copy_from_user(&data, buf, 64))
0349         return -EFAULT;
0350 
0351     ret = vfio_fsl_mc_send_command(region->ioaddr, data);
0352     if (ret)
0353         return ret;
0354 
0355     return count;
0356 
0357 }
0358 
0359 static int vfio_fsl_mc_mmap_mmio(struct vfio_fsl_mc_region region,
0360                  struct vm_area_struct *vma)
0361 {
0362     u64 size = vma->vm_end - vma->vm_start;
0363     u64 pgoff, base;
0364     u8 region_cacheable;
0365 
0366     pgoff = vma->vm_pgoff &
0367         ((1U << (VFIO_FSL_MC_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
0368     base = pgoff << PAGE_SHIFT;
0369 
0370     if (region.size < PAGE_SIZE || base + size > region.size)
0371         return -EINVAL;
0372 
0373     region_cacheable = (region.type & FSL_MC_REGION_CACHEABLE) &&
0374                (region.type & FSL_MC_REGION_SHAREABLE);
0375     if (!region_cacheable)
0376         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
0377 
0378     vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff;
0379 
0380     return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
0381                    size, vma->vm_page_prot);
0382 }
0383 
0384 static int vfio_fsl_mc_mmap(struct vfio_device *core_vdev,
0385                 struct vm_area_struct *vma)
0386 {
0387     struct vfio_fsl_mc_device *vdev =
0388         container_of(core_vdev, struct vfio_fsl_mc_device, vdev);
0389     struct fsl_mc_device *mc_dev = vdev->mc_dev;
0390     unsigned int index;
0391 
0392     index = vma->vm_pgoff >> (VFIO_FSL_MC_OFFSET_SHIFT - PAGE_SHIFT);
0393 
0394     if (vma->vm_end < vma->vm_start)
0395         return -EINVAL;
0396     if (vma->vm_start & ~PAGE_MASK)
0397         return -EINVAL;
0398     if (vma->vm_end & ~PAGE_MASK)
0399         return -EINVAL;
0400     if (!(vma->vm_flags & VM_SHARED))
0401         return -EINVAL;
0402     if (index >= mc_dev->obj_desc.region_count)
0403         return -EINVAL;
0404 
0405     if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_MMAP))
0406         return -EINVAL;
0407 
0408     if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ)
0409             && (vma->vm_flags & VM_READ))
0410         return -EINVAL;
0411 
0412     if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE)
0413             && (vma->vm_flags & VM_WRITE))
0414         return -EINVAL;
0415 
0416     vma->vm_private_data = mc_dev;
0417 
0418     return vfio_fsl_mc_mmap_mmio(vdev->regions[index], vma);
0419 }
0420 
0421 static const struct vfio_device_ops vfio_fsl_mc_ops = {
0422     .name       = "vfio-fsl-mc",
0423     .open_device    = vfio_fsl_mc_open_device,
0424     .close_device   = vfio_fsl_mc_close_device,
0425     .ioctl      = vfio_fsl_mc_ioctl,
0426     .read       = vfio_fsl_mc_read,
0427     .write      = vfio_fsl_mc_write,
0428     .mmap       = vfio_fsl_mc_mmap,
0429 };
0430 
0431 static int vfio_fsl_mc_bus_notifier(struct notifier_block *nb,
0432                     unsigned long action, void *data)
0433 {
0434     struct vfio_fsl_mc_device *vdev = container_of(nb,
0435                     struct vfio_fsl_mc_device, nb);
0436     struct device *dev = data;
0437     struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
0438     struct fsl_mc_device *mc_cont = to_fsl_mc_device(mc_dev->dev.parent);
0439 
0440     if (action == BUS_NOTIFY_ADD_DEVICE &&
0441         vdev->mc_dev == mc_cont) {
0442         mc_dev->driver_override = kasprintf(GFP_KERNEL, "%s",
0443                             vfio_fsl_mc_ops.name);
0444         if (!mc_dev->driver_override)
0445             dev_warn(dev, "VFIO_FSL_MC: Setting driver override for device in dprc %s failed\n",
0446                  dev_name(&mc_cont->dev));
0447         else
0448             dev_info(dev, "VFIO_FSL_MC: Setting driver override for device in dprc %s\n",
0449                  dev_name(&mc_cont->dev));
0450     } else if (action == BUS_NOTIFY_BOUND_DRIVER &&
0451         vdev->mc_dev == mc_cont) {
0452         struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
0453 
0454         if (mc_drv && mc_drv != &vfio_fsl_mc_driver)
0455             dev_warn(dev, "VFIO_FSL_MC: Object %s bound to driver %s while DPRC bound to vfio-fsl-mc\n",
0456                  dev_name(dev), mc_drv->driver.name);
0457     }
0458 
0459     return 0;
0460 }
0461 
0462 static int vfio_fsl_mc_init_device(struct vfio_fsl_mc_device *vdev)
0463 {
0464     struct fsl_mc_device *mc_dev = vdev->mc_dev;
0465     int ret;
0466 
0467     /* Non-dprc devices share mc_io from parent */
0468     if (!is_fsl_mc_bus_dprc(mc_dev)) {
0469         struct fsl_mc_device *mc_cont = to_fsl_mc_device(mc_dev->dev.parent);
0470 
0471         mc_dev->mc_io = mc_cont->mc_io;
0472         return 0;
0473     }
0474 
0475     vdev->nb.notifier_call = vfio_fsl_mc_bus_notifier;
0476     ret = bus_register_notifier(&fsl_mc_bus_type, &vdev->nb);
0477     if (ret)
0478         return ret;
0479 
0480     /* open DPRC, allocate a MC portal */
0481     ret = dprc_setup(mc_dev);
0482     if (ret) {
0483         dev_err(&mc_dev->dev, "VFIO_FSL_MC: Failed to setup DPRC (%d)\n", ret);
0484         goto out_nc_unreg;
0485     }
0486     return 0;
0487 
0488 out_nc_unreg:
0489     bus_unregister_notifier(&fsl_mc_bus_type, &vdev->nb);
0490     return ret;
0491 }
0492 
0493 static int vfio_fsl_mc_scan_container(struct fsl_mc_device *mc_dev)
0494 {
0495     int ret;
0496 
0497     /* non dprc devices do not scan for other devices */
0498     if (!is_fsl_mc_bus_dprc(mc_dev))
0499         return 0;
0500     ret = dprc_scan_container(mc_dev, false);
0501     if (ret) {
0502         dev_err(&mc_dev->dev,
0503             "VFIO_FSL_MC: Container scanning failed (%d)\n", ret);
0504         dprc_remove_devices(mc_dev, NULL, 0);
0505         return ret;
0506     }
0507     return 0;
0508 }
0509 
0510 static void vfio_fsl_uninit_device(struct vfio_fsl_mc_device *vdev)
0511 {
0512     struct fsl_mc_device *mc_dev = vdev->mc_dev;
0513 
0514     if (!is_fsl_mc_bus_dprc(mc_dev))
0515         return;
0516 
0517     dprc_cleanup(mc_dev);
0518     bus_unregister_notifier(&fsl_mc_bus_type, &vdev->nb);
0519 }
0520 
0521 static int vfio_fsl_mc_probe(struct fsl_mc_device *mc_dev)
0522 {
0523     struct vfio_fsl_mc_device *vdev;
0524     struct device *dev = &mc_dev->dev;
0525     int ret;
0526 
0527     vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
0528     if (!vdev)
0529         return -ENOMEM;
0530 
0531     vfio_init_group_dev(&vdev->vdev, dev, &vfio_fsl_mc_ops);
0532     vdev->mc_dev = mc_dev;
0533     mutex_init(&vdev->igate);
0534 
0535     if (is_fsl_mc_bus_dprc(mc_dev))
0536         ret = vfio_assign_device_set(&vdev->vdev, &mc_dev->dev);
0537     else
0538         ret = vfio_assign_device_set(&vdev->vdev, mc_dev->dev.parent);
0539     if (ret)
0540         goto out_uninit;
0541 
0542     ret = vfio_fsl_mc_init_device(vdev);
0543     if (ret)
0544         goto out_uninit;
0545 
0546     ret = vfio_register_group_dev(&vdev->vdev);
0547     if (ret) {
0548         dev_err(dev, "VFIO_FSL_MC: Failed to add to vfio group\n");
0549         goto out_device;
0550     }
0551 
0552     ret = vfio_fsl_mc_scan_container(mc_dev);
0553     if (ret)
0554         goto out_group_dev;
0555     dev_set_drvdata(dev, vdev);
0556     return 0;
0557 
0558 out_group_dev:
0559     vfio_unregister_group_dev(&vdev->vdev);
0560 out_device:
0561     vfio_fsl_uninit_device(vdev);
0562 out_uninit:
0563     vfio_uninit_group_dev(&vdev->vdev);
0564     kfree(vdev);
0565     return ret;
0566 }
0567 
0568 static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev)
0569 {
0570     struct device *dev = &mc_dev->dev;
0571     struct vfio_fsl_mc_device *vdev = dev_get_drvdata(dev);
0572 
0573     vfio_unregister_group_dev(&vdev->vdev);
0574     mutex_destroy(&vdev->igate);
0575 
0576     dprc_remove_devices(mc_dev, NULL, 0);
0577     vfio_fsl_uninit_device(vdev);
0578 
0579     vfio_uninit_group_dev(&vdev->vdev);
0580     kfree(vdev);
0581     return 0;
0582 }
0583 
0584 static struct fsl_mc_driver vfio_fsl_mc_driver = {
0585     .probe      = vfio_fsl_mc_probe,
0586     .remove     = vfio_fsl_mc_remove,
0587     .driver = {
0588         .name   = "vfio-fsl-mc",
0589         .owner  = THIS_MODULE,
0590     },
0591     .driver_managed_dma = true,
0592 };
0593 
0594 static int __init vfio_fsl_mc_driver_init(void)
0595 {
0596     return fsl_mc_driver_register(&vfio_fsl_mc_driver);
0597 }
0598 
0599 static void __exit vfio_fsl_mc_driver_exit(void)
0600 {
0601     fsl_mc_driver_unregister(&vfio_fsl_mc_driver);
0602 }
0603 
0604 module_init(vfio_fsl_mc_driver_init);
0605 module_exit(vfio_fsl_mc_driver_exit);
0606 
0607 MODULE_LICENSE("Dual BSD/GPL");
0608 MODULE_DESCRIPTION("VFIO for FSL-MC devices - User Level meta-driver");