From patchwork Fri Mar 25 15:18:02 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sakari Ailus X-Patchwork-Id: 662691 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p2PFIVoZ006153 for ; Fri, 25 Mar 2011 15:18:39 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752786Ab1CYPSV (ORCPT ); Fri, 25 Mar 2011 11:18:21 -0400 Received: from smtp.nokia.com ([147.243.1.47]:58307 "EHLO mgw-sa01.nokia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752438Ab1CYPSV (ORCPT ); Fri, 25 Mar 2011 11:18:21 -0400 Received: from nokia.com (localhost [127.0.0.1]) by mgw-sa01.nokia.com (Switch-3.4.3/Switch-3.4.3) with ESMTP id p2PFIISa012975; Fri, 25 Mar 2011 17:18:18 +0200 Received: from maxwell.research.nokia.com ([maxwell.research.nokia.com [172.21.50.162]]) by mgw-sa01.nokia.com with ESMTP id p2PFI2VM012757 ; Fri, 25 Mar 2011 17:18:03 +0200 Received: from kaali.localdomain (kaali.localdomain [192.168.239.7]) by maxwell.research.nokia.com (Postfix) with ESMTPS id 6197D3861EA; Fri, 25 Mar 2011 17:18:02 +0200 (EET) Received: from sailus by kaali.localdomain with local (Exim 4.72) (envelope-from ) id 1Q38m2-00026W-AW; Fri, 25 Mar 2011 17:18:02 +0200 From: Sakari Ailus To: linux-omap@vger.kernel.org Cc: laurent.pinchart@ideasonboard.com, david.cohen@nokia.com, hiroshi.doyu@nokia.com Subject: [PATCH 4/4] omap iommu: Prevent iommu implementations from being unloaded while in use Date: Fri, 25 Mar 2011 17:18:02 +0200 Message-Id: <1301066282-8040-4-git-send-email-sakari.ailus@maxwell.research.nokia.com> X-Mailer: git-send-email 1.7.2.3 In-Reply-To: <4D8CB217.1050909@maxwell.research.nokia.com> References: <4D8CB217.1050909@maxwell.research.nokia.com> X-Nokia-AV: Clean Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 25 Mar 2011 15:18:39 +0000 (UTC) diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c index f0fea0b..430ed94 100644 --- a/arch/arm/plat-omap/iommu.c +++ b/arch/arm/plat-omap/iommu.c @@ -35,6 +35,7 @@ static const struct iommu_functions *arch_iommu; static struct platform_driver omap_iommu_driver; static struct kmem_cache *iopte_cachep; +static struct mutex arch_iommu_mutex; /** * install_iommu_arch - Install archtecure specific iommu functions @@ -45,10 +46,17 @@ static struct kmem_cache *iopte_cachep; **/ int install_iommu_arch(const struct iommu_functions *ops) { - if (arch_iommu) + mutex_lock(&arch_iommu_mutex); + + if (arch_iommu) { + mutex_unlock(&arch_iommu_mutex); return -EBUSY; + } arch_iommu = ops; + + mutex_unlock(&arch_iommu_mutex); + return 0; } EXPORT_SYMBOL_GPL(install_iommu_arch); @@ -58,13 +66,22 @@ EXPORT_SYMBOL_GPL(install_iommu_arch); * @ops: a pointer to architecture specific iommu functions * * This interface uninstalls the iommu algorighm installed previously. + * + * Note: This function may only be called at module_exit() function of + * a module which implements arch_iommu. Otherwise another mechanism + * from the module use count only to ensure the arch_iommu stays there + * has to be implemented. **/ void uninstall_iommu_arch(const struct iommu_functions *ops) { + mutex_lock(&arch_iommu_mutex); + if (arch_iommu != ops) pr_err("%s: not your arch\n", __func__); arch_iommu = NULL; + + mutex_unlock(&arch_iommu_mutex); } EXPORT_SYMBOL_GPL(uninstall_iommu_arch); @@ -104,14 +121,20 @@ static int iommu_enable(struct iommu *obj) if (!obj) return -EINVAL; - if (!arch_iommu) + mutex_lock(&arch_iommu_mutex); + if (!arch_iommu || !try_module_get(arch_iommu->module)) { + mutex_unlock(&arch_iommu_mutex); return -ENOENT; + } clk_enable(obj->clk); err = arch_iommu->enable(obj); clk_disable(obj->clk); + + mutex_unlock(&arch_iommu_mutex); + return err; } @@ -125,6 +148,8 @@ static void iommu_disable(struct iommu *obj) arch_iommu->disable(obj); clk_disable(obj->clk); + + module_put(arch_iommu->module); } /* @@ -1058,6 +1083,8 @@ static int __init omap_iommu_init(void) return -ENOMEM; iopte_cachep = p; + mutex_init(&arch_iommu_mutex); + return platform_driver_register(&omap_iommu_driver); } module_init(omap_iommu_init);