GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / tidspbridge / rmgr / strm.c
blobef2ec9497b1cc665d6b0f7ae42bf7a3d965e42d5
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 #include <linux/types.h>
21 /* ----------------------------------- Host OS */
22 #include <dspbridge/host_os.h>
24 /* ----------------------------------- DSP/BIOS Bridge */
25 #include <dspbridge/dbdefs.h>
27 /* ----------------------------------- Trace & Debug */
28 #include <dspbridge/dbc.h>
30 /* ----------------------------------- OS Adaptation Layer */
31 #include <dspbridge/sync.h>
33 /* ----------------------------------- Bridge Driver */
34 #include <dspbridge/dspdefs.h>
36 /* ----------------------------------- Resource Manager */
37 #include <dspbridge/nodepriv.h>
39 /* ----------------------------------- Others */
40 #include <dspbridge/cmm.h>
42 /* ----------------------------------- This */
43 #include <dspbridge/strm.h>
45 #include <dspbridge/cfg.h>
46 #include <dspbridge/resourcecleanup.h>
48 /* ----------------------------------- Defines, Data Structures, Typedefs */
49 #define DEFAULTTIMEOUT 10000
50 #define DEFAULTNUMBUFS 2
53 * ======== strm_mgr ========
54 * The strm_mgr contains device information needed to open the underlying
55 * channels of a stream.
57 struct strm_mgr {
58 struct dev_object *dev_obj; /* Device for this processor */
59 struct chnl_mgr *hchnl_mgr; /* Channel manager */
60 /* Function interface to Bridge driver */
61 struct bridge_drv_interface *intf_fxns;
65 * ======== strm_object ========
66 * This object is allocated in strm_open().
68 struct strm_object {
69 struct strm_mgr *strm_mgr_obj;
70 struct chnl_object *chnl_obj;
71 u32 dir; /* DSP_TONODE or DSP_FROMNODE */
72 u32 utimeout;
73 u32 num_bufs; /* Max # of bufs allowed in stream */
74 u32 un_bufs_in_strm; /* Current # of bufs in stream */
75 u32 ul_n_bytes; /* bytes transferred since idled */
76 /* STREAM_IDLE, STREAM_READY, ... */
77 enum dsp_streamstate strm_state;
78 void *user_event; /* Saved for strm_get_info() */
79 enum dsp_strmmode strm_mode; /* STRMMODE_[PROCCOPY][ZEROCOPY]... */
80 u32 udma_chnl_id; /* DMA chnl id */
81 u32 udma_priority; /* DMA priority:DMAPRI_[LOW][HIGH] */
82 u32 segment_id; /* >0 is SM segment.=0 is local heap */
83 u32 buf_alignment; /* Alignment for stream bufs */
84 /* Stream's SM address translator */
85 struct cmm_xlatorobject *xlator;
88 /* ----------------------------------- Globals */
89 static u32 refs; /* module reference count */
91 /* ----------------------------------- Function Prototypes */
92 static int delete_strm(struct strm_object *stream_obj);
95 * ======== strm_allocate_buffer ========
96 * Purpose:
97 * Allocates buffers for a stream.
99 int strm_allocate_buffer(struct strm_res_object *strmres, u32 usize,
100 u8 **ap_buffer, u32 num_bufs,
101 struct process_context *pr_ctxt)
103 int status = 0;
104 u32 alloc_cnt = 0;
105 u32 i;
106 struct strm_object *stream_obj = strmres->hstream;
108 DBC_REQUIRE(refs > 0);
109 DBC_REQUIRE(ap_buffer != NULL);
111 if (stream_obj) {
113 * Allocate from segment specified at time of stream open.
115 if (usize == 0)
116 status = -EINVAL;
118 } else {
119 status = -EFAULT;
122 if (status)
123 goto func_end;
125 for (i = 0; i < num_bufs; i++) {
126 DBC_ASSERT(stream_obj->xlator != NULL);
127 (void)cmm_xlator_alloc_buf(stream_obj->xlator, &ap_buffer[i],
128 usize);
129 if (ap_buffer[i] == NULL) {
130 status = -ENOMEM;
131 alloc_cnt = i;
132 break;
135 if (status)
136 strm_free_buffer(strmres, ap_buffer, alloc_cnt, pr_ctxt);
138 if (status)
139 goto func_end;
141 drv_proc_update_strm_res(num_bufs, strmres);
143 func_end:
144 return status;
148 * ======== strm_close ========
149 * Purpose:
150 * Close a stream opened with strm_open().
152 int strm_close(struct strm_res_object *strmres,
153 struct process_context *pr_ctxt)
155 struct bridge_drv_interface *intf_fxns;
156 struct chnl_info chnl_info_obj;
157 int status = 0;
158 struct strm_object *stream_obj = strmres->hstream;
160 DBC_REQUIRE(refs > 0);
162 if (!stream_obj) {
163 status = -EFAULT;
164 } else {
165 /* Have all buffers been reclaimed? If not, return
166 * -EPIPE */
167 intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
168 status =
169 (*intf_fxns->pfn_chnl_get_info) (stream_obj->chnl_obj,
170 &chnl_info_obj);
171 DBC_ASSERT(!status);
173 if (chnl_info_obj.cio_cs > 0 || chnl_info_obj.cio_reqs > 0)
174 status = -EPIPE;
175 else
176 status = delete_strm(stream_obj);
179 if (status)
180 goto func_end;
182 idr_remove(pr_ctxt->stream_id, strmres->id);
183 func_end:
184 DBC_ENSURE(status == 0 || status == -EFAULT ||
185 status == -EPIPE || status == -EPERM);
187 dev_dbg(bridge, "%s: stream_obj: %p, status 0x%x\n", __func__,
188 stream_obj, status);
189 return status;
193 * ======== strm_create ========
194 * Purpose:
195 * Create a STRM manager object.
197 int strm_create(struct strm_mgr **strm_man,
198 struct dev_object *dev_obj)
200 struct strm_mgr *strm_mgr_obj;
201 int status = 0;
203 DBC_REQUIRE(refs > 0);
204 DBC_REQUIRE(strm_man != NULL);
205 DBC_REQUIRE(dev_obj != NULL);
207 *strm_man = NULL;
208 /* Allocate STRM manager object */
209 strm_mgr_obj = kzalloc(sizeof(struct strm_mgr), GFP_KERNEL);
210 if (strm_mgr_obj == NULL)
211 status = -ENOMEM;
212 else
213 strm_mgr_obj->dev_obj = dev_obj;
215 /* Get Channel manager and Bridge function interface */
216 if (!status) {
217 status = dev_get_chnl_mgr(dev_obj, &(strm_mgr_obj->hchnl_mgr));
218 if (!status) {
219 (void)dev_get_intf_fxns(dev_obj,
220 &(strm_mgr_obj->intf_fxns));
221 DBC_ASSERT(strm_mgr_obj->intf_fxns != NULL);
225 if (!status)
226 *strm_man = strm_mgr_obj;
227 else
228 kfree(strm_mgr_obj);
230 DBC_ENSURE((!status && *strm_man) || (status && *strm_man == NULL));
232 return status;
236 * ======== strm_delete ========
237 * Purpose:
238 * Delete the STRM Manager Object.
240 void strm_delete(struct strm_mgr *strm_mgr_obj)
242 DBC_REQUIRE(refs > 0);
243 DBC_REQUIRE(strm_mgr_obj);
245 kfree(strm_mgr_obj);
249 * ======== strm_exit ========
250 * Purpose:
251 * Discontinue usage of STRM module.
253 void strm_exit(void)
255 DBC_REQUIRE(refs > 0);
257 refs--;
259 DBC_ENSURE(refs >= 0);
263 * ======== strm_free_buffer ========
264 * Purpose:
265 * Frees the buffers allocated for a stream.
267 int strm_free_buffer(struct strm_res_object *strmres, u8 ** ap_buffer,
268 u32 num_bufs, struct process_context *pr_ctxt)
270 int status = 0;
271 u32 i = 0;
272 struct strm_object *stream_obj = strmres->hstream;
274 DBC_REQUIRE(refs > 0);
275 DBC_REQUIRE(ap_buffer != NULL);
277 if (!stream_obj)
278 status = -EFAULT;
280 if (!status) {
281 for (i = 0; i < num_bufs; i++) {
282 DBC_ASSERT(stream_obj->xlator != NULL);
283 status =
284 cmm_xlator_free_buf(stream_obj->xlator,
285 ap_buffer[i]);
286 if (status)
287 break;
288 ap_buffer[i] = NULL;
291 drv_proc_update_strm_res(num_bufs - i, strmres);
293 return status;
297 * ======== strm_get_info ========
298 * Purpose:
299 * Retrieves information about a stream.
301 int strm_get_info(struct strm_object *stream_obj,
302 struct stream_info *stream_info,
303 u32 stream_info_size)
305 struct bridge_drv_interface *intf_fxns;
306 struct chnl_info chnl_info_obj;
307 int status = 0;
308 void *virt_base = NULL; /* NULL if no SM used */
310 DBC_REQUIRE(refs > 0);
311 DBC_REQUIRE(stream_info != NULL);
312 DBC_REQUIRE(stream_info_size >= sizeof(struct stream_info));
314 if (!stream_obj) {
315 status = -EFAULT;
316 } else {
317 if (stream_info_size < sizeof(struct stream_info)) {
318 /* size of users info */
319 status = -EINVAL;
322 if (status)
323 goto func_end;
325 intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
326 status =
327 (*intf_fxns->pfn_chnl_get_info) (stream_obj->chnl_obj,
328 &chnl_info_obj);
329 if (status)
330 goto func_end;
332 if (stream_obj->xlator) {
333 /* We have a translator */
334 DBC_ASSERT(stream_obj->segment_id > 0);
335 cmm_xlator_info(stream_obj->xlator, (u8 **) &virt_base, 0,
336 stream_obj->segment_id, false);
338 stream_info->segment_id = stream_obj->segment_id;
339 stream_info->strm_mode = stream_obj->strm_mode;
340 stream_info->virt_base = virt_base;
341 stream_info->user_strm->number_bufs_allowed = stream_obj->num_bufs;
342 stream_info->user_strm->number_bufs_in_stream = chnl_info_obj.cio_cs +
343 chnl_info_obj.cio_reqs;
344 /* # of bytes transferred since last call to DSPStream_Idle() */
345 stream_info->user_strm->ul_number_bytes = chnl_info_obj.bytes_tx;
346 stream_info->user_strm->sync_object_handle = chnl_info_obj.event_obj;
347 /* Determine stream state based on channel state and info */
348 if (chnl_info_obj.dw_state & CHNL_STATEEOS) {
349 stream_info->user_strm->ss_stream_state = STREAM_DONE;
350 } else {
351 if (chnl_info_obj.cio_cs > 0)
352 stream_info->user_strm->ss_stream_state = STREAM_READY;
353 else if (chnl_info_obj.cio_reqs > 0)
354 stream_info->user_strm->ss_stream_state =
355 STREAM_PENDING;
356 else
357 stream_info->user_strm->ss_stream_state = STREAM_IDLE;
360 func_end:
361 return status;
365 * ======== strm_idle ========
366 * Purpose:
367 * Idles a particular stream.
369 int strm_idle(struct strm_object *stream_obj, bool flush_data)
371 struct bridge_drv_interface *intf_fxns;
372 int status = 0;
374 DBC_REQUIRE(refs > 0);
376 if (!stream_obj) {
377 status = -EFAULT;
378 } else {
379 intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
381 status = (*intf_fxns->pfn_chnl_idle) (stream_obj->chnl_obj,
382 stream_obj->utimeout,
383 flush_data);
386 dev_dbg(bridge, "%s: stream_obj: %p flush_data: 0x%x status: 0x%x\n",
387 __func__, stream_obj, flush_data, status);
388 return status;
392 * ======== strm_init ========
393 * Purpose:
394 * Initialize the STRM module.
396 bool strm_init(void)
398 bool ret = true;
400 DBC_REQUIRE(refs >= 0);
402 if (ret)
403 refs++;
405 DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0)));
407 return ret;
411 * ======== strm_issue ========
412 * Purpose:
413 * Issues a buffer on a stream
415 int strm_issue(struct strm_object *stream_obj, u8 *pbuf, u32 ul_bytes,
416 u32 ul_buf_size, u32 dw_arg)
418 struct bridge_drv_interface *intf_fxns;
419 int status = 0;
420 void *tmp_buf = NULL;
422 DBC_REQUIRE(refs > 0);
423 DBC_REQUIRE(pbuf != NULL);
425 if (!stream_obj) {
426 status = -EFAULT;
427 } else {
428 intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
430 if (stream_obj->segment_id != 0) {
431 tmp_buf = cmm_xlator_translate(stream_obj->xlator,
432 (void *)pbuf,
433 CMM_VA2DSPPA);
434 if (tmp_buf == NULL)
435 status = -ESRCH;
438 if (!status) {
439 status = (*intf_fxns->pfn_chnl_add_io_req)
440 (stream_obj->chnl_obj, pbuf, ul_bytes, ul_buf_size,
441 (u32) tmp_buf, dw_arg);
443 if (status == -EIO)
444 status = -ENOSR;
447 dev_dbg(bridge, "%s: stream_obj: %p pbuf: %p ul_bytes: 0x%x dw_arg:"
448 " 0x%x status: 0x%x\n", __func__, stream_obj, pbuf,
449 ul_bytes, dw_arg, status);
450 return status;
454 * ======== strm_open ========
455 * Purpose:
456 * Open a stream for sending/receiving data buffers to/from a task or
457 * XDAIS socket node on the DSP.
459 int strm_open(struct node_object *hnode, u32 dir, u32 index,
460 struct strm_attr *pattr,
461 struct strm_res_object **strmres,
462 struct process_context *pr_ctxt)
464 struct strm_mgr *strm_mgr_obj;
465 struct bridge_drv_interface *intf_fxns;
466 u32 ul_chnl_id;
467 struct strm_object *strm_obj = NULL;
468 s8 chnl_mode;
469 struct chnl_attr chnl_attr_obj;
470 int status = 0;
471 struct cmm_object *hcmm_mgr = NULL; /* Shared memory manager hndl */
473 void *stream_res;
475 DBC_REQUIRE(refs > 0);
476 DBC_REQUIRE(strmres != NULL);
477 DBC_REQUIRE(pattr != NULL);
478 *strmres = NULL;
479 if (dir != DSP_TONODE && dir != DSP_FROMNODE) {
480 status = -EPERM;
481 } else {
482 /* Get the channel id from the node (set in node_connect()) */
483 status = node_get_channel_id(hnode, dir, index, &ul_chnl_id);
485 if (!status)
486 status = node_get_strm_mgr(hnode, &strm_mgr_obj);
488 if (!status) {
489 strm_obj = kzalloc(sizeof(struct strm_object), GFP_KERNEL);
490 if (strm_obj == NULL) {
491 status = -ENOMEM;
492 } else {
493 strm_obj->strm_mgr_obj = strm_mgr_obj;
494 strm_obj->dir = dir;
495 strm_obj->strm_state = STREAM_IDLE;
496 strm_obj->user_event = pattr->user_event;
497 if (pattr->stream_attr_in != NULL) {
498 strm_obj->utimeout =
499 pattr->stream_attr_in->utimeout;
500 strm_obj->num_bufs =
501 pattr->stream_attr_in->num_bufs;
502 strm_obj->strm_mode =
503 pattr->stream_attr_in->strm_mode;
504 strm_obj->segment_id =
505 pattr->stream_attr_in->segment_id;
506 strm_obj->buf_alignment =
507 pattr->stream_attr_in->buf_alignment;
508 strm_obj->udma_chnl_id =
509 pattr->stream_attr_in->udma_chnl_id;
510 strm_obj->udma_priority =
511 pattr->stream_attr_in->udma_priority;
512 chnl_attr_obj.uio_reqs =
513 pattr->stream_attr_in->num_bufs;
514 } else {
515 strm_obj->utimeout = DEFAULTTIMEOUT;
516 strm_obj->num_bufs = DEFAULTNUMBUFS;
517 strm_obj->strm_mode = STRMMODE_PROCCOPY;
518 strm_obj->segment_id = 0; /* local mem */
519 strm_obj->buf_alignment = 0;
520 strm_obj->udma_chnl_id = 0;
521 strm_obj->udma_priority = 0;
522 chnl_attr_obj.uio_reqs = DEFAULTNUMBUFS;
524 chnl_attr_obj.reserved1 = NULL;
525 /* DMA chnl flush timeout */
526 chnl_attr_obj.reserved2 = strm_obj->utimeout;
527 chnl_attr_obj.event_obj = NULL;
528 if (pattr->user_event != NULL)
529 chnl_attr_obj.event_obj = pattr->user_event;
533 if (status)
534 goto func_cont;
536 if ((pattr->virt_base == NULL) || !(pattr->ul_virt_size > 0))
537 goto func_cont;
539 /* No System DMA */
540 DBC_ASSERT(strm_obj->strm_mode != STRMMODE_LDMA);
541 /* Get the shared mem mgr for this streams dev object */
542 status = dev_get_cmm_mgr(strm_mgr_obj->dev_obj, &hcmm_mgr);
543 if (!status) {
544 /*Allocate a SM addr translator for this strm. */
545 status = cmm_xlator_create(&strm_obj->xlator, hcmm_mgr, NULL);
546 if (!status) {
547 DBC_ASSERT(strm_obj->segment_id > 0);
548 /* Set translators Virt Addr attributes */
549 status = cmm_xlator_info(strm_obj->xlator,
550 (u8 **) &pattr->virt_base,
551 pattr->ul_virt_size,
552 strm_obj->segment_id, true);
555 func_cont:
556 if (!status) {
557 /* Open channel */
558 chnl_mode = (dir == DSP_TONODE) ?
559 CHNL_MODETODSP : CHNL_MODEFROMDSP;
560 intf_fxns = strm_mgr_obj->intf_fxns;
561 status = (*intf_fxns->pfn_chnl_open) (&(strm_obj->chnl_obj),
562 strm_mgr_obj->hchnl_mgr,
563 chnl_mode, ul_chnl_id,
564 &chnl_attr_obj);
565 if (status) {
567 * over-ride non-returnable status codes so we return
568 * something documented
570 if (status != -ENOMEM && status !=
571 -EINVAL && status != -EPERM) {
573 * We got a status that's not return-able.
574 * Assert that we got something we were
575 * expecting (-EFAULT isn't acceptable,
576 * strm_mgr_obj->hchnl_mgr better be valid or we
577 * assert here), and then return -EPERM.
579 DBC_ASSERT(status == -ENOSR ||
580 status == -ECHRNG ||
581 status == -EALREADY ||
582 status == -EIO);
583 status = -EPERM;
587 if (!status) {
588 status = drv_proc_insert_strm_res_element(strm_obj,
589 &stream_res, pr_ctxt);
590 if (status)
591 delete_strm(strm_obj);
592 else
593 *strmres = (struct strm_res_object *)stream_res;
594 } else {
595 (void)delete_strm(strm_obj);
598 /* ensure we return a documented error code */
599 DBC_ENSURE((!status && strm_obj) ||
600 (*strmres == NULL && (status == -EFAULT ||
601 status == -EPERM
602 || status == -EINVAL)));
604 dev_dbg(bridge, "%s: hnode: %p dir: 0x%x index: 0x%x pattr: %p "
605 "strmres: %p status: 0x%x\n", __func__,
606 hnode, dir, index, pattr, strmres, status);
607 return status;
611 * ======== strm_reclaim ========
612 * Purpose:
613 * Relcaims a buffer from a stream.
615 int strm_reclaim(struct strm_object *stream_obj, u8 ** buf_ptr,
616 u32 *nbytes, u32 *buff_size, u32 *pdw_arg)
618 struct bridge_drv_interface *intf_fxns;
619 struct chnl_ioc chnl_ioc_obj;
620 int status = 0;
621 void *tmp_buf = NULL;
623 DBC_REQUIRE(refs > 0);
624 DBC_REQUIRE(buf_ptr != NULL);
625 DBC_REQUIRE(nbytes != NULL);
626 DBC_REQUIRE(pdw_arg != NULL);
628 if (!stream_obj) {
629 status = -EFAULT;
630 goto func_end;
632 intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
634 status =
635 (*intf_fxns->pfn_chnl_get_ioc) (stream_obj->chnl_obj,
636 stream_obj->utimeout,
637 &chnl_ioc_obj);
638 if (!status) {
639 *nbytes = chnl_ioc_obj.byte_size;
640 if (buff_size)
641 *buff_size = chnl_ioc_obj.buf_size;
643 *pdw_arg = chnl_ioc_obj.dw_arg;
644 if (!CHNL_IS_IO_COMPLETE(chnl_ioc_obj)) {
645 if (CHNL_IS_TIMED_OUT(chnl_ioc_obj)) {
646 status = -ETIME;
647 } else {
648 /* Allow reclaims after idle to succeed */
649 if (!CHNL_IS_IO_CANCELLED(chnl_ioc_obj))
650 status = -EPERM;
654 /* Translate zerocopy buffer if channel not canceled. */
655 if (!status
656 && (!CHNL_IS_IO_CANCELLED(chnl_ioc_obj))
657 && (stream_obj->strm_mode == STRMMODE_ZEROCOPY)) {
659 * This is a zero-copy channel so chnl_ioc_obj.pbuf
660 * contains the DSP address of SM. We need to
661 * translate it to a virtual address for the user
662 * thread to access.
663 * Note: Could add CMM_DSPPA2VA to CMM in the future.
665 tmp_buf = cmm_xlator_translate(stream_obj->xlator,
666 chnl_ioc_obj.pbuf,
667 CMM_DSPPA2PA);
668 if (tmp_buf != NULL) {
669 /* now convert this GPP Pa to Va */
670 tmp_buf = cmm_xlator_translate(stream_obj->
671 xlator,
672 tmp_buf,
673 CMM_PA2VA);
675 if (tmp_buf == NULL)
676 status = -ESRCH;
678 chnl_ioc_obj.pbuf = tmp_buf;
680 *buf_ptr = chnl_ioc_obj.pbuf;
682 func_end:
683 /* ensure we return a documented return code */
684 DBC_ENSURE(!status || status == -EFAULT ||
685 status == -ETIME || status == -ESRCH ||
686 status == -EPERM);
688 dev_dbg(bridge, "%s: stream_obj: %p buf_ptr: %p nbytes: %p "
689 "pdw_arg: %p status 0x%x\n", __func__, stream_obj,
690 buf_ptr, nbytes, pdw_arg, status);
691 return status;
695 * ======== strm_register_notify ========
696 * Purpose:
697 * Register to be notified on specific events for this stream.
699 int strm_register_notify(struct strm_object *stream_obj, u32 event_mask,
700 u32 notify_type, struct dsp_notification
701 * hnotification)
703 struct bridge_drv_interface *intf_fxns;
704 int status = 0;
706 DBC_REQUIRE(refs > 0);
707 DBC_REQUIRE(hnotification != NULL);
709 if (!stream_obj) {
710 status = -EFAULT;
711 } else if ((event_mask & ~((DSP_STREAMIOCOMPLETION) |
712 DSP_STREAMDONE)) != 0) {
713 status = -EINVAL;
714 } else {
715 if (notify_type != DSP_SIGNALEVENT)
716 status = -ENOSYS;
719 if (!status) {
720 intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
722 status =
723 (*intf_fxns->pfn_chnl_register_notify) (stream_obj->
724 chnl_obj,
725 event_mask,
726 notify_type,
727 hnotification);
729 /* ensure we return a documented return code */
730 DBC_ENSURE(!status || status == -EFAULT ||
731 status == -ETIME || status == -ESRCH ||
732 status == -ENOSYS || status == -EPERM);
733 return status;
737 * ======== strm_select ========
738 * Purpose:
739 * Selects a ready stream.
741 int strm_select(struct strm_object **strm_tab, u32 strms,
742 u32 *pmask, u32 utimeout)
744 u32 index;
745 struct chnl_info chnl_info_obj;
746 struct bridge_drv_interface *intf_fxns;
747 struct sync_object **sync_events = NULL;
748 u32 i;
749 int status = 0;
751 DBC_REQUIRE(refs > 0);
752 DBC_REQUIRE(strm_tab != NULL);
753 DBC_REQUIRE(pmask != NULL);
754 DBC_REQUIRE(strms > 0);
756 *pmask = 0;
757 for (i = 0; i < strms; i++) {
758 if (!strm_tab[i]) {
759 status = -EFAULT;
760 break;
763 if (status)
764 goto func_end;
766 /* Determine which channels have IO ready */
767 for (i = 0; i < strms; i++) {
768 intf_fxns = strm_tab[i]->strm_mgr_obj->intf_fxns;
769 status = (*intf_fxns->pfn_chnl_get_info) (strm_tab[i]->chnl_obj,
770 &chnl_info_obj);
771 if (status) {
772 break;
773 } else {
774 if (chnl_info_obj.cio_cs > 0)
775 *pmask |= (1 << i);
779 if (!status && utimeout > 0 && *pmask == 0) {
780 /* Non-zero timeout */
781 sync_events = kmalloc(strms * sizeof(struct sync_object *),
782 GFP_KERNEL);
784 if (sync_events == NULL) {
785 status = -ENOMEM;
786 } else {
787 for (i = 0; i < strms; i++) {
788 intf_fxns =
789 strm_tab[i]->strm_mgr_obj->intf_fxns;
790 status = (*intf_fxns->pfn_chnl_get_info)
791 (strm_tab[i]->chnl_obj, &chnl_info_obj);
792 if (status)
793 break;
794 else
795 sync_events[i] =
796 chnl_info_obj.sync_event;
800 if (!status) {
801 status =
802 sync_wait_on_multiple_events(sync_events, strms,
803 utimeout, &index);
804 if (!status) {
805 /* Since we waited on the event, we have to
806 * reset it */
807 sync_set_event(sync_events[index]);
808 *pmask = 1 << index;
812 func_end:
813 kfree(sync_events);
815 DBC_ENSURE((!status && (*pmask != 0 || utimeout == 0)) ||
816 (status && *pmask == 0));
818 return status;
822 * ======== delete_strm ========
823 * Purpose:
824 * Frees the resources allocated for a stream.
826 static int delete_strm(struct strm_object *stream_obj)
828 struct bridge_drv_interface *intf_fxns;
829 int status = 0;
831 if (stream_obj) {
832 if (stream_obj->chnl_obj) {
833 intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
834 /* Channel close can fail only if the channel handle
835 * is invalid. */
836 status = (*intf_fxns->pfn_chnl_close)
837 (stream_obj->chnl_obj);
838 /* Free all SM address translator resources */
839 if (!status) {
840 if (stream_obj->xlator) {
841 /* force free */
842 (void)cmm_xlator_delete(stream_obj->
843 xlator,
844 true);
848 kfree(stream_obj);
849 } else {
850 status = -EFAULT;
852 return status;