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