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