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 { 4291b9969dSJason Gunthorpe struct mdev_driver *drv = 4391b9969dSJason 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 5191b9969dSJason 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 { 6291b9969dSJason Gunthorpe struct mdev_driver *drv = 6391b9969dSJason Gunthorpe container_of(dev->driver, struct mdev_driver, driver); 647b96953bSKirti Wankhede struct mdev_device *mdev = to_mdev_device(dev); 657b96953bSKirti Wankhede 6691b9969dSJason 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 74*88a21f26SJason Gunthorpe static int mdev_match(struct device *dev, struct device_driver *drv) 75*88a21f26SJason Gunthorpe { 76*88a21f26SJason Gunthorpe /* 77*88a21f26SJason Gunthorpe * No drivers automatically match. Drivers are only bound by explicit 78*88a21f26SJason Gunthorpe * device_driver_attach() 79*88a21f26SJason Gunthorpe */ 80*88a21f26SJason Gunthorpe return 0; 81*88a21f26SJason Gunthorpe } 82*88a21f26SJason Gunthorpe 837b96953bSKirti Wankhede struct bus_type mdev_bus_type = { 847b96953bSKirti Wankhede .name = "mdev", 857b96953bSKirti Wankhede .probe = mdev_probe, 867b96953bSKirti Wankhede .remove = mdev_remove, 87*88a21f26SJason Gunthorpe .match = mdev_match, 887b96953bSKirti Wankhede }; 897b96953bSKirti Wankhede EXPORT_SYMBOL_GPL(mdev_bus_type); 907b96953bSKirti Wankhede 917b96953bSKirti Wankhede /** 927b96953bSKirti Wankhede * mdev_register_driver - register a new MDEV driver 937b96953bSKirti Wankhede * @drv: the driver to register 947b96953bSKirti Wankhede * 957b96953bSKirti Wankhede * Returns a negative value on error, otherwise 0. 967b96953bSKirti Wankhede **/ 9791b9969dSJason Gunthorpe int mdev_register_driver(struct mdev_driver *drv) 987b96953bSKirti Wankhede { 997b96953bSKirti Wankhede /* initialize common driver fields */ 1007b96953bSKirti Wankhede drv->driver.bus = &mdev_bus_type; 1017b96953bSKirti Wankhede 1027b96953bSKirti Wankhede /* register with core */ 1037b96953bSKirti Wankhede return driver_register(&drv->driver); 1047b96953bSKirti Wankhede } 1057b96953bSKirti Wankhede EXPORT_SYMBOL(mdev_register_driver); 1067b96953bSKirti Wankhede 1077b96953bSKirti Wankhede /* 1087b96953bSKirti Wankhede * mdev_unregister_driver - unregister MDEV driver 1097b96953bSKirti Wankhede * @drv: the driver to unregister 1107b96953bSKirti Wankhede */ 1117b96953bSKirti Wankhede void mdev_unregister_driver(struct mdev_driver *drv) 1127b96953bSKirti Wankhede { 1137b96953bSKirti Wankhede driver_unregister(&drv->driver); 1147b96953bSKirti Wankhede } 1157b96953bSKirti Wankhede EXPORT_SYMBOL(mdev_unregister_driver); 1167b96953bSKirti Wankhede 1177b96953bSKirti Wankhede int mdev_bus_register(void) 1187b96953bSKirti Wankhede { 1197b96953bSKirti Wankhede return bus_register(&mdev_bus_type); 1207b96953bSKirti Wankhede } 1217b96953bSKirti Wankhede 1227b96953bSKirti Wankhede void mdev_bus_unregister(void) 1237b96953bSKirti Wankhede { 1247b96953bSKirti Wankhede bus_unregister(&mdev_bus_type); 1257b96953bSKirti Wankhede } 126