compat: Backport fault_in_multipages_{writeable,readable}
[~tnikolova/compat/.git] / include / linux / compat-3.5.h
index 1d9128a..74c8176 100644 (file)
@@ -8,6 +8,73 @@
 
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0))
 
+/*
+ * This backports:
+ *
+ * commit f56f821feb7b36223f309e0ec05986bb137ce418
+ * Author: Daniel Vetter <daniel.vetter@ffwll.ch>
+ * Date:   Sun Mar 25 19:47:41 2012 +0200
+ *
+ *     mm: extend prefault helpers to fault in more than PAGE_SIZE
+ *
+ * The new functions are used by drm/i915 driver.
+ *
+ */
+
+static inline int fault_in_multipages_writeable(char __user *uaddr, int size)
+{
+        int ret = 0;
+        char __user *end = uaddr + size - 1;
+
+        if (unlikely(size == 0))
+                return ret;
+
+        /*
+         * Writing zeroes into userspace here is OK, because we know that if
+         * the zero gets there, we'll be overwriting it.
+         */
+        while (uaddr <= end) {
+                ret = __put_user(0, uaddr);
+                if (ret != 0)
+                        return ret;
+                uaddr += PAGE_SIZE;
+        }
+
+        /* Check whether the range spilled into the next page. */
+        if (((unsigned long)uaddr & PAGE_MASK) ==
+                        ((unsigned long)end & PAGE_MASK))
+                ret = __put_user(0, end);
+
+        return ret;
+}
+
+static inline int fault_in_multipages_readable(const char __user *uaddr,
+                                               int size)
+{
+        volatile char c;
+        int ret = 0;
+        const char __user *end = uaddr + size - 1;
+
+        if (unlikely(size == 0))
+                return ret;
+
+        while (uaddr <= end) {
+                ret = __get_user(c, uaddr);
+                if (ret != 0)
+                        return ret;
+                uaddr += PAGE_SIZE;
+        }
+
+        /* Check whether the range spilled into the next page. */
+        if (((unsigned long)uaddr & PAGE_MASK) ==
+                        ((unsigned long)end & PAGE_MASK)) {
+                ret = __get_user(c, end);
+                (void)c;
+        }
+
+        return ret;
+}
+
 /* switcheroo is available on >= 2.6.34 */
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
 #include <linux/vga_switcheroo.h>