summaryrefslogtreecommitdiff
path: root/patches
diff options
context:
space:
mode:
authorTobias Powalowski <tobias@T-POWA-LX.(none)>2009-04-29 13:23:27 +0200
committerTobias Powalowski <tobias@T-POWA-LX.(none)>2009-04-29 13:23:27 +0200
commit3486ba66cf246e62d60944502ea018c8cb672a2e (patch)
treea1d52a5144b82af7b104a2e800952692058d3215 /patches
parentc0c2ae4e6f0dd5acfc061b336b6388da898a769f (diff)
'bump to latest version'
Diffstat (limited to 'patches')
-rw-r--r--patches/drm-intel.patch1789
1 files changed, 0 insertions, 1789 deletions
diff --git a/patches/drm-intel.patch b/patches/drm-intel.patch
deleted file mode 100644
index 2e04b73..0000000
--- a/patches/drm-intel.patch
+++ /dev/null
@@ -1,1789 +0,0 @@
-From: Li Peng <peng.li@intel.com>
-Date: Fri, 13 Mar 2009 02:25:07 +0000 (+0800)
-Subject: drm/i915: Fix LVDS dither setting
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fanholt%2Fdrm-intel.git;a=commitdiff_plain;h=2b5cde2b272f56ec67b56a2af8c067d42eff7328
-
-drm/i915: Fix LVDS dither setting
-
-Update bdb_lvds_options structure according to its defination in
-2D driver. Then we can parse and set 'lvds_dither' bit correctly
-on non-965 chips.
-
-Signed-off-by: Li Peng <peng.li@intel.com>
-Signed-off-by: Eric Anholt <eric@anholt.net>
----
-
-diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h
-index 5ea715a..de621aa 100644
---- a/drivers/gpu/drm/i915/intel_bios.h
-+++ b/drivers/gpu/drm/i915/intel_bios.h
-@@ -162,13 +162,13 @@ struct bdb_lvds_options {
- u8 panel_type;
- u8 rsvd1;
- /* LVDS capabilities, stored in a dword */
-- u8 rsvd2:1;
-- u8 lvds_edid:1;
-- u8 pixel_dither:1;
-- u8 pfit_ratio_auto:1;
-- u8 pfit_gfx_mode_enhanced:1;
-- u8 pfit_text_mode_enhanced:1;
- u8 pfit_mode:2;
-+ u8 pfit_text_mode_enhanced:1;
-+ u8 pfit_gfx_mode_enhanced:1;
-+ u8 pfit_ratio_auto:1;
-+ u8 pixel_dither:1;
-+ u8 lvds_edid:1;
-+ u8 rsvd2:1;
- u8 rsvd4;
- } __attribute__((packed));
-
-diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
-index 0d211af..6619f26 100644
---- a/drivers/gpu/drm/i915/intel_lvds.c
-+++ b/drivers/gpu/drm/i915/intel_lvds.c
-@@ -265,7 +265,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
- pfit_control = 0;
-
- if (!IS_I965G(dev)) {
-- if (dev_priv->panel_wants_dither)
-+ if (dev_priv->panel_wants_dither || dev_priv->lvds_dither)
- pfit_control |= PANEL_8TO6_DITHER_ENABLE;
- }
- else
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 12 Mar 2009 23:27:11 +0000 (-0700)
-Subject: drm/i915: Change DCC tiling detection case to cover only mobile parts.
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fanholt%2Fdrm-intel.git;a=commitdiff_plain;h=8cff2cfacd44232f556d6538f8844b4ed9154e2d
-
-drm/i915: Change DCC tiling detection case to cover only mobile parts.
-
-Later spec investigation has revealed that every 9xx mobile part has
-had this register in this format. Also, no non-mobile parts have been shown
-to have this register. So make all mobile use the same code, and all
-non-mobile use the hack 965 detection.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-(cherry picked from commit 568d9a8f6d4bf81e0672c74573dc02981d31e3ea)
----
-
-diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
-index 7fb4191..4cce1ae 100644
---- a/drivers/gpu/drm/i915/i915_gem_tiling.c
-+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
-@@ -96,16 +96,16 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
- */
- swizzle_x = I915_BIT_6_SWIZZLE_NONE;
- swizzle_y = I915_BIT_6_SWIZZLE_NONE;
-- } else if ((!IS_I965G(dev) && !IS_G33(dev)) || IS_I965GM(dev) ||
-- IS_GM45(dev)) {
-+ } else if (IS_MOBILE(dev)) {
- uint32_t dcc;
-
-- /* On 915-945 and GM965, channel interleave by the CPU is
-- * determined by DCC. The CPU will alternate based on bit 6
-- * in interleaved mode, and the GPU will then also alternate
-- * on bit 6, 9, and 10 for X, but the CPU may also optionally
-- * alternate based on bit 17 (XOR not disabled and XOR
-- * bit == 17).
-+ /* On mobile 9xx chipsets, channel interleave by the CPU is
-+ * determined by DCC. For single-channel, neither the CPU
-+ * nor the GPU do swizzling. For dual channel interleaved,
-+ * the GPU's interleave is bit 9 and 10 for X tiled, and bit
-+ * 9 for Y tiled. The CPU's interleave is independent, and
-+ * can be based on either bit 11 (haven't seen this yet) or
-+ * bit 17 (common).
- */
- dcc = I915_READ(DCC);
- switch (dcc & DCC_ADDRESSING_MODE_MASK) {
-@@ -115,19 +115,18 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev)
- swizzle_y = I915_BIT_6_SWIZZLE_NONE;
- break;
- case DCC_ADDRESSING_MODE_DUAL_CHANNEL_INTERLEAVED:
-- if (IS_I915G(dev) || IS_I915GM(dev) ||
-- dcc & DCC_CHANNEL_XOR_DISABLE) {
-+ if (dcc & DCC_CHANNEL_XOR_DISABLE) {
-+ /* This is the base swizzling by the GPU for
-+ * tiled buffers.
-+ */
- swizzle_x = I915_BIT_6_SWIZZLE_9_10;
- swizzle_y = I915_BIT_6_SWIZZLE_9;
-- } else if ((IS_I965GM(dev) || IS_GM45(dev)) &&
-- (dcc & DCC_CHANNEL_XOR_BIT_17) == 0) {
-- /* GM965/GM45 does either bit 11 or bit 17
-- * swizzling.
-- */
-+ } else if ((dcc & DCC_CHANNEL_XOR_BIT_17) == 0) {
-+ /* Bit 11 swizzling by the CPU in addition. */
- swizzle_x = I915_BIT_6_SWIZZLE_9_10_11;
- swizzle_y = I915_BIT_6_SWIZZLE_9_11;
- } else {
-- /* Bit 17 or perhaps other swizzling */
-+ /* Bit 17 swizzling by the CPU in addition. */
- swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN;
- swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN;
- }
-From: Kristian Høgsberg <krh@redhat.com>
-Date: Fri, 13 Mar 2009 19:42:14 +0000 (-0400)
-Subject: drm/i915: Read the right SDVO register when detecting SVDO/HDMI.
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fanholt%2Fdrm-intel.git;a=commitdiff_plain;h=b44f64db3da6b62f93a3418ca0a61d607d5d45fe
-
-drm/i915: Read the right SDVO register when detecting SVDO/HDMI.
-
-This fixes incorrect detection of the second SDVO/HDMI output on G4X, and
-extra boot time on pre-G4X.
-
-Signed-off-by: Kristian Høgsberg <krh@redhat.com>
-Signed-off-by: Eric Anholt <eric@anholt.net>
-(cherry picked from commit 13520b051e8888dd3af9bda639d83e7df76613d1)
----
-
-diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
-index a283427..601a76f 100644
---- a/drivers/gpu/drm/i915/intel_display.c
-+++ b/drivers/gpu/drm/i915/intel_display.c
-@@ -1474,13 +1474,21 @@ static void intel_setup_outputs(struct drm_device *dev)
-
- if (IS_I9XX(dev)) {
- int found;
-+ u32 reg;
-
- if (I915_READ(SDVOB) & SDVO_DETECTED) {
- found = intel_sdvo_init(dev, SDVOB);
- if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
- intel_hdmi_init(dev, SDVOB);
- }
-- if (!IS_G4X(dev) || (I915_READ(SDVOB) & SDVO_DETECTED)) {
-+
-+ /* Before G4X SDVOC doesn't have its own detect register */
-+ if (IS_G4X(dev))
-+ reg = SDVOC;
-+ else
-+ reg = SDVOB;
-+
-+ if (I915_READ(reg) & SDVO_DETECTED) {
- found = intel_sdvo_init(dev, SDVOC);
- if (!found && SUPPORTS_INTEGRATED_HDMI(dev))
- intel_hdmi_init(dev, SDVOC);
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 9 Mar 2009 16:42:23 +0000 (-0700)
-Subject: drm/i915: Fix lock order reversal in GTT pwrite path.
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fanholt%2Fdrm-intel.git;a=commitdiff_plain;h=f00b1c89b9287124596ab4dbeb630f1840c16ae7
-
-drm/i915: Fix lock order reversal in GTT pwrite path.
-
-Since the pagefault path determines that the lock order we use has to be
-mmap_sem -> struct_mutex, we can't allow page faults to occur while the
-struct_mutex is held. To fix this in pwrite, we first try optimistically to
-see if we can copy from user without faulting. If it fails, fall back to
-using get_user_pages to pin the user's memory, and map those pages
-atomically when copying it to the GPU.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-(cherry picked from commit 3de09aa3b38910d366f4710ffdf430c9d387d1a3)
----
-
-diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
-index 37427e4..35f8c7b 100644
---- a/drivers/gpu/drm/i915/i915_gem.c
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -223,29 +223,34 @@ fast_user_write(struct io_mapping *mapping,
- */
-
- static inline int
--slow_user_write(struct io_mapping *mapping,
-- loff_t page_base, int page_offset,
-- char __user *user_data,
-- int length)
-+slow_kernel_write(struct io_mapping *mapping,
-+ loff_t gtt_base, int gtt_offset,
-+ struct page *user_page, int user_offset,
-+ int length)
- {
-- char __iomem *vaddr;
-+ char *src_vaddr, *dst_vaddr;
- unsigned long unwritten;
-
-- vaddr = io_mapping_map_wc(mapping, page_base);
-- if (vaddr == NULL)
-- return -EFAULT;
-- unwritten = __copy_from_user(vaddr + page_offset,
-- user_data, length);
-- io_mapping_unmap(vaddr);
-+ dst_vaddr = io_mapping_map_atomic_wc(mapping, gtt_base);
-+ src_vaddr = kmap_atomic(user_page, KM_USER1);
-+ unwritten = __copy_from_user_inatomic_nocache(dst_vaddr + gtt_offset,
-+ src_vaddr + user_offset,
-+ length);
-+ kunmap_atomic(src_vaddr, KM_USER1);
-+ io_mapping_unmap_atomic(dst_vaddr);
- if (unwritten)
- return -EFAULT;
- return 0;
- }
-
-+/**
-+ * This is the fast pwrite path, where we copy the data directly from the
-+ * user into the GTT, uncached.
-+ */
- static int
--i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
-- struct drm_i915_gem_pwrite *args,
-- struct drm_file *file_priv)
-+i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
-+ struct drm_i915_gem_pwrite *args,
-+ struct drm_file *file_priv)
- {
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
- drm_i915_private_t *dev_priv = dev->dev_private;
-@@ -273,7 +278,6 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
-
- obj_priv = obj->driver_private;
- offset = obj_priv->gtt_offset + args->offset;
-- obj_priv->dirty = 1;
-
- while (remain > 0) {
- /* Operation in this page
-@@ -292,16 +296,11 @@ i915_gem_gtt_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
- page_offset, user_data, page_length);
-
- /* If we get a fault while copying data, then (presumably) our
-- * source page isn't available. In this case, use the
-- * non-atomic function
-+ * source page isn't available. Return the error and we'll
-+ * retry in the slow path.
- */
-- if (ret) {
-- ret = slow_user_write (dev_priv->mm.gtt_mapping,
-- page_base, page_offset,
-- user_data, page_length);
-- if (ret)
-- goto fail;
-- }
-+ if (ret)
-+ goto fail;
-
- remain -= page_length;
- user_data += page_length;
-@@ -315,6 +314,115 @@ fail:
- return ret;
- }
-
-+/**
-+ * This is the fallback GTT pwrite path, which uses get_user_pages to pin
-+ * the memory and maps it using kmap_atomic for copying.
-+ *
-+ * This code resulted in x11perf -rgb10text consuming about 10% more CPU
-+ * than using i915_gem_gtt_pwrite_fast on a G45 (32-bit).
-+ */
-+static int
-+i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
-+ struct drm_i915_gem_pwrite *args,
-+ struct drm_file *file_priv)
-+{
-+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+ drm_i915_private_t *dev_priv = dev->dev_private;
-+ ssize_t remain;
-+ loff_t gtt_page_base, offset;
-+ loff_t first_data_page, last_data_page, num_pages;
-+ loff_t pinned_pages, i;
-+ struct page **user_pages;
-+ struct mm_struct *mm = current->mm;
-+ int gtt_page_offset, data_page_offset, data_page_index, page_length;
-+ int ret;
-+ uint64_t data_ptr = args->data_ptr;
-+
-+ remain = args->size;
-+
-+ /* Pin the user pages containing the data. We can't fault while
-+ * holding the struct mutex, and all of the pwrite implementations
-+ * want to hold it while dereferencing the user data.
-+ */
-+ first_data_page = data_ptr / PAGE_SIZE;
-+ last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE;
-+ num_pages = last_data_page - first_data_page + 1;
-+
-+ user_pages = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL);
-+ if (user_pages == NULL)
-+ return -ENOMEM;
-+
-+ down_read(&mm->mmap_sem);
-+ pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr,
-+ num_pages, 0, 0, user_pages, NULL);
-+ up_read(&mm->mmap_sem);
-+ if (pinned_pages < num_pages) {
-+ ret = -EFAULT;
-+ goto out_unpin_pages;
-+ }
-+
-+ mutex_lock(&dev->struct_mutex);
-+ ret = i915_gem_object_pin(obj, 0);
-+ if (ret)
-+ goto out_unlock;
-+
-+ ret = i915_gem_object_set_to_gtt_domain(obj, 1);
-+ if (ret)
-+ goto out_unpin_object;
-+
-+ obj_priv = obj->driver_private;
-+ offset = obj_priv->gtt_offset + args->offset;
-+
-+ while (remain > 0) {
-+ /* Operation in this page
-+ *
-+ * gtt_page_base = page offset within aperture
-+ * gtt_page_offset = offset within page in aperture
-+ * data_page_index = page number in get_user_pages return
-+ * data_page_offset = offset with data_page_index page.
-+ * page_length = bytes to copy for this page
-+ */
-+ gtt_page_base = offset & PAGE_MASK;
-+ gtt_page_offset = offset & ~PAGE_MASK;
-+ data_page_index = data_ptr / PAGE_SIZE - first_data_page;
-+ data_page_offset = data_ptr & ~PAGE_MASK;
-+
-+ page_length = remain;
-+ if ((gtt_page_offset + page_length) > PAGE_SIZE)
-+ page_length = PAGE_SIZE - gtt_page_offset;
-+ if ((data_page_offset + page_length) > PAGE_SIZE)
-+ page_length = PAGE_SIZE - data_page_offset;
-+
-+ ret = slow_kernel_write(dev_priv->mm.gtt_mapping,
-+ gtt_page_base, gtt_page_offset,
-+ user_pages[data_page_index],
-+ data_page_offset,
-+ page_length);
-+
-+ /* If we get a fault while copying data, then (presumably) our
-+ * source page isn't available. Return the error and we'll
-+ * retry in the slow path.
-+ */
-+ if (ret)
-+ goto out_unpin_object;
-+
-+ remain -= page_length;
-+ offset += page_length;
-+ data_ptr += page_length;
-+ }
-+
-+out_unpin_object:
-+ i915_gem_object_unpin(obj);
-+out_unlock:
-+ mutex_unlock(&dev->struct_mutex);
-+out_unpin_pages:
-+ for (i = 0; i < pinned_pages; i++)
-+ page_cache_release(user_pages[i]);
-+ kfree(user_pages);
-+
-+ return ret;
-+}
-+
- static int
- i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
- struct drm_i915_gem_pwrite *args,
-@@ -388,9 +496,13 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
- if (obj_priv->phys_obj)
- ret = i915_gem_phys_pwrite(dev, obj, args, file_priv);
- else if (obj_priv->tiling_mode == I915_TILING_NONE &&
-- dev->gtt_total != 0)
-- ret = i915_gem_gtt_pwrite(dev, obj, args, file_priv);
-- else
-+ dev->gtt_total != 0) {
-+ ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file_priv);
-+ if (ret == -EFAULT) {
-+ ret = i915_gem_gtt_pwrite_slow(dev, obj, args,
-+ file_priv);
-+ }
-+ } else
- ret = i915_gem_shmem_pwrite(dev, obj, args, file_priv);
-
- #if WATCH_PWRITE
-From: Eric Anholt <eric@anholt.net>
-Date: Thu, 19 Mar 2009 21:10:50 +0000 (-0700)
-Subject: drm/i915: Make GEM object's page lists refcounted instead of get/free.
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fanholt%2Fdrm-intel.git;a=commitdiff_plain;h=0df23beadf0d3f83ddd6f9bd5242948ece129e2d
-
-drm/i915: Make GEM object's page lists refcounted instead of get/free.
-
-We've wanted this for a few consumers that touch the pages directly (such as
-the following commit), which have been doing the refcounting outside of
-get/put pages.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-(cherry picked from commit 856fa1988ea483fc2dab84a16681dcfde821b740)
----
-
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index d6cc986..75e3384 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -404,7 +404,8 @@ struct drm_i915_gem_object {
- /** AGP memory structure for our GTT binding. */
- DRM_AGP_MEM *agp_mem;
-
-- struct page **page_list;
-+ struct page **pages;
-+ int pages_refcount;
-
- /**
- * Current offset of the object in GTT space.
-diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
-index 35f8c7b..b998d65 100644
---- a/drivers/gpu/drm/i915/i915_gem.c
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -43,8 +43,8 @@ static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
- uint64_t offset,
- uint64_t size);
- static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj);
--static int i915_gem_object_get_page_list(struct drm_gem_object *obj);
--static void i915_gem_object_free_page_list(struct drm_gem_object *obj);
-+static int i915_gem_object_get_pages(struct drm_gem_object *obj);
-+static void i915_gem_object_put_pages(struct drm_gem_object *obj);
- static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
- static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
- unsigned alignment);
-@@ -928,29 +928,30 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
- }
-
- static void
--i915_gem_object_free_page_list(struct drm_gem_object *obj)
-+i915_gem_object_put_pages(struct drm_gem_object *obj)
- {
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
- int page_count = obj->size / PAGE_SIZE;
- int i;
-
-- if (obj_priv->page_list == NULL)
-- return;
-+ BUG_ON(obj_priv->pages_refcount == 0);
-
-+ if (--obj_priv->pages_refcount != 0)
-+ return;
-
- for (i = 0; i < page_count; i++)
-- if (obj_priv->page_list[i] != NULL) {
-+ if (obj_priv->pages[i] != NULL) {
- if (obj_priv->dirty)
-- set_page_dirty(obj_priv->page_list[i]);
-- mark_page_accessed(obj_priv->page_list[i]);
-- page_cache_release(obj_priv->page_list[i]);
-+ set_page_dirty(obj_priv->pages[i]);
-+ mark_page_accessed(obj_priv->pages[i]);
-+ page_cache_release(obj_priv->pages[i]);
- }
- obj_priv->dirty = 0;
-
-- drm_free(obj_priv->page_list,
-+ drm_free(obj_priv->pages,
- page_count * sizeof(struct page *),
- DRM_MEM_DRIVER);
-- obj_priv->page_list = NULL;
-+ obj_priv->pages = NULL;
- }
-
- static void
-@@ -1402,7 +1403,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
- if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
- i915_gem_clear_fence_reg(obj);
-
-- i915_gem_object_free_page_list(obj);
-+ i915_gem_object_put_pages(obj);
-
- if (obj_priv->gtt_space) {
- atomic_dec(&dev->gtt_count);
-@@ -1521,7 +1522,7 @@ i915_gem_evict_everything(struct drm_device *dev)
- }
-
- static int
--i915_gem_object_get_page_list(struct drm_gem_object *obj)
-+i915_gem_object_get_pages(struct drm_gem_object *obj)
- {
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
- int page_count, i;
-@@ -1530,18 +1531,19 @@ i915_gem_object_get_page_list(struct drm_gem_object *obj)
- struct page *page;
- int ret;
-
-- if (obj_priv->page_list)
-+ if (obj_priv->pages_refcount++ != 0)
- return 0;
-
- /* Get the list of pages out of our struct file. They'll be pinned
- * at this point until we release them.
- */
- page_count = obj->size / PAGE_SIZE;
-- BUG_ON(obj_priv->page_list != NULL);
-- obj_priv->page_list = drm_calloc(page_count, sizeof(struct page *),
-- DRM_MEM_DRIVER);
-- if (obj_priv->page_list == NULL) {
-+ BUG_ON(obj_priv->pages != NULL);
-+ obj_priv->pages = drm_calloc(page_count, sizeof(struct page *),
-+ DRM_MEM_DRIVER);
-+ if (obj_priv->pages == NULL) {
- DRM_ERROR("Faled to allocate page list\n");
-+ obj_priv->pages_refcount--;
- return -ENOMEM;
- }
-
-@@ -1552,10 +1554,10 @@ i915_gem_object_get_page_list(struct drm_gem_object *obj)
- if (IS_ERR(page)) {
- ret = PTR_ERR(page);
- DRM_ERROR("read_mapping_page failed: %d\n", ret);
-- i915_gem_object_free_page_list(obj);
-+ i915_gem_object_put_pages(obj);
- return ret;
- }
-- obj_priv->page_list[i] = page;
-+ obj_priv->pages[i] = page;
- }
- return 0;
- }
-@@ -1878,7 +1880,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
- DRM_INFO("Binding object of size %d at 0x%08x\n",
- obj->size, obj_priv->gtt_offset);
- #endif
-- ret = i915_gem_object_get_page_list(obj);
-+ ret = i915_gem_object_get_pages(obj);
- if (ret) {
- drm_mm_put_block(obj_priv->gtt_space);
- obj_priv->gtt_space = NULL;
-@@ -1890,12 +1892,12 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
- * into the GTT.
- */
- obj_priv->agp_mem = drm_agp_bind_pages(dev,
-- obj_priv->page_list,
-+ obj_priv->pages,
- page_count,
- obj_priv->gtt_offset,
- obj_priv->agp_type);
- if (obj_priv->agp_mem == NULL) {
-- i915_gem_object_free_page_list(obj);
-+ i915_gem_object_put_pages(obj);
- drm_mm_put_block(obj_priv->gtt_space);
- obj_priv->gtt_space = NULL;
- return -ENOMEM;
-@@ -1922,10 +1924,10 @@ i915_gem_clflush_object(struct drm_gem_object *obj)
- * to GPU, and we can ignore the cache flush because it'll happen
- * again at bind time.
- */
-- if (obj_priv->page_list == NULL)
-+ if (obj_priv->pages == NULL)
- return;
-
-- drm_clflush_pages(obj_priv->page_list, obj->size / PAGE_SIZE);
-+ drm_clflush_pages(obj_priv->pages, obj->size / PAGE_SIZE);
- }
-
- /** Flushes any GPU write domain for the object if it's dirty. */
-@@ -2270,7 +2272,7 @@ i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj)
- for (i = 0; i <= (obj->size - 1) / PAGE_SIZE; i++) {
- if (obj_priv->page_cpu_valid[i])
- continue;
-- drm_clflush_pages(obj_priv->page_list + i, 1);
-+ drm_clflush_pages(obj_priv->pages + i, 1);
- }
- drm_agp_chipset_flush(dev);
- }
-@@ -2336,7 +2338,7 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
- if (obj_priv->page_cpu_valid[i])
- continue;
-
-- drm_clflush_pages(obj_priv->page_list + i, 1);
-+ drm_clflush_pages(obj_priv->pages + i, 1);
-
- obj_priv->page_cpu_valid[i] = 1;
- }
-@@ -3304,7 +3306,7 @@ i915_gem_init_hws(struct drm_device *dev)
-
- dev_priv->status_gfx_addr = obj_priv->gtt_offset;
-
-- dev_priv->hw_status_page = kmap(obj_priv->page_list[0]);
-+ dev_priv->hw_status_page = kmap(obj_priv->pages[0]);
- if (dev_priv->hw_status_page == NULL) {
- DRM_ERROR("Failed to map status page.\n");
- memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
-@@ -3334,7 +3336,7 @@ i915_gem_cleanup_hws(struct drm_device *dev)
- obj = dev_priv->hws_obj;
- obj_priv = obj->driver_private;
-
-- kunmap(obj_priv->page_list[0]);
-+ kunmap(obj_priv->pages[0]);
- i915_gem_object_unpin(obj);
- drm_gem_object_unreference(obj);
- dev_priv->hws_obj = NULL;
-@@ -3637,20 +3639,20 @@ void i915_gem_detach_phys_object(struct drm_device *dev,
- if (!obj_priv->phys_obj)
- return;
-
-- ret = i915_gem_object_get_page_list(obj);
-+ ret = i915_gem_object_get_pages(obj);
- if (ret)
- goto out;
-
- page_count = obj->size / PAGE_SIZE;
-
- for (i = 0; i < page_count; i++) {
-- char *dst = kmap_atomic(obj_priv->page_list[i], KM_USER0);
-+ char *dst = kmap_atomic(obj_priv->pages[i], KM_USER0);
- char *src = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
-
- memcpy(dst, src, PAGE_SIZE);
- kunmap_atomic(dst, KM_USER0);
- }
-- drm_clflush_pages(obj_priv->page_list, page_count);
-+ drm_clflush_pages(obj_priv->pages, page_count);
- drm_agp_chipset_flush(dev);
- out:
- obj_priv->phys_obj->cur_obj = NULL;
-@@ -3693,7 +3695,7 @@ i915_gem_attach_phys_object(struct drm_device *dev,
- obj_priv->phys_obj = dev_priv->mm.phys_objs[id - 1];
- obj_priv->phys_obj->cur_obj = obj;
-
-- ret = i915_gem_object_get_page_list(obj);
-+ ret = i915_gem_object_get_pages(obj);
- if (ret) {
- DRM_ERROR("failed to get page list\n");
- goto out;
-@@ -3702,7 +3704,7 @@ i915_gem_attach_phys_object(struct drm_device *dev,
- page_count = obj->size / PAGE_SIZE;
-
- for (i = 0; i < page_count; i++) {
-- char *src = kmap_atomic(obj_priv->page_list[i], KM_USER0);
-+ char *src = kmap_atomic(obj_priv->pages[i], KM_USER0);
- char *dst = obj_priv->phys_obj->handle->vaddr + (i * PAGE_SIZE);
-
- memcpy(dst, src, PAGE_SIZE);
-From: Eric Anholt <eric@anholt.net>
-Date: Mon, 9 Mar 2009 20:42:30 +0000 (-0700)
-Subject: drm/i915: Fix lock order reversal in shmem pwrite path.
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fanholt%2Fdrm-intel.git;a=commitdiff_plain;h=74cdcb9e0156a844efc0c0551c68f0c133c11115
-
-drm/i915: Fix lock order reversal in shmem pwrite path.
-
-Like the GTT pwrite path fix, this uses an optimistic path and a
-fallback to get_user_pages. Note that this means we have to stop using
-vfs_write and roll it ourselves.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-(cherry picked from commit 40123c1f8dd920dcff7a42cde5b351d7d0b0422e)
----
-
-diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
-index b998d65..bdc7326 100644
---- a/drivers/gpu/drm/i915/i915_gem.c
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -136,6 +136,33 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
- return 0;
- }
-
-+static inline int
-+slow_shmem_copy(struct page *dst_page,
-+ int dst_offset,
-+ struct page *src_page,
-+ int src_offset,
-+ int length)
-+{
-+ char *dst_vaddr, *src_vaddr;
-+
-+ dst_vaddr = kmap_atomic(dst_page, KM_USER0);
-+ if (dst_vaddr == NULL)
-+ return -ENOMEM;
-+
-+ src_vaddr = kmap_atomic(src_page, KM_USER1);
-+ if (src_vaddr == NULL) {
-+ kunmap_atomic(dst_vaddr, KM_USER0);
-+ return -ENOMEM;
-+ }
-+
-+ memcpy(dst_vaddr + dst_offset, src_vaddr + src_offset, length);
-+
-+ kunmap_atomic(src_vaddr, KM_USER1);
-+ kunmap_atomic(dst_vaddr, KM_USER0);
-+
-+ return 0;
-+}
-+
- /**
- * Reads data from the object referenced by handle.
- *
-@@ -243,6 +270,23 @@ slow_kernel_write(struct io_mapping *mapping,
- return 0;
- }
-
-+static inline int
-+fast_shmem_write(struct page **pages,
-+ loff_t page_base, int page_offset,
-+ char __user *data,
-+ int length)
-+{
-+ char __iomem *vaddr;
-+
-+ vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0);
-+ if (vaddr == NULL)
-+ return -ENOMEM;
-+ __copy_from_user_inatomic(vaddr + page_offset, data, length);
-+ kunmap_atomic(vaddr, KM_USER0);
-+
-+ return 0;
-+}
-+
- /**
- * This is the fast pwrite path, where we copy the data directly from the
- * user into the GTT, uncached.
-@@ -423,39 +467,175 @@ out_unpin_pages:
- return ret;
- }
-
-+/**
-+ * This is the fast shmem pwrite path, which attempts to directly
-+ * copy_from_user into the kmapped pages backing the object.
-+ */
- static int
--i915_gem_shmem_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
-- struct drm_i915_gem_pwrite *args,
-- struct drm_file *file_priv)
-+i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj,
-+ struct drm_i915_gem_pwrite *args,
-+ struct drm_file *file_priv)
- {
-+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+ ssize_t remain;
-+ loff_t offset, page_base;
-+ char __user *user_data;
-+ int page_offset, page_length;
- int ret;
-- loff_t offset;
-- ssize_t written;
-+
-+ user_data = (char __user *) (uintptr_t) args->data_ptr;
-+ remain = args->size;
-
- mutex_lock(&dev->struct_mutex);
-
-+ ret = i915_gem_object_get_pages(obj);
-+ if (ret != 0)
-+ goto fail_unlock;
-+
- ret = i915_gem_object_set_to_cpu_domain(obj, 1);
-- if (ret) {
-- mutex_unlock(&dev->struct_mutex);
-- return ret;
-+ if (ret != 0)
-+ goto fail_put_pages;
-+
-+ obj_priv = obj->driver_private;
-+ offset = args->offset;
-+ obj_priv->dirty = 1;
-+
-+ while (remain > 0) {
-+ /* Operation in this page
-+ *
-+ * page_base = page offset within aperture
-+ * page_offset = offset within page
-+ * page_length = bytes to copy for this page
-+ */
-+ page_base = (offset & ~(PAGE_SIZE-1));
-+ page_offset = offset & (PAGE_SIZE-1);
-+ page_length = remain;
-+ if ((page_offset + remain) > PAGE_SIZE)
-+ page_length = PAGE_SIZE - page_offset;
-+
-+ ret = fast_shmem_write(obj_priv->pages,
-+ page_base, page_offset,
-+ user_data, page_length);
-+ if (ret)
-+ goto fail_put_pages;
-+
-+ remain -= page_length;
-+ user_data += page_length;
-+ offset += page_length;
- }
-
-+fail_put_pages:
-+ i915_gem_object_put_pages(obj);
-+fail_unlock:
-+ mutex_unlock(&dev->struct_mutex);
-+
-+ return ret;
-+}
-+
-+/**
-+ * This is the fallback shmem pwrite path, which uses get_user_pages to pin
-+ * the memory and maps it using kmap_atomic for copying.
-+ *
-+ * This avoids taking mmap_sem for faulting on the user's address while the
-+ * struct_mutex is held.
-+ */
-+static int
-+i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
-+ struct drm_i915_gem_pwrite *args,
-+ struct drm_file *file_priv)
-+{
-+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+ struct mm_struct *mm = current->mm;
-+ struct page **user_pages;
-+ ssize_t remain;
-+ loff_t offset, pinned_pages, i;
-+ loff_t first_data_page, last_data_page, num_pages;
-+ int shmem_page_index, shmem_page_offset;
-+ int data_page_index, data_page_offset;
-+ int page_length;
-+ int ret;
-+ uint64_t data_ptr = args->data_ptr;
-+
-+ remain = args->size;
-+
-+ /* Pin the user pages containing the data. We can't fault while
-+ * holding the struct mutex, and all of the pwrite implementations
-+ * want to hold it while dereferencing the user data.
-+ */
-+ first_data_page = data_ptr / PAGE_SIZE;
-+ last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE;
-+ num_pages = last_data_page - first_data_page + 1;
-+
-+ user_pages = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL);
-+ if (user_pages == NULL)
-+ return -ENOMEM;
-+
-+ down_read(&mm->mmap_sem);
-+ pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr,
-+ num_pages, 0, 0, user_pages, NULL);
-+ up_read(&mm->mmap_sem);
-+ if (pinned_pages < num_pages) {
-+ ret = -EFAULT;
-+ goto fail_put_user_pages;
-+ }
-+
-+ mutex_lock(&dev->struct_mutex);
-+
-+ ret = i915_gem_object_get_pages(obj);
-+ if (ret != 0)
-+ goto fail_unlock;
-+
-+ ret = i915_gem_object_set_to_cpu_domain(obj, 1);
-+ if (ret != 0)
-+ goto fail_put_pages;
-+
-+ obj_priv = obj->driver_private;
- offset = args->offset;
-+ obj_priv->dirty = 1;
-
-- written = vfs_write(obj->filp,
-- (char __user *)(uintptr_t) args->data_ptr,
-- args->size, &offset);
-- if (written != args->size) {
-- mutex_unlock(&dev->struct_mutex);
-- if (written < 0)
-- return written;
-- else
-- return -EINVAL;
-+ while (remain > 0) {
-+ /* Operation in this page
-+ *
-+ * shmem_page_index = page number within shmem file
-+ * shmem_page_offset = offset within page in shmem file
-+ * data_page_index = page number in get_user_pages return
-+ * data_page_offset = offset with data_page_index page.
-+ * page_length = bytes to copy for this page
-+ */
-+ shmem_page_index = offset / PAGE_SIZE;
-+ shmem_page_offset = offset & ~PAGE_MASK;
-+ data_page_index = data_ptr / PAGE_SIZE - first_data_page;
-+ data_page_offset = data_ptr & ~PAGE_MASK;
-+
-+ page_length = remain;
-+ if ((shmem_page_offset + page_length) > PAGE_SIZE)
-+ page_length = PAGE_SIZE - shmem_page_offset;
-+ if ((data_page_offset + page_length) > PAGE_SIZE)
-+ page_length = PAGE_SIZE - data_page_offset;
-+
-+ ret = slow_shmem_copy(obj_priv->pages[shmem_page_index],
-+ shmem_page_offset,
-+ user_pages[data_page_index],
-+ data_page_offset,
-+ page_length);
-+ if (ret)
-+ goto fail_put_pages;
-+
-+ remain -= page_length;
-+ data_ptr += page_length;
-+ offset += page_length;
- }
-
-+fail_put_pages:
-+ i915_gem_object_put_pages(obj);
-+fail_unlock:
- mutex_unlock(&dev->struct_mutex);
-+fail_put_user_pages:
-+ for (i = 0; i < pinned_pages; i++)
-+ page_cache_release(user_pages[i]);
-+ kfree(user_pages);
-
-- return 0;
-+ return ret;
- }
-
- /**
-@@ -502,8 +682,13 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
- ret = i915_gem_gtt_pwrite_slow(dev, obj, args,
- file_priv);
- }
-- } else
-- ret = i915_gem_shmem_pwrite(dev, obj, args, file_priv);
-+ } else {
-+ ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file_priv);
-+ if (ret == -EFAULT) {
-+ ret = i915_gem_shmem_pwrite_slow(dev, obj, args,
-+ file_priv);
-+ }
-+ }
-
- #if WATCH_PWRITE
- if (ret)
-From: Eric Anholt <eric@anholt.net>
-Date: Tue, 10 Mar 2009 18:44:52 +0000 (-0700)
-Subject: drm/i915: Fix lock order reversal in shmem pread path.
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fanholt%2Fdrm-intel.git;a=commitdiff_plain;h=e2c7ebeb32ff1d85ec975bce452575674b7d65c4
-
-drm/i915: Fix lock order reversal in shmem pread path.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-(cherry picked from commit eb01459fbbccb4ca0b879cbfc97e33ac6eabf975)
----
-
-diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
-index bdc7326..010af90 100644
---- a/drivers/gpu/drm/i915/i915_gem.c
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -137,6 +137,24 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
- }
-
- static inline int
-+fast_shmem_read(struct page **pages,
-+ loff_t page_base, int page_offset,
-+ char __user *data,
-+ int length)
-+{
-+ char __iomem *vaddr;
-+ int ret;
-+
-+ vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0);
-+ if (vaddr == NULL)
-+ return -ENOMEM;
-+ ret = __copy_to_user_inatomic(data, vaddr + page_offset, length);
-+ kunmap_atomic(vaddr, KM_USER0);
-+
-+ return ret;
-+}
-+
-+static inline int
- slow_shmem_copy(struct page *dst_page,
- int dst_offset,
- struct page *src_page,
-@@ -164,6 +182,179 @@ slow_shmem_copy(struct page *dst_page,
- }
-
- /**
-+ * This is the fast shmem pread path, which attempts to copy_from_user directly
-+ * from the backing pages of the object to the user's address space. On a
-+ * fault, it fails so we can fall back to i915_gem_shmem_pwrite_slow().
-+ */
-+static int
-+i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj,
-+ struct drm_i915_gem_pread *args,
-+ struct drm_file *file_priv)
-+{
-+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+ ssize_t remain;
-+ loff_t offset, page_base;
-+ char __user *user_data;
-+ int page_offset, page_length;
-+ int ret;
-+
-+ user_data = (char __user *) (uintptr_t) args->data_ptr;
-+ remain = args->size;
-+
-+ mutex_lock(&dev->struct_mutex);
-+
-+ ret = i915_gem_object_get_pages(obj);
-+ if (ret != 0)
-+ goto fail_unlock;
-+
-+ ret = i915_gem_object_set_cpu_read_domain_range(obj, args->offset,
-+ args->size);
-+ if (ret != 0)
-+ goto fail_put_pages;
-+
-+ obj_priv = obj->driver_private;
-+ offset = args->offset;
-+
-+ while (remain > 0) {
-+ /* Operation in this page
-+ *
-+ * page_base = page offset within aperture
-+ * page_offset = offset within page
-+ * page_length = bytes to copy for this page
-+ */
-+ page_base = (offset & ~(PAGE_SIZE-1));
-+ page_offset = offset & (PAGE_SIZE-1);
-+ page_length = remain;
-+ if ((page_offset + remain) > PAGE_SIZE)
-+ page_length = PAGE_SIZE - page_offset;
-+
-+ ret = fast_shmem_read(obj_priv->pages,
-+ page_base, page_offset,
-+ user_data, page_length);
-+ if (ret)
-+ goto fail_put_pages;
-+
-+ remain -= page_length;
-+ user_data += page_length;
-+ offset += page_length;
-+ }
-+
-+fail_put_pages:
-+ i915_gem_object_put_pages(obj);
-+fail_unlock:
-+ mutex_unlock(&dev->struct_mutex);
-+
-+ return ret;
-+}
-+
-+/**
-+ * This is the fallback shmem pread path, which allocates temporary storage
-+ * in kernel space to copy_to_user into outside of the struct_mutex, so we
-+ * can copy out of the object's backing pages while holding the struct mutex
-+ * and not take page faults.
-+ */
-+static int
-+i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj,
-+ struct drm_i915_gem_pread *args,
-+ struct drm_file *file_priv)
-+{
-+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
-+ struct mm_struct *mm = current->mm;
-+ struct page **user_pages;
-+ ssize_t remain;
-+ loff_t offset, pinned_pages, i;
-+ loff_t first_data_page, last_data_page, num_pages;
-+ int shmem_page_index, shmem_page_offset;
-+ int data_page_index, data_page_offset;
-+ int page_length;
-+ int ret;
-+ uint64_t data_ptr = args->data_ptr;
-+
-+ remain = args->size;
-+
-+ /* Pin the user pages containing the data. We can't fault while
-+ * holding the struct mutex, yet we want to hold it while
-+ * dereferencing the user data.
-+ */
-+ first_data_page = data_ptr / PAGE_SIZE;
-+ last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE;
-+ num_pages = last_data_page - first_data_page + 1;
-+
-+ user_pages = kcalloc(num_pages, sizeof(struct page *), GFP_KERNEL);
-+ if (user_pages == NULL)
-+ return -ENOMEM;
-+
-+ down_read(&mm->mmap_sem);
-+ pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr,
-+ num_pages, 0, 0, user_pages, NULL);
-+ up_read(&mm->mmap_sem);
-+ if (pinned_pages < num_pages) {
-+ ret = -EFAULT;
-+ goto fail_put_user_pages;
-+ }
-+
-+ mutex_lock(&dev->struct_mutex);
-+
-+ ret = i915_gem_object_get_pages(obj);
-+ if (ret != 0)
-+ goto fail_unlock;
-+
-+ ret = i915_gem_object_set_cpu_read_domain_range(obj, args->offset,
-+ args->size);
-+ if (ret != 0)
-+ goto fail_put_pages;
-+
-+ obj_priv = obj->driver_private;
-+ offset = args->offset;
-+
-+ while (remain > 0) {
-+ /* Operation in this page
-+ *
-+ * shmem_page_index = page number within shmem file
-+ * shmem_page_offset = offset within page in shmem file
-+ * data_page_index = page number in get_user_pages return
-+ * data_page_offset = offset with data_page_index page.
-+ * page_length = bytes to copy for this page
-+ */
-+ shmem_page_index = offset / PAGE_SIZE;
-+ shmem_page_offset = offset & ~PAGE_MASK;
-+ data_page_index = data_ptr / PAGE_SIZE - first_data_page;
-+ data_page_offset = data_ptr & ~PAGE_MASK;
-+
-+ page_length = remain;
-+ if ((shmem_page_offset + page_length) > PAGE_SIZE)
-+ page_length = PAGE_SIZE - shmem_page_offset;
-+ if ((data_page_offset + page_length) > PAGE_SIZE)
-+ page_length = PAGE_SIZE - data_page_offset;
-+
-+ ret = slow_shmem_copy(user_pages[data_page_index],
-+ data_page_offset,
-+ obj_priv->pages[shmem_page_index],
-+ shmem_page_offset,
-+ page_length);
-+ if (ret)
-+ goto fail_put_pages;
-+
-+ remain -= page_length;
-+ data_ptr += page_length;
-+ offset += page_length;
-+ }
-+
-+fail_put_pages:
-+ i915_gem_object_put_pages(obj);
-+fail_unlock:
-+ mutex_unlock(&dev->struct_mutex);
-+fail_put_user_pages:
-+ for (i = 0; i < pinned_pages; i++) {
-+ SetPageDirty(user_pages[i]);
-+ page_cache_release(user_pages[i]);
-+ }
-+ kfree(user_pages);
-+
-+ return ret;
-+}
-+
-+/**
- * Reads data from the object referenced by handle.
- *
- * On error, the contents of *data are undefined.
-@@ -175,8 +366,6 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
- struct drm_i915_gem_pread *args = data;
- struct drm_gem_object *obj;
- struct drm_i915_gem_object *obj_priv;
-- ssize_t read;
-- loff_t offset;
- int ret;
-
- obj = drm_gem_object_lookup(dev, file_priv, args->handle);
-@@ -194,33 +383,13 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
- return -EINVAL;
- }
-
-- mutex_lock(&dev->struct_mutex);
--
-- ret = i915_gem_object_set_cpu_read_domain_range(obj, args->offset,
-- args->size);
-- if (ret != 0) {
-- drm_gem_object_unreference(obj);
-- mutex_unlock(&dev->struct_mutex);
-- return ret;
-- }
--
-- offset = args->offset;
--
-- read = vfs_read(obj->filp, (char __user *)(uintptr_t)args->data_ptr,
-- args->size, &offset);
-- if (read != args->size) {
-- drm_gem_object_unreference(obj);
-- mutex_unlock(&dev->struct_mutex);
-- if (read < 0)
-- return read;
-- else
-- return -EINVAL;
-- }
-+ ret = i915_gem_shmem_pread_fast(dev, obj, args, file_priv);
-+ if (ret != 0)
-+ ret = i915_gem_shmem_pread_slow(dev, obj, args, file_priv);
-
- drm_gem_object_unreference(obj);
-- mutex_unlock(&dev->struct_mutex);
-
-- return 0;
-+ return ret;
- }
-
- /* This is the fast write path which cannot handle
-From: Eric Anholt <eric@anholt.net>
-Date: Wed, 11 Mar 2009 19:30:04 +0000 (-0700)
-Subject: drm/i915: Fix lock order reversal with cliprects and cmdbuf in non-DRI2 paths.
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fanholt%2Fdrm-intel.git;a=commitdiff_plain;h=02a96e00c7d4e9764bc1a52b7017fd57e694f191
-
-drm/i915: Fix lock order reversal with cliprects and cmdbuf in non-DRI2 paths.
-
-This introduces allocation in the batch submission path that wasn't there
-previously, but these are compatibility paths so we care about simplicity
-more than performance.
-
-kernel.org bug #12419.
-
-Signed-off-by: Eric Anholt <eric@anholt.net>
-Reviewed-by: Keith Packard <keithp@keithp.com>
-Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-(cherry picked from commit 201361a54ed187d8595a283e3a4ddb213bc8323b)
----
-
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index 6d21b9e..ae83fe0 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -356,7 +356,7 @@ static int validate_cmd(int cmd)
- return ret;
- }
-
--static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwords)
-+static int i915_emit_cmds(struct drm_device * dev, int *buffer, int dwords)
- {
- drm_i915_private_t *dev_priv = dev->dev_private;
- int i;
-@@ -370,8 +370,7 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor
- for (i = 0; i < dwords;) {
- int cmd, sz;
-
-- if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd)))
-- return -EINVAL;
-+ cmd = buffer[i];
-
- if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords)
- return -EINVAL;
-@@ -379,11 +378,7 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor
- OUT_RING(cmd);
-
- while (++i, --sz) {
-- if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i],
-- sizeof(cmd))) {
-- return -EINVAL;
-- }
-- OUT_RING(cmd);
-+ OUT_RING(buffer[i]);
- }
- }
-
-@@ -397,17 +392,13 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor
-
- int
- i915_emit_box(struct drm_device *dev,
-- struct drm_clip_rect __user *boxes,
-+ struct drm_clip_rect *boxes,
- int i, int DR1, int DR4)
- {
- drm_i915_private_t *dev_priv = dev->dev_private;
-- struct drm_clip_rect box;
-+ struct drm_clip_rect box = boxes[i];
- RING_LOCALS;
-
-- if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) {
-- return -EFAULT;
-- }
--
- if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) {
- DRM_ERROR("Bad box %d,%d..%d,%d\n",
- box.x1, box.y1, box.x2, box.y2);
-@@ -460,7 +451,9 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
- }
-
- static int i915_dispatch_cmdbuffer(struct drm_device * dev,
-- drm_i915_cmdbuffer_t * cmd)
-+ drm_i915_cmdbuffer_t *cmd,
-+ struct drm_clip_rect *cliprects,
-+ void *cmdbuf)
- {
- int nbox = cmd->num_cliprects;
- int i = 0, count, ret;
-@@ -476,13 +469,13 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev,
-
- for (i = 0; i < count; i++) {
- if (i < nbox) {
-- ret = i915_emit_box(dev, cmd->cliprects, i,
-+ ret = i915_emit_box(dev, cliprects, i,
- cmd->DR1, cmd->DR4);
- if (ret)
- return ret;
- }
-
-- ret = i915_emit_cmds(dev, (int __user *)cmd->buf, cmd->sz / 4);
-+ ret = i915_emit_cmds(dev, cmdbuf, cmd->sz / 4);
- if (ret)
- return ret;
- }
-@@ -492,10 +485,10 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev,
- }
-
- static int i915_dispatch_batchbuffer(struct drm_device * dev,
-- drm_i915_batchbuffer_t * batch)
-+ drm_i915_batchbuffer_t * batch,
-+ struct drm_clip_rect *cliprects)
- {
- drm_i915_private_t *dev_priv = dev->dev_private;
-- struct drm_clip_rect __user *boxes = batch->cliprects;
- int nbox = batch->num_cliprects;
- int i = 0, count;
- RING_LOCALS;
-@@ -511,7 +504,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
-
- for (i = 0; i < count; i++) {
- if (i < nbox) {
-- int ret = i915_emit_box(dev, boxes, i,
-+ int ret = i915_emit_box(dev, cliprects, i,
- batch->DR1, batch->DR4);
- if (ret)
- return ret;
-@@ -626,6 +619,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
- master_priv->sarea_priv;
- drm_i915_batchbuffer_t *batch = data;
- int ret;
-+ struct drm_clip_rect *cliprects = NULL;
-
- if (!dev_priv->allow_batchbuffer) {
- DRM_ERROR("Batchbuffer ioctl disabled\n");
-@@ -637,17 +631,35 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
-
- RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-- if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects,
-- batch->num_cliprects *
-- sizeof(struct drm_clip_rect)))
-- return -EFAULT;
-+ if (batch->num_cliprects < 0)
-+ return -EINVAL;
-+
-+ if (batch->num_cliprects) {
-+ cliprects = drm_calloc(batch->num_cliprects,
-+ sizeof(struct drm_clip_rect),
-+ DRM_MEM_DRIVER);
-+ if (cliprects == NULL)
-+ return -ENOMEM;
-+
-+ ret = copy_from_user(cliprects, batch->cliprects,
-+ batch->num_cliprects *
-+ sizeof(struct drm_clip_rect));
-+ if (ret != 0)
-+ goto fail_free;
-+ }
-
- mutex_lock(&dev->struct_mutex);
-- ret = i915_dispatch_batchbuffer(dev, batch);
-+ ret = i915_dispatch_batchbuffer(dev, batch, cliprects);
- mutex_unlock(&dev->struct_mutex);
-
- if (sarea_priv)
- sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-+
-+fail_free:
-+ drm_free(cliprects,
-+ batch->num_cliprects * sizeof(struct drm_clip_rect),
-+ DRM_MEM_DRIVER);
-+
- return ret;
- }
-
-@@ -659,6 +671,8 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
- drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
- master_priv->sarea_priv;
- drm_i915_cmdbuffer_t *cmdbuf = data;
-+ struct drm_clip_rect *cliprects = NULL;
-+ void *batch_data;
- int ret;
-
- DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n",
-@@ -666,25 +680,50 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
-
- RING_LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-- if (cmdbuf->num_cliprects &&
-- DRM_VERIFYAREA_READ(cmdbuf->cliprects,
-- cmdbuf->num_cliprects *
-- sizeof(struct drm_clip_rect))) {
-- DRM_ERROR("Fault accessing cliprects\n");
-- return -EFAULT;
-+ if (cmdbuf->num_cliprects < 0)
-+ return -EINVAL;
-+
-+ batch_data = drm_alloc(cmdbuf->sz, DRM_MEM_DRIVER);
-+ if (batch_data == NULL)
-+ return -ENOMEM;
-+
-+ ret = copy_from_user(batch_data, cmdbuf->buf, cmdbuf->sz);
-+ if (ret != 0)
-+ goto fail_batch_free;
-+
-+ if (cmdbuf->num_cliprects) {
-+ cliprects = drm_calloc(cmdbuf->num_cliprects,
-+ sizeof(struct drm_clip_rect),
-+ DRM_MEM_DRIVER);
-+ if (cliprects == NULL)
-+ goto fail_batch_free;
-+
-+ ret = copy_from_user(cliprects, cmdbuf->cliprects,
-+ cmdbuf->num_cliprects *
-+ sizeof(struct drm_clip_rect));
-+ if (ret != 0)
-+ goto fail_clip_free;
- }
-
- mutex_lock(&dev->struct_mutex);
-- ret = i915_dispatch_cmdbuffer(dev, cmdbuf);
-+ ret = i915_dispatch_cmdbuffer(dev, cmdbuf, cliprects, batch_data);
- mutex_unlock(&dev->struct_mutex);
- if (ret) {
- DRM_ERROR("i915_dispatch_cmdbuffer failed\n");
-- return ret;
-+ goto fail_batch_free;
- }
-
- if (sarea_priv)
- sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
-- return 0;
-+
-+fail_batch_free:
-+ drm_free(batch_data, cmdbuf->sz, DRM_MEM_DRIVER);
-+fail_clip_free:
-+ drm_free(cliprects,
-+ cmdbuf->num_cliprects * sizeof(struct drm_clip_rect),
-+ DRM_MEM_DRIVER);
-+
-+ return ret;
- }
-
- static int i915_flip_bufs(struct drm_device *dev, void *data,
-diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
-index 75e3384..2c02ce6 100644
---- a/drivers/gpu/drm/i915/i915_drv.h
-+++ b/drivers/gpu/drm/i915/i915_drv.h
-@@ -520,7 +520,7 @@ extern int i915_driver_device_is_agp(struct drm_device * dev);
- extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg);
- extern int i915_emit_box(struct drm_device *dev,
-- struct drm_clip_rect __user *boxes,
-+ struct drm_clip_rect *boxes,
- int i, int DR1, int DR4);
-
- /* i915_irq.c */
-diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
-index 010af90..2bda151 100644
---- a/drivers/gpu/drm/i915/i915_gem.c
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -2891,11 +2891,10 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
- static int
- i915_dispatch_gem_execbuffer(struct drm_device *dev,
- struct drm_i915_gem_execbuffer *exec,
-+ struct drm_clip_rect *cliprects,
- uint64_t exec_offset)
- {
- drm_i915_private_t *dev_priv = dev->dev_private;
-- struct drm_clip_rect __user *boxes = (struct drm_clip_rect __user *)
-- (uintptr_t) exec->cliprects_ptr;
- int nbox = exec->num_cliprects;
- int i = 0, count;
- uint32_t exec_start, exec_len;
-@@ -2916,7 +2915,7 @@ i915_dispatch_gem_execbuffer(struct drm_device *dev,
-
- for (i = 0; i < count; i++) {
- if (i < nbox) {
-- int ret = i915_emit_box(dev, boxes, i,
-+ int ret = i915_emit_box(dev, cliprects, i,
- exec->DR1, exec->DR4);
- if (ret)
- return ret;
-@@ -2983,6 +2982,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
- struct drm_gem_object **object_list = NULL;
- struct drm_gem_object *batch_obj;
- struct drm_i915_gem_object *obj_priv;
-+ struct drm_clip_rect *cliprects = NULL;
- int ret, i, pinned = 0;
- uint64_t exec_offset;
- uint32_t seqno, flush_domains;
-@@ -3019,6 +3019,23 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
- goto pre_mutex_err;
- }
-
-+ if (args->num_cliprects != 0) {
-+ cliprects = drm_calloc(args->num_cliprects, sizeof(*cliprects),
-+ DRM_MEM_DRIVER);
-+ if (cliprects == NULL)
-+ goto pre_mutex_err;
-+
-+ ret = copy_from_user(cliprects,
-+ (struct drm_clip_rect __user *)
-+ (uintptr_t) args->cliprects_ptr,
-+ sizeof(*cliprects) * args->num_cliprects);
-+ if (ret != 0) {
-+ DRM_ERROR("copy %d cliprects failed: %d\n",
-+ args->num_cliprects, ret);
-+ goto pre_mutex_err;
-+ }
-+ }
-+
- mutex_lock(&dev->struct_mutex);
-
- i915_verify_inactive(dev, __FILE__, __LINE__);
-@@ -3155,7 +3172,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
- #endif
-
- /* Exec the batchbuffer */
-- ret = i915_dispatch_gem_execbuffer(dev, args, exec_offset);
-+ ret = i915_dispatch_gem_execbuffer(dev, args, cliprects, exec_offset);
- if (ret) {
- DRM_ERROR("dispatch failed %d\n", ret);
- goto err;
-@@ -3224,6 +3241,8 @@ pre_mutex_err:
- DRM_MEM_DRIVER);
- drm_free(exec_list, sizeof(*exec_list) * args->buffer_count,
- DRM_MEM_DRIVER);
-+ drm_free(cliprects, sizeof(*cliprects) * args->num_cliprects,
-+ DRM_MEM_DRIVER);
-
- return ret;
- }
-From: Zhao Yakui <yakui.zhao@intel.com>
-Date: Tue, 3 Mar 2009 10:07:52 +0000 (+0800)
-Subject: drm/i915: Sync crt hotplug detection with intel video driver
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fanholt%2Fdrm-intel.git;a=commitdiff_plain;h=67b61c3f8c443d575e0b19327b0daa860ca50d2e
-
-drm/i915: Sync crt hotplug detection with intel video driver
-
-This covers:
-Use long crt hotplug activation time on GM45.
-
-Signed-off-by: Zhao Yakui <yakui.zhao@intel.com>
-Signed-off-by: Eric Anholt <eric@anholt.net>
-(cherry picked from commit 771cb081354161eea21534ba58e5cc1a2db94a25)
----
-
-diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
-index 90600d8..cc2938d 100644
---- a/drivers/gpu/drm/i915/i915_reg.h
-+++ b/drivers/gpu/drm/i915/i915_reg.h
-@@ -629,6 +629,22 @@
- #define TV_HOTPLUG_INT_EN (1 << 18)
- #define CRT_HOTPLUG_INT_EN (1 << 9)
- #define CRT_HOTPLUG_FORCE_DETECT (1 << 3)
-+#define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8)
-+/* must use period 64 on GM45 according to docs */
-+#define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8)
-+#define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7)
-+#define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7)
-+#define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5)
-+#define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5)
-+#define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5)
-+#define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5)
-+#define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5)
-+#define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4)
-+#define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4)
-+#define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2)
-+#define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2)
-+#define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */
-+
-
- #define PORT_HOTPLUG_STAT 0x61114
- #define HDMIB_HOTPLUG_INT_STATUS (1 << 29)
-diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
-index dcaed34..61c108e 100644
---- a/drivers/gpu/drm/i915/intel_crt.c
-+++ b/drivers/gpu/drm/i915/intel_crt.c
-@@ -133,20 +133,39 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
- {
- struct drm_device *dev = connector->dev;
- struct drm_i915_private *dev_priv = dev->dev_private;
-- u32 temp;
--
-- unsigned long timeout = jiffies + msecs_to_jiffies(1000);
--
-- temp = I915_READ(PORT_HOTPLUG_EN);
--
-- I915_WRITE(PORT_HOTPLUG_EN,
-- temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5));
-+ u32 hotplug_en;
-+ int i, tries = 0;
-+ /*
-+ * On 4 series desktop, CRT detect sequence need to be done twice
-+ * to get a reliable result.
-+ */
-
-- do {
-- if (!(I915_READ(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT))
-- break;
-- msleep(1);
-- } while (time_after(timeout, jiffies));
-+ if (IS_G4X(dev) && !IS_GM45(dev))
-+ tries = 2;
-+ else
-+ tries = 1;
-+ hotplug_en = I915_READ(PORT_HOTPLUG_EN);
-+ hotplug_en &= ~(CRT_HOTPLUG_MASK);
-+ hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
-+
-+ if (IS_GM45(dev))
-+ hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
-+
-+ hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
-+
-+ for (i = 0; i < tries ; i++) {
-+ unsigned long timeout;
-+ /* turn on the FORCE_DETECT */
-+ I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
-+ timeout = jiffies + msecs_to_jiffies(1000);
-+ /* wait for FORCE_DETECT to go off */
-+ do {
-+ if (!(I915_READ(PORT_HOTPLUG_EN) &
-+ CRT_HOTPLUG_FORCE_DETECT))
-+ break;
-+ msleep(1);
-+ } while (time_after(timeout, jiffies));
-+ }
-
- if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) ==
- CRT_HOTPLUG_MONITOR_COLOR)
-From: Chris Wilson <chris@chris-wilson.co.uk>
-Date: Fri, 6 Mar 2009 23:27:52 +0000 (+0000)
-Subject: drm/i915: Check for dev->primary->master before dereference.
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fanholt%2Fdrm-intel.git;a=commitdiff_plain;h=50531aeb8d87e79b167cc1ae16c2e3a0cd079011
-
-drm/i915: Check for dev->primary->master before dereference.
-
-I've hit the occasional oops inside i915_wait_ring() with an indication of
-a NULL derefence of dev->primary->master. Adding a NULL check is
-consistent with the other potential users of dev->primary->master.
-
-Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-Signed-off-by: Eric Anholt <eric@anholt.net>
-(cherry picked from commit 98787c057fdefdce6230ff46f2c1105835005a4c)
----
-
-diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
-index ae83fe0..a818b37 100644
---- a/drivers/gpu/drm/i915/i915_dma.c
-+++ b/drivers/gpu/drm/i915/i915_dma.c
-@@ -41,7 +41,6 @@
- int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
- {
- drm_i915_private_t *dev_priv = dev->dev_private;
-- struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
- drm_i915_ring_buffer_t *ring = &(dev_priv->ring);
- u32 acthd_reg = IS_I965G(dev) ? ACTHD_I965 : ACTHD;
- u32 last_acthd = I915_READ(acthd_reg);
-@@ -58,8 +57,12 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller)
- if (ring->space >= n)
- return 0;
-
-- if (master_priv->sarea_priv)
-- master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-+ if (dev->primary->master) {
-+ struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv;
-+ if (master_priv->sarea_priv)
-+ master_priv->sarea_priv->perf_boxes |= I915_BOX_WAIT;
-+ }
-+
-
- if (ring->head != last_head)
- i = 0;
-From: Dave Airlie <airlied@redhat.com>
-Date: Sun, 29 Mar 2009 00:29:48 +0000 (-0400)
-Subject: drm/i915: check the return value from the copy from user
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fanholt%2Fdrm-intel.git;a=commitdiff_plain;h=f545c63d84939dbc26645abf61f4c9f0e4dd5fb1
-
-drm/i915: check the return value from the copy from user
-
-This produced a warning on my build, not sure why super-warning-man didn't
-notice this one, its much worse than the %z one.
-
-Signed-off-by: Dave Airlie <airlied@redhat.com>
-(cherry picked from commit d008877550d8ca8c6878dd494e50c1b9209f38d4)
----
-
-diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
-index 2bda151..7ed3977 100644
---- a/drivers/gpu/drm/i915/i915_gem.c
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -446,13 +446,16 @@ fast_shmem_write(struct page **pages,
- int length)
- {
- char __iomem *vaddr;
-+ unsigned long unwritten;
-
- vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0);
- if (vaddr == NULL)
- return -ENOMEM;
-- __copy_from_user_inatomic(vaddr + page_offset, data, length);
-+ unwritten = __copy_from_user_inatomic(vaddr + page_offset, data, length);
- kunmap_atomic(vaddr, KM_USER0);
-
-+ if (unwritten)
-+ return -EFAULT;
- return 0;
- }
-
-From: Jesse Barnes <jbarnes@virtuousgeek.org>
-Date: Fri, 20 Mar 2009 21:16:33 +0000 (-0700)
-Subject: drm/i915: check for -EINVAL from vm_insert_pfn
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fanholt%2Fdrm-intel.git;a=commitdiff_plain;h=d0a6a131deaf7d8fc4913ee1a3def4117bcc26d2
-
-drm/i915: check for -EINVAL from vm_insert_pfn
-
-Indicates something is wrong with the mapping; and apparently triggers
-in current kernels.
-
-Signed-off-by: Jesse Barnes <jbarnes@virtuosugeek.org>
-Signed-off-by: Eric Anholt <eric@anholt.net>
-(cherry picked from commit 959b887cf42fd63cf10e28a7f26126f78aa1c0b0)
----
-
-diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
-index 7ed3977..fbfa155 100644
---- a/drivers/gpu/drm/i915/i915_gem.c
-+++ b/drivers/gpu/drm/i915/i915_gem.c
-@@ -1072,6 +1072,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
- case -EAGAIN:
- return VM_FAULT_OOM;
- case -EFAULT:
-+ case -EINVAL:
- return VM_FAULT_SIGBUS;
- default:
- return VM_FAULT_NOPAGE;
-From: Jesse Barnes <jbarnes@virtuousgeek.org>
-Date: Wed, 1 Apr 2009 01:22:31 +0000 (-0700)
-Subject: drm: Use pgprot_writecombine in GEM GTT mapping to get the right bits for !PAT.
-X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fanholt%2Fdrm-intel.git;a=commitdiff_plain;h=71d7aec4bbf923eaf43563c03459726a746cd332
-
-drm: Use pgprot_writecombine in GEM GTT mapping to get the right bits for !PAT.
-
-Otherwise, the PAGE_CACHE_WC would end up getting us a UC-only mapping, and
-the write performance of GTT maps dropped 10x.
-
-Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-[anholt: cleaned up unused var]
-Signed-off-by: Eric Anholt <eric@anholt.net>
-(cherry picked from commit 1055f9ddad093f54dfd708a0f976582034d4ce1a)
----
-
-diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
-index 88d3368..7ee1ce1 100644
---- a/drivers/gpu/drm/drm_gem.c
-+++ b/drivers/gpu/drm/drm_gem.c
-@@ -505,7 +505,6 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
- struct drm_map *map = NULL;
- struct drm_gem_object *obj;
- struct drm_hash_item *hash;
-- unsigned long prot;
- int ret = 0;
-
- mutex_lock(&dev->struct_mutex);
-@@ -538,11 +537,7 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
- vma->vm_ops = obj->dev->driver->gem_vm_ops;
- vma->vm_private_data = map->handle;
- /* FIXME: use pgprot_writecombine when available */
-- prot = pgprot_val(vma->vm_page_prot);
--#ifdef CONFIG_X86
-- prot |= _PAGE_CACHE_WC;
--#endif
-- vma->vm_page_prot = __pgprot(prot);
-+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-
- /* Take a ref for this mapping of the object, so that the fault
- * handler can dereference the mmap offset's pointer to the object.