svn commit: r187750 - in user/thompsa/usb/sys/dev/usb2: controller core

Andrew Thompson thompsa at FreeBSD.org
Mon Jan 26 17:21:12 PST 2009


Author: thompsa
Date: Tue Jan 27 01:21:11 2009
New Revision: 187750
URL: http://svn.freebsd.org/changeset/base/187750

Log:
  Change over to using taskqueue(9) instead of hand rolled threads and the
  config_td system.

Deleted:
  user/thompsa/usb/sys/dev/usb2/core/usb2_config_td.c
  user/thompsa/usb/sys/dev/usb2/core/usb2_config_td.h
Modified:
  user/thompsa/usb/sys/dev/usb2/controller/usb2_bus.h
  user/thompsa/usb/sys/dev/usb2/controller/usb2_controller.c
  user/thompsa/usb/sys/dev/usb2/core/usb2_device.c
  user/thompsa/usb/sys/dev/usb2/core/usb2_device.h
  user/thompsa/usb/sys/dev/usb2/core/usb2_hub.c
  user/thompsa/usb/sys/dev/usb2/core/usb2_process.c
  user/thompsa/usb/sys/dev/usb2/core/usb2_process.h
  user/thompsa/usb/sys/dev/usb2/core/usb2_transfer.c
  user/thompsa/usb/sys/dev/usb2/core/usb2_transfer.h

Modified: user/thompsa/usb/sys/dev/usb2/controller/usb2_bus.h
==============================================================================
--- user/thompsa/usb/sys/dev/usb2/controller/usb2_bus.h	Tue Jan 27 00:31:25 2009	(r187749)
+++ user/thompsa/usb/sys/dev/usb2/controller/usb2_bus.h	Tue Jan 27 01:21:11 2009	(r187750)
@@ -28,16 +28,6 @@
 #define	_USB2_BUS_H_
 
 /*
- * The following structure defines the USB explore message sent to the
- * USB explore process.
- */
-
-struct usb2_bus_msg {
-	struct usb2_proc_msg hdr;
-	struct usb2_bus *bus;
-};
-
-/*
  * The following structure defines the USB statistics structure.
  */
 struct usb2_bus_stat {
@@ -51,23 +41,14 @@ struct usb2_bus_stat {
 struct usb2_bus {
 	struct usb2_bus_stat stats_err;
 	struct usb2_bus_stat stats_ok;
+	struct usb2_process done_proc;
 	struct usb2_process explore_proc;
-	struct usb2_process roothub_proc;
-	/*
-	 * There are two callback processes. One for Giant locked
-	 * callbacks. One for non-Giant locked callbacks. This should
-	 * avoid congestion and reduce response time in most cases.
-	 */
-	struct usb2_process giant_callback_proc;
-	struct usb2_process non_giant_callback_proc;
-	struct usb2_bus_msg explore_msg[2];
-	struct usb2_bus_msg detach_msg[2];
-	struct usb2_bus_msg attach_msg[2];
-	struct usb2_bus_msg roothub_msg[2];
-	/*
-	 * This mutex protects the USB hardware:
-	 */
-	struct mtx bus_mtx;
+	struct usb2_task explore_task;
+	struct usb2_task attach_task;
+	struct usb2_task detach_task;
+	struct usb2_task roothub_task;
+	struct mtx bus_mtx;			/* This mutex protects the USB
+					 * hardware */
 	struct usb2_perm perm;
 	struct usb2_xfer_queue intr_q;
 	struct usb2_callout power_wdog;	/* power management */

Modified: user/thompsa/usb/sys/dev/usb2/controller/usb2_controller.c
==============================================================================
--- user/thompsa/usb/sys/dev/usb2/controller/usb2_controller.c	Tue Jan 27 00:31:25 2009	(r187749)
+++ user/thompsa/usb/sys/dev/usb2/controller/usb2_controller.c	Tue Jan 27 01:21:11 2009	(r187750)
@@ -43,6 +43,10 @@
 #include <dev/usb2/controller/usb2_bus.h>
 
 /* function prototypes */
+static usb2_task_fn_t usb2_bus_explore;
+static usb2_task_fn_t usb2_bus_attach;
+static usb2_task_fn_t usb2_bus_detach;
+static usb2_task_fn_t usb2_bus_roothub;
 
 static device_probe_t usb2_probe;
 static device_attach_t usb2_attach;
@@ -59,7 +63,6 @@ static void	usb2_bus_mem_alloc_all_cb(st
 static void	usb2_bus_mem_free_all_cb(struct usb2_bus *,
 		    struct usb2_page_cache *, struct usb2_page *, uint32_t,
 		    uint32_t);
-static void	usb2_bus_roothub(struct usb2_proc_msg *pm);
 
 /* static variables */
 
@@ -153,31 +156,13 @@ usb2_detach(device_t dev)
 	usb2_callout_drain(&bus->power_wdog);
 
 	/* Let the USB explore process detach all devices. */
-
-	USB_BUS_LOCK(bus);
-	if (usb2_proc_msignal(&bus->explore_proc,
-	    &bus->detach_msg[0], &bus->detach_msg[1])) {
-		/* ignore */
-	}
+	usb2_proc_enqueue(&bus->explore_proc, &bus->explore_task);
 	/* Wait for detach to complete */
+	usb2_proc_drain(&bus->explore_proc, &bus->explore_task);
 
-	usb2_proc_mwait(&bus->explore_proc,
-	    &bus->detach_msg[0], &bus->detach_msg[1]);
-
-	USB_BUS_UNLOCK(bus);
-
-	/* Get rid of USB callback processes */
-
-	usb2_proc_unsetup(&bus->giant_callback_proc);
-	usb2_proc_unsetup(&bus->non_giant_callback_proc);
-
-	/* Get rid of USB roothub process */
-
-	usb2_proc_unsetup(&bus->roothub_proc);
-
-	/* Get rid of USB explore process */
-
-	usb2_proc_unsetup(&bus->explore_proc);
+	/* Get rid of USB processes */
+	usb2_proc_free(&bus->done_proc);
+	usb2_proc_free(&bus->explore_proc);
 
 	return (0);
 }
@@ -188,14 +173,14 @@ usb2_detach(device_t dev)
  * This function is used to explore the device tree from the root.
  *------------------------------------------------------------------------*/
 static void
-usb2_bus_explore(struct usb2_proc_msg *pm)
+usb2_bus_explore(void *context, struct usb2_task *task)
 {
-	struct usb2_bus *bus;
+	struct usb2_bus *bus = context;
 	struct usb2_device *udev;
 
-	bus = ((struct usb2_bus_msg *)pm)->bus;
 	udev = bus->devices[USB_ROOT_HUB_ADDR];
 
+	USB_BUS_LOCK(bus);
 	if (udev && udev->hub) {
 
 		if (bus->do_probe) {
@@ -208,8 +193,6 @@ usb2_bus_explore(struct usb2_proc_msg *p
 		}
 		USB_BUS_UNLOCK(bus);
 
-		mtx_lock(&Giant);
-
 		/*
 		 * First update the USB power state!
 		 */
@@ -219,12 +202,12 @@ usb2_bus_explore(struct usb2_proc_msg *p
 		 * Explore the Root USB HUB. This call can sleep,
 		 * exiting Giant, which is actually Giant.
 		 */
+		mtx_lock(&Giant);
 		(udev->hub->explore) (udev);
-
 		mtx_unlock(&Giant);
-
-		USB_BUS_LOCK(bus);
+		return;
 	}
+	USB_BUS_UNLOCK(bus);
 }
 
 /*------------------------------------------------------------------------*
@@ -233,13 +216,13 @@ usb2_bus_explore(struct usb2_proc_msg *p
  * This function is used to detach the device tree from the root.
  *------------------------------------------------------------------------*/
 static void
-usb2_bus_detach(struct usb2_proc_msg *pm)
+usb2_bus_detach(void *context, struct usb2_task *task)
 {
-	struct usb2_bus *bus;
+	struct usb2_bus *bus = context;
 	struct usb2_device *udev;
 	device_t dev;
 
-	bus = ((struct usb2_bus_msg *)pm)->bus;
+	USB_BUS_LOCK(bus);
 	udev = bus->devices[USB_ROOT_HUB_ADDR];
 	dev = bus->bdev;
 	/* clear the softc */
@@ -262,6 +245,7 @@ usb2_bus_detach(struct usb2_proc_msg *pm
 	USB_BUS_LOCK(bus);
 	/* clear bdev variable last */
 	bus->bdev = NULL;
+	USB_BUS_UNLOCK(bus);
 }
 
 static void
@@ -287,15 +271,14 @@ usb2_power_wdog(void *arg)
  * This function attaches USB in context of the explore thread.
  *------------------------------------------------------------------------*/
 static void
-usb2_bus_attach(struct usb2_proc_msg *pm)
+usb2_bus_attach(void *context, struct usb2_task *task)
 {
-	struct usb2_bus *bus;
+	struct usb2_bus *bus = context;
 	struct usb2_device *child;
 	device_t dev;
 	usb2_error_t err;
 	uint8_t speed;
 
-	bus = ((struct usb2_bus_msg *)pm)->bus;
 	dev = bus->bdev;
 
 	DPRINTF("\n");
@@ -326,11 +309,9 @@ usb2_bus_attach(struct usb2_proc_msg *pm
 		return;
 	}
 
-	USB_BUS_UNLOCK(bus);
 	mtx_lock(&Giant);		/* XXX not required by USB */
 
 	/* Allocate the Root USB device */
-
 	child = usb2_alloc_device(bus->bdev, bus, NULL, 0, 0, 1,
 	    speed, USB_MODE_HOST);
 	if (child) {
@@ -344,9 +325,7 @@ usb2_bus_attach(struct usb2_proc_msg *pm
 	} else {
 		err = USB_ERR_NOMEM;
 	}
-
 	mtx_unlock(&Giant);
-	USB_BUS_LOCK(bus);
 
 	if (err) {
 		device_printf(bus->bdev, "Root HUB problem, error=%s\n",
@@ -357,10 +336,8 @@ usb2_bus_attach(struct usb2_proc_msg *pm
 	device_set_softc(dev, bus);
 
 	/* start watchdog - this function will unlock the BUS lock ! */
-	usb2_power_wdog(bus);
-
-	/* need to return locked */
 	USB_BUS_LOCK(bus);
+	usb2_power_wdog(bus);
 }
 
 /*------------------------------------------------------------------------*
@@ -376,53 +353,20 @@ static void
 usb2_attach_sub(device_t dev, struct usb2_bus *bus)
 {
 	/* Initialise USB process messages */
-	bus->explore_msg[0].hdr.pm_callback = &usb2_bus_explore;
-	bus->explore_msg[0].bus = bus;
-	bus->explore_msg[1].hdr.pm_callback = &usb2_bus_explore;
-	bus->explore_msg[1].bus = bus;
-
-	bus->detach_msg[0].hdr.pm_callback = &usb2_bus_detach;
-	bus->detach_msg[0].bus = bus;
-	bus->detach_msg[1].hdr.pm_callback = &usb2_bus_detach;
-	bus->detach_msg[1].bus = bus;
-
-	bus->attach_msg[0].hdr.pm_callback = &usb2_bus_attach;
-	bus->attach_msg[0].bus = bus;
-	bus->attach_msg[1].hdr.pm_callback = &usb2_bus_attach;
-	bus->attach_msg[1].bus = bus;
-
-	bus->roothub_msg[0].hdr.pm_callback = &usb2_bus_roothub;
-	bus->roothub_msg[0].bus = bus;
-	bus->roothub_msg[1].hdr.pm_callback = &usb2_bus_roothub;
-	bus->roothub_msg[1].bus = bus;
-
-	/* Create USB explore, roothub and callback processes */
-
-	if (usb2_proc_setup(&bus->giant_callback_proc,
-	    &bus->bus_mtx, USB_PRI_MED)) {
-		printf("WARNING: Creation of USB Giant "
-		    "callback process failed.\n");
-	} else if (usb2_proc_setup(&bus->non_giant_callback_proc,
-	    &bus->bus_mtx, USB_PRI_HIGH)) {
-		printf("WARNING: Creation of USB non-Giant "
-		    "callback process failed.\n");
-	} else if (usb2_proc_setup(&bus->roothub_proc,
-	    &bus->bus_mtx, USB_PRI_HIGH)) {
-		printf("WARNING: Creation of USB roothub "
-		    "process failed.\n");
-	} else if (usb2_proc_setup(&bus->explore_proc,
-	    &bus->bus_mtx, USB_PRI_MED)) {
-		printf("WARNING: Creation of USB explore "
-		    "process failed.\n");
-	} else {
-		/* Get final attach going */
-		USB_BUS_LOCK(bus);
-		if (usb2_proc_msignal(&bus->explore_proc,
-		    &bus->attach_msg[0], &bus->attach_msg[1])) {
-			/* ignore */
-		}
-		USB_BUS_UNLOCK(bus);
-	}
+	USB_TASK_INIT(&bus->explore_task, usb2_bus_explore, bus, NULL);
+	USB_TASK_INIT(&bus->attach_task, usb2_bus_attach, bus, NULL);
+	USB_TASK_INIT(&bus->detach_task, usb2_bus_detach, bus, NULL);
+	USB_TASK_INIT(&bus->roothub_task, usb2_bus_roothub, bus, NULL);
+
+	/* Create a new USB process */
+	usb2_proc_create(&bus->explore_proc, USB_PRI_MED,
+	    device_get_nameunit(dev));
+	usb2_proc_create(&bus->done_proc, USB_PRI_HIGH,
+	    device_get_nameunit(bus->parent));
+
+	/* Get final attach going */
+	usb2_proc_enqueue(&bus->explore_proc, &bus->attach_task);
+
 }
 
 /*------------------------------------------------------------------------*
@@ -580,15 +524,13 @@ usb2_bus_mem_free_all(struct usb2_bus *b
  * roothub and is called from the roothub process.
  *------------------------------------------------------------------------*/
 static void
-usb2_bus_roothub(struct usb2_proc_msg *pm)
+usb2_bus_roothub(void *context, struct usb2_task *task)
 {
-	struct usb2_bus *bus;
-
-	bus = ((struct usb2_bus_msg *)pm)->bus;
-
-	USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
+	struct usb2_bus *bus = context;
 
+	USB_BUS_LOCK(bus);
 	(bus->methods->roothub_exec) (bus);
+	USB_BUS_UNLOCK(bus);
 }
 
 /*------------------------------------------------------------------------*
@@ -602,8 +544,5 @@ usb2_bus_roothub_exec(struct usb2_bus *b
 {
 	USB_BUS_LOCK_ASSERT(bus, MA_OWNED);
 
-	if (usb2_proc_msignal(&bus->roothub_proc,
-	    &bus->roothub_msg[0], &bus->roothub_msg[1])) {
-		/* ignore */
-	}
+	usb2_proc_enqueue(&bus->done_proc, &bus->roothub_task);
 }

Modified: user/thompsa/usb/sys/dev/usb2/core/usb2_device.c
==============================================================================
--- user/thompsa/usb/sys/dev/usb2/core/usb2_device.c	Tue Jan 27 00:31:25 2009	(r187749)
+++ user/thompsa/usb/sys/dev/usb2/core/usb2_device.c	Tue Jan 27 01:21:11 2009	(r187750)
@@ -55,6 +55,7 @@
 #include <dev/usb2/controller/usb2_bus.h>
 
 /* function prototypes */
+static usb2_task_fn_t	usb2_clear_stall;
 
 static void	usb2_fill_pipe_data(struct usb2_device *, uint8_t,
 		    struct usb2_endpoint_descriptor *, struct usb2_pipe *);
@@ -68,7 +69,6 @@ static void	usb2_init_attach_arg(struct 
 		    struct usb2_attach_arg *);
 static void	usb2_suspend_resume_sub(struct usb2_device *, device_t,
 		    uint8_t);
-static void	usb2_clear_stall_proc(struct usb2_proc_msg *_pm);
 static void	usb2_check_strings(struct usb2_device *);
 static usb2_error_t usb2_fill_iface_data(struct usb2_device *, uint8_t,
 		    uint8_t);
@@ -1221,26 +1221,19 @@ usb2_suspend_resume(struct usb2_device *
 }
 
 /*------------------------------------------------------------------------*
- *      usb2_clear_stall_proc
+ *      usb2_clear_stall
  *
  * This function performs generic USB clear stall operations.
  *------------------------------------------------------------------------*/
 static void
-usb2_clear_stall_proc(struct usb2_proc_msg *_pm)
+usb2_clear_stall(void *context, struct usb2_task *task)
 {
-	struct usb2_clear_stall_msg *pm = (void *)_pm;
-	struct usb2_device *udev = pm->udev;
-
-	/* Change lock */
-	USB_BUS_UNLOCK(udev->bus);
-	mtx_lock(udev->default_mtx);
+	struct usb2_device *udev = context;
 
 	/* Start clear stall callback */
+	mtx_lock(udev->default_mtx);
 	usb2_transfer_start(udev->default_xfer[1]);
-
-	/* Change lock */
 	mtx_unlock(udev->default_mtx);
-	USB_BUS_LOCK(udev->bus);
 }
 
 /*------------------------------------------------------------------------*
@@ -1314,10 +1307,7 @@ usb2_alloc_device(device_t parent_dev, s
 	mtx_init(udev->default_mtx, "USB device mutex", NULL, MTX_DEF);
 
 	/* initialise generic clear stall */
-	udev->cs_msg[0].hdr.pm_callback = &usb2_clear_stall_proc;
-	udev->cs_msg[0].udev = udev;
-	udev->cs_msg[1].hdr.pm_callback = &usb2_clear_stall_proc;
-	udev->cs_msg[1].udev = udev;
+	USB_TASK_INIT(&udev->clearstall_task, usb2_clear_stall, udev, NULL);
 
 	/* initialise some USB device fields */
 	udev->parent_hub = parent_hub;
@@ -1722,14 +1712,11 @@ usb2_free_device(struct usb2_device *ude
 	/* template unsetup, if any */
 	(usb2_temp_unsetup_p) (udev);
 
-	/* 
+	/*
 	 * Make sure that our clear-stall messages are not queued
 	 * anywhere:
 	 */
-	USB_BUS_LOCK(udev->bus);
-	usb2_proc_mwait(&udev->bus->non_giant_callback_proc,
-	    &udev->cs_msg[0], &udev->cs_msg[1]);
-	USB_BUS_UNLOCK(udev->bus);
+	usb2_proc_drain(&bus->done_proc, &udev->clearstall_task);
 
 	sx_destroy(udev->default_sx);
 	sx_destroy(udev->default_sx + 1);

Modified: user/thompsa/usb/sys/dev/usb2/core/usb2_device.h
==============================================================================
--- user/thompsa/usb/sys/dev/usb2/core/usb2_device.h	Tue Jan 27 00:31:25 2009	(r187749)
+++ user/thompsa/usb/sys/dev/usb2/core/usb2_device.h	Tue Jan 27 01:21:11 2009	(r187750)
@@ -31,11 +31,6 @@ struct usb2_symlink;
 
 #define	USB_DEFAULT_XFER_MAX 2
 
-struct usb2_clear_stall_msg {
-	struct usb2_proc_msg hdr;
-	struct usb2_device *udev;
-};
-
 /*
  * The following structure defines an USB pipe which is equal to an
  * USB endpoint.
@@ -99,8 +94,8 @@ struct usb2_power_save {
  * these structures for every USB device.
  */
 struct usb2_device {
-	struct usb2_clear_stall_msg cs_msg[2];	/* generic clear stall
-						 * messages */
+	struct usb2_task clearstall_task;
+
 	struct usb2_perm perm;
 	struct sx default_sx[2];
 	struct mtx default_mtx[1];

Modified: user/thompsa/usb/sys/dev/usb2/core/usb2_hub.c
==============================================================================
--- user/thompsa/usb/sys/dev/usb2/core/usb2_hub.c	Tue Jan 27 00:31:25 2009	(r187749)
+++ user/thompsa/usb/sys/dev/usb2/core/usb2_hub.c	Tue Jan 27 01:21:11 2009	(r187750)
@@ -1354,10 +1354,7 @@ usb2_needs_explore(struct usb2_bus *bus,
 	if (do_probe) {
 		bus->do_probe = 1;
 	}
-	if (usb2_proc_msignal(&bus->explore_proc,
-	    &bus->explore_msg[0], &bus->explore_msg[1])) {
-		/* ignore */
-	}
+	usb2_proc_enqueue(&bus->explore_proc, &bus->explore_task);
 	USB_BUS_UNLOCK(bus);
 }
 

Modified: user/thompsa/usb/sys/dev/usb2/core/usb2_process.c
==============================================================================
--- user/thompsa/usb/sys/dev/usb2/core/usb2_process.c	Tue Jan 27 00:31:25 2009	(r187749)
+++ user/thompsa/usb/sys/dev/usb2/core/usb2_process.c	Tue Jan 27 01:21:11 2009	(r187750)
@@ -31,26 +31,8 @@
 #include <dev/usb2/core/usb2_debug.h>
 #include <dev/usb2/core/usb2_util.h>
 
-#include <sys/proc.h>
-#include <sys/kthread.h>
-#include <sys/sched.h>
-
-#if (__FreeBSD_version < 700000)
-#define	thread_lock(td) mtx_lock_spin(&sched_lock)
-#define	thread_unlock(td) mtx_unlock_spin(&sched_lock)
-#endif
+#include <sys/taskqueue.h>
 
-#if (__FreeBSD_version >= 800000)
-#define	USB_THREAD_CREATE(f, s, p, ...) \
-		kproc_create((f), (s), (p), RFHIGHPID, 0, __VA_ARGS__)
-#define	USB_THREAD_SUSPEND(p)   kproc_suspend(p,0)
-#define	USB_THREAD_EXIT(err)	kproc_exit(err)
-#else
-#define	USB_THREAD_CREATE(f, s, p, ...) \
-		kthread_create((f), (s), (p), RFHIGHPID, 0, __VA_ARGS__)
-#define	USB_THREAD_SUSPEND(p)   kthread_suspend(p,0)
-#define	USB_THREAD_EXIT(err)	kthread_exit(err)
-#endif
 
 #if USB_DEBUG
 static int usb2_proc_debug;
@@ -60,416 +42,67 @@ SYSCTL_INT(_hw_usb2_proc, OID_AUTO, debu
     "Debug level");
 #endif
 
-/*------------------------------------------------------------------------*
- *	usb2_process
- *
- * This function is the USB process dispatcher.
- *------------------------------------------------------------------------*/
-static void
-usb2_process(void *arg)
-{
-	struct usb2_process *up = arg;
-	struct usb2_proc_msg *pm;
-	struct thread *td;
-
-	/* adjust priority */
-	td = curthread;
-	thread_lock(td);
-	sched_prio(td, up->up_prio);
-	thread_unlock(td);
-
-	mtx_lock(up->up_mtx);
-
-	up->up_curtd = td;
-
-	while (1) {
-
-		if (up->up_gone) {
-			break;
-		}
-		/*
-		 * NOTE to reimplementors: dequeueing a command from the
-		 * "used" queue and executing it must be atomic, with regard
-		 * to the "up_mtx" mutex. That means any attempt to queue a
-		 * command by another thread must be blocked until either:
-		 *
-		 * 1) the command sleeps
-		 *
-		 * 2) the command returns
-		 *
-		 * Here is a practical example that shows how this helps
-		 * solving a problem:
-		 *
-		 * Assume that you want to set the baud rate on a USB serial
-		 * device. During the programming of the device you don't
-		 * want to receive nor transmit any data, because it will be
-		 * garbage most likely anyway. The programming of our USB
-		 * device takes 20 milliseconds and it needs to call
-		 * functions that sleep.
-		 *
-		 * Non-working solution: Before we queue the programming
-		 * command, we stop transmission and reception of data. Then
-		 * we queue a programming command. At the end of the
-		 * programming command we enable transmission and reception
-		 * of data.
-		 *
-		 * Problem: If a second programming command is queued while the
-		 * first one is sleeping, we end up enabling transmission
-		 * and reception of data too early.
-		 *
-		 * Working solution: Before we queue the programming command,
-		 * we stop transmission and reception of data. Then we queue
-		 * a programming command. Then we queue a second command
-		 * that only enables transmission and reception of data.
-		 *
-		 * Why it works: If a second programming command is queued
-		 * while the first one is sleeping, then the queueing of a
-		 * second command to enable the data transfers, will cause
-		 * the previous one, which is still on the queue, to be
-		 * removed from the queue, and re-inserted after the last
-		 * baud rate programming command, which then gives the
-		 * desired result.
-		 */
-		pm = TAILQ_FIRST(&up->up_qhead);
-
-		if (pm) {
-			DPRINTF("Message pm=%p, cb=%p (enter)\n",
-			    pm, pm->pm_callback);
-
-			(pm->pm_callback) (pm);
-
-			if (pm == TAILQ_FIRST(&up->up_qhead)) {
-				/* nothing changed */
-				TAILQ_REMOVE(&up->up_qhead, pm, pm_qentry);
-				pm->pm_qentry.tqe_prev = NULL;
-			}
-			DPRINTF("Message pm=%p (leave)\n", pm);
-
-			continue;
-		}
-		/* end if messages - check if anyone is waiting for sync */
-		if (up->up_dsleep) {
-			up->up_dsleep = 0;
-			usb2_cv_broadcast(&up->up_drain);
-		}
-		up->up_msleep = 1;
-		usb2_cv_wait(&up->up_cv, up->up_mtx);
-	}
-
-	up->up_ptr = NULL;
-	usb2_cv_signal(&up->up_cv);
-	mtx_unlock(up->up_mtx);
-
-	USB_THREAD_EXIT(0);
-}
-
-/*------------------------------------------------------------------------*
- *	usb2_proc_setup
- *
- * This function will create a process using the given "prio" that can
- * execute callbacks. The mutex pointed to by "p_mtx" will be applied
- * before calling the callbacks and released after that the callback
- * has returned. The structure pointed to by "up" is assumed to be
- * zeroed before this function is called.
- *
- * Return values:
- *    0: success
- * Else: failure
- *------------------------------------------------------------------------*/
-uint8_t
-usb2_proc_setup(struct usb2_process *up, struct mtx *p_mtx, uint8_t prio)
+int
+usb2_proc_create(struct usb2_process *up, int prio, const char *name)
 {
-	up->up_mtx = p_mtx;
-	up->up_prio = prio;
-
-	TAILQ_INIT(&up->up_qhead);
-
-	usb2_cv_init(&up->up_cv, "WMSG");
-	usb2_cv_init(&up->up_drain, "DMSG");
-
-	if (USB_THREAD_CREATE(&usb2_process, up,
-	    &up->up_ptr, "USBPROC")) {
-		DPRINTFN(0, "Unable to create USB process.");
-		up->up_ptr = NULL;
-		goto error;
-	}
+	up->up_tq = taskqueue_create(name, M_WAITOK,
+	    taskqueue_thread_enqueue, &up->up_tq);
+	if (up->up_tq == NULL)
+		return (ENOMEM);
+	taskqueue_start_threads(&up->up_tq, 1, prio,
+	    "usb: %s", name);
 	return (0);
-
-error:
-	usb2_proc_unsetup(up);
-	return (1);
 }
 
-/*------------------------------------------------------------------------*
- *	usb2_proc_unsetup
- *
- * NOTE: If the structure pointed to by "up" is all zero, this
- * function does nothing.
- *
- * NOTE: Messages that are pending on the process queue will not be
- * removed nor called.
- *------------------------------------------------------------------------*/
 void
-usb2_proc_unsetup(struct usb2_process *up)
+usb2_proc_free(struct usb2_process *up)
 {
-	if (!(up->up_mtx)) {
-		/* not initialised */
-		return;
-	}
-	usb2_proc_drain(up);
-
-	usb2_cv_destroy(&up->up_cv);
-	usb2_cv_destroy(&up->up_drain);
-
-	/* make sure that we do not enter here again */
-	up->up_mtx = NULL;
-}
-
-/*------------------------------------------------------------------------*
- *	usb2_proc_msignal
- *
- * This function will queue one of the passed USB process messages on
- * the USB process queue. The first message that is not already queued
- * will get queued. If both messages are already queued the one queued
- * last will be removed from the queue and queued in the end. The USB
- * process mutex must be locked when calling this function. This
- * function exploits the fact that a process can only do one callback
- * at a time. The message that was queued is returned.
- *------------------------------------------------------------------------*/
-void   *
-usb2_proc_msignal(struct usb2_process *up, void *_pm0, void *_pm1)
-{
-	struct usb2_proc_msg *pm0 = _pm0;
-	struct usb2_proc_msg *pm1 = _pm1;
-	struct usb2_proc_msg *pm2;
-	uint32_t d;
-	uint8_t t;
-
-	mtx_assert(up->up_mtx, MA_OWNED);
-
-	t = 0;
-
-	if (pm0->pm_qentry.tqe_prev) {
-		t |= 1;
-	}
-	if (pm1->pm_qentry.tqe_prev) {
-		t |= 2;
-	}
-	if (t == 0) {
-		/*
-		 * No entries are queued. Queue "pm0" and use the existing
-		 * message number.
-		 */
-		pm2 = pm0;
-	} else if (t == 1) {
-		/* Check if we need to increment the message number. */
-		if (pm0->pm_num == up->up_msg_num) {
-			up->up_msg_num++;
-		}
-		pm2 = pm1;
-	} else if (t == 2) {
-		/* Check if we need to increment the message number. */
-		if (pm1->pm_num == up->up_msg_num) {
-			up->up_msg_num++;
-		}
-		pm2 = pm0;
-	} else if (t == 3) {
-		/*
-		 * Both entries are queued. Re-queue the entry closest to
-		 * the end.
-		 */
-		d = (pm1->pm_num - pm0->pm_num);
-
-		/* Check sign after subtraction */
-		if (d & 0x80000000) {
-			pm2 = pm0;
-		} else {
-			pm2 = pm1;
-		}
-
-		TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry);
-	} else {
-		pm2 = NULL;		/* panic - should not happen */
-	}
-
-	DPRINTF(" t=%u, num=%u\n", t, up->up_msg_num);
-
-	/* Put message last on queue */
-
-	pm2->pm_num = up->up_msg_num;
-	TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry);
-
-	/* Check if we need to wakeup the USB process. */
-
-	if (up->up_msleep) {
-		up->up_msleep = 0;	/* save "cv_signal()" calls */
-		usb2_cv_signal(&up->up_cv);
+	if (up->up_tq) {
+		taskqueue_free(up->up_tq);
+		up->up_tq = NULL;
 	}
-	return (pm2);
 }
 
-/*------------------------------------------------------------------------*
- *	usb2_proc_is_gone
- *
- * Return values:
- *    0: USB process is running
- * Else: USB process is tearing down
- *------------------------------------------------------------------------*/
-uint8_t
-usb2_proc_is_gone(struct usb2_process *up)
+void
+usb2_proc_block(struct usb2_process *up)
 {
-	mtx_assert(up->up_mtx, MA_OWNED);
-
-	return (up->up_gone ? 1 : 0);
+	taskqueue_block(up->up_tq);
 }
 
-/*------------------------------------------------------------------------*
- *	usb2_proc_mwait
- *
- * This function will return when the USB process message pointed to
- * by "pm" is no longer on a queue. This function must be called
- * having "up->up_mtx" locked.
- *------------------------------------------------------------------------*/
 void
-usb2_proc_mwait(struct usb2_process *up, void *_pm0, void *_pm1)
+usb2_proc_unblock(struct usb2_process *up)
 {
-	struct usb2_proc_msg *pm0 = _pm0;
-	struct usb2_proc_msg *pm1 = _pm1;
-
-	mtx_assert(up->up_mtx, MA_OWNED);
-
-	if (up->up_curtd == curthread) {
-		/* Just remove the messages from the queue. */
-		if (pm0->pm_qentry.tqe_prev) {
-			TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry);
-			pm0->pm_qentry.tqe_prev = NULL;
-		}
-		if (pm1->pm_qentry.tqe_prev) {
-			TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry);
-			pm1->pm_qentry.tqe_prev = NULL;
-		}
-	} else
-		while (pm0->pm_qentry.tqe_prev ||
-		    pm1->pm_qentry.tqe_prev) {
-			/* check if config thread is gone */
-			if (up->up_gone)
-				break;
-			up->up_dsleep = 1;
-			usb2_cv_wait(&up->up_drain, up->up_mtx);
-		}
+	taskqueue_unblock(up->up_tq);
 }
 
-/*------------------------------------------------------------------------*
- *	usb2_proc_drain
- *
- * This function will tear down an USB process, waiting for the
- * currently executing command to return.
- *
- * NOTE: If the structure pointed to by "up" is all zero,
- * this function does nothing.
- *------------------------------------------------------------------------*/
 void
-usb2_proc_drain(struct usb2_process *up)
+usb2_proc_enqueue(struct usb2_process *up, struct usb2_task *task)
 {
-	if (!(up->up_mtx)) {
-		/* not initialised */
+	if (up->up_tq == NULL)
 		return;
-	}
-	if (up->up_mtx != &Giant) {
-		mtx_assert(up->up_mtx, MA_NOTOWNED);
-	}
-	mtx_lock(up->up_mtx);
-
-	/* Set the gone flag */
-
-	up->up_gone = 1;
-
-	while (up->up_ptr) {
-
-		/* Check if we need to wakeup the USB process */
 
-		if (up->up_msleep || up->up_csleep) {
-			up->up_msleep = 0;
-			up->up_csleep = 0;
-			usb2_cv_signal(&up->up_cv);
-		}
-		/* Check if we are still cold booted */
-
-		if (cold) {
-			USB_THREAD_SUSPEND(up->up_ptr);
-			printf("WARNING: A USB process has been left suspended!\n");
-			break;
-		}
-		usb2_cv_wait(&up->up_cv, up->up_mtx);
-	}
-	/* Check if someone is waiting - should not happen */
-
-	if (up->up_dsleep) {
-		up->up_dsleep = 0;
-		usb2_cv_broadcast(&up->up_drain);
-		DPRINTF("WARNING: Someone is waiting "
-		    "for USB process drain!\n");
-	}
-	mtx_unlock(up->up_mtx);
+	taskqueue_enqueue(up->up_tq, &task->ut_task);
 }
 
-/*------------------------------------------------------------------------*
- *	usb2_proc_cwait
- *
- * This function will suspend the current process until
- * "usb2_proc_signal()" or "usb2_proc_drain()" is called. The
- * "timeout" parameter defines the maximum wait time in system
- * ticks. If "timeout" is zero that means no timeout.
- *
- * NOTE: This function can only be called from within an USB process.
- *
- * Return values:
- *   USB_PROC_WAIT_TIMEOUT: Timeout
- *   USB_PROC_WAIT_NORMAL: Success
- *   Else: USB process is tearing down
- *------------------------------------------------------------------------*/
-uint8_t
-usb2_proc_cwait(struct usb2_process *up, int timeout)
+void
+usb2_proc_drain(struct usb2_process *up, struct usb2_task *task)
 {
-	int error;
-
-	mtx_assert(up->up_mtx, MA_OWNED);
-
-	if (up->up_gone) {
-		return (USB_PROC_WAIT_DRAIN);
-	}
-	up->up_csleep = 1;
-
-	if (timeout == 0) {
-		usb2_cv_wait(&up->up_cv, up->up_mtx);
-		error = 0;
-	} else {
-		error = usb2_cv_timedwait(&up->up_cv, up->up_mtx, timeout);
-	}
-
-	up->up_csleep = 0;
-
-	if (up->up_gone) {
-		return (USB_PROC_WAIT_DRAIN);
-	}
-	if (error == EWOULDBLOCK) {
-		return (USB_PROC_WAIT_TIMEOUT);
-	}
-	return (0);
+	taskqueue_drain(up->up_tq, &task->ut_task);
 }
 
 /*------------------------------------------------------------------------*
- *	usb2_proc_csignal
+ *	usb2_proc_dispatch
  *
- * This function will wakeup the given USB process.
+ * This function is used to lock the mutex before calling the task
  *------------------------------------------------------------------------*/
 void
-usb2_proc_csignal(struct usb2_process *up)
+usb2_proc_dispatch(void *arg, int pending)
 {
-	mtx_assert(up->up_mtx, MA_OWNED);
+	struct usb2_task *task = arg;
 
-	if (up->up_csleep) {
-		up->up_csleep = 0;
-		usb2_cv_signal(&up->up_cv);
-	}
+	if (task->ut_mtx)
+		mtx_lock(task->ut_mtx);
+	task->ut_func(task->ut_context, task);
+	if (task->ut_mtx)
+		mtx_unlock(task->ut_mtx);
 }

Modified: user/thompsa/usb/sys/dev/usb2/core/usb2_process.h
==============================================================================
--- user/thompsa/usb/sys/dev/usb2/core/usb2_process.h	Tue Jan 27 00:31:25 2009	(r187749)
+++ user/thompsa/usb/sys/dev/usb2/core/usb2_process.h	Tue Jan 27 01:21:11 2009	(r187750)
@@ -28,63 +28,47 @@
 #define	_USB2_PROCESS_H_
 
 #include <sys/priority.h>
+#include <sys/taskqueue.h>
 
 /* defines */
 #define	USB_PRI_HIGH PI_NET
 #define	USB_PRI_MED PI_DISK
+struct usb2_task;
 
-#define	USB_PROC_WAIT_TIMEOUT 2
-#define	USB_PROC_WAIT_DRAIN   1
-#define	USB_PROC_WAIT_NORMAL  0
-
-/* structure prototypes */
-
-struct usb2_proc_msg;
-
-/* typedefs */
-
-typedef void (usb2_proc_callback_t)(struct usb2_proc_msg *hdr);
-
-/*
- * The following structure defines the USB process message header.
- */
-struct usb2_proc_msg {
-	TAILQ_ENTRY(usb2_proc_msg) pm_qentry;
-	usb2_proc_callback_t *pm_callback;
-	uint32_t pm_num;
-};
-
+typedef void usb2_task_fn_t(void *context, struct usb2_task *task);
 /*
  * The following structure defines the USB process.
  */
 struct usb2_process {
-	TAILQ_HEAD(, usb2_proc_msg) up_qhead;
-	struct cv up_cv;
-	struct cv up_drain;
-
-	struct proc *up_ptr;
-	struct thread *up_curtd;
-	struct mtx *up_mtx;
-
-	uint32_t up_msg_num;
-
-	uint8_t	up_prio;
-	uint8_t	up_gone;
-	uint8_t	up_msleep;
-	uint8_t	up_csleep;
-	uint8_t	up_dsleep;
+	struct taskqueue	*up_tq;
 };
 
-/* prototypes */
+struct usb2_task {
+	struct task	ut_task;
+	struct mtx	*ut_mtx;
+	usb2_task_fn_t	*ut_func;
+	void		*ut_context;
+	int		ut_arg;
+};
 
-uint8_t	usb2_proc_cwait(struct usb2_process *up, int timeout);
-uint8_t	usb2_proc_is_gone(struct usb2_process *up);
-uint8_t	usb2_proc_setup(struct usb2_process *up, struct mtx *p_mtx,
-	    uint8_t prio);
-void	usb2_proc_csignal(struct usb2_process *up);
-void	usb2_proc_drain(struct usb2_process *up);
-void	usb2_proc_mwait(struct usb2_process *up, void *pm0, void *pm1);
-void	usb2_proc_unsetup(struct usb2_process *up);
-void   *usb2_proc_msignal(struct usb2_process *up, void *pm0, void *pm1);
+#define USB_TASK_INIT(t, f, c, m) do {				\
+	TASK_INIT(&(t)->ut_task, 0, usb2_proc_dispatch, t);	\
+	(t)->ut_func = (f);					\

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-user mailing list