staging: tidspbridge: set9 remove hungarian from structs
[linux-block.git] / drivers / staging / tidspbridge / rmgr / node.c
CommitLineData
7d55524d
ORL
1/*
2 * node.c
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * DSP/BIOS Bridge Node Manager.
7 *
8 * Copyright (C) 2005-2006 Texas Instruments, Inc.
9 *
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.
13 *
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.
17 */
18
2094f12d 19#include <linux/types.h>
b5a38aba 20#include <linux/bitmap.h>
0005391f
IN
21#include <linux/list.h>
22
7d55524d
ORL
23/* ----------------------------------- Host OS */
24#include <dspbridge/host_os.h>
25
26/* ----------------------------------- DSP/BIOS Bridge */
7d55524d
ORL
27#include <dspbridge/dbdefs.h>
28
29/* ----------------------------------- Trace & Debug */
30#include <dspbridge/dbc.h>
31
32/* ----------------------------------- OS Adaptation Layer */
7d55524d
ORL
33#include <dspbridge/memdefs.h>
34#include <dspbridge/proc.h>
35#include <dspbridge/strm.h>
36#include <dspbridge/sync.h>
37#include <dspbridge/ntfy.h>
38
39/* ----------------------------------- Platform Manager */
40#include <dspbridge/cmm.h>
41#include <dspbridge/cod.h>
42#include <dspbridge/dev.h>
43#include <dspbridge/msg.h>
44
45/* ----------------------------------- Resource Manager */
46#include <dspbridge/dbdcd.h>
47#include <dspbridge/disp.h>
48#include <dspbridge/rms_sh.h>
49
50/* ----------------------------------- Link Driver */
51#include <dspbridge/dspdefs.h>
52#include <dspbridge/dspioctl.h>
53
54/* ----------------------------------- Others */
7d55524d
ORL
55#include <dspbridge/uuidutil.h>
56
57/* ----------------------------------- This */
58#include <dspbridge/nodepriv.h>
59#include <dspbridge/node.h>
677f2ded 60#include <dspbridge/dmm.h>
7d55524d
ORL
61
62/* Static/Dynamic Loader includes */
63#include <dspbridge/dbll.h>
64#include <dspbridge/nldr.h>
65
66#include <dspbridge/drv.h>
7d55524d
ORL
67#include <dspbridge/resourcecleanup.h>
68#include <_tiomap.h>
69
61a5b769
FC
70#include <dspbridge/dspdeh.h>
71
7d55524d
ORL
72#define HOSTPREFIX "/host"
73#define PIPEPREFIX "/dbpipe"
74
75#define MAX_INPUTS(h) \
76 ((h)->dcd_props.obj_data.node_obj.ndb_props.num_input_streams)
77#define MAX_OUTPUTS(h) \
78 ((h)->dcd_props.obj_data.node_obj.ndb_props.num_output_streams)
79
80#define NODE_GET_PRIORITY(h) ((h)->prio)
81#define NODE_SET_PRIORITY(hnode, prio) ((hnode)->prio = prio)
82#define NODE_SET_STATE(hnode, state) ((hnode)->node_state = state)
83
84#define MAXPIPES 100 /* Max # of /pipe connections (CSL limit) */
85#define MAXDEVSUFFIXLEN 2 /* Max(Log base 10 of MAXPIPES, MAXSTREAMS) */
86
87#define PIPENAMELEN (sizeof(PIPEPREFIX) + MAXDEVSUFFIXLEN)
88#define HOSTNAMELEN (sizeof(HOSTPREFIX) + MAXDEVSUFFIXLEN)
89
90#define MAXDEVNAMELEN 32 /* dsp_ndbprops.ac_name size */
91#define CREATEPHASE 1
92#define EXECUTEPHASE 2
93#define DELETEPHASE 3
94
95/* Define default STRM parameters */
96/*
97 * TBD: Put in header file, make global DSP_STRMATTRS with defaults,
98 * or make defaults configurable.
99 */
100#define DEFAULTBUFSIZE 32
101#define DEFAULTNBUFS 2
102#define DEFAULTSEGID 0
103#define DEFAULTALIGNMENT 0
104#define DEFAULTTIMEOUT 10000
105
106#define RMSQUERYSERVER 0
107#define RMSCONFIGURESERVER 1
108#define RMSCREATENODE 2
109#define RMSEXECUTENODE 3
110#define RMSDELETENODE 4
111#define RMSCHANGENODEPRIORITY 5
112#define RMSREADMEMORY 6
113#define RMSWRITEMEMORY 7
114#define RMSCOPY 8
115#define MAXTIMEOUT 2000
116
117#define NUMRMSFXNS 9
118
119#define PWR_TIMEOUT 500 /* default PWR timeout in msec */
120
121#define STACKSEGLABEL "L1DSRAM_HEAP" /* Label for DSP Stack Segment Addr */
122
123/*
124 * ======== node_mgr ========
125 */
126struct node_mgr {
085467b8 127 struct dev_object *dev_obj; /* Device object */
7d55524d
ORL
128 /* Function interface to Bridge driver */
129 struct bridge_drv_interface *intf_fxns;
085467b8 130 struct dcd_manager *dcd_mgr; /* Proc/Node data manager */
7d55524d 131 struct disp_object *disp_obj; /* Node dispatcher */
0005391f 132 struct list_head node_list; /* List of all allocated nodes */
7d55524d
ORL
133 u32 num_nodes; /* Number of nodes in node_list */
134 u32 num_created; /* Number of nodes *created* on DSP */
b5a38aba
IN
135 DECLARE_BITMAP(pipe_map, MAXPIPES); /* Pipe connection bitmap */
136 DECLARE_BITMAP(pipe_done_map, MAXPIPES); /* Pipes that are half free */
137 /* Channel allocation bitmap */
138 DECLARE_BITMAP(chnl_map, CHNL_MAXCHANNELS);
139 /* DMA Channel allocation bitmap */
140 DECLARE_BITMAP(dma_chnl_map, CHNL_MAXCHANNELS);
141 /* Zero-Copy Channel alloc bitmap */
142 DECLARE_BITMAP(zc_chnl_map, CHNL_MAXCHANNELS);
7d55524d
ORL
143 struct ntfy_object *ntfy_obj; /* Manages registered notifications */
144 struct mutex node_mgr_lock; /* For critical sections */
dab7f7fe 145 u32 fxn_addrs[NUMRMSFXNS]; /* RMS function addresses */
7d55524d
ORL
146 struct msg_mgr *msg_mgr_obj;
147
148 /* Processor properties needed by Node Dispatcher */
6c66e948 149 u32 num_chnls; /* Total number of channels */
dab7f7fe
RS
150 u32 chnl_offset; /* Offset of chnl ids rsvd for RMS */
151 u32 chnl_buf_size; /* Buffer size for data to RMS */
7d55524d
ORL
152 int proc_family; /* eg, 5000 */
153 int proc_type; /* eg, 5510 */
a534f17b
RS
154 u32 dsp_word_size; /* Size of DSP word on host bytes */
155 u32 dsp_data_mau_size; /* Size of DSP data MAU */
156 u32 dsp_mau_size; /* Size of MAU */
7d55524d
ORL
157 s32 min_pri; /* Minimum runtime priority for node */
158 s32 max_pri; /* Maximum runtime priority for node */
159
160 struct strm_mgr *strm_mgr_obj; /* STRM manager */
161
162 /* Loader properties */
163 struct nldr_object *nldr_obj; /* Handle to loader */
164 struct node_ldr_fxns nldr_fxns; /* Handle to loader functions */
165 bool loader_init; /* Loader Init function succeeded? */
166};
167
168/*
169 * ======== connecttype ========
170 */
171enum connecttype {
172 NOTCONNECTED = 0,
173 NODECONNECT,
174 HOSTCONNECT,
175 DEVICECONNECT,
176};
177
178/*
179 * ======== stream_chnl ========
180 */
181struct stream_chnl {
182 enum connecttype type; /* Type of stream connection */
183 u32 dev_id; /* pipe or channel id */
184};
185
186/*
187 * ======== node_object ========
188 */
189struct node_object {
190 struct list_head list_elem;
085467b8 191 struct node_mgr *node_mgr; /* The manager of this node */
a534f17b 192 struct proc_object *processor; /* Back pointer to processor */
7d55524d
ORL
193 struct dsp_uuid node_uuid; /* Node's ID */
194 s32 prio; /* Node's current priority */
a534f17b 195 u32 timeout; /* Timeout for blocking NODE calls */
7d55524d 196 u32 heap_size; /* Heap Size */
a534f17b
RS
197 u32 dsp_heap_virt_addr; /* Heap Size */
198 u32 gpp_heap_virt_addr; /* Heap Size */
7d55524d
ORL
199 enum node_type ntype; /* Type of node: message, task, etc */
200 enum node_state node_state; /* NODE_ALLOCATED, NODE_CREATED, ... */
201 u32 num_inputs; /* Current number of inputs */
202 u32 num_outputs; /* Current number of outputs */
203 u32 max_input_index; /* Current max input stream index */
204 u32 max_output_index; /* Current max output stream index */
205 struct stream_chnl *inputs; /* Node's input streams */
206 struct stream_chnl *outputs; /* Node's output streams */
207 struct node_createargs create_args; /* Args for node create func */
208 nodeenv node_env; /* Environment returned by RMS */
209 struct dcd_genericobj dcd_props; /* Node properties from DCD */
210 struct dsp_cbdata *pargs; /* Optional args to pass to node */
211 struct ntfy_object *ntfy_obj; /* Manages registered notifications */
212 char *pstr_dev_name; /* device name, if device node */
213 struct sync_object *sync_done; /* Synchronize node_terminate */
214 s32 exit_status; /* execute function return status */
215
216 /* Information needed for node_get_attr() */
217 void *device_owner; /* If dev node, task that owns it */
218 u32 num_gpp_inputs; /* Current # of from GPP streams */
219 u32 num_gpp_outputs; /* Current # of to GPP streams */
220 /* Current stream connections */
221 struct dsp_streamconnect *stream_connect;
222
223 /* Message queue */
224 struct msg_queue *msg_queue_obj;
225
226 /* These fields used for SM messaging */
227 struct cmm_xlatorobject *xlator; /* Node's SM addr translator */
228
229 /* Handle to pass to dynamic loader */
230 struct nldr_nodeobject *nldr_node_obj;
231 bool loaded; /* Code is (dynamically) loaded */
232 bool phase_split; /* Phases split in many libs or ovly */
233
234};
235
236/* Default buffer attributes */
237static struct dsp_bufferattr node_dfltbufattrs = {
57104f0f
IN
238 .cb_struct = 0,
239 .segment_id = 1,
240 .buf_alignment = 0,
7d55524d
ORL
241};
242
243static void delete_node(struct node_object *hnode,
244 struct process_context *pr_ctxt);
245static void delete_node_mgr(struct node_mgr *hnode_mgr);
e6890692 246static void fill_stream_connect(struct node_object *node1,
5e2eae57
RS
247 struct node_object *node2, u32 stream1,
248 u32 stream2);
7d55524d
ORL
249static void fill_stream_def(struct node_object *hnode,
250 struct node_strmdef *pstrm_def,
251 struct dsp_strmattr *pattrs);
252static void free_stream(struct node_mgr *hnode_mgr, struct stream_chnl stream);
318b5df9 253static int get_fxn_address(struct node_object *hnode, u32 * fxn_addr,
5e2eae57 254 u32 phase);
7d55524d
ORL
255static int get_node_props(struct dcd_manager *hdcd_mgr,
256 struct node_object *hnode,
cd4f13c0 257 const struct dsp_uuid *node_uuid,
aa09b091 258 struct dcd_genericobj *dcd_prop);
7d55524d
ORL
259static int get_proc_props(struct node_mgr *hnode_mgr,
260 struct dev_object *hdev_obj);
261static int get_rms_fxns(struct node_mgr *hnode_mgr);
5e2eae57 262static u32 ovly(void *priv_ref, u32 dsp_run_addr, u32 dsp_load_addr,
95870a88 263 u32 ul_num_bytes, u32 mem_space);
5e2eae57 264static u32 mem_write(void *priv_ref, u32 dsp_add, void *pbuf,
95870a88 265 u32 ul_num_bytes, u32 mem_space);
7d55524d
ORL
266
267static u32 refs; /* module reference count */
268
269/* Dynamic loader functions. */
270static struct node_ldr_fxns nldr_fxns = {
271 nldr_allocate,
272 nldr_create,
273 nldr_delete,
274 nldr_exit,
275 nldr_get_fxn_addr,
276 nldr_init,
277 nldr_load,
278 nldr_unload,
279};
280
281enum node_state node_get_state(void *hnode)
282{
283 struct node_object *pnode = (struct node_object *)hnode;
284 if (!pnode)
285 return -1;
57104f0f 286 return pnode->node_state;
7d55524d
ORL
287}
288
289/*
290 * ======== node_allocate ========
291 * Purpose:
292 * Allocate GPP resources to manage a node on the DSP.
293 */
294int node_allocate(struct proc_object *hprocessor,
0624f52f
ER
295 const struct dsp_uuid *node_uuid,
296 const struct dsp_cbdata *pargs,
297 const struct dsp_nodeattrin *attr_in,
298 struct node_res_object **noderes,
299 struct process_context *pr_ctxt)
7d55524d
ORL
300{
301 struct node_mgr *hnode_mgr;
302 struct dev_object *hdev_obj;
303 struct node_object *pnode = NULL;
304 enum node_type node_type = NODE_TASK;
305 struct node_msgargs *pmsg_args;
306 struct node_taskargs *ptask_args;
307 u32 num_streams;
308 struct bridge_drv_interface *intf_fxns;
309 int status = 0;
310 struct cmm_object *hcmm_mgr = NULL; /* Shared memory manager hndl */
311 u32 proc_id;
312 u32 pul_value;
313 u32 dynext_base;
314 u32 off_set = 0;
315 u32 ul_stack_seg_addr, ul_stack_seg_val;
316 u32 ul_gpp_mem_base;
317 struct cfg_hostres *host_res;
318 struct bridge_dev_context *pbridge_context;
319 u32 mapped_addr = 0;
320 u32 map_attrs = 0x0;
321 struct dsp_processorstate proc_state;
677f2ded
FC
322#ifdef DSP_DMM_DEBUG
323 struct dmm_object *dmm_mgr;
324 struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
325#endif
7d55524d
ORL
326
327 void *node_res;
328
329 DBC_REQUIRE(refs > 0);
330 DBC_REQUIRE(hprocessor != NULL);
0624f52f 331 DBC_REQUIRE(noderes != NULL);
fb6aabb7 332 DBC_REQUIRE(node_uuid != NULL);
7d55524d 333
0624f52f 334 *noderes = NULL;
7d55524d
ORL
335
336 status = proc_get_processor_id(hprocessor, &proc_id);
337
338 if (proc_id != DSP_UNIT)
339 goto func_end;
340
341 status = proc_get_dev_object(hprocessor, &hdev_obj);
a741ea6e 342 if (!status) {
7d55524d
ORL
343 status = dev_get_node_manager(hdev_obj, &hnode_mgr);
344 if (hnode_mgr == NULL)
345 status = -EPERM;
346
347 }
348
b66e0986 349 if (status)
7d55524d
ORL
350 goto func_end;
351
352 status = dev_get_bridge_context(hdev_obj, &pbridge_context);
353 if (!pbridge_context) {
354 status = -EFAULT;
355 goto func_end;
356 }
357
358 status = proc_get_state(hprocessor, &proc_state,
359 sizeof(struct dsp_processorstate));
b66e0986 360 if (status)
7d55524d
ORL
361 goto func_end;
362 /* If processor is in error state then don't attempt
363 to send the message */
364 if (proc_state.proc_state == PROC_ERROR) {
365 status = -EPERM;
366 goto func_end;
367 }
368
369 /* Assuming that 0 is not a valid function address */
dab7f7fe 370 if (hnode_mgr->fxn_addrs[0] == 0) {
7d55524d
ORL
371 /* No RMS on target - we currently can't handle this */
372 pr_err("%s: Failed, no RMS in base image\n", __func__);
373 status = -EPERM;
374 } else {
375 /* Validate attr_in fields, if non-NULL */
376 if (attr_in) {
377 /* Check if attr_in->prio is within range */
378 if (attr_in->prio < hnode_mgr->min_pri ||
379 attr_in->prio > hnode_mgr->max_pri)
380 status = -EDOM;
381 }
382 }
383 /* Allocate node object and fill in */
b66e0986 384 if (status)
7d55524d
ORL
385 goto func_end;
386
387 pnode = kzalloc(sizeof(struct node_object), GFP_KERNEL);
388 if (pnode == NULL) {
389 status = -ENOMEM;
390 goto func_end;
391 }
085467b8 392 pnode->node_mgr = hnode_mgr;
7d55524d
ORL
393 /* This critical section protects get_node_props */
394 mutex_lock(&hnode_mgr->node_mgr_lock);
395
396 /* Get dsp_ndbprops from node database */
085467b8 397 status = get_node_props(hnode_mgr->dcd_mgr, pnode, node_uuid,
7d55524d 398 &(pnode->dcd_props));
b66e0986 399 if (status)
7d55524d
ORL
400 goto func_cont;
401
fb6aabb7 402 pnode->node_uuid = *node_uuid;
a534f17b 403 pnode->processor = hprocessor;
7d55524d 404 pnode->ntype = pnode->dcd_props.obj_data.node_obj.ndb_props.ntype;
a534f17b 405 pnode->timeout = pnode->dcd_props.obj_data.node_obj.ndb_props.timeout;
7d55524d
ORL
406 pnode->prio = pnode->dcd_props.obj_data.node_obj.ndb_props.prio;
407
408 /* Currently only C64 DSP builds support Node Dynamic * heaps */
409 /* Allocate memory for node heap */
410 pnode->create_args.asa.task_arg_obj.heap_size = 0;
a534f17b
RS
411 pnode->create_args.asa.task_arg_obj.dsp_heap_addr = 0;
412 pnode->create_args.asa.task_arg_obj.dsp_heap_res_addr = 0;
413 pnode->create_args.asa.task_arg_obj.gpp_heap_addr = 0;
7d55524d
ORL
414 if (!attr_in)
415 goto func_cont;
416
417 /* Check if we have a user allocated node heap */
418 if (!(attr_in->pgpp_virt_addr))
419 goto func_cont;
420
421 /* check for page aligned Heap size */
422 if (((attr_in->heap_size) & (PG_SIZE4K - 1))) {
423 pr_err("%s: node heap size not aligned to 4K, size = 0x%x \n",
424 __func__, attr_in->heap_size);
425 status = -EINVAL;
426 } else {
427 pnode->create_args.asa.task_arg_obj.heap_size =
428 attr_in->heap_size;
a534f17b 429 pnode->create_args.asa.task_arg_obj.gpp_heap_addr =
7d55524d
ORL
430 (u32) attr_in->pgpp_virt_addr;
431 }
b66e0986 432 if (status)
7d55524d
ORL
433 goto func_cont;
434
2fa28a51
FC
435 status = proc_reserve_memory(hprocessor,
436 pnode->create_args.asa.task_arg_obj.
437 heap_size + PAGE_SIZE,
438 (void **)&(pnode->create_args.asa.
a534f17b 439 task_arg_obj.dsp_heap_res_addr),
2fa28a51
FC
440 pr_ctxt);
441 if (status) {
442 pr_err("%s: Failed to reserve memory for heap: 0x%x\n",
443 __func__, status);
444 goto func_cont;
445 }
677f2ded
FC
446#ifdef DSP_DMM_DEBUG
447 status = dmm_get_handle(p_proc_object, &dmm_mgr);
448 if (!dmm_mgr) {
449 status = DSP_EHANDLE;
450 goto func_cont;
451 }
452
453 dmm_mem_map_dump(dmm_mgr);
454#endif
455
7d55524d
ORL
456 map_attrs |= DSP_MAPLITTLEENDIAN;
457 map_attrs |= DSP_MAPELEMSIZE32;
458 map_attrs |= DSP_MAPVIRTUALADDR;
459 status = proc_map(hprocessor, (void *)attr_in->pgpp_virt_addr,
460 pnode->create_args.asa.task_arg_obj.heap_size,
2fa28a51 461 (void *)pnode->create_args.asa.task_arg_obj.
a534f17b 462 dsp_heap_res_addr, (void **)&mapped_addr, map_attrs,
7d55524d 463 pr_ctxt);
b66e0986 464 if (status)
7d55524d
ORL
465 pr_err("%s: Failed to map memory for Heap: 0x%x\n",
466 __func__, status);
467 else
a534f17b 468 pnode->create_args.asa.task_arg_obj.dsp_heap_addr =
7d55524d
ORL
469 (u32) mapped_addr;
470
471func_cont:
472 mutex_unlock(&hnode_mgr->node_mgr_lock);
473 if (attr_in != NULL) {
474 /* Overrides of NBD properties */
a534f17b 475 pnode->timeout = attr_in->timeout;
7d55524d
ORL
476 pnode->prio = attr_in->prio;
477 }
478 /* Create object to manage notifications */
a741ea6e 479 if (!status) {
7d55524d
ORL
480 pnode->ntfy_obj = kmalloc(sizeof(struct ntfy_object),
481 GFP_KERNEL);
482 if (pnode->ntfy_obj)
483 ntfy_init(pnode->ntfy_obj);
484 else
485 status = -ENOMEM;
486 }
487
a741ea6e 488 if (!status) {
7d55524d
ORL
489 node_type = node_get_type(pnode);
490 /* Allocate dsp_streamconnect array for device, task, and
491 * dais socket nodes. */
492 if (node_type != NODE_MESSAGE) {
493 num_streams = MAX_INPUTS(pnode) + MAX_OUTPUTS(pnode);
494 pnode->stream_connect = kzalloc(num_streams *
495 sizeof(struct dsp_streamconnect),
496 GFP_KERNEL);
497 if (num_streams > 0 && pnode->stream_connect == NULL)
498 status = -ENOMEM;
499
500 }
a741ea6e 501 if (!status && (node_type == NODE_TASK ||
7d55524d
ORL
502 node_type == NODE_DAISSOCKET)) {
503 /* Allocate arrays for maintainig stream connections */
504 pnode->inputs = kzalloc(MAX_INPUTS(pnode) *
505 sizeof(struct stream_chnl), GFP_KERNEL);
506 pnode->outputs = kzalloc(MAX_OUTPUTS(pnode) *
507 sizeof(struct stream_chnl), GFP_KERNEL);
508 ptask_args = &(pnode->create_args.asa.task_arg_obj);
509 ptask_args->strm_in_def = kzalloc(MAX_INPUTS(pnode) *
510 sizeof(struct node_strmdef),
511 GFP_KERNEL);
512 ptask_args->strm_out_def = kzalloc(MAX_OUTPUTS(pnode) *
513 sizeof(struct node_strmdef),
514 GFP_KERNEL);
515 if ((MAX_INPUTS(pnode) > 0 && (pnode->inputs == NULL ||
516 ptask_args->strm_in_def
517 == NULL))
518 || (MAX_OUTPUTS(pnode) > 0
519 && (pnode->outputs == NULL
520 || ptask_args->strm_out_def == NULL)))
521 status = -ENOMEM;
522 }
523 }
a741ea6e 524 if (!status && (node_type != NODE_DEVICE)) {
7d55524d
ORL
525 /* Create an event that will be posted when RMS_EXIT is
526 * received. */
527 pnode->sync_done = kzalloc(sizeof(struct sync_object),
528 GFP_KERNEL);
529 if (pnode->sync_done)
530 sync_init_event(pnode->sync_done);
531 else
532 status = -ENOMEM;
533
a741ea6e 534 if (!status) {
7d55524d
ORL
535 /*Get the shared mem mgr for this nodes dev object */
536 status = cmm_get_handle(hprocessor, &hcmm_mgr);
a741ea6e 537 if (!status) {
7d55524d
ORL
538 /* Allocate a SM addr translator for this node
539 * w/ deflt attr */
540 status = cmm_xlator_create(&pnode->xlator,
541 hcmm_mgr, NULL);
542 }
543 }
a741ea6e 544 if (!status) {
7d55524d
ORL
545 /* Fill in message args */
546 if ((pargs != NULL) && (pargs->cb_data > 0)) {
547 pmsg_args =
548 &(pnode->create_args.asa.node_msg_args);
549 pmsg_args->pdata = kzalloc(pargs->cb_data,
550 GFP_KERNEL);
551 if (pmsg_args->pdata == NULL) {
552 status = -ENOMEM;
553 } else {
554 pmsg_args->arg_length = pargs->cb_data;
555 memcpy(pmsg_args->pdata,
556 pargs->node_data,
557 pargs->cb_data);
558 }
559 }
560 }
561 }
562
a741ea6e 563 if (!status && node_type != NODE_DEVICE) {
7d55524d
ORL
564 /* Create a message queue for this node */
565 intf_fxns = hnode_mgr->intf_fxns;
566 status =
09f13304 567 (*intf_fxns->msg_create_queue) (hnode_mgr->msg_mgr_obj,
7d55524d
ORL
568 &pnode->msg_queue_obj,
569 0,
570 pnode->create_args.asa.
571 node_msg_args.max_msgs,
572 pnode);
573 }
574
a741ea6e 575 if (!status) {
7d55524d
ORL
576 /* Create object for dynamic loading */
577
3c882de5 578 status = hnode_mgr->nldr_fxns.allocate(hnode_mgr->nldr_obj,
7d55524d
ORL
579 (void *)pnode,
580 &pnode->dcd_props.
581 obj_data.node_obj,
582 &pnode->
583 nldr_node_obj,
584 &pnode->phase_split);
585 }
586
587 /* Compare value read from Node Properties and check if it is same as
588 * STACKSEGLABEL, if yes read the Address of STACKSEGLABEL, calculate
589 * GPP Address, Read the value in that address and override the
590 * stack_seg value in task args */
a741ea6e 591 if (!status &&
7d55524d
ORL
592 (char *)pnode->dcd_props.obj_data.node_obj.ndb_props.
593 stack_seg_name != NULL) {
594 if (strcmp((char *)
595 pnode->dcd_props.obj_data.node_obj.ndb_props.
596 stack_seg_name, STACKSEGLABEL) == 0) {
597 status =
598 hnode_mgr->nldr_fxns.
09f13304 599 get_fxn_addr(pnode->nldr_node_obj, "DYNEXT_BEG",
7d55524d 600 &dynext_base);
b66e0986 601 if (status)
7d55524d
ORL
602 pr_err("%s: Failed to get addr for DYNEXT_BEG"
603 " status = 0x%x\n", __func__, status);
604
605 status =
606 hnode_mgr->nldr_fxns.
09f13304 607 get_fxn_addr(pnode->nldr_node_obj,
7d55524d
ORL
608 "L1DSRAM_HEAP", &pul_value);
609
b66e0986 610 if (status)
7d55524d
ORL
611 pr_err("%s: Failed to get addr for L1DSRAM_HEAP"
612 " status = 0x%x\n", __func__, status);
613
614 host_res = pbridge_context->resources;
615 if (!host_res)
616 status = -EPERM;
617
b66e0986 618 if (status) {
7d55524d
ORL
619 pr_err("%s: Failed to get host resource, status"
620 " = 0x%x\n", __func__, status);
621 goto func_end;
622 }
623
5108de0a 624 ul_gpp_mem_base = (u32) host_res->mem_base[1];
7d55524d
ORL
625 off_set = pul_value - dynext_base;
626 ul_stack_seg_addr = ul_gpp_mem_base + off_set;
7124cb17 627 ul_stack_seg_val = readl(ul_stack_seg_addr);
7d55524d
ORL
628
629 dev_dbg(bridge, "%s: StackSegVal = 0x%x, StackSegAddr ="
630 " 0x%x\n", __func__, ul_stack_seg_val,
631 ul_stack_seg_addr);
632
633 pnode->create_args.asa.task_arg_obj.stack_seg =
634 ul_stack_seg_val;
635
636 }
637 }
638
a741ea6e 639 if (!status) {
7d55524d
ORL
640 /* Add the node to the node manager's list of allocated
641 * nodes. */
7d55524d
ORL
642 NODE_SET_STATE(pnode, NODE_ALLOCATED);
643
644 mutex_lock(&hnode_mgr->node_mgr_lock);
645
0005391f
IN
646 list_add_tail(&pnode->list_elem, &hnode_mgr->node_list);
647 ++(hnode_mgr->num_nodes);
7d55524d
ORL
648
649 /* Exit critical section */
650 mutex_unlock(&hnode_mgr->node_mgr_lock);
651
652 /* Preset this to assume phases are split
653 * (for overlay and dll) */
654 pnode->phase_split = true;
655
7d55524d
ORL
656 /* Notify all clients registered for DSP_NODESTATECHANGE. */
657 proc_notify_all_clients(hprocessor, DSP_NODESTATECHANGE);
658 } else {
659 /* Cleanup */
660 if (pnode)
661 delete_node(pnode, pr_ctxt);
662
663 }
664
a741ea6e 665 if (!status) {
0624f52f
ER
666 status = drv_insert_node_res_element(pnode, &node_res, pr_ctxt);
667 if (status) {
668 delete_node(pnode, pr_ctxt);
669 goto func_end;
670 }
671
672 *noderes = (struct node_res_object *)node_res;
7d55524d
ORL
673 drv_proc_node_update_heap_status(node_res, true);
674 drv_proc_node_update_status(node_res, true);
675 }
0624f52f 676 DBC_ENSURE((status && *noderes == NULL) || (!status && *noderes));
7d55524d 677func_end:
0624f52f
ER
678 dev_dbg(bridge, "%s: hprocessor: %p pNodeId: %p pargs: %p attr_in: %p "
679 "node_res: %p status: 0x%x\n", __func__, hprocessor,
680 node_uuid, pargs, attr_in, noderes, status);
7d55524d
ORL
681 return status;
682}
683
684/*
685 * ======== node_alloc_msg_buf ========
686 * Purpose:
687 * Allocates buffer for zero copy messaging.
688 */
689DBAPI node_alloc_msg_buf(struct node_object *hnode, u32 usize,
e6bf74f0
MN
690 struct dsp_bufferattr *pattr,
691 u8 **pbuffer)
7d55524d
ORL
692{
693 struct node_object *pnode = (struct node_object *)hnode;
694 int status = 0;
695 bool va_flag = false;
696 bool set_info;
697 u32 proc_id;
698
699 DBC_REQUIRE(refs > 0);
700 DBC_REQUIRE(pbuffer != NULL);
701
702 DBC_REQUIRE(usize > 0);
703
704 if (!pnode)
705 status = -EFAULT;
706 else if (node_get_type(pnode) == NODE_DEVICE)
707 status = -EPERM;
708
b66e0986 709 if (status)
7d55524d
ORL
710 goto func_end;
711
712 if (pattr == NULL)
713 pattr = &node_dfltbufattrs; /* set defaults */
714
a534f17b 715 status = proc_get_processor_id(pnode->processor, &proc_id);
7d55524d
ORL
716 if (proc_id != DSP_UNIT) {
717 DBC_ASSERT(NULL);
718 goto func_end;
719 }
720 /* If segment ID includes MEM_SETVIRTUALSEGID then pbuffer is a
721 * virt address, so set this info in this node's translator
722 * object for future ref. If MEM_GETVIRTUALSEGID then retrieve
723 * virtual address from node's translator. */
724 if ((pattr->segment_id & MEM_SETVIRTUALSEGID) ||
725 (pattr->segment_id & MEM_GETVIRTUALSEGID)) {
726 va_flag = true;
727 set_info = (pattr->segment_id & MEM_SETVIRTUALSEGID) ?
728 true : false;
729 /* Clear mask bits */
730 pattr->segment_id &= ~MEM_MASKVIRTUALSEGID;
731 /* Set/get this node's translators virtual address base/size */
732 status = cmm_xlator_info(pnode->xlator, pbuffer, usize,
733 pattr->segment_id, set_info);
734 }
a741ea6e 735 if (!status && (!va_flag)) {
7d55524d
ORL
736 if (pattr->segment_id != 1) {
737 /* Node supports single SM segment only. */
738 status = -EBADR;
739 }
740 /* Arbitrary SM buffer alignment not supported for host side
741 * allocs, but guaranteed for the following alignment
742 * values. */
743 switch (pattr->buf_alignment) {
744 case 0:
745 case 1:
746 case 2:
747 case 4:
748 break;
749 default:
750 /* alignment value not suportted */
751 status = -EPERM;
752 break;
753 }
a741ea6e 754 if (!status) {
7d55524d
ORL
755 /* allocate physical buffer from seg_id in node's
756 * translator */
757 (void)cmm_xlator_alloc_buf(pnode->xlator, pbuffer,
758 usize);
759 if (*pbuffer == NULL) {
760 pr_err("%s: error - Out of shared memory\n",
761 __func__);
762 status = -ENOMEM;
763 }
764 }
765 }
766func_end:
767 return status;
768}
769
770/*
771 * ======== node_change_priority ========
772 * Purpose:
773 * Change the priority of a node in the allocated state, or that is
774 * currently running or paused on the target.
775 */
776int node_change_priority(struct node_object *hnode, s32 prio)
777{
778 struct node_object *pnode = (struct node_object *)hnode;
779 struct node_mgr *hnode_mgr = NULL;
780 enum node_type node_type;
781 enum node_state state;
782 int status = 0;
783 u32 proc_id;
784
785 DBC_REQUIRE(refs > 0);
786
085467b8 787 if (!hnode || !hnode->node_mgr) {
7d55524d
ORL
788 status = -EFAULT;
789 } else {
085467b8 790 hnode_mgr = hnode->node_mgr;
7d55524d
ORL
791 node_type = node_get_type(hnode);
792 if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET)
793 status = -EPERM;
794 else if (prio < hnode_mgr->min_pri || prio > hnode_mgr->max_pri)
795 status = -EDOM;
796 }
b66e0986 797 if (status)
7d55524d
ORL
798 goto func_end;
799
800 /* Enter critical section */
801 mutex_lock(&hnode_mgr->node_mgr_lock);
802
803 state = node_get_state(hnode);
804 if (state == NODE_ALLOCATED || state == NODE_PAUSED) {
805 NODE_SET_PRIORITY(hnode, prio);
806 } else {
807 if (state != NODE_RUNNING) {
808 status = -EBADR;
809 goto func_cont;
810 }
a534f17b 811 status = proc_get_processor_id(pnode->processor, &proc_id);
7d55524d
ORL
812 if (proc_id == DSP_UNIT) {
813 status =
814 disp_node_change_priority(hnode_mgr->disp_obj,
815 hnode,
dab7f7fe 816 hnode_mgr->fxn_addrs
7d55524d
ORL
817 [RMSCHANGENODEPRIORITY],
818 hnode->node_env, prio);
819 }
a741ea6e 820 if (status >= 0)
7d55524d
ORL
821 NODE_SET_PRIORITY(hnode, prio);
822
823 }
824func_cont:
825 /* Leave critical section */
826 mutex_unlock(&hnode_mgr->node_mgr_lock);
827func_end:
828 return status;
829}
830
831/*
832 * ======== node_connect ========
833 * Purpose:
834 * Connect two nodes on the DSP, or a node on the DSP to the GPP.
835 */
5e2eae57 836int node_connect(struct node_object *node1, u32 stream1,
e6890692 837 struct node_object *node2,
21aaf42e
MN
838 u32 stream2, struct dsp_strmattr *pattrs,
839 struct dsp_cbdata *conn_param)
7d55524d
ORL
840{
841 struct node_mgr *hnode_mgr;
842 char *pstr_dev_name = NULL;
843 enum node_type node1_type = NODE_TASK;
844 enum node_type node2_type = NODE_TASK;
57104f0f 845 enum dsp_strmmode strm_mode;
7d55524d
ORL
846 struct node_strmdef *pstrm_def;
847 struct node_strmdef *input = NULL;
848 struct node_strmdef *output = NULL;
849 struct node_object *dev_node_obj;
850 struct node_object *hnode;
851 struct stream_chnl *pstream;
b5a38aba
IN
852 u32 pipe_id;
853 u32 chnl_id;
7d55524d
ORL
854 s8 chnl_mode;
855 u32 dw_length;
856 int status = 0;
857 DBC_REQUIRE(refs > 0);
858
57104f0f
IN
859 if (!node1 || !node2)
860 return -EFAULT;
861
862 /* The two nodes must be on the same processor */
863 if (node1 != (struct node_object *)DSP_HGPPNODE &&
864 node2 != (struct node_object *)DSP_HGPPNODE &&
085467b8 865 node1->node_mgr != node2->node_mgr)
57104f0f
IN
866 return -EPERM;
867
868 /* Cannot connect a node to itself */
869 if (node1 == node2)
870 return -EPERM;
871
872 /* node_get_type() will return NODE_GPP if hnode = DSP_HGPPNODE. */
873 node1_type = node_get_type(node1);
874 node2_type = node_get_type(node2);
875 /* Check stream indices ranges */
876 if ((node1_type != NODE_GPP && node1_type != NODE_DEVICE &&
877 stream1 >= MAX_OUTPUTS(node1)) ||
878 (node2_type != NODE_GPP && node2_type != NODE_DEVICE &&
879 stream2 >= MAX_INPUTS(node2)))
880 return -EINVAL;
7d55524d 881
57104f0f
IN
882 /*
883 * Only the following types of connections are allowed:
884 * task/dais socket < == > task/dais socket
885 * task/dais socket < == > device
886 * task/dais socket < == > GPP
887 *
888 * ie, no message nodes, and at least one task or dais
889 * socket node.
890 */
891 if (node1_type == NODE_MESSAGE || node2_type == NODE_MESSAGE ||
892 (node1_type != NODE_TASK &&
893 node1_type != NODE_DAISSOCKET &&
894 node2_type != NODE_TASK &&
895 node2_type != NODE_DAISSOCKET))
896 return -EPERM;
7d55524d
ORL
897 /*
898 * Check stream mode. Default is STRMMODE_PROCCOPY.
899 */
57104f0f
IN
900 if (pattrs && pattrs->strm_mode != STRMMODE_PROCCOPY)
901 return -EPERM; /* illegal stream mode */
7d55524d
ORL
902
903 if (node1_type != NODE_GPP) {
085467b8 904 hnode_mgr = node1->node_mgr;
7d55524d 905 } else {
e6890692 906 DBC_ASSERT(node2 != (struct node_object *)DSP_HGPPNODE);
085467b8 907 hnode_mgr = node2->node_mgr;
7d55524d 908 }
57104f0f 909
7d55524d
ORL
910 /* Enter critical section */
911 mutex_lock(&hnode_mgr->node_mgr_lock);
912
913 /* Nodes must be in the allocated state */
57104f0f
IN
914 if (node1_type != NODE_GPP &&
915 node_get_state(node1) != NODE_ALLOCATED) {
7d55524d 916 status = -EBADR;
57104f0f
IN
917 goto out_unlock;
918 }
7d55524d 919
57104f0f
IN
920 if (node2_type != NODE_GPP &&
921 node_get_state(node2) != NODE_ALLOCATED) {
7d55524d 922 status = -EBADR;
57104f0f
IN
923 goto out_unlock;
924 }
7d55524d 925
57104f0f
IN
926 /*
927 * Check that stream indices for task and dais socket nodes
928 * are not already be used. (Device nodes checked later)
929 */
930 if (node1_type == NODE_TASK || node1_type == NODE_DAISSOCKET) {
931 output = &(node1->create_args.asa.
932 task_arg_obj.strm_out_def[stream1]);
933 if (output->sz_device) {
934 status = -EISCONN;
935 goto out_unlock;
7d55524d 936 }
7d55524d 937
57104f0f
IN
938 }
939 if (node2_type == NODE_TASK || node2_type == NODE_DAISSOCKET) {
940 input = &(node2->create_args.asa.
941 task_arg_obj.strm_in_def[stream2]);
942 if (input->sz_device) {
943 status = -EISCONN;
944 goto out_unlock;
7d55524d 945 }
57104f0f 946
7d55524d
ORL
947 }
948 /* Connecting two task nodes? */
57104f0f
IN
949 if ((node1_type == NODE_TASK || node1_type == NODE_DAISSOCKET) &&
950 (node2_type == NODE_TASK ||
951 node2_type == NODE_DAISSOCKET)) {
7d55524d 952 /* Find available pipe */
b5a38aba
IN
953 pipe_id = find_first_zero_bit(hnode_mgr->pipe_map, MAXPIPES);
954 if (pipe_id == MAXPIPES) {
7d55524d 955 status = -ECONNREFUSED;
57104f0f
IN
956 goto out_unlock;
957 }
958 set_bit(pipe_id, hnode_mgr->pipe_map);
959 node1->outputs[stream1].type = NODECONNECT;
960 node2->inputs[stream2].type = NODECONNECT;
961 node1->outputs[stream1].dev_id = pipe_id;
962 node2->inputs[stream2].dev_id = pipe_id;
963 output->sz_device = kzalloc(PIPENAMELEN + 1, GFP_KERNEL);
964 input->sz_device = kzalloc(PIPENAMELEN + 1, GFP_KERNEL);
965 if (!output->sz_device || !input->sz_device) {
966 /* Undo the connection */
967 kfree(output->sz_device);
968 kfree(input->sz_device);
969 clear_bit(pipe_id, hnode_mgr->pipe_map);
970 status = -ENOMEM;
971 goto out_unlock;
7d55524d 972 }
57104f0f
IN
973 /* Copy "/dbpipe<pipId>" name to device names */
974 sprintf(output->sz_device, "%s%d", PIPEPREFIX, pipe_id);
975 strcpy(input->sz_device, output->sz_device);
7d55524d
ORL
976 }
977 /* Connecting task node to host? */
57104f0f
IN
978 if (node1_type == NODE_GPP || node2_type == NODE_GPP) {
979 pstr_dev_name = kzalloc(HOSTNAMELEN + 1, GFP_KERNEL);
980 if (!pstr_dev_name) {
981 status = -ENOMEM;
982 goto out_unlock;
7d55524d 983 }
57104f0f
IN
984
985 DBC_ASSERT((node1_type == NODE_GPP) ||
986 (node2_type == NODE_GPP));
987
988 chnl_mode = (node1_type == NODE_GPP) ?
989 CHNL_MODETODSP : CHNL_MODEFROMDSP;
990
991 /*
992 * Reserve a channel id. We need to put the name "/host<id>"
7d55524d
ORL
993 * in the node's create_args, but the host
994 * side channel will not be opened until DSPStream_Open is
57104f0f
IN
995 * called for this node.
996 */
997 strm_mode = pattrs ? pattrs->strm_mode : STRMMODE_PROCCOPY;
998 switch (strm_mode) {
999 case STRMMODE_RDMA:
1000 chnl_id = find_first_zero_bit(hnode_mgr->dma_chnl_map,
1001 CHNL_MAXCHANNELS);
1002 if (chnl_id < CHNL_MAXCHANNELS) {
1003 set_bit(chnl_id, hnode_mgr->dma_chnl_map);
7d55524d
ORL
1004 /* dma chans are 2nd transport chnl set
1005 * ids(e.g. 16-31) */
6c66e948 1006 chnl_id = chnl_id + hnode_mgr->num_chnls;
57104f0f
IN
1007 }
1008 break;
1009 case STRMMODE_ZEROCOPY:
1010 chnl_id = find_first_zero_bit(hnode_mgr->zc_chnl_map,
1011 CHNL_MAXCHANNELS);
1012 if (chnl_id < CHNL_MAXCHANNELS) {
1013 set_bit(chnl_id, hnode_mgr->zc_chnl_map);
7d55524d
ORL
1014 /* zero-copy chans are 3nd transport set
1015 * (e.g. 32-47) */
57104f0f 1016 chnl_id = chnl_id +
6c66e948 1017 (2 * hnode_mgr->num_chnls);
7d55524d 1018 }
57104f0f
IN
1019 break;
1020 case STRMMODE_PROCCOPY:
b5a38aba
IN
1021 chnl_id = find_first_zero_bit(hnode_mgr->chnl_map,
1022 CHNL_MAXCHANNELS);
57104f0f 1023 if (chnl_id < CHNL_MAXCHANNELS)
b5a38aba 1024 set_bit(chnl_id, hnode_mgr->chnl_map);
57104f0f
IN
1025 break;
1026 default:
1027 status = -EINVAL;
1028 goto out_unlock;
7d55524d 1029 }
b5a38aba 1030 if (chnl_id == CHNL_MAXCHANNELS) {
7d55524d 1031 status = -ECONNREFUSED;
57104f0f 1032 goto out_unlock;
7d55524d 1033 }
57104f0f
IN
1034
1035 if (node1 == (struct node_object *)DSP_HGPPNODE) {
1036 node2->inputs[stream2].type = HOSTCONNECT;
1037 node2->inputs[stream2].dev_id = chnl_id;
1038 input->sz_device = pstr_dev_name;
7d55524d 1039 } else {
57104f0f
IN
1040 node1->outputs[stream1].type = HOSTCONNECT;
1041 node1->outputs[stream1].dev_id = chnl_id;
1042 output->sz_device = pstr_dev_name;
7d55524d 1043 }
57104f0f 1044 sprintf(pstr_dev_name, "%s%d", HOSTPREFIX, chnl_id);
7d55524d
ORL
1045 }
1046 /* Connecting task node to device node? */
57104f0f 1047 if ((node1_type == NODE_DEVICE) || (node2_type == NODE_DEVICE)) {
7d55524d
ORL
1048 if (node2_type == NODE_DEVICE) {
1049 /* node1 == > device */
e6890692
RS
1050 dev_node_obj = node2;
1051 hnode = node1;
5e2eae57 1052 pstream = &(node1->outputs[stream1]);
7d55524d
ORL
1053 pstrm_def = output;
1054 } else {
1055 /* device == > node2 */
e6890692
RS
1056 dev_node_obj = node1;
1057 hnode = node2;
5e2eae57 1058 pstream = &(node2->inputs[stream2]);
7d55524d
ORL
1059 pstrm_def = input;
1060 }
1061 /* Set up create args */
1062 pstream->type = DEVICECONNECT;
1063 dw_length = strlen(dev_node_obj->pstr_dev_name);
57104f0f 1064 if (conn_param)
7d55524d 1065 pstrm_def->sz_device = kzalloc(dw_length + 1 +
57104f0f
IN
1066 conn_param->cb_data,
1067 GFP_KERNEL);
1068 else
7d55524d 1069 pstrm_def->sz_device = kzalloc(dw_length + 1,
57104f0f
IN
1070 GFP_KERNEL);
1071 if (!pstrm_def->sz_device) {
7d55524d 1072 status = -ENOMEM;
57104f0f
IN
1073 goto out_unlock;
1074 }
1075 /* Copy device name */
1076 strncpy(pstrm_def->sz_device,
7d55524d 1077 dev_node_obj->pstr_dev_name, dw_length);
57104f0f
IN
1078 if (conn_param)
1079 strncat(pstrm_def->sz_device,
7d55524d
ORL
1080 (char *)conn_param->node_data,
1081 (u32) conn_param->cb_data);
57104f0f 1082 dev_node_obj->device_owner = hnode;
7d55524d 1083 }
57104f0f
IN
1084 /* Fill in create args */
1085 if (node1_type == NODE_TASK || node1_type == NODE_DAISSOCKET) {
1086 node1->create_args.asa.task_arg_obj.num_outputs++;
1087 fill_stream_def(node1, output, pattrs);
1088 }
1089 if (node2_type == NODE_TASK || node2_type == NODE_DAISSOCKET) {
1090 node2->create_args.asa.task_arg_obj.num_inputs++;
1091 fill_stream_def(node2, input, pattrs);
1092 }
1093 /* Update node1 and node2 stream_connect */
1094 if (node1_type != NODE_GPP && node1_type != NODE_DEVICE) {
1095 node1->num_outputs++;
1096 if (stream1 > node1->max_output_index)
1097 node1->max_output_index = stream1;
7d55524d 1098
57104f0f
IN
1099 }
1100 if (node2_type != NODE_GPP && node2_type != NODE_DEVICE) {
1101 node2->num_inputs++;
1102 if (stream2 > node2->max_input_index)
1103 node2->max_input_index = stream2;
7d55524d 1104
7d55524d 1105 }
57104f0f 1106 fill_stream_connect(node1, node2, stream1, stream2);
7d55524d
ORL
1107 /* end of sync_enter_cs */
1108 /* Exit critical section */
57104f0f
IN
1109out_unlock:
1110 if (status && pstr_dev_name)
1111 kfree(pstr_dev_name);
7d55524d 1112 mutex_unlock(&hnode_mgr->node_mgr_lock);
5e2eae57 1113 dev_dbg(bridge, "%s: node1: %p stream1: %d node2: %p stream2: %d"
57104f0f
IN
1114 "pattrs: %p status: 0x%x\n", __func__, node1,
1115 stream1, node2, stream2, pattrs, status);
7d55524d
ORL
1116 return status;
1117}
1118
1119/*
1120 * ======== node_create ========
1121 * Purpose:
1122 * Create a node on the DSP by remotely calling the node's create function.
1123 */
1124int node_create(struct node_object *hnode)
1125{
1126 struct node_object *pnode = (struct node_object *)hnode;
1127 struct node_mgr *hnode_mgr;
1128 struct bridge_drv_interface *intf_fxns;
1129 u32 ul_create_fxn;
1130 enum node_type node_type;
1131 int status = 0;
1132 int status1 = 0;
1133 struct dsp_cbdata cb_data;
1134 u32 proc_id = 255;
1135 struct dsp_processorstate proc_state;
1136 struct proc_object *hprocessor;
b3d23688 1137#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
7d55524d
ORL
1138 struct dspbridge_platform_data *pdata =
1139 omap_dspbridge_dev->dev.platform_data;
1140#endif
1141
1142 DBC_REQUIRE(refs > 0);
1143 if (!pnode) {
1144 status = -EFAULT;
1145 goto func_end;
1146 }
a534f17b 1147 hprocessor = hnode->processor;
7d55524d
ORL
1148 status = proc_get_state(hprocessor, &proc_state,
1149 sizeof(struct dsp_processorstate));
b66e0986 1150 if (status)
7d55524d
ORL
1151 goto func_end;
1152 /* If processor is in error state then don't attempt to create
1153 new node */
1154 if (proc_state.proc_state == PROC_ERROR) {
1155 status = -EPERM;
1156 goto func_end;
1157 }
1158 /* create struct dsp_cbdata struct for PWR calls */
1159 cb_data.cb_data = PWR_TIMEOUT;
1160 node_type = node_get_type(hnode);
085467b8 1161 hnode_mgr = hnode->node_mgr;
7d55524d
ORL
1162 intf_fxns = hnode_mgr->intf_fxns;
1163 /* Get access to node dispatcher */
1164 mutex_lock(&hnode_mgr->node_mgr_lock);
1165
1166 /* Check node state */
1167 if (node_get_state(hnode) != NODE_ALLOCATED)
1168 status = -EBADR;
1169
a741ea6e 1170 if (!status)
a534f17b 1171 status = proc_get_processor_id(pnode->processor, &proc_id);
7d55524d 1172
b66e0986 1173 if (status)
7d55524d
ORL
1174 goto func_cont2;
1175
1176 if (proc_id != DSP_UNIT)
1177 goto func_cont2;
1178
1179 /* Make sure streams are properly connected */
1180 if ((hnode->num_inputs && hnode->max_input_index >
1181 hnode->num_inputs - 1) ||
1182 (hnode->num_outputs && hnode->max_output_index >
1183 hnode->num_outputs - 1))
1184 status = -ENOTCONN;
1185
a741ea6e 1186 if (!status) {
7d55524d
ORL
1187 /* If node's create function is not loaded, load it */
1188 /* Boost the OPP level to max level that DSP can be requested */
b3d23688 1189#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
7d55524d
ORL
1190 if (pdata->cpu_set_freq)
1191 (*pdata->cpu_set_freq) (pdata->mpu_speed[VDD1_OPP3]);
1192#endif
09f13304 1193 status = hnode_mgr->nldr_fxns.load(hnode->nldr_node_obj,
7d55524d
ORL
1194 NLDR_CREATE);
1195 /* Get address of node's create function */
a741ea6e 1196 if (!status) {
7d55524d
ORL
1197 hnode->loaded = true;
1198 if (node_type != NODE_DEVICE) {
1199 status = get_fxn_address(hnode, &ul_create_fxn,
1200 CREATEPHASE);
1201 }
1202 } else {
1203 pr_err("%s: failed to load create code: 0x%x\n",
1204 __func__, status);
1205 }
1206 /* Request the lowest OPP level */
b3d23688 1207#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
7d55524d
ORL
1208 if (pdata->cpu_set_freq)
1209 (*pdata->cpu_set_freq) (pdata->mpu_speed[VDD1_OPP1]);
1210#endif
1211 /* Get address of iAlg functions, if socket node */
a741ea6e 1212 if (!status) {
7d55524d 1213 if (node_type == NODE_DAISSOCKET) {
09f13304 1214 status = hnode_mgr->nldr_fxns.get_fxn_addr
7d55524d
ORL
1215 (hnode->nldr_node_obj,
1216 hnode->dcd_props.obj_data.node_obj.
1217 pstr_i_alg_name,
1218 &hnode->create_args.asa.
dab7f7fe 1219 task_arg_obj.dais_arg);
7d55524d
ORL
1220 }
1221 }
1222 }
a741ea6e 1223 if (!status) {
7d55524d
ORL
1224 if (node_type != NODE_DEVICE) {
1225 status = disp_node_create(hnode_mgr->disp_obj, hnode,
dab7f7fe 1226 hnode_mgr->fxn_addrs
7d55524d
ORL
1227 [RMSCREATENODE],
1228 ul_create_fxn,
1229 &(hnode->create_args),
1230 &(hnode->node_env));
a741ea6e 1231 if (status >= 0) {
7d55524d
ORL
1232 /* Set the message queue id to the node env
1233 * pointer */
1234 intf_fxns = hnode_mgr->intf_fxns;
09f13304 1235 (*intf_fxns->msg_set_queue_id) (hnode->
7d55524d
ORL
1236 msg_queue_obj,
1237 hnode->node_env);
1238 }
1239 }
1240 }
1241 /* Phase II/Overlays: Create, execute, delete phases possibly in
1242 * different files/sections. */
1243 if (hnode->loaded && hnode->phase_split) {
1244 /* If create code was dynamically loaded, we can now unload
1245 * it. */
09f13304 1246 status1 = hnode_mgr->nldr_fxns.unload(hnode->nldr_node_obj,
7d55524d
ORL
1247 NLDR_CREATE);
1248 hnode->loaded = false;
1249 }
b66e0986 1250 if (status1)
7d55524d
ORL
1251 pr_err("%s: Failed to unload create code: 0x%x\n",
1252 __func__, status1);
1253func_cont2:
1254 /* Update node state and node manager state */
a741ea6e 1255 if (status >= 0) {
7d55524d
ORL
1256 NODE_SET_STATE(hnode, NODE_CREATED);
1257 hnode_mgr->num_created++;
1258 goto func_cont;
1259 }
1260 if (status != -EBADR) {
1261 /* Put back in NODE_ALLOCATED state if error occurred */
1262 NODE_SET_STATE(hnode, NODE_ALLOCATED);
1263 }
1264func_cont:
1265 /* Free access to node dispatcher */
1266 mutex_unlock(&hnode_mgr->node_mgr_lock);
1267func_end:
a741ea6e 1268 if (status >= 0) {
a534f17b 1269 proc_notify_clients(hnode->processor, DSP_NODESTATECHANGE);
7d55524d
ORL
1270 ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
1271 }
1272
1273 dev_dbg(bridge, "%s: hnode: %p status: 0x%x\n", __func__,
1274 hnode, status);
1275 return status;
1276}
1277
1278/*
1279 * ======== node_create_mgr ========
1280 * Purpose:
1281 * Create a NODE Manager object.
1282 */
e6bf74f0 1283int node_create_mgr(struct node_mgr **node_man,
7d55524d
ORL
1284 struct dev_object *hdev_obj)
1285{
1286 u32 i;
1287 struct node_mgr *node_mgr_obj = NULL;
1288 struct disp_attr disp_attr_obj;
1289 char *sz_zl_file = "";
1290 struct nldr_attrs nldr_attrs_obj;
1291 int status = 0;
1292 u8 dev_type;
57104f0f 1293
7d55524d 1294 DBC_REQUIRE(refs > 0);
daa89e6c 1295 DBC_REQUIRE(node_man != NULL);
7d55524d
ORL
1296 DBC_REQUIRE(hdev_obj != NULL);
1297
daa89e6c 1298 *node_man = NULL;
7d55524d
ORL
1299 /* Allocate Node manager object */
1300 node_mgr_obj = kzalloc(sizeof(struct node_mgr), GFP_KERNEL);
57104f0f
IN
1301 if (!node_mgr_obj)
1302 return -ENOMEM;
1303
085467b8 1304 node_mgr_obj->dev_obj = hdev_obj;
57104f0f
IN
1305
1306 node_mgr_obj->ntfy_obj = kmalloc(sizeof(struct ntfy_object),
1307 GFP_KERNEL);
1308 if (!node_mgr_obj->ntfy_obj) {
7d55524d 1309 status = -ENOMEM;
57104f0f 1310 goto out_err;
7d55524d 1311 }
57104f0f 1312 ntfy_init(node_mgr_obj->ntfy_obj);
7d55524d 1313
57104f0f
IN
1314 INIT_LIST_HEAD(&node_mgr_obj->node_list);
1315
1316 dev_get_dev_type(hdev_obj, &dev_type);
1317
085467b8 1318 status = dcd_create_manager(sz_zl_file, &node_mgr_obj->dcd_mgr);
57104f0f
IN
1319 if (status)
1320 goto out_err;
1321
1322 status = get_proc_props(node_mgr_obj, hdev_obj);
1323 if (status)
1324 goto out_err;
7d55524d 1325
7d55524d 1326 /* Create NODE Dispatcher */
dab7f7fe
RS
1327 disp_attr_obj.chnl_offset = node_mgr_obj->chnl_offset;
1328 disp_attr_obj.chnl_buf_size = node_mgr_obj->chnl_buf_size;
57104f0f
IN
1329 disp_attr_obj.proc_family = node_mgr_obj->proc_family;
1330 disp_attr_obj.proc_type = node_mgr_obj->proc_type;
1331
1332 status = disp_create(&node_mgr_obj->disp_obj, hdev_obj, &disp_attr_obj);
1333 if (status)
1334 goto out_err;
1335
7d55524d 1336 /* Create a STRM Manager */
57104f0f
IN
1337 status = strm_create(&node_mgr_obj->strm_mgr_obj, hdev_obj);
1338 if (status)
1339 goto out_err;
7d55524d 1340
57104f0f
IN
1341 dev_get_intf_fxns(hdev_obj, &node_mgr_obj->intf_fxns);
1342 /* Get msg_ctrl queue manager */
1343 dev_get_msg_mgr(hdev_obj, &node_mgr_obj->msg_mgr_obj);
1344 mutex_init(&node_mgr_obj->node_mgr_lock);
1345
1346 /* Block out reserved channels */
dab7f7fe 1347 for (i = 0; i < node_mgr_obj->chnl_offset; i++)
57104f0f
IN
1348 set_bit(i, node_mgr_obj->chnl_map);
1349
1350 /* Block out channels reserved for RMS */
dab7f7fe
RS
1351 set_bit(node_mgr_obj->chnl_offset, node_mgr_obj->chnl_map);
1352 set_bit(node_mgr_obj->chnl_offset + 1, node_mgr_obj->chnl_map);
57104f0f
IN
1353
1354 /* NO RM Server on the IVA */
1355 if (dev_type != IVA_UNIT) {
1356 /* Get addresses of any RMS functions loaded */
1357 status = get_rms_fxns(node_mgr_obj);
1358 if (status)
1359 goto out_err;
7d55524d
ORL
1360 }
1361
1362 /* Get loader functions and create loader */
57104f0f
IN
1363 node_mgr_obj->nldr_fxns = nldr_fxns; /* Dyn loader funcs */
1364
09f13304 1365 nldr_attrs_obj.ovly = ovly;
dab7f7fe 1366 nldr_attrs_obj.write = mem_write;
a534f17b
RS
1367 nldr_attrs_obj.dsp_word_size = node_mgr_obj->dsp_word_size;
1368 nldr_attrs_obj.dsp_mau_size = node_mgr_obj->dsp_mau_size;
09f13304 1369 node_mgr_obj->loader_init = node_mgr_obj->nldr_fxns.init();
e17ba7f2 1370 status = node_mgr_obj->nldr_fxns.create(&node_mgr_obj->nldr_obj,
57104f0f
IN
1371 hdev_obj,
1372 &nldr_attrs_obj);
1373 if (status)
1374 goto out_err;
7d55524d 1375
57104f0f 1376 *node_man = node_mgr_obj;
7d55524d 1377
b66e0986 1378 DBC_ENSURE((status && *node_man == NULL) || (!status && *node_man));
7d55524d 1379
57104f0f
IN
1380 return status;
1381out_err:
1382 delete_node_mgr(node_mgr_obj);
7d55524d
ORL
1383 return status;
1384}
1385
1386/*
1387 * ======== node_delete ========
1388 * Purpose:
1389 * Delete a node on the DSP by remotely calling the node's delete function.
1390 * Loads the node's delete function if necessary. Free GPP side resources
1391 * after node's delete function returns.
1392 */
0624f52f 1393int node_delete(struct node_res_object *noderes,
7d55524d
ORL
1394 struct process_context *pr_ctxt)
1395{
0624f52f 1396 struct node_object *pnode = noderes->hnode;
7d55524d
ORL
1397 struct node_mgr *hnode_mgr;
1398 struct proc_object *hprocessor;
1399 struct disp_object *disp_obj;
1400 u32 ul_delete_fxn;
1401 enum node_type node_type;
1402 enum node_state state;
1403 int status = 0;
1404 int status1 = 0;
1405 struct dsp_cbdata cb_data;
1406 u32 proc_id;
1407 struct bridge_drv_interface *intf_fxns;
1408
0624f52f 1409 void *node_res = noderes;
7d55524d
ORL
1410
1411 struct dsp_processorstate proc_state;
1412 DBC_REQUIRE(refs > 0);
1413
0624f52f 1414 if (!pnode) {
7d55524d
ORL
1415 status = -EFAULT;
1416 goto func_end;
1417 }
1418 /* create struct dsp_cbdata struct for PWR call */
1419 cb_data.cb_data = PWR_TIMEOUT;
085467b8 1420 hnode_mgr = pnode->node_mgr;
a534f17b 1421 hprocessor = pnode->processor;
7d55524d 1422 disp_obj = hnode_mgr->disp_obj;
0624f52f 1423 node_type = node_get_type(pnode);
7d55524d
ORL
1424 intf_fxns = hnode_mgr->intf_fxns;
1425 /* Enter critical section */
1426 mutex_lock(&hnode_mgr->node_mgr_lock);
1427
0624f52f 1428 state = node_get_state(pnode);
7d55524d
ORL
1429 /* Execute delete phase code for non-device node in all cases
1430 * except when the node was only allocated. Delete phase must be
1431 * executed even if create phase was executed, but failed.
1432 * If the node environment pointer is non-NULL, the delete phase
1433 * code must be executed. */
0624f52f 1434 if (!(state == NODE_ALLOCATED && pnode->node_env == (u32) NULL) &&
7d55524d 1435 node_type != NODE_DEVICE) {
a534f17b 1436 status = proc_get_processor_id(pnode->processor, &proc_id);
b66e0986 1437 if (status)
7d55524d
ORL
1438 goto func_cont1;
1439
1440 if (proc_id == DSP_UNIT || proc_id == IVA_UNIT) {
1441 /* If node has terminated, execute phase code will
1442 * have already been unloaded in node_on_exit(). If the
1443 * node is PAUSED, the execute phase is loaded, and it
1444 * is now ok to unload it. If the node is running, we
1445 * will unload the execute phase only after deleting
1446 * the node. */
0624f52f
ER
1447 if (state == NODE_PAUSED && pnode->loaded &&
1448 pnode->phase_split) {
7d55524d
ORL
1449 /* Ok to unload execute code as long as node
1450 * is not * running */
1451 status1 =
1452 hnode_mgr->nldr_fxns.
09f13304 1453 unload(pnode->nldr_node_obj,
7d55524d 1454 NLDR_EXECUTE);
0624f52f
ER
1455 pnode->loaded = false;
1456 NODE_SET_STATE(pnode, NODE_DONE);
7d55524d
ORL
1457 }
1458 /* Load delete phase code if not loaded or if haven't
1459 * * unloaded EXECUTE phase */
0624f52f
ER
1460 if ((!(pnode->loaded) || (state == NODE_RUNNING)) &&
1461 pnode->phase_split) {
7d55524d
ORL
1462 status =
1463 hnode_mgr->nldr_fxns.
09f13304 1464 load(pnode->nldr_node_obj, NLDR_DELETE);
a741ea6e 1465 if (!status)
0624f52f 1466 pnode->loaded = true;
7d55524d
ORL
1467 else
1468 pr_err("%s: fail - load delete code:"
1469 " 0x%x\n", __func__, status);
1470 }
1471 }
1472func_cont1:
a741ea6e 1473 if (!status) {
7d55524d 1474 /* Unblock a thread trying to terminate the node */
0624f52f 1475 (void)sync_set_event(pnode->sync_done);
7d55524d
ORL
1476 if (proc_id == DSP_UNIT) {
1477 /* ul_delete_fxn = address of node's delete
1478 * function */
0624f52f 1479 status = get_fxn_address(pnode, &ul_delete_fxn,
7d55524d
ORL
1480 DELETEPHASE);
1481 } else if (proc_id == IVA_UNIT)
0624f52f 1482 ul_delete_fxn = (u32) pnode->node_env;
a741ea6e 1483 if (!status) {
7d55524d
ORL
1484 status = proc_get_state(hprocessor,
1485 &proc_state,
1486 sizeof(struct
1487 dsp_processorstate));
1488 if (proc_state.proc_state != PROC_ERROR) {
1489 status =
0624f52f 1490 disp_node_delete(disp_obj, pnode,
7d55524d 1491 hnode_mgr->
dab7f7fe 1492 fxn_addrs
7d55524d
ORL
1493 [RMSDELETENODE],
1494 ul_delete_fxn,
0624f52f 1495 pnode->node_env);
7d55524d 1496 } else
0624f52f 1497 NODE_SET_STATE(pnode, NODE_DONE);
7d55524d
ORL
1498
1499 /* Unload execute, if not unloaded, and delete
1500 * function */
1501 if (state == NODE_RUNNING &&
0624f52f 1502 pnode->phase_split) {
7d55524d
ORL
1503 status1 =
1504 hnode_mgr->nldr_fxns.
09f13304 1505 unload(pnode->nldr_node_obj,
7d55524d
ORL
1506 NLDR_EXECUTE);
1507 }
b66e0986 1508 if (status1)
7d55524d
ORL
1509 pr_err("%s: fail - unload execute code:"
1510 " 0x%x\n", __func__, status1);
1511
1512 status1 =
09f13304 1513 hnode_mgr->nldr_fxns.unload(pnode->
7d55524d
ORL
1514 nldr_node_obj,
1515 NLDR_DELETE);
0624f52f 1516 pnode->loaded = false;
b66e0986 1517 if (status1)
7d55524d
ORL
1518 pr_err("%s: fail - unload delete code: "
1519 "0x%x\n", __func__, status1);
1520 }
1521 }
1522 }
1523 /* Free host side resources even if a failure occurred */
1524 /* Remove node from hnode_mgr->node_list */
0005391f 1525 list_del(&pnode->list_elem);
7d55524d
ORL
1526 hnode_mgr->num_nodes--;
1527 /* Decrement count of nodes created on DSP */
1528 if ((state != NODE_ALLOCATED) || ((state == NODE_ALLOCATED) &&
0624f52f 1529 (pnode->node_env != (u32) NULL)))
7d55524d
ORL
1530 hnode_mgr->num_created--;
1531 /* Free host-side resources allocated by node_create()
1532 * delete_node() fails if SM buffers not freed by client! */
0624f52f
ER
1533 drv_proc_node_update_status(node_res, false);
1534 delete_node(pnode, pr_ctxt);
1535
1536 /*
1537 * Release all Node resources and its context
1538 */
1539 idr_remove(pr_ctxt->node_id, ((struct node_res_object *)node_res)->id);
1540 kfree(node_res);
7d55524d 1541
7d55524d
ORL
1542 /* Exit critical section */
1543 mutex_unlock(&hnode_mgr->node_mgr_lock);
1544 proc_notify_clients(hprocessor, DSP_NODESTATECHANGE);
1545func_end:
0624f52f 1546 dev_dbg(bridge, "%s: pnode: %p status 0x%x\n", __func__, pnode, status);
7d55524d
ORL
1547 return status;
1548}
1549
1550/*
1551 * ======== node_delete_mgr ========
1552 * Purpose:
1553 * Delete the NODE Manager.
1554 */
1555int node_delete_mgr(struct node_mgr *hnode_mgr)
1556{
7d55524d
ORL
1557 DBC_REQUIRE(refs > 0);
1558
57104f0f
IN
1559 if (!hnode_mgr)
1560 return -EFAULT;
7d55524d 1561
57104f0f
IN
1562 delete_node_mgr(hnode_mgr);
1563
1564 return 0;
7d55524d
ORL
1565}
1566
1567/*
1568 * ======== node_enum_nodes ========
1569 * Purpose:
1570 * Enumerate currently allocated nodes.
1571 */
1572int node_enum_nodes(struct node_mgr *hnode_mgr, void **node_tab,
e6bf74f0
MN
1573 u32 node_tab_size, u32 *pu_num_nodes,
1574 u32 *pu_allocated)
7d55524d
ORL
1575{
1576 struct node_object *hnode;
0005391f 1577 u32 i = 0;
7d55524d
ORL
1578 int status = 0;
1579 DBC_REQUIRE(refs > 0);
1580 DBC_REQUIRE(node_tab != NULL || node_tab_size == 0);
1581 DBC_REQUIRE(pu_num_nodes != NULL);
1582 DBC_REQUIRE(pu_allocated != NULL);
1583
1584 if (!hnode_mgr) {
1585 status = -EFAULT;
1586 goto func_end;
1587 }
1588 /* Enter critical section */
1589 mutex_lock(&hnode_mgr->node_mgr_lock);
1590
1591 if (hnode_mgr->num_nodes > node_tab_size) {
1592 *pu_allocated = hnode_mgr->num_nodes;
1593 *pu_num_nodes = 0;
1594 status = -EINVAL;
1595 } else {
0005391f
IN
1596 list_for_each_entry(hnode, &hnode_mgr->node_list, list_elem)
1597 node_tab[i++] = hnode;
7d55524d
ORL
1598 *pu_allocated = *pu_num_nodes = hnode_mgr->num_nodes;
1599 }
1600 /* end of sync_enter_cs */
1601 /* Exit critical section */
1602 mutex_unlock(&hnode_mgr->node_mgr_lock);
1603func_end:
1604 return status;
1605}
1606
1607/*
1608 * ======== node_exit ========
1609 * Purpose:
1610 * Discontinue usage of NODE module.
1611 */
1612void node_exit(void)
1613{
1614 DBC_REQUIRE(refs > 0);
1615
1616 refs--;
1617
1618 DBC_ENSURE(refs >= 0);
1619}
1620
1621/*
1622 * ======== node_free_msg_buf ========
1623 * Purpose:
1624 * Frees the message buffer.
1625 */
9d7d0a52 1626int node_free_msg_buf(struct node_object *hnode, u8 * pbuffer,
21aaf42e 1627 struct dsp_bufferattr *pattr)
7d55524d
ORL
1628{
1629 struct node_object *pnode = (struct node_object *)hnode;
1630 int status = 0;
1631 u32 proc_id;
1632 DBC_REQUIRE(refs > 0);
1633 DBC_REQUIRE(pbuffer != NULL);
1634 DBC_REQUIRE(pnode != NULL);
1635 DBC_REQUIRE(pnode->xlator != NULL);
1636
1637 if (!hnode) {
1638 status = -EFAULT;
1639 goto func_end;
1640 }
a534f17b 1641 status = proc_get_processor_id(pnode->processor, &proc_id);
7d55524d 1642 if (proc_id == DSP_UNIT) {
a741ea6e 1643 if (!status) {
7d55524d
ORL
1644 if (pattr == NULL) {
1645 /* set defaults */
1646 pattr = &node_dfltbufattrs;
1647 }
1648 /* Node supports single SM segment only */
1649 if (pattr->segment_id != 1)
1650 status = -EBADR;
1651
1652 /* pbuffer is clients Va. */
1653 status = cmm_xlator_free_buf(pnode->xlator, pbuffer);
1654 }
1655 } else {
1656 DBC_ASSERT(NULL); /* BUG */
1657 }
1658func_end:
1659 return status;
1660}
1661
1662/*
1663 * ======== node_get_attr ========
1664 * Purpose:
1665 * Copy the current attributes of the specified node into a dsp_nodeattr
1666 * structure.
1667 */
1668int node_get_attr(struct node_object *hnode,
e6bf74f0 1669 struct dsp_nodeattr *pattr, u32 attr_size)
7d55524d
ORL
1670{
1671 struct node_mgr *hnode_mgr;
7d55524d
ORL
1672 DBC_REQUIRE(refs > 0);
1673 DBC_REQUIRE(pattr != NULL);
1674 DBC_REQUIRE(attr_size >= sizeof(struct dsp_nodeattr));
1675
57104f0f
IN
1676 if (!hnode)
1677 return -EFAULT;
1678
085467b8 1679 hnode_mgr = hnode->node_mgr;
57104f0f
IN
1680 /* Enter hnode_mgr critical section (since we're accessing
1681 * data that could be changed by node_change_priority() and
1682 * node_connect(). */
1683 mutex_lock(&hnode_mgr->node_mgr_lock);
1684 pattr->cb_struct = sizeof(struct dsp_nodeattr);
1685 /* dsp_nodeattrin */
1686 pattr->in_node_attr_in.cb_struct =
1687 sizeof(struct dsp_nodeattrin);
1688 pattr->in_node_attr_in.prio = hnode->prio;
a534f17b 1689 pattr->in_node_attr_in.timeout = hnode->timeout;
57104f0f
IN
1690 pattr->in_node_attr_in.heap_size =
1691 hnode->create_args.asa.task_arg_obj.heap_size;
1692 pattr->in_node_attr_in.pgpp_virt_addr = (void *)
a534f17b 1693 hnode->create_args.asa.task_arg_obj.gpp_heap_addr;
57104f0f
IN
1694 pattr->node_attr_inputs = hnode->num_gpp_inputs;
1695 pattr->node_attr_outputs = hnode->num_gpp_outputs;
1696 /* dsp_nodeinfo */
1697 get_node_info(hnode, &(pattr->node_info));
1698 /* end of sync_enter_cs */
1699 /* Exit critical section */
1700 mutex_unlock(&hnode_mgr->node_mgr_lock);
1701
1702 return 0;
7d55524d
ORL
1703}
1704
1705/*
1706 * ======== node_get_channel_id ========
1707 * Purpose:
1708 * Get the channel index reserved for a stream connection between the
1709 * host and a node.
1710 */
1711int node_get_channel_id(struct node_object *hnode, u32 dir, u32 index,
e6bf74f0 1712 u32 *chan_id)
7d55524d
ORL
1713{
1714 enum node_type node_type;
1715 int status = -EINVAL;
1716 DBC_REQUIRE(refs > 0);
1717 DBC_REQUIRE(dir == DSP_TONODE || dir == DSP_FROMNODE);
318b5df9 1718 DBC_REQUIRE(chan_id != NULL);
7d55524d
ORL
1719
1720 if (!hnode) {
1721 status = -EFAULT;
1722 return status;
1723 }
1724 node_type = node_get_type(hnode);
1725 if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET) {
1726 status = -EPERM;
1727 return status;
1728 }
1729 if (dir == DSP_TONODE) {
1730 if (index < MAX_INPUTS(hnode)) {
1731 if (hnode->inputs[index].type == HOSTCONNECT) {
318b5df9 1732 *chan_id = hnode->inputs[index].dev_id;
7d55524d
ORL
1733 status = 0;
1734 }
1735 }
1736 } else {
1737 DBC_ASSERT(dir == DSP_FROMNODE);
1738 if (index < MAX_OUTPUTS(hnode)) {
1739 if (hnode->outputs[index].type == HOSTCONNECT) {
318b5df9 1740 *chan_id = hnode->outputs[index].dev_id;
7d55524d
ORL
1741 status = 0;
1742 }
1743 }
1744 }
1745 return status;
1746}
1747
1748/*
1749 * ======== node_get_message ========
1750 * Purpose:
1751 * Retrieve a message from a node on the DSP.
1752 */
1753int node_get_message(struct node_object *hnode,
e6bf74f0 1754 struct dsp_msg *message, u32 utimeout)
7d55524d
ORL
1755{
1756 struct node_mgr *hnode_mgr;
1757 enum node_type node_type;
1758 struct bridge_drv_interface *intf_fxns;
1759 int status = 0;
1760 void *tmp_buf;
1761 struct dsp_processorstate proc_state;
1762 struct proc_object *hprocessor;
1763
1764 DBC_REQUIRE(refs > 0);
c8c1ad8c 1765 DBC_REQUIRE(message != NULL);
7d55524d
ORL
1766
1767 if (!hnode) {
1768 status = -EFAULT;
1769 goto func_end;
1770 }
a534f17b 1771 hprocessor = hnode->processor;
7d55524d
ORL
1772 status = proc_get_state(hprocessor, &proc_state,
1773 sizeof(struct dsp_processorstate));
b66e0986 1774 if (status)
7d55524d
ORL
1775 goto func_end;
1776 /* If processor is in error state then don't attempt to get the
1777 message */
1778 if (proc_state.proc_state == PROC_ERROR) {
1779 status = -EPERM;
1780 goto func_end;
1781 }
085467b8 1782 hnode_mgr = hnode->node_mgr;
7d55524d
ORL
1783 node_type = node_get_type(hnode);
1784 if (node_type != NODE_MESSAGE && node_type != NODE_TASK &&
1785 node_type != NODE_DAISSOCKET) {
1786 status = -EPERM;
1787 goto func_end;
1788 }
1789 /* This function will block unless a message is available. Since
1790 * DSPNode_RegisterNotify() allows notification when a message
1791 * is available, the system can be designed so that
1792 * DSPNode_GetMessage() is only called when a message is
1793 * available. */
1794 intf_fxns = hnode_mgr->intf_fxns;
1795 status =
09f13304 1796 (*intf_fxns->msg_get) (hnode->msg_queue_obj, message, utimeout);
7d55524d 1797 /* Check if message contains SM descriptor */
b4da7fc3 1798 if (status || !(message->cmd & DSP_RMSBUFDESC))
7d55524d
ORL
1799 goto func_end;
1800
1801 /* Translate DSP byte addr to GPP Va. */
1802 tmp_buf = cmm_xlator_translate(hnode->xlator,
b4da7fc3 1803 (void *)(message->arg1 *
085467b8 1804 hnode->node_mgr->
a534f17b 1805 dsp_word_size), CMM_DSPPA2PA);
7d55524d
ORL
1806 if (tmp_buf != NULL) {
1807 /* now convert this GPP Pa to Va */
1808 tmp_buf = cmm_xlator_translate(hnode->xlator, tmp_buf,
1809 CMM_PA2VA);
1810 if (tmp_buf != NULL) {
1811 /* Adjust SM size in msg */
b4da7fc3 1812 message->arg1 = (u32) tmp_buf;
a534f17b 1813 message->arg2 *= hnode->node_mgr->dsp_word_size;
7d55524d
ORL
1814 } else {
1815 status = -ESRCH;
1816 }
1817 } else {
1818 status = -ESRCH;
1819 }
1820func_end:
c8c1ad8c
RS
1821 dev_dbg(bridge, "%s: hnode: %p message: %p utimeout: 0x%x\n", __func__,
1822 hnode, message, utimeout);
7d55524d
ORL
1823 return status;
1824}
1825
1826/*
1827 * ======== node_get_nldr_obj ========
1828 */
1829int node_get_nldr_obj(struct node_mgr *hnode_mgr,
daa89e6c 1830 struct nldr_object **nldr_ovlyobj)
7d55524d
ORL
1831{
1832 int status = 0;
1833 struct node_mgr *node_mgr_obj = hnode_mgr;
daa89e6c 1834 DBC_REQUIRE(nldr_ovlyobj != NULL);
7d55524d
ORL
1835
1836 if (!hnode_mgr)
1837 status = -EFAULT;
1838 else
daa89e6c 1839 *nldr_ovlyobj = node_mgr_obj->nldr_obj;
7d55524d 1840
a741ea6e 1841 DBC_ENSURE(!status || (nldr_ovlyobj != NULL && *nldr_ovlyobj == NULL));
7d55524d
ORL
1842 return status;
1843}
1844
1845/*
1846 * ======== node_get_strm_mgr ========
1847 * Purpose:
1848 * Returns the Stream manager.
1849 */
1850int node_get_strm_mgr(struct node_object *hnode,
daa89e6c 1851 struct strm_mgr **strm_man)
7d55524d
ORL
1852{
1853 int status = 0;
1854
1855 DBC_REQUIRE(refs > 0);
1856
1857 if (!hnode)
1858 status = -EFAULT;
1859 else
085467b8 1860 *strm_man = hnode->node_mgr->strm_mgr_obj;
7d55524d
ORL
1861
1862 return status;
1863}
1864
1865/*
1866 * ======== node_get_load_type ========
1867 */
1868enum nldr_loadtype node_get_load_type(struct node_object *hnode)
1869{
1870 DBC_REQUIRE(refs > 0);
1871 DBC_REQUIRE(hnode);
1872 if (!hnode) {
1873 dev_dbg(bridge, "%s: Failed. hnode: %p\n", __func__, hnode);
1874 return -1;
1875 } else {
a534f17b 1876 return hnode->dcd_props.obj_data.node_obj.load_type;
7d55524d
ORL
1877 }
1878}
1879
1880/*
1881 * ======== node_get_timeout ========
1882 * Purpose:
1883 * Returns the timeout value for this node.
1884 */
1885u32 node_get_timeout(struct node_object *hnode)
1886{
1887 DBC_REQUIRE(refs > 0);
1888 DBC_REQUIRE(hnode);
1889 if (!hnode) {
1890 dev_dbg(bridge, "%s: failed. hnode: %p\n", __func__, hnode);
1891 return 0;
1892 } else {
a534f17b 1893 return hnode->timeout;
7d55524d
ORL
1894 }
1895}
1896
1897/*
1898 * ======== node_get_type ========
1899 * Purpose:
1900 * Returns the node type.
1901 */
1902enum node_type node_get_type(struct node_object *hnode)
1903{
1904 enum node_type node_type;
1905
1906 if (hnode == (struct node_object *)DSP_HGPPNODE)
1907 node_type = NODE_GPP;
1908 else {
1909 if (!hnode)
1910 node_type = -1;
1911 else
1912 node_type = hnode->ntype;
1913 }
1914 return node_type;
1915}
1916
1917/*
1918 * ======== node_init ========
1919 * Purpose:
1920 * Initialize the NODE module.
1921 */
1922bool node_init(void)
1923{
1924 DBC_REQUIRE(refs >= 0);
1925
1926 refs++;
1927
1928 return true;
1929}
1930
1931/*
1932 * ======== node_on_exit ========
1933 * Purpose:
1934 * Gets called when RMS_EXIT is received for a node.
1935 */
95870a88 1936void node_on_exit(struct node_object *hnode, s32 node_status)
7d55524d
ORL
1937{
1938 if (!hnode)
1939 return;
1940
1941 /* Set node state to done */
1942 NODE_SET_STATE(hnode, NODE_DONE);
95870a88 1943 hnode->exit_status = node_status;
7d55524d 1944 if (hnode->loaded && hnode->phase_split) {
085467b8 1945 (void)hnode->node_mgr->nldr_fxns.unload(hnode->
7d55524d
ORL
1946 nldr_node_obj,
1947 NLDR_EXECUTE);
1948 hnode->loaded = false;
1949 }
1950 /* Unblock call to node_terminate */
1951 (void)sync_set_event(hnode->sync_done);
1952 /* Notify clients */
a534f17b 1953 proc_notify_clients(hnode->processor, DSP_NODESTATECHANGE);
7d55524d
ORL
1954 ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
1955}
1956
1957/*
1958 * ======== node_pause ========
1959 * Purpose:
1960 * Suspend execution of a node currently running on the DSP.
1961 */
1962int node_pause(struct node_object *hnode)
1963{
1964 struct node_object *pnode = (struct node_object *)hnode;
1965 enum node_type node_type;
1966 enum node_state state;
1967 struct node_mgr *hnode_mgr;
1968 int status = 0;
1969 u32 proc_id;
1970 struct dsp_processorstate proc_state;
1971 struct proc_object *hprocessor;
1972
1973 DBC_REQUIRE(refs > 0);
1974
1975 if (!hnode) {
1976 status = -EFAULT;
1977 } else {
1978 node_type = node_get_type(hnode);
1979 if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET)
1980 status = -EPERM;
1981 }
b66e0986 1982 if (status)
7d55524d
ORL
1983 goto func_end;
1984
a534f17b 1985 status = proc_get_processor_id(pnode->processor, &proc_id);
7d55524d
ORL
1986
1987 if (proc_id == IVA_UNIT)
1988 status = -ENOSYS;
1989
a741ea6e 1990 if (!status) {
085467b8 1991 hnode_mgr = hnode->node_mgr;
7d55524d
ORL
1992
1993 /* Enter critical section */
1994 mutex_lock(&hnode_mgr->node_mgr_lock);
1995 state = node_get_state(hnode);
1996 /* Check node state */
1997 if (state != NODE_RUNNING)
1998 status = -EBADR;
1999
b66e0986 2000 if (status)
7d55524d 2001 goto func_cont;
a534f17b 2002 hprocessor = hnode->processor;
7d55524d
ORL
2003 status = proc_get_state(hprocessor, &proc_state,
2004 sizeof(struct dsp_processorstate));
b66e0986 2005 if (status)
7d55524d
ORL
2006 goto func_cont;
2007 /* If processor is in error state then don't attempt
2008 to send the message */
2009 if (proc_state.proc_state == PROC_ERROR) {
2010 status = -EPERM;
2011 goto func_cont;
2012 }
2013
2014 status = disp_node_change_priority(hnode_mgr->disp_obj, hnode,
dab7f7fe 2015 hnode_mgr->fxn_addrs[RMSCHANGENODEPRIORITY],
7d55524d
ORL
2016 hnode->node_env, NODE_SUSPENDEDPRI);
2017
2018 /* Update state */
a741ea6e 2019 if (status >= 0)
7d55524d
ORL
2020 NODE_SET_STATE(hnode, NODE_PAUSED);
2021
2022func_cont:
2023 /* End of sync_enter_cs */
2024 /* Leave critical section */
2025 mutex_unlock(&hnode_mgr->node_mgr_lock);
a741ea6e 2026 if (status >= 0) {
a534f17b 2027 proc_notify_clients(hnode->processor,
7d55524d
ORL
2028 DSP_NODESTATECHANGE);
2029 ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
2030 }
2031 }
2032func_end:
2033 dev_dbg(bridge, "%s: hnode: %p status 0x%x\n", __func__, hnode, status);
2034 return status;
2035}
2036
2037/*
2038 * ======== node_put_message ========
2039 * Purpose:
2040 * Send a message to a message node, task node, or XDAIS socket node. This
2041 * function will block until the message stream can accommodate the
2042 * message, or a timeout occurs.
2043 */
2044int node_put_message(struct node_object *hnode,
9d7d0a52 2045 const struct dsp_msg *pmsg, u32 utimeout)
7d55524d
ORL
2046{
2047 struct node_mgr *hnode_mgr = NULL;
2048 enum node_type node_type;
2049 struct bridge_drv_interface *intf_fxns;
2050 enum node_state state;
2051 int status = 0;
2052 void *tmp_buf;
2053 struct dsp_msg new_msg;
2054 struct dsp_processorstate proc_state;
2055 struct proc_object *hprocessor;
2056
2057 DBC_REQUIRE(refs > 0);
2058 DBC_REQUIRE(pmsg != NULL);
2059
2060 if (!hnode) {
2061 status = -EFAULT;
2062 goto func_end;
2063 }
a534f17b 2064 hprocessor = hnode->processor;
7d55524d
ORL
2065 status = proc_get_state(hprocessor, &proc_state,
2066 sizeof(struct dsp_processorstate));
b66e0986 2067 if (status)
7d55524d
ORL
2068 goto func_end;
2069 /* If processor is in bad state then don't attempt sending the
2070 message */
2071 if (proc_state.proc_state == PROC_ERROR) {
2072 status = -EPERM;
2073 goto func_end;
2074 }
085467b8 2075 hnode_mgr = hnode->node_mgr;
7d55524d
ORL
2076 node_type = node_get_type(hnode);
2077 if (node_type != NODE_MESSAGE && node_type != NODE_TASK &&
2078 node_type != NODE_DAISSOCKET)
2079 status = -EPERM;
2080
a741ea6e 2081 if (!status) {
7d55524d
ORL
2082 /* Check node state. Can't send messages to a node after
2083 * we've sent the RMS_EXIT command. There is still the
2084 * possibility that node_terminate can be called after we've
2085 * checked the state. Could add another SYNC object to
2086 * prevent this (can't use node_mgr_lock, since we don't
2087 * want to block other NODE functions). However, the node may
2088 * still exit on its own, before this message is sent. */
2089 mutex_lock(&hnode_mgr->node_mgr_lock);
2090 state = node_get_state(hnode);
2091 if (state == NODE_TERMINATING || state == NODE_DONE)
2092 status = -EBADR;
2093
2094 /* end of sync_enter_cs */
2095 mutex_unlock(&hnode_mgr->node_mgr_lock);
2096 }
b66e0986 2097 if (status)
7d55524d
ORL
2098 goto func_end;
2099
2100 /* assign pmsg values to new msg */
2101 new_msg = *pmsg;
2102 /* Now, check if message contains a SM buffer descriptor */
b4da7fc3 2103 if (pmsg->cmd & DSP_RMSBUFDESC) {
7d55524d
ORL
2104 /* Translate GPP Va to DSP physical buf Ptr. */
2105 tmp_buf = cmm_xlator_translate(hnode->xlator,
b4da7fc3 2106 (void *)new_msg.arg1,
7d55524d
ORL
2107 CMM_VA2DSPPA);
2108 if (tmp_buf != NULL) {
2109 /* got translation, convert to MAUs in msg */
a534f17b 2110 if (hnode->node_mgr->dsp_word_size != 0) {
b4da7fc3 2111 new_msg.arg1 =
7d55524d 2112 (u32) tmp_buf /
a534f17b 2113 hnode->node_mgr->dsp_word_size;
7d55524d 2114 /* MAUs */
085467b8 2115 new_msg.arg2 /= hnode->node_mgr->
a534f17b 2116 dsp_word_size;
7d55524d 2117 } else {
a534f17b 2118 pr_err("%s: dsp_word_size is zero!\n",
7d55524d
ORL
2119 __func__);
2120 status = -EPERM; /* bad DSPWordSize */
2121 }
2122 } else { /* failed to translate buffer address */
2123 status = -ESRCH;
2124 }
2125 }
a741ea6e 2126 if (!status) {
7d55524d 2127 intf_fxns = hnode_mgr->intf_fxns;
09f13304 2128 status = (*intf_fxns->msg_put) (hnode->msg_queue_obj,
7d55524d
ORL
2129 &new_msg, utimeout);
2130 }
2131func_end:
2132 dev_dbg(bridge, "%s: hnode: %p pmsg: %p utimeout: 0x%x, "
2133 "status 0x%x\n", __func__, hnode, pmsg, utimeout, status);
2134 return status;
2135}
2136
2137/*
2138 * ======== node_register_notify ========
2139 * Purpose:
2140 * Register to be notified on specific events for this node.
2141 */
2142int node_register_notify(struct node_object *hnode, u32 event_mask,
2143 u32 notify_type,
2144 struct dsp_notification *hnotification)
2145{
2146 struct bridge_drv_interface *intf_fxns;
2147 int status = 0;
2148
2149 DBC_REQUIRE(refs > 0);
2150 DBC_REQUIRE(hnotification != NULL);
2151
2152 if (!hnode) {
2153 status = -EFAULT;
2154 } else {
2155 /* Check if event mask is a valid node related event */
2156 if (event_mask & ~(DSP_NODESTATECHANGE | DSP_NODEMESSAGEREADY))
2157 status = -EINVAL;
2158
2159 /* Check if notify type is valid */
2160 if (notify_type != DSP_SIGNALEVENT)
2161 status = -EINVAL;
2162
2163 /* Only one Notification can be registered at a
2164 * time - Limitation */
2165 if (event_mask == (DSP_NODESTATECHANGE | DSP_NODEMESSAGEREADY))
2166 status = -EINVAL;
2167 }
a741ea6e 2168 if (!status) {
7d55524d
ORL
2169 if (event_mask == DSP_NODESTATECHANGE) {
2170 status = ntfy_register(hnode->ntfy_obj, hnotification,
2171 event_mask & DSP_NODESTATECHANGE,
2172 notify_type);
2173 } else {
2174 /* Send Message part of event mask to msg_ctrl */
085467b8 2175 intf_fxns = hnode->node_mgr->intf_fxns;
09f13304 2176 status = (*intf_fxns->msg_register_notify)
7d55524d
ORL
2177 (hnode->msg_queue_obj,
2178 event_mask & DSP_NODEMESSAGEREADY, notify_type,
2179 hnotification);
2180 }
2181
2182 }
2183 dev_dbg(bridge, "%s: hnode: %p event_mask: 0x%x notify_type: 0x%x "
2184 "hnotification: %p status 0x%x\n", __func__, hnode,
2185 event_mask, notify_type, hnotification, status);
2186 return status;
2187}
2188
2189/*
2190 * ======== node_run ========
2191 * Purpose:
2192 * Start execution of a node's execute phase, or resume execution of a node
2193 * that has been suspended (via NODE_NodePause()) on the DSP. Load the
2194 * node's execute function if necessary.
2195 */
2196int node_run(struct node_object *hnode)
2197{
2198 struct node_object *pnode = (struct node_object *)hnode;
2199 struct node_mgr *hnode_mgr;
2200 enum node_type node_type;
2201 enum node_state state;
2202 u32 ul_execute_fxn;
2203 u32 ul_fxn_addr;
2204 int status = 0;
2205 u32 proc_id;
2206 struct bridge_drv_interface *intf_fxns;
2207 struct dsp_processorstate proc_state;
2208 struct proc_object *hprocessor;
2209
2210 DBC_REQUIRE(refs > 0);
2211
2212 if (!hnode) {
2213 status = -EFAULT;
2214 goto func_end;
2215 }
a534f17b 2216 hprocessor = hnode->processor;
7d55524d
ORL
2217 status = proc_get_state(hprocessor, &proc_state,
2218 sizeof(struct dsp_processorstate));
b66e0986 2219 if (status)
7d55524d
ORL
2220 goto func_end;
2221 /* If processor is in error state then don't attempt to run the node */
2222 if (proc_state.proc_state == PROC_ERROR) {
2223 status = -EPERM;
2224 goto func_end;
2225 }
2226 node_type = node_get_type(hnode);
2227 if (node_type == NODE_DEVICE)
2228 status = -EPERM;
b66e0986 2229 if (status)
7d55524d
ORL
2230 goto func_end;
2231
085467b8 2232 hnode_mgr = hnode->node_mgr;
7d55524d
ORL
2233 if (!hnode_mgr) {
2234 status = -EFAULT;
2235 goto func_end;
2236 }
2237 intf_fxns = hnode_mgr->intf_fxns;
2238 /* Enter critical section */
2239 mutex_lock(&hnode_mgr->node_mgr_lock);
2240
2241 state = node_get_state(hnode);
2242 if (state != NODE_CREATED && state != NODE_PAUSED)
2243 status = -EBADR;
2244
a741ea6e 2245 if (!status)
a534f17b 2246 status = proc_get_processor_id(pnode->processor, &proc_id);
7d55524d 2247
b66e0986 2248 if (status)
7d55524d
ORL
2249 goto func_cont1;
2250
2251 if ((proc_id != DSP_UNIT) && (proc_id != IVA_UNIT))
2252 goto func_cont1;
2253
2254 if (state == NODE_CREATED) {
2255 /* If node's execute function is not loaded, load it */
2256 if (!(hnode->loaded) && hnode->phase_split) {
2257 status =
09f13304 2258 hnode_mgr->nldr_fxns.load(hnode->nldr_node_obj,
7d55524d 2259 NLDR_EXECUTE);
a741ea6e 2260 if (!status) {
7d55524d
ORL
2261 hnode->loaded = true;
2262 } else {
2263 pr_err("%s: fail - load execute code: 0x%x\n",
2264 __func__, status);
2265 }
2266 }
a741ea6e 2267 if (!status) {
7d55524d
ORL
2268 /* Get address of node's execute function */
2269 if (proc_id == IVA_UNIT)
2270 ul_execute_fxn = (u32) hnode->node_env;
2271 else {
2272 status = get_fxn_address(hnode, &ul_execute_fxn,
2273 EXECUTEPHASE);
2274 }
2275 }
a741ea6e 2276 if (!status) {
dab7f7fe 2277 ul_fxn_addr = hnode_mgr->fxn_addrs[RMSEXECUTENODE];
7d55524d
ORL
2278 status =
2279 disp_node_run(hnode_mgr->disp_obj, hnode,
2280 ul_fxn_addr, ul_execute_fxn,
2281 hnode->node_env);
2282 }
2283 } else if (state == NODE_PAUSED) {
dab7f7fe 2284 ul_fxn_addr = hnode_mgr->fxn_addrs[RMSCHANGENODEPRIORITY];
7d55524d
ORL
2285 status = disp_node_change_priority(hnode_mgr->disp_obj, hnode,
2286 ul_fxn_addr, hnode->node_env,
2287 NODE_GET_PRIORITY(hnode));
2288 } else {
2289 /* We should never get here */
2290 DBC_ASSERT(false);
2291 }
2292func_cont1:
2293 /* Update node state. */
a741ea6e 2294 if (status >= 0)
7d55524d
ORL
2295 NODE_SET_STATE(hnode, NODE_RUNNING);
2296 else /* Set state back to previous value */
2297 NODE_SET_STATE(hnode, state);
2298 /*End of sync_enter_cs */
2299 /* Exit critical section */
2300 mutex_unlock(&hnode_mgr->node_mgr_lock);
a741ea6e 2301 if (status >= 0) {
a534f17b 2302 proc_notify_clients(hnode->processor, DSP_NODESTATECHANGE);
7d55524d
ORL
2303 ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
2304 }
2305func_end:
2306 dev_dbg(bridge, "%s: hnode: %p status 0x%x\n", __func__, hnode, status);
2307 return status;
2308}
2309
2310/*
2311 * ======== node_terminate ========
2312 * Purpose:
2313 * Signal a node running on the DSP that it should exit its execute phase
2314 * function.
2315 */
e6bf74f0 2316int node_terminate(struct node_object *hnode, int *pstatus)
7d55524d
ORL
2317{
2318 struct node_object *pnode = (struct node_object *)hnode;
2319 struct node_mgr *hnode_mgr = NULL;
2320 enum node_type node_type;
2321 struct bridge_drv_interface *intf_fxns;
2322 enum node_state state;
2323 struct dsp_msg msg, killmsg;
2324 int status = 0;
2325 u32 proc_id, kill_time_out;
2326 struct deh_mgr *hdeh_mgr;
2327 struct dsp_processorstate proc_state;
2328
2329 DBC_REQUIRE(refs > 0);
2330 DBC_REQUIRE(pstatus != NULL);
2331
085467b8 2332 if (!hnode || !hnode->node_mgr) {
7d55524d
ORL
2333 status = -EFAULT;
2334 goto func_end;
2335 }
a534f17b 2336 if (pnode->processor == NULL) {
7d55524d
ORL
2337 status = -EFAULT;
2338 goto func_end;
2339 }
a534f17b 2340 status = proc_get_processor_id(pnode->processor, &proc_id);
7d55524d 2341
a741ea6e 2342 if (!status) {
085467b8 2343 hnode_mgr = hnode->node_mgr;
7d55524d
ORL
2344 node_type = node_get_type(hnode);
2345 if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET)
2346 status = -EPERM;
2347 }
a741ea6e 2348 if (!status) {
7d55524d
ORL
2349 /* Check node state */
2350 mutex_lock(&hnode_mgr->node_mgr_lock);
2351 state = node_get_state(hnode);
2352 if (state != NODE_RUNNING) {
2353 status = -EBADR;
2354 /* Set the exit status if node terminated on
2355 * its own. */
2356 if (state == NODE_DONE)
2357 *pstatus = hnode->exit_status;
2358
2359 } else {
2360 NODE_SET_STATE(hnode, NODE_TERMINATING);
2361 }
2362 /* end of sync_enter_cs */
2363 mutex_unlock(&hnode_mgr->node_mgr_lock);
2364 }
a741ea6e 2365 if (!status) {
7d55524d
ORL
2366 /*
2367 * Send exit message. Do not change state to NODE_DONE
2368 * here. That will be done in callback.
2369 */
a534f17b 2370 status = proc_get_state(pnode->processor, &proc_state,
7d55524d 2371 sizeof(struct dsp_processorstate));
b66e0986 2372 if (status)
7d55524d
ORL
2373 goto func_cont;
2374 /* If processor is in error state then don't attempt to send
2375 * A kill task command */
2376 if (proc_state.proc_state == PROC_ERROR) {
2377 status = -EPERM;
2378 goto func_cont;
2379 }
2380
b4da7fc3
RS
2381 msg.cmd = RMS_EXIT;
2382 msg.arg1 = hnode->node_env;
2383 killmsg.cmd = RMS_KILLTASK;
2384 killmsg.arg1 = hnode->node_env;
7d55524d
ORL
2385 intf_fxns = hnode_mgr->intf_fxns;
2386
a534f17b 2387 if (hnode->timeout > MAXTIMEOUT)
7d55524d
ORL
2388 kill_time_out = MAXTIMEOUT;
2389 else
a534f17b 2390 kill_time_out = (hnode->timeout) * 2;
7d55524d 2391
09f13304 2392 status = (*intf_fxns->msg_put) (hnode->msg_queue_obj, &msg,
a534f17b 2393 hnode->timeout);
b66e0986 2394 if (status)
7d55524d
ORL
2395 goto func_cont;
2396
2397 /*
2398 * Wait on synchronization object that will be
2399 * posted in the callback on receiving RMS_EXIT
2400 * message, or by node_delete. Check for valid hnode,
2401 * in case posted by node_delete().
2402 */
2403 status = sync_wait_on_event(hnode->sync_done,
2404 kill_time_out / 2);
2405 if (status != ETIME)
2406 goto func_cont;
2407
09f13304 2408 status = (*intf_fxns->msg_put)(hnode->msg_queue_obj,
a534f17b 2409 &killmsg, hnode->timeout);
b66e0986 2410 if (status)
7d55524d
ORL
2411 goto func_cont;
2412 status = sync_wait_on_event(hnode->sync_done,
2413 kill_time_out / 2);
b66e0986 2414 if (status) {
7d55524d
ORL
2415 /*
2416 * Here it goes the part of the simulation of
2417 * the DSP exception.
2418 */
085467b8 2419 dev_get_deh_mgr(hnode_mgr->dev_obj, &hdeh_mgr);
7d55524d
ORL
2420 if (!hdeh_mgr)
2421 goto func_cont;
2422
61a5b769 2423 bridge_deh_notify(hdeh_mgr, DSP_SYSERROR, DSP_EXCEPTIONABORT);
7d55524d
ORL
2424 }
2425 }
2426func_cont:
a741ea6e 2427 if (!status) {
7d55524d
ORL
2428 /* Enter CS before getting exit status, in case node was
2429 * deleted. */
2430 mutex_lock(&hnode_mgr->node_mgr_lock);
2431 /* Make sure node wasn't deleted while we blocked */
2432 if (!hnode) {
2433 status = -EPERM;
2434 } else {
2435 *pstatus = hnode->exit_status;
2436 dev_dbg(bridge, "%s: hnode: %p env 0x%x status 0x%x\n",
2437 __func__, hnode, hnode->node_env, status);
2438 }
2439 mutex_unlock(&hnode_mgr->node_mgr_lock);
2440 } /*End of sync_enter_cs */
2441func_end:
2442 return status;
2443}
2444
2445/*
2446 * ======== delete_node ========
2447 * Purpose:
2448 * Free GPP resources allocated in node_allocate() or node_connect().
2449 */
2450static void delete_node(struct node_object *hnode,
2451 struct process_context *pr_ctxt)
2452{
2453 struct node_mgr *hnode_mgr;
7d55524d
ORL
2454 struct bridge_drv_interface *intf_fxns;
2455 u32 i;
2456 enum node_type node_type;
2457 struct stream_chnl stream;
2458 struct node_msgargs node_msg_args;
2459 struct node_taskargs task_arg_obj;
677f2ded
FC
2460#ifdef DSP_DMM_DEBUG
2461 struct dmm_object *dmm_mgr;
2462 struct proc_object *p_proc_object =
a534f17b 2463 (struct proc_object *)hnode->processor;
677f2ded 2464#endif
7d55524d
ORL
2465 int status;
2466 if (!hnode)
2467 goto func_end;
085467b8 2468 hnode_mgr = hnode->node_mgr;
7d55524d
ORL
2469 if (!hnode_mgr)
2470 goto func_end;
7d1d6283 2471
7d55524d
ORL
2472 node_type = node_get_type(hnode);
2473 if (node_type != NODE_DEVICE) {
2474 node_msg_args = hnode->create_args.asa.node_msg_args;
2475 kfree(node_msg_args.pdata);
2476
2477 /* Free msg_ctrl queue */
2478 if (hnode->msg_queue_obj) {
2479 intf_fxns = hnode_mgr->intf_fxns;
09f13304 2480 (*intf_fxns->msg_delete_queue) (hnode->
7d55524d
ORL
2481 msg_queue_obj);
2482 hnode->msg_queue_obj = NULL;
2483 }
2484
2485 kfree(hnode->sync_done);
2486
2487 /* Free all stream info */
2488 if (hnode->inputs) {
2489 for (i = 0; i < MAX_INPUTS(hnode); i++) {
2490 stream = hnode->inputs[i];
2491 free_stream(hnode_mgr, stream);
2492 }
2493 kfree(hnode->inputs);
2494 hnode->inputs = NULL;
2495 }
2496 if (hnode->outputs) {
2497 for (i = 0; i < MAX_OUTPUTS(hnode); i++) {
2498 stream = hnode->outputs[i];
2499 free_stream(hnode_mgr, stream);
2500 }
2501 kfree(hnode->outputs);
2502 hnode->outputs = NULL;
2503 }
2504 task_arg_obj = hnode->create_args.asa.task_arg_obj;
2505 if (task_arg_obj.strm_in_def) {
2506 for (i = 0; i < MAX_INPUTS(hnode); i++) {
2507 kfree(task_arg_obj.strm_in_def[i].sz_device);
2508 task_arg_obj.strm_in_def[i].sz_device = NULL;
2509 }
2510 kfree(task_arg_obj.strm_in_def);
2511 task_arg_obj.strm_in_def = NULL;
2512 }
2513 if (task_arg_obj.strm_out_def) {
2514 for (i = 0; i < MAX_OUTPUTS(hnode); i++) {
2515 kfree(task_arg_obj.strm_out_def[i].sz_device);
2516 task_arg_obj.strm_out_def[i].sz_device = NULL;
2517 }
2518 kfree(task_arg_obj.strm_out_def);
2519 task_arg_obj.strm_out_def = NULL;
2520 }
a534f17b
RS
2521 if (task_arg_obj.dsp_heap_res_addr) {
2522 status = proc_un_map(hnode->processor, (void *)
2523 task_arg_obj.dsp_heap_addr,
7d55524d 2524 pr_ctxt);
2fa28a51 2525
a534f17b 2526 status = proc_un_reserve_memory(hnode->processor,
2fa28a51
FC
2527 (void *)
2528 task_arg_obj.
a534f17b 2529 dsp_heap_res_addr,
2fa28a51 2530 pr_ctxt);
677f2ded
FC
2531#ifdef DSP_DMM_DEBUG
2532 status = dmm_get_handle(p_proc_object, &dmm_mgr);
2533 if (dmm_mgr)
2534 dmm_mem_map_dump(dmm_mgr);
2535 else
2536 status = DSP_EHANDLE;
2537#endif
7d55524d
ORL
2538 }
2539 }
2540 if (node_type != NODE_MESSAGE) {
2541 kfree(hnode->stream_connect);
2542 hnode->stream_connect = NULL;
2543 }
2544 kfree(hnode->pstr_dev_name);
2545 hnode->pstr_dev_name = NULL;
2546
2547 if (hnode->ntfy_obj) {
2548 ntfy_delete(hnode->ntfy_obj);
2549 kfree(hnode->ntfy_obj);
2550 hnode->ntfy_obj = NULL;
2551 }
2552
2553 /* These were allocated in dcd_get_object_def (via node_allocate) */
2554 kfree(hnode->dcd_props.obj_data.node_obj.pstr_create_phase_fxn);
2555 hnode->dcd_props.obj_data.node_obj.pstr_create_phase_fxn = NULL;
2556
2557 kfree(hnode->dcd_props.obj_data.node_obj.pstr_execute_phase_fxn);
2558 hnode->dcd_props.obj_data.node_obj.pstr_execute_phase_fxn = NULL;
2559
2560 kfree(hnode->dcd_props.obj_data.node_obj.pstr_delete_phase_fxn);
2561 hnode->dcd_props.obj_data.node_obj.pstr_delete_phase_fxn = NULL;
2562
2563 kfree(hnode->dcd_props.obj_data.node_obj.pstr_i_alg_name);
2564 hnode->dcd_props.obj_data.node_obj.pstr_i_alg_name = NULL;
2565
2566 /* Free all SM address translator resources */
7d1d6283 2567 kfree(hnode->xlator);
7d55524d
ORL
2568 kfree(hnode->nldr_node_obj);
2569 hnode->nldr_node_obj = NULL;
085467b8 2570 hnode->node_mgr = NULL;
7d55524d
ORL
2571 kfree(hnode);
2572 hnode = NULL;
2573func_end:
2574 return;
2575}
2576
2577/*
2578 * ======== delete_node_mgr ========
2579 * Purpose:
2580 * Frees the node manager.
2581 */
2582static void delete_node_mgr(struct node_mgr *hnode_mgr)
2583{
0005391f 2584 struct node_object *hnode, *tmp;
7d55524d
ORL
2585
2586 if (hnode_mgr) {
2587 /* Free resources */
085467b8
RS
2588 if (hnode_mgr->dcd_mgr)
2589 dcd_destroy_manager(hnode_mgr->dcd_mgr);
7d55524d
ORL
2590
2591 /* Remove any elements remaining in lists */
0005391f
IN
2592 list_for_each_entry_safe(hnode, tmp, &hnode_mgr->node_list,
2593 list_elem) {
2594 list_del(&hnode->list_elem);
2595 delete_node(hnode, NULL);
7d55524d
ORL
2596 }
2597 mutex_destroy(&hnode_mgr->node_mgr_lock);
2598 if (hnode_mgr->ntfy_obj) {
2599 ntfy_delete(hnode_mgr->ntfy_obj);
2600 kfree(hnode_mgr->ntfy_obj);
2601 }
2602
7d55524d
ORL
2603 if (hnode_mgr->disp_obj)
2604 disp_delete(hnode_mgr->disp_obj);
2605
2606 if (hnode_mgr->strm_mgr_obj)
2607 strm_delete(hnode_mgr->strm_mgr_obj);
2608
2609 /* Delete the loader */
2610 if (hnode_mgr->nldr_obj)
e17ba7f2 2611 hnode_mgr->nldr_fxns.delete(hnode_mgr->nldr_obj);
7d55524d
ORL
2612
2613 if (hnode_mgr->loader_init)
09f13304 2614 hnode_mgr->nldr_fxns.exit();
7d55524d
ORL
2615
2616 kfree(hnode_mgr);
2617 }
2618}
2619
2620/*
2621 * ======== fill_stream_connect ========
2622 * Purpose:
2623 * Fills stream information.
2624 */
e6890692
RS
2625static void fill_stream_connect(struct node_object *node1,
2626 struct node_object *node2,
5e2eae57 2627 u32 stream1, u32 stream2)
7d55524d
ORL
2628{
2629 u32 strm_index;
2630 struct dsp_streamconnect *strm1 = NULL;
2631 struct dsp_streamconnect *strm2 = NULL;
2632 enum node_type node1_type = NODE_TASK;
2633 enum node_type node2_type = NODE_TASK;
2634
e6890692
RS
2635 node1_type = node_get_type(node1);
2636 node2_type = node_get_type(node2);
2637 if (node1 != (struct node_object *)DSP_HGPPNODE) {
7d55524d
ORL
2638
2639 if (node1_type != NODE_DEVICE) {
e6890692
RS
2640 strm_index = node1->num_inputs +
2641 node1->num_outputs - 1;
2642 strm1 = &(node1->stream_connect[strm_index]);
7d55524d 2643 strm1->cb_struct = sizeof(struct dsp_streamconnect);
5e2eae57 2644 strm1->this_node_stream_index = stream1;
7d55524d
ORL
2645 }
2646
e6890692 2647 if (node2 != (struct node_object *)DSP_HGPPNODE) {
7d55524d
ORL
2648 /* NODE == > NODE */
2649 if (node1_type != NODE_DEVICE) {
e6890692
RS
2650 strm1->connected_node = node2;
2651 strm1->ui_connected_node_id = node2->node_uuid;
5e2eae57 2652 strm1->connected_node_stream_index = stream2;
7d55524d
ORL
2653 strm1->connect_type = CONNECTTYPE_NODEOUTPUT;
2654 }
2655 if (node2_type != NODE_DEVICE) {
e6890692
RS
2656 strm_index = node2->num_inputs +
2657 node2->num_outputs - 1;
2658 strm2 = &(node2->stream_connect[strm_index]);
7d55524d
ORL
2659 strm2->cb_struct =
2660 sizeof(struct dsp_streamconnect);
5e2eae57 2661 strm2->this_node_stream_index = stream2;
e6890692
RS
2662 strm2->connected_node = node1;
2663 strm2->ui_connected_node_id = node1->node_uuid;
5e2eae57 2664 strm2->connected_node_stream_index = stream1;
7d55524d
ORL
2665 strm2->connect_type = CONNECTTYPE_NODEINPUT;
2666 }
2667 } else if (node1_type != NODE_DEVICE)
2668 strm1->connect_type = CONNECTTYPE_GPPOUTPUT;
2669 } else {
2670 /* GPP == > NODE */
e6890692
RS
2671 DBC_ASSERT(node2 != (struct node_object *)DSP_HGPPNODE);
2672 strm_index = node2->num_inputs + node2->num_outputs - 1;
2673 strm2 = &(node2->stream_connect[strm_index]);
7d55524d 2674 strm2->cb_struct = sizeof(struct dsp_streamconnect);
5e2eae57 2675 strm2->this_node_stream_index = stream2;
7d55524d
ORL
2676 strm2->connect_type = CONNECTTYPE_GPPINPUT;
2677 }
2678}
2679
2680/*
2681 * ======== fill_stream_def ========
2682 * Purpose:
2683 * Fills Stream attributes.
2684 */
2685static void fill_stream_def(struct node_object *hnode,
2686 struct node_strmdef *pstrm_def,
2687 struct dsp_strmattr *pattrs)
2688{
085467b8 2689 struct node_mgr *hnode_mgr = hnode->node_mgr;
7d55524d
ORL
2690
2691 if (pattrs != NULL) {
2692 pstrm_def->num_bufs = pattrs->num_bufs;
2693 pstrm_def->buf_size =
a534f17b 2694 pattrs->buf_size / hnode_mgr->dsp_data_mau_size;
7d55524d
ORL
2695 pstrm_def->seg_id = pattrs->seg_id;
2696 pstrm_def->buf_alignment = pattrs->buf_alignment;
a534f17b 2697 pstrm_def->timeout = pattrs->timeout;
7d55524d
ORL
2698 } else {
2699 pstrm_def->num_bufs = DEFAULTNBUFS;
2700 pstrm_def->buf_size =
a534f17b 2701 DEFAULTBUFSIZE / hnode_mgr->dsp_data_mau_size;
7d55524d
ORL
2702 pstrm_def->seg_id = DEFAULTSEGID;
2703 pstrm_def->buf_alignment = DEFAULTALIGNMENT;
a534f17b 2704 pstrm_def->timeout = DEFAULTTIMEOUT;
7d55524d
ORL
2705 }
2706}
2707
2708/*
2709 * ======== free_stream ========
2710 * Purpose:
2711 * Updates the channel mask and frees the pipe id.
2712 */
2713static void free_stream(struct node_mgr *hnode_mgr, struct stream_chnl stream)
2714{
2715 /* Free up the pipe id unless other node has not yet been deleted. */
2716 if (stream.type == NODECONNECT) {
b5a38aba 2717 if (test_bit(stream.dev_id, hnode_mgr->pipe_done_map)) {
7d55524d 2718 /* The other node has already been deleted */
b5a38aba
IN
2719 clear_bit(stream.dev_id, hnode_mgr->pipe_done_map);
2720 clear_bit(stream.dev_id, hnode_mgr->pipe_map);
7d55524d
ORL
2721 } else {
2722 /* The other node has not been deleted yet */
b5a38aba 2723 set_bit(stream.dev_id, hnode_mgr->pipe_done_map);
7d55524d
ORL
2724 }
2725 } else if (stream.type == HOSTCONNECT) {
6c66e948 2726 if (stream.dev_id < hnode_mgr->num_chnls) {
b5a38aba 2727 clear_bit(stream.dev_id, hnode_mgr->chnl_map);
6c66e948 2728 } else if (stream.dev_id < (2 * hnode_mgr->num_chnls)) {
7d55524d 2729 /* dsp-dma */
6c66e948 2730 clear_bit(stream.dev_id - (1 * hnode_mgr->num_chnls),
b5a38aba 2731 hnode_mgr->dma_chnl_map);
6c66e948 2732 } else if (stream.dev_id < (3 * hnode_mgr->num_chnls)) {
7d55524d 2733 /* zero-copy */
6c66e948 2734 clear_bit(stream.dev_id - (2 * hnode_mgr->num_chnls),
b5a38aba 2735 hnode_mgr->zc_chnl_map);
7d55524d
ORL
2736 }
2737 }
2738}
2739
2740/*
2741 * ======== get_fxn_address ========
2742 * Purpose:
2743 * Retrieves the address for create, execute or delete phase for a node.
2744 */
318b5df9 2745static int get_fxn_address(struct node_object *hnode, u32 * fxn_addr,
5e2eae57 2746 u32 phase)
7d55524d
ORL
2747{
2748 char *pstr_fxn_name = NULL;
085467b8 2749 struct node_mgr *hnode_mgr = hnode->node_mgr;
7d55524d
ORL
2750 int status = 0;
2751 DBC_REQUIRE(node_get_type(hnode) == NODE_TASK ||
2752 node_get_type(hnode) == NODE_DAISSOCKET ||
2753 node_get_type(hnode) == NODE_MESSAGE);
2754
5e2eae57 2755 switch (phase) {
7d55524d
ORL
2756 case CREATEPHASE:
2757 pstr_fxn_name =
2758 hnode->dcd_props.obj_data.node_obj.pstr_create_phase_fxn;
2759 break;
2760 case EXECUTEPHASE:
2761 pstr_fxn_name =
2762 hnode->dcd_props.obj_data.node_obj.pstr_execute_phase_fxn;
2763 break;
2764 case DELETEPHASE:
2765 pstr_fxn_name =
2766 hnode->dcd_props.obj_data.node_obj.pstr_delete_phase_fxn;
2767 break;
2768 default:
2769 /* Should never get here */
2770 DBC_ASSERT(false);
2771 break;
2772 }
2773
2774 status =
09f13304 2775 hnode_mgr->nldr_fxns.get_fxn_addr(hnode->nldr_node_obj,
318b5df9 2776 pstr_fxn_name, fxn_addr);
7d55524d
ORL
2777
2778 return status;
2779}
2780
2781/*
2782 * ======== get_node_info ========
2783 * Purpose:
2784 * Retrieves the node information.
2785 */
fb6aabb7 2786void get_node_info(struct node_object *hnode, struct dsp_nodeinfo *node_info)
7d55524d
ORL
2787{
2788 u32 i;
2789
2790 DBC_REQUIRE(hnode);
fb6aabb7 2791 DBC_REQUIRE(node_info != NULL);
7d55524d 2792
fb6aabb7
RS
2793 node_info->cb_struct = sizeof(struct dsp_nodeinfo);
2794 node_info->nb_node_database_props =
7d55524d 2795 hnode->dcd_props.obj_data.node_obj.ndb_props;
fb6aabb7
RS
2796 node_info->execution_priority = hnode->prio;
2797 node_info->device_owner = hnode->device_owner;
2798 node_info->number_streams = hnode->num_inputs + hnode->num_outputs;
2799 node_info->node_env = hnode->node_env;
7d55524d 2800
fb6aabb7 2801 node_info->ns_execution_state = node_get_state(hnode);
7d55524d
ORL
2802
2803 /* Copy stream connect data */
2804 for (i = 0; i < hnode->num_inputs + hnode->num_outputs; i++)
fb6aabb7 2805 node_info->sc_stream_connection[i] = hnode->stream_connect[i];
7d55524d
ORL
2806
2807}
2808
2809/*
2810 * ======== get_node_props ========
2811 * Purpose:
2812 * Retrieve node properties.
2813 */
2814static int get_node_props(struct dcd_manager *hdcd_mgr,
2815 struct node_object *hnode,
cd4f13c0 2816 const struct dsp_uuid *node_uuid,
aa09b091 2817 struct dcd_genericobj *dcd_prop)
7d55524d
ORL
2818{
2819 u32 len;
2820 struct node_msgargs *pmsg_args;
2821 struct node_taskargs *task_arg_obj;
2822 enum node_type node_type = NODE_TASK;
2823 struct dsp_ndbprops *pndb_props =
aa09b091 2824 &(dcd_prop->obj_data.node_obj.ndb_props);
7d55524d
ORL
2825 int status = 0;
2826 char sz_uuid[MAXUUIDLEN];
2827
fb6aabb7 2828 status = dcd_get_object_def(hdcd_mgr, (struct dsp_uuid *)node_uuid,
aa09b091 2829 DSP_DCDNODETYPE, dcd_prop);
7d55524d 2830
a741ea6e 2831 if (!status) {
7d55524d
ORL
2832 hnode->ntype = node_type = pndb_props->ntype;
2833
2834 /* Create UUID value to set in registry. */
fb6aabb7 2835 uuid_uuid_to_string((struct dsp_uuid *)node_uuid, sz_uuid,
7d55524d
ORL
2836 MAXUUIDLEN);
2837 dev_dbg(bridge, "(node) UUID: %s\n", sz_uuid);
2838
2839 /* Fill in message args that come from NDB */
2840 if (node_type != NODE_DEVICE) {
2841 pmsg_args = &(hnode->create_args.asa.node_msg_args);
2842 pmsg_args->seg_id =
aa09b091 2843 dcd_prop->obj_data.node_obj.msg_segid;
7d55524d 2844 pmsg_args->notify_type =
aa09b091 2845 dcd_prop->obj_data.node_obj.msg_notify_type;
7d55524d
ORL
2846 pmsg_args->max_msgs = pndb_props->message_depth;
2847 dev_dbg(bridge, "(node) Max Number of Messages: 0x%x\n",
2848 pmsg_args->max_msgs);
2849 } else {
2850 /* Copy device name */
2851 DBC_REQUIRE(pndb_props->ac_name);
2852 len = strlen(pndb_props->ac_name);
2853 DBC_ASSERT(len < MAXDEVNAMELEN);
2854 hnode->pstr_dev_name = kzalloc(len + 1, GFP_KERNEL);
2855 if (hnode->pstr_dev_name == NULL) {
2856 status = -ENOMEM;
2857 } else {
2858 strncpy(hnode->pstr_dev_name,
2859 pndb_props->ac_name, len);
2860 }
2861 }
2862 }
a741ea6e 2863 if (!status) {
7d55524d
ORL
2864 /* Fill in create args that come from NDB */
2865 if (node_type == NODE_TASK || node_type == NODE_DAISSOCKET) {
2866 task_arg_obj = &(hnode->create_args.asa.task_arg_obj);
2867 task_arg_obj->prio = pndb_props->prio;
2868 task_arg_obj->stack_size = pndb_props->stack_size;
2869 task_arg_obj->sys_stack_size =
2870 pndb_props->sys_stack_size;
2871 task_arg_obj->stack_seg = pndb_props->stack_seg;
2872 dev_dbg(bridge, "(node) Priority: 0x%x Stack Size: "
2873 "0x%x words System Stack Size: 0x%x words "
2874 "Stack Segment: 0x%x profile count : 0x%x\n",
2875 task_arg_obj->prio, task_arg_obj->stack_size,
2876 task_arg_obj->sys_stack_size,
2877 task_arg_obj->stack_seg,
2878 pndb_props->count_profiles);
2879 }
2880 }
2881
2882 return status;
2883}
2884
2885/*
2886 * ======== get_proc_props ========
2887 * Purpose:
2888 * Retrieve the processor properties.
2889 */
2890static int get_proc_props(struct node_mgr *hnode_mgr,
2891 struct dev_object *hdev_obj)
2892{
2893 struct cfg_hostres *host_res;
2894 struct bridge_dev_context *pbridge_context;
2895 int status = 0;
2896
2897 status = dev_get_bridge_context(hdev_obj, &pbridge_context);
2898 if (!pbridge_context)
2899 status = -EFAULT;
2900
a741ea6e 2901 if (!status) {
7d55524d
ORL
2902 host_res = pbridge_context->resources;
2903 if (!host_res)
2904 return -EPERM;
dab7f7fe
RS
2905 hnode_mgr->chnl_offset = host_res->chnl_offset;
2906 hnode_mgr->chnl_buf_size = host_res->chnl_buf_size;
6c66e948 2907 hnode_mgr->num_chnls = host_res->num_chnls;
7d55524d
ORL
2908
2909 /*
2910 * PROC will add an API to get dsp_processorinfo.
2911 * Fill in default values for now.
2912 */
2913 /* TODO -- Instead of hard coding, take from registry */
2914 hnode_mgr->proc_family = 6000;
2915 hnode_mgr->proc_type = 6410;
2916 hnode_mgr->min_pri = DSP_NODE_MIN_PRIORITY;
2917 hnode_mgr->max_pri = DSP_NODE_MAX_PRIORITY;
a534f17b
RS
2918 hnode_mgr->dsp_word_size = DSPWORDSIZE;
2919 hnode_mgr->dsp_data_mau_size = DSPWORDSIZE;
2920 hnode_mgr->dsp_mau_size = 1;
7d55524d
ORL
2921
2922 }
2923 return status;
2924}
2925
2926/*
2927 * ======== node_get_uuid_props ========
2928 * Purpose:
2929 * Fetch Node UUID properties from DCD/DOF file.
2930 */
2931int node_get_uuid_props(void *hprocessor,
9d7d0a52 2932 const struct dsp_uuid *node_uuid,
e6bf74f0 2933 struct dsp_ndbprops *node_props)
7d55524d
ORL
2934{
2935 struct node_mgr *hnode_mgr = NULL;
2936 struct dev_object *hdev_obj;
2937 int status = 0;
2938 struct dcd_nodeprops dcd_node_props;
2939 struct dsp_processorstate proc_state;
2940
2941 DBC_REQUIRE(refs > 0);
2942 DBC_REQUIRE(hprocessor != NULL);
fb6aabb7 2943 DBC_REQUIRE(node_uuid != NULL);
7d55524d 2944
fb6aabb7 2945 if (hprocessor == NULL || node_uuid == NULL) {
7d55524d
ORL
2946 status = -EFAULT;
2947 goto func_end;
2948 }
2949 status = proc_get_state(hprocessor, &proc_state,
2950 sizeof(struct dsp_processorstate));
b66e0986 2951 if (status)
7d55524d
ORL
2952 goto func_end;
2953 /* If processor is in error state then don't attempt
2954 to send the message */
2955 if (proc_state.proc_state == PROC_ERROR) {
2956 status = -EPERM;
2957 goto func_end;
2958 }
2959
2960 status = proc_get_dev_object(hprocessor, &hdev_obj);
2961 if (hdev_obj) {
2962 status = dev_get_node_manager(hdev_obj, &hnode_mgr);
2963 if (hnode_mgr == NULL) {
2964 status = -EFAULT;
2965 goto func_end;
2966 }
2967 }
2968
2969 /*
2970 * Enter the critical section. This is needed because
2971 * dcd_get_object_def will ultimately end up calling dbll_open/close,
2972 * which needs to be protected in order to not corrupt the zlib manager
2973 * (COD).
2974 */
2975 mutex_lock(&hnode_mgr->node_mgr_lock);
2976
2977 dcd_node_props.pstr_create_phase_fxn = NULL;
2978 dcd_node_props.pstr_execute_phase_fxn = NULL;
2979 dcd_node_props.pstr_delete_phase_fxn = NULL;
2980 dcd_node_props.pstr_i_alg_name = NULL;
2981
085467b8 2982 status = dcd_get_object_def(hnode_mgr->dcd_mgr,
fb6aabb7 2983 (struct dsp_uuid *)node_uuid, DSP_DCDNODETYPE,
7d55524d
ORL
2984 (struct dcd_genericobj *)&dcd_node_props);
2985
a741ea6e 2986 if (!status) {
7d55524d
ORL
2987 *node_props = dcd_node_props.ndb_props;
2988 kfree(dcd_node_props.pstr_create_phase_fxn);
2989
2990 kfree(dcd_node_props.pstr_execute_phase_fxn);
2991
2992 kfree(dcd_node_props.pstr_delete_phase_fxn);
2993
2994 kfree(dcd_node_props.pstr_i_alg_name);
2995 }
2996 /* Leave the critical section, we're done. */
2997 mutex_unlock(&hnode_mgr->node_mgr_lock);
2998func_end:
2999 return status;
3000}
3001
3002/*
3003 * ======== get_rms_fxns ========
3004 * Purpose:
3005 * Retrieve the RMS functions.
3006 */
3007static int get_rms_fxns(struct node_mgr *hnode_mgr)
3008{
3009 s32 i;
085467b8 3010 struct dev_object *dev_obj = hnode_mgr->dev_obj;
7d55524d
ORL
3011 int status = 0;
3012
3013 static char *psz_fxns[NUMRMSFXNS] = {
3014 "RMS_queryServer", /* RMSQUERYSERVER */
3015 "RMS_configureServer", /* RMSCONFIGURESERVER */
3016 "RMS_createNode", /* RMSCREATENODE */
3017 "RMS_executeNode", /* RMSEXECUTENODE */
3018 "RMS_deleteNode", /* RMSDELETENODE */
3019 "RMS_changeNodePriority", /* RMSCHANGENODEPRIORITY */
3020 "RMS_readMemory", /* RMSREADMEMORY */
3021 "RMS_writeMemory", /* RMSWRITEMEMORY */
3022 "RMS_copy", /* RMSCOPY */
3023 };
3024
3025 for (i = 0; i < NUMRMSFXNS; i++) {
3026 status = dev_get_symbol(dev_obj, psz_fxns[i],
dab7f7fe 3027 &(hnode_mgr->fxn_addrs[i]));
b66e0986 3028 if (status) {
7d55524d
ORL
3029 if (status == -ESPIPE) {
3030 /*
3031 * May be loaded dynamically (in the future),
3032 * but return an error for now.
3033 */
3034 dev_dbg(bridge, "%s: RMS function: %s currently"
3035 " not loaded\n", __func__, psz_fxns[i]);
3036 } else {
3037 dev_dbg(bridge, "%s: Symbol not found: %s "
3038 "status = 0x%x\n", __func__,
3039 psz_fxns[i], status);
3040 break;
3041 }
3042 }
3043 }
3044
3045 return status;
3046}
3047
3048/*
3049 * ======== ovly ========
3050 * Purpose:
3051 * Called during overlay.Sends command to RMS to copy a block of data.
3052 */
5e2eae57 3053static u32 ovly(void *priv_ref, u32 dsp_run_addr, u32 dsp_load_addr,
95870a88 3054 u32 ul_num_bytes, u32 mem_space)
7d55524d
ORL
3055{
3056 struct node_object *hnode = (struct node_object *)priv_ref;
3057 struct node_mgr *hnode_mgr;
3058 u32 ul_bytes = 0;
3059 u32 ul_size;
3060 u32 ul_timeout;
3061 int status = 0;
3062 struct bridge_dev_context *hbridge_context;
3063 /* Function interface to Bridge driver*/
3064 struct bridge_drv_interface *intf_fxns;
3065
3066 DBC_REQUIRE(hnode);
3067
085467b8 3068 hnode_mgr = hnode->node_mgr;
7d55524d 3069
a534f17b
RS
3070 ul_size = ul_num_bytes / hnode_mgr->dsp_word_size;
3071 ul_timeout = hnode->timeout;
7d55524d
ORL
3072
3073 /* Call new MemCopy function */
3074 intf_fxns = hnode_mgr->intf_fxns;
085467b8 3075 status = dev_get_bridge_context(hnode_mgr->dev_obj, &hbridge_context);
a741ea6e 3076 if (!status) {
7d55524d 3077 status =
3c882de5 3078 (*intf_fxns->brd_mem_copy) (hbridge_context,
5e2eae57 3079 dsp_run_addr, dsp_load_addr,
95870a88 3080 ul_num_bytes, (u32) mem_space);
a741ea6e 3081 if (!status)
7d55524d
ORL
3082 ul_bytes = ul_num_bytes;
3083 else
3084 pr_debug("%s: failed to copy brd memory, status 0x%x\n",
3085 __func__, status);
3086 } else {
3087 pr_debug("%s: failed to get Bridge context, status 0x%x\n",
3088 __func__, status);
3089 }
3090
3091 return ul_bytes;
3092}
3093
3094/*
3095 * ======== mem_write ========
3096 */
5e2eae57 3097static u32 mem_write(void *priv_ref, u32 dsp_add, void *pbuf,
95870a88 3098 u32 ul_num_bytes, u32 mem_space)
7d55524d
ORL
3099{
3100 struct node_object *hnode = (struct node_object *)priv_ref;
3101 struct node_mgr *hnode_mgr;
3102 u16 mem_sect_type;
3103 u32 ul_timeout;
3104 int status = 0;
3105 struct bridge_dev_context *hbridge_context;
3106 /* Function interface to Bridge driver */
3107 struct bridge_drv_interface *intf_fxns;
3108
3109 DBC_REQUIRE(hnode);
95870a88 3110 DBC_REQUIRE(mem_space & DBLL_CODE || mem_space & DBLL_DATA);
7d55524d 3111
085467b8 3112 hnode_mgr = hnode->node_mgr;
7d55524d 3113
a534f17b 3114 ul_timeout = hnode->timeout;
95870a88 3115 mem_sect_type = (mem_space & DBLL_CODE) ? RMS_CODE : RMS_DATA;
7d55524d
ORL
3116
3117 /* Call new MemWrite function */
3118 intf_fxns = hnode_mgr->intf_fxns;
085467b8 3119 status = dev_get_bridge_context(hnode_mgr->dev_obj, &hbridge_context);
3c882de5 3120 status = (*intf_fxns->brd_mem_write) (hbridge_context, pbuf,
5e2eae57 3121 dsp_add, ul_num_bytes, mem_sect_type);
7d55524d
ORL
3122
3123 return ul_num_bytes;
3124}
3125
4f551c8f 3126#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
7d55524d
ORL
3127/*
3128 * ======== node_find_addr ========
3129 */
3130int node_find_addr(struct node_mgr *node_mgr, u32 sym_addr,
3131 u32 offset_range, void *sym_addr_output, char *sym_name)
3132{
3133 struct node_object *node_obj;
3134 int status = -ENOENT;
7d55524d
ORL
3135
3136 pr_debug("%s(0x%x, 0x%x, 0x%x, 0x%x, %s)\n", __func__,
3137 (unsigned int) node_mgr,
3138 sym_addr, offset_range,
3139 (unsigned int) sym_addr_output, sym_name);
3140
0005391f 3141 list_for_each_entry(node_obj, &node_mgr->node_list, list_elem) {
7d55524d
ORL
3142 status = nldr_find_addr(node_obj->nldr_node_obj, sym_addr,
3143 offset_range, sym_addr_output, sym_name);
a741ea6e 3144 if (!status)
7d55524d 3145 break;
7d55524d
ORL
3146 }
3147
3148 return status;
3149}
4f551c8f 3150#endif