From patchwork Sat Oct 17 01:32:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 317837 Delivered-To: patches@linaro.org Received: by 2002:a92:d603:0:0:0:0:0 with SMTP id w3csp1946870ilm; Fri, 16 Oct 2020 18:33:04 -0700 (PDT) X-Received: by 2002:a63:d90d:: with SMTP id r13mr5067417pgg.99.1602898384522; Fri, 16 Oct 2020 18:33:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1602898384; cv=none; d=google.com; s=arc-20160816; b=bPypXG3B3rhrOsRgxMzkMopp1s827MitghedVeA8ZUWHonY+ZJNSNj/b0wFpLceo0e j3Giu156knFpoajtNBkFkQDcSiXtE66CSXoV2OmRVoHrKTczkQbpsMN/0Zs81Q9sucgC Ap0b7HE6l3qJ5lXmYJeu6GNSplgVUf3/qZk1oFXeHjxM8s3r7A/G1NoEwJsQfnvx19be NquDRXS85j/9e8POtBDRTrqqV9swWvV5vl+fpwZtE+ajlHrvwcNNCrLFPI7O6z2+dIOX 3ZRuZXxzblJEpgVSzJ2KIolDkzniAB0XVACnyOfq5jyvFvWW7HsiqtUormdCGT1IHj7n akNw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=5JS+ofakZjaBRclqK0JsnBtbw/MSyxiaxYZw7ITSz8A=; b=NsE+SFgrpuI0JdyL3aHrYzWPIMeE4fRBIURxyqwk8h/vVADMQ3aCH9gn1fQ/WWnFYS n5HKo2g+0ycMWkYDTuvfVM+CqdaN/i3Dz+9q28d5+CAc25Vz9RuiPVluCY7uWESkrTqP GYmfQfU34Gb3t2XI73TldgsxROm7c/tv5QDNGvdnKbwPtyjbZ9JvZxovC6UggIPo8E2o w1eJllLYmyD2su2S1qfqrKgL8WW7Gb5aqDUeuVWcHp/8B6FjjRBGRta63JPM30RnHhAF 6FBNF5sPpwNUPn+4ONltfOXb+H2vpM+gr2Gm4P4vSO7hcn1AhaDz2yoBDYBxNuoerPDE x9IA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=zosJqPip; spf=pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id a2sor1817526pgt.56.2020.10.16.18.33.04 for (Google Transport Security); Fri, 16 Oct 2020 18:33:04 -0700 (PDT) Received-SPF: pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=zosJqPip; spf=pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org 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=5JS+ofakZjaBRclqK0JsnBtbw/MSyxiaxYZw7ITSz8A=; b=zosJqPipL88vQmn/Ice0dk5+DA3sFK1R1jd+v/oEjsPUGL8yfLJfc8EWxltw0DOdjx yeyTqPFtnrvc2QMQWLCTu4TbdbDseqTIyG/HiT0c0HOFJ/3oMvGoWYq9DaCgXUyqI4WJ LPZdbcNl/JNK18gktQQZ/lYkvtzyGb0M8/+/z6+70SQg8C9IjRddBJYreqVRdi6uwbcr t61HeZuzDG9Wx9sLW6TPmc9qCvSr0lvtjRrfMtn82thg6iyBtihL/iDAQMKbdAi0ady8 TK+b4XeOIEss4cik7oUfWWJHHbM9Y/6G24uJ4a3+9b6sj+8BainWlVNKmmOEKe1dBwXA NX7w== 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=5JS+ofakZjaBRclqK0JsnBtbw/MSyxiaxYZw7ITSz8A=; b=fE1aIlXR+0TVVO20KQwRBGolWx9Vf+70Mwdb7ouKY2oxYw4K3d/xPaSSzn9N4WEe4g NMmYkHrqeTJalYDNRe8RuUu5AJ+Rj76W0t7h28EwvZ4nhZwVts4DKiZ08Y3NIADXI7FY q5tSxpyruotISuHIEefiiPcL+QD8tUAjdmujdzar+cQGlmP9oV5StedZrkxJ+equeCq4 qlkPAHu1LUPSnjF/xDdZSo8Vq4LR8UCJiVOB3hNHSewtTotk64GzUfZt5lYFuK2mmjQQ u2Le2GqJnG40sS4GwBDdhTa6pW++6IUS5rqPPE9dn2zfwI0krcWWcxAEdf6yvaT++W15 wAUw== X-Gm-Message-State: AOAM533dI1OzR7jqzrPw9TB76616MYp8OTXcGzWQDeZTGW0pAyyn4mSE qbTNA9c1ceEIR+TvtcL2u+2HaGIs X-Google-Smtp-Source: ABdhPJz1N0pYDuw3CW1/vgCKc/82gqk7kLV7GRy/Bj4uD7n3se/g1EQJgUKjs/gC0C6grIK6SlC1FA== X-Received: by 2002:a65:5249:: with SMTP id q9mr5404634pgp.79.1602898383937; Fri, 16 Oct 2020 18:33:03 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([2601:1c2:680:1319:692:26ff:feda:3a81]) by smtp.gmail.com with ESMTPSA id e186sm4222122pfh.60.2020.10.16.18.33.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2020 18:33:03 -0700 (PDT) From: John Stultz To: lkml Cc: John Stultz , Sumit Semwal , Liam Mark , Laura Abbott , Brian Starkey , Hridya Valsaraju , Suren Baghdasaryan , Sandeep Patil , Daniel Mentz , Chris Goldsworthy , =?utf-8?q?=C3=98rjan_Eide?= , Robin Murphy , Ezequiel Garcia , Simon Ser , James Jones , linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org Subject: [PATCH v4 1/7] dma-buf: system_heap: Rework system heap to use sgtables instead of pagelists Date: Sat, 17 Oct 2020 01:32:49 +0000 Message-Id: <20201017013255.43568-2-john.stultz@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201017013255.43568-1-john.stultz@linaro.org> References: <20201017013255.43568-1-john.stultz@linaro.org> MIME-Version: 1.0 In preparation for some patches to optmize the system heap code, rework the dmabuf exporter to utilize sgtables rather then pageslists for tracking the associated pages. This will allow for large order page allocations, as well as more efficient page pooling. In doing so, the system heap stops using the heap-helpers logic which sadly is not quite as generic as I was hoping it to be, so this patch adds heap specific implementations of the dma_buf_ops function handlers. 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 Reviewed-by: Brian Starkey Signed-off-by: John Stultz --- v2: * Fix locking issue and an unused return value Reported-by: kernel test robot Julia Lawall * Make system_heap_buf_ops static Reported-by: kernel test robot v3: * Use the new sgtable mapping functions, as Suggested-by: Daniel Mentz v4: * Make sys_heap static (indirectly) Reported-by: kernel test robot * Spelling fix suggested by BrianS --- drivers/dma-buf/heaps/system_heap.c | 344 ++++++++++++++++++++++++---- 1 file changed, 298 insertions(+), 46 deletions(-) -- 2.17.1 diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index 0bf688e3c023..5c44f9c06807 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -3,7 +3,11 @@ * DMABUF System heap exporter * * Copyright (C) 2011 Google, Inc. - * Copyright (C) 2019 Linaro Ltd. + * Copyright (C) 2019, 2020 Linaro Ltd. + * + * Portions based off of Andrew Davis' SRAM heap: + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis */ #include @@ -15,72 +19,321 @@ #include #include #include -#include -#include +#include + +static struct dma_heap *sys_heap; -#include "heap-helpers.h" +struct system_heap_buffer { + struct dma_heap *heap; + struct list_head attachments; + struct mutex lock; + unsigned long len; + struct sg_table sg_table; + int vmap_cnt; + void *vaddr; +}; -struct dma_heap *sys_heap; +struct dma_heap_attachment { + struct device *dev; + struct sg_table *table; + struct list_head list; +}; -static void system_heap_free(struct heap_helper_buffer *buffer) +static struct sg_table *dup_sg_table(struct sg_table *table) { - pgoff_t pg; + struct sg_table *new_table; + int ret, i; + struct scatterlist *sg, *new_sg; + + new_table = kzalloc(sizeof(*new_table), GFP_KERNEL); + if (!new_table) + return ERR_PTR(-ENOMEM); + + ret = sg_alloc_table(new_table, table->orig_nents, GFP_KERNEL); + if (ret) { + kfree(new_table); + return ERR_PTR(-ENOMEM); + } + + new_sg = new_table->sgl; + for_each_sgtable_sg(table, sg, i) { + sg_set_page(new_sg, sg_page(sg), sg->length, sg->offset); + new_sg = sg_next(new_sg); + } + + return new_table; +} + +static int system_heap_attach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + struct sg_table *table; + + a = kzalloc(sizeof(*a), GFP_KERNEL); + if (!a) + return -ENOMEM; + + table = dup_sg_table(&buffer->sg_table); + if (IS_ERR(table)) { + kfree(a); + return -ENOMEM; + } + + a->table = table; + a->dev = attachment->dev; + INIT_LIST_HEAD(&a->list); + + attachment->priv = a; + + mutex_lock(&buffer->lock); + list_add(&a->list, &buffer->attachments); + mutex_unlock(&buffer->lock); + + return 0; +} + +static void system_heap_detach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a = attachment->priv; + + mutex_lock(&buffer->lock); + list_del(&a->list); + mutex_unlock(&buffer->lock); + + sg_free_table(a->table); + kfree(a->table); + kfree(a); +} - for (pg = 0; pg < buffer->pagecount; pg++) - __free_page(buffer->pages[pg]); - kfree(buffer->pages); +static struct sg_table *system_heap_map_dma_buf(struct dma_buf_attachment *attachment, + enum dma_data_direction direction) +{ + struct dma_heap_attachment *a = attachment->priv; + struct sg_table *table = a->table; + int ret; + + ret = dma_map_sgtable(attachment->dev, table, direction, 0); + if (ret) + return ERR_PTR(ret); + + return table; +} + +static void system_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, + struct sg_table *table, + enum dma_data_direction direction) +{ + dma_unmap_sgtable(attachment->dev, table, direction, 0); +} + +static int system_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, + enum dma_data_direction direction) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + + mutex_lock(&buffer->lock); + + if (buffer->vmap_cnt) + invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); + + list_for_each_entry(a, &buffer->attachments, list) { + dma_sync_sgtable_for_cpu(a->dev, a->table, direction); + } + mutex_unlock(&buffer->lock); + + return 0; +} + +static int system_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, + enum dma_data_direction direction) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + + mutex_lock(&buffer->lock); + + if (buffer->vmap_cnt) + flush_kernel_vmap_range(buffer->vaddr, buffer->len); + + list_for_each_entry(a, &buffer->attachments, list) { + dma_sync_sgtable_for_device(a->dev, a->table, direction); + } + mutex_unlock(&buffer->lock); + + return 0; +} + +static int system_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + struct sg_table *table = &buffer->sg_table; + unsigned long addr = vma->vm_start; + struct sg_page_iter piter; + int ret; + + for_each_sgtable_page(table, &piter, vma->vm_pgoff) { + struct page *page = sg_page_iter_page(&piter); + + ret = remap_pfn_range(vma, addr, page_to_pfn(page), PAGE_SIZE, + vma->vm_page_prot); + if (ret) + return ret; + addr += PAGE_SIZE; + if (addr >= vma->vm_end) + return 0; + } + return 0; +} + +static void *system_heap_do_vmap(struct system_heap_buffer *buffer) +{ + struct sg_table *table = &buffer->sg_table; + int npages = PAGE_ALIGN(buffer->len) / PAGE_SIZE; + struct page **pages = vmalloc(sizeof(struct page *) * npages); + struct page **tmp = pages; + struct sg_page_iter piter; + void *vaddr; + + if (!pages) + return ERR_PTR(-ENOMEM); + + 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); + vfree(pages); + + if (!vaddr) + return ERR_PTR(-ENOMEM); + + return vaddr; +} + +static void *system_heap_vmap(struct dma_buf *dmabuf) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + void *vaddr; + + mutex_lock(&buffer->lock); + if (buffer->vmap_cnt) { + buffer->vmap_cnt++; + vaddr = buffer->vaddr; + goto out; + } + + vaddr = system_heap_do_vmap(buffer); + if (IS_ERR(vaddr)) + goto out; + + buffer->vaddr = vaddr; + buffer->vmap_cnt++; +out: + mutex_unlock(&buffer->lock); + + return vaddr; +} + +static void system_heap_vunmap(struct dma_buf *dmabuf, void *vaddr) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + + mutex_lock(&buffer->lock); + if (!--buffer->vmap_cnt) { + vunmap(buffer->vaddr); + buffer->vaddr = NULL; + } + mutex_unlock(&buffer->lock); +} + +static void system_heap_dma_buf_release(struct dma_buf *dmabuf) +{ + struct system_heap_buffer *buffer = dmabuf->priv; + struct sg_table *table; + struct scatterlist *sg; + int i; + + table = &buffer->sg_table; + for_each_sgtable_sg(table, sg, i) + __free_page(sg_page(sg)); + sg_free_table(table); kfree(buffer); } +static const struct dma_buf_ops system_heap_buf_ops = { + .attach = system_heap_attach, + .detach = system_heap_detach, + .map_dma_buf = system_heap_map_dma_buf, + .unmap_dma_buf = system_heap_unmap_dma_buf, + .begin_cpu_access = system_heap_dma_buf_begin_cpu_access, + .end_cpu_access = system_heap_dma_buf_end_cpu_access, + .mmap = system_heap_mmap, + .vmap = system_heap_vmap, + .vunmap = system_heap_vunmap, + .release = system_heap_dma_buf_release, +}; + static int system_heap_allocate(struct dma_heap *heap, unsigned long len, unsigned long fd_flags, unsigned long heap_flags) { - struct heap_helper_buffer *helper_buffer; + struct system_heap_buffer *buffer; + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); struct dma_buf *dmabuf; - int ret = -ENOMEM; + struct sg_table *table; + struct scatterlist *sg; + pgoff_t pagecount; pgoff_t pg; + int i, ret = -ENOMEM; - helper_buffer = kzalloc(sizeof(*helper_buffer), GFP_KERNEL); - if (!helper_buffer) + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) return -ENOMEM; - init_heap_helper_buffer(helper_buffer, system_heap_free); - helper_buffer->heap = heap; - helper_buffer->size = len; - - helper_buffer->pagecount = len / PAGE_SIZE; - helper_buffer->pages = kmalloc_array(helper_buffer->pagecount, - sizeof(*helper_buffer->pages), - GFP_KERNEL); - if (!helper_buffer->pages) { - ret = -ENOMEM; - goto err0; - } + INIT_LIST_HEAD(&buffer->attachments); + mutex_init(&buffer->lock); + buffer->heap = heap; + buffer->len = len; - for (pg = 0; pg < helper_buffer->pagecount; pg++) { + table = &buffer->sg_table; + pagecount = len / PAGE_SIZE; + if (sg_alloc_table(table, pagecount, GFP_KERNEL)) + goto free_buffer; + + sg = table->sgl; + for (pg = 0; pg < pagecount; pg++) { + struct page *page; /* * Avoid trying to allocate memory if the process - * has been killed by by SIGKILL + * has been killed by SIGKILL */ if (fatal_signal_pending(current)) - goto err1; - - helper_buffer->pages[pg] = alloc_page(GFP_KERNEL | __GFP_ZERO); - if (!helper_buffer->pages[pg]) - goto err1; + goto free_pages; + page = alloc_page(GFP_KERNEL | __GFP_ZERO); + if (!page) + goto free_pages; + sg_set_page(sg, page, page_size(page), 0); + sg = sg_next(sg); } /* create the dmabuf */ - dmabuf = heap_helper_export_dmabuf(helper_buffer, fd_flags); + exp_info.ops = &system_heap_buf_ops; + exp_info.size = buffer->len; + exp_info.flags = fd_flags; + exp_info.priv = buffer; + dmabuf = dma_buf_export(&exp_info); if (IS_ERR(dmabuf)) { ret = PTR_ERR(dmabuf); - goto err1; + goto free_pages; } - helper_buffer->dmabuf = dmabuf; - ret = dma_buf_fd(dmabuf, fd_flags); if (ret < 0) { dma_buf_put(dmabuf); @@ -90,12 +343,12 @@ static int system_heap_allocate(struct dma_heap *heap, return ret; -err1: - while (pg > 0) - __free_page(helper_buffer->pages[--pg]); - kfree(helper_buffer->pages); -err0: - kfree(helper_buffer); +free_pages: + for_each_sgtable_sg(table, sg, i) + __free_page(sg_page(sg)); + sg_free_table(table); +free_buffer: + kfree(buffer); return ret; } @@ -107,7 +360,6 @@ static const struct dma_heap_ops system_heap_ops = { static int system_heap_create(void) { struct dma_heap_export_info exp_info; - int ret = 0; exp_info.name = "system"; exp_info.ops = &system_heap_ops; @@ -115,9 +367,9 @@ static int system_heap_create(void) sys_heap = dma_heap_add(&exp_info); if (IS_ERR(sys_heap)) - ret = PTR_ERR(sys_heap); + return PTR_ERR(sys_heap); - return ret; + return 0; } module_init(system_heap_create); MODULE_LICENSE("GPL v2"); From patchwork Sat Oct 17 01:32:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 317838 Delivered-To: patches@linaro.org Received: by 2002:a92:d603:0:0:0:0:0 with SMTP id w3csp1946880ilm; Fri, 16 Oct 2020 18:33:06 -0700 (PDT) X-Received: by 2002:a63:f053:: with SMTP id s19mr1714981pgj.56.1602898386035; Fri, 16 Oct 2020 18:33:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1602898386; cv=none; d=google.com; s=arc-20160816; b=mAEqSopwfQYpkw86g8+e+boylc/F3/oVdi6LvY5OmY475XEF/37gENQrGWzAqj/JD2 83vT1I3fxbJZJ6sQiqgcjsTYnBURNPtuW92xZB6w4tGkYXp0aKyK1vX7bF40gErzPn/a FcRubTWUY8kOCD7LR0Tv3ZB5inLF7btT3HE7wXLTnLKocSIejYV4hyC08wY4Mmg6bdaP wxJL4TY/JyO+ZXr6973Bq+SgSmhw6qy9tj/jWrWAZPFobpCc4kIHBPH6jR3nz+WdaEIS b1JnWApAcGXs9/2NjO/ytjOAWOkP7BHOJHTc5k+YqZJSuEggDuPLXh//uY9CgXGlx12Y 0AIw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=sz6fxaq3RpBzDvE0Efn4zSKYKcie3tSIuGNKkyogZUQ=; b=zk0Rn6rOFuYQOwx5H+8sbncqQwlZkspN4ITBm5OZXUmvbCCAx4JI+kBviP330cq9Oh o5/dpdsL3lgDR4g6BoldwKMj9RLLtFtvSsqw2q976xho2/HNl9gb3G8sXnqsrV/8K50o uhjXAmuk+qGA5SkeB+AO669kfz/QvR+TRycqxFu/K4tcN5vS7TTa8s2e7SMP77VmSDZ2 fVQ4xLE18T+bsN3+WnMXKMXnNuRUxHlZScevMXU/FJpqeiMeFJ19ng0GsTp3DO3z2D3B dU4qCDQps5jWLfGM8n9YSi4wXUsYtGGGNqtBtjrLCiBGwp05k14x4P2LTJPhsnIy2gDH /3Jg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=kmuKKEz0; spf=pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id it13sor2186184pjb.19.2020.10.16.18.33.05 for (Google Transport Security); Fri, 16 Oct 2020 18:33:06 -0700 (PDT) Received-SPF: pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=kmuKKEz0; spf=pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org 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=sz6fxaq3RpBzDvE0Efn4zSKYKcie3tSIuGNKkyogZUQ=; b=kmuKKEz0QTDWSQeJ9K1X0f/mXzUULphmOM0Pfyc+WZAz+Ieu40SJ/0zBbhPHPba9i5 QWf2V9iBImkh930xP5af6/C+g2qWDTyxnLg7iUPwv/VAUeqgbA1B7eDtjzjQ4RiXuqNH niaLUMFh1SZRHFZoBeR4NewCuT7ATgcBHzama1c6gQll9KaYXRwKRym7vH+UJAZ/Q3nB xyOX7P/X8pX0Jpfa99FYaUr5CCv5dcKDHGiUNoEIbuk4DNQBM/DpjZ0bujM//LJjwASi zf5gQIlsWjpAeW/NuKJ0Oq+EuwsKWGf00fp9tlTc6fLihQyjgu1cuKGruL+OKX4aMKL8 qKsA== 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=sz6fxaq3RpBzDvE0Efn4zSKYKcie3tSIuGNKkyogZUQ=; b=BlQlCeDW6latxQ5YWNZm3ZJ+HHmalVrU60kDgd3QQLdbYbJxN5Vekt3EaZsy9VMlXh XvB+YVds/PPGurK5I4Z5vu2m7Ry/u8uI0ZTNYWvXUpOjnMqnmRa4Gkj30zOJa5y1i2XD OvrGn2cDijpZitzQ+EPfPAbwsmIHDWPVPk+ulOcRc1WlmaZBPWzfkuN4sCxfSckmaZjC HyTRFjxrDyut7gMtne5bTwgzKMmHNqYB/kyo/n8PGiqMmC5LjO0DWgPeULR+v3tjs3cU 0l2OGDECTXYcQvqFdJECH3zLY7owFfqhn559LTlZHKJ5mFnnNjE+bJHPe3AXg/yNgDoh nbrw== X-Gm-Message-State: AOAM533wNmt71AwydHL5GmoLPUWsaD7xLk918fE8wAOkQG/DtNTCsnNi dh/BXdo68/CjKEkAS2wOcR5auLi2 X-Google-Smtp-Source: ABdhPJxC2GlJ57pZkuZuFysrT2nn9auWEqUhyimYGIACyURqb9YcHErLp8ePjnqNd1OoAB2qGmaeJg== X-Received: by 2002:a17:90a:5b05:: with SMTP id o5mr6676822pji.139.1602898385600; Fri, 16 Oct 2020 18:33:05 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([2601:1c2:680:1319:692:26ff:feda:3a81]) by smtp.gmail.com with ESMTPSA id e186sm4222122pfh.60.2020.10.16.18.33.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2020 18:33:05 -0700 (PDT) From: John Stultz To: lkml Cc: John Stultz , Sumit Semwal , Liam Mark , Laura Abbott , Brian Starkey , Hridya Valsaraju , Suren Baghdasaryan , Sandeep Patil , Daniel Mentz , Chris Goldsworthy , =?utf-8?q?=C3=98rjan_Eide?= , Robin Murphy , Ezequiel Garcia , Simon Ser , James Jones , linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org Subject: [PATCH v4 2/7] dma-buf: heaps: Move heap-helper logic into the cma_heap implementation Date: Sat, 17 Oct 2020 01:32:50 +0000 Message-Id: <20201017013255.43568-3-john.stultz@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201017013255.43568-1-john.stultz@linaro.org> References: <20201017013255.43568-1-john.stultz@linaro.org> MIME-Version: 1.0 Since the heap-helpers logic ended up not being as generic as hoped, move the heap-helpers dma_buf_ops implementations into the cma_heap directly. This will allow us to remove the heap_helpers code in a following patch. 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 Reviewed-by: Brian Starkey Signed-off-by: John Stultz --- v2: * Fix unused return value and locking issue Reported-by: kernel test robot Julia Lawall * Make cma_heap_buf_ops static suggested by kernel test robot * Fix uninitialized return in cma Reported-by: kernel test robot * Minor cleanups v3: * Use the new sgtable mapping functions, as Suggested-by: Daniel Mentz v4: * Spelling fix suggested by BrianS --- drivers/dma-buf/heaps/cma_heap.c | 317 ++++++++++++++++++++++++++----- 1 file changed, 267 insertions(+), 50 deletions(-) -- 2.17.1 diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c index 626cf7fd033a..d6fab7cdeaf9 100644 --- a/drivers/dma-buf/heaps/cma_heap.c +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -2,76 +2,291 @@ /* * DMABUF CMA heap exporter * - * Copyright (C) 2012, 2019 Linaro Ltd. + * Copyright (C) 2012, 2019, 2020 Linaro Ltd. * Author: for ST-Ericsson. + * + * Also utilizing parts of Andrew Davis' SRAM heap: + * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/ + * Andrew F. Davis */ - #include -#include #include -#include #include +#include +#include #include -#include #include +#include +#include #include -#include #include -#include +#include -#include "heap-helpers.h" struct cma_heap { struct dma_heap *heap; struct cma *cma; }; -static void cma_heap_free(struct heap_helper_buffer *buffer) +struct cma_heap_buffer { + struct cma_heap *heap; + struct list_head attachments; + struct mutex lock; + unsigned long len; + struct page *cma_pages; + struct page **pages; + pgoff_t pagecount; + int vmap_cnt; + void *vaddr; +}; + +struct dma_heap_attachment { + struct device *dev; + struct sg_table table; + struct list_head list; +}; + +static int cma_heap_attach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) { - struct cma_heap *cma_heap = dma_heap_get_drvdata(buffer->heap); - unsigned long nr_pages = buffer->pagecount; - struct page *cma_pages = buffer->priv_virt; + struct cma_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + int ret; - /* free page list */ - kfree(buffer->pages); - /* release memory */ - cma_release(cma_heap->cma, cma_pages, nr_pages); + a = kzalloc(sizeof(*a), GFP_KERNEL); + if (!a) + return -ENOMEM; + + ret = sg_alloc_table_from_pages(&a->table, buffer->pages, + buffer->pagecount, 0, + buffer->pagecount << PAGE_SHIFT, + GFP_KERNEL); + if (ret) { + kfree(a); + return ret; + } + + a->dev = attachment->dev; + INIT_LIST_HEAD(&a->list); + + attachment->priv = a; + + mutex_lock(&buffer->lock); + list_add(&a->list, &buffer->attachments); + mutex_unlock(&buffer->lock); + + return 0; +} + +static void cma_heap_detach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a = attachment->priv; + + mutex_lock(&buffer->lock); + list_del(&a->list); + mutex_unlock(&buffer->lock); + + sg_free_table(&a->table); + kfree(a); +} + +static struct sg_table *cma_heap_map_dma_buf(struct dma_buf_attachment *attachment, + enum dma_data_direction direction) +{ + struct dma_heap_attachment *a = attachment->priv; + struct sg_table *table = &a->table; + int ret; + + ret = dma_map_sgtable(attachment->dev, table, direction, 0); + if (ret) + return ERR_PTR(-ENOMEM); + return table; +} + +static void cma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, + struct sg_table *table, + enum dma_data_direction direction) +{ + dma_unmap_sgtable(attachment->dev, table, direction, 0); +} + +static int cma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, + enum dma_data_direction direction) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + + if (buffer->vmap_cnt) + invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); + + mutex_lock(&buffer->lock); + list_for_each_entry(a, &buffer->attachments, list) { + dma_sync_sgtable_for_cpu(a->dev, &a->table, direction); + } + mutex_unlock(&buffer->lock); + + return 0; +} + +static int cma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, + enum dma_data_direction direction) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + struct dma_heap_attachment *a; + + if (buffer->vmap_cnt) + flush_kernel_vmap_range(buffer->vaddr, buffer->len); + + mutex_lock(&buffer->lock); + list_for_each_entry(a, &buffer->attachments, list) { + dma_sync_sgtable_for_device(a->dev, &a->table, direction); + } + mutex_unlock(&buffer->lock); + + return 0; +} + +static vm_fault_t cma_heap_vm_fault(struct vm_fault *vmf) +{ + struct vm_area_struct *vma = vmf->vma; + struct cma_heap_buffer *buffer = vma->vm_private_data; + + if (vmf->pgoff > buffer->pagecount) + return VM_FAULT_SIGBUS; + + vmf->page = buffer->pages[vmf->pgoff]; + get_page(vmf->page); + + return 0; +} + +static const struct vm_operations_struct dma_heap_vm_ops = { + .fault = cma_heap_vm_fault, +}; + +static int cma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + + if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0) + return -EINVAL; + + vma->vm_ops = &dma_heap_vm_ops; + vma->vm_private_data = buffer; + + return 0; +} + +static void *cma_heap_do_vmap(struct cma_heap_buffer *buffer) +{ + void *vaddr; + + vaddr = vmap(buffer->pages, buffer->pagecount, VM_MAP, PAGE_KERNEL); + if (!vaddr) + return ERR_PTR(-ENOMEM); + + return vaddr; +} + +static void *cma_heap_vmap(struct dma_buf *dmabuf) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + void *vaddr; + + mutex_lock(&buffer->lock); + if (buffer->vmap_cnt) { + buffer->vmap_cnt++; + vaddr = buffer->vaddr; + goto out; + } + + vaddr = cma_heap_do_vmap(buffer); + if (IS_ERR(vaddr)) + goto out; + + buffer->vaddr = vaddr; + buffer->vmap_cnt++; +out: + mutex_unlock(&buffer->lock); + + return vaddr; +} + +static void cma_heap_vunmap(struct dma_buf *dmabuf, void *vaddr) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + + mutex_lock(&buffer->lock); + if (!--buffer->vmap_cnt) { + vunmap(buffer->vaddr); + buffer->vaddr = NULL; + } + mutex_unlock(&buffer->lock); +} + +static void cma_heap_dma_buf_release(struct dma_buf *dmabuf) +{ + struct cma_heap_buffer *buffer = dmabuf->priv; + struct cma_heap *cma_heap = buffer->heap; + + if (buffer->vmap_cnt > 0) { + WARN(1, "%s: buffer still mapped in the kernel\n", __func__); + vunmap(buffer->vaddr); + } + + cma_release(cma_heap->cma, buffer->cma_pages, buffer->pagecount); kfree(buffer); } -/* dmabuf heap CMA operations functions */ +static const struct dma_buf_ops cma_heap_buf_ops = { + .attach = cma_heap_attach, + .detach = cma_heap_detach, + .map_dma_buf = cma_heap_map_dma_buf, + .unmap_dma_buf = cma_heap_unmap_dma_buf, + .begin_cpu_access = cma_heap_dma_buf_begin_cpu_access, + .end_cpu_access = cma_heap_dma_buf_end_cpu_access, + .mmap = cma_heap_mmap, + .vmap = cma_heap_vmap, + .vunmap = cma_heap_vunmap, + .release = cma_heap_dma_buf_release, +}; + static int cma_heap_allocate(struct dma_heap *heap, - unsigned long len, - unsigned long fd_flags, - unsigned long heap_flags) + unsigned long len, + unsigned long fd_flags, + unsigned long heap_flags) { struct cma_heap *cma_heap = dma_heap_get_drvdata(heap); - struct heap_helper_buffer *helper_buffer; - struct page *cma_pages; + struct cma_heap_buffer *buffer; + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); size_t size = PAGE_ALIGN(len); - unsigned long nr_pages = size >> PAGE_SHIFT; + pgoff_t pagecount = size >> PAGE_SHIFT; unsigned long align = get_order(size); + struct page *cma_pages; struct dma_buf *dmabuf; int ret = -ENOMEM; pgoff_t pg; - if (align > CONFIG_CMA_ALIGNMENT) - align = CONFIG_CMA_ALIGNMENT; - - helper_buffer = kzalloc(sizeof(*helper_buffer), GFP_KERNEL); - if (!helper_buffer) + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) return -ENOMEM; - init_heap_helper_buffer(helper_buffer, cma_heap_free); - helper_buffer->heap = heap; - helper_buffer->size = len; + INIT_LIST_HEAD(&buffer->attachments); + mutex_init(&buffer->lock); + buffer->len = size; + + if (align > CONFIG_CMA_ALIGNMENT) + align = CONFIG_CMA_ALIGNMENT; - cma_pages = cma_alloc(cma_heap->cma, nr_pages, align, false); + cma_pages = cma_alloc(cma_heap->cma, pagecount, align, false); if (!cma_pages) - goto free_buf; + goto free_buffer; + /* Clear the cma pages */ if (PageHighMem(cma_pages)) { - unsigned long nr_clear_pages = nr_pages; + unsigned long nr_clear_pages = pagecount; struct page *page = cma_pages; while (nr_clear_pages > 0) { @@ -85,7 +300,6 @@ static int cma_heap_allocate(struct dma_heap *heap, */ if (fatal_signal_pending(current)) goto free_cma; - page++; nr_clear_pages--; } @@ -93,28 +307,30 @@ static int cma_heap_allocate(struct dma_heap *heap, memset(page_address(cma_pages), 0, size); } - helper_buffer->pagecount = nr_pages; - helper_buffer->pages = kmalloc_array(helper_buffer->pagecount, - sizeof(*helper_buffer->pages), - GFP_KERNEL); - if (!helper_buffer->pages) { + buffer->pages = kmalloc_array(pagecount, sizeof(*buffer->pages), GFP_KERNEL); + if (!buffer->pages) { ret = -ENOMEM; goto free_cma; } - for (pg = 0; pg < helper_buffer->pagecount; pg++) - helper_buffer->pages[pg] = &cma_pages[pg]; + for (pg = 0; pg < pagecount; pg++) + buffer->pages[pg] = &cma_pages[pg]; + + buffer->cma_pages = cma_pages; + buffer->heap = cma_heap; + buffer->pagecount = pagecount; /* create the dmabuf */ - dmabuf = heap_helper_export_dmabuf(helper_buffer, fd_flags); + exp_info.ops = &cma_heap_buf_ops; + exp_info.size = buffer->len; + exp_info.flags = fd_flags; + exp_info.priv = buffer; + dmabuf = dma_buf_export(&exp_info); if (IS_ERR(dmabuf)) { ret = PTR_ERR(dmabuf); goto free_pages; } - helper_buffer->dmabuf = dmabuf; - helper_buffer->priv_virt = cma_pages; - ret = dma_buf_fd(dmabuf, fd_flags); if (ret < 0) { dma_buf_put(dmabuf); @@ -125,11 +341,12 @@ static int cma_heap_allocate(struct dma_heap *heap, return ret; free_pages: - kfree(helper_buffer->pages); + kfree(buffer->pages); free_cma: - cma_release(cma_heap->cma, cma_pages, nr_pages); -free_buf: - kfree(helper_buffer); + cma_release(cma_heap->cma, cma_pages, pagecount); +free_buffer: + kfree(buffer); + return ret; } From patchwork Sat Oct 17 01:32:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 317839 Delivered-To: patches@linaro.org Received: by 2002:a92:d603:0:0:0:0:0 with SMTP id w3csp1946896ilm; Fri, 16 Oct 2020 18:33:08 -0700 (PDT) X-Received: by 2002:a63:f807:: with SMTP id n7mr5479333pgh.311.1602898388012; Fri, 16 Oct 2020 18:33:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1602898388; cv=none; d=google.com; s=arc-20160816; b=azBXqUX9KIEL56BATr4Yvcw5B/i5HqgkVxa42bqFkTpMbe7YEHOap9e4D6Nxn+sEom etbR0OmNsYjBdlnQgZlvQ9HGGsRhrwhIvtFWhGg/aJiyIP3ryzS2yzZpzgUEyahyIwLQ ZW4ehESCSUERpGMnFBNeNWGsHqRJPEhluY1OphQbD8z/YaUKz+mMnHI4kglqXg1n0Fcv znmKn5ke4v9+CxPNTroswmEztM01ZKJwIW7JVe1DTctdLhKfiOmvv82XXF0JNpIgsYZR nn7wZiYABdXjIW4xLtw8Skh+Gj5ZUcyEZgoolVbqkXGdM81vjs4bt8byR82nqM6B5mXg sbCQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=/CAm5bWjnLRF5xW6wICKjDF43YTUJt4tBtw4MXOZQXs=; b=DrQOQ0glf9M2tP8PWx9OsuAsOTqWKiqTXZ3fNCtzS9zV7EBP/wgDtb4JKIeefG0JOF 836MDHpcvgnoFY02Grci4H+pppEDuzIVE/MM3GOJ9DMPX6T1+3y/7LX6VPlAGPj027qL mzTspRJGHL72ya2lEUns1vLeSXgnU5KUdtzr36OjKJUn5LL5MA2PO0o0ZlaeSJu0H+Nt 12ajl3X4f7zeaUOO2QIyzGcj9dnMYfi3jSUF2lLfZtkOVE77mk8qTV5GrrDQDPTes2KI mFUW9RTSJeIVh1VIbtAgQdP3mWvV3mkj9L2P1RlA22hENoWndk6OdfDvKXuwCTpWaDgd JwMQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Pl3V0wHt; spf=pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id ob3sor2101845pjb.27.2020.10.16.18.33.07 for (Google Transport Security); Fri, 16 Oct 2020 18:33:07 -0700 (PDT) Received-SPF: pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Pl3V0wHt; spf=pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org 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=/CAm5bWjnLRF5xW6wICKjDF43YTUJt4tBtw4MXOZQXs=; b=Pl3V0wHtX/10KV/MC3rXOcTw6WAZJSul3E1Vk7IuEM59gxNEYDoxSY17w1ahSsk8VP anxYRsYJVDLavlx5sIEHXSHrb0twXdtCPvYr7T2THa5a6IVQhB+WDTGCv6903vtyhRKP VBZFv/F55BO3wY4PBapsV2l/Ha1QxN8TMEwD4OYT5ffdUx9qpcpkS1Mro8OIdsEVNclT lT17FH8vJUfmvy7sNL8Gg5kX/1H0BRKo3/ft5ZN+9BpZO9jVQzNTzZlxtckH7KResr8w m2g0Nbjb/NBV4wIquE/IgI1SnkLPHIeMViI8JAC6AzIOGi0J43w3E/wgJhp1TDllBU/k /X9g== 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=/CAm5bWjnLRF5xW6wICKjDF43YTUJt4tBtw4MXOZQXs=; b=kjGc8eneb2Jyq3krwQszrZwxksQwLtItGaEoFmKeVgNW5jZ5tdlfWxgG2AmKd4Af1C 449O2Cr3wH4lBOm5oRnG5r9gMQY2lvKKTmR32C1kaQcMLfEdGFNySFhqIQLX+FLzgZY9 tvstIGsE0o4lMpCfpLF9To2nlxi7W8j3QfzEmgQKBk0Z6CqE7EerzRvdCVdIkQd39ZTV OtYUyiSC/WVA1Ym7NhckIpyNW8wLAwo6HO0zjcw5RwM4HxYW5IyCrH544MrNkXmaI9Pc NkF4gBHbwHekcoPtV0g8x7kgMXwBYULpT+4ZK/FIFe4Mu74VULD6tPakJRnWXXzKXtAu Ae1g== X-Gm-Message-State: AOAM530NnxQJopFrlRe5n+vLQuz4/ppWiRFpP5mfnZ+1znvTz6r5Ut6S RYyEAyTwwL5VlS/POzRWVHSTPfHk X-Google-Smtp-Source: ABdhPJz3SuGIM0clMNOXoTmyj3ORLLv/LECGizCCGJ8mT+k1qLg3I7uOEvzF+34UeqgHPIX1hlL9eQ== X-Received: by 2002:a17:90a:9ab:: with SMTP id 40mr6534541pjo.26.1602898387575; Fri, 16 Oct 2020 18:33:07 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([2601:1c2:680:1319:692:26ff:feda:3a81]) by smtp.gmail.com with ESMTPSA id e186sm4222122pfh.60.2020.10.16.18.33.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2020 18:33:06 -0700 (PDT) From: John Stultz To: lkml Cc: John Stultz , Sumit Semwal , Liam Mark , Laura Abbott , Brian Starkey , Hridya Valsaraju , Suren Baghdasaryan , Sandeep Patil , Daniel Mentz , Chris Goldsworthy , =?utf-8?q?=C3=98rjan_Eide?= , Robin Murphy , Ezequiel Garcia , Simon Ser , James Jones , linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org Subject: [PATCH v4 3/7] dma-buf: heaps: Remove heap-helpers code Date: Sat, 17 Oct 2020 01:32:51 +0000 Message-Id: <20201017013255.43568-4-john.stultz@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201017013255.43568-1-john.stultz@linaro.org> References: <20201017013255.43568-1-john.stultz@linaro.org> MIME-Version: 1.0 The heap-helpers code was not as generic as initially hoped and it is now not being used, so remove it from the tree. 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 Reviewed-by: Brian Starkey Signed-off-by: John Stultz --- drivers/dma-buf/heaps/Makefile | 1 - drivers/dma-buf/heaps/heap-helpers.c | 270 --------------------------- drivers/dma-buf/heaps/heap-helpers.h | 53 ------ 3 files changed, 324 deletions(-) delete mode 100644 drivers/dma-buf/heaps/heap-helpers.c delete mode 100644 drivers/dma-buf/heaps/heap-helpers.h -- 2.17.1 diff --git a/drivers/dma-buf/heaps/Makefile b/drivers/dma-buf/heaps/Makefile index 6e54cdec3da0..974467791032 100644 --- a/drivers/dma-buf/heaps/Makefile +++ b/drivers/dma-buf/heaps/Makefile @@ -1,4 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 -obj-y += heap-helpers.o obj-$(CONFIG_DMABUF_HEAPS_SYSTEM) += system_heap.o obj-$(CONFIG_DMABUF_HEAPS_CMA) += cma_heap.o diff --git a/drivers/dma-buf/heaps/heap-helpers.c b/drivers/dma-buf/heaps/heap-helpers.c deleted file mode 100644 index d0696cf937af..000000000000 --- a/drivers/dma-buf/heaps/heap-helpers.c +++ /dev/null @@ -1,270 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "heap-helpers.h" - -void init_heap_helper_buffer(struct heap_helper_buffer *buffer, - void (*free)(struct heap_helper_buffer *)) -{ - buffer->priv_virt = NULL; - mutex_init(&buffer->lock); - buffer->vmap_cnt = 0; - buffer->vaddr = NULL; - buffer->pagecount = 0; - buffer->pages = NULL; - INIT_LIST_HEAD(&buffer->attachments); - buffer->free = free; -} - -struct dma_buf *heap_helper_export_dmabuf(struct heap_helper_buffer *buffer, - int fd_flags) -{ - DEFINE_DMA_BUF_EXPORT_INFO(exp_info); - - exp_info.ops = &heap_helper_ops; - exp_info.size = buffer->size; - exp_info.flags = fd_flags; - exp_info.priv = buffer; - - return dma_buf_export(&exp_info); -} - -static void *dma_heap_map_kernel(struct heap_helper_buffer *buffer) -{ - void *vaddr; - - vaddr = vmap(buffer->pages, buffer->pagecount, VM_MAP, PAGE_KERNEL); - if (!vaddr) - return ERR_PTR(-ENOMEM); - - return vaddr; -} - -static void dma_heap_buffer_destroy(struct heap_helper_buffer *buffer) -{ - if (buffer->vmap_cnt > 0) { - WARN(1, "%s: buffer still mapped in the kernel\n", __func__); - vunmap(buffer->vaddr); - } - - buffer->free(buffer); -} - -static void *dma_heap_buffer_vmap_get(struct heap_helper_buffer *buffer) -{ - void *vaddr; - - if (buffer->vmap_cnt) { - buffer->vmap_cnt++; - return buffer->vaddr; - } - vaddr = dma_heap_map_kernel(buffer); - if (IS_ERR(vaddr)) - return vaddr; - buffer->vaddr = vaddr; - buffer->vmap_cnt++; - return vaddr; -} - -static void dma_heap_buffer_vmap_put(struct heap_helper_buffer *buffer) -{ - if (!--buffer->vmap_cnt) { - vunmap(buffer->vaddr); - buffer->vaddr = NULL; - } -} - -struct dma_heaps_attachment { - struct device *dev; - struct sg_table table; - struct list_head list; -}; - -static int dma_heap_attach(struct dma_buf *dmabuf, - struct dma_buf_attachment *attachment) -{ - struct dma_heaps_attachment *a; - struct heap_helper_buffer *buffer = dmabuf->priv; - int ret; - - a = kzalloc(sizeof(*a), GFP_KERNEL); - if (!a) - return -ENOMEM; - - ret = sg_alloc_table_from_pages(&a->table, buffer->pages, - buffer->pagecount, 0, - buffer->pagecount << PAGE_SHIFT, - GFP_KERNEL); - if (ret) { - kfree(a); - return ret; - } - - a->dev = attachment->dev; - INIT_LIST_HEAD(&a->list); - - attachment->priv = a; - - mutex_lock(&buffer->lock); - list_add(&a->list, &buffer->attachments); - mutex_unlock(&buffer->lock); - - return 0; -} - -static void dma_heap_detach(struct dma_buf *dmabuf, - struct dma_buf_attachment *attachment) -{ - struct dma_heaps_attachment *a = attachment->priv; - struct heap_helper_buffer *buffer = dmabuf->priv; - - mutex_lock(&buffer->lock); - list_del(&a->list); - mutex_unlock(&buffer->lock); - - sg_free_table(&a->table); - kfree(a); -} - -static -struct sg_table *dma_heap_map_dma_buf(struct dma_buf_attachment *attachment, - enum dma_data_direction direction) -{ - struct dma_heaps_attachment *a = attachment->priv; - struct sg_table *table = &a->table; - int ret; - - ret = dma_map_sgtable(attachment->dev, table, direction, 0); - if (ret) - table = ERR_PTR(ret); - return table; -} - -static void dma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, - struct sg_table *table, - enum dma_data_direction direction) -{ - dma_unmap_sgtable(attachment->dev, table, direction, 0); -} - -static vm_fault_t dma_heap_vm_fault(struct vm_fault *vmf) -{ - struct vm_area_struct *vma = vmf->vma; - struct heap_helper_buffer *buffer = vma->vm_private_data; - - if (vmf->pgoff > buffer->pagecount) - return VM_FAULT_SIGBUS; - - vmf->page = buffer->pages[vmf->pgoff]; - get_page(vmf->page); - - return 0; -} - -static const struct vm_operations_struct dma_heap_vm_ops = { - .fault = dma_heap_vm_fault, -}; - -static int dma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) -{ - struct heap_helper_buffer *buffer = dmabuf->priv; - - if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0) - return -EINVAL; - - vma->vm_ops = &dma_heap_vm_ops; - vma->vm_private_data = buffer; - - return 0; -} - -static void dma_heap_dma_buf_release(struct dma_buf *dmabuf) -{ - struct heap_helper_buffer *buffer = dmabuf->priv; - - dma_heap_buffer_destroy(buffer); -} - -static int dma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, - enum dma_data_direction direction) -{ - struct heap_helper_buffer *buffer = dmabuf->priv; - struct dma_heaps_attachment *a; - int ret = 0; - - mutex_lock(&buffer->lock); - - if (buffer->vmap_cnt) - invalidate_kernel_vmap_range(buffer->vaddr, buffer->size); - - list_for_each_entry(a, &buffer->attachments, list) { - dma_sync_sg_for_cpu(a->dev, a->table.sgl, a->table.nents, - direction); - } - mutex_unlock(&buffer->lock); - - return ret; -} - -static int dma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, - enum dma_data_direction direction) -{ - struct heap_helper_buffer *buffer = dmabuf->priv; - struct dma_heaps_attachment *a; - - mutex_lock(&buffer->lock); - - if (buffer->vmap_cnt) - flush_kernel_vmap_range(buffer->vaddr, buffer->size); - - list_for_each_entry(a, &buffer->attachments, list) { - dma_sync_sg_for_device(a->dev, a->table.sgl, a->table.nents, - direction); - } - mutex_unlock(&buffer->lock); - - return 0; -} - -static void *dma_heap_dma_buf_vmap(struct dma_buf *dmabuf) -{ - struct heap_helper_buffer *buffer = dmabuf->priv; - void *vaddr; - - mutex_lock(&buffer->lock); - vaddr = dma_heap_buffer_vmap_get(buffer); - mutex_unlock(&buffer->lock); - - return vaddr; -} - -static void dma_heap_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) -{ - struct heap_helper_buffer *buffer = dmabuf->priv; - - mutex_lock(&buffer->lock); - dma_heap_buffer_vmap_put(buffer); - mutex_unlock(&buffer->lock); -} - -const struct dma_buf_ops heap_helper_ops = { - .map_dma_buf = dma_heap_map_dma_buf, - .unmap_dma_buf = dma_heap_unmap_dma_buf, - .mmap = dma_heap_mmap, - .release = dma_heap_dma_buf_release, - .attach = dma_heap_attach, - .detach = dma_heap_detach, - .begin_cpu_access = dma_heap_dma_buf_begin_cpu_access, - .end_cpu_access = dma_heap_dma_buf_end_cpu_access, - .vmap = dma_heap_dma_buf_vmap, - .vunmap = dma_heap_dma_buf_vunmap, -}; diff --git a/drivers/dma-buf/heaps/heap-helpers.h b/drivers/dma-buf/heaps/heap-helpers.h deleted file mode 100644 index 805d2df88024..000000000000 --- a/drivers/dma-buf/heaps/heap-helpers.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * DMABUF Heaps helper code - * - * Copyright (C) 2011 Google, Inc. - * Copyright (C) 2019 Linaro Ltd. - */ - -#ifndef _HEAP_HELPERS_H -#define _HEAP_HELPERS_H - -#include -#include - -/** - * struct heap_helper_buffer - helper buffer metadata - * @heap: back pointer to the heap the buffer came from - * @dmabuf: backing dma-buf for this buffer - * @size: size of the buffer - * @priv_virt pointer to heap specific private value - * @lock mutext to protect the data in this structure - * @vmap_cnt count of vmap references on the buffer - * @vaddr vmap'ed virtual address - * @pagecount number of pages in the buffer - * @pages list of page pointers - * @attachments list of device attachments - * - * @free heap callback to free the buffer - */ -struct heap_helper_buffer { - struct dma_heap *heap; - struct dma_buf *dmabuf; - size_t size; - - void *priv_virt; - struct mutex lock; - int vmap_cnt; - void *vaddr; - pgoff_t pagecount; - struct page **pages; - struct list_head attachments; - - void (*free)(struct heap_helper_buffer *buffer); -}; - -void init_heap_helper_buffer(struct heap_helper_buffer *buffer, - void (*free)(struct heap_helper_buffer *)); - -struct dma_buf *heap_helper_export_dmabuf(struct heap_helper_buffer *buffer, - int fd_flags); - -extern const struct dma_buf_ops heap_helper_ops; -#endif /* _HEAP_HELPERS_H */ From patchwork Sat Oct 17 01:32:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 317840 Delivered-To: patches@linaro.org Received: by 2002:a92:d603:0:0:0:0:0 with SMTP id w3csp1946915ilm; Fri, 16 Oct 2020 18:33:10 -0700 (PDT) X-Received: by 2002:a17:90b:2301:: with SMTP id mt1mr6402121pjb.80.1602898389843; Fri, 16 Oct 2020 18:33:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1602898389; cv=none; d=google.com; s=arc-20160816; b=uabt2xQosPVVuhg1EalcCO5hNLmOGgChE8EAgCeFUZX6p4Gpus+WhEhxBP0H4nP0ji JpWWgt27zAAShUsy9NmTs4t1Ce3zcbEhgHBlyDVNJUmPDnYGJQocTT7gOFf9i7wNowJT qj+oQVDUQZWL05D+t+M4Ktx+9s3Wmy5CFin539zawreIhmh/R0/tIbeksKcmg0VFRxNu TDTY3L0q+gU3SjiPKvskoIUI/rYs/zseYu6u/MM0AgsxnscAKpcGvEupZ4PlDOlW1HEY JQZf0btyL/fyFaNQjufqzQ516Q6XvQvaKvpB9wkPj3QjD0GGPV1JQDvjJv33Y/6aY14h bx/w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=iR7YqdbhZNfVJF8uMwOtE0JylwHTqdGMkjBgVBa33M8=; b=OmPIQm7Ogu0YXd+yphGd7PCxupeBKwseDbNx9J1OTElzSaAQx+kf/XHNk9o/5y9nZp LRTf7YDtDCLBU12ay2/zjoCYcL2CQDg6Zv52qXp9zjerfTIRKfaCDYOVQ1mTgijkNjyW M6Q+Ob/HoydkhXC31i9jVKjuA09c0KIZk32y6lBYPNikjt1cMbad2gUgDb0mKB9gWzba quvgurlFShD+9weyZ83CSsdoxxlKUBblhzgK8rpiKPaVXn1rOEpNG8/0uCqaExajM2yz WySNCE0jGaqDDxCz1iaudV3y4p48XveSsy6lyH9h7+/dhtPvl7rNMxfS7MUDJCZvG/RT n+Uw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dz8HkwFv; spf=pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id v124sor1824936pfv.55.2020.10.16.18.33.09 for (Google Transport Security); Fri, 16 Oct 2020 18:33:09 -0700 (PDT) Received-SPF: pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=dz8HkwFv; spf=pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org 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=iR7YqdbhZNfVJF8uMwOtE0JylwHTqdGMkjBgVBa33M8=; b=dz8HkwFvcyxf+bexCqIpuVcjDY5ERSJDBUb292BjZsQIEXZZVNtxyexC8GKQ+df5JU V2Kl3Gjyt0qB/dZivUP0fuWlS1U1Qacn9uU72UtRjxKSCtenZVd+CyLuEUaHxYX9OI4Q QCheDW+AwHAJx7xHNn3X9pjWsWss+KxeDz83WfxPLCL28i6aHR6saOuuDmVHCXKBzjSM hymLFJY931oEO0GIAISh6/cpYCp6LjXXK84DRpfEq4Ix92XpkjPYfITBPGJLqOxMqWfJ xI3K0Eu8X0pTjU+QpUFKyt6qK5D8zmLc+3aTMZre+ZW8QpDScklXsihXYnE11slZ0N9S 7fLg== 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=iR7YqdbhZNfVJF8uMwOtE0JylwHTqdGMkjBgVBa33M8=; b=uhSfDJnMDfDcrP3EVVfxIcOuW2CWwRFH0fBDNawiLO9x1mJYDY/Q5YBrzX+Y4CPtAC zz02CnxASm0ZdL3c5eQrlQG3/3nlFGG3Iiv0KhdOE82syqfTteb322XFBDiwxlcgMBwX 4lpWVfhg4VAGziU29xACfqxquAbEhun4K0KH+n7HOW2hygqdZWFCC+PS0wF9/5N3w7rd xHLgjsKKTeyep0mfr1OESl8H2FzB+QLCfDLm2Jt5Ns1FZXmBKxD4BaXT85Dh3oFWf0pb egTDsxHd5SAqLAuAHbcvg/JgWgzd8sbzt5mvqhEvS01fPlBWV4O0SlgD0HvU3g8G3t8h YAfA== X-Gm-Message-State: AOAM533OAOdnG4gDbvau7ARCt7KpR7ZRRsk1ZetNtCExkR+NrG3dxM7i 5sGmF/qYtV25la0bIhcXbkFWgBhD X-Google-Smtp-Source: ABdhPJyxwwN2FExTuTs2c6ri2s4xoSO3uY6KplbKRjgUGJkaOeCWmiOtqzlDnc0H1K40t5IU+QJGDg== X-Received: by 2002:a62:6044:0:b029:151:1a04:895 with SMTP id u65-20020a6260440000b02901511a040895mr6340247pfb.34.1602898389334; Fri, 16 Oct 2020 18:33:09 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([2601:1c2:680:1319:692:26ff:feda:3a81]) by smtp.gmail.com with ESMTPSA id e186sm4222122pfh.60.2020.10.16.18.33.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2020 18:33:08 -0700 (PDT) From: John Stultz To: lkml Cc: John Stultz , Sumit Semwal , Liam Mark , Laura Abbott , Brian Starkey , Hridya Valsaraju , Suren Baghdasaryan , Sandeep Patil , Daniel Mentz , Chris Goldsworthy , =?utf-8?q?=C3=98rjan_Eide?= , Robin Murphy , Ezequiel Garcia , Simon Ser , James Jones , linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org Subject: [PATCH v4 4/7] dma-buf: heaps: Skip sync if not mapped Date: Sat, 17 Oct 2020 01:32:52 +0000 Message-Id: <20201017013255.43568-5-john.stultz@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201017013255.43568-1-john.stultz@linaro.org> References: <20201017013255.43568-1-john.stultz@linaro.org> MIME-Version: 1.0 This patch is basically a port of Ørjan Eide's similar patch for ION https://lore.kernel.org/lkml/20200414134629.54567-1-orjan.eide@arm.com/ Only sync the sg-list of dma-buf heap attachment when the attachment is actually mapped on the device. dma-bufs may be synced at any time. It can be reached from user space via DMA_BUF_IOCTL_SYNC, so there are no guarantees from callers on when syncs may be attempted, and dma_buf_end_cpu_access() and dma_buf_begin_cpu_access() may not be paired. Since the sg_list's dma_address isn't set up until the buffer is used on the device, and dma_map_sg() is called on it, the dma_address will be NULL if sync is attempted on the dma-buf before it's mapped on a device. Before v5.0 (commit 55897af63091 ("dma-direct: merge swiotlb_dma_ops into the dma_direct code")) this was a problem as the dma-api (at least the swiotlb_dma_ops on arm64) would use the potentially invalid dma_address. How that failed depended on how the device handled physical address 0. If 0 was a valid address to physical ram, that page would get flushed a lot, while the actual pages in the buffer would not get synced correctly. While if 0 is an invalid physical address it may cause a fault and trigger a crash. In v5.0 this was incidentally fixed by commit 55897af63091 ("dma-direct: merge swiotlb_dma_ops into the dma_direct code"), as this moved the dma-api to use the page pointer in the sg_list, and (for Ion buffers at least) this will always be valid if the sg_list exists at all. But, this issue is re-introduced in v5.3 with commit 449fa54d6815 ("dma-direct: correct the physical addr in dma_direct_sync_sg_for_cpu/device") moves the dma-api back to the old behaviour and picks the dma_address that may be invalid. dma-buf core doesn't ensure that the buffer is mapped on the device, and thus have a valid sg_list, before calling the exporter's begin_cpu_access. Logic and commit message originally by: Ørjan Eide 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 Reviewed-by: Brian Starkey Signed-off-by: John Stultz --- drivers/dma-buf/heaps/cma_heap.c | 10 ++++++++++ drivers/dma-buf/heaps/system_heap.c | 10 ++++++++++ 2 files changed, 20 insertions(+) -- 2.17.1 diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c index d6fab7cdeaf9..d7f5d3d7a0c0 100644 --- a/drivers/dma-buf/heaps/cma_heap.c +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -44,6 +44,7 @@ struct dma_heap_attachment { struct device *dev; struct sg_table table; struct list_head list; + bool mapped; }; static int cma_heap_attach(struct dma_buf *dmabuf, @@ -68,6 +69,7 @@ static int cma_heap_attach(struct dma_buf *dmabuf, a->dev = attachment->dev; INIT_LIST_HEAD(&a->list); + a->mapped = false; attachment->priv = a; @@ -102,6 +104,7 @@ static struct sg_table *cma_heap_map_dma_buf(struct dma_buf_attachment *attachme ret = dma_map_sgtable(attachment->dev, table, direction, 0); if (ret) return ERR_PTR(-ENOMEM); + a->mapped = true; return table; } @@ -109,6 +112,9 @@ static void cma_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, struct sg_table *table, enum dma_data_direction direction) { + struct dma_heap_attachment *a = attachment->priv; + + a->mapped = false; dma_unmap_sgtable(attachment->dev, table, direction, 0); } @@ -123,6 +129,8 @@ static int cma_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, 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); } mutex_unlock(&buffer->lock); @@ -141,6 +149,8 @@ static int cma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, 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); } mutex_unlock(&buffer->lock); diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index 5c44f9c06807..15b36bc862b1 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -37,6 +37,7 @@ struct dma_heap_attachment { struct device *dev; struct sg_table *table; struct list_head list; + bool mapped; }; static struct sg_table *dup_sg_table(struct sg_table *table) @@ -84,6 +85,7 @@ static int system_heap_attach(struct dma_buf *dmabuf, a->table = table; a->dev = attachment->dev; INIT_LIST_HEAD(&a->list); + a->mapped = false; attachment->priv = a; @@ -120,6 +122,7 @@ static struct sg_table *system_heap_map_dma_buf(struct dma_buf_attachment *attac if (ret) return ERR_PTR(ret); + a->mapped = true; return table; } @@ -127,6 +130,9 @@ static void system_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, struct sg_table *table, enum dma_data_direction direction) { + struct dma_heap_attachment *a = attachment->priv; + + a->mapped = false; dma_unmap_sgtable(attachment->dev, table, direction, 0); } @@ -142,6 +148,8 @@ static int system_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, 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); } mutex_unlock(&buffer->lock); @@ -161,6 +169,8 @@ static int system_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, 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); } mutex_unlock(&buffer->lock); From patchwork Sat Oct 17 01:32:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 317841 Delivered-To: patches@linaro.org Received: by 2002:a92:d603:0:0:0:0:0 with SMTP id w3csp1946939ilm; Fri, 16 Oct 2020 18:33:12 -0700 (PDT) X-Received: by 2002:a63:3d8:: with SMTP id 207mr5637753pgd.238.1602898391892; Fri, 16 Oct 2020 18:33:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1602898391; cv=none; d=google.com; s=arc-20160816; b=inYQ4GU+K/Wl+288zpvvBo+EPYBqHKoJU6mxZxWR3dqkma9tAQcvpkwXmtaOoADjfv 7xL8mvU0Ulq1buthcw3QLNKqumMTTr4rJuyd29MItqIWSPJq1VTjq8t+tv4DKq4vDqkH URHxumi+4gk/fPvqaGDShOw/ifXzyx4uNhimRQ7CoZ70gxAczLcCu9Z15+2EbsIVdYrd PJ93shYC0SqAkllVFLf5VMvxk1d0+c+pREaZtLhC77WvcpuX5elzdNHziAl/bipOS1gf jk0fW6UZOUhE8G36Yrrii9VDkoDJVUOV0PJP6annfFS1SwURCGAXRp2Ezoa6bzEhx3um z5gg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=rVjH5kAWpZ89/EmydrKRHj8zSjZ6vFxUYPy5820x7gY=; b=zf8qVFbBUBBLl71H+L0HMKBfEsFtqewNC/9N89/A8VYkBg+D2LVz0IJFb5gcQhneRn 764/ZMpLtaMbQGcbz6i/Y3GkIpWFLKVczEc8Cr54yobUuycwemTL+2wQZL+p07bjT9ZS CRFC9GjRHYNZ8unShdhugjSVjx3CVYK+llSqyA7SBweNg5Dl7f/S9ZYECJp+XLQycy0j QenOlB98Zb1PHr3lfGQodqu6X9wNiuq8kzJF8N7Yir9lxVuegIhu/c2oMIgfTuyR1avd jLoXKDD7/wL8mrO60lcZYlnP00jfT0KQz+P0KgGHGjPJ6Rgg6j1+RakuEMDICkOSt92g nzHQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="edXQs/lj"; spf=pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id br19sor1971868pjb.34.2020.10.16.18.33.11 for (Google Transport Security); Fri, 16 Oct 2020 18:33:11 -0700 (PDT) Received-SPF: pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="edXQs/lj"; spf=pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org 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=rVjH5kAWpZ89/EmydrKRHj8zSjZ6vFxUYPy5820x7gY=; b=edXQs/ljn6jSQStwnUbD4V+a+8zcDraCwpp4BTxpiIKMSZmEGxDmCiMkYqzDun9WOc Zqxzw00DhPfpezDGHHVd+Kl2K85ex0NOwlxWMVD/bHibltSvCeRM0Oe0AV4NbrBH0Qd1 4wRQaS39euUGKr3kMDFv3TlIhaG4nBM3gpfbp+qyuGHJabXmWHcokHFpGHO4owQuDOn1 SfJzcSj9PgzBalEhzDFNztta+t9lKcAiR1c55rnNb99lEqUfQtBuJ0ORRWyTHX8aNRuu VY94rsF5u0cKG3YLjh7pMtdxhoSbiuQmTn5sM/w+EJd1APnZoX/DOWPRF/MT5jhKrRUf pp8w== 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=rVjH5kAWpZ89/EmydrKRHj8zSjZ6vFxUYPy5820x7gY=; b=g/4lgGM9ih8oCBQcIgyYRiu6U87sNufHsT0/OmPdaj42DkIR2dd53mbVEZWEKK5QyJ aUagjhTCdSvEcfpxJBkfr0+uNEQaAfpdhPQMJ0QtVbiYcRjKByCtGBABRUInfuHDIssu 2Z9C5VXrT9n5tw+5G6ZE25Kc+VBmIVXBPBP+d6j0+1w4FKcfEFruOrjvQUfFyE4Cg25Z Lo38zfc+OFk10oQp0iXqnJ+mEJ7cLSsqxD0nGT7cA0FXCpkrTme9j/x08bXY53yL1wjA rvreJEnb2EdkjfpuqOvjXcusIysBaQYgaZSGLWjHBtlWO3ee+fVhtSHwURkaCi99XgII erXA== X-Gm-Message-State: AOAM531sKQpNZWUpxXMfQAMyjFqUixNvi+7jedM74+AqE0Gg0RVKSRrX ccV1Ts3dBvWSpOTdPbRJVYMrWMac X-Google-Smtp-Source: ABdhPJw86UGDLegHXXcXES9E+SyOsX3eXBD4zTF9CKEX4dxI4kY4dqabeTAnwwZQ9xlVM67RK1N6Sg== X-Received: by 2002:a17:90a:fe13:: with SMTP id ck19mr6803215pjb.207.1602898391559; Fri, 16 Oct 2020 18:33:11 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([2601:1c2:680:1319:692:26ff:feda:3a81]) by smtp.gmail.com with ESMTPSA id e186sm4222122pfh.60.2020.10.16.18.33.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2020 18:33:10 -0700 (PDT) From: John Stultz To: lkml Cc: John Stultz , Sumit Semwal , Liam Mark , Laura Abbott , Brian Starkey , Hridya Valsaraju , Suren Baghdasaryan , Sandeep Patil , Daniel Mentz , Chris Goldsworthy , =?utf-8?q?=C3=98rjan_Eide?= , Robin Murphy , Ezequiel Garcia , Simon Ser , James Jones , linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org Subject: [PATCH v4 5/7] dma-buf: system_heap: Allocate higher order pages if available Date: Sat, 17 Oct 2020 01:32:53 +0000 Message-Id: <20201017013255.43568-6-john.stultz@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201017013255.43568-1-john.stultz@linaro.org> References: <20201017013255.43568-1-john.stultz@linaro.org> MIME-Version: 1.0 While the system heap can return non-contiguous pages, try to allocate larger order pages if possible. This will allow slight performance gains and make implementing page pooling easier. 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 Reviewed-by: Brian Starkey Signed-off-by: John Stultz --- v3: * Use page_size() rather then opencoding it --- drivers/dma-buf/heaps/system_heap.c | 83 ++++++++++++++++++++++------- 1 file changed, 65 insertions(+), 18 deletions(-) -- 2.17.1 diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index 15b36bc862b1..ef4b2c1032df 100644 --- a/drivers/dma-buf/heaps/system_heap.c +++ b/drivers/dma-buf/heaps/system_heap.c @@ -40,6 +40,14 @@ struct dma_heap_attachment { bool mapped; }; +#define HIGH_ORDER_GFP (((GFP_HIGHUSER | __GFP_ZERO | __GFP_NOWARN \ + | __GFP_NORETRY) & ~__GFP_RECLAIM) \ + | __GFP_COMP) +#define LOW_ORDER_GFP (GFP_HIGHUSER | __GFP_ZERO | __GFP_COMP) +static gfp_t order_flags[] = {HIGH_ORDER_GFP, LOW_ORDER_GFP, LOW_ORDER_GFP}; +static const unsigned int orders[] = {8, 4, 0}; +#define NUM_ORDERS ARRAY_SIZE(orders) + static struct sg_table *dup_sg_table(struct sg_table *table) { struct sg_table *new_table; @@ -270,8 +278,11 @@ static void system_heap_dma_buf_release(struct dma_buf *dmabuf) int i; table = &buffer->sg_table; - for_each_sgtable_sg(table, sg, i) - __free_page(sg_page(sg)); + for_each_sg(table->sgl, sg, table->nents, i) { + struct page *page = sg_page(sg); + + __free_pages(page, compound_order(page)); + } sg_free_table(table); kfree(buffer); } @@ -289,6 +300,26 @@ static const struct dma_buf_ops system_heap_buf_ops = { .release = system_heap_dma_buf_release, }; +static struct page *alloc_largest_available(unsigned long size, + unsigned int max_order) +{ + struct page *page; + int i; + + for (i = 0; i < NUM_ORDERS; i++) { + if (size < (PAGE_SIZE << orders[i])) + continue; + if (max_order < orders[i]) + continue; + + page = alloc_pages(order_flags[i], orders[i]); + if (!page) + continue; + return page; + } + return NULL; +} + static int system_heap_allocate(struct dma_heap *heap, unsigned long len, unsigned long fd_flags, @@ -296,11 +327,13 @@ static int system_heap_allocate(struct dma_heap *heap, { struct system_heap_buffer *buffer; DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + unsigned long size_remaining = len; + unsigned int max_order = orders[0]; struct dma_buf *dmabuf; struct sg_table *table; struct scatterlist *sg; - pgoff_t pagecount; - pgoff_t pg; + struct list_head pages; + struct page *page, *tmp_page; int i, ret = -ENOMEM; buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); @@ -312,25 +345,35 @@ static int system_heap_allocate(struct dma_heap *heap, buffer->heap = heap; buffer->len = len; - table = &buffer->sg_table; - pagecount = len / PAGE_SIZE; - if (sg_alloc_table(table, pagecount, GFP_KERNEL)) - goto free_buffer; - - sg = table->sgl; - for (pg = 0; pg < pagecount; pg++) { - struct page *page; + INIT_LIST_HEAD(&pages); + i = 0; + while (size_remaining > 0) { /* * Avoid trying to allocate memory if the process * has been killed by SIGKILL */ if (fatal_signal_pending(current)) - goto free_pages; - page = alloc_page(GFP_KERNEL | __GFP_ZERO); + goto free_buffer; + + page = alloc_largest_available(size_remaining, max_order); if (!page) - goto free_pages; + goto free_buffer; + + list_add_tail(&page->lru, &pages); + size_remaining -= page_size(page); + max_order = compound_order(page); + i++; + } + + table = &buffer->sg_table; + if (sg_alloc_table(table, i, GFP_KERNEL)) + goto free_buffer; + + sg = table->sgl; + list_for_each_entry_safe(page, tmp_page, &pages, lru) { sg_set_page(sg, page, page_size(page), 0); sg = sg_next(sg); + list_del(&page->lru); } /* create the dmabuf */ @@ -350,14 +393,18 @@ static int system_heap_allocate(struct dma_heap *heap, /* just return, as put will call release and that will free */ return ret; } - return ret; free_pages: - for_each_sgtable_sg(table, sg, i) - __free_page(sg_page(sg)); + for_each_sgtable_sg(table, sg, i) { + struct page *p = sg_page(sg); + + __free_pages(p, compound_order(p)); + } sg_free_table(table); free_buffer: + list_for_each_entry_safe(page, tmp_page, &pages, lru) + __free_pages(page, compound_order(page)); kfree(buffer); return ret; From patchwork Sat Oct 17 01:32:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 317842 Delivered-To: patches@linaro.org Received: by 2002:a92:d603:0:0:0:0:0 with SMTP id w3csp1946971ilm; Fri, 16 Oct 2020 18:33:15 -0700 (PDT) X-Received: by 2002:a62:53c1:0:b029:156:438e:2d6c with SMTP id h184-20020a6253c10000b0290156438e2d6cmr6355719pfb.37.1602898394981; Fri, 16 Oct 2020 18:33:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1602898394; cv=none; d=google.com; s=arc-20160816; b=TUXbzEuuUjfsleqgqZTm60yU5ZYVwaUfqWSuLYi7wtitCo5GF64Cxy4am4+n9j8Uir puDWL1WR6CXWBLA+1NvA6R5rtOC8z3ts7wMq4t6esCHfbmZRtjs4akbx+nqamTYYQdNC MV6DkxYB3Hmb/MiNGOHAMQg59KLwK2i7xtlC/ctPnRxMyGbCyVFH4Koy8I1wb57kmOsr +giM8xzAz7e4BY+94CQkuCP8gX1SkPQmrEHHCbfdClfxmaebyN66EsEgWkG7CmMXo+2E bC4ZuhLM/S/++A+TKc3j/Zddexf9RbOEHZVhj+ZIHNDWxAGbFAha7ok1IFXc/uZrxcOq Rfhg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=P68wKVWfyCPNBm8l+XiI7Y585elPVzN5iuk0IO/H+/E=; b=xxTbjdTjqKQFU1rHsaISmolJsEGqTLvNZGNhC8vSzIekMMsRxlpD4IdFfGkQE+niDJ 5aMVZeFvOoRa3Ehp/AoIKoyE6v++Zs6fr7ih1FsNpXVXWYyxhFZboyIgEEIVN5qoUd1R nuwsFy8Dqcle/DPqhuIKjxRSo4ZFPLizAjpm8YxggP1IK1H1uHnKeLCjdhMj4vc7tQVd +FWKJ7MNn+59PYsIcFpBHxzw18MdMJxrcgF6/fyqnCx3+jlpb2HXbXXhl9NbVLUZqFkX ZYvlGa3UvIMJHz2/LAiPf/8A7DFnoMFdoLDDLSwaXUZPi68bHYLvSI75nLC7A6zxusGt yWSg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=bdWzJhf+; spf=pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id mq8sor2053233pjb.6.2020.10.16.18.33.14 for (Google Transport Security); Fri, 16 Oct 2020 18:33:14 -0700 (PDT) Received-SPF: pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=bdWzJhf+; spf=pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org 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=P68wKVWfyCPNBm8l+XiI7Y585elPVzN5iuk0IO/H+/E=; b=bdWzJhf+Kt74SwdjGClZiLTK6Liqdc61K8jTehvBvcFdqmcILzkkCu6ynV2hBRrVEu 1pRQZehRxNgqVrBa+pMecr5Dr5+lqyMsuF9ucnzNvuTHw6CYBI5fUrMj2ZPC1UISlEk3 vLSJokv2OQC/BD4QC9wF367LFkQRvq06c0vFklyVkA+BJQHi0RBeH04qnblM6/0wWzzG 6ZR1WV9D+zUofDWUzH14k1P3gCaQQA2uWDojbYTMR6x+otkXIYbKyvhQxxUm0gOS/xbS cRYRiVFLPRMQtjWVoUAm9wKpGrsUL/6T1fVEeBTIzDsoNW/by0HXALYNmTPMIN3ewHq/ Q38g== 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=P68wKVWfyCPNBm8l+XiI7Y585elPVzN5iuk0IO/H+/E=; b=JjJ42IkEGGG6ZTCBMYi/vd1qj0B+/qWWtgYxawaLoFkCWqSghwf7XA0ssaiP/rF/xx vWYO4YGqdNC6/kjoQy1YWJo63t58feWxo1bIAl5deyZUo4/7TogeOsL11S03SZwqXfO/ h2jIEcqANjLYT5fogNALPV7XgvTuYwFtVHWbN09iwF5g92aO8cqTrX+g11M3M6DwBhMG 1ACLA1ujeK6C3NHS5YloqbFI1W+MDNy/qIigzRBx2jkso8Dj1Dx73u19n1jh1omgliu1 1lGISLl4LxyZDCVMFL8DBzf6ME1v1SVlRiwNXsm9mmoVT8dTA99ZbzrdcZlkOUoqFGaJ TVUw== X-Gm-Message-State: AOAM530Ok1tZVUb/Bj0cgr9ZgVyUEEVZFPFHt2XekTug3fIqkP4/NEdL giW+GOsY9T5XLRmr6qIp5bnaruEz X-Google-Smtp-Source: ABdhPJxXdKj7nSAtkG+Eczc0+aZcCvZHERtkfZGx5ovLSOefr82WKn91iVR+sj6Dnq0bOj3NmoOHFw== X-Received: by 2002:a17:90a:8c87:: with SMTP id b7mr6918045pjo.66.1602898394682; Fri, 16 Oct 2020 18:33:14 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([2601:1c2:680:1319:692:26ff:feda:3a81]) by smtp.gmail.com with ESMTPSA id e186sm4222122pfh.60.2020.10.16.18.33.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2020 18:33:14 -0700 (PDT) From: John Stultz To: lkml Cc: John Stultz , Sumit Semwal , Liam Mark , Laura Abbott , Brian Starkey , Hridya Valsaraju , Suren Baghdasaryan , Sandeep Patil , Daniel Mentz , Chris Goldsworthy , =?utf-8?q?=C3=98rjan_Eide?= , Robin Murphy , Ezequiel Garcia , Simon Ser , James Jones , linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org Subject: [PATCH v4 6/7] dma-buf: dma-heap: Keep track of the heap device struct Date: Sat, 17 Oct 2020 01:32:54 +0000 Message-Id: <20201017013255.43568-7-john.stultz@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201017013255.43568-1-john.stultz@linaro.org> References: <20201017013255.43568-1-john.stultz@linaro.org> MIME-Version: 1.0 Keep track of the heap device struct. This will be useful for special DMA allocations and actions. 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: John Stultz --- drivers/dma-buf/dma-heap.c | 33 +++++++++++++++++++++++++-------- include/linux/dma-heap.h | 9 +++++++++ 2 files changed, 34 insertions(+), 8 deletions(-) -- 2.17.1 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 Sat Oct 17 01:32:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 317843 Delivered-To: patches@linaro.org Received: by 2002:a92:d603:0:0:0:0:0 with SMTP id w3csp1946993ilm; Fri, 16 Oct 2020 18:33:17 -0700 (PDT) X-Received: by 2002:a17:902:c086:b029:d3:deab:e812 with SMTP id j6-20020a170902c086b02900d3deabe812mr6509560pld.51.1602898397464; Fri, 16 Oct 2020 18:33:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1602898397; cv=none; d=google.com; s=arc-20160816; b=eHsF77yxmJTqB6IDVowqPbAQuvgJqD9WYgcXv+L8YmtbIy06EXfv9WSUh5qwXloSfE vDPQrVqs2gv3uZ0IP0IWD53KRwho0A6LT+1spk3+ZUq+6SKoXsUbn2kK/masMy9SFO6Y AnLCRpXCn8QoXUeva5nrTw6w5po9aT28DHGDMypWgWOcyS/zP8egLCUGEbo2jguPWtog 1JTSWvQ8GDNCIb/MHZWMOQ+hCYnIqreHE2SUnPbwN3QqTLwd58z7AeB7vB+5lc0YUA8W stB4bwPrCOQ+kiKFTPoog28Sgz/Fs7hC6JAN0AjmhH2YYpEs++mlKaKOIQCzqQ/ROhha Gdxg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=6oHXHsrLfgpTNXoI1E5O96yDTjCsZQKa/PUoP1mStQ0=; b=PIYVlU8xsw98lajhvoQqbQg484mhfb3kB+7FxWRrruwp/QgC6VwLD5jQwNkOPf+FRS KnEQxzOy+tPyBIywlTX3FNd7Y+JdiI6WKU+3S65mYcCEhjfMJWlA2EeKFl9E4s6ci/bz lrZ+49pNpFdXP6p7W/jqQjcqmlGzkA4WQqdNMxH0BNIeosfLph9DJzfJmuYa7fK/HuTw mrK5urS8fpszSReTnEcVlk763rnuE5aExC42Lt7LzgfiDn6HrDCaYIt58USSLpF2Yxg7 OM1f7GS7ZlDFV9LC2cbrj6TwJAjxxWbegTLJdzpa09V7pd7Jf1Fh61yp7SNxwtHzqj2M bdgw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=cUiPeL3F; spf=pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id kn18sor2048488pjb.41.2020.10.16.18.33.17 for (Google Transport Security); Fri, 16 Oct 2020 18:33:17 -0700 (PDT) Received-SPF: pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=cUiPeL3F; spf=pass (google.com: domain of john.stultz@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=john.stultz@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org 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=6oHXHsrLfgpTNXoI1E5O96yDTjCsZQKa/PUoP1mStQ0=; b=cUiPeL3FFnLfOGlkp+FRVgZGoW9QTOselzAKWpxe0hC2UMDNCugE7dcBYBPuq8r80A iXE2K4jr7y345HhFFjYSI5NVr8bW0iDtBqvVvsfwdWgwASNxNmxRXzMMHC5axuwAB9G9 FYsFWP02nI5ns8rTbxaurL7mCxgAlR6fEBzS69L7h3Kvm70d8MVxRLZaL8wophkH21A1 rUEbPBdOvilpjUCyxMXG4UbvMWmP1Z10tfq5yoOVngbdRnuPkuHJ0V0j2AeHHni7bvtb 9VBhpHQqZOJCeC6q+b1M1Njkr3Zf78Xf0Z5R9jQeqxNdfGc6JxK5X9YHi8TVoAnZSi4r BfaA== 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=6oHXHsrLfgpTNXoI1E5O96yDTjCsZQKa/PUoP1mStQ0=; b=Asv/Yx9gmOymCYKORX5WGgryzLPiON9KocjMUI1XywPF4ZuluLHvlE1GlLks2H8ooT wpcJE2Q68YrgdZiehjOLCbgZunRuVFaSZT0ON/O6VNQ/P2rOQImcX/I/42fM9nyOTc1H uYX/w1xQ3zYaK7lyiWBleIE0rKVi+qTMESz+iZzB142IJgKT6gOx5lPgyoVX722AS52V dv2TNNjRJIjKSqKSc56oIbVqL2F3mF90VdubSLSv66XSqyiWOTmB6Aon+YPzu5s+DwO5 AeHIVzE1pmgkk9HUL/jsP7dCj/gZs5kWAH6/D3sk5rP9sqrLuHjsV9pixa/cKOL8qsQ+ 3rnA== X-Gm-Message-State: AOAM533+S76FZ944HcpeamvWs7fTWWB2WKOjk5zbF9qz0kW/xcAHthI+ 0UWLZUD9uKngqS7wOOoMlr6CYblx X-Google-Smtp-Source: ABdhPJwXUMDQW5DbNK8+xbjk7S3Noz5N4La1PstaIPJE8mBaqUIjrh3Ki4Q90tk0FCMQx44QPDa2QA== X-Received: by 2002:a17:90a:d3d5:: with SMTP id d21mr6636885pjw.168.1602898397098; Fri, 16 Oct 2020 18:33:17 -0700 (PDT) Return-Path: Received: from localhost.localdomain ([2601:1c2:680:1319:692:26ff:feda:3a81]) by smtp.gmail.com with ESMTPSA id e186sm4222122pfh.60.2020.10.16.18.33.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 16 Oct 2020 18:33:16 -0700 (PDT) From: John Stultz To: lkml Cc: John Stultz , Sumit Semwal , Liam Mark , Laura Abbott , Brian Starkey , Hridya Valsaraju , Suren Baghdasaryan , Sandeep Patil , Daniel Mentz , Chris Goldsworthy , =?utf-8?q?=C3=98rjan_Eide?= , Robin Murphy , Ezequiel Garcia , Simon Ser , James Jones , linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org Subject: [PATCH v4 7/7] dma-buf: system_heap: Add a system-uncached heap re-using the system heap Date: Sat, 17 Oct 2020 01:32:55 +0000 Message-Id: <20201017013255.43568-8-john.stultz@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20201017013255.43568-1-john.stultz@linaro.org> References: <20201017013255.43568-1-john.stultz@linaro.org> MIME-Version: 1.0 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 (possibly, needs more review): - https://android-review.googlesource.com/c/platform/frameworks/av/+/1360640/17/media/codec2/vndk/C2DmaBufAllocator.cpp#325 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: 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(-) -- 2.17.1 diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c index ef4b2c1032df..a328c76249d2 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 \ @@ -94,7 +99,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); @@ -124,9 +129,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); @@ -139,9 +148,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, @@ -155,10 +167,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); @@ -176,10 +190,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); @@ -194,6 +210,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); @@ -215,17 +234,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) @@ -320,10 +343,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); @@ -344,6 +368,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; @@ -393,6 +418,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: @@ -410,10 +447,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; @@ -426,6 +493,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);