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