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