All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH][3/17] REV 2 USB virt 2.6 split driver---xenidc buffer references
@ 2005-11-23 16:12 harry
  0 siblings, 0 replies; only message in thread
From: harry @ 2005-11-23 16:12 UTC (permalink / raw)
  To: xen-devel

[-- Attachment #1: Type: text/plain, Size: 467 bytes --]

This patch implements the generic code to support local and remote
buffer references for the xenidc transport which is used by the USB
driver.

Local buffer references are used to describe local memory and are
converted into remote buffer references for communication with other
domains.  The other domains use remote buffer references to map the
buffers into their local address space for bulk data transfer.

Signed-off-by: Harry Butterworth <butterwo@uk.ibm.com>


[-- Attachment #2: p3-xenidc-buffer-references.patch --]
[-- Type: text/x-patch, Size: 47559 bytes --]

diff -r cf3c717101a8 -r a64ebf373f9c linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile	Wed Nov 23 15:13:22 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile	Wed Nov 23 15:38:27 2005
@@ -4,3 +4,5 @@
 xenidc-objs += xenidc_callback.o
 xenidc-objs += xenidc_work.o
 xenidc-objs += xenidc_buffer_resource_provider.o
+xenidc-objs += xenidc_local_buffer_reference.o
+xenidc-objs += xenidc_remote_buffer_reference.o
diff -r cf3c717101a8 -r a64ebf373f9c linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_local_buffer_reference.c
--- /dev/null	Wed Nov 23 15:13:22 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_local_buffer_reference.c	Wed Nov 23 15:38:27 2005
@@ -0,0 +1,385 @@
+/*****************************************************************************/
+/* Xen inter-domain communication local buffer references.                   */
+/*                                                                           */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation                      */
+/*                                                                           */
+/* 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                   */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm-xen/xenidc_local_buffer_reference.h>
+#include "xenidc_trace.h"
+
+#define XENIDC_LBR_HASH_COUNT 255
+static DEFINE_RWLOCK(xenidc_lbr_lock);
+static struct list_head xenidc_lbr_concrete_hash[XENIDC_LBR_HASH_COUNT];
+static struct list_head xenidc_lbr_copy_hash[XENIDC_LBR_HASH_COUNT];
+static struct list_head xenidc_lbr_virtual_hash[XENIDC_LBR_HASH_COUNT];
+
+static void xenidc_lbr_init(void)
+{
+	static int initialised = 0;
+	unsigned long flags;
+	trace();
+	write_lock_irqsave(&xenidc_lbr_lock, flags);
+	if (!initialised) {
+		int i;
+		for (i = 0; i < XENIDC_LBR_HASH_COUNT; i++) {
+			INIT_LIST_HEAD(&xenidc_lbr_concrete_hash[i]);
+			INIT_LIST_HEAD(&xenidc_lbr_copy_hash[i]);
+			INIT_LIST_HEAD(&xenidc_lbr_virtual_hash[i]);
+		}
+		initialised = 1;
+	}
+	write_unlock_irqrestore(&xenidc_lbr_lock,flags);
+}
+
+static void
+xenidc_lbr_default_zero(struct xenidc_lbr_concrete_class *class,
+struct xenidc_lbr *lbr)
+{
+	struct xenidc_lbr temp_lbr = *lbr;
+	u8 buffer[64];
+	trace();
+	memset(buffer, 0, 64);
+	do {
+		xenidc_buffer_byte_count this_go =
+			min(temp_lbr.byte_count, (xenidc_buffer_byte_count)64);
+		class->copy_in_or_out(class, &temp_lbr, buffer, this_go, 0);
+		xenidc_lbr_advance(&temp_lbr, this_go);
+	} while (temp_lbr.byte_count != 0);
+}
+
+xenidc_lbr_type
+xenidc_lbr_register_concrete_class(struct xenidc_lbr_concrete_class *class,
+xenidc_lbr_copy_in_or_out_function *copy_in_or_out,
+xenidc_lbr_zero_function *zero,
+xenidc_lbr_calculate_rbr_resources_function *calculate_rbr_resources,
+xenidc_lbr_create_rbr_function *create_rbr,
+xenidc_lbr_revoke_rbr_function *revoke_rbr)
+{
+	static xenidc_lbr_type type_index = 0;
+	unsigned long flags;
+	trace();
+	xenidc_lbr_init();
+	INIT_LIST_HEAD(&class->link);
+	if (zero == NULL)
+		zero = xenidc_lbr_default_zero;
+	class->copy_in_or_out = copy_in_or_out;
+	class->zero = zero;
+	class->calculate_rbr_resources = calculate_rbr_resources;
+	class->create_rbr = create_rbr;
+	class->revoke_rbr = revoke_rbr;
+	write_lock_irqsave(&xenidc_lbr_lock, flags);
+	class->type = ++type_index;
+	list_add_tail(&class->link, &xenidc_lbr_concrete_hash[
+				class->type % XENIDC_LBR_HASH_COUNT]);
+	write_unlock_irqrestore(&xenidc_lbr_lock, flags);
+	return class->type;
+}
+
+static inline struct xenidc_lbr_concrete_class *
+xenidc_lbr_find_concrete_class(xenidc_lbr_type type)
+{
+	int i = type % XENIDC_LBR_HASH_COUNT;
+	struct xenidc_lbr_concrete_class *class;
+	unsigned long flags;
+	trace();
+	read_lock_irqsave(&xenidc_lbr_lock, flags);
+	list_for_each_entry(class, &xenidc_lbr_concrete_hash[i], link) {
+		if (class->type == type) {
+			read_unlock_irqrestore(&xenidc_lbr_lock, flags);
+			return class;
+		}
+	}
+	read_unlock_irqrestore(&xenidc_lbr_lock, flags);
+	BUG();
+	return NULL;
+}
+
+void
+xenidc_lbr_register_copy_class(struct xenidc_lbr_copy_class *class,
+xenidc_lbr_type target_type, xenidc_lbr_type source_type,
+xenidc_lbr_copy_function *copy)
+{
+	unsigned long flags;
+	int i = ((target_type << 16 | source_type) % XENIDC_LBR_HASH_COUNT);
+	trace();
+	INIT_LIST_HEAD(&class->link);
+	class->target_type = target_type;
+	class->source_type = source_type;
+	class->copy = copy;
+	write_lock_irqsave(&xenidc_lbr_lock, flags);
+	list_add_tail(&class->link, &xenidc_lbr_copy_hash[i]);
+	write_unlock_irqrestore(&xenidc_lbr_lock, flags);
+}
+
+static inline struct xenidc_lbr_copy_class *
+xenidc_lbr_find_copy_class(xenidc_lbr_type target_type,
+xenidc_lbr_type source_type)
+{
+	int i = ((target_type << 16 | source_type) % XENIDC_LBR_HASH_COUNT);
+	struct xenidc_lbr_copy_class *class;
+	unsigned long flags;
+	trace();
+	read_lock_irqsave(&xenidc_lbr_lock, flags);
+	list_for_each_entry(class, &xenidc_lbr_copy_hash[i], link) {
+		if ((class->target_type == target_type) &&
+					(class->source_type == source_type)) {
+			read_unlock_irqrestore(&xenidc_lbr_lock, flags);
+			return class;
+		}
+	}
+	read_unlock_irqrestore(&xenidc_lbr_lock, flags);
+	return NULL;
+}
+
+xenidc_lbr_type
+xenidc_lbr_register_virtual_class(struct xenidc_lbr_virtual_class *class,
+xenidc_lbr_resolve_function *resolve,
+xenidc_lbr_advance_function *advance)
+{
+	static xenidc_lbr_type type_index = 0;
+	unsigned long flags;
+	trace();
+	xenidc_lbr_init();
+	INIT_LIST_HEAD(&class->link);
+	class->resolve = resolve;
+	class->advance = advance;
+	write_lock_irqsave(&xenidc_lbr_lock, flags);
+	class->type = ++type_index | XENIDC_LBR_TYPE_FLAG_VIRTUAL |
+		((advance != NULL) ? XENIDC_LBR_TYPE_FLAG_VIRTUAL_ADVANCE : 0);
+	list_add_tail(&class->link, &xenidc_lbr_virtual_hash
+					[class->type % XENIDC_LBR_HASH_COUNT]);
+	write_unlock_irqrestore(&xenidc_lbr_lock, flags);
+	return class->type;
+}
+
+static inline struct xenidc_lbr_virtual_class *
+xenidc_lbr_find_virtual_class(xenidc_lbr_type type)
+{
+	int i = type % XENIDC_LBR_HASH_COUNT;
+	struct xenidc_lbr_virtual_class *class;
+	unsigned long flags;
+	trace();
+	read_lock_irqsave(&xenidc_lbr_lock, flags);
+	list_for_each_entry(class, &xenidc_lbr_virtual_hash[i], link) {
+		if (class->type == type) {
+			read_unlock_irqrestore(&xenidc_lbr_lock, flags);
+			return class;
+		}
+	}
+	read_unlock_irqrestore(&xenidc_lbr_lock, flags);
+	BUG();
+	return NULL;
+}
+
+struct xenidc_lbr xenidc_lbr_resolve(struct xenidc_lbr *lbr)
+{
+	struct xenidc_lbr resolved_lbr = *lbr;
+	trace();
+	while (1) {
+		if ((resolved_lbr.type & XENIDC_LBR_TYPE_FLAG_VIRTUAL) == 0) {
+			return resolved_lbr;
+		} else {
+			struct xenidc_lbr_virtual_class *class =
+			      xenidc_lbr_find_virtual_class(resolved_lbr.type);
+			resolved_lbr = class->resolve(class, &resolved_lbr);
+		}
+	}
+}
+
+int
+xenidc_lbr_calculate_rbr_resources(struct xenidc_lbr *lbr,
+struct xenidc_address *address, struct xenidc_buffer_resource_list *list)
+{
+	trace();
+	if (lbr->byte_count != 0) {
+		struct xenidc_lbr_concrete_class *class;
+		class = xenidc_lbr_find_concrete_class(lbr->type);
+		return class->calculate_rbr_resources(class, lbr, address,
+									list);
+	} else {
+		*list = xenidc_buffer_resource_list_null();
+		return 0;
+	}
+}
+
+struct xenidc_lbr_concrete_class **
+xenidc_lbr_create_rbr(struct xenidc_lbr *lbr, struct xenidc_address *address,
+struct xenidc_buffer_resource_provider *provider, struct xenidc_rbr *rbr,
+int access_flags)
+{
+	trace();
+	if (lbr->byte_count != 0) {
+		struct xenidc_lbr_concrete_class *class;
+		class = xenidc_lbr_find_concrete_class(lbr->type);
+		return class->create_rbr(class, lbr, address, provider, rbr,
+								access_flags);
+	} else {
+		memset(rbr, 0, sizeof(*rbr));
+		return NULL;
+	}
+}
+
+void
+xenidc_lbr_revoke_rbr(struct xenidc_lbr_concrete_class **context,
+struct xenidc_callback *callback)
+{
+	trace();
+	if (context != NULL) {
+		(*context)->revoke_rbr(context, callback);
+	} else {
+		xenidc_callback_success(callback);
+	}
+}
+
+xenidc_buffer_byte_count
+xenidc_lbr_copy_in_or_out(struct xenidc_lbr *lbr, void *buffer,
+xenidc_buffer_byte_count buffer_byte_count, int out)
+{
+	xenidc_buffer_byte_count byte_count = min(lbr->byte_count,
+							buffer_byte_count);
+	xenidc_buffer_byte_count remainder_offset = 0;
+	xenidc_buffer_byte_count remainder_count = byte_count;
+	struct xenidc_lbr top_lbr = *lbr;
+	trace();
+	/* Total amount to copy is the smaller of the two buffers.           */
+	while (remainder_count != 0) {
+		/* top_lbr might be virtual so we resolve it to get a        */
+		/* concrete lbr for the first contiguous chunk of top_lbr.   */
+		struct xenidc_lbr resolved_lbr = xenidc_lbr_resolve(&top_lbr);
+		/* resolved_lbr is guaranteed to be concrete so we can look  */
+		/* its copy method.                                          */
+		struct xenidc_lbr_concrete_class *class =
+			xenidc_lbr_find_concrete_class(resolved_lbr.type);
+		/* Amount to copy this go may be restricted by the size of   */
+		/* resolved lbr.                                             */
+		xenidc_buffer_byte_count this_go = min(resolved_lbr.byte_count,
+							remainder_count);
+		class->copy_in_or_out(class, &resolved_lbr,
+			(char *)buffer + remainder_offset, this_go, out);
+		remainder_offset += this_go;
+		remainder_count -= this_go;
+		xenidc_lbr_advance(&top_lbr, this_go);
+	}
+	return byte_count;
+}
+
+void xenidc_lbr_zero(struct xenidc_lbr *lbr)
+{
+	struct xenidc_lbr top_lbr = *lbr;
+	trace();
+	while (top_lbr.byte_count != 0) {
+		/* top_lbr might be virtual so we resolve it to get a        */
+		/* concrete lbr for the first contiguous chunk of top_lbr.   */
+		struct xenidc_lbr resolved_lbr = xenidc_lbr_resolve(&top_lbr);
+		struct xenidc_lbr_concrete_class *class;
+		class = xenidc_lbr_find_concrete_class(resolved_lbr.type);
+		class->zero(class, &resolved_lbr);
+		xenidc_lbr_advance(&top_lbr, resolved_lbr.byte_count);
+	}
+}
+
+xenidc_buffer_byte_count
+xenidc_lbr_copy(struct xenidc_lbr *target, struct xenidc_lbr *source)
+{
+	xenidc_buffer_byte_count byte_count = min(target->byte_count,
+							source->byte_count);
+	struct xenidc_lbr top_target_lbr = *target;
+	struct xenidc_lbr top_source_lbr = *source;
+	xenidc_buffer_byte_count remainder_count = byte_count;
+	trace();
+	/* Total amount to copy is the smaller of the two buffers. */
+	while (remainder_count != 0) {
+		struct xenidc_lbr resolved_target_lbr;
+		struct xenidc_lbr resolved_source_lbr;
+		xenidc_buffer_byte_count this_go;
+		struct xenidc_lbr_copy_class *copy_class;
+		resolved_target_lbr = xenidc_lbr_resolve(&top_target_lbr);
+		resolved_source_lbr = xenidc_lbr_resolve(&top_source_lbr);
+		this_go = min(resolved_target_lbr.byte_count,
+					resolved_source_lbr.byte_count);
+		copy_class = xenidc_lbr_find_copy_class(
+					resolved_target_lbr.type,
+					resolved_source_lbr.type);
+		if (copy_class != NULL) {
+			copy_class->copy(copy_class, &resolved_target_lbr,
+						&resolved_source_lbr, this_go);
+		} else {
+			u8 buffer[64];
+			struct xenidc_lbr_concrete_class
+				*target_concrete_class, *source_concrete_class;
+			struct xenidc_lbr temp_target, temp_source;
+			xenidc_buffer_byte_count nested_remainder_count;
+			target_concrete_class = xenidc_lbr_find_concrete_class(
+						resolved_target_lbr.type);
+			source_concrete_class = xenidc_lbr_find_concrete_class(
+						resolved_source_lbr.type);
+			temp_target = resolved_target_lbr;
+			temp_source = resolved_source_lbr;
+			nested_remainder_count = this_go;
+			do {
+				xenidc_buffer_byte_count nested_this_go;
+                                nested_this_go = min(
+						(xenidc_buffer_byte_count)64,
+						nested_remainder_count);
+				source_concrete_class->copy_in_or_out(
+							source_concrete_class,
+							&temp_source,
+							buffer, nested_this_go,
+							1);
+				target_concrete_class->copy_in_or_out(
+							target_concrete_class,
+							&temp_target,
+							buffer, nested_this_go,
+							0);
+				xenidc_lbr_advance(&temp_target,
+							nested_this_go);
+				xenidc_lbr_advance(&temp_source,
+							nested_this_go);
+				nested_remainder_count -= nested_this_go;
+			} while (nested_remainder_count != 0);
+		}
+		xenidc_lbr_advance(&top_target_lbr, this_go);
+		xenidc_lbr_advance(&top_source_lbr, this_go);
+		remainder_count -= this_go;
+	}
+	return byte_count;
+}
+
+xenidc_buffer_byte_count
+xenidc_lbr_virtual_advance(struct xenidc_lbr *lbr,
+xenidc_buffer_byte_count byte_count)
+{
+	xenidc_buffer_byte_count actual_byte_count;
+	struct xenidc_lbr_virtual_class *class;
+	trace();
+	actual_byte_count = min(lbr->byte_count, byte_count);
+	class = xenidc_lbr_find_virtual_class(lbr->type);
+	class->advance(class, lbr, actual_byte_count);
+	return actual_byte_count;
+}
+
+EXPORT_SYMBOL(xenidc_lbr_register_concrete_class);
+EXPORT_SYMBOL(xenidc_lbr_register_copy_class);
+EXPORT_SYMBOL(xenidc_lbr_register_virtual_class);
+EXPORT_SYMBOL(xenidc_lbr_copy_in_or_out);
+EXPORT_SYMBOL(xenidc_lbr_zero);
+EXPORT_SYMBOL(xenidc_lbr_copy);
+EXPORT_SYMBOL(xenidc_lbr_virtual_advance);
diff -r cf3c717101a8 -r a64ebf373f9c linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_remote_buffer_reference.c
--- /dev/null	Wed Nov 23 15:13:22 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_remote_buffer_reference.c	Wed Nov 23 15:38:27 2005
@@ -0,0 +1,130 @@
+/*****************************************************************************/
+/* Xen inter-domain communication remote buffer references                   */
+/*                                                                           */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation                      */
+/*                                                                           */
+/* 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                   */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm-xen/xenidc_remote_buffer_reference.h>
+#include "xenidc_trace.h"
+
+#define XENIDC_RBR_HASH_COUNT 255
+static DEFINE_RWLOCK(xenidc_rbr_lock);
+static struct list_head xenidc_rbr_mappable_hash[XENIDC_RBR_HASH_COUNT];
+
+static void xenidc_rbr_init(void)
+{
+	static int initialised = 0;
+	unsigned long flags;
+	trace();
+	write_lock_irqsave(&xenidc_rbr_lock, flags);
+	if (!initialised) {
+		int i;
+		for (i = 0; i < XENIDC_RBR_HASH_COUNT; i++) {
+			INIT_LIST_HEAD(&xenidc_rbr_mappable_hash[i]);
+		}
+		initialised = 1;
+	}
+	write_unlock_irqrestore(&xenidc_rbr_lock, flags);
+}
+
+void
+xenidc_rbr_register_buffer_mappable_class(
+struct xenidc_rbr_mappable_class *class, xenidc_rbr_type type,
+xenidc_rbr_calculate_map_resources_function *calculate_map_resources,
+xenidc_rbr_map_function *map, xenidc_rbr_unmap_function *unmap)
+{
+	int i = (class->type % XENIDC_RBR_HASH_COUNT);
+	unsigned long flags;
+	trace();
+	xenidc_rbr_init();
+	INIT_LIST_HEAD(&class->link);
+	class->type = type;
+	class->calculate_map_resources = calculate_map_resources;
+	class->map = map;
+	class->unmap = unmap;
+	write_lock_irqsave(&xenidc_rbr_lock, flags);
+	list_add_tail(&class->link, &xenidc_rbr_mappable_hash[i]);
+	write_unlock_irqrestore(&xenidc_rbr_lock, flags);
+}
+
+static inline struct xenidc_rbr_mappable_class *
+xenidc_rbr_find_mappable_class(xenidc_rbr_type type)
+{
+	int i = type % XENIDC_RBR_HASH_COUNT;
+	struct xenidc_rbr_mappable_class *class;
+	unsigned long flags;
+	trace();
+	read_lock_irqsave(&xenidc_rbr_lock, flags);
+	list_for_each_entry(class, &xenidc_rbr_mappable_hash[i], link) {
+		if (class->type == type) {
+			read_unlock_irqrestore(
+				&xenidc_rbr_lock, flags);
+			return class;
+		}
+	}
+	read_unlock_irqrestore(&xenidc_rbr_lock, flags);
+	return NULL;
+}
+
+int
+xenidc_rbr_calculate_map_resources(struct xenidc_rbr *rbr,
+struct xenidc_address *address, struct xenidc_buffer_resource_list *list)
+{
+	trace();
+	if (rbr->byte_count != 0) {
+		struct xenidc_rbr_mappable_class *class;
+		class = xenidc_rbr_find_mappable_class(rbr->type);
+		if (class != NULL) {
+			return class->calculate_map_resources(class, rbr,
+							      address, list);
+		} else {
+			return 1;
+		}
+	} else {
+		*list = xenidc_buffer_resource_list_null();
+		return 0;
+	}
+}
+
+struct xenidc_rbr_mappable_class **
+xenidc_rbr_map(struct xenidc_rbr *rbr, struct xenidc_address *address,
+struct xenidc_buffer_resource_provider *provider, void **mapping,
+int access_flags)
+{
+	trace();
+	if (rbr->byte_count != 0) {
+		struct xenidc_rbr_mappable_class *class;
+		class = xenidc_rbr_find_mappable_class(rbr->type);
+		return class->map(class, rbr, address, provider, mapping,
+								access_flags);
+	} else {
+		*mapping = NULL;
+		return (struct xenidc_rbr_mappable_class **)1;
+	}
+}
+
+void xenidc_rbr_unmap(struct xenidc_rbr_mappable_class **context)
+{
+	trace();
+	if (context != (struct xenidc_rbr_mappable_class **)1) {
+		(*context)->unmap(context);
+	}
+}
diff -r cf3c717101a8 -r a64ebf373f9c linux-2.6-xen-sparse/include/asm-xen/xenidc_address.h
--- /dev/null	Wed Nov 23 15:13:22 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenidc_address.h	Wed Nov 23 15:38:27 2005
@@ -0,0 +1,63 @@
+/*****************************************************************************/
+/* Xen inter-domain communication address.                                   */
+/*                                                                           */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation                      */
+/*                                                                           */
+/* 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 xenidc_address type represents an address on the                      */
+/* interdomain-communication bus.  This is useful as an opaque type to pass  */
+/* through any layers of code that don't need to be coupled to the           */
+/* underlying implementation details of the IDC code.                        */
+
+#ifndef __ASM_XEN_XENIDC_ADDRESS_H__
+#define __ASM_XEN_XENIDC_ADDRESS_H__
+
+struct xenidc_address {
+	const char *local;
+	const char *remote;
+	int remote_id;
+};
+
+static inline void
+xenidc_address_init(struct xenidc_address *address, const char *local,
+const char *remote, int remote_id)
+{
+	address->local = local;
+	address->remote = remote;
+	address->remote_id = remote_id;
+}
+
+static inline const char *
+xenidc_address_query_local_domain(struct xenidc_address *address)
+{
+	return address->local;
+}
+
+static inline const char *
+xenidc_address_query_remote_domain(struct xenidc_address *address)
+{
+	return address->remote;
+}
+
+static inline int
+xenidc_address_query_remote_domain_id(struct xenidc_address *address)
+{
+	return address->remote_id;
+}
+
+#endif
diff -r cf3c717101a8 -r a64ebf373f9c linux-2.6-xen-sparse/include/asm-xen/xenidc_local_buffer_reference.h
--- /dev/null	Wed Nov 23 15:13:22 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenidc_local_buffer_reference.h	Wed Nov 23 15:38:27 2005
@@ -0,0 +1,358 @@
+/*****************************************************************************/
+/* Xen inter-domain communication local buffer reference object.             */
+/*                                                                           */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation                      */
+/*                                                                           */
+/* 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                   */
+/*                                                                           */
+/*****************************************************************************/
+/*                                                                           */
+/* Local buffer references are an abstraction for pointers to memory which   */
+/* are useful for the following reasons:                                     */
+/*                                                                           */
+/* They allow clients to describe what type of memory they are passing to a  */
+/* service which makes it possible to implement services which deal with     */
+/* whatever memory the client happens to have rather than forcing the client */
+/* to implement memory management code to convert to the form required by    */
+/* the service.  This makes it possible to move memory management code out   */
+/* of clients and out of services and into a single core memory management   */
+/* implementation.  This is good for code quality and maintainability.       */
+/*                                                                           */
+/* They also bundle together the buffer pointer, any start offset (for       */
+/* example into a page table) and the buffer length into one convenient      */
+/* structure and provide functions for performing all the necessary buffer   */
+/* manipulation arithmetic operations.  This is convenient for clients and   */
+/* good for code quality because the buffer manipulations are easy to use    */
+/* and make it less likely for arithmetic errors to lead to buffer overflows.*/
+/*                                                                           */
+/* They are also useful for implementing logical buffer operations like      */
+/* concatenation of buffers and viewing a buffer as a wrapping buffer.       */
+/* Again, this is a convenient mechanism which is easier to review and less  */
+/* error prone than explicit arithmetic.                                     */
+/*                                                                           */
+/* This interface provides the basic functions and mechanisms for installing */
+/* different types of local buffer references for referencing different      */
+/* kinds of memory, referencing memory in different ways an copying between  */
+/* different kinds of memory.                                                */
+/*                                                                           */
+/* There are three kinds of registration:                                    */
+/*                                                                           */
+/* A concrete class is used to register a type of memory.  For example       */
+/* "kernel virtual address space" would be one kind of memory.  Another kind */
+/* might for example be shared page cache memory not mapped into the kernel  */
+/* virtual address space but for which synchronous access was possible using */
+/* some hypervisor calls.                                                    */
+/*                                                                           */
+/* A virtual class is used to register a way of viewing other local buffers. */
+/* For example, concatenation is a way of looking at two buffers and         */
+/* wrapping is a way of looking at a single buffer.                          */
+/*                                                                           */
+/* A copy class is used to implement a fast-path mechanism for copying       */
+/* between two potentially different types of concrete classes.              */
+/* There is an inefficient default mechanism as a fallback but any kinds of  */
+/* copying for which performance is a concern should have a bespoke copy     */
+/* class.                                                                    */
+
+#ifndef __ASM_XEN_XENIDC_LBR_H__
+#define __ASM_XEN_XENIDC_LBR_H__
+
+#include "xenidc_buffer_resource_provider.h"
+#include "xenidc_remote_buffer_reference.h"
+#include "xenidc_address.h"
+#include "xenidc_callback.h"
+
+/* These flags are private to the implementation but exposed for use in      */
+/* inline functions below.                                                   */
+
+#define XENIDC_LBR_TYPE_FLAG_VIRTUAL         0x80000000
+#define XENIDC_LBR_TYPE_FLAG_VIRTUAL_ADVANCE 0x40000000
+
+/* When used, these flags specify what kind of access is _allowed_. */
+
+#define XENIDC_LBR_ACCESS_FLAGS_READ  1
+#define XENIDC_LBR_ACCESS_FLAGS_WRITE 2
+
+typedef u32 xenidc_lbr_type;
+
+/* A local buffer reference consists of a type, a type-specific base, a      */
+/* byte_offset into the buffer referenced by the base and a byte_count of    */
+/* the size of the buffer starting at the byte_offset.                       */
+/*                                                                           */
+/* It's OK to copy xenidc_lbr structs and pass them around.  They are just a */
+/* convenient way of bundling what would otherwise be four parameters.       */
+
+struct xenidc_lbr {
+	xenidc_lbr_type type;
+	void *base;
+	xenidc_buffer_byte_count byte_offset;
+	xenidc_buffer_byte_count byte_count;
+};
+
+static inline xenidc_buffer_byte_count
+xenidc_lbr_query_byte_offset(struct xenidc_lbr *lbr)
+{
+	return lbr->byte_offset;
+}
+
+static inline xenidc_buffer_byte_count
+xenidc_lbr_query_byte_count(struct xenidc_lbr *lbr)
+{
+	return lbr->byte_count;
+}
+
+struct xenidc_lbr_concrete_class;
+struct xenidc_lbr_virtual_class;
+struct xenidc_lbr_copy_class;
+
+typedef void
+xenidc_lbr_copy_in_or_out_function(struct xenidc_lbr_concrete_class *class,
+struct xenidc_lbr *lbr, void *buffer, xenidc_buffer_byte_count byte_count,
+int out);
+
+typedef void
+xenidc_lbr_zero_function(struct xenidc_lbr_concrete_class *class,
+struct xenidc_lbr *lbr);
+
+typedef int
+xenidc_lbr_calculate_rbr_resources_function(
+struct xenidc_lbr_concrete_class *class, struct xenidc_lbr *lbr,
+struct xenidc_address *address, struct xenidc_buffer_resource_list *list);
+
+typedef struct xenidc_lbr_concrete_class **
+xenidc_lbr_create_rbr_function(struct xenidc_lbr_concrete_class *class,
+struct xenidc_lbr *lbr, struct xenidc_address *address,
+struct xenidc_buffer_resource_provider *provider, struct xenidc_rbr *rbr,
+int access_flags);
+
+typedef void
+xenidc_lbr_revoke_rbr_function(struct xenidc_lbr_concrete_class **context,
+struct xenidc_callback *callback);
+
+typedef void
+xenidc_lbr_copy_function(struct xenidc_lbr_copy_class *class,
+struct xenidc_lbr *target, struct xenidc_lbr *source,
+xenidc_buffer_byte_count byte_count);
+
+typedef struct xenidc_lbr
+xenidc_lbr_resolve_function(struct xenidc_lbr_virtual_class *class,
+struct xenidc_lbr *lbr);
+
+typedef void
+xenidc_lbr_advance_function(struct xenidc_lbr_virtual_class *class,
+struct xenidc_lbr *lbr, xenidc_buffer_byte_count byte_count);
+
+/* Concrete class for registering a new type of memory. */
+
+struct xenidc_lbr_concrete_class {
+	struct list_head link;
+	xenidc_lbr_type type;
+	xenidc_lbr_copy_in_or_out_function *copy_in_or_out;
+	xenidc_lbr_zero_function *zero;
+	xenidc_lbr_calculate_rbr_resources_function *calculate_rbr_resources;
+	xenidc_lbr_create_rbr_function *create_rbr;
+	xenidc_lbr_revoke_rbr_function *revoke_rbr;
+};
+
+/* xenidc_lbr_register_concrete_class returns a xenidc_lbr_type which the */
+/* type implementation must use when creating local buffer references for    */
+/* its clients.                                                              */
+/*                                                                           */
+/* The type implementation provides a few methods:                           */
+/*                                                                           */
+/* copy_in_or_out is used for copying into the LBR from the kernel virtual   */
+/* address space or vice-versa and is used in the fallback mechanism for     */
+/* copying between different lbr types by staging the data.                  */
+/*                                                                           */
+/* zero is optional and implements a fast zero of the buffer passed in.  The */
+/* inefficient default zero operation stages zero bytes into the buffer      */
+/* using copy_in_or_out.                                                     */
+/*                                                                           */
+/* The type implementation is required to provide a method to generate a     */
+/* remote buffer reference for remote access to the buffer.  There is        */
+/* currently no default for this though one could be implemented. The        */
+/* calculate_rbr_resources function returns a list of resources that would   */
+/* be required to create a rbr for the lbr.                                  */
+/*                                                                           */
+/* create_rbr creates an rbr for the lbr.                                    */
+/*                                                                           */
+/* revoke_rbr revokes a created rbr.                                         */
+
+xenidc_lbr_type
+xenidc_lbr_register_concrete_class(struct xenidc_lbr_concrete_class *class,
+xenidc_lbr_copy_in_or_out_function *copy_in_or_out,
+xenidc_lbr_zero_function *zero,
+xenidc_lbr_calculate_rbr_resources_function *calculate_rbr_resources,
+xenidc_lbr_create_rbr_function *create_rbr,
+xenidc_lbr_revoke_rbr_function *revoke_rbr);
+
+/* Concrete class for registering a fast-path copy function. */
+
+struct xenidc_lbr_copy_class {
+	struct list_head link;
+	xenidc_lbr_type target_type;
+	xenidc_lbr_type source_type;
+	xenidc_lbr_copy_function *copy;
+};
+
+/* xenidc_lbr_register_copy_class is used to register a function for         */
+/* performing an efficient copy between two types of local buffer references.*/
+
+void
+xenidc_lbr_register_copy_class(struct xenidc_lbr_copy_class *class,
+xenidc_lbr_type target_type, xenidc_lbr_type source_type,
+xenidc_lbr_copy_function *copy);
+
+/* Virtual class for registering a way of viewing local buffers. */
+
+struct xenidc_lbr_virtual_class {
+	struct list_head link;
+	xenidc_lbr_type type;
+	xenidc_lbr_resolve_function *resolve;
+	xenidc_lbr_advance_function *advance;
+};
+
+/* xenidc_lbr_register_virtual_class is used to register a virtual class for */
+/* a new way of viewing local buffers.          */
+/* The type implementation provides a resolve function which takes its type  */
+/* of local buffer reference and returns a local buffer reference for an     */
+/* underlying buffer type which is the maximal contiguous chunk at the front */
+/* of the reference passed as a parameter.  This is generally sufficient to  */
+/* implement all the buffer operations.  The wrapping type also needs to     */
+/* provide a virtual advance function for wrapping the buffer offset.        */
+
+xenidc_lbr_type
+xenidc_lbr_register_virtual_class(struct xenidc_lbr_virtual_class *class,
+xenidc_lbr_resolve_function *resolve,
+xenidc_lbr_advance_function *advance /* NULL for the efficient default */);
+
+/* Resolve returns a concrete lbr referencing a contiguous chunk at the head */
+/* of the lbr passed as a parameter.  This is used by the implementation of  */
+/* the bulk data transfer service.                                           */
+
+struct xenidc_lbr xenidc_lbr_resolve(struct xenidc_lbr *lbr);
+
+/* Calculate RBR resources calculates the resources required to create an    */
+/* RBR for the LBR.                                                          */
+/* This is used by the implementation of the bulk data transfer service.     */
+
+int
+xenidc_lbr_calculate_rbr_resources(struct xenidc_lbr *lbr,
+struct xenidc_address *address, struct xenidc_buffer_resource_list *list);
+
+/* Create RBR creates a RBR for the LBR by calling the appropriate type      */
+/* specific implementation.  This is called by the implementation of the     */
+/* bulk data transfer services.                                              */
+
+struct xenidc_lbr_concrete_class **
+xenidc_lbr_create_rbr(struct xenidc_lbr *lbr, struct xenidc_address *address,
+struct xenidc_buffer_resource_provider *provider, struct xenidc_rbr *rbr,
+int access_flags);
+
+/* Revoke RBR revokes a created RBR by calling the appropriate type specific */
+/* implementation.  This is called by the implementation of the bulk data    */
+/* transfer services.                                                        */
+
+void
+xenidc_lbr_revoke_rbr(struct xenidc_lbr_concrete_class **context,
+struct xenidc_callback *callback);
+
+/* Copy between an lbr and a buffer. Returns the number of bytes copied      */
+/* which is the minimum of the source and target byte_counts.                */
+
+xenidc_buffer_byte_count
+xenidc_lbr_copy_in_or_out(struct xenidc_lbr *lbr, void *buffer,
+xenidc_buffer_byte_count buffer_byte_count, int out);
+
+static inline xenidc_buffer_byte_count
+xenidc_lbr_copy_out(struct xenidc_lbr *lbr, void *target,
+xenidc_buffer_byte_count target_byte_count)
+{
+	return xenidc_lbr_copy_in_or_out(lbr, target, target_byte_count, 1);
+}
+
+static inline xenidc_buffer_byte_count
+xenidc_lbr_copy_in(struct xenidc_lbr *lbr, void *source,
+xenidc_buffer_byte_count source_byte_count)
+{
+	return xenidc_lbr_copy_in_or_out(lbr, source, source_byte_count, 0);
+}
+
+/* Zero a local buffer. */
+
+void xenidc_lbr_zero(struct xenidc_lbr *lbr);
+
+/* Copy between two local buffers. */
+
+xenidc_buffer_byte_count
+xenidc_lbr_copy(struct xenidc_lbr *target, struct xenidc_lbr *source);
+
+/* xenidc_lbr_virtual_advance is only exposed for the inline function below. */
+/* Do not call it directly.                                                  */
+
+xenidc_buffer_byte_count
+xenidc_lbr_virtual_advance(struct xenidc_lbr *lbr,
+xenidc_buffer_byte_count byte_count);
+
+/* Advance increments the offset and decrements the length by the amount     */
+/* specified which is useful to advance the reference after having copied a  */
+/* chunk of data into the start of the buffer.                               */
+/* Advance returns the remaining length.                                     */
+
+static inline xenidc_buffer_byte_count
+xenidc_lbr_advance(struct xenidc_lbr *lbr, xenidc_buffer_byte_count byte_count)
+{
+	if ((lbr->type & XENIDC_LBR_TYPE_FLAG_VIRTUAL_ADVANCE) == 0) {
+		if (lbr->byte_count > byte_count) {
+			lbr->byte_offset += byte_count;
+			lbr->byte_count -= byte_count;
+		} else {
+			lbr->byte_offset += lbr->byte_count;
+			lbr->byte_count = 0;
+		}
+		return lbr->byte_count;
+	} else {
+		return xenidc_lbr_virtual_advance(lbr, byte_count);
+	}
+}
+
+/* Truncate reduces the length of the buffer which results in a reference to */
+/* the first byte_count bytes of the buffer (or the whole buffer, whichever  */
+/* is less).                                                                 */
+/* Truncate returns the resulting length of the buffer.                      */
+
+static inline xenidc_buffer_byte_count
+xenidc_lbr_truncate(struct xenidc_lbr *lbr,
+xenidc_buffer_byte_count byte_count)
+{
+	if (lbr->byte_count > byte_count) {
+		lbr->byte_count = byte_count;
+	}
+	return lbr->byte_count;
+}
+
+/* Subrange reduces the range of the buffer by advancing the start           */
+/* byte_offset bytes and reducing the length to the minimum of byte_count    */
+/* and the remaining length.  Subrange returns the resulting length of the   */
+/* buffer.                                                                   */
+
+static inline xenidc_buffer_byte_count
+xenidc_lbr_subrange(struct xenidc_lbr *lbr,
+xenidc_buffer_byte_count byte_offset, xenidc_buffer_byte_count byte_count)
+{
+	(void)xenidc_lbr_advance(lbr, byte_offset);
+	return xenidc_lbr_truncate(lbr, byte_count);
+}
+
+#endif
diff -r cf3c717101a8 -r a64ebf373f9c linux-2.6-xen-sparse/include/asm-xen/xenidc_remote_buffer_reference.h
--- /dev/null	Wed Nov 23 15:13:22 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenidc_remote_buffer_reference.h	Wed Nov 23 15:38:27 2005
@@ -0,0 +1,147 @@
+/*****************************************************************************/
+/* Xen inter-domain communication remote buffer references.                  */
+/*                                                                           */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation                      */
+/*                                                                           */
+/* 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                   */
+/*                                                                           */
+/*****************************************************************************/
+/*                                                                           */
+/* A xenidc_rbr object is sent on the wire between two domains to allow the  */
+/* receiving domain to access a buffer belonging to the sending domain.      */
+/*                                                                           */
+/* In general, there may be a number of different kinds of buffers and ways  */
+/* of describing them.  This interface provides a default 'NULL'             */
+/* implementation of remote buffer references (for zero length buffers) and  */
+/* a mechanism for installing new types of remote buffer reference for other */
+/* kinds of buffers or buffers described in different ways.                  */
+
+#ifndef __ASM_XEN_XENIDC_RBR_H__
+#define __ASM_XEN_XENIDC_RBR_H__
+
+#include <linux/list.h>
+#include <asm/types.h>
+#include <asm-xen/xenidc_buffer_resource_provider.h>
+#include "xenidc_address.h"
+
+typedef u32 xenidc_rbr_type;
+
+#define XENIDC_RBR_TYPE_NULL 0
+
+#define XENIDC_RBR_ACCESS_FLAGS_READ  1
+#define XENIDC_RBR_ACCESS_FLAGS_WRITE 2
+
+/* The different types of remote buffer reference must all use the same      */
+/* xenidc_rbr structure which provides 32 bytes of space for type-specific   */
+/* use.                                                                      */
+
+#define XENIDC_RBR_BASE_BYTE_COUNT 32
+
+typedef u32 xenidc_buffer_byte_count;
+
+struct xenidc_rbr {
+	xenidc_rbr_type type;
+	u32             reserved;
+	struct {
+		u64 base_space[ XENIDC_RBR_BASE_BYTE_COUNT / 8 ];
+	} base;
+	xenidc_buffer_byte_count byte_offset;
+	xenidc_buffer_byte_count byte_count;
+};
+
+/* xenidc_rbr_query_byte_count returns the size of the buffer in bytes.      */
+
+static inline xenidc_buffer_byte_count
+xenidc_rbr_query_byte_count(struct xenidc_rbr *rbr)
+{
+	return rbr->byte_count;
+}
+
+struct xenidc_rbr_mappable_class;
+
+typedef int
+xenidc_rbr_calculate_map_resources_function(
+struct xenidc_rbr_mappable_class *class, struct xenidc_rbr *rbr,
+struct xenidc_address *address, struct xenidc_buffer_resource_list *list);
+
+typedef struct xenidc_rbr_mappable_class **
+xenidc_rbr_map_function(struct xenidc_rbr_mappable_class *class,
+struct xenidc_rbr *rbr, struct xenidc_address *address,
+struct xenidc_buffer_resource_provider *provider, void **mapping,
+int access_flags);
+
+typedef void
+xenidc_rbr_unmap_function(struct xenidc_rbr_mappable_class **context);
+
+/* If a client might attempt to map a remote buffer reference into the local */
+/* address space (determined by design) then the remote buffer reference     */
+/* type implementation must register the methods required to perform the     */
+/* mapping.                                                                  */
+
+/* The type implementation must provide a xenidc_rbr_mappable_class.         */
+
+struct xenidc_rbr_mappable_class {
+	struct list_head link;
+	xenidc_rbr_type type;
+	xenidc_rbr_calculate_map_resources_function *calculate_map_resources;
+	xenidc_rbr_map_function *map;
+	xenidc_rbr_unmap_function *unmap;
+};
+
+/* The type implementation calls the register function with its class        */
+/* structure, type, calculate_map_resources, map and unmap functions.        */
+
+void
+xenidc_rbr_register_buffer_mappable_class(
+struct xenidc_rbr_mappable_class *class, xenidc_rbr_type type,
+xenidc_rbr_calculate_map_resources_function *calculate_map_resources,
+xenidc_rbr_map_function *map, xenidc_rbr_unmap_function *unmap);
+
+/* xenidc_rbr_calculate_map_resources is called to calculate what buffer     */
+/* resources would be required to map the rbr into the local address space.  */
+/* This is called by the generic code that does mapping on behalf of clients */
+/* and resolves to the type specific implementation.                         */
+
+int xenidc_rbr_calculate_map_resources(struct xenidc_rbr *rbr,
+struct xenidc_address *address, struct xenidc_buffer_resource_list *list);
+
+/* xenidc_rbr_map is called to map a rbr into the local address space.  This */
+/* is called by the generic code that does mapping on behalf of the clients  */
+/* and resolves to the type specific implementation.                         */
+/*                                                                           */
+/* FIXME: This is a synchronous call. A network transparent RBR              */
+/* implementation may need to stage the data into a buffer during this call  */
+/* so would require this to be an asynchronous call with a callback.  Since  */
+/* the damage here is contained within the generic code and won't impact the */
+/* drivers we can add this feature later if required.                        */
+
+struct xenidc_rbr_mappable_class **
+xenidc_rbr_map(struct xenidc_rbr *rbr,struct xenidc_address *address,
+struct xenidc_buffer_resource_provider *provider, void **mapping,
+int access_flags);
+
+/* xenidc_rbr_unmap is called to unmap an rbr from the local address space.  */
+/* This is called by the generic code that does unmapping on behalf of the   */
+/* clients and resolves to the type specific implementation.                 */
+/*                                                                           */
+/* FIXME: This is a synchronous call. A network transparent RBR              */
+/* implementation may need to stage the data from a buffer during this call  */
+/* so would require this to be an asynchronous call with a callback.  Since  */
+/* the damage here is contained within the generic code and won't impact the */
+/* drivers we can add this feature later if required.                        */
+
+void xenidc_rbr_unmap(struct xenidc_rbr_mappable_class **context);
+
+#endif

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-11-23 16:12 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-11-23 16:12 [PATCH][3/17] REV 2 USB virt 2.6 split driver---xenidc buffer references harry

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.