Hello!
This quick update on the patchset which replaces custom consistent dma
regions usage in dma-mapping framework in favour of generic vmalloc
areas created on demand for each allocation. The main purpose for this
patchset is to remove 2MiB limit of dma coherent/writecombine
allocations.
In this version arch-independent VM_DMA flag has been replaced with
ARM-specific VM_ARM_DMA_CONSISTENT flag.
This patch is based on vanilla v3.5-rc4 release.
Best regards
Marek Szyprowski
Samsung Poland R&D Center
Changelog:
v4:
- replaced arch-independent VM_DMA flag with ARM-specific
VM_ARM_DMA_CONSISTENT flag
v3: http://thread.gmane.org/gmane.linux.kernel.mm/80028/
- rebased onto v3.4-rc2: added support for IOMMU-aware implementation
of dma-mapping calls, unified with CMA coherent dma pool
- implemented changes requested by Minchan Kim: added more checks for
vmarea->flags & VM_DMA, renamed some variables, removed obsole locks,
squashed find_vm_area() exporting patch into the main redesign patch
v2: http://thread.gmane.org/gmane.linux.kernel.mm/78563
- added support for atomic allocations (served from preallocated pool)
- minor cleanup here and there
- rebased onto v3.4-rc7
v1: http://thread.gmane.org/gmane.linux.kernel.mm/76703
- initial version
Patch summary:
Marek Szyprowski (2):
mm: vmalloc: use const void * for caller argument
ARM: dma-mapping: remove custom consistent dma region
Documentation/kernel-parameters.txt | 2 +-
arch/arm/include/asm/dma-mapping.h | 2 +-
arch/arm/mm/dma-mapping.c | 505 +++++++++++++----------------------
arch/arm/mm/mm.h | 3 +
include/linux/vmalloc.h | 9 +-
mm/vmalloc.c | 28 ++-
6 files changed, 207 insertions(+), 342 deletions(-)
--
1.7.1.569.g6f426
From: Subash Patel <subash.rp(a)samsung.com>
This patch series is split and re-send of my original patch, after request
from Inki Dae.
Below two patches add the required error checks in drm dmabuf when the
system fails to allocate pages for the scatter-gather. This is very rare
situation, and occurs when the system is under memory pressure.
Scatter-gather asks for memory using sg_kmalloc() and this can return no
memory. Without below return value checks, the code will crash the system
due to invalid pointer access.
Subash Patel (2):
DRM: Exynos: return NULL if exynos_pages_to_sg fails
DRM: Exynos: check for null in return value of
dma_buf_map_attachment()
drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--
1.7.9.5
Hey,
Due to inertia, I thought I would take a shot at implicit synchronization as well.
I have just barely enough to make it work for nouveau to synchronize with itself
now using the cpu. Hopefully the general idea is correct but I feel the
implementation wrong.
There are 2 ways to get deadlocks if no proper care is taken to avoid it,
the first being 2 tasks taking each device's lock in a different order,
the second 2 devices waiting on completion of each other before starting
own work. The easiest way to avoid this is to introduce a global
dma_buf_submit_mutex so in cases where synchronization is needed.
This way only 1 submission involving dma-buffer synchronisation can be made
simultaneously. This will make it impossible to deadlock because even if you
take dma mutex->dev a mutex->dev b mutex, and swap a and b, the dmabuf mutex
would prevent this from being done at the same time.
That leaves the real problem of the synchronization itself. I felt that because
the code involved was already sharing dma-buf's, the easiest way to implement it
would be.. another dma-buf. Some hardware might have specific requirements on them,
so I haven't pinned down the exact details yet.
It's a bit of intermingling between drm and dma-buf namespace since it is an early
wip, any comments are welcome though.
This is what I used so far:
#define DRM_PRIME_FENCE_MAX 2
struct drm_prime_fence {
struct dma_buf *sync_buf;
uint64_t offset;
uint32_t value;
enum {
/* Nop is to allow preparations in case dma_buf
* is different for release, so the call will
* never fail at that point.
*/
DRM_PRIME_FENCE_NOP = 0,
DRM_PRIME_FENCE_WAIT_EQ,
// DRM_PRIME_FENCE_WAIT_GE, /* block while ((int)(cur - expected) < 0); */
DRM_PRIME_FENCE_SET
} op;
};
and added to struct dma_buf_ops:
/* drm_prime_fence_ is written by function to indicate what is needed
* to acquire this buffer, up to DRM_PRIME_FENCE_MAX buffers are allowed
* sync_acquire returns a negative value on error, otherwise
* amounts of fence ops that need to be executed.
*
* Release is not allowed to fail and merely returns number of
* fence ops that needs to be executed after command stream is done.
* Abort occurs when there's a failure between acquire and release,
* for example because dma-buf's from multiple devices are involved
* and the other one failed to acquire.
*/
int (*sync_acquire)(struct dma_buf *, struct drm_prime_fence fence[2],
unsigned long align, unsigned long release_write);
int (*sync_release)(struct dma_buf * struct drm_prime_fence fence[2]);
void (*sync_abort)(struct dma_buf *);
I'm not completely sure about this part yet, align can be seen as minimum
alignment requirement, ideally I would negotiate those earlier but I haven't
found the correct place yet, maybe on attach?
nouveau writes a 16 byte stamp as part of it's semaphore ops
(4 bytes programmable, 4 bytes pad, 8 bytes timestamp) which is why I need
to communicate those requirements somehow. Not all nouveau cards wold support
DRM_PRIME_FENCE_WAIT_GE either.
I think there is a great power in making the sync object itself just another
dma-buf that can be written to and/or read. Especially since all graphics
card have some way to write an arbitrary 4-byte value to an arbitrary location
(even the oldest intel cards have a blitter! :D). I'm hoping for more input
into making the api better for other users too, which is why I'm posting
this as early as I had something working (for some definition of working).
Thoughts?
~Maarten
The goal of those patches is to allow ION clients (drivers or userland applications)
to use Contiguous Memory Allocator (CMA).
To get more info about CMA:
http://lists.linaro.org/pipermail/linaro-mm-sig/2012-February/001328.html
patches version 6:
- add private field in ion_platform_heap to pass the device
linked with CMA.
- rework CMA heap to use private field.
- prepare CMA heap for incoming dma_common_get_sgtable function
http://lists.linaro.org/pipermail/linaro-mm-sig/2012-June/002109.html
- simplify ion-ux500 driver.
patches version 5:
- port patches on android kernel 3.4 where ION use dmabuf
- add ion_cma_heap_map_dma and ion_cma_heap_unmap_dma functions
patches version 4:
- add ION_HEAP_TYPE_DMA heap type in ion_heap_type enum.
- CMA heap is now a "native" ION heap.
- add ion_heap_create_full function to keep backward compatibilty.
- clean up included files in CMA heap
- ux500-ion is using ion_heap_create_full instead of ion_heap_create
patches version 3:
- add a private field in ion_heap structure instead of expose ion_device
structure to all heaps
- ion_cma_heap is no more a platform driver
- ion_cma_heap use ion_heap private field to store the device pointer and
make the link with reserved CMA regions
- provide ux500-ion driver and configuration file for snowball board to give
an example of how use CMA heaps
patches version 2:
- fix comments done by Andy Green
Benjamin Gaignard (4):
fix ion_platform_data definition
add private field in ion_heap and ion_platform_heap structure
add CMA heap
add test/example driver for ux500 platform
arch/arm/mach-ux500/board-mop500.c | 64 +++++++++++++
drivers/gpu/ion/Kconfig | 5 +
drivers/gpu/ion/Makefile | 5 +-
drivers/gpu/ion/ion_cma_heap.c | 179 ++++++++++++++++++++++++++++++++++++
drivers/gpu/ion/ion_heap.c | 11 +++
drivers/gpu/ion/ion_priv.h | 8 ++
drivers/gpu/ion/ux500/Makefile | 1 +
drivers/gpu/ion/ux500/ux500_ion.c | 134 +++++++++++++++++++++++++++
include/linux/ion.h | 7 +-
9 files changed, 412 insertions(+), 2 deletions(-)
create mode 100644 drivers/gpu/ion/ion_cma_heap.c
create mode 100644 drivers/gpu/ion/ux500/Makefile
create mode 100644 drivers/gpu/ion/ux500/ux500_ion.c
--
1.7.10
From: Subash Patel <subash.rp(a)samsung.com>
exynos_pages_to_sg() internally calls sg_kmalloc() which can return
no pages when the system is under high memory crunch. One such instance
is chromeos-install in the chromeos. This patch adds check for the return
value of the function in subject to return NULL on failure.
Change-Id: I541ed30491a926ebe72738225041c9f2d88007bc
Signed-off-by: Subash Patel <subash.ramaswamy(a)linaro.org>
CC: dri-devel(a)lists.freedesktop.org
CC: linux-samsung-soc(a)vger.kernel.org
CC: linaro-mm-sig(a)lists.linaro.org
CC: inki.dae(a)samsung.com
CC: airlied(a)redhat.com
CC: olofj(a)chromium.org
---
drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
index 97325c1..52cf761 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
@@ -87,6 +87,10 @@ static struct sg_table *
npages = buf->size / buf->page_size;
sgt = exynos_pages_to_sg(buf->pages, npages, buf->page_size);
+ if (!sgt) {
+ DRM_DEBUG_PRIME("exynos_pages_to_sg returned NULL!\n");
+ goto err_unlock;
+ }
nents = dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir);
DRM_DEBUG_PRIME("npages = %d buffer size = 0x%lx page_size = 0x%lx\n",
--
1.7.9.5
Hi Linus,
I would like to ask for pulling another minor fixup for ARM dma-mapping
redesign and extensions merged in v3.5-rc1.
The following changes since commit 6b16351acbd415e66ba16bf7d473ece1574cf0bc:
Linux 3.5-rc4 (2012-06-24 12:53:04 -0700)
with the top-most commit 593f47355467b9ef44293698817e2bdb347e2d11
ARM: dma-mapping: fix buffer chunk allocation order
are available in the git repository at:
git://git.linaro.org/people/mszyprowski/linux-dma-mapping.git fixes-for-linus
Marek Szyprowski (1):
ARM: dma-mapping: fix buffer chunk allocation order
arch/arm/mm/dma-mapping.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
Thanks!
Best regards
Marek Szyprowski
Samsung Poland R&D Center
From: Subash Patel <subash.rp(a)samsung.com>
exynos_pages_to_sg() internally calls sg_kmalloc() which can return
no pages when the system is under high memory crunch. One such instance
is chromeos-install in the chromeos. This patch adds check for the return
value of the function in subject to return NULL on failure.
BUG=chrome-os-partner:9481
TEST=built, ran on snow and tried chromeos-install without a crash
Change-Id: I0abda74beaedae002a17de9962d7a462a2a7c2fb
Signed-off-by: Subash Patel <subash.rp(a)samsung.com>
---
drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
index 97325c1..c908a29 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
@@ -87,6 +87,10 @@ static struct sg_table *
npages = buf->size / buf->page_size;
sgt = exynos_pages_to_sg(buf->pages, npages, buf->page_size);
+ if (!sgt) {
+ DRM_DEBUG_PRIME("exynos_pages_to_sg returned NULL!\n");
+ goto err_unlock;
+ }
nents = dma_map_sg(attach->dev, sgt->sgl, sgt->nents, dir);
DRM_DEBUG_PRIME("npages = %d buffer size = 0x%lx page_size = 0x%lx\n",
@@ -241,7 +245,7 @@ struct drm_gem_object *exynos_dmabuf_prime_import(struct drm_device *drm_dev,
sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
- if (IS_ERR(sgt)) {
+ if (IS_ERR_OR_NULL(sgt)) {
ret = PTR_ERR(sgt);
goto err_buf_detach;
}
--
1.7.9.5