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 = 43 container_of(dev->driver, struct mdev_driver, driver); 44 struct mdev_device *mdev = to_mdev_device(dev); 45 int ret; 46 47 ret = mdev_attach_iommu(mdev); 48 if (ret) 49 return ret; 50 51 if (drv->probe) { 52 ret = drv->probe(mdev); 53 if (ret) 54 mdev_detach_iommu(mdev); 55 } 56 57 return ret; 58 } 59 60 static int mdev_remove(struct device *dev) 61 { 62 struct mdev_driver *drv = 63 container_of(dev->driver, struct mdev_driver, driver); 64 struct mdev_device *mdev = to_mdev_device(dev); 65 66 if (drv->remove) 67 drv->remove(mdev); 68 69 mdev_detach_iommu(mdev); 70 71 return 0; 72 } 73 74 static int mdev_match(struct device *dev, struct device_driver *drv) 75 { 76 /* 77 * No drivers automatically match. Drivers are only bound by explicit 78 * device_driver_attach() 79 */ 80 return 0; 81 } 82 83 struct bus_type mdev_bus_type = { 84 .name = "mdev", 85 .probe = mdev_probe, 86 .remove = mdev_remove, 87 .match = mdev_match, 88 }; 89 EXPORT_SYMBOL_GPL(mdev_bus_type); 90 91 /** 92 * mdev_register_driver - register a new MDEV driver 93 * @drv: the driver to register 94 * 95 * Returns a negative value on error, otherwise 0. 96 **/ 97 int mdev_register_driver(struct mdev_driver *drv) 98 { 99 /* initialize common driver fields */ 100 drv->driver.bus = &mdev_bus_type; 101 102 /* register with core */ 103 return driver_register(&drv->driver); 104 } 105 EXPORT_SYMBOL(mdev_register_driver); 106 107 /* 108 * mdev_unregister_driver - unregister MDEV driver 109 * @drv: the driver to unregister 110 */ 111 void mdev_unregister_driver(struct mdev_driver *drv) 112 { 113 driver_unregister(&drv->driver); 114 } 115 EXPORT_SYMBOL(mdev_unregister_driver); 116 117 int mdev_bus_register(void) 118 { 119 return bus_register(&mdev_bus_type); 120 } 121 122 void mdev_bus_unregister(void) 123 { 124 bus_unregister(&mdev_bus_type); 125 } 126