From 4af242aad17cf5b7b119fc5d17184711a7addccd Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Fri, 3 Jul 2015 05:47:56 +0000 Subject: [PATCH] Implement busdma_md_unload() and busdma_sync(). While here: 1. have the Python bindings contain constants for the space identifiers and the sync operation. 2. change the segment iterators to return None when done, not ENXIO. --- tools/bus_space/C/lang.c | 14 +++++++ tools/bus_space/C/libbus.h | 8 ++++ tools/bus_space/Python/lang.c | 68 ++++++++++++++++++++++++++----- tools/bus_space/busdma.c | 77 ++++++++++++++++++++++++++++------- tools/bus_space/busdma.h | 3 ++ 5 files changed, 146 insertions(+), 24 deletions(-) diff --git a/tools/bus_space/C/lang.c b/tools/bus_space/C/lang.c index ab7d36fee538..d9c3f52cde18 100644 --- a/tools/bus_space/C/lang.c +++ b/tools/bus_space/C/lang.c @@ -182,6 +182,13 @@ busdma_md_load(busdma_md_t md, void *buf, size_t len, u_int flags) return (bd_md_load(md, buf, len, flags)); } +int +busdma_md_unload(busdma_md_t md) +{ + + return (bd_md_unload(md)); +} + busdma_seg_t busdma_md_first_seg(busdma_md_t md, int space) { @@ -218,3 +225,10 @@ busdma_seg_get_size(busdma_seg_t seg) error = bd_seg_get_size(seg, &size); return ((error) ? ~0UL : size); } + +int +busdma_sync(busdma_md_t md, int op, bus_addr_t base, bus_size_t size) +{ + + return (bd_sync(md, op, base, size)); +} diff --git a/tools/bus_space/C/libbus.h b/tools/bus_space/C/libbus.h index 16cdadea4fa1..50efd3808cc8 100644 --- a/tools/bus_space/C/libbus.h +++ b/tools/bus_space/C/libbus.h @@ -61,6 +61,7 @@ int busdma_mem_free(busdma_md_t md); int busdma_md_create(busdma_tag_t tag, u_int flags, busdma_md_t *out_p); int busdma_md_destroy(busdma_md_t md); int busdma_md_load(busdma_md_t md, void *buf, size_t len, u_int flags); +int busdma_md_unload(busdma_md_t md); #define BUSDMA_MD_BUS_SPACE 0 #define BUSDMA_MD_PHYS_SPACE 1 @@ -72,4 +73,11 @@ int busdma_md_next_seg(busdma_md_t, busdma_seg_t seg); bus_addr_t busdma_seg_get_addr(busdma_seg_t seg); bus_size_t busdma_seg_get_size(busdma_seg_t seg); +#define BUSDMA_SYNC_PREREAD 1 +#define BUSDMA_SYNC_POSTREAD 2 +#define BUSDMA_SYNC_PREWRITE 4 +#define BUSDMA_SYNC_POSTWRITE 8 + +int busdma_sync(busdma_md_t md, int op, bus_addr_t, bus_size_t); + #endif /* _LIBBUS_SPACE_H_ */ diff --git a/tools/bus_space/Python/lang.c b/tools/bus_space/Python/lang.c index a90e0bd89565..0b96db3fcfd5 100644 --- a/tools/bus_space/Python/lang.c +++ b/tools/bus_space/Python/lang.c @@ -277,6 +277,21 @@ busdma_md_load(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject * +busdma_md_unload(PyObject *self, PyObject *args) +{ + int error, mdid; + + if (!PyArg_ParseTuple(args, "i", &mdid)) + return (NULL); + error = bd_md_unload(mdid); + if (error) { + PyErr_SetString(PyExc_IOError, strerror(error)); + return (NULL); + } + Py_RETURN_NONE; +} + static PyObject * busdma_mem_alloc(PyObject *self, PyObject *args) { @@ -316,10 +331,8 @@ busdma_md_first_seg(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "ii", &mdid, &what)) return (NULL); sid = bd_md_first_seg(mdid, what); - if (sid == -1) { - PyErr_SetString(PyExc_IOError, strerror(errno)); - return (NULL); - } + if (sid == -1) + Py_RETURN_NONE; return (Py_BuildValue("i", sid)); } @@ -331,10 +344,8 @@ busdma_md_next_seg(PyObject *self, PyObject *args) if (!PyArg_ParseTuple(args, "ii", &mdid, &sid)) return (NULL); sid = bd_md_next_seg(mdid, sid); - if (sid == -1) { - PyErr_SetString(PyExc_IOError, strerror(errno)); - return (NULL); - } + if (sid == -1) + Py_RETURN_NONE; return (Py_BuildValue("i", sid)); } @@ -370,6 +381,22 @@ busdma_seg_get_size(PyObject *self, PyObject *args) return (Py_BuildValue("k", size)); } +static PyObject * +busdma_sync(PyObject *self, PyObject *args) +{ + u_long base, size; + int error, mdid, op; + + if (!PyArg_ParseTuple(args, "iikk", &mdid, &op, &base, &size)) + return (NULL); + error = bd_sync(mdid, op, base, size); + if (error) { + PyErr_SetString(PyExc_IOError, strerror(error)); + return (NULL); + } + Py_RETURN_NONE; +} + static PyMethodDef bus_methods[] = { { "read_1", bus_read_1, METH_VARARGS, "Read a 1-byte data item." }, { "read_2", bus_read_2, METH_VARARGS, "Read a 2-byte data item." }, @@ -403,6 +430,8 @@ static PyMethodDef busdma_methods[] = { "Destroy a previously created memory descriptor." }, { "md_load", busdma_md_load, METH_VARARGS, "Load a buffer into a memory descriptor." }, + { "md_unload", busdma_md_unload, METH_VARARGS, + "Unload a memory descriptor." }, { "mem_alloc", busdma_mem_alloc, METH_VARARGS, "Allocate memory according to the DMA constraints." }, @@ -417,13 +446,32 @@ static PyMethodDef busdma_methods[] = { "Return the address of the segment." }, { "seg_get_size", busdma_seg_get_size, METH_VARARGS, "Return the size of the segment." }, + + { "sync", busdma_sync, METH_VARARGS, + "Keep memory/caches coherent WRT to DMA." }, + { NULL, NULL, 0, NULL } }; PyMODINIT_FUNC initbus(void) { + PyObject *bus, *busdma; - Py_InitModule("bus", bus_methods); - Py_InitModule("busdma", busdma_methods); + bus = Py_InitModule("bus", bus_methods); + if (bus == NULL) + return; + busdma = Py_InitModule("busdma", busdma_methods); + if (busdma == NULL) + return; + PyModule_AddObject(bus, "dma", busdma); + + PyModule_AddObject(busdma, "MD_BUS_SPACE", Py_BuildValue("i", 0)); + PyModule_AddObject(busdma, "MD_PHYS_SPACE", Py_BuildValue("i", 1)); + PyModule_AddObject(busdma, "MD_VIRT_SPACE", Py_BuildValue("i", 2)); + + PyModule_AddObject(busdma, "SYNC_PREREAD", Py_BuildValue("i", 1)); + PyModule_AddObject(busdma, "SYNC_POSTREAD", Py_BuildValue("i", 2)); + PyModule_AddObject(busdma, "SYNC_PREWRITE", Py_BuildValue("i", 4)); + PyModule_AddObject(busdma, "SYNC_POSTWRITE", Py_BuildValue("i", 8)); } diff --git a/tools/bus_space/busdma.c b/tools/bus_space/busdma.c index 5ec124f918d7..44c7b68ca5b7 100644 --- a/tools/bus_space/busdma.c +++ b/tools/bus_space/busdma.c @@ -262,6 +262,20 @@ bd_md_add_seg(struct obj *md, int type, u_long addr, u_long size) return (0); } +static int +bd_md_del_segs(struct obj *md, int type, int unmap) +{ + struct obj *seg, *seg0; + + for (seg = md->u.md.seg[type]; seg != NULL; seg = seg0) { + if (unmap) + munmap((void *)seg->u.seg.address, seg->u.seg.size); + seg0 = seg->u.seg.next; + obj_free(seg); + } + return (0); +} + int bd_md_create(int tid, u_int flags) { @@ -344,6 +358,29 @@ bd_md_load(int mdid, void *buf, u_long len, u_int flags) return (error); } +int +bd_md_unload(int mdid) +{ + struct proto_ioc_busdma ioc; + struct obj *md; + int error; + + md = obj_lookup(mdid, OBJ_TYPE_MD); + if (md == NULL) + return (errno); + + memset(&ioc, 0, sizeof(ioc)); + ioc.request = PROTO_IOC_BUSDMA_MD_UNLOAD; + ioc.key = md->key; + if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1) + return (errno); + + bd_md_del_segs(md, BUSDMA_MD_VIRT, 0); + bd_md_del_segs(md, BUSDMA_MD_PHYS, 0); + bd_md_del_segs(md, BUSDMA_MD_BUS, 0); + return (0); +} + int bd_mem_alloc(int tid, u_int flags) { @@ -409,31 +446,21 @@ int bd_mem_free(int mdid) { struct proto_ioc_busdma ioc; - struct obj *md, *seg, *seg0; + struct obj *md; md = obj_lookup(mdid, OBJ_TYPE_MD); if (md == NULL) return (errno); - for (seg = md->u.md.seg[BUSDMA_MD_VIRT]; seg != NULL; seg = seg0) { - munmap((void *)seg->u.seg.address, seg->u.seg.size); - seg0 = seg->u.seg.next; - obj_free(seg); - } - for (seg = md->u.md.seg[BUSDMA_MD_PHYS]; seg != NULL; seg = seg0) { - seg0 = seg->u.seg.next; - obj_free(seg); - } - for (seg = md->u.md.seg[BUSDMA_MD_BUS]; seg != NULL; seg = seg0) { - seg0 = seg->u.seg.next; - obj_free(seg); - } memset(&ioc, 0, sizeof(ioc)); ioc.request = PROTO_IOC_BUSDMA_MEM_FREE; ioc.key = md->key; if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1) return (errno); + bd_md_del_segs(md, BUSDMA_MD_VIRT, 1); + bd_md_del_segs(md, BUSDMA_MD_PHYS, 0); + bd_md_del_segs(md, BUSDMA_MD_BUS, 0); md->parent->refcnt--; obj_free(md); return (0); @@ -509,3 +536,25 @@ bd_seg_get_size(int sid, u_long *size_p) *size_p = seg->u.seg.size; return (0); } + +int +bd_sync(int mdid, u_int op, u_long base, u_long size) +{ + struct proto_ioc_busdma ioc; + struct obj *md; + + md = obj_lookup(mdid, OBJ_TYPE_MD); + if (md == NULL) + return (errno); + + memset(&ioc, 0, sizeof(ioc)); + ioc.request = PROTO_IOC_BUSDMA_SYNC; + ioc.key = md->key; + ioc.u.sync.op = op; + ioc.u.sync.base = base; + ioc.u.sync.size = size; + if (ioctl(md->fd, PROTO_IOC_BUSDMA, &ioc) == -1) + return (errno); + + return (0); +} diff --git a/tools/bus_space/busdma.h b/tools/bus_space/busdma.h index 23a9250b42d1..cf9d4f27542f 100644 --- a/tools/bus_space/busdma.h +++ b/tools/bus_space/busdma.h @@ -40,6 +40,7 @@ int bd_tag_destroy(int tid); int bd_md_create(int tid, u_int flags); int bd_md_destroy(int mdid); int bd_md_load(int mdid, void *buf, u_long len, u_int flags); +int bd_md_unload(int mdid); int bd_mem_alloc(int tid, u_int flags); int bd_mem_free(int mdid); @@ -50,4 +51,6 @@ int bd_md_next_seg(int mdid, int sid); int bd_seg_get_addr(int sid, u_long *); int bd_seg_get_size(int sid, u_long *); +int bd_sync(int mdid, u_int op, u_long base, u_long size); + #endif /* _TOOLS_BUS_DMA_H_ */