From patchwork Thu Jun 26 20:49:41 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thierry Reding X-Patchwork-Id: 4432221 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 7A2239F319 for ; Thu, 26 Jun 2014 20:52:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 91EDB20381 for ; Thu, 26 Jun 2014 20:52:57 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A7F6C20379 for ; Thu, 26 Jun 2014 20:52:56 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1X0Gcr-0001w4-5L; Thu, 26 Jun 2014 20:50:33 +0000 Received: from mail-we0-x22f.google.com ([2a00:1450:400c:c03::22f]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1X0Gcc-0000m4-KN for linux-arm-kernel@lists.infradead.org; Thu, 26 Jun 2014 20:50:20 +0000 Received: by mail-we0-f175.google.com with SMTP id k48so4363657wev.20 for ; Thu, 26 Jun 2014 13:49:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=YMYmeZ4X62cHQZsxFq+vVZi9RdpSQ/fX3V1o5qW9kWQ=; b=kdFW2m/STw3KpSR7gyMvQDrxn5Z6oe8bOAEd5rLLtUcvHUOBy3H0JOEP4FpVnGj156 yxrHEAlU+OGTkJwbJDoWXesY1HFaP3O/6qdbHe727WXdIlKd30wQYKnMq5CjKTUOywY9 jfuj/dSA2I0Zwy4w/0o/znAsyNRgURt6tnRPwmvsGffMgiLF/zfpULxkVNdltHV1w6ll MqjsytD3SzXE29vruuVG4w4A0PFHg0H2/qxOAJq18xzZumyPWkrd3bfCG00KGyT8Ee4M fL9Q58lSFdNZnzV0DaAG+FI/zSo1uFeZtwWFAOgIxGGZub1NuwEww96AhbDP3f6kk7YS zw6w== X-Received: by 10.180.84.7 with SMTP id u7mr6856181wiy.27.1403815795479; Thu, 26 Jun 2014 13:49:55 -0700 (PDT) Received: from localhost (port-12740.pppoe.wtnet.de. [84.46.49.245]) by mx.google.com with ESMTPSA id a13sm16733743wjs.12.2014.06.26.13.49.54 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 26 Jun 2014 13:49:54 -0700 (PDT) From: Thierry Reding To: Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , Kumar Gala , Stephen Warren , Arnd Bergmann , Will Deacon , Joerg Roedel Subject: [RFC 01/10] iommu: Add IOMMU device registry Date: Thu, 26 Jun 2014 22:49:41 +0200 Message-Id: <1403815790-8548-2-git-send-email-thierry.reding@gmail.com> X-Mailer: git-send-email 2.0.0 In-Reply-To: <1403815790-8548-1-git-send-email-thierry.reding@gmail.com> References: <1403815790-8548-1-git-send-email-thierry.reding@gmail.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140626_135018_838557_3AF563CE X-CRM114-Status: GOOD ( 17.80 ) X-Spam-Score: -0.8 (/) Cc: Olav Haugan , devicetree@vger.kernel.org, Grant Grundler , Rhyland Klein , iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org, Marc Zyngier , Allen Martin , Paul Walmsley , linux-tegra@vger.kernel.org, Cho KyongHo , Dave Martin , linux-arm-kernel@lists.infradead.org, Hiroshi Doyu X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Thierry Reding Add an IOMMU device registry for drivers to register with and implement a method for users of the IOMMU API to attach to an IOMMU device. This allows to support deferred probing and gives the IOMMU API a convenient hook to perform early initialization of a device if necessary. Signed-off-by: Thierry Reding --- drivers/iommu/iommu.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/iommu.h | 27 +++++++++++++++ 2 files changed, 120 insertions(+) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 806b55d056b7..5e9e82c73bbf 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -29,8 +29,12 @@ #include #include #include +#include #include +static DEFINE_MUTEX(iommus_lock); +static LIST_HEAD(iommus); + static struct kset *iommu_group_kset; static struct ida iommu_group_ida; static struct mutex iommu_group_mutex; @@ -1004,3 +1008,92 @@ int iommu_domain_set_attr(struct iommu_domain *domain, return ret; } EXPORT_SYMBOL_GPL(iommu_domain_set_attr); + +int iommu_add(struct iommu *iommu) +{ + mutex_lock(&iommus_lock); + list_add_tail(&iommu->list, &iommus); + mutex_unlock(&iommus_lock); + + return 0; +} +EXPORT_SYMBOL_GPL(iommu_add); + +void iommu_remove(struct iommu *iommu) +{ + mutex_lock(&iommus_lock); + list_del_init(&iommu->list); + mutex_unlock(&iommus_lock); +} +EXPORT_SYMBOL_GPL(iommu_remove); + +static int of_iommu_attach(struct device *dev) +{ + struct of_phandle_iter iter; + struct iommu *iommu; + + mutex_lock(&iommus_lock); + + of_property_for_each_phandle_with_args(iter, dev->of_node, "iommus", + "#iommu-cells", 0) { + bool found = false; + int err; + + /* skip disabled IOMMUs */ + if (!of_device_is_available(iter.out_args.np)) + continue; + + list_for_each_entry(iommu, &iommus, list) { + if (iommu->dev->of_node == iter.out_args.np) { + err = iommu->ops->attach(iommu, dev); + if (err < 0) { + } + + found = true; + } + } + + if (!found) { + mutex_unlock(&iommus_lock); + return -EPROBE_DEFER; + } + } + + mutex_unlock(&iommus_lock); + + return 0; +} + +static int of_iommu_detach(struct device *dev) +{ + /* TODO: implement */ + return -ENOSYS; +} + +int iommu_attach(struct device *dev) +{ + int err = 0; + + if (IS_ENABLED(CONFIG_OF) && dev->of_node) { + err = of_iommu_attach(dev); + if (!err) + return 0; + } + + return err; +} +EXPORT_SYMBOL_GPL(iommu_attach); + +int iommu_detach(struct device *dev) +{ + int err = 0; + + if (IS_ENABLED(CONFIG_OF) && dev->of_node) { + err = of_iommu_detach(dev); + if (!err) + return 0; + } + + return err; +} +EXPORT_SYMBOL_GPL(iommu_detach); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 284a4683fdc1..ac2ceef194d4 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -43,6 +43,17 @@ struct notifier_block; typedef int (*iommu_fault_handler_t)(struct iommu_domain *, struct device *, unsigned long, int, void *); +struct iommu { + struct device *dev; + + struct list_head list; + + const struct iommu_ops *ops; +}; + +int iommu_add(struct iommu *iommu); +void iommu_remove(struct iommu *iommu); + struct iommu_domain_geometry { dma_addr_t aperture_start; /* First address that can be mapped */ dma_addr_t aperture_end; /* Last address that can be mapped */ @@ -130,6 +141,9 @@ struct iommu_ops { /* Get the numer of window per domain */ u32 (*domain_get_windows)(struct iommu_domain *domain); + int (*attach)(struct iommu *iommu, struct device *dev); + int (*detach)(struct iommu *iommu, struct device *dev); + unsigned long pgsize_bitmap; }; @@ -192,6 +206,10 @@ extern int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr, phys_addr_t offset, u64 size, int prot); extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr); + +int iommu_attach(struct device *dev); +int iommu_detach(struct device *dev); + /** * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework * @domain: the iommu domain where the fault has happened @@ -396,6 +414,15 @@ static inline int iommu_domain_set_attr(struct iommu_domain *domain, return -EINVAL; } +static inline int iommu_attach(struct device *dev) +{ + return 0; +} + +static inline int iommu_detach(struct device *dev) +{ + return 0; +} #endif /* CONFIG_IOMMU_API */ #endif /* __LINUX_IOMMU_H */