static int send_message(struct disp_object *disp_obj, u32 timeout, u32 ul_bytes, u32 *pdw_arg) { struct bridge_drv_interface *intf_fxns; struct chnl_object *chnl_obj; u32 dw_arg = 0; u8 *pbuf; struct chnl_ioc chnl_ioc_obj; int status = 0; *pdw_arg = (u32) NULL; intf_fxns = disp_obj->intf_fxns; chnl_obj = disp_obj->chnl_to_dsp; pbuf = disp_obj->buf; /* */ status = (*intf_fxns->chnl_add_io_req) (chnl_obj, pbuf, ul_bytes, 0, 0L, dw_arg); if (status) goto func_end; status = (*intf_fxns->chnl_get_ioc) (chnl_obj, timeout, &chnl_ioc_obj); if (!status) { if (!CHNL_IS_IO_COMPLETE(chnl_ioc_obj)) { if (CHNL_IS_TIMED_OUT(chnl_ioc_obj)) status = -ETIME; else status = -EPERM; } } /* */ if (status) goto func_end; chnl_obj = disp_obj->chnl_from_dsp; ul_bytes = REPLYSIZE; status = (*intf_fxns->chnl_add_io_req) (chnl_obj, pbuf, ul_bytes, 0, 0L, dw_arg); if (status) goto func_end; status = (*intf_fxns->chnl_get_ioc) (chnl_obj, timeout, &chnl_ioc_obj); if (!status) { if (CHNL_IS_TIMED_OUT(chnl_ioc_obj)) { status = -ETIME; } else if (chnl_ioc_obj.byte_size < ul_bytes) { /* */ status = -EPERM; } else { if (CHNL_IS_IO_COMPLETE(chnl_ioc_obj)) { if (*((int *)chnl_ioc_obj.buf) < 0) { /* */ status = -EREMOTEIO; dev_dbg(bridge, "%s: DSP-side failed:" " DSP errcode = 0x%x, Kernel " "errcode = %d\n", __func__, *(int *)pbuf, status); } *pdw_arg = (((rms_word *) (chnl_ioc_obj.buf))[1]); } else { status = -EPERM; } } } func_end: return status; }
/* * ======== strm_reclaim ======== * Purpose: * Relcaims a buffer from a stream. */ int strm_reclaim(struct strm_object *stream_obj, u8 ** buf_ptr, u32 *nbytes, u32 *buff_size, u32 *pdw_arg) { struct bridge_drv_interface *intf_fxns; struct chnl_ioc chnl_ioc_obj; int status = 0; void *tmp_buf = NULL; DBC_REQUIRE(refs > 0); DBC_REQUIRE(buf_ptr != NULL); DBC_REQUIRE(nbytes != NULL); DBC_REQUIRE(pdw_arg != NULL); if (!stream_obj) { status = -EFAULT; goto func_end; } intf_fxns = stream_obj->strm_mgr_obj->intf_fxns; status = (*intf_fxns->chnl_get_ioc) (stream_obj->chnl_obj, stream_obj->timeout, &chnl_ioc_obj); if (!status) { *nbytes = chnl_ioc_obj.byte_size; if (buff_size) *buff_size = chnl_ioc_obj.buf_size; *pdw_arg = chnl_ioc_obj.arg; if (!CHNL_IS_IO_COMPLETE(chnl_ioc_obj)) { if (CHNL_IS_TIMED_OUT(chnl_ioc_obj)) { status = -ETIME; } else { /* Allow reclaims after idle to succeed */ if (!CHNL_IS_IO_CANCELLED(chnl_ioc_obj)) status = -EPERM; } } /* Translate zerocopy buffer if channel not canceled. */ if (!status && (!CHNL_IS_IO_CANCELLED(chnl_ioc_obj)) && (stream_obj->strm_mode == STRMMODE_ZEROCOPY)) { /* * This is a zero-copy channel so chnl_ioc_obj.buf * contains the DSP address of SM. We need to * translate it to a virtual address for the user * thread to access. * Note: Could add CMM_DSPPA2VA to CMM in the future. */ tmp_buf = cmm_xlator_translate(stream_obj->xlator, chnl_ioc_obj.buf, CMM_DSPPA2PA); if (tmp_buf != NULL) { /* now convert this GPP Pa to Va */ tmp_buf = cmm_xlator_translate(stream_obj-> xlator, tmp_buf, CMM_PA2VA); } if (tmp_buf == NULL) status = -ESRCH; chnl_ioc_obj.buf = tmp_buf; } *buf_ptr = chnl_ioc_obj.buf; } func_end: /* ensure we return a documented return code */ DBC_ENSURE(!status || status == -EFAULT || status == -ETIME || status == -ESRCH || status == -EPERM); dev_dbg(bridge, "%s: stream_obj: %p buf_ptr: %p nbytes: %p " "pdw_arg: %p status 0x%x\n", __func__, stream_obj, buf_ptr, nbytes, pdw_arg, status); return status; }