aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c191
1 files changed, 159 insertions, 32 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 1449b452cc6..ee896d91c5b 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -43,8 +43,6 @@ static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
43 uint64_t offset, 43 uint64_t offset,
44 uint64_t size); 44 uint64_t size);
45static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj); 45static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj);
46static int i915_gem_object_get_pages(struct drm_gem_object *obj);
47static void i915_gem_object_put_pages(struct drm_gem_object *obj);
48static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); 46static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
49static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, 47static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
50 unsigned alignment); 48 unsigned alignment);
@@ -143,15 +141,27 @@ fast_shmem_read(struct page **pages,
143 int length) 141 int length)
144{ 142{
145 char __iomem *vaddr; 143 char __iomem *vaddr;
146 int ret; 144 int unwritten;
147 145
148 vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0); 146 vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0);
149 if (vaddr == NULL) 147 if (vaddr == NULL)
150 return -ENOMEM; 148 return -ENOMEM;
151 ret = __copy_to_user_inatomic(data, vaddr + page_offset, length); 149 unwritten = __copy_to_user_inatomic(data, vaddr + page_offset, length);
152 kunmap_atomic(vaddr, KM_USER0); 150 kunmap_atomic(vaddr, KM_USER0);
153 151
154 return ret; 152 if (unwritten)
153 return -EFAULT;
154
155 return 0;
156}
157
158static int i915_gem_object_needs_bit17_swizzle(struct drm_gem_object *obj)
159{
160 drm_i915_private_t *dev_priv = obj->dev->dev_private;
161 struct drm_i915_gem_object *obj_priv = obj->driver_private;
162
163 return dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 &&
164 obj_priv->tiling_mode != I915_TILING_NONE;
155} 165}
156 166
157static inline int 167static inline int
@@ -181,6 +191,64 @@ slow_shmem_copy(struct page *dst_page,
181 return 0; 191 return 0;
182} 192}
183 193
194static inline int
195slow_shmem_bit17_copy(struct page *gpu_page,
196 int gpu_offset,
197 struct page *cpu_page,
198 int cpu_offset,
199 int length,
200 int is_read)
201{
202 char *gpu_vaddr, *cpu_vaddr;
203
204 /* Use the unswizzled path if this page isn't affected. */
205 if ((page_to_phys(gpu_page) & (1 << 17)) == 0) {
206 if (is_read)
207 return slow_shmem_copy(cpu_page, cpu_offset,
208 gpu_page, gpu_offset, length);
209 else
210 return slow_shmem_copy(gpu_page, gpu_offset,
211 cpu_page, cpu_offset, length);
212 }
213
214 gpu_vaddr = kmap_atomic(gpu_page, KM_USER0);
215 if (gpu_vaddr == NULL)
216 return -ENOMEM;
217
218 cpu_vaddr = kmap_atomic(cpu_page, KM_USER1);
219 if (cpu_vaddr == NULL) {
220 kunmap_atomic(gpu_vaddr, KM_USER0);
221 return -ENOMEM;
222 }
223
224 /* Copy the data, XORing A6 with A17 (1). The user already knows he's
225 * XORing with the other bits (A9 for Y, A9 and A10 for X)
226 */
227 while (length > 0) {
228 int cacheline_end = ALIGN(gpu_offset + 1, 64);
229 int this_length = min(cacheline_end - gpu_offset, length);
230 int swizzled_gpu_offset = gpu_offset ^ 64;
231
232 if (is_read) {
233 memcpy(cpu_vaddr + cpu_offset,
234 gpu_vaddr + swizzled_gpu_offset,
235 this_length);
236 } else {
237 memcpy(gpu_vaddr + swizzled_gpu_offset,
238 cpu_vaddr + cpu_offset,
239 this_length);
240 }
241 cpu_offset += this_length;
242 gpu_offset += this_length;
243 length -= this_length;
244 }
245
246 kunmap_atomic(cpu_vaddr, KM_USER1);
247 kunmap_atomic(gpu_vaddr, KM_USER0);
248
249 return 0;
250}
251
184/** 252/**
185 * This is the fast shmem pread path, which attempts to copy_from_user directly 253 * This is the fast shmem pread path, which attempts to copy_from_user directly
186 * from the backing pages of the object to the user's address space. On a 254 * from the backing pages of the object to the user's address space. On a
@@ -269,6 +337,7 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj,
269 int page_length; 337 int page_length;
270 int ret; 338 int ret;
271 uint64_t data_ptr = args->data_ptr; 339 uint64_t data_ptr = args->data_ptr;
340 int do_bit17_swizzling;
272 341
273 remain = args->size; 342 remain = args->size;
274 343
@@ -286,13 +355,15 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj,
286 355
287 down_read(&mm->mmap_sem); 356 down_read(&mm->mmap_sem);
288 pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, 357 pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr,
289 num_pages, 0, 0, user_pages, NULL); 358 num_pages, 1, 0, user_pages, NULL);
290 up_read(&mm->mmap_sem); 359 up_read(&mm->mmap_sem);
291 if (pinned_pages < num_pages) { 360 if (pinned_pages < num_pages) {
292 ret = -EFAULT; 361 ret = -EFAULT;
293 goto fail_put_user_pages; 362 goto fail_put_user_pages;
294 } 363 }
295 364
365 do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
366
296 mutex_lock(&dev->struct_mutex); 367 mutex_lock(&dev->struct_mutex);
297 368
298 ret = i915_gem_object_get_pages(obj); 369 ret = i915_gem_object_get_pages(obj);
@@ -327,11 +398,20 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj,
327 if ((data_page_offset + page_length) > PAGE_SIZE) 398 if ((data_page_offset + page_length) > PAGE_SIZE)
328 page_length = PAGE_SIZE - data_page_offset; 399 page_length = PAGE_SIZE - data_page_offset;
329 400
330 ret = slow_shmem_copy(user_pages[data_page_index], 401 if (do_bit17_swizzling) {
331 data_page_offset, 402 ret = slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
332 obj_priv->pages[shmem_page_index], 403 shmem_page_offset,
333 shmem_page_offset, 404 user_pages[data_page_index],
334 page_length); 405 data_page_offset,
406 page_length,
407 1);
408 } else {
409 ret = slow_shmem_copy(user_pages[data_page_index],
410 data_page_offset,
411 obj_priv->pages[shmem_page_index],
412 shmem_page_offset,
413 page_length);
414 }
335 if (ret) 415 if (ret)
336 goto fail_put_pages; 416 goto fail_put_pages;
337 417
@@ -383,9 +463,14 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
383 return -EINVAL; 463 return -EINVAL;
384 } 464 }
385 465
386 ret = i915_gem_shmem_pread_fast(dev, obj, args, file_priv); 466 if (i915_gem_object_needs_bit17_swizzle(obj)) {
387 if (ret != 0)
388 ret = i915_gem_shmem_pread_slow(dev, obj, args, file_priv); 467 ret = i915_gem_shmem_pread_slow(dev, obj, args, file_priv);
468 } else {
469 ret = i915_gem_shmem_pread_fast(dev, obj, args, file_priv);
470 if (ret != 0)
471 ret = i915_gem_shmem_pread_slow(dev, obj, args,
472 file_priv);
473 }
389 474
390 drm_gem_object_unreference(obj); 475 drm_gem_object_unreference(obj);
391 476
@@ -727,6 +812,7 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
727 int page_length; 812 int page_length;
728 int ret; 813 int ret;
729 uint64_t data_ptr = args->data_ptr; 814 uint64_t data_ptr = args->data_ptr;
815 int do_bit17_swizzling;
730 816
731 remain = args->size; 817 remain = args->size;
732 818
@@ -751,6 +837,8 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
751 goto fail_put_user_pages; 837 goto fail_put_user_pages;
752 } 838 }
753 839
840 do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj);
841
754 mutex_lock(&dev->struct_mutex); 842 mutex_lock(&dev->struct_mutex);
755 843
756 ret = i915_gem_object_get_pages(obj); 844 ret = i915_gem_object_get_pages(obj);
@@ -785,11 +873,20 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj,
785 if ((data_page_offset + page_length) > PAGE_SIZE) 873 if ((data_page_offset + page_length) > PAGE_SIZE)
786 page_length = PAGE_SIZE - data_page_offset; 874 page_length = PAGE_SIZE - data_page_offset;
787 875
788 ret = slow_shmem_copy(obj_priv->pages[shmem_page_index], 876 if (do_bit17_swizzling) {
789 shmem_page_offset, 877 ret = slow_shmem_bit17_copy(obj_priv->pages[shmem_page_index],
790 user_pages[data_page_index], 878 shmem_page_offset,
791 data_page_offset, 879 user_pages[data_page_index],
792 page_length); 880 data_page_offset,
881 page_length,
882 0);
883 } else {
884 ret = slow_shmem_copy(obj_priv->pages[shmem_page_index],
885 shmem_page_offset,
886 user_pages[data_page_index],
887 data_page_offset,
888 page_length);
889 }
793 if (ret) 890 if (ret)
794 goto fail_put_pages; 891 goto fail_put_pages;
795 892
@@ -854,6 +951,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
854 ret = i915_gem_gtt_pwrite_slow(dev, obj, args, 951 ret = i915_gem_gtt_pwrite_slow(dev, obj, args,
855 file_priv); 952 file_priv);
856 } 953 }
954 } else if (i915_gem_object_needs_bit17_swizzle(obj)) {
955 ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file_priv);
857 } else { 956 } else {
858 ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file_priv); 957 ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file_priv);
859 if (ret == -EFAULT) { 958 if (ret == -EFAULT) {
@@ -1285,7 +1384,7 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
1285 return 0; 1384 return 0;
1286} 1385}
1287 1386
1288static void 1387void
1289i915_gem_object_put_pages(struct drm_gem_object *obj) 1388i915_gem_object_put_pages(struct drm_gem_object *obj)
1290{ 1389{
1291 struct drm_i915_gem_object *obj_priv = obj->driver_private; 1390 struct drm_i915_gem_object *obj_priv = obj->driver_private;
@@ -1297,6 +1396,9 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
1297 if (--obj_priv->pages_refcount != 0) 1396 if (--obj_priv->pages_refcount != 0)
1298 return; 1397 return;
1299 1398
1399 if (obj_priv->tiling_mode != I915_TILING_NONE)
1400 i915_gem_object_save_bit_17_swizzle(obj);
1401
1300 for (i = 0; i < page_count; i++) 1402 for (i = 0; i < page_count; i++)
1301 if (obj_priv->pages[i] != NULL) { 1403 if (obj_priv->pages[i] != NULL) {
1302 if (obj_priv->dirty) 1404 if (obj_priv->dirty)
@@ -1494,8 +1596,19 @@ i915_gem_retire_request(struct drm_device *dev,
1494 1596
1495 if (obj->write_domain != 0) 1597 if (obj->write_domain != 0)
1496 i915_gem_object_move_to_flushing(obj); 1598 i915_gem_object_move_to_flushing(obj);
1497 else 1599 else {
1600 /* Take a reference on the object so it won't be
1601 * freed while the spinlock is held. The list
1602 * protection for this spinlock is safe when breaking
1603 * the lock like this since the next thing we do
1604 * is just get the head of the list again.
1605 */
1606 drm_gem_object_reference(obj);
1498 i915_gem_object_move_to_inactive(obj); 1607 i915_gem_object_move_to_inactive(obj);
1608 spin_unlock(&dev_priv->mm.active_list_lock);
1609 drm_gem_object_unreference(obj);
1610 spin_lock(&dev_priv->mm.active_list_lock);
1611 }
1499 } 1612 }
1500out: 1613out:
1501 spin_unlock(&dev_priv->mm.active_list_lock); 1614 spin_unlock(&dev_priv->mm.active_list_lock);
@@ -1884,7 +1997,7 @@ i915_gem_evict_everything(struct drm_device *dev)
1884 return ret; 1997 return ret;
1885} 1998}
1886 1999
1887static int 2000int
1888i915_gem_object_get_pages(struct drm_gem_object *obj) 2001i915_gem_object_get_pages(struct drm_gem_object *obj)
1889{ 2002{
1890 struct drm_i915_gem_object *obj_priv = obj->driver_private; 2003 struct drm_i915_gem_object *obj_priv = obj->driver_private;
@@ -1922,6 +2035,10 @@ i915_gem_object_get_pages(struct drm_gem_object *obj)
1922 } 2035 }
1923 obj_priv->pages[i] = page; 2036 obj_priv->pages[i] = page;
1924 } 2037 }
2038
2039 if (obj_priv->tiling_mode != I915_TILING_NONE)
2040 i915_gem_object_do_bit_17_swizzle(obj);
2041
1925 return 0; 2042 return 0;
1926} 2043}
1927 2044
@@ -3002,13 +3119,13 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
3002 drm_free(*relocs, reloc_count * sizeof(**relocs), 3119 drm_free(*relocs, reloc_count * sizeof(**relocs),
3003 DRM_MEM_DRIVER); 3120 DRM_MEM_DRIVER);
3004 *relocs = NULL; 3121 *relocs = NULL;
3005 return ret; 3122 return -EFAULT;
3006 } 3123 }
3007 3124
3008 reloc_index += exec_list[i].relocation_count; 3125 reloc_index += exec_list[i].relocation_count;
3009 } 3126 }
3010 3127
3011 return ret; 3128 return 0;
3012} 3129}
3013 3130
3014static int 3131static int
@@ -3017,23 +3134,28 @@ i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list,
3017 struct drm_i915_gem_relocation_entry *relocs) 3134 struct drm_i915_gem_relocation_entry *relocs)
3018{ 3135{
3019 uint32_t reloc_count = 0, i; 3136 uint32_t reloc_count = 0, i;
3020 int ret; 3137 int ret = 0;
3021 3138
3022 for (i = 0; i < buffer_count; i++) { 3139 for (i = 0; i < buffer_count; i++) {
3023 struct drm_i915_gem_relocation_entry __user *user_relocs; 3140 struct drm_i915_gem_relocation_entry __user *user_relocs;
3141 int unwritten;
3024 3142
3025 user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr; 3143 user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr;
3026 3144
3027 if (ret == 0) { 3145 unwritten = copy_to_user(user_relocs,
3028 ret = copy_to_user(user_relocs, 3146 &relocs[reloc_count],
3029 &relocs[reloc_count], 3147 exec_list[i].relocation_count *
3030 exec_list[i].relocation_count * 3148 sizeof(*relocs));
3031 sizeof(*relocs)); 3149
3150 if (unwritten) {
3151 ret = -EFAULT;
3152 goto err;
3032 } 3153 }
3033 3154
3034 reloc_count += exec_list[i].relocation_count; 3155 reloc_count += exec_list[i].relocation_count;
3035 } 3156 }
3036 3157
3158err:
3037 drm_free(relocs, reloc_count * sizeof(*relocs), DRM_MEM_DRIVER); 3159 drm_free(relocs, reloc_count * sizeof(*relocs), DRM_MEM_DRIVER);
3038 3160
3039 return ret; 3161 return ret;
@@ -3243,7 +3365,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
3243 exec_offset = exec_list[args->buffer_count - 1].offset; 3365 exec_offset = exec_list[args->buffer_count - 1].offset;
3244 3366
3245#if WATCH_EXEC 3367#if WATCH_EXEC
3246 i915_gem_dump_object(object_list[args->buffer_count - 1], 3368 i915_gem_dump_object(batch_obj,
3247 args->batch_len, 3369 args->batch_len,
3248 __func__, 3370 __func__,
3249 ~0); 3371 ~0);
@@ -3308,10 +3430,12 @@ err:
3308 (uintptr_t) args->buffers_ptr, 3430 (uintptr_t) args->buffers_ptr,
3309 exec_list, 3431 exec_list,
3310 sizeof(*exec_list) * args->buffer_count); 3432 sizeof(*exec_list) * args->buffer_count);
3311 if (ret) 3433 if (ret) {
3434 ret = -EFAULT;
3312 DRM_ERROR("failed to copy %d exec entries " 3435 DRM_ERROR("failed to copy %d exec entries "
3313 "back to user (%d)\n", 3436 "back to user (%d)\n",
3314 args->buffer_count, ret); 3437 args->buffer_count, ret);
3438 }
3315 } 3439 }
3316 3440
3317 /* Copy the updated relocations out regardless of current error 3441 /* Copy the updated relocations out regardless of current error
@@ -3593,6 +3717,7 @@ void i915_gem_free_object(struct drm_gem_object *obj)
3593 i915_gem_free_mmap_offset(obj); 3717 i915_gem_free_mmap_offset(obj);
3594 3718
3595 drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER); 3719 drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
3720 kfree(obj_priv->bit_17);
3596 drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); 3721 drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
3597} 3722}
3598 3723
@@ -3962,8 +4087,10 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
3962 dev_priv->mm.suspended = 0; 4087 dev_priv->mm.suspended = 0;
3963 4088
3964 ret = i915_gem_init_ringbuffer(dev); 4089 ret = i915_gem_init_ringbuffer(dev);
3965 if (ret != 0) 4090 if (ret != 0) {
4091 mutex_unlock(&dev->struct_mutex);
3966 return ret; 4092 return ret;
4093 }
3967 4094
3968 spin_lock(&dev_priv->mm.active_list_lock); 4095 spin_lock(&dev_priv->mm.active_list_lock);
3969 BUG_ON(!list_empty(&dev_priv->mm.active_list)); 4096 BUG_ON(!list_empty(&dev_priv->mm.active_list));