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 16 static 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 34 static 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 40 static 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 59 static 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 72 struct bus_type mdev_bus_type = { 73 .name = "mdev", 74 .probe = mdev_probe, 75 .remove = mdev_remove, 76 }; 77 EXPORT_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 **/ 86 int 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 } 96 EXPORT_SYMBOL(mdev_register_driver); 97 98 /* 99 * mdev_unregister_driver - unregister MDEV driver 100 * @drv: the driver to unregister 101 */ 102 void mdev_unregister_driver(struct mdev_driver *drv) 103 { 104 driver_unregister(&drv->driver); 105 } 106 EXPORT_SYMBOL(mdev_unregister_driver); 107 108 int mdev_bus_register(void) 109 { 110 return bus_register(&mdev_bus_type); 111 } 112 113 void mdev_bus_unregister(void) 114 { 115 bus_unregister(&mdev_bus_type); 116 } 117