xref: /freebsd/sys/contrib/vchiq/interface/compat/vchi_bsd.c (revision e453e498cbb88570a3ff7b3679de65c88707da95)
1262f27b2SOleksandr Tymoshenko /*-
2262f27b2SOleksandr Tymoshenko  * Copyright (c) 2010 Max Khon <fjoe@freebsd.org>
3262f27b2SOleksandr Tymoshenko  * All rights reserved.
4262f27b2SOleksandr Tymoshenko  *
5262f27b2SOleksandr Tymoshenko  * This software was developed by Max Khon under sponsorship from
6262f27b2SOleksandr Tymoshenko  * the FreeBSD Foundation and Ethon Technologies GmbH.
7262f27b2SOleksandr Tymoshenko  *
8262f27b2SOleksandr Tymoshenko  * Redistribution and use in source and binary forms, with or without
9262f27b2SOleksandr Tymoshenko  * modification, are permitted provided that the following conditions
10262f27b2SOleksandr Tymoshenko  * are met:
11262f27b2SOleksandr Tymoshenko  * 1. Redistributions of source code must retain the above copyright
12262f27b2SOleksandr Tymoshenko  *    notice, this list of conditions and the following disclaimer.
13262f27b2SOleksandr Tymoshenko  * 2. Redistributions in binary form must reproduce the above copyright
14262f27b2SOleksandr Tymoshenko  *    notice, this list of conditions and the following disclaimer in the
15262f27b2SOleksandr Tymoshenko  *    documentation and/or other materials provided with the distribution.
16262f27b2SOleksandr Tymoshenko  *
17262f27b2SOleksandr Tymoshenko  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18262f27b2SOleksandr Tymoshenko  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19262f27b2SOleksandr Tymoshenko  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20262f27b2SOleksandr Tymoshenko  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21262f27b2SOleksandr Tymoshenko  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22262f27b2SOleksandr Tymoshenko  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23262f27b2SOleksandr Tymoshenko  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24262f27b2SOleksandr Tymoshenko  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25262f27b2SOleksandr Tymoshenko  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26262f27b2SOleksandr Tymoshenko  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27262f27b2SOleksandr Tymoshenko  * SUCH DAMAGE.
28262f27b2SOleksandr Tymoshenko  *
29262f27b2SOleksandr Tymoshenko  * $Id: bsd-compat.c 9253 2010-09-02 10:12:09Z fjoe $
30262f27b2SOleksandr Tymoshenko  */
31262f27b2SOleksandr Tymoshenko 
32262f27b2SOleksandr Tymoshenko #include <sys/types.h>
33262f27b2SOleksandr Tymoshenko #include <sys/limits.h>
34262f27b2SOleksandr Tymoshenko #include <sys/bus.h>
35262f27b2SOleksandr Tymoshenko #include <sys/callout.h>
36262f27b2SOleksandr Tymoshenko #include <sys/firmware.h>
37262f27b2SOleksandr Tymoshenko #include <sys/param.h>
38262f27b2SOleksandr Tymoshenko #include <sys/proc.h>
39*e453e498SBrooks Davis #include <sys/stdarg.h>
40262f27b2SOleksandr Tymoshenko #include <sys/syscallsubr.h>
41262f27b2SOleksandr Tymoshenko #include <sys/systm.h>
42262f27b2SOleksandr Tymoshenko #include <sys/taskqueue.h>
43262f27b2SOleksandr Tymoshenko 
44262f27b2SOleksandr Tymoshenko #include "mbox_if.h"
45262f27b2SOleksandr Tymoshenko 
46262f27b2SOleksandr Tymoshenko #include <interface/compat/vchi_bsd.h>
47262f27b2SOleksandr Tymoshenko 
48262f27b2SOleksandr Tymoshenko MALLOC_DEFINE(M_VCHI, "VCHI", "VCHI");
49262f27b2SOleksandr Tymoshenko 
50262f27b2SOleksandr Tymoshenko /*
51262f27b2SOleksandr Tymoshenko  * Timer API
52262f27b2SOleksandr Tymoshenko  */
53262f27b2SOleksandr Tymoshenko static void
run_timer(void * arg)54262f27b2SOleksandr Tymoshenko run_timer(void *arg)
55262f27b2SOleksandr Tymoshenko {
56262f27b2SOleksandr Tymoshenko 	struct timer_list *t = (struct timer_list *) arg;
57262f27b2SOleksandr Tymoshenko 	void (*function)(unsigned long);
58262f27b2SOleksandr Tymoshenko 
59262f27b2SOleksandr Tymoshenko 	mtx_lock_spin(&t->mtx);
60262f27b2SOleksandr Tymoshenko 	if (callout_pending(&t->callout)) {
61262f27b2SOleksandr Tymoshenko 		/* callout was reset */
62262f27b2SOleksandr Tymoshenko 		mtx_unlock_spin(&t->mtx);
63262f27b2SOleksandr Tymoshenko 		return;
64262f27b2SOleksandr Tymoshenko 	}
65262f27b2SOleksandr Tymoshenko 	if (!callout_active(&t->callout)) {
66262f27b2SOleksandr Tymoshenko 		/* callout was stopped */
67262f27b2SOleksandr Tymoshenko 		mtx_unlock_spin(&t->mtx);
68262f27b2SOleksandr Tymoshenko 		return;
69262f27b2SOleksandr Tymoshenko 	}
70262f27b2SOleksandr Tymoshenko 	callout_deactivate(&t->callout);
71262f27b2SOleksandr Tymoshenko 
72262f27b2SOleksandr Tymoshenko 	function = t->function;
73262f27b2SOleksandr Tymoshenko 	mtx_unlock_spin(&t->mtx);
74262f27b2SOleksandr Tymoshenko 
75262f27b2SOleksandr Tymoshenko 	function(t->data);
76262f27b2SOleksandr Tymoshenko }
77262f27b2SOleksandr Tymoshenko 
78262f27b2SOleksandr Tymoshenko void
vchiq_init_timer(struct timer_list * t)7904b8208fSEmmanuel Vadot vchiq_init_timer(struct timer_list *t)
80262f27b2SOleksandr Tymoshenko {
81262f27b2SOleksandr Tymoshenko 	mtx_init(&t->mtx, "dahdi timer lock", NULL, MTX_SPIN);
82fd90e2edSJung-uk Kim 	callout_init(&t->callout, 1);
83262f27b2SOleksandr Tymoshenko 	t->expires = 0;
84262f27b2SOleksandr Tymoshenko 	/*
85262f27b2SOleksandr Tymoshenko 	 * function and data are not initialized intentionally:
86262f27b2SOleksandr Tymoshenko 	 * they are not initialized by Linux implementation too
87262f27b2SOleksandr Tymoshenko 	 */
88262f27b2SOleksandr Tymoshenko }
89262f27b2SOleksandr Tymoshenko 
90262f27b2SOleksandr Tymoshenko void
vchiq_setup_timer(struct timer_list * t,void (* function)(unsigned long),unsigned long data)9104b8208fSEmmanuel Vadot vchiq_setup_timer(struct timer_list *t, void (*function)(unsigned long), unsigned long data)
92262f27b2SOleksandr Tymoshenko {
93262f27b2SOleksandr Tymoshenko 	t->function = function;
94262f27b2SOleksandr Tymoshenko 	t->data = data;
9504b8208fSEmmanuel Vadot 	vchiq_init_timer(t);
96262f27b2SOleksandr Tymoshenko }
97262f27b2SOleksandr Tymoshenko 
98262f27b2SOleksandr Tymoshenko void
vchiq_mod_timer(struct timer_list * t,unsigned long expires)9904b8208fSEmmanuel Vadot vchiq_mod_timer(struct timer_list *t, unsigned long expires)
100262f27b2SOleksandr Tymoshenko {
101262f27b2SOleksandr Tymoshenko 	mtx_lock_spin(&t->mtx);
102262f27b2SOleksandr Tymoshenko 	callout_reset(&t->callout, expires - jiffies, run_timer, t);
103262f27b2SOleksandr Tymoshenko 	mtx_unlock_spin(&t->mtx);
104262f27b2SOleksandr Tymoshenko }
105262f27b2SOleksandr Tymoshenko 
106262f27b2SOleksandr Tymoshenko void
vchiq_add_timer(struct timer_list * t)10704b8208fSEmmanuel Vadot vchiq_add_timer(struct timer_list *t)
108262f27b2SOleksandr Tymoshenko {
10904b8208fSEmmanuel Vadot 	vchiq_mod_timer(t, t->expires);
110262f27b2SOleksandr Tymoshenko }
111262f27b2SOleksandr Tymoshenko 
112262f27b2SOleksandr Tymoshenko int
vchiq_del_timer_sync(struct timer_list * t)11304b8208fSEmmanuel Vadot vchiq_del_timer_sync(struct timer_list *t)
114262f27b2SOleksandr Tymoshenko {
115262f27b2SOleksandr Tymoshenko 	mtx_lock_spin(&t->mtx);
116262f27b2SOleksandr Tymoshenko 	callout_stop(&t->callout);
117262f27b2SOleksandr Tymoshenko 	mtx_unlock_spin(&t->mtx);
118262f27b2SOleksandr Tymoshenko 
119262f27b2SOleksandr Tymoshenko 	mtx_destroy(&t->mtx);
120262f27b2SOleksandr Tymoshenko 	return 0;
121262f27b2SOleksandr Tymoshenko }
122262f27b2SOleksandr Tymoshenko 
123262f27b2SOleksandr Tymoshenko int
vchiq_del_timer(struct timer_list * t)12404b8208fSEmmanuel Vadot vchiq_del_timer(struct timer_list *t)
125262f27b2SOleksandr Tymoshenko {
12604b8208fSEmmanuel Vadot 	vchiq_del_timer_sync(t);
127262f27b2SOleksandr Tymoshenko 	return 0;
128262f27b2SOleksandr Tymoshenko }
129262f27b2SOleksandr Tymoshenko 
130262f27b2SOleksandr Tymoshenko /*
131262f27b2SOleksandr Tymoshenko  * Completion API
132262f27b2SOleksandr Tymoshenko  */
133262f27b2SOleksandr Tymoshenko void
init_completion(struct completion * c)134262f27b2SOleksandr Tymoshenko init_completion(struct completion *c)
135262f27b2SOleksandr Tymoshenko {
136262f27b2SOleksandr Tymoshenko 	cv_init(&c->cv, "VCHI completion cv");
137262f27b2SOleksandr Tymoshenko 	mtx_init(&c->lock, "VCHI completion lock", "condvar", MTX_DEF);
138262f27b2SOleksandr Tymoshenko 	c->done = 0;
139262f27b2SOleksandr Tymoshenko }
140262f27b2SOleksandr Tymoshenko 
141262f27b2SOleksandr Tymoshenko void
destroy_completion(struct completion * c)142262f27b2SOleksandr Tymoshenko destroy_completion(struct completion *c)
143262f27b2SOleksandr Tymoshenko {
144262f27b2SOleksandr Tymoshenko 	cv_destroy(&c->cv);
145262f27b2SOleksandr Tymoshenko 	mtx_destroy(&c->lock);
146262f27b2SOleksandr Tymoshenko }
147262f27b2SOleksandr Tymoshenko 
148262f27b2SOleksandr Tymoshenko void
complete(struct completion * c)149262f27b2SOleksandr Tymoshenko complete(struct completion *c)
150262f27b2SOleksandr Tymoshenko {
151262f27b2SOleksandr Tymoshenko 	mtx_lock(&c->lock);
152262f27b2SOleksandr Tymoshenko 
153262f27b2SOleksandr Tymoshenko 	if (c->done >= 0) {
154262f27b2SOleksandr Tymoshenko 		KASSERT(c->done < INT_MAX, ("c->done overflow")); /* XXX check */
155262f27b2SOleksandr Tymoshenko 		c->done++;
156262f27b2SOleksandr Tymoshenko 		cv_signal(&c->cv);
157262f27b2SOleksandr Tymoshenko 	} else {
158262f27b2SOleksandr Tymoshenko 		KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
159262f27b2SOleksandr Tymoshenko 	}
160262f27b2SOleksandr Tymoshenko 
161262f27b2SOleksandr Tymoshenko 	mtx_unlock(&c->lock);
162262f27b2SOleksandr Tymoshenko }
163262f27b2SOleksandr Tymoshenko 
164262f27b2SOleksandr Tymoshenko void
complete_all(struct completion * c)165262f27b2SOleksandr Tymoshenko complete_all(struct completion *c)
166262f27b2SOleksandr Tymoshenko {
167262f27b2SOleksandr Tymoshenko 	mtx_lock(&c->lock);
168262f27b2SOleksandr Tymoshenko 
169262f27b2SOleksandr Tymoshenko 	if (c->done >= 0) {
170262f27b2SOleksandr Tymoshenko 		KASSERT(c->done < INT_MAX, ("c->done overflow")); /* XXX check */
171262f27b2SOleksandr Tymoshenko 		c->done = -1;
172262f27b2SOleksandr Tymoshenko 		cv_broadcast(&c->cv);
173262f27b2SOleksandr Tymoshenko 	} else {
174262f27b2SOleksandr Tymoshenko 		KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
175262f27b2SOleksandr Tymoshenko 	}
176262f27b2SOleksandr Tymoshenko 
177262f27b2SOleksandr Tymoshenko 	mtx_unlock(&c->lock);
178262f27b2SOleksandr Tymoshenko }
179262f27b2SOleksandr Tymoshenko 
180262f27b2SOleksandr Tymoshenko void
INIT_COMPLETION_locked(struct completion * c)181262f27b2SOleksandr Tymoshenko INIT_COMPLETION_locked(struct completion *c)
182262f27b2SOleksandr Tymoshenko {
183262f27b2SOleksandr Tymoshenko 	mtx_lock(&c->lock);
184262f27b2SOleksandr Tymoshenko 
185262f27b2SOleksandr Tymoshenko 	c->done = 0;
186262f27b2SOleksandr Tymoshenko 
187262f27b2SOleksandr Tymoshenko 	mtx_unlock(&c->lock);
188262f27b2SOleksandr Tymoshenko }
189262f27b2SOleksandr Tymoshenko 
190262f27b2SOleksandr Tymoshenko static void
_completion_claim(struct completion * c)191262f27b2SOleksandr Tymoshenko _completion_claim(struct completion *c)
192262f27b2SOleksandr Tymoshenko {
193262f27b2SOleksandr Tymoshenko 
194262f27b2SOleksandr Tymoshenko 	KASSERT(mtx_owned(&c->lock),
195262f27b2SOleksandr Tymoshenko 	    ("_completion_claim should be called with acquired lock"));
196262f27b2SOleksandr Tymoshenko 	KASSERT(c->done != 0, ("_completion_claim on non-waited completion"));
197262f27b2SOleksandr Tymoshenko 	if (c->done > 0)
198262f27b2SOleksandr Tymoshenko 		c->done--;
199262f27b2SOleksandr Tymoshenko 	else
200262f27b2SOleksandr Tymoshenko 		KASSERT(c->done == -1, ("Invalid value of c->done: %d", c->done));
201262f27b2SOleksandr Tymoshenko }
202262f27b2SOleksandr Tymoshenko 
203262f27b2SOleksandr Tymoshenko void
wait_for_completion(struct completion * c)204262f27b2SOleksandr Tymoshenko wait_for_completion(struct completion *c)
205262f27b2SOleksandr Tymoshenko {
206262f27b2SOleksandr Tymoshenko 	mtx_lock(&c->lock);
207262f27b2SOleksandr Tymoshenko 	if (!c->done)
208262f27b2SOleksandr Tymoshenko 		cv_wait(&c->cv, &c->lock);
209262f27b2SOleksandr Tymoshenko 	c->done--;
210262f27b2SOleksandr Tymoshenko 	mtx_unlock(&c->lock);
211262f27b2SOleksandr Tymoshenko }
212262f27b2SOleksandr Tymoshenko 
213262f27b2SOleksandr Tymoshenko int
try_wait_for_completion(struct completion * c)214262f27b2SOleksandr Tymoshenko try_wait_for_completion(struct completion *c)
215262f27b2SOleksandr Tymoshenko {
216262f27b2SOleksandr Tymoshenko 	int res = 0;
217262f27b2SOleksandr Tymoshenko 
218262f27b2SOleksandr Tymoshenko 	mtx_lock(&c->lock);
219262f27b2SOleksandr Tymoshenko 	if (!c->done)
220262f27b2SOleksandr Tymoshenko 		res = 1;
221262f27b2SOleksandr Tymoshenko 	else
222262f27b2SOleksandr Tymoshenko 		c->done--;
223262f27b2SOleksandr Tymoshenko 	mtx_unlock(&c->lock);
224262f27b2SOleksandr Tymoshenko 	return res == 0;
225262f27b2SOleksandr Tymoshenko }
226262f27b2SOleksandr Tymoshenko 
227262f27b2SOleksandr Tymoshenko int
wait_for_completion_interruptible_timeout(struct completion * c,unsigned long timeout)228262f27b2SOleksandr Tymoshenko wait_for_completion_interruptible_timeout(struct completion *c, unsigned long timeout)
229262f27b2SOleksandr Tymoshenko {
230262f27b2SOleksandr Tymoshenko 	int res = 0;
231262f27b2SOleksandr Tymoshenko 	unsigned long start, now;
232262f27b2SOleksandr Tymoshenko 	start = jiffies;
233262f27b2SOleksandr Tymoshenko 
234262f27b2SOleksandr Tymoshenko 	mtx_lock(&c->lock);
235262f27b2SOleksandr Tymoshenko 	while (c->done == 0) {
236262f27b2SOleksandr Tymoshenko 		res = cv_timedwait_sig(&c->cv, &c->lock, timeout);
237262f27b2SOleksandr Tymoshenko 		if (res)
238262f27b2SOleksandr Tymoshenko 			goto out;
239262f27b2SOleksandr Tymoshenko 		now = jiffies;
240262f27b2SOleksandr Tymoshenko 		if (timeout < (now - start)) {
241262f27b2SOleksandr Tymoshenko 			res = EWOULDBLOCK;
242262f27b2SOleksandr Tymoshenko 			goto out;
243262f27b2SOleksandr Tymoshenko 		}
244262f27b2SOleksandr Tymoshenko 
245262f27b2SOleksandr Tymoshenko 		timeout -= (now - start);
246262f27b2SOleksandr Tymoshenko 		start = now;
247262f27b2SOleksandr Tymoshenko 	}
248262f27b2SOleksandr Tymoshenko 
249262f27b2SOleksandr Tymoshenko 	_completion_claim(c);
250262f27b2SOleksandr Tymoshenko 	res = 0;
251262f27b2SOleksandr Tymoshenko 
252262f27b2SOleksandr Tymoshenko out:
253262f27b2SOleksandr Tymoshenko 	mtx_unlock(&c->lock);
254262f27b2SOleksandr Tymoshenko 
255262f27b2SOleksandr Tymoshenko 	if (res == EWOULDBLOCK) {
256262f27b2SOleksandr Tymoshenko 		return 0;
257262f27b2SOleksandr Tymoshenko 	} else if ((res == EINTR) || (res == ERESTART)) {
258262f27b2SOleksandr Tymoshenko 		return -ERESTART;
259262f27b2SOleksandr Tymoshenko 	} else {
260262f27b2SOleksandr Tymoshenko 		KASSERT((res == 0), ("res = %d", res));
261262f27b2SOleksandr Tymoshenko 		return timeout;
262262f27b2SOleksandr Tymoshenko 	}
263262f27b2SOleksandr Tymoshenko }
264262f27b2SOleksandr Tymoshenko 
265262f27b2SOleksandr Tymoshenko int
wait_for_completion_interruptible(struct completion * c)266262f27b2SOleksandr Tymoshenko wait_for_completion_interruptible(struct completion *c)
267262f27b2SOleksandr Tymoshenko {
268262f27b2SOleksandr Tymoshenko 	int res = 0;
269262f27b2SOleksandr Tymoshenko 
270262f27b2SOleksandr Tymoshenko 	mtx_lock(&c->lock);
271262f27b2SOleksandr Tymoshenko 	while (c->done == 0) {
272262f27b2SOleksandr Tymoshenko 		res = cv_wait_sig(&c->cv, &c->lock);
273262f27b2SOleksandr Tymoshenko 		if (res)
274262f27b2SOleksandr Tymoshenko 			goto out;
275262f27b2SOleksandr Tymoshenko 	}
276262f27b2SOleksandr Tymoshenko 
277262f27b2SOleksandr Tymoshenko 	_completion_claim(c);
278262f27b2SOleksandr Tymoshenko 
279262f27b2SOleksandr Tymoshenko out:
280262f27b2SOleksandr Tymoshenko 	mtx_unlock(&c->lock);
281262f27b2SOleksandr Tymoshenko 
282262f27b2SOleksandr Tymoshenko 	if ((res == EINTR) || (res == ERESTART))
283262f27b2SOleksandr Tymoshenko 		res = -ERESTART;
284262f27b2SOleksandr Tymoshenko 	return res;
285262f27b2SOleksandr Tymoshenko }
286262f27b2SOleksandr Tymoshenko 
287262f27b2SOleksandr Tymoshenko int
wait_for_completion_killable(struct completion * c)288262f27b2SOleksandr Tymoshenko wait_for_completion_killable(struct completion *c)
289262f27b2SOleksandr Tymoshenko {
290262f27b2SOleksandr Tymoshenko 
291262f27b2SOleksandr Tymoshenko 	return wait_for_completion_interruptible(c);
292262f27b2SOleksandr Tymoshenko }
293262f27b2SOleksandr Tymoshenko 
294262f27b2SOleksandr Tymoshenko /*
295262f27b2SOleksandr Tymoshenko  * Semaphore API
296262f27b2SOleksandr Tymoshenko  */
297262f27b2SOleksandr Tymoshenko 
sema_sysinit(void * arg)298262f27b2SOleksandr Tymoshenko void sema_sysinit(void *arg)
299262f27b2SOleksandr Tymoshenko {
300262f27b2SOleksandr Tymoshenko 	struct semaphore *s = arg;
301262f27b2SOleksandr Tymoshenko 
302262f27b2SOleksandr Tymoshenko 	_sema_init(s, 1);
303262f27b2SOleksandr Tymoshenko }
304262f27b2SOleksandr Tymoshenko 
305262f27b2SOleksandr Tymoshenko void
_sema_init(struct semaphore * s,int value)306262f27b2SOleksandr Tymoshenko _sema_init(struct semaphore *s, int value)
307262f27b2SOleksandr Tymoshenko {
308262f27b2SOleksandr Tymoshenko 	bzero(s, sizeof(*s));
309262f27b2SOleksandr Tymoshenko 	mtx_init(&s->mtx, "sema lock", "VCHIQ sepmaphore backing lock",
310262f27b2SOleksandr Tymoshenko 		MTX_DEF | MTX_NOWITNESS | MTX_QUIET);
311262f27b2SOleksandr Tymoshenko 	cv_init(&s->cv, "sema cv");
312262f27b2SOleksandr Tymoshenko 	s->value = value;
313262f27b2SOleksandr Tymoshenko }
314262f27b2SOleksandr Tymoshenko 
315262f27b2SOleksandr Tymoshenko void
_sema_destroy(struct semaphore * s)316262f27b2SOleksandr Tymoshenko _sema_destroy(struct semaphore *s)
317262f27b2SOleksandr Tymoshenko {
318262f27b2SOleksandr Tymoshenko 	mtx_destroy(&s->mtx);
319262f27b2SOleksandr Tymoshenko 	cv_destroy(&s->cv);
320262f27b2SOleksandr Tymoshenko }
321262f27b2SOleksandr Tymoshenko 
322262f27b2SOleksandr Tymoshenko void
down(struct semaphore * s)323262f27b2SOleksandr Tymoshenko down(struct semaphore *s)
324262f27b2SOleksandr Tymoshenko {
325262f27b2SOleksandr Tymoshenko 
326262f27b2SOleksandr Tymoshenko 	mtx_lock(&s->mtx);
327262f27b2SOleksandr Tymoshenko 	while (s->value == 0) {
328262f27b2SOleksandr Tymoshenko 		s->waiters++;
329262f27b2SOleksandr Tymoshenko 		cv_wait(&s->cv, &s->mtx);
330262f27b2SOleksandr Tymoshenko 		s->waiters--;
331262f27b2SOleksandr Tymoshenko 	}
332262f27b2SOleksandr Tymoshenko 
333262f27b2SOleksandr Tymoshenko 	s->value--;
334262f27b2SOleksandr Tymoshenko 	mtx_unlock(&s->mtx);
335262f27b2SOleksandr Tymoshenko }
336262f27b2SOleksandr Tymoshenko 
337262f27b2SOleksandr Tymoshenko int
down_interruptible(struct semaphore * s)338262f27b2SOleksandr Tymoshenko down_interruptible(struct semaphore *s)
339262f27b2SOleksandr Tymoshenko {
340262f27b2SOleksandr Tymoshenko 	int ret ;
341262f27b2SOleksandr Tymoshenko 
342262f27b2SOleksandr Tymoshenko 	ret = 0;
343262f27b2SOleksandr Tymoshenko 
344262f27b2SOleksandr Tymoshenko 	mtx_lock(&s->mtx);
345262f27b2SOleksandr Tymoshenko 
346262f27b2SOleksandr Tymoshenko 	while (s->value == 0) {
347262f27b2SOleksandr Tymoshenko 		s->waiters++;
348262f27b2SOleksandr Tymoshenko 		ret = cv_wait_sig(&s->cv, &s->mtx);
349262f27b2SOleksandr Tymoshenko 		s->waiters--;
350262f27b2SOleksandr Tymoshenko 
351262f27b2SOleksandr Tymoshenko 		if (ret == EINTR) {
352262f27b2SOleksandr Tymoshenko 			mtx_unlock(&s->mtx);
353262f27b2SOleksandr Tymoshenko 			return (-EINTR);
354262f27b2SOleksandr Tymoshenko 		}
355262f27b2SOleksandr Tymoshenko 
356262f27b2SOleksandr Tymoshenko 		if (ret == ERESTART)
357262f27b2SOleksandr Tymoshenko 			continue;
358262f27b2SOleksandr Tymoshenko 	}
359262f27b2SOleksandr Tymoshenko 
360262f27b2SOleksandr Tymoshenko 	s->value--;
361262f27b2SOleksandr Tymoshenko 	mtx_unlock(&s->mtx);
362262f27b2SOleksandr Tymoshenko 
363262f27b2SOleksandr Tymoshenko 	return (0);
364262f27b2SOleksandr Tymoshenko }
365262f27b2SOleksandr Tymoshenko 
366262f27b2SOleksandr Tymoshenko int
down_trylock(struct semaphore * s)367262f27b2SOleksandr Tymoshenko down_trylock(struct semaphore *s)
368262f27b2SOleksandr Tymoshenko {
369262f27b2SOleksandr Tymoshenko 	int ret;
370262f27b2SOleksandr Tymoshenko 
371262f27b2SOleksandr Tymoshenko 	ret = 0;
372262f27b2SOleksandr Tymoshenko 
373262f27b2SOleksandr Tymoshenko 	mtx_lock(&s->mtx);
374262f27b2SOleksandr Tymoshenko 
375262f27b2SOleksandr Tymoshenko 	if (s->value > 0) {
376262f27b2SOleksandr Tymoshenko 		/* Success. */
377262f27b2SOleksandr Tymoshenko 		s->value--;
378262f27b2SOleksandr Tymoshenko 		ret = 0;
379262f27b2SOleksandr Tymoshenko 	} else {
380262f27b2SOleksandr Tymoshenko 		ret = -EAGAIN;
381262f27b2SOleksandr Tymoshenko 	}
382262f27b2SOleksandr Tymoshenko 
383262f27b2SOleksandr Tymoshenko 	mtx_unlock(&s->mtx);
384262f27b2SOleksandr Tymoshenko 
385262f27b2SOleksandr Tymoshenko 	return (ret);
386262f27b2SOleksandr Tymoshenko }
387262f27b2SOleksandr Tymoshenko 
388262f27b2SOleksandr Tymoshenko void
up(struct semaphore * s)389262f27b2SOleksandr Tymoshenko up(struct semaphore *s)
390262f27b2SOleksandr Tymoshenko {
391262f27b2SOleksandr Tymoshenko 	mtx_lock(&s->mtx);
392262f27b2SOleksandr Tymoshenko 	s->value++;
393262f27b2SOleksandr Tymoshenko 	if (s->waiters && s->value > 0)
394262f27b2SOleksandr Tymoshenko 		cv_signal(&s->cv);
395262f27b2SOleksandr Tymoshenko 
396262f27b2SOleksandr Tymoshenko 	mtx_unlock(&s->mtx);
397262f27b2SOleksandr Tymoshenko }
398262f27b2SOleksandr Tymoshenko 
399262f27b2SOleksandr Tymoshenko /*
400262f27b2SOleksandr Tymoshenko  * Logging API
401262f27b2SOleksandr Tymoshenko  */
402262f27b2SOleksandr Tymoshenko void
rlprintf(int pps,const char * fmt,...)403262f27b2SOleksandr Tymoshenko rlprintf(int pps, const char *fmt, ...)
404262f27b2SOleksandr Tymoshenko {
405262f27b2SOleksandr Tymoshenko 	va_list ap;
406262f27b2SOleksandr Tymoshenko 	static struct timeval last_printf;
407262f27b2SOleksandr Tymoshenko 	static int count;
408262f27b2SOleksandr Tymoshenko 
409262f27b2SOleksandr Tymoshenko 	if (ppsratecheck(&last_printf, &count, pps)) {
410262f27b2SOleksandr Tymoshenko 		va_start(ap, fmt);
411262f27b2SOleksandr Tymoshenko 		vprintf(fmt, ap);
412262f27b2SOleksandr Tymoshenko 		va_end(ap);
413262f27b2SOleksandr Tymoshenko 	}
414262f27b2SOleksandr Tymoshenko }
415262f27b2SOleksandr Tymoshenko 
416262f27b2SOleksandr Tymoshenko void
device_rlprintf(int pps,device_t dev,const char * fmt,...)417262f27b2SOleksandr Tymoshenko device_rlprintf(int pps, device_t dev, const char *fmt, ...)
418262f27b2SOleksandr Tymoshenko {
419262f27b2SOleksandr Tymoshenko 	va_list ap;
420262f27b2SOleksandr Tymoshenko 	static struct timeval last_printf;
421262f27b2SOleksandr Tymoshenko 	static int count;
422262f27b2SOleksandr Tymoshenko 
423262f27b2SOleksandr Tymoshenko 	if (ppsratecheck(&last_printf, &count, pps)) {
424262f27b2SOleksandr Tymoshenko 		va_start(ap, fmt);
425262f27b2SOleksandr Tymoshenko 		device_print_prettyname(dev);
426262f27b2SOleksandr Tymoshenko 		vprintf(fmt, ap);
427262f27b2SOleksandr Tymoshenko 		va_end(ap);
428262f27b2SOleksandr Tymoshenko 	}
429262f27b2SOleksandr Tymoshenko }
430262f27b2SOleksandr Tymoshenko 
431262f27b2SOleksandr Tymoshenko /*
432262f27b2SOleksandr Tymoshenko  * Signals API
433262f27b2SOleksandr Tymoshenko  */
434262f27b2SOleksandr Tymoshenko 
435262f27b2SOleksandr Tymoshenko void
flush_signals(VCHIQ_THREAD_T thr)436262f27b2SOleksandr Tymoshenko flush_signals(VCHIQ_THREAD_T thr)
437262f27b2SOleksandr Tymoshenko {
438262f27b2SOleksandr Tymoshenko 	printf("Implement ME: %s\n", __func__);
439262f27b2SOleksandr Tymoshenko }
440262f27b2SOleksandr Tymoshenko 
441262f27b2SOleksandr Tymoshenko int
fatal_signal_pending(VCHIQ_THREAD_T thr)442262f27b2SOleksandr Tymoshenko fatal_signal_pending(VCHIQ_THREAD_T thr)
443262f27b2SOleksandr Tymoshenko {
444262f27b2SOleksandr Tymoshenko 	printf("Implement ME: %s\n", __func__);
445262f27b2SOleksandr Tymoshenko 	return (0);
446262f27b2SOleksandr Tymoshenko }
447262f27b2SOleksandr Tymoshenko 
448262f27b2SOleksandr Tymoshenko /*
449262f27b2SOleksandr Tymoshenko  * kthread API
450262f27b2SOleksandr Tymoshenko  */
451262f27b2SOleksandr Tymoshenko 
452262f27b2SOleksandr Tymoshenko /*
453262f27b2SOleksandr Tymoshenko  *  This is a hack to avoid memory leak
454262f27b2SOleksandr Tymoshenko  */
455262f27b2SOleksandr Tymoshenko #define MAX_THREAD_DATA_SLOTS	32
456262f27b2SOleksandr Tymoshenko static int thread_data_slot = 0;
457262f27b2SOleksandr Tymoshenko 
458262f27b2SOleksandr Tymoshenko struct thread_data {
459262f27b2SOleksandr Tymoshenko 	void *data;
460262f27b2SOleksandr Tymoshenko 	int (*threadfn)(void *);
461262f27b2SOleksandr Tymoshenko };
462262f27b2SOleksandr Tymoshenko 
463262f27b2SOleksandr Tymoshenko static struct thread_data thread_slots[MAX_THREAD_DATA_SLOTS];
464262f27b2SOleksandr Tymoshenko 
465262f27b2SOleksandr Tymoshenko static void
kthread_wrapper(void * data)466262f27b2SOleksandr Tymoshenko kthread_wrapper(void *data)
467262f27b2SOleksandr Tymoshenko {
468262f27b2SOleksandr Tymoshenko 	struct thread_data *slot;
469262f27b2SOleksandr Tymoshenko 
470262f27b2SOleksandr Tymoshenko 	slot = data;
471262f27b2SOleksandr Tymoshenko 	slot->threadfn(slot->data);
472262f27b2SOleksandr Tymoshenko }
473262f27b2SOleksandr Tymoshenko 
474262f27b2SOleksandr Tymoshenko VCHIQ_THREAD_T
vchiq_thread_create(int (* threadfn)(void * data),void * data,const char namefmt[],...)475262f27b2SOleksandr Tymoshenko vchiq_thread_create(int (*threadfn)(void *data),
476262f27b2SOleksandr Tymoshenko 	void *data,
477262f27b2SOleksandr Tymoshenko 	const char namefmt[], ...)
478262f27b2SOleksandr Tymoshenko {
479262f27b2SOleksandr Tymoshenko 	VCHIQ_THREAD_T newp;
480262f27b2SOleksandr Tymoshenko 	va_list ap;
481262f27b2SOleksandr Tymoshenko 	char name[MAXCOMLEN+1];
482262f27b2SOleksandr Tymoshenko 	struct thread_data *slot;
483262f27b2SOleksandr Tymoshenko 
484262f27b2SOleksandr Tymoshenko 	if (thread_data_slot >= MAX_THREAD_DATA_SLOTS) {
485262f27b2SOleksandr Tymoshenko 		printf("kthread_create: out of thread data slots\n");
486262f27b2SOleksandr Tymoshenko 		return (NULL);
487262f27b2SOleksandr Tymoshenko 	}
488262f27b2SOleksandr Tymoshenko 
489262f27b2SOleksandr Tymoshenko 	slot = &thread_slots[thread_data_slot];
490262f27b2SOleksandr Tymoshenko 	slot->data = data;
491262f27b2SOleksandr Tymoshenko 	slot->threadfn = threadfn;
492262f27b2SOleksandr Tymoshenko 
493262f27b2SOleksandr Tymoshenko 	va_start(ap, namefmt);
494262f27b2SOleksandr Tymoshenko 	vsnprintf(name, sizeof(name), namefmt, ap);
495262f27b2SOleksandr Tymoshenko 	va_end(ap);
496262f27b2SOleksandr Tymoshenko 
497262f27b2SOleksandr Tymoshenko 	newp = NULL;
498262f27b2SOleksandr Tymoshenko 	if (kproc_create(kthread_wrapper, (void*)slot, &newp, 0, 0,
499262f27b2SOleksandr Tymoshenko 	    "%s", name) != 0) {
500262f27b2SOleksandr Tymoshenko 		/* Just to be sure */
501262f27b2SOleksandr Tymoshenko 		newp = NULL;
502262f27b2SOleksandr Tymoshenko 	}
503262f27b2SOleksandr Tymoshenko 	else
504262f27b2SOleksandr Tymoshenko 		thread_data_slot++;
505262f27b2SOleksandr Tymoshenko 
506262f27b2SOleksandr Tymoshenko 	return newp;
507262f27b2SOleksandr Tymoshenko }
508262f27b2SOleksandr Tymoshenko 
509262f27b2SOleksandr Tymoshenko void
set_user_nice(VCHIQ_THREAD_T thr,int nice)510262f27b2SOleksandr Tymoshenko set_user_nice(VCHIQ_THREAD_T thr, int nice)
511262f27b2SOleksandr Tymoshenko {
512262f27b2SOleksandr Tymoshenko 	/* NOOP */
513262f27b2SOleksandr Tymoshenko }
514262f27b2SOleksandr Tymoshenko 
515262f27b2SOleksandr Tymoshenko void
wake_up_process(VCHIQ_THREAD_T thr)516262f27b2SOleksandr Tymoshenko wake_up_process(VCHIQ_THREAD_T thr)
517262f27b2SOleksandr Tymoshenko {
518262f27b2SOleksandr Tymoshenko 	/* NOOP */
519262f27b2SOleksandr Tymoshenko }
520262f27b2SOleksandr Tymoshenko 
521262f27b2SOleksandr Tymoshenko void
bcm_mbox_write(int channel,uint32_t data)522262f27b2SOleksandr Tymoshenko bcm_mbox_write(int channel, uint32_t data)
523262f27b2SOleksandr Tymoshenko {
524262f27b2SOleksandr Tymoshenko 	device_t mbox;
525262f27b2SOleksandr Tymoshenko 
526262f27b2SOleksandr Tymoshenko         mbox = devclass_get_device(devclass_find("mbox"), 0);
527262f27b2SOleksandr Tymoshenko 
528262f27b2SOleksandr Tymoshenko         if (mbox)
529262f27b2SOleksandr Tymoshenko                 MBOX_WRITE(mbox, channel, data);
530262f27b2SOleksandr Tymoshenko }
531