This patch contain some minor code cleanup compared to previous one.dump_stack() was removed since BUG() will anyway do that work.And changed (vma != NULL) to (vma) Cheers,Ameya. On Thu, Apr 23, 2009 at 12:58 PM, Ameya Palande <ameya.palande@xxxxxxxxx> wrote:>> From: Omar Ramirez Luna <x0084701@xxxxxx>>> From: Omar Ramirez Luna <x0084701@xxxxxx>>> Currently, we walk through the entire page table> translating the addresses from virtual to physical> whenever we map a buffer. This custom implementation> is meant to be optimized for performance, but it bypasses> the standard memory management subsystem.>> This patch removes the custom implementation and uses> the kernel APIs to get the virtual to physical maps.>> Map times for DMM>> Buffer | Kernel APIs | Custom Implement. |> Size | time (usec) | time (usec) |> 4 KB | 427 | 396 |> 64 KB | 1038 | 824 |> 1 MB | 9827 | 7110 |> 4 MB | 37811 | 26916 |> 6 MB | 56366 | 39978 |>> This patch also contains the following cleanup by Ameya Palande.> 1. Coding style improvements> 2. Performance improvement by removal of duplicate code, and variables.> 3. Bugfix for missing SYNC_LeaveCS() call> 4. Extra error checking>> Signed-off-by: Hari Kanigeri <h-kanigeri2@xxxxxx>> Signed-off-by: Omar Ramirez Luna <x0084701@xxxxxx>> Signed-off-by: Ameya Palande <ameya.palande@xxxxxxxxx>> Acked-by: Hiroshi DOYU <Hiroshi.DOYU@xxxxxxxxx>> Tested-by: Felipe Contreras <felipe.contreras@xxxxxxxxx>> ---> drivers/dsp/bridge/wmd/tiomap3430.c | 650 ++++++++++++-----------------------> 1 files changed, 221 insertions(+), 429 deletions(-)>> diff --git a/drivers/dsp/bridge/wmd/tiomap3430.c b/drivers/dsp/bridge/wmd/tiomap3430.c> index fb71e96..2ab585d 100644> --- a/drivers/dsp/bridge/wmd/tiomap3430.c> +++ b/drivers/dsp/bridge/wmd/tiomap3430.c> @@ -1,4 +1,3 @@> -> /*> * tiomap.c> *> @@ -133,9 +132,7 @@ static DSP_STATUS WMD_DEV_Create(OUT struct WMD_DEV_CONTEXT **ppDevContext,> static DSP_STATUS WMD_DEV_Ctrl(struct WMD_DEV_CONTEXT *pDevContext, u32 dwCmd,> IN OUT void *pArgs);> static DSP_STATUS WMD_DEV_Destroy(struct WMD_DEV_CONTEXT *pDevContext);> -static DSP_STATUS TIOMAP_VirtToPhysical(struct mm_struct *mm, u32 ulMpuAddr,> - u32 ulNumBytes, u32 *numOfTableEntries,> - u32 *physicalAddrTable);> +static u32 user_va2pa(struct mm_struct *mm, u32 address);> static DSP_STATUS PteUpdate(struct WMD_DEV_CONTEXT *hDevContext, u32 pa,> u32 va, u32 size,> struct HW_MMUMapAttrs_t *mapAttrs);> @@ -143,7 +140,7 @@ static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,> u32 size, struct HW_MMUMapAttrs_t *attrs);> static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *hDevContext,> u32 ulMpuAddr, u32 ulVirtAddr,> - u32 ulNumBytes, u32 ulMapAttr);> + u32 ulNumBytes, struct HW_MMUMapAttrs_t *hwAttrs);> static DSP_STATUS run_IdleBoot(u32 prcm_base, u32 cm_base,> u32 sysctrl_base);> void GetHWRegs(u32 prcm_base, u32 cm_base);> @@ -270,6 +267,18 @@ static inline void flush_all(struct WMD_DEV_CONTEXT *pDevContext)> tlb_flush_all(pDevContext->dwDSPMmuBase);> }>> +static void bad_page_dump(u32 pa, struct page *pg)> +{> + pr_emerg("DSPBRIDGE: MAP function: COUNT 0 FOR PA 0x%x\n", pa);> + pr_emerg("Bad page state in process '%s'\n"> + "page:%p flags:0x%0*lx mapping:%p mapcount:%d count:%d\n"> + "Backtrace:\n",> + current->comm, pg, (int)(2*sizeof(unsigned long)),> + (unsigned long)pg->flags, pg->mapping,> + page_mapcount(pg), page_count(pg));> + BUG();> +}> +> /*> * ======== WMD_DRV_Entry ========> * purpose:> @@ -1352,11 +1361,16 @@ static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,> DSP_STATUS status = DSP_SOK;> struct WMD_DEV_CONTEXT *pDevContext = hDevContext;> struct HW_MMUMapAttrs_t hwAttrs;> - u32 numOfActualTabEntries = 0;> - u32 *pPhysAddrPageTbl = NULL;> struct vm_area_struct *vma;> struct mm_struct *mm = current->mm;> - u32 temp = 0;> + u32 write = 0;> + u32 numUsrPgs = 0;> + struct page *mappedPage, *pg;> + s32 pgNum;> + u32 va = ulVirtAddr;> + struct task_struct *curr_task = current;> + u32 pgI = 0;> + u32 mpuAddr, pa;>> DBG_Trace(DBG_ENTER, "> WMD_BRD_MemMap hDevContext %x, pa %x, va %x, "> "size %x, ulMapAttr %x\n", hDevContext, ulMpuAddr, ulVirtAddr,> @@ -1393,8 +1407,10 @@ static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,> /* Size is 64 bit */> hwAttrs.elementSize = HW_ELEM_SIZE_64BIT;> } else {> - /* Mixedsize isn't enabled, so size can't be> - * zero here */> + /*> + * Mixedsize isn't enabled, so size can't be> + * zero here> + */> DBG_Trace(DBG_LEVEL7,> "WMD_BRD_MemMap: MMU element size is zero\n");> return DSP_EINVALIDARG;> @@ -1406,93 +1422,151 @@ static DSP_STATUS WMD_BRD_MemMap(struct WMD_DEV_CONTEXT *hDevContext,> hwAttrs.donotlockmpupage = 0;>> if (attrs & DSP_MAPVMALLOCADDR) {> - status = MemMapVmalloc(hDevContext, ulMpuAddr, ulVirtAddr,> - ulNumBytes, ulMapAttr);> - return status;> + return MemMapVmalloc(hDevContext, ulMpuAddr, ulVirtAddr,> + ulNumBytes, &hwAttrs);> }> - /* Do OS-specific user-va to pa translation.> + /*> + * Do OS-specific user-va to pa translation.> * Combine physically contiguous regions to reduce TLBs.> - * Pass the translated pa to PteUpdate. */> + * Pass the translated pa to PteUpdate.> + */> if ((attrs & DSP_MAPPHYSICALADDR)) {> status = PteUpdate(pDevContext, ulMpuAddr, ulVirtAddr,> ulNumBytes, &hwAttrs);> goto func_cont;> }>> - /* Important Note: ulMpuAddr is mapped from user application process> + /*> + * Important Note: ulMpuAddr is mapped from user application process> * to current process - it must lie completely within the current> - * virtual memory address space in order to be of use to us here! */> + * virtual memory address space in order to be of use to us here!> + */> down_read(&mm->mmap_sem);> vma = find_vma(mm, ulMpuAddr);> - up_read(&mm->mmap_sem);> if (vma)> DBG_Trace(DBG_LEVEL6, "VMAfor UserBuf: ulMpuAddr=%x, "> "ulNumBytes=%x, vm_start=%x vm_end=%x vm_flags=%x \n",> ulMpuAddr, ulNumBytes, vma->vm_start,> vma->vm_end, vma->vm_flags);>> - /* It is observed that under some circumstances, the user buffer is> + /*> + * It is observed that under some circumstances, the user buffer is> * spread across several VMAs. So loop through and check if the entire> - * user buffer is covered */> - while ((vma != NULL) && (ulMpuAddr + ulNumBytes > vma->vm_end)) {> + * user buffer is covered> + */> + while ((vma) && (ulMpuAddr + ulNumBytes > vma->vm_end)) {> /* jump to the next VMA region */> - down_read(&mm->mmap_sem);> vma = find_vma(mm, vma->vm_end + 1);> - up_read(&mm->mmap_sem);> DBG_Trace(DBG_LEVEL6, "VMAfor UserBuf ulMpuAddr=%x, "> "ulNumBytes=%x, vm_start=%x vm_end=%x vm_flags=%x\n",> ulMpuAddr, ulNumBytes, vma->vm_start,> vma->vm_end, vma->vm_flags);> }> - if (vma == NULL) {> + if (!vma) {> DBG_Trace(DBG_LEVEL7, "Failed to get the VMA region for "> "MPU Buffer !!! \n");> status = DSP_EINVALIDARG;> - }> - if (DSP_FAILED(status))> + up_read(&mm->mmap_sem);> goto func_cont;> - pPhysAddrPageTbl = DMM_GetPhysicalAddrTable();> - /* Build the array with virtual to physical translations */> - status = TIOMAP_VirtToPhysical(mm, ulMpuAddr, ulNumBytes,> - &numOfActualTabEntries, pPhysAddrPageTbl);> - if (DSP_FAILED(status)) {> - DBG_Trace(DBG_LEVEL7,> - "WMD_BRD_MemMap: TIOMAP_VirtToPhysical",> - " failed\n");> - return DSP_EFAIL;> }> - temp = 0;> - DBG_Trace(DBG_LEVEL4, "WMD_BRD_MemMap: numOfActualTabEntries=%d, "> - "ulNumBytes= %d\n", numOfActualTabEntries, ulNumBytes);> - /* Update the DSP MMU table with the physical addresses received from> - from translation function */> - while (temp < numOfActualTabEntries) {> - status = PteSet(pDevContext->pPtAttrs, pPhysAddrPageTbl[temp++],> - ulVirtAddr, HW_PAGE_SIZE_4KB, &hwAttrs);> - if (DSP_FAILED(status)) {> - DBG_Trace(DBG_LEVEL7,> - "WMD_BRD_MemMap: FAILED IN PTESET \n");> - return DSP_EFAIL;> +> + if (vma->vm_flags & VM_IO) {> + numUsrPgs = ulNumBytes / PG_SIZE_4K;> + mpuAddr = ulMpuAddr;> + DBG_Trace(DBG_LEVEL4, "WMD_BRD_MemMap:numOfActualTabEntries=%d,"> + "ulNumBytes= %d\n", numUsrPgs, ulNumBytes);> + /* Get the physical addresses for user buffer */> + for (pgI = 0; pgI < numUsrPgs; pgI++) {> + pa = user_va2pa(mm, mpuAddr);> + if (!pa) {> + status = DSP_EFAIL;> + pr_err("DSPBRIDGE: VM_IO mapping physical"> + "address is invalid\n");> + break;> + }> + if (pfn_valid(__phys_to_pfn(pa))) {> + pg = phys_to_page(pa);> + get_page(pg);> + if (page_count(pg) < 1) {> + pr_err("Bad page in VM_IO buffer\n");> + bad_page_dump(pa, pg);> + }> + }> + status = PteSet(pDevContext->pPtAttrs, pa,> + va, HW_PAGE_SIZE_4KB, &hwAttrs);> + if (DSP_FAILED(status)) {> + DBG_Trace(DBG_LEVEL7,> + "WMD_BRD_MemMap: FAILED IN VM_IO"> + "PTESET \n");> + break;> + }> + va += HW_PAGE_SIZE_4KB;> + mpuAddr += HW_PAGE_SIZE_4KB;> + pa += HW_PAGE_SIZE_4KB;> + }> + } else {> + numUsrPgs = ulNumBytes / PG_SIZE_4K;> + if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE))> + write = 1;> +> + for (pgI = 0; pgI < numUsrPgs; pgI++) {> + pgNum = get_user_pages(curr_task, mm, ulMpuAddr, 1,> + write, 1, &mappedPage, NULL);> + if (pgNum > 0) {> + if (page_count(mappedPage) < 1) {> + pr_err("Bad page count after doing"> + "get_user_pages on"> + "user buffer\n");> + bad_page_dump(page_to_phys(mappedPage),> + mappedPage);> + }> + status = PteSet(pDevContext->pPtAttrs,> + page_to_phys(mappedPage), va,> + HW_PAGE_SIZE_4KB, &hwAttrs);> + if (DSP_FAILED(status)) {> + DBG_Trace(DBG_LEVEL7,> + "WMD_BRD_MemMap: FAILED IN PTESET \n");> + break;> + }> + va += HW_PAGE_SIZE_4KB;> + ulMpuAddr += HW_PAGE_SIZE_4KB;> + } else {> + pr_err("DSPBRIDGE: get_user_pages FAILED,"> + "MPU addr = 0x%x,"> + "vma->vm_flags = 0x%lx,"> + "get_user_pages Err"> + "Value = %d, Buffer"> + "size=0x%x\n", ulMpuAddr,> + vma->vm_flags, pgNum,> + ulNumBytes);> + status = DSP_EFAIL;> + break;> + }> }> - ulVirtAddr += HW_PAGE_SIZE_4KB;> }> - if (DSP_FAILED(status))> - DBG_Trace(DBG_LEVEL5, "WMD_BRD_MemMap: PteSet failed \n");> - else> - DBG_Trace(DBG_LEVEL5, "WMD_BRD_MemMap: PteSet passed \n");> -> + up_read(&mm->mmap_sem);> func_cont:> /* Don't propogate Linux or HW status to upper layers */> if (DSP_SUCCEEDED(status)) {> status = DSP_SOK;> } else {> DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap status %x\n", status);> + /*> + * Roll out the mapped pages incase it failed in middle of> + * mapping> + */> + if (pgI) {> + WMD_BRD_MemUnMap(pDevContext, ulVirtAddr,> + (pgI * PG_SIZE_4K));> + }> status = DSP_EFAIL;> }> - /* In any case, flush the TLB> + /*> + * In any case, flush the TLB> * This is called from here instead from PteUpdate to avoid unnecessary> * repetition while mapping non-contiguous physical regions of a virtual> - * region */> + * region> + */> flush_all(pDevContext);> DBG_Trace(DBG_ENTER, "< WMD_BRD_MemMap status %x\n", status);> return status;> @@ -1550,16 +1624,20 @@ static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,> pteVal = *(u32 *)pteAddrL1;> pteSize = HW_MMU_PteSizeL1(pteVal);> if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {> - /* Get the L2 PA from the L1 PTE, and find> - * corresponding L2 VA */> + /*> + * Get the L2 PA from the L1 PTE, and find> + * corresponding L2 VA> + */> L2BasePa = HW_MMU_PteCoarseL1(pteVal);> L2BaseVa = L2BasePa - pt->L2BasePa + pt->L2BaseVa;> L2PageNum = (L2BasePa - pt->L2BasePa) /> HW_MMU_COARSE_PAGE_SIZE;> - /* Find the L2 PTE address from which we will start> + /*> + * Find the L2 PTE address from which we will start> * clearing, the number of PTEs to be cleared on this> * page, and the size of VA space that needs to be> - * cleared on this L2 page */> + * cleared on this L2 page> + */> pteAddrL2 = HW_MMU_PteAddrL2(L2BaseVa, vaCurr);> pteCount = pteAddrL2 & (HW_MMU_COARSE_PAGE_SIZE - 1);> pteCount = (HW_MMU_COARSE_PAGE_SIZE - pteCount) /> @@ -1571,12 +1649,14 @@ static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,> DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap L2BasePa %x, "> "L2BaseVa %x pteAddrL2 %x, remBytesL2 %x\n",> L2BasePa, L2BaseVa, pteAddrL2, remBytesL2);> - /* Unmap the VA space on this L2 PT. A quicker way> + /*> + * Unmap the VA space on this L2 PT. A quicker way> * would be to clear pteCount entries starting from> * pteAddrL2. However, below code checks that we don't> * clear invalid entries or less than 64KB for a 64KB> * entry. Similar checking is done for L1 PTEs too> - * below */> + * below> + */> while (remBytesL2 && (DSP_SUCCEEDED(status))) {> pteVal = *(u32 *)pteAddrL2;> pteSize = HW_MMU_PteSizeL2(pteVal);> @@ -1595,7 +1675,6 @@ static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,> pAddr;> pAddr += HW_PAGE_SIZE_4KB;> }> -> if (HW_MMU_PteClear(pteAddrL2,> vaCurr, pteSize) == RET_OK) {> status = DSP_SOK;> @@ -1615,13 +1694,16 @@ static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,> if (remBytesL2 == 0) {> pt->pgInfo[L2PageNum].numEntries -= pteCount;> if (pt->pgInfo[L2PageNum].numEntries == 0) {> - /* Clear the L1 PTE pointing to the> - * L2 PT */> + /*> + * Clear the L1 PTE pointing to the> + * L2 PT> + */> if (RET_OK == HW_MMU_PteClear(L1BaseVa,> vaCurrOrig, HW_MMU_COARSE_PAGE_SIZE))> status = DSP_SOK;> else {> status = DSP_EFAIL;> + SYNC_LeaveCS(pt->hCSObj);> goto EXIT_LOOP;> }> }> @@ -1639,8 +1721,19 @@ static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,> /* pteSize = 1 MB or 16 MB */> if ((pteSize != 0) && (remBytes >= pteSize) &&> !(vaCurr & (pteSize - 1))) {> - if (HW_MMU_PteClear(L1BaseVa,> - vaCurr, pteSize) == RET_OK) {> + if (pteSize == HW_PAGE_SIZE_1MB)> + numof4KPages = 256;> + else> + numof4KPages = 4096;> + temp = 0;> + /* Collect Physical addresses from VA */> + pAddr = (pteVal & ~(pteSize - 1));> + while (temp++ < numof4KPages) {> + pPhysAddrPageTbl[pacount++] = pAddr;> + pAddr += HW_PAGE_SIZE_4KB;> + }> + if (HW_MMU_PteClear(L1BaseVa, vaCurr, pteSize)> + == RET_OK) {> status = DSP_SOK;> remBytes -= pteSize;> vaCurr += pteSize;> @@ -1652,23 +1745,25 @@ static DSP_STATUS WMD_BRD_MemUnMap(struct WMD_DEV_CONTEXT *hDevContext,> status = DSP_EFAIL;> }> }> - /* It is better to flush the TLB here, so that any stale old entries> - * get flushed */> + /*> + * It is better to flush the TLB here, so that any stale old entries> + * get flushed> + */> EXIT_LOOP:> flush_all(pDevContext);> - temp = 0;> - while (temp < pacount) {> + for (temp = 0; temp < pacount; temp++) {> patemp = pPhysAddrPageTbl[temp];> if (pfn_valid(__phys_to_pfn(patemp))) {> pg = phys_to_page(patemp);> - if (page_count(pg) < 1)> - printk(KERN_INFO "DSPBRIDGE:UNMAP function: "> - "COUNT 0 FOR PA 0x%x, size = 0x%x\n",> - patemp, ulNumBytes);> + if (page_count(pg) < 1) {> + pr_info("DSPBRIDGE:UNMAP function: COUNT 0"> + "FOR PA 0x%x, size = 0x%x\n",> + patemp, ulNumBytes);> + bad_page_dump(patemp, pg);> + }> SetPageDirty(pg);> page_cache_release(pg);> }> - temp++;> }> DBG_Trace(DBG_LEVEL1, "WMD_BRD_MemUnMap vaCurr %x, pteAddrL1 %x "> "pteAddrL2 %x\n", vaCurr, pteAddrL1, pteAddrL2);> @@ -1676,263 +1771,36 @@ EXIT_LOOP:> "remBytesL2 %x\n", status, remBytes, remBytesL2);> return status;> }> +> /*> - * ========= TIOMAP_VirtToPhysical ==========> - * Purpose:> - * This function builds the array with virtual to physical> - * address translation> + * ======== user_va2pa ========> + * Purpose:> + * This function walks through the Linux page tables to convert a userland> + * virtual address to physical address> */> -static DSP_STATUS TIOMAP_VirtToPhysical(struct mm_struct *mm, u32 ulMpuAddr,> - u32 ulNumBytes,> - u32 *numOfTableEntries,> - u32 *physicalAddrTable)> +static u32 user_va2pa(struct mm_struct *mm, u32 address)> {> - u32 pAddr;> - u32 chunkSz;> - DSP_STATUS status = DSP_SOK;> - volatile u32 pteVal;> - u32 pteSize;> pgd_t *pgd;> pmd_t *pmd;> - volatile pte_t *ptep;> - u32 numEntries = 0;> - u32 numof4KPages = 0;> - u32 phyEntryCounter = 0;> - u32 temp = 0;> - u32 numUsrPgs;> - struct task_struct *curr_task = current;> - struct vm_area_struct *vma;> - u32 write = 0;> -> -> - DBG_Trace(DBG_ENTER, "TIOMAP_VirtToPhysical: START:ulMpuAddr=%x, "> - "ulNumBytes=%x\n", ulMpuAddr, ulNumBytes);> - if (physicalAddrTable == NULL)> - return DSP_EMEMORY;> - down_read(&mm->mmap_sem);> - vma = find_vma(mm, ulMpuAddr);> - up_read(&mm->mmap_sem);> -> - if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE))> - write = 1;> - while (ulNumBytes) {> - DBG_Trace(DBG_LEVEL4, "TIOMAP_VirtToPhysical:Read the next PGD "> - "and PMD entry\n");> - numEntries = 0;> - /* Get the first level page table entry information */> - /* Read the pointer to first level page table entry */> - pgd = pgd_offset(mm, ulMpuAddr);> - /* Read the value in the first level page table entry */> - pteVal = *(u32 *)pgd;> - /* Find the page size that is pointed by the first level page> - * table entry */> - pteSize = HW_MMU_PteSizeL1(pteVal); /* update 16 or 1 */> - /* If pteSize is zero, then call the get_user_pages to create> - * the page table entries for this buffer> - */> - if (!pteSize) {> - down_read(&mm->mmap_sem);> - /* This call invokes handle_mmu _fault call, which> - *causes all pages to be created before we scan the> - * page tables> - */> - numUsrPgs = get_user_pages(curr_task, mm, ulMpuAddr, 1,> - write, 1, NULL, NULL);> - up_read(&mm->mmap_sem);> - /* Get the first level page table entry information */> - /* Read the pointer to first level page table entry */> - pgd = pgd_offset(mm, ulMpuAddr);> - /* Read the value in the first level page table entry*/> - pteVal = *(u32 *)pgd;> - /* Find the page size that is pointed by the first level> - * page table entry> - */> - pteSize = HW_MMU_PteSizeL1(pteVal);> - DBG_Trace(DBG_LEVEL4, "First level get_user_pages "> - "called\n");> - }> - /* If the page size is 4K or 64K, then we have to traverse to> - * second level page table */> - if (pteSize == HW_MMU_COARSE_PAGE_SIZE) {> - DBG_Trace(DBG_LEVEL5, "Read the next PMD entry\n");> - /* Get the second level page table information */> - pmd = pmd_offset(pgd, ulMpuAddr);> - ptep = pte_offset_map(pmd, ulMpuAddr);> - do {> - ptep = ptep+numEntries;> - /* Read the value of second level page table> - * entry */> - pteVal = *(u32 *)ptep;> - /* Find the size of page the second level> - * table entry is pointing */> - /* update 64 or 4 */> - pteSize = HW_MMU_PteSizeL2(pteVal);> - /* If pteSize is invalid, then call> - * get_user_pages to create the> - * page table entries> - */> - if (!pteSize) {> - numUsrPgs => - (ulNumBytes/HW_PAGE_SIZE_4KB);> - down_read(&mm->mmap_sem);> - /* This call invokes> - *handle_mmu _fault call, which causes> - *all pages to be created before we scan> - * the page tables */> - if (numUsrPgs <= PAGES_II_LVL_TABLE) {> - get_user_pages(curr_task, mm,> - ulMpuAddr, numUsrPgs, write, 1,> - NULL, NULL);> - DBG_Trace(DBG_LEVEL4,> - "get_user_pages, numUsrPgs"> - "= %d\n", numUsrPgs);> - } else {> - get_user_pages(curr_task, mm,> - ulMpuAddr, PAGES_II_LVL_TABLE,> - write, 1, NULL, NULL);> - DBG_Trace(DBG_LEVEL4,> - "get_user_pages, numUsrPgs"> - "= %d\n", PAGES_II_LVL_TABLE);> - }> - up_read(&mm->mmap_sem);> - /* Read the value of second level page> - * table entry */> - pteVal = *(u32 *)ptep;> - /* Find the size of page the second> - * level table entry is pointing */> - pteSize = HW_MMU_PteSizeL2(pteVal);> - }> - DBG_Trace(DBG_LEVEL4, "TIOMAP_VirtToPhysical:"> - "*pmd=%x, *pgd=%x, ptep = %x, pteVal="> - " %x, pteSize=%x\n", *pmd,> - *(u32 *)pgd, (u32)ptep, pteVal,> - pteSize);> -> - /* Extract the physical Addresses */> - switch (pteSize) {> - case HW_PAGE_SIZE_64KB:> - pAddr = pteVal & MMU_LARGE_PAGE_MASK;> - chunkSz = HW_PAGE_SIZE_64KB;> - numEntries = 16;> - if (ulNumBytes >= HW_PAGE_SIZE_64KB)> - numof4KPages = 16;> - else {> - numof4KPages = ulNumBytes /> - HW_PAGE_SIZE_4KB;> - }> - break;> - case HW_PAGE_SIZE_4KB:> - pAddr = pteVal & MMU_SMALL_PAGE_MASK;> - chunkSz = HW_PAGE_SIZE_4KB;> - numEntries = 1;> - numof4KPages = 1;> - break;> - default:> - DBG_Trace(DBG_LEVEL7,> - "TIOMAP_VirtToPhysical:"> - "Descriptor"> - "Format Fault-II level,"> - " PTE size = %x\n",> - pteSize);> - return DSP_EFAIL;> - }> - temp = 0;> - while (temp++ < numof4KPages) {> - physicalAddrTable[phyEntryCounter++] => - pAddr;> - DBG_Trace(DBG_LEVEL4,> - "TIOMAP_VirtToPhysical:"> - "physicalAddrTable[%d]= %x\n",> - (phyEntryCounter-1), pAddr);> - pAddr += HW_PAGE_SIZE_4KB;> - }> - if (DSP_SUCCEEDED(status)) {> - /* Go to the next page */> - ulMpuAddr += chunkSz;> - /* Update the number of bytes that> - * are copied */> - if (chunkSz > ulNumBytes)> - ulNumBytes = 0;> - else> - ulNumBytes -= chunkSz;> - DBG_Trace(DBG_LEVEL4,> - "TIOMAP_VirtToPhysical: mpuCurr"> - " = %x, pagesize = %x, "> - "numBytesRem=%x\n",> - ulMpuAddr, chunkSz, ulNumBytes);> - } else {> - DBG_Trace(DBG_LEVEL7,> - " TIOMAP_VirtToPhysical:PTEupdate"> - "failed\n");> - }> - /* It is observed that the pgd value (first level page> - * table entry) is changed after reading the 512> - * entries in second level table. So, call the pgd> - * functions after reaching 512 entries in second> - * level table */> - } while ((ulMpuAddr & 0x001ff000) && (ulNumBytes));> - } else {> - /* Extract the Address to update the IVA MMU table> - * with */> - switch (pteSize) {> - case HW_PAGE_SIZE_16MB:> - pAddr = pteVal & MMU_SSECTION_ADDR_MASK;> - if (ulNumBytes >= HW_PAGE_SIZE_16MB) {> - chunkSz = HW_PAGE_SIZE_16MB;> - numEntries = 16;> - numof4KPages = 4096;> - } else {> - chunkSz = HW_PAGE_SIZE_1MB;> - numEntries = 1;> - numof4KPages = 256;> - }> - break;> - case HW_PAGE_SIZE_1MB:> - pAddr = pteVal & MMU_SECTION_ADDR_MASK;> - chunkSz = HW_PAGE_SIZE_1MB;> - numEntries = 1;> - numof4KPages = 256;> - break;> - default:> - DBG_Trace(DBG_LEVEL7,> - "TIOMAP_VirtToPhysical:Descriptor"> - "Format Faul-I level, PTE size = "> - "%x\n", pteSize);> - return DSP_EFAIL;> + pte_t *ptep, pte;> +> + pgd = pgd_offset(mm, address);> + if (!(pgd_none(*pgd) || pgd_bad(*pgd))) {> + pmd = pmd_offset(pgd, address);> + if (!(pmd_none(*pmd) || pmd_bad(*pmd))) {> + ptep = pte_offset_map(pmd, address);> + if (ptep) {> + pte = *ptep;> + if (pte_present(pte))> + return pte & PAGE_MASK;> }> - temp = 0;> - while (temp++ < numof4KPages) {> - physicalAddrTable[phyEntryCounter++] => - pAddr;> - DBG_Trace(DBG_LEVEL4,> - "TIOMAP_VirtToPhysical:"> - "physicalAddrTable[%d]= %x\n",> - (phyEntryCounter-1), pAddr);> - pAddr += HW_PAGE_SIZE_4KB;> - }> - if (DSP_SUCCEEDED(status)) {> - /* Go to the next page */> - ulMpuAddr += chunkSz;> - /* Update the number of bytes that are copied */> - ulNumBytes -= chunkSz;> - DBG_Trace(DBG_LEVEL4,> - "TIOMAP_VirtToPhysical: mpuCurr = %x, "> - "pagesize = %x, numBytesRem=%x\n",> - ulMpuAddr, chunkSz, ulNumBytes);> - } else {> - DBG_Trace(DBG_LEVEL7,> - " TIOMAP_VirtToPhysical:PTEupdate"> - "failed\n");> - }> -> }> }> - *numOfTableEntries = phyEntryCounter;> - DBG_Trace(DBG_LEVEL4, " TIOMAP_VirtToPhysical:numofTableEntries=%d\n",> - phyEntryCounter);> - return status;> +> + return 0;> }>> +> /*> * ======== PteUpdate ========> * This function calculates the optimum page-aligned addresses and sizes> @@ -2000,64 +1868,9 @@ static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,> u32 L2BaseVa = 0;> u32 L2BasePa = 0;> u32 L2PageNum = 0;> - u32 num4KEntries = 0;> - u32 temp = 0;> - struct page *pg = NULL;> - u32 patemp;> -> DSP_STATUS status = DSP_SOK;> DBG_Trace(DBG_ENTER, "> PteSet pPgTableAttrs %x, pa %x, va %x, "> "size %x, attrs %x\n", pt, pa, va, size, attrs);> - /* Lock the MPU pages that are getting mapped if this> - * attribute is set */> - if (attrs->donotlockmpupage == 0) {> - switch (size) {> - case HW_PAGE_SIZE_64KB:> - num4KEntries = 16;> - break;> - case HW_PAGE_SIZE_4KB:> - num4KEntries = 1;> - break;> - case HW_PAGE_SIZE_16MB:> - num4KEntries = 4096;> - break;> - case HW_PAGE_SIZE_1MB:> - num4KEntries = 256;> - break;> - default:> - return DSP_EFAIL;> - }> - patemp = pa;> - while (temp++ < num4KEntries) {> - /* FIXME: This is a hack to avoid getting pages for> - * video overlay */> - if (pfn_valid(__phys_to_pfn(patemp))) {> - pg = phys_to_page(patemp);> - get_page(pg);> - }> - if (page_count(pg) < 1) {> - printk(KERN_EMERG "DSPBRIDGE:MAP function: "> - "COUNT 0 FOR PA 0x%x\n", patemp);> - printk(KERN_EMERG "Bad page state"> - KERN_EMERG "in process '%s'\n"> - KERN_EMERG "page:%p flags:0x%0*lx "> - KERN_EMERG "mapping:%p mapcount:%d "> - KERN_EMERG "count:%d\n"> - KERN_EMERG "Trying to fix it up, but "> - KERN_EMERG "a reboot is needed\n"> - KERN_EMERG "Backtrace:\n",> - current->comm, pg,> - (int)(2*sizeof(unsigned long)),> - (unsigned long)pg->flags, pg->mapping,> - page_mapcount(pg), page_count(pg));> - dump_stack();> - BUG_ON(1);> - }> -> - patemp += HW_PAGE_SIZE_4KB;> - }> - }> - attrs->donotlockmpupage = 0;> L1BaseVa = pt->L1BaseVa;> pgTblVa = L1BaseVa;> if ((size == HW_PAGE_SIZE_64KB) || (size == HW_PAGE_SIZE_4KB)) {> @@ -2108,7 +1921,6 @@ static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,> pt->pgInfo[L2PageNum].numEntries += 16;> else> pt->pgInfo[L2PageNum].numEntries++;> -> DBG_Trace(DBG_LEVEL1, "L2 BaseVa %x, BasePa %x, "> "PageNum %x numEntries %x\n", L2BaseVa,> L2BasePa, L2PageNum,> @@ -2129,14 +1941,11 @@ static DSP_STATUS PteSet(struct PgTableAttrs *pt, u32 pa, u32 va,> }>> /* Memory map kernel VA -- memory allocated with vmalloc */> -static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *hDevContext,> - u32 ulMpuAddr, u32 ulVirtAddr,> - u32 ulNumBytes, u32 ulMapAttr)> +static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *pDevContext,> + u32 ulMpuAddr, u32 ulVirtAddr, u32 ulNumBytes,> + struct HW_MMUMapAttrs_t *hwAttrs)> {> - u32 attrs = ulMapAttr;> DSP_STATUS status = DSP_SOK;> - struct WMD_DEV_CONTEXT *pDevContext = hDevContext;> - struct HW_MMUMapAttrs_t hwAttrs;> struct page *pPage[1];> u32 i;> u32 paCurr;> @@ -2144,59 +1953,35 @@ static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *hDevContext,> u32 vaCurr;> u32 sizeCurr;> u32 numPages;> + u32 pa;> + u32 numOf4KPages;> + u32 temp = 0;>> DBG_Trace(DBG_ENTER, "> MemMapVmalloc hDevContext %x, pa %x, va %x, "> - "size %x, ulMapAttr %x\n", hDevContext, ulMpuAddr,> - ulVirtAddr, ulNumBytes, ulMapAttr);> - /* Take mapping properties */> - if (attrs & DSP_MAPBIGENDIAN)> - hwAttrs.endianism = HW_BIG_ENDIAN;> - else> - hwAttrs.endianism = HW_LITTLE_ENDIAN;> + "size %x\n", pDevContext, ulMpuAddr, ulVirtAddr, ulNumBytes);>> - hwAttrs.mixedSize = (enum HW_MMUMixedSize_t)> - ((attrs & DSP_MAPMIXEDELEMSIZE) >> 2);> - /* Ignore elementSize if mixedSize is enabled */> - if (hwAttrs.mixedSize == 0) {> - if (attrs & DSP_MAPELEMSIZE8) {> - /* Size is 8 bit */> - hwAttrs.elementSize = HW_ELEM_SIZE_8BIT;> - } else if (attrs & DSP_MAPELEMSIZE16) {> - /* Size is 16 bit */> - hwAttrs.elementSize = HW_ELEM_SIZE_16BIT;> - } else if (attrs & DSP_MAPELEMSIZE32) {> - /* Size is 32 bit */> - hwAttrs.elementSize = HW_ELEM_SIZE_32BIT;> - } else if (attrs & DSP_MAPELEMSIZE64) {> - /* Size is 64 bit */> - hwAttrs.elementSize = HW_ELEM_SIZE_64BIT;> - } else {> - /* Mixedsize isn't enabled, so size can't be zero> - * here */> - DBG_Trace(DBG_LEVEL7, "WMD_BRD_MemMap: MMU element "> - "size is zero\n");> - return DSP_EINVALIDARG;> - }> - }> - /* Do Kernel va to pa translation.> + /*> + * Do Kernel va to pa translation.> * Combine physically contiguous regions to reduce TLBs.> - * Pass the translated pa to PteUpdate. */> + * Pass the translated pa to PteUpdate.> + */> numPages = ulNumBytes / PAGE_SIZE; /* PAGE_SIZE = OS page size */> - if (DSP_FAILED(status))> - goto func_cont;> -> i = 0;> vaCurr = ulMpuAddr;> pPage[0] = vmalloc_to_page((void *)vaCurr);> paNext = page_to_phys(pPage[0]);> while (DSP_SUCCEEDED(status) && (i < numPages)) {> - /* Reuse paNext from the previous iteraion to avoid> - * an extra va2pa call */> + /*> + * Reuse paNext from the previous iteraion to avoid> + * an extra va2pa call> + */> paCurr = paNext;> sizeCurr = PAGE_SIZE;> - /* If the next page is physically contiguous,> + /*> + * If the next page is physically contiguous,> * map it with the current one by increasing> - * the size of the region to be mapped */> + * the size of the region to be mapped> + */> while (++i < numPages) {> pPage[0] = vmalloc_to_page((void *)(vaCurr + sizeCurr));> paNext = page_to_phys(pPage[0]);> @@ -2212,11 +1997,16 @@ static DSP_STATUS MemMapVmalloc(struct WMD_DEV_CONTEXT *hDevContext,> status = DSP_EMEMORY;> break;> }> + pa = paCurr;> + numOf4KPages = sizeCurr / HW_PAGE_SIZE_4KB;> + while (temp++ < numOf4KPages) {> + get_page(phys_to_page(pa));> + pa += HW_PAGE_SIZE_4KB;> + }> status = PteUpdate(pDevContext, paCurr, ulVirtAddr +> - (vaCurr - ulMpuAddr), sizeCurr, &hwAttrs);> + (vaCurr - ulMpuAddr), sizeCurr, hwAttrs);> vaCurr += sizeCurr;> }> -func_cont:> /* Don't propogate Linux or HW status to upper layers */> if (DSP_SUCCEEDED(status)) {> status = DSP_SOK;> @@ -2226,12 +2016,14 @@ func_cont:> DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap status %x\n", status);> status = DSP_EFAIL;> }> - /* In any case, flush the TLB> + /*> + * In any case, flush the TLB> * This is called from here instead from PteUpdate to avoid unnecessary> * repetition while mapping non-contiguous physical regions of a virtual> - * region */> + * region> + */> flush_all(pDevContext);> - DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap at end status %x\n", status);> + DBG_Trace(DBG_LEVEL7, "< WMD_BRD_MemMap at end status %x\n", status);> return status;> }>> --> 1.6.2.4>> --> 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��.n��������+%����;��w��{.n�����{�������ܨ}���Ơz�j:+v�����w����ޙ��&�)ߡ�a����z�ޗ���ݢj��w�f