Messages in this thread |  | | | From | Kumar Gala <> | | Subject | Re: [PATCH 1/9] [I/OAT] DMA memcpy subsystem | | Date | Thu, 30 Mar 2006 02:01:20 -0600 |
| |
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/
|  |