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