staging: ti dspbridge: Rename words with camel case
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / tidspbridge / rmgr / strm.c
blobf6922f485037de1de2fdab51ab806fd379594915
1 /*
2 * strm.c
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6 * DSP/BIOS Bridge Stream Manager.
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.
19 /* ----------------------------------- Host OS */
20 #include <dspbridge/host_os.h>
22 /* ----------------------------------- DSP/BIOS Bridge */
23 #include <dspbridge/std.h>
24 #include <dspbridge/dbdefs.h>
26 /* ----------------------------------- Trace & Debug */
27 #include <dspbridge/dbc.h>
29 /* ----------------------------------- OS Adaptation Layer */
30 #include <dspbridge/sync.h>
32 /* ----------------------------------- Bridge Driver */
33 #include <dspbridge/dspdefs.h>
35 /* ----------------------------------- Resource Manager */
36 #include <dspbridge/nodepriv.h>
38 /* ----------------------------------- Others */
39 #include <dspbridge/cmm.h>
41 /* ----------------------------------- This */
42 #include <dspbridge/strm.h>
44 #include <dspbridge/cfg.h>
45 #include <dspbridge/resourcecleanup.h>
47 /* ----------------------------------- Defines, Data Structures, Typedefs */
48 #define DEFAULTTIMEOUT 10000
49 #define DEFAULTNUMBUFS 2
52 * ======== strm_mgr ========
53 * The strm_mgr contains device information needed to open the underlying
54 * channels of a stream.
56 struct strm_mgr {
57 struct dev_object *dev_obj; /* Device for this processor */
58 struct chnl_mgr *hchnl_mgr; /* Channel manager */
59 /* Function interface to Bridge driver */
60 struct bridge_drv_interface *intf_fxns;
64 * ======== strm_object ========
65 * This object is allocated in strm_open().
67 struct strm_object {
68 struct strm_mgr *strm_mgr_obj;
69 struct chnl_object *chnl_obj;
70 u32 dir; /* DSP_TONODE or DSP_FROMNODE */
71 u32 utimeout;
72 u32 num_bufs; /* Max # of bufs allowed in stream */
73 u32 un_bufs_in_strm; /* Current # of bufs in stream */
74 u32 ul_n_bytes; /* bytes transferred since idled */
75 /* STREAM_IDLE, STREAM_READY, ... */
76 enum dsp_streamstate strm_state;
77 void *user_event; /* Saved for strm_get_info() */
78 enum dsp_strmmode strm_mode; /* STRMMODE_[PROCCOPY][ZEROCOPY]... */
79 u32 udma_chnl_id; /* DMA chnl id */
80 u32 udma_priority; /* DMA priority:DMAPRI_[LOW][HIGH] */
81 u32 segment_id; /* >0 is SM segment.=0 is local heap */
82 u32 buf_alignment; /* Alignment for stream bufs */
83 /* Stream's SM address translator */
84 struct cmm_xlatorobject *xlator;
87 /* ----------------------------------- Globals */
88 static u32 refs; /* module reference count */
90 /* ----------------------------------- Function Prototypes */
91 static int delete_strm(struct strm_object *stream_obj);
92 static void delete_strm_mgr(struct strm_mgr *strm_mgr_obj);
95 * ======== strm_allocate_buffer ========
96 * Purpose:
97 * Allocates buffers for a stream.
99 int strm_allocate_buffer(struct strm_object *stream_obj, u32 usize,
100 OUT u8 **ap_buffer, u32 num_bufs,
101 struct process_context *pr_ctxt)
103 int status = 0;
104 u32 alloc_cnt = 0;
105 u32 i;
107 void *hstrm_res;
109 DBC_REQUIRE(refs > 0);
110 DBC_REQUIRE(ap_buffer != NULL);
112 if (stream_obj) {
114 * Allocate from segment specified at time of stream open.
116 if (usize == 0)
117 status = -EINVAL;
119 } else {
120 status = -EFAULT;
123 if (DSP_FAILED(status))
124 goto func_end;
126 for (i = 0; i < num_bufs; i++) {
127 DBC_ASSERT(stream_obj->xlator != NULL);
128 (void)cmm_xlator_alloc_buf(stream_obj->xlator, &ap_buffer[i],
129 usize);
130 if (ap_buffer[i] == NULL) {
131 status = -ENOMEM;
132 alloc_cnt = i;
133 break;
136 if (DSP_FAILED(status))
137 strm_free_buffer(stream_obj, ap_buffer, alloc_cnt, pr_ctxt);
139 if (DSP_FAILED(status))
140 goto func_end;
142 if (drv_get_strm_res_element(stream_obj, &hstrm_res, pr_ctxt) !=
143 -ENOENT)
144 drv_proc_update_strm_res(num_bufs, hstrm_res);
146 func_end:
147 return status;
151 * ======== strm_close ========
152 * Purpose:
153 * Close a stream opened with strm_open().
155 int strm_close(struct strm_object *stream_obj,
156 struct process_context *pr_ctxt)
158 struct bridge_drv_interface *intf_fxns;
159 struct chnl_info chnl_info_obj;
160 int status = 0;
162 void *hstrm_res;
164 DBC_REQUIRE(refs > 0);
166 if (!stream_obj) {
167 status = -EFAULT;
168 } else {
169 /* Have all buffers been reclaimed? If not, return
170 * -EPIPE */
171 intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
172 status =
173 (*intf_fxns->pfn_chnl_get_info) (stream_obj->chnl_obj,
174 &chnl_info_obj);
175 DBC_ASSERT(DSP_SUCCEEDED(status));
177 if (chnl_info_obj.cio_cs > 0 || chnl_info_obj.cio_reqs > 0)
178 status = -EPIPE;
179 else
180 status = delete_strm(stream_obj);
183 if (DSP_FAILED(status))
184 goto func_end;
186 if (drv_get_strm_res_element(stream_obj, &hstrm_res, pr_ctxt) !=
187 -ENOENT)
188 drv_proc_remove_strm_res_element(hstrm_res, pr_ctxt);
189 func_end:
190 DBC_ENSURE(status == 0 || status == -EFAULT ||
191 status == -EPIPE || status == -EPERM);
193 dev_dbg(bridge, "%s: stream_obj: %p, status 0x%x\n", __func__,
194 stream_obj, status);
195 return status;
199 * ======== strm_create ========
200 * Purpose:
201 * Create a STRM manager object.
203 int strm_create(OUT struct strm_mgr **strm_man,
204 struct dev_object *dev_obj)
206 struct strm_mgr *strm_mgr_obj;
207 int status = 0;
209 DBC_REQUIRE(refs > 0);
210 DBC_REQUIRE(strm_man != NULL);
211 DBC_REQUIRE(dev_obj != NULL);
213 *strm_man = NULL;
214 /* Allocate STRM manager object */
215 strm_mgr_obj = kzalloc(sizeof(struct strm_mgr), GFP_KERNEL);
216 if (strm_mgr_obj == NULL)
217 status = -ENOMEM;
218 else
219 strm_mgr_obj->dev_obj = dev_obj;
221 /* Get Channel manager and Bridge function interface */
222 if (DSP_SUCCEEDED(status)) {
223 status = dev_get_chnl_mgr(dev_obj, &(strm_mgr_obj->hchnl_mgr));
224 if (DSP_SUCCEEDED(status)) {
225 (void)dev_get_intf_fxns(dev_obj,
226 &(strm_mgr_obj->intf_fxns));
227 DBC_ASSERT(strm_mgr_obj->intf_fxns != NULL);
231 if (DSP_SUCCEEDED(status))
232 *strm_man = strm_mgr_obj;
233 else
234 delete_strm_mgr(strm_mgr_obj);
236 DBC_ENSURE((DSP_SUCCEEDED(status) && *strm_man) ||
237 (DSP_FAILED(status) && *strm_man == NULL));
239 return status;
243 * ======== strm_delete ========
244 * Purpose:
245 * Delete the STRM Manager Object.
247 void strm_delete(struct strm_mgr *strm_mgr_obj)
249 DBC_REQUIRE(refs > 0);
250 DBC_REQUIRE(strm_mgr_obj);
252 delete_strm_mgr(strm_mgr_obj);
256 * ======== strm_exit ========
257 * Purpose:
258 * Discontinue usage of STRM module.
260 void strm_exit(void)
262 DBC_REQUIRE(refs > 0);
264 refs--;
266 DBC_ENSURE(refs >= 0);
270 * ======== strm_free_buffer ========
271 * Purpose:
272 * Frees the buffers allocated for a stream.
274 int strm_free_buffer(struct strm_object *stream_obj, u8 ** ap_buffer,
275 u32 num_bufs, struct process_context *pr_ctxt)
277 int status = 0;
278 u32 i = 0;
280 void *hstrm_res = NULL;
282 DBC_REQUIRE(refs > 0);
283 DBC_REQUIRE(ap_buffer != NULL);
285 if (!stream_obj)
286 status = -EFAULT;
288 if (DSP_SUCCEEDED(status)) {
289 for (i = 0; i < num_bufs; i++) {
290 DBC_ASSERT(stream_obj->xlator != NULL);
291 status =
292 cmm_xlator_free_buf(stream_obj->xlator,
293 ap_buffer[i]);
294 if (DSP_FAILED(status))
295 break;
296 ap_buffer[i] = NULL;
299 if (drv_get_strm_res_element(stream_obj, hstrm_res, pr_ctxt) !=
300 -ENOENT)
301 drv_proc_update_strm_res(num_bufs - i, hstrm_res);
303 return status;
307 * ======== strm_get_info ========
308 * Purpose:
309 * Retrieves information about a stream.
311 int strm_get_info(struct strm_object *stream_obj,
312 OUT struct stream_info *stream_info,
313 u32 stream_info_size)
315 struct bridge_drv_interface *intf_fxns;
316 struct chnl_info chnl_info_obj;
317 int status = 0;
318 void *virt_base = NULL; /* NULL if no SM used */
320 DBC_REQUIRE(refs > 0);
321 DBC_REQUIRE(stream_info != NULL);
322 DBC_REQUIRE(stream_info_size >= sizeof(struct stream_info));
324 if (!stream_obj) {
325 status = -EFAULT;
326 } else {
327 if (stream_info_size < sizeof(struct stream_info)) {
328 /* size of users info */
329 status = -EINVAL;
332 if (DSP_FAILED(status))
333 goto func_end;
335 intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
336 status =
337 (*intf_fxns->pfn_chnl_get_info) (stream_obj->chnl_obj,
338 &chnl_info_obj);
339 if (DSP_FAILED(status))
340 goto func_end;
342 if (stream_obj->xlator) {
343 /* We have a translator */
344 DBC_ASSERT(stream_obj->segment_id > 0);
345 cmm_xlator_info(stream_obj->xlator, (u8 **) &virt_base, 0,
346 stream_obj->segment_id, false);
348 stream_info->segment_id = stream_obj->segment_id;
349 stream_info->strm_mode = stream_obj->strm_mode;
350 stream_info->virt_base = virt_base;
351 stream_info->user_strm->number_bufs_allowed = stream_obj->num_bufs;
352 stream_info->user_strm->number_bufs_in_stream = chnl_info_obj.cio_cs +
353 chnl_info_obj.cio_reqs;
354 /* # of bytes transferred since last call to DSPStream_Idle() */
355 stream_info->user_strm->ul_number_bytes = chnl_info_obj.bytes_tx;
356 stream_info->user_strm->sync_object_handle = chnl_info_obj.event_obj;
357 /* Determine stream state based on channel state and info */
358 if (chnl_info_obj.dw_state & CHNL_STATEEOS) {
359 stream_info->user_strm->ss_stream_state = STREAM_DONE;
360 } else {
361 if (chnl_info_obj.cio_cs > 0)
362 stream_info->user_strm->ss_stream_state = STREAM_READY;
363 else if (chnl_info_obj.cio_reqs > 0)
364 stream_info->user_strm->ss_stream_state =
365 STREAM_PENDING;
366 else
367 stream_info->user_strm->ss_stream_state = STREAM_IDLE;
370 func_end:
371 return status;
375 * ======== strm_idle ========
376 * Purpose:
377 * Idles a particular stream.
379 int strm_idle(struct strm_object *stream_obj, bool flush_data)
381 struct bridge_drv_interface *intf_fxns;
382 int status = 0;
384 DBC_REQUIRE(refs > 0);
386 if (!stream_obj) {
387 status = -EFAULT;
388 } else {
389 intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
391 status = (*intf_fxns->pfn_chnl_idle) (stream_obj->chnl_obj,
392 stream_obj->utimeout,
393 flush_data);
396 dev_dbg(bridge, "%s: stream_obj: %p flush_data: 0x%x status: 0x%x\n",
397 __func__, stream_obj, flush_data, status);
398 return status;
402 * ======== strm_init ========
403 * Purpose:
404 * Initialize the STRM module.
406 bool strm_init(void)
408 bool ret = true;
410 DBC_REQUIRE(refs >= 0);
412 if (ret)
413 refs++;
415 DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0)));
417 return ret;
421 * ======== strm_issue ========
422 * Purpose:
423 * Issues a buffer on a stream
425 int strm_issue(struct strm_object *stream_obj, IN u8 *pbuf, u32 ul_bytes,
426 u32 ul_buf_size, u32 dw_arg)
428 struct bridge_drv_interface *intf_fxns;
429 int status = 0;
430 void *tmp_buf = NULL;
432 DBC_REQUIRE(refs > 0);
433 DBC_REQUIRE(pbuf != NULL);
435 if (!stream_obj) {
436 status = -EFAULT;
437 } else {
438 intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
440 if (stream_obj->segment_id != 0) {
441 tmp_buf = cmm_xlator_translate(stream_obj->xlator,
442 (void *)pbuf,
443 CMM_VA2DSPPA);
444 if (tmp_buf == NULL)
445 status = -ESRCH;
448 if (DSP_SUCCEEDED(status)) {
449 status = (*intf_fxns->pfn_chnl_add_io_req)
450 (stream_obj->chnl_obj, pbuf, ul_bytes, ul_buf_size,
451 (u32) tmp_buf, dw_arg);
453 if (status == -EIO)
454 status = -ENOSR;
457 dev_dbg(bridge, "%s: stream_obj: %p pbuf: %p ul_bytes: 0x%x dw_arg:"
458 " 0x%x status: 0x%x\n", __func__, stream_obj, pbuf,
459 ul_bytes, dw_arg, status);
460 return status;
464 * ======== strm_open ========
465 * Purpose:
466 * Open a stream for sending/receiving data buffers to/from a task or
467 * XDAIS socket node on the DSP.
469 int strm_open(struct node_object *hnode, u32 dir, u32 index,
470 IN struct strm_attr *pattr,
471 OUT struct strm_object **strm_objct,
472 struct process_context *pr_ctxt)
474 struct strm_mgr *strm_mgr_obj;
475 struct bridge_drv_interface *intf_fxns;
476 u32 ul_chnl_id;
477 struct strm_object *strm_obj = NULL;
478 s8 chnl_mode;
479 struct chnl_attr chnl_attr_obj;
480 int status = 0;
481 struct cmm_object *hcmm_mgr = NULL; /* Shared memory manager hndl */
483 void *hstrm_res;
485 DBC_REQUIRE(refs > 0);
486 DBC_REQUIRE(strm_objct != NULL);
487 DBC_REQUIRE(pattr != NULL);
488 *strm_objct = NULL;
489 if (dir != DSP_TONODE && dir != DSP_FROMNODE) {
490 status = -EPERM;
491 } else {
492 /* Get the channel id from the node (set in node_connect()) */
493 status = node_get_channel_id(hnode, dir, index, &ul_chnl_id);
495 if (DSP_SUCCEEDED(status))
496 status = node_get_strm_mgr(hnode, &strm_mgr_obj);
498 if (DSP_SUCCEEDED(status)) {
499 strm_obj = kzalloc(sizeof(struct strm_object), GFP_KERNEL);
500 if (strm_obj == NULL) {
501 status = -ENOMEM;
502 } else {
503 strm_obj->strm_mgr_obj = strm_mgr_obj;
504 strm_obj->dir = dir;
505 strm_obj->strm_state = STREAM_IDLE;
506 strm_obj->user_event = pattr->user_event;
507 if (pattr->stream_attr_in != NULL) {
508 strm_obj->utimeout =
509 pattr->stream_attr_in->utimeout;
510 strm_obj->num_bufs =
511 pattr->stream_attr_in->num_bufs;
512 strm_obj->strm_mode =
513 pattr->stream_attr_in->strm_mode;
514 strm_obj->segment_id =
515 pattr->stream_attr_in->segment_id;
516 strm_obj->buf_alignment =
517 pattr->stream_attr_in->buf_alignment;
518 strm_obj->udma_chnl_id =
519 pattr->stream_attr_in->udma_chnl_id;
520 strm_obj->udma_priority =
521 pattr->stream_attr_in->udma_priority;
522 chnl_attr_obj.uio_reqs =
523 pattr->stream_attr_in->num_bufs;
524 } else {
525 strm_obj->utimeout = DEFAULTTIMEOUT;
526 strm_obj->num_bufs = DEFAULTNUMBUFS;
527 strm_obj->strm_mode = STRMMODE_PROCCOPY;
528 strm_obj->segment_id = 0; /* local mem */
529 strm_obj->buf_alignment = 0;
530 strm_obj->udma_chnl_id = 0;
531 strm_obj->udma_priority = 0;
532 chnl_attr_obj.uio_reqs = DEFAULTNUMBUFS;
534 chnl_attr_obj.reserved1 = NULL;
535 /* DMA chnl flush timeout */
536 chnl_attr_obj.reserved2 = strm_obj->utimeout;
537 chnl_attr_obj.event_obj = NULL;
538 if (pattr->user_event != NULL)
539 chnl_attr_obj.event_obj = pattr->user_event;
543 if (DSP_FAILED(status))
544 goto func_cont;
546 if ((pattr->virt_base == NULL) || !(pattr->ul_virt_size > 0))
547 goto func_cont;
549 /* No System DMA */
550 DBC_ASSERT(strm_obj->strm_mode != STRMMODE_LDMA);
551 /* Get the shared mem mgr for this streams dev object */
552 status = dev_get_cmm_mgr(strm_mgr_obj->dev_obj, &hcmm_mgr);
553 if (DSP_SUCCEEDED(status)) {
554 /*Allocate a SM addr translator for this strm. */
555 status = cmm_xlator_create(&strm_obj->xlator, hcmm_mgr, NULL);
556 if (DSP_SUCCEEDED(status)) {
557 DBC_ASSERT(strm_obj->segment_id > 0);
558 /* Set translators Virt Addr attributes */
559 status = cmm_xlator_info(strm_obj->xlator,
560 (u8 **) &pattr->virt_base,
561 pattr->ul_virt_size,
562 strm_obj->segment_id, true);
565 func_cont:
566 if (DSP_SUCCEEDED(status)) {
567 /* Open channel */
568 chnl_mode = (dir == DSP_TONODE) ?
569 CHNL_MODETODSP : CHNL_MODEFROMDSP;
570 intf_fxns = strm_mgr_obj->intf_fxns;
571 status = (*intf_fxns->pfn_chnl_open) (&(strm_obj->chnl_obj),
572 strm_mgr_obj->hchnl_mgr,
573 chnl_mode, ul_chnl_id,
574 &chnl_attr_obj);
575 if (DSP_FAILED(status)) {
577 * over-ride non-returnable status codes so we return
578 * something documented
580 if (status != -ENOMEM && status !=
581 -EINVAL && status != -EPERM) {
583 * We got a status that's not return-able.
584 * Assert that we got something we were
585 * expecting (-EFAULT isn't acceptable,
586 * strm_mgr_obj->hchnl_mgr better be valid or we
587 * assert here), and then return -EPERM.
589 DBC_ASSERT(status == -ENOSR ||
590 status == -ECHRNG ||
591 status == -EALREADY ||
592 status == -EIO);
593 status = -EPERM;
597 if (DSP_SUCCEEDED(status)) {
598 *strm_objct = strm_obj;
599 drv_proc_insert_strm_res_element(*strm_objct, &hstrm_res,
600 pr_ctxt);
601 } else {
602 (void)delete_strm(strm_obj);
605 /* ensure we return a documented error code */
606 DBC_ENSURE((DSP_SUCCEEDED(status) && *strm_objct) ||
607 (*strm_objct == NULL && (status == -EFAULT ||
608 status == -EPERM
609 || status == -EINVAL)));
611 dev_dbg(bridge, "%s: hnode: %p dir: 0x%x index: 0x%x pattr: %p "
612 "strm_objct: %p status: 0x%x\n", __func__,
613 hnode, dir, index, pattr, strm_objct, status);
614 return status;
618 * ======== strm_reclaim ========
619 * Purpose:
620 * Relcaims a buffer from a stream.
622 int strm_reclaim(struct strm_object *stream_obj, OUT u8 ** buf_ptr,
623 u32 *pulBytes, u32 *pulBufSize, u32 *pdw_arg)
625 struct bridge_drv_interface *intf_fxns;
626 struct chnl_ioc chnl_ioc_obj;
627 int status = 0;
628 void *tmp_buf = NULL;
630 DBC_REQUIRE(refs > 0);
631 DBC_REQUIRE(buf_ptr != NULL);
632 DBC_REQUIRE(pulBytes != NULL);
633 DBC_REQUIRE(pdw_arg != NULL);
635 if (!stream_obj) {
636 status = -EFAULT;
637 goto func_end;
639 intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
641 status =
642 (*intf_fxns->pfn_chnl_get_ioc) (stream_obj->chnl_obj,
643 stream_obj->utimeout,
644 &chnl_ioc_obj);
645 if (DSP_SUCCEEDED(status)) {
646 *pulBytes = chnl_ioc_obj.byte_size;
647 if (pulBufSize)
648 *pulBufSize = chnl_ioc_obj.buf_size;
650 *pdw_arg = chnl_ioc_obj.dw_arg;
651 if (!CHNL_IS_IO_COMPLETE(chnl_ioc_obj)) {
652 if (CHNL_IS_TIMED_OUT(chnl_ioc_obj)) {
653 status = -ETIME;
654 } else {
655 /* Allow reclaims after idle to succeed */
656 if (!CHNL_IS_IO_CANCELLED(chnl_ioc_obj))
657 status = -EPERM;
661 /* Translate zerocopy buffer if channel not canceled. */
662 if (DSP_SUCCEEDED(status)
663 && (!CHNL_IS_IO_CANCELLED(chnl_ioc_obj))
664 && (stream_obj->strm_mode == STRMMODE_ZEROCOPY)) {
666 * This is a zero-copy channel so chnl_ioc_obj.pbuf
667 * contains the DSP address of SM. We need to
668 * translate it to a virtual address for the user
669 * thread to access.
670 * Note: Could add CMM_DSPPA2VA to CMM in the future.
672 tmp_buf = cmm_xlator_translate(stream_obj->xlator,
673 chnl_ioc_obj.pbuf,
674 CMM_DSPPA2PA);
675 if (tmp_buf != NULL) {
676 /* now convert this GPP Pa to Va */
677 tmp_buf = cmm_xlator_translate(stream_obj->
678 xlator,
679 tmp_buf,
680 CMM_PA2VA);
682 if (tmp_buf == NULL)
683 status = -ESRCH;
685 chnl_ioc_obj.pbuf = tmp_buf;
687 *buf_ptr = chnl_ioc_obj.pbuf;
689 func_end:
690 /* ensure we return a documented return code */
691 DBC_ENSURE(DSP_SUCCEEDED(status) || status == -EFAULT ||
692 status == -ETIME || status == -ESRCH ||
693 status == -EPERM);
695 dev_dbg(bridge, "%s: stream_obj: %p buf_ptr: %p pulBytes: %p "
696 "pdw_arg: %p status 0x%x\n", __func__, stream_obj,
697 buf_ptr, pulBytes, pdw_arg, status);
698 return status;
702 * ======== strm_register_notify ========
703 * Purpose:
704 * Register to be notified on specific events for this stream.
706 int strm_register_notify(struct strm_object *stream_obj, u32 event_mask,
707 u32 notify_type, struct dsp_notification
708 * hnotification)
710 struct bridge_drv_interface *intf_fxns;
711 int status = 0;
713 DBC_REQUIRE(refs > 0);
714 DBC_REQUIRE(hnotification != NULL);
716 if (!stream_obj) {
717 status = -EFAULT;
718 } else if ((event_mask & ~((DSP_STREAMIOCOMPLETION) |
719 DSP_STREAMDONE)) != 0) {
720 status = -EINVAL;
721 } else {
722 if (notify_type != DSP_SIGNALEVENT)
723 status = -ENOSYS;
726 if (DSP_SUCCEEDED(status)) {
727 intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
729 status =
730 (*intf_fxns->pfn_chnl_register_notify) (stream_obj->
731 chnl_obj,
732 event_mask,
733 notify_type,
734 hnotification);
736 /* ensure we return a documented return code */
737 DBC_ENSURE(DSP_SUCCEEDED(status) || status == -EFAULT ||
738 status == -ETIME || status == -ESRCH ||
739 status == -ENOSYS || status == -EPERM);
740 return status;
744 * ======== strm_select ========
745 * Purpose:
746 * Selects a ready stream.
748 int strm_select(IN struct strm_object **strm_tab, u32 strms,
749 OUT u32 *pmask, u32 utimeout)
751 u32 index;
752 struct chnl_info chnl_info_obj;
753 struct bridge_drv_interface *intf_fxns;
754 struct sync_object **sync_events = NULL;
755 u32 i;
756 int status = 0;
758 DBC_REQUIRE(refs > 0);
759 DBC_REQUIRE(strm_tab != NULL);
760 DBC_REQUIRE(pmask != NULL);
761 DBC_REQUIRE(strms > 0);
763 *pmask = 0;
764 for (i = 0; i < strms; i++) {
765 if (!strm_tab[i]) {
766 status = -EFAULT;
767 break;
770 if (DSP_FAILED(status))
771 goto func_end;
773 /* Determine which channels have IO ready */
774 for (i = 0; i < strms; i++) {
775 intf_fxns = strm_tab[i]->strm_mgr_obj->intf_fxns;
776 status = (*intf_fxns->pfn_chnl_get_info) (strm_tab[i]->chnl_obj,
777 &chnl_info_obj);
778 if (DSP_FAILED(status)) {
779 break;
780 } else {
781 if (chnl_info_obj.cio_cs > 0)
782 *pmask |= (1 << i);
786 if (DSP_SUCCEEDED(status) && utimeout > 0 && *pmask == 0) {
787 /* Non-zero timeout */
788 sync_events = kmalloc(strms * sizeof(struct sync_object *),
789 GFP_KERNEL);
791 if (sync_events == NULL) {
792 status = -ENOMEM;
793 } else {
794 for (i = 0; i < strms; i++) {
795 intf_fxns =
796 strm_tab[i]->strm_mgr_obj->intf_fxns;
797 status = (*intf_fxns->pfn_chnl_get_info)
798 (strm_tab[i]->chnl_obj, &chnl_info_obj);
799 if (DSP_FAILED(status))
800 break;
801 else
802 sync_events[i] =
803 chnl_info_obj.sync_event;
807 if (DSP_SUCCEEDED(status)) {
808 status =
809 sync_wait_on_multiple_events(sync_events, strms,
810 utimeout, &index);
811 if (DSP_SUCCEEDED(status)) {
812 /* Since we waited on the event, we have to
813 * reset it */
814 sync_set_event(sync_events[index]);
815 *pmask = 1 << index;
819 func_end:
820 kfree(sync_events);
822 DBC_ENSURE((DSP_SUCCEEDED(status) && (*pmask != 0 || utimeout == 0)) ||
823 (DSP_FAILED(status) && *pmask == 0));
825 return status;
829 * ======== delete_strm ========
830 * Purpose:
831 * Frees the resources allocated for a stream.
833 static int delete_strm(struct strm_object *stream_obj)
835 struct bridge_drv_interface *intf_fxns;
836 int status = 0;
838 if (stream_obj) {
839 if (stream_obj->chnl_obj) {
840 intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
841 /* Channel close can fail only if the channel handle
842 * is invalid. */
843 status = (*intf_fxns->pfn_chnl_close)
844 (stream_obj->chnl_obj);
845 /* Free all SM address translator resources */
846 if (DSP_SUCCEEDED(status)) {
847 if (stream_obj->xlator) {
848 /* force free */
849 (void)cmm_xlator_delete(stream_obj->
850 xlator,
851 true);
855 kfree(stream_obj);
856 } else {
857 status = -EFAULT;
859 return status;
863 * ======== delete_strm_mgr ========
864 * Purpose:
865 * Frees stream manager.
867 static void delete_strm_mgr(struct strm_mgr *strm_mgr_obj)
869 if (strm_mgr_obj)
870 kfree(strm_mgr_obj);