4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6 * DSP/BIOS Bridge Node 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>
20 /* ----------------------------------- Host OS */
21 #include <dspbridge/host_os.h>
23 /* ----------------------------------- DSP/BIOS Bridge */
24 #include <dspbridge/dbdefs.h>
26 /* ----------------------------------- Trace & Debug */
27 #include <dspbridge/dbc.h>
29 /* ----------------------------------- OS Adaptation Layer */
30 #include <dspbridge/cfg.h>
31 #include <dspbridge/list.h>
32 #include <dspbridge/memdefs.h>
33 #include <dspbridge/proc.h>
34 #include <dspbridge/strm.h>
35 #include <dspbridge/sync.h>
36 #include <dspbridge/ntfy.h>
38 /* ----------------------------------- Platform Manager */
39 #include <dspbridge/cmm.h>
40 #include <dspbridge/cod.h>
41 #include <dspbridge/dev.h>
42 #include <dspbridge/msg.h>
44 /* ----------------------------------- Resource Manager */
45 #include <dspbridge/dbdcd.h>
46 #include <dspbridge/disp.h>
47 #include <dspbridge/rms_sh.h>
49 /* ----------------------------------- Link Driver */
50 #include <dspbridge/dspdefs.h>
51 #include <dspbridge/dspioctl.h>
53 /* ----------------------------------- Others */
54 #include <dspbridge/gb.h>
55 #include <dspbridge/uuidutil.h>
57 /* ----------------------------------- This */
58 #include <dspbridge/nodepriv.h>
59 #include <dspbridge/node.h>
60 #include <dspbridge/dmm.h>
62 /* Static/Dynamic Loader includes */
63 #include <dspbridge/dbll.h>
64 #include <dspbridge/nldr.h>
66 #include <dspbridge/drv.h>
67 #include <dspbridge/drvdefs.h>
68 #include <dspbridge/resourcecleanup.h>
71 #include <dspbridge/dspdeh.h>
73 #define HOSTPREFIX "/host"
74 #define PIPEPREFIX "/dbpipe"
76 #define MAX_INPUTS(h) \
77 ((h)->dcd_props.obj_data.node_obj.ndb_props.num_input_streams)
78 #define MAX_OUTPUTS(h) \
79 ((h)->dcd_props.obj_data.node_obj.ndb_props.num_output_streams)
81 #define NODE_GET_PRIORITY(h) ((h)->prio)
82 #define NODE_SET_PRIORITY(hnode, prio) ((hnode)->prio = prio)
83 #define NODE_SET_STATE(hnode, state) ((hnode)->node_state = state)
85 #define MAXPIPES 100 /* Max # of /pipe connections (CSL limit) */
86 #define MAXDEVSUFFIXLEN 2 /* Max(Log base 10 of MAXPIPES, MAXSTREAMS) */
88 #define PIPENAMELEN (sizeof(PIPEPREFIX) + MAXDEVSUFFIXLEN)
89 #define HOSTNAMELEN (sizeof(HOSTPREFIX) + MAXDEVSUFFIXLEN)
91 #define MAXDEVNAMELEN 32 /* dsp_ndbprops.ac_name size */
93 #define EXECUTEPHASE 2
96 /* Define default STRM parameters */
98 * TBD: Put in header file, make global DSP_STRMATTRS with defaults,
99 * or make defaults configurable.
101 #define DEFAULTBUFSIZE 32
102 #define DEFAULTNBUFS 2
103 #define DEFAULTSEGID 0
104 #define DEFAULTALIGNMENT 0
105 #define DEFAULTTIMEOUT 10000
107 #define RMSQUERYSERVER 0
108 #define RMSCONFIGURESERVER 1
109 #define RMSCREATENODE 2
110 #define RMSEXECUTENODE 3
111 #define RMSDELETENODE 4
112 #define RMSCHANGENODEPRIORITY 5
113 #define RMSREADMEMORY 6
114 #define RMSWRITEMEMORY 7
116 #define MAXTIMEOUT 2000
120 #define PWR_TIMEOUT 500 /* default PWR timeout in msec */
122 #define STACKSEGLABEL "L1DSRAM_HEAP" /* Label for DSP Stack Segment Addr */
125 * ======== node_mgr ========
128 struct dev_object
*hdev_obj
; /* Device object */
129 /* Function interface to Bridge driver */
130 struct bridge_drv_interface
*intf_fxns
;
131 struct dcd_manager
*hdcd_mgr
; /* Proc/Node data manager */
132 struct disp_object
*disp_obj
; /* Node dispatcher */
133 struct lst_list
*node_list
; /* List of all allocated nodes */
134 u32 num_nodes
; /* Number of nodes in node_list */
135 u32 num_created
; /* Number of nodes *created* on DSP */
136 struct gb_t_map
*pipe_map
; /* Pipe connection bit map */
137 struct gb_t_map
*pipe_done_map
; /* Pipes that are half free */
138 struct gb_t_map
*chnl_map
; /* Channel allocation bit map */
139 struct gb_t_map
*dma_chnl_map
; /* DMA Channel allocation bit map */
140 struct gb_t_map
*zc_chnl_map
; /* Zero-Copy Channel alloc bit map */
141 struct ntfy_object
*ntfy_obj
; /* Manages registered notifications */
142 struct mutex node_mgr_lock
; /* For critical sections */
143 u32 ul_fxn_addrs
[NUMRMSFXNS
]; /* RMS function addresses */
144 struct msg_mgr
*msg_mgr_obj
;
146 /* Processor properties needed by Node Dispatcher */
147 u32 ul_num_chnls
; /* Total number of channels */
148 u32 ul_chnl_offset
; /* Offset of chnl ids rsvd for RMS */
149 u32 ul_chnl_buf_size
; /* Buffer size for data to RMS */
150 int proc_family
; /* eg, 5000 */
151 int proc_type
; /* eg, 5510 */
152 u32 udsp_word_size
; /* Size of DSP word on host bytes */
153 u32 udsp_data_mau_size
; /* Size of DSP data MAU */
154 u32 udsp_mau_size
; /* Size of MAU */
155 s32 min_pri
; /* Minimum runtime priority for node */
156 s32 max_pri
; /* Maximum runtime priority for node */
158 struct strm_mgr
*strm_mgr_obj
; /* STRM manager */
160 /* Loader properties */
161 struct nldr_object
*nldr_obj
; /* Handle to loader */
162 struct node_ldr_fxns nldr_fxns
; /* Handle to loader functions */
163 bool loader_init
; /* Loader Init function succeeded? */
167 * ======== connecttype ========
177 * ======== stream_chnl ========
180 enum connecttype type
; /* Type of stream connection */
181 u32 dev_id
; /* pipe or channel id */
185 * ======== node_object ========
188 struct list_head list_elem
;
189 struct node_mgr
*hnode_mgr
; /* The manager of this node */
190 struct proc_object
*hprocessor
; /* Back pointer to processor */
191 struct dsp_uuid node_uuid
; /* Node's ID */
192 s32 prio
; /* Node's current priority */
193 u32 utimeout
; /* Timeout for blocking NODE calls */
194 u32 heap_size
; /* Heap Size */
195 u32 udsp_heap_virt_addr
; /* Heap Size */
196 u32 ugpp_heap_virt_addr
; /* Heap Size */
197 enum node_type ntype
; /* Type of node: message, task, etc */
198 enum node_state node_state
; /* NODE_ALLOCATED, NODE_CREATED, ... */
199 u32 num_inputs
; /* Current number of inputs */
200 u32 num_outputs
; /* Current number of outputs */
201 u32 max_input_index
; /* Current max input stream index */
202 u32 max_output_index
; /* Current max output stream index */
203 struct stream_chnl
*inputs
; /* Node's input streams */
204 struct stream_chnl
*outputs
; /* Node's output streams */
205 struct node_createargs create_args
; /* Args for node create func */
206 nodeenv node_env
; /* Environment returned by RMS */
207 struct dcd_genericobj dcd_props
; /* Node properties from DCD */
208 struct dsp_cbdata
*pargs
; /* Optional args to pass to node */
209 struct ntfy_object
*ntfy_obj
; /* Manages registered notifications */
210 char *pstr_dev_name
; /* device name, if device node */
211 struct sync_object
*sync_done
; /* Synchronize node_terminate */
212 s32 exit_status
; /* execute function return status */
214 /* Information needed for node_get_attr() */
215 void *device_owner
; /* If dev node, task that owns it */
216 u32 num_gpp_inputs
; /* Current # of from GPP streams */
217 u32 num_gpp_outputs
; /* Current # of to GPP streams */
218 /* Current stream connections */
219 struct dsp_streamconnect
*stream_connect
;
222 struct msg_queue
*msg_queue_obj
;
224 /* These fields used for SM messaging */
225 struct cmm_xlatorobject
*xlator
; /* Node's SM addr translator */
227 /* Handle to pass to dynamic loader */
228 struct nldr_nodeobject
*nldr_node_obj
;
229 bool loaded
; /* Code is (dynamically) loaded */
230 bool phase_split
; /* Phases split in many libs or ovly */
234 /* Default buffer attributes */
235 static struct dsp_bufferattr node_dfltbufattrs
= {
238 0, /* buf_alignment */
241 static void delete_node(struct node_object
*hnode
,
242 struct process_context
*pr_ctxt
);
243 static void delete_node_mgr(struct node_mgr
*hnode_mgr
);
244 static void fill_stream_connect(struct node_object
*node1
,
245 struct node_object
*node2
, u32 stream1
,
247 static void fill_stream_def(struct node_object
*hnode
,
248 struct node_strmdef
*pstrm_def
,
249 struct dsp_strmattr
*pattrs
);
250 static void free_stream(struct node_mgr
*hnode_mgr
, struct stream_chnl stream
);
251 static int get_fxn_address(struct node_object
*hnode
, u32
* fxn_addr
,
253 static int get_node_props(struct dcd_manager
*hdcd_mgr
,
254 struct node_object
*hnode
,
255 CONST
struct dsp_uuid
*node_uuid
,
256 struct dcd_genericobj
*dcd_prop
);
257 static int get_proc_props(struct node_mgr
*hnode_mgr
,
258 struct dev_object
*hdev_obj
);
259 static int get_rms_fxns(struct node_mgr
*hnode_mgr
);
260 static u32
ovly(void *priv_ref
, u32 dsp_run_addr
, u32 dsp_load_addr
,
261 u32 ul_num_bytes
, u32 mem_space
);
262 static u32
mem_write(void *priv_ref
, u32 dsp_add
, void *pbuf
,
263 u32 ul_num_bytes
, u32 mem_space
);
265 static u32 refs
; /* module reference count */
267 /* Dynamic loader functions. */
268 static struct node_ldr_fxns nldr_fxns
= {
279 enum node_state
node_get_state(void *hnode
)
281 struct node_object
*pnode
= (struct node_object
*)hnode
;
285 return pnode
->node_state
;
289 * ======== node_allocate ========
291 * Allocate GPP resources to manage a node on the DSP.
293 int node_allocate(struct proc_object
*hprocessor
,
294 IN CONST
struct dsp_uuid
*node_uuid
,
295 OPTIONAL IN CONST
struct dsp_cbdata
*pargs
,
296 OPTIONAL IN CONST
struct dsp_nodeattrin
*attr_in
,
297 OUT
struct node_object
**ph_node
,
298 struct process_context
*pr_ctxt
)
300 struct node_mgr
*hnode_mgr
;
301 struct dev_object
*hdev_obj
;
302 struct node_object
*pnode
= NULL
;
303 enum node_type node_type
= NODE_TASK
;
304 struct node_msgargs
*pmsg_args
;
305 struct node_taskargs
*ptask_args
;
307 struct bridge_drv_interface
*intf_fxns
;
309 struct cmm_object
*hcmm_mgr
= NULL
; /* Shared memory manager hndl */
314 u32 ul_stack_seg_addr
, ul_stack_seg_val
;
316 struct cfg_hostres
*host_res
;
317 struct bridge_dev_context
*pbridge_context
;
320 struct dsp_processorstate proc_state
;
322 struct dmm_object
*dmm_mgr
;
323 struct proc_object
*p_proc_object
= (struct proc_object
*)hprocessor
;
328 DBC_REQUIRE(refs
> 0);
329 DBC_REQUIRE(hprocessor
!= NULL
);
330 DBC_REQUIRE(ph_node
!= NULL
);
331 DBC_REQUIRE(node_uuid
!= NULL
);
335 status
= proc_get_processor_id(hprocessor
, &proc_id
);
337 if (proc_id
!= DSP_UNIT
)
340 status
= proc_get_dev_object(hprocessor
, &hdev_obj
);
341 if (DSP_SUCCEEDED(status
)) {
342 status
= dev_get_node_manager(hdev_obj
, &hnode_mgr
);
343 if (hnode_mgr
== NULL
)
348 if (DSP_FAILED(status
))
351 status
= dev_get_bridge_context(hdev_obj
, &pbridge_context
);
352 if (!pbridge_context
) {
357 status
= proc_get_state(hprocessor
, &proc_state
,
358 sizeof(struct dsp_processorstate
));
359 if (DSP_FAILED(status
))
361 /* If processor is in error state then don't attempt
362 to send the message */
363 if (proc_state
.proc_state
== PROC_ERROR
) {
368 /* Assuming that 0 is not a valid function address */
369 if (hnode_mgr
->ul_fxn_addrs
[0] == 0) {
370 /* No RMS on target - we currently can't handle this */
371 pr_err("%s: Failed, no RMS in base image\n", __func__
);
374 /* Validate attr_in fields, if non-NULL */
376 /* Check if attr_in->prio is within range */
377 if (attr_in
->prio
< hnode_mgr
->min_pri
||
378 attr_in
->prio
> hnode_mgr
->max_pri
)
382 /* Allocate node object and fill in */
383 if (DSP_FAILED(status
))
386 pnode
= kzalloc(sizeof(struct node_object
), GFP_KERNEL
);
391 pnode
->hnode_mgr
= hnode_mgr
;
392 /* This critical section protects get_node_props */
393 mutex_lock(&hnode_mgr
->node_mgr_lock
);
395 /* Get dsp_ndbprops from node database */
396 status
= get_node_props(hnode_mgr
->hdcd_mgr
, pnode
, node_uuid
,
397 &(pnode
->dcd_props
));
398 if (DSP_FAILED(status
))
401 pnode
->node_uuid
= *node_uuid
;
402 pnode
->hprocessor
= hprocessor
;
403 pnode
->ntype
= pnode
->dcd_props
.obj_data
.node_obj
.ndb_props
.ntype
;
404 pnode
->utimeout
= pnode
->dcd_props
.obj_data
.node_obj
.ndb_props
.utimeout
;
405 pnode
->prio
= pnode
->dcd_props
.obj_data
.node_obj
.ndb_props
.prio
;
407 /* Currently only C64 DSP builds support Node Dynamic * heaps */
408 /* Allocate memory for node heap */
409 pnode
->create_args
.asa
.task_arg_obj
.heap_size
= 0;
410 pnode
->create_args
.asa
.task_arg_obj
.udsp_heap_addr
= 0;
411 pnode
->create_args
.asa
.task_arg_obj
.udsp_heap_res_addr
= 0;
412 pnode
->create_args
.asa
.task_arg_obj
.ugpp_heap_addr
= 0;
416 /* Check if we have a user allocated node heap */
417 if (!(attr_in
->pgpp_virt_addr
))
420 /* check for page aligned Heap size */
421 if (((attr_in
->heap_size
) & (PG_SIZE4K
- 1))) {
422 pr_err("%s: node heap size not aligned to 4K, size = 0x%x \n",
423 __func__
, attr_in
->heap_size
);
426 pnode
->create_args
.asa
.task_arg_obj
.heap_size
=
428 pnode
->create_args
.asa
.task_arg_obj
.ugpp_heap_addr
=
429 (u32
) attr_in
->pgpp_virt_addr
;
431 if (DSP_FAILED(status
))
434 status
= proc_reserve_memory(hprocessor
,
435 pnode
->create_args
.asa
.task_arg_obj
.
436 heap_size
+ PAGE_SIZE
,
437 (void **)&(pnode
->create_args
.asa
.
438 task_arg_obj
.udsp_heap_res_addr
),
440 if (DSP_FAILED(status
)) {
441 pr_err("%s: Failed to reserve memory for heap: 0x%x\n",
446 status
= dmm_get_handle(p_proc_object
, &dmm_mgr
);
448 status
= DSP_EHANDLE
;
452 dmm_mem_map_dump(dmm_mgr
);
455 map_attrs
|= DSP_MAPLITTLEENDIAN
;
456 map_attrs
|= DSP_MAPELEMSIZE32
;
457 map_attrs
|= DSP_MAPVIRTUALADDR
;
458 status
= proc_map(hprocessor
, (void *)attr_in
->pgpp_virt_addr
,
459 pnode
->create_args
.asa
.task_arg_obj
.heap_size
,
460 (void *)pnode
->create_args
.asa
.task_arg_obj
.
461 udsp_heap_res_addr
, (void **)&mapped_addr
, map_attrs
,
463 if (DSP_FAILED(status
))
464 pr_err("%s: Failed to map memory for Heap: 0x%x\n",
467 pnode
->create_args
.asa
.task_arg_obj
.udsp_heap_addr
=
471 mutex_unlock(&hnode_mgr
->node_mgr_lock
);
472 if (attr_in
!= NULL
) {
473 /* Overrides of NBD properties */
474 pnode
->utimeout
= attr_in
->utimeout
;
475 pnode
->prio
= attr_in
->prio
;
477 /* Create object to manage notifications */
478 if (DSP_SUCCEEDED(status
)) {
479 pnode
->ntfy_obj
= kmalloc(sizeof(struct ntfy_object
),
482 ntfy_init(pnode
->ntfy_obj
);
487 if (DSP_SUCCEEDED(status
)) {
488 node_type
= node_get_type(pnode
);
489 /* Allocate dsp_streamconnect array for device, task, and
490 * dais socket nodes. */
491 if (node_type
!= NODE_MESSAGE
) {
492 num_streams
= MAX_INPUTS(pnode
) + MAX_OUTPUTS(pnode
);
493 pnode
->stream_connect
= kzalloc(num_streams
*
494 sizeof(struct dsp_streamconnect
),
496 if (num_streams
> 0 && pnode
->stream_connect
== NULL
)
500 if (DSP_SUCCEEDED(status
) && (node_type
== NODE_TASK
||
501 node_type
== NODE_DAISSOCKET
)) {
502 /* Allocate arrays for maintainig stream connections */
503 pnode
->inputs
= kzalloc(MAX_INPUTS(pnode
) *
504 sizeof(struct stream_chnl
), GFP_KERNEL
);
505 pnode
->outputs
= kzalloc(MAX_OUTPUTS(pnode
) *
506 sizeof(struct stream_chnl
), GFP_KERNEL
);
507 ptask_args
= &(pnode
->create_args
.asa
.task_arg_obj
);
508 ptask_args
->strm_in_def
= kzalloc(MAX_INPUTS(pnode
) *
509 sizeof(struct node_strmdef
),
511 ptask_args
->strm_out_def
= kzalloc(MAX_OUTPUTS(pnode
) *
512 sizeof(struct node_strmdef
),
514 if ((MAX_INPUTS(pnode
) > 0 && (pnode
->inputs
== NULL
||
515 ptask_args
->strm_in_def
517 || (MAX_OUTPUTS(pnode
) > 0
518 && (pnode
->outputs
== NULL
519 || ptask_args
->strm_out_def
== NULL
)))
523 if (DSP_SUCCEEDED(status
) && (node_type
!= NODE_DEVICE
)) {
524 /* Create an event that will be posted when RMS_EXIT is
526 pnode
->sync_done
= kzalloc(sizeof(struct sync_object
),
528 if (pnode
->sync_done
)
529 sync_init_event(pnode
->sync_done
);
533 if (DSP_SUCCEEDED(status
)) {
534 /*Get the shared mem mgr for this nodes dev object */
535 status
= cmm_get_handle(hprocessor
, &hcmm_mgr
);
536 if (DSP_SUCCEEDED(status
)) {
537 /* Allocate a SM addr translator for this node
539 status
= cmm_xlator_create(&pnode
->xlator
,
543 if (DSP_SUCCEEDED(status
)) {
544 /* Fill in message args */
545 if ((pargs
!= NULL
) && (pargs
->cb_data
> 0)) {
547 &(pnode
->create_args
.asa
.node_msg_args
);
548 pmsg_args
->pdata
= kzalloc(pargs
->cb_data
,
550 if (pmsg_args
->pdata
== NULL
) {
553 pmsg_args
->arg_length
= pargs
->cb_data
;
554 memcpy(pmsg_args
->pdata
,
562 if (DSP_SUCCEEDED(status
) && node_type
!= NODE_DEVICE
) {
563 /* Create a message queue for this node */
564 intf_fxns
= hnode_mgr
->intf_fxns
;
566 (*intf_fxns
->pfn_msg_create_queue
) (hnode_mgr
->msg_mgr_obj
,
567 &pnode
->msg_queue_obj
,
569 pnode
->create_args
.asa
.
570 node_msg_args
.max_msgs
,
574 if (DSP_SUCCEEDED(status
)) {
575 /* Create object for dynamic loading */
577 status
= hnode_mgr
->nldr_fxns
.pfn_allocate(hnode_mgr
->nldr_obj
,
583 &pnode
->phase_split
);
586 /* Compare value read from Node Properties and check if it is same as
587 * STACKSEGLABEL, if yes read the Address of STACKSEGLABEL, calculate
588 * GPP Address, Read the value in that address and override the
589 * stack_seg value in task args */
590 if (DSP_SUCCEEDED(status
) &&
591 (char *)pnode
->dcd_props
.obj_data
.node_obj
.ndb_props
.
592 stack_seg_name
!= NULL
) {
594 pnode
->dcd_props
.obj_data
.node_obj
.ndb_props
.
595 stack_seg_name
, STACKSEGLABEL
) == 0) {
597 hnode_mgr
->nldr_fxns
.
598 pfn_get_fxn_addr(pnode
->nldr_node_obj
, "DYNEXT_BEG",
600 if (DSP_FAILED(status
))
601 pr_err("%s: Failed to get addr for DYNEXT_BEG"
602 " status = 0x%x\n", __func__
, status
);
605 hnode_mgr
->nldr_fxns
.
606 pfn_get_fxn_addr(pnode
->nldr_node_obj
,
607 "L1DSRAM_HEAP", &pul_value
);
609 if (DSP_FAILED(status
))
610 pr_err("%s: Failed to get addr for L1DSRAM_HEAP"
611 " status = 0x%x\n", __func__
, status
);
613 host_res
= pbridge_context
->resources
;
617 if (DSP_FAILED(status
)) {
618 pr_err("%s: Failed to get host resource, status"
619 " = 0x%x\n", __func__
, status
);
623 ul_gpp_mem_base
= (u32
) host_res
->dw_mem_base
[1];
624 off_set
= pul_value
- dynext_base
;
625 ul_stack_seg_addr
= ul_gpp_mem_base
+ off_set
;
626 ul_stack_seg_val
= readl(ul_stack_seg_addr
);
628 dev_dbg(bridge
, "%s: StackSegVal = 0x%x, StackSegAddr ="
629 " 0x%x\n", __func__
, ul_stack_seg_val
,
632 pnode
->create_args
.asa
.task_arg_obj
.stack_seg
=
638 if (DSP_SUCCEEDED(status
)) {
639 /* Add the node to the node manager's list of allocated
641 lst_init_elem((struct list_head
*)pnode
);
642 NODE_SET_STATE(pnode
, NODE_ALLOCATED
);
644 mutex_lock(&hnode_mgr
->node_mgr_lock
);
646 lst_put_tail(hnode_mgr
->node_list
, (struct list_head
*) pnode
);
647 ++(hnode_mgr
->num_nodes
);
649 /* Exit critical section */
650 mutex_unlock(&hnode_mgr
->node_mgr_lock
);
652 /* Preset this to assume phases are split
653 * (for overlay and dll) */
654 pnode
->phase_split
= true;
656 if (DSP_SUCCEEDED(status
))
659 /* Notify all clients registered for DSP_NODESTATECHANGE. */
660 proc_notify_all_clients(hprocessor
, DSP_NODESTATECHANGE
);
664 delete_node(pnode
, pr_ctxt
);
668 if (DSP_SUCCEEDED(status
)) {
669 drv_insert_node_res_element(*ph_node
, &node_res
, pr_ctxt
);
670 drv_proc_node_update_heap_status(node_res
, true);
671 drv_proc_node_update_status(node_res
, true);
673 DBC_ENSURE((DSP_FAILED(status
) && (*ph_node
== NULL
)) ||
674 (DSP_SUCCEEDED(status
) && *ph_node
));
676 dev_dbg(bridge
, "%s: hprocessor: %p node_uuid: %p pargs: %p attr_in:"
677 " %p ph_node: %p status: 0x%x\n", __func__
, hprocessor
,
678 node_uuid
, pargs
, attr_in
, ph_node
, status
);
683 * ======== node_alloc_msg_buf ========
685 * Allocates buffer for zero copy messaging.
687 DBAPI
node_alloc_msg_buf(struct node_object
*hnode
, u32 usize
,
688 OPTIONAL IN OUT
struct dsp_bufferattr
*pattr
,
691 struct node_object
*pnode
= (struct node_object
*)hnode
;
693 bool va_flag
= false;
697 DBC_REQUIRE(refs
> 0);
698 DBC_REQUIRE(pbuffer
!= NULL
);
700 DBC_REQUIRE(usize
> 0);
704 else if (node_get_type(pnode
) == NODE_DEVICE
)
707 if (DSP_FAILED(status
))
711 pattr
= &node_dfltbufattrs
; /* set defaults */
713 status
= proc_get_processor_id(pnode
->hprocessor
, &proc_id
);
714 if (proc_id
!= DSP_UNIT
) {
718 /* If segment ID includes MEM_SETVIRTUALSEGID then pbuffer is a
719 * virt address, so set this info in this node's translator
720 * object for future ref. If MEM_GETVIRTUALSEGID then retrieve
721 * virtual address from node's translator. */
722 if ((pattr
->segment_id
& MEM_SETVIRTUALSEGID
) ||
723 (pattr
->segment_id
& MEM_GETVIRTUALSEGID
)) {
725 set_info
= (pattr
->segment_id
& MEM_SETVIRTUALSEGID
) ?
727 /* Clear mask bits */
728 pattr
->segment_id
&= ~MEM_MASKVIRTUALSEGID
;
729 /* Set/get this node's translators virtual address base/size */
730 status
= cmm_xlator_info(pnode
->xlator
, pbuffer
, usize
,
731 pattr
->segment_id
, set_info
);
733 if (DSP_SUCCEEDED(status
) && (!va_flag
)) {
734 if (pattr
->segment_id
!= 1) {
735 /* Node supports single SM segment only. */
738 /* Arbitrary SM buffer alignment not supported for host side
739 * allocs, but guaranteed for the following alignment
741 switch (pattr
->buf_alignment
) {
748 /* alignment value not suportted */
752 if (DSP_SUCCEEDED(status
)) {
753 /* allocate physical buffer from seg_id in node's
755 (void)cmm_xlator_alloc_buf(pnode
->xlator
, pbuffer
,
757 if (*pbuffer
== NULL
) {
758 pr_err("%s: error - Out of shared memory\n",
769 * ======== node_change_priority ========
771 * Change the priority of a node in the allocated state, or that is
772 * currently running or paused on the target.
774 int node_change_priority(struct node_object
*hnode
, s32 prio
)
776 struct node_object
*pnode
= (struct node_object
*)hnode
;
777 struct node_mgr
*hnode_mgr
= NULL
;
778 enum node_type node_type
;
779 enum node_state state
;
783 DBC_REQUIRE(refs
> 0);
785 if (!hnode
|| !hnode
->hnode_mgr
) {
788 hnode_mgr
= hnode
->hnode_mgr
;
789 node_type
= node_get_type(hnode
);
790 if (node_type
!= NODE_TASK
&& node_type
!= NODE_DAISSOCKET
)
792 else if (prio
< hnode_mgr
->min_pri
|| prio
> hnode_mgr
->max_pri
)
795 if (DSP_FAILED(status
))
798 /* Enter critical section */
799 mutex_lock(&hnode_mgr
->node_mgr_lock
);
801 state
= node_get_state(hnode
);
802 if (state
== NODE_ALLOCATED
|| state
== NODE_PAUSED
) {
803 NODE_SET_PRIORITY(hnode
, prio
);
805 if (state
!= NODE_RUNNING
) {
809 status
= proc_get_processor_id(pnode
->hprocessor
, &proc_id
);
810 if (proc_id
== DSP_UNIT
) {
812 disp_node_change_priority(hnode_mgr
->disp_obj
,
814 hnode_mgr
->ul_fxn_addrs
815 [RMSCHANGENODEPRIORITY
],
816 hnode
->node_env
, prio
);
818 if (DSP_SUCCEEDED(status
))
819 NODE_SET_PRIORITY(hnode
, prio
);
823 /* Leave critical section */
824 mutex_unlock(&hnode_mgr
->node_mgr_lock
);
830 * ======== node_connect ========
832 * Connect two nodes on the DSP, or a node on the DSP to the GPP.
834 int node_connect(struct node_object
*node1
, u32 stream1
,
835 struct node_object
*node2
,
836 u32 stream2
, OPTIONAL IN
struct dsp_strmattr
*pattrs
,
837 OPTIONAL IN
struct dsp_cbdata
*conn_param
)
839 struct node_mgr
*hnode_mgr
;
840 char *pstr_dev_name
= NULL
;
841 enum node_type node1_type
= NODE_TASK
;
842 enum node_type node2_type
= NODE_TASK
;
843 struct node_strmdef
*pstrm_def
;
844 struct node_strmdef
*input
= NULL
;
845 struct node_strmdef
*output
= NULL
;
846 struct node_object
*dev_node_obj
;
847 struct node_object
*hnode
;
848 struct stream_chnl
*pstream
;
849 u32 pipe_id
= GB_NOBITS
;
850 u32 chnl_id
= GB_NOBITS
;
854 DBC_REQUIRE(refs
> 0);
856 if ((node1
!= (struct node_object
*)DSP_HGPPNODE
&& !node1
) ||
857 (node2
!= (struct node_object
*)DSP_HGPPNODE
&& !node2
))
860 if (DSP_SUCCEEDED(status
)) {
861 /* The two nodes must be on the same processor */
862 if (node1
!= (struct node_object
*)DSP_HGPPNODE
&&
863 node2
!= (struct node_object
*)DSP_HGPPNODE
&&
864 node1
->hnode_mgr
!= node2
->hnode_mgr
)
866 /* Cannot connect a node to itself */
871 if (DSP_SUCCEEDED(status
)) {
872 /* node_get_type() will return NODE_GPP if hnode =
874 node1_type
= node_get_type(node1
);
875 node2_type
= node_get_type(node2
);
876 /* Check stream indices ranges */
877 if ((node1_type
!= NODE_GPP
&& node1_type
!= NODE_DEVICE
&&
878 stream1
>= MAX_OUTPUTS(node1
)) || (node2_type
!= NODE_GPP
885 if (DSP_SUCCEEDED(status
)) {
887 * Only the following types of connections are allowed:
888 * task/dais socket < == > task/dais socket
889 * task/dais socket < == > device
890 * task/dais socket < == > GPP
892 * ie, no message nodes, and at least one task or dais
895 if (node1_type
== NODE_MESSAGE
|| node2_type
== NODE_MESSAGE
||
896 (node1_type
!= NODE_TASK
&& node1_type
!= NODE_DAISSOCKET
&&
897 node2_type
!= NODE_TASK
&& node2_type
!= NODE_DAISSOCKET
))
901 * Check stream mode. Default is STRMMODE_PROCCOPY.
903 if (DSP_SUCCEEDED(status
) && pattrs
) {
904 if (pattrs
->strm_mode
!= STRMMODE_PROCCOPY
)
905 status
= -EPERM
; /* illegal stream mode */
908 if (DSP_FAILED(status
))
911 if (node1_type
!= NODE_GPP
) {
912 hnode_mgr
= node1
->hnode_mgr
;
914 DBC_ASSERT(node2
!= (struct node_object
*)DSP_HGPPNODE
);
915 hnode_mgr
= node2
->hnode_mgr
;
917 /* Enter critical section */
918 mutex_lock(&hnode_mgr
->node_mgr_lock
);
920 /* Nodes must be in the allocated state */
921 if (node1_type
!= NODE_GPP
&& node_get_state(node1
) != NODE_ALLOCATED
)
924 if (node2_type
!= NODE_GPP
&& node_get_state(node2
) != NODE_ALLOCATED
)
927 if (DSP_SUCCEEDED(status
)) {
928 /* Check that stream indices for task and dais socket nodes
929 * are not already be used. (Device nodes checked later) */
930 if (node1_type
== NODE_TASK
|| node1_type
== NODE_DAISSOCKET
) {
932 &(node1
->create_args
.asa
.
933 task_arg_obj
.strm_out_def
[stream1
]);
934 if (output
->sz_device
!= NULL
)
938 if (node2_type
== NODE_TASK
|| node2_type
== NODE_DAISSOCKET
) {
940 &(node2
->create_args
.asa
.
941 task_arg_obj
.strm_in_def
[stream2
]);
942 if (input
->sz_device
!= NULL
)
947 /* Connecting two task nodes? */
948 if (DSP_SUCCEEDED(status
) && ((node1_type
== NODE_TASK
||
949 node1_type
== NODE_DAISSOCKET
)
950 && (node2_type
== NODE_TASK
951 || node2_type
== NODE_DAISSOCKET
))) {
952 /* Find available pipe */
953 pipe_id
= gb_findandset(hnode_mgr
->pipe_map
);
954 if (pipe_id
== GB_NOBITS
) {
955 status
= -ECONNREFUSED
;
957 node1
->outputs
[stream1
].type
= NODECONNECT
;
958 node2
->inputs
[stream2
].type
= NODECONNECT
;
959 node1
->outputs
[stream1
].dev_id
= pipe_id
;
960 node2
->inputs
[stream2
].dev_id
= pipe_id
;
961 output
->sz_device
= kzalloc(PIPENAMELEN
+ 1,
963 input
->sz_device
= kzalloc(PIPENAMELEN
+ 1, GFP_KERNEL
);
964 if (output
->sz_device
== NULL
||
965 input
->sz_device
== NULL
) {
966 /* Undo the connection */
967 kfree(output
->sz_device
);
969 kfree(input
->sz_device
);
971 output
->sz_device
= NULL
;
972 input
->sz_device
= NULL
;
973 gb_clear(hnode_mgr
->pipe_map
, pipe_id
);
976 /* Copy "/dbpipe<pipId>" name to device names */
977 sprintf(output
->sz_device
, "%s%d",
978 PIPEPREFIX
, pipe_id
);
979 strcpy(input
->sz_device
, output
->sz_device
);
983 /* Connecting task node to host? */
984 if (DSP_SUCCEEDED(status
) && (node1_type
== NODE_GPP
||
985 node2_type
== NODE_GPP
)) {
986 if (node1_type
== NODE_GPP
) {
987 chnl_mode
= CHNL_MODETODSP
;
989 DBC_ASSERT(node2_type
== NODE_GPP
);
990 chnl_mode
= CHNL_MODEFROMDSP
;
992 /* Reserve a channel id. We need to put the name "/host<id>"
993 * in the node's create_args, but the host
994 * side channel will not be opened until DSPStream_Open is
995 * called for this node. */
997 if (pattrs
->strm_mode
== STRMMODE_RDMA
) {
999 gb_findandset(hnode_mgr
->dma_chnl_map
);
1000 /* dma chans are 2nd transport chnl set
1001 * ids(e.g. 16-31) */
1002 (chnl_id
!= GB_NOBITS
) ?
1005 hnode_mgr
->ul_num_chnls
) : chnl_id
;
1006 } else if (pattrs
->strm_mode
== STRMMODE_ZEROCOPY
) {
1007 chnl_id
= gb_findandset(hnode_mgr
->zc_chnl_map
);
1008 /* zero-copy chans are 3nd transport set
1010 (chnl_id
!= GB_NOBITS
) ? (chnl_id
= chnl_id
+
1015 } else { /* must be PROCCOPY */
1016 DBC_ASSERT(pattrs
->strm_mode
==
1018 chnl_id
= gb_findandset(hnode_mgr
->chnl_map
);
1022 /* default to PROCCOPY */
1023 chnl_id
= gb_findandset(hnode_mgr
->chnl_map
);
1025 if (chnl_id
== GB_NOBITS
) {
1026 status
= -ECONNREFUSED
;
1029 pstr_dev_name
= kzalloc(HOSTNAMELEN
+ 1, GFP_KERNEL
);
1030 if (pstr_dev_name
!= NULL
)
1034 if (pattrs
->strm_mode
== STRMMODE_RDMA
) {
1035 gb_clear(hnode_mgr
->dma_chnl_map
, chnl_id
-
1036 hnode_mgr
->ul_num_chnls
);
1037 } else if (pattrs
->strm_mode
== STRMMODE_ZEROCOPY
) {
1038 gb_clear(hnode_mgr
->zc_chnl_map
, chnl_id
-
1039 (2 * hnode_mgr
->ul_num_chnls
));
1041 DBC_ASSERT(pattrs
->strm_mode
==
1043 gb_clear(hnode_mgr
->chnl_map
, chnl_id
);
1046 gb_clear(hnode_mgr
->chnl_map
, chnl_id
);
1050 if (DSP_SUCCEEDED(status
)) {
1051 if (node1
== (struct node_object
*)DSP_HGPPNODE
) {
1052 node2
->inputs
[stream2
].type
= HOSTCONNECT
;
1053 node2
->inputs
[stream2
].dev_id
= chnl_id
;
1054 input
->sz_device
= pstr_dev_name
;
1056 node1
->outputs
[stream1
].type
= HOSTCONNECT
;
1057 node1
->outputs
[stream1
].dev_id
= chnl_id
;
1058 output
->sz_device
= pstr_dev_name
;
1060 sprintf(pstr_dev_name
, "%s%d", HOSTPREFIX
, chnl_id
);
1063 /* Connecting task node to device node? */
1064 if (DSP_SUCCEEDED(status
) && ((node1_type
== NODE_DEVICE
) ||
1065 (node2_type
== NODE_DEVICE
))) {
1066 if (node2_type
== NODE_DEVICE
) {
1067 /* node1 == > device */
1068 dev_node_obj
= node2
;
1070 pstream
= &(node1
->outputs
[stream1
]);
1073 /* device == > node2 */
1074 dev_node_obj
= node1
;
1076 pstream
= &(node2
->inputs
[stream2
]);
1079 /* Set up create args */
1080 pstream
->type
= DEVICECONNECT
;
1081 dw_length
= strlen(dev_node_obj
->pstr_dev_name
);
1082 if (conn_param
!= NULL
) {
1083 pstrm_def
->sz_device
= kzalloc(dw_length
+ 1 +
1084 conn_param
->cb_data
,
1087 pstrm_def
->sz_device
= kzalloc(dw_length
+ 1,
1090 if (pstrm_def
->sz_device
== NULL
) {
1093 /* Copy device name */
1094 strncpy(pstrm_def
->sz_device
,
1095 dev_node_obj
->pstr_dev_name
, dw_length
);
1096 if (conn_param
!= NULL
) {
1097 strncat(pstrm_def
->sz_device
,
1098 (char *)conn_param
->node_data
,
1099 (u32
) conn_param
->cb_data
);
1101 dev_node_obj
->device_owner
= hnode
;
1104 if (DSP_SUCCEEDED(status
)) {
1105 /* Fill in create args */
1106 if (node1_type
== NODE_TASK
|| node1_type
== NODE_DAISSOCKET
) {
1107 node1
->create_args
.asa
.task_arg_obj
.num_outputs
++;
1108 fill_stream_def(node1
, output
, pattrs
);
1110 if (node2_type
== NODE_TASK
|| node2_type
== NODE_DAISSOCKET
) {
1111 node2
->create_args
.asa
.task_arg_obj
.num_inputs
++;
1112 fill_stream_def(node2
, input
, pattrs
);
1114 /* Update node1 and node2 stream_connect */
1115 if (node1_type
!= NODE_GPP
&& node1_type
!= NODE_DEVICE
) {
1116 node1
->num_outputs
++;
1117 if (stream1
> node1
->max_output_index
)
1118 node1
->max_output_index
= stream1
;
1121 if (node2_type
!= NODE_GPP
&& node2_type
!= NODE_DEVICE
) {
1122 node2
->num_inputs
++;
1123 if (stream2
> node2
->max_input_index
)
1124 node2
->max_input_index
= stream2
;
1127 fill_stream_connect(node1
, node2
, stream1
, stream2
);
1129 /* end of sync_enter_cs */
1130 /* Exit critical section */
1131 mutex_unlock(&hnode_mgr
->node_mgr_lock
);
1133 dev_dbg(bridge
, "%s: node1: %p stream1: %d node2: %p stream2: %d"
1134 "pattrs: %p status: 0x%x\n", __func__
, node1
,
1135 stream1
, node2
, stream2
, pattrs
, status
);
1140 * ======== node_create ========
1142 * Create a node on the DSP by remotely calling the node's create function.
1144 int node_create(struct node_object
*hnode
)
1146 struct node_object
*pnode
= (struct node_object
*)hnode
;
1147 struct node_mgr
*hnode_mgr
;
1148 struct bridge_drv_interface
*intf_fxns
;
1150 enum node_type node_type
;
1153 struct dsp_cbdata cb_data
;
1155 struct dsp_processorstate proc_state
;
1156 struct proc_object
*hprocessor
;
1157 #if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
1158 struct dspbridge_platform_data
*pdata
=
1159 omap_dspbridge_dev
->dev
.platform_data
;
1162 DBC_REQUIRE(refs
> 0);
1167 hprocessor
= hnode
->hprocessor
;
1168 status
= proc_get_state(hprocessor
, &proc_state
,
1169 sizeof(struct dsp_processorstate
));
1170 if (DSP_FAILED(status
))
1172 /* If processor is in error state then don't attempt to create
1174 if (proc_state
.proc_state
== PROC_ERROR
) {
1178 /* create struct dsp_cbdata struct for PWR calls */
1179 cb_data
.cb_data
= PWR_TIMEOUT
;
1180 node_type
= node_get_type(hnode
);
1181 hnode_mgr
= hnode
->hnode_mgr
;
1182 intf_fxns
= hnode_mgr
->intf_fxns
;
1183 /* Get access to node dispatcher */
1184 mutex_lock(&hnode_mgr
->node_mgr_lock
);
1186 /* Check node state */
1187 if (node_get_state(hnode
) != NODE_ALLOCATED
)
1190 if (DSP_SUCCEEDED(status
))
1191 status
= proc_get_processor_id(pnode
->hprocessor
, &proc_id
);
1193 if (DSP_FAILED(status
))
1196 if (proc_id
!= DSP_UNIT
)
1199 /* Make sure streams are properly connected */
1200 if ((hnode
->num_inputs
&& hnode
->max_input_index
>
1201 hnode
->num_inputs
- 1) ||
1202 (hnode
->num_outputs
&& hnode
->max_output_index
>
1203 hnode
->num_outputs
- 1))
1206 if (DSP_SUCCEEDED(status
)) {
1207 /* If node's create function is not loaded, load it */
1208 /* Boost the OPP level to max level that DSP can be requested */
1209 #if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
1210 if (pdata
->cpu_set_freq
)
1211 (*pdata
->cpu_set_freq
) (pdata
->mpu_speed
[VDD1_OPP3
]);
1213 status
= hnode_mgr
->nldr_fxns
.pfn_load(hnode
->nldr_node_obj
,
1215 /* Get address of node's create function */
1216 if (DSP_SUCCEEDED(status
)) {
1217 hnode
->loaded
= true;
1218 if (node_type
!= NODE_DEVICE
) {
1219 status
= get_fxn_address(hnode
, &ul_create_fxn
,
1223 pr_err("%s: failed to load create code: 0x%x\n",
1226 /* Request the lowest OPP level */
1227 #if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
1228 if (pdata
->cpu_set_freq
)
1229 (*pdata
->cpu_set_freq
) (pdata
->mpu_speed
[VDD1_OPP1
]);
1231 /* Get address of iAlg functions, if socket node */
1232 if (DSP_SUCCEEDED(status
)) {
1233 if (node_type
== NODE_DAISSOCKET
) {
1234 status
= hnode_mgr
->nldr_fxns
.pfn_get_fxn_addr
1235 (hnode
->nldr_node_obj
,
1236 hnode
->dcd_props
.obj_data
.node_obj
.
1238 &hnode
->create_args
.asa
.
1239 task_arg_obj
.ul_dais_arg
);
1243 if (DSP_SUCCEEDED(status
)) {
1244 if (node_type
!= NODE_DEVICE
) {
1245 status
= disp_node_create(hnode_mgr
->disp_obj
, hnode
,
1246 hnode_mgr
->ul_fxn_addrs
1249 &(hnode
->create_args
),
1250 &(hnode
->node_env
));
1251 if (DSP_SUCCEEDED(status
)) {
1252 /* Set the message queue id to the node env
1254 intf_fxns
= hnode_mgr
->intf_fxns
;
1255 (*intf_fxns
->pfn_msg_set_queue_id
) (hnode
->
1261 /* Phase II/Overlays: Create, execute, delete phases possibly in
1262 * different files/sections. */
1263 if (hnode
->loaded
&& hnode
->phase_split
) {
1264 /* If create code was dynamically loaded, we can now unload
1266 status1
= hnode_mgr
->nldr_fxns
.pfn_unload(hnode
->nldr_node_obj
,
1268 hnode
->loaded
= false;
1270 if (DSP_FAILED(status1
))
1271 pr_err("%s: Failed to unload create code: 0x%x\n",
1274 /* Update node state and node manager state */
1275 if (DSP_SUCCEEDED(status
)) {
1276 NODE_SET_STATE(hnode
, NODE_CREATED
);
1277 hnode_mgr
->num_created
++;
1280 if (status
!= -EBADR
) {
1281 /* Put back in NODE_ALLOCATED state if error occurred */
1282 NODE_SET_STATE(hnode
, NODE_ALLOCATED
);
1285 /* Free access to node dispatcher */
1286 mutex_unlock(&hnode_mgr
->node_mgr_lock
);
1288 if (DSP_SUCCEEDED(status
)) {
1289 proc_notify_clients(hnode
->hprocessor
, DSP_NODESTATECHANGE
);
1290 ntfy_notify(hnode
->ntfy_obj
, DSP_NODESTATECHANGE
);
1293 dev_dbg(bridge
, "%s: hnode: %p status: 0x%x\n", __func__
,
1299 * ======== node_create_mgr ========
1301 * Create a NODE Manager object.
1303 int node_create_mgr(OUT
struct node_mgr
**node_man
,
1304 struct dev_object
*hdev_obj
)
1307 struct node_mgr
*node_mgr_obj
= NULL
;
1308 struct disp_attr disp_attr_obj
;
1309 char *sz_zl_file
= "";
1310 struct nldr_attrs nldr_attrs_obj
;
1313 DBC_REQUIRE(refs
> 0);
1314 DBC_REQUIRE(node_man
!= NULL
);
1315 DBC_REQUIRE(hdev_obj
!= NULL
);
1318 /* Allocate Node manager object */
1319 node_mgr_obj
= kzalloc(sizeof(struct node_mgr
), GFP_KERNEL
);
1321 node_mgr_obj
->hdev_obj
= hdev_obj
;
1322 node_mgr_obj
->node_list
= kzalloc(sizeof(struct lst_list
),
1324 node_mgr_obj
->pipe_map
= gb_create(MAXPIPES
);
1325 node_mgr_obj
->pipe_done_map
= gb_create(MAXPIPES
);
1326 if (node_mgr_obj
->node_list
== NULL
1327 || node_mgr_obj
->pipe_map
== NULL
1328 || node_mgr_obj
->pipe_done_map
== NULL
) {
1331 INIT_LIST_HEAD(&node_mgr_obj
->node_list
->head
);
1332 node_mgr_obj
->ntfy_obj
= kmalloc(
1333 sizeof(struct ntfy_object
), GFP_KERNEL
);
1334 if (node_mgr_obj
->ntfy_obj
)
1335 ntfy_init(node_mgr_obj
->ntfy_obj
);
1339 node_mgr_obj
->num_created
= 0;
1343 /* get devNodeType */
1344 if (DSP_SUCCEEDED(status
))
1345 status
= dev_get_dev_type(hdev_obj
, &dev_type
);
1347 /* Create the DCD Manager */
1348 if (DSP_SUCCEEDED(status
)) {
1350 dcd_create_manager(sz_zl_file
, &node_mgr_obj
->hdcd_mgr
);
1351 if (DSP_SUCCEEDED(status
))
1352 status
= get_proc_props(node_mgr_obj
, hdev_obj
);
1355 /* Create NODE Dispatcher */
1356 if (DSP_SUCCEEDED(status
)) {
1357 disp_attr_obj
.ul_chnl_offset
= node_mgr_obj
->ul_chnl_offset
;
1358 disp_attr_obj
.ul_chnl_buf_size
= node_mgr_obj
->ul_chnl_buf_size
;
1359 disp_attr_obj
.proc_family
= node_mgr_obj
->proc_family
;
1360 disp_attr_obj
.proc_type
= node_mgr_obj
->proc_type
;
1362 disp_create(&node_mgr_obj
->disp_obj
, hdev_obj
,
1365 /* Create a STRM Manager */
1366 if (DSP_SUCCEEDED(status
))
1367 status
= strm_create(&node_mgr_obj
->strm_mgr_obj
, hdev_obj
);
1369 if (DSP_SUCCEEDED(status
)) {
1370 dev_get_intf_fxns(hdev_obj
, &node_mgr_obj
->intf_fxns
);
1371 /* Get msg_ctrl queue manager */
1372 dev_get_msg_mgr(hdev_obj
, &node_mgr_obj
->msg_mgr_obj
);
1373 mutex_init(&node_mgr_obj
->node_mgr_lock
);
1374 node_mgr_obj
->chnl_map
= gb_create(node_mgr_obj
->ul_num_chnls
);
1375 /* dma chnl map. ul_num_chnls is # per transport */
1376 node_mgr_obj
->dma_chnl_map
=
1377 gb_create(node_mgr_obj
->ul_num_chnls
);
1378 node_mgr_obj
->zc_chnl_map
=
1379 gb_create(node_mgr_obj
->ul_num_chnls
);
1380 if ((node_mgr_obj
->chnl_map
== NULL
)
1381 || (node_mgr_obj
->dma_chnl_map
== NULL
)
1382 || (node_mgr_obj
->zc_chnl_map
== NULL
)) {
1385 /* Block out reserved channels */
1386 for (i
= 0; i
< node_mgr_obj
->ul_chnl_offset
; i
++)
1387 gb_set(node_mgr_obj
->chnl_map
, i
);
1389 /* Block out channels reserved for RMS */
1390 gb_set(node_mgr_obj
->chnl_map
,
1391 node_mgr_obj
->ul_chnl_offset
);
1392 gb_set(node_mgr_obj
->chnl_map
,
1393 node_mgr_obj
->ul_chnl_offset
+ 1);
1396 if (DSP_SUCCEEDED(status
)) {
1397 /* NO RM Server on the IVA */
1398 if (dev_type
!= IVA_UNIT
) {
1399 /* Get addresses of any RMS functions loaded */
1400 status
= get_rms_fxns(node_mgr_obj
);
1404 /* Get loader functions and create loader */
1405 if (DSP_SUCCEEDED(status
))
1406 node_mgr_obj
->nldr_fxns
= nldr_fxns
; /* Dyn loader funcs */
1408 if (DSP_SUCCEEDED(status
)) {
1409 nldr_attrs_obj
.pfn_ovly
= ovly
;
1410 nldr_attrs_obj
.pfn_write
= mem_write
;
1411 nldr_attrs_obj
.us_dsp_word_size
= node_mgr_obj
->udsp_word_size
;
1412 nldr_attrs_obj
.us_dsp_mau_size
= node_mgr_obj
->udsp_mau_size
;
1413 node_mgr_obj
->loader_init
= node_mgr_obj
->nldr_fxns
.pfn_init();
1415 node_mgr_obj
->nldr_fxns
.pfn_create(&node_mgr_obj
->nldr_obj
,
1419 if (DSP_SUCCEEDED(status
))
1420 *node_man
= node_mgr_obj
;
1422 delete_node_mgr(node_mgr_obj
);
1424 DBC_ENSURE((DSP_FAILED(status
) && (*node_man
== NULL
)) ||
1425 (DSP_SUCCEEDED(status
) && *node_man
));
1431 * ======== node_delete ========
1433 * Delete a node on the DSP by remotely calling the node's delete function.
1434 * Loads the node's delete function if necessary. Free GPP side resources
1435 * after node's delete function returns.
1437 int node_delete(struct node_object
*hnode
,
1438 struct process_context
*pr_ctxt
)
1440 struct node_object
*pnode
= (struct node_object
*)hnode
;
1441 struct node_mgr
*hnode_mgr
;
1442 struct proc_object
*hprocessor
;
1443 struct disp_object
*disp_obj
;
1445 enum node_type node_type
;
1446 enum node_state state
;
1449 struct dsp_cbdata cb_data
;
1451 struct bridge_drv_interface
*intf_fxns
;
1455 struct dsp_processorstate proc_state
;
1456 DBC_REQUIRE(refs
> 0);
1462 /* create struct dsp_cbdata struct for PWR call */
1463 cb_data
.cb_data
= PWR_TIMEOUT
;
1464 hnode_mgr
= hnode
->hnode_mgr
;
1465 hprocessor
= hnode
->hprocessor
;
1466 disp_obj
= hnode_mgr
->disp_obj
;
1467 node_type
= node_get_type(hnode
);
1468 intf_fxns
= hnode_mgr
->intf_fxns
;
1469 /* Enter critical section */
1470 mutex_lock(&hnode_mgr
->node_mgr_lock
);
1472 state
= node_get_state(hnode
);
1473 /* Execute delete phase code for non-device node in all cases
1474 * except when the node was only allocated. Delete phase must be
1475 * executed even if create phase was executed, but failed.
1476 * If the node environment pointer is non-NULL, the delete phase
1477 * code must be executed. */
1478 if (!(state
== NODE_ALLOCATED
&& hnode
->node_env
== (u32
) NULL
) &&
1479 node_type
!= NODE_DEVICE
) {
1480 status
= proc_get_processor_id(pnode
->hprocessor
, &proc_id
);
1481 if (DSP_FAILED(status
))
1484 if (proc_id
== DSP_UNIT
|| proc_id
== IVA_UNIT
) {
1485 /* If node has terminated, execute phase code will
1486 * have already been unloaded in node_on_exit(). If the
1487 * node is PAUSED, the execute phase is loaded, and it
1488 * is now ok to unload it. If the node is running, we
1489 * will unload the execute phase only after deleting
1491 if (state
== NODE_PAUSED
&& hnode
->loaded
&&
1492 hnode
->phase_split
) {
1493 /* Ok to unload execute code as long as node
1494 * is not * running */
1496 hnode_mgr
->nldr_fxns
.
1497 pfn_unload(hnode
->nldr_node_obj
,
1499 hnode
->loaded
= false;
1500 NODE_SET_STATE(hnode
, NODE_DONE
);
1502 /* Load delete phase code if not loaded or if haven't
1503 * * unloaded EXECUTE phase */
1504 if ((!(hnode
->loaded
) || (state
== NODE_RUNNING
)) &&
1505 hnode
->phase_split
) {
1507 hnode_mgr
->nldr_fxns
.
1508 pfn_load(hnode
->nldr_node_obj
, NLDR_DELETE
);
1509 if (DSP_SUCCEEDED(status
))
1510 hnode
->loaded
= true;
1512 pr_err("%s: fail - load delete code:"
1513 " 0x%x\n", __func__
, status
);
1517 if (DSP_SUCCEEDED(status
)) {
1518 /* Unblock a thread trying to terminate the node */
1519 (void)sync_set_event(hnode
->sync_done
);
1520 if (proc_id
== DSP_UNIT
) {
1521 /* ul_delete_fxn = address of node's delete
1523 status
= get_fxn_address(hnode
, &ul_delete_fxn
,
1525 } else if (proc_id
== IVA_UNIT
)
1526 ul_delete_fxn
= (u32
) hnode
->node_env
;
1527 if (DSP_SUCCEEDED(status
)) {
1528 status
= proc_get_state(hprocessor
,
1531 dsp_processorstate
));
1532 if (proc_state
.proc_state
!= PROC_ERROR
) {
1534 disp_node_delete(disp_obj
, hnode
,
1541 NODE_SET_STATE(hnode
, NODE_DONE
);
1543 /* Unload execute, if not unloaded, and delete
1545 if (state
== NODE_RUNNING
&&
1546 hnode
->phase_split
) {
1548 hnode_mgr
->nldr_fxns
.
1549 pfn_unload(hnode
->nldr_node_obj
,
1552 if (DSP_FAILED(status1
))
1553 pr_err("%s: fail - unload execute code:"
1554 " 0x%x\n", __func__
, status1
);
1557 hnode_mgr
->nldr_fxns
.pfn_unload(hnode
->
1560 hnode
->loaded
= false;
1561 if (DSP_FAILED(status1
))
1562 pr_err("%s: fail - unload delete code: "
1563 "0x%x\n", __func__
, status1
);
1567 /* Free host side resources even if a failure occurred */
1568 /* Remove node from hnode_mgr->node_list */
1569 lst_remove_elem(hnode_mgr
->node_list
, (struct list_head
*)hnode
);
1570 hnode_mgr
->num_nodes
--;
1571 /* Decrement count of nodes created on DSP */
1572 if ((state
!= NODE_ALLOCATED
) || ((state
== NODE_ALLOCATED
) &&
1573 (hnode
->node_env
!= (u32
) NULL
)))
1574 hnode_mgr
->num_created
--;
1575 /* Free host-side resources allocated by node_create()
1576 * delete_node() fails if SM buffers not freed by client! */
1577 if (drv_get_node_res_element(hnode
, &node_res
, pr_ctxt
) !=
1579 drv_proc_node_update_status(node_res
, false);
1580 delete_node(hnode
, pr_ctxt
);
1582 drv_remove_node_res_element(node_res
, pr_ctxt
);
1583 /* Exit critical section */
1584 mutex_unlock(&hnode_mgr
->node_mgr_lock
);
1585 proc_notify_clients(hprocessor
, DSP_NODESTATECHANGE
);
1587 dev_dbg(bridge
, "%s: hnode: %p status 0x%x\n", __func__
, hnode
, status
);
1592 * ======== node_delete_mgr ========
1594 * Delete the NODE Manager.
1596 int node_delete_mgr(struct node_mgr
*hnode_mgr
)
1600 DBC_REQUIRE(refs
> 0);
1603 delete_node_mgr(hnode_mgr
);
1611 * ======== node_enum_nodes ========
1613 * Enumerate currently allocated nodes.
1615 int node_enum_nodes(struct node_mgr
*hnode_mgr
, void **node_tab
,
1616 u32 node_tab_size
, OUT u32
*pu_num_nodes
,
1617 OUT u32
*pu_allocated
)
1619 struct node_object
*hnode
;
1622 DBC_REQUIRE(refs
> 0);
1623 DBC_REQUIRE(node_tab
!= NULL
|| node_tab_size
== 0);
1624 DBC_REQUIRE(pu_num_nodes
!= NULL
);
1625 DBC_REQUIRE(pu_allocated
!= NULL
);
1631 /* Enter critical section */
1632 mutex_lock(&hnode_mgr
->node_mgr_lock
);
1634 if (hnode_mgr
->num_nodes
> node_tab_size
) {
1635 *pu_allocated
= hnode_mgr
->num_nodes
;
1639 hnode
= (struct node_object
*)lst_first(hnode_mgr
->
1641 for (i
= 0; i
< hnode_mgr
->num_nodes
; i
++) {
1643 node_tab
[i
] = hnode
;
1644 hnode
= (struct node_object
*)lst_next
1645 (hnode_mgr
->node_list
,
1646 (struct list_head
*)hnode
);
1648 *pu_allocated
= *pu_num_nodes
= hnode_mgr
->num_nodes
;
1650 /* end of sync_enter_cs */
1651 /* Exit critical section */
1652 mutex_unlock(&hnode_mgr
->node_mgr_lock
);
1658 * ======== node_exit ========
1660 * Discontinue usage of NODE module.
1662 void node_exit(void)
1664 DBC_REQUIRE(refs
> 0);
1668 DBC_ENSURE(refs
>= 0);
1672 * ======== node_free_msg_buf ========
1674 * Frees the message buffer.
1676 int node_free_msg_buf(struct node_object
*hnode
, IN u8
* pbuffer
,
1677 OPTIONAL
struct dsp_bufferattr
*pattr
)
1679 struct node_object
*pnode
= (struct node_object
*)hnode
;
1682 DBC_REQUIRE(refs
> 0);
1683 DBC_REQUIRE(pbuffer
!= NULL
);
1684 DBC_REQUIRE(pnode
!= NULL
);
1685 DBC_REQUIRE(pnode
->xlator
!= NULL
);
1691 status
= proc_get_processor_id(pnode
->hprocessor
, &proc_id
);
1692 if (proc_id
== DSP_UNIT
) {
1693 if (DSP_SUCCEEDED(status
)) {
1694 if (pattr
== NULL
) {
1696 pattr
= &node_dfltbufattrs
;
1698 /* Node supports single SM segment only */
1699 if (pattr
->segment_id
!= 1)
1702 /* pbuffer is clients Va. */
1703 status
= cmm_xlator_free_buf(pnode
->xlator
, pbuffer
);
1706 DBC_ASSERT(NULL
); /* BUG */
1713 * ======== node_get_attr ========
1715 * Copy the current attributes of the specified node into a dsp_nodeattr
1718 int node_get_attr(struct node_object
*hnode
,
1719 OUT
struct dsp_nodeattr
*pattr
, u32 attr_size
)
1721 struct node_mgr
*hnode_mgr
;
1723 DBC_REQUIRE(refs
> 0);
1724 DBC_REQUIRE(pattr
!= NULL
);
1725 DBC_REQUIRE(attr_size
>= sizeof(struct dsp_nodeattr
));
1730 hnode_mgr
= hnode
->hnode_mgr
;
1731 /* Enter hnode_mgr critical section (since we're accessing
1732 * data that could be changed by node_change_priority() and
1733 * node_connect(). */
1734 mutex_lock(&hnode_mgr
->node_mgr_lock
);
1735 pattr
->cb_struct
= sizeof(struct dsp_nodeattr
);
1736 /* dsp_nodeattrin */
1737 pattr
->in_node_attr_in
.cb_struct
=
1738 sizeof(struct dsp_nodeattrin
);
1739 pattr
->in_node_attr_in
.prio
= hnode
->prio
;
1740 pattr
->in_node_attr_in
.utimeout
= hnode
->utimeout
;
1741 pattr
->in_node_attr_in
.heap_size
=
1742 hnode
->create_args
.asa
.task_arg_obj
.heap_size
;
1743 pattr
->in_node_attr_in
.pgpp_virt_addr
= (void *)
1744 hnode
->create_args
.asa
.task_arg_obj
.ugpp_heap_addr
;
1745 pattr
->node_attr_inputs
= hnode
->num_gpp_inputs
;
1746 pattr
->node_attr_outputs
= hnode
->num_gpp_outputs
;
1748 get_node_info(hnode
, &(pattr
->node_info
));
1749 /* end of sync_enter_cs */
1750 /* Exit critical section */
1751 mutex_unlock(&hnode_mgr
->node_mgr_lock
);
1757 * ======== node_get_channel_id ========
1759 * Get the channel index reserved for a stream connection between the
1762 int node_get_channel_id(struct node_object
*hnode
, u32 dir
, u32 index
,
1765 enum node_type node_type
;
1766 int status
= -EINVAL
;
1767 DBC_REQUIRE(refs
> 0);
1768 DBC_REQUIRE(dir
== DSP_TONODE
|| dir
== DSP_FROMNODE
);
1769 DBC_REQUIRE(chan_id
!= NULL
);
1775 node_type
= node_get_type(hnode
);
1776 if (node_type
!= NODE_TASK
&& node_type
!= NODE_DAISSOCKET
) {
1780 if (dir
== DSP_TONODE
) {
1781 if (index
< MAX_INPUTS(hnode
)) {
1782 if (hnode
->inputs
[index
].type
== HOSTCONNECT
) {
1783 *chan_id
= hnode
->inputs
[index
].dev_id
;
1788 DBC_ASSERT(dir
== DSP_FROMNODE
);
1789 if (index
< MAX_OUTPUTS(hnode
)) {
1790 if (hnode
->outputs
[index
].type
== HOSTCONNECT
) {
1791 *chan_id
= hnode
->outputs
[index
].dev_id
;
1800 * ======== node_get_message ========
1802 * Retrieve a message from a node on the DSP.
1804 int node_get_message(struct node_object
*hnode
,
1805 OUT
struct dsp_msg
*message
, u32 utimeout
)
1807 struct node_mgr
*hnode_mgr
;
1808 enum node_type node_type
;
1809 struct bridge_drv_interface
*intf_fxns
;
1812 struct dsp_processorstate proc_state
;
1813 struct proc_object
*hprocessor
;
1815 DBC_REQUIRE(refs
> 0);
1816 DBC_REQUIRE(message
!= NULL
);
1822 hprocessor
= hnode
->hprocessor
;
1823 status
= proc_get_state(hprocessor
, &proc_state
,
1824 sizeof(struct dsp_processorstate
));
1825 if (DSP_FAILED(status
))
1827 /* If processor is in error state then don't attempt to get the
1829 if (proc_state
.proc_state
== PROC_ERROR
) {
1833 hnode_mgr
= hnode
->hnode_mgr
;
1834 node_type
= node_get_type(hnode
);
1835 if (node_type
!= NODE_MESSAGE
&& node_type
!= NODE_TASK
&&
1836 node_type
!= NODE_DAISSOCKET
) {
1840 /* This function will block unless a message is available. Since
1841 * DSPNode_RegisterNotify() allows notification when a message
1842 * is available, the system can be designed so that
1843 * DSPNode_GetMessage() is only called when a message is
1845 intf_fxns
= hnode_mgr
->intf_fxns
;
1847 (*intf_fxns
->pfn_msg_get
) (hnode
->msg_queue_obj
, message
, utimeout
);
1848 /* Check if message contains SM descriptor */
1849 if (DSP_FAILED(status
) || !(message
->dw_cmd
& DSP_RMSBUFDESC
))
1852 /* Translate DSP byte addr to GPP Va. */
1853 tmp_buf
= cmm_xlator_translate(hnode
->xlator
,
1854 (void *)(message
->dw_arg1
*
1856 udsp_word_size
), CMM_DSPPA2PA
);
1857 if (tmp_buf
!= NULL
) {
1858 /* now convert this GPP Pa to Va */
1859 tmp_buf
= cmm_xlator_translate(hnode
->xlator
, tmp_buf
,
1861 if (tmp_buf
!= NULL
) {
1862 /* Adjust SM size in msg */
1863 message
->dw_arg1
= (u32
) tmp_buf
;
1864 message
->dw_arg2
*= hnode
->hnode_mgr
->udsp_word_size
;
1872 dev_dbg(bridge
, "%s: hnode: %p message: %p utimeout: 0x%x\n", __func__
,
1873 hnode
, message
, utimeout
);
1878 * ======== node_get_nldr_obj ========
1880 int node_get_nldr_obj(struct node_mgr
*hnode_mgr
,
1881 struct nldr_object
**nldr_ovlyobj
)
1884 struct node_mgr
*node_mgr_obj
= hnode_mgr
;
1885 DBC_REQUIRE(nldr_ovlyobj
!= NULL
);
1890 *nldr_ovlyobj
= node_mgr_obj
->nldr_obj
;
1892 DBC_ENSURE(DSP_SUCCEEDED(status
) || ((nldr_ovlyobj
!= NULL
) &&
1893 (*nldr_ovlyobj
== NULL
)));
1898 * ======== node_get_strm_mgr ========
1900 * Returns the Stream manager.
1902 int node_get_strm_mgr(struct node_object
*hnode
,
1903 struct strm_mgr
**strm_man
)
1907 DBC_REQUIRE(refs
> 0);
1912 *strm_man
= hnode
->hnode_mgr
->strm_mgr_obj
;
1918 * ======== node_get_load_type ========
1920 enum nldr_loadtype
node_get_load_type(struct node_object
*hnode
)
1922 DBC_REQUIRE(refs
> 0);
1925 dev_dbg(bridge
, "%s: Failed. hnode: %p\n", __func__
, hnode
);
1928 return hnode
->dcd_props
.obj_data
.node_obj
.us_load_type
;
1933 * ======== node_get_timeout ========
1935 * Returns the timeout value for this node.
1937 u32
node_get_timeout(struct node_object
*hnode
)
1939 DBC_REQUIRE(refs
> 0);
1942 dev_dbg(bridge
, "%s: failed. hnode: %p\n", __func__
, hnode
);
1945 return hnode
->utimeout
;
1950 * ======== node_get_type ========
1952 * Returns the node type.
1954 enum node_type
node_get_type(struct node_object
*hnode
)
1956 enum node_type node_type
;
1958 if (hnode
== (struct node_object
*)DSP_HGPPNODE
)
1959 node_type
= NODE_GPP
;
1964 node_type
= hnode
->ntype
;
1970 * ======== node_init ========
1972 * Initialize the NODE module.
1974 bool node_init(void)
1976 DBC_REQUIRE(refs
>= 0);
1984 * ======== node_on_exit ========
1986 * Gets called when RMS_EXIT is received for a node.
1988 void node_on_exit(struct node_object
*hnode
, s32 node_status
)
1993 /* Set node state to done */
1994 NODE_SET_STATE(hnode
, NODE_DONE
);
1995 hnode
->exit_status
= node_status
;
1996 if (hnode
->loaded
&& hnode
->phase_split
) {
1997 (void)hnode
->hnode_mgr
->nldr_fxns
.pfn_unload(hnode
->
2000 hnode
->loaded
= false;
2002 /* Unblock call to node_terminate */
2003 (void)sync_set_event(hnode
->sync_done
);
2004 /* Notify clients */
2005 proc_notify_clients(hnode
->hprocessor
, DSP_NODESTATECHANGE
);
2006 ntfy_notify(hnode
->ntfy_obj
, DSP_NODESTATECHANGE
);
2010 * ======== node_pause ========
2012 * Suspend execution of a node currently running on the DSP.
2014 int node_pause(struct node_object
*hnode
)
2016 struct node_object
*pnode
= (struct node_object
*)hnode
;
2017 enum node_type node_type
;
2018 enum node_state state
;
2019 struct node_mgr
*hnode_mgr
;
2022 struct dsp_processorstate proc_state
;
2023 struct proc_object
*hprocessor
;
2025 DBC_REQUIRE(refs
> 0);
2030 node_type
= node_get_type(hnode
);
2031 if (node_type
!= NODE_TASK
&& node_type
!= NODE_DAISSOCKET
)
2034 if (DSP_FAILED(status
))
2037 status
= proc_get_processor_id(pnode
->hprocessor
, &proc_id
);
2039 if (proc_id
== IVA_UNIT
)
2042 if (DSP_SUCCEEDED(status
)) {
2043 hnode_mgr
= hnode
->hnode_mgr
;
2045 /* Enter critical section */
2046 mutex_lock(&hnode_mgr
->node_mgr_lock
);
2047 state
= node_get_state(hnode
);
2048 /* Check node state */
2049 if (state
!= NODE_RUNNING
)
2052 if (DSP_FAILED(status
))
2054 hprocessor
= hnode
->hprocessor
;
2055 status
= proc_get_state(hprocessor
, &proc_state
,
2056 sizeof(struct dsp_processorstate
));
2057 if (DSP_FAILED(status
))
2059 /* If processor is in error state then don't attempt
2060 to send the message */
2061 if (proc_state
.proc_state
== PROC_ERROR
) {
2066 status
= disp_node_change_priority(hnode_mgr
->disp_obj
, hnode
,
2067 hnode_mgr
->ul_fxn_addrs
[RMSCHANGENODEPRIORITY
],
2068 hnode
->node_env
, NODE_SUSPENDEDPRI
);
2071 if (DSP_SUCCEEDED(status
))
2072 NODE_SET_STATE(hnode
, NODE_PAUSED
);
2075 /* End of sync_enter_cs */
2076 /* Leave critical section */
2077 mutex_unlock(&hnode_mgr
->node_mgr_lock
);
2078 if (DSP_SUCCEEDED(status
)) {
2079 proc_notify_clients(hnode
->hprocessor
,
2080 DSP_NODESTATECHANGE
);
2081 ntfy_notify(hnode
->ntfy_obj
, DSP_NODESTATECHANGE
);
2085 dev_dbg(bridge
, "%s: hnode: %p status 0x%x\n", __func__
, hnode
, status
);
2090 * ======== node_put_message ========
2092 * Send a message to a message node, task node, or XDAIS socket node. This
2093 * function will block until the message stream can accommodate the
2094 * message, or a timeout occurs.
2096 int node_put_message(struct node_object
*hnode
,
2097 IN CONST
struct dsp_msg
*pmsg
, u32 utimeout
)
2099 struct node_mgr
*hnode_mgr
= NULL
;
2100 enum node_type node_type
;
2101 struct bridge_drv_interface
*intf_fxns
;
2102 enum node_state state
;
2105 struct dsp_msg new_msg
;
2106 struct dsp_processorstate proc_state
;
2107 struct proc_object
*hprocessor
;
2109 DBC_REQUIRE(refs
> 0);
2110 DBC_REQUIRE(pmsg
!= NULL
);
2116 hprocessor
= hnode
->hprocessor
;
2117 status
= proc_get_state(hprocessor
, &proc_state
,
2118 sizeof(struct dsp_processorstate
));
2119 if (DSP_FAILED(status
))
2121 /* If processor is in bad state then don't attempt sending the
2123 if (proc_state
.proc_state
== PROC_ERROR
) {
2127 hnode_mgr
= hnode
->hnode_mgr
;
2128 node_type
= node_get_type(hnode
);
2129 if (node_type
!= NODE_MESSAGE
&& node_type
!= NODE_TASK
&&
2130 node_type
!= NODE_DAISSOCKET
)
2133 if (DSP_SUCCEEDED(status
)) {
2134 /* Check node state. Can't send messages to a node after
2135 * we've sent the RMS_EXIT command. There is still the
2136 * possibility that node_terminate can be called after we've
2137 * checked the state. Could add another SYNC object to
2138 * prevent this (can't use node_mgr_lock, since we don't
2139 * want to block other NODE functions). However, the node may
2140 * still exit on its own, before this message is sent. */
2141 mutex_lock(&hnode_mgr
->node_mgr_lock
);
2142 state
= node_get_state(hnode
);
2143 if (state
== NODE_TERMINATING
|| state
== NODE_DONE
)
2146 /* end of sync_enter_cs */
2147 mutex_unlock(&hnode_mgr
->node_mgr_lock
);
2149 if (DSP_FAILED(status
))
2152 /* assign pmsg values to new msg */
2154 /* Now, check if message contains a SM buffer descriptor */
2155 if (pmsg
->dw_cmd
& DSP_RMSBUFDESC
) {
2156 /* Translate GPP Va to DSP physical buf Ptr. */
2157 tmp_buf
= cmm_xlator_translate(hnode
->xlator
,
2158 (void *)new_msg
.dw_arg1
,
2160 if (tmp_buf
!= NULL
) {
2161 /* got translation, convert to MAUs in msg */
2162 if (hnode
->hnode_mgr
->udsp_word_size
!= 0) {
2165 hnode
->hnode_mgr
->udsp_word_size
;
2167 new_msg
.dw_arg2
/= hnode
->hnode_mgr
->
2170 pr_err("%s: udsp_word_size is zero!\n",
2172 status
= -EPERM
; /* bad DSPWordSize */
2174 } else { /* failed to translate buffer address */
2178 if (DSP_SUCCEEDED(status
)) {
2179 intf_fxns
= hnode_mgr
->intf_fxns
;
2180 status
= (*intf_fxns
->pfn_msg_put
) (hnode
->msg_queue_obj
,
2181 &new_msg
, utimeout
);
2184 dev_dbg(bridge
, "%s: hnode: %p pmsg: %p utimeout: 0x%x, "
2185 "status 0x%x\n", __func__
, hnode
, pmsg
, utimeout
, status
);
2190 * ======== node_register_notify ========
2192 * Register to be notified on specific events for this node.
2194 int node_register_notify(struct node_object
*hnode
, u32 event_mask
,
2196 struct dsp_notification
*hnotification
)
2198 struct bridge_drv_interface
*intf_fxns
;
2201 DBC_REQUIRE(refs
> 0);
2202 DBC_REQUIRE(hnotification
!= NULL
);
2207 /* Check if event mask is a valid node related event */
2208 if (event_mask
& ~(DSP_NODESTATECHANGE
| DSP_NODEMESSAGEREADY
))
2211 /* Check if notify type is valid */
2212 if (notify_type
!= DSP_SIGNALEVENT
)
2215 /* Only one Notification can be registered at a
2216 * time - Limitation */
2217 if (event_mask
== (DSP_NODESTATECHANGE
| DSP_NODEMESSAGEREADY
))
2220 if (DSP_SUCCEEDED(status
)) {
2221 if (event_mask
== DSP_NODESTATECHANGE
) {
2222 status
= ntfy_register(hnode
->ntfy_obj
, hnotification
,
2223 event_mask
& DSP_NODESTATECHANGE
,
2226 /* Send Message part of event mask to msg_ctrl */
2227 intf_fxns
= hnode
->hnode_mgr
->intf_fxns
;
2228 status
= (*intf_fxns
->pfn_msg_register_notify
)
2229 (hnode
->msg_queue_obj
,
2230 event_mask
& DSP_NODEMESSAGEREADY
, notify_type
,
2235 dev_dbg(bridge
, "%s: hnode: %p event_mask: 0x%x notify_type: 0x%x "
2236 "hnotification: %p status 0x%x\n", __func__
, hnode
,
2237 event_mask
, notify_type
, hnotification
, status
);
2242 * ======== node_run ========
2244 * Start execution of a node's execute phase, or resume execution of a node
2245 * that has been suspended (via NODE_NodePause()) on the DSP. Load the
2246 * node's execute function if necessary.
2248 int node_run(struct node_object
*hnode
)
2250 struct node_object
*pnode
= (struct node_object
*)hnode
;
2251 struct node_mgr
*hnode_mgr
;
2252 enum node_type node_type
;
2253 enum node_state state
;
2258 struct bridge_drv_interface
*intf_fxns
;
2259 struct dsp_processorstate proc_state
;
2260 struct proc_object
*hprocessor
;
2262 DBC_REQUIRE(refs
> 0);
2268 hprocessor
= hnode
->hprocessor
;
2269 status
= proc_get_state(hprocessor
, &proc_state
,
2270 sizeof(struct dsp_processorstate
));
2271 if (DSP_FAILED(status
))
2273 /* If processor is in error state then don't attempt to run the node */
2274 if (proc_state
.proc_state
== PROC_ERROR
) {
2278 node_type
= node_get_type(hnode
);
2279 if (node_type
== NODE_DEVICE
)
2281 if (DSP_FAILED(status
))
2284 hnode_mgr
= hnode
->hnode_mgr
;
2289 intf_fxns
= hnode_mgr
->intf_fxns
;
2290 /* Enter critical section */
2291 mutex_lock(&hnode_mgr
->node_mgr_lock
);
2293 state
= node_get_state(hnode
);
2294 if (state
!= NODE_CREATED
&& state
!= NODE_PAUSED
)
2297 if (DSP_SUCCEEDED(status
))
2298 status
= proc_get_processor_id(pnode
->hprocessor
, &proc_id
);
2300 if (DSP_FAILED(status
))
2303 if ((proc_id
!= DSP_UNIT
) && (proc_id
!= IVA_UNIT
))
2306 if (state
== NODE_CREATED
) {
2307 /* If node's execute function is not loaded, load it */
2308 if (!(hnode
->loaded
) && hnode
->phase_split
) {
2310 hnode_mgr
->nldr_fxns
.pfn_load(hnode
->nldr_node_obj
,
2312 if (DSP_SUCCEEDED(status
)) {
2313 hnode
->loaded
= true;
2315 pr_err("%s: fail - load execute code: 0x%x\n",
2319 if (DSP_SUCCEEDED(status
)) {
2320 /* Get address of node's execute function */
2321 if (proc_id
== IVA_UNIT
)
2322 ul_execute_fxn
= (u32
) hnode
->node_env
;
2324 status
= get_fxn_address(hnode
, &ul_execute_fxn
,
2328 if (DSP_SUCCEEDED(status
)) {
2329 ul_fxn_addr
= hnode_mgr
->ul_fxn_addrs
[RMSEXECUTENODE
];
2331 disp_node_run(hnode_mgr
->disp_obj
, hnode
,
2332 ul_fxn_addr
, ul_execute_fxn
,
2335 } else if (state
== NODE_PAUSED
) {
2336 ul_fxn_addr
= hnode_mgr
->ul_fxn_addrs
[RMSCHANGENODEPRIORITY
];
2337 status
= disp_node_change_priority(hnode_mgr
->disp_obj
, hnode
,
2338 ul_fxn_addr
, hnode
->node_env
,
2339 NODE_GET_PRIORITY(hnode
));
2341 /* We should never get here */
2345 /* Update node state. */
2346 if (DSP_SUCCEEDED(status
))
2347 NODE_SET_STATE(hnode
, NODE_RUNNING
);
2348 else /* Set state back to previous value */
2349 NODE_SET_STATE(hnode
, state
);
2350 /*End of sync_enter_cs */
2351 /* Exit critical section */
2352 mutex_unlock(&hnode_mgr
->node_mgr_lock
);
2353 if (DSP_SUCCEEDED(status
)) {
2354 proc_notify_clients(hnode
->hprocessor
, DSP_NODESTATECHANGE
);
2355 ntfy_notify(hnode
->ntfy_obj
, DSP_NODESTATECHANGE
);
2358 dev_dbg(bridge
, "%s: hnode: %p status 0x%x\n", __func__
, hnode
, status
);
2363 * ======== node_terminate ========
2365 * Signal a node running on the DSP that it should exit its execute phase
2368 int node_terminate(struct node_object
*hnode
, OUT
int *pstatus
)
2370 struct node_object
*pnode
= (struct node_object
*)hnode
;
2371 struct node_mgr
*hnode_mgr
= NULL
;
2372 enum node_type node_type
;
2373 struct bridge_drv_interface
*intf_fxns
;
2374 enum node_state state
;
2375 struct dsp_msg msg
, killmsg
;
2377 u32 proc_id
, kill_time_out
;
2378 struct deh_mgr
*hdeh_mgr
;
2379 struct dsp_processorstate proc_state
;
2381 DBC_REQUIRE(refs
> 0);
2382 DBC_REQUIRE(pstatus
!= NULL
);
2384 if (!hnode
|| !hnode
->hnode_mgr
) {
2388 if (pnode
->hprocessor
== NULL
) {
2392 status
= proc_get_processor_id(pnode
->hprocessor
, &proc_id
);
2394 if (DSP_SUCCEEDED(status
)) {
2395 hnode_mgr
= hnode
->hnode_mgr
;
2396 node_type
= node_get_type(hnode
);
2397 if (node_type
!= NODE_TASK
&& node_type
!= NODE_DAISSOCKET
)
2400 if (DSP_SUCCEEDED(status
)) {
2401 /* Check node state */
2402 mutex_lock(&hnode_mgr
->node_mgr_lock
);
2403 state
= node_get_state(hnode
);
2404 if (state
!= NODE_RUNNING
) {
2406 /* Set the exit status if node terminated on
2408 if (state
== NODE_DONE
)
2409 *pstatus
= hnode
->exit_status
;
2412 NODE_SET_STATE(hnode
, NODE_TERMINATING
);
2414 /* end of sync_enter_cs */
2415 mutex_unlock(&hnode_mgr
->node_mgr_lock
);
2417 if (DSP_SUCCEEDED(status
)) {
2419 * Send exit message. Do not change state to NODE_DONE
2420 * here. That will be done in callback.
2422 status
= proc_get_state(pnode
->hprocessor
, &proc_state
,
2423 sizeof(struct dsp_processorstate
));
2424 if (DSP_FAILED(status
))
2426 /* If processor is in error state then don't attempt to send
2427 * A kill task command */
2428 if (proc_state
.proc_state
== PROC_ERROR
) {
2433 msg
.dw_cmd
= RMS_EXIT
;
2434 msg
.dw_arg1
= hnode
->node_env
;
2435 killmsg
.dw_cmd
= RMS_KILLTASK
;
2436 killmsg
.dw_arg1
= hnode
->node_env
;
2437 intf_fxns
= hnode_mgr
->intf_fxns
;
2439 if (hnode
->utimeout
> MAXTIMEOUT
)
2440 kill_time_out
= MAXTIMEOUT
;
2442 kill_time_out
= (hnode
->utimeout
) * 2;
2444 status
= (*intf_fxns
->pfn_msg_put
) (hnode
->msg_queue_obj
, &msg
,
2446 if (DSP_FAILED(status
))
2450 * Wait on synchronization object that will be
2451 * posted in the callback on receiving RMS_EXIT
2452 * message, or by node_delete. Check for valid hnode,
2453 * in case posted by node_delete().
2455 status
= sync_wait_on_event(hnode
->sync_done
,
2457 if (status
!= ETIME
)
2460 status
= (*intf_fxns
->pfn_msg_put
)(hnode
->msg_queue_obj
,
2461 &killmsg
, hnode
->utimeout
);
2462 if (DSP_FAILED(status
))
2464 status
= sync_wait_on_event(hnode
->sync_done
,
2466 if (DSP_FAILED(status
)) {
2468 * Here it goes the part of the simulation of
2469 * the DSP exception.
2471 dev_get_deh_mgr(hnode_mgr
->hdev_obj
, &hdeh_mgr
);
2475 bridge_deh_notify(hdeh_mgr
, DSP_SYSERROR
, DSP_EXCEPTIONABORT
);
2479 if (DSP_SUCCEEDED(status
)) {
2480 /* Enter CS before getting exit status, in case node was
2482 mutex_lock(&hnode_mgr
->node_mgr_lock
);
2483 /* Make sure node wasn't deleted while we blocked */
2487 *pstatus
= hnode
->exit_status
;
2488 dev_dbg(bridge
, "%s: hnode: %p env 0x%x status 0x%x\n",
2489 __func__
, hnode
, hnode
->node_env
, status
);
2491 mutex_unlock(&hnode_mgr
->node_mgr_lock
);
2492 } /*End of sync_enter_cs */
2498 * ======== delete_node ========
2500 * Free GPP resources allocated in node_allocate() or node_connect().
2502 static void delete_node(struct node_object
*hnode
,
2503 struct process_context
*pr_ctxt
)
2505 struct node_mgr
*hnode_mgr
;
2506 struct cmm_xlatorobject
*xlator
;
2507 struct bridge_drv_interface
*intf_fxns
;
2509 enum node_type node_type
;
2510 struct stream_chnl stream
;
2511 struct node_msgargs node_msg_args
;
2512 struct node_taskargs task_arg_obj
;
2513 #ifdef DSP_DMM_DEBUG
2514 struct dmm_object
*dmm_mgr
;
2515 struct proc_object
*p_proc_object
=
2516 (struct proc_object
*)hnode
->hprocessor
;
2521 hnode_mgr
= hnode
->hnode_mgr
;
2524 xlator
= hnode
->xlator
;
2525 node_type
= node_get_type(hnode
);
2526 if (node_type
!= NODE_DEVICE
) {
2527 node_msg_args
= hnode
->create_args
.asa
.node_msg_args
;
2528 kfree(node_msg_args
.pdata
);
2530 /* Free msg_ctrl queue */
2531 if (hnode
->msg_queue_obj
) {
2532 intf_fxns
= hnode_mgr
->intf_fxns
;
2533 (*intf_fxns
->pfn_msg_delete_queue
) (hnode
->
2535 hnode
->msg_queue_obj
= NULL
;
2538 kfree(hnode
->sync_done
);
2540 /* Free all stream info */
2541 if (hnode
->inputs
) {
2542 for (i
= 0; i
< MAX_INPUTS(hnode
); i
++) {
2543 stream
= hnode
->inputs
[i
];
2544 free_stream(hnode_mgr
, stream
);
2546 kfree(hnode
->inputs
);
2547 hnode
->inputs
= NULL
;
2549 if (hnode
->outputs
) {
2550 for (i
= 0; i
< MAX_OUTPUTS(hnode
); i
++) {
2551 stream
= hnode
->outputs
[i
];
2552 free_stream(hnode_mgr
, stream
);
2554 kfree(hnode
->outputs
);
2555 hnode
->outputs
= NULL
;
2557 task_arg_obj
= hnode
->create_args
.asa
.task_arg_obj
;
2558 if (task_arg_obj
.strm_in_def
) {
2559 for (i
= 0; i
< MAX_INPUTS(hnode
); i
++) {
2560 kfree(task_arg_obj
.strm_in_def
[i
].sz_device
);
2561 task_arg_obj
.strm_in_def
[i
].sz_device
= NULL
;
2563 kfree(task_arg_obj
.strm_in_def
);
2564 task_arg_obj
.strm_in_def
= NULL
;
2566 if (task_arg_obj
.strm_out_def
) {
2567 for (i
= 0; i
< MAX_OUTPUTS(hnode
); i
++) {
2568 kfree(task_arg_obj
.strm_out_def
[i
].sz_device
);
2569 task_arg_obj
.strm_out_def
[i
].sz_device
= NULL
;
2571 kfree(task_arg_obj
.strm_out_def
);
2572 task_arg_obj
.strm_out_def
= NULL
;
2574 if (task_arg_obj
.udsp_heap_res_addr
) {
2575 status
= proc_un_map(hnode
->hprocessor
, (void *)
2576 task_arg_obj
.udsp_heap_addr
,
2579 status
= proc_un_reserve_memory(hnode
->hprocessor
,
2584 #ifdef DSP_DMM_DEBUG
2585 status
= dmm_get_handle(p_proc_object
, &dmm_mgr
);
2587 dmm_mem_map_dump(dmm_mgr
);
2589 status
= DSP_EHANDLE
;
2593 if (node_type
!= NODE_MESSAGE
) {
2594 kfree(hnode
->stream_connect
);
2595 hnode
->stream_connect
= NULL
;
2597 kfree(hnode
->pstr_dev_name
);
2598 hnode
->pstr_dev_name
= NULL
;
2600 if (hnode
->ntfy_obj
) {
2601 ntfy_delete(hnode
->ntfy_obj
);
2602 kfree(hnode
->ntfy_obj
);
2603 hnode
->ntfy_obj
= NULL
;
2606 /* These were allocated in dcd_get_object_def (via node_allocate) */
2607 kfree(hnode
->dcd_props
.obj_data
.node_obj
.pstr_create_phase_fxn
);
2608 hnode
->dcd_props
.obj_data
.node_obj
.pstr_create_phase_fxn
= NULL
;
2610 kfree(hnode
->dcd_props
.obj_data
.node_obj
.pstr_execute_phase_fxn
);
2611 hnode
->dcd_props
.obj_data
.node_obj
.pstr_execute_phase_fxn
= NULL
;
2613 kfree(hnode
->dcd_props
.obj_data
.node_obj
.pstr_delete_phase_fxn
);
2614 hnode
->dcd_props
.obj_data
.node_obj
.pstr_delete_phase_fxn
= NULL
;
2616 kfree(hnode
->dcd_props
.obj_data
.node_obj
.pstr_i_alg_name
);
2617 hnode
->dcd_props
.obj_data
.node_obj
.pstr_i_alg_name
= NULL
;
2619 /* Free all SM address translator resources */
2621 (void)cmm_xlator_delete(xlator
, true); /* force free */
2625 kfree(hnode
->nldr_node_obj
);
2626 hnode
->nldr_node_obj
= NULL
;
2627 hnode
->hnode_mgr
= NULL
;
2635 * ======== delete_node_mgr ========
2637 * Frees the node manager.
2639 static void delete_node_mgr(struct node_mgr
*hnode_mgr
)
2641 struct node_object
*hnode
;
2644 /* Free resources */
2645 if (hnode_mgr
->hdcd_mgr
)
2646 dcd_destroy_manager(hnode_mgr
->hdcd_mgr
);
2648 /* Remove any elements remaining in lists */
2649 if (hnode_mgr
->node_list
) {
2650 while ((hnode
= (struct node_object
*)
2651 lst_get_head(hnode_mgr
->node_list
)))
2652 delete_node(hnode
, NULL
);
2654 DBC_ASSERT(LST_IS_EMPTY(hnode_mgr
->node_list
));
2655 kfree(hnode_mgr
->node_list
);
2657 mutex_destroy(&hnode_mgr
->node_mgr_lock
);
2658 if (hnode_mgr
->ntfy_obj
) {
2659 ntfy_delete(hnode_mgr
->ntfy_obj
);
2660 kfree(hnode_mgr
->ntfy_obj
);
2663 if (hnode_mgr
->pipe_map
)
2664 gb_delete(hnode_mgr
->pipe_map
);
2666 if (hnode_mgr
->pipe_done_map
)
2667 gb_delete(hnode_mgr
->pipe_done_map
);
2669 if (hnode_mgr
->chnl_map
)
2670 gb_delete(hnode_mgr
->chnl_map
);
2672 if (hnode_mgr
->dma_chnl_map
)
2673 gb_delete(hnode_mgr
->dma_chnl_map
);
2675 if (hnode_mgr
->zc_chnl_map
)
2676 gb_delete(hnode_mgr
->zc_chnl_map
);
2678 if (hnode_mgr
->disp_obj
)
2679 disp_delete(hnode_mgr
->disp_obj
);
2681 if (hnode_mgr
->strm_mgr_obj
)
2682 strm_delete(hnode_mgr
->strm_mgr_obj
);
2684 /* Delete the loader */
2685 if (hnode_mgr
->nldr_obj
)
2686 hnode_mgr
->nldr_fxns
.pfn_delete(hnode_mgr
->nldr_obj
);
2688 if (hnode_mgr
->loader_init
)
2689 hnode_mgr
->nldr_fxns
.pfn_exit();
2696 * ======== fill_stream_connect ========
2698 * Fills stream information.
2700 static void fill_stream_connect(struct node_object
*node1
,
2701 struct node_object
*node2
,
2702 u32 stream1
, u32 stream2
)
2705 struct dsp_streamconnect
*strm1
= NULL
;
2706 struct dsp_streamconnect
*strm2
= NULL
;
2707 enum node_type node1_type
= NODE_TASK
;
2708 enum node_type node2_type
= NODE_TASK
;
2710 node1_type
= node_get_type(node1
);
2711 node2_type
= node_get_type(node2
);
2712 if (node1
!= (struct node_object
*)DSP_HGPPNODE
) {
2714 if (node1_type
!= NODE_DEVICE
) {
2715 strm_index
= node1
->num_inputs
+
2716 node1
->num_outputs
- 1;
2717 strm1
= &(node1
->stream_connect
[strm_index
]);
2718 strm1
->cb_struct
= sizeof(struct dsp_streamconnect
);
2719 strm1
->this_node_stream_index
= stream1
;
2722 if (node2
!= (struct node_object
*)DSP_HGPPNODE
) {
2723 /* NODE == > NODE */
2724 if (node1_type
!= NODE_DEVICE
) {
2725 strm1
->connected_node
= node2
;
2726 strm1
->ui_connected_node_id
= node2
->node_uuid
;
2727 strm1
->connected_node_stream_index
= stream2
;
2728 strm1
->connect_type
= CONNECTTYPE_NODEOUTPUT
;
2730 if (node2_type
!= NODE_DEVICE
) {
2731 strm_index
= node2
->num_inputs
+
2732 node2
->num_outputs
- 1;
2733 strm2
= &(node2
->stream_connect
[strm_index
]);
2735 sizeof(struct dsp_streamconnect
);
2736 strm2
->this_node_stream_index
= stream2
;
2737 strm2
->connected_node
= node1
;
2738 strm2
->ui_connected_node_id
= node1
->node_uuid
;
2739 strm2
->connected_node_stream_index
= stream1
;
2740 strm2
->connect_type
= CONNECTTYPE_NODEINPUT
;
2742 } else if (node1_type
!= NODE_DEVICE
)
2743 strm1
->connect_type
= CONNECTTYPE_GPPOUTPUT
;
2746 DBC_ASSERT(node2
!= (struct node_object
*)DSP_HGPPNODE
);
2747 strm_index
= node2
->num_inputs
+ node2
->num_outputs
- 1;
2748 strm2
= &(node2
->stream_connect
[strm_index
]);
2749 strm2
->cb_struct
= sizeof(struct dsp_streamconnect
);
2750 strm2
->this_node_stream_index
= stream2
;
2751 strm2
->connect_type
= CONNECTTYPE_GPPINPUT
;
2756 * ======== fill_stream_def ========
2758 * Fills Stream attributes.
2760 static void fill_stream_def(struct node_object
*hnode
,
2761 struct node_strmdef
*pstrm_def
,
2762 struct dsp_strmattr
*pattrs
)
2764 struct node_mgr
*hnode_mgr
= hnode
->hnode_mgr
;
2766 if (pattrs
!= NULL
) {
2767 pstrm_def
->num_bufs
= pattrs
->num_bufs
;
2768 pstrm_def
->buf_size
=
2769 pattrs
->buf_size
/ hnode_mgr
->udsp_data_mau_size
;
2770 pstrm_def
->seg_id
= pattrs
->seg_id
;
2771 pstrm_def
->buf_alignment
= pattrs
->buf_alignment
;
2772 pstrm_def
->utimeout
= pattrs
->utimeout
;
2774 pstrm_def
->num_bufs
= DEFAULTNBUFS
;
2775 pstrm_def
->buf_size
=
2776 DEFAULTBUFSIZE
/ hnode_mgr
->udsp_data_mau_size
;
2777 pstrm_def
->seg_id
= DEFAULTSEGID
;
2778 pstrm_def
->buf_alignment
= DEFAULTALIGNMENT
;
2779 pstrm_def
->utimeout
= DEFAULTTIMEOUT
;
2784 * ======== free_stream ========
2786 * Updates the channel mask and frees the pipe id.
2788 static void free_stream(struct node_mgr
*hnode_mgr
, struct stream_chnl stream
)
2790 /* Free up the pipe id unless other node has not yet been deleted. */
2791 if (stream
.type
== NODECONNECT
) {
2792 if (gb_test(hnode_mgr
->pipe_done_map
, stream
.dev_id
)) {
2793 /* The other node has already been deleted */
2794 gb_clear(hnode_mgr
->pipe_done_map
, stream
.dev_id
);
2795 gb_clear(hnode_mgr
->pipe_map
, stream
.dev_id
);
2797 /* The other node has not been deleted yet */
2798 gb_set(hnode_mgr
->pipe_done_map
, stream
.dev_id
);
2800 } else if (stream
.type
== HOSTCONNECT
) {
2801 if (stream
.dev_id
< hnode_mgr
->ul_num_chnls
) {
2802 gb_clear(hnode_mgr
->chnl_map
, stream
.dev_id
);
2803 } else if (stream
.dev_id
< (2 * hnode_mgr
->ul_num_chnls
)) {
2805 gb_clear(hnode_mgr
->dma_chnl_map
, stream
.dev_id
-
2806 (1 * hnode_mgr
->ul_num_chnls
));
2807 } else if (stream
.dev_id
< (3 * hnode_mgr
->ul_num_chnls
)) {
2809 gb_clear(hnode_mgr
->zc_chnl_map
, stream
.dev_id
-
2810 (2 * hnode_mgr
->ul_num_chnls
));
2816 * ======== get_fxn_address ========
2818 * Retrieves the address for create, execute or delete phase for a node.
2820 static int get_fxn_address(struct node_object
*hnode
, u32
* fxn_addr
,
2823 char *pstr_fxn_name
= NULL
;
2824 struct node_mgr
*hnode_mgr
= hnode
->hnode_mgr
;
2826 DBC_REQUIRE(node_get_type(hnode
) == NODE_TASK
||
2827 node_get_type(hnode
) == NODE_DAISSOCKET
||
2828 node_get_type(hnode
) == NODE_MESSAGE
);
2833 hnode
->dcd_props
.obj_data
.node_obj
.pstr_create_phase_fxn
;
2837 hnode
->dcd_props
.obj_data
.node_obj
.pstr_execute_phase_fxn
;
2841 hnode
->dcd_props
.obj_data
.node_obj
.pstr_delete_phase_fxn
;
2844 /* Should never get here */
2850 hnode_mgr
->nldr_fxns
.pfn_get_fxn_addr(hnode
->nldr_node_obj
,
2851 pstr_fxn_name
, fxn_addr
);
2857 * ======== get_node_info ========
2859 * Retrieves the node information.
2861 void get_node_info(struct node_object
*hnode
, struct dsp_nodeinfo
*node_info
)
2866 DBC_REQUIRE(node_info
!= NULL
);
2868 node_info
->cb_struct
= sizeof(struct dsp_nodeinfo
);
2869 node_info
->nb_node_database_props
=
2870 hnode
->dcd_props
.obj_data
.node_obj
.ndb_props
;
2871 node_info
->execution_priority
= hnode
->prio
;
2872 node_info
->device_owner
= hnode
->device_owner
;
2873 node_info
->number_streams
= hnode
->num_inputs
+ hnode
->num_outputs
;
2874 node_info
->node_env
= hnode
->node_env
;
2876 node_info
->ns_execution_state
= node_get_state(hnode
);
2878 /* Copy stream connect data */
2879 for (i
= 0; i
< hnode
->num_inputs
+ hnode
->num_outputs
; i
++)
2880 node_info
->sc_stream_connection
[i
] = hnode
->stream_connect
[i
];
2885 * ======== get_node_props ========
2887 * Retrieve node properties.
2889 static int get_node_props(struct dcd_manager
*hdcd_mgr
,
2890 struct node_object
*hnode
,
2891 CONST
struct dsp_uuid
*node_uuid
,
2892 struct dcd_genericobj
*dcd_prop
)
2895 struct node_msgargs
*pmsg_args
;
2896 struct node_taskargs
*task_arg_obj
;
2897 enum node_type node_type
= NODE_TASK
;
2898 struct dsp_ndbprops
*pndb_props
=
2899 &(dcd_prop
->obj_data
.node_obj
.ndb_props
);
2901 char sz_uuid
[MAXUUIDLEN
];
2903 status
= dcd_get_object_def(hdcd_mgr
, (struct dsp_uuid
*)node_uuid
,
2904 DSP_DCDNODETYPE
, dcd_prop
);
2906 if (DSP_SUCCEEDED(status
)) {
2907 hnode
->ntype
= node_type
= pndb_props
->ntype
;
2909 /* Create UUID value to set in registry. */
2910 uuid_uuid_to_string((struct dsp_uuid
*)node_uuid
, sz_uuid
,
2912 dev_dbg(bridge
, "(node) UUID: %s\n", sz_uuid
);
2914 /* Fill in message args that come from NDB */
2915 if (node_type
!= NODE_DEVICE
) {
2916 pmsg_args
= &(hnode
->create_args
.asa
.node_msg_args
);
2918 dcd_prop
->obj_data
.node_obj
.msg_segid
;
2919 pmsg_args
->notify_type
=
2920 dcd_prop
->obj_data
.node_obj
.msg_notify_type
;
2921 pmsg_args
->max_msgs
= pndb_props
->message_depth
;
2922 dev_dbg(bridge
, "(node) Max Number of Messages: 0x%x\n",
2923 pmsg_args
->max_msgs
);
2925 /* Copy device name */
2926 DBC_REQUIRE(pndb_props
->ac_name
);
2927 len
= strlen(pndb_props
->ac_name
);
2928 DBC_ASSERT(len
< MAXDEVNAMELEN
);
2929 hnode
->pstr_dev_name
= kzalloc(len
+ 1, GFP_KERNEL
);
2930 if (hnode
->pstr_dev_name
== NULL
) {
2933 strncpy(hnode
->pstr_dev_name
,
2934 pndb_props
->ac_name
, len
);
2938 if (DSP_SUCCEEDED(status
)) {
2939 /* Fill in create args that come from NDB */
2940 if (node_type
== NODE_TASK
|| node_type
== NODE_DAISSOCKET
) {
2941 task_arg_obj
= &(hnode
->create_args
.asa
.task_arg_obj
);
2942 task_arg_obj
->prio
= pndb_props
->prio
;
2943 task_arg_obj
->stack_size
= pndb_props
->stack_size
;
2944 task_arg_obj
->sys_stack_size
=
2945 pndb_props
->sys_stack_size
;
2946 task_arg_obj
->stack_seg
= pndb_props
->stack_seg
;
2947 dev_dbg(bridge
, "(node) Priority: 0x%x Stack Size: "
2948 "0x%x words System Stack Size: 0x%x words "
2949 "Stack Segment: 0x%x profile count : 0x%x\n",
2950 task_arg_obj
->prio
, task_arg_obj
->stack_size
,
2951 task_arg_obj
->sys_stack_size
,
2952 task_arg_obj
->stack_seg
,
2953 pndb_props
->count_profiles
);
2961 * ======== get_proc_props ========
2963 * Retrieve the processor properties.
2965 static int get_proc_props(struct node_mgr
*hnode_mgr
,
2966 struct dev_object
*hdev_obj
)
2968 struct cfg_hostres
*host_res
;
2969 struct bridge_dev_context
*pbridge_context
;
2972 status
= dev_get_bridge_context(hdev_obj
, &pbridge_context
);
2973 if (!pbridge_context
)
2976 if (DSP_SUCCEEDED(status
)) {
2977 host_res
= pbridge_context
->resources
;
2980 hnode_mgr
->ul_chnl_offset
= host_res
->dw_chnl_offset
;
2981 hnode_mgr
->ul_chnl_buf_size
= host_res
->dw_chnl_buf_size
;
2982 hnode_mgr
->ul_num_chnls
= host_res
->dw_num_chnls
;
2985 * PROC will add an API to get dsp_processorinfo.
2986 * Fill in default values for now.
2988 /* TODO -- Instead of hard coding, take from registry */
2989 hnode_mgr
->proc_family
= 6000;
2990 hnode_mgr
->proc_type
= 6410;
2991 hnode_mgr
->min_pri
= DSP_NODE_MIN_PRIORITY
;
2992 hnode_mgr
->max_pri
= DSP_NODE_MAX_PRIORITY
;
2993 hnode_mgr
->udsp_word_size
= DSPWORDSIZE
;
2994 hnode_mgr
->udsp_data_mau_size
= DSPWORDSIZE
;
2995 hnode_mgr
->udsp_mau_size
= 1;
3002 * ======== node_get_uuid_props ========
3004 * Fetch Node UUID properties from DCD/DOF file.
3006 int node_get_uuid_props(void *hprocessor
,
3007 IN CONST
struct dsp_uuid
*node_uuid
,
3008 OUT
struct dsp_ndbprops
*node_props
)
3010 struct node_mgr
*hnode_mgr
= NULL
;
3011 struct dev_object
*hdev_obj
;
3013 struct dcd_nodeprops dcd_node_props
;
3014 struct dsp_processorstate proc_state
;
3016 DBC_REQUIRE(refs
> 0);
3017 DBC_REQUIRE(hprocessor
!= NULL
);
3018 DBC_REQUIRE(node_uuid
!= NULL
);
3020 if (hprocessor
== NULL
|| node_uuid
== NULL
) {
3024 status
= proc_get_state(hprocessor
, &proc_state
,
3025 sizeof(struct dsp_processorstate
));
3026 if (DSP_FAILED(status
))
3028 /* If processor is in error state then don't attempt
3029 to send the message */
3030 if (proc_state
.proc_state
== PROC_ERROR
) {
3035 status
= proc_get_dev_object(hprocessor
, &hdev_obj
);
3037 status
= dev_get_node_manager(hdev_obj
, &hnode_mgr
);
3038 if (hnode_mgr
== NULL
) {
3045 * Enter the critical section. This is needed because
3046 * dcd_get_object_def will ultimately end up calling dbll_open/close,
3047 * which needs to be protected in order to not corrupt the zlib manager
3050 mutex_lock(&hnode_mgr
->node_mgr_lock
);
3052 dcd_node_props
.pstr_create_phase_fxn
= NULL
;
3053 dcd_node_props
.pstr_execute_phase_fxn
= NULL
;
3054 dcd_node_props
.pstr_delete_phase_fxn
= NULL
;
3055 dcd_node_props
.pstr_i_alg_name
= NULL
;
3057 status
= dcd_get_object_def(hnode_mgr
->hdcd_mgr
,
3058 (struct dsp_uuid
*)node_uuid
, DSP_DCDNODETYPE
,
3059 (struct dcd_genericobj
*)&dcd_node_props
);
3061 if (DSP_SUCCEEDED(status
)) {
3062 *node_props
= dcd_node_props
.ndb_props
;
3063 kfree(dcd_node_props
.pstr_create_phase_fxn
);
3065 kfree(dcd_node_props
.pstr_execute_phase_fxn
);
3067 kfree(dcd_node_props
.pstr_delete_phase_fxn
);
3069 kfree(dcd_node_props
.pstr_i_alg_name
);
3071 /* Leave the critical section, we're done. */
3072 mutex_unlock(&hnode_mgr
->node_mgr_lock
);
3078 * ======== get_rms_fxns ========
3080 * Retrieve the RMS functions.
3082 static int get_rms_fxns(struct node_mgr
*hnode_mgr
)
3085 struct dev_object
*dev_obj
= hnode_mgr
->hdev_obj
;
3088 static char *psz_fxns
[NUMRMSFXNS
] = {
3089 "RMS_queryServer", /* RMSQUERYSERVER */
3090 "RMS_configureServer", /* RMSCONFIGURESERVER */
3091 "RMS_createNode", /* RMSCREATENODE */
3092 "RMS_executeNode", /* RMSEXECUTENODE */
3093 "RMS_deleteNode", /* RMSDELETENODE */
3094 "RMS_changeNodePriority", /* RMSCHANGENODEPRIORITY */
3095 "RMS_readMemory", /* RMSREADMEMORY */
3096 "RMS_writeMemory", /* RMSWRITEMEMORY */
3097 "RMS_copy", /* RMSCOPY */
3100 for (i
= 0; i
< NUMRMSFXNS
; i
++) {
3101 status
= dev_get_symbol(dev_obj
, psz_fxns
[i
],
3102 &(hnode_mgr
->ul_fxn_addrs
[i
]));
3103 if (DSP_FAILED(status
)) {
3104 if (status
== -ESPIPE
) {
3106 * May be loaded dynamically (in the future),
3107 * but return an error for now.
3109 dev_dbg(bridge
, "%s: RMS function: %s currently"
3110 " not loaded\n", __func__
, psz_fxns
[i
]);
3112 dev_dbg(bridge
, "%s: Symbol not found: %s "
3113 "status = 0x%x\n", __func__
,
3114 psz_fxns
[i
], status
);
3124 * ======== ovly ========
3126 * Called during overlay.Sends command to RMS to copy a block of data.
3128 static u32
ovly(void *priv_ref
, u32 dsp_run_addr
, u32 dsp_load_addr
,
3129 u32 ul_num_bytes
, u32 mem_space
)
3131 struct node_object
*hnode
= (struct node_object
*)priv_ref
;
3132 struct node_mgr
*hnode_mgr
;
3137 struct bridge_dev_context
*hbridge_context
;
3138 /* Function interface to Bridge driver*/
3139 struct bridge_drv_interface
*intf_fxns
;
3143 hnode_mgr
= hnode
->hnode_mgr
;
3145 ul_size
= ul_num_bytes
/ hnode_mgr
->udsp_word_size
;
3146 ul_timeout
= hnode
->utimeout
;
3148 /* Call new MemCopy function */
3149 intf_fxns
= hnode_mgr
->intf_fxns
;
3150 status
= dev_get_bridge_context(hnode_mgr
->hdev_obj
, &hbridge_context
);
3151 if (DSP_SUCCEEDED(status
)) {
3153 (*intf_fxns
->pfn_brd_mem_copy
) (hbridge_context
,
3154 dsp_run_addr
, dsp_load_addr
,
3155 ul_num_bytes
, (u32
) mem_space
);
3156 if (DSP_SUCCEEDED(status
))
3157 ul_bytes
= ul_num_bytes
;
3159 pr_debug("%s: failed to copy brd memory, status 0x%x\n",
3162 pr_debug("%s: failed to get Bridge context, status 0x%x\n",
3170 * ======== mem_write ========
3172 static u32
mem_write(void *priv_ref
, u32 dsp_add
, void *pbuf
,
3173 u32 ul_num_bytes
, u32 mem_space
)
3175 struct node_object
*hnode
= (struct node_object
*)priv_ref
;
3176 struct node_mgr
*hnode_mgr
;
3180 struct bridge_dev_context
*hbridge_context
;
3181 /* Function interface to Bridge driver */
3182 struct bridge_drv_interface
*intf_fxns
;
3185 DBC_REQUIRE(mem_space
& DBLL_CODE
|| mem_space
& DBLL_DATA
);
3187 hnode_mgr
= hnode
->hnode_mgr
;
3189 ul_timeout
= hnode
->utimeout
;
3190 mem_sect_type
= (mem_space
& DBLL_CODE
) ? RMS_CODE
: RMS_DATA
;
3192 /* Call new MemWrite function */
3193 intf_fxns
= hnode_mgr
->intf_fxns
;
3194 status
= dev_get_bridge_context(hnode_mgr
->hdev_obj
, &hbridge_context
);
3195 status
= (*intf_fxns
->pfn_brd_mem_write
) (hbridge_context
, pbuf
,
3196 dsp_add
, ul_num_bytes
, mem_sect_type
);
3198 return ul_num_bytes
;
3201 #ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
3203 * ======== node_find_addr ========
3205 int node_find_addr(struct node_mgr
*node_mgr
, u32 sym_addr
,
3206 u32 offset_range
, void *sym_addr_output
, char *sym_name
)
3208 struct node_object
*node_obj
;
3209 int status
= -ENOENT
;
3212 pr_debug("%s(0x%x, 0x%x, 0x%x, 0x%x, %s)\n", __func__
,
3213 (unsigned int) node_mgr
,
3214 sym_addr
, offset_range
,
3215 (unsigned int) sym_addr_output
, sym_name
);
3217 node_obj
= (struct node_object
*)(node_mgr
->node_list
->head
.next
);
3219 for (n
= 0; n
< node_mgr
->num_nodes
; n
++) {
3220 status
= nldr_find_addr(node_obj
->nldr_node_obj
, sym_addr
,
3221 offset_range
, sym_addr_output
, sym_name
);
3223 if (DSP_SUCCEEDED(status
))
3226 node_obj
= (struct node_object
*) (node_obj
->list_elem
.next
);