Re: [PATCH] DSPBRIDGE: Replacing custom mapping implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux