From patchwork Fri Mar 30 16:03:49 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Omar Ramirez Luna X-Patchwork-Id: 7551 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 1C0F923E13 for ; Fri, 30 Mar 2012 16:03:59 +0000 (UTC) Received: from mail-gx0-f180.google.com (mail-gx0-f180.google.com [209.85.161.180]) by fiordland.canonical.com (Postfix) with ESMTP id D1871A180D0 for ; Fri, 30 Mar 2012 16:03:58 +0000 (UTC) Received: by mail-gx0-f180.google.com with SMTP id u1so501325ggl.11 for ; Fri, 30 Mar 2012 09:03:58 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf :mime-version:from:to:cc:subject:date:message-id:x-mailer :x-gm-message-state; bh=fNGdB5kG8RhetniOfoovIxBsN7Gph1tUC2BDqamtc/Q=; b=LXsLJDkUN1TwRYvCJjGG+jnNaLPH4wSvsMIK8ek8xz42JmfFPsq7fVmgvdK6nas/kX cQgzJjJppu4mylG6iOISSch28SnpVUlnn6Srv5+OVXjC0yRtSz/ZlVIzRwwRaCSUZVlR Qe1tSiAbCI9HnuzGLdzfzM7x+716EYT0azZ1YwOQAnuxNHmWv7UfoVGDHJSwzmvEO/fN at0HfVOjjImETmYWNJ8l03ZJ4x+PSPbErbdbWssxo5rW3OPuQ5LCaDxByuNl/u6ocnfe g9QqXCUo/yC3QzYflC6fCXUaxRQqXvOTfjSnUuE77e4wskXASprNiOhMVV4J/NnNbLTo lnxA== Received: by 10.50.186.161 with SMTP id fl1mr1770106igc.44.1333123438416; Fri, 30 Mar 2012 09:03:58 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.5.205 with SMTP id 13csp2994ibw; Fri, 30 Mar 2012 09:03:57 -0700 (PDT) Received: by 10.236.183.165 with SMTP id q25mr2413901yhm.95.1333123437289; Fri, 30 Mar 2012 09:03:57 -0700 (PDT) Received: from mail-gx0-f178.google.com (mail-gx0-f178.google.com [209.85.161.178]) by mx.google.com with ESMTPS id d67si10280192yhh.128.2012.03.30.09.03.57 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 30 Mar 2012 09:03:57 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.161.178 is neither permitted nor denied by best guess record for domain of omar.luna@linaro.org) client-ip=209.85.161.178; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.161.178 is neither permitted nor denied by best guess record for domain of omar.luna@linaro.org) smtp.mail=omar.luna@linaro.org Received: by ggno1 with SMTP id o1so496822ggn.37 for ; Fri, 30 Mar 2012 09:03:57 -0700 (PDT) MIME-Version: 1.0 Received: by 10.60.4.162 with SMTP id l2mr3863891oel.3.1333123436937; Fri, 30 Mar 2012 09:03:56 -0700 (PDT) Received: from localhost.localdomain (dragon.ti.com. [192.94.94.33]) by mx.google.com with ESMTPS id t5sm7583816oef.10.2012.03.30.09.03.55 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 30 Mar 2012 09:03:56 -0700 (PDT) From: Omar Ramirez Luna To: Joerg Roedel Cc: Ohad Ben-Cohen , Tony Lindgren , Laurent Pinchart , iommu@lists.linux-foundation.org, linux-omap@vger.kernel.org, linux-arm-kernel@lists.infradead.org, patches@linaro.org, linaro-dev@lists.linaro.org, Omar Ramirez Luna Subject: [PATCH] iommu: OMAP: device detach on domain destroy Date: Fri, 30 Mar 2012 11:03:49 -0500 Message-Id: <1333123429-3727-1-git-send-email-omar.luna@linaro.org> X-Mailer: git-send-email 1.7.4.1 X-Gm-Message-State: ALoCoQmfpJHWX76Uq2nsSeUrA0+J4IrSWbGZWE7MOu45BOo02Hq2zdvjxhRiR0c51xRr806E/Ta9 'domain_destroy with devices attached' case isn't yet handled, instead code assumes that the device was already detached. If the domain is destroyed the hardware still has access to invalid pointers to its page table and internal iommu object. In order to detach the users we need to track devices using the iommu, current use cases only have one user of iommu per instance. When required this can evolve to a list with the devices using the iommu_dev. Reported-by: Joerg Roedel Reviewed-by: Ohad Ben-Cohen Signed-off-by: Omar Ramirez Luna --- drivers/iommu/omap-iommu.c | 32 +++++++++++++++++++++++--------- 1 files changed, 23 insertions(+), 9 deletions(-) diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 821062a..e32bd15 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c @@ -41,11 +41,13 @@ * @pgtable: the page table * @iommu_dev: an omap iommu device attached to this domain. only a single * iommu device can be attached for now. + * @dev: Device using this domain. * @lock: domain lock, should be taken when attaching/detaching */ struct omap_iommu_domain { u32 *pgtable; struct omap_iommu *iommu_dev; + struct device *dev; spinlock_t lock; }; @@ -1074,6 +1076,7 @@ omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev) } omap_domain->iommu_dev = arch_data->iommu_dev = oiommu; + omap_domain->dev = dev; oiommu->domain = domain; /* temporary workaround */ @@ -1084,19 +1087,16 @@ out: return ret; } -static void omap_iommu_detach_dev(struct iommu_domain *domain, - struct device *dev) +static void _omap_iommu_detach_dev(struct omap_iommu_domain *omap_domain, + struct device *dev) { - struct omap_iommu_domain *omap_domain = domain->priv; - struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; struct omap_iommu *oiommu = dev_to_omap_iommu(dev); - - spin_lock(&omap_domain->lock); + struct omap_iommu_arch_data *arch_data = dev->archdata.iommu; /* only a single device is supported per domain for now */ if (omap_domain->iommu_dev != oiommu) { dev_err(dev, "invalid iommu device\n"); - goto out; + return; } iopgtable_clear_entry_all(oiommu); @@ -1104,11 +1104,19 @@ static void omap_iommu_detach_dev(struct iommu_domain *domain, omap_iommu_detach(oiommu); omap_domain->iommu_dev = arch_data->iommu_dev = NULL; + omap_domain->dev = NULL; /* temporary workaround */ clk_disable(oiommu->clk); +} -out: +static void omap_iommu_detach_dev(struct iommu_domain *domain, + struct device *dev) +{ + struct omap_iommu_domain *omap_domain = domain->priv; + + spin_lock(&omap_domain->lock); + _omap_iommu_detach_dev(omap_domain, dev); spin_unlock(&omap_domain->lock); } @@ -1147,13 +1155,19 @@ out: return -ENOMEM; } -/* assume device was already detached */ static void omap_iommu_domain_destroy(struct iommu_domain *domain) { struct omap_iommu_domain *omap_domain = domain->priv; domain->priv = NULL; + /* + * An iommu device is still attached + * (currently, only one device can be attached) ? + */ + if (omap_domain->iommu_dev) + _omap_iommu_detach_dev(omap_domain, omap_domain->dev); + kfree(omap_domain->pgtable); kfree(omap_domain); }