Background: bridge_close() has the responsibility to cleanup all the resources allocated by user space process. One of those resources is DMMRes which is used for tracking DMM resource allocation done in PROC_Map() and PROC_UnMap(). DRV_ProcFreeDMMRes() function was used for cleaning up DMMRes has following problems which are fixed by this patch: 1. It access and modifies pDMMRes pointer when it is already freed by PROC_UnMap() 2. Instead of passing ulDSPAddr it passes ulDSPResAddr to PROC_UnMap() which will not retrive correct DMMRes element. CC: Omar Ramirez Luna <omar.ramirez@xxxxxx> CC: Nishanth Menon <nm@xxxxxx> CC: Deepak Chitriki Rudramuni <deepak.chitriki@xxxxxx> CC: Felipe Contreras <felipe.contreras@xxxxxxxxx> CC: Phil Carmody <ext-phil.2.carmody@xxxxxxxxx> Signed-off-by: Ameya Palande <ameya.palande@xxxxxxxxx> --- arch/arm/plat-omap/include/dspbridge/drv.h | 14 ---- .../plat-omap/include/dspbridge/resourcecleanup.h | 4 +- drivers/dsp/bridge/rmgr/drv.c | 63 ++++++++------------ drivers/dsp/bridge/rmgr/drv_interface.c | 7 +- 4 files changed, 30 insertions(+), 58 deletions(-) diff --git a/arch/arm/plat-omap/include/dspbridge/drv.h b/arch/arm/plat-omap/include/dspbridge/drv.h index b6a5fd2..ba11359 100644 --- a/arch/arm/plat-omap/include/dspbridge/drv.h +++ b/arch/arm/plat-omap/include/dspbridge/drv.h @@ -384,18 +384,4 @@ struct PROCESS_CONTEXT{ */ extern DSP_STATUS DRV_ReleaseResources(IN u32 dwContext, struct DRV_OBJECT *hDrvObject); - -/* - * ======== DRV_ProcFreeDMMRes ======== - * Purpose: - * Actual DMM De-Allocation. - * Parameters: - * hPCtxt: Path to the driver Registry Key. - * Returns: - * DSP_SOK if success; - */ - - - extern DSP_STATUS DRV_ProcFreeDMMRes(HANDLE hPCtxt); - #endif /* DRV_ */ diff --git a/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h b/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h index ffbcf5e..d399a2e 100644 --- a/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h +++ b/arch/arm/plat-omap/include/dspbridge/resourcecleanup.h @@ -25,13 +25,13 @@ extern DSP_STATUS DRV_GetProcCtxtList(struct PROCESS_CONTEXT **pPctxt, extern DSP_STATUS DRV_InsertProcContext(struct DRV_OBJECT *hDrVObject, HANDLE hPCtxt); -extern DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE pCtxt); +extern DSP_STATUS DRV_Remove_All_DMM_Res_Elements(HANDLE hPCtxt); extern DSP_STATUS DRV_RemoveAllNodeResElements(HANDLE pCtxt); extern DSP_STATUS DRV_ProcSetPID(HANDLE pCtxt, s32 hProcess); -extern DSP_STATUS DRV_RemoveAllResources(HANDLE pPctxt); +extern void DRV_RemoveAllResources(HANDLE pPctxt); extern DSP_STATUS DRV_RemoveProcContext(struct DRV_OBJECT *hDRVObject, HANDLE pr_ctxt); diff --git a/drivers/dsp/bridge/rmgr/drv.c b/drivers/dsp/bridge/rmgr/drv.c index eca46ca..570f8a4 100644 --- a/drivers/dsp/bridge/rmgr/drv.c +++ b/drivers/dsp/bridge/rmgr/drv.c @@ -259,52 +259,39 @@ DSP_STATUS DRV_UpdateDMMResElement(HANDLE hDMMRes, u32 pMpuAddr, u32 ulSize, return status; } -/* Actual DMM De-Allocation */ -DSP_STATUS DRV_ProcFreeDMMRes(HANDLE hPCtxt) +/* Release all DMM resources and its context */ +DSP_STATUS DRV_Remove_All_DMM_Res_Elements(HANDLE hPCtxt) { - struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt; + struct PROCESS_CONTEXT *p_ctxt = (struct PROCESS_CONTEXT *)hPCtxt; DSP_STATUS status = DSP_SOK; - struct DMM_RES_OBJECT *pDMMList = pCtxt->pDMMList; - struct DMM_RES_OBJECT *pDMMRes = NULL; - - GT_0trace(curTrace, GT_ENTER, "\nDRV_ProcFreeDMMRes: 1\n"); - while (pDMMList != NULL) { - pDMMRes = pDMMList; - pDMMList = pDMMList->next; - if (pDMMRes->dmmAllocated) { - status = PROC_UnMap(pDMMRes->hProcessor, - (void *)pDMMRes->ulDSPResAddr, pCtxt); + struct DMM_RES_OBJECT *p_dmm_list = p_ctxt->pDMMList; + struct DMM_RES_OBJECT *p_cur_res; + + while (p_dmm_list) { + p_cur_res = p_dmm_list; + p_dmm_list = p_dmm_list->next; + if (p_cur_res->dmmAllocated) { + /* + * PROC_UnMap will free memory allocated to p_cur_res + * pointer. So we need to save following data for the + * execution of PROC_UnReserveMemory() + */ + void *h_processor = p_cur_res->hProcessor; + u32 dsp_res_addr = p_cur_res->ulDSPResAddr; + + status = PROC_UnMap(p_cur_res->hProcessor, + (void *)p_cur_res->ulDSPAddr, p_ctxt); if (DSP_FAILED(status)) pr_debug("%s: PROC_UnMap failed! status =" - " 0x%xn", __func__, status); - status = PROC_UnReserveMemory(pDMMRes->hProcessor, - (void *)pDMMRes->ulDSPResAddr); + " 0x%x\n", __func__, status); + status = PROC_UnReserveMemory(h_processor, + (void *)dsp_res_addr); if (DSP_FAILED(status)) pr_debug("%s: PROC_UnReserveMemory failed!" - " status = 0x%xn", __func__, status); - pDMMRes->dmmAllocated = 0; + " status = 0x%x\n", __func__, status); } } - return status; -} - -/* Release all DMM resources and its context -* This is called from .bridge_release. */ -DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE hPCtxt) -{ - struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt; - DSP_STATUS status = DSP_SOK; - struct DMM_RES_OBJECT *pTempDMMRes2 = NULL; - struct DMM_RES_OBJECT *pTempDMMRes = NULL; - - DRV_ProcFreeDMMRes(pCtxt); - pTempDMMRes = pCtxt->pDMMList; - while (pTempDMMRes != NULL) { - pTempDMMRes2 = pTempDMMRes; - pTempDMMRes = pTempDMMRes->next; - MEM_Free(pTempDMMRes2); - } - pCtxt->pDMMList = NULL; + p_ctxt->pDMMList = NULL; return status; } diff --git a/drivers/dsp/bridge/rmgr/drv_interface.c b/drivers/dsp/bridge/rmgr/drv_interface.c index 625f88e..2e56704 100644 --- a/drivers/dsp/bridge/rmgr/drv_interface.c +++ b/drivers/dsp/bridge/rmgr/drv_interface.c @@ -604,15 +604,14 @@ static int bridge_mmap(struct file *filp, struct vm_area_struct *vma) /* To remove all process resources before removing the process from the * process context list*/ -DSP_STATUS DRV_RemoveAllResources(HANDLE hPCtxt) +void DRV_RemoveAllResources(HANDLE hPCtxt) { - DSP_STATUS status = DSP_SOK; struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt; DRV_RemoveAllSTRMResElements(pCtxt); DRV_RemoveAllNodeResElements(pCtxt); - DRV_RemoveAllDMMResElements(pCtxt); + DRV_Remove_All_DMM_Res_Elements(pCtxt); pCtxt->resState = PROC_RES_FREED; - return status; + return; } /* Bridge driver initialization and de-initialization functions */ -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html