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