drm/i915: vfree() no longer ignores the low bits of the address
authorChris Wilson <chris@chris-wilson.co.uk>
Thu, 18 Aug 2016 16:16:42 +0000 (17:16 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Thu, 18 Aug 2016 21:36:23 +0000 (22:36 +0100)
Since vfree() now likes to WARN when passed a non-page-aligned pointer,
we need to discard the low bits to comply with it.

Fixes: d31d7cb1460c ("drm/i915: Support for creating write combined type vmaps")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20160818161718.27187-3-chris@chris-wilson.co.uk
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c

index a08d2595cb6daf7b9b495d3e280e0b3c12e87e7d..5b778ceba82e50865cbb126486ef655c2ec99267 100644 (file)
@@ -3897,6 +3897,11 @@ static inline bool __i915_request_irq_complete(struct drm_i915_gem_request *req)
 void i915_memcpy_init_early(struct drm_i915_private *dev_priv);
 bool i915_memcpy_from_wc(void *dst, const void *src, unsigned long len);
 
+#define ptr_mask_bits(ptr) ({                                          \
+       unsigned long __v = (unsigned long)(ptr);                       \
+       (typeof(ptr))(__v & PAGE_MASK);                                 \
+})
+
 #define ptr_unpack_bits(ptr, bits) ({                                  \
        unsigned long __v = (unsigned long)(ptr);                       \
        (bits) = __v & ~PAGE_MASK;                                      \
index a8d0f70c22f9a7adc7d81f408a5a69941b745ea3..cffa57b14246c6379ab7e0a93807e58077acb7d9 100644 (file)
@@ -2094,11 +2094,14 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
        list_del(&obj->global_list);
 
        if (obj->mapping) {
-               /* low bits are ignored by is_vmalloc_addr and kmap_to_page */
-               if (is_vmalloc_addr(obj->mapping))
-                       vunmap(obj->mapping);
+               void *ptr;
+
+               ptr = ptr_mask_bits(obj->mapping);
+               if (is_vmalloc_addr(ptr))
+                       vunmap(ptr);
                else
-                       kunmap(kmap_to_page(obj->mapping));
+                       kunmap(kmap_to_page(ptr));
+
                obj->mapping = NULL;
        }