USB: ftdi_sio: Add more identifiers
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / tidspbridge / core / msg_sm.c
blob94d9e04a22fa0f98ef70869e4949f9d74bece149
1 /*
2 * msg_sm.c
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6 * Implements upper edge functions for Bridge message module.
8 * Copyright (C) 2005-2006 Texas Instruments, Inc.
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.
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.
18 #include <linux/types.h>
20 /* ----------------------------------- DSP/BIOS Bridge */
21 #include <dspbridge/dbdefs.h>
23 /* ----------------------------------- Trace & Debug */
24 #include <dspbridge/dbc.h>
26 /* ----------------------------------- OS Adaptation Layer */
27 #include <dspbridge/sync.h>
29 /* ----------------------------------- Platform Manager */
30 #include <dspbridge/dev.h>
32 /* ----------------------------------- Others */
33 #include <dspbridge/io_sm.h>
35 /* ----------------------------------- This */
36 #include <_msg_sm.h>
37 #include <dspbridge/dspmsg.h>
39 /* ----------------------------------- Function Prototypes */
40 static int add_new_msg(struct list_head *msg_list);
41 static void delete_msg_mgr(struct msg_mgr *hmsg_mgr);
42 static void delete_msg_queue(struct msg_queue *msg_queue_obj, u32 num_to_dsp);
43 static void free_msg_list(struct list_head *msg_list);
46 * ======== bridge_msg_create ========
47 * Create an object to manage message queues. Only one of these objects
48 * can exist per device object.
50 int bridge_msg_create(struct msg_mgr **msg_man,
51 struct dev_object *hdev_obj,
52 msg_onexit msg_callback)
54 struct msg_mgr *msg_mgr_obj;
55 struct io_mgr *hio_mgr;
56 int status = 0;
58 if (!msg_man || !msg_callback || !hdev_obj)
59 return -EFAULT;
61 dev_get_io_mgr(hdev_obj, &hio_mgr);
62 if (!hio_mgr)
63 return -EFAULT;
65 *msg_man = NULL;
66 /* Allocate msg_ctrl manager object */
67 msg_mgr_obj = kzalloc(sizeof(struct msg_mgr), GFP_KERNEL);
68 if (!msg_mgr_obj)
69 return -ENOMEM;
71 msg_mgr_obj->on_exit = msg_callback;
72 msg_mgr_obj->iomgr = hio_mgr;
73 /* List of MSG_QUEUEs */
74 INIT_LIST_HEAD(&msg_mgr_obj->queue_list);
76 * Queues of message frames for messages to the DSP. Message
77 * frames will only be added to the free queue when a
78 * msg_queue object is created.
80 INIT_LIST_HEAD(&msg_mgr_obj->msg_free_list);
81 INIT_LIST_HEAD(&msg_mgr_obj->msg_used_list);
82 spin_lock_init(&msg_mgr_obj->msg_mgr_lock);
85 * Create an event to be used by bridge_msg_put() in waiting
86 * for an available free frame from the message manager.
88 msg_mgr_obj->sync_event =
89 kzalloc(sizeof(struct sync_object), GFP_KERNEL);
90 if (!msg_mgr_obj->sync_event) {
91 kfree(msg_mgr_obj);
92 return -ENOMEM;
94 sync_init_event(msg_mgr_obj->sync_event);
96 *msg_man = msg_mgr_obj;
98 return status;
102 * ======== bridge_msg_create_queue ========
103 * Create a msg_queue for sending/receiving messages to/from a node
104 * on the DSP.
106 int bridge_msg_create_queue(struct msg_mgr *hmsg_mgr, struct msg_queue **msgq,
107 u32 msgq_id, u32 max_msgs, void *arg)
109 u32 i;
110 u32 num_allocated = 0;
111 struct msg_queue *msg_q;
112 int status = 0;
114 if (!hmsg_mgr || msgq == NULL)
115 return -EFAULT;
117 *msgq = NULL;
118 /* Allocate msg_queue object */
119 msg_q = kzalloc(sizeof(struct msg_queue), GFP_KERNEL);
120 if (!msg_q)
121 return -ENOMEM;
123 msg_q->max_msgs = max_msgs;
124 msg_q->msg_mgr = hmsg_mgr;
125 msg_q->arg = arg; /* Node handle */
126 msg_q->msgq_id = msgq_id; /* Node env (not valid yet) */
127 /* Queues of Message frames for messages from the DSP */
128 INIT_LIST_HEAD(&msg_q->msg_free_list);
129 INIT_LIST_HEAD(&msg_q->msg_used_list);
131 /* Create event that will be signalled when a message from
132 * the DSP is available. */
133 msg_q->sync_event = kzalloc(sizeof(struct sync_object), GFP_KERNEL);
134 if (!msg_q->sync_event) {
135 status = -ENOMEM;
136 goto out_err;
139 sync_init_event(msg_q->sync_event);
141 /* Create a notification list for message ready notification. */
142 msg_q->ntfy_obj = kmalloc(sizeof(struct ntfy_object), GFP_KERNEL);
143 if (!msg_q->ntfy_obj) {
144 status = -ENOMEM;
145 goto out_err;
147 ntfy_init(msg_q->ntfy_obj);
149 /* Create events that will be used to synchronize cleanup
150 * when the object is deleted. sync_done will be set to
151 * unblock threads in MSG_Put() or MSG_Get(). sync_done_ack
152 * will be set by the unblocked thread to signal that it
153 * is unblocked and will no longer reference the object. */
154 msg_q->sync_done = kzalloc(sizeof(struct sync_object), GFP_KERNEL);
155 if (!msg_q->sync_done) {
156 status = -ENOMEM;
157 goto out_err;
159 sync_init_event(msg_q->sync_done);
161 msg_q->sync_done_ack = kzalloc(sizeof(struct sync_object), GFP_KERNEL);
162 if (!msg_q->sync_done_ack) {
163 status = -ENOMEM;
164 goto out_err;
166 sync_init_event(msg_q->sync_done_ack);
168 /* Enter critical section */
169 spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
170 /* Initialize message frames and put in appropriate queues */
171 for (i = 0; i < max_msgs && !status; i++) {
172 status = add_new_msg(&hmsg_mgr->msg_free_list);
173 if (!status) {
174 num_allocated++;
175 status = add_new_msg(&msg_q->msg_free_list);
178 if (status) {
179 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
180 goto out_err;
183 list_add_tail(&msg_q->list_elem, &hmsg_mgr->queue_list);
184 *msgq = msg_q;
185 /* Signal that free frames are now available */
186 if (!list_empty(&hmsg_mgr->msg_free_list))
187 sync_set_event(hmsg_mgr->sync_event);
189 /* Exit critical section */
190 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
192 return 0;
193 out_err:
194 delete_msg_queue(msg_q, num_allocated);
195 return status;
199 * ======== bridge_msg_delete ========
200 * Delete a msg_ctrl manager allocated in bridge_msg_create().
202 void bridge_msg_delete(struct msg_mgr *hmsg_mgr)
204 if (hmsg_mgr)
205 delete_msg_mgr(hmsg_mgr);
209 * ======== bridge_msg_delete_queue ========
210 * Delete a msg_ctrl queue allocated in bridge_msg_create_queue.
212 void bridge_msg_delete_queue(struct msg_queue *msg_queue_obj)
214 struct msg_mgr *hmsg_mgr;
215 u32 io_msg_pend;
217 if (!msg_queue_obj || !msg_queue_obj->msg_mgr)
218 return;
220 hmsg_mgr = msg_queue_obj->msg_mgr;
221 msg_queue_obj->done = true;
222 /* Unblock all threads blocked in MSG_Get() or MSG_Put(). */
223 io_msg_pend = msg_queue_obj->io_msg_pend;
224 while (io_msg_pend) {
225 /* Unblock thread */
226 sync_set_event(msg_queue_obj->sync_done);
227 /* Wait for acknowledgement */
228 sync_wait_on_event(msg_queue_obj->sync_done_ack, SYNC_INFINITE);
229 io_msg_pend = msg_queue_obj->io_msg_pend;
231 /* Remove message queue from hmsg_mgr->queue_list */
232 spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
233 list_del(&msg_queue_obj->list_elem);
234 /* Free the message queue object */
235 delete_msg_queue(msg_queue_obj, msg_queue_obj->max_msgs);
236 if (list_empty(&hmsg_mgr->msg_free_list))
237 sync_reset_event(hmsg_mgr->sync_event);
238 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
242 * ======== bridge_msg_get ========
243 * Get a message from a msg_ctrl queue.
245 int bridge_msg_get(struct msg_queue *msg_queue_obj,
246 struct dsp_msg *pmsg, u32 utimeout)
248 struct msg_frame *msg_frame_obj;
249 struct msg_mgr *hmsg_mgr;
250 struct sync_object *syncs[2];
251 u32 index;
252 int status = 0;
254 if (!msg_queue_obj || pmsg == NULL)
255 return -ENOMEM;
257 hmsg_mgr = msg_queue_obj->msg_mgr;
259 spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
260 /* If a message is already there, get it */
261 if (!list_empty(&msg_queue_obj->msg_used_list)) {
262 msg_frame_obj = list_first_entry(&msg_queue_obj->msg_used_list,
263 struct msg_frame, list_elem);
264 list_del(&msg_frame_obj->list_elem);
265 *pmsg = msg_frame_obj->msg_data.msg;
266 list_add_tail(&msg_frame_obj->list_elem,
267 &msg_queue_obj->msg_free_list);
268 if (list_empty(&msg_queue_obj->msg_used_list))
269 sync_reset_event(msg_queue_obj->sync_event);
270 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
271 return 0;
274 if (msg_queue_obj->done) {
275 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
276 return -EPERM;
278 msg_queue_obj->io_msg_pend++;
279 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
282 * Wait til message is available, timeout, or done. We don't
283 * have to schedule the DPC, since the DSP will send messages
284 * when they are available.
286 syncs[0] = msg_queue_obj->sync_event;
287 syncs[1] = msg_queue_obj->sync_done;
288 status = sync_wait_on_multiple_events(syncs, 2, utimeout, &index);
290 spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
291 if (msg_queue_obj->done) {
292 msg_queue_obj->io_msg_pend--;
293 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
295 * Signal that we're not going to access msg_queue_obj
296 * anymore, so it can be deleted.
298 sync_set_event(msg_queue_obj->sync_done_ack);
299 return -EPERM;
301 if (!status && !list_empty(&msg_queue_obj->msg_used_list)) {
302 /* Get msg from used list */
303 msg_frame_obj = list_first_entry(&msg_queue_obj->msg_used_list,
304 struct msg_frame, list_elem);
305 list_del(&msg_frame_obj->list_elem);
306 /* Copy message into pmsg and put frame on the free list */
307 *pmsg = msg_frame_obj->msg_data.msg;
308 list_add_tail(&msg_frame_obj->list_elem,
309 &msg_queue_obj->msg_free_list);
311 msg_queue_obj->io_msg_pend--;
312 /* Reset the event if there are still queued messages */
313 if (!list_empty(&msg_queue_obj->msg_used_list))
314 sync_set_event(msg_queue_obj->sync_event);
316 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
318 return status;
322 * ======== bridge_msg_put ========
323 * Put a message onto a msg_ctrl queue.
325 int bridge_msg_put(struct msg_queue *msg_queue_obj,
326 const struct dsp_msg *pmsg, u32 utimeout)
328 struct msg_frame *msg_frame_obj;
329 struct msg_mgr *hmsg_mgr;
330 struct sync_object *syncs[2];
331 u32 index;
332 int status;
334 if (!msg_queue_obj || !pmsg || !msg_queue_obj->msg_mgr)
335 return -EFAULT;
337 hmsg_mgr = msg_queue_obj->msg_mgr;
339 spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
341 /* If a message frame is available, use it */
342 if (!list_empty(&hmsg_mgr->msg_free_list)) {
343 msg_frame_obj = list_first_entry(&hmsg_mgr->msg_free_list,
344 struct msg_frame, list_elem);
345 list_del(&msg_frame_obj->list_elem);
346 msg_frame_obj->msg_data.msg = *pmsg;
347 msg_frame_obj->msg_data.msgq_id =
348 msg_queue_obj->msgq_id;
349 list_add_tail(&msg_frame_obj->list_elem,
350 &hmsg_mgr->msg_used_list);
351 hmsg_mgr->msgs_pending++;
353 if (list_empty(&hmsg_mgr->msg_free_list))
354 sync_reset_event(hmsg_mgr->sync_event);
356 /* Release critical section before scheduling DPC */
357 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
358 /* Schedule a DPC, to do the actual data transfer: */
359 iosm_schedule(hmsg_mgr->iomgr);
360 return 0;
363 if (msg_queue_obj->done) {
364 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
365 return -EPERM;
367 msg_queue_obj->io_msg_pend++;
369 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
371 /* Wait til a free message frame is available, timeout, or done */
372 syncs[0] = hmsg_mgr->sync_event;
373 syncs[1] = msg_queue_obj->sync_done;
374 status = sync_wait_on_multiple_events(syncs, 2, utimeout, &index);
375 if (status)
376 return status;
378 /* Enter critical section */
379 spin_lock_bh(&hmsg_mgr->msg_mgr_lock);
380 if (msg_queue_obj->done) {
381 msg_queue_obj->io_msg_pend--;
382 /* Exit critical section */
383 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
385 * Signal that we're not going to access msg_queue_obj
386 * anymore, so it can be deleted.
388 sync_set_event(msg_queue_obj->sync_done_ack);
389 return -EPERM;
392 if (list_empty(&hmsg_mgr->msg_free_list)) {
393 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
394 return -EFAULT;
397 /* Get msg from free list */
398 msg_frame_obj = list_first_entry(&hmsg_mgr->msg_free_list,
399 struct msg_frame, list_elem);
401 * Copy message into pmsg and put frame on the
402 * used list.
404 list_del(&msg_frame_obj->list_elem);
405 msg_frame_obj->msg_data.msg = *pmsg;
406 msg_frame_obj->msg_data.msgq_id = msg_queue_obj->msgq_id;
407 list_add_tail(&msg_frame_obj->list_elem, &hmsg_mgr->msg_used_list);
408 hmsg_mgr->msgs_pending++;
410 * Schedule a DPC, to do the actual
411 * data transfer.
413 iosm_schedule(hmsg_mgr->iomgr);
415 msg_queue_obj->io_msg_pend--;
416 /* Reset event if there are still frames available */
417 if (!list_empty(&hmsg_mgr->msg_free_list))
418 sync_set_event(hmsg_mgr->sync_event);
420 /* Exit critical section */
421 spin_unlock_bh(&hmsg_mgr->msg_mgr_lock);
423 return 0;
427 * ======== bridge_msg_register_notify ========
429 int bridge_msg_register_notify(struct msg_queue *msg_queue_obj,
430 u32 event_mask, u32 notify_type,
431 struct dsp_notification *hnotification)
433 int status = 0;
435 if (!msg_queue_obj || !hnotification) {
436 status = -ENOMEM;
437 goto func_end;
440 if (!(event_mask == DSP_NODEMESSAGEREADY || event_mask == 0)) {
441 status = -EPERM;
442 goto func_end;
445 if (notify_type != DSP_SIGNALEVENT) {
446 status = -EBADR;
447 goto func_end;
450 if (event_mask)
451 status = ntfy_register(msg_queue_obj->ntfy_obj, hnotification,
452 event_mask, notify_type);
453 else
454 status = ntfy_unregister(msg_queue_obj->ntfy_obj,
455 hnotification);
457 if (status == -EINVAL) {
458 /* Not registered. Ok, since we couldn't have known. Node
459 * notifications are split between node state change handled
460 * by NODE, and message ready handled by msg_ctrl. */
461 status = 0;
463 func_end:
464 return status;
468 * ======== bridge_msg_set_queue_id ========
470 void bridge_msg_set_queue_id(struct msg_queue *msg_queue_obj, u32 msgq_id)
473 * A message queue must be created when a node is allocated,
474 * so that node_register_notify() can be called before the node
475 * is created. Since we don't know the node environment until the
476 * node is created, we need this function to set msg_queue_obj->msgq_id
477 * to the node environment, after the node is created.
479 if (msg_queue_obj)
480 msg_queue_obj->msgq_id = msgq_id;
484 * ======== add_new_msg ========
485 * Must be called in message manager critical section.
487 static int add_new_msg(struct list_head *msg_list)
489 struct msg_frame *pmsg;
491 pmsg = kzalloc(sizeof(struct msg_frame), GFP_ATOMIC);
492 if (!pmsg)
493 return -ENOMEM;
495 list_add_tail(&pmsg->list_elem, msg_list);
497 return 0;
501 * ======== delete_msg_mgr ========
503 static void delete_msg_mgr(struct msg_mgr *hmsg_mgr)
505 if (!hmsg_mgr)
506 return;
508 /* FIXME: free elements from queue_list? */
509 free_msg_list(&hmsg_mgr->msg_free_list);
510 free_msg_list(&hmsg_mgr->msg_used_list);
511 kfree(hmsg_mgr->sync_event);
512 kfree(hmsg_mgr);
516 * ======== delete_msg_queue ========
518 static void delete_msg_queue(struct msg_queue *msg_queue_obj, u32 num_to_dsp)
520 struct msg_mgr *hmsg_mgr;
521 struct msg_frame *pmsg, *tmp;
522 u32 i;
524 if (!msg_queue_obj || !msg_queue_obj->msg_mgr)
525 return;
527 hmsg_mgr = msg_queue_obj->msg_mgr;
529 /* Pull off num_to_dsp message frames from Msg manager and free */
530 i = 0;
531 list_for_each_entry_safe(pmsg, tmp, &hmsg_mgr->msg_free_list,
532 list_elem) {
533 list_del(&pmsg->list_elem);
534 kfree(pmsg);
535 if (i++ >= num_to_dsp)
536 break;
539 free_msg_list(&msg_queue_obj->msg_free_list);
540 free_msg_list(&msg_queue_obj->msg_used_list);
542 if (msg_queue_obj->ntfy_obj) {
543 ntfy_delete(msg_queue_obj->ntfy_obj);
544 kfree(msg_queue_obj->ntfy_obj);
547 kfree(msg_queue_obj->sync_event);
548 kfree(msg_queue_obj->sync_done);
549 kfree(msg_queue_obj->sync_done_ack);
551 kfree(msg_queue_obj);
555 * ======== free_msg_list ========
557 static void free_msg_list(struct list_head *msg_list)
559 struct msg_frame *pmsg, *tmp;
561 if (!msg_list)
562 return;
564 list_for_each_entry_safe(pmsg, tmp, msg_list, list_elem) {
565 list_del(&pmsg->list_elem);
566 kfree(pmsg);