From patchwork Wed Nov 11 14:54:16 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robin Murphy X-Patchwork-Id: 7596181 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 2F8F6BF90C for ; Wed, 11 Nov 2015 14:58:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 719052066E for ; Wed, 11 Nov 2015 14:58:14 +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 8079E205E2 for ; Wed, 11 Nov 2015 14:58:13 +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 1ZwWnq-0007J2-Uy; Wed, 11 Nov 2015 14:55:14 +0000 Received: from eu-smtp-delivery-143.mimecast.com ([146.101.78.143]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZwWnN-0007Dj-Sn for linux-arm-kernel@lists.infradead.org; Wed, 11 Nov 2015 14:54:47 +0000 Received: from cam-owa2.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) by eu-smtp-1.mimecast.com with ESMTP id uk-mta-5-I2HDqB33Rk-xLia-u8w4fA-1; Wed, 11 Nov 2015 14:54:20 +0000 Received: from e104324-lin.cambridge.arm.com ([10.1.2.79]) by cam-owa2.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Wed, 11 Nov 2015 14:54:19 +0000 From: Robin Murphy To: iommu@lists.linux-foundation.org, linux-arm-kernel@lists.infradead.org Subject: [PATCH] iommu/dma: Map scatterlists more parsimoniously Date: Wed, 11 Nov 2015 14:54:16 +0000 Message-Id: <104b4682056bc5b4aa0afadd39196c03fc06555d.1447249098.git.robin.murphy@arm.com> X-Mailer: git-send-email 1.9.1 X-OriginalArrivalTime: 11 Nov 2015 14:54:19.0551 (UTC) FILETIME=[D804B2F0:01D11C90] X-MC-Unique: I2HDqB33Rk-xLia-u8w4fA-1 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20151111_065446_246421_E5AB80F3 X-CRM114-Status: GOOD ( 10.37 ) X-Spam-Score: -4.2 (----) 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: joro@8bytes.org, tiffany.lin@mediatek.com, djkurtz@chromium.org, yong.wu@mediatek.com, tfiga@chromium.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-Spam-Status: No, score=-4.5 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable 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 Whilst blindly assuming the worst case for segment boundaries and aligning every segment individually is safe from the point of view of respecting the device's parameters, it is also undeniably a waste of IOVA space. Futhermore, the knock-on effects of more pages than necessary being exposed to device access, additional overhead in page table updates and TLB invalidations, etc., are even more undesirable. Improve matters by taking the actual boundary mask into account to actively detect the cases in which we really do need to adjust a segment, and avoid wasting space in the remainder. Signed-off-by: Robin Murphy Tested-by: Yong Wu Reviewed-by: Daniel Kurtz --- Hi all, I've given this some brief testing on Juno with USB and (via magic PCI hacks) SATA to confirm that all the +1s and -1s at least seem to be in the right places, so I'm throwing it out now for a head-start on checking whether it also helps the media folks with the v4l portability issues they're up against (I'm confident it should). If all goes well I figure I'll repost next week based on rc1 instead of some random local development commit. Robin. drivers/iommu/dma-iommu.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 3a20db4..821ebc4 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -441,6 +441,7 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, struct scatterlist *s, *prev = NULL; dma_addr_t dma_addr; size_t iova_len = 0; + unsigned long mask = dma_get_seg_boundary(dev); int i; /* @@ -460,17 +461,19 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, s->length = s_length; /* - * The simple way to avoid the rare case of a segment - * crossing the boundary mask is to pad the previous one - * to end at a naturally-aligned IOVA for this one's size, - * at the cost of potentially over-allocating a little. + * With a single size-aligned IOVA allocation, no segment risks + * crossing the boundary mask unless the total size exceeds + * the mask itself. The simple way to maintain alignment when + * that does happen is to pad the previous segment to end at the + * next boundary, at the cost of over-allocating a little. */ if (prev) { - size_t pad_len = roundup_pow_of_two(s_length); + size_t pad_len = (mask - iova_len + 1) & mask; - pad_len = (pad_len - iova_len) & (pad_len - 1); - prev->length += pad_len; - iova_len += pad_len; + if (pad_len && pad_len < s_length - 1) { + prev->length += pad_len; + iova_len += pad_len; + } } iova_len += s_length;