aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/tidspbridge/rmgr/node.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/tidspbridge/rmgr/node.c')
-rw-r--r--drivers/staging/tidspbridge/rmgr/node.c3029
1 files changed, 0 insertions, 3029 deletions
diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c
deleted file mode 100644
index 9d3044a384ee..000000000000
--- a/drivers/staging/tidspbridge/rmgr/node.c
+++ /dev/null
@@ -1,3029 +0,0 @@
-/*
- * node.c
- *
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
- *
- * DSP/BIOS Bridge Node Manager.
- *
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
- *
- * This package is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#include <linux/types.h>
-#include <linux/bitmap.h>
-#include <linux/list.h>
-
-/* ----------------------------------- Host OS */
-#include <dspbridge/host_os.h>
-
-/* ----------------------------------- DSP/BIOS Bridge */
-#include <dspbridge/dbdefs.h>
-
-/* ----------------------------------- OS Adaptation Layer */
-#include <dspbridge/memdefs.h>
-#include <dspbridge/proc.h>
-#include <dspbridge/strm.h>
-#include <dspbridge/sync.h>
-#include <dspbridge/ntfy.h>
-
-/* ----------------------------------- Platform Manager */
-#include <dspbridge/cmm.h>
-#include <dspbridge/cod.h>
-#include <dspbridge/dev.h>
-#include <dspbridge/msg.h>
-
-/* ----------------------------------- Resource Manager */
-#include <dspbridge/dbdcd.h>
-#include <dspbridge/disp.h>
-#include <dspbridge/rms_sh.h>
-
-/* ----------------------------------- Link Driver */
-#include <dspbridge/dspdefs.h>
-#include <dspbridge/dspioctl.h>
-
-/* ----------------------------------- Others */
-#include <dspbridge/uuidutil.h>
-
-/* ----------------------------------- This */
-#include <dspbridge/nodepriv.h>
-#include <dspbridge/node.h>
-#include <dspbridge/dmm.h>
-
-/* Static/Dynamic Loader includes */
-#include <dspbridge/dbll.h>
-#include <dspbridge/nldr.h>
-
-#include <dspbridge/drv.h>
-#include <dspbridge/resourcecleanup.h>
-#include <_tiomap.h>
-
-#include <dspbridge/dspdeh.h>
-
-#define HOSTPREFIX "/host"
-#define PIPEPREFIX "/dbpipe"
-
-#define MAX_INPUTS(h) \
- ((h)->dcd_props.obj_data.node_obj.ndb_props.num_input_streams)
-#define MAX_OUTPUTS(h) \
- ((h)->dcd_props.obj_data.node_obj.ndb_props.num_output_streams)
-
-#define NODE_GET_PRIORITY(h) ((h)->prio)
-#define NODE_SET_PRIORITY(hnode, prio) ((hnode)->prio = prio)
-#define NODE_SET_STATE(hnode, state) ((hnode)->node_state = state)
-
-#define MAXPIPES 100 /* Max # of /pipe connections (CSL limit) */
-#define MAXDEVSUFFIXLEN 2 /* Max(Log base 10 of MAXPIPES, MAXSTREAMS) */
-
-#define PIPENAMELEN (sizeof(PIPEPREFIX) + MAXDEVSUFFIXLEN)
-#define HOSTNAMELEN (sizeof(HOSTPREFIX) + MAXDEVSUFFIXLEN)
-
-#define MAXDEVNAMELEN 32 /* dsp_ndbprops.ac_name size */
-#define CREATEPHASE 1
-#define EXECUTEPHASE 2
-#define DELETEPHASE 3
-
-/* Define default STRM parameters */
-/*
- * TBD: Put in header file, make global DSP_STRMATTRS with defaults,
- * or make defaults configurable.
- */
-#define DEFAULTBUFSIZE 32
-#define DEFAULTNBUFS 2
-#define DEFAULTSEGID 0
-#define DEFAULTALIGNMENT 0
-#define DEFAULTTIMEOUT 10000
-
-#define RMSQUERYSERVER 0
-#define RMSCONFIGURESERVER 1
-#define RMSCREATENODE 2
-#define RMSEXECUTENODE 3
-#define RMSDELETENODE 4
-#define RMSCHANGENODEPRIORITY 5
-#define RMSREADMEMORY 6
-#define RMSWRITEMEMORY 7
-#define RMSCOPY 8
-#define MAXTIMEOUT 2000
-
-#define NUMRMSFXNS 9
-
-#define PWR_TIMEOUT 500 /* default PWR timeout in msec */
-
-#define STACKSEGLABEL "L1DSRAM_HEAP" /* Label for DSP Stack Segment Addr */
-
-/*
- * ======== node_mgr ========
- */
-struct node_mgr {
- struct dev_object *dev_obj; /* Device object */
- /* Function interface to Bridge driver */
- struct bridge_drv_interface *intf_fxns;
- struct dcd_manager *dcd_mgr; /* Proc/Node data manager */
- struct disp_object *disp_obj; /* Node dispatcher */
- struct list_head node_list; /* List of all allocated nodes */
- u32 num_nodes; /* Number of nodes in node_list */
- u32 num_created; /* Number of nodes *created* on DSP */
- DECLARE_BITMAP(pipe_map, MAXPIPES); /* Pipe connection bitmap */
- DECLARE_BITMAP(pipe_done_map, MAXPIPES); /* Pipes that are half free */
- /* Channel allocation bitmap */
- DECLARE_BITMAP(chnl_map, CHNL_MAXCHANNELS);
- /* DMA Channel allocation bitmap */
- DECLARE_BITMAP(dma_chnl_map, CHNL_MAXCHANNELS);
- /* Zero-Copy Channel alloc bitmap */
- DECLARE_BITMAP(zc_chnl_map, CHNL_MAXCHANNELS);
- struct ntfy_object *ntfy_obj; /* Manages registered notifications */
- struct mutex node_mgr_lock; /* For critical sections */
- u32 fxn_addrs[NUMRMSFXNS]; /* RMS function addresses */
- struct msg_mgr *msg_mgr_obj;
-
- /* Processor properties needed by Node Dispatcher */
- u32 num_chnls; /* Total number of channels */
- u32 chnl_offset; /* Offset of chnl ids rsvd for RMS */
- u32 chnl_buf_size; /* Buffer size for data to RMS */
- int proc_family; /* eg, 5000 */
- int proc_type; /* eg, 5510 */
- u32 dsp_word_size; /* Size of DSP word on host bytes */
- u32 dsp_data_mau_size; /* Size of DSP data MAU */
- u32 dsp_mau_size; /* Size of MAU */
- s32 min_pri; /* Minimum runtime priority for node */
- s32 max_pri; /* Maximum runtime priority for node */
-
- struct strm_mgr *strm_mgr_obj; /* STRM manager */
-
- /* Loader properties */
- struct nldr_object *nldr_obj; /* Handle to loader */
- struct node_ldr_fxns nldr_fxns; /* Handle to loader functions */
-};
-
-/*
- * ======== connecttype ========
- */
-enum connecttype {
- NOTCONNECTED = 0,
- NODECONNECT,
- HOSTCONNECT,
- DEVICECONNECT,
-};
-
-/*
- * ======== stream_chnl ========
- */
-struct stream_chnl {
- enum connecttype type; /* Type of stream connection */
- u32 dev_id; /* pipe or channel id */
-};
-
-/*
- * ======== node_object ========
- */
-struct node_object {
- struct list_head list_elem;
- struct node_mgr *node_mgr; /* The manager of this node */
- struct proc_object *processor; /* Back pointer to processor */
- struct dsp_uuid node_uuid; /* Node's ID */
- s32 prio; /* Node's current priority */
- u32 timeout; /* Timeout for blocking NODE calls */
- u32 heap_size; /* Heap Size */
- u32 dsp_heap_virt_addr; /* Heap Size */
- u32 gpp_heap_virt_addr; /* Heap Size */
- enum node_type ntype; /* Type of node: message, task, etc */
- enum node_state node_state; /* NODE_ALLOCATED, NODE_CREATED, ... */
- u32 num_inputs; /* Current number of inputs */
- u32 num_outputs; /* Current number of outputs */
- u32 max_input_index; /* Current max input stream index */
- u32 max_output_index; /* Current max output stream index */
- struct stream_chnl *inputs; /* Node's input streams */
- struct stream_chnl *outputs; /* Node's output streams */
- struct node_createargs create_args; /* Args for node create func */
- nodeenv node_env; /* Environment returned by RMS */
- struct dcd_genericobj dcd_props; /* Node properties from DCD */
- struct dsp_cbdata *args; /* Optional args to pass to node */
- struct ntfy_object *ntfy_obj; /* Manages registered notifications */
- char *str_dev_name; /* device name, if device node */
- struct sync_object *sync_done; /* Synchronize node_terminate */
- s32 exit_status; /* execute function return status */
-
- /* Information needed for node_get_attr() */
- void *device_owner; /* If dev node, task that owns it */
- u32 num_gpp_inputs; /* Current # of from GPP streams */
- u32 num_gpp_outputs; /* Current # of to GPP streams */
- /* Current stream connections */
- struct dsp_streamconnect *stream_connect;
-
- /* Message queue */
- struct msg_queue *msg_queue_obj;
-
- /* These fields used for SM messaging */
- struct cmm_xlatorobject *xlator; /* Node's SM addr translator */
-
- /* Handle to pass to dynamic loader */
- struct nldr_nodeobject *nldr_node_obj;
- bool loaded; /* Code is (dynamically) loaded */
- bool phase_split; /* Phases split in many libs or ovly */
-
-};
-
-/* Default buffer attributes */
-static struct dsp_bufferattr node_dfltbufattrs = {
- .cb_struct = 0,
- .segment_id = 1,
- .buf_alignment = 0,
-};
-
-static void delete_node(struct node_object *hnode,
- struct process_context *pr_ctxt);
-static void delete_node_mgr(struct node_mgr *hnode_mgr);
-static void fill_stream_connect(struct node_object *node1,
- struct node_object *node2, u32 stream1,
- u32 stream2);
-static void fill_stream_def(struct node_object *hnode,
- struct node_strmdef *pstrm_def,
- struct dsp_strmattr *pattrs);
-static void free_stream(struct node_mgr *hnode_mgr, struct stream_chnl stream);
-static int get_fxn_address(struct node_object *hnode, u32 *fxn_addr,
- u32 phase);
-static int get_node_props(struct dcd_manager *hdcd_mgr,
- struct node_object *hnode,
- const struct dsp_uuid *node_uuid,
- struct dcd_genericobj *dcd_prop);
-static int get_proc_props(struct node_mgr *hnode_mgr,
- struct dev_object *hdev_obj);
-static int get_rms_fxns(struct node_mgr *hnode_mgr);
-static u32 ovly(void *priv_ref, u32 dsp_run_addr, u32 dsp_load_addr,
- u32 ul_num_bytes, u32 mem_space);
-static u32 mem_write(void *priv_ref, u32 dsp_add, void *pbuf,
- u32 ul_num_bytes, u32 mem_space);
-
-/* Dynamic loader functions. */
-static struct node_ldr_fxns nldr_fxns = {
- nldr_allocate,
- nldr_create,
- nldr_delete,
- nldr_get_fxn_addr,
- nldr_load,
- nldr_unload,
-};
-
-enum node_state node_get_state(void *hnode)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- if (!pnode)
- return -1;
- return pnode->node_state;
-}
-
-/*
- * ======== node_allocate ========
- * Purpose:
- * Allocate GPP resources to manage a node on the DSP.
- */
-int node_allocate(struct proc_object *hprocessor,
- const struct dsp_uuid *node_uuid,
- const struct dsp_cbdata *pargs,
- const struct dsp_nodeattrin *attr_in,
- struct node_res_object **noderes,
- struct process_context *pr_ctxt)
-{
- struct node_mgr *hnode_mgr;
- struct dev_object *hdev_obj;
- struct node_object *pnode = NULL;
- enum node_type node_type = NODE_TASK;
- struct node_msgargs *pmsg_args;
- struct node_taskargs *ptask_args;
- u32 num_streams;
- struct bridge_drv_interface *intf_fxns;
- int status = 0;
- struct cmm_object *hcmm_mgr = NULL; /* Shared memory manager hndl */
- u32 proc_id;
- u32 pul_value;
- u32 dynext_base;
- u32 off_set = 0;
- u32 ul_stack_seg_val;
- struct cfg_hostres *host_res;
- struct bridge_dev_context *pbridge_context;
- u32 mapped_addr = 0;
- u32 map_attrs = 0x0;
- struct dsp_processorstate proc_state;
-#ifdef DSP_DMM_DEBUG
- struct dmm_object *dmm_mgr;
- struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
-#endif
-
- void *node_res;
-
- *noderes = NULL;
-
- status = proc_get_processor_id(hprocessor, &proc_id);
-
- if (proc_id != DSP_UNIT)
- goto func_end;
-
- status = proc_get_dev_object(hprocessor, &hdev_obj);
- if (!status) {
- status = dev_get_node_manager(hdev_obj, &hnode_mgr);
- if (hnode_mgr == NULL)
- status = -EPERM;
-
- }
-
- if (status)
- goto func_end;
-
- status = dev_get_bridge_context(hdev_obj, &pbridge_context);
- if (!pbridge_context) {
- status = -EFAULT;
- goto func_end;
- }
-
- status = proc_get_state(hprocessor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_end;
- /* If processor is in error state then don't attempt
- to send the message */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_end;
- }
-
- /* Assuming that 0 is not a valid function address */
- if (hnode_mgr->fxn_addrs[0] == 0) {
- /* No RMS on target - we currently can't handle this */
- pr_err("%s: Failed, no RMS in base image\n", __func__);
- status = -EPERM;
- } else {
- /* Validate attr_in fields, if non-NULL */
- if (attr_in) {
- /* Check if attr_in->prio is within range */
- if (attr_in->prio < hnode_mgr->min_pri ||
- attr_in->prio > hnode_mgr->max_pri)
- status = -EDOM;
- }
- }
- /* Allocate node object and fill in */
- if (status)
- goto func_end;
-
- pnode = kzalloc(sizeof(struct node_object), GFP_KERNEL);
- if (pnode == NULL) {
- status = -ENOMEM;
- goto func_end;
- }
- pnode->node_mgr = hnode_mgr;
- /* This critical section protects get_node_props */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- /* Get dsp_ndbprops from node database */
- status = get_node_props(hnode_mgr->dcd_mgr, pnode, node_uuid,
- &(pnode->dcd_props));
- if (status)
- goto func_cont;
-
- pnode->node_uuid = *node_uuid;
- pnode->processor = hprocessor;
- pnode->ntype = pnode->dcd_props.obj_data.node_obj.ndb_props.ntype;
- pnode->timeout = pnode->dcd_props.obj_data.node_obj.ndb_props.timeout;
- pnode->prio = pnode->dcd_props.obj_data.node_obj.ndb_props.prio;
-
- /* Currently only C64 DSP builds support Node Dynamic * heaps */
- /* Allocate memory for node heap */
- pnode->create_args.asa.task_arg_obj.heap_size = 0;
- pnode->create_args.asa.task_arg_obj.dsp_heap_addr = 0;
- pnode->create_args.asa.task_arg_obj.dsp_heap_res_addr = 0;
- pnode->create_args.asa.task_arg_obj.gpp_heap_addr = 0;
- if (!attr_in)
- goto func_cont;
-
- /* Check if we have a user allocated node heap */
- if (!(attr_in->pgpp_virt_addr))
- goto func_cont;
-
- /* check for page aligned Heap size */
- if (((attr_in->heap_size) & (PG_SIZE4K - 1))) {
- pr_err("%s: node heap size not aligned to 4K, size = 0x%x\n",
- __func__, attr_in->heap_size);
- status = -EINVAL;
- } else {
- pnode->create_args.asa.task_arg_obj.heap_size =
- attr_in->heap_size;
- pnode->create_args.asa.task_arg_obj.gpp_heap_addr =
- (u32) attr_in->pgpp_virt_addr;
- }
- if (status)
- goto func_cont;
-
- status = proc_reserve_memory(hprocessor,
- pnode->create_args.asa.task_arg_obj.
- heap_size + PAGE_SIZE,
- (void **)&(pnode->create_args.asa.
- task_arg_obj.dsp_heap_res_addr),
- pr_ctxt);
- if (status) {
- pr_err("%s: Failed to reserve memory for heap: 0x%x\n",
- __func__, status);
- goto func_cont;
- }
-#ifdef DSP_DMM_DEBUG
- status = dmm_get_handle(p_proc_object, &dmm_mgr);
- if (!dmm_mgr) {
- status = DSP_EHANDLE;
- goto func_cont;
- }
-
- dmm_mem_map_dump(dmm_mgr);
-#endif
-
- map_attrs |= DSP_MAPLITTLEENDIAN;
- map_attrs |= DSP_MAPELEMSIZE32;
- map_attrs |= DSP_MAPVIRTUALADDR;
- status = proc_map(hprocessor, (void *)attr_in->pgpp_virt_addr,
- pnode->create_args.asa.task_arg_obj.heap_size,
- (void *)pnode->create_args.asa.task_arg_obj.
- dsp_heap_res_addr, (void **)&mapped_addr, map_attrs,
- pr_ctxt);
- if (status)
- pr_err("%s: Failed to map memory for Heap: 0x%x\n",
- __func__, status);
- else
- pnode->create_args.asa.task_arg_obj.dsp_heap_addr =
- (u32) mapped_addr;
-
-func_cont:
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- if (attr_in != NULL) {
- /* Overrides of NBD properties */
- pnode->timeout = attr_in->timeout;
- pnode->prio = attr_in->prio;
- }
- /* Create object to manage notifications */
- if (!status) {
- pnode->ntfy_obj = kmalloc(sizeof(struct ntfy_object),
- GFP_KERNEL);
- if (pnode->ntfy_obj)
- ntfy_init(pnode->ntfy_obj);
- else
- status = -ENOMEM;
- }
-
- if (!status) {
- node_type = node_get_type(pnode);
- /* Allocate dsp_streamconnect array for device, task, and
- * dais socket nodes. */
- if (node_type != NODE_MESSAGE) {
- num_streams = MAX_INPUTS(pnode) + MAX_OUTPUTS(pnode);
- pnode->stream_connect = kzalloc(num_streams *
- sizeof(struct dsp_streamconnect),
- GFP_KERNEL);
- if (num_streams > 0 && pnode->stream_connect == NULL)
- status = -ENOMEM;
-
- }
- if (!status && (node_type == NODE_TASK ||
- node_type == NODE_DAISSOCKET)) {
- /* Allocate arrays for maintainig stream connections */
- pnode->inputs = kzalloc(MAX_INPUTS(pnode) *
- sizeof(struct stream_chnl), GFP_KERNEL);
- pnode->outputs = kzalloc(MAX_OUTPUTS(pnode) *
- sizeof(struct stream_chnl), GFP_KERNEL);
- ptask_args = &(pnode->create_args.asa.task_arg_obj);
- ptask_args->strm_in_def = kzalloc(MAX_INPUTS(pnode) *
- sizeof(struct node_strmdef),
- GFP_KERNEL);
- ptask_args->strm_out_def = kzalloc(MAX_OUTPUTS(pnode) *
- sizeof(struct node_strmdef),
- GFP_KERNEL);
- if ((MAX_INPUTS(pnode) > 0 && (pnode->inputs == NULL ||
- ptask_args->strm_in_def
- == NULL))
- || (MAX_OUTPUTS(pnode) > 0
- && (pnode->outputs == NULL
- || ptask_args->strm_out_def == NULL)))
- status = -ENOMEM;
- }
- }
- if (!status && (node_type != NODE_DEVICE)) {
- /* Create an event that will be posted when RMS_EXIT is
- * received. */
- pnode->sync_done = kzalloc(sizeof(struct sync_object),
- GFP_KERNEL);
- if (pnode->sync_done)
- sync_init_event(pnode->sync_done);
- else
- status = -ENOMEM;
-
- if (!status) {
- /*Get the shared mem mgr for this nodes dev object */
- status = cmm_get_handle(hprocessor, &hcmm_mgr);
- if (!status) {
- /* Allocate a SM addr translator for this node
- * w/ deflt attr */
- status = cmm_xlator_create(&pnode->xlator,
- hcmm_mgr, NULL);
- }
- }
- if (!status) {
- /* Fill in message args */
- if ((pargs != NULL) && (pargs->cb_data > 0)) {
- pmsg_args =
- &(pnode->create_args.asa.node_msg_args);
- pmsg_args->pdata = kzalloc(pargs->cb_data,
- GFP_KERNEL);
- if (pmsg_args->pdata == NULL) {
- status = -ENOMEM;
- } else {
- pmsg_args->arg_length = pargs->cb_data;
- memcpy(pmsg_args->pdata,
- pargs->node_data,
- pargs->cb_data);
- }
- }
- }
- }
-
- if (!status && node_type != NODE_DEVICE) {
- /* Create a message queue for this node */
- intf_fxns = hnode_mgr->intf_fxns;
- status =
- (*intf_fxns->msg_create_queue) (hnode_mgr->msg_mgr_obj,
- &pnode->msg_queue_obj,
- 0,
- pnode->create_args.asa.
- node_msg_args.max_msgs,
- pnode);
- }
-
- if (!status) {
- /* Create object for dynamic loading */
-
- status = hnode_mgr->nldr_fxns.allocate(hnode_mgr->nldr_obj,
- (void *)pnode,
- &pnode->dcd_props.
- obj_data.node_obj,
- &pnode->
- nldr_node_obj,
- &pnode->phase_split);
- }
-
- /* Compare value read from Node Properties and check if it is same as
- * STACKSEGLABEL, if yes read the Address of STACKSEGLABEL, calculate
- * GPP Address, Read the value in that address and override the
- * stack_seg value in task args */
- if (!status &&
- (char *)pnode->dcd_props.obj_data.node_obj.ndb_props.
- stack_seg_name != NULL) {
- if (strcmp((char *)
- pnode->dcd_props.obj_data.node_obj.ndb_props.
- stack_seg_name, STACKSEGLABEL) == 0) {
- void __iomem *stack_seg;
- u32 stack_seg_pa;
-
- status =
- hnode_mgr->nldr_fxns.
- get_fxn_addr(pnode->nldr_node_obj, "DYNEXT_BEG",
- &dynext_base);
- if (status)
- pr_err("%s: Failed to get addr for DYNEXT_BEG"
- " status = 0x%x\n", __func__, status);
-
- status =
- hnode_mgr->nldr_fxns.
- get_fxn_addr(pnode->nldr_node_obj,
- "L1DSRAM_HEAP", &pul_value);
-
- if (status)
- pr_err("%s: Failed to get addr for L1DSRAM_HEAP"
- " status = 0x%x\n", __func__, status);
-
- host_res = pbridge_context->resources;
- if (!host_res)
- status = -EPERM;
-
- if (status) {
- pr_err("%s: Failed to get host resource, status"
- " = 0x%x\n", __func__, status);
- goto func_end;
- }
-
- off_set = pul_value - dynext_base;
- stack_seg_pa = host_res->mem_phys[1] + off_set;
- stack_seg = ioremap(stack_seg_pa, SZ_32);
- if (!stack_seg) {
- status = -ENOMEM;
- goto func_end;
- }
-
- ul_stack_seg_val = readl(stack_seg);
-
- iounmap(stack_seg);
-
- dev_dbg(bridge, "%s: StackSegVal = 0x%x, StackSegAddr ="
- " 0x%x\n", __func__, ul_stack_seg_val,
- host_res->mem_base[1] + off_set);
-
- pnode->create_args.asa.task_arg_obj.stack_seg =
- ul_stack_seg_val;
-
- }
- }
-
- if (!status) {
- /* Add the node to the node manager's list of allocated
- * nodes. */
- NODE_SET_STATE(pnode, NODE_ALLOCATED);
-
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- list_add_tail(&pnode->list_elem, &hnode_mgr->node_list);
- ++(hnode_mgr->num_nodes);
-
- /* Exit critical section */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
-
- /* Preset this to assume phases are split
- * (for overlay and dll) */
- pnode->phase_split = true;
-
- /* Notify all clients registered for DSP_NODESTATECHANGE. */
- proc_notify_all_clients(hprocessor, DSP_NODESTATECHANGE);
- } else {
- /* Cleanup */
- if (pnode)
- delete_node(pnode, pr_ctxt);
-
- }
-
- if (!status) {
- status = drv_insert_node_res_element(pnode, &node_res, pr_ctxt);
- if (status) {
- delete_node(pnode, pr_ctxt);
- goto func_end;
- }
-
- *noderes = (struct node_res_object *)node_res;
- drv_proc_node_update_heap_status(node_res, true);
- drv_proc_node_update_status(node_res, true);
- }
-func_end:
- dev_dbg(bridge, "%s: hprocessor: %p pNodeId: %p pargs: %p attr_in: %p "
- "node_res: %p status: 0x%x\n", __func__, hprocessor,
- node_uuid, pargs, attr_in, noderes, status);
- return status;
-}
-
-/*
- * ======== node_alloc_msg_buf ========
- * Purpose:
- * Allocates buffer for zero copy messaging.
- */
-DBAPI node_alloc_msg_buf(struct node_object *hnode, u32 usize,
- struct dsp_bufferattr *pattr,
- u8 **pbuffer)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- int status = 0;
- bool va_flag = false;
- bool set_info;
- u32 proc_id;
-
- if (!pnode)
- status = -EFAULT;
- else if (node_get_type(pnode) == NODE_DEVICE)
- status = -EPERM;
-
- if (status)
- goto func_end;
-
- if (pattr == NULL)
- pattr = &node_dfltbufattrs; /* set defaults */
-
- status = proc_get_processor_id(pnode->processor, &proc_id);
- if (proc_id != DSP_UNIT)
- goto func_end;
-
- /* If segment ID includes MEM_SETVIRTUALSEGID then pbuffer is a
- * virt address, so set this info in this node's translator
- * object for future ref. If MEM_GETVIRTUALSEGID then retrieve
- * virtual address from node's translator. */
- if ((pattr->segment_id & MEM_SETVIRTUALSEGID) ||
- (pattr->segment_id & MEM_GETVIRTUALSEGID)) {
- va_flag = true;
- set_info = (pattr->segment_id & MEM_SETVIRTUALSEGID) ?
- true : false;
- /* Clear mask bits */
- pattr->segment_id &= ~MEM_MASKVIRTUALSEGID;
- /* Set/get this node's translators virtual address base/size */
- status = cmm_xlator_info(pnode->xlator, pbuffer, usize,
- pattr->segment_id, set_info);
- }
- if (!status && (!va_flag)) {
- if (pattr->segment_id != 1) {
- /* Node supports single SM segment only. */
- status = -EBADR;
- }
- /* Arbitrary SM buffer alignment not supported for host side
- * allocs, but guaranteed for the following alignment
- * values. */
- switch (pattr->buf_alignment) {
- case 0:
- case 1:
- case 2:
- case 4:
- break;
- default:
- /* alignment value not supportted */
- status = -EPERM;
- break;
- }
- if (!status) {
- /* allocate physical buffer from seg_id in node's
- * translator */
- (void)cmm_xlator_alloc_buf(pnode->xlator, pbuffer,
- usize);
- if (*pbuffer == NULL) {
- pr_err("%s: error - Out of shared memory\n",
- __func__);
- status = -ENOMEM;
- }
- }
- }
-func_end:
- return status;
-}
-
-/*
- * ======== node_change_priority ========
- * Purpose:
- * Change the priority of a node in the allocated state, or that is
- * currently running or paused on the target.
- */
-int node_change_priority(struct node_object *hnode, s32 prio)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- struct node_mgr *hnode_mgr = NULL;
- enum node_type node_type;
- enum node_state state;
- int status = 0;
- u32 proc_id;
-
- if (!hnode || !hnode->node_mgr) {
- status = -EFAULT;
- } else {
- hnode_mgr = hnode->node_mgr;
- node_type = node_get_type(hnode);
- if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET)
- status = -EPERM;
- else if (prio < hnode_mgr->min_pri || prio > hnode_mgr->max_pri)
- status = -EDOM;
- }
- if (status)
- goto func_end;
-
- /* Enter critical section */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- state = node_get_state(hnode);
- if (state == NODE_ALLOCATED || state == NODE_PAUSED) {
- NODE_SET_PRIORITY(hnode, prio);
- } else {
- if (state != NODE_RUNNING) {
- status = -EBADR;
- goto func_cont;
- }
- status = proc_get_processor_id(pnode->processor, &proc_id);
- if (proc_id == DSP_UNIT) {
- status =
- disp_node_change_priority(hnode_mgr->disp_obj,
- hnode,
- hnode_mgr->fxn_addrs
- [RMSCHANGENODEPRIORITY],
- hnode->node_env, prio);
- }
- if (status >= 0)
- NODE_SET_PRIORITY(hnode, prio);
-
- }
-func_cont:
- /* Leave critical section */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
-func_end:
- return status;
-}
-
-/*
- * ======== node_connect ========
- * Purpose:
- * Connect two nodes on the DSP, or a node on the DSP to the GPP.
- */
-int node_connect(struct node_object *node1, u32 stream1,
- struct node_object *node2,
- u32 stream2, struct dsp_strmattr *pattrs,
- struct dsp_cbdata *conn_param)
-{
- struct node_mgr *hnode_mgr;
- char *pstr_dev_name = NULL;
- enum node_type node1_type = NODE_TASK;
- enum node_type node2_type = NODE_TASK;
- enum dsp_strmmode strm_mode;
- struct node_strmdef *pstrm_def;
- struct node_strmdef *input = NULL;
- struct node_strmdef *output = NULL;
- struct node_object *dev_node_obj;
- struct node_object *hnode;
- struct stream_chnl *pstream;
- u32 pipe_id;
- u32 chnl_id;
- s8 chnl_mode;
- u32 dw_length;
- int status = 0;
-
- if (!node1 || !node2)
- return -EFAULT;
-
- /* The two nodes must be on the same processor */
- if (node1 != (struct node_object *)DSP_HGPPNODE &&
- node2 != (struct node_object *)DSP_HGPPNODE &&
- node1->node_mgr != node2->node_mgr)
- return -EPERM;
-
- /* Cannot connect a node to itself */
- if (node1 == node2)
- return -EPERM;
-
- /* node_get_type() will return NODE_GPP if hnode = DSP_HGPPNODE. */
- node1_type = node_get_type(node1);
- node2_type = node_get_type(node2);
- /* Check stream indices ranges */
- if ((node1_type != NODE_GPP && node1_type != NODE_DEVICE &&
- stream1 >= MAX_OUTPUTS(node1)) ||
- (node2_type != NODE_GPP && node2_type != NODE_DEVICE &&
- stream2 >= MAX_INPUTS(node2)))
- return -EINVAL;
-
- /*
- * Only the following types of connections are allowed:
- * task/dais socket < == > task/dais socket
- * task/dais socket < == > device
- * task/dais socket < == > GPP
- *
- * ie, no message nodes, and at least one task or dais
- * socket node.
- */
- if (node1_type == NODE_MESSAGE || node2_type == NODE_MESSAGE ||
- (node1_type != NODE_TASK &&
- node1_type != NODE_DAISSOCKET &&
- node2_type != NODE_TASK &&
- node2_type != NODE_DAISSOCKET))
- return -EPERM;
- /*
- * Check stream mode. Default is STRMMODE_PROCCOPY.
- */
- if (pattrs && pattrs->strm_mode != STRMMODE_PROCCOPY)
- return -EPERM; /* illegal stream mode */
-
- if (node1_type != NODE_GPP)
- hnode_mgr = node1->node_mgr;
- else
- hnode_mgr = node2->node_mgr;
-
- /* Enter critical section */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- /* Nodes must be in the allocated state */
- if (node1_type != NODE_GPP &&
- node_get_state(node1) != NODE_ALLOCATED) {
- status = -EBADR;
- goto out_unlock;
- }
-
- if (node2_type != NODE_GPP &&
- node_get_state(node2) != NODE_ALLOCATED) {
- status = -EBADR;
- goto out_unlock;
- }
-
- /*
- * Check that stream indices for task and dais socket nodes
- * are not already be used. (Device nodes checked later)
- */
- if (node1_type == NODE_TASK || node1_type == NODE_DAISSOCKET) {
- output = &(node1->create_args.asa.
- task_arg_obj.strm_out_def[stream1]);
- if (output->sz_device) {
- status = -EISCONN;
- goto out_unlock;
- }
-
- }
- if (node2_type == NODE_TASK || node2_type == NODE_DAISSOCKET) {
- input = &(node2->create_args.asa.
- task_arg_obj.strm_in_def[stream2]);
- if (input->sz_device) {
- status = -EISCONN;
- goto out_unlock;
- }
-
- }
- /* Connecting two task nodes? */
- if ((node1_type == NODE_TASK || node1_type == NODE_DAISSOCKET) &&
- (node2_type == NODE_TASK ||
- node2_type == NODE_DAISSOCKET)) {
- /* Find available pipe */
- pipe_id = find_first_zero_bit(hnode_mgr->pipe_map, MAXPIPES);
- if (pipe_id == MAXPIPES) {
- status = -ECONNREFUSED;
- goto out_unlock;
- }
- set_bit(pipe_id, hnode_mgr->pipe_map);
- node1->outputs[stream1].type = NODECONNECT;
- node2->inputs[stream2].type = NODECONNECT;
- node1->outputs[stream1].dev_id = pipe_id;
- node2->inputs[stream2].dev_id = pipe_id;
- output->sz_device = kzalloc(PIPENAMELEN + 1, GFP_KERNEL);
- input->sz_device = kzalloc(PIPENAMELEN + 1, GFP_KERNEL);
- if (!output->sz_device || !input->sz_device) {
- /* Undo the connection */
- kfree(output->sz_device);
- kfree(input->sz_device);
- clear_bit(pipe_id, hnode_mgr->pipe_map);
- status = -ENOMEM;
- goto out_unlock;
- }
- /* Copy "/dbpipe<pipId>" name to device names */
- sprintf(output->sz_device, "%s%d", PIPEPREFIX, pipe_id);
- strcpy(input->sz_device, output->sz_device);
- }
- /* Connecting task node to host? */
- if (node1_type == NODE_GPP || node2_type == NODE_GPP) {
- pstr_dev_name = kzalloc(HOSTNAMELEN + 1, GFP_KERNEL);
- if (!pstr_dev_name) {
- status = -ENOMEM;
- goto out_unlock;
- }
-
- chnl_mode = (node1_type == NODE_GPP) ?
- CHNL_MODETODSP : CHNL_MODEFROMDSP;
-
- /*
- * Reserve a channel id. We need to put the name "/host<id>"
- * in the node's create_args, but the host
- * side channel will not be opened until DSPStream_Open is
- * called for this node.
- */
- strm_mode = pattrs ? pattrs->strm_mode : STRMMODE_PROCCOPY;
- switch (strm_mode) {
- case STRMMODE_RDMA:
- chnl_id = find_first_zero_bit(hnode_mgr->dma_chnl_map,
- CHNL_MAXCHANNELS);
- if (chnl_id < CHNL_MAXCHANNELS) {
- set_bit(chnl_id, hnode_mgr->dma_chnl_map);
- /* dma chans are 2nd transport chnl set
- * ids(e.g. 16-31) */
- chnl_id = chnl_id + hnode_mgr->num_chnls;
- }
- break;
- case STRMMODE_ZEROCOPY:
- chnl_id = find_first_zero_bit(hnode_mgr->zc_chnl_map,
- CHNL_MAXCHANNELS);
- if (chnl_id < CHNL_MAXCHANNELS) {
- set_bit(chnl_id, hnode_mgr->zc_chnl_map);
- /* zero-copy chans are 3nd transport set
- * (e.g. 32-47) */
- chnl_id = chnl_id +
- (2 * hnode_mgr->num_chnls);
- }
- break;
- case STRMMODE_PROCCOPY:
- chnl_id = find_first_zero_bit(hnode_mgr->chnl_map,
- CHNL_MAXCHANNELS);
- if (chnl_id < CHNL_MAXCHANNELS)
- set_bit(chnl_id, hnode_mgr->chnl_map);
- break;
- default:
- status = -EINVAL;
- goto out_unlock;
- }
- if (chnl_id == CHNL_MAXCHANNELS) {
- status = -ECONNREFUSED;
- goto out_unlock;
- }
-
- if (node1 == (struct node_object *)DSP_HGPPNODE) {
- node2->inputs[stream2].type = HOSTCONNECT;
- node2->inputs[stream2].dev_id = chnl_id;
- input->sz_device = pstr_dev_name;
- } else {
- node1->outputs[stream1].type = HOSTCONNECT;
- node1->outputs[stream1].dev_id = chnl_id;
- output->sz_device = pstr_dev_name;
- }
- sprintf(pstr_dev_name, "%s%d", HOSTPREFIX, chnl_id);
- }
- /* Connecting task node to device node? */
- if ((node1_type == NODE_DEVICE) || (node2_type == NODE_DEVICE)) {
- if (node2_type == NODE_DEVICE) {
- /* node1 == > device */
- dev_node_obj = node2;
- hnode = node1;
- pstream = &(node1->outputs[stream1]);
- pstrm_def = output;
- } else {
- /* device == > node2 */
- dev_node_obj = node1;
- hnode = node2;
- pstream = &(node2->inputs[stream2]);
- pstrm_def = input;
- }
- /* Set up create args */
- pstream->type = DEVICECONNECT;
- dw_length = strlen(dev_node_obj->str_dev_name);
- if (conn_param)
- pstrm_def->sz_device = kzalloc(dw_length + 1 +
- conn_param->cb_data,
- GFP_KERNEL);
- else
- pstrm_def->sz_device = kzalloc(dw_length + 1,
- GFP_KERNEL);
- if (!pstrm_def->sz_device) {
- status = -ENOMEM;
- goto out_unlock;
- }
- /* Copy device name */
- strncpy(pstrm_def->sz_device,
- dev_node_obj->str_dev_name, dw_length);
- if (conn_param)
- strncat(pstrm_def->sz_device,
- (char *)conn_param->node_data,
- (u32) conn_param->cb_data);
- dev_node_obj->device_owner = hnode;
- }
- /* Fill in create args */
- if (node1_type == NODE_TASK || node1_type == NODE_DAISSOCKET) {
- node1->create_args.asa.task_arg_obj.num_outputs++;
- fill_stream_def(node1, output, pattrs);
- }
- if (node2_type == NODE_TASK || node2_type == NODE_DAISSOCKET) {
- node2->create_args.asa.task_arg_obj.num_inputs++;
- fill_stream_def(node2, input, pattrs);
- }
- /* Update node1 and node2 stream_connect */
- if (node1_type != NODE_GPP && node1_type != NODE_DEVICE) {
- node1->num_outputs++;
- if (stream1 > node1->max_output_index)
- node1->max_output_index = stream1;
-
- }
- if (node2_type != NODE_GPP && node2_type != NODE_DEVICE) {
- node2->num_inputs++;
- if (stream2 > node2->max_input_index)
- node2->max_input_index = stream2;
-
- }
- fill_stream_connect(node1, node2, stream1, stream2);
- /* end of sync_enter_cs */
- /* Exit critical section */
-out_unlock:
- if (status && pstr_dev_name)
- kfree(pstr_dev_name);
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- dev_dbg(bridge, "%s: node1: %p stream1: %d node2: %p stream2: %d"
- "pattrs: %p status: 0x%x\n", __func__, node1,
- stream1, node2, stream2, pattrs, status);
- return status;
-}
-
-/*
- * ======== node_create ========
- * Purpose:
- * Create a node on the DSP by remotely calling the node's create function.
- */
-int node_create(struct node_object *hnode)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- struct node_mgr *hnode_mgr;
- struct bridge_drv_interface *intf_fxns;
- u32 ul_create_fxn;
- enum node_type node_type;
- int status = 0;
- int status1 = 0;
- struct dsp_cbdata cb_data;
- u32 proc_id = 255;
- struct dsp_processorstate proc_state;
- struct proc_object *hprocessor;
-#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
- struct dspbridge_platform_data *pdata =
- omap_dspbridge_dev->dev.platform_data;
-#endif
-
- if (!pnode) {
- status = -EFAULT;
- goto func_end;
- }
- hprocessor = hnode->processor;
- status = proc_get_state(hprocessor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_end;
- /* If processor is in error state then don't attempt to create
- new node */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_end;
- }
- /* create struct dsp_cbdata struct for PWR calls */
- cb_data.cb_data = PWR_TIMEOUT;
- node_type = node_get_type(hnode);
- hnode_mgr = hnode->node_mgr;
- intf_fxns = hnode_mgr->intf_fxns;
- /* Get access to node dispatcher */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- /* Check node state */
- if (node_get_state(hnode) != NODE_ALLOCATED)
- status = -EBADR;
-
- if (!status)
- status = proc_get_processor_id(pnode->processor, &proc_id);
-
- if (status)
- goto func_cont2;
-
- if (proc_id != DSP_UNIT)
- goto func_cont2;
-
- /* Make sure streams are properly connected */
- if ((hnode->num_inputs && hnode->max_input_index >
- hnode->num_inputs - 1) ||
- (hnode->num_outputs && hnode->max_output_index >
- hnode->num_outputs - 1))
- status = -ENOTCONN;
-
- if (!status) {
- /* If node's create function is not loaded, load it */
- /* Boost the OPP level to max level that DSP can be requested */
-#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
- if (pdata->cpu_set_freq)
- (*pdata->cpu_set_freq) (pdata->mpu_speed[VDD1_OPP3]);
-#endif
- status = hnode_mgr->nldr_fxns.load(hnode->nldr_node_obj,
- NLDR_CREATE);
- /* Get address of node's create function */
- if (!status) {
- hnode->loaded = true;
- if (node_type != NODE_DEVICE) {
- status = get_fxn_address(hnode, &ul_create_fxn,
- CREATEPHASE);
- }
- } else {
- pr_err("%s: failed to load create code: 0x%x\n",
- __func__, status);
- }
- /* Request the lowest OPP level */
-#if defined(CONFIG_TIDSPBRIDGE_DVFS) && !defined(CONFIG_CPU_FREQ)
- if (pdata->cpu_set_freq)
- (*pdata->cpu_set_freq) (pdata->mpu_speed[VDD1_OPP1]);
-#endif
- /* Get address of iAlg functions, if socket node */
- if (!status) {
- if (node_type == NODE_DAISSOCKET) {
- status = hnode_mgr->nldr_fxns.get_fxn_addr
- (hnode->nldr_node_obj,
- hnode->dcd_props.obj_data.node_obj.
- str_i_alg_name,
- &hnode->create_args.asa.
- task_arg_obj.dais_arg);
- }
- }
- }
- if (!status) {
- if (node_type != NODE_DEVICE) {
- status = disp_node_create(hnode_mgr->disp_obj, hnode,
- hnode_mgr->fxn_addrs
- [RMSCREATENODE],
- ul_create_fxn,
- &(hnode->create_args),
- &(hnode->node_env));
- if (status >= 0) {
- /* Set the message queue id to the node env
- * pointer */
- intf_fxns = hnode_mgr->intf_fxns;
- (*intf_fxns->msg_set_queue_id) (hnode->
- msg_queue_obj,
- hnode->node_env);
- }
- }
- }
- /* Phase II/Overlays: Create, execute, delete phases possibly in
- * different files/sections. */
- if (hnode->loaded && hnode->phase_split) {
- /* If create code was dynamically loaded, we can now unload
- * it. */
- status1 = hnode_mgr->nldr_fxns.unload(hnode->nldr_node_obj,
- NLDR_CREATE);
- hnode->loaded = false;
- }
- if (status1)
- pr_err("%s: Failed to unload create code: 0x%x\n",
- __func__, status1);
-func_cont2:
- /* Update node state and node manager state */
- if (status >= 0) {
- NODE_SET_STATE(hnode, NODE_CREATED);
- hnode_mgr->num_created++;
- goto func_cont;
- }
- if (status != -EBADR) {
- /* Put back in NODE_ALLOCATED state if error occurred */
- NODE_SET_STATE(hnode, NODE_ALLOCATED);
- }
-func_cont:
- /* Free access to node dispatcher */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
-func_end:
- if (status >= 0) {
- proc_notify_clients(hnode->processor, DSP_NODESTATECHANGE);
- ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
- }
-
- dev_dbg(bridge, "%s: hnode: %p status: 0x%x\n", __func__,
- hnode, status);
- return status;
-}
-
-/*
- * ======== node_create_mgr ========
- * Purpose:
- * Create a NODE Manager object.
- */
-int node_create_mgr(struct node_mgr **node_man,
- struct dev_object *hdev_obj)
-{
- u32 i;
- struct node_mgr *node_mgr_obj = NULL;
- struct disp_attr disp_attr_obj;
- char *sz_zl_file = "";
- struct nldr_attrs nldr_attrs_obj;
- int status = 0;
- u8 dev_type;
-
- *node_man = NULL;
- /* Allocate Node manager object */
- node_mgr_obj = kzalloc(sizeof(struct node_mgr), GFP_KERNEL);
- if (!node_mgr_obj)
- return -ENOMEM;
-
- node_mgr_obj->dev_obj = hdev_obj;
-
- node_mgr_obj->ntfy_obj = kmalloc(sizeof(struct ntfy_object),
- GFP_KERNEL);
- if (!node_mgr_obj->ntfy_obj) {
- status = -ENOMEM;
- goto out_err;
- }
- ntfy_init(node_mgr_obj->ntfy_obj);
-
- INIT_LIST_HEAD(&node_mgr_obj->node_list);
-
- dev_get_dev_type(hdev_obj, &dev_type);
-
- status = dcd_create_manager(sz_zl_file, &node_mgr_obj->dcd_mgr);
- if (status)
- goto out_err;
-
- status = get_proc_props(node_mgr_obj, hdev_obj);
- if (status)
- goto out_err;
-
- /* Create NODE Dispatcher */
- disp_attr_obj.chnl_offset = node_mgr_obj->chnl_offset;
- disp_attr_obj.chnl_buf_size = node_mgr_obj->chnl_buf_size;
- disp_attr_obj.proc_family = node_mgr_obj->proc_family;
- disp_attr_obj.proc_type = node_mgr_obj->proc_type;
-
- status = disp_create(&node_mgr_obj->disp_obj, hdev_obj, &disp_attr_obj);
- if (status)
- goto out_err;
-
- /* Create a STRM Manager */
- status = strm_create(&node_mgr_obj->strm_mgr_obj, hdev_obj);
- if (status)
- goto out_err;
-
- dev_get_intf_fxns(hdev_obj, &node_mgr_obj->intf_fxns);
- /* Get msg_ctrl queue manager */
- dev_get_msg_mgr(hdev_obj, &node_mgr_obj->msg_mgr_obj);
- mutex_init(&node_mgr_obj->node_mgr_lock);
-
- /* Block out reserved channels */
- for (i = 0; i < node_mgr_obj->chnl_offset; i++)
- set_bit(i, node_mgr_obj->chnl_map);
-
- /* Block out channels reserved for RMS */
- set_bit(node_mgr_obj->chnl_offset, node_mgr_obj->chnl_map);
- set_bit(node_mgr_obj->chnl_offset + 1, node_mgr_obj->chnl_map);
-
- /* NO RM Server on the IVA */
- if (dev_type != IVA_UNIT) {
- /* Get addresses of any RMS functions loaded */
- status = get_rms_fxns(node_mgr_obj);
- if (status)
- goto out_err;
- }
-
- /* Get loader functions and create loader */
- node_mgr_obj->nldr_fxns = nldr_fxns; /* Dyn loader funcs */
-
- nldr_attrs_obj.ovly = ovly;
- nldr_attrs_obj.write = mem_write;
- nldr_attrs_obj.dsp_word_size = node_mgr_obj->dsp_word_size;
- nldr_attrs_obj.dsp_mau_size = node_mgr_obj->dsp_mau_size;
- status = node_mgr_obj->nldr_fxns.create(&node_mgr_obj->nldr_obj,
- hdev_obj,
- &nldr_attrs_obj);
- if (status)
- goto out_err;
-
- *node_man = node_mgr_obj;
-
- return status;
-out_err:
- delete_node_mgr(node_mgr_obj);
- return status;
-}
-
-/*
- * ======== node_delete ========
- * Purpose:
- * Delete a node on the DSP by remotely calling the node's delete function.
- * Loads the node's delete function if necessary. Free GPP side resources
- * after node's delete function returns.
- */
-int node_delete(struct node_res_object *noderes,
- struct process_context *pr_ctxt)
-{
- struct node_object *pnode = noderes->node;
- struct node_mgr *hnode_mgr;
- struct proc_object *hprocessor;
- struct disp_object *disp_obj;
- u32 ul_delete_fxn;
- enum node_type node_type;
- enum node_state state;
- int status = 0;
- int status1 = 0;
- struct dsp_cbdata cb_data;
- u32 proc_id;
- struct bridge_drv_interface *intf_fxns;
-
- void *node_res = noderes;
-
- struct dsp_processorstate proc_state;
-
- if (!pnode) {
- status = -EFAULT;
- goto func_end;
- }
- /* create struct dsp_cbdata struct for PWR call */
- cb_data.cb_data = PWR_TIMEOUT;
- hnode_mgr = pnode->node_mgr;
- hprocessor = pnode->processor;
- disp_obj = hnode_mgr->disp_obj;
- node_type = node_get_type(pnode);
- intf_fxns = hnode_mgr->intf_fxns;
- /* Enter critical section */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- state = node_get_state(pnode);
- /* Execute delete phase code for non-device node in all cases
- * except when the node was only allocated. Delete phase must be
- * executed even if create phase was executed, but failed.
- * If the node environment pointer is non-NULL, the delete phase
- * code must be executed. */
- if (!(state == NODE_ALLOCATED && pnode->node_env == (u32) NULL) &&
- node_type != NODE_DEVICE) {
- status = proc_get_processor_id(pnode->processor, &proc_id);
- if (status)
- goto func_cont1;
-
- if (proc_id == DSP_UNIT || proc_id == IVA_UNIT) {
- /* If node has terminated, execute phase code will
- * have already been unloaded in node_on_exit(). If the
- * node is PAUSED, the execute phase is loaded, and it
- * is now ok to unload it. If the node is running, we
- * will unload the execute phase only after deleting
- * the node. */
- if (state == NODE_PAUSED && pnode->loaded &&
- pnode->phase_split) {
- /* Ok to unload execute code as long as node
- * is not * running */
- status1 =
- hnode_mgr->nldr_fxns.
- unload(pnode->nldr_node_obj,
- NLDR_EXECUTE);
- pnode->loaded = false;
- NODE_SET_STATE(pnode, NODE_DONE);
- }
- /* Load delete phase code if not loaded or if haven't
- * * unloaded EXECUTE phase */
- if ((!(pnode->loaded) || (state == NODE_RUNNING)) &&
- pnode->phase_split) {
- status =
- hnode_mgr->nldr_fxns.
- load(pnode->nldr_node_obj, NLDR_DELETE);
- if (!status)
- pnode->loaded = true;
- else
- pr_err("%s: fail - load delete code:"
- " 0x%x\n", __func__, status);
- }
- }
-func_cont1:
- if (!status) {
- /* Unblock a thread trying to terminate the node */
- (void)sync_set_event(pnode->sync_done);
- if (proc_id == DSP_UNIT) {
- /* ul_delete_fxn = address of node's delete
- * function */
- status = get_fxn_address(pnode, &ul_delete_fxn,
- DELETEPHASE);
- } else if (proc_id == IVA_UNIT)
- ul_delete_fxn = (u32) pnode->node_env;
- if (!status) {
- status = proc_get_state(hprocessor,
- &proc_state,
- sizeof(struct
- dsp_processorstate));
- if (proc_state.proc_state != PROC_ERROR) {
- status =
- disp_node_delete(disp_obj, pnode,
- hnode_mgr->
- fxn_addrs
- [RMSDELETENODE],
- ul_delete_fxn,
- pnode->node_env);
- } else
- NODE_SET_STATE(pnode, NODE_DONE);
-
- /* Unload execute, if not unloaded, and delete
- * function */
- if (state == NODE_RUNNING &&
- pnode->phase_split) {
- status1 =
- hnode_mgr->nldr_fxns.
- unload(pnode->nldr_node_obj,
- NLDR_EXECUTE);
- }
- if (status1)
- pr_err("%s: fail - unload execute code:"
- " 0x%x\n", __func__, status1);
-
- status1 =
- hnode_mgr->nldr_fxns.unload(pnode->
- nldr_node_obj,
- NLDR_DELETE);
- pnode->loaded = false;
- if (status1)
- pr_err("%s: fail - unload delete code: "
- "0x%x\n", __func__, status1);
- }
- }
- }
- /* Free host side resources even if a failure occurred */
- /* Remove node from hnode_mgr->node_list */
- list_del(&pnode->list_elem);
- hnode_mgr->num_nodes--;
- /* Decrement count of nodes created on DSP */
- if ((state != NODE_ALLOCATED) || ((state == NODE_ALLOCATED) &&
- (pnode->node_env != (u32) NULL)))
- hnode_mgr->num_created--;
- /* Free host-side resources allocated by node_create()
- * delete_node() fails if SM buffers not freed by client! */
- drv_proc_node_update_status(node_res, false);
- delete_node(pnode, pr_ctxt);
-
- /*
- * Release all Node resources and its context
- */
- idr_remove(pr_ctxt->node_id, ((struct node_res_object *)node_res)->id);
- kfree(node_res);
-
- /* Exit critical section */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- proc_notify_clients(hprocessor, DSP_NODESTATECHANGE);
-func_end:
- dev_dbg(bridge, "%s: pnode: %p status 0x%x\n", __func__, pnode, status);
- return status;
-}
-
-/*
- * ======== node_delete_mgr ========
- * Purpose:
- * Delete the NODE Manager.
- */
-int node_delete_mgr(struct node_mgr *hnode_mgr)
-{
- if (!hnode_mgr)
- return -EFAULT;
-
- delete_node_mgr(hnode_mgr);
-
- return 0;
-}
-
-/*
- * ======== node_enum_nodes ========
- * Purpose:
- * Enumerate currently allocated nodes.
- */
-int node_enum_nodes(struct node_mgr *hnode_mgr, void **node_tab,
- u32 node_tab_size, u32 *pu_num_nodes,
- u32 *pu_allocated)
-{
- struct node_object *hnode;
- u32 i = 0;
- int status = 0;
-
- if (!hnode_mgr) {
- status = -EFAULT;
- goto func_end;
- }
- /* Enter critical section */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- if (hnode_mgr->num_nodes > node_tab_size) {
- *pu_allocated = hnode_mgr->num_nodes;
- *pu_num_nodes = 0;
- status = -EINVAL;
- } else {
- list_for_each_entry(hnode, &hnode_mgr->node_list, list_elem)
- node_tab[i++] = hnode;
- *pu_allocated = *pu_num_nodes = hnode_mgr->num_nodes;
- }
- /* end of sync_enter_cs */
- /* Exit critical section */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
-func_end:
- return status;
-}
-
-/*
- * ======== node_free_msg_buf ========
- * Purpose:
- * Frees the message buffer.
- */
-int node_free_msg_buf(struct node_object *hnode, u8 *pbuffer,
- struct dsp_bufferattr *pattr)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- int status = 0;
- u32 proc_id;
-
- if (!hnode) {
- status = -EFAULT;
- goto func_end;
- }
- status = proc_get_processor_id(pnode->processor, &proc_id);
- if (proc_id == DSP_UNIT) {
- if (!status) {
- if (pattr == NULL) {
- /* set defaults */
- pattr = &node_dfltbufattrs;
- }
- /* Node supports single SM segment only */
- if (pattr->segment_id != 1)
- status = -EBADR;
-
- /* pbuffer is clients Va. */
- status = cmm_xlator_free_buf(pnode->xlator, pbuffer);
- }
- } else {
- }
-func_end:
- return status;
-}
-
-/*
- * ======== node_get_attr ========
- * Purpose:
- * Copy the current attributes of the specified node into a dsp_nodeattr
- * structure.
- */
-int node_get_attr(struct node_object *hnode,
- struct dsp_nodeattr *pattr, u32 attr_size)
-{
- struct node_mgr *hnode_mgr;
-
- if (!hnode)
- return -EFAULT;
-
- hnode_mgr = hnode->node_mgr;
- /* Enter hnode_mgr critical section since we're accessing
- * data that could be changed by node_change_priority() and
- * node_connect(). */
- mutex_lock(&hnode_mgr->node_mgr_lock);
- pattr->cb_struct = sizeof(struct dsp_nodeattr);
- /* dsp_nodeattrin */
- pattr->in_node_attr_in.cb_struct =
- sizeof(struct dsp_nodeattrin);
- pattr->in_node_attr_in.prio = hnode->prio;
- pattr->in_node_attr_in.timeout = hnode->timeout;
- pattr->in_node_attr_in.heap_size =
- hnode->create_args.asa.task_arg_obj.heap_size;
- pattr->in_node_attr_in.pgpp_virt_addr = (void *)
- hnode->create_args.asa.task_arg_obj.gpp_heap_addr;
- pattr->node_attr_inputs = hnode->num_gpp_inputs;
- pattr->node_attr_outputs = hnode->num_gpp_outputs;
- /* dsp_nodeinfo */
- get_node_info(hnode, &(pattr->node_info));
- /* end of sync_enter_cs */
- /* Exit critical section */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
-
- return 0;
-}
-
-/*
- * ======== node_get_channel_id ========
- * Purpose:
- * Get the channel index reserved for a stream connection between the
- * host and a node.
- */
-int node_get_channel_id(struct node_object *hnode, u32 dir, u32 index,
- u32 *chan_id)
-{
- enum node_type node_type;
- int status = -EINVAL;
-
- if (!hnode) {
- status = -EFAULT;
- return status;
- }
- node_type = node_get_type(hnode);
- if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET) {
- status = -EPERM;
- return status;
- }
- if (dir == DSP_TONODE) {
- if (index < MAX_INPUTS(hnode)) {
- if (hnode->inputs[index].type == HOSTCONNECT) {
- *chan_id = hnode->inputs[index].dev_id;
- status = 0;
- }
- }
- } else {
- if (index < MAX_OUTPUTS(hnode)) {
- if (hnode->outputs[index].type == HOSTCONNECT) {
- *chan_id = hnode->outputs[index].dev_id;
- status = 0;
- }
- }
- }
- return status;
-}
-
-/*
- * ======== node_get_message ========
- * Purpose:
- * Retrieve a message from a node on the DSP.
- */
-int node_get_message(struct node_object *hnode,
- struct dsp_msg *message, u32 utimeout)
-{
- struct node_mgr *hnode_mgr;
- enum node_type node_type;
- struct bridge_drv_interface *intf_fxns;
- int status = 0;
- void *tmp_buf;
- struct dsp_processorstate proc_state;
- struct proc_object *hprocessor;
-
- if (!hnode) {
- status = -EFAULT;
- goto func_end;
- }
- hprocessor = hnode->processor;
- status = proc_get_state(hprocessor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_end;
- /* If processor is in error state then don't attempt to get the
- message */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_end;
- }
- hnode_mgr = hnode->node_mgr;
- node_type = node_get_type(hnode);
- if (node_type != NODE_MESSAGE && node_type != NODE_TASK &&
- node_type != NODE_DAISSOCKET) {
- status = -EPERM;
- goto func_end;
- }
- /* This function will block unless a message is available. Since
- * DSPNode_RegisterNotify() allows notification when a message
- * is available, the system can be designed so that
- * DSPNode_GetMessage() is only called when a message is
- * available. */
- intf_fxns = hnode_mgr->intf_fxns;
- status =
- (*intf_fxns->msg_get) (hnode->msg_queue_obj, message, utimeout);
- /* Check if message contains SM descriptor */
- if (status || !(message->cmd & DSP_RMSBUFDESC))
- goto func_end;
-
- /* Translate DSP byte addr to GPP Va. */
- tmp_buf = cmm_xlator_translate(hnode->xlator,
- (void *)(message->arg1 *
- hnode->node_mgr->
- dsp_word_size), CMM_DSPPA2PA);
- if (tmp_buf != NULL) {
- /* now convert this GPP Pa to Va */
- tmp_buf = cmm_xlator_translate(hnode->xlator, tmp_buf,
- CMM_PA2VA);
- if (tmp_buf != NULL) {
- /* Adjust SM size in msg */
- message->arg1 = (u32) tmp_buf;
- message->arg2 *= hnode->node_mgr->dsp_word_size;
- } else {
- status = -ESRCH;
- }
- } else {
- status = -ESRCH;
- }
-func_end:
- dev_dbg(bridge, "%s: hnode: %p message: %p utimeout: 0x%x\n", __func__,
- hnode, message, utimeout);
- return status;
-}
-
-/*
- * ======== node_get_nldr_obj ========
- */
-int node_get_nldr_obj(struct node_mgr *hnode_mgr,
- struct nldr_object **nldr_ovlyobj)
-{
- int status = 0;
- struct node_mgr *node_mgr_obj = hnode_mgr;
-
- if (!hnode_mgr)
- status = -EFAULT;
- else
- *nldr_ovlyobj = node_mgr_obj->nldr_obj;
-
- return status;
-}
-
-/*
- * ======== node_get_strm_mgr ========
- * Purpose:
- * Returns the Stream manager.
- */
-int node_get_strm_mgr(struct node_object *hnode,
- struct strm_mgr **strm_man)
-{
- int status = 0;
-
- if (!hnode)
- status = -EFAULT;
- else
- *strm_man = hnode->node_mgr->strm_mgr_obj;
-
- return status;
-}
-
-/*
- * ======== node_get_load_type ========
- */
-enum nldr_loadtype node_get_load_type(struct node_object *hnode)
-{
- if (!hnode) {
- dev_dbg(bridge, "%s: Failed. hnode: %p\n", __func__, hnode);
- return -1;
- } else {
- return hnode->dcd_props.obj_data.node_obj.load_type;
- }
-}
-
-/*
- * ======== node_get_timeout ========
- * Purpose:
- * Returns the timeout value for this node.
- */
-u32 node_get_timeout(struct node_object *hnode)
-{
- if (!hnode) {
- dev_dbg(bridge, "%s: failed. hnode: %p\n", __func__, hnode);
- return 0;
- } else {
- return hnode->timeout;
- }
-}
-
-/*
- * ======== node_get_type ========
- * Purpose:
- * Returns the node type.
- */
-enum node_type node_get_type(struct node_object *hnode)
-{
- enum node_type node_type;
-
- if (hnode == (struct node_object *)DSP_HGPPNODE)
- node_type = NODE_GPP;
- else {
- if (!hnode)
- node_type = -1;
- else
- node_type = hnode->ntype;
- }
- return node_type;
-}
-
-/*
- * ======== node_on_exit ========
- * Purpose:
- * Gets called when RMS_EXIT is received for a node.
- */
-void node_on_exit(struct node_object *hnode, s32 node_status)
-{
- if (!hnode)
- return;
-
- /* Set node state to done */
- NODE_SET_STATE(hnode, NODE_DONE);
- hnode->exit_status = node_status;
- if (hnode->loaded && hnode->phase_split) {
- (void)hnode->node_mgr->nldr_fxns.unload(hnode->
- nldr_node_obj,
- NLDR_EXECUTE);
- hnode->loaded = false;
- }
- /* Unblock call to node_terminate */
- (void)sync_set_event(hnode->sync_done);
- /* Notify clients */
- proc_notify_clients(hnode->processor, DSP_NODESTATECHANGE);
- ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
-}
-
-/*
- * ======== node_pause ========
- * Purpose:
- * Suspend execution of a node currently running on the DSP.
- */
-int node_pause(struct node_object *hnode)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- enum node_type node_type;
- enum node_state state;
- struct node_mgr *hnode_mgr;
- int status = 0;
- u32 proc_id;
- struct dsp_processorstate proc_state;
- struct proc_object *hprocessor;
-
- if (!hnode) {
- status = -EFAULT;
- } else {
- node_type = node_get_type(hnode);
- if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET)
- status = -EPERM;
- }
- if (status)
- goto func_end;
-
- status = proc_get_processor_id(pnode->processor, &proc_id);
-
- if (proc_id == IVA_UNIT)
- status = -ENOSYS;
-
- if (!status) {
- hnode_mgr = hnode->node_mgr;
-
- /* Enter critical section */
- mutex_lock(&hnode_mgr->node_mgr_lock);
- state = node_get_state(hnode);
- /* Check node state */
- if (state != NODE_RUNNING)
- status = -EBADR;
-
- if (status)
- goto func_cont;
- hprocessor = hnode->processor;
- status = proc_get_state(hprocessor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_cont;
- /* If processor is in error state then don't attempt
- to send the message */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_cont;
- }
-
- status = disp_node_change_priority(hnode_mgr->disp_obj, hnode,
- hnode_mgr->fxn_addrs[RMSCHANGENODEPRIORITY],
- hnode->node_env, NODE_SUSPENDEDPRI);
-
- /* Update state */
- if (status >= 0)
- NODE_SET_STATE(hnode, NODE_PAUSED);
-
-func_cont:
- /* End of sync_enter_cs */
- /* Leave critical section */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- if (status >= 0) {
- proc_notify_clients(hnode->processor,
- DSP_NODESTATECHANGE);
- ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
- }
- }
-func_end:
- dev_dbg(bridge, "%s: hnode: %p status 0x%x\n", __func__, hnode, status);
- return status;
-}
-
-/*
- * ======== node_put_message ========
- * Purpose:
- * Send a message to a message node, task node, or XDAIS socket node. This
- * function will block until the message stream can accommodate the
- * message, or a timeout occurs.
- */
-int node_put_message(struct node_object *hnode,
- const struct dsp_msg *pmsg, u32 utimeout)
-{
- struct node_mgr *hnode_mgr = NULL;
- enum node_type node_type;
- struct bridge_drv_interface *intf_fxns;
- enum node_state state;
- int status = 0;
- void *tmp_buf;
- struct dsp_msg new_msg;
- struct dsp_processorstate proc_state;
- struct proc_object *hprocessor;
-
- if (!hnode) {
- status = -EFAULT;
- goto func_end;
- }
- hprocessor = hnode->processor;
- status = proc_get_state(hprocessor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_end;
- /* If processor is in bad state then don't attempt sending the
- message */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_end;
- }
- hnode_mgr = hnode->node_mgr;
- node_type = node_get_type(hnode);
- if (node_type != NODE_MESSAGE && node_type != NODE_TASK &&
- node_type != NODE_DAISSOCKET)
- status = -EPERM;
-
- if (!status) {
- /* Check node state. Can't send messages to a node after
- * we've sent the RMS_EXIT command. There is still the
- * possibility that node_terminate can be called after we've
- * checked the state. Could add another SYNC object to
- * prevent this (can't use node_mgr_lock, since we don't
- * want to block other NODE functions). However, the node may
- * still exit on its own, before this message is sent. */
- mutex_lock(&hnode_mgr->node_mgr_lock);
- state = node_get_state(hnode);
- if (state == NODE_TERMINATING || state == NODE_DONE)
- status = -EBADR;
-
- /* end of sync_enter_cs */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- }
- if (status)
- goto func_end;
-
- /* assign pmsg values to new msg */
- new_msg = *pmsg;
- /* Now, check if message contains a SM buffer descriptor */
- if (pmsg->cmd & DSP_RMSBUFDESC) {
- /* Translate GPP Va to DSP physical buf Ptr. */
- tmp_buf = cmm_xlator_translate(hnode->xlator,
- (void *)new_msg.arg1,
- CMM_VA2DSPPA);
- if (tmp_buf != NULL) {
- /* got translation, convert to MAUs in msg */
- if (hnode->node_mgr->dsp_word_size != 0) {
- new_msg.arg1 =
- (u32) tmp_buf /
- hnode->node_mgr->dsp_word_size;
- /* MAUs */
- new_msg.arg2 /= hnode->node_mgr->
- dsp_word_size;
- } else {
- pr_err("%s: dsp_word_size is zero!\n",
- __func__);
- status = -EPERM; /* bad DSPWordSize */
- }
- } else { /* failed to translate buffer address */
- status = -ESRCH;
- }
- }
- if (!status) {
- intf_fxns = hnode_mgr->intf_fxns;
- status = (*intf_fxns->msg_put) (hnode->msg_queue_obj,
- &new_msg, utimeout);
- }
-func_end:
- dev_dbg(bridge, "%s: hnode: %p pmsg: %p utimeout: 0x%x, "
- "status 0x%x\n", __func__, hnode, pmsg, utimeout, status);
- return status;
-}
-
-/*
- * ======== node_register_notify ========
- * Purpose:
- * Register to be notified on specific events for this node.
- */
-int node_register_notify(struct node_object *hnode, u32 event_mask,
- u32 notify_type,
- struct dsp_notification *hnotification)
-{
- struct bridge_drv_interface *intf_fxns;
- int status = 0;
-
- if (!hnode) {
- status = -EFAULT;
- } else {
- /* Check if event mask is a valid node related event */
- if (event_mask & ~(DSP_NODESTATECHANGE | DSP_NODEMESSAGEREADY))
- status = -EINVAL;
-
- /* Check if notify type is valid */
- if (notify_type != DSP_SIGNALEVENT)
- status = -EINVAL;
-
- /* Only one Notification can be registered at a
- * time - Limitation */
- if (event_mask == (DSP_NODESTATECHANGE | DSP_NODEMESSAGEREADY))
- status = -EINVAL;
- }
- if (!status) {
- if (event_mask == DSP_NODESTATECHANGE) {
- status = ntfy_register(hnode->ntfy_obj, hnotification,
- event_mask & DSP_NODESTATECHANGE,
- notify_type);
- } else {
- /* Send Message part of event mask to msg_ctrl */
- intf_fxns = hnode->node_mgr->intf_fxns;
- status = (*intf_fxns->msg_register_notify)
- (hnode->msg_queue_obj,
- event_mask & DSP_NODEMESSAGEREADY, notify_type,
- hnotification);
- }
-
- }
- dev_dbg(bridge, "%s: hnode: %p event_mask: 0x%x notify_type: 0x%x "
- "hnotification: %p status 0x%x\n", __func__, hnode,
- event_mask, notify_type, hnotification, status);
- return status;
-}
-
-/*
- * ======== node_run ========
- * Purpose:
- * Start execution of a node's execute phase, or resume execution of a node
- * that has been suspended (via NODE_NodePause()) on the DSP. Load the
- * node's execute function if necessary.
- */
-int node_run(struct node_object *hnode)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- struct node_mgr *hnode_mgr;
- enum node_type node_type;
- enum node_state state;
- u32 ul_execute_fxn;
- u32 ul_fxn_addr;
- int status = 0;
- u32 proc_id;
- struct bridge_drv_interface *intf_fxns;
- struct dsp_processorstate proc_state;
- struct proc_object *hprocessor;
-
- if (!hnode) {
- status = -EFAULT;
- goto func_end;
- }
- hprocessor = hnode->processor;
- status = proc_get_state(hprocessor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_end;
- /* If processor is in error state then don't attempt to run the node */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_end;
- }
- node_type = node_get_type(hnode);
- if (node_type == NODE_DEVICE)
- status = -EPERM;
- if (status)
- goto func_end;
-
- hnode_mgr = hnode->node_mgr;
- if (!hnode_mgr) {
- status = -EFAULT;
- goto func_end;
- }
- intf_fxns = hnode_mgr->intf_fxns;
- /* Enter critical section */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- state = node_get_state(hnode);
- if (state != NODE_CREATED && state != NODE_PAUSED)
- status = -EBADR;
-
- if (!status)
- status = proc_get_processor_id(pnode->processor, &proc_id);
-
- if (status)
- goto func_cont1;
-
- if ((proc_id != DSP_UNIT) && (proc_id != IVA_UNIT))
- goto func_cont1;
-
- if (state == NODE_CREATED) {
- /* If node's execute function is not loaded, load it */
- if (!(hnode->loaded) && hnode->phase_split) {
- status =
- hnode_mgr->nldr_fxns.load(hnode->nldr_node_obj,
- NLDR_EXECUTE);
- if (!status) {
- hnode->loaded = true;
- } else {
- pr_err("%s: fail - load execute code: 0x%x\n",
- __func__, status);
- }
- }
- if (!status) {
- /* Get address of node's execute function */
- if (proc_id == IVA_UNIT)
- ul_execute_fxn = (u32) hnode->node_env;
- else {
- status = get_fxn_address(hnode, &ul_execute_fxn,
- EXECUTEPHASE);
- }
- }
- if (!status) {
- ul_fxn_addr = hnode_mgr->fxn_addrs[RMSEXECUTENODE];
- status =
- disp_node_run(hnode_mgr->disp_obj, hnode,
- ul_fxn_addr, ul_execute_fxn,
- hnode->node_env);
- }
- } else if (state == NODE_PAUSED) {
- ul_fxn_addr = hnode_mgr->fxn_addrs[RMSCHANGENODEPRIORITY];
- status = disp_node_change_priority(hnode_mgr->disp_obj, hnode,
- ul_fxn_addr, hnode->node_env,
- NODE_GET_PRIORITY(hnode));
- } else {
- /* We should never get here */
- }
-func_cont1:
- /* Update node state. */
- if (status >= 0)
- NODE_SET_STATE(hnode, NODE_RUNNING);
- else /* Set state back to previous value */
- NODE_SET_STATE(hnode, state);
- /*End of sync_enter_cs */
- /* Exit critical section */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- if (status >= 0) {
- proc_notify_clients(hnode->processor, DSP_NODESTATECHANGE);
- ntfy_notify(hnode->ntfy_obj, DSP_NODESTATECHANGE);
- }
-func_end:
- dev_dbg(bridge, "%s: hnode: %p status 0x%x\n", __func__, hnode, status);
- return status;
-}
-
-/*
- * ======== node_terminate ========
- * Purpose:
- * Signal a node running on the DSP that it should exit its execute phase
- * function.
- */
-int node_terminate(struct node_object *hnode, int *pstatus)
-{
- struct node_object *pnode = (struct node_object *)hnode;
- struct node_mgr *hnode_mgr = NULL;
- enum node_type node_type;
- struct bridge_drv_interface *intf_fxns;
- enum node_state state;
- struct dsp_msg msg, killmsg;
- int status = 0;
- u32 proc_id, kill_time_out;
- struct deh_mgr *hdeh_mgr;
- struct dsp_processorstate proc_state;
-
- if (!hnode || !hnode->node_mgr) {
- status = -EFAULT;
- goto func_end;
- }
- if (pnode->processor == NULL) {
- status = -EFAULT;
- goto func_end;
- }
- status = proc_get_processor_id(pnode->processor, &proc_id);
-
- if (!status) {
- hnode_mgr = hnode->node_mgr;
- node_type = node_get_type(hnode);
- if (node_type != NODE_TASK && node_type != NODE_DAISSOCKET)
- status = -EPERM;
- }
- if (!status) {
- /* Check node state */
- mutex_lock(&hnode_mgr->node_mgr_lock);
- state = node_get_state(hnode);
- if (state != NODE_RUNNING) {
- status = -EBADR;
- /* Set the exit status if node terminated on
- * its own. */
- if (state == NODE_DONE)
- *pstatus = hnode->exit_status;
-
- } else {
- NODE_SET_STATE(hnode, NODE_TERMINATING);
- }
- /* end of sync_enter_cs */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- }
- if (!status) {
- /*
- * Send exit message. Do not change state to NODE_DONE
- * here. That will be done in callback.
- */
- status = proc_get_state(pnode->processor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_cont;
- /* If processor is in error state then don't attempt to send
- * A kill task command */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_cont;
- }
-
- msg.cmd = RMS_EXIT;
- msg.arg1 = hnode->node_env;
- killmsg.cmd = RMS_KILLTASK;
- killmsg.arg1 = hnode->node_env;
- intf_fxns = hnode_mgr->intf_fxns;
-
- if (hnode->timeout > MAXTIMEOUT)
- kill_time_out = MAXTIMEOUT;
- else
- kill_time_out = (hnode->timeout) * 2;
-
- status = (*intf_fxns->msg_put) (hnode->msg_queue_obj, &msg,
- hnode->timeout);
- if (status)
- goto func_cont;
-
- /*
- * Wait on synchronization object that will be
- * posted in the callback on receiving RMS_EXIT
- * message, or by node_delete. Check for valid hnode,
- * in case posted by node_delete().
- */
- status = sync_wait_on_event(hnode->sync_done,
- kill_time_out / 2);
- if (status != ETIME)
- goto func_cont;
-
- status = (*intf_fxns->msg_put)(hnode->msg_queue_obj,
- &killmsg, hnode->timeout);
- if (status)
- goto func_cont;
- status = sync_wait_on_event(hnode->sync_done,
- kill_time_out / 2);
- if (status) {
- /*
- * Here it goes the part of the simulation of
- * the DSP exception.
- */
- dev_get_deh_mgr(hnode_mgr->dev_obj, &hdeh_mgr);
- if (!hdeh_mgr)
- goto func_cont;
-
- bridge_deh_notify(hdeh_mgr, DSP_SYSERROR,
- DSP_EXCEPTIONABORT);
- }
- }
-func_cont:
- if (!status) {
- /* Enter CS before getting exit status, in case node was
- * deleted. */
- mutex_lock(&hnode_mgr->node_mgr_lock);
- /* Make sure node wasn't deleted while we blocked */
- if (!hnode) {
- status = -EPERM;
- } else {
- *pstatus = hnode->exit_status;
- dev_dbg(bridge, "%s: hnode: %p env 0x%x status 0x%x\n",
- __func__, hnode, hnode->node_env, status);
- }
- mutex_unlock(&hnode_mgr->node_mgr_lock);
- } /*End of sync_enter_cs */
-func_end:
- return status;
-}
-
-/*
- * ======== delete_node ========
- * Purpose:
- * Free GPP resources allocated in node_allocate() or node_connect().
- */
-static void delete_node(struct node_object *hnode,
- struct process_context *pr_ctxt)
-{
- struct node_mgr *hnode_mgr;
- struct bridge_drv_interface *intf_fxns;
- u32 i;
- enum node_type node_type;
- struct stream_chnl stream;
- struct node_msgargs node_msg_args;
- struct node_taskargs task_arg_obj;
-#ifdef DSP_DMM_DEBUG
- struct dmm_object *dmm_mgr;
- struct proc_object *p_proc_object =
- (struct proc_object *)hnode->processor;
-#endif
- int status;
- if (!hnode)
- goto func_end;
- hnode_mgr = hnode->node_mgr;
- if (!hnode_mgr)
- goto func_end;
-
- node_type = node_get_type(hnode);
- if (node_type != NODE_DEVICE) {
- node_msg_args = hnode->create_args.asa.node_msg_args;
- kfree(node_msg_args.pdata);
-
- /* Free msg_ctrl queue */
- if (hnode->msg_queue_obj) {
- intf_fxns = hnode_mgr->intf_fxns;
- (*intf_fxns->msg_delete_queue) (hnode->
- msg_queue_obj);
- hnode->msg_queue_obj = NULL;
- }
-
- kfree(hnode->sync_done);
-
- /* Free all stream info */
- if (hnode->inputs) {
- for (i = 0; i < MAX_INPUTS(hnode); i++) {
- stream = hnode->inputs[i];
- free_stream(hnode_mgr, stream);
- }
- kfree(hnode->inputs);
- hnode->inputs = NULL;
- }
- if (hnode->outputs) {
- for (i = 0; i < MAX_OUTPUTS(hnode); i++) {
- stream = hnode->outputs[i];
- free_stream(hnode_mgr, stream);
- }
- kfree(hnode->outputs);
- hnode->outputs = NULL;
- }
- task_arg_obj = hnode->create_args.asa.task_arg_obj;
- if (task_arg_obj.strm_in_def) {
- for (i = 0; i < MAX_INPUTS(hnode); i++) {
- kfree(task_arg_obj.strm_in_def[i].sz_device);
- task_arg_obj.strm_in_def[i].sz_device = NULL;
- }
- kfree(task_arg_obj.strm_in_def);
- task_arg_obj.strm_in_def = NULL;
- }
- if (task_arg_obj.strm_out_def) {
- for (i = 0; i < MAX_OUTPUTS(hnode); i++) {
- kfree(task_arg_obj.strm_out_def[i].sz_device);
- task_arg_obj.strm_out_def[i].sz_device = NULL;
- }
- kfree(task_arg_obj.strm_out_def);
- task_arg_obj.strm_out_def = NULL;
- }
- if (task_arg_obj.dsp_heap_res_addr) {
- status = proc_un_map(hnode->processor, (void *)
- task_arg_obj.dsp_heap_addr,
- pr_ctxt);
-
- status = proc_un_reserve_memory(hnode->processor,
- (void *)
- task_arg_obj.
- dsp_heap_res_addr,
- pr_ctxt);
-#ifdef DSP_DMM_DEBUG
- status = dmm_get_handle(p_proc_object, &dmm_mgr);
- if (dmm_mgr)
- dmm_mem_map_dump(dmm_mgr);
- else
- status = DSP_EHANDLE;
-#endif
- }
- }
- if (node_type != NODE_MESSAGE) {
- kfree(hnode->stream_connect);
- hnode->stream_connect = NULL;
- }
- kfree(hnode->str_dev_name);
- hnode->str_dev_name = NULL;
-
- if (hnode->ntfy_obj) {
- ntfy_delete(hnode->ntfy_obj);
- kfree(hnode->ntfy_obj);
- hnode->ntfy_obj = NULL;
- }
-
- /* These were allocated in dcd_get_object_def (via node_allocate) */
- kfree(hnode->dcd_props.obj_data.node_obj.str_create_phase_fxn);
- hnode->dcd_props.obj_data.node_obj.str_create_phase_fxn = NULL;
-
- kfree(hnode->dcd_props.obj_data.node_obj.str_execute_phase_fxn);
- hnode->dcd_props.obj_data.node_obj.str_execute_phase_fxn = NULL;
-
- kfree(hnode->dcd_props.obj_data.node_obj.str_delete_phase_fxn);
- hnode->dcd_props.obj_data.node_obj.str_delete_phase_fxn = NULL;
-
- kfree(hnode->dcd_props.obj_data.node_obj.str_i_alg_name);
- hnode->dcd_props.obj_data.node_obj.str_i_alg_name = NULL;
-
- /* Free all SM address translator resources */
- kfree(hnode->xlator);
- kfree(hnode->nldr_node_obj);
- hnode->nldr_node_obj = NULL;
- hnode->node_mgr = NULL;
- kfree(hnode);
- hnode = NULL;
-func_end:
- return;
-}
-
-/*
- * ======== delete_node_mgr ========
- * Purpose:
- * Frees the node manager.
- */
-static void delete_node_mgr(struct node_mgr *hnode_mgr)
-{
- struct node_object *hnode, *tmp;
-
- if (hnode_mgr) {
- /* Free resources */
- if (hnode_mgr->dcd_mgr)
- dcd_destroy_manager(hnode_mgr->dcd_mgr);
-
- /* Remove any elements remaining in lists */
- list_for_each_entry_safe(hnode, tmp, &hnode_mgr->node_list,
- list_elem) {
- list_del(&hnode->list_elem);
- delete_node(hnode, NULL);
- }
- mutex_destroy(&hnode_mgr->node_mgr_lock);
- if (hnode_mgr->ntfy_obj) {
- ntfy_delete(hnode_mgr->ntfy_obj);
- kfree(hnode_mgr->ntfy_obj);
- }
-
- if (hnode_mgr->disp_obj)
- disp_delete(hnode_mgr->disp_obj);
-
- if (hnode_mgr->strm_mgr_obj)
- strm_delete(hnode_mgr->strm_mgr_obj);
-
- /* Delete the loader */
- if (hnode_mgr->nldr_obj)
- hnode_mgr->nldr_fxns.delete(hnode_mgr->nldr_obj);
-
- kfree(hnode_mgr);
- }
-}
-
-/*
- * ======== fill_stream_connect ========
- * Purpose:
- * Fills stream information.
- */
-static void fill_stream_connect(struct node_object *node1,
- struct node_object *node2,
- u32 stream1, u32 stream2)
-{
- u32 strm_index;
- struct dsp_streamconnect *strm1 = NULL;
- struct dsp_streamconnect *strm2 = NULL;
- enum node_type node1_type = NODE_TASK;
- enum node_type node2_type = NODE_TASK;
-
- node1_type = node_get_type(node1);
- node2_type = node_get_type(node2);
- if (node1 != (struct node_object *)DSP_HGPPNODE) {
-
- if (node1_type != NODE_DEVICE) {
- strm_index = node1->num_inputs +
- node1->num_outputs - 1;
- strm1 = &(node1->stream_connect[strm_index]);
- strm1->cb_struct = sizeof(struct dsp_streamconnect);
- strm1->this_node_stream_index = stream1;
- }
-
- if (node2 != (struct node_object *)DSP_HGPPNODE) {
- /* NODE == > NODE */
- if (node1_type != NODE_DEVICE) {
- strm1->connected_node = node2;
- strm1->ui_connected_node_id = node2->node_uuid;
- strm1->connected_node_stream_index = stream2;
- strm1->connect_type = CONNECTTYPE_NODEOUTPUT;
- }
- if (node2_type != NODE_DEVICE) {
- strm_index = node2->num_inputs +
- node2->num_outputs - 1;
- strm2 = &(node2->stream_connect[strm_index]);
- strm2->cb_struct =
- sizeof(struct dsp_streamconnect);
- strm2->this_node_stream_index = stream2;
- strm2->connected_node = node1;
- strm2->ui_connected_node_id = node1->node_uuid;
- strm2->connected_node_stream_index = stream1;
- strm2->connect_type = CONNECTTYPE_NODEINPUT;
- }
- } else if (node1_type != NODE_DEVICE)
- strm1->connect_type = CONNECTTYPE_GPPOUTPUT;
- } else {
- /* GPP == > NODE */
- strm_index = node2->num_inputs + node2->num_outputs - 1;
- strm2 = &(node2->stream_connect[strm_index]);
- strm2->cb_struct = sizeof(struct dsp_streamconnect);
- strm2->this_node_stream_index = stream2;
- strm2->connect_type = CONNECTTYPE_GPPINPUT;
- }
-}
-
-/*
- * ======== fill_stream_def ========
- * Purpose:
- * Fills Stream attributes.
- */
-static void fill_stream_def(struct node_object *hnode,
- struct node_strmdef *pstrm_def,
- struct dsp_strmattr *pattrs)
-{
- struct node_mgr *hnode_mgr = hnode->node_mgr;
-
- if (pattrs != NULL) {
- pstrm_def->num_bufs = pattrs->num_bufs;
- pstrm_def->buf_size =
- pattrs->buf_size / hnode_mgr->dsp_data_mau_size;
- pstrm_def->seg_id = pattrs->seg_id;
- pstrm_def->buf_alignment = pattrs->buf_alignment;
- pstrm_def->timeout = pattrs->timeout;
- } else {
- pstrm_def->num_bufs = DEFAULTNBUFS;
- pstrm_def->buf_size =
- DEFAULTBUFSIZE / hnode_mgr->dsp_data_mau_size;
- pstrm_def->seg_id = DEFAULTSEGID;
- pstrm_def->buf_alignment = DEFAULTALIGNMENT;
- pstrm_def->timeout = DEFAULTTIMEOUT;
- }
-}
-
-/*
- * ======== free_stream ========
- * Purpose:
- * Updates the channel mask and frees the pipe id.
- */
-static void free_stream(struct node_mgr *hnode_mgr, struct stream_chnl stream)
-{
- /* Free up the pipe id unless other node has not yet been deleted. */
- if (stream.type == NODECONNECT) {
- if (test_bit(stream.dev_id, hnode_mgr->pipe_done_map)) {
- /* The other node has already been deleted */
- clear_bit(stream.dev_id, hnode_mgr->pipe_done_map);
- clear_bit(stream.dev_id, hnode_mgr->pipe_map);
- } else {
- /* The other node has not been deleted yet */
- set_bit(stream.dev_id, hnode_mgr->pipe_done_map);
- }
- } else if (stream.type == HOSTCONNECT) {
- if (stream.dev_id < hnode_mgr->num_chnls) {
- clear_bit(stream.dev_id, hnode_mgr->chnl_map);
- } else if (stream.dev_id < (2 * hnode_mgr->num_chnls)) {
- /* dsp-dma */
- clear_bit(stream.dev_id - (1 * hnode_mgr->num_chnls),
- hnode_mgr->dma_chnl_map);
- } else if (stream.dev_id < (3 * hnode_mgr->num_chnls)) {
- /* zero-copy */
- clear_bit(stream.dev_id - (2 * hnode_mgr->num_chnls),
- hnode_mgr->zc_chnl_map);
- }
- }
-}
-
-/*
- * ======== get_fxn_address ========
- * Purpose:
- * Retrieves the address for create, execute or delete phase for a node.
- */
-static int get_fxn_address(struct node_object *hnode, u32 *fxn_addr,
- u32 phase)
-{
- char *pstr_fxn_name = NULL;
- struct node_mgr *hnode_mgr = hnode->node_mgr;
- int status = 0;
-
- switch (phase) {
- case CREATEPHASE:
- pstr_fxn_name =
- hnode->dcd_props.obj_data.node_obj.str_create_phase_fxn;
- break;
- case EXECUTEPHASE:
- pstr_fxn_name =
- hnode->dcd_props.obj_data.node_obj.str_execute_phase_fxn;
- break;
- case DELETEPHASE:
- pstr_fxn_name =
- hnode->dcd_props.obj_data.node_obj.str_delete_phase_fxn;
- break;
- default:
- /* Should never get here */
- break;
- }
-
- status =
- hnode_mgr->nldr_fxns.get_fxn_addr(hnode->nldr_node_obj,
- pstr_fxn_name, fxn_addr);
-
- return status;
-}
-
-/*
- * ======== get_node_info ========
- * Purpose:
- * Retrieves the node information.
- */
-void get_node_info(struct node_object *hnode, struct dsp_nodeinfo *node_info)
-{
- u32 i;
-
- node_info->cb_struct = sizeof(struct dsp_nodeinfo);
- node_info->nb_node_database_props =
- hnode->dcd_props.obj_data.node_obj.ndb_props;
- node_info->execution_priority = hnode->prio;
- node_info->device_owner = hnode->device_owner;
- node_info->number_streams = hnode->num_inputs + hnode->num_outputs;
- node_info->node_env = hnode->node_env;
-
- node_info->ns_execution_state = node_get_state(hnode);
-
- /* Copy stream connect data */
- for (i = 0; i < hnode->num_inputs + hnode->num_outputs; i++)
- node_info->sc_stream_connection[i] = hnode->stream_connect[i];
-
-}
-
-/*
- * ======== get_node_props ========
- * Purpose:
- * Retrieve node properties.
- */
-static int get_node_props(struct dcd_manager *hdcd_mgr,
- struct node_object *hnode,
- const struct dsp_uuid *node_uuid,
- struct dcd_genericobj *dcd_prop)
-{
- u32 len;
- struct node_msgargs *pmsg_args;
- struct node_taskargs *task_arg_obj;
- enum node_type node_type = NODE_TASK;
- struct dsp_ndbprops *pndb_props =
- &(dcd_prop->obj_data.node_obj.ndb_props);
- int status = 0;
- char sz_uuid[MAXUUIDLEN];
-
- status = dcd_get_object_def(hdcd_mgr, (struct dsp_uuid *)node_uuid,
- DSP_DCDNODETYPE, dcd_prop);
-
- if (!status) {
- hnode->ntype = node_type = pndb_props->ntype;
-
- /* Create UUID value to set in registry. */
- snprintf(sz_uuid, MAXUUIDLEN, "%pUL", node_uuid);
- dev_dbg(bridge, "(node) UUID: %s\n", sz_uuid);
-
- /* Fill in message args that come from NDB */
- if (node_type != NODE_DEVICE) {
- pmsg_args = &(hnode->create_args.asa.node_msg_args);
- pmsg_args->seg_id =
- dcd_prop->obj_data.node_obj.msg_segid;
- pmsg_args->notify_type =
- dcd_prop->obj_data.node_obj.msg_notify_type;
- pmsg_args->max_msgs = pndb_props->message_depth;
- dev_dbg(bridge, "(node) Max Number of Messages: 0x%x\n",
- pmsg_args->max_msgs);
- } else {
- /* Copy device name */
- len = strlen(pndb_props->ac_name);
- hnode->str_dev_name = kzalloc(len + 1, GFP_KERNEL);
- if (hnode->str_dev_name == NULL) {
- status = -ENOMEM;
- } else {
- strncpy(hnode->str_dev_name,
- pndb_props->ac_name, len);
- }
- }
- }
- if (!status) {
- /* Fill in create args that come from NDB */
- if (node_type == NODE_TASK || node_type == NODE_DAISSOCKET) {
- task_arg_obj = &(hnode->create_args.asa.task_arg_obj);
- task_arg_obj->prio = pndb_props->prio;
- task_arg_obj->stack_size = pndb_props->stack_size;
- task_arg_obj->sys_stack_size =
- pndb_props->sys_stack_size;
- task_arg_obj->stack_seg = pndb_props->stack_seg;
- dev_dbg(bridge, "(node) Priority: 0x%x Stack Size: "
- "0x%x words System Stack Size: 0x%x words "
- "Stack Segment: 0x%x profile count : 0x%x\n",
- task_arg_obj->prio, task_arg_obj->stack_size,
- task_arg_obj->sys_stack_size,
- task_arg_obj->stack_seg,
- pndb_props->count_profiles);
- }
- }
-
- return status;
-}
-
-/*
- * ======== get_proc_props ========
- * Purpose:
- * Retrieve the processor properties.
- */
-static int get_proc_props(struct node_mgr *hnode_mgr,
- struct dev_object *hdev_obj)
-{
- struct cfg_hostres *host_res;
- struct bridge_dev_context *pbridge_context;
- int status = 0;
-
- status = dev_get_bridge_context(hdev_obj, &pbridge_context);
- if (!pbridge_context)
- status = -EFAULT;
-
- if (!status) {
- host_res = pbridge_context->resources;
- if (!host_res)
- return -EPERM;
- hnode_mgr->chnl_offset = host_res->chnl_offset;
- hnode_mgr->chnl_buf_size = host_res->chnl_buf_size;
- hnode_mgr->num_chnls = host_res->num_chnls;
-
- /*
- * PROC will add an API to get dsp_processorinfo.
- * Fill in default values for now.
- */
- /* TODO -- Instead of hard coding, take from registry */
- hnode_mgr->proc_family = 6000;
- hnode_mgr->proc_type = 6410;
- hnode_mgr->min_pri = DSP_NODE_MIN_PRIORITY;
- hnode_mgr->max_pri = DSP_NODE_MAX_PRIORITY;
- hnode_mgr->dsp_word_size = DSPWORDSIZE;
- hnode_mgr->dsp_data_mau_size = DSPWORDSIZE;
- hnode_mgr->dsp_mau_size = 1;
-
- }
- return status;
-}
-
-/*
- * ======== node_get_uuid_props ========
- * Purpose:
- * Fetch Node UUID properties from DCD/DOF file.
- */
-int node_get_uuid_props(void *hprocessor,
- const struct dsp_uuid *node_uuid,
- struct dsp_ndbprops *node_props)
-{
- struct node_mgr *hnode_mgr = NULL;
- struct dev_object *hdev_obj;
- int status = 0;
- struct dcd_nodeprops dcd_node_props;
- struct dsp_processorstate proc_state;
-
- if (hprocessor == NULL || node_uuid == NULL) {
- status = -EFAULT;
- goto func_end;
- }
- status = proc_get_state(hprocessor, &proc_state,
- sizeof(struct dsp_processorstate));
- if (status)
- goto func_end;
- /* If processor is in error state then don't attempt
- to send the message */
- if (proc_state.proc_state == PROC_ERROR) {
- status = -EPERM;
- goto func_end;
- }
-
- status = proc_get_dev_object(hprocessor, &hdev_obj);
- if (hdev_obj) {
- status = dev_get_node_manager(hdev_obj, &hnode_mgr);
- if (hnode_mgr == NULL) {
- status = -EFAULT;
- goto func_end;
- }
- }
-
- /*
- * Enter the critical section. This is needed because
- * dcd_get_object_def will ultimately end up calling dbll_open/close,
- * which needs to be protected in order to not corrupt the zlib manager
- * (COD).
- */
- mutex_lock(&hnode_mgr->node_mgr_lock);
-
- dcd_node_props.str_create_phase_fxn = NULL;
- dcd_node_props.str_execute_phase_fxn = NULL;
- dcd_node_props.str_delete_phase_fxn = NULL;
- dcd_node_props.str_i_alg_name = NULL;
-
- status = dcd_get_object_def(hnode_mgr->dcd_mgr,
- (struct dsp_uuid *)node_uuid, DSP_DCDNODETYPE,
- (struct dcd_genericobj *)&dcd_node_props);
-
- if (!status) {
- *node_props = dcd_node_props.ndb_props;
- kfree(dcd_node_props.str_create_phase_fxn);
-
- kfree(dcd_node_props.str_execute_phase_fxn);
-
- kfree(dcd_node_props.str_delete_phase_fxn);
-
- kfree(dcd_node_props.str_i_alg_name);
- }
- /* Leave the critical section, we're done. */
- mutex_unlock(&hnode_mgr->node_mgr_lock);
-func_end:
- return status;
-}
-
-/*
- * ======== get_rms_fxns ========
- * Purpose:
- * Retrieve the RMS functions.
- */
-static int get_rms_fxns(struct node_mgr *hnode_mgr)
-{
- s32 i;
- struct dev_object *dev_obj = hnode_mgr->dev_obj;
- int status = 0;
-
- static char *psz_fxns[NUMRMSFXNS] = {
- "RMS_queryServer", /* RMSQUERYSERVER */
- "RMS_configureServer", /* RMSCONFIGURESERVER */
- "RMS_createNode", /* RMSCREATENODE */
- "RMS_executeNode", /* RMSEXECUTENODE */
- "RMS_deleteNode", /* RMSDELETENODE */
- "RMS_changeNodePriority", /* RMSCHANGENODEPRIORITY */
- "RMS_readMemory", /* RMSREADMEMORY */
- "RMS_writeMemory", /* RMSWRITEMEMORY */
- "RMS_copy", /* RMSCOPY */
- };
-
- for (i = 0; i < NUMRMSFXNS; i++) {
- status = dev_get_symbol(dev_obj, psz_fxns[i],
- &(hnode_mgr->fxn_addrs[i]));
- if (status) {
- if (status == -ESPIPE) {
- /*
- * May be loaded dynamically (in the future),
- * but return an error for now.
- */
- dev_dbg(bridge, "%s: RMS function: %s currently"
- " not loaded\n", __func__, psz_fxns[i]);
- } else {
- dev_dbg(bridge, "%s: Symbol not found: %s "
- "status = 0x%x\n", __func__,
- psz_fxns[i], status);
- break;
- }
- }
- }
-
- return status;
-}
-
-/*
- * ======== ovly ========
- * Purpose:
- * Called during overlay.Sends command to RMS to copy a block of data.
- */
-static u32 ovly(void *priv_ref, u32 dsp_run_addr, u32 dsp_load_addr,
- u32 ul_num_bytes, u32 mem_space)
-{
- struct node_object *hnode = (struct node_object *)priv_ref;
- struct node_mgr *hnode_mgr;
- u32 ul_bytes = 0;
- u32 ul_size;
- u32 ul_timeout;
- int status = 0;
- struct bridge_dev_context *hbridge_context;
- /* Function interface to Bridge driver*/
- struct bridge_drv_interface *intf_fxns;
-
- hnode_mgr = hnode->node_mgr;
-
- ul_size = ul_num_bytes / hnode_mgr->dsp_word_size;
- ul_timeout = hnode->timeout;
-
- /* Call new MemCopy function */
- intf_fxns = hnode_mgr->intf_fxns;
- status = dev_get_bridge_context(hnode_mgr->dev_obj, &hbridge_context);
- if (!status) {
- status =
- (*intf_fxns->brd_mem_copy) (hbridge_context,
- dsp_run_addr, dsp_load_addr,
- ul_num_bytes, (u32) mem_space);
- if (!status)
- ul_bytes = ul_num_bytes;
- else
- pr_debug("%s: failed to copy brd memory, status 0x%x\n",
- __func__, status);
- } else {
- pr_debug("%s: failed to get Bridge context, status 0x%x\n",
- __func__, status);
- }
-
- return ul_bytes;
-}
-
-/*
- * ======== mem_write ========
- */
-static u32 mem_write(void *priv_ref, u32 dsp_add, void *pbuf,
- u32 ul_num_bytes, u32 mem_space)
-{
- struct node_object *hnode = (struct node_object *)priv_ref;
- struct node_mgr *hnode_mgr;
- u16 mem_sect_type;
- u32 ul_timeout;
- int status = 0;
- struct bridge_dev_context *hbridge_context;
- /* Function interface to Bridge driver */
- struct bridge_drv_interface *intf_fxns;
-
- hnode_mgr = hnode->node_mgr;
-
- ul_timeout = hnode->timeout;
- mem_sect_type = (mem_space & DBLL_CODE) ? RMS_CODE : RMS_DATA;
-
- /* Call new MemWrite function */
- intf_fxns = hnode_mgr->intf_fxns;
- status = dev_get_bridge_context(hnode_mgr->dev_obj, &hbridge_context);
- status = (*intf_fxns->brd_mem_write) (hbridge_context, pbuf,
- dsp_add, ul_num_bytes, mem_sect_type);
-
- return ul_num_bytes;
-}
-
-#ifdef CONFIG_TIDSPBRIDGE_BACKTRACE
-/*
- * ======== node_find_addr ========
- */
-int node_find_addr(struct node_mgr *node_mgr, u32 sym_addr,
- u32 offset_range, void *sym_addr_output, char *sym_name)
-{
- struct node_object *node_obj;
- int status = -ENOENT;
-
- list_for_each_entry(node_obj, &node_mgr->node_list, list_elem) {
- status = nldr_find_addr(node_obj->nldr_node_obj, sym_addr,
- offset_range, sym_addr_output, sym_name);
- if (!status) {
- pr_debug("%s(0x%x, 0x%x, 0x%x, 0x%x, %s)\n", __func__,
- (unsigned int) node_mgr,
- sym_addr, offset_range,
- (unsigned int) sym_addr_output, sym_name);
- break;
- }
- }
-
- return status;
-}
-#endif