aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/tidspbridge/rmgr/strm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/tidspbridge/rmgr/strm.c')
-rw-r--r--drivers/staging/tidspbridge/rmgr/strm.c733
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;
-}