Hello USB guys,

The following patch is to add a implementation, called `sleepout'.
Please reviews.  I'd like to commit it into HEAD if no objections.

  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).

regards,
Weongyo Jeong

Index: usb_sleepout.c
===================================================================
--- usb_sleepout.c      (revision 0)
+++ usb_sleepout.c      (revision 0)
@@ -0,0 +1,122 @@
+/*-
+ * 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));
+}

Property changes on: usb_sleepout.c
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native

Index: usb_sleepout.h
===================================================================
--- usb_sleepout.h      (revision 0)
+++ usb_sleepout.h      (revision 0)
@@ -0,0 +1,53 @@
+/*-
+ * 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;
+};
+
+#define        SLEEPOUT_RUNTASK(_so, _task)    \
+       taskqueue_enqueue((_so)->s_taskqueue, (_task))
+#define        SLEEPOUT_DRAINTASK(_so, _task)  \
+       taskqueue_drain((_so)->s_taskqueue, (_task))
+
+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

Property changes on: usb_sleepout.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Id
Added: svn:eol-style
   + native

_______________________________________________
freebsd-usb@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-usb
To unsubscribe, send any mail to "freebsd-usb-unsubscr...@freebsd.org"

Reply via email to