From 800930b924c19a56b3a6e94ad351cd0715fb410d Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 28 Feb 2014 20:30:08 +0000 Subject: brcm2708: update against latest rpi-3.10.y branch Update our copies of the brcm2708 patches to the latest rpi-3.10-y rebased against linux-3.10.y stable (3.10.32). This should hopefully make it easier for us in the future to leverage the raspberry/rpi-* branches. Signed-off-by: Florian Fainelli git-svn-id: svn://svn.openwrt.org/openwrt/trunk@39770 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- ...create_pagelist-copes-with-vmalloc-memory.patch | 138 +++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 target/linux/brcm2708/patches-3.10/0108-vchiq-create_pagelist-copes-with-vmalloc-memory.patch (limited to 'target/linux/brcm2708/patches-3.10/0108-vchiq-create_pagelist-copes-with-vmalloc-memory.patch') diff --git a/target/linux/brcm2708/patches-3.10/0108-vchiq-create_pagelist-copes-with-vmalloc-memory.patch b/target/linux/brcm2708/patches-3.10/0108-vchiq-create_pagelist-copes-with-vmalloc-memory.patch new file mode 100644 index 0000000000..c2e25e1fdd --- /dev/null +++ b/target/linux/brcm2708/patches-3.10/0108-vchiq-create_pagelist-copes-with-vmalloc-memory.patch @@ -0,0 +1,138 @@ +From 974102eef65cd2576157b089db47386c5b29dee6 Mon Sep 17 00:00:00 2001 +From: Vincent Sanders +Date: Mon, 2 Sep 2013 16:44:57 +0100 +Subject: [PATCH 108/174] vchiq: create_pagelist copes with vmalloc memory + +Signed-off-by: Daniel Stone +--- + .../interface/vchiq_arm/vchiq_2835_arm.c | 83 ++++++++++++++-------- + 1 file changed, 53 insertions(+), 30 deletions(-) + +--- a/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c ++++ b/drivers/misc/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +@@ -374,6 +374,7 @@ create_pagelist(char __user *buf, size_t + unsigned int num_pages, offset, i; + char *addr, *base_addr, *next_addr; + int run, addridx, actual_pages; ++ unsigned long *need_release; + + offset = (unsigned int)buf & (PAGE_SIZE - 1); + num_pages = (count + offset + PAGE_SIZE - 1) / PAGE_SIZE; +@@ -384,9 +385,10 @@ create_pagelist(char __user *buf, size_t + ** list + */ + pagelist = kmalloc(sizeof(PAGELIST_T) + +- (num_pages * sizeof(unsigned long)) + +- (num_pages * sizeof(pages[0])), +- GFP_KERNEL); ++ (num_pages * sizeof(unsigned long)) + ++ sizeof(unsigned long) + ++ (num_pages * sizeof(pages[0])), ++ GFP_KERNEL); + + vchiq_log_trace(vchiq_arm_log_level, + "create_pagelist - %x", (unsigned int)pagelist); +@@ -394,28 +396,44 @@ create_pagelist(char __user *buf, size_t + return -ENOMEM; + + addrs = pagelist->addrs; +- pages = (struct page **)(addrs + num_pages); ++ need_release = (unsigned long *)(addrs + num_pages); ++ pages = (struct page **)(addrs + num_pages + 1); + +- down_read(&task->mm->mmap_sem); +- actual_pages = get_user_pages(task, task->mm, +- (unsigned long)buf & ~(PAGE_SIZE - 1), num_pages, +- (type == PAGELIST_READ) /*Write */ , 0 /*Force */ , +- pages, NULL /*vmas */); +- up_read(&task->mm->mmap_sem); +- +- if (actual_pages != num_pages) +- { +- /* This is probably due to the process being killed */ +- while (actual_pages > 0) +- { +- actual_pages--; +- page_cache_release(pages[actual_pages]); +- } +- kfree(pagelist); +- if (actual_pages == 0) +- actual_pages = -ENOMEM; +- return actual_pages; +- } ++ if (is_vmalloc_addr(buf)) { ++ for (actual_pages = 0; actual_pages < num_pages; actual_pages++) { ++ pages[actual_pages] = vmalloc_to_page(buf + (actual_pages * PAGE_SIZE)); ++ } ++ *need_release = 0; /* do not try and release vmalloc pages */ ++ } else { ++ down_read(&task->mm->mmap_sem); ++ actual_pages = get_user_pages(task, task->mm, ++ (unsigned long)buf & ~(PAGE_SIZE - 1), ++ num_pages, ++ (type == PAGELIST_READ) /*Write */ , ++ 0 /*Force */ , ++ pages, ++ NULL /*vmas */); ++ up_read(&task->mm->mmap_sem); ++ ++ if (actual_pages != num_pages) { ++ vchiq_log_info(vchiq_arm_log_level, ++ "create_pagelist - only %d/%d pages locked", ++ actual_pages, ++ num_pages); ++ ++ /* This is probably due to the process being killed */ ++ while (actual_pages > 0) ++ { ++ actual_pages--; ++ page_cache_release(pages[actual_pages]); ++ } ++ kfree(pagelist); ++ if (actual_pages == 0) ++ actual_pages = -ENOMEM; ++ return actual_pages; ++ } ++ *need_release = 1; /* release user pages */ ++ } + + pagelist->length = count; + pagelist->type = type; +@@ -482,6 +500,7 @@ create_pagelist(char __user *buf, size_t + static void + free_pagelist(PAGELIST_T *pagelist, int actual) + { ++ unsigned long *need_release; + struct page **pages; + unsigned int num_pages, i; + +@@ -492,7 +511,8 @@ free_pagelist(PAGELIST_T *pagelist, int + (pagelist->length + pagelist->offset + PAGE_SIZE - 1) / + PAGE_SIZE; + +- pages = (struct page **)(pagelist->addrs + num_pages); ++ need_release = (unsigned long *)(pagelist->addrs + num_pages); ++ pages = (struct page **)(pagelist->addrs + num_pages + 1); + + /* Deal with any partial cache lines (fragments) */ + if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS) { +@@ -528,11 +548,14 @@ free_pagelist(PAGELIST_T *pagelist, int + up(&g_free_fragments_sema); + } + +- for (i = 0; i < num_pages; i++) { +- if (pagelist->type != PAGELIST_WRITE) +- set_page_dirty(pages[i]); +- page_cache_release(pages[i]); +- } ++ if (*need_release) { ++ for (i = 0; i < num_pages; i++) { ++ if (pagelist->type != PAGELIST_WRITE) ++ set_page_dirty(pages[i]); ++ ++ page_cache_release(pages[i]); ++ } ++ } + + kfree(pagelist); + } -- cgit v1.2.3