Hi Greg, Today's linux-next merge of the staging tree got a conflict in drivers/staging/tidspbridge/rmgr/drv_interface.c between commit 5a63177a6967 ("staging: tidspbridge: fix bridge_open memory leaks") from Linus' tree and commit 518761dba127 ("staging: tidspbridge: remove unused header") from the staging tree. I fixed it up (I think - see below) and can carry the fix as necessary. -- Cheers, Stephen Rothwell sfr@xxxxxxxxxxxxxxxx diff --cc drivers/staging/tidspbridge/rmgr/drv_interface.c index 385740b,31b5140..0000000 --- a/drivers/staging/tidspbridge/rmgr/drv_interface.c +++ b/drivers/staging/tidspbridge/rmgr/drv_interface.c @@@ -131,7 -117,157 +117,166 @@@ MODULE_AUTHOR("Texas Instruments") MODULE_LICENSE("GPL"); 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; - } ++ if (!pr_ctxt) ++ return -ENOMEM; ++ ++ 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->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL); - if (pr_ctxt->stream_id) - idr_init(pr_ctxt->stream_id); - else - status = -ENOMEM; - } else { ++ pr_ctxt->node_id = kzalloc(sizeof(struct idr), GFP_KERNEL); ++ if (!pr_ctxt->node_id) { + status = -ENOMEM; ++ goto err1; + } -err: ++ ++ idr_init(pr_ctxt->node_id); ++ ++ pr_ctxt->stream_id = kzalloc(sizeof(struct idr), GFP_KERNEL); ++ if (!pr_ctxt->stream_id) { ++ status = -ENOMEM; ++ goto err2; ++ } ++ ++ idr_init(pr_ctxt->stream_id); ++ + filp->private_data = pr_ctxt; ++ + #ifdef CONFIG_TIDSPBRIDGE_RECOVERY - if (!status) - atomic_inc(&bridge_cref); ++ atomic_inc(&bridge_cref); + #endif ++ return 0; ++ ++err2: ++ kfree(pr_ctxt->node_id); ++err1: ++ kfree(pr_ctxt); + 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->node_id); ++ kfree(pr_ctxt->stream_id); + 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; + + #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 status; + + vma->vm_flags |= VM_RESERVED | VM_IO; + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + dev_dbg(bridge, "%s: vm filp %p start %lx end %lx page_prot %ulx " + "flags %lx\n", __func__, filp, + 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, @@@ -405,14 -540,10 +549,13 @@@ static int __devexit omap34_xx_bridge_r if (driver_context) { /* Put the DSP in reset state */ - ret = dsp_deinit(driver_context); + dsp_deinit(driver_context); driver_context = 0; - DBC_ASSERT(ret == true); } + kfree(drv_datap); + dev_set_drvdata(bridge, NULL); + func_cont: mem_ext_phys_pool_release();
Attachment:
pgpcU8P5E2UXt.pgp
Description: PGP signature