@@ -101,6 +101,15 @@ struct DMM_MAP_OBJECT {
struct DMM_MAP_OBJECT *next;
} ;
+/*
+ * New structure (member of process context) used for accounting of DMM
+ * reserved memory information
+ */
+struct DMM_RSV_OBJECT {
+ struct list_head link;
+ u32 dsp_reserved_addr;
+};
+
/* New structure (member of process context) abstracts DMM resource info */
struct DSPHEAP_RES_OBJECT {
s32 heapAllocated; /* DMM status */
@@ -141,6 +150,10 @@ struct PROCESS_CONTEXT{
/* DMM mapped memory resources */
struct DMM_MAP_OBJECT *dmm_map_list;
+ /* DMM reserved memory resources */
+ struct list_head dmm_rsv_list;
+ spinlock_t dmm_rsv_list_lock;
+
/* DSP Heap resources */
struct DSPHEAP_RES_OBJECT *pDSPHEAPList;
@@ -560,7 +560,7 @@
* Details:
*/
extern DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor,
- u32 ulSize, void **ppRsvAddr);
+ u32 ulSize, void **ppRsvAddr, struct PROCESS_CONTEXT *pr_ctxt);
/*
* ======== PROC_UnMap ========
@@ -604,6 +604,7 @@
* Details:
*/
extern DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor,
- void *pRsvAddr);
+ void *pRsvAddr, struct PROCESS_CONTEXT *pr_ctxt,
+ int cleanup);
#endif /* PROC_ */
@@ -385,9 +385,10 @@ DSP_STATUS DMM_ReserveMemory(struct DMM_OBJECT *hDmmMgr, u32 size,
node->MappedSize = 0;
/* Return the chunk's starting address */
*pRsvAddr = rsvAddr;
- } else
+ } else {
/*dSP chunk of given size is not available */
status = DSP_EMEMORY;
+ }
SYNC_LeaveCS(pDmmObj->hDmmLock);
GT_3trace(DMM_debugMask, GT_4CLASS,
@@ -1054,12 +1054,13 @@ u32 PROCWRAP_ReserveMemory(union Trapped_Args *args, void *pr_ctxt)
GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_ReserveMemory: entered\n");
status = PROC_ReserveMemory(args->ARGS_PROC_RSVMEM.hProcessor,
- args->ARGS_PROC_RSVMEM.ulSize, &pRsvAddr);
+ args->ARGS_PROC_RSVMEM.ulSize, &pRsvAddr,
+ pr_ctxt);
if (DSP_SUCCEEDED(status)) {
if (put_user(pRsvAddr, args->ARGS_PROC_RSVMEM.ppRsvAddr)) {
status = DSP_EINVALIDARG;
PROC_UnReserveMemory(args->ARGS_PROC_RSVMEM.hProcessor,
- pRsvAddr);
+ pRsvAddr, pr_ctxt, 1);
}
}
return status;
@@ -1100,7 +1101,7 @@ u32 PROCWRAP_UnReserveMemory(union Trapped_Args *args, void *pr_ctxt)
GT_0trace(WCD_debugMask, GT_ENTER,
"PROCWRAP_UnReserveMemory: entered\n");
status = PROC_UnReserveMemory(args->ARGS_PROC_UNRSVMEM.hProcessor,
- args->ARGS_PROC_UNRSVMEM.pRsvAddr);
+ args->ARGS_PROC_UNRSVMEM.pRsvAddr, pr_ctxt, 1);
return status;
}
@@ -277,25 +277,20 @@ DSP_STATUS DRV_ProcFreeDMMRes(HANDLE hPCtxt)
if (DSP_FAILED(status))
pr_debug("%s: PROC_UnMap failed! status ="
" 0x%xn", __func__, status);
- status = PROC_UnReserveMemory(pDMMRes->hProcessor,
- (void *)pDMMRes->ulDSPResAddr);
- if (DSP_FAILED(status))
- pr_debug("%s: PROC_UnReserveMemory failed!"
- " status = 0x%xn", __func__, status);
pDMMRes->dmmAllocated = 0;
}
}
return status;
}
-/* Release all DMM resources and its context
-* This is called from .bridge_release. */
+/* Release all Mapped and Reserved DMM resources */
DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE hPCtxt)
{
struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
DSP_STATUS status = DSP_SOK;
struct DMM_MAP_OBJECT *pTempDMMRes2 = NULL;
struct DMM_MAP_OBJECT *pTempDMMRes = NULL;
+ struct DMM_RSV_OBJECT *temp, *rsv_obj;
DRV_ProcFreeDMMRes(pCtxt);
pTempDMMRes = pCtxt->dmm_map_list;
@@ -305,6 +300,24 @@ DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE hPCtxt)
kfree(pTempDMMRes2);
}
pCtxt->dmm_map_list = NULL;
+
+ /* Free DMM reserved memory resources */
+ spin_lock(&pCtxt->dmm_rsv_list_lock);
+ list_for_each_entry_safe(rsv_obj, temp, &pCtxt->dmm_rsv_list, link) {
+ /*
+ * Since we have already acquired spin lock for dmm_rsv_list,
+ * we don't want to perform cleanup in PROC_UnReserveMemory.
+ */
+ status = PROC_UnReserveMemory(pCtxt->hProcessor,
+ (void *)rsv_obj->dsp_reserved_addr, pCtxt, 0);
+ if (DSP_FAILED(status))
+ pr_err("%s: PROC_UnReserveMemory failed!"
+ " status = 0x%xn", __func__, status);
+ list_del(&rsv_obj->link);
+ kfree(rsv_obj);
+ }
+ spin_unlock(&pCtxt->dmm_rsv_list_lock);
+
return status;
}
@@ -497,10 +497,13 @@ static int bridge_open(struct inode *ip, struct file *filp)
* process context list.
*/
pr_ctxt = MEM_Calloc(sizeof(struct PROCESS_CONTEXT), MEM_PAGED);
- if (pr_ctxt)
+ if (pr_ctxt) {
pr_ctxt->resState = PROC_RES_ALLOCATED;
- else
+ spin_lock_init(&pr_ctxt->dmm_rsv_list_lock);
+ INIT_LIST_HEAD(&pr_ctxt->dmm_rsv_list);
+ } else {
status = -ENOMEM;
+ }
filp->private_data = pr_ctxt;
@@ -454,7 +454,7 @@ DSP_STATUS NODE_Allocate(struct PROC_OBJECT *hProcessor,
status = PROC_ReserveMemory(hProcessor,
pNode->createArgs.asa.taskArgs.uHeapSize + PAGE_SIZE,
(void **)&(pNode->createArgs.asa.taskArgs.
- uDSPHeapResAddr));
+ uDSPHeapResAddr), pr_ctxt);
if (DSP_FAILED(status)) {
GT_1trace(NODE_debugMask, GT_5CLASS,
"NODE_Allocate:Failed to reserve "
@@ -2726,7 +2726,8 @@ static void DeleteNode(struct NODE_OBJECT *hNode,
" Status = 0x%x\n", (u32)status);
}
status = PROC_UnReserveMemory(hNode->hProcessor,
- (void *)taskArgs.uDSPHeapResAddr);
+ (void *)taskArgs.uDSPHeapResAddr,
+ pr_ctxt, 1);
if (DSP_SUCCEEDED(status)) {
GT_0trace(NODE_debugMask, GT_5CLASS,
"DSPProcessor_UnReserveMemory "
@@ -1430,7 +1430,7 @@ func_end:
* Reserve a virtually contiguous region of DSP address space.
*/
DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor, u32 ulSize,
- void **ppRsvAddr)
+ void **ppRsvAddr, struct PROCESS_CONTEXT *pr_ctxt)
{
struct DMM_OBJECT *hDmmMgr;
DSP_STATUS status = DSP_SOK;
@@ -1450,8 +1450,21 @@ DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor, u32 ulSize,
if (DSP_FAILED(status)) {
GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_ReserveMemory: "
"Failed to get DMM Mgr handle: 0x%x\n", status);
- } else
+ } else {
status = DMM_ReserveMemory(hDmmMgr, ulSize, (u32 *)ppRsvAddr);
+ if (status == DSP_SOK) {
+ struct DMM_RSV_OBJECT *rsv_obj =
+ kmalloc(sizeof(struct DMM_RSV_OBJECT),
+ GFP_KERNEL);
+ if (rsv_obj) {
+ rsv_obj->dsp_reserved_addr = (u32) *ppRsvAddr;
+ spin_lock(&pr_ctxt->dmm_rsv_list_lock);
+ list_add(&rsv_obj->link,
+ &pr_ctxt->dmm_rsv_list);
+ spin_unlock(&pr_ctxt->dmm_rsv_list_lock);
+ }
+ }
+ }
GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_ReserveMemory [0x%x]",
status);
@@ -1704,7 +1717,8 @@ func_end:
* Purpose:
* Frees a previously reserved region of DSP address space.
*/
-DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor, void *pRsvAddr)
+DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor, void *pRsvAddr,
+ struct PROCESS_CONTEXT *pr_ctxt, int cleanup)
{
struct DMM_OBJECT *hDmmMgr;
DSP_STATUS status = DSP_SOK;
@@ -1720,12 +1734,32 @@ DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor, void *pRsvAddr)
goto func_end;
}
status = DMM_GetHandle(pProcObject, &hDmmMgr);
- if (DSP_FAILED(status))
+ if (DSP_FAILED(status)) {
GT_1trace(PROC_DebugMask, GT_7CLASS,
"PROC_UnReserveMemory: Failed to get DMM Mgr "
"handle: 0x%x\n", status);
- else
+ } else {
status = DMM_UnReserveMemory(hDmmMgr, (u32) pRsvAddr);
+ /*
+ * cleanup flag handles the special case when this function
+ * is called while doing clenaup from
+ * DRV_RemoveAllDMMResElements
+ */
+ if (status == DSP_SOK && cleanup) {
+ struct DMM_RSV_OBJECT *temp, *rsv_obj;
+ spin_lock(&pr_ctxt->dmm_rsv_list_lock);
+ list_for_each_entry_safe(rsv_obj, temp,
+ &pr_ctxt->dmm_rsv_list, link) {
+ if (rsv_obj->dsp_reserved_addr ==
+ (u32)pRsvAddr) {
+ list_del(&rsv_obj->link);
+ kfree(rsv_obj);
+ break;
+ }
+ }
+ spin_unlock(&pr_ctxt->dmm_rsv_list_lock);
+ }
+ }
GT_1trace(PROC_DebugMask, GT_ENTER,
"Leaving PROC_UnReserveMemory [0x%x]",