All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH][1/17] REV 2 USB virt 2.6 split driver---xenidc platform
@ 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: 464 bytes --]

This patch implements some platform facilities used by the xenidc
transport which is in turn used by the USB driver:

o - A callback object for asynchronous completion of requests submitted
to services.
o - A work item object for scheduling tasks which builds on the native
linux work queues.
o - Some simple trace macros for the xenidc code.
o - An error type which is supposed to be platform independent.

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


[-- Attachment #2: p1-xenidc-platform.patch --]
[-- Type: text/x-patch, Size: 29704 bytes --]

diff -r 1d754a4ad350 -r 14b148d759ae linux-2.6-xen-sparse/arch/xen/Kconfig
--- a/linux-2.6-xen-sparse/arch/xen/Kconfig	Wed Nov 23 11:32:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/Kconfig	Wed Nov 23 15:08:28 2005
@@ -38,6 +38,14 @@
 	  (e.g., hard drives, network cards). This allows you to configure
 	  such devices and also includes some low-level support that is
 	  otherwise not compiled into the kernel.
+
+config XEN_IDC_TRACE
+	bool "Inter-domain communication code tracing"
+	default n
+	help
+	  This option causes the IDC code to output a continual trace of its
+          activity.
+	  Say N here unless you are trying to debug this code.
 
 config XEN_BLKDEV_BACKEND
 	bool "Block-device backend driver"
diff -r 1d754a4ad350 -r 14b148d759ae linux-2.6-xen-sparse/drivers/xen/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/Makefile	Wed Nov 23 11:32:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/Makefile	Wed Nov 23 15:08:28 2005
@@ -7,6 +7,7 @@
 obj-y	+= balloon/
 obj-y	+= privcmd/
 obj-y	+= xenbus/
+obj-y	+= xenidc/
 
 obj-$(CONFIG_XEN_BLKDEV_BACKEND)	+= blkback/
 obj-$(CONFIG_XEN_NETDEV_BACKEND)	+= netback/
diff -r 1d754a4ad350 -r 14b148d759ae linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile
--- /dev/null	Wed Nov 23 11:32:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile	Wed Nov 23 15:08:28 2005
@@ -0,0 +1,5 @@
+obj-y += xenidc.o
+
+xenidc-objs =
+xenidc-objs += xenidc_callback.o
+xenidc-objs += xenidc_work.o
diff -r 1d754a4ad350 -r 14b148d759ae linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_callback.c
--- /dev/null	Wed Nov 23 11:32:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_callback.c	Wed Nov 23 15:08:28 2005
@@ -0,0 +1,46 @@
+/*****************************************************************************/
+/* A callback object for use in scheduling completion of asynchronous        */
+/* requests.                                                                 */
+/*                                                                           */
+/* 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/module.h>
+#include "xenidc_callback.h"
+
+void xenidc_callback_serialiser_function(void *context)
+{
+	struct xenidc_callback_serialiser *serialiser =
+				(struct xenidc_callback_serialiser *)context;
+	unsigned long flags;
+
+	spin_lock_irqsave(&serialiser->lock, flags);
+	while (!list_empty(&serialiser->list) && !serialiser->running) {
+		struct xenidc_callback *callback =
+				xenidc_callback_link_to(serialiser->list.next);
+		list_del_init(xenidc_callback_to_link(callback));
+		serialiser->running = 1;
+		spin_unlock_irqrestore(&serialiser->lock, flags);
+		xenidc_callback_complete_synchronously(callback);
+		spin_lock_irqsave(&serialiser->lock, flags);
+		serialiser->running = 0;
+	}
+	spin_unlock_irqrestore(&serialiser->lock, flags);
+}
+
+EXPORT_SYMBOL(xenidc_callback_serialiser_function);
diff -r 1d754a4ad350 -r 14b148d759ae linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_trace.h
--- /dev/null	Wed Nov 23 11:32:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_trace.h	Wed Nov 23 15:08:28 2005
@@ -0,0 +1,45 @@
+/*****************************************************************************/
+/* Simple trace macros.                                                      */
+/*                                                                           */
+/* 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                   */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef XENIDC_TRACE_H
+#define XENIDC_TRACE_H
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+
+#if (defined(CONFIG_XEN_IDC_TRACE) || defined(XEN_IDC_TRACE))
+
+#define trace_info(format, ...) \
+printk(KERN_INFO "xenidc %s: " format "\n", __FUNCTION__, ## __VA_ARGS__)
+#define trace() trace_info( "" )
+/* The traceonly macro is used to enclose code which should only be compiled */
+/* in when tracing is enabled.                                               */
+#define traceonly(S) S
+
+#else
+
+#define trace_info(format, ...)
+#define trace()
+#define traceonly(S)
+
+#endif
+
+#endif
diff -r 1d754a4ad350 -r 14b148d759ae linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_work.c
--- /dev/null	Wed Nov 23 11:32:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_work.c	Wed Nov 23 15:08:28 2005
@@ -0,0 +1,84 @@
+/*****************************************************************************/
+/* Enhanced work queue service                                               */
+/* 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/module.h>
+#include "xenidc_work.h"
+
+static void xenidc_work_function(void *ignored);
+
+DEFINE_SPINLOCK(xenidc_work_list_lock);
+LIST_HEAD(xenidc_work_list);
+DECLARE_WORK(xenidc_work_work, xenidc_work_function, NULL);
+DECLARE_WAIT_QUEUE_HEAD(xenidc_work_waitqueue);
+LIST_HEAD(xenidc_work_condition);
+
+void xenidc_work_wake_up(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&xenidc_work_list_lock, flags);
+	while (!list_empty(&xenidc_work_condition))
+		list_del_init(xenidc_work_condition.next);
+	spin_unlock_irqrestore(&xenidc_work_list_lock, flags);
+	wake_up(&xenidc_work_waitqueue);
+}
+
+int xenidc_work_schedule(struct xenidc_work *work)
+{
+	int scheduled = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&xenidc_work_list_lock, flags);
+	if (list_empty(&work->link)) {
+		list_add_tail(&work->link, &xenidc_work_list);
+		scheduled = 1;
+	}
+	spin_unlock_irqrestore(&xenidc_work_list_lock, flags);
+
+	if (scheduled) {
+		xenidc_work_wake_up();
+		schedule_work(&xenidc_work_work);
+	}
+
+	return scheduled;
+}
+
+static void xenidc_work_function(void *ignored)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&xenidc_work_list_lock, flags);
+	while (!list_empty(&xenidc_work_list)) {
+		struct xenidc_work *work = list_entry(xenidc_work_list.next,
+						      struct xenidc_work,
+						      link);
+		list_del_init(&work->link);
+		spin_unlock_irqrestore(&xenidc_work_list_lock, flags);
+		xenidc_work_perform_synchronously(work);
+		spin_lock_irqsave(&xenidc_work_list_lock, flags);
+	}
+	spin_unlock_irqrestore(&xenidc_work_list_lock, flags);
+}
+
+EXPORT_SYMBOL(xenidc_work_schedule);
+EXPORT_SYMBOL(xenidc_work_list);
+EXPORT_SYMBOL(xenidc_work_condition);
+EXPORT_SYMBOL(xenidc_work_waitqueue);
+EXPORT_SYMBOL(xenidc_work_wake_up);
diff -r 1d754a4ad350 -r 14b148d759ae linux-2.6-xen-sparse/include/asm-xen/xenidc_callback.h
--- /dev/null	Wed Nov 23 11:32:44 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenidc_callback.h	Wed Nov 23 15:08:28 2005
@@ -0,0 +1,152 @@
+/*****************************************************************************/
+/* A callback object for use in scheduling completion of asynchronous        */
+/* requests.                                                                 */
+/*                                                                           */
+/* 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                   */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef XENIDC_CALLBACK_H
+#define XENIDC_CALLBACK_H
+
+#include <linux/spinlock.h>
+#include "xenidc_error.h"
+#include "xenidc_work.h"
+
+/* Service parameter blocks contain callbacks for asynchronous completions.  */
+
+struct xenidc_callback {
+	struct xenidc_work work;
+	xenidc_error error;
+};
+
+#define XENIDC_CALLBACK_LINK work.XENIDC_WORK_LINK
+
+/* Client of service initialises callback with its callback function.        */
+
+typedef void xenidc_callback_function(struct xenidc_callback *callback);
+
+static inline void
+xenidc_callback_init(struct xenidc_callback *callback,
+xenidc_callback_function *function)
+{
+	xenidc_work_init(&callback->work, (void (*)(void *))function,
+								callback);
+	callback->error = XENIDC_ERROR_SUCCESS;
+}
+
+/* Client may use link whilst it owns parameter block. Service may use link  */
+/* whilst it owns parameter block.  Link is reserved whilst callback is      */
+/* scheduled for completion.                                                 */
+
+static inline struct list_head *
+xenidc_callback_to_link(struct xenidc_callback *callback)
+{
+	return xenidc_work_to_link(&callback->work);
+}
+
+/* Cast back from contained link of callback to callback. */
+
+static inline struct xenidc_callback *
+xenidc_callback_link_to(struct list_head *link)
+{
+	return container_of(xenidc_work_link_to(link), struct xenidc_callback,
+									work);
+}
+
+/* Service which completes requests concurrently may call                    */
+/* xenidc_callback_complete or xenidc_callback_success to complete the       */
+/* callback.                                                                 */
+
+static inline void
+xenidc_callback_complete(struct xenidc_callback *callback, xenidc_error error)
+{
+	callback->error = error;
+	xenidc_work_schedule(&callback->work);
+}
+
+static inline void
+xenidc_callback_success(struct xenidc_callback *callback)
+{
+	xenidc_callback_complete(callback, 0);
+}
+
+/* These functions used by serialiser below. */
+
+static inline void
+xenidc_callback_set_error(struct xenidc_callback *callback,
+xenidc_error error)
+{
+	callback->error = error;
+}
+
+static inline void
+xenidc_callback_complete_synchronously(struct xenidc_callback *callback)
+{
+	xenidc_work_perform_synchronously(&callback->work);
+}
+
+/* When callback completes, client may call xenidc_callback_query_error to   */
+/* get the error code.                                                       */
+
+static inline xenidc_error
+xenidc_callback_query_error(struct xenidc_callback *callback)
+{
+	return callback->error;
+}
+
+/* Services which must serialise completions to preserve submission order    */
+/* can use one of these.                                                     */
+
+struct xenidc_callback_serialiser {
+	spinlock_t lock;
+	struct list_head list;
+	struct xenidc_work work;
+	int running;
+};
+
+void xenidc_callback_serialiser_function(void *context);
+
+#define XENIDC_CALLBACK_SERIALISER_INIT( name ) {			\
+	.lock = SPIN_LOCK_UNLOCKED,					\
+	.list = LIST_HEAD_INIT( name.list ),				\
+	.work = XENIDC_WORK_INIT					\
+		( name.work, xenidc_callback_serialiser_function, &name ),\
+	.running = 0							\
+}
+
+#define XENIDC_CALLBACK_SERIALISER( name ) \
+struct xenidc_callback_serialiser name =   \
+XENIDC_CALLBACK_SERIALISER_INIT( name )
+
+/* The service completes the callback to the serialiser which serialises the */
+/* completions to the client, performing them in submission order.           */
+
+static inline void
+xenidc_callback_serialiser_complete_callback(
+struct xenidc_callback_serialiser *serialiser,
+struct xenidc_callback *callback, xenidc_error error)
+{
+	unsigned long flags;
+	xenidc_callback_set_error(callback, error);
+	spin_lock_irqsave(&serialiser->lock, flags);
+	list_add_tail(xenidc_callback_to_link(callback), &serialiser->list);
+	spin_unlock_irqrestore(&serialiser->lock, flags);
+	xenidc_work_schedule(&serialiser->work);
+}
+
+#endif
diff -r 1d754a4ad350 -r 14b148d759ae linux-2.6-xen-sparse/include/asm-xen/xenidc_error.h
--- /dev/null	Wed Nov 23 11:32:44 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenidc_error.h	Wed Nov 23 15:08:28 2005
@@ -0,0 +1,121 @@
+/*****************************************************************************/
+/* The xenidc_error type is supposed to be safe for use on the wire between  */
+/* different operating systems which may use different values for the posix  */
+/* error types or may not even use the posix error types at all.             */
+/*                                                                           */
+/* 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                   */
+/*                                                                           */
+/*****************************************************************************/
+/*                                                                           */
+/* Ideally, we'd simply define all the error values we needed here and map   */
+/* the local error values to those and back again.  In practice, we are      */
+/* building on top of another operating system which has its own set of      */
+/* error values and driver interfaces which don't define precisely which     */
+/* ones may be returned under what conditions.                               */
+/*                                                                           */
+/* Some error return values are significant for the operation of the         */
+/* inter-domain protocols and some are not.  In general, the correct mapping */
+/* of protocol-significant error values between operating systems may be a   */
+/* function of the protocol.                                                 */
+/*                                                                           */
+/* The strategy adopted here is to allow individual protocols to extract the */
+/* error return values which are significant to them and map them into a     */
+/* range of error values reserved for protocol use.  Any values not          */
+/* specifically significant to a protocol are handled by the fallback        */
+/* mapping code in this file.                                                */
+/*                                                                           */
+/* This makes it possible to construct a mapping as a function of protocol   */
+/* and allows us to avoid discarding potentially useful error code           */
+/* information in the general case.                                          */
+/*                                                                           */
+/* For the fallback case of any error codes we are not specifically          */
+/* interested in for a protocol-specific purpose we use the linux definition */
+/* of the posix error values.  Other operating systems will need their own   */
+/* equivalent of this file to map their error values to and from these.      */
+
+#ifndef __ASM_XEN_XENIDC_ERROR_H__
+#define __ASM_XEN_XENIDC_ERROR_H__
+
+#include <linux/errno.h>
+#include <asm/types.h>
+
+typedef s32 xenidc_error;
+
+/* The error values we single out with some OS independent, protocol         */
+/* specific meaning are all positive.  The negative ones are all potentially */
+/* OS specific and might not have an exact representation in the local OS.   */
+/* Assuming we have singled out the right ones in the protocol specific code */
+/* this shouldn't matter.                                                    */
+
+/* The first few error numbers are reserved for success and transport errors */
+/* which are common to all IDC protocols.                                    */
+
+#define XENIDC_ERROR_SUCCESS                   (xenidc_error)0
+#define XENIDC_ERROR_FAILURE                   (xenidc_error)1
+#define XENIDC_ERROR_DISCONNECT                (xenidc_error)2
+/* Unexpected transaction/transaction in wrong sequence, underlength etc: */
+#define XENIDC_ERROR_INVALID_PROTOCOL          (xenidc_error)3
+/* Parameter value wrong: */
+#define XENIDC_ERROR_INVALID_PARAMETER         (xenidc_error)4
+/* Something about a request exceeded a hard-coded limit: */
+#define XENIDC_ERROR_TOO_BIG                   (xenidc_error)5
+
+/* Protocols can define their own set of protocol specific errors starting   */
+/* at this one.  The driver code on either side must translate between the   */
+/* local OS specific error codes and the protocol specific error codes.      */
+
+#define XENIDC_ERROR_PROTOCOL_SPECIFIC_FIRST   (xenidc_error)1024
+
+/* These functions map between the wire error type and the local error type. */
+
+static inline xenidc_error xenidc_error_map_local_to(int error)
+{
+	switch (error) {
+	case 0:
+		return XENIDC_ERROR_SUCCESS;
+	case -ENOTCONN:
+		return XENIDC_ERROR_DISCONNECT;
+	case -EPROTO:
+		return XENIDC_ERROR_INVALID_PROTOCOL;
+	case -EINVAL:
+		return XENIDC_ERROR_INVALID_PARAMETER;
+	case -E2BIG:
+		return XENIDC_ERROR_TOO_BIG;
+	default:
+		return (xenidc_error)error;
+	}
+}
+
+static inline int xenidc_error_map_to_local(xenidc_error error)
+{
+	switch (error) {
+	case XENIDC_ERROR_SUCCESS:
+		return 0;
+	case XENIDC_ERROR_DISCONNECT:
+		return -ENOTCONN;
+	case XENIDC_ERROR_INVALID_PROTOCOL:
+		return -EPROTO;
+	case XENIDC_ERROR_INVALID_PARAMETER:
+		return -EINVAL;
+	case XENIDC_ERROR_TOO_BIG:
+		return -E2BIG;
+	default:
+		return (int)error;
+	}
+}
+
+#endif
diff -r 1d754a4ad350 -r 14b148d759ae linux-2.6-xen-sparse/include/asm-xen/xenidc_work.h
--- /dev/null	Wed Nov 23 11:32:44 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenidc_work.h	Wed Nov 23 15:08:28 2005
@@ -0,0 +1,153 @@
+/*****************************************************************************/
+/* Enhanced work queue service which allows work items to wait for           */
+/* conditions met by other work items.                                       */
+/*                                                                           */
+/* 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                   */
+/*                                                                           */
+/*****************************************************************************/
+
+/* This work queue service is a lot like the linux work queue service except */
+/* that it provides the interface xenidc_work_until which allows the client  */
+/* to wait for a condition to be met even when the client is executing on a  */
+/* work thread and the condition will only be satisfied by execution of      */
+/* another work item.                                                        */
+/*                                                                           */
+/* The other significant difference is that xenidc_work work items are run   */
+/* by multiple threads (threads waiting in xenidc_work_until() run           */
+/* work_items until their condition is met) so it's possible for a work item */
+/* to be executed multiple times concurrently and clients must use locking   */
+/* to protect against this where necessary.                                  */
+
+#ifndef XENIDC_WORK_H
+#define XENIDC_WORK_H
+
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+
+/* Clients allocate xenidc_work work items to use the service. */
+
+struct xenidc_work {
+	struct list_head link;
+	void (*function) (void *context);
+	void *context;
+};
+
+/* The xenidc_work object contains a link for use by the service whist the   */
+/* work item is scheduled. The link may be used by the client whilst the     */
+/* work item is not scheduled.  The link is initialised by the init function */
+/* and must be left initialised if used by the client.                       */
+
+#define XENIDC_WORK_LINK link
+
+/* Macro for initialisation of static xenidc_work objects. */
+
+#define XENIDC_WORK_INIT( name, fn, ctx ) \
+{ .link = LIST_HEAD_INIT( name.link ), .function = fn, .context = ctx }
+
+/* Macro to declare a static xenidc_work object. */
+
+#define XENIDC_WORK( name, fn, ctx ) \
+struct xenidc_work name = XENIDC_WORK_INIT( name, fn, ctx )
+
+static inline void
+xenidc_work_init(struct xenidc_work *work, void (*function) (void *context),
+void *context)
+{
+	INIT_LIST_HEAD(&work->link);
+	work->function = function;
+	work->context = context;
+}
+
+/* Cast xenidc_work object to contained link. */
+
+static inline struct list_head *xenidc_work_to_link(struct xenidc_work *work)
+{
+	return &work->link;
+}
+
+/* Cast contained link of xenidc_work object back to xenidc_work object. */
+
+static inline struct xenidc_work *xenidc_work_link_to(struct list_head *link)
+{
+	return container_of(link, struct xenidc_work, link);
+}
+
+/* Schedule a xenidc_work object for later execution.  It is legal to call   */
+/* this even if the object is already scheduled. Returns 1 if scheduled this */
+/* time or 0 if already scheduled.                                           */
+
+int xenidc_work_schedule(struct xenidc_work *work);
+
+/* Perform the task represented by the xenidc_work object synchronously on   */
+/* the callers thread.                                                       */
+
+static inline void xenidc_work_perform_synchronously(struct xenidc_work *work)
+{
+	work->function(work->context);
+}
+
+/* Don't use any of these, they're just exposed for the macro below. */
+
+extern spinlock_t        xenidc_work_list_lock;
+extern struct list_head  xenidc_work_list;
+extern wait_queue_head_t xenidc_work_waitqueue;
+extern struct list_head  xenidc_work_condition;
+
+/* Wait for a condition to be met. This works whether or not you call it     */
+/* from a work item and works even when the condition will only be satisfied */
+/* by another work item.                                                     */
+
+#define xenidc_work_until( condition )					      \
+do {									      \
+	unsigned long flags;						      \
+									      \
+	spin_lock_irqsave(&xenidc_work_list_lock, flags);		      \
+	for (;;) {							      \
+		struct list_head link;					      \
+									      \
+		while (!list_empty(&xenidc_work_list) && !(condition)) {      \
+			struct xenidc_work *work;			      \
+			work = list_entry(xenidc_work_list.next,	      \
+							xenidc_work, link);   \
+			list_del_init(&work->link);			      \
+			spin_unlock_irqrestore(&xenidc_work_list_lock, flags);\
+			xenidc_work_perform_synchronously(work);	      \
+			spin_lock_irqsave(&xenidc_work_list_lock, flags);     \
+		}							      \
+									      \
+		if (condition)						      \
+			break;						      \
+									      \
+		INIT_LIST_HEAD(&link);					      \
+		list_add_tail(&link, &xenidc_work_condition);		      \
+		spin_unlock_irqrestore(&xenidc_work_list_lock, flags);	      \
+		wait_event(xenidc_work_waitqueue, list_empty(&link));	      \
+		spin_lock_irqsave(&xenidc_work_list_lock, flags);	      \
+	}								      \
+	spin_unlock_irqrestore(&xenidc_work_list_lock, flags);		      \
+}									      \
+while (0)
+
+/* When you satisfy a condition, you should call this to kick any threads    */
+/* waiting on the condition.                                                 */
+
+void xenidc_work_wake_up(void);
+
+#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][1/17] REV 2 USB virt 2.6 split driver---xenidc platform 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.