The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/usb_process.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* $FreeBSD: releng/11.2/sys/dev/usb/usb_process.c 331722 2018-03-29 02:50:57Z eadler $ */
    2 /*-
    3  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #ifdef USB_GLOBAL_INCLUDE_FILE
   28 #include USB_GLOBAL_INCLUDE_FILE
   29 #else
   30 #include <sys/stdint.h>
   31 #include <sys/stddef.h>
   32 #include <sys/param.h>
   33 #include <sys/queue.h>
   34 #include <sys/types.h>
   35 #include <sys/systm.h>
   36 #include <sys/kernel.h>
   37 #include <sys/bus.h>
   38 #include <sys/module.h>
   39 #include <sys/lock.h>
   40 #include <sys/mutex.h>
   41 #include <sys/condvar.h>
   42 #include <sys/sysctl.h>
   43 #include <sys/sx.h>
   44 #include <sys/unistd.h>
   45 #include <sys/callout.h>
   46 #include <sys/malloc.h>
   47 #include <sys/priv.h>
   48 
   49 #include <dev/usb/usb.h>
   50 #include <dev/usb/usbdi.h>
   51 #include <dev/usb/usbdi_util.h>
   52 #include <dev/usb/usb_process.h>
   53 
   54 #define USB_DEBUG_VAR usb_proc_debug
   55 #include <dev/usb/usb_debug.h>
   56 #include <dev/usb/usb_util.h>
   57 
   58 #include <sys/proc.h>
   59 #include <sys/kthread.h>
   60 #include <sys/sched.h>
   61 #endif                  /* USB_GLOBAL_INCLUDE_FILE */
   62 
   63 #if (__FreeBSD_version < 700000)
   64 #define thread_lock(td) mtx_lock_spin(&sched_lock)
   65 #define thread_unlock(td) mtx_unlock_spin(&sched_lock)
   66 #endif
   67 
   68 #if (__FreeBSD_version >= 800000)
   69 static struct proc *usbproc;
   70 static int usb_pcount;
   71 #define USB_THREAD_CREATE(f, s, p, ...) \
   72                 kproc_kthread_add((f), (s), &usbproc, (p), RFHIGHPID, \
   73                     0, "usb", __VA_ARGS__)
   74 #if (__FreeBSD_version >= 900000)
   75 #define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check()
   76 #else
   77 #define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check(curthread)
   78 #endif
   79 #define USB_THREAD_SUSPEND(p)   kthread_suspend(p,0)
   80 #define USB_THREAD_EXIT(err)    kthread_exit()
   81 #else
   82 #define USB_THREAD_CREATE(f, s, p, ...) \
   83                 kthread_create((f), (s), (p), RFHIGHPID, 0, __VA_ARGS__)
   84 #define USB_THREAD_SUSPEND_CHECK() kthread_suspend_check(curproc)
   85 #define USB_THREAD_SUSPEND(p)   kthread_suspend(p,0)
   86 #define USB_THREAD_EXIT(err)    kthread_exit(err)
   87 #endif
   88 
   89 #ifdef USB_DEBUG
   90 static int usb_proc_debug;
   91 
   92 static SYSCTL_NODE(_hw_usb, OID_AUTO, proc, CTLFLAG_RW, 0, "USB process");
   93 SYSCTL_INT(_hw_usb_proc, OID_AUTO, debug, CTLFLAG_RWTUN, &usb_proc_debug, 0,
   94     "Debug level");
   95 #endif
   96 
   97 /*------------------------------------------------------------------------*
   98  *      usb_process
   99  *
  100  * This function is the USB process dispatcher.
  101  *------------------------------------------------------------------------*/
  102 static void
  103 usb_process(void *arg)
  104 {
  105         struct usb_process *up = arg;
  106         struct usb_proc_msg *pm;
  107         struct thread *td;
  108 
  109         /* in case of attach error, check for suspended */
  110         USB_THREAD_SUSPEND_CHECK();
  111 
  112         /* adjust priority */
  113         td = curthread;
  114         thread_lock(td);
  115         sched_prio(td, up->up_prio);
  116         thread_unlock(td);
  117 
  118         mtx_lock(up->up_mtx);
  119 
  120         up->up_curtd = td;
  121 
  122         while (1) {
  123 
  124                 if (up->up_gone)
  125                         break;
  126 
  127                 /*
  128                  * NOTE to reimplementors: dequeueing a command from the
  129                  * "used" queue and executing it must be atomic, with regard
  130                  * to the "up_mtx" mutex. That means any attempt to queue a
  131                  * command by another thread must be blocked until either:
  132                  *
  133                  * 1) the command sleeps
  134                  *
  135                  * 2) the command returns
  136                  *
  137                  * Here is a practical example that shows how this helps
  138                  * solving a problem:
  139                  *
  140                  * Assume that you want to set the baud rate on a USB serial
  141                  * device. During the programming of the device you don't
  142                  * want to receive nor transmit any data, because it will be
  143                  * garbage most likely anyway. The programming of our USB
  144                  * device takes 20 milliseconds and it needs to call
  145                  * functions that sleep.
  146                  *
  147                  * Non-working solution: Before we queue the programming
  148                  * command, we stop transmission and reception of data. Then
  149                  * we queue a programming command. At the end of the
  150                  * programming command we enable transmission and reception
  151                  * of data.
  152                  *
  153                  * Problem: If a second programming command is queued while the
  154                  * first one is sleeping, we end up enabling transmission
  155                  * and reception of data too early.
  156                  *
  157                  * Working solution: Before we queue the programming command,
  158                  * we stop transmission and reception of data. Then we queue
  159                  * a programming command. Then we queue a second command
  160                  * that only enables transmission and reception of data.
  161                  *
  162                  * Why it works: If a second programming command is queued
  163                  * while the first one is sleeping, then the queueing of a
  164                  * second command to enable the data transfers, will cause
  165                  * the previous one, which is still on the queue, to be
  166                  * removed from the queue, and re-inserted after the last
  167                  * baud rate programming command, which then gives the
  168                  * desired result.
  169                  */
  170                 pm = TAILQ_FIRST(&up->up_qhead);
  171 
  172                 if (pm) {
  173                         DPRINTF("Message pm=%p, cb=%p (enter)\n",
  174                             pm, pm->pm_callback);
  175 
  176                         (pm->pm_callback) (pm);
  177 
  178                         if (pm == TAILQ_FIRST(&up->up_qhead)) {
  179                                 /* nothing changed */
  180                                 TAILQ_REMOVE(&up->up_qhead, pm, pm_qentry);
  181                                 pm->pm_qentry.tqe_prev = NULL;
  182                         }
  183                         DPRINTF("Message pm=%p (leave)\n", pm);
  184 
  185                         continue;
  186                 }
  187                 /* end if messages - check if anyone is waiting for sync */
  188                 if (up->up_dsleep) {
  189                         up->up_dsleep = 0;
  190                         cv_broadcast(&up->up_drain);
  191                 }
  192                 up->up_msleep = 1;
  193                 cv_wait(&up->up_cv, up->up_mtx);
  194         }
  195 
  196         up->up_ptr = NULL;
  197         cv_signal(&up->up_cv);
  198         mtx_unlock(up->up_mtx);
  199 #if (__FreeBSD_version >= 800000)
  200         /* Clear the proc pointer if this is the last thread. */
  201         if (--usb_pcount == 0)
  202                 usbproc = NULL;
  203 #endif
  204 
  205         USB_THREAD_EXIT(0);
  206 }
  207 
  208 /*------------------------------------------------------------------------*
  209  *      usb_proc_create
  210  *
  211  * This function will create a process using the given "prio" that can
  212  * execute callbacks. The mutex pointed to by "p_mtx" will be applied
  213  * before calling the callbacks and released after that the callback
  214  * has returned. The structure pointed to by "up" is assumed to be
  215  * zeroed before this function is called.
  216  *
  217  * Return values:
  218  *    0: success
  219  * Else: failure
  220  *------------------------------------------------------------------------*/
  221 int
  222 usb_proc_create(struct usb_process *up, struct mtx *p_mtx,
  223     const char *pmesg, uint8_t prio)
  224 {
  225         up->up_mtx = p_mtx;
  226         up->up_prio = prio;
  227 
  228         TAILQ_INIT(&up->up_qhead);
  229 
  230         cv_init(&up->up_cv, "-");
  231         cv_init(&up->up_drain, "usbdrain");
  232 
  233         if (USB_THREAD_CREATE(&usb_process, up,
  234             &up->up_ptr, "%s", pmesg)) {
  235                 DPRINTFN(0, "Unable to create USB process.");
  236                 up->up_ptr = NULL;
  237                 goto error;
  238         }
  239 #if (__FreeBSD_version >= 800000)
  240         usb_pcount++;
  241 #endif
  242         return (0);
  243 
  244 error:
  245         usb_proc_free(up);
  246         return (ENOMEM);
  247 }
  248 
  249 /*------------------------------------------------------------------------*
  250  *      usb_proc_free
  251  *
  252  * NOTE: If the structure pointed to by "up" is all zero, this
  253  * function does nothing.
  254  *
  255  * NOTE: Messages that are pending on the process queue will not be
  256  * removed nor called.
  257  *------------------------------------------------------------------------*/
  258 void
  259 usb_proc_free(struct usb_process *up)
  260 {
  261         /* check if not initialised */
  262         if (up->up_mtx == NULL)
  263                 return;
  264 
  265         usb_proc_drain(up);
  266 
  267         cv_destroy(&up->up_cv);
  268         cv_destroy(&up->up_drain);
  269 
  270         /* make sure that we do not enter here again */
  271         up->up_mtx = NULL;
  272 }
  273 
  274 /*------------------------------------------------------------------------*
  275  *      usb_proc_msignal
  276  *
  277  * This function will queue one of the passed USB process messages on
  278  * the USB process queue. The first message that is not already queued
  279  * will get queued. If both messages are already queued the one queued
  280  * last will be removed from the queue and queued in the end. The USB
  281  * process mutex must be locked when calling this function. This
  282  * function exploits the fact that a process can only do one callback
  283  * at a time. The message that was queued is returned.
  284  *------------------------------------------------------------------------*/
  285 void   *
  286 usb_proc_msignal(struct usb_process *up, void *_pm0, void *_pm1)
  287 {
  288         struct usb_proc_msg *pm0 = _pm0;
  289         struct usb_proc_msg *pm1 = _pm1;
  290         struct usb_proc_msg *pm2;
  291         usb_size_t d;
  292         uint8_t t;
  293 
  294         /* check if gone, return dummy value */
  295         if (up->up_gone)
  296                 return (_pm0);
  297 
  298         mtx_assert(up->up_mtx, MA_OWNED);
  299 
  300         t = 0;
  301 
  302         if (pm0->pm_qentry.tqe_prev) {
  303                 t |= 1;
  304         }
  305         if (pm1->pm_qentry.tqe_prev) {
  306                 t |= 2;
  307         }
  308         if (t == 0) {
  309                 /*
  310                  * No entries are queued. Queue "pm0" and use the existing
  311                  * message number.
  312                  */
  313                 pm2 = pm0;
  314         } else if (t == 1) {
  315                 /* Check if we need to increment the message number. */
  316                 if (pm0->pm_num == up->up_msg_num) {
  317                         up->up_msg_num++;
  318                 }
  319                 pm2 = pm1;
  320         } else if (t == 2) {
  321                 /* Check if we need to increment the message number. */
  322                 if (pm1->pm_num == up->up_msg_num) {
  323                         up->up_msg_num++;
  324                 }
  325                 pm2 = pm0;
  326         } else if (t == 3) {
  327                 /*
  328                  * Both entries are queued. Re-queue the entry closest to
  329                  * the end.
  330                  */
  331                 d = (pm1->pm_num - pm0->pm_num);
  332 
  333                 /* Check sign after subtraction */
  334                 if (d & 0x80000000) {
  335                         pm2 = pm0;
  336                 } else {
  337                         pm2 = pm1;
  338                 }
  339 
  340                 TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry);
  341         } else {
  342                 pm2 = NULL;             /* panic - should not happen */
  343         }
  344 
  345         DPRINTF(" t=%u, num=%u\n", t, up->up_msg_num);
  346 
  347         /* Put message last on queue */
  348 
  349         pm2->pm_num = up->up_msg_num;
  350         TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry);
  351 
  352         /* Check if we need to wakeup the USB process. */
  353 
  354         if (up->up_msleep) {
  355                 up->up_msleep = 0;      /* save "cv_signal()" calls */
  356                 cv_signal(&up->up_cv);
  357         }
  358         return (pm2);
  359 }
  360 
  361 /*------------------------------------------------------------------------*
  362  *      usb_proc_is_gone
  363  *
  364  * Return values:
  365  *    0: USB process is running
  366  * Else: USB process is tearing down
  367  *------------------------------------------------------------------------*/
  368 uint8_t
  369 usb_proc_is_gone(struct usb_process *up)
  370 {
  371         if (up->up_gone)
  372                 return (1);
  373 
  374         /*
  375          * Allow calls when up_mtx is NULL, before the USB process
  376          * structure is initialised.
  377          */
  378         if (up->up_mtx != NULL)
  379                 mtx_assert(up->up_mtx, MA_OWNED);
  380         return (0);
  381 }
  382 
  383 /*------------------------------------------------------------------------*
  384  *      usb_proc_mwait
  385  *
  386  * This function will return when the USB process message pointed to
  387  * by "pm" is no longer on a queue. This function must be called
  388  * having "up->up_mtx" locked.
  389  *------------------------------------------------------------------------*/
  390 void
  391 usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1)
  392 {
  393         struct usb_proc_msg *pm0 = _pm0;
  394         struct usb_proc_msg *pm1 = _pm1;
  395 
  396         /* check if gone */
  397         if (up->up_gone)
  398                 return;
  399 
  400         mtx_assert(up->up_mtx, MA_OWNED);
  401 
  402         if (up->up_curtd == curthread) {
  403                 /* Just remove the messages from the queue. */
  404                 if (pm0->pm_qentry.tqe_prev) {
  405                         TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry);
  406                         pm0->pm_qentry.tqe_prev = NULL;
  407                 }
  408                 if (pm1->pm_qentry.tqe_prev) {
  409                         TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry);
  410                         pm1->pm_qentry.tqe_prev = NULL;
  411                 }
  412         } else
  413                 while (pm0->pm_qentry.tqe_prev ||
  414                     pm1->pm_qentry.tqe_prev) {
  415                         /* check if config thread is gone */
  416                         if (up->up_gone)
  417                                 break;
  418                         up->up_dsleep = 1;
  419                         cv_wait(&up->up_drain, up->up_mtx);
  420                 }
  421 }
  422 
  423 /*------------------------------------------------------------------------*
  424  *      usb_proc_drain
  425  *
  426  * This function will tear down an USB process, waiting for the
  427  * currently executing command to return.
  428  *
  429  * NOTE: If the structure pointed to by "up" is all zero,
  430  * this function does nothing.
  431  *------------------------------------------------------------------------*/
  432 void
  433 usb_proc_drain(struct usb_process *up)
  434 {
  435         /* check if not initialised */
  436         if (up->up_mtx == NULL)
  437                 return;
  438         /* handle special case with Giant */
  439         if (up->up_mtx != &Giant)
  440                 mtx_assert(up->up_mtx, MA_NOTOWNED);
  441 
  442         mtx_lock(up->up_mtx);
  443 
  444         /* Set the gone flag */
  445 
  446         up->up_gone = 1;
  447 
  448         while (up->up_ptr) {
  449 
  450                 /* Check if we need to wakeup the USB process */
  451 
  452                 if (up->up_msleep || up->up_csleep) {
  453                         up->up_msleep = 0;
  454                         up->up_csleep = 0;
  455                         cv_signal(&up->up_cv);
  456                 }
  457 #ifndef EARLY_AP_STARTUP
  458                 /* Check if we are still cold booted */
  459                 if (cold) {
  460                         USB_THREAD_SUSPEND(up->up_ptr);
  461                         printf("WARNING: A USB process has "
  462                             "been left suspended\n");
  463                         break;
  464                 }
  465 #endif
  466                 cv_wait(&up->up_cv, up->up_mtx);
  467         }
  468         /* Check if someone is waiting - should not happen */
  469 
  470         if (up->up_dsleep) {
  471                 up->up_dsleep = 0;
  472                 cv_broadcast(&up->up_drain);
  473                 DPRINTF("WARNING: Someone is waiting "
  474                     "for USB process drain!\n");
  475         }
  476         mtx_unlock(up->up_mtx);
  477 }
  478 
  479 /*------------------------------------------------------------------------*
  480  *      usb_proc_rewakeup
  481  *
  482  * This function is called to re-wakeup the given USB
  483  * process. This usually happens after that the USB system has been in
  484  * polling mode, like during a panic. This function must be called
  485  * having "up->up_mtx" locked.
  486  *------------------------------------------------------------------------*/
  487 void
  488 usb_proc_rewakeup(struct usb_process *up)
  489 {
  490         /* check if not initialised */
  491         if (up->up_mtx == NULL)
  492                 return;
  493         /* check if gone */
  494         if (up->up_gone)
  495                 return;
  496 
  497         mtx_assert(up->up_mtx, MA_OWNED);
  498 
  499         if (up->up_msleep == 0) {
  500                 /* re-wakeup */
  501                 cv_signal(&up->up_cv);
  502         }
  503 }
  504 
  505 /*------------------------------------------------------------------------*
  506  *      usb_proc_is_called_from
  507  *
  508  * This function will return non-zero if called from inside the USB
  509  * process passed as first argument. Else this function returns zero.
  510  *------------------------------------------------------------------------*/
  511 int
  512 usb_proc_is_called_from(struct usb_process *up)
  513 {
  514         return (up->up_curtd == curthread);
  515 }

Cache object: e4706438d868b0c0452661d86ed10743


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.