From 22195cbd3451a75abaf30651a61cf85c89061327 Mon Sep 17 00:00:00 2001 From: Jike Song Date: Thu, 1 Dec 2016 13:20:05 +0800 Subject: vfio: vfio_register_notifier: classify iommu notifier Currently vfio_register_notifier assumes that there is only one notifier chain, which is in vfio_iommu. However, the user might also be interested in events other than vfio_iommu, for example, vfio_group. Refactor vfio_{un}register_notifier implementation to make it feasible. Cc: Paolo Bonzini Cc: Xiao Guangrong Reviewed-by: Kirti Wankhede Signed-off-by: Jike Song [aw: merge with commit 816ca69ea9c7 ("vfio: Fix handling of error returned by 'vfio_group_get_from_dev()'"), remove typedef] Signed-off-by: Alex Williamson --- drivers/vfio/vfio.c | 84 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 25 deletions(-) (limited to 'drivers/vfio/vfio.c') diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 7b39313abf0d..6cc2a9ffac10 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -2008,59 +2008,44 @@ err_unpin_pages: } EXPORT_SYMBOL(vfio_unpin_pages); -int vfio_register_notifier(struct device *dev, struct notifier_block *nb) +static int vfio_register_iommu_notifier(struct vfio_group *group, + unsigned long *events, + struct notifier_block *nb) { struct vfio_container *container; - struct vfio_group *group; struct vfio_iommu_driver *driver; int ret; - if (!dev || !nb) - return -EINVAL; - - group = vfio_group_get_from_dev(dev); - if (!group) - return -ENODEV; - ret = vfio_group_add_container_user(group); if (ret) - goto err_register_nb; + return -EINVAL; container = group->container; down_read(&container->group_lock); driver = container->iommu_driver; if (likely(driver && driver->ops->register_notifier)) - ret = driver->ops->register_notifier(container->iommu_data, nb); + ret = driver->ops->register_notifier(container->iommu_data, + events, nb); else ret = -ENOTTY; up_read(&container->group_lock); vfio_group_try_dissolve_container(group); -err_register_nb: - vfio_group_put(group); return ret; } -EXPORT_SYMBOL(vfio_register_notifier); -int vfio_unregister_notifier(struct device *dev, struct notifier_block *nb) +static int vfio_unregister_iommu_notifier(struct vfio_group *group, + struct notifier_block *nb) { struct vfio_container *container; - struct vfio_group *group; struct vfio_iommu_driver *driver; int ret; - if (!dev || !nb) - return -EINVAL; - - group = vfio_group_get_from_dev(dev); - if (!group) - return -ENODEV; - ret = vfio_group_add_container_user(group); if (ret) - goto err_unregister_nb; + return -EINVAL; container = group->container; down_read(&container->group_lock); @@ -2075,7 +2060,56 @@ int vfio_unregister_notifier(struct device *dev, struct notifier_block *nb) up_read(&container->group_lock); vfio_group_try_dissolve_container(group); -err_unregister_nb: + return ret; +} + +int vfio_register_notifier(struct device *dev, enum vfio_notify_type type, + unsigned long *events, struct notifier_block *nb) +{ + struct vfio_group *group; + int ret; + + if (!dev || !nb || !events || (*events == 0)) + return -EINVAL; + + group = vfio_group_get_from_dev(dev); + if (!group) + return -ENODEV; + + switch (type) { + case VFIO_IOMMU_NOTIFY: + ret = vfio_register_iommu_notifier(group, events, nb); + break; + default: + ret = -EINVAL; + } + + vfio_group_put(group); + return ret; +} +EXPORT_SYMBOL(vfio_register_notifier); + +int vfio_unregister_notifier(struct device *dev, enum vfio_notify_type type, + struct notifier_block *nb) +{ + struct vfio_group *group; + int ret; + + if (!dev || !nb) + return -EINVAL; + + group = vfio_group_get_from_dev(dev); + if (!group) + return -ENODEV; + + switch (type) { + case VFIO_IOMMU_NOTIFY: + ret = vfio_unregister_iommu_notifier(group, nb); + break; + default: + ret = -EINVAL; + } + vfio_group_put(group); return ret; } -- cgit v1.2.3-59-g8ed1b