1 /*
2  * sync.c
3  *
4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5  *
6  * Synchronization services.
7  *
8  * Copyright (C) 2005-2006 Texas Instruments, Inc.
9  *
10  * This package is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  *
14  * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
16  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
17  */
18 
19 /*  ----------------------------------- Host OS */
20 #include <dspbridge/host_os.h>
21 
22 /*  ----------------------------------- This */
23 #include <dspbridge/sync.h>
24 #include <dspbridge/ntfy.h>
25 
26 DEFINE_SPINLOCK(sync_lock);
27 
28 /**
29  * sync_set_event() - set or signal and specified event
30  * @event:	Event to be set..
31  *
32  * set the @event, if there is an thread waiting for the event
33  * it will be waken up, this function only wakes one thread.
34  */
35 
sync_set_event(struct sync_object * event)36 void sync_set_event(struct sync_object *event)
37 {
38 	spin_lock_bh(&sync_lock);
39 	complete(&event->comp);
40 	if (event->multi_comp)
41 		complete(event->multi_comp);
42 	spin_unlock_bh(&sync_lock);
43 }
44 
45 /**
46  * sync_wait_on_multiple_events() - waits for multiple events to be set.
47  * @events:	Array of events to wait for them.
48  * @count:	number of elements of the array.
49  * @timeout	timeout on waiting for the evetns.
50  * @pu_index	index of the event set.
51  *
52  * This functios will wait until any of the array element is set or until
53  * timeout. In case of success the function will return 0 and
54  * @pu_index will store the index of the array element set or in case
55  * of timeout the function will return -ETIME or in case of
56  * interrupting by a signal it will return -EPERM.
57  */
58 
sync_wait_on_multiple_events(struct sync_object ** events,unsigned count,unsigned timeout,unsigned * index)59 int sync_wait_on_multiple_events(struct sync_object **events,
60 				     unsigned count, unsigned timeout,
61 				     unsigned *index)
62 {
63 	unsigned i;
64 	int status = -EPERM;
65 	struct completion m_comp;
66 
67 	init_completion(&m_comp);
68 
69 	if (SYNC_INFINITE == timeout)
70 		timeout = MAX_SCHEDULE_TIMEOUT;
71 
72 	spin_lock_bh(&sync_lock);
73 	for (i = 0; i < count; i++) {
74 		if (completion_done(&events[i]->comp)) {
75 			INIT_COMPLETION(events[i]->comp);
76 			*index = i;
77 			spin_unlock_bh(&sync_lock);
78 			status = 0;
79 			goto func_end;
80 		}
81 	}
82 
83 	for (i = 0; i < count; i++)
84 		events[i]->multi_comp = &m_comp;
85 
86 	spin_unlock_bh(&sync_lock);
87 
88 	if (!wait_for_completion_interruptible_timeout(&m_comp,
89 					msecs_to_jiffies(timeout)))
90 		status = -ETIME;
91 
92 	spin_lock_bh(&sync_lock);
93 	for (i = 0; i < count; i++) {
94 		if (completion_done(&events[i]->comp)) {
95 			INIT_COMPLETION(events[i]->comp);
96 			*index = i;
97 			status = 0;
98 		}
99 		events[i]->multi_comp = NULL;
100 	}
101 	spin_unlock_bh(&sync_lock);
102 func_end:
103 	return status;
104 }
105 
106 /**
107  * dsp_notifier_event() - callback function to nofity events
108  * @this:		pointer to itself struct notifier_block
109  * @event:	event to be notified.
110  * @data:		Currently not used.
111  *
112  */
dsp_notifier_event(struct notifier_block * this,unsigned long event,void * data)113 int dsp_notifier_event(struct notifier_block *this, unsigned long event,
114 							void *data)
115 {
116 	struct  ntfy_event *ne = container_of(this, struct ntfy_event,
117 							noti_block);
118 	if (ne->event & event)
119 		sync_set_event(&ne->sync_obj);
120 	return NOTIFY_OK;
121 }
122