From patchwork Wed Feb 4 09:23:19 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Carlo Caione X-Patchwork-Id: 5775481 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 59351BF440 for ; Wed, 4 Feb 2015 09:26:14 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 65F4E202DD for ; Wed, 4 Feb 2015 09:26:13 +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 71AD0202AE for ; Wed, 4 Feb 2015 09:26:12 +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 1YIwC1-00059g-3h; Wed, 04 Feb 2015 09:24:17 +0000 Received: from mail-we0-x235.google.com ([2a00:1450:400c:c03::235]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1YIwBq-00053a-Lo for linux-arm-kernel@lists.infradead.org; Wed, 04 Feb 2015 09:24:08 +0000 Received: by mail-we0-f181.google.com with SMTP id k48so499576wev.12 for ; Wed, 04 Feb 2015 01:23:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=BLmj33PYI45GMj3RNTkZ9RohAMVOQlYdti5yinLithg=; b=l/v0frvqcw49O9kXkSqhNAAKQz8WcLjjn+kZ4jcOt905Mqcuk9msdxt5fcL1nU3Td2 LW4tZT0WwKTOuC0oTqc359NAwPAmQHp14+X49ECOTZ5+F1wnc3fTLtSynBJ26x10DKS4 +mn+7ze/QiksAkqYX/Nyy5DPklTLDhbxOhH/rDOyCqeWcaFrd7wak0M+ZuK3SoqfBryE nTZLVYI5BMTj2hP5c+IXxwkNNZut/BtTaV6aV2OUTKbDuw0aJQYCSgHNtqf9WLh8FzWU 3f3gQiBzyA+iTxRLAdgtNDjqjTSsvShpk6uxXg575DVuktsLentoBiF2ylmLbMFSsiqM I3pA== X-Received: by 10.180.108.165 with SMTP id hl5mr43915038wib.39.1423041824070; Wed, 04 Feb 2015 01:23:44 -0800 (PST) Received: from nuc.localdomain (2-238-57-164.ip242.fastwebnet.it. [2.238.57.164]) by mx.google.com with ESMTPSA id q10sm1763066wjr.41.2015.02.04.01.23.43 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 04 Feb 2015 01:23:43 -0800 (PST) From: Carlo Caione To: linux-arm-kernel@lists.infradead.org, jstpierre@mecheye.net, drake@endlessm.com, linux@arm.linux.org.uk, m.szyprowski@samsung.com, robdclark@gmail.com, inki.dae@samsung.com, linux-samsung-soc@vger.kernel.org, sw0312.kim@samsung.com, kgene@kernel.org, jy0922.shim@samsung.com, lauraa@codeaurora.org Subject: [PATCH v2 1/2] drm/exynos: fix DMA_ATTR_NO_KERNEL_MAPPING usage Date: Wed, 4 Feb 2015 10:23:19 +0100 Message-Id: <1423041800-27859-2-git-send-email-carlo@caione.org> X-Mailer: git-send-email 2.2.2 In-Reply-To: <1423041800-27859-1-git-send-email-carlo@caione.org> References: <1423041800-27859-1-git-send-email-carlo@caione.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150204_012407_046028_9EA1CA54 X-CRM114-Status: GOOD ( 17.48 ) X-Spam-Score: -0.7 (/) Cc: Carlo Caione 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=-4.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED, T_DKIM_INVALID, T_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 The Exynos DRM driver doesn't follow the correct API when dealing with dma_{alloc, mmap, free}_attrs functions and the DMA_ATTR_NO_KERNEL_MAPPING attribute. When a IOMMU is not available and the DMA_ATTR_NO_KERNEL_MAPPING is used, the driver should use the pointer returned by dma_alloc_attr() as a cookie. The Exynos DRM driver directly uses the non-requested virtual kernel address returned by the DMA mapping subsystem. This just works now because the non-IOMMU codepath doesn't obey DMA_ATTR_NO_KERNEL_MAPPING but we need to fix it before fixing the DMA layer. Signed-off-by: Carlo Caione Acked-by: Joonyoung Shim Acked-by: Marek Szyprowski --- drivers/gpu/drm/exynos/exynos_drm_buf.c | 6 +++--- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 29 +++++++++-------------------- drivers/gpu/drm/exynos/exynos_drm_gem.h | 2 ++ 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_buf.c b/drivers/gpu/drm/exynos/exynos_drm_buf.c index 9c80884..24994ba 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_buf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_buf.c @@ -63,11 +63,11 @@ static int lowlevel_buffer_allocate(struct drm_device *dev, return -ENOMEM; } - buf->kvaddr = (void __iomem *)dma_alloc_attrs(dev->dev, + buf->cookie = dma_alloc_attrs(dev->dev, buf->size, &buf->dma_addr, GFP_KERNEL, &buf->dma_attrs); - if (!buf->kvaddr) { + if (!buf->cookie) { DRM_ERROR("failed to allocate buffer.\n"); ret = -ENOMEM; goto err_free; @@ -132,7 +132,7 @@ static void lowlevel_buffer_deallocate(struct drm_device *dev, buf->sgt = NULL; if (!is_drm_iommu_supported(dev)) { - dma_free_attrs(dev->dev, buf->size, buf->kvaddr, + dma_free_attrs(dev->dev, buf->size, buf->cookie, (dma_addr_t)buf->dma_addr, &buf->dma_attrs); drm_free_large(buf->pages); } else diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index e12ea90..84f8dfe 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -79,9 +79,9 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, struct drm_framebuffer *fb) { struct fb_info *fbi = helper->fbdev; - struct drm_device *dev = helper->dev; struct exynos_drm_gem_buf *buffer; unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3); + unsigned int nr_pages; unsigned long offset; drm_fb_helper_fill_fix(fbi, fb->pitches[0], fb->depth); @@ -94,25 +94,14 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper, return -EFAULT; } - /* map pages with kernel virtual space. */ + nr_pages = buffer->size >> PAGE_SHIFT; + + buffer->kvaddr = (void __iomem *) vmap(buffer->pages, + nr_pages, VM_MAP, + pgprot_writecombine(PAGE_KERNEL)); if (!buffer->kvaddr) { - if (is_drm_iommu_supported(dev)) { - unsigned int nr_pages = buffer->size >> PAGE_SHIFT; - - buffer->kvaddr = (void __iomem *) vmap(buffer->pages, - nr_pages, VM_MAP, - pgprot_writecombine(PAGE_KERNEL)); - } else { - phys_addr_t dma_addr = buffer->dma_addr; - if (dma_addr) - buffer->kvaddr = (void __iomem *)phys_to_virt(dma_addr); - else - buffer->kvaddr = (void __iomem *)NULL; - } - if (!buffer->kvaddr) { - DRM_ERROR("failed to map pages to kernel space.\n"); - return -EIO; - } + DRM_ERROR("failed to map pages to kernel space.\n"); + return -EIO; } /* buffer count to framebuffer always is 1 at booting time. */ @@ -313,7 +302,7 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev, struct exynos_drm_gem_obj *exynos_gem_obj = exynos_fbd->exynos_gem_obj; struct drm_framebuffer *fb; - if (is_drm_iommu_supported(dev) && exynos_gem_obj->buffer->kvaddr) + if (exynos_gem_obj->buffer->kvaddr) vunmap(exynos_gem_obj->buffer->kvaddr); /* release drm framebuffer and real buffer */ diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index ec58fe9..308173c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h @@ -22,6 +22,7 @@ /* * exynos drm gem buffer structure. * + * @cookie: cookie returned by dma_alloc_attrs * @kvaddr: kernel virtual address to allocated memory region. * *userptr: user space address. * @dma_addr: bus address(accessed by dma) to allocated memory region. @@ -35,6 +36,7 @@ * VM_PFNMAP or not. */ struct exynos_drm_gem_buf { + void *cookie; void __iomem *kvaddr; unsigned long userptr; dma_addr_t dma_addr;