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