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