1*d2912cb1SThomas 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 { 427b96953bSKirti Wankhede struct mdev_driver *drv = to_mdev_driver(dev->driver); 437b96953bSKirti Wankhede struct mdev_device *mdev = to_mdev_device(dev); 447b96953bSKirti Wankhede int ret; 457b96953bSKirti Wankhede 467b96953bSKirti Wankhede ret = mdev_attach_iommu(mdev); 477b96953bSKirti Wankhede if (ret) 487b96953bSKirti Wankhede return ret; 497b96953bSKirti Wankhede 507b96953bSKirti Wankhede if (drv && drv->probe) { 517b96953bSKirti Wankhede ret = drv->probe(dev); 527b96953bSKirti Wankhede if (ret) 537b96953bSKirti Wankhede mdev_detach_iommu(mdev); 547b96953bSKirti Wankhede } 557b96953bSKirti Wankhede 567b96953bSKirti Wankhede return ret; 577b96953bSKirti Wankhede } 587b96953bSKirti Wankhede 597b96953bSKirti Wankhede static int mdev_remove(struct device *dev) 607b96953bSKirti Wankhede { 617b96953bSKirti Wankhede struct mdev_driver *drv = to_mdev_driver(dev->driver); 627b96953bSKirti Wankhede struct mdev_device *mdev = to_mdev_device(dev); 637b96953bSKirti Wankhede 647b96953bSKirti Wankhede if (drv && drv->remove) 657b96953bSKirti Wankhede drv->remove(dev); 667b96953bSKirti Wankhede 677b96953bSKirti Wankhede mdev_detach_iommu(mdev); 687b96953bSKirti Wankhede 697b96953bSKirti Wankhede return 0; 707b96953bSKirti Wankhede } 717b96953bSKirti Wankhede 727b96953bSKirti Wankhede struct bus_type mdev_bus_type = { 737b96953bSKirti Wankhede .name = "mdev", 747b96953bSKirti Wankhede .probe = mdev_probe, 757b96953bSKirti Wankhede .remove = mdev_remove, 767b96953bSKirti Wankhede }; 777b96953bSKirti Wankhede EXPORT_SYMBOL_GPL(mdev_bus_type); 787b96953bSKirti Wankhede 797b96953bSKirti Wankhede /** 807b96953bSKirti Wankhede * mdev_register_driver - register a new MDEV driver 817b96953bSKirti Wankhede * @drv: the driver to register 827b96953bSKirti Wankhede * @owner: module owner of driver to be registered 837b96953bSKirti Wankhede * 847b96953bSKirti Wankhede * Returns a negative value on error, otherwise 0. 857b96953bSKirti Wankhede **/ 867b96953bSKirti Wankhede int mdev_register_driver(struct mdev_driver *drv, struct module *owner) 877b96953bSKirti Wankhede { 887b96953bSKirti Wankhede /* initialize common driver fields */ 897b96953bSKirti Wankhede drv->driver.name = drv->name; 907b96953bSKirti Wankhede drv->driver.bus = &mdev_bus_type; 917b96953bSKirti Wankhede drv->driver.owner = owner; 927b96953bSKirti Wankhede 937b96953bSKirti Wankhede /* register with core */ 947b96953bSKirti Wankhede return driver_register(&drv->driver); 957b96953bSKirti Wankhede } 967b96953bSKirti Wankhede EXPORT_SYMBOL(mdev_register_driver); 977b96953bSKirti Wankhede 987b96953bSKirti Wankhede /* 997b96953bSKirti Wankhede * mdev_unregister_driver - unregister MDEV driver 1007b96953bSKirti Wankhede * @drv: the driver to unregister 1017b96953bSKirti Wankhede */ 1027b96953bSKirti Wankhede void mdev_unregister_driver(struct mdev_driver *drv) 1037b96953bSKirti Wankhede { 1047b96953bSKirti Wankhede driver_unregister(&drv->driver); 1057b96953bSKirti Wankhede } 1067b96953bSKirti Wankhede EXPORT_SYMBOL(mdev_unregister_driver); 1077b96953bSKirti Wankhede 1087b96953bSKirti Wankhede int mdev_bus_register(void) 1097b96953bSKirti Wankhede { 1107b96953bSKirti Wankhede return bus_register(&mdev_bus_type); 1117b96953bSKirti Wankhede } 1127b96953bSKirti Wankhede 1137b96953bSKirti Wankhede void mdev_bus_unregister(void) 1147b96953bSKirti Wankhede { 1157b96953bSKirti Wankhede bus_unregister(&mdev_bus_type); 1167b96953bSKirti Wankhede } 117