int disp_node_run(struct disp_object *disp_obj, struct node_object *hnode, u32 rms_fxn, u32 ul_execute_fxn, nodeenv node_env) { u32 dw_arg; struct rms_command *rms_cmd; int status = 0; u8 dev_type; status = dev_get_dev_type(disp_obj->dev_obj, &dev_type); if (!status) { if (dev_type == DSP_UNIT) { /* */ rms_cmd = (struct rms_command *)disp_obj->buf; rms_cmd->fxn = (rms_word) (rms_fxn); rms_cmd->arg1 = (rms_word) node_env; rms_cmd->arg2 = (rms_word) (ul_execute_fxn); rms_cmd->data = node_get_type(hnode); status = send_message(disp_obj, node_get_timeout(hnode), sizeof(struct rms_command), &dw_arg); } } return status; }
int api_init_complete2(void) { int status = 0; struct cfg_devnode *dev_node; struct dev_object *hdev_obj; struct drv_data *drv_datap; u8 dev_type; for (hdev_obj = dev_get_first(); hdev_obj != NULL; hdev_obj = dev_get_next(hdev_obj)) { if (dev_get_dev_node(hdev_obj, &dev_node)) continue; if (dev_get_dev_type(hdev_obj, &dev_type)) continue; if ((dev_type == DSP_UNIT) || (dev_type == IVA_UNIT)) { drv_datap = dev_get_drvdata(bridge); if (drv_datap && drv_datap->base_img) proc_auto_start(dev_node, hdev_obj); } } return status; }
/* * ======== api_init_complete2 ======== * Purpose: * Perform any required bridge initialization which cannot * be performed in api_init() or dev_start_device() due * to the fact that some services are not yet * completely initialized. * Parameters: * Returns: * 0: Allow this device to load * -EPERM: Failure. * Requires: * Bridge API initialized. * Ensures: */ int api_init_complete2(void) { int status = 0; struct cfg_devnode *dev_node; struct dev_object *hdev_obj; struct drv_data *drv_datap; u8 dev_type; /* Walk the list of DevObjects, get each devnode, and attempting to * autostart the board. Note that this requires COF loading, which * requires KFILE. */ for (hdev_obj = dev_get_first(); hdev_obj != NULL; hdev_obj = dev_get_next(hdev_obj)) { if (dev_get_dev_node(hdev_obj, &dev_node)) continue; if (dev_get_dev_type(hdev_obj, &dev_type)) continue; if ((dev_type == DSP_UNIT) || (dev_type == IVA_UNIT)) { drv_datap = dev_get_drvdata(bridge); if (drv_datap && drv_datap->base_img) proc_auto_start(dev_node, hdev_obj); } } return status; }
/* * ======== mgr_enum_processor_info ======== * Enumerate and get configuration information about available * DSP processors. */ int mgr_enum_processor_info(u32 processor_id, struct dsp_processorinfo * processor_info, u32 processor_info_size, u8 *pu_num_procs) { int status = 0; int status1 = 0; int status2 = 0; struct dsp_uuid temp_uuid; u32 temp_index = 0; u32 proc_index = 0; struct dcd_genericobj gen_obj; struct mgr_object *pmgr_obj = NULL; struct mgr_processorextinfo *ext_info; struct dev_object *hdev_obj; struct drv_object *hdrv_obj; u8 dev_type; struct cfg_devnode *dev_node; struct drv_data *drv_datap = dev_get_drvdata(bridge); bool proc_detect = false; *pu_num_procs = 0; /* Retrieve the Object handle from the driver data */ if (!drv_datap || !drv_datap->drv_object) { status = -ENODATA; pr_err("%s: Failed to retrieve the object handle\n", __func__); } else { hdrv_obj = drv_datap->drv_object; } if (!status) { status = drv_get_dev_object(processor_id, hdrv_obj, &hdev_obj); if (!status) { status = dev_get_dev_type(hdev_obj, (u8 *) &dev_type); status = dev_get_dev_node(hdev_obj, &dev_node); if (dev_type != DSP_UNIT) status = -EPERM; if (!status) processor_info->processor_type = DSPTYPE64; } } if (status) goto func_end; /* Get The Manager Object from the driver data */ if (drv_datap && drv_datap->mgr_object) { pmgr_obj = drv_datap->mgr_object; } else { dev_dbg(bridge, "%s: Failed to get MGR Object\n", __func__); goto func_end; } /* Forever loop till we hit no more items in the * Enumeration. We will exit the loop other than 0; */ while (status1 == 0) { status1 = dcd_enumerate_object(temp_index++, DSP_DCDPROCESSORTYPE, &temp_uuid); if (status1 != 0) break; proc_index++; /* Get the Object properties to find the Device/Processor * Type */ if (proc_detect != false) continue; status2 = dcd_get_object_def(pmgr_obj->dcd_mgr, (struct dsp_uuid *)&temp_uuid, DSP_DCDPROCESSORTYPE, &gen_obj); if (!status2) { /* Get the Obj def */ if (processor_info_size < sizeof(struct mgr_processorextinfo)) { *processor_info = gen_obj.obj_data.proc_info; } else { /* extended info */ ext_info = (struct mgr_processorextinfo *) processor_info; *ext_info = gen_obj.obj_data.ext_proc_obj; } dev_dbg(bridge, "%s: Got proctype from DCD %x\n", __func__, processor_info->processor_type); /* See if we got the needed processor */ if (dev_type == DSP_UNIT) { if (processor_info->processor_type == DSPPROCTYPE_C64) proc_detect = true; } else if (dev_type == IVA_UNIT) { if (processor_info->processor_type == IVAPROCTYPE_ARM7) proc_detect = true; } /* User applications only check for chip type, so * this is a clumsy overwrite */ processor_info->processor_type = DSPTYPE64; } else { dev_dbg(bridge, "%s: Failed to get DCD processor info " "%x\n", __func__, status2); status = -EPERM; } } *pu_num_procs = proc_index; if (proc_detect == false) { dev_dbg(bridge, "%s: Failed to get proc info from DCD, so use " "CFG registry\n", __func__); processor_info->processor_type = DSPTYPE64; } func_end: return status; }
int disp_create(struct disp_object **dispatch_obj, struct dev_object *hdev_obj, const struct disp_attr *disp_attrs) { struct disp_object *disp_obj; struct bridge_drv_interface *intf_fxns; u32 ul_chnl_id; struct chnl_attr chnl_attr_obj; int status = 0; u8 dev_type; *dispatch_obj = NULL; /* */ disp_obj = kzalloc(sizeof(struct disp_object), GFP_KERNEL); if (disp_obj == NULL) status = -ENOMEM; else disp_obj->dev_obj = hdev_obj; /* */ if (!status) { status = dev_get_chnl_mgr(hdev_obj, &(disp_obj->chnl_mgr)); if (!status) { (void)dev_get_intf_fxns(hdev_obj, &intf_fxns); disp_obj->intf_fxns = intf_fxns; } } /* */ if (status) goto func_cont; status = dev_get_dev_type(hdev_obj, &dev_type); if (status) goto func_cont; if (dev_type != DSP_UNIT) { status = -EPERM; goto func_cont; } disp_obj->char_size = DSPWORDSIZE; disp_obj->word_size = DSPWORDSIZE; disp_obj->data_mau_size = DSPWORDSIZE; /* */ chnl_attr_obj.uio_reqs = CHNLIOREQS; chnl_attr_obj.event_obj = NULL; ul_chnl_id = disp_attrs->chnl_offset + CHNLTORMSOFFSET; status = (*intf_fxns->chnl_open) (&(disp_obj->chnl_to_dsp), disp_obj->chnl_mgr, CHNL_MODETODSP, ul_chnl_id, &chnl_attr_obj); if (!status) { ul_chnl_id = disp_attrs->chnl_offset + CHNLFROMRMSOFFSET; status = (*intf_fxns->chnl_open) (&(disp_obj->chnl_from_dsp), disp_obj->chnl_mgr, CHNL_MODEFROMDSP, ul_chnl_id, &chnl_attr_obj); } if (!status) { /* */ disp_obj->bufsize = disp_attrs->chnl_buf_size; disp_obj->bufsize_rms = RMS_COMMANDBUFSIZE; disp_obj->buf = kzalloc(disp_obj->bufsize, GFP_KERNEL); if (disp_obj->buf == NULL) status = -ENOMEM; } func_cont: if (!status) *dispatch_obj = disp_obj; else delete_disp(disp_obj); return status; }
int disp_node_create(struct disp_object *disp_obj, struct node_object *hnode, u32 rms_fxn, u32 ul_create_fxn, const struct node_createargs *pargs, nodeenv *node_env) { struct node_msgargs node_msg_args; struct node_taskargs task_arg_obj; struct rms_command *rms_cmd; struct rms_msg_args *pmsg_args; struct rms_more_task_args *more_task_args; enum node_type node_type; u32 dw_length; rms_word *pdw_buf = NULL; u32 ul_bytes; u32 i; u32 total; u32 chars_in_rms_word; s32 task_args_offset; s32 sio_in_def_offset; s32 sio_out_def_offset; s32 sio_defs_offset; s32 args_offset = -1; s32 offset; struct node_strmdef strm_def; u32 max; int status = 0; struct dsp_nodeinfo node_info; u8 dev_type; status = dev_get_dev_type(disp_obj->dev_obj, &dev_type); if (status) goto func_end; if (dev_type != DSP_UNIT) { dev_dbg(bridge, "%s: unknown device type = 0x%x\n", __func__, dev_type); goto func_end; } node_type = node_get_type(hnode); node_msg_args = pargs->asa.node_msg_args; max = disp_obj->bufsize_rms; /* */ chars_in_rms_word = sizeof(rms_word) / disp_obj->char_size; /* */ dw_length = (node_msg_args.arg_length + chars_in_rms_word - 1) / chars_in_rms_word; /* */ total = sizeof(struct rms_command) / sizeof(rms_word) + sizeof(struct rms_msg_args) / sizeof(rms_word) - 1 + dw_length; if (total >= max) { status = -EPERM; dev_dbg(bridge, "%s: Message args too large for buffer! size " "= %d, max = %d\n", __func__, total, max); } /* */ if (!status) { total = 0; /* */ pdw_buf = (rms_word *) disp_obj->buf; rms_cmd = (struct rms_command *)pdw_buf; rms_cmd->fxn = (rms_word) (rms_fxn); rms_cmd->arg1 = (rms_word) (ul_create_fxn); if (node_get_load_type(hnode) == NLDR_DYNAMICLOAD) { /* */ rms_cmd->arg2 = 1; /* */ } else { /* */ rms_cmd->arg2 = 0; /* */ } rms_cmd->data = node_get_type(hnode); /* */ args_offset = 3; total += sizeof(struct rms_command) / sizeof(rms_word); /* */ pmsg_args = (struct rms_msg_args *)(pdw_buf + total); pmsg_args->max_msgs = node_msg_args.max_msgs; pmsg_args->segid = node_msg_args.seg_id; pmsg_args->notify_type = node_msg_args.notify_type; pmsg_args->arg_length = node_msg_args.arg_length; total += sizeof(struct rms_msg_args) / sizeof(rms_word) - 1; memcpy(pdw_buf + total, node_msg_args.pdata, node_msg_args.arg_length); total += dw_length; } if (status) goto func_end; /* */ if (node_type == NODE_TASK || node_type == NODE_DAISSOCKET) { task_arg_obj = pargs->asa.task_arg_obj; task_args_offset = total; total += sizeof(struct rms_more_task_args) / sizeof(rms_word) + 1 + task_arg_obj.num_inputs + task_arg_obj.num_outputs; /* */ if (total < max) { total = task_args_offset; more_task_args = (struct rms_more_task_args *)(pdw_buf + total); /* */ get_node_info(hnode, &node_info); more_task_args->priority = node_info.execution_priority; more_task_args->stack_size = task_arg_obj.stack_size; more_task_args->sysstack_size = task_arg_obj.sys_stack_size; more_task_args->stack_seg = task_arg_obj.stack_seg; more_task_args->heap_addr = task_arg_obj.dsp_heap_addr; more_task_args->heap_size = task_arg_obj.heap_size; more_task_args->misc = task_arg_obj.dais_arg; more_task_args->num_input_streams = task_arg_obj.num_inputs; total += sizeof(struct rms_more_task_args) / sizeof(rms_word); dev_dbg(bridge, "%s: dsp_heap_addr %x, heap_size %x\n", __func__, task_arg_obj.dsp_heap_addr, task_arg_obj.heap_size); /* */ sio_in_def_offset = total; total += task_arg_obj.num_inputs; pdw_buf[total++] = task_arg_obj.num_outputs; sio_out_def_offset = total; total += task_arg_obj.num_outputs; sio_defs_offset = total; /* */ offset = sio_defs_offset; for (i = 0; i < task_arg_obj.num_inputs; i++) { if (status) break; pdw_buf[sio_in_def_offset + i] = (offset - args_offset) * (sizeof(rms_word) / DSPWORDSIZE); strm_def = task_arg_obj.strm_in_def[i]; status = fill_stream_def(pdw_buf, &total, offset, strm_def, max, chars_in_rms_word); offset = total; } for (i = 0; (i < task_arg_obj.num_outputs) && (!status); i++) { pdw_buf[sio_out_def_offset + i] = (offset - args_offset) * (sizeof(rms_word) / DSPWORDSIZE); strm_def = task_arg_obj.strm_out_def[i]; status = fill_stream_def(pdw_buf, &total, offset, strm_def, max, chars_in_rms_word); offset = total; } } else { /* */ status = -EPERM; } } if (!status) { ul_bytes = total * sizeof(rms_word); status = send_message(disp_obj, node_get_timeout(hnode), ul_bytes, node_env); } func_end: return status; }
int bridge_io_create(struct io_mgr **io_man, struct dev_object *hdev_obj, const struct io_attrs *mgr_attrts) { struct io_mgr *pio_mgr = NULL; struct bridge_dev_context *hbridge_context = NULL; struct cfg_devnode *dev_node_obj; struct chnl_mgr *hchnl_mgr; u8 dev_type; if (!io_man || !mgr_attrts || mgr_attrts->word_size == 0) return -EFAULT; *io_man = NULL; dev_get_chnl_mgr(hdev_obj, &hchnl_mgr); if (!hchnl_mgr || hchnl_mgr->iomgr) return -EFAULT; dev_get_bridge_context(hdev_obj, &hbridge_context); if (!hbridge_context) return -EFAULT; dev_get_dev_type(hdev_obj, &dev_type); pio_mgr = kzalloc(sizeof(struct io_mgr), GFP_KERNEL); if (!pio_mgr) return -ENOMEM; pio_mgr->chnl_mgr = hchnl_mgr; pio_mgr->word_size = mgr_attrts->word_size; if (dev_type == DSP_UNIT) { tasklet_init(&pio_mgr->dpc_tasklet, io_dpc, (u32) pio_mgr); pio_mgr->dpc_req = 0; pio_mgr->dpc_sched = 0; spin_lock_init(&pio_mgr->dpc_lock); if (dev_get_dev_node(hdev_obj, &dev_node_obj)) { bridge_io_destroy(pio_mgr); return -EIO; } } pio_mgr->bridge_context = hbridge_context; pio_mgr->shared_irq = mgr_attrts->irq_shared; if (dsp_wdt_init()) { bridge_io_destroy(pio_mgr); return -EPERM; } hchnl_mgr->iomgr = pio_mgr; *io_man = pio_mgr; return 0; }