From: Hiroshi DOYU <Hiroshi.DOYU@xxxxxxxxx>
Based on the discussion:
http://www.spinics.net/lists/arm-kernel/msg72810.html
HACK: export "follow_page()" for dspbridge cache operation
Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@xxxxxxxxx>
---
drivers/dsp/bridge/rmgr/proc.c | 68
++++++++++++++++++++++++++++++---------
mm/memory.c | 1 +
2 files changed, 53 insertions(+), 16 deletions(-)
diff --git a/drivers/dsp/bridge/rmgr/proc.c b/drivers/dsp/bridge/rmgr/proc.c
index 491661f..3e05281 100644
--- a/drivers/dsp/bridge/rmgr/proc.c
+++ b/drivers/dsp/bridge/rmgr/proc.c
@@ -574,8 +574,43 @@ DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR
hProcessor, OUT DSP_HNODE *aNodeTab,
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_check_vma(unsigned long start, u32 len)
+static int memory_sync_vma(unsigned long start, u32 len,
+ enum DSP_FLUSHTYPE ftype)
{
int err = 0;
unsigned long end;
@@ -585,14 +620,19 @@ static int memory_check_vma(unsigned long start,
u32 len)
if (end <= start)
return -EINVAL;
- down_read(¤t->mm->mmap_sem);
-
while ((vma = find_vma(current->mm, start)) != NULL) {
+ ssize_t size;
- if (vma->vm_start > start) {
- err = -EINVAL;
+ if (vma->vm_flags & (VM_IO | VM_PFNMAP))
+ return -EINVAL;
+
+ if (vma->vm_start > start)
+ return -EINVAL;
+
+ size = min_t(ssize_t, vma->vm_end - start, len);
+ err = memory_sync_page(vma, start, size, ftype);
+ if (err)
break;
- }
if (end <= vma->vm_end)
break;
@@ -603,8 +643,6 @@ static int memory_check_vma(unsigned long start, u32
len)
if (!vma)
err = -EINVAL;
- up_read(¤t->mm->mmap_sem);
-
return err;
}
@@ -629,17 +667,15 @@ static DSP_STATUS proc_memory_sync(DSP_HPROCESSOR
hProcessor, void *pMpuAddr,
goto err_out;
}
- if (memory_check_vma((u32)pMpuAddr, ulSize)) {
- GT_3trace(PROC_DebugMask, GT_7CLASS,
- "%s: InValid address parameters\n",
- __func__, pMpuAddr, ulSize);
+ down_read(¤t->mm->mmap_sem);
+
+ if (memory_sync_vma((u32)pMpuAddr, ulSize, FlushMemType)) {
+ pr_err("%s: InValid address parameters %p %x\n",
+ __func__, pMpuAddr, ulSize);
status = DSP_EHANDLE;
- goto err_out;
}
- (void)SYNC_EnterCS(hProcLock);
- MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
- (void)SYNC_LeaveCS(hProcLock);
+ up_read(¤t->mm->mmap_sem);
err_out:
GT_2trace(PROC_DebugMask, GT_ENTER,
diff --git a/mm/memory.c b/mm/memory.c
index 6ab19dd..377be88 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1228,6 +1228,7 @@ no_page_table:
return ERR_PTR(-EFAULT);
return page;
}
+EXPORT_SYMBOL_GPL(follow_page);
int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
unsigned long start, int nr_pages, unsigned int gup_flags,
--
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