From: Will Deacon Date: Thu, 19 Dec 2019 12:03:41 +0000 (+0000) Subject: drivers/iommu: Take a ref to the IOMMU driver prior to ->add_device() X-Git-Tag: v5.15~4539^2^2~12 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=25f003de987aed630db265ceae9cd978537a3f80;p=platform%2Fkernel%2Flinux-starfive.git drivers/iommu: Take a ref to the IOMMU driver prior to ->add_device() To avoid accidental removal of an active IOMMU driver module, take a reference to the driver module in 'iommu_probe_device()' immediately prior to invoking the '->add_device()' callback and hold it until the after the device has been removed by '->remove_device()'. Suggested-by: Joerg Roedel Signed-off-by: Will Deacon Tested-by: John Garry # smmu v3 Reviewed-by: Greg Kroah-Hartman Signed-off-by: Joerg Roedel --- diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 3abe19e..32ceda1 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -22,6 +22,7 @@ #include #include #include +#include #include static struct kset *iommu_group_kset; @@ -185,10 +186,21 @@ int iommu_probe_device(struct device *dev) if (!iommu_get_dev_param(dev)) return -ENOMEM; + if (!try_module_get(ops->owner)) { + ret = -EINVAL; + goto err_free_dev_param; + } + ret = ops->add_device(dev); if (ret) - iommu_free_dev_param(dev); + goto err_module_put; + + return 0; +err_module_put: + module_put(ops->owner); +err_free_dev_param: + iommu_free_dev_param(dev); return ret; } @@ -199,7 +211,10 @@ void iommu_release_device(struct device *dev) if (dev->iommu_group) ops->remove_device(dev); - iommu_free_dev_param(dev); + if (dev->iommu_param) { + module_put(ops->owner); + iommu_free_dev_param(dev); + } } static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus, diff --git a/include/linux/iommu.h b/include/linux/iommu.h index f2223cb..e9f94d3 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -246,9 +246,10 @@ struct iommu_iotlb_gather { * @sva_get_pasid: Get PASID associated to a SVA handle * @page_response: handle page request response * @cache_invalidate: invalidate translation caches - * @pgsize_bitmap: bitmap of all possible supported page sizes * @sva_bind_gpasid: bind guest pasid and mm * @sva_unbind_gpasid: unbind guest pasid and mm + * @pgsize_bitmap: bitmap of all possible supported page sizes + * @owner: Driver module providing these ops */ struct iommu_ops { bool (*capable)(enum iommu_cap); @@ -318,6 +319,7 @@ struct iommu_ops { int (*sva_unbind_gpasid)(struct device *dev, int pasid); unsigned long pgsize_bitmap; + struct module *owner; }; /**