Add patch dspbridge_flushall.diff
authorPali Rohár <pali.rohar@gmail.com>
Sat, 1 Oct 2011 20:56:22 +0000 (22:56 +0200)
committerPali Rohár <pali.rohar@gmail.com>
Sat, 1 Oct 2011 21:31:54 +0000 (23:31 +0200)
* sometimes happens that DSP cache is incoherent with main memory, which leads to memory errors
* it is fixed with this patch
* the patch also adds FLUSHALL DSP ioctl code.

kernel-power-2.6.28/debian/patches/dspbridge_flushall.diff [new file with mode: 0644]
kernel-power-2.6.28/debian/patches/series

diff --git a/kernel-power-2.6.28/debian/patches/dspbridge_flushall.diff b/kernel-power-2.6.28/debian/patches/dspbridge_flushall.diff
new file mode 100644 (file)
index 0000000..0dbfc7c
--- /dev/null
@@ -0,0 +1,266 @@
+diff -rupN kernel-power-2.6.28.orig/arch/arm/plat-omap/include/dspbridge/dbdefs.h kernel-power-2.6.28/arch/arm/plat-omap/include/dspbridge/dbdefs.h
+--- kernel-power-2.6.28.orig/arch/arm/plat-omap/include/dspbridge/dbdefs.h     2011-05-12 20:03:00.000000000 +0100
++++ kernel-power-2.6.28/arch/arm/plat-omap/include/dspbridge/dbdefs.h  2011-05-12 21:06:45.000000000 +0100
+@@ -253,6 +253,7 @@
+               PROC_INVALIDATE_MEM = 0,
+               PROC_WRITEBACK_MEM,
+               PROC_WRITEBACK_INVALIDATE_MEM,
++              PROC_WRBK_INV_ALL
+       } ;
+ /* Memory Segment Status Values */
+diff -rupN kernel-power-2.6.28.orig/arch/arm/plat-omap/include/dspbridge/mem.h kernel-power-2.6.28/arch/arm/plat-omap/include/dspbridge/mem.h
+--- kernel-power-2.6.28.orig/arch/arm/plat-omap/include/dspbridge/mem.h        2011-05-12 20:03:00.000000000 +0100
++++ kernel-power-2.6.28/arch/arm/plat-omap/include/dspbridge/mem.h     2011-05-12 21:07:22.000000000 +0100
+@@ -137,7 +137,7 @@ do {                                                       \
+  *  Ensures:
+  *      Cache is synchronized
+  */
+-      extern void MEM_FlushCache(void *pMemBuf, u32 cBytes, s32 FlushType);
++      extern void MEM_FlushCache(void *pMemBuf, u32 cBytes, u32 FlushType);
+ /*
+  *  ======== MEM_Free ========
+diff -rupN kernel-power-2.6.28.orig/drivers/dsp/bridge/pmgr/wcd.c kernel-power-2.6.28/drivers/dsp/bridge/pmgr/wcd.c
+--- kernel-power-2.6.28.orig/drivers/dsp/bridge/pmgr/wcd.c     2011-05-12 20:01:58.000000000 +0100
++++ kernel-power-2.6.28/drivers/dsp/bridge/pmgr/wcd.c  2011-05-12 21:08:06.000000000 +0100
+@@ -795,7 +795,7 @@ u32 PROCWRAP_FlushMemory(union Trapped_A
+               return DSP_EHANDLE;
+       if (args->ARGS_PROC_FLUSHMEMORY.ulFlags >
+-                                       PROC_WRITEBACK_INVALIDATE_MEM)
++                                       PROC_WRBK_INV_ALL)
+               return DSP_EINVALIDARG;
+       status = PROC_FlushMemory(args->ARGS_PROC_FLUSHMEMORY.hProcessor,
+@@ -1216,7 +1216,7 @@ bool validate_node_handle(struct NODE_OB
+ {
+       bool retVal = false;
+       struct PROCESS_CONTEXT *pCtxt = pr_ctxt;
+-      struct NODE_RES_OBJECT *pNode = pCtxt->pNodeList;
++      struct NODE_RES_OBJECT *pNode;
+       if (hNode == (struct NODE_OBJECT *) DSP_HGPPNODE)
+               retVal = true;
+@@ -1224,6 +1224,7 @@ bool validate_node_handle(struct NODE_OB
+       if (mutex_lock_interruptible(&pCtxt->node_mutex))
+               return DSP_EFAIL;
++      pNode = pCtxt->pNodeList;
+       while (pNode && !retVal) {
+               if (hNode == pNode->hNode)
+                       retVal = true;
+@@ -1683,11 +1684,12 @@ bool validate_strm_handle(struct STRM_OB
+ {
+       bool retVal = false;
+       struct PROCESS_CONTEXT *pCtxt = pr_ctxt;
+-      struct STRM_RES_OBJECT *pStrm = pCtxt->pSTRMList;
++      struct STRM_RES_OBJECT *pStrm;
+       if (mutex_lock_interruptible(&pCtxt->strm_mutex))
+               return DSP_EFAIL;
++      pStrm = pCtxt->pSTRMList;
+       while (pStrm && !retVal) {
+               if (hStrm == pStrm->hStream)
+                       retVal = true;
+diff -rupN kernel-power-2.6.28.orig/drivers/dsp/bridge/rmgr/drv.c kernel-power-2.6.28/drivers/dsp/bridge/rmgr/drv.c
+--- kernel-power-2.6.28.orig/drivers/dsp/bridge/rmgr/drv.c     2011-05-12 20:01:58.000000000 +0100
++++ kernel-power-2.6.28/drivers/dsp/bridge/rmgr/drv.c  2011-05-12 20:41:01.000000000 +0100
+@@ -97,8 +97,10 @@ DSP_STATUS DRV_InsertNodeResElement(HAND
+               status = DSP_EHANDLE;
+       }
+       if (DSP_SUCCEEDED(status)) {
+-              if (mutex_lock_interruptible(&pCtxt->node_mutex))
++              if (mutex_lock_interruptible(&pCtxt->node_mutex)) {
++                      MEM_Free(*pNodeRes);
+                       return DSP_EFAIL;
++              }
+               (*pNodeRes)->hNode = hNode;
+               if (pCtxt->pNodeList != NULL) {
+                       pTempNodeRes = pCtxt->pNodeList;
+@@ -208,8 +210,10 @@ DSP_STATUS DRV_InsertDMMResElement(HANDL
+               status = DSP_EHANDLE;
+       }
+       if (DSP_SUCCEEDED(status)) {
+-              if (mutex_lock_interruptible(&pCtxt->dmm_mutex))
++              if (mutex_lock_interruptible(&pCtxt->dmm_mutex)) {
++                      MEM_Free(*pDMMRes);
+                       return DSP_EFAIL;
++              }
+               if (pCtxt->pDMMList != NULL) {
+                       GT_0trace(curTrace, GT_5CLASS,
+@@ -439,8 +443,10 @@ DSP_STATUS DRV_ProcInsertSTRMResElement(
+               status = DSP_EHANDLE;
+       }
+       if (DSP_SUCCEEDED(status)) {
+-              if (mutex_lock_interruptible(&pCtxt->strm_mutex))
++              if (mutex_lock_interruptible(&pCtxt->strm_mutex)) {
++                      MEM_Free(*pSTRMRes);
+                       return DSP_EFAIL;
++              }
+               (*pSTRMRes)->hStream = hStreamHandle;
+               if (pCtxt->pSTRMList != NULL) {
+                       GT_0trace(curTrace, GT_ENTER,
+diff -rupN kernel-power-2.6.28.orig/drivers/dsp/bridge/rmgr/proc.c kernel-power-2.6.28/drivers/dsp/bridge/rmgr/proc.c
+--- kernel-power-2.6.28.orig/drivers/dsp/bridge/rmgr/proc.c    2011-05-12 20:01:58.000000000 +0100
++++ kernel-power-2.6.28/drivers/dsp/bridge/rmgr/proc.c 2011-05-12 21:10:35.000000000 +0100
+@@ -564,43 +564,8 @@ DSP_STATUS PROC_EnumNodes(void *hProcess
+       return status;
+ }
+-/* Cache operation against kernel address instead of users */
+-static int memory_sync_page(struct vm_area_struct *vma, unsigned long start,
+-                          ssize_t len, enum DSP_FLUSHTYPE ftype)
+-{
+-      struct page *page;
+-      void *kaddr;
+-      unsigned long offset;
+-      ssize_t rest;
+-
+-      while (len) {
+-              page = follow_page(vma, start, FOLL_GET);
+-              if (!page) {
+-                      pr_err("%s: no page for %08lx\n", __func__, start);
+-                      return -EINVAL;
+-              } else if (IS_ERR(page)) {
+-                      pr_err("%s: err page for %08lx(%lu)\n", __func__, start,
+-                             IS_ERR(page));
+-                      return IS_ERR(page);
+-              }
+-
+-              offset = start & ~PAGE_MASK;
+-              kaddr = page_address(page) + offset;
+-              rest = min_t(ssize_t, PAGE_SIZE - offset, len);
+-
+-              MEM_FlushCache(kaddr, rest, ftype);
+-
+-              put_page(page);
+-              len -= rest;
+-              start += rest;
+-      }
+-
+-      return 0;
+-}
+-
+ /* Check if the given area blongs to process virtul memory address space */
+-static int memory_sync_vma(unsigned long start, u32 len,
+-                         enum DSP_FLUSHTYPE ftype)
++static int memory_check_vma(unsigned long start, u32 len)
+ {
+       int err = 0;
+       unsigned long end;
+@@ -610,19 +575,14 @@ static int memory_sync_vma(unsigned long
+       if (end <= start)
+               return -EINVAL;
+-      while ((vma = find_vma(current->mm, start)) != NULL) {
+-              ssize_t size;
+-
+-              if (vma->vm_flags & (VM_IO | VM_PFNMAP))
+-                      return -EINVAL;
++      down_read(&current->mm->mmap_sem);
+-              if (vma->vm_start > start)
+-                      return -EINVAL;
++      while ((vma = find_vma(current->mm, start)) != NULL) {
+-              size = min_t(ssize_t, vma->vm_end - start, len);
+-              err = memory_sync_page(vma, start, size, ftype);
+-              if (err)
++              if (vma->vm_start > start) {
++                      err = -EINVAL;
+                       break;
++              }
+               if (end <= vma->vm_end)
+                       break;
+@@ -633,12 +593,13 @@ static int memory_sync_vma(unsigned long
+       if (!vma)
+               err = -EINVAL;
++      up_read(&current->mm->mmap_sem);
++
+       return err;
+ }
+ static DSP_STATUS proc_memory_sync(void *hProcessor, void *pMpuAddr,
+-                                 u32 ulSize, u32 ulFlags,
+-                                 enum DSP_FLUSHTYPE FlushMemType)
++                                 u32 ulSize, u32 ulFlags)
+ {
+       /* Keep STATUS here for future additions to this function */
+       DSP_STATUS status = DSP_SOK;
+@@ -649,16 +610,20 @@ static DSP_STATUS proc_memory_sync(void 
+                 "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x, ulFlags 0x%x\n",
+                 __func__, hProcessor, pMpuAddr, ulSize, ulFlags);
+-      down_read(&current->mm->mmap_sem);
+-
+-      if (memory_sync_vma((u32)pMpuAddr, ulSize, FlushMemType)) {
+-              pr_err("%s: InValid address parameters %p %x\n",
+-                     __func__, pMpuAddr, ulSize);
++      if (memory_check_vma((u32)pMpuAddr, ulSize)) {
++              GT_3trace(PROC_DebugMask, GT_7CLASS,
++                        "%s: InValid address parameters\n",
++                        __func__, pMpuAddr, ulSize);
+               status = DSP_EHANDLE;
++              goto err_out;
++
+       }
+-      up_read(&current->mm->mmap_sem);
++      (void)SYNC_EnterCS(hProcLock);
++      MEM_FlushCache(pMpuAddr, ulSize, ulFlags);
++      (void)SYNC_LeaveCS(hProcLock);
++err_out:
+       GT_2trace(PROC_DebugMask, GT_ENTER,
+                 "Leaving %s [0x%x]", __func__, status);
+@@ -673,9 +638,7 @@ static DSP_STATUS proc_memory_sync(void 
+ DSP_STATUS PROC_FlushMemory(void *hProcessor, void *pMpuAddr,
+                           u32 ulSize, u32 ulFlags)
+ {
+-      enum DSP_FLUSHTYPE mtype = PROC_WRITEBACK_INVALIDATE_MEM;
+-
+-      return proc_memory_sync(hProcessor, pMpuAddr, ulSize, ulFlags, mtype);
++      return proc_memory_sync(hProcessor, pMpuAddr, ulSize, ulFlags);
+ }
+ /*
+@@ -686,9 +649,7 @@ DSP_STATUS PROC_FlushMemory(void *hProce
+ DSP_STATUS PROC_InvalidateMemory(void *hProcessor, void *pMpuAddr,
+                                u32 ulSize)
+ {
+-      enum DSP_FLUSHTYPE mtype = PROC_INVALIDATE_MEM;
+-
+-      return proc_memory_sync(hProcessor, pMpuAddr, ulSize, 0, mtype);
++      return proc_memory_sync(hProcessor, pMpuAddr, ulSize, 0);
+ }
+ /*
+diff -rupN kernel-power-2.6.28.orig/drivers/dsp/bridge/services/mem.c kernel-power-2.6.28/drivers/dsp/bridge/services/mem.c
+--- kernel-power-2.6.28.orig/drivers/dsp/bridge/services/mem.c 2011-05-12 20:01:58.000000000 +0100
++++ kernel-power-2.6.28/drivers/dsp/bridge/services/mem.c      2011-05-12 21:11:37.000000000 +0100
+@@ -420,7 +420,7 @@ void MEM_Exit(void)
+  *  Purpose:
+  *      Flush cache
+  */
+-void MEM_FlushCache(void *pMemBuf, u32 cBytes, s32 FlushType)
++void MEM_FlushCache(void *pMemBuf, u32 cBytes, u32 FlushType)
+ {
+       if (!pMemBuf)
+               return;
+@@ -444,6 +444,10 @@ void MEM_FlushCache(void *pMemBuf, u32 c
+               outer_flush_range(__pa((u32)pMemBuf), __pa((u32)pMemBuf +
+                                 cBytes));
+       break;
++      /* Writeback and Invalidate all */
++      case PROC_WRBK_INV_ALL:
++              __cpuc_flush_kern_all();
++              break;
+       }
+ }
index 4423891..2aadc20 100644 (file)
@@ -49,6 +49,7 @@ joikuspot.diff
 dspbridge.diff
 dspbridge_ioctl_buffer_overrun.diff
 dspbridge_new_api.diff
+dspbridge_flushall.diff
 phys_to_page.diff
 ext4-data-corruption.diff
 patch_swap_notify_core_support_2.6.28.diff