Beispiel #1
0
Datei: strm.c Projekt: 7799/linux
/*
 *  ======== strm_get_info ========
 *  Purpose:
 *      Retrieves information about a stream.
 */
int strm_get_info(struct strm_object *stream_obj,
			 struct stream_info *stream_info,
			 u32 stream_info_size)
{
	struct bridge_drv_interface *intf_fxns;
	struct chnl_info chnl_info_obj;
	int status = 0;
	void *virt_base = NULL;	/* NULL if no SM used */

	if (!stream_obj) {
		status = -EFAULT;
	} else {
		if (stream_info_size < sizeof(struct stream_info)) {
			/* size of users info */
			status = -EINVAL;
		}
	}
	if (status)
		goto func_end;

	intf_fxns = stream_obj->strm_mgr_obj->intf_fxns;
	status =
	    (*intf_fxns->chnl_get_info) (stream_obj->chnl_obj,
						  &chnl_info_obj);
	if (status)
		goto func_end;

	if (stream_obj->xlator) {
		/* We have a translator */
		cmm_xlator_info(stream_obj->xlator, (u8 **) &virt_base, 0,
				stream_obj->segment_id, false);
	}
	stream_info->segment_id = stream_obj->segment_id;
	stream_info->strm_mode = stream_obj->strm_mode;
	stream_info->virt_base = virt_base;
	stream_info->user_strm->number_bufs_allowed = stream_obj->num_bufs;
	stream_info->user_strm->number_bufs_in_stream = chnl_info_obj.cio_cs +
	    chnl_info_obj.cio_reqs;
	/* # of bytes transferred since last call to DSPStream_Idle() */
	stream_info->user_strm->number_bytes = chnl_info_obj.bytes_tx;
	stream_info->user_strm->sync_object_handle = chnl_info_obj.event_obj;
	/* Determine stream state based on channel state and info */
	if (chnl_info_obj.state & CHNL_STATEEOS) {
		stream_info->user_strm->ss_stream_state = STREAM_DONE;
	} else {
		if (chnl_info_obj.cio_cs > 0)
			stream_info->user_strm->ss_stream_state = STREAM_READY;
		else if (chnl_info_obj.cio_reqs > 0)
			stream_info->user_strm->ss_stream_state =
			    STREAM_PENDING;
		else
			stream_info->user_strm->ss_stream_state = STREAM_IDLE;

	}
func_end:
	return status;
}
Beispiel #2
0
/*
 *  ======== strm_open ========
 *  Purpose:
 *      Open a stream for sending/receiving data buffers to/from a task or
 *      XDAIS socket node on the DSP.
 */
int strm_open(struct node_object *hnode, u32 dir, u32 index,
		     struct strm_attr *pattr,
		     struct strm_res_object **strmres,
		     struct process_context *pr_ctxt)
{
	struct strm_mgr *strm_mgr_obj;
	struct bridge_drv_interface *intf_fxns;
	u32 ul_chnl_id;
	struct strm_object *strm_obj = NULL;
	s8 chnl_mode;
	struct chnl_attr chnl_attr_obj;
	int status = 0;
	struct cmm_object *hcmm_mgr = NULL;	/* Shared memory manager hndl */

	void *stream_res;

	DBC_REQUIRE(refs > 0);
	DBC_REQUIRE(strmres != NULL);
	DBC_REQUIRE(pattr != NULL);
	*strmres = NULL;
	if (dir != DSP_TONODE && dir != DSP_FROMNODE) {
		status = -EPERM;
	} else {
		/* Get the channel id from the node (set in node_connect()) */
		status = node_get_channel_id(hnode, dir, index, &ul_chnl_id);
	}
	if (!status)
		status = node_get_strm_mgr(hnode, &strm_mgr_obj);

	if (!status) {
		strm_obj = kzalloc(sizeof(struct strm_object), GFP_KERNEL);
		if (strm_obj == NULL) {
			status = -ENOMEM;
		} else {
			strm_obj->strm_mgr_obj = strm_mgr_obj;
			strm_obj->dir = dir;
			strm_obj->strm_state = STREAM_IDLE;
			strm_obj->user_event = pattr->user_event;
			if (pattr->stream_attr_in != NULL) {
				strm_obj->timeout =
				    pattr->stream_attr_in->timeout;
				strm_obj->num_bufs =
				    pattr->stream_attr_in->num_bufs;
				strm_obj->strm_mode =
				    pattr->stream_attr_in->strm_mode;
				strm_obj->segment_id =
				    pattr->stream_attr_in->segment_id;
				strm_obj->buf_alignment =
				    pattr->stream_attr_in->buf_alignment;
				strm_obj->dma_chnl_id =
				    pattr->stream_attr_in->dma_chnl_id;
				strm_obj->dma_priority =
				    pattr->stream_attr_in->dma_priority;
				chnl_attr_obj.uio_reqs =
				    pattr->stream_attr_in->num_bufs;
			} else {
				strm_obj->timeout = DEFAULTTIMEOUT;
				strm_obj->num_bufs = DEFAULTNUMBUFS;
				strm_obj->strm_mode = STRMMODE_PROCCOPY;
				strm_obj->segment_id = 0;	/* local mem */
				strm_obj->buf_alignment = 0;
				strm_obj->dma_chnl_id = 0;
				strm_obj->dma_priority = 0;
				chnl_attr_obj.uio_reqs = DEFAULTNUMBUFS;
			}
			chnl_attr_obj.reserved1 = NULL;
			/* DMA chnl flush timeout */
			chnl_attr_obj.reserved2 = strm_obj->timeout;
			chnl_attr_obj.event_obj = NULL;
			if (pattr->user_event != NULL)
				chnl_attr_obj.event_obj = pattr->user_event;

		}
	}
	if (status)
		goto func_cont;

	if ((pattr->virt_base == NULL) || !(pattr->virt_size > 0))
		goto func_cont;

	/* No System DMA */
	DBC_ASSERT(strm_obj->strm_mode != STRMMODE_LDMA);
	/* Get the shared mem mgr for this streams dev object */
	status = dev_get_cmm_mgr(strm_mgr_obj->dev_obj, &hcmm_mgr);
	if (!status) {
		/*Allocate a SM addr translator for this strm. */
		status = cmm_xlator_create(&strm_obj->xlator, hcmm_mgr, NULL);
		if (!status) {
			DBC_ASSERT(strm_obj->segment_id > 0);
			/*  Set translators Virt Addr attributes */
			status = cmm_xlator_info(strm_obj->xlator,
						 (u8 **) &pattr->virt_base,
						 pattr->virt_size,
						 strm_obj->segment_id, true);
		}
	}
func_cont:
	if (!status) {
		/* Open channel */
		chnl_mode = (dir == DSP_TONODE) ?
		    CHNL_MODETODSP : CHNL_MODEFROMDSP;
		intf_fxns = strm_mgr_obj->intf_fxns;
		status = (*intf_fxns->chnl_open) (&(strm_obj->chnl_obj),
						      strm_mgr_obj->chnl_mgr,
						      chnl_mode, ul_chnl_id,
						      &chnl_attr_obj);
		if (status) {
			/*
			 * over-ride non-returnable status codes so we return
			 * something documented
			 */
			if (status != -ENOMEM && status !=
			    -EINVAL && status != -EPERM) {
				/*
				 * We got a status that's not return-able.
				 * Assert that we got something we were
				 * expecting (-EFAULT isn't acceptable,
				 * strm_mgr_obj->chnl_mgr better be valid or we
				 * assert here), and then return -EPERM.
				 */
				DBC_ASSERT(status == -ENOSR ||
					   status == -ECHRNG ||
					   status == -EALREADY ||
					   status == -EIO);
				status = -EPERM;
			}
		}
	}
	if (!status) {
		status = drv_proc_insert_strm_res_element(strm_obj,
							&stream_res, pr_ctxt);
		if (status)
			delete_strm(strm_obj);
		else
			*strmres = (struct strm_res_object *)stream_res;
	} else {
		(void)delete_strm(strm_obj);
	}

	/* ensure we return a documented error code */
	DBC_ENSURE((!status && strm_obj) ||
		   (*strmres == NULL && (status == -EFAULT ||
					status == -EPERM
					|| status == -EINVAL)));

	dev_dbg(bridge, "%s: hnode: %p dir: 0x%x index: 0x%x pattr: %p "
		"strmres: %p status: 0x%x\n", __func__,
		hnode, dir, index, pattr, strmres, status);
	return status;
}
Beispiel #3
0
/*
 *  ======== node_alloc_msg_buf ========
 *  Purpose:
 *      Allocates buffer for zero copy messaging.
 */
DBAPI node_alloc_msg_buf(struct node_object *hnode, u32 usize,
			 struct dsp_bufferattr *pattr,
			 u8 **pbuffer)
{
	struct node_object *pnode = (struct node_object *)hnode;
	int status = 0;
	bool va_flag = false;
	bool set_info;
	u32 proc_id;

	DBC_REQUIRE(refs > 0);
	DBC_REQUIRE(pbuffer != NULL);

	DBC_REQUIRE(usize > 0);

	if (!pnode)
		status = -EFAULT;
	else if (node_get_type(pnode) == NODE_DEVICE)
		status = -EPERM;

	if (status)
		goto func_end;

	if (pattr == NULL)
		pattr = &node_dfltbufattrs;	/* set defaults */

	status = proc_get_processor_id(pnode->hprocessor, &proc_id);
	if (proc_id != DSP_UNIT) {
		DBC_ASSERT(NULL);
		goto func_end;
	}
	/*  If segment ID includes MEM_SETVIRTUALSEGID then pbuffer is a
	 *  virt  address, so set this info in this node's translator
	 *  object for  future ref. If MEM_GETVIRTUALSEGID then retrieve
	 *  virtual address  from node's translator. */
	if ((pattr->segment_id & MEM_SETVIRTUALSEGID) ||
	    (pattr->segment_id & MEM_GETVIRTUALSEGID)) {
		va_flag = true;
		set_info = (pattr->segment_id & MEM_SETVIRTUALSEGID) ?
		    true : false;
		/* Clear mask bits */
		pattr->segment_id &= ~MEM_MASKVIRTUALSEGID;
		/* Set/get this node's translators virtual address base/size */
		status = cmm_xlator_info(pnode->xlator, pbuffer, usize,
					 pattr->segment_id, set_info);
	}
	if (!status && (!va_flag)) {
		if (pattr->segment_id != 1) {
			/* Node supports single SM segment only. */
			status = -EBADR;
		}
		/*  Arbitrary SM buffer alignment not supported for host side
		 *  allocs, but guaranteed for the following alignment
		 *  values. */
		switch (pattr->buf_alignment) {
		case 0:
		case 1:
		case 2:
		case 4:
			break;
		default:
			/* alignment value not suportted */
			status = -EPERM;
			break;
		}
		if (!status) {
			/* allocate physical buffer from seg_id in node's
			 * translator */
			(void)cmm_xlator_alloc_buf(pnode->xlator, pbuffer,
						   usize);
			if (*pbuffer == NULL) {
				pr_err("%s: error - Out of shared memory\n",
				       __func__);
				status = -ENOMEM;
			}
		}
	}
func_end:
	return status;
}