Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Aug 2010 23:24:38 GMT
From:      Jakub Wojciech Klama <jceel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 182338 for review
Message-ID:  <201008122324.o7CNOcXI056652@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@182338?ac=10

Change 182338 by jceel@jceel on 2010/08/12 23:24:18

	Add channel allocation mechanism.

Affected files ...

.. //depot/projects/soc2010/jceel_dma/sys/arm/davinci/davinci_devices.c#4 edit
.. //depot/projects/soc2010/jceel_dma/sys/dev/gpdma/gpdma.c#3 edit
.. //depot/projects/soc2010/jceel_dma/sys/dev/gpdma/gpdma.h#3 edit

Differences ...

==== //depot/projects/soc2010/jceel_dma/sys/arm/davinci/davinci_devices.c#4 (text+ko) ====

@@ -30,9 +30,24 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 
+#include <dev/gpdma/gpdma.h>
+#include <dev/gpdma/gpdma_cdev.h>
+
 #include <arm/davinci/davincivar.h>
 #include <arm/davinci/davincireg.h>
 
+struct gpdma_allocation davinci_edma_allocations[] = {
+	{ "edma0", 12, 12, gpdma_memutils_init, NULL },
+	{ "edma0", 13, 15, gpdma_cdev_init, NULL },
+	{ "edma0", 24, 25, gpdma_cdev_init, NULL },
+	{ "edma0", 30, 31, gpdma_cdev_init, NULL },
+	{ "edma0", 45, 47, gpdma_cdev_init, NULL },
+	{ "edma0", 55, 63, gpdma_cdev_init, NULL },
+	{ NULL },
+};
+
+struct gpdma_allocation *gpdma_allocations = davinci_edma_allocations;
+
 struct obio_device davinci_devices[] = {
 	{ "aintc", DAVINCI_AINTC_BASE, DAVINCI_AINTC_SIZE,
 	    { -1 },

==== //depot/projects/soc2010/jceel_dma/sys/dev/gpdma/gpdma.c#3 (text+ko) ====

@@ -45,8 +45,8 @@
 #include <dev/gpdma/gpdma_cdev.h>
 #include "gpdma_if.h"
 
+#undef	DEBUG
 #define	DEBUG
-//#undef	DEBUG
 #ifdef	DEBUG
 #define	debugf(fmt, args...) do { \
 	    printf("gpdma: " fmt "\n", ##args); } while (0)
@@ -58,47 +58,54 @@
 
 LIST_HEAD(, gpdma_engine) gpdma_engines;
 struct mtx gpdma_engines_mtx;
+extern struct gpdma_allocation *gpdma_allocations __attribute__ ((weak));
 
 static struct gpdma_engine *gpdma_engine_by_name(const char *);
 static struct gpdma_engine *gpdma_engine_by_res(struct resource *);
-static void gpdma_dmamap_load_cb(void *, bus_dma_segment_t *, int, int);
-static void gpdma_dmamap_load_cb2(void *, bus_dma_segment_t *, int, bus_size_t, int);
+void gpdma_dmamap_load_cb(void *, bus_dma_segment_t *, int, int);
+void gpdma_dmamap_load_cb2(void *, bus_dma_segment_t *, int,
+    bus_size_t, int);
 void gpdma_init(void *);
+static void gpdma_initialize_channels(struct gpdma_engine *,
+    struct gpdma_allocation *);
 static int gpdma_check_transfer(struct gpdma_transfer *);
 
-static void
+struct gpdma_mapping
+{
+	int		gm_error;
+	bus_addr_t 	gm_addr;
+	bus_size_t	gm_len;
+};
+
+void
 gpdma_dmamap_load_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
 {
-	bus_dma_segment_t *seg = (bus_dma_segment_t *)arg;
+	struct gpdma_mapping *map = (struct gpdma_mapping *)arg;
 
-	KASSERT(nseg == 1, ("bus_dmamap_load returned nseg != 1"));
+//	KASSERT(nseg == 1, ("bus_dmamap_load returned nseg != 1"));
 
-	if (error) {
-		printf("gpdma_dmamap_load_cb: error %d\n", error);
-		panic("cannot map DMA memory");
+	map->gm_error = error;
+	
+	if (segs != NULL) {
+		map->gm_addr = segs[0].ds_addr;
+		map->gm_len = segs[0].ds_len;	
 	}
-
-	seg->ds_addr = segs[0].ds_addr;
-	seg->ds_len = segs[0].ds_len;	
 }
 
-static void
+void
 gpdma_dmamap_load_cb2(void *arg, bus_dma_segment_t *segs, int nseg,
     bus_size_t mapsize, int error)
 {
-	bus_dma_segment_t *seg = (bus_dma_segment_t *)arg;
+	struct gpdma_mapping *map = (struct gpdma_mapping *)arg;
 
 	KASSERT(nseg == 1, ("bus_dmamap_load returned nseg != 1"));
 
-	printf("mapsize=%ld\n", mapsize);
-
-	if (error) {
-		printf("gpdma_dmamap_load_cb2: error %d\n", error);
-		panic("cannot map DMA memory");
+	map->gm_error = error;
+	
+	if (segs != NULL) {
+		map->gm_addr = segs[0].ds_addr;
+		map->gm_len = segs[0].ds_len;
 	}
-
-	seg->ds_addr = segs[0].ds_addr;
-	seg->ds_len = segs[0].ds_len;
 }
 
 static int
@@ -116,14 +123,43 @@
 	debugf("initialized");
 }
 
+static void
+gpdma_initialize_channels(struct gpdma_engine *engine,
+    struct gpdma_allocation *alloc)
+{
+	int i, j;
+	struct resource **rv;
+
+	printf("gpdma_initialize_channels(engine=%p, alloc=%p)\n", engine, alloc);
+
+	for (i = 0; alloc[i].da_engine != NULL; i++) {
+
+		printf("alloc: name=%s start=%d end=%d func=%p\n", alloc[i].da_engine, alloc[i].da_start, alloc[i].da_end, alloc[i].da_initializer);
+
+		if (!strcmp(device_get_nameunit(engine->de_dev),
+		    alloc[i].da_engine)) {
+			rv = malloc((alloc[i].da_end - alloc[i].da_start) * 
+			    sizeof(struct resource *), M_GPDMA, M_WAITOK);
+
+			for (j = alloc[i].da_start; j <= alloc[i].da_end; j++) {
+				rv[j - alloc[i].da_start] = gpdma_alloc_channel(
+				    alloc[i].da_engine, j);
+	
+				printf("allocated channel, res=%p\n", rv[j - alloc[i].da_start]);
+			}
+
+			alloc[i].da_initializer(rv, 
+			    alloc[i].da_end - alloc[i].da_start, 
+			    alloc[i].da_arg);
+		}
+	}
+}
+
 int
 gpdma_register_driver(device_t dev, const struct gpdma_capabilities *caps,
     bus_dma_tag_t dmatag)
 {
 	struct gpdma_engine *engine;
-	struct gpdma_engine_cdev *cdev;
-	struct resource *rv;
-	int i;
 
 	engine = malloc(sizeof(struct gpdma_engine), M_GPDMA, M_WAITOK);
 
@@ -146,14 +182,9 @@
 
 	printf("registered new DMA engine: %s\n", device_get_nameunit(dev));
 
-	LIST_INIT(&engine->de_cdevs);
-
-	for (i = 0; i < 15; i++) {
-		cdev = malloc(sizeof(*cdev), M_GPDMA, M_WAITOK);
-		rv = gpdma_alloc_channel(device_get_nameunit(engine->de_dev), i);
-		gpdma_make_cdev(engine, rv, &cdev->dec_cdev);
-		LIST_INSERT_HEAD(&engine->de_cdevs, cdev, dec_link);
-	}
+	//LIST_INIT(&engine->de_cdevs);
+	if (gpdma_allocations != NULL)
+		gpdma_initialize_channels(engine, gpdma_allocations);
 
 	return (0);
 }
@@ -213,7 +244,7 @@
 #endif
 
 	rv = rman_reserve_resource(&engine->de_rman, chno, chno, 1,
-	    RF_ACTIVE, NULL);
+	    RF_ACTIVE, engine->de_dev);
 
 	return (rv);
 }
@@ -235,6 +266,14 @@
 	return (engine->de_dmatag);
 }
 
+const struct gpdma_capabilities *
+gpdma_get_caps(struct resource *res)
+{
+	struct gpdma_engine *engine = gpdma_engine_by_res(res);
+
+	return (engine->de_caps);
+}
+
 int
 gpdma_program_transfer(struct gpdma_transfer *xfer, void **cookiep)
 {
@@ -280,6 +319,18 @@
 	return (GPDMA_STOP_CHANNEL(engine->de_dev, channel));
 }
 
+int
+gpdma_get_transfer_status(void *cookie)
+{
+	struct gpdma_transfer *xfer = (struct gpdma_transfer *)cookie;
+	struct gpdma_engine *engine = xfer->dt_engine;
+	int channel = rman_get_start(xfer->dt_res);
+	int status;
+
+	GPDMA_POLL_CHANNEL(engine->de_dev, channel, &status);
+	return (status);
+}
+
 struct gpdma_transfer *
 gpdma_alloc_transfer(struct resource *res)
 {
@@ -301,6 +352,7 @@
 void
 gpdma_free_transfer(struct gpdma_transfer *xfer)
 {
+
 	free(xfer, M_GPDMA);
 }
 
@@ -310,6 +362,7 @@
 {
 	struct gpdma_buffer *buf = &xfer->dt_buffers[buffer];
 
+	buf->db_needsync = 0;
 	buf->db_addr = paddr;
 	buf->db_length = length;
 	return (0);
@@ -320,7 +373,7 @@
     size_t length)
 {
 	struct gpdma_buffer *buf = &xfer->dt_buffers[buffer];
-	bus_dma_segment_t seg;
+	struct gpdma_mapping map;
 
 	bus_dma_tag_create(xfer->dt_engine->de_dmatag,
 	    1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
@@ -328,14 +381,25 @@
 	    NULL, NULL, &buf->db_dmatag);
 
 	bus_dmamap_create(buf->db_dmatag, 0, &buf->db_dmamap);
+	
+	printf("gpdma_load_buffer_virt(xfer=%p buffer=%d addr=%p length=%d)\n", xfer, buffer, addr, length);
+	printf("buf=%p map=%p tag=%p\n", buf, buf->db_dmamap, buf->db_dmatag);
+	
 	bus_dmamap_load(buf->db_dmatag, buf->db_dmamap, addr, 
-	    length, gpdma_dmamap_load_cb, &seg, BUS_DMA_NOWAIT);
+	    length, gpdma_dmamap_load_cb, &map, BUS_DMA_NOWAIT);
+
+	if (map.gm_error != 0)
+		return (map.gm_error);
 
-	if (seg.ds_len != length)
+	if (map.gm_len != length)
 		return (EFBIG);
 
-	buf->db_addr = seg.ds_addr;
-	buf->db_length = seg.ds_len;
+	if (map.gm_addr == 0)
+		return (EINVAL);
+
+	buf->db_needsync = 1;
+	buf->db_addr = map.gm_addr;
+	buf->db_length = map.gm_len;
 	return (0);
 }
 
@@ -343,9 +407,11 @@
 gpdma_load_buffer_uio(struct gpdma_transfer *xfer, int buffer, struct uio *uio)
 {
 	struct gpdma_buffer *buf = &xfer->dt_buffers[buffer];
-	bus_dma_segment_t seg;
+	struct gpdma_mapping map;
 	bus_size_t length = uio->uio_resid;
 
+	printf("gpdma_load_buffer_uio: addr=%p\n", uio->uio_iov->iov_base);
+
 	bus_dma_tag_create(xfer->dt_engine->de_dmatag,
 	    1, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
 	    NULL, NULL, length, 1, length, BUS_DMA_ALLOCNOW,
@@ -353,37 +419,48 @@
 
 	bus_dmamap_create(buf->db_dmatag, 0, &buf->db_dmamap);
 	bus_dmamap_load_uio(buf->db_dmatag, buf->db_dmamap, uio, 
-	    gpdma_dmamap_load_cb2, &seg, BUS_DMA_NOWAIT);
+	    gpdma_dmamap_load_cb2, &map, BUS_DMA_NOWAIT);
+
+	if (map.gm_error != 0)
+		return (map.gm_error);
 
-	if (seg.ds_len != length)
+	if (map.gm_len != length)
 		return (EFBIG);
 
-	buf->db_addr = seg.ds_addr;
-	buf->db_length = seg.ds_len;
+	if (map.gm_addr == 0)
+		return (EINVAL);
+
+	buf->db_needsync = 1;
+	buf->db_addr = map.gm_addr;
+	buf->db_length = map.gm_len;
 	return (0);
 }
 
 inline void
 gpdma_set_transfer_func(struct gpdma_transfer *xfer, int func)
 {
+	
 	xfer->dt_func = func;
 }
 
 inline void
 gpdma_set_transfer_opts(struct gpdma_transfer *xfer, int flags)
 {
+
 	xfer->dt_flags = flags;
 }
 
 inline void
 gpdma_set_transfer_link(struct gpdma_transfer *xfer, struct gpdma_transfer *xfer2)
 {
+
 	xfer->dt_next = xfer2;
 }
 
 inline void
 gpdma_set_transfer_callback(struct gpdma_transfer *xfer, gpdma_callback_t cb, void *arg)
 {
+
 	xfer->dt_callback = cb;
 	xfer->dt_callback_arg = arg;
 }
@@ -391,30 +468,35 @@
 inline void
 gpdma_set_transfer_flags(struct gpdma_transfer *xfer, int flags)
 {
+
 	xfer->dt_flags = flags;
 }
 
 inline int
 gpdma_get_buffer_layout(struct gpdma_transfer *xfer, int buffer)
 {
+
 	return (xfer->dt_buffers[buffer].db_type);
 }
 
 inline void
 gpdma_set_buffer_layout(struct gpdma_transfer *xfer, int buffer, int type)
 {
+	
 	xfer->dt_buffers[buffer].db_type = type;
 }
 
 inline void
 gpdma_set_buffer_flags(struct gpdma_transfer *xfer, int buffer, int flags)
 {
+
 	xfer->dt_buffers[buffer].db_flags = flags;
 }
 
 inline void
 gpdma_set_buffer_stride(struct gpdma_transfer *xfer, int buffer, int stride_width, int stride_spacing)
 {
+
 	xfer->dt_buffers[buffer].db_stride_width = stride_width;
 	xfer->dt_buffers[buffer].db_stride_spacing = stride_spacing;
 }
@@ -422,6 +504,7 @@
 inline void
 gpdma_set_buffer_fifo_width(struct gpdma_transfer *xfer, int buffer, int width)
 {
+
 	xfer->dt_buffers[buffer].db_fifo_width = width;
 }
 

==== //depot/projects/soc2010/jceel_dma/sys/dev/gpdma/gpdma.h#3 (text+ko) ====

@@ -44,6 +44,7 @@
 typedef struct gpdma_engine *gpdma_engine_t;
 typedef struct gpdma_transfer *gpdma_transfer_t;
 typedef void (*gpdma_callback_t)(int status, void *arg);
+typedef void (*gpdma_initializer_t)(struct resource **res, int nch, void *arg);
 
 enum gpdma_op {
 	GPDMA_FILL 	= 0x1,
@@ -78,6 +79,14 @@
 	LIST_HEAD(, gpdma_engine_cdev)	de_cdevs;
 };
 
+struct gpdma_allocation {
+	const char *			da_engine;
+	int				da_start;
+	int				da_end;
+	gpdma_initializer_t		da_initializer;
+	void *				da_arg;
+};
+
 struct gpdma_capabilities {
 	uint32_t			dc_ops;
 	uint32_t			dc_buffers;
@@ -107,6 +116,7 @@
 	void *			db_immediate;
 
 	/* Private fields: */
+	int			db_needsync;
 	bus_dma_tag_t		db_dmatag;
 	bus_dmamap_t		db_dmamap;
 };
@@ -120,6 +130,7 @@
 #define	GPDMA_TRANSFER_NOINTR		0x4 /* don't generate callbacks */
 #define	GPDMA_TRANSFER_STRIDE_CALLBACK	0x8 /* callback on every stride */
 #define	GPDMA_TRANSFER_STRIDE_SYNC	0x10 /* sync on every stride */
+#define	GPDMA_TRANSFER_BLOCKING		0x20 /* block until transfer completed */
 	gpdma_callback_t		dt_callback;
 	void *			dt_callback_arg;
 	struct gpdma_buffer	dt_buffers[8];
@@ -145,14 +156,15 @@
 
 struct resource *gpdma_alloc_channel(const char *name, int);
 int gpdma_release_channel(struct resource *);
-
 bus_dma_tag_t gpdma_get_dma_tag(struct resource *);
+const struct gpdma_capabilities *gpdma_get_caps(struct resource *);
 
 gpdma_transfer_t gpdma_alloc_transfer(struct resource *);
 void gpdma_free_transfer(gpdma_transfer_t);
 int gpdma_program_transfer(gpdma_transfer_t, void **);
 int gpdma_start_transfer(void *);
 int gpdma_stop_transfer(void *);
+int gpdma_get_transfer_status(void *);
 
 int gpdma_load_buffer_raw(gpdma_transfer_t, int, bus_addr_t, bus_size_t);
 int gpdma_load_buffer_virt(gpdma_transfer_t, int, void *, size_t);
@@ -170,5 +182,7 @@
 void gpdma_set_buffer_stride(gpdma_transfer_t, int, int, int);
 void gpdma_set_buffer_fifo_width(gpdma_transfer_t, int, int);
 
+void gpdma_memutils_init(struct resource **, int, void *);
+
 #endif	/* _SYS_DEV_GPDMA_GPDMA_H */
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008122324.o7CNOcXI056652>