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