dma: port Linux's dmaengine There are no users or devices yet. This compiles and runs the initialization code. Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
diff --git a/kern/drivers/Kbuild b/kern/drivers/Kbuild index 86e9b80..21eec97 100644 --- a/kern/drivers/Kbuild +++ b/kern/drivers/Kbuild
@@ -1,3 +1,4 @@ obj-y += net/ obj-y += dev/ +obj-y += dma/ obj-y += timers/
diff --git a/kern/drivers/dma/Kbuild b/kern/drivers/dma/Kbuild new file mode 100644 index 0000000..43bf5c7 --- /dev/null +++ b/kern/drivers/dma/Kbuild
@@ -0,0 +1 @@ +obj-y += dmaengine.o
diff --git a/kern/drivers/dma/dmaengine.c b/kern/drivers/dma/dmaengine.c index e1ebca3..d881b46 100644 --- a/kern/drivers/dma/dmaengine.c +++ b/kern/drivers/dma/dmaengine.c
@@ -43,33 +43,18 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include <linux/platform_device.h> -#include <linux/dma-mapping.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/mm.h> -#include <linux/device.h> +#include <linux_compat.h> +#include <smallidpool.h> + #include <linux/dmaengine.h> -#include <linux/hardirq.h> -#include <linux/spinlock.h> -#include <linux/percpu.h> -#include <linux/rcupdate.h> -#include <linux/mutex.h> -#include <linux/jiffies.h> -#include <linux/rculist.h> -#include <linux/idr.h> -#include <linux/slab.h> -#include <linux/acpi.h> -#include <linux/acpi_dma.h> -#include <linux/of_dma.h> -#include <linux/mempool.h> -#include <linux/numa.h> static DEFINE_MUTEX(dma_list_mutex); -static DEFINE_IDA(dma_ida); -static LIST_HEAD(dma_device_list); +static struct u16_pool *dma_ida; + +static LINUX_LIST_HEAD(dma_device_list); static long dmaengine_ref_count; +#if 0 // AKAROS /* --- sysfs implementation --- */ /** @@ -162,7 +147,7 @@ chan_dev = container_of(dev, typeof(*chan_dev), device); if (atomic_sub_and_test(chan_dev->idr_ref, 1)) { - ida_free(&dma_ida, chan_dev->dev_id); + put_u16(dma_ida, chan_dev->dev_id); kfree(chan_dev->idr_ref); } kfree(chan_dev); @@ -173,6 +158,7 @@ .dev_groups = dma_dev_groups, .dev_release = chan_dev_release, }; +#endif /* --- client and device registration --- */ @@ -191,7 +177,11 @@ static struct module *dma_chan_to_owner(struct dma_chan *chan) { +#if 0 // AKAROS return chan->device->dev->driver->owner; +#else + return NULL; +#endif } /** @@ -386,9 +376,13 @@ */ static bool dma_chan_is_local(struct dma_chan *chan, int cpu) { +#if 0 // AKAROS int node = dev_to_node(chan->device->dev); return node == NUMA_NO_NODE || cpumask_test_cpu(cpu, cpumask_of_node(node)); +#else + return true; +#endif } /** @@ -451,7 +445,7 @@ /* undo the last distribution */ for_each_dma_cap_mask(cap, dma_cap_mask_all) for_each_possible_cpu(cpu) - per_cpu_ptr(channel_table[cap], cpu)->chan = NULL; + _PERCPU_VARPTR(*channel_table[cap], cpu)->chan = NULL; list_for_each_entry(device, &dma_device_list, global_node) { if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) @@ -468,7 +462,7 @@ for_each_dma_cap_mask(cap, dma_cap_mask_all) for_each_online_cpu(cpu) { chan = min_chan(cap, cpu); - per_cpu_ptr(channel_table[cap], cpu)->chan = chan; + _PERCPU_VARPTR(*channel_table[cap], cpu)->chan = chan; } } @@ -702,6 +696,7 @@ struct dma_device *d, *_d; struct dma_chan *chan = NULL; +#if 0 // AKAROS /* If device-tree is present get slave info from here */ if (dev->of_node) chan = of_dma_request_slave_channel(dev->of_node, name); @@ -709,6 +704,7 @@ /* If device was enumerated by ACPI get slave info from here */ if (has_acpi_companion(dev) && !chan) chan = acpi_dma_request_slave_chan_by_name(dev, name); +#endif if (chan) { /* Valid channel found or requester need to be deferred */ @@ -786,8 +782,8 @@ void dma_release_channel(struct dma_chan *chan) { qlock(&dma_list_mutex); - WARN_ONCE(chan->client_count != 1, - "chan reference count %d != 1\n", chan->client_count); + if (chan->client_count != 1) + warn_once("chan reference count %d != 1\n", chan->client_count); dma_chan_put(chan); /* drop PRIVATE cap enabled by __dma_request_channel() */ if (--chan->device->privatecnt == 0) @@ -898,7 +894,7 @@ static int get_dma_id(struct dma_device *device) { - int rc = ida_alloc(&dma_ida, MEM_WAIT); + int rc = get_u16(dma_ida); if (rc < 0) return rc; @@ -1031,12 +1027,15 @@ } chan->chan_id = chancnt++; +#if 0 // AKAROS chan->dev->device.class = &dma_devclass; chan->dev->device.parent = device->dev; chan->dev->chan = chan; chan->dev->idr_ref = idr_ref; chan->dev->dev_id = device->dev_id; +#endif atomic_inc(idr_ref); +#if 0 // AKAROS dev_set_name(&chan->dev->device, "dma%dchan%d", device->dev_id, chan->chan_id); @@ -1048,6 +1047,7 @@ atomic_dec(idr_ref); goto err_out; } +#endif chan->client_count = 0; } @@ -1087,7 +1087,7 @@ err_out: /* if we never registered a channel just release the idr */ if (atomic_read(idr_ref) == 0) { - ida_free(&dma_ida, device->dev_id); + put_u16(dma_ida, device->dev_id); kfree(idr_ref); return rc; } @@ -1098,7 +1098,9 @@ qlock(&dma_list_mutex); chan->dev->chan = NULL; qunlock(&dma_list_mutex); +#if 0 // AKAROS device_unregister(&chan->dev->device); +#endif free_percpu(chan->local); } return rc; @@ -1122,13 +1124,15 @@ qunlock(&dma_list_mutex); list_for_each_entry(chan, &device->channels, device_node) { - WARN_ONCE(chan->client_count, - "%s called while %d clients hold a reference\n", - __func__, chan->client_count); + if (chan->client_count) + warn_once( "%s called while %d clients hold a reference\n", + __func__, chan->client_count); qlock(&dma_list_mutex); chan->dev->chan = NULL; qunlock(&dma_list_mutex); +#if 0 // AKAROS device_unregister(&chan->dev->device); +#endif free_percpu(chan->local); } } @@ -1153,6 +1157,7 @@ void *p; int ret; +#if 0 // AKAROS p = devres_alloc(dmam_device_release, sizeof(void *), MEM_WAIT); if (!p) return -ENOMEM; @@ -1164,6 +1169,9 @@ } else { devres_free(p); } +#else + ret = dma_async_device_register(device); +#endif return ret; } @@ -1172,7 +1180,9 @@ struct dmaengine_unmap_pool { struct kmem_cache *cache; const char *name; +#if 0 // AKAROS mempool_t *pool; +#endif size_t size; }; @@ -1229,13 +1239,17 @@ DMA_BIDIRECTIONAL); } cnt = unmap->map_cnt; +#if 0 // AKAROS mempool_free(unmap, __get_unmap_pool(cnt)->pool); +#else + kmem_cache_free(__get_unmap_pool(cnt)->cache, unmap); +#endif } void dmaengine_unmap_put(struct dmaengine_unmap_data *unmap) { if (unmap) - kref_put(&unmap->kref, dmaengine_unmap); + kref_put(&unmap->kref); } EXPORT_SYMBOL_GPL(dmaengine_unmap_put); @@ -1246,8 +1260,10 @@ for (i = 0; i < ARRAY_SIZE(unmap_pool); i++) { struct dmaengine_unmap_pool *p = &unmap_pool[i]; +#if 0 // AKAROS mempool_destroy(p->pool); p->pool = NULL; +#endif kmem_cache_destroy(p->cache); p->cache = NULL; } @@ -1264,13 +1280,15 @@ size = sizeof(struct dmaengine_unmap_data) + sizeof(dma_addr_t) * p->size; - p->cache = kmem_cache_create(p->name, size, 0, - SLAB_HWCACHE_ALIGN, NULL); + p->cache = kmem_cache_create(p->name, size, ARCH_CL_SIZE, + 0, NULL, NULL, NULL, NULL); if (!p->cache) break; +#if 0 // AKAROS p->pool = mempool_create_slab_pool(1, p->cache); if (!p->pool) break; +#endif } if (i == ARRAY_SIZE(unmap_pool)) @@ -1285,12 +1303,16 @@ { struct dmaengine_unmap_data *unmap; +#if 0 // AKAROS unmap = mempool_alloc(__get_unmap_pool(nr)->pool, flags); +#else + unmap = kmem_cache_alloc(__get_unmap_pool(nr)->cache, flags); +#endif if (!unmap) return NULL; memset(unmap, 0, sizeof(*unmap)); - kref_init(&unmap->kref); + kref_init(&unmap->kref, dmaengine_unmap, 1); unmap->dev = dev; unmap->map_cnt = nr; @@ -1376,8 +1398,17 @@ if (err) return err; +#if 0 // AKAROS return class_register(&dma_devclass); +#else + return 0; +#endif } arch_initcall(dma_bus_init); - +static void __init dmaengine_init(void) +{ + dma_ida = create_u16_pool(MAX_U16_POOL_SZ); + assert(dma_ida); +} +init_func_2(dmaengine_init);
diff --git a/kern/drivers/dma/dmaengine.h b/kern/drivers/dma/dmaengine.h index fcd6cd5..75e9d89 100644 --- a/kern/drivers/dma/dmaengine.h +++ b/kern/drivers/dma/dmaengine.h
@@ -6,7 +6,6 @@ #ifndef DMAENGINE_H #define DMAENGINE_H -#include <linux/bug.h> #include <linux/dmaengine.h> /**
diff --git a/kern/include/linux/dmaengine.h b/kern/include/linux/dmaengine.h index d5c07e6..cf40297 100644 --- a/kern/include/linux/dmaengine.h +++ b/kern/include/linux/dmaengine.h
@@ -17,14 +17,12 @@ #ifndef LINUX_DMAENGINE_H #define LINUX_DMAENGINE_H -#include <linux/device.h> -#include <linux/err.h> -#include <linux/uio.h> -#include <linux/bug.h> -#include <linux/scatterlist.h> -#include <linux/bitmap.h> -#include <linux/types.h> -#include <asm/page.h> +#include <linux_compat.h> + +#define CONFIG_DMA_ENGINE +#define CONFIG_ASYNC_TX_DMA +#define CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH +#define CONFIG_RAPIDIO_DMA_ENGINE /** * typedef dma_cookie_t - an opaque DMA cookie