lkml.org 
[lkml]   [2006]   [Mar]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
From
SubjectRe: [PATCH 1/9] [I/OAT] DMA memcpy subsystem
Date

On Mar 29, 2006, at 4:55 PM, Chris Leech wrote:

> Provides an API for offloading memory copies to DMA devices
>
> Signed-off-by: Chris Leech <christopher.leech@intel.com>
> ---
>
> drivers/Kconfig | 2
> drivers/Makefile | 1
> drivers/dma/Kconfig | 13 +
> drivers/dma/Makefile | 1
> drivers/dma/dmaengine.c | 405 ++++++++++++++++++++++++++++++++++
> +++++++++++
> include/linux/dmaengine.h | 337 ++++++++++++++++++++++++++++++++++
> +++
> 6 files changed, 759 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/Kconfig b/drivers/Kconfig
> index 9f5c0da..f89ac05 100644
> --- a/drivers/Kconfig
> +++ b/drivers/Kconfig
> @@ -72,4 +72,6 @@ source "drivers/edac/Kconfig"
>
> source "drivers/rtc/Kconfig"
>
> +source "drivers/dma/Kconfig"
> +
> endmenu
> diff --git a/drivers/Makefile b/drivers/Makefile
> index 4249552..9b808a6 100644
> --- a/drivers/Makefile
> +++ b/drivers/Makefile
> @@ -74,3 +74,4 @@ obj-$(CONFIG_SGI_SN) += sn/
> obj-y += firmware/
> obj-$(CONFIG_CRYPTO) += crypto/
> obj-$(CONFIG_SUPERH) += sh/
> +obj-$(CONFIG_DMA_ENGINE) += dma/
> diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
> new file mode 100644
> index 0000000..f9ac4bc
> --- /dev/null
> +++ b/drivers/dma/Kconfig
> @@ -0,0 +1,13 @@
> +#
> +# DMA engine configuration
> +#
> +
> +menu "DMA Engine support"
> +
> +config DMA_ENGINE
> + bool "Support for DMA engines"
> + ---help---
> + DMA engines offload copy operations from the CPU to dedicated
> + hardware, allowing the copies to happen asynchronously.
> +
> +endmenu
> diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
> new file mode 100644
> index 0000000..10b7391
> --- /dev/null
> +++ b/drivers/dma/Makefile
> @@ -0,0 +1 @@
> +obj-y += dmaengine.o
> diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
> new file mode 100644
> index 0000000..683456a
> --- /dev/null
> +++ b/drivers/dma/dmaengine.c
> @@ -0,0 +1,405 @@
> +/*
> + * Copyright(c) 2004 - 2006 Intel Corporation. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> modify it
> + * under the terms of the GNU General Public License as published
> by the Free
> + * Software Foundation; either version 2 of the License, or (at
> your option)
> + * any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
> License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public
> License along with
> + * this program; if not, write to the Free Software Foundation,
> Inc., 59
> + * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
> + *
> + * The full GNU General Public License is included in this
> distribution in the
> + * file called COPYING.
> + */
> +
> +/*
> + * This code implements the DMA subsystem. It provides a HW-
> neutral interface
> + * for other kernel code to use asynchronous memory copy
> capabilities,
> + * if present, and allows different HW DMA drivers to register as
> providing
> + * this capability.
> + *
> + * Due to the fact we are accelerating what is already a
> relatively fast
> + * operation, the code goes to great lengths to avoid additional
> overhead,
> + * such as locking.
> + *
> + * LOCKING:
> + *
> + * The subsystem keeps two global lists, dma_device_list and
> dma_client_list.
> + * Both of these are protected by a spinlock, dma_list_lock.
> + *
> + * Each device has a channels list, which runs unlocked but is
> never modified
> + * once the device is registered, it's just setup by the driver.
> + *
> + * Each client has a channels list, it's only modified under the
> client->lock
> + * and in an RCU callback, so it's safe to read under rcu_read_lock
> ().
> + *
> + * Each device has a kref, which is initialized to 1 when the
> device is
> + * registered. A kref_put is done for each class_device
> registered. When the
> + * class_device is released, the coresponding kref_put is done in
> the release
> + * method. Every time one of the device's channels is allocated to
> a client,
> + * a kref_get occurs. When the channel is freed, the coresponding
> kref_put
> + * happens. The device's release function does a completion, so
> + * unregister_device does a remove event, class_device_unregister,
> a kref_put
> + * for the first reference, then waits on the completion for all
> other
> + * references to finish.
> + *
> + * Each channel has an open-coded implementation of Rusty
> Russell's "bigref,"
> + * with a kref and a per_cpu local_t. A single reference is set
> when on an
> + * ADDED event, and removed with a REMOVE event. Net DMA client
> takes an
> + * extra reference per outstanding transaction. The relase
> function does a
> + * kref_put on the device. -ChrisL
> + */
> +
> +#include <linux/init.h>
> +#include <linux/module.h>
> +#include <linux/device.h>
> +#include <linux/dmaengine.h>
> +#include <linux/hardirq.h>
> +#include <linux/spinlock.h>
> +#include <linux/percpu.h>
> +#include <linux/rcupdate.h>
> +
> +static DEFINE_SPINLOCK(dma_list_lock);
> +static LIST_HEAD(dma_device_list);
> +static LIST_HEAD(dma_client_list);
> +
> +/* --- sysfs implementation --- */
> +
> +static ssize_t show_memcpy_count(struct class_device *cd, char *buf)
> +{
> + struct dma_chan *chan = container_of(cd, struct dma_chan,
> class_dev);
> + unsigned long count = 0;
> + int i;
> +
> + for_each_cpu(i)
> + count += per_cpu_ptr(chan->local, i)->memcpy_count;
> +
> + return sprintf(buf, "%lu\n", count);
> +}
> +
> +static ssize_t show_bytes_transferred(struct class_device *cd,
> char *buf)
> +{
> + struct dma_chan *chan = container_of(cd, struct dma_chan,
> class_dev);
> + unsigned long count = 0;
> + int i;
> +
> + for_each_cpu(i)
> + count += per_cpu_ptr(chan->local, i)->bytes_transferred;
> +
> + return sprintf(buf, "%lu\n", count);
> +}
> +

What is the utility of exporting memcpy_count, and bytes_transferred
to userspace via sysfs? Is this really for debug (and thus should be
under debugfs?)

> +static ssize_t show_in_use(struct class_device *cd, char *buf)
> +{
> + struct dma_chan *chan = container_of(cd, struct dma_chan,
> class_dev);
> +
> + return sprintf(buf, "%d\n", (chan->client ? 1 : 0));
> +}
> +
> +static struct class_device_attribute dma_class_attrs[] = {
> + __ATTR(memcpy_count, S_IRUGO, show_memcpy_count, NULL),
> + __ATTR(bytes_transferred, S_IRUGO, show_bytes_transferred, NULL),
> + __ATTR(in_use, S_IRUGO, show_in_use, NULL),
> + __ATTR_NULL
> +};
> +

[snip]

- kumar
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2006-03-30 10:04    [from the cache]
©2003-2011 Jasper Spaans