/* * ======== cmm_xlator_alloc_buf ======== */ void *cmm_xlator_alloc_buf(struct cmm_xlatorobject *xlator, void *pVaBuf, u32 uPaSize) { struct cmm_xlator *xlator_obj = (struct cmm_xlator *)xlator; void *pbuf = NULL; struct cmm_attrs attrs; DBC_REQUIRE(refs > 0); DBC_REQUIRE(xlator != NULL); DBC_REQUIRE(xlator_obj->hcmm_mgr != NULL); DBC_REQUIRE(pVaBuf != NULL); DBC_REQUIRE(uPaSize > 0); DBC_REQUIRE(xlator_obj->ul_seg_id > 0); if (xlator_obj) { attrs.ul_seg_id = xlator_obj->ul_seg_id; *(volatile u32 *)pVaBuf = 0; /* Alloc SM */ pbuf = cmm_calloc_buf(xlator_obj->hcmm_mgr, uPaSize, &attrs, NULL); if (pbuf) { /* convert to translator(node/strm) process Virtual * address */ *(volatile u32 **)pVaBuf = (u32 *) cmm_xlator_translate(xlator, pbuf, CMM_PA2VA); } } return pbuf; }
/* * ======== cmm_xlator_free_buf ======== * Purpose: * Free the given SM buffer and descriptor. * Does not free virtual memory. */ int cmm_xlator_free_buf(struct cmm_xlatorobject *xlator, void *pBufVa) { struct cmm_xlator *xlator_obj = (struct cmm_xlator *)xlator; int status = -EPERM; void *buf_pa = NULL; DBC_REQUIRE(refs > 0); DBC_REQUIRE(pBufVa != NULL); DBC_REQUIRE(xlator_obj->ul_seg_id > 0); if (xlator_obj) { /* convert Va to Pa so we can free it. */ buf_pa = cmm_xlator_translate(xlator, pBufVa, CMM_VA2PA); if (buf_pa) { status = cmm_free_buf(xlator_obj->hcmm_mgr, buf_pa, xlator_obj->ul_seg_id); if (DSP_FAILED(status)) { /* Uh oh, this shouldn't happen. Descriptor * gone! */ DBC_ASSERT(false); /* CMM is leaking mem */ } } } return status; }
/* * ======== strm_issue ======== * Purpose: * Issues a buffer on a stream */ int strm_issue(struct strm_object *stream_obj, u8 *pbuf, u32 ul_bytes, u32 ul_buf_size, u32 dw_arg) { struct bridge_drv_interface *intf_fxns; int status = 0; void *tmp_buf = NULL; if (!stream_obj) { status = -EFAULT; } else { intf_fxns = stream_obj->strm_mgr_obj->intf_fxns; if (stream_obj->segment_id != 0) { tmp_buf = cmm_xlator_translate(stream_obj->xlator, (void *)pbuf, CMM_VA2DSPPA); if (tmp_buf == NULL) status = -ESRCH; } if (!status) { status = (*intf_fxns->chnl_add_io_req) (stream_obj->chnl_obj, pbuf, ul_bytes, ul_buf_size, (u32) tmp_buf, dw_arg); } if (status == -EIO) status = -ENOSR; } dev_dbg(bridge, "%s: stream_obj: %p pbuf: %p ul_bytes: 0x%x dw_arg:" " 0x%x status: 0x%x\n", __func__, stream_obj, pbuf, ul_bytes, dw_arg, status); 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; }