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