128 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2013 - Virtual Open Systems4 * Author: Antonios Motakis <a.motakis@virtualopensystems.com>5 */6 7#include <linux/module.h>8#include <linux/slab.h>9#include <linux/vfio.h>10#include <linux/pm_runtime.h>11#include <linux/platform_device.h>12 13#include "vfio_platform_private.h"14 15#define DRIVER_VERSION "0.10"16#define DRIVER_AUTHOR "Antonios Motakis <a.motakis@virtualopensystems.com>"17#define DRIVER_DESC "VFIO for platform devices - User Level meta-driver"18 19static bool reset_required = true;20module_param(reset_required, bool, 0444);21MODULE_PARM_DESC(reset_required, "override reset requirement (default: 1)");22 23/* probing devices from the linux platform bus */24 25static struct resource *get_platform_resource(struct vfio_platform_device *vdev,26 int num)27{28 struct platform_device *dev = (struct platform_device *) vdev->opaque;29 30 return platform_get_mem_or_io(dev, num);31}32 33static int get_platform_irq(struct vfio_platform_device *vdev, int i)34{35 struct platform_device *pdev = (struct platform_device *) vdev->opaque;36 37 return platform_get_irq_optional(pdev, i);38}39 40static int vfio_platform_init_dev(struct vfio_device *core_vdev)41{42 struct vfio_platform_device *vdev =43 container_of(core_vdev, struct vfio_platform_device, vdev);44 struct platform_device *pdev = to_platform_device(core_vdev->dev);45 46 vdev->opaque = (void *) pdev;47 vdev->name = pdev->name;48 vdev->flags = VFIO_DEVICE_FLAGS_PLATFORM;49 vdev->get_resource = get_platform_resource;50 vdev->get_irq = get_platform_irq;51 vdev->reset_required = reset_required;52 53 return vfio_platform_init_common(vdev);54}55 56static const struct vfio_device_ops vfio_platform_ops;57static int vfio_platform_probe(struct platform_device *pdev)58{59 struct vfio_platform_device *vdev;60 int ret;61 62 vdev = vfio_alloc_device(vfio_platform_device, vdev, &pdev->dev,63 &vfio_platform_ops);64 if (IS_ERR(vdev))65 return PTR_ERR(vdev);66 67 ret = vfio_register_group_dev(&vdev->vdev);68 if (ret)69 goto out_put_vdev;70 71 pm_runtime_enable(&pdev->dev);72 dev_set_drvdata(&pdev->dev, vdev);73 return 0;74 75out_put_vdev:76 vfio_put_device(&vdev->vdev);77 return ret;78}79 80static void vfio_platform_release_dev(struct vfio_device *core_vdev)81{82 struct vfio_platform_device *vdev =83 container_of(core_vdev, struct vfio_platform_device, vdev);84 85 vfio_platform_release_common(vdev);86}87 88static void vfio_platform_remove(struct platform_device *pdev)89{90 struct vfio_platform_device *vdev = dev_get_drvdata(&pdev->dev);91 92 vfio_unregister_group_dev(&vdev->vdev);93 pm_runtime_disable(vdev->device);94 vfio_put_device(&vdev->vdev);95}96 97static const struct vfio_device_ops vfio_platform_ops = {98 .name = "vfio-platform",99 .init = vfio_platform_init_dev,100 .release = vfio_platform_release_dev,101 .open_device = vfio_platform_open_device,102 .close_device = vfio_platform_close_device,103 .ioctl = vfio_platform_ioctl,104 .read = vfio_platform_read,105 .write = vfio_platform_write,106 .mmap = vfio_platform_mmap,107 .bind_iommufd = vfio_iommufd_physical_bind,108 .unbind_iommufd = vfio_iommufd_physical_unbind,109 .attach_ioas = vfio_iommufd_physical_attach_ioas,110 .detach_ioas = vfio_iommufd_physical_detach_ioas,111};112 113static struct platform_driver vfio_platform_driver = {114 .probe = vfio_platform_probe,115 .remove_new = vfio_platform_remove,116 .driver = {117 .name = "vfio-platform",118 },119 .driver_managed_dma = true,120};121 122module_platform_driver(vfio_platform_driver);123 124MODULE_VERSION(DRIVER_VERSION);125MODULE_LICENSE("GPL v2");126MODULE_AUTHOR(DRIVER_AUTHOR);127MODULE_DESCRIPTION(DRIVER_DESC);128