diff options
Diffstat (limited to 'drivers/staging/tidspbridge/rmgr/strm.c')
-rw-r--r-- | drivers/staging/tidspbridge/rmgr/strm.c | 733 |
1 files changed, 0 insertions, 733 deletions
diff --git a/drivers/staging/tidspbridge/rmgr/strm.c b/drivers/staging/tidspbridge/rmgr/strm.c deleted file mode 100644 index b88b27bbe2e7..000000000000 --- a/drivers/staging/tidspbridge/rmgr/strm.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - * strm.c - * - * DSP-BIOS Bridge driver support functions for TI OMAP processors. - * - * DSP/BIOS Bridge Stream Manager. - * - * Copyright (C) 2005-2006 Texas Instruments, Inc. - * - * This package is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#include <linux/types.h> - -/* ----------------------------------- Host OS */ -#include <dspbridge/host_os.h> - -/* ----------------------------------- DSP/BIOS Bridge */ -#include <dspbridge/dbdefs.h> - -/* ----------------------------------- OS Adaptation Layer */ -#include <dspbridge/sync.h> - -/* ----------------------------------- Bridge Driver */ -#include <dspbridge/dspdefs.h> - -/* ----------------------------------- Resource Manager */ -#include <dspbridge/nodepriv.h> - -/* ----------------------------------- Others */ -#include <dspbridge/cmm.h> - -/* ----------------------------------- This */ -#include <dspbridge/strm.h> - -#include <dspbridge/resourcecleanup.h> - -/* ----------------------------------- Defines, Data Structures, Typedefs */ -#define DEFAULTTIMEOUT 10000 -#define DEFAULTNUMBUFS 2 - -/* - * ======== strm_mgr ======== - * The strm_mgr contains device information needed to open the underlying - * channels of a stream. - */ -struct strm_mgr { - struct dev_object *dev_obj; /* Device for this processor */ - struct chnl_mgr *chnl_mgr; /* Channel manager */ - /* Function interface to Bridge driver */ - struct bridge_drv_interface *intf_fxns; -}; - -/* - * ======== strm_object ======== - * This object is allocated in strm_open(). - */ -struct strm_object { - struct strm_mgr *strm_mgr_obj; - struct chnl_object *chnl_obj; - u32 dir; /* DSP_TONODE or DSP_FROMNODE */ - u32 timeout; - u32 num_bufs; /* Max # of bufs allowed in stream */ - u32 bufs_in_strm; /* Current # of bufs in stream */ - u32 bytes; /* bytes transferred since idled */ - /* STREAM_IDLE, STREAM_READY, ... */ - enum dsp_streamstate strm_state; - void *user_event; /* Saved for strm_get_info() */ - enum dsp_strmmode strm_mode; /* STRMMODE_[PROCCOPY][ZEROCOPY]... */ - u32 dma_chnl_id; /* DMA chnl id */ - u32 dma_priority; /* DMA priority:DMAPRI_[LOW][HIGH] */ - u32 segment_id; /* >0 is SM segment.=0 is local heap */ - u32 buf_alignment; /* Alignment for stream bufs */ - /* Stream's SM address translator */ - struct cmm_xlatorobject *xlator; -}; - -/* ----------------------------------- Function Prototypes */ -static int delete_strm(struct strm_object *stream_obj); - -/* - * ======== strm_allocate_buffer ======== - * Purpose: - * Allocates buffers for a stream. - */ -int strm_allocate_buffer(struct strm_res_object *strmres, u32 usize, - u8 **ap_buffer, u32 num_bufs, - struct process_context *pr_ctxt) -{ - int status = 0; - u32 alloc_cnt = 0; - u32 i; - struct strm_object *stream_obj = strmres->stream; - - if (stream_obj) { - /* - * Allocate from segment specified at time of stream open. - */ - if (usize == 0) - status = -EINVAL; - - } else { - status = -EFAULT; - } - - if (status) - goto func_end; - - for (i = 0; i < num_bufs; i++) { - (void)cmm_xlator_alloc_buf(stream_obj->xlator, &ap_buffer[i], - usize); - if (ap_buffer[i] == NULL) { - status = -ENOMEM; - alloc_cnt = i; - break; - } - } - if (status) - strm_free_buffer(strmres, ap_buffer, alloc_cnt, pr_ctxt); - - if (status) - goto func_end; - - drv_proc_update_strm_res(num_bufs, strmres); - -func_end: - return status; -} - -/* - * ======== strm_close ======== - * Purpose: - * Close a stream opened with strm_open(). - */ -int strm_close(struct strm_res_object *strmres, - struct process_context *pr_ctxt) -{ - struct bridge_drv_interface *intf_fxns; - struct chnl_info chnl_info_obj; - int status = 0; - struct strm_object *stream_obj = strmres->stream; - - if (!stream_obj) { - status = -EFAULT; - } else { - /* Have all buffers been reclaimed? If not, return - * -EPIPE */ - intf_fxns = stream_obj->strm_mgr_obj->intf_fxns; - status = - (*intf_fxns->chnl_get_info) (stream_obj->chnl_obj, - &chnl_info_obj); - - if (chnl_info_obj.cio_cs > 0 || chnl_info_obj.cio_reqs > 0) - status = -EPIPE; - else - status = delete_strm(stream_obj); - } - - if (status) - goto func_end; - - idr_remove(pr_ctxt->stream_id, strmres->id); -func_end: - dev_dbg(bridge, "%s: stream_obj: %p, status 0x%x\n", __func__, - stream_obj, status); - return status; -} - -/* - * ======== strm_create ======== - * Purpose: - * Create a STRM manager object. - */ -int strm_create(struct strm_mgr **strm_man, - struct dev_object *dev_obj) -{ - struct strm_mgr *strm_mgr_obj; - int status = 0; - - *strm_man = NULL; - /* Allocate STRM manager object */ - strm_mgr_obj = kzalloc(sizeof(struct strm_mgr), GFP_KERNEL); - if (strm_mgr_obj == NULL) - status = -ENOMEM; - else - strm_mgr_obj->dev_obj = dev_obj; - - /* Get Channel manager and Bridge function interface */ - if (!status) { - status = dev_get_chnl_mgr(dev_obj, &(strm_mgr_obj->chnl_mgr)); - if (!status) { - (void)dev_get_intf_fxns(dev_obj, - &(strm_mgr_obj->intf_fxns)); - } - } - - if (!status) - *strm_man = strm_mgr_obj; - else - kfree(strm_mgr_obj); - - return status; -} - -/* - * ======== strm_delete ======== - * Purpose: - * Delete the STRM Manager Object. - */ -void strm_delete(struct strm_mgr *strm_mgr_obj) -{ - kfree(strm_mgr_obj); -} - -/* - * ======== strm_free_buffer ======== - * Purpose: - * Frees the buffers allocated for a stream. - */ -int strm_free_buffer(struct strm_res_object *strmres, u8 **ap_buffer, - u32 num_bufs, struct process_context *pr_ctxt) -{ - int status = 0; - u32 i = 0; - struct strm_object *stream_obj = strmres->stream; - - if (!stream_obj) - status = -EFAULT; - - if (!status) { - for (i = 0; i < num_bufs; i++) { - status = - cmm_xlator_free_buf(stream_obj->xlator, - ap_buffer[i]); - if (status) - break; - ap_buffer[i] = NULL; - } - } - drv_proc_update_strm_res(num_bufs - i, strmres); - - return status; -} - -/* - * ======== 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; -} - -/* - * ======== strm_idle ======== - * Purpose: - * Idles a particular stream. - */ -int strm_idle(struct strm_object *stream_obj, bool flush_data) -{ - struct bridge_drv_interface *intf_fxns; - int status = 0; - - if (!stream_obj) { - status = -EFAULT; - } else { - intf_fxns = stream_obj->strm_mgr_obj->intf_fxns; - - status = (*intf_fxns->chnl_idle) (stream_obj->chnl_obj, - stream_obj->timeout, - flush_data); - } - - dev_dbg(bridge, "%s: stream_obj: %p flush_data: 0x%x status: 0x%x\n", - __func__, stream_obj, flush_data, status); - 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_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; - - *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 */ - /* 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) { - /* 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. - */ - 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); - } - - 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; -} - -/* - * ======== 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; - - 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: - 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; -} - -/* - * ======== strm_register_notify ======== - * Purpose: - * Register to be notified on specific events for this stream. - */ -int strm_register_notify(struct strm_object *stream_obj, u32 event_mask, - u32 notify_type, struct dsp_notification - *hnotification) -{ - struct bridge_drv_interface *intf_fxns; - int status = 0; - - if (!stream_obj) { - status = -EFAULT; - } else if ((event_mask & ~((DSP_STREAMIOCOMPLETION) | - DSP_STREAMDONE)) != 0) { - status = -EINVAL; - } else { - if (notify_type != DSP_SIGNALEVENT) - status = -ENOSYS; - - } - if (!status) { - intf_fxns = stream_obj->strm_mgr_obj->intf_fxns; - - status = - (*intf_fxns->chnl_register_notify) (stream_obj-> - chnl_obj, - event_mask, - notify_type, - hnotification); - } - - return status; -} - -/* - * ======== strm_select ======== - * Purpose: - * Selects a ready stream. - */ -int strm_select(struct strm_object **strm_tab, u32 strms, - u32 *pmask, u32 utimeout) -{ - u32 index; - struct chnl_info chnl_info_obj; - struct bridge_drv_interface *intf_fxns; - struct sync_object **sync_events = NULL; - u32 i; - int status = 0; - - *pmask = 0; - for (i = 0; i < strms; i++) { - if (!strm_tab[i]) { - status = -EFAULT; - break; - } - } - if (status) - goto func_end; - - /* Determine which channels have IO ready */ - for (i = 0; i < strms; i++) { - intf_fxns = strm_tab[i]->strm_mgr_obj->intf_fxns; - status = (*intf_fxns->chnl_get_info) (strm_tab[i]->chnl_obj, - &chnl_info_obj); - if (status) { - break; - } else { - if (chnl_info_obj.cio_cs > 0) - *pmask |= (1 << i); - - } - } - if (!status && utimeout > 0 && *pmask == 0) { - /* Non-zero timeout */ - sync_events = kmalloc(strms * sizeof(struct sync_object *), - GFP_KERNEL); - - if (sync_events == NULL) { - status = -ENOMEM; - } else { - for (i = 0; i < strms; i++) { - intf_fxns = - strm_tab[i]->strm_mgr_obj->intf_fxns; - status = (*intf_fxns->chnl_get_info) - (strm_tab[i]->chnl_obj, &chnl_info_obj); - if (status) - break; - else - sync_events[i] = - chnl_info_obj.sync_event; - - } - } - if (!status) { - status = - sync_wait_on_multiple_events(sync_events, strms, - utimeout, &index); - if (!status) { - /* Since we waited on the event, we have to - * reset it */ - sync_set_event(sync_events[index]); - *pmask = 1 << index; - } - } - } -func_end: - kfree(sync_events); - - return status; -} - -/* - * ======== delete_strm ======== - * Purpose: - * Frees the resources allocated for a stream. - */ -static int delete_strm(struct strm_object *stream_obj) -{ - struct bridge_drv_interface *intf_fxns; - int status = 0; - - if (stream_obj) { - if (stream_obj->chnl_obj) { - intf_fxns = stream_obj->strm_mgr_obj->intf_fxns; - /* Channel close can fail only if the channel handle - * is invalid. */ - status = (*intf_fxns->chnl_close) - (stream_obj->chnl_obj); - } - /* Free all SM address translator resources */ - kfree(stream_obj->xlator); - kfree(stream_obj); - } else { - status = -EFAULT; - } - return status; -} |