From patchwork Wed Jan 20 21:09:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 12033675 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9238CC4332E for ; Wed, 20 Jan 2021 21:09:48 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 5C2882343E for ; Wed, 20 Jan 2021 21:09:48 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 5C2882343E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B613E6E459; Wed, 20 Jan 2021 21:09:43 +0000 (UTC) Received: from mail-pl1-x62e.google.com (mail-pl1-x62e.google.com [IPv6:2607:f8b0:4864:20::62e]) by gabe.freedesktop.org (Postfix) with ESMTPS id ACD9D6E459 for ; Wed, 20 Jan 2021 21:09:42 +0000 (UTC) Received: by mail-pl1-x62e.google.com with SMTP id b8so13197958plh.12 for ; Wed, 20 Jan 2021 13:09:42 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=5p3XfY6TOWEdcAK7xdoxc0ak2IFt6vsK1MpKBtv9a0E=; b=dIylZNXUT8UQ3UamF1ogl2nvky0NOqNfe4p5pAKibTyvbKpekUSnf9ybDFs54ibA61 C/ZTwYE6NnSTMniIt78BwgL8jFAh3+rjQvmEWrMrKSJKxbkS0hz96dBKkbEbw9gtFk18 KYuxSgNMJkmdWQ8aLW21q7KBpR80cNf8dfF8N2tIS4SgJpoyaXfqI8wcVAXoTU0krNs6 gdYQeDCNH6YNcse2uf33htcQmPbFox6z6dKVg1FTtNAccuiwdwNizrjmiGcGMnc+kPU+ uA6gayZCbJYLyJQXyg1ltt7mbeoFgUj879fNhy/VNvLDe6KbpVOg4yo1OSBtH16wV3xG JLMg== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=5p3XfY6TOWEdcAK7xdoxc0ak2IFt6vsK1MpKBtv9a0E=; b=qiQvF0e1RkuSliWx+OJumXYQxxk73mrwlU4iZBbx9RKIhdMttCvVCHm7Z2LJrqUJ48 cOtt5QA6VJ7dbIbJb6BESHyZJa/mJt5k9hrm4Qsefr6bEr8+yZylAKGLhp8wwN+eEJfh K5+kRhlboONI+P9+9bSm4JZiL1tb+Pqa3gw26s0k5db7FrQRsSVHf2r9zbhu17+o2P+A TjUF5PeJQnCl7A2dDaojR6fkqCXBkSjzmoiCtC2cSdHhOYubTHRDwWHiFwDyNRTuG67D 8QMO5cL0g50Q6c2T5e37eTeHxzkFQ4u+rYFjTHSYJoH88dE8M1AlwZiplgK1bER9X445 OqwQ== X-Gm-Message-State: AOAM533mkU/Mu9fPL21huYD5BKfqHIGsB6qcfyHlYn2JPIHYCbsP5RmA EvMU6NdftOVonY8zuzduWcIAkA== X-Google-Smtp-Source: ABdhPJws6ddONO6NY88RoQ3BGsVYEJuaBeog/gKtwE5U4aqwU6w4J5JtoB3QT6Z/CXX0IqrItU/FPA== X-Received: by 2002:a17:902:b203:b029:dc:973:3ad0 with SMTP id t3-20020a170902b203b02900dc09733ad0mr11671800plr.44.1611176982332; Wed, 20 Jan 2021 13:09:42 -0800 (PST) Received: from localhost.localdomain ([2601:1c2:680:1319:692:26ff:feda:3a81]) by smtp.gmail.com with ESMTPSA id f15sm3265629pja.24.2021.01.20.13.09.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 13:09:41 -0800 (PST) From: John Stultz To: lkml Subject: [PATCH 1/3] dma-buf: dma-heap: Keep track of the heap device struct Date: Wed, 20 Jan 2021 21:09:35 +0000 Message-Id: <20210120210937.15069-2-john.stultz@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210120210937.15069-1-john.stultz@linaro.org> References: <20210120210937.15069-1-john.stultz@linaro.org> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: dri-devel@lists.freedesktop.org, Bing Song , Sandeep Patil , Chris Goldsworthy , Ezequiel Garcia , Robin Murphy , James Jones , Liam Mark , Laura Abbott , Hridya Valsaraju , =?utf-8?q?=C3=98rjan_Eide?= , linux-media@vger.kernel.org, Suren Baghdasaryan , Daniel Mentz Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Keep track of the heap device struct. This will be useful for special DMA allocations and actions. Cc: Daniel Vetter Cc: Sumit Semwal Cc: Liam Mark Cc: Laura Abbott Cc: Brian Starkey Cc: Hridya Valsaraju Cc: Suren Baghdasaryan Cc: Sandeep Patil Cc: Daniel Mentz Cc: Chris Goldsworthy Cc: Ørjan Eide Cc: Robin Murphy Cc: Ezequiel Garcia Cc: Simon Ser Cc: James Jones Cc: Bing Song Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Signed-off-by: John Stultz --- drivers/dma-buf/dma-heap.c | 33 +++++++++++++++++++++++++-------- include/linux/dma-heap.h | 9 +++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index afd22c9dbdcf..72c746755d89 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -30,6 +30,7 @@ * @heap_devt heap device node * @list list head connecting to list of heaps * @heap_cdev heap char device + * @heap_dev heap device struct * * Represents a heap of memory from which buffers can be made. */ @@ -40,6 +41,7 @@ struct dma_heap { dev_t heap_devt; struct list_head list; struct cdev heap_cdev; + struct device *heap_dev; }; static LIST_HEAD(heap_list); @@ -190,10 +192,21 @@ void *dma_heap_get_drvdata(struct dma_heap *heap) return heap->priv; } +/** + * dma_heap_get_dev() - get device struct for the heap + * @heap: DMA-Heap to retrieve device struct from + * + * Returns: + * The device struct for the heap. + */ +struct device *dma_heap_get_dev(struct dma_heap *heap) +{ + return heap->heap_dev; +} + struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info) { struct dma_heap *heap, *h, *err_ret; - struct device *dev_ret; unsigned int minor; int ret; @@ -247,16 +260,20 @@ struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info) goto err1; } - dev_ret = device_create(dma_heap_class, - NULL, - heap->heap_devt, - NULL, - heap->name); - if (IS_ERR(dev_ret)) { + heap->heap_dev = device_create(dma_heap_class, + NULL, + heap->heap_devt, + NULL, + heap->name); + if (IS_ERR(heap->heap_dev)) { pr_err("dma_heap: Unable to create device\n"); - err_ret = ERR_CAST(dev_ret); + err_ret = ERR_CAST(heap->heap_dev); goto err2; } + + /* Make sure it doesn't disappear on us */ + heap->heap_dev = get_device(heap->heap_dev); + /* Add heap to the list */ mutex_lock(&heap_list_lock); list_add(&heap->list, &heap_list); diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h index 454e354d1ffb..82857e096910 100644 --- a/include/linux/dma-heap.h +++ b/include/linux/dma-heap.h @@ -50,6 +50,15 @@ struct dma_heap_export_info { */ void *dma_heap_get_drvdata(struct dma_heap *heap); +/** + * dma_heap_get_dev() - get device struct for the heap + * @heap: DMA-Heap to retrieve device struct from + * + * Returns: + * The device struct for the heap. + */ +struct device *dma_heap_get_dev(struct dma_heap *heap); + /** * dma_heap_add - adds a heap to dmabuf heaps * @exp_info: information needed to register this heap From patchwork Wed Jan 20 21:09:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 12033677 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id A5721C4332D for ; Wed, 20 Jan 2021 21:09:53 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 719692343E for ; Wed, 20 Jan 2021 21:09:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 719692343E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 74E236E461; Wed, 20 Jan 2021 21:09:47 +0000 (UTC) Received: from mail-pg1-x52c.google.com (mail-pg1-x52c.google.com [IPv6:2607:f8b0:4864:20::52c]) by gabe.freedesktop.org (Postfix) with ESMTPS id 9A4B96E45D for ; Wed, 20 Jan 2021 21:09:44 +0000 (UTC) Received: by mail-pg1-x52c.google.com with SMTP id c22so16020202pgg.13 for ; Wed, 20 Jan 2021 13:09:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=70VHM4qOcLMs7abWCHQ8/cB/OWCqfqACUfmBJLnT76E=; b=jI4fSVLQvKGQwgXsM931OypebHN0gXP+30HiABCi/YAmKN2A/X/jpIuDzgMishcIrg TOLzFWyrZMSMXvtHBziBBL1b/Hqa6qfJU5so9K3j1L30wPOuXhn70FHpVhq5Wo0e76E0 LQDfErM3vHRVtQj0PVspAb0lrCDIYFU3kjSf0ZFTCGhOr7kTOFOsLbKFX4oJuRhIltFq Eiz5VMO8TyyeoHgMrRhBGXqvnfmBnK7Fcnptm/S0oHRW4vSsOw/MTkzZ+G+XC2Lf4AzW MBHKkRp/PiomeKihLmLr3apkv2m6VkzTokGRz3njt42Al+RUNRGQUpsPdL8JUXuH8dEp DLVA== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=70VHM4qOcLMs7abWCHQ8/cB/OWCqfqACUfmBJLnT76E=; b=EjKRAtVKTbVo9CWLtGmQLa7w2bcfS/2O6YrmtqhFuo7jkWBZBOcySFfR6HV+8dOq3R pvBtCTuymI0mzu2r5kDDGINdLXedfg1wZ7Za/Y9DL4MG2gq8RLDgDV6ooi4h4i7IiqXS 95JEnjU0xFD5nqPQdRJjk8We7PGnxsmYtL/sQoiAO/9Irka1XKXHwZD8KLfIwsUhaAqU oihNFXTxqqB049Sc0qMVwNOeCcXs/A/eT4uS7DSAT6jRAks822W4j+BxGTUD6yopINme 5pyEiqbsi3P+n9aQj9EDIxOmmljMcrCz4O5zITNjPHRNa8JSAebYOtLGnuNIm45Q+B2N qQkA== X-Gm-Message-State: AOAM5328PLfJv6PVIw46PVSA3lFJZBCEgSVBOcaWu4wd7AXfY7zFTGQO Ue+bvHcL70PCgXphYJI1O+OZXw== X-Google-Smtp-Source: ABdhPJwLg0H5Ihwkfb9pFIwPEFrOx7Mr1rq28WBlhMkbxwiGEReRjpIzEN/k9w5o8dBXSgJHlSpcRA== X-Received: by 2002:a63:4746:: with SMTP id w6mr10957460pgk.377.1611176984206; Wed, 20 Jan 2021 13:09:44 -0800 (PST) Received: from localhost.localdomain ([2601:1c2:680:1319:692:26ff:feda:3a81]) by smtp.gmail.com with ESMTPSA id f15sm3265629pja.24.2021.01.20.13.09.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 13:09:43 -0800 (PST) From: John Stultz To: lkml Subject: [PATCH 2/3] dma-buf: system_heap: Add a system-uncached heap re-using the system heap Date: Wed, 20 Jan 2021 21:09:36 +0000 Message-Id: <20210120210937.15069-3-john.stultz@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210120210937.15069-1-john.stultz@linaro.org> References: <20210120210937.15069-1-john.stultz@linaro.org> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: dri-devel@lists.freedesktop.org, Bing Song , Sandeep Patil , Chris Goldsworthy , Ezequiel Garcia , Robin Murphy , James Jones , Liam Mark , Laura Abbott , Hridya Valsaraju , =?utf-8?q?=C3=98rjan_Eide?= , linux-media@vger.kernel.org, Suren Baghdasaryan , Daniel Mentz Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" This adds a heap that allocates non-contiguous buffers that are marked as writecombined, so they are not cached by the CPU. This is useful, as most graphics buffers are usually not touched by the CPU or only written into once by the CPU. So when mapping the buffer over and over between devices, we can skip the CPU syncing, which saves a lot of cache management overhead, greatly improving performance. For folk using ION, there was a ION_FLAG_CACHED flag, which signaled if the returned buffer should be CPU cacheable or not. With DMA-BUF heaps, we do not yet have such a flag, and by default the current heaps (system and cma) produce CPU cachable buffers. So for folks transitioning from ION to DMA-BUF Heaps, this fills in some of that missing functionality. There has been a suggestion to make this functionality a flag (DMAHEAP_FLAG_UNCACHED?) on the system heap, similar to how ION used the ION_FLAG_CACHED. But I want to make sure an _UNCACHED flag would truely be a generic attribute across all heaps. So far that has been unclear, so having it as a separate heap seemes better for now. (But I'm open to discussion on this point!) This is a rework of earlier efforts to add a uncached system heap, done utilizing the exisitng system heap, adding just a bit of logic to handle the uncached case. Feedback would be very welcome! Many thanks to Liam Mark for his help to get this working. Pending opensource users of this code include: * AOSP HiKey960 gralloc: - https://android-review.googlesource.com/c/device/linaro/hikey/+/1399519 - Visibly improves performance over the system heap * AOSP Codec2: - https://android-review.googlesource.com/c/platform/frameworks/av/+/1543685 Cc: Daniel Vetter Cc: Sumit Semwal Cc: Liam Mark Cc: Laura Abbott Cc: Brian Starkey Cc: Hridya Valsaraju Cc: Suren Baghdasaryan Cc: Sandeep Patil Cc: Daniel Mentz Cc: Chris Goldsworthy Cc: Ørjan Eide Cc: Robin Murphy Cc: Ezequiel Garcia Cc: Simon Ser Cc: James Jones Cc: Bing Song Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Signed-off-by: John Stultz --- v4: * Make sys_uncached_heap static, as Reported-by: kernel test robot * Fix wrong return value, caught by smatch Reported-by: kernel test robot Reported-by: Dan Carpenter * Ensure we call flush/invalidate_kernel_vmap_range() in the uncached cases to try to address feedback about VIVT caches from Christoph * Reorder a few lines as suggested by BrianS * Avoid holding the initial mapping for the lifetime of the buffer as suggested by BrianS * Fix a unlikely race between allocate and updating the dma_mask that BrianS noticed. --- drivers/dma-buf/heaps/system_heap.c | 111 ++++++++++++++++++++++++---- 1 file changed, 95 insertions(+), 16 deletions(-) diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index 17e0e9a68baf..3548b20cb98c 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -22,6 +22,7 @@ #include static struct dma_heap *sys_heap; +static struct dma_heap *sys_uncached_heap; struct system_heap_buffer { struct dma_heap *heap; @@ -31,6 +32,8 @@ struct system_heap_buffer { struct sg_table sg_table; int vmap_cnt; void *vaddr; + + bool uncached; }; struct dma_heap_attachment { @@ -38,6 +41,8 @@ struct dma_heap_attachment { struct sg_table *table; struct list_head list; bool mapped; + + bool uncached; }; #define HIGH_ORDER_GFP (((GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN \ @@ -100,7 +105,7 @@ static int system_heap_attach(struct dma_buf *dmabuf, a->dev = attachment->dev; INIT_LIST_HEAD(&a->list); a->mapped = false; - + a->uncached = buffer->uncached; attachment->priv = a; mutex_lock(&buffer->lock); @@ -130,9 +135,13 @@ static struct sg_table *system_heap_map_dma_buf(struct dma_buf_attachment *attac { struct dma_heap_attachment *a = attachment->priv; struct sg_table *table = a->table; + int attr = 0; int ret; - ret = dma_map_sgtable(attachment->dev, table, direction, 0); + if (a->uncached) + attr = DMA_ATTR_SKIP_CPU_SYNC; + + ret = dma_map_sgtable(attachment->dev, table, direction, attr); if (ret) return ERR_PTR(ret); @@ -145,9 +154,12 @@ static void system_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, enum dma_data_direction direction) { struct dma_heap_attachment *a = attachment->priv; + int attr = 0; + if (a->uncached) + attr = DMA_ATTR_SKIP_CPU_SYNC; a->mapped = false; - dma_unmap_sgtable(attachment->dev, table, direction, 0); + dma_unmap_sgtable(attachment->dev, table, direction, attr); } static int system_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, @@ -161,10 +173,12 @@ static int system_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, if (buffer->vmap_cnt) invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); - list_for_each_entry(a, &buffer->attachments, list) { - if (!a->mapped) - continue; - dma_sync_sgtable_for_cpu(a->dev, a->table, direction); + if (!buffer->uncached) { + list_for_each_entry(a, &buffer->attachments, list) { + if (!a->mapped) + continue; + dma_sync_sgtable_for_cpu(a->dev, a->table, direction); + } } mutex_unlock(&buffer->lock); @@ -182,10 +196,12 @@ static int system_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, if (buffer->vmap_cnt) flush_kernel_vmap_range(buffer->vaddr, buffer->len); - list_for_each_entry(a, &buffer->attachments, list) { - if (!a->mapped) - continue; - dma_sync_sgtable_for_device(a->dev, a->table, direction); + if (!buffer->uncached) { + list_for_each_entry(a, &buffer->attachments, list) { + if (!a->mapped) + continue; + dma_sync_sgtable_for_device(a->dev, a->table, direction); + } } mutex_unlock(&buffer->lock); @@ -200,6 +216,9 @@ static int system_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) struct sg_page_iter piter; int ret; + if (buffer->uncached) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + for_each_sgtable_page(table, &piter, vma->vm_pgoff) { struct page *page = sg_page_iter_page(&piter); @@ -221,17 +240,21 @@ static void *system_heap_do_vmap(struct system_heap_buffer *buffer) struct page **pages = vmalloc(sizeof(struct page *) * npages); struct page **tmp = pages; struct sg_page_iter piter; + pgprot_t pgprot = PAGE_KERNEL; void *vaddr; if (!pages) return ERR_PTR(-ENOMEM); + if (buffer->uncached) + pgprot = pgprot_writecombine(PAGE_KERNEL); + for_each_sgtable_page(table, &piter, 0) { WARN_ON(tmp - pages >= npages); *tmp++ = sg_page_iter_page(&piter); } - vaddr = vmap(pages, npages, VM_MAP, PAGE_KERNEL); + vaddr = vmap(pages, npages, VM_MAP, pgprot); vfree(pages); if (!vaddr) @@ -331,10 +354,11 @@ static struct page *alloc_largest_available(unsigned long size, return NULL; } -static int system_heap_allocate(struct dma_heap *heap, - unsigned long len, - unsigned long fd_flags, - unsigned long heap_flags) +static int system_heap_do_allocate(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags, + bool uncached) { struct system_heap_buffer *buffer; DEFINE_DMA_BUF_EXPORT_INFO(exp_info); @@ -355,6 +379,7 @@ static int system_heap_allocate(struct dma_heap *heap, mutex_init(&buffer->lock); buffer->heap = heap; buffer->len = len; + buffer->uncached = uncached; INIT_LIST_HEAD(&pages); i = 0; @@ -404,6 +429,18 @@ static int system_heap_allocate(struct dma_heap *heap, /* just return, as put will call release and that will free */ return ret; } + + /* + * For uncached buffers, we need to initially flush cpu cache, since + * the __GFP_ZERO on the allocation means the zeroing was done by the + * cpu and thus it is likely cached. Map (and implicitly flush) and + * unmap it now so we don't get corruption later on. + */ + if (buffer->uncached) { + dma_map_sgtable(dma_heap_get_dev(heap), table, DMA_BIDIRECTIONAL, 0); + dma_unmap_sgtable(dma_heap_get_dev(heap), table, DMA_BIDIRECTIONAL, 0); + } + return ret; free_pages: @@ -421,10 +458,40 @@ static int system_heap_allocate(struct dma_heap *heap, return ret; } +static int system_heap_allocate(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) +{ + return system_heap_do_allocate(heap, len, fd_flags, heap_flags, false); +} + static const struct dma_heap_ops system_heap_ops = { .allocate = system_heap_allocate, }; +static int system_uncached_heap_allocate(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) +{ + return system_heap_do_allocate(heap, len, fd_flags, heap_flags, true); +} + +/* Dummy function to be used until we can call coerce_mask_and_coherent */ +static int system_uncached_heap_not_initialized(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) +{ + return -EBUSY; +} + +static struct dma_heap_ops system_uncached_heap_ops = { + /* After system_heap_create is complete, we will swap this */ + .allocate = system_uncached_heap_not_initialized, +}; + static int system_heap_create(void) { struct dma_heap_export_info exp_info; @@ -437,6 +504,18 @@ static int system_heap_create(void) if (IS_ERR(sys_heap)) return PTR_ERR(sys_heap); + exp_info.name = "system-uncached"; + exp_info.ops = &system_uncached_heap_ops; + exp_info.priv = NULL; + + sys_uncached_heap = dma_heap_add(&exp_info); + if (IS_ERR(sys_uncached_heap)) + return PTR_ERR(sys_uncached_heap); + + dma_coerce_mask_and_coherent(dma_heap_get_dev(sys_uncached_heap), DMA_BIT_MASK(64)); + mb(); /* make sure we only set allocate after dma_mask is set */ + system_uncached_heap_ops.allocate = system_uncached_heap_allocate; + return 0; } module_init(system_heap_create); From patchwork Wed Jan 20 21:09:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 12033679 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.6 required=3.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7DB6EC433E0 for ; Wed, 20 Jan 2021 21:09:51 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 3E35B2343E for ; Wed, 20 Jan 2021 21:09:50 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 3E35B2343E Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D240D6E45D; Wed, 20 Jan 2021 21:09:46 +0000 (UTC) Received: from mail-pg1-x52f.google.com (mail-pg1-x52f.google.com [IPv6:2607:f8b0:4864:20::52f]) by gabe.freedesktop.org (Postfix) with ESMTPS id 68E316E45D for ; Wed, 20 Jan 2021 21:09:46 +0000 (UTC) Received: by mail-pg1-x52f.google.com with SMTP id c132so16084534pga.3 for ; Wed, 20 Jan 2021 13:09:46 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=H4+X0xWeooH24gYhSYvXX9x75t8RTwKg5FJ1Ffw/87E=; b=b+9dZxp4AirxgnJJSr4dySxi/WJW1ARIEAf6hNM3BR6rRHmNRJ1MZpwJ/OBt4UYMY8 74ECTrUU5Uil9qGJ7UZJT3o60mz3sfiRSorXPkmty6sTDdyuLqvgUxyWgmcTJe2Tc/3Y hQDyLsBwYERkBEox9qzKb0srA+DM7+gD+ck9f2hcZZ4VifojYxJWZu5+h066eQNlqQkW WTNIByqh6IaEZEa2iqKZhuBmlIop5JUJslwRi0p3MgdJXLIuLzfzP0BoKR/uEb8aby56 kW8NUHY2+Uvckz0UPPxHeKrgMis65PYRLsvnRES7q738rjV7tRJep+hw+/Iqm6OfsekA 0riw== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=H4+X0xWeooH24gYhSYvXX9x75t8RTwKg5FJ1Ffw/87E=; b=IEnhj27mMrwYDMljS2/+8G7UziW29Xm0wmNPJPN23rd7n7FL+0r2pA2CLaJsyLhWKG zmamUbCwmVSp8jEWXszm2tE7QnD5MvQceMe9l2rNeZAqfz7pDAEMF1nioHUosk/em0iA +lUunc3Cdv2G2JS9ZMEpicTPTIixWKaH+7ry3fCua5VTVEOlpvhiPKBDjTwHktUV753d OCqNWJ9Mh1FOlBQt8X6t1TTb783EX7/BFiE/5MpjJyfnJvlT6x6UrtuqqY9CVzOdvC2f RFq3BB+i90oNKscZ9LMamuXsvZJ3J8AATmd+5JwV2tRLHctjjdvAewQg9F2YTYN+xaly /Xzw== X-Gm-Message-State: AOAM5331Py50AXsLFRs51APfH1gh+x9zGq+EZJ5RQtjqUf93mup7u+Fc EzHMFQG9RiXLB7vFPbOIrxvF4A== X-Google-Smtp-Source: ABdhPJyv4JjWfOCxuhxS+jF+NOmU+TvHCVz4VkCmpOfeGTszmzT23aBKlf3HPpm7AJDat28vcTMDGA== X-Received: by 2002:a62:8fca:0:b029:1a9:39bc:ed37 with SMTP id n193-20020a628fca0000b02901a939bced37mr10984394pfd.61.1611176985973; Wed, 20 Jan 2021 13:09:45 -0800 (PST) Received: from localhost.localdomain ([2601:1c2:680:1319:692:26ff:feda:3a81]) by smtp.gmail.com with ESMTPSA id f15sm3265629pja.24.2021.01.20.13.09.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Jan 2021 13:09:45 -0800 (PST) From: John Stultz To: lkml Subject: [PATCH 3/3] dma-buf: cma_heap: Add a cma-uncached heap re-using the cma heap Date: Wed, 20 Jan 2021 21:09:37 +0000 Message-Id: <20210120210937.15069-4-john.stultz@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20210120210937.15069-1-john.stultz@linaro.org> References: <20210120210937.15069-1-john.stultz@linaro.org> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: dri-devel@lists.freedesktop.org, Sandeep Patil , Chris Goldsworthy , Ezequiel Garcia , Suren Baghdasaryan , James Jones , Robin Murphy , Liam Mark , Bing Song , Laura Abbott , Hridya Valsaraju , =?utf-8?q?=C3=98rjan_Eide?= , linux-media@vger.kernel.org, Daniel Mentz Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Bing Song This adds a heap that allocates CMA buffers that are marked as writecombined, so they are not cached by the CPU. Cc: Daniel Vetter Cc: Sumit Semwal Cc: Liam Mark Cc: Laura Abbott Cc: Brian Starkey Cc: Hridya Valsaraju Cc: Suren Baghdasaryan Cc: Sandeep Patil Cc: Daniel Mentz Cc: Chris Goldsworthy Cc: Ørjan Eide Cc: Robin Murphy Cc: Ezequiel Garcia Cc: Simon Ser Cc: James Jones Cc: linux-media@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Signed-off-by: Bing Song Signed-off-by: John Stultz --- drivers/dma-buf/heaps/cma_heap.c | 119 +++++++++++++++++++++++++++---- 1 file changed, 107 insertions(+), 12 deletions(-) diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c index 364fc2f3e499..1b8c6eb0a8ea 100644 --- a/drivers/dma-buf/heaps/cma_heap.c +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -38,6 +38,7 @@ struct cma_heap_buffer { pgoff_t pagecount; int vmap_cnt; void *vaddr; + bool uncached; }; struct dma_heap_attachment { @@ -45,6 +46,7 @@ struct dma_heap_attachment { struct sg_table table; struct list_head list; bool mapped; + bool uncached; }; static int cma_heap_attach(struct dma_buf *dmabuf, @@ -70,6 +72,7 @@ static int cma_heap_attach(struct dma_buf *dmabuf, a->dev = attachment->dev; INIT_LIST_HEAD(&a->list); a->mapped = false; + a->uncached = buffer->uncached; attachment->priv = a; @@ -99,8 +102,12 @@ static struct sg_table *cma_heap_map_dma_buf(struct dma_buf_attachment *attachme { struct dma_heap_attachment *a = attachment->priv; struct sg_table *table = &a->table; + int attr = 0; int ret; + if (a->uncached) + attr = DMA_ATTR_SKIP_CPU_SYNC; + ret = dma_map_sgtable(attachment->dev, table, direction, 0); if (ret) return ERR_PTR(-ENOMEM); @@ -113,7 +120,10 @@ static void cma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, enum dma_data_direction direction) { struct dma_heap_attachment *a = attachment->priv; + int attr = 0; + if (a->uncached) + attr = DMA_ATTR_SKIP_CPU_SYNC; a->mapped = false; dma_unmap_sgtable(attachment->dev, table, direction, 0); } @@ -128,10 +138,12 @@ static int cma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); mutex_lock(&buffer->lock); - list_for_each_entry(a, &buffer->attachments, list) { - if (!a->mapped) - continue; - dma_sync_sgtable_for_cpu(a->dev, &a->table, direction); + if (!buffer->uncached) { + list_for_each_entry(a, &buffer->attachments, list) { + if (!a->mapped) + continue; + dma_sync_sgtable_for_cpu(a->dev, &a->table, direction); + } } mutex_unlock(&buffer->lock); @@ -148,10 +160,12 @@ static int cma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, flush_kernel_vmap_range(buffer->vaddr, buffer->len); mutex_lock(&buffer->lock); - list_for_each_entry(a, &buffer->attachments, list) { - if (!a->mapped) - continue; - dma_sync_sgtable_for_device(a->dev, &a->table, direction); + if (!buffer->uncached) { + list_for_each_entry(a, &buffer->attachments, list) { + if (!a->mapped) + continue; + dma_sync_sgtable_for_device(a->dev, &a->table, direction); + } } mutex_unlock(&buffer->lock); @@ -183,6 +197,9 @@ static int cma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0) return -EINVAL; + if (buffer->uncached) + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + vma->vm_ops = &dma_heap_vm_ops; vma->vm_private_data = buffer; @@ -191,9 +208,13 @@ static int cma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) static void *cma_heap_do_vmap(struct cma_heap_buffer *buffer) { + pgprot_t pgprot = PAGE_KERNEL; void *vaddr; - vaddr = vmap(buffer->pages, buffer->pagecount, VM_MAP, PAGE_KERNEL); + if (buffer->uncached) + pgprot = pgprot_writecombine(PAGE_KERNEL); + + vaddr = vmap(buffer->pages, buffer->pagecount, VM_MAP, pgprot); if (!vaddr) return ERR_PTR(-ENOMEM); @@ -271,10 +292,11 @@ static const struct dma_buf_ops cma_heap_buf_ops = { .release = cma_heap_dma_buf_release, }; -static int cma_heap_allocate(struct dma_heap *heap, +static int cma_heap_do_allocate(struct dma_heap *heap, unsigned long len, unsigned long fd_flags, - unsigned long heap_flags) + unsigned long heap_flags, + bool uncached) { struct cma_heap *cma_heap = dma_heap_get_drvdata(heap); struct cma_heap_buffer *buffer; @@ -283,8 +305,9 @@ static int cma_heap_allocate(struct dma_heap *heap, pgoff_t pagecount = size >> PAGE_SHIFT; unsigned long align = get_order(size); struct page *cma_pages; + struct sg_table table; struct dma_buf *dmabuf; - int ret = -ENOMEM; + int ret = -ENOMEM, ret_sg_table; pgoff_t pg; buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); @@ -294,6 +317,7 @@ static int cma_heap_allocate(struct dma_heap *heap, INIT_LIST_HEAD(&buffer->attachments); mutex_init(&buffer->lock); buffer->len = size; + buffer->uncached = uncached; if (align > CONFIG_CMA_ALIGNMENT) align = CONFIG_CMA_ALIGNMENT; @@ -356,6 +380,18 @@ static int cma_heap_allocate(struct dma_heap *heap, return ret; } + if (buffer->uncached) { + ret_sg_table = sg_alloc_table(&table, 1, GFP_KERNEL); + if (ret_sg_table) + return ret_sg_table; + + sg_set_page(table.sgl, cma_pages, size, 0); + + dma_map_sgtable(dma_heap_get_dev(heap), &table, DMA_BIDIRECTIONAL, 0); + dma_unmap_sgtable(dma_heap_get_dev(heap), &table, DMA_BIDIRECTIONAL, 0); + sg_free_table(&table); + } + return ret; free_pages: @@ -368,14 +404,45 @@ static int cma_heap_allocate(struct dma_heap *heap, return ret; } +static int cma_heap_allocate(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) +{ + return cma_heap_do_allocate(heap, len, fd_flags, heap_flags, false); +} + +static int cma_uncached_heap_allocate(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) +{ + return cma_heap_do_allocate(heap, len, fd_flags, heap_flags, true); +} + +/* Dummy function to be used until we can call coerce_mask_and_coherent */ +static int cma_uncached_heap_not_initialized(struct dma_heap *heap, + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) +{ + return -EBUSY; +} + static const struct dma_heap_ops cma_heap_ops = { .allocate = cma_heap_allocate, }; +static struct dma_heap_ops cma_uncached_heap_ops = { + .allocate = cma_uncached_heap_not_initialized, +}; + static int __add_cma_heap(struct cma *cma, void *data) { struct cma_heap *cma_heap; struct dma_heap_export_info exp_info; + const char *postfixed = "-uncached"; + char *cma_name; cma_heap = kzalloc(sizeof(*cma_heap), GFP_KERNEL); if (!cma_heap) @@ -394,6 +461,34 @@ static int __add_cma_heap(struct cma *cma, void *data) return ret; } + cma_heap = kzalloc(sizeof(*cma_heap), GFP_KERNEL); + if (!cma_heap) + return -ENOMEM; + cma_heap->cma = cma; + + cma_name = kzalloc(strlen(cma_get_name(cma)) + strlen(postfixed) + 1, GFP_KERNEL); + if (!cma_name) { + kfree(cma_heap); + return -ENOMEM; + } + + exp_info.name = strcat(strcpy(cma_name, cma_get_name(cma)), postfixed); + exp_info.ops = &cma_uncached_heap_ops; + exp_info.priv = cma_heap; + + cma_heap->heap = dma_heap_add(&exp_info); + if (IS_ERR(cma_heap->heap)) { + int ret = PTR_ERR(cma_heap->heap); + + kfree(cma_heap); + kfree(cma_name); + return ret; + } + + dma_coerce_mask_and_coherent(dma_heap_get_dev(cma_heap->heap), DMA_BIT_MASK(64)); + mb(); /* make sure we only set allocate after dma_mask is set */ + cma_uncached_heap_ops.allocate = cma_uncached_heap_allocate; + return 0; }