1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/types.h>
19
20
21#include <dspbridge/dbdefs.h>
22
23
24#include <dspbridge/sync.h>
25
26
27#include <dspbridge/dev.h>
28
29
30#include <dspbridge/io_sm.h>
31
32
33#include <_msg_sm.h>
34#include <dspbridge/dspmsg.h>
35
36
37static int add_new_msg(struct list_head *msg_list);
38static void delete_msg_mgr(struct msg_mgr *hmsg_mgr);
39static void delete_msg_queue(struct msg_queue *msg_queue_obj, u32 num_to_dsp);
40static void free_msg_list(struct list_head *msg_list);
41
42
43
44
45
46
47int bridge_msg_create(struct msg_mgr **msg_man,
48 struct dev_object *hdev_obj,
49 msg_onexit msg_callback)
50{
51 struct msg_mgr *msg_mgr_obj;
52 struct io_mgr *hio_mgr;
53 int status = 0;
54
55 if (!msg_man || !msg_callback || !hdev_obj)
56 return -EFAULT;
57
58 dev_get_io_mgr(hdev_obj, &hio_mgr);
59 if (!hio_mgr)
60 return -EFAULT;
61
62 *msg_man = NULL;
63
64 msg_mgr_obj = kzalloc(sizeof(struct msg_mgr), GFP_KERNEL);
65 if (!msg_mgr_obj)
66 return -ENOMEM;
67
68 msg_mgr_obj->on_exit = msg_callback;
69 msg_mgr_obj->iomgr = hio_mgr;
70
71 INIT_LIST_HEAD(&msg_mgr_obj->queue_list);
72
73
74
75
76
77 INIT_LIST_HEAD(&msg_mgr_obj->msg_free_list);
78 INIT_LIST_HEAD(&msg_mgr_obj->msg_used_list);
79 spin_lock_init(&msg_mgr_obj->msg_mgr_lock);
80
81
82
83
84
85 msg_mgr_obj->sync_event =
86 kzalloc(sizeof(struct sync_object), GFP_KERNEL);
87 if (!msg_mgr_obj->sync_event) {
88 kfree(msg_mgr_obj);
89 return -ENOMEM;
90 }
91 sync_init_event(msg_mgr_obj->sync_event);
92
93 *msg_man = msg_mgr_obj;
94
95 return status;
96}
97
98
99
100
101
102
103int bridge_msg_create_queue(struct msg_mgr *hmsg_mgr, struct msg_queue **msgq,
104 u32 msgq_id, u32 max_msgs, void *arg)
105{
106 u32 i;
107 u32 num_allocated = 0;
108 struct msg_queue *msg_q;
109 int status = 0;
110
111 if (!hmsg_mgr || msgq == NULL)
112 return -EFAULT;
113
114 *msgq = NULL;
115
116 msg_q = kzalloc(sizeof(struct msg_queue), GFP_KERNEL);
117 if (!msg_q)
118 return -ENOMEM;
119
120 msg_q->max_msgs = max_msgs;
121 msg_q->msg_mgr = hmsg_mgr;
122 msg_q->arg = arg;
123 msg_q->msgq_id = msgq_id;
124
125 INIT_LIST_HEAD(&msg_q->msg_free_list);
126 INIT_LIST_HEAD(&msg_q->msg_used_list);
127
128
129
130 msg_q->sync_event = kzalloc(sizeof(struct sync_object), GFP_KERNEL);
131 if (!msg_q->sync_event) {
132 status = -ENOMEM;
133 goto out_err;
134
135 }
136 sync_init_event(msg_q->sync_event);
137
138
139 msg_q->ntfy_obj = kmalloc(sizeof(struct ntfy_object), GFP_KERNEL);
140 if (!msg_q->ntfy_obj) {
141 status = -ENOMEM;
142 goto out_err;
143 }
144 ntfy_init(msg_q->ntfy_obj);
145
146
147
148
149
150
151 msg_q->sync_done = kzalloc(sizeof(struct sync_object), GFP_KERNEL);
152 if (!msg_q->sync_done) {
153 status = -ENOMEM;
154 goto out_err;
155 }
156 sync_init_event(msg_q->sync_done);
157
158 msg_q->sync_done_ack = kzalloc(sizeof(struct sync_object), GFP_KERNEL);
159 if (!msg_q->sync_done_ack) {
160 status = -ENOMEM;
161 goto out_err;
162 }
163 sync_init_event(msg_q->sync_done_ack);
164
165
166 spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
167
168 for (i = 0; i < max_msgs && !status; i++) {
169 status = add_new_msg(&hmsg_mgr->msg_free_list);
170 if (!status) {
171 num_allocated++;
172 status = add_new_msg(&msg_q->msg_free_list);
173 }
174 }
175 if (status) {
176 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
177 goto out_err;
178 }
179
180 list_add_tail(&msg_q->list_elem, &hmsg_mgr->queue_list);
181 *msgq = msg_q;
182
183 if (!list_empty(&hmsg_mgr->msg_free_list))
184 sync_set_event(hmsg_mgr->sync_event);
185
186
187 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
188
189 return 0;
190out_err:
191 delete_msg_queue(msg_q, num_allocated);
192 return status;
193}
194
195
196
197
198
199void bridge_msg_delete(struct msg_mgr *hmsg_mgr)
200{
201 delete_msg_mgr(hmsg_mgr);
202}
203
204
205
206
207
208void bridge_msg_delete_queue(struct msg_queue *msg_queue_obj)
209{
210 struct msg_mgr *hmsg_mgr;
211 u32 io_msg_pend;
212
213 if (!msg_queue_obj || !msg_queue_obj->msg_mgr)
214 return;
215
216 hmsg_mgr = msg_queue_obj->msg_mgr;
217 msg_queue_obj->done = true;
218
219 io_msg_pend = msg_queue_obj->io_msg_pend;
220 while (io_msg_pend) {
221
222 sync_set_event(msg_queue_obj->sync_done);
223
224 sync_wait_on_event(msg_queue_obj->sync_done_ack, SYNC_INFINITE);
225 io_msg_pend = msg_queue_obj->io_msg_pend;
226 }
227
228 spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
229 list_del(&msg_queue_obj->list_elem);
230
231 delete_msg_queue(msg_queue_obj, msg_queue_obj->max_msgs);
232 if (list_empty(&hmsg_mgr->msg_free_list))
233 sync_reset_event(hmsg_mgr->sync_event);
234 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
235}
236
237
238
239
240
241int bridge_msg_get(struct msg_queue *msg_queue_obj,
242 struct dsp_msg *pmsg, u32 utimeout)
243{
244 struct msg_frame *msg_frame_obj;
245 struct msg_mgr *hmsg_mgr;
246 struct sync_object *syncs[2];
247 u32 index;
248 int status = 0;
249
250 if (!msg_queue_obj || pmsg == NULL)
251 return -ENOMEM;
252
253 hmsg_mgr = msg_queue_obj->msg_mgr;
254
255 spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
256
257 if (!list_empty(&msg_queue_obj->msg_used_list)) {
258 msg_frame_obj = list_first_entry(&msg_queue_obj->msg_used_list,
259 struct msg_frame, list_elem);
260 list_del(&msg_frame_obj->list_elem);
261 *pmsg = msg_frame_obj->msg_data.msg;
262 list_add_tail(&msg_frame_obj->list_elem,
263 &msg_queue_obj->msg_free_list);
264 if (list_empty(&msg_queue_obj->msg_used_list))
265 sync_reset_event(msg_queue_obj->sync_event);
266 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
267 return 0;
268 }
269
270 if (msg_queue_obj->done) {
271 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
272 return -EPERM;
273 }
274 msg_queue_obj->io_msg_pend++;
275 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
276
277
278
279
280
281
282 syncs[0] = msg_queue_obj->sync_event;
283 syncs[1] = msg_queue_obj->sync_done;
284 status = sync_wait_on_multiple_events(syncs, 2, utimeout, &index);
285
286 spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
287 if (msg_queue_obj->done) {
288 msg_queue_obj->io_msg_pend--;
289 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
290
291
292
293
294 sync_set_event(msg_queue_obj->sync_done_ack);
295 return -EPERM;
296 }
297 if (!status && !list_empty(&msg_queue_obj->msg_used_list)) {
298
299 msg_frame_obj = list_first_entry(&msg_queue_obj->msg_used_list,
300 struct msg_frame, list_elem);
301 list_del(&msg_frame_obj->list_elem);
302
303 *pmsg = msg_frame_obj->msg_data.msg;
304 list_add_tail(&msg_frame_obj->list_elem,
305 &msg_queue_obj->msg_free_list);
306 }
307 msg_queue_obj->io_msg_pend--;
308
309 if (!list_empty(&msg_queue_obj->msg_used_list))
310 sync_set_event(msg_queue_obj->sync_event);
311
312 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
313
314 return status;
315}
316
317
318
319
320
321int bridge_msg_put(struct msg_queue *msg_queue_obj,
322 const struct dsp_msg *pmsg, u32 utimeout)
323{
324 struct msg_frame *msg_frame_obj;
325 struct msg_mgr *hmsg_mgr;
326 struct sync_object *syncs[2];
327 u32 index;
328 int status;
329
330 if (!msg_queue_obj || !pmsg || !msg_queue_obj->msg_mgr)
331 return -EFAULT;
332
333 hmsg_mgr = msg_queue_obj->msg_mgr;
334
335 spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
336
337
338 if (!list_empty(&hmsg_mgr->msg_free_list)) {
339 msg_frame_obj = list_first_entry(&hmsg_mgr->msg_free_list,
340 struct msg_frame, list_elem);
341 list_del(&msg_frame_obj->list_elem);
342 msg_frame_obj->msg_data.msg = *pmsg;
343 msg_frame_obj->msg_data.msgq_id =
344 msg_queue_obj->msgq_id;
345 list_add_tail(&msg_frame_obj->list_elem,
346 &hmsg_mgr->msg_used_list);
347 hmsg_mgr->msgs_pending++;
348
349 if (list_empty(&hmsg_mgr->msg_free_list))
350 sync_reset_event(hmsg_mgr->sync_event);
351
352
353 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
354
355 iosm_schedule(hmsg_mgr->iomgr);
356 return 0;
357 }
358
359 if (msg_queue_obj->done) {
360 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
361 return -EPERM;
362 }
363 msg_queue_obj->io_msg_pend++;
364
365 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
366
367
368 syncs[0] = hmsg_mgr->sync_event;
369 syncs[1] = msg_queue_obj->sync_done;
370 status = sync_wait_on_multiple_events(syncs, 2, utimeout, &index);
371 if (status)
372 return status;
373
374
375 spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
376 if (msg_queue_obj->done) {
377 msg_queue_obj->io_msg_pend--;
378
379 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
380
381
382
383
384 sync_set_event(msg_queue_obj->sync_done_ack);
385 return -EPERM;
386 }
387
388 if (list_empty(&hmsg_mgr->msg_free_list)) {
389 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
390 return -EFAULT;
391 }
392
393
394 msg_frame_obj = list_first_entry(&hmsg_mgr->msg_free_list,
395 struct msg_frame, list_elem);
396
397
398
399
400 list_del(&msg_frame_obj->list_elem);
401 msg_frame_obj->msg_data.msg = *pmsg;
402 msg_frame_obj->msg_data.msgq_id = msg_queue_obj->msgq_id;
403 list_add_tail(&msg_frame_obj->list_elem, &hmsg_mgr->msg_used_list);
404 hmsg_mgr->msgs_pending++;
405
406
407
408
409 iosm_schedule(hmsg_mgr->iomgr);
410
411 msg_queue_obj->io_msg_pend--;
412
413 if (!list_empty(&hmsg_mgr->msg_free_list))
414 sync_set_event(hmsg_mgr->sync_event);
415
416
417 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
418
419 return 0;
420}
421
422
423
424
425int bridge_msg_register_notify(struct msg_queue *msg_queue_obj,
426 u32 event_mask, u32 notify_type,
427 struct dsp_notification *hnotification)
428{
429 int status = 0;
430
431 if (!msg_queue_obj || !hnotification) {
432 status = -ENOMEM;
433 goto func_end;
434 }
435
436 if (!(event_mask == DSP_NODEMESSAGEREADY || event_mask == 0)) {
437 status = -EPERM;
438 goto func_end;
439 }
440
441 if (notify_type != DSP_SIGNALEVENT) {
442 status = -EBADR;
443 goto func_end;
444 }
445
446 if (event_mask)
447 status = ntfy_register(msg_queue_obj->ntfy_obj, hnotification,
448 event_mask, notify_type);
449 else
450 status = ntfy_unregister(msg_queue_obj->ntfy_obj,
451 hnotification);
452
453 if (status == -EINVAL) {
454
455
456
457 status = 0;
458 }
459func_end:
460 return status;
461}
462
463
464
465
466void bridge_msg_set_queue_id(struct msg_queue *msg_queue_obj, u32 msgq_id)
467{
468
469
470
471
472
473
474
475 if (msg_queue_obj)
476 msg_queue_obj->msgq_id = msgq_id;
477}
478
479
480
481
482
483static int add_new_msg(struct list_head *msg_list)
484{
485 struct msg_frame *pmsg;
486
487 pmsg = kzalloc(sizeof(struct msg_frame), GFP_ATOMIC);
488 if (!pmsg)
489 return -ENOMEM;
490
491 list_add_tail(&pmsg->list_elem, msg_list);
492
493 return 0;
494}
495
496
497
498
499static void delete_msg_mgr(struct msg_mgr *hmsg_mgr)
500{
501 if (!hmsg_mgr)
502 return;
503
504
505 free_msg_list(&hmsg_mgr->msg_free_list);
506 free_msg_list(&hmsg_mgr->msg_used_list);
507 kfree(hmsg_mgr->sync_event);
508 kfree(hmsg_mgr);
509}
510
511
512
513
514static void delete_msg_queue(struct msg_queue *msg_queue_obj, u32 num_to_dsp)
515{
516 struct msg_mgr *hmsg_mgr;
517 struct msg_frame *pmsg, *tmp;
518 u32 i;
519
520 if (!msg_queue_obj || !msg_queue_obj->msg_mgr)
521 return;
522
523 hmsg_mgr = msg_queue_obj->msg_mgr;
524
525
526 i = 0;
527 list_for_each_entry_safe(pmsg, tmp, &hmsg_mgr->msg_free_list,
528 list_elem) {
529 list_del(&pmsg->list_elem);
530 kfree(pmsg);
531 if (i++ >= num_to_dsp)
532 break;
533 }
534
535 free_msg_list(&msg_queue_obj->msg_free_list);
536 free_msg_list(&msg_queue_obj->msg_used_list);
537
538 if (msg_queue_obj->ntfy_obj) {
539 ntfy_delete(msg_queue_obj->ntfy_obj);
540 kfree(msg_queue_obj->ntfy_obj);
541 }
542
543 kfree(msg_queue_obj->sync_event);
544 kfree(msg_queue_obj->sync_done);
545 kfree(msg_queue_obj->sync_done_ack);
546
547 kfree(msg_queue_obj);
548}
549
550
551
552
553static void free_msg_list(struct list_head *msg_list)
554{
555 struct msg_frame *pmsg, *tmp;
556
557 if (!msg_list)
558 return;
559
560 list_for_each_entry_safe(pmsg, tmp, msg_list, list_elem) {
561 list_del(&pmsg->list_elem);
562 kfree(pmsg);
563 }
564}
565