From patchwork Tue Mar 14 08:48:47 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oza Pawandeep X-Patchwork-Id: 9622747 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id F2C5260244 for ; Tue, 14 Mar 2017 08:49:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E7A232850F for ; Tue, 14 Mar 2017 08:49:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DC86A2851F; Tue, 14 Mar 2017 08:49:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 720DC2850F for ; Tue, 14 Mar 2017 08:49:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Owner; bh=ms3EEImGBfU11QBLScv/awknS7168SJ22KD5K1R7LRY=; b=oAr iLt4DnR5WAGtjYSAh24+zl/jjWv/AoWe10WUdj+ncLIH6nBVmNjXxYTB+dn9ye3EAZKURrsBLXcM+ OmdF2SgQTFWQ/81IrBOZBGYYJw95RGXw67iq4C+vph39aX7KQEvturFylfIo4/9eIurmi1J+15HsK 7i7Y1yJmhBXmmOTJiyRzyWfvCB9aw7Je8POf7aB2Z5BfsocM66xIlr1pZK8ftMf+ho52gjqP2IEeh XS3kBsfId6CyQA2JuZn3T9UQCHf9t2BOl6y2vYudTbVrTH+6wSyQy7KDGNX9zipr5QNXItTWIaG9/ AUNoxgtV1Zm69dUhx2f9m6SgePkRs0Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cni9P-0001E7-6n; Tue, 14 Mar 2017 08:49:51 +0000 Received: from mail-qt0-x22c.google.com ([2607:f8b0:400d:c0d::22c]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1cni90-0001CI-63 for linux-arm-kernel@lists.infradead.org; Tue, 14 Mar 2017 08:49:28 +0000 Received: by mail-qt0-x22c.google.com with SMTP id r45so50471489qte.3 for ; Tue, 14 Mar 2017 01:49:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=from:to:cc:subject:date:message-id; bh=c2ot29WRif0300X0HRZcfhfClYb8Pda10v/SFCj/QVQ=; b=g2ba75zVagGoigYIWoopNxtrSEeF7NCJYyQGLtiyD11wkkmxpcGEvHi56Po715757j i6lpITDcOjkbTsdOxjDdY71lPwcOUKshIylARbzAni4hrKYpileQ5tMC4VKUFisR4sNW aPyJw1MXU7xl6byDOT6328MekL/WTu3ysY74s= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=c2ot29WRif0300X0HRZcfhfClYb8Pda10v/SFCj/QVQ=; b=Iu6unQtsWWHHxdr1LVIHIKnzzcxhStfJihiWn80GbFyFqG62pmikziqdUNIWIuHz36 7x43/7FP4A3zjQwAf2GGHP04GlepNN6aHPAL0tiiokmD4g1ayst7NMgGQ1jDnDsOMrj1 Pj2BjUJYxHqcS6svcBA8DxLLBG+EgmwjzmIKydqYhY7ANn9BZObI+kGqi/NZEpOBgLRz 3iHeY85zHR8kEUilLj2ma9bcKv9wqRG0GT71Bq876/kcWuVcvt3YcI3fCOwWHaTcHs12 EO4iVdZ+SrJCqH9fIFqMQVkDphJUM/j6Dgdf4kR4au4/XseCXOY6kLi8lhVndGBvQEmn u0Mw== X-Gm-Message-State: AMke39nozI2o2floHetWTcFxsI8GWM9AvjUtfz62CpY4ZYCFiLup+55AWix8uigPx67PlSfI X-Received: by 10.200.34.250 with SMTP id g55mr38109512qta.155.1489481344373; Tue, 14 Mar 2017 01:49:04 -0700 (PDT) Received: from anjanavk-OptiPlex-7010.dhcp.avagotech.net ([192.19.237.250]) by smtp.gmail.com with ESMTPSA id r30sm13955614qtc.66.2017.03.14.01.49.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 14 Mar 2017 01:49:03 -0700 (PDT) From: Oza Pawandeep To: Joerg Roedel , Robin Murphy Subject: [RFC PATCH] iommu/dma: check pci host bridge dma_mask for IOVA allocation Date: Tue, 14 Mar 2017 14:18:47 +0530 Message-Id: <1489481327-2862-1-git-send-email-oza.oza@broadcom.com> X-Mailer: git-send-email 1.9.1 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170314_014926_309642_D03B5F57 X-CRM114-Status: GOOD ( 14.18 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Oza Pawandeep , iommu@lists.linux-foundation.org, bcm-kernel-feedback-list@broadcom.com, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org 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 It is possible that PCI device supports 64-bit DMA addressing, and thus it's driver sets device's dma_mask to DMA_BIT_MASK(64), however PCI host bridge may have limitations on the inbound transaction addressing. As an example, consider NVME SSD device connected to iproc-PCIe controller. Currently, the IOMMU DMA ops only considers PCI device dma_mask when allocating an IOVA. This is particularly problematic on ARM/ARM64 SOCs where the IOMMU (i.e. SMMU) translates IOVA to PA for in-bound transactions only after PCI Host has forwarded these transactions on SOC IO bus. This means on such ARM/ARM64 SOCs the IOVA of in-bound transactions has to honor the addressing restrictions of the PCI Host. This patch tries to solve above described IOVA allocation problem by: 1. Adding iommu_get_dma_mask() to get dma_mask of any device 2. For PCI device, iommu_get_dma_mask() compare dma_mask of PCI device and corresponding PCI Host dma_mask (if set). 3. Use iommu_get_dma_mask() in IOMMU DMA ops implementation instead of dma_get_mask() Signed-off-by: Oza Pawandeep Reviewed-by: Anup Patel Reviewed-by: Scott Branden --- drivers/iommu/dma-iommu.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 48d36ce..e93e536 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -108,6 +108,42 @@ int iommu_get_dma_cookie(struct iommu_domain *domain) } EXPORT_SYMBOL(iommu_get_dma_cookie); +static u64 __iommu_dma_mask(struct device *dev, bool is_coherent) +{ +#ifdef CONFIG_PCI + u64 pci_hb_dma_mask; + + if (dev_is_pci(dev)) { + struct pci_dev *pdev = to_pci_dev(dev); + struct pci_host_bridge *br = pci_find_host_bridge(pdev->bus); + + if ((!is_coherent) && !(br->dev.dma_mask)) + goto default_dev_dma_mask; + + /* pci host bridge dma-mask. */ + pci_hb_dma_mask = (!is_coherent) ? *br->dev.dma_mask : + br->dev.coherent_dma_mask; + + if (pci_hb_dma_mask && ((pci_hb_dma_mask) < (*dev->dma_mask))) + return pci_hb_dma_mask; + } +default_dev_dma_mask: +#endif + return (!is_coherent) ? dma_get_mask(dev) : + dev->coherent_dma_mask; +} + +static u64 __iommu_dma_get_coherent_mask(struct device *dev) +{ + return __iommu_dma_mask(dev, true); +} + +static u64 __iommu_dma_get_mask(struct device *dev) +{ + return __iommu_dma_mask(dev, false); +} + + /** * iommu_get_msi_cookie - Acquire just MSI remapping resources * @domain: IOMMU domain to prepare @@ -461,7 +497,7 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp, if (!pages) return NULL; - iova = __alloc_iova(domain, size, dev->coherent_dma_mask, dev); + iova = __alloc_iova(domain, size, __iommu_dma_get_coherent_mask(dev), dev); if (!iova) goto out_free_pages; @@ -532,7 +568,7 @@ static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys, struct iova_domain *iovad = cookie_iovad(domain); size_t iova_off = iova_offset(iovad, phys); size_t len = iova_align(iovad, size + iova_off); - struct iova *iova = __alloc_iova(domain, len, dma_get_mask(dev), dev); + struct iova *iova = __alloc_iova(domain, len, __iommu_dma_get_mask(dev), dev); if (!iova) return DMA_ERROR_CODE; @@ -690,7 +726,7 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, prev = s; } - iova = __alloc_iova(domain, iova_len, dma_get_mask(dev), dev); + iova = __alloc_iova(domain, iova_len, __iommu_dma_get_mask(dev), dev); if (!iova) goto out_restore_sg; @@ -760,7 +796,7 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev, msi_page->phys = msi_addr; if (iovad) { - iova = __alloc_iova(domain, size, dma_get_mask(dev), dev); + iova = __alloc_iova(domain, size, __iommu_dma_get_mask(dev), dev); if (!iova) goto out_free_page; msi_page->iova = iova_dma_addr(iovad, iova);