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.
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().
69 struct strm_mgr
*strm_mgr_obj
;
70 struct chnl_object
*chnl_obj
;
71 u32 dir
; /* DSP_TONODE or DSP_FROMNODE */
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 ========
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
)
106 struct strm_object
*stream_obj
= strmres
->hstream
;
108 DBC_REQUIRE(refs
> 0);
109 DBC_REQUIRE(ap_buffer
!= NULL
);
113 * Allocate from segment specified at time of stream open.
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
],
129 if (ap_buffer
[i
] == NULL
) {
136 strm_free_buffer(strmres
, ap_buffer
, alloc_cnt
, pr_ctxt
);
141 drv_proc_update_strm_res(num_bufs
, strmres
);
148 * ======== strm_close ========
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
;
158 struct strm_object
*stream_obj
= strmres
->hstream
;
160 DBC_REQUIRE(refs
> 0);
165 /* Have all buffers been reclaimed? If not, return
167 intf_fxns
= stream_obj
->strm_mgr_obj
->intf_fxns
;
169 (*intf_fxns
->pfn_chnl_get_info
) (stream_obj
->chnl_obj
,
173 if (chnl_info_obj
.cio_cs
> 0 || chnl_info_obj
.cio_reqs
> 0)
176 status
= delete_strm(stream_obj
);
182 idr_remove(pr_ctxt
->stream_id
, strmres
->id
);
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__
,
193 * ======== strm_create ========
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
;
203 DBC_REQUIRE(refs
> 0);
204 DBC_REQUIRE(strm_man
!= NULL
);
205 DBC_REQUIRE(dev_obj
!= NULL
);
208 /* Allocate STRM manager object */
209 strm_mgr_obj
= kzalloc(sizeof(struct strm_mgr
), GFP_KERNEL
);
210 if (strm_mgr_obj
== NULL
)
213 strm_mgr_obj
->dev_obj
= dev_obj
;
215 /* Get Channel manager and Bridge function interface */
217 status
= dev_get_chnl_mgr(dev_obj
, &(strm_mgr_obj
->hchnl_mgr
));
219 (void)dev_get_intf_fxns(dev_obj
,
220 &(strm_mgr_obj
->intf_fxns
));
221 DBC_ASSERT(strm_mgr_obj
->intf_fxns
!= NULL
);
226 *strm_man
= strm_mgr_obj
;
230 DBC_ENSURE((!status
&& *strm_man
) || (status
&& *strm_man
== NULL
));
236 * ======== strm_delete ========
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
);
249 * ======== strm_exit ========
251 * Discontinue usage of STRM module.
255 DBC_REQUIRE(refs
> 0);
259 DBC_ENSURE(refs
>= 0);
263 * ======== strm_free_buffer ========
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
)
272 struct strm_object
*stream_obj
= strmres
->hstream
;
274 DBC_REQUIRE(refs
> 0);
275 DBC_REQUIRE(ap_buffer
!= NULL
);
281 for (i
= 0; i
< num_bufs
; i
++) {
282 DBC_ASSERT(stream_obj
->xlator
!= NULL
);
284 cmm_xlator_free_buf(stream_obj
->xlator
,
291 drv_proc_update_strm_res(num_bufs
- i
, strmres
);
297 * ======== strm_get_info ========
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
;
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
));
317 if (stream_info_size
< sizeof(struct stream_info
)) {
318 /* size of users info */
325 intf_fxns
= stream_obj
->strm_mgr_obj
->intf_fxns
;
327 (*intf_fxns
->pfn_chnl_get_info
) (stream_obj
->chnl_obj
,
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
;
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
=
357 stream_info
->user_strm
->ss_stream_state
= STREAM_IDLE
;
365 * ======== strm_idle ========
367 * Idles a particular stream.
369 int strm_idle(struct strm_object
*stream_obj
, bool flush_data
)
371 struct bridge_drv_interface
*intf_fxns
;
374 DBC_REQUIRE(refs
> 0);
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
,
386 dev_dbg(bridge
, "%s: stream_obj: %p flush_data: 0x%x status: 0x%x\n",
387 __func__
, stream_obj
, flush_data
, status
);
392 * ======== strm_init ========
394 * Initialize the STRM module.
400 DBC_REQUIRE(refs
>= 0);
405 DBC_ENSURE((ret
&& (refs
> 0)) || (!ret
&& (refs
>= 0)));
411 * ======== strm_issue ========
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
;
420 void *tmp_buf
= NULL
;
422 DBC_REQUIRE(refs
> 0);
423 DBC_REQUIRE(pbuf
!= NULL
);
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
,
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
);
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
);
454 * ======== strm_open ========
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
;
467 struct strm_object
*strm_obj
= NULL
;
469 struct chnl_attr chnl_attr_obj
;
471 struct cmm_object
*hcmm_mgr
= NULL
; /* Shared memory manager hndl */
475 DBC_REQUIRE(refs
> 0);
476 DBC_REQUIRE(strmres
!= NULL
);
477 DBC_REQUIRE(pattr
!= NULL
);
479 if (dir
!= DSP_TONODE
&& dir
!= DSP_FROMNODE
) {
482 /* Get the channel id from the node (set in node_connect()) */
483 status
= node_get_channel_id(hnode
, dir
, index
, &ul_chnl_id
);
486 status
= node_get_strm_mgr(hnode
, &strm_mgr_obj
);
489 strm_obj
= kzalloc(sizeof(struct strm_object
), GFP_KERNEL
);
490 if (strm_obj
== NULL
) {
493 strm_obj
->strm_mgr_obj
= strm_mgr_obj
;
495 strm_obj
->strm_state
= STREAM_IDLE
;
496 strm_obj
->user_event
= pattr
->user_event
;
497 if (pattr
->stream_attr_in
!= NULL
) {
499 pattr
->stream_attr_in
->utimeout
;
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
;
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
;
536 if ((pattr
->virt_base
== NULL
) || !(pattr
->ul_virt_size
> 0))
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
);
544 /*Allocate a SM addr translator for this strm. */
545 status
= cmm_xlator_create(&strm_obj
->xlator
, hcmm_mgr
, NULL
);
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
,
552 strm_obj
->segment_id
, true);
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
,
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
||
581 status
== -EALREADY
||
588 status
= drv_proc_insert_strm_res_element(strm_obj
,
589 &stream_res
, pr_ctxt
);
591 delete_strm(strm_obj
);
593 *strmres
= (struct strm_res_object
*)stream_res
;
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
||
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
);
611 * ======== strm_reclaim ========
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
;
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
);
632 intf_fxns
= stream_obj
->strm_mgr_obj
->intf_fxns
;
635 (*intf_fxns
->pfn_chnl_get_ioc
) (stream_obj
->chnl_obj
,
636 stream_obj
->utimeout
,
639 *nbytes
= chnl_ioc_obj
.byte_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
)) {
648 /* Allow reclaims after idle to succeed */
649 if (!CHNL_IS_IO_CANCELLED(chnl_ioc_obj
))
654 /* Translate zerocopy buffer if channel not canceled. */
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
663 * Note: Could add CMM_DSPPA2VA to CMM in the future.
665 tmp_buf
= cmm_xlator_translate(stream_obj
->xlator
,
668 if (tmp_buf
!= NULL
) {
669 /* now convert this GPP Pa to Va */
670 tmp_buf
= cmm_xlator_translate(stream_obj
->
678 chnl_ioc_obj
.pbuf
= tmp_buf
;
680 *buf_ptr
= chnl_ioc_obj
.pbuf
;
683 /* ensure we return a documented return code */
684 DBC_ENSURE(!status
|| status
== -EFAULT
||
685 status
== -ETIME
|| status
== -ESRCH
||
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
);
695 * ======== strm_register_notify ========
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
703 struct bridge_drv_interface
*intf_fxns
;
706 DBC_REQUIRE(refs
> 0);
707 DBC_REQUIRE(hnotification
!= NULL
);
711 } else if ((event_mask
& ~((DSP_STREAMIOCOMPLETION
) |
712 DSP_STREAMDONE
)) != 0) {
715 if (notify_type
!= DSP_SIGNALEVENT
)
720 intf_fxns
= stream_obj
->strm_mgr_obj
->intf_fxns
;
723 (*intf_fxns
->pfn_chnl_register_notify
) (stream_obj
->
729 /* ensure we return a documented return code */
730 DBC_ENSURE(!status
|| status
== -EFAULT
||
731 status
== -ETIME
|| status
== -ESRCH
||
732 status
== -ENOSYS
|| status
== -EPERM
);
737 * ======== strm_select ========
739 * Selects a ready stream.
741 int strm_select(struct strm_object
**strm_tab
, u32 strms
,
742 u32
*pmask
, u32 utimeout
)
745 struct chnl_info chnl_info_obj
;
746 struct bridge_drv_interface
*intf_fxns
;
747 struct sync_object
**sync_events
= NULL
;
751 DBC_REQUIRE(refs
> 0);
752 DBC_REQUIRE(strm_tab
!= NULL
);
753 DBC_REQUIRE(pmask
!= NULL
);
754 DBC_REQUIRE(strms
> 0);
757 for (i
= 0; i
< strms
; i
++) {
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
,
774 if (chnl_info_obj
.cio_cs
> 0)
779 if (!status
&& utimeout
> 0 && *pmask
== 0) {
780 /* Non-zero timeout */
781 sync_events
= kmalloc(strms
* sizeof(struct sync_object
*),
784 if (sync_events
== NULL
) {
787 for (i
= 0; i
< strms
; i
++) {
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
);
796 chnl_info_obj
.sync_event
;
802 sync_wait_on_multiple_events(sync_events
, strms
,
805 /* Since we waited on the event, we have to
807 sync_set_event(sync_events
[index
]);
815 DBC_ENSURE((!status
&& (*pmask
!= 0 || utimeout
== 0)) ||
816 (status
&& *pmask
== 0));
822 * ======== delete_strm ========
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
;
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
836 status
= (*intf_fxns
->pfn_chnl_close
)
837 (stream_obj
->chnl_obj
);
838 /* Free all SM address translator resources */
840 if (stream_obj
->xlator
) {
842 (void)cmm_xlator_delete(stream_obj
->