summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk@arm.linux.org.uk>2013-06-22 22:52:16 +0100
committerRussell King <rmk@arm.linux.org.uk>2013-06-23 12:01:51 +0100
commit955fec6d52229bfd78514739300b6f754dcc40a3 (patch)
tree5923b54cff405d98f2902f609573e65764bb2bcb
parent77278b1df19e482dc26c2a9636fbf97dd882a70d (diff)
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().
-rw-r--r--bmm_lib.c33
-rw-r--r--bmm_lib_priv.h1
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"