/* ======== DMM_CreateTables ======== * Purpose: * Create table to hold the information of physical address * the buffer pages that is passed by the user, and the table * to hold the information of the virtual memory that is reserved * for DSP. */ DSP_STATUS DMM_CreateTables(struct DMM_OBJECT *hDmmMgr, u32 addr, u32 size) { struct DMM_OBJECT *pDmmObj = (struct DMM_OBJECT *)hDmmMgr; DSP_STATUS status = DSP_SOK; GT_3trace(DMM_debugMask, GT_ENTER, "Entered DMM_CreateTables () hDmmMgr %x, addr" " %x, size %x\n", hDmmMgr, addr, size); status = DMM_DeleteTables(pDmmObj); if (DSP_SUCCEEDED(status)) { SYNC_EnterCS(pDmmObj->hDmmLock); dynMemMapBeg = addr; TableSize = (size/PG_SIZE_4K) + 1; /* Create the free list */ pVirtualMappingTable = (struct MapPage *) MEM_Calloc (TableSize*sizeof(struct MapPage), MEM_NONPAGED); if (pVirtualMappingTable == NULL) status = DSP_EMEMORY; else { /* This table will be used * to store the virtual to physical * address translations */ pPhysicalAddrTable = (u32 *)MEM_Calloc (TableSize*sizeof(u32), MEM_NONPAGED); GT_1trace(DMM_debugMask, GT_4CLASS, "DMM_CreateTables: Allocate" "memory for pPhysicalAddrTable=%d entries\n", TableSize); if (pPhysicalAddrTable == NULL) { status = DSP_EMEMORY; GT_0trace(DMM_debugMask, GT_7CLASS, "DMM_CreateTables: Memory allocation for " "pPhysicalAddrTable failed\n"); } else { /* On successful allocation, * all entries are zero ('free') */ iFreeRegion = 0; iFreeSize = TableSize*PG_SIZE_4K; pVirtualMappingTable[0].RegionSize = TableSize; } } SYNC_LeaveCS(pDmmObj->hDmmLock); } else GT_0trace(DMM_debugMask, GT_7CLASS, "DMM_CreateTables: DMM_DeleteTables" "Failure\n"); GT_1trace(DMM_debugMask, GT_4CLASS, "Leaving DMM_CreateTables status" "0x%x\n", status); return status; }
/* * ======== CreateChirpList ======== * Purpose: * Initialize a queue of channel I/O Request/Completion packets. * Parameters: * uChirps: Number of Chirps to allocate. * Returns: * Pointer to queue of IRPs, or NULL. * Requires: * Ensures: */ static struct LST_LIST *CreateChirpList(u32 uChirps) { struct LST_LIST *pChirpList; struct CHNL_IRP *pChirp; u32 i; pChirpList = MEM_Calloc(sizeof(struct LST_LIST), MEM_NONPAGED); if (pChirpList) { INIT_LIST_HEAD(&pChirpList->head); /* Make N chirps and place on queue. */ for (i = 0; (i < uChirps) && ((pChirp = MakeNewChirp()) != NULL); i++) { LST_PutTail(pChirpList, (struct list_head *)pChirp); } /* If we couldn't allocate all chirps, free those allocated: */ if (i != uChirps) { FreeChirpList(pChirpList); pChirpList = NULL; } } return pChirpList; }
/* * ======== NTFY_Create ======== * Purpose: * Create an empty list of notifications. */ DSP_STATUS NTFY_Create(struct NTFY_OBJECT **phNtfy) { struct NTFY_OBJECT *pNtfy; DSP_STATUS status = DSP_SOK; DBC_Require(phNtfy != NULL); *phNtfy = NULL; MEM_AllocObject(pNtfy, struct NTFY_OBJECT, NTFY_SIGNATURE); if (pNtfy) { status = SYNC_InitializeDPCCS(&pNtfy->hSync); if (DSP_SUCCEEDED(status)) { pNtfy->notifyList = MEM_Calloc(sizeof(struct LST_LIST), MEM_NONPAGED); if (pNtfy->notifyList == NULL) { (void) SYNC_DeleteCS(pNtfy->hSync); MEM_FreeObject(pNtfy); status = DSP_EMEMORY; } else { INIT_LIST_HEAD(&pNtfy->notifyList->head); *phNtfy = pNtfy; } } } else { status = DSP_EMEMORY; } DBC_Ensure((DSP_FAILED(status) && *phNtfy == NULL) || (DSP_SUCCEEDED(status) && MEM_IsValidHandle((*phNtfy), NTFY_SIGNATURE))); return status; }
/* * ======== WMD_CHNL_Create ======== * Create a channel manager object, responsible for opening new channels * and closing old ones for a given board. */ DSP_STATUS WMD_CHNL_Create(OUT struct CHNL_MGR **phChnlMgr, struct DEV_OBJECT *hDevObject, IN CONST struct CHNL_MGRATTRS *pMgrAttrs) { DSP_STATUS status = DSP_SOK; struct CHNL_MGR *pChnlMgr = NULL; s32 cChannels; /* Check DBC requirements: */ DBC_Require(phChnlMgr != NULL); DBC_Require(pMgrAttrs != NULL); DBC_Require(pMgrAttrs->cChannels > 0); DBC_Require(pMgrAttrs->cChannels <= CHNL_MAXCHANNELS); DBC_Require(pMgrAttrs->uWordSize != 0); /* Allocate channel manager object: */ MEM_AllocObject(pChnlMgr, struct CHNL_MGR, CHNL_MGRSIGNATURE); if (pChnlMgr) { /* The cChannels attr must equal the # of supported * chnls for each transport(# chnls for PCPY = DDMA = * ZCPY): i.e. pMgrAttrs->cChannels = CHNL_MAXCHANNELS = * DDMA_MAXDDMACHNLS = DDMA_MAXZCPYCHNLS. */ DBC_Assert(pMgrAttrs->cChannels == CHNL_MAXCHANNELS); cChannels = CHNL_MAXCHANNELS + CHNL_MAXCHANNELS * CHNL_PCPY; /* Create array of channels: */ pChnlMgr->apChannel = MEM_Calloc( sizeof(struct CHNL_OBJECT *) * cChannels, MEM_NONPAGED); if (pChnlMgr->apChannel) { /* Initialize CHNL_MGR object: */ /* Shared memory driver. */ pChnlMgr->dwType = CHNL_TYPESM; pChnlMgr->uWordSize = pMgrAttrs->uWordSize; /* total # chnls supported */ pChnlMgr->cChannels = cChannels; pChnlMgr->cOpenChannels = 0; pChnlMgr->dwOutputMask = 0; pChnlMgr->dwLastOutput = 0; pChnlMgr->hDevObject = hDevObject; if (DSP_SUCCEEDED(status)) status = SYNC_InitializeDPCCS( &pChnlMgr->hCSObj); } else { status = DSP_EMEMORY; } } else { status = DSP_EMEMORY; } if (DSP_FAILED(status)) { WMD_CHNL_Destroy(pChnlMgr); *phChnlMgr = NULL; } else { /* Return channel manager object to caller... */ *phChnlMgr = pChnlMgr; } return status; }
/* * ======== GS_alloc ======== * purpose: * Allocates memory of the specified size. */ void *GS_alloc(u32 size) { void *p; p = MEM_Calloc(size, MEM_PAGED); if (p == NULL) return NULL; cumsize += size; return p; }
/* * ======== freeBlock ======== * TO DO: freeBlock() allocates memory, which could result in failure. * Could allocate an RMM_Header in RMM_alloc(), to be kept in a pool. * freeBlock() could use an RMM_Header from the pool, freeing as blocks * are coalesced. */ static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr, u32 size) { struct RMM_Header *head; struct RMM_Header *thead; struct RMM_Header *rhead; bool retVal = true; /* Create a memory header to hold the newly free'd block. */ rhead = MEM_Calloc(sizeof(struct RMM_Header), MEM_PAGED); if (rhead == NULL) { retVal = false; } else { /* search down the free list to find the right place for addr */ head = target->freeList[segid]; if (addr >= head->addr) { while (head->next != NULL && addr > head->next->addr) head = head->next; thead = head->next; head->next = rhead; rhead->next = thead; rhead->addr = addr; rhead->size = size; } else { *rhead = *head; head->next = rhead; head->addr = addr; head->size = size; thead = rhead->next; } /* join with upper block, if possible */ if (thead != NULL && (rhead->addr + rhead->size) == thead->addr) { head->next = rhead->next; thead->size = size + thead->size; thead->addr = addr; MEM_Free(rhead); rhead = thead; } /* join with the lower block, if possible */ if ((head->addr + head->size) == rhead->addr) { head->next = rhead->next; head->size = head->size + rhead->size; MEM_Free(rhead); } } return retVal; }
/* * ======== regsupInit ======== * Purpose: * Initialize the Registry Support module's private state. */ bool regsupInit(void) { if (pRegKey != NULL) return true; /* Need to allocate and setup our registry. */ pRegKey = MEM_Calloc(sizeof(struct RegKeyStruct), MEM_NONPAGED); if (pRegKey == NULL) return false; return true; }
/* * ======== MakeNewChirp ======== * Allocate the memory for a new channel IRP. */ static struct CHNL_IRP *MakeNewChirp(void) { struct CHNL_IRP *pChirp; pChirp = (struct CHNL_IRP *)MEM_Calloc( sizeof(struct CHNL_IRP), MEM_NONPAGED); if (pChirp != NULL) { /* LST_InitElem only resets the list's member values. */ LST_InitElem(&pChirp->link); } return pChirp; }
/* * ======== AddNewMsg ======== * Must be called in message manager critical section. */ static DSP_STATUS AddNewMsg(struct LST_LIST *msgList) { struct MSG_FRAME *pMsg; DSP_STATUS status = DSP_SOK; pMsg = (struct MSG_FRAME *)MEM_Calloc(sizeof(struct MSG_FRAME), MEM_PAGED); if (pMsg != NULL) { LST_InitElem((struct LST_ELEM *) pMsg); LST_PutTail(msgList, (struct LST_ELEM *) pMsg); } else { status = DSP_EMEMORY; } return status; }
/* * ======== LST_Create ======== * Purpose: * Allocates and initializes a circular list. */ struct LST_LIST *LST_Create(void) { struct LST_LIST *pList; GT_0trace(LST_debugMask, GT_ENTER, "LST_Create: entered\n"); pList = (struct LST_LIST *) MEM_Calloc(sizeof(struct LST_LIST), MEM_NONPAGED); if (pList != NULL) { pList->head.next = &pList->head; pList->head.prev = &pList->head; pList->head.self = NULL; } return pList; }
/** ============================================================================ * @func LIST_Create * * @desc Allocates and initializes a circular list. * * @modif None * ============================================================================ */ EXPORT_API DSP_STATUS LIST_Create (OUT List ** list) { DSP_STATUS status = DSP_SOK ; List * myList = NULL ; TRC_1ENTER ("LIST_Create", list) ; DBC_Require (list != NULL) ; if (list == NULL) { status = DSP_EINVALIDARG ; SET_FAILURE_REASON ; } else { status = MEM_Calloc ((Void **) &myList, sizeof(List), MEM_DEFAULT) ; if (DSP_FAILED (status)) { status = DSP_EMEMORY ; SET_FAILURE_REASON ; } else { DBC_Assert (myList != NULL) ; myList->head.next = &(myList->head) ; myList->head.prev = &(myList->head) ; *list = myList ; } } DBC_Ensure ( (DSP_SUCCEEDED (status) && (*list != NULL)) || (DSP_FAILED (status))) ; TRC_1LEAVE ("LIST_Create", status) ; return status ; }
/* * ======== COD_Open ======== * Open library for reading sections. */ DSP_STATUS COD_Open(struct COD_MANAGER *hMgr, IN char *pszCoffPath, COD_FLAGS flags, struct COD_LIBRARYOBJ **pLib) { DSP_STATUS status = DSP_SOK; struct COD_LIBRARYOBJ *lib = NULL; DBC_Require(cRefs > 0); DBC_Require(IsValid(hMgr)); DBC_Require(pszCoffPath != NULL); DBC_Require(flags == COD_NOLOAD || flags == COD_SYMB); DBC_Require(pLib != NULL); GT_4trace(COD_debugMask, GT_ENTER, "Entered COD_Open, hMgr: 0x%x\n\t " "pszCoffPath: 0x%x\tflags: 0x%x\tlib: 0x%x\n", hMgr, pszCoffPath, flags, pLib); *pLib = NULL; lib = MEM_Calloc(sizeof(struct COD_LIBRARYOBJ), MEM_NONPAGED); if (lib == NULL) { GT_0trace(COD_debugMask, GT_7CLASS, "COD_Open: Out Of Memory\n"); status = DSP_EMEMORY; } if (DSP_SUCCEEDED(status)) { lib->hCodMgr = hMgr; status = hMgr->fxns.openFxn(hMgr->target, pszCoffPath, flags, &lib->dbllLib); if (DSP_FAILED(status)) { GT_1trace(COD_debugMask, GT_7CLASS, "COD_Open failed: 0x%x\n", status); } else { *pLib = lib; } } return status; }
/* * ======== PROCWRAP_GetTrace ======== */ u32 PROCWRAP_GetTrace(union Trapped_Args *args, void *pr_ctxt) { DSP_STATUS status; u8 *pBuf; GT_0trace(WCD_debugMask, GT_ENTER, "PROCWRAP_GetTrace: entered\n"); DBC_Require(args->ARGS_PROC_GETTRACE.uMaxSize <= MAX_TRACEBUFLEN); pBuf = MEM_Calloc(args->ARGS_PROC_GETTRACE.uMaxSize, MEM_NONPAGED); if (pBuf != NULL) { status = PROC_GetTrace(args->ARGS_PROC_GETTRACE.hProcessor, pBuf, args->ARGS_PROC_GETTRACE.uMaxSize); } else { status = DSP_EMEMORY; } cp_to_usr(args->ARGS_PROC_GETTRACE.pBuf, pBuf, status, args->ARGS_PROC_GETTRACE.uMaxSize); if (pBuf) MEM_Free(pBuf); return status; }
/* This function is called when an application opens a handle to the * bridge driver. */ static int bridge_open(struct inode *ip, struct file *filp) { int status = 0; struct PROCESS_CONTEXT *pr_ctxt = NULL; #ifdef CONFIG_BRIDGE_RECOVERY if (recover) wait_for_completion(&bridge_open_comp); #endif /* * Allocate a new process context and insert it into global * process context list. */ pr_ctxt = MEM_Calloc(sizeof(struct PROCESS_CONTEXT), MEM_PAGED); if (pr_ctxt) { pr_ctxt->resState = 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); mutex_init(&pr_ctxt->node_mutex); mutex_init(&pr_ctxt->strm_mutex); } else { status = -ENOMEM; } filp->private_data = pr_ctxt; #ifdef CONFIG_BRIDGE_RECOVERY if (!status) atomic_inc(&bridge_cref); #endif return status; }
/* * ======== COD_Create ======== * Purpose: * Create an object to manage code on a DSP system. * This object can be used to load an initial program image with * arguments that can later be expanded with * dynamically loaded object files. * */ DSP_STATUS COD_Create(OUT struct COD_MANAGER **phMgr, char *pstrDummyFile, IN OPTIONAL CONST struct COD_ATTRS *attrs) { struct COD_MANAGER *hMgrNew; struct DBLL_Attrs zlAttrs; DSP_STATUS status = DSP_SOK; DBC_Require(cRefs > 0); DBC_Require(phMgr != NULL); GT_3trace(COD_debugMask, GT_ENTER, "Entered COD_Create, Args: \t\nphMgr: " "0x%x\t\npstrDummyFile: 0x%x\t\nattr: 0x%x\n", phMgr, pstrDummyFile, attrs); /* assume failure */ *phMgr = NULL; /* we don't support non-default attrs yet */ if (attrs != NULL) return DSP_ENOTIMPL; hMgrNew = MEM_Calloc(sizeof(struct COD_MANAGER), MEM_NONPAGED); if (hMgrNew == NULL) { GT_0trace(COD_debugMask, GT_7CLASS, "COD_Create: Out Of Memory\n"); return DSP_EMEMORY; } hMgrNew->ulMagic = MAGIC; /* Set up loader functions */ hMgrNew->fxns = dbllFxns; /* initialize the ZL module */ hMgrNew->fxns.initFxn(); zlAttrs.alloc = (DBLL_AllocFxn)NoOp; zlAttrs.free = (DBLL_FreeFxn)NoOp; zlAttrs.fread = (DBLL_ReadFxn)COD_fRead; zlAttrs.fseek = (DBLL_SeekFxn)COD_fSeek; zlAttrs.ftell = (DBLL_TellFxn)COD_fTell; zlAttrs.fclose = (DBLL_FCloseFxn)COD_fClose; zlAttrs.fopen = (DBLL_FOpenFxn)COD_fOpen; zlAttrs.symLookup = NULL; zlAttrs.baseImage = true; zlAttrs.logWrite = NULL; zlAttrs.logWriteHandle = NULL; zlAttrs.write = NULL; zlAttrs.rmmHandle = NULL; zlAttrs.wHandle = NULL; zlAttrs.symHandle = NULL; zlAttrs.symArg = NULL; hMgrNew->attrs = zlAttrs; status = hMgrNew->fxns.createFxn(&hMgrNew->target, &zlAttrs); if (DSP_FAILED(status)) { COD_Delete(hMgrNew); GT_1trace(COD_debugMask, GT_7CLASS, "COD_Create:ZL Create Failed: 0x%x\n", status); return COD_E_ZLCREATEFAILED; } /* return the new manager */ *phMgr = hMgrNew; GT_1trace(COD_debugMask, GT_1CLASS, "COD_Create: Success CodMgr: 0x%x\n", *phMgr); return DSP_SOK; }
/** ============================================================================ * @func LDRV_getLinkGppCfg * * @desc Gets the pointer to kernel configuration structure after creating * it (if required). Copies only GPP structures. * * @modif None * ============================================================================ */ NORMAL_API DSP_STATUS LDRV_getLinkGppCfg (IN LINKCFG_Object * linkCfg, OUT LINKCFG_Object ** knlLinkCfg) { DSP_STATUS status = DSP_SOK ; LINKCFG_Object * knlCfg = NULL ; Void * tmpUsrPtr ; Uint32 size ; Uint32 procId ; Uint32 i ; TRC_2ENTER ("LDRV_getLinkCfg", linkCfg, knlLinkCfg) ; DBC_Require (linkCfg != NULL) ; DBC_Require (knlLinkCfg != NULL) ; /* ------------------------------------------------------------------------ * Allocate memory for the global LINKCFG object and initialize it. * ------------------------------------------------------------------------ */ status = MEM_Calloc ((Void **) knlLinkCfg, sizeof (LINKCFG_Object), MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { knlCfg = *knlLinkCfg ; /* Copy the contents of the object from user-space. Return value * indicates number of bytes that were not copied. */ status = USER_copyFromUser ((Void *) knlCfg, (Void *) linkCfg, sizeof (LINKCFG_Object)) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } } else { SET_FAILURE_REASON ; } /* ------------------------------------------------------------------------ * Allocate memory required for the GPP object and initialize it. * ------------------------------------------------------------------------ */ if (DSP_SUCCEEDED (status)) { tmpUsrPtr = (Void *) knlCfg->gppObject ; size = sizeof (LINKCFG_Gpp) ; /* Allocate memory for the GPP object. */ status = MEM_Alloc ((Void **) &(knlCfg->gppObject), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the object from user-space. */ status = USER_copyFromUser ((Void *) (knlCfg->gppObject), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } } else { SET_FAILURE_REASON ; } } /* ------------------------------------------------------------------------ * Get the DSP Config if available, this ensures that multi-process works, * If values provided at setup are from a process, proc_attach done by some * other process then copy_to_user must pass. * ------------------------------------------------------------------------ */ for (procId = 0 ; (procId < MAX_DSPS) && (DSP_SUCCEEDED (status)) ; ) { status = LDRV_getLinkDspCfg (procId, knlCfg->dspConfigs [procId], *knlLinkCfg) ; if (DSP_SUCCEEDED(status)) procId++ ; } if (DSP_FAILED (status)) { /* Free the copied DSP values */ for (i = 0 ; i < procId ; i++) { LDRV_freeLinkDspCfg (i, *knlLinkCfg) ; } /* Free the GPP value */ LDRV_freeLinkGppCfg (knlCfg) ; } TRC_1LEAVE ("LDRV_getLinkGppCfg", status) ; return status ; }
/** ============================================================================ * @func LDRV_getLinkDspCfg * * @desc Gets the pointer to kernel configuration structure after creating * it (if required). Copies only DSP structures. * * @modif None * ============================================================================ */ NORMAL_API DSP_STATUS LDRV_getLinkDspCfg (IN ProcessorId procId, IN LINKCFG_DspConfig * dspCfg, OUT LINKCFG_Object * knlLinkCfg) { DSP_STATUS status = DSP_SOK ; LINKCFG_DspConfig * knlDspCfg = NULL ; LINKCFG_Dsp * dspObject = NULL ; #if !(defined (ONLY_PROC_COMPONENT)) LINKCFG_LinkDrv * linkDrvObject = NULL ; #endif /* if !(defined (ONLY_PROC_COMPONENT)) */ Void * tmpUsrPtr ; Void * tmpKnlPtr ; Uint32 size ; Uint32 tableId ; TRC_3ENTER ("LDRV_getLinkDspCfg",procId, dspCfg, knlLinkCfg) ; DBC_Require (knlLinkCfg != NULL) ; DBC_Require (IS_VALID_PROCID (procId)) ; if (DSP_SUCCEEDED (status)) { size = sizeof (LINKCFG_DspConfig) ; /* Allocate memory for the DSP object. */ status = MEM_Alloc ((Void **) &(tmpKnlPtr), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the objects from user-space. */ status = USER_copyFromUser ((Void *) tmpKnlPtr, (void *) dspCfg, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } else { knlLinkCfg->dspConfigs [procId] = tmpKnlPtr ; knlDspCfg = tmpKnlPtr ; } } else { SET_FAILURE_REASON ; } } /* ------------------------------------------------------------------------ * Allocate memory required for the DSP and initialize it. * ------------------------------------------------------------------------ */ if (DSP_SUCCEEDED (status)) { tmpUsrPtr = knlDspCfg->dspObject ; size = sizeof (LINKCFG_Dsp) ; /* Allocate memory for the DSP object. */ status = MEM_Alloc ((Void **) &(knlDspCfg->dspObject), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the objects from user-space. */ status = USER_copyFromUser ((Void *) knlDspCfg->dspObject, (void *) tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } else { dspObject = knlDspCfg->dspObject ; } } else { SET_FAILURE_REASON ; } } /* ------------------------------------------------------------------------ * Allocate memory required for the Link driver object array and initialize * it. * ------------------------------------------------------------------------ */ #if !(defined (ONLY_PROC_COMPONENT)) if (DSP_SUCCEEDED (status)) { tmpUsrPtr = (Void *) knlDspCfg->linkDrvObjects ; size = sizeof (LINKCFG_LinkDrv) * knlDspCfg->numDrvs ; /* Allocate memory for the Link Driver object array. */ status = MEM_Alloc ((Void **) &(knlDspCfg->linkDrvObjects), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the objects from user-space. */ status = USER_copyFromUser ((Void *) (knlDspCfg->linkDrvObjects), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } else { linkDrvObject = &knlDspCfg->linkDrvObjects [dspObject->linkDrvId] ; } } else { SET_FAILURE_REASON ; } } #endif /* if !(defined (ONLY_PROC_COMPONENT)) */ /* ------------------------------------------------------------------------ * Allocate memory required for the array of memory tables and initialize * it. * ------------------------------------------------------------------------ */ if (DSP_SUCCEEDED (status)) { tmpUsrPtr = (Void *) knlDspCfg->memTables ; size = sizeof (LINKCFG_MemEntry *) * knlDspCfg->numMemTables ; /* Allocate memory for the array of pointers to memory tables. */ status = MEM_Calloc ((Void **) &(knlDspCfg->memTables), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the array of pointers from user-space. */ status = USER_copyFromUser ((Void *) (knlDspCfg->memTables), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } else { tableId = knlDspCfg->dspObject->memTableId ; tmpUsrPtr = (Void *) knlDspCfg->memTables [tableId] ; size = sizeof (LINKCFG_MemEntry) * knlDspCfg->dspObject->memEntries ; /* Allocate memory for the memory table. */ status = MEM_Alloc ((Void **) &(knlDspCfg->memTables [tableId]), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the objects from user-space. */ status = USER_copyFromUser ( (Void *) (knlDspCfg->memTables [tableId]), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } } else { SET_FAILURE_REASON ; } } } else { SET_FAILURE_REASON ; } } #if !(defined (ONLY_PROC_COMPONENT)) /* ------------------------------------------------------------------------ * Allocate memory required for the array of IPS tables and initialize it. * ------------------------------------------------------------------------ */ if (DSP_SUCCEEDED (status)) { tmpUsrPtr = (Void *) knlDspCfg->ipsTables ; size = sizeof (LINKCFG_Ips *) * knlDspCfg->numIpsTables ; /* Allocate memory for the array of pointers to IPS tables. */ status = MEM_Calloc ((Void **) &(knlDspCfg->ipsTables), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the array of pointers from user-space. */ status = USER_copyFromUser ((Void *) (knlDspCfg->ipsTables), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } else { tableId = linkDrvObject->ipsTableId; tmpUsrPtr = (Void *) knlDspCfg->ipsTables [tableId] ; size = sizeof (LINKCFG_Ips) * linkDrvObject->numIpsEntries ; /* Allocate memory for the IPS table. */ status = MEM_Alloc ((Void **) &(knlDspCfg->ipsTables [tableId]), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the objects from user-space. */ status = USER_copyFromUser ((Void *) (knlDspCfg->ipsTables [tableId]), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } } } } else { SET_FAILURE_REASON ; } } #if defined (POOL_COMPONENT) /* ------------------------------------------------------------------------ * Allocate memory required for the array of Pool tables and initialize it. * ------------------------------------------------------------------------ */ if (DSP_SUCCEEDED (status)) { tmpUsrPtr = (Void *) knlDspCfg->poolTables ; size = sizeof (LINKCFG_Pool *) * knlDspCfg->numPoolTables ; /* Allocate memory for the array of pointers to Pool tables. */ status = MEM_Calloc ((Void **) &(knlDspCfg->poolTables), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the array of pointers from user-space. */ status = USER_copyFromUser ((Void *) (knlDspCfg->poolTables), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } else { tableId = linkDrvObject->poolTableId ; tmpUsrPtr = (Void *) knlDspCfg->poolTables [tableId] ; size = sizeof (LINKCFG_Pool) * linkDrvObject->numPools ; /* Allocate memory for the Pool table. */ status = MEM_Alloc ((Void **) &(knlDspCfg->poolTables [tableId]), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the objects from user-space. */ status = USER_copyFromUser ( (Void *) (knlDspCfg->poolTables [tableId]), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } } else { SET_FAILURE_REASON ; } } } else { SET_FAILURE_REASON ; } } #endif /* if defined (POOL_COMPONENT) */ #if defined (CHNL_COMPONENT) /* ------------------------------------------------------------------------ * Allocate memory required for the array of Data driver tables and * initialize it. * ------------------------------------------------------------------------ */ if (DSP_SUCCEEDED (status)) { tmpUsrPtr = (Void *) knlDspCfg->dataTables ; size = sizeof (LINKCFG_DataDrv *) * knlDspCfg->numDataTables ; /* Allocate memory for the array of pointers to Data driver tables. */ status = MEM_Calloc ((Void **) &(knlDspCfg->dataTables), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the array of pointers from user-space. */ status = USER_copyFromUser ((Void *) (knlDspCfg->dataTables), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } else { tableId = linkDrvObject->dataTableId ; tmpUsrPtr = (Void *) knlDspCfg->dataTables [tableId] ; size = sizeof (LINKCFG_DataDrv) * linkDrvObject->numDataDrivers ; /* Allocate memory for the Data driver table. */ status = MEM_Alloc ((Void **) &(knlDspCfg->dataTables [tableId]), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the objects from user-space. */ status = USER_copyFromUser ( (Void *) (knlDspCfg->dataTables [tableId]), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } } else { SET_FAILURE_REASON ; } } } else { SET_FAILURE_REASON ; } } #endif /* if defined (CHNL_COMPONENT) */ #if defined (MSGQ_COMPONENT) /* ------------------------------------------------------------------------ * Allocate memory required for the MQT object array and initialize it. * ------------------------------------------------------------------------ */ if (DSP_SUCCEEDED (status)) { tmpUsrPtr = (Void *) knlDspCfg->mqtObjects ; size = sizeof (LINKCFG_Mqt) * knlDspCfg->numMqts ; /* Allocate memory for the MQT object array. */ status = MEM_Alloc ((Void **) &(knlDspCfg->mqtObjects), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the objects from user-space. */ status = USER_copyFromUser ((Void *) (knlDspCfg->mqtObjects), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } } else { SET_FAILURE_REASON ; } } #endif /* if defined (MSGQ_COMPONENT) */ #if defined (RINGIO_COMPONENT) /* ------------------------------------------------------------------------ * Allocate memory required for the RingIO object array and initialize it. * ------------------------------------------------------------------------ */ if (DSP_SUCCEEDED (status)) { tmpUsrPtr = (Void *) knlDspCfg->ringIoObjects ; size = sizeof (LINKCFG_RingIo) * knlDspCfg->numRingIo ; /* Allocate memory for the RingIO object array. */ status = MEM_Alloc ((Void **) &(knlDspCfg->ringIoObjects), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the objects from user-space. */ status = USER_copyFromUser ((Void *)(knlDspCfg->ringIoObjects), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } } else { SET_FAILURE_REASON ; } } #endif /* if defined (RINGIO_COMPONENT) */ #if defined (MPLIST_COMPONENT) /* ------------------------------------------------------------------------ * Allocate memory required for the MPLIST object array and initialize it. * ------------------------------------------------------------------------ */ if (DSP_SUCCEEDED (status)) { tmpUsrPtr = (Void *) knlDspCfg->mplistObjects ; size = sizeof (LINKCFG_MpList) * knlDspCfg->numMpList ; /* Allocate memory for the MPLIST object array. */ status = MEM_Alloc ((Void **) &(knlDspCfg->mplistObjects), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the objects from user-space. */ status = USER_copyFromUser ((Void *)(knlDspCfg->mplistObjects), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } } else { SET_FAILURE_REASON ; } } #endif /* if defined (MPLIST_COMPONENT) */ #if defined (MPCS_COMPONENT) /* ------------------------------------------------------------------------ * Allocate memory required for the MPCS object array and initialize it. * ------------------------------------------------------------------------ */ if (DSP_SUCCEEDED (status)) { tmpUsrPtr = (Void *) knlDspCfg->mpcsObjects ; size = sizeof (LINKCFG_Mpcs) * knlDspCfg->numMpcs ; /* Allocate memory for the MPCS object array. */ status = MEM_Alloc ((Void **) &(knlDspCfg->mpcsObjects), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the objects from user-space. */ status = USER_copyFromUser ((Void *) (knlDspCfg->mpcsObjects), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } } else { SET_FAILURE_REASON ; } } #endif /* if defined (MPCS_COMPONENT) */ #if defined (LOG_COMPONENT) /* ------------------------------------------------------------------------ * Allocate memory required for the LOG object and initialize it. * ------------------------------------------------------------------------ */ if (DSP_SUCCEEDED (status)) { tmpUsrPtr = (Void *) knlDspCfg->logObject ; size = sizeof (LINKCFG_Log) ; /* Allocate memory for the GPP object. */ status = MEM_Alloc ((Void **) &(knlDspCfg->logObject), size, MEM_DEFAULT) ; if (DSP_SUCCEEDED (status)) { /* Copy the contents of the object from user-space. */ status = USER_copyFromUser ((Void *) (knlDspCfg->logObject), tmpUsrPtr, size) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } } else { SET_FAILURE_REASON ; } } #endif /* if defined (LOG_COMPONENT) */ #endif /* if !(defined (ONLY_PROC_COMPONENT)) */ if (DSP_FAILED (status)) { LDRV_freeLinkDspCfg (procId, knlLinkCfg) ; } TRC_1LEAVE ("LDRV_getLinkDspCfg", status) ; return status ; }
/* * ======== DBLL_open ======== */ DSP_STATUS DBLL_open(struct DBLL_TarObj *target, char *file, DBLL_Flags flags, struct DBLL_LibraryObj **pLib) { struct DBLL_TarObj *zlTarget = (struct DBLL_TarObj *)target; struct DBLL_LibraryObj *zlLib = NULL; s32 err; DSP_STATUS status = DSP_SOK; DBC_Require(cRefs > 0); DBC_Require(MEM_IsValidHandle(zlTarget, DBLL_TARGSIGNATURE)); DBC_Require(zlTarget->attrs.fopen != NULL); DBC_Require(file != NULL); DBC_Require(pLib != NULL); GT_3trace(DBLL_debugMask, GT_ENTER, "DBLL_open: target: 0x%x file: %s pLib:" " 0x%x\n", target, file, pLib); zlLib = zlTarget->head; while (zlLib != NULL) { if (strcmp(zlLib->fileName, file) == 0) { /* Library is already opened */ zlLib->openRef++; break; } zlLib = zlLib->next; } if (zlLib == NULL) { /* Allocate DBL library object */ MEM_AllocObject(zlLib, struct DBLL_LibraryObj, DBLL_LIBSIGNATURE); if (zlLib == NULL) { GT_0trace(DBLL_debugMask, GT_6CLASS, "DBLL_open: Memory allocation failed\n"); status = DSP_EMEMORY; } else { zlLib->ulPos = 0; /* Increment ref count to allow close on failure * later on */ zlLib->openRef++; zlLib->pTarget = zlTarget; /* Keep a copy of the file name */ zlLib->fileName = MEM_Calloc(strlen(file) + 1, MEM_PAGED); if (zlLib->fileName == NULL) { GT_0trace(DBLL_debugMask, GT_6CLASS, "DBLL_open: Memory " "allocation failed\n"); status = DSP_EMEMORY; } else { strncpy(zlLib->fileName, file, strlen(file) + 1); } zlLib->symTab = NULL; } } /* * Set up objects needed by the dynamic loader */ if (DSP_FAILED(status)) goto func_cont; /* Stream */ zlLib->stream.dlStream.read_buffer = readBuffer; zlLib->stream.dlStream.set_file_posn = setFilePosn; zlLib->stream.lib = zlLib; /* Symbol */ zlLib->symbol.dlSymbol.Add_To_Symbol_Table = addToSymbolTable; zlLib->symbol.dlSymbol.Find_Matching_Symbol = findSymbol; zlLib->symbol.dlSymbol.Purge_Symbol_Table = purgeSymbolTable; zlLib->symbol.dlSymbol.Allocate = allocate; zlLib->symbol.dlSymbol.Deallocate = deallocate; zlLib->symbol.dlSymbol.Error_Report = errorReport; zlLib->symbol.lib = zlLib; /* Allocate */ zlLib->allocate.dlAlloc.Allocate = rmmAlloc; zlLib->allocate.dlAlloc.Deallocate = rmmDealloc; zlLib->allocate.lib = zlLib; /* Init */ zlLib->init.dlInit.connect = connect; zlLib->init.dlInit.readmem = readMem; zlLib->init.dlInit.writemem = writeMem; zlLib->init.dlInit.fillmem = fillMem; zlLib->init.dlInit.execute = execute; zlLib->init.dlInit.release = release; zlLib->init.lib = zlLib; if (DSP_SUCCEEDED(status) && zlLib->fp == NULL) status = dofOpen(zlLib); zlLib->ulPos = (*(zlLib->pTarget->attrs.ftell)) (zlLib->fp); (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, (long) 0, SEEK_SET); /* Create a hash table for symbols if flag is set */ if (zlLib->symTab != NULL || !(flags & DBLL_SYMB)) goto func_cont; zlLib->symTab = GH_create(MAXBUCKETS, sizeof(struct Symbol), nameHash, nameMatch, symDelete); if (zlLib->symTab == NULL) { status = DSP_EMEMORY; } else { /* Do a fake load to get symbols - set write function to NoOp */ zlLib->init.dlInit.writemem = NoOp; err = Dynamic_Open_Module(&zlLib->stream.dlStream, &zlLib->symbol.dlSymbol, &zlLib->allocate.dlAlloc, &zlLib->init.dlInit, 0, &zlLib->mHandle); if (err != 0) { GT_1trace(DBLL_debugMask, GT_6CLASS, "DBLL_open: " "Dynamic_Load_Module failed: 0x%lx\n", err); status = DSP_EDYNLOAD; } else { /* Now that we have the symbol table, we can unload */ err = Dynamic_Unload_Module(zlLib->mHandle, &zlLib->symbol.dlSymbol, &zlLib->allocate.dlAlloc, &zlLib->init.dlInit); if (err != 0) { GT_1trace(DBLL_debugMask, GT_6CLASS, "DBLL_open: " "Dynamic_Unload_Module failed: 0x%lx\n", err); status = DSP_EDYNLOAD; } zlLib->mHandle = NULL; } } func_cont: if (DSP_SUCCEEDED(status)) { if (zlLib->openRef == 1) { /* First time opened - insert in list */ if (zlTarget->head) (zlTarget->head)->prev = zlLib; zlLib->prev = NULL; zlLib->next = zlTarget->head; zlTarget->head = zlLib; } *pLib = (struct DBLL_LibraryObj *)zlLib; } else { *pLib = NULL; if (zlLib != NULL) DBLL_close((struct DBLL_LibraryObj *)zlLib); } DBC_Ensure((DSP_SUCCEEDED(status) && (zlLib->openRef > 0) && MEM_IsValidHandle(((struct DBLL_LibraryObj *)(*pLib)), DBLL_LIBSIGNATURE)) || (DSP_FAILED(status) && *pLib == NULL)); return status; }
/* * ======== RMM_alloc ======== */ DSP_STATUS RMM_alloc(struct RMM_TargetObj *target, u32 segid, u32 size, u32 align, u32 *dspAddr, bool reserve) { struct RMM_OvlySect *sect; struct RMM_OvlySect *prevSect = NULL; struct RMM_OvlySect *newSect; u32 addr; DSP_STATUS status = DSP_SOK; DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE)); DBC_Require(dspAddr != NULL); DBC_Require(size > 0); DBC_Require(reserve || (target->numSegs > 0)); DBC_Require(cRefs > 0); GT_6trace(RMM_debugMask, GT_ENTER, "RMM_alloc(0x%lx, 0x%lx, 0x%lx, 0x%lx, " "0x%lx, 0x%lx)\n", target, segid, size, align, dspAddr, reserve); if (!reserve) { if (!allocBlock(target, segid, size, align, dspAddr)) { status = DSP_EMEMORY; } else { /* Increment the number of allocated blocks in this * segment */ target->segTab[segid].number++; } goto func_end; } /* An overlay section - See if block is already in use. If not, * insert into the list in ascending address size. */ addr = *dspAddr; sect = (struct RMM_OvlySect *)LST_First(target->ovlyList); /* Find place to insert new list element. List is sorted from * smallest to largest address. */ while (sect != NULL) { if (addr <= sect->addr) { /* Check for overlap with sect */ if ((addr + size > sect->addr) || (prevSect && (prevSect->addr + prevSect->size > addr))) { status = DSP_EOVERLAYMEMORY; } break; } prevSect = sect; sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList, (struct LST_ELEM *)sect); } if (DSP_SUCCEEDED(status)) { /* No overlap - allocate list element for new section. */ newSect = MEM_Calloc(sizeof(struct RMM_OvlySect), MEM_PAGED); if (newSect == NULL) { status = DSP_EMEMORY; } else { LST_InitElem((struct LST_ELEM *)newSect); newSect->addr = addr; newSect->size = size; newSect->page = segid; if (sect == NULL) { /* Put new section at the end of the list */ LST_PutTail(target->ovlyList, (struct LST_ELEM *)newSect); } else { /* Put new section just before sect */ LST_InsertBefore(target->ovlyList, (struct LST_ELEM *)newSect, (struct LST_ELEM *)sect); } } } func_end: return status; }
/* * ======== RMM_create ======== */ DSP_STATUS RMM_create(struct RMM_TargetObj **pTarget, struct RMM_Segment segTab[], u32 numSegs) { struct RMM_Header *hptr; struct RMM_Segment *sptr, *tmp; struct RMM_TargetObj *target; s32 i; DSP_STATUS status = DSP_SOK; DBC_Require(pTarget != NULL); DBC_Require(numSegs == 0 || segTab != NULL); GT_3trace(RMM_debugMask, GT_ENTER, "RMM_create(0x%lx, 0x%lx, 0x%lx)\n", pTarget, segTab, numSegs); /* Allocate DBL target object */ MEM_AllocObject(target, struct RMM_TargetObj, RMM_TARGSIGNATURE); if (target == NULL) { GT_0trace(RMM_debugMask, GT_6CLASS, "RMM_create: Memory allocation failed\n"); status = DSP_EMEMORY; } if (DSP_FAILED(status)) goto func_cont; target->numSegs = numSegs; if (!(numSegs > 0)) goto func_cont; /* Allocate the memory for freelist from host's memory */ target->freeList = MEM_Calloc(numSegs * sizeof(struct RMM_Header *), MEM_PAGED); if (target->freeList == NULL) { GT_0trace(RMM_debugMask, GT_6CLASS, "RMM_create: Memory allocation failed\n"); status = DSP_EMEMORY; } else { /* Allocate headers for each element on the free list */ for (i = 0; i < (s32) numSegs; i++) { target->freeList[i] = MEM_Calloc(sizeof(struct RMM_Header), MEM_PAGED); if (target->freeList[i] == NULL) { GT_0trace(RMM_debugMask, GT_6CLASS, "RMM_create: Memory " "allocation failed\n"); status = DSP_EMEMORY; break; } } /* Allocate memory for initial segment table */ target->segTab = MEM_Calloc(numSegs * sizeof(struct RMM_Segment), MEM_PAGED); if (target->segTab == NULL) { GT_0trace(RMM_debugMask, GT_6CLASS, "RMM_create: Memory allocation failed\n"); status = DSP_EMEMORY; } else { /* Initialize segment table and free list */ sptr = target->segTab; for (i = 0, tmp = segTab; numSegs > 0; numSegs--, i++) { *sptr = *tmp; hptr = target->freeList[i]; hptr->addr = tmp->base; hptr->size = tmp->length; hptr->next = NULL; tmp++; sptr++; } } } func_cont: /* Initialize overlay memory list */ if (DSP_SUCCEEDED(status)) { target->ovlyList = LST_Create(); if (target->ovlyList == NULL) { GT_0trace(RMM_debugMask, GT_6CLASS, "RMM_create: Memory allocation failed\n"); status = DSP_EMEMORY; } } if (DSP_SUCCEEDED(status)) { *pTarget = target; } else { *pTarget = NULL; if (target) RMM_delete(target); } DBC_Ensure((DSP_SUCCEEDED(status) && MEM_IsValidHandle((*pTarget), RMM_TARGSIGNATURE)) || (DSP_FAILED(status) && *pTarget == NULL)); return status; }
/* * ======== WMD_DEH_Notify ======== * DEH error notification function. Informs user about the error. */ void WMD_DEH_Notify(struct DEH_MGR *hDehMgr, u32 ulEventMask, u32 dwErrInfo) { struct DEH_MGR *pDehMgr = (struct DEH_MGR *)hDehMgr; struct WMD_DEV_CONTEXT *pDevContext; u32 memPhysical = 0; u32 HW_MMU_MAX_TLB_COUNT = 31; extern u32 faultAddr; u32 cnt = 0; if (MEM_IsValidHandle(pDehMgr, SIGNATURE)) { printk(KERN_INFO "WMD_DEH_Notify: ********** DEVICE EXCEPTION " "**********\n"); pDevContext = (struct WMD_DEV_CONTEXT *)pDehMgr->hWmdContext; switch (ulEventMask) { case DSP_SYSERROR: /* reset errInfo structure before use */ pDehMgr->errInfo.dwErrMask = DSP_SYSERROR; pDehMgr->errInfo.dwVal1 = 0L; pDehMgr->errInfo.dwVal2 = 0L; pDehMgr->errInfo.dwVal3 = 0L; pDehMgr->errInfo.dwVal1 = dwErrInfo; printk(KERN_ERR "WMD_DEH_Notify: DSP_SYSERROR, errInfo " "= 0x%x\n", dwErrInfo); dump_dl_modules(pDevContext); dump_dsp_stack(pDevContext); break; case DSP_MMUFAULT: /* MMU fault routine should have set err info * structure */ pDehMgr->errInfo.dwErrMask = DSP_MMUFAULT; printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT," "errInfo = 0x%x\n", dwErrInfo); printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, High " "Address = 0x%x\n", (unsigned int)pDehMgr->errInfo.dwVal1); printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, Low " "Address = 0x%x\n", (unsigned int)pDehMgr->errInfo.dwVal2); printk(KERN_INFO "WMD_DEH_Notify: DSP_MMUFAULT, fault " "address = 0x%x\n", (unsigned int)faultAddr); PrintDspTraceBuffer(pDevContext); dump_dl_modules(pDevContext); dummyVaAddr = (u32)MEM_Calloc(sizeof(char) * 0x1000, MEM_PAGED); memPhysical = VirtToPhys(PG_ALIGN_LOW((u32)dummyVaAddr, PG_SIZE_4K)); pDevContext = (struct WMD_DEV_CONTEXT *) pDehMgr->hWmdContext; /* Reset the dynamic mmu index to fixed count if it * exceeds 31. So that the dynmmuindex is always * between the range of standard/fixed entries * and 31. */ if (pDevContext->numTLBEntries > HW_MMU_MAX_TLB_COUNT) { pDevContext->numTLBEntries = pDevContext-> fixedTLBEntries; } HW_MMU_TLBAdd(pDevContext->dwDSPMmuBase, memPhysical, faultAddr, HW_PAGE_SIZE_4KB, 1, &mapAttrs, HW_SET, HW_SET); /* * Send a GP Timer interrupt to DSP * The DSP expects a GP timer interrupt after an * MMU-Fault Request GPTimer */ if (timer) { omap_dm_timer_enable(timer); /* Enable overflow interrupt */ omap_dm_timer_set_int_enable(timer, GPTIMER_IRQ_OVERFLOW); /* * Set counter value to overflow counter after * one tick and start timer */ omap_dm_timer_set_load_start(timer, 0, 0xfffffffe); /* Wait 80us for timer to overflow */ udelay(80); /* Check interrupt status and */ /* wait for interrupt */ cnt = 0; while (!(omap_dm_timer_read_status(timer) & GPTIMER_IRQ_OVERFLOW)) { if (cnt++ >= GPTIMER_IRQ_WAIT_MAX_CNT) { pr_err("%s: GPTimer interrupt" " failed\n", __func__); break; } } } /* Clear MMU interrupt */ HW_MMU_EventAck(pDevContext->dwDSPMmuBase, HW_MMU_TRANSLATION_FAULT); dump_dsp_stack(hDehMgr->hWmdContext); if (timer) omap_dm_timer_disable(timer); break; #ifdef CONFIG_BRIDGE_NTFY_PWRERR case DSP_PWRERROR: /* reset errInfo structure before use */ pDehMgr->errInfo.dwErrMask = DSP_PWRERROR; pDehMgr->errInfo.dwVal1 = 0L; pDehMgr->errInfo.dwVal2 = 0L; pDehMgr->errInfo.dwVal3 = 0L; pDehMgr->errInfo.dwVal1 = dwErrInfo; printk(KERN_ERR "WMD_DEH_Notify: DSP_PWRERROR, errInfo " "= 0x%x\n", dwErrInfo); break; #endif /* CONFIG_BRIDGE_NTFY_PWRERR */ #ifdef CONFIG_BRIDGE_WDT3 case DSP_WDTOVERFLOW: pDehMgr->errInfo.dwErrMask = DSP_WDTOVERFLOW; pDehMgr->errInfo.dwVal1 = 0L; pDehMgr->errInfo.dwVal2 = 0L; pDehMgr->errInfo.dwVal3 = 0L; pr_err("WMD_DEH_Notify: DSP_WDTOVERFLOW \n "); break; #endif default: DBG_Trace(DBG_LEVEL6, "WMD_DEH_Notify: Unknown Error, errInfo = " "0x%x\n", dwErrInfo); break; } /* Filter subsequent notifications when an error occurs */ if (pDevContext->dwBrdState != BRD_ERROR) { NTFY_Notify(pDehMgr->hNtfy, ulEventMask); #ifdef CONFIG_BRIDGE_RECOVERY bridge_recover_schedule(); #endif } /* Set the Board state as ERROR */ pDevContext->dwBrdState = BRD_ERROR; /* Disable all the clocks that were enabled by DSP */ (void)DSP_PeripheralClocks_Disable(pDevContext, NULL); #ifdef CONFIG_BRIDGE_WDT3 /* * Avoid the subsequent WDT if it happens once, * also If MMU fault occurs */ dsp_wdt_enable(false); #endif } }
/* * ======== NTFY_Register ======== * Purpose: * Add a notification element to the list. If the notification is already * registered, and uEventMask != 0, the notification will get posted for * events specified in the new event mask. If the notification is already * registered and uEventMask == 0, the notification will be unregistered. */ DSP_STATUS NTFY_Register(struct NTFY_OBJECT *hNtfy, struct DSP_NOTIFICATION *hNotification, u32 uEventMask, u32 uNotifyType) { struct NOTIFICATION *pNotify; struct SYNC_ATTRS syncAttrs; DSP_STATUS status = DSP_SOK; DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE)); if (hNotification == NULL) status = DSP_EHANDLE; /* Return DSP_ENOTIMPL if uNotifyType is not supported */ if (DSP_SUCCEEDED(status)) { if (!IsValidNotifyMask(uNotifyType)) status = DSP_ENOTIMPL; } if (DSP_FAILED(status)) return status; (void)SYNC_EnterCS(hNtfy->hSync); pNotify = (struct NOTIFICATION *)LST_First(hNtfy->notifyList); while (pNotify != NULL) { /* If there is more than one notification type, each * type may require its own handler code. */ if (hNotification->handle == pNotify->hSync) { /* found */ break; } pNotify = (struct NOTIFICATION *)LST_Next(hNtfy->notifyList, (struct list_head *)pNotify); } if (pNotify == NULL) { /* Not registered */ if (uEventMask == 0) { status = DSP_EVALUE; } else { /* Allocate NOTIFICATION object, add to list */ pNotify = MEM_Calloc(sizeof(struct NOTIFICATION), MEM_PAGED); if (pNotify == NULL) status = DSP_EMEMORY; } if (DSP_SUCCEEDED(status)) { LST_InitElem((struct list_head *)pNotify); /* If there is more than one notification type, each * type may require its own handler code. */ status = SYNC_OpenEvent(&pNotify->hSync, &syncAttrs); hNotification->handle = pNotify->hSync; if (DSP_SUCCEEDED(status)) { pNotify->uEventMask = uEventMask; pNotify->uNotifyType = uNotifyType; LST_PutTail(hNtfy->notifyList, (struct list_head *)pNotify); } else { DeleteNotify(pNotify); } } } else { /* Found in list */ if (uEventMask == 0) { /* Remove from list and free */ LST_RemoveElem(hNtfy->notifyList, (struct list_head *)pNotify); DeleteNotify(pNotify); } else { /* Update notification mask (type shouldn't change) */ pNotify->uEventMask = uEventMask; } } (void)SYNC_LeaveCS(hNtfy->hSync); return status; }