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