From patchwork Tue Apr 17 15:58:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Robin Murphy X-Patchwork-Id: 10345521 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 CC53160542 for ; Tue, 17 Apr 2018 15:58:25 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BF81D28438 for ; Tue, 17 Apr 2018 15:58:25 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B31E228451; Tue, 17 Apr 2018 15:58:25 +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=-5.2 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 1C26928438 for ; Tue, 17 Apr 2018 15:58:24 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 921E76E159; Tue, 17 Apr 2018 15:58:22 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from foss.arm.com (usa-sjc-mx-foss1.foss.arm.com [217.140.101.70]) by gabe.freedesktop.org (Postfix) with ESMTP id D58BA6E159; Tue, 17 Apr 2018 15:58:20 +0000 (UTC) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 897EB1435; Tue, 17 Apr 2018 08:58:20 -0700 (PDT) Received: from e110467-lin.cambridge.arm.com (e110467-lin.cambridge.arm.com [10.1.210.88]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 4ECFA3F25D; Tue, 17 Apr 2018 08:58:19 -0700 (PDT) From: Robin Murphy To: amd-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org Subject: [PATCH v2 1/3] drm/prime: Iterate SG DMA addresses separately Date: Tue, 17 Apr 2018 16:58:13 +0100 Message-Id: X-Mailer: git-send-email 2.16.1.dirty X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: okaya@codeaurora.org, alexander.deucher@amd.com, christian.koenig@amd.com MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP For dma_map_sg(), DMA API implementations are free to merge consecutive segments into a single DMA mapping if conditions are suitable, thus the resulting DMA addresses which drm_prime_sg_to_page_addr_arrays() iterates may be packed into fewer entries than ttm->sg->nents implies. The current implementation does not account for this, meaning that its callers either have to reject the 0 < count < nents case or risk getting bogus DMA addresses beyond the first segment. Fortunately this is quite easy to handle without having to rejig structures to also store the mapped count, since the total DMA length should still be equal to the total buffer length. All we need is a second scatterlist cursor to iterate through the DMA addresses independently of the page addresses. Signed-off-by: Robin Murphy Reviewed-by: Christian König for the whole --- v2: Remember to iterate dma_len correctly as well. drivers/gpu/drm/drm_prime.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 7856a9b3f8a8..b8ca06ea7d80 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -933,16 +933,18 @@ int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, dma_addr_t *addrs, int max_entries) { unsigned count; - struct scatterlist *sg; + struct scatterlist *sg, *dma_sg; struct page *page; - u32 len, index; + u32 len, dma_len, index; dma_addr_t addr; index = 0; + dma_sg = sgt->sgl; + dma_len = sg_dma_len(dma_sg); + addr = sg_dma_address(dma_sg); for_each_sg(sgt->sgl, sg, sgt->nents, count) { len = sg->length; page = sg_page(sg); - addr = sg_dma_address(sg); while (len > 0) { if (WARN_ON(index >= max_entries)) @@ -955,8 +957,15 @@ int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, page++; addr += PAGE_SIZE; len -= PAGE_SIZE; + dma_len -= PAGE_SIZE; index++; } + + if (dma_len == 0) { + dma_sg = sg_next(dma_sg); + dma_len = sg_dma_len(dma_sg); + addr = sg_dma_address(dma_sg); + } } return 0; }