From 955fec6d52229bfd78514739300b6f754dcc40a3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 22 Jun 2013 22:52:16 +0100 Subject: Use free-by-physical address kernel API Use the new free-by-physical address kernel API. This allows us to free bmm buffers which have not been mapped into user memory. This also allows us to free a bmm buffer which failed to mmap(). --- bmm_lib.c | 33 ++++++++++++++++++++++++--------- bmm_lib_priv.h | 1 + 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/bmm_lib.c b/bmm_lib.c index 3e4ebd2..64a11e7 100644 --- a/bmm_lib.c +++ b/bmm_lib.c @@ -35,10 +35,11 @@ #endif #define API_FEAT_MIN 0x0000 -#define API_COMP_MAX 0x0000 +#define API_COMP_MAX 0x0001 #define API_FEAT(x) ((x) >> 16) #define API_COMP(x) ((x) & 0xffff) #define API_FEAT_GET_DMABUF_FD 0x0001 +#define API_FEAT_FREE_PHYS 0x0002 static unsigned bmm_api; static int bmm_fd = -1; @@ -249,10 +250,8 @@ void *bmm_malloc_aligned(unsigned long size, int attr, unsigned align) pr_debug("bmm_malloc return paddr = 0x%08lx\n", io.output); vaddr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, bmm_fd, io.output); - if ((int)vaddr == -1) { - /* FIXME: we can't free the bmm buffer without a vaddr! */ - goto err_free_buf; - } + if ((int)vaddr == -1) + goto err_free_bmm; buf->vaddr = vaddr; buf->paddr = io.output; @@ -265,6 +264,15 @@ void *bmm_malloc_aligned(unsigned long size, int attr, unsigned align) return vaddr; + err_free_bmm: + if (API_FEAT(bmm_api) >= API_FEAT_FREE_PHYS) { + /* Modern APIs allow us to free this failed allocation */ + io.input = io.output; + io.output = 0; + io.arg = 0; + ioctl(bmm_fd, BMM_FREE_PHYS, &io); + } + err_free_buf: free(buf); return NULL; @@ -293,10 +301,17 @@ void bmm_free(void *vaddr) munmap(buf->vaddr, buf->size); - io.input = (unsigned long)buf->vaddr; - io.output = 0; - io.arg = 0; - ioctl(bmm_fd, BMM_FREE, &io); + if (API_FEAT(bmm_api) >= API_FEAT_FREE_PHYS) { + io.input = buf->paddr; + io.output = 0; + io.arg = 0; + ioctl(bmm_fd, BMM_FREE_PHYS, &io); + } else { + io.input = (unsigned long)buf->vaddr; + io.output = 0; + io.arg = 0; + ioctl(bmm_fd, BMM_FREE, &io); + } free(buf); } diff --git a/bmm_lib_priv.h b/bmm_lib_priv.h index a93db78..f10a77b 100644 --- a/bmm_lib_priv.h +++ b/bmm_lib_priv.h @@ -43,6 +43,7 @@ typedef struct { #define BMM_MALLOC_ALIGNED _IOWR(BMEM_IOCTL_MAGIC, 17, ioctl_arg_t) #define BMM_API_VERSION _IOWR(BMEM_IOCTL_MAGIC, 18, ioctl_arg_t) #define BMM_GET_DMABUF_FD _IOWR(BMEM_IOCTL_MAGIC, 19, ioctl_arg_t) +#define BMM_FREE_PHYS _IOWR(BMEM_IOCTL_MAGIC, 20, ioctl_arg_t) #define BMM_DEVICE_FILE "/dev/bmm" -- cgit