linux/drivers/vfio/mdev/mdev_driver.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * MDEV driver
   4 *
   5 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
   6 *     Author: Neo Jia <cjia@nvidia.com>
   7 *             Kirti Wankhede <kwankhede@nvidia.com>
   8 */
   9
  10#include <linux/device.h>
  11#include <linux/iommu.h>
  12#include <linux/mdev.h>
  13
  14#include "mdev_private.h"
  15
  16static int mdev_attach_iommu(struct mdev_device *mdev)
  17{
  18        int ret;
  19        struct iommu_group *group;
  20
  21        group = iommu_group_alloc();
  22        if (IS_ERR(group))
  23                return PTR_ERR(group);
  24
  25        ret = iommu_group_add_device(group, &mdev->dev);
  26        if (!ret)
  27                dev_info(&mdev->dev, "MDEV: group_id = %d\n",
  28                         iommu_group_id(group));
  29
  30        iommu_group_put(group);
  31        return ret;
  32}
  33
  34static void mdev_detach_iommu(struct mdev_device *mdev)
  35{
  36        iommu_group_remove_device(&mdev->dev);
  37        dev_info(&mdev->dev, "MDEV: detaching iommu\n");
  38}
  39
  40static int mdev_probe(struct device *dev)
  41{
  42        struct mdev_driver *drv = to_mdev_driver(dev->driver);
  43        struct mdev_device *mdev = to_mdev_device(dev);
  44        int ret;
  45
  46        ret = mdev_attach_iommu(mdev);
  47        if (ret)
  48                return ret;
  49
  50        if (drv && drv->probe) {
  51                ret = drv->probe(dev);
  52                if (ret)
  53                        mdev_detach_iommu(mdev);
  54        }
  55
  56        return ret;
  57}
  58
  59static int mdev_remove(struct device *dev)
  60{
  61        struct mdev_driver *drv = to_mdev_driver(dev->driver);
  62        struct mdev_device *mdev = to_mdev_device(dev);
  63
  64        if (drv && drv->remove)
  65                drv->remove(dev);
  66
  67        mdev_detach_iommu(mdev);
  68
  69        return 0;
  70}
  71
  72struct bus_type mdev_bus_type = {
  73        .name           = "mdev",
  74        .probe          = mdev_probe,
  75        .remove         = mdev_remove,
  76};
  77EXPORT_SYMBOL_GPL(mdev_bus_type);
  78
  79/**
  80 * mdev_register_driver - register a new MDEV driver
  81 * @drv: the driver to register
  82 * @owner: module owner of driver to be registered
  83 *
  84 * Returns a negative value on error, otherwise 0.
  85 **/
  86int mdev_register_driver(struct mdev_driver *drv, struct module *owner)
  87{
  88        /* initialize common driver fields */
  89        drv->driver.name = drv->name;
  90        drv->driver.bus = &mdev_bus_type;
  91        drv->driver.owner = owner;
  92
  93        /* register with core */
  94        return driver_register(&drv->driver);
  95}
  96EXPORT_SYMBOL(mdev_register_driver);
  97
  98/*
  99 * mdev_unregister_driver - unregister MDEV driver
 100 * @drv: the driver to unregister
 101 */
 102void mdev_unregister_driver(struct mdev_driver *drv)
 103{
 104        driver_unregister(&drv->driver);
 105}
 106EXPORT_SYMBOL(mdev_unregister_driver);
 107
 108int mdev_bus_register(void)
 109{
 110        return bus_register(&mdev_bus_type);
 111}
 112
 113void mdev_bus_unregister(void)
 114{
 115        bus_unregister(&mdev_bus_type);
 116}
 117