From patchwork Tue Apr 5 21:01:29 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mitchel Humpherys X-Patchwork-Id: 8755131 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 2B701C0553 for ; Tue, 5 Apr 2016 21:03:47 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2EB702034C for ; Tue, 5 Apr 2016 21:03:46 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3377B20306 for ; Tue, 5 Apr 2016 21:03:45 +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 1anY6o-0003p0-U9; Tue, 05 Apr 2016 21:01:58 +0000 Received: from smtp.codeaurora.org ([198.145.29.96]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1anY6e-0003fn-Mq for linux-arm-kernel@lists.infradead.org; Tue, 05 Apr 2016 21:01:49 +0000 Received: from smtp.codeaurora.org (localhost [127.0.0.1]) by smtp.codeaurora.org (Postfix) with ESMTP id A5ABB6160A; Tue, 5 Apr 2016 21:01:27 +0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 99ABF615D6; Tue, 5 Apr 2016 21:01:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from mitchelh-linux.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: mitchelh@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id ACE8660269; Tue, 5 Apr 2016 21:01:26 +0000 (UTC) From: Mitchel Humpherys To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org, Joerg Roedel , Robin Murphy , Will Deacon Subject: [PATCH 1/2] iommu: Support dynamic pgsize_bitmap Date: Tue, 5 Apr 2016 14:01:29 -0700 Message-Id: <1459890090-16040-1-git-send-email-mitchelh@codeaurora.org> X-Mailer: git-send-email 2.8.0 X-Virus-Scanned: ClamAV using ClamSMTP X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160405_140148_825866_B9E9EBAF X-CRM114-Status: GOOD ( 18.04 ) X-Spam-Score: -2.9 (--) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Mitchel Humpherys , Pratik Patel MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Currently we use a single pgsize_bitmap per IOMMU driver. However, some IOMMU drivers might service different IOMMUs with different supported page sizes. Some drivers might also want to restrict page sizes for different use cases. Support these use cases by adding a .get_pgsize_bitmap function to the iommu_ops which can optionally be used by the driver to return a domain-specific pgsize_bitmap. Signed-off-by: Mitchel Humpherys --- drivers/iommu/iommu.c | 28 +++++++++++++++++++--------- include/linux/iommu.h | 3 +++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index bfd4f7c3b1d8..6141710f3091 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -325,6 +325,13 @@ int iommu_group_set_name(struct iommu_group *group, const char *name) } EXPORT_SYMBOL_GPL(iommu_group_set_name); +static unsigned long iommu_get_pgsize_bitmap(struct iommu_domain *domain) +{ + if (domain->ops->get_pgsize_bitmap) + return domain->ops->get_pgsize_bitmap(domain); + return domain->ops->pgsize_bitmap; +} + static int iommu_group_create_direct_mappings(struct iommu_group *group, struct device *dev) { @@ -337,9 +344,9 @@ static int iommu_group_create_direct_mappings(struct iommu_group *group, if (!domain || domain->type != IOMMU_DOMAIN_DMA) return 0; - BUG_ON(!domain->ops->pgsize_bitmap); + BUG_ON(!(domain->ops->pgsize_bitmap || domain->ops->get_pgsize_bitmap)); - pg_size = 1UL << __ffs(domain->ops->pgsize_bitmap); + pg_size = 1UL << __ffs(iommu_get_pgsize_bitmap(domain)); INIT_LIST_HEAD(&mappings); iommu_get_dm_regions(dev, &mappings); @@ -1318,14 +1325,15 @@ int iommu_map(struct iommu_domain *domain, unsigned long iova, int ret = 0; if (unlikely(domain->ops->map == NULL || - domain->ops->pgsize_bitmap == 0UL)) + (domain->ops->pgsize_bitmap == 0UL && + !domain->ops->get_pgsize_bitmap))) return -ENODEV; if (unlikely(!(domain->type & __IOMMU_DOMAIN_PAGING))) return -EINVAL; /* find out the minimum page size supported */ - min_pagesz = 1 << __ffs(domain->ops->pgsize_bitmap); + min_pagesz = 1 << __ffs(iommu_get_pgsize_bitmap(domain)); /* * both the virtual address and the physical one, as well as @@ -1372,14 +1380,15 @@ size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size) unsigned long orig_iova = iova; if (unlikely(domain->ops->unmap == NULL || - domain->ops->pgsize_bitmap == 0UL)) + (domain->ops->pgsize_bitmap == 0UL && + !domain->ops->get_pgsize_bitmap))) return -ENODEV; if (unlikely(!(domain->type & __IOMMU_DOMAIN_PAGING))) return -EINVAL; /* find out the minimum page size supported */ - min_pagesz = 1 << __ffs(domain->ops->pgsize_bitmap); + min_pagesz = 1 << __ffs(iommu_get_pgsize_bitmap(domain)); /* * The virtual address, as well as the size of the mapping, must be @@ -1425,10 +1434,11 @@ size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova, unsigned int i, min_pagesz; int ret; - if (unlikely(domain->ops->pgsize_bitmap == 0UL)) + if (unlikely(domain->ops->pgsize_bitmap == 0UL && + !domain->ops->get_pgsize_bitmap)) return 0; - min_pagesz = 1 << __ffs(domain->ops->pgsize_bitmap); + min_pagesz = 1 << __ffs(iommu_get_pgsize_bitmap(domain)); for_each_sg(sg, s, nents, i) { phys_addr_t phys = page_to_phys(sg_page(s)) + s->offset; @@ -1509,7 +1519,7 @@ int iommu_domain_get_attr(struct iommu_domain *domain, break; case DOMAIN_ATTR_PAGING: paging = data; - *paging = (domain->ops->pgsize_bitmap != 0UL); + *paging = (iommu_get_pgsize_bitmap(domain) != 0UL); break; case DOMAIN_ATTR_WINDOWS: count = data; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index a5c539fa5d2b..03f8d50670db 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -156,6 +156,8 @@ struct iommu_dm_region { * @domain_get_windows: Return the number of windows for a domain * @of_xlate: add OF master IDs to iommu grouping * @pgsize_bitmap: bitmap of supported page sizes + * @get_pgsize_bitmap: gets a bitmap of supported page sizes for a domain + * This takes precedence over @pgsize_bitmap. * @priv: per-instance data private to the iommu driver */ struct iommu_ops { @@ -200,6 +202,7 @@ struct iommu_ops { #endif unsigned long pgsize_bitmap; + unsigned long (*get_pgsize_bitmap)(struct iommu_domain *domain); void *priv; };