* [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.