1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 27b96953bSKirti Wankhede /* 37b96953bSKirti Wankhede * MDEV driver 47b96953bSKirti Wankhede * 57b96953bSKirti Wankhede * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. 67b96953bSKirti Wankhede * Author: Neo Jia <cjia@nvidia.com> 77b96953bSKirti Wankhede * Kirti Wankhede <kwankhede@nvidia.com> 87b96953bSKirti Wankhede */ 97b96953bSKirti Wankhede 107b96953bSKirti Wankhede #include <linux/device.h> 117b96953bSKirti Wankhede #include <linux/iommu.h> 127b96953bSKirti Wankhede #include <linux/mdev.h> 137b96953bSKirti Wankhede 147b96953bSKirti Wankhede #include "mdev_private.h" 157b96953bSKirti Wankhede 167b96953bSKirti Wankhede static int mdev_attach_iommu(struct mdev_device *mdev) 177b96953bSKirti Wankhede { 187b96953bSKirti Wankhede int ret; 197b96953bSKirti Wankhede struct iommu_group *group; 207b96953bSKirti Wankhede 217b96953bSKirti Wankhede group = iommu_group_alloc(); 227b96953bSKirti Wankhede if (IS_ERR(group)) 237b96953bSKirti Wankhede return PTR_ERR(group); 247b96953bSKirti Wankhede 257b96953bSKirti Wankhede ret = iommu_group_add_device(group, &mdev->dev); 267b96953bSKirti Wankhede if (!ret) 277b96953bSKirti Wankhede dev_info(&mdev->dev, "MDEV: group_id = %d\n", 287b96953bSKirti Wankhede iommu_group_id(group)); 297b96953bSKirti Wankhede 307b96953bSKirti Wankhede iommu_group_put(group); 317b96953bSKirti Wankhede return ret; 327b96953bSKirti Wankhede } 337b96953bSKirti Wankhede 347b96953bSKirti Wankhede static void mdev_detach_iommu(struct mdev_device *mdev) 357b96953bSKirti Wankhede { 367b96953bSKirti Wankhede iommu_group_remove_device(&mdev->dev); 377b96953bSKirti Wankhede dev_info(&mdev->dev, "MDEV: detaching iommu\n"); 387b96953bSKirti Wankhede } 397b96953bSKirti Wankhede 407b96953bSKirti Wankhede static int mdev_probe(struct device *dev) 417b96953bSKirti Wankhede { 42*91b9969dSJason Gunthorpe struct mdev_driver *drv = 43*91b9969dSJason Gunthorpe container_of(dev->driver, struct mdev_driver, driver); 447b96953bSKirti Wankhede struct mdev_device *mdev = to_mdev_device(dev); 457b96953bSKirti Wankhede int ret; 467b96953bSKirti Wankhede 477b96953bSKirti Wankhede ret = mdev_attach_iommu(mdev); 487b96953bSKirti Wankhede if (ret) 497b96953bSKirti Wankhede return ret; 507b96953bSKirti Wankhede 51*91b9969dSJason Gunthorpe if (drv->probe) { 522a3d15f2SJason Gunthorpe ret = drv->probe(mdev); 537b96953bSKirti Wankhede if (ret) 547b96953bSKirti Wankhede mdev_detach_iommu(mdev); 557b96953bSKirti Wankhede } 567b96953bSKirti Wankhede 577b96953bSKirti Wankhede return ret; 587b96953bSKirti Wankhede } 597b96953bSKirti Wankhede 607b96953bSKirti Wankhede static int mdev_remove(struct device *dev) 617b96953bSKirti Wankhede { 62*91b9969dSJason Gunthorpe struct mdev_driver *drv = 63*91b9969dSJason Gunthorpe container_of(dev->driver, struct mdev_driver, driver); 647b96953bSKirti Wankhede struct mdev_device *mdev = to_mdev_device(dev); 657b96953bSKirti Wankhede 66*91b9969dSJason Gunthorpe if (drv->remove) 672a3d15f2SJason Gunthorpe drv->remove(mdev); 687b96953bSKirti Wankhede 697b96953bSKirti Wankhede mdev_detach_iommu(mdev); 707b96953bSKirti Wankhede 717b96953bSKirti Wankhede return 0; 727b96953bSKirti Wankhede } 737b96953bSKirti Wankhede 747b96953bSKirti Wankhede struct bus_type mdev_bus_type = { 757b96953bSKirti Wankhede .name = "mdev", 767b96953bSKirti Wankhede .probe = mdev_probe, 777b96953bSKirti Wankhede .remove = mdev_remove, 787b96953bSKirti Wankhede }; 797b96953bSKirti Wankhede EXPORT_SYMBOL_GPL(mdev_bus_type); 807b96953bSKirti Wankhede 817b96953bSKirti Wankhede /** 827b96953bSKirti Wankhede * mdev_register_driver - register a new MDEV driver 837b96953bSKirti Wankhede * @drv: the driver to register 847b96953bSKirti Wankhede * 857b96953bSKirti Wankhede * Returns a negative value on error, otherwise 0. 867b96953bSKirti Wankhede **/ 87*91b9969dSJason Gunthorpe int mdev_register_driver(struct mdev_driver *drv) 887b96953bSKirti Wankhede { 897b96953bSKirti Wankhede /* initialize common driver fields */ 907b96953bSKirti Wankhede drv->driver.bus = &mdev_bus_type; 917b96953bSKirti Wankhede 927b96953bSKirti Wankhede /* register with core */ 937b96953bSKirti Wankhede return driver_register(&drv->driver); 947b96953bSKirti Wankhede } 957b96953bSKirti Wankhede EXPORT_SYMBOL(mdev_register_driver); 967b96953bSKirti Wankhede 977b96953bSKirti Wankhede /* 987b96953bSKirti Wankhede * mdev_unregister_driver - unregister MDEV driver 997b96953bSKirti Wankhede * @drv: the driver to unregister 1007b96953bSKirti Wankhede */ 1017b96953bSKirti Wankhede void mdev_unregister_driver(struct mdev_driver *drv) 1027b96953bSKirti Wankhede { 1037b96953bSKirti Wankhede driver_unregister(&drv->driver); 1047b96953bSKirti Wankhede } 1057b96953bSKirti Wankhede EXPORT_SYMBOL(mdev_unregister_driver); 1067b96953bSKirti Wankhede 1077b96953bSKirti Wankhede int mdev_bus_register(void) 1087b96953bSKirti Wankhede { 1097b96953bSKirti Wankhede return bus_register(&mdev_bus_type); 1107b96953bSKirti Wankhede } 1117b96953bSKirti Wankhede 1127b96953bSKirti Wankhede void mdev_bus_unregister(void) 1137b96953bSKirti Wankhede { 1147b96953bSKirti Wankhede bus_unregister(&mdev_bus_type); 1157b96953bSKirti Wankhede } 116