usb_process.c revision 187994
1/* $FreeBSD: head/sys/dev/usb2/core/usb2_process.c 187994 2009-02-02 00:49:39Z 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}
165
166/*------------------------------------------------------------------------*
167 *	usb2_proc_setup
168 *
169 * This function will create a process using the given "prio" that can
170 * execute callbacks. The mutex pointed to by "p_mtx" will be applied
171 * before calling the callbacks and released after that the callback
172 * has returned. The structure pointed to by "up" is assumed to be
173 * zeroed before this function is called.
174 *
175 * Return values:
176 *    0: success
177 * Else: failure
178 *------------------------------------------------------------------------*/
179uint8_t
180usb2_proc_setup(struct usb2_process *up, struct mtx *p_mtx, uint8_t prio)
181{
182	up->up_mtx = p_mtx;
183	up->up_prio = prio;
184
185	TAILQ_INIT(&up->up_qhead);
186
187	usb2_cv_init(&up->up_cv, "wmsg");
188	usb2_cv_init(&up->up_drain, "dmsg");
189
190	if (USB_THREAD_CREATE(&usb2_process, up,
191	    &up->up_ptr, "usbproc")) {
192		DPRINTFN(0, "Unable to create USB process.");
193		up->up_ptr = NULL;
194		goto error;
195	}
196	return (0);
197
198error:
199	usb2_proc_unsetup(up);
200	return (1);
201}
202
203/*------------------------------------------------------------------------*
204 *	usb2_proc_unsetup
205 *
206 * NOTE: If the structure pointed to by "up" is all zero, this
207 * function does nothing.
208 *
209 * NOTE: Messages that are pending on the process queue will not be
210 * removed nor called.
211 *------------------------------------------------------------------------*/
212void
213usb2_proc_unsetup(struct usb2_process *up)
214{
215	if (!(up->up_mtx)) {
216		/* not initialised */
217		return;
218	}
219	usb2_proc_drain(up);
220
221	usb2_cv_destroy(&up->up_cv);
222	usb2_cv_destroy(&up->up_drain);
223
224	/* make sure that we do not enter here again */
225	up->up_mtx = NULL;
226}
227
228/*------------------------------------------------------------------------*
229 *	usb2_proc_msignal
230 *
231 * This function will queue one of the passed USB process messages on
232 * the USB process queue. The first message that is not already queued
233 * will get queued. If both messages are already queued the one queued
234 * last will be removed from the queue and queued in the end. The USB
235 * process mutex must be locked when calling this function. This
236 * function exploits the fact that a process can only do one callback
237 * at a time. The message that was queued is returned.
238 *------------------------------------------------------------------------*/
239void   *
240usb2_proc_msignal(struct usb2_process *up, void *_pm0, void *_pm1)
241{
242	struct usb2_proc_msg *pm0 = _pm0;
243	struct usb2_proc_msg *pm1 = _pm1;
244	struct usb2_proc_msg *pm2;
245	uint32_t d;
246	uint8_t t;
247
248	mtx_assert(up->up_mtx, MA_OWNED);
249
250	t = 0;
251
252	if (pm0->pm_qentry.tqe_prev) {
253		t |= 1;
254	}
255	if (pm1->pm_qentry.tqe_prev) {
256		t |= 2;
257	}
258	if (t == 0) {
259		/*
260		 * No entries are queued. Queue "pm0" and use the existing
261		 * message number.
262		 */
263		pm2 = pm0;
264	} else if (t == 1) {
265		/* Check if we need to increment the message number. */
266		if (pm0->pm_num == up->up_msg_num) {
267			up->up_msg_num++;
268		}
269		pm2 = pm1;
270	} else if (t == 2) {
271		/* Check if we need to increment the message number. */
272		if (pm1->pm_num == up->up_msg_num) {
273			up->up_msg_num++;
274		}
275		pm2 = pm0;
276	} else if (t == 3) {
277		/*
278		 * Both entries are queued. Re-queue the entry closest to
279		 * the end.
280		 */
281		d = (pm1->pm_num - pm0->pm_num);
282
283		/* Check sign after subtraction */
284		if (d & 0x80000000) {
285			pm2 = pm0;
286		} else {
287			pm2 = pm1;
288		}
289
290		TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry);
291	} else {
292		pm2 = NULL;		/* panic - should not happen */
293	}
294
295	DPRINTF(" t=%u, num=%u\n", t, up->up_msg_num);
296
297	/* Put message last on queue */
298
299	pm2->pm_num = up->up_msg_num;
300	TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry);
301
302	/* Check if we need to wakeup the USB process. */
303
304	if (up->up_msleep) {
305		up->up_msleep = 0;	/* save "cv_signal()" calls */
306		usb2_cv_signal(&up->up_cv);
307	}
308	return (pm2);
309}
310
311/*------------------------------------------------------------------------*
312 *	usb2_proc_is_gone
313 *
314 * Return values:
315 *    0: USB process is running
316 * Else: USB process is tearing down
317 *------------------------------------------------------------------------*/
318uint8_t
319usb2_proc_is_gone(struct usb2_process *up)
320{
321	mtx_assert(up->up_mtx, MA_OWNED);
322
323	return (up->up_gone ? 1 : 0);
324}
325
326/*------------------------------------------------------------------------*
327 *	usb2_proc_mwait
328 *
329 * This function will return when the USB process message pointed to
330 * by "pm" is no longer on a queue. This function must be called
331 * having "up->up_mtx" locked.
332 *------------------------------------------------------------------------*/
333void
334usb2_proc_mwait(struct usb2_process *up, void *_pm0, void *_pm1)
335{
336	struct usb2_proc_msg *pm0 = _pm0;
337	struct usb2_proc_msg *pm1 = _pm1;
338
339	mtx_assert(up->up_mtx, MA_OWNED);
340
341	if (up->up_curtd == curthread) {
342		/* Just remove the messages from the queue. */
343		if (pm0->pm_qentry.tqe_prev) {
344			TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry);
345			pm0->pm_qentry.tqe_prev = NULL;
346		}
347		if (pm1->pm_qentry.tqe_prev) {
348			TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry);
349			pm1->pm_qentry.tqe_prev = NULL;
350		}
351	} else
352		while (pm0->pm_qentry.tqe_prev ||
353		    pm1->pm_qentry.tqe_prev) {
354			/* check if config thread is gone */
355			if (up->up_gone)
356				break;
357			up->up_dsleep = 1;
358			usb2_cv_wait(&up->up_drain, up->up_mtx);
359		}
360}
361
362/*------------------------------------------------------------------------*
363 *	usb2_proc_drain
364 *
365 * This function will tear down an USB process, waiting for the
366 * currently executing command to return.
367 *
368 * NOTE: If the structure pointed to by "up" is all zero,
369 * this function does nothing.
370 *------------------------------------------------------------------------*/
371void
372usb2_proc_drain(struct usb2_process *up)
373{
374	if (!(up->up_mtx)) {
375		/* not initialised */
376		return;
377	}
378	if (up->up_mtx != &Giant) {
379		mtx_assert(up->up_mtx, MA_NOTOWNED);
380	}
381	mtx_lock(up->up_mtx);
382
383	/* Set the gone flag */
384
385	up->up_gone = 1;
386
387	while (up->up_ptr) {
388
389		/* Check if we need to wakeup the USB process */
390
391		if (up->up_msleep || up->up_csleep) {
392			up->up_msleep = 0;
393			up->up_csleep = 0;
394			usb2_cv_signal(&up->up_cv);
395		}
396		/* Check if we are still cold booted */
397
398		if (cold) {
399			USB_THREAD_SUSPEND(up->up_ptr);
400			printf("WARNING: A USB process has been left suspended!\n");
401			break;
402		}
403		usb2_cv_wait(&up->up_cv, up->up_mtx);
404	}
405	/* Check if someone is waiting - should not happen */
406
407	if (up->up_dsleep) {
408		up->up_dsleep = 0;
409		usb2_cv_broadcast(&up->up_drain);
410		DPRINTF("WARNING: Someone is waiting "
411		    "for USB process drain!\n");
412	}
413	mtx_unlock(up->up_mtx);
414}
415
416/*------------------------------------------------------------------------*
417 *	usb2_proc_cwait
418 *
419 * This function will suspend the current process until
420 * "usb2_proc_signal()" or "usb2_proc_drain()" is called. The
421 * "timeout" parameter defines the maximum wait time in system
422 * ticks. If "timeout" is zero that means no timeout.
423 *
424 * NOTE: This function can only be called from within an USB process.
425 *
426 * Return values:
427 *   USB_PROC_WAIT_TIMEOUT: Timeout
428 *   USB_PROC_WAIT_NORMAL: Success
429 *   Else: USB process is tearing down
430 *------------------------------------------------------------------------*/
431uint8_t
432usb2_proc_cwait(struct usb2_process *up, int timeout)
433{
434	int error;
435
436	mtx_assert(up->up_mtx, MA_OWNED);
437
438	if (up->up_gone) {
439		return (USB_PROC_WAIT_DRAIN);
440	}
441	up->up_csleep = 1;
442
443	if (timeout == 0) {
444		usb2_cv_wait(&up->up_cv, up->up_mtx);
445		error = 0;
446	} else {
447		error = usb2_cv_timedwait(&up->up_cv, up->up_mtx, timeout);
448	}
449
450	up->up_csleep = 0;
451
452	if (up->up_gone) {
453		return (USB_PROC_WAIT_DRAIN);
454	}
455	if (error == EWOULDBLOCK) {
456		return (USB_PROC_WAIT_TIMEOUT);
457	}
458	return (0);
459}
460
461/*------------------------------------------------------------------------*
462 *	usb2_proc_csignal
463 *
464 * This function will wakeup the given USB process.
465 *------------------------------------------------------------------------*/
466void
467usb2_proc_csignal(struct usb2_process *up)
468{
469	mtx_assert(up->up_mtx, MA_OWNED);
470
471	if (up->up_csleep) {
472		up->up_csleep = 0;
473		usb2_cv_signal(&up->up_cv);
474	}
475}
476