Example #1
0
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;
}
Example #2
0
/*
 *  ======== 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;
}