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