arm: tegra: usb_phy: fix hsic suspend issue on xmm
[linux-2.6.git] / mm / madvise.c
index 18970ae..74bf193 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/pagemap.h>
 #include <linux/syscalls.h>
 #include <linux/mempolicy.h>
+#include <linux/page-isolation.h>
 #include <linux/hugetlb.h>
 #include <linux/sched.h>
 #include <linux/ksm.h>
@@ -70,6 +71,12 @@ static long madvise_behavior(struct vm_area_struct * vma,
                if (error)
                        goto out;
                break;
+       case MADV_HUGEPAGE:
+       case MADV_NOHUGEPAGE:
+               error = hugepage_madvise(vma, &new_flags, behavior);
+               if (error)
+                       goto out;
+               break;
        }
 
        if (new_flags == vma->vm_flags) {
@@ -211,7 +218,7 @@ static long madvise_remove(struct vm_area_struct *vma,
        endoff = (loff_t)(end - vma->vm_start - 1)
                        + ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
 
-       /* vmtruncate_range needs to take i_mutex and i_alloc_sem */
+       /* vmtruncate_range needs to take i_mutex */
        up_read(&current->mm->mmap_sem);
        error = vmtruncate_range(mapping->host, offset, endoff);
        down_read(&current->mm->mmap_sem);
@@ -222,7 +229,7 @@ static long madvise_remove(struct vm_area_struct *vma,
 /*
  * Error injection support for memory error handling.
  */
-static int madvise_hwpoison(unsigned long start, unsigned long end)
+static int madvise_hwpoison(int bhv, unsigned long start, unsigned long end)
 {
        int ret = 0;
 
@@ -230,14 +237,21 @@ static int madvise_hwpoison(unsigned long start, unsigned long end)
                return -EPERM;
        for (; start < end; start += PAGE_SIZE) {
                struct page *p;
-               int ret = get_user_pages(current, current->mm, start, 1,
-                                               0, 0, &p, NULL);
+               int ret = get_user_pages_fast(start, 1, 0, &p);
                if (ret != 1)
                        return ret;
+               if (bhv == MADV_SOFT_OFFLINE) {
+                       printk(KERN_INFO "Soft offlining page %lx at %lx\n",
+                               page_to_pfn(p), start);
+                       ret = soft_offline_page(p, MF_COUNT_INCREASED);
+                       if (ret)
+                               break;
+                       continue;
+               }
                printk(KERN_INFO "Injecting memory failure for page %lx at %lx\n",
                       page_to_pfn(p), start);
                /* Ignore return value for now */
-               __memory_failure(page_to_pfn(p), 0, 1);
+               __memory_failure(page_to_pfn(p), 0, MF_COUNT_INCREASED);
        }
        return ret;
 }
@@ -275,6 +289,10 @@ madvise_behavior_valid(int behavior)
        case MADV_MERGEABLE:
        case MADV_UNMERGEABLE:
 #endif
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+       case MADV_HUGEPAGE:
+       case MADV_NOHUGEPAGE:
+#endif
                return 1;
 
        default:
@@ -334,8 +352,8 @@ SYSCALL_DEFINE3(madvise, unsigned long, start, size_t, len_in, int, behavior)
        size_t len;
 
 #ifdef CONFIG_MEMORY_FAILURE
-       if (behavior == MADV_HWPOISON)
-               return madvise_hwpoison(start, start+len_in);
+       if (behavior == MADV_HWPOISON || behavior == MADV_SOFT_OFFLINE)
+               return madvise_hwpoison(behavior, start, start+len_in);
 #endif
        if (!madvise_behavior_valid(behavior))
                return error;