usb_process.c revision 184610
1/* $FreeBSD: head/sys/dev/usb2/core/usb2_process.c 184610 2008-11-04 02:31:03Z alfred $ */ 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#define USB_DEBUG_VAR usb2_proc_debug 28 29#include <dev/usb2/core/usb2_core.h> 30#include <dev/usb2/core/usb2_process.h> 31#include <dev/usb2/core/usb2_debug.h> 32#include <dev/usb2/core/usb2_util.h> 33 34#include <sys/proc.h> 35#include <sys/kthread.h> 36#include <sys/sched.h> 37 38#if (__FreeBSD_version < 700000) 39#define thread_lock(td) mtx_lock_spin(&sched_lock) 40#define thread_unlock(td) mtx_unlock_spin(&sched_lock) 41#endif 42 43#if (__FreeBSD_version >= 800000) 44#define USB_THREAD_CREATE(f, s, p, ...) \ 45 kproc_create((f), (s), (p), RFHIGHPID, 0, __VA_ARGS__) 46#define USB_THREAD_SUSPEND(p) kproc_suspend(p,0) 47#define USB_THREAD_EXIT(err) kproc_exit(err) 48#else 49#define USB_THREAD_CREATE(f, s, p, ...) \ 50 kthread_create((f), (s), (p), RFHIGHPID, 0, __VA_ARGS__) 51#define USB_THREAD_SUSPEND(p) kthread_suspend(p,0) 52#define USB_THREAD_EXIT(err) kthread_exit(err) 53#endif 54 55#if USB_DEBUG 56static int usb2_proc_debug; 57 58SYSCTL_NODE(_hw_usb2, OID_AUTO, proc, CTLFLAG_RW, 0, "USB process"); 59SYSCTL_INT(_hw_usb2_proc, OID_AUTO, debug, CTLFLAG_RW, &usb2_proc_debug, 0, 60 "Debug level"); 61#endif 62 63/*------------------------------------------------------------------------* 64 * usb2_process 65 * 66 * This function is the USB process dispatcher. 67 *------------------------------------------------------------------------*/ 68static void 69usb2_process(void *arg) 70{ 71 struct usb2_process *up = arg; 72 struct usb2_proc_msg *pm; 73 struct thread *td; 74 75 /* adjust priority */ 76 td = curthread; 77 thread_lock(td); 78 sched_prio(td, up->up_prio); 79 thread_unlock(td); 80 81 mtx_lock(up->up_mtx); 82 83 up->up_curtd = td; 84 85 while (1) { 86 87 if (up->up_gone) { 88 break; 89 } 90 /* 91 * NOTE to reimplementors: dequeueing a command from the 92 * "used" queue and executing it must be atomic, with regard 93 * to the "up_mtx" mutex. That means any attempt to queue a 94 * command by another thread must be blocked until either: 95 * 96 * 1) the command sleeps 97 * 98 * 2) the command returns 99 * 100 * Here is a practical example that shows how this helps 101 * solving a problem: 102 * 103 * Assume that you want to set the baud rate on a USB serial 104 * device. During the programming of the device you don't 105 * want to receive nor transmit any data, because it will be 106 * garbage most likely anyway. The programming of our USB 107 * device takes 20 milliseconds and it needs to call 108 * functions that sleep. 109 * 110 * Non-working solution: Before we queue the programming 111 * command, we stop transmission and reception of data. Then 112 * we queue a programming command. At the end of the 113 * programming command we enable transmission and reception 114 * of data. 115 * 116 * Problem: If a second programming command is queued while the 117 * first one is sleeping, we end up enabling transmission 118 * and reception of data too early. 119 * 120 * Working solution: Before we queue the programming command, 121 * we stop transmission and reception of data. Then we queue 122 * a programming command. Then we queue a second command 123 * that only enables transmission and reception of data. 124 * 125 * Why it works: If a second programming command is queued 126 * while the first one is sleeping, then the queueing of a 127 * second command to enable the data transfers, will cause 128 * the previous one, which is still on the queue, to be 129 * removed from the queue, and re-inserted after the last 130 * baud rate programming command, which then gives the 131 * desired result. 132 */ 133 pm = TAILQ_FIRST(&up->up_qhead); 134 135 if (pm) { 136 DPRINTF("Message pm=%p, cb=%p (enter)\n", 137 pm, pm->pm_callback); 138 139 (pm->pm_callback) (pm); 140 141 if (pm == TAILQ_FIRST(&up->up_qhead)) { 142 /* nothing changed */ 143 TAILQ_REMOVE(&up->up_qhead, pm, pm_qentry); 144 pm->pm_qentry.tqe_prev = NULL; 145 } 146 DPRINTF("Message pm=%p (leave)\n", pm); 147 148 continue; 149 } 150 /* end if messages - check if anyone is waiting for sync */ 151 if (up->up_dsleep) { 152 up->up_dsleep = 0; 153 usb2_cv_broadcast(&up->up_drain); 154 } 155 up->up_msleep = 1; 156 usb2_cv_wait(&up->up_cv, up->up_mtx); 157 } 158 159 up->up_ptr = NULL; 160 usb2_cv_signal(&up->up_cv); 161 mtx_unlock(up->up_mtx); 162 163 USB_THREAD_EXIT(0); 164 return; 165} 166 167/*------------------------------------------------------------------------* 168 * usb2_proc_setup 169 * 170 * This function will create a process using the given "prio" that can 171 * execute callbacks. The mutex pointed to by "p_mtx" will be applied 172 * before calling the callbacks and released after that the callback 173 * has returned. The structure pointed to by "up" is assumed to be 174 * zeroed before this function is called. 175 * 176 * Return values: 177 * 0: success 178 * Else: failure 179 *------------------------------------------------------------------------*/ 180uint8_t 181usb2_proc_setup(struct usb2_process *up, struct mtx *p_mtx, uint8_t prio) 182{ 183 up->up_mtx = p_mtx; 184 up->up_prio = prio; 185 186 TAILQ_INIT(&up->up_qhead); 187 188 usb2_cv_init(&up->up_cv, "WMSG"); 189 usb2_cv_init(&up->up_drain, "DMSG"); 190 191 if (USB_THREAD_CREATE(&usb2_process, up, 192 &up->up_ptr, "USBPROC")) { 193 DPRINTFN(0, "Unable to create USB process."); 194 up->up_ptr = NULL; 195 goto error; 196 } 197 return (0); 198 199error: 200 usb2_proc_unsetup(up); 201 return (1); 202} 203 204/*------------------------------------------------------------------------* 205 * usb2_proc_unsetup 206 * 207 * NOTE: If the structure pointed to by "up" is all zero, this 208 * function does nothing. 209 * 210 * NOTE: Messages that are pending on the process queue will not be 211 * removed nor called. 212 *------------------------------------------------------------------------*/ 213void 214usb2_proc_unsetup(struct usb2_process *up) 215{ 216 if (!(up->up_mtx)) { 217 /* not initialised */ 218 return; 219 } 220 usb2_proc_drain(up); 221 222 usb2_cv_destroy(&up->up_cv); 223 usb2_cv_destroy(&up->up_drain); 224 225 /* make sure that we do not enter here again */ 226 up->up_mtx = NULL; 227 return; 228} 229 230/*------------------------------------------------------------------------* 231 * usb2_proc_msignal 232 * 233 * This function will queue one of the passed USB process messages on 234 * the USB process queue. The first message that is not already queued 235 * will get queued. If both messages are already queued the one queued 236 * last will be removed from the queue and queued in the end. The USB 237 * process mutex must be locked when calling this function. This 238 * function exploits the fact that a process can only do one callback 239 * at a time. The message that was queued is returned. 240 *------------------------------------------------------------------------*/ 241void * 242usb2_proc_msignal(struct usb2_process *up, void *_pm0, void *_pm1) 243{ 244 struct usb2_proc_msg *pm0 = _pm0; 245 struct usb2_proc_msg *pm1 = _pm1; 246 struct usb2_proc_msg *pm2; 247 uint32_t d; 248 uint8_t t; 249 250 mtx_assert(up->up_mtx, MA_OWNED); 251 252 t = 0; 253 254 if (pm0->pm_qentry.tqe_prev) { 255 t |= 1; 256 } 257 if (pm1->pm_qentry.tqe_prev) { 258 t |= 2; 259 } 260 if (t == 0) { 261 /* 262 * No entries are queued. Queue "pm0" and use the existing 263 * message number. 264 */ 265 pm2 = pm0; 266 } else if (t == 1) { 267 /* Check if we need to increment the message number. */ 268 if (pm0->pm_num == up->up_msg_num) { 269 up->up_msg_num++; 270 } 271 pm2 = pm1; 272 } else if (t == 2) { 273 /* Check if we need to increment the message number. */ 274 if (pm1->pm_num == up->up_msg_num) { 275 up->up_msg_num++; 276 } 277 pm2 = pm0; 278 } else if (t == 3) { 279 /* 280 * Both entries are queued. Re-queue the entry closest to 281 * the end. 282 */ 283 d = (pm1->pm_num - pm0->pm_num); 284 285 /* Check sign after subtraction */ 286 if (d & 0x80000000) { 287 pm2 = pm0; 288 } else { 289 pm2 = pm1; 290 } 291 292 TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry); 293 } else { 294 pm2 = NULL; /* panic - should not happen */ 295 } 296 297 DPRINTF(" t=%u, num=%u\n", t, up->up_msg_num); 298 299 /* Put message last on queue */ 300 301 pm2->pm_num = up->up_msg_num; 302 TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry); 303 304 /* Check if we need to wakeup the USB process. */ 305 306 if (up->up_msleep) { 307 up->up_msleep = 0; /* save "cv_signal()" calls */ 308 usb2_cv_signal(&up->up_cv); 309 } 310 return (pm2); 311} 312 313/*------------------------------------------------------------------------* 314 * usb2_proc_is_gone 315 * 316 * Return values: 317 * 0: USB process is running 318 * Else: USB process is tearing down 319 *------------------------------------------------------------------------*/ 320uint8_t 321usb2_proc_is_gone(struct usb2_process *up) 322{ 323 mtx_assert(up->up_mtx, MA_OWNED); 324 325 return (up->up_gone ? 1 : 0); 326} 327 328/*------------------------------------------------------------------------* 329 * usb2_proc_mwait 330 * 331 * This function will return when the USB process message pointed to 332 * by "pm" is no longer on a queue. This function must be called 333 * having "up->up_mtx" locked. 334 *------------------------------------------------------------------------*/ 335void 336usb2_proc_mwait(struct usb2_process *up, void *_pm0, void *_pm1) 337{ 338 struct usb2_proc_msg *pm0 = _pm0; 339 struct usb2_proc_msg *pm1 = _pm1; 340 341 mtx_assert(up->up_mtx, MA_OWNED); 342 343 if (up->up_curtd == curthread) { 344 /* Just remove the messages from the queue. */ 345 if (pm0->pm_qentry.tqe_prev) { 346 TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry); 347 pm0->pm_qentry.tqe_prev = NULL; 348 } 349 if (pm1->pm_qentry.tqe_prev) { 350 TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry); 351 pm1->pm_qentry.tqe_prev = NULL; 352 } 353 } else 354 while (pm0->pm_qentry.tqe_prev || 355 pm1->pm_qentry.tqe_prev) { 356 /* check if config thread is gone */ 357 if (up->up_gone) 358 break; 359 up->up_dsleep = 1; 360 usb2_cv_wait(&up->up_drain, up->up_mtx); 361 } 362 return; 363} 364 365/*------------------------------------------------------------------------* 366 * usb2_proc_drain 367 * 368 * This function will tear down an USB process, waiting for the 369 * currently executing command to return. 370 * 371 * NOTE: If the structure pointed to by "up" is all zero, 372 * this function does nothing. 373 *------------------------------------------------------------------------*/ 374void 375usb2_proc_drain(struct usb2_process *up) 376{ 377 if (!(up->up_mtx)) { 378 /* not initialised */ 379 return; 380 } 381 if (up->up_mtx != &Giant) { 382 mtx_assert(up->up_mtx, MA_NOTOWNED); 383 } 384 mtx_lock(up->up_mtx); 385 386 /* Set the gone flag */ 387 388 up->up_gone = 1; 389 390 while (up->up_ptr) { 391 392 /* Check if we need to wakeup the USB process */ 393 394 if (up->up_msleep || up->up_csleep) { 395 up->up_msleep = 0; 396 up->up_csleep = 0; 397 usb2_cv_signal(&up->up_cv); 398 } 399 /* Check if we are still cold booted */ 400 401 if (cold) { 402 USB_THREAD_SUSPEND(up->up_ptr); 403 printf("WARNING: A USB process has been left suspended!\n"); 404 break; 405 } 406 usb2_cv_wait(&up->up_cv, up->up_mtx); 407 } 408 /* Check if someone is waiting - should not happen */ 409 410 if (up->up_dsleep) { 411 up->up_dsleep = 0; 412 usb2_cv_broadcast(&up->up_drain); 413 DPRINTF("WARNING: Someone is waiting " 414 "for USB process drain!\n"); 415 } 416 mtx_unlock(up->up_mtx); 417 return; 418} 419 420/*------------------------------------------------------------------------* 421 * usb2_proc_cwait 422 * 423 * This function will suspend the current process until 424 * "usb2_proc_signal()" or "usb2_proc_drain()" is called. The 425 * "timeout" parameter defines the maximum wait time in system 426 * ticks. If "timeout" is zero that means no timeout. 427 * 428 * NOTE: This function can only be called from within an USB process. 429 * 430 * Return values: 431 * USB_PROC_WAIT_TIMEOUT: Timeout 432 * USB_PROC_WAIT_NORMAL: Success 433 * Else: USB process is tearing down 434 *------------------------------------------------------------------------*/ 435uint8_t 436usb2_proc_cwait(struct usb2_process *up, int timeout) 437{ 438 int error; 439 440 mtx_assert(up->up_mtx, MA_OWNED); 441 442 if (up->up_gone) { 443 return (USB_PROC_WAIT_DRAIN); 444 } 445 up->up_csleep = 1; 446 447 if (timeout == 0) { 448 usb2_cv_wait(&up->up_cv, up->up_mtx); 449 error = 0; 450 } else { 451 error = usb2_cv_timedwait(&up->up_cv, up->up_mtx, timeout); 452 } 453 454 up->up_csleep = 0; 455 456 if (up->up_gone) { 457 return (USB_PROC_WAIT_DRAIN); 458 } 459 if (error == EWOULDBLOCK) { 460 return (USB_PROC_WAIT_TIMEOUT); 461 } 462 return (0); 463} 464 465/*------------------------------------------------------------------------* 466 * usb2_proc_csignal 467 * 468 * This function will wakeup the given USB process. 469 *------------------------------------------------------------------------*/ 470void 471usb2_proc_csignal(struct usb2_process *up) 472{ 473 mtx_assert(up->up_mtx, MA_OWNED); 474 475 if (up->up_csleep) { 476 up->up_csleep = 0; 477 usb2_cv_signal(&up->up_cv); 478 } 479 return; 480} 481