svn commit: r212280 - in user/weongyo/usb/sys: dev/usb modules/usb/usb

Weongyo Jeong weongyo at FreeBSD.org
Mon Sep 6 23:52:05 UTC 2010


Author: weongyo
Date: Mon Sep  6 23:52:04 2010
New Revision: 212280
URL: http://svn.freebsd.org/changeset/base/212280

Log:
  Adds `sleepout' prototype which is a comic combination of callout(9) and
  taskqueue(8) only for USB drivers to implement one step timer.  In
  current USB drivers using callout(9) interface they all have two step
  execution flow as follows:
  
    1. callout callback is fired by the interrupt context.  Then it needs
       to pass it to USB process context because it could sleep(!) while
       callout(9) don't allow it.
    2. In the USB process context it operates USB commands that most of
       times it'd be blocked at least 125 us (it'd be always true for USB)
  
  In a view of driver developer it'd be more convenient if USB stack has a
  feature like this (timer supporting blocking).  This's an experimental.

Added:
  user/weongyo/usb/sys/dev/usb/usb_sleepout.c   (contents, props changed)
  user/weongyo/usb/sys/dev/usb/usb_sleepout.h   (contents, props changed)
Modified:
  user/weongyo/usb/sys/modules/usb/usb/Makefile

Added: user/weongyo/usb/sys/dev/usb/usb_sleepout.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/weongyo/usb/sys/dev/usb/usb_sleepout.c	Mon Sep  6 23:52:04 2010	(r212280)
@@ -0,0 +1,123 @@
+/*-
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+
+#include <dev/usb/usb_sleepout.h>
+
+void
+sleepout_create(struct sleepout *s, const char *name)
+{
+
+	s->s_taskqueue = taskqueue_create(name, M_WAITOK,
+	    taskqueue_thread_enqueue, &s->s_taskqueue);
+	/* XXX adjusts the priority. */
+	taskqueue_start_threads(&s->s_taskqueue, 1, PI_NET, "%s sleepout",
+	    name);
+}
+
+void
+sleepout_free(struct sleepout *s)
+{
+
+	taskqueue_free(s->s_taskqueue);
+}
+
+static void
+_sleepout_taskqueue_callback(void *arg, int pending)
+{
+	struct sleepout_task *st = arg;
+
+	(void)pending;
+
+	if (st->st_mtx != NULL)
+		mtx_lock(st->st_mtx);
+
+	st->st_func(st->st_arg);
+
+	if (st->st_mtx != NULL)
+		mtx_unlock(st->st_mtx);
+}
+
+void
+sleepout_init(struct sleepout *s, struct sleepout_task *st, int mpsafe)
+{
+
+	st->st_sleepout = s;
+	callout_init(&st->st_callout, mpsafe);
+	TASK_INIT(&st->st_task, 0, _sleepout_taskqueue_callback, st);
+	st->st_mtx = NULL;
+}
+
+void
+sleepout_init_mtx(struct sleepout *s, struct sleepout_task *st, struct mtx *mtx,
+    int flags)
+{
+
+	st->st_sleepout = s;
+	callout_init_mtx(&st->st_callout, mtx, flags);
+	TASK_INIT(&st->st_task, 0, _sleepout_taskqueue_callback, st);
+	st->st_mtx = mtx;
+}
+
+static void
+_sleepout_callout_callback(void *arg)
+{
+	struct sleepout_task *st = arg;
+	struct sleepout *s = st->st_sleepout;
+
+	taskqueue_enqueue(s->s_taskqueue, &st->st_task);
+}
+
+int
+sleepout_reset(struct sleepout_task *st, int to_ticks, sleepout_func_t ftn,
+    void *arg)
+{
+
+	st->st_func = ftn;
+	st->st_arg = arg;
+	return (callout_reset(&st->st_callout, to_ticks,
+	    _sleepout_callout_callback, st));
+}
+
+int
+sleepout_pending(struct sleepout_task *st)
+{
+
+	return (callout_pending(&st->st_callout));
+}
+
+int
+sleepout_stop(struct sleepout_task *st)
+{
+
+	return (callout_stop(&st->st_callout));
+}
+
+int
+sleepout_drain(struct sleepout_task *st)
+{
+	struct sleepout *s = st->st_sleepout;
+
+	taskqueue_drain(s->s_taskqueue, &st->st_task);
+	return (callout_drain(&st->st_callout));
+	
+}

Added: user/weongyo/usb/sys/dev/usb/usb_sleepout.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/weongyo/usb/sys/dev/usb/usb_sleepout.h	Mon Sep  6 23:52:04 2010	(r212280)
@@ -0,0 +1,48 @@
+/*-
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _USB_SLEEPOUT_H_
+#define	_USB_SLEEPOUT_H_
+
+#include <sys/callout.h>
+#include <sys/taskqueue.h>
+
+struct sleepout {
+	struct taskqueue	*s_taskqueue;
+};
+
+typedef void (*sleepout_func_t)(void *);
+
+struct sleepout_task {
+	struct sleepout		*st_sleepout;
+	struct callout		st_callout;
+	struct task		st_task;
+	struct mtx		*st_mtx;
+	sleepout_func_t		st_func;
+	void			*st_arg;
+};
+
+void	sleepout_create(struct sleepout *, const char *);
+void	sleepout_free(struct sleepout *);
+void	sleepout_init(struct sleepout *, struct sleepout_task *, int);
+void	sleepout_init_mtx(struct sleepout *, struct sleepout_task *,
+	    struct mtx *, int);
+int	sleepout_reset(struct sleepout_task *, int, sleepout_func_t, void *);
+int	sleepout_pending(struct sleepout_task *);
+int	sleepout_stop(struct sleepout_task *);
+int	sleepout_drain(struct sleepout_task *);
+
+#endif

Modified: user/weongyo/usb/sys/modules/usb/usb/Makefile
==============================================================================
--- user/weongyo/usb/sys/modules/usb/usb/Makefile	Mon Sep  6 23:11:56 2010	(r212279)
+++ user/weongyo/usb/sys/modules/usb/usb/Makefile	Mon Sep  6 23:52:04 2010	(r212280)
@@ -33,10 +33,11 @@ KMOD=	usb
 SRCS=	bus_if.h device_if.h usb_if.h usb_if.c vnode_if.h \
 	opt_usb.h opt_bus.h opt_ddb.h \
 	usbdevs.h usbdevs_data.h \
+	usb_sleepout.h \
 	usb_busdma.c usb_controller.c usb_compat_linux.c usb_core.c usb_debug.c \
 	usb_dev.c usb_device.c usb_dynamic.c usb_error.c usb_generic.c \
 	usb_handle_request.c usb_hid.c usb_hub.c usb_lookup.c usb_mbuf.c \
 	usb_msctest.c usb_parse.c usb_process.c usb_request.c \
-	usb_transfer.c usb_util.c 
+	usb_sleepout.c usb_transfer.c usb_util.c 
 
 .include <bsd.kmod.mk>


More information about the svn-src-user mailing list