From owner-p4-projects@FreeBSD.ORG Thu Aug 12 23:24:39 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 7B6701065696; Thu, 12 Aug 2010 23:24:39 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2750E1065673 for ; Thu, 12 Aug 2010 23:24:39 +0000 (UTC) (envelope-from jceel@freebsd.org) Received: from skunkworks.freebsd.org (skunkworks.freebsd.org [IPv6:2001:4f8:fff6::2d]) by mx1.freebsd.org (Postfix) with ESMTP id 12FB08FC08 for ; Thu, 12 Aug 2010 23:24:39 +0000 (UTC) Received: from skunkworks.freebsd.org (localhost [127.0.0.1]) by skunkworks.freebsd.org (8.14.4/8.14.4) with ESMTP id o7CNOc8T056655 for ; Thu, 12 Aug 2010 23:24:38 GMT (envelope-from jceel@freebsd.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.4/8.14.4/Submit) id o7CNOcXI056652 for perforce@freebsd.org; Thu, 12 Aug 2010 23:24:38 GMT (envelope-from jceel@freebsd.org) Date: Thu, 12 Aug 2010 23:24:38 GMT Message-Id: <201008122324.o7CNOcXI056652@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to jceel@freebsd.org using -f From: Jakub Wojciech Klama To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 182338 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Aug 2010 23:24:39 -0000 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 #include +#include +#include + #include #include +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 #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 */