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