|
@@ -48,9 +48,6 @@
|
|
|
/* ----------------------------------- Resource Manager */
|
|
|
#include <dspbridge/pwr.h>
|
|
|
|
|
|
-/* ----------------------------------- This */
|
|
|
-#include <drv_interface.h>
|
|
|
-
|
|
|
#include <dspbridge/resourcecleanup.h>
|
|
|
#include <dspbridge/chnl.h>
|
|
|
#include <dspbridge/proc.h>
|
|
@@ -133,6 +130,161 @@ MODULE_VERSION(DSPBRIDGE_VERSION);
|
|
|
|
|
|
static char *driver_name = DRIVER_NAME;
|
|
|
|
|
|
+/*
|
|
|
+ * This function is called when an application opens handle to the
|
|
|
+ * bridge driver.
|
|
|
+ */
|
|
|
+static int bridge_open(struct inode *ip, struct file *filp)
|
|
|
+{
|
|
|
+ int status = 0;
|
|
|
+ struct process_context *pr_ctxt = NULL;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Allocate a new process context and insert it into global
|
|
|
+ * process context list.
|
|
|
+ */
|
|
|
+
|
|
|
+#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
|
|
|
+ if (recover) {
|
|
|
+ if (filp->f_flags & O_NONBLOCK ||
|
|
|
+ wait_for_completion_interruptible(&bridge_open_comp))
|
|
|
+ return -EBUSY;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ pr_ctxt = kzalloc(sizeof(struct process_context), GFP_KERNEL);
|
|
|
+ if (pr_ctxt) {
|
|
|
+ pr_ctxt->res_state = PROC_RES_ALLOCATED;
|
|
|
+ spin_lock_init(&pr_ctxt->dmm_map_lock);
|
|
|
+ INIT_LIST_HEAD(&pr_ctxt->dmm_map_list);
|
|
|
+ spin_lock_init(&pr_ctxt->dmm_rsv_lock);
|
|
|
+ INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list);
|
|
|
+
|
|
|
+ pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
|
|
|
+ if (pr_ctxt->node_id) {
|
|
|
+ idr_init(pr_ctxt->node_id);
|
|
|
+ } else {
|
|
|
+ status = -ENOMEM;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
|
|
|
+ if (pr_ctxt->stream_id)
|
|
|
+ idr_init(pr_ctxt->stream_id);
|
|
|
+ else
|
|
|
+ status = -ENOMEM;
|
|
|
+ } else {
|
|
|
+ status = -ENOMEM;
|
|
|
+ }
|
|
|
+err:
|
|
|
+ filp->private_data = pr_ctxt;
|
|
|
+#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
|
|
|
+ if (!status)
|
|
|
+ atomic_inc(&bridge_cref);
|
|
|
+#endif
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+ * This function is called when an application closes handle to the bridge
|
|
|
+ * driver.
|
|
|
+ */
|
|
|
+static int bridge_release(struct inode *ip, struct file *filp)
|
|
|
+{
|
|
|
+ int status = 0;
|
|
|
+ struct process_context *pr_ctxt;
|
|
|
+
|
|
|
+ if (!filp->private_data) {
|
|
|
+ status = -EIO;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ pr_ctxt = filp->private_data;
|
|
|
+ flush_signals(current);
|
|
|
+ drv_remove_all_resources(pr_ctxt);
|
|
|
+ proc_detach(pr_ctxt);
|
|
|
+ kfree(pr_ctxt);
|
|
|
+
|
|
|
+ filp->private_data = NULL;
|
|
|
+
|
|
|
+err:
|
|
|
+#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
|
|
|
+ if (!atomic_dec_return(&bridge_cref))
|
|
|
+ complete(&bridge_comp);
|
|
|
+#endif
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
+/* This function provides IO interface to the bridge driver. */
|
|
|
+static long bridge_ioctl(struct file *filp, unsigned int code,
|
|
|
+ unsigned long args)
|
|
|
+{
|
|
|
+ int status;
|
|
|
+ u32 retval = 0;
|
|
|
+ union trapped_args buf_in;
|
|
|
+
|
|
|
+ DBC_REQUIRE(filp != NULL);
|
|
|
+#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
|
|
|
+ if (recover) {
|
|
|
+ status = -EIO;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+#ifdef CONFIG_PM
|
|
|
+ status = omap34_xxbridge_suspend_lockout(&bridge_suspend_data, filp);
|
|
|
+ if (status != 0)
|
|
|
+ return status;
|
|
|
+#endif
|
|
|
+
|
|
|
+ if (!filp->private_data) {
|
|
|
+ status = -EIO;
|
|
|
+ goto err;
|
|
|
+ }
|
|
|
+
|
|
|
+ status = copy_from_user(&buf_in, (union trapped_args *)args,
|
|
|
+ sizeof(union trapped_args));
|
|
|
+
|
|
|
+ if (!status) {
|
|
|
+ status = api_call_dev_ioctl(code, &buf_in, &retval,
|
|
|
+ filp->private_data);
|
|
|
+
|
|
|
+ if (!status) {
|
|
|
+ status = retval;
|
|
|
+ } else {
|
|
|
+ dev_dbg(bridge, "%s: IOCTL Failed, code: 0x%x "
|
|
|
+ "status 0x%x\n", __func__, code, status);
|
|
|
+ status = -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+err:
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
+/* This function maps kernel space memory to user space memory. */
|
|
|
+static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
|
|
|
+{
|
|
|
+ u32 offset = vma->vm_pgoff << PAGE_SHIFT;
|
|
|
+ u32 status;
|
|
|
+
|
|
|
+ DBC_ASSERT(vma->vm_start < vma->vm_end);
|
|
|
+
|
|
|
+ vma->vm_flags |= VM_RESERVED | VM_IO;
|
|
|
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
|
|
+
|
|
|
+ dev_dbg(bridge, "%s: vm filp %p offset %x start %lx end %lx page_prot "
|
|
|
+ "%lx flags %lx\n", __func__, filp, offset,
|
|
|
+ vma->vm_start, vma->vm_end, vma->vm_page_prot, vma->vm_flags);
|
|
|
+
|
|
|
+ status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
|
|
+ vma->vm_end - vma->vm_start,
|
|
|
+ vma->vm_page_prot);
|
|
|
+ if (status != 0)
|
|
|
+ status = -EAGAIN;
|
|
|
+
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
static const struct file_operations bridge_fops = {
|
|
|
.open = bridge_open,
|
|
|
.release = bridge_release,
|
|
@@ -477,161 +629,6 @@ static void __exit bridge_exit(void)
|
|
|
platform_driver_unregister(&bridge_driver);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * This function is called when an application opens handle to the
|
|
|
- * bridge driver.
|
|
|
- */
|
|
|
-static int bridge_open(struct inode *ip, struct file *filp)
|
|
|
-{
|
|
|
- int status = 0;
|
|
|
- struct process_context *pr_ctxt = NULL;
|
|
|
-
|
|
|
- /*
|
|
|
- * Allocate a new process context and insert it into global
|
|
|
- * process context list.
|
|
|
- */
|
|
|
-
|
|
|
-#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
|
|
|
- if (recover) {
|
|
|
- if (filp->f_flags & O_NONBLOCK ||
|
|
|
- wait_for_completion_interruptible(&bridge_open_comp))
|
|
|
- return -EBUSY;
|
|
|
- }
|
|
|
-#endif
|
|
|
- pr_ctxt = kzalloc(sizeof(struct process_context), GFP_KERNEL);
|
|
|
- if (pr_ctxt) {
|
|
|
- pr_ctxt->res_state = PROC_RES_ALLOCATED;
|
|
|
- spin_lock_init(&pr_ctxt->dmm_map_lock);
|
|
|
- INIT_LIST_HEAD(&pr_ctxt->dmm_map_list);
|
|
|
- spin_lock_init(&pr_ctxt->dmm_rsv_lock);
|
|
|
- INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list);
|
|
|
-
|
|
|
- pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
|
|
|
- if (pr_ctxt->node_id) {
|
|
|
- idr_init(pr_ctxt->node_id);
|
|
|
- } else {
|
|
|
- status = -ENOMEM;
|
|
|
- goto err;
|
|
|
- }
|
|
|
-
|
|
|
- pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL);
|
|
|
- if (pr_ctxt->stream_id)
|
|
|
- idr_init(pr_ctxt->stream_id);
|
|
|
- else
|
|
|
- status = -ENOMEM;
|
|
|
- } else {
|
|
|
- status = -ENOMEM;
|
|
|
- }
|
|
|
-err:
|
|
|
- filp->private_data = pr_ctxt;
|
|
|
-#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
|
|
|
- if (!status)
|
|
|
- atomic_inc(&bridge_cref);
|
|
|
-#endif
|
|
|
- return status;
|
|
|
-}
|
|
|
-
|
|
|
-/*
|
|
|
- * This function is called when an application closes handle to the bridge
|
|
|
- * driver.
|
|
|
- */
|
|
|
-static int bridge_release(struct inode *ip, struct file *filp)
|
|
|
-{
|
|
|
- int status = 0;
|
|
|
- struct process_context *pr_ctxt;
|
|
|
-
|
|
|
- if (!filp->private_data) {
|
|
|
- status = -EIO;
|
|
|
- goto err;
|
|
|
- }
|
|
|
-
|
|
|
- pr_ctxt = filp->private_data;
|
|
|
- flush_signals(current);
|
|
|
- drv_remove_all_resources(pr_ctxt);
|
|
|
- proc_detach(pr_ctxt);
|
|
|
- kfree(pr_ctxt);
|
|
|
-
|
|
|
- filp->private_data = NULL;
|
|
|
-
|
|
|
-err:
|
|
|
-#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
|
|
|
- if (!atomic_dec_return(&bridge_cref))
|
|
|
- complete(&bridge_comp);
|
|
|
-#endif
|
|
|
- return status;
|
|
|
-}
|
|
|
-
|
|
|
-/* This function provides IO interface to the bridge driver. */
|
|
|
-static long bridge_ioctl(struct file *filp, unsigned int code,
|
|
|
- unsigned long args)
|
|
|
-{
|
|
|
- int status;
|
|
|
- u32 retval = 0;
|
|
|
- union trapped_args buf_in;
|
|
|
-
|
|
|
- DBC_REQUIRE(filp != NULL);
|
|
|
-#ifdef CONFIG_TIDSPBRIDGE_RECOVERY
|
|
|
- if (recover) {
|
|
|
- status = -EIO;
|
|
|
- goto err;
|
|
|
- }
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_PM
|
|
|
- status = omap34_xxbridge_suspend_lockout(&bridge_suspend_data, filp);
|
|
|
- if (status != 0)
|
|
|
- return status;
|
|
|
-#endif
|
|
|
-
|
|
|
- if (!filp->private_data) {
|
|
|
- status = -EIO;
|
|
|
- goto err;
|
|
|
- }
|
|
|
-
|
|
|
- status = copy_from_user(&buf_in, (union trapped_args *)args,
|
|
|
- sizeof(union trapped_args));
|
|
|
-
|
|
|
- if (!status) {
|
|
|
- status = api_call_dev_ioctl(code, &buf_in, &retval,
|
|
|
- filp->private_data);
|
|
|
-
|
|
|
- if (!status) {
|
|
|
- status = retval;
|
|
|
- } else {
|
|
|
- dev_dbg(bridge, "%s: IOCTL Failed, code: 0x%x "
|
|
|
- "status 0x%x\n", __func__, code, status);
|
|
|
- status = -1;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
-err:
|
|
|
- return status;
|
|
|
-}
|
|
|
-
|
|
|
-/* This function maps kernel space memory to user space memory. */
|
|
|
-static int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
|
|
|
-{
|
|
|
- u32 offset = vma->vm_pgoff << PAGE_SHIFT;
|
|
|
- u32 status;
|
|
|
-
|
|
|
- DBC_ASSERT(vma->vm_start < vma->vm_end);
|
|
|
-
|
|
|
- vma->vm_flags |= VM_RESERVED | VM_IO;
|
|
|
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
|
|
|
-
|
|
|
- dev_dbg(bridge, "%s: vm filp %p offset %x start %lx end %lx page_prot "
|
|
|
- "%lx flags %lx\n", __func__, filp, offset,
|
|
|
- vma->vm_start, vma->vm_end, vma->vm_page_prot, vma->vm_flags);
|
|
|
-
|
|
|
- status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
|
|
|
- vma->vm_end - vma->vm_start,
|
|
|
- vma->vm_page_prot);
|
|
|
- if (status != 0)
|
|
|
- status = -EAGAIN;
|
|
|
-
|
|
|
- return status;
|
|
|
-}
|
|
|
-
|
|
|
/* To remove all process resources before removing the process from the
|
|
|
* process context list */
|
|
|
int drv_remove_all_resources(void *process_ctxt)
|