diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 2209 |
1 files changed, 1109 insertions, 1100 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index eb6c473c6d1b..8eb8453208b5 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -37,7 +37,9 @@ | |||
37 | #include <linux/intel-gtt.h> | 37 | #include <linux/intel-gtt.h> |
38 | 38 | ||
39 | static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); | 39 | static uint32_t i915_gem_get_gtt_alignment(struct drm_gem_object *obj); |
40 | static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj); | 40 | |
41 | static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj, | ||
42 | bool pipelined); | ||
41 | static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); | 43 | static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj); |
42 | static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); | 44 | static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj); |
43 | static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, | 45 | static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, |
@@ -46,7 +48,8 @@ static int i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, | |||
46 | uint64_t offset, | 48 | uint64_t offset, |
47 | uint64_t size); | 49 | uint64_t size); |
48 | static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj); | 50 | static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *obj); |
49 | static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); | 51 | static int i915_gem_object_wait_rendering(struct drm_gem_object *obj, |
52 | bool interruptible); | ||
50 | static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, | 53 | static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, |
51 | unsigned alignment); | 54 | unsigned alignment); |
52 | static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); | 55 | static void i915_gem_clear_fence_reg(struct drm_gem_object *obj); |
@@ -55,9 +58,111 @@ static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *o | |||
55 | struct drm_file *file_priv); | 58 | struct drm_file *file_priv); |
56 | static void i915_gem_free_object_tail(struct drm_gem_object *obj); | 59 | static void i915_gem_free_object_tail(struct drm_gem_object *obj); |
57 | 60 | ||
61 | static int | ||
62 | i915_gem_object_get_pages(struct drm_gem_object *obj, | ||
63 | gfp_t gfpmask); | ||
64 | |||
65 | static void | ||
66 | i915_gem_object_put_pages(struct drm_gem_object *obj); | ||
67 | |||
58 | static LIST_HEAD(shrink_list); | 68 | static LIST_HEAD(shrink_list); |
59 | static DEFINE_SPINLOCK(shrink_list_lock); | 69 | static DEFINE_SPINLOCK(shrink_list_lock); |
60 | 70 | ||
71 | /* some bookkeeping */ | ||
72 | static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv, | ||
73 | size_t size) | ||
74 | { | ||
75 | dev_priv->mm.object_count++; | ||
76 | dev_priv->mm.object_memory += size; | ||
77 | } | ||
78 | |||
79 | static void i915_gem_info_remove_obj(struct drm_i915_private *dev_priv, | ||
80 | size_t size) | ||
81 | { | ||
82 | dev_priv->mm.object_count--; | ||
83 | dev_priv->mm.object_memory -= size; | ||
84 | } | ||
85 | |||
86 | static void i915_gem_info_add_gtt(struct drm_i915_private *dev_priv, | ||
87 | size_t size) | ||
88 | { | ||
89 | dev_priv->mm.gtt_count++; | ||
90 | dev_priv->mm.gtt_memory += size; | ||
91 | } | ||
92 | |||
93 | static void i915_gem_info_remove_gtt(struct drm_i915_private *dev_priv, | ||
94 | size_t size) | ||
95 | { | ||
96 | dev_priv->mm.gtt_count--; | ||
97 | dev_priv->mm.gtt_memory -= size; | ||
98 | } | ||
99 | |||
100 | static void i915_gem_info_add_pin(struct drm_i915_private *dev_priv, | ||
101 | size_t size) | ||
102 | { | ||
103 | dev_priv->mm.pin_count++; | ||
104 | dev_priv->mm.pin_memory += size; | ||
105 | } | ||
106 | |||
107 | static void i915_gem_info_remove_pin(struct drm_i915_private *dev_priv, | ||
108 | size_t size) | ||
109 | { | ||
110 | dev_priv->mm.pin_count--; | ||
111 | dev_priv->mm.pin_memory -= size; | ||
112 | } | ||
113 | |||
114 | int | ||
115 | i915_gem_check_is_wedged(struct drm_device *dev) | ||
116 | { | ||
117 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
118 | struct completion *x = &dev_priv->error_completion; | ||
119 | unsigned long flags; | ||
120 | int ret; | ||
121 | |||
122 | if (!atomic_read(&dev_priv->mm.wedged)) | ||
123 | return 0; | ||
124 | |||
125 | ret = wait_for_completion_interruptible(x); | ||
126 | if (ret) | ||
127 | return ret; | ||
128 | |||
129 | /* Success, we reset the GPU! */ | ||
130 | if (!atomic_read(&dev_priv->mm.wedged)) | ||
131 | return 0; | ||
132 | |||
133 | /* GPU is hung, bump the completion count to account for | ||
134 | * the token we just consumed so that we never hit zero and | ||
135 | * end up waiting upon a subsequent completion event that | ||
136 | * will never happen. | ||
137 | */ | ||
138 | spin_lock_irqsave(&x->wait.lock, flags); | ||
139 | x->done++; | ||
140 | spin_unlock_irqrestore(&x->wait.lock, flags); | ||
141 | return -EIO; | ||
142 | } | ||
143 | |||
144 | static int i915_mutex_lock_interruptible(struct drm_device *dev) | ||
145 | { | ||
146 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
147 | int ret; | ||
148 | |||
149 | ret = i915_gem_check_is_wedged(dev); | ||
150 | if (ret) | ||
151 | return ret; | ||
152 | |||
153 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
154 | if (ret) | ||
155 | return ret; | ||
156 | |||
157 | if (atomic_read(&dev_priv->mm.wedged)) { | ||
158 | mutex_unlock(&dev->struct_mutex); | ||
159 | return -EAGAIN; | ||
160 | } | ||
161 | |||
162 | WARN_ON(i915_verify_lists(dev)); | ||
163 | return 0; | ||
164 | } | ||
165 | |||
61 | static inline bool | 166 | static inline bool |
62 | i915_gem_object_is_inactive(struct drm_i915_gem_object *obj_priv) | 167 | i915_gem_object_is_inactive(struct drm_i915_gem_object *obj_priv) |
63 | { | 168 | { |
@@ -66,7 +171,8 @@ i915_gem_object_is_inactive(struct drm_i915_gem_object *obj_priv) | |||
66 | obj_priv->pin_count == 0; | 171 | obj_priv->pin_count == 0; |
67 | } | 172 | } |
68 | 173 | ||
69 | int i915_gem_do_init(struct drm_device *dev, unsigned long start, | 174 | int i915_gem_do_init(struct drm_device *dev, |
175 | unsigned long start, | ||
70 | unsigned long end) | 176 | unsigned long end) |
71 | { | 177 | { |
72 | drm_i915_private_t *dev_priv = dev->dev_private; | 178 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -80,7 +186,7 @@ int i915_gem_do_init(struct drm_device *dev, unsigned long start, | |||
80 | drm_mm_init(&dev_priv->mm.gtt_space, start, | 186 | drm_mm_init(&dev_priv->mm.gtt_space, start, |
81 | end - start); | 187 | end - start); |
82 | 188 | ||
83 | dev->gtt_total = (uint32_t) (end - start); | 189 | dev_priv->mm.gtt_total = end - start; |
84 | 190 | ||
85 | return 0; | 191 | return 0; |
86 | } | 192 | } |
@@ -103,14 +209,16 @@ int | |||
103 | i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, | 209 | i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, |
104 | struct drm_file *file_priv) | 210 | struct drm_file *file_priv) |
105 | { | 211 | { |
212 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
106 | struct drm_i915_gem_get_aperture *args = data; | 213 | struct drm_i915_gem_get_aperture *args = data; |
107 | 214 | ||
108 | if (!(dev->driver->driver_features & DRIVER_GEM)) | 215 | if (!(dev->driver->driver_features & DRIVER_GEM)) |
109 | return -ENODEV; | 216 | return -ENODEV; |
110 | 217 | ||
111 | args->aper_size = dev->gtt_total; | 218 | mutex_lock(&dev->struct_mutex); |
112 | args->aper_available_size = (args->aper_size - | 219 | args->aper_size = dev_priv->mm.gtt_total; |
113 | atomic_read(&dev->pin_memory)); | 220 | args->aper_available_size = args->aper_size - dev_priv->mm.pin_memory; |
221 | mutex_unlock(&dev->struct_mutex); | ||
114 | 222 | ||
115 | return 0; | 223 | return 0; |
116 | } | 224 | } |
@@ -136,12 +244,17 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data, | |||
136 | return -ENOMEM; | 244 | return -ENOMEM; |
137 | 245 | ||
138 | ret = drm_gem_handle_create(file_priv, obj, &handle); | 246 | ret = drm_gem_handle_create(file_priv, obj, &handle); |
139 | /* drop reference from allocate - handle holds it now */ | ||
140 | drm_gem_object_unreference_unlocked(obj); | ||
141 | if (ret) { | 247 | if (ret) { |
248 | drm_gem_object_release(obj); | ||
249 | i915_gem_info_remove_obj(dev->dev_private, obj->size); | ||
250 | kfree(obj); | ||
142 | return ret; | 251 | return ret; |
143 | } | 252 | } |
144 | 253 | ||
254 | /* drop reference from allocate - handle holds it now */ | ||
255 | drm_gem_object_unreference(obj); | ||
256 | trace_i915_gem_object_create(obj); | ||
257 | |||
145 | args->handle = handle; | 258 | args->handle = handle; |
146 | return 0; | 259 | return 0; |
147 | } | 260 | } |
@@ -152,19 +265,14 @@ fast_shmem_read(struct page **pages, | |||
152 | char __user *data, | 265 | char __user *data, |
153 | int length) | 266 | int length) |
154 | { | 267 | { |
155 | char __iomem *vaddr; | 268 | char *vaddr; |
156 | int unwritten; | 269 | int ret; |
157 | 270 | ||
158 | vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]); | 271 | vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]); |
159 | if (vaddr == NULL) | 272 | ret = __copy_to_user_inatomic(data, vaddr + page_offset, length); |
160 | return -ENOMEM; | ||
161 | unwritten = __copy_to_user_inatomic(data, vaddr + page_offset, length); | ||
162 | kunmap_atomic(vaddr); | 273 | kunmap_atomic(vaddr); |
163 | 274 | ||
164 | if (unwritten) | 275 | return ret; |
165 | return -EFAULT; | ||
166 | |||
167 | return 0; | ||
168 | } | 276 | } |
169 | 277 | ||
170 | static int i915_gem_object_needs_bit17_swizzle(struct drm_gem_object *obj) | 278 | static int i915_gem_object_needs_bit17_swizzle(struct drm_gem_object *obj) |
@@ -258,22 +366,10 @@ i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
258 | loff_t offset, page_base; | 366 | loff_t offset, page_base; |
259 | char __user *user_data; | 367 | char __user *user_data; |
260 | int page_offset, page_length; | 368 | int page_offset, page_length; |
261 | int ret; | ||
262 | 369 | ||
263 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 370 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
264 | remain = args->size; | 371 | remain = args->size; |
265 | 372 | ||
266 | mutex_lock(&dev->struct_mutex); | ||
267 | |||
268 | ret = i915_gem_object_get_pages(obj, 0); | ||
269 | if (ret != 0) | ||
270 | goto fail_unlock; | ||
271 | |||
272 | ret = i915_gem_object_set_cpu_read_domain_range(obj, args->offset, | ||
273 | args->size); | ||
274 | if (ret != 0) | ||
275 | goto fail_put_pages; | ||
276 | |||
277 | obj_priv = to_intel_bo(obj); | 373 | obj_priv = to_intel_bo(obj); |
278 | offset = args->offset; | 374 | offset = args->offset; |
279 | 375 | ||
@@ -290,23 +386,17 @@ i915_gem_shmem_pread_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
290 | if ((page_offset + remain) > PAGE_SIZE) | 386 | if ((page_offset + remain) > PAGE_SIZE) |
291 | page_length = PAGE_SIZE - page_offset; | 387 | page_length = PAGE_SIZE - page_offset; |
292 | 388 | ||
293 | ret = fast_shmem_read(obj_priv->pages, | 389 | if (fast_shmem_read(obj_priv->pages, |
294 | page_base, page_offset, | 390 | page_base, page_offset, |
295 | user_data, page_length); | 391 | user_data, page_length)) |
296 | if (ret) | 392 | return -EFAULT; |
297 | goto fail_put_pages; | ||
298 | 393 | ||
299 | remain -= page_length; | 394 | remain -= page_length; |
300 | user_data += page_length; | 395 | user_data += page_length; |
301 | offset += page_length; | 396 | offset += page_length; |
302 | } | 397 | } |
303 | 398 | ||
304 | fail_put_pages: | 399 | return 0; |
305 | i915_gem_object_put_pages(obj); | ||
306 | fail_unlock: | ||
307 | mutex_unlock(&dev->struct_mutex); | ||
308 | |||
309 | return ret; | ||
310 | } | 400 | } |
311 | 401 | ||
312 | static int | 402 | static int |
@@ -367,31 +457,28 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
367 | last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; | 457 | last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; |
368 | num_pages = last_data_page - first_data_page + 1; | 458 | num_pages = last_data_page - first_data_page + 1; |
369 | 459 | ||
370 | user_pages = drm_calloc_large(num_pages, sizeof(struct page *)); | 460 | user_pages = drm_malloc_ab(num_pages, sizeof(struct page *)); |
371 | if (user_pages == NULL) | 461 | if (user_pages == NULL) |
372 | return -ENOMEM; | 462 | return -ENOMEM; |
373 | 463 | ||
464 | mutex_unlock(&dev->struct_mutex); | ||
374 | down_read(&mm->mmap_sem); | 465 | down_read(&mm->mmap_sem); |
375 | pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, | 466 | pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, |
376 | num_pages, 1, 0, user_pages, NULL); | 467 | num_pages, 1, 0, user_pages, NULL); |
377 | up_read(&mm->mmap_sem); | 468 | up_read(&mm->mmap_sem); |
469 | mutex_lock(&dev->struct_mutex); | ||
378 | if (pinned_pages < num_pages) { | 470 | if (pinned_pages < num_pages) { |
379 | ret = -EFAULT; | 471 | ret = -EFAULT; |
380 | goto fail_put_user_pages; | 472 | goto out; |
381 | } | 473 | } |
382 | 474 | ||
383 | do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); | 475 | ret = i915_gem_object_set_cpu_read_domain_range(obj, |
384 | 476 | args->offset, | |
385 | mutex_lock(&dev->struct_mutex); | 477 | args->size); |
386 | |||
387 | ret = i915_gem_object_get_pages_or_evict(obj); | ||
388 | if (ret) | 478 | if (ret) |
389 | goto fail_unlock; | 479 | goto out; |
390 | 480 | ||
391 | ret = i915_gem_object_set_cpu_read_domain_range(obj, args->offset, | 481 | do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); |
392 | args->size); | ||
393 | if (ret != 0) | ||
394 | goto fail_put_pages; | ||
395 | 482 | ||
396 | obj_priv = to_intel_bo(obj); | 483 | obj_priv = to_intel_bo(obj); |
397 | offset = args->offset; | 484 | offset = args->offset; |
@@ -436,11 +523,7 @@ i915_gem_shmem_pread_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
436 | offset += page_length; | 523 | offset += page_length; |
437 | } | 524 | } |
438 | 525 | ||
439 | fail_put_pages: | 526 | out: |
440 | i915_gem_object_put_pages(obj); | ||
441 | fail_unlock: | ||
442 | mutex_unlock(&dev->struct_mutex); | ||
443 | fail_put_user_pages: | ||
444 | for (i = 0; i < pinned_pages; i++) { | 527 | for (i = 0; i < pinned_pages; i++) { |
445 | SetPageDirty(user_pages[i]); | 528 | SetPageDirty(user_pages[i]); |
446 | page_cache_release(user_pages[i]); | 529 | page_cache_release(user_pages[i]); |
@@ -462,37 +545,64 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, | |||
462 | struct drm_i915_gem_pread *args = data; | 545 | struct drm_i915_gem_pread *args = data; |
463 | struct drm_gem_object *obj; | 546 | struct drm_gem_object *obj; |
464 | struct drm_i915_gem_object *obj_priv; | 547 | struct drm_i915_gem_object *obj_priv; |
465 | int ret; | 548 | int ret = 0; |
549 | |||
550 | ret = i915_mutex_lock_interruptible(dev); | ||
551 | if (ret) | ||
552 | return ret; | ||
466 | 553 | ||
467 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 554 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
468 | if (obj == NULL) | 555 | if (obj == NULL) { |
469 | return -ENOENT; | 556 | ret = -ENOENT; |
557 | goto unlock; | ||
558 | } | ||
470 | obj_priv = to_intel_bo(obj); | 559 | obj_priv = to_intel_bo(obj); |
471 | 560 | ||
472 | /* Bounds check source. */ | 561 | /* Bounds check source. */ |
473 | if (args->offset > obj->size || args->size > obj->size - args->offset) { | 562 | if (args->offset > obj->size || args->size > obj->size - args->offset) { |
474 | ret = -EINVAL; | 563 | ret = -EINVAL; |
475 | goto err; | 564 | goto out; |
476 | } | 565 | } |
477 | 566 | ||
567 | if (args->size == 0) | ||
568 | goto out; | ||
569 | |||
478 | if (!access_ok(VERIFY_WRITE, | 570 | if (!access_ok(VERIFY_WRITE, |
479 | (char __user *)(uintptr_t)args->data_ptr, | 571 | (char __user *)(uintptr_t)args->data_ptr, |
480 | args->size)) { | 572 | args->size)) { |
481 | ret = -EFAULT; | 573 | ret = -EFAULT; |
482 | goto err; | 574 | goto out; |
483 | } | 575 | } |
484 | 576 | ||
485 | if (i915_gem_object_needs_bit17_swizzle(obj)) { | 577 | ret = fault_in_pages_writeable((char __user *)(uintptr_t)args->data_ptr, |
486 | ret = i915_gem_shmem_pread_slow(dev, obj, args, file_priv); | 578 | args->size); |
487 | } else { | 579 | if (ret) { |
488 | ret = i915_gem_shmem_pread_fast(dev, obj, args, file_priv); | 580 | ret = -EFAULT; |
489 | if (ret != 0) | 581 | goto out; |
490 | ret = i915_gem_shmem_pread_slow(dev, obj, args, | ||
491 | file_priv); | ||
492 | } | 582 | } |
493 | 583 | ||
494 | err: | 584 | ret = i915_gem_object_get_pages_or_evict(obj); |
495 | drm_gem_object_unreference_unlocked(obj); | 585 | if (ret) |
586 | goto out; | ||
587 | |||
588 | ret = i915_gem_object_set_cpu_read_domain_range(obj, | ||
589 | args->offset, | ||
590 | args->size); | ||
591 | if (ret) | ||
592 | goto out_put; | ||
593 | |||
594 | ret = -EFAULT; | ||
595 | if (!i915_gem_object_needs_bit17_swizzle(obj)) | ||
596 | ret = i915_gem_shmem_pread_fast(dev, obj, args, file_priv); | ||
597 | if (ret == -EFAULT) | ||
598 | ret = i915_gem_shmem_pread_slow(dev, obj, args, file_priv); | ||
599 | |||
600 | out_put: | ||
601 | i915_gem_object_put_pages(obj); | ||
602 | out: | ||
603 | drm_gem_object_unreference(obj); | ||
604 | unlock: | ||
605 | mutex_unlock(&dev->struct_mutex); | ||
496 | return ret; | 606 | return ret; |
497 | } | 607 | } |
498 | 608 | ||
@@ -513,9 +623,7 @@ fast_user_write(struct io_mapping *mapping, | |||
513 | unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset, | 623 | unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset, |
514 | user_data, length); | 624 | user_data, length); |
515 | io_mapping_unmap_atomic(vaddr_atomic); | 625 | io_mapping_unmap_atomic(vaddr_atomic); |
516 | if (unwritten) | 626 | return unwritten; |
517 | return -EFAULT; | ||
518 | return 0; | ||
519 | } | 627 | } |
520 | 628 | ||
521 | /* Here's the write path which can sleep for | 629 | /* Here's the write path which can sleep for |
@@ -548,18 +656,14 @@ fast_shmem_write(struct page **pages, | |||
548 | char __user *data, | 656 | char __user *data, |
549 | int length) | 657 | int length) |
550 | { | 658 | { |
551 | char __iomem *vaddr; | 659 | char *vaddr; |
552 | unsigned long unwritten; | 660 | int ret; |
553 | 661 | ||
554 | vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]); | 662 | vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT]); |
555 | if (vaddr == NULL) | 663 | ret = __copy_from_user_inatomic(vaddr + page_offset, data, length); |
556 | return -ENOMEM; | ||
557 | unwritten = __copy_from_user_inatomic(vaddr + page_offset, data, length); | ||
558 | kunmap_atomic(vaddr); | 664 | kunmap_atomic(vaddr); |
559 | 665 | ||
560 | if (unwritten) | 666 | return ret; |
561 | return -EFAULT; | ||
562 | return 0; | ||
563 | } | 667 | } |
564 | 668 | ||
565 | /** | 669 | /** |
@@ -577,22 +681,10 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
577 | loff_t offset, page_base; | 681 | loff_t offset, page_base; |
578 | char __user *user_data; | 682 | char __user *user_data; |
579 | int page_offset, page_length; | 683 | int page_offset, page_length; |
580 | int ret; | ||
581 | 684 | ||
582 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 685 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
583 | remain = args->size; | 686 | remain = args->size; |
584 | 687 | ||
585 | |||
586 | mutex_lock(&dev->struct_mutex); | ||
587 | ret = i915_gem_object_pin(obj, 0); | ||
588 | if (ret) { | ||
589 | mutex_unlock(&dev->struct_mutex); | ||
590 | return ret; | ||
591 | } | ||
592 | ret = i915_gem_object_set_to_gtt_domain(obj, 1); | ||
593 | if (ret) | ||
594 | goto fail; | ||
595 | |||
596 | obj_priv = to_intel_bo(obj); | 688 | obj_priv = to_intel_bo(obj); |
597 | offset = obj_priv->gtt_offset + args->offset; | 689 | offset = obj_priv->gtt_offset + args->offset; |
598 | 690 | ||
@@ -609,26 +701,21 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
609 | if ((page_offset + remain) > PAGE_SIZE) | 701 | if ((page_offset + remain) > PAGE_SIZE) |
610 | page_length = PAGE_SIZE - page_offset; | 702 | page_length = PAGE_SIZE - page_offset; |
611 | 703 | ||
612 | ret = fast_user_write (dev_priv->mm.gtt_mapping, page_base, | ||
613 | page_offset, user_data, page_length); | ||
614 | |||
615 | /* If we get a fault while copying data, then (presumably) our | 704 | /* If we get a fault while copying data, then (presumably) our |
616 | * source page isn't available. Return the error and we'll | 705 | * source page isn't available. Return the error and we'll |
617 | * retry in the slow path. | 706 | * retry in the slow path. |
618 | */ | 707 | */ |
619 | if (ret) | 708 | if (fast_user_write(dev_priv->mm.gtt_mapping, page_base, |
620 | goto fail; | 709 | page_offset, user_data, page_length)) |
710 | |||
711 | return -EFAULT; | ||
621 | 712 | ||
622 | remain -= page_length; | 713 | remain -= page_length; |
623 | user_data += page_length; | 714 | user_data += page_length; |
624 | offset += page_length; | 715 | offset += page_length; |
625 | } | 716 | } |
626 | 717 | ||
627 | fail: | 718 | return 0; |
628 | i915_gem_object_unpin(obj); | ||
629 | mutex_unlock(&dev->struct_mutex); | ||
630 | |||
631 | return ret; | ||
632 | } | 719 | } |
633 | 720 | ||
634 | /** | 721 | /** |
@@ -665,27 +752,24 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
665 | last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; | 752 | last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; |
666 | num_pages = last_data_page - first_data_page + 1; | 753 | num_pages = last_data_page - first_data_page + 1; |
667 | 754 | ||
668 | user_pages = drm_calloc_large(num_pages, sizeof(struct page *)); | 755 | user_pages = drm_malloc_ab(num_pages, sizeof(struct page *)); |
669 | if (user_pages == NULL) | 756 | if (user_pages == NULL) |
670 | return -ENOMEM; | 757 | return -ENOMEM; |
671 | 758 | ||
759 | mutex_unlock(&dev->struct_mutex); | ||
672 | down_read(&mm->mmap_sem); | 760 | down_read(&mm->mmap_sem); |
673 | pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, | 761 | pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, |
674 | num_pages, 0, 0, user_pages, NULL); | 762 | num_pages, 0, 0, user_pages, NULL); |
675 | up_read(&mm->mmap_sem); | 763 | up_read(&mm->mmap_sem); |
764 | mutex_lock(&dev->struct_mutex); | ||
676 | if (pinned_pages < num_pages) { | 765 | if (pinned_pages < num_pages) { |
677 | ret = -EFAULT; | 766 | ret = -EFAULT; |
678 | goto out_unpin_pages; | 767 | goto out_unpin_pages; |
679 | } | 768 | } |
680 | 769 | ||
681 | mutex_lock(&dev->struct_mutex); | ||
682 | ret = i915_gem_object_pin(obj, 0); | ||
683 | if (ret) | ||
684 | goto out_unlock; | ||
685 | |||
686 | ret = i915_gem_object_set_to_gtt_domain(obj, 1); | 770 | ret = i915_gem_object_set_to_gtt_domain(obj, 1); |
687 | if (ret) | 771 | if (ret) |
688 | goto out_unpin_object; | 772 | goto out_unpin_pages; |
689 | 773 | ||
690 | obj_priv = to_intel_bo(obj); | 774 | obj_priv = to_intel_bo(obj); |
691 | offset = obj_priv->gtt_offset + args->offset; | 775 | offset = obj_priv->gtt_offset + args->offset; |
@@ -721,10 +805,6 @@ i915_gem_gtt_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
721 | data_ptr += page_length; | 805 | data_ptr += page_length; |
722 | } | 806 | } |
723 | 807 | ||
724 | out_unpin_object: | ||
725 | i915_gem_object_unpin(obj); | ||
726 | out_unlock: | ||
727 | mutex_unlock(&dev->struct_mutex); | ||
728 | out_unpin_pages: | 808 | out_unpin_pages: |
729 | for (i = 0; i < pinned_pages; i++) | 809 | for (i = 0; i < pinned_pages; i++) |
730 | page_cache_release(user_pages[i]); | 810 | page_cache_release(user_pages[i]); |
@@ -747,21 +827,10 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
747 | loff_t offset, page_base; | 827 | loff_t offset, page_base; |
748 | char __user *user_data; | 828 | char __user *user_data; |
749 | int page_offset, page_length; | 829 | int page_offset, page_length; |
750 | int ret; | ||
751 | 830 | ||
752 | user_data = (char __user *) (uintptr_t) args->data_ptr; | 831 | user_data = (char __user *) (uintptr_t) args->data_ptr; |
753 | remain = args->size; | 832 | remain = args->size; |
754 | 833 | ||
755 | mutex_lock(&dev->struct_mutex); | ||
756 | |||
757 | ret = i915_gem_object_get_pages(obj, 0); | ||
758 | if (ret != 0) | ||
759 | goto fail_unlock; | ||
760 | |||
761 | ret = i915_gem_object_set_to_cpu_domain(obj, 1); | ||
762 | if (ret != 0) | ||
763 | goto fail_put_pages; | ||
764 | |||
765 | obj_priv = to_intel_bo(obj); | 834 | obj_priv = to_intel_bo(obj); |
766 | offset = args->offset; | 835 | offset = args->offset; |
767 | obj_priv->dirty = 1; | 836 | obj_priv->dirty = 1; |
@@ -779,23 +848,17 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev, struct drm_gem_object *obj, | |||
779 | if ((page_offset + remain) > PAGE_SIZE) | 848 | if ((page_offset + remain) > PAGE_SIZE) |
780 | page_length = PAGE_SIZE - page_offset; | 849 | page_length = PAGE_SIZE - page_offset; |
781 | 850 | ||
782 | ret = fast_shmem_write(obj_priv->pages, | 851 | if (fast_shmem_write(obj_priv->pages, |
783 | page_base, page_offset, | 852 | page_base, page_offset, |
784 | user_data, page_length); | 853 | user_data, page_length)) |
785 | if (ret) | 854 | return -EFAULT; |
786 | goto fail_put_pages; | ||
787 | 855 | ||
788 | remain -= page_length; | 856 | remain -= page_length; |
789 | user_data += page_length; | 857 | user_data += page_length; |
790 | offset += page_length; | 858 | offset += page_length; |
791 | } | 859 | } |
792 | 860 | ||
793 | fail_put_pages: | 861 | return 0; |
794 | i915_gem_object_put_pages(obj); | ||
795 | fail_unlock: | ||
796 | mutex_unlock(&dev->struct_mutex); | ||
797 | |||
798 | return ret; | ||
799 | } | 862 | } |
800 | 863 | ||
801 | /** | 864 | /** |
@@ -833,30 +896,26 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
833 | last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; | 896 | last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; |
834 | num_pages = last_data_page - first_data_page + 1; | 897 | num_pages = last_data_page - first_data_page + 1; |
835 | 898 | ||
836 | user_pages = drm_calloc_large(num_pages, sizeof(struct page *)); | 899 | user_pages = drm_malloc_ab(num_pages, sizeof(struct page *)); |
837 | if (user_pages == NULL) | 900 | if (user_pages == NULL) |
838 | return -ENOMEM; | 901 | return -ENOMEM; |
839 | 902 | ||
903 | mutex_unlock(&dev->struct_mutex); | ||
840 | down_read(&mm->mmap_sem); | 904 | down_read(&mm->mmap_sem); |
841 | pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, | 905 | pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, |
842 | num_pages, 0, 0, user_pages, NULL); | 906 | num_pages, 0, 0, user_pages, NULL); |
843 | up_read(&mm->mmap_sem); | 907 | up_read(&mm->mmap_sem); |
908 | mutex_lock(&dev->struct_mutex); | ||
844 | if (pinned_pages < num_pages) { | 909 | if (pinned_pages < num_pages) { |
845 | ret = -EFAULT; | 910 | ret = -EFAULT; |
846 | goto fail_put_user_pages; | 911 | goto out; |
847 | } | 912 | } |
848 | 913 | ||
849 | do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); | 914 | ret = i915_gem_object_set_to_cpu_domain(obj, 1); |
850 | |||
851 | mutex_lock(&dev->struct_mutex); | ||
852 | |||
853 | ret = i915_gem_object_get_pages_or_evict(obj); | ||
854 | if (ret) | 915 | if (ret) |
855 | goto fail_unlock; | 916 | goto out; |
856 | 917 | ||
857 | ret = i915_gem_object_set_to_cpu_domain(obj, 1); | 918 | do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); |
858 | if (ret != 0) | ||
859 | goto fail_put_pages; | ||
860 | 919 | ||
861 | obj_priv = to_intel_bo(obj); | 920 | obj_priv = to_intel_bo(obj); |
862 | offset = args->offset; | 921 | offset = args->offset; |
@@ -902,11 +961,7 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev, struct drm_gem_object *obj, | |||
902 | offset += page_length; | 961 | offset += page_length; |
903 | } | 962 | } |
904 | 963 | ||
905 | fail_put_pages: | 964 | out: |
906 | i915_gem_object_put_pages(obj); | ||
907 | fail_unlock: | ||
908 | mutex_unlock(&dev->struct_mutex); | ||
909 | fail_put_user_pages: | ||
910 | for (i = 0; i < pinned_pages; i++) | 965 | for (i = 0; i < pinned_pages; i++) |
911 | page_cache_release(user_pages[i]); | 966 | page_cache_release(user_pages[i]); |
912 | drm_free_large(user_pages); | 967 | drm_free_large(user_pages); |
@@ -921,29 +976,46 @@ fail_put_user_pages: | |||
921 | */ | 976 | */ |
922 | int | 977 | int |
923 | i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | 978 | i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, |
924 | struct drm_file *file_priv) | 979 | struct drm_file *file) |
925 | { | 980 | { |
926 | struct drm_i915_gem_pwrite *args = data; | 981 | struct drm_i915_gem_pwrite *args = data; |
927 | struct drm_gem_object *obj; | 982 | struct drm_gem_object *obj; |
928 | struct drm_i915_gem_object *obj_priv; | 983 | struct drm_i915_gem_object *obj_priv; |
929 | int ret = 0; | 984 | int ret = 0; |
930 | 985 | ||
931 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 986 | ret = i915_mutex_lock_interruptible(dev); |
932 | if (obj == NULL) | 987 | if (ret) |
933 | return -ENOENT; | 988 | return ret; |
989 | |||
990 | obj = drm_gem_object_lookup(dev, file, args->handle); | ||
991 | if (obj == NULL) { | ||
992 | ret = -ENOENT; | ||
993 | goto unlock; | ||
994 | } | ||
934 | obj_priv = to_intel_bo(obj); | 995 | obj_priv = to_intel_bo(obj); |
935 | 996 | ||
997 | |||
936 | /* Bounds check destination. */ | 998 | /* Bounds check destination. */ |
937 | if (args->offset > obj->size || args->size > obj->size - args->offset) { | 999 | if (args->offset > obj->size || args->size > obj->size - args->offset) { |
938 | ret = -EINVAL; | 1000 | ret = -EINVAL; |
939 | goto err; | 1001 | goto out; |
940 | } | 1002 | } |
941 | 1003 | ||
1004 | if (args->size == 0) | ||
1005 | goto out; | ||
1006 | |||
942 | if (!access_ok(VERIFY_READ, | 1007 | if (!access_ok(VERIFY_READ, |
943 | (char __user *)(uintptr_t)args->data_ptr, | 1008 | (char __user *)(uintptr_t)args->data_ptr, |
944 | args->size)) { | 1009 | args->size)) { |
945 | ret = -EFAULT; | 1010 | ret = -EFAULT; |
946 | goto err; | 1011 | goto out; |
1012 | } | ||
1013 | |||
1014 | ret = fault_in_pages_readable((char __user *)(uintptr_t)args->data_ptr, | ||
1015 | args->size); | ||
1016 | if (ret) { | ||
1017 | ret = -EFAULT; | ||
1018 | goto out; | ||
947 | } | 1019 | } |
948 | 1020 | ||
949 | /* We can only do the GTT pwrite on untiled buffers, as otherwise | 1021 | /* We can only do the GTT pwrite on untiled buffers, as otherwise |
@@ -953,32 +1025,47 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
953 | * perspective, requiring manual detiling by the client. | 1025 | * perspective, requiring manual detiling by the client. |
954 | */ | 1026 | */ |
955 | if (obj_priv->phys_obj) | 1027 | if (obj_priv->phys_obj) |
956 | ret = i915_gem_phys_pwrite(dev, obj, args, file_priv); | 1028 | ret = i915_gem_phys_pwrite(dev, obj, args, file); |
957 | else if (obj_priv->tiling_mode == I915_TILING_NONE && | 1029 | else if (obj_priv->tiling_mode == I915_TILING_NONE && |
958 | dev->gtt_total != 0 && | 1030 | obj_priv->gtt_space && |
959 | obj->write_domain != I915_GEM_DOMAIN_CPU) { | 1031 | obj->write_domain != I915_GEM_DOMAIN_CPU) { |
960 | ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file_priv); | 1032 | ret = i915_gem_object_pin(obj, 0); |
961 | if (ret == -EFAULT) { | 1033 | if (ret) |
962 | ret = i915_gem_gtt_pwrite_slow(dev, obj, args, | 1034 | goto out; |
963 | file_priv); | 1035 | |
964 | } | 1036 | ret = i915_gem_object_set_to_gtt_domain(obj, 1); |
965 | } else if (i915_gem_object_needs_bit17_swizzle(obj)) { | 1037 | if (ret) |
966 | ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file_priv); | 1038 | goto out_unpin; |
1039 | |||
1040 | ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file); | ||
1041 | if (ret == -EFAULT) | ||
1042 | ret = i915_gem_gtt_pwrite_slow(dev, obj, args, file); | ||
1043 | |||
1044 | out_unpin: | ||
1045 | i915_gem_object_unpin(obj); | ||
967 | } else { | 1046 | } else { |
968 | ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file_priv); | 1047 | ret = i915_gem_object_get_pages_or_evict(obj); |
969 | if (ret == -EFAULT) { | 1048 | if (ret) |
970 | ret = i915_gem_shmem_pwrite_slow(dev, obj, args, | 1049 | goto out; |
971 | file_priv); | ||
972 | } | ||
973 | } | ||
974 | 1050 | ||
975 | #if WATCH_PWRITE | 1051 | ret = i915_gem_object_set_to_cpu_domain(obj, 1); |
976 | if (ret) | 1052 | if (ret) |
977 | DRM_INFO("pwrite failed %d\n", ret); | 1053 | goto out_put; |
978 | #endif | ||
979 | 1054 | ||
980 | err: | 1055 | ret = -EFAULT; |
981 | drm_gem_object_unreference_unlocked(obj); | 1056 | if (!i915_gem_object_needs_bit17_swizzle(obj)) |
1057 | ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file); | ||
1058 | if (ret == -EFAULT) | ||
1059 | ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file); | ||
1060 | |||
1061 | out_put: | ||
1062 | i915_gem_object_put_pages(obj); | ||
1063 | } | ||
1064 | |||
1065 | out: | ||
1066 | drm_gem_object_unreference(obj); | ||
1067 | unlock: | ||
1068 | mutex_unlock(&dev->struct_mutex); | ||
982 | return ret; | 1069 | return ret; |
983 | } | 1070 | } |
984 | 1071 | ||
@@ -1014,19 +1101,19 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
1014 | if (write_domain != 0 && read_domains != write_domain) | 1101 | if (write_domain != 0 && read_domains != write_domain) |
1015 | return -EINVAL; | 1102 | return -EINVAL; |
1016 | 1103 | ||
1104 | ret = i915_mutex_lock_interruptible(dev); | ||
1105 | if (ret) | ||
1106 | return ret; | ||
1107 | |||
1017 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 1108 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
1018 | if (obj == NULL) | 1109 | if (obj == NULL) { |
1019 | return -ENOENT; | 1110 | ret = -ENOENT; |
1111 | goto unlock; | ||
1112 | } | ||
1020 | obj_priv = to_intel_bo(obj); | 1113 | obj_priv = to_intel_bo(obj); |
1021 | 1114 | ||
1022 | mutex_lock(&dev->struct_mutex); | ||
1023 | |||
1024 | intel_mark_busy(dev, obj); | 1115 | intel_mark_busy(dev, obj); |
1025 | 1116 | ||
1026 | #if WATCH_BUF | ||
1027 | DRM_INFO("set_domain_ioctl %p(%zd), %08x %08x\n", | ||
1028 | obj, obj->size, read_domains, write_domain); | ||
1029 | #endif | ||
1030 | if (read_domains & I915_GEM_DOMAIN_GTT) { | 1117 | if (read_domains & I915_GEM_DOMAIN_GTT) { |
1031 | ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0); | 1118 | ret = i915_gem_object_set_to_gtt_domain(obj, write_domain != 0); |
1032 | 1119 | ||
@@ -1050,12 +1137,12 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
1050 | ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0); | 1137 | ret = i915_gem_object_set_to_cpu_domain(obj, write_domain != 0); |
1051 | } | 1138 | } |
1052 | 1139 | ||
1053 | |||
1054 | /* Maintain LRU order of "inactive" objects */ | 1140 | /* Maintain LRU order of "inactive" objects */ |
1055 | if (ret == 0 && i915_gem_object_is_inactive(obj_priv)) | 1141 | if (ret == 0 && i915_gem_object_is_inactive(obj_priv)) |
1056 | list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); | 1142 | list_move_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list); |
1057 | 1143 | ||
1058 | drm_gem_object_unreference(obj); | 1144 | drm_gem_object_unreference(obj); |
1145 | unlock: | ||
1059 | mutex_unlock(&dev->struct_mutex); | 1146 | mutex_unlock(&dev->struct_mutex); |
1060 | return ret; | 1147 | return ret; |
1061 | } | 1148 | } |
@@ -1069,30 +1156,27 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, | |||
1069 | { | 1156 | { |
1070 | struct drm_i915_gem_sw_finish *args = data; | 1157 | struct drm_i915_gem_sw_finish *args = data; |
1071 | struct drm_gem_object *obj; | 1158 | struct drm_gem_object *obj; |
1072 | struct drm_i915_gem_object *obj_priv; | ||
1073 | int ret = 0; | 1159 | int ret = 0; |
1074 | 1160 | ||
1075 | if (!(dev->driver->driver_features & DRIVER_GEM)) | 1161 | if (!(dev->driver->driver_features & DRIVER_GEM)) |
1076 | return -ENODEV; | 1162 | return -ENODEV; |
1077 | 1163 | ||
1078 | mutex_lock(&dev->struct_mutex); | 1164 | ret = i915_mutex_lock_interruptible(dev); |
1165 | if (ret) | ||
1166 | return ret; | ||
1167 | |||
1079 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 1168 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
1080 | if (obj == NULL) { | 1169 | if (obj == NULL) { |
1081 | mutex_unlock(&dev->struct_mutex); | 1170 | ret = -ENOENT; |
1082 | return -ENOENT; | 1171 | goto unlock; |
1083 | } | 1172 | } |
1084 | 1173 | ||
1085 | #if WATCH_BUF | ||
1086 | DRM_INFO("%s: sw_finish %d (%p %zd)\n", | ||
1087 | __func__, args->handle, obj, obj->size); | ||
1088 | #endif | ||
1089 | obj_priv = to_intel_bo(obj); | ||
1090 | |||
1091 | /* Pinned buffers may be scanout, so flush the cache */ | 1174 | /* Pinned buffers may be scanout, so flush the cache */ |
1092 | if (obj_priv->pin_count) | 1175 | if (to_intel_bo(obj)->pin_count) |
1093 | i915_gem_object_flush_cpu_write_domain(obj); | 1176 | i915_gem_object_flush_cpu_write_domain(obj); |
1094 | 1177 | ||
1095 | drm_gem_object_unreference(obj); | 1178 | drm_gem_object_unreference(obj); |
1179 | unlock: | ||
1096 | mutex_unlock(&dev->struct_mutex); | 1180 | mutex_unlock(&dev->struct_mutex); |
1097 | return ret; | 1181 | return ret; |
1098 | } | 1182 | } |
@@ -1181,13 +1265,13 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
1181 | 1265 | ||
1182 | /* Need a new fence register? */ | 1266 | /* Need a new fence register? */ |
1183 | if (obj_priv->tiling_mode != I915_TILING_NONE) { | 1267 | if (obj_priv->tiling_mode != I915_TILING_NONE) { |
1184 | ret = i915_gem_object_get_fence_reg(obj); | 1268 | ret = i915_gem_object_get_fence_reg(obj, true); |
1185 | if (ret) | 1269 | if (ret) |
1186 | goto unlock; | 1270 | goto unlock; |
1187 | } | 1271 | } |
1188 | 1272 | ||
1189 | if (i915_gem_object_is_inactive(obj_priv)) | 1273 | if (i915_gem_object_is_inactive(obj_priv)) |
1190 | list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); | 1274 | list_move_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list); |
1191 | 1275 | ||
1192 | pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) + | 1276 | pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) + |
1193 | page_offset; | 1277 | page_offset; |
@@ -1246,7 +1330,7 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) | |||
1246 | obj->size / PAGE_SIZE, 0, 0); | 1330 | obj->size / PAGE_SIZE, 0, 0); |
1247 | if (!list->file_offset_node) { | 1331 | if (!list->file_offset_node) { |
1248 | DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); | 1332 | DRM_ERROR("failed to allocate offset for bo %d\n", obj->name); |
1249 | ret = -ENOMEM; | 1333 | ret = -ENOSPC; |
1250 | goto out_free_list; | 1334 | goto out_free_list; |
1251 | } | 1335 | } |
1252 | 1336 | ||
@@ -1258,9 +1342,9 @@ i915_gem_create_mmap_offset(struct drm_gem_object *obj) | |||
1258 | } | 1342 | } |
1259 | 1343 | ||
1260 | list->hash.key = list->file_offset_node->start; | 1344 | list->hash.key = list->file_offset_node->start; |
1261 | if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) { | 1345 | ret = drm_ht_insert_item(&mm->offset_hash, &list->hash); |
1346 | if (ret) { | ||
1262 | DRM_ERROR("failed to add to map hash\n"); | 1347 | DRM_ERROR("failed to add to map hash\n"); |
1263 | ret = -ENOMEM; | ||
1264 | goto out_free_mm; | 1348 | goto out_free_mm; |
1265 | } | 1349 | } |
1266 | 1350 | ||
@@ -1345,14 +1429,14 @@ i915_gem_get_gtt_alignment(struct drm_gem_object *obj) | |||
1345 | * Minimum alignment is 4k (GTT page size), but might be greater | 1429 | * Minimum alignment is 4k (GTT page size), but might be greater |
1346 | * if a fence register is needed for the object. | 1430 | * if a fence register is needed for the object. |
1347 | */ | 1431 | */ |
1348 | if (IS_I965G(dev) || obj_priv->tiling_mode == I915_TILING_NONE) | 1432 | if (INTEL_INFO(dev)->gen >= 4 || obj_priv->tiling_mode == I915_TILING_NONE) |
1349 | return 4096; | 1433 | return 4096; |
1350 | 1434 | ||
1351 | /* | 1435 | /* |
1352 | * Previous chips need to be aligned to the size of the smallest | 1436 | * Previous chips need to be aligned to the size of the smallest |
1353 | * fence register that can contain the object. | 1437 | * fence register that can contain the object. |
1354 | */ | 1438 | */ |
1355 | if (IS_I9XX(dev)) | 1439 | if (INTEL_INFO(dev)->gen == 3) |
1356 | start = 1024*1024; | 1440 | start = 1024*1024; |
1357 | else | 1441 | else |
1358 | start = 512*1024; | 1442 | start = 512*1024; |
@@ -1390,29 +1474,27 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
1390 | if (!(dev->driver->driver_features & DRIVER_GEM)) | 1474 | if (!(dev->driver->driver_features & DRIVER_GEM)) |
1391 | return -ENODEV; | 1475 | return -ENODEV; |
1392 | 1476 | ||
1393 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 1477 | ret = i915_mutex_lock_interruptible(dev); |
1394 | if (obj == NULL) | 1478 | if (ret) |
1395 | return -ENOENT; | 1479 | return ret; |
1396 | |||
1397 | mutex_lock(&dev->struct_mutex); | ||
1398 | 1480 | ||
1481 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | ||
1482 | if (obj == NULL) { | ||
1483 | ret = -ENOENT; | ||
1484 | goto unlock; | ||
1485 | } | ||
1399 | obj_priv = to_intel_bo(obj); | 1486 | obj_priv = to_intel_bo(obj); |
1400 | 1487 | ||
1401 | if (obj_priv->madv != I915_MADV_WILLNEED) { | 1488 | if (obj_priv->madv != I915_MADV_WILLNEED) { |
1402 | DRM_ERROR("Attempting to mmap a purgeable buffer\n"); | 1489 | DRM_ERROR("Attempting to mmap a purgeable buffer\n"); |
1403 | drm_gem_object_unreference(obj); | 1490 | ret = -EINVAL; |
1404 | mutex_unlock(&dev->struct_mutex); | 1491 | goto out; |
1405 | return -EINVAL; | ||
1406 | } | 1492 | } |
1407 | 1493 | ||
1408 | |||
1409 | if (!obj_priv->mmap_offset) { | 1494 | if (!obj_priv->mmap_offset) { |
1410 | ret = i915_gem_create_mmap_offset(obj); | 1495 | ret = i915_gem_create_mmap_offset(obj); |
1411 | if (ret) { | 1496 | if (ret) |
1412 | drm_gem_object_unreference(obj); | 1497 | goto out; |
1413 | mutex_unlock(&dev->struct_mutex); | ||
1414 | return ret; | ||
1415 | } | ||
1416 | } | 1498 | } |
1417 | 1499 | ||
1418 | args->offset = obj_priv->mmap_offset; | 1500 | args->offset = obj_priv->mmap_offset; |
@@ -1423,20 +1505,18 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data, | |||
1423 | */ | 1505 | */ |
1424 | if (!obj_priv->agp_mem) { | 1506 | if (!obj_priv->agp_mem) { |
1425 | ret = i915_gem_object_bind_to_gtt(obj, 0); | 1507 | ret = i915_gem_object_bind_to_gtt(obj, 0); |
1426 | if (ret) { | 1508 | if (ret) |
1427 | drm_gem_object_unreference(obj); | 1509 | goto out; |
1428 | mutex_unlock(&dev->struct_mutex); | ||
1429 | return ret; | ||
1430 | } | ||
1431 | } | 1510 | } |
1432 | 1511 | ||
1512 | out: | ||
1433 | drm_gem_object_unreference(obj); | 1513 | drm_gem_object_unreference(obj); |
1514 | unlock: | ||
1434 | mutex_unlock(&dev->struct_mutex); | 1515 | mutex_unlock(&dev->struct_mutex); |
1435 | 1516 | return ret; | |
1436 | return 0; | ||
1437 | } | 1517 | } |
1438 | 1518 | ||
1439 | void | 1519 | static void |
1440 | i915_gem_object_put_pages(struct drm_gem_object *obj) | 1520 | i915_gem_object_put_pages(struct drm_gem_object *obj) |
1441 | { | 1521 | { |
1442 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 1522 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
@@ -1470,13 +1550,25 @@ i915_gem_object_put_pages(struct drm_gem_object *obj) | |||
1470 | obj_priv->pages = NULL; | 1550 | obj_priv->pages = NULL; |
1471 | } | 1551 | } |
1472 | 1552 | ||
1553 | static uint32_t | ||
1554 | i915_gem_next_request_seqno(struct drm_device *dev, | ||
1555 | struct intel_ring_buffer *ring) | ||
1556 | { | ||
1557 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
1558 | |||
1559 | ring->outstanding_lazy_request = true; | ||
1560 | return dev_priv->next_seqno; | ||
1561 | } | ||
1562 | |||
1473 | static void | 1563 | static void |
1474 | i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno, | 1564 | i915_gem_object_move_to_active(struct drm_gem_object *obj, |
1475 | struct intel_ring_buffer *ring) | 1565 | struct intel_ring_buffer *ring) |
1476 | { | 1566 | { |
1477 | struct drm_device *dev = obj->dev; | 1567 | struct drm_device *dev = obj->dev; |
1478 | drm_i915_private_t *dev_priv = dev->dev_private; | 1568 | struct drm_i915_private *dev_priv = dev->dev_private; |
1479 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 1569 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
1570 | uint32_t seqno = i915_gem_next_request_seqno(dev, ring); | ||
1571 | |||
1480 | BUG_ON(ring == NULL); | 1572 | BUG_ON(ring == NULL); |
1481 | obj_priv->ring = ring; | 1573 | obj_priv->ring = ring; |
1482 | 1574 | ||
@@ -1485,10 +1577,10 @@ i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno, | |||
1485 | drm_gem_object_reference(obj); | 1577 | drm_gem_object_reference(obj); |
1486 | obj_priv->active = 1; | 1578 | obj_priv->active = 1; |
1487 | } | 1579 | } |
1580 | |||
1488 | /* Move from whatever list we were on to the tail of execution. */ | 1581 | /* Move from whatever list we were on to the tail of execution. */ |
1489 | spin_lock(&dev_priv->mm.active_list_lock); | 1582 | list_move_tail(&obj_priv->mm_list, &dev_priv->mm.active_list); |
1490 | list_move_tail(&obj_priv->list, &ring->active_list); | 1583 | list_move_tail(&obj_priv->ring_list, &ring->active_list); |
1491 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
1492 | obj_priv->last_rendering_seqno = seqno; | 1584 | obj_priv->last_rendering_seqno = seqno; |
1493 | } | 1585 | } |
1494 | 1586 | ||
@@ -1500,7 +1592,8 @@ i915_gem_object_move_to_flushing(struct drm_gem_object *obj) | |||
1500 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 1592 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
1501 | 1593 | ||
1502 | BUG_ON(!obj_priv->active); | 1594 | BUG_ON(!obj_priv->active); |
1503 | list_move_tail(&obj_priv->list, &dev_priv->mm.flushing_list); | 1595 | list_move_tail(&obj_priv->mm_list, &dev_priv->mm.flushing_list); |
1596 | list_del_init(&obj_priv->ring_list); | ||
1504 | obj_priv->last_rendering_seqno = 0; | 1597 | obj_priv->last_rendering_seqno = 0; |
1505 | } | 1598 | } |
1506 | 1599 | ||
@@ -1538,11 +1631,11 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj) | |||
1538 | drm_i915_private_t *dev_priv = dev->dev_private; | 1631 | drm_i915_private_t *dev_priv = dev->dev_private; |
1539 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 1632 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
1540 | 1633 | ||
1541 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
1542 | if (obj_priv->pin_count != 0) | 1634 | if (obj_priv->pin_count != 0) |
1543 | list_del_init(&obj_priv->list); | 1635 | list_move_tail(&obj_priv->mm_list, &dev_priv->mm.pinned_list); |
1544 | else | 1636 | else |
1545 | list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); | 1637 | list_move_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list); |
1638 | list_del_init(&obj_priv->ring_list); | ||
1546 | 1639 | ||
1547 | BUG_ON(!list_empty(&obj_priv->gpu_write_list)); | 1640 | BUG_ON(!list_empty(&obj_priv->gpu_write_list)); |
1548 | 1641 | ||
@@ -1552,30 +1645,28 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj) | |||
1552 | obj_priv->active = 0; | 1645 | obj_priv->active = 0; |
1553 | drm_gem_object_unreference(obj); | 1646 | drm_gem_object_unreference(obj); |
1554 | } | 1647 | } |
1555 | i915_verify_inactive(dev, __FILE__, __LINE__); | 1648 | WARN_ON(i915_verify_lists(dev)); |
1556 | } | 1649 | } |
1557 | 1650 | ||
1558 | static void | 1651 | static void |
1559 | i915_gem_process_flushing_list(struct drm_device *dev, | 1652 | i915_gem_process_flushing_list(struct drm_device *dev, |
1560 | uint32_t flush_domains, uint32_t seqno, | 1653 | uint32_t flush_domains, |
1561 | struct intel_ring_buffer *ring) | 1654 | struct intel_ring_buffer *ring) |
1562 | { | 1655 | { |
1563 | drm_i915_private_t *dev_priv = dev->dev_private; | 1656 | drm_i915_private_t *dev_priv = dev->dev_private; |
1564 | struct drm_i915_gem_object *obj_priv, *next; | 1657 | struct drm_i915_gem_object *obj_priv, *next; |
1565 | 1658 | ||
1566 | list_for_each_entry_safe(obj_priv, next, | 1659 | list_for_each_entry_safe(obj_priv, next, |
1567 | &dev_priv->mm.gpu_write_list, | 1660 | &ring->gpu_write_list, |
1568 | gpu_write_list) { | 1661 | gpu_write_list) { |
1569 | struct drm_gem_object *obj = &obj_priv->base; | 1662 | struct drm_gem_object *obj = &obj_priv->base; |
1570 | 1663 | ||
1571 | if ((obj->write_domain & flush_domains) == | 1664 | if (obj->write_domain & flush_domains) { |
1572 | obj->write_domain && | ||
1573 | obj_priv->ring->ring_flag == ring->ring_flag) { | ||
1574 | uint32_t old_write_domain = obj->write_domain; | 1665 | uint32_t old_write_domain = obj->write_domain; |
1575 | 1666 | ||
1576 | obj->write_domain = 0; | 1667 | obj->write_domain = 0; |
1577 | list_del_init(&obj_priv->gpu_write_list); | 1668 | list_del_init(&obj_priv->gpu_write_list); |
1578 | i915_gem_object_move_to_active(obj, seqno, ring); | 1669 | i915_gem_object_move_to_active(obj, ring); |
1579 | 1670 | ||
1580 | /* update the fence lru list */ | 1671 | /* update the fence lru list */ |
1581 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) { | 1672 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) { |
@@ -1593,23 +1684,27 @@ i915_gem_process_flushing_list(struct drm_device *dev, | |||
1593 | } | 1684 | } |
1594 | 1685 | ||
1595 | uint32_t | 1686 | uint32_t |
1596 | i915_add_request(struct drm_device *dev, struct drm_file *file_priv, | 1687 | i915_add_request(struct drm_device *dev, |
1597 | uint32_t flush_domains, struct intel_ring_buffer *ring) | 1688 | struct drm_file *file, |
1689 | struct drm_i915_gem_request *request, | ||
1690 | struct intel_ring_buffer *ring) | ||
1598 | { | 1691 | { |
1599 | drm_i915_private_t *dev_priv = dev->dev_private; | 1692 | drm_i915_private_t *dev_priv = dev->dev_private; |
1600 | struct drm_i915_file_private *i915_file_priv = NULL; | 1693 | struct drm_i915_file_private *file_priv = NULL; |
1601 | struct drm_i915_gem_request *request; | ||
1602 | uint32_t seqno; | 1694 | uint32_t seqno; |
1603 | int was_empty; | 1695 | int was_empty; |
1604 | 1696 | ||
1605 | if (file_priv != NULL) | 1697 | if (file != NULL) |
1606 | i915_file_priv = file_priv->driver_priv; | 1698 | file_priv = file->driver_priv; |
1607 | 1699 | ||
1608 | request = kzalloc(sizeof(*request), GFP_KERNEL); | 1700 | if (request == NULL) { |
1609 | if (request == NULL) | 1701 | request = kzalloc(sizeof(*request), GFP_KERNEL); |
1610 | return 0; | 1702 | if (request == NULL) |
1703 | return 0; | ||
1704 | } | ||
1611 | 1705 | ||
1612 | seqno = ring->add_request(dev, ring, file_priv, flush_domains); | 1706 | seqno = ring->add_request(dev, ring, 0); |
1707 | ring->outstanding_lazy_request = false; | ||
1613 | 1708 | ||
1614 | request->seqno = seqno; | 1709 | request->seqno = seqno; |
1615 | request->ring = ring; | 1710 | request->ring = ring; |
@@ -1617,23 +1712,20 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, | |||
1617 | was_empty = list_empty(&ring->request_list); | 1712 | was_empty = list_empty(&ring->request_list); |
1618 | list_add_tail(&request->list, &ring->request_list); | 1713 | list_add_tail(&request->list, &ring->request_list); |
1619 | 1714 | ||
1620 | if (i915_file_priv) { | 1715 | if (file_priv) { |
1716 | spin_lock(&file_priv->mm.lock); | ||
1717 | request->file_priv = file_priv; | ||
1621 | list_add_tail(&request->client_list, | 1718 | list_add_tail(&request->client_list, |
1622 | &i915_file_priv->mm.request_list); | 1719 | &file_priv->mm.request_list); |
1623 | } else { | 1720 | spin_unlock(&file_priv->mm.lock); |
1624 | INIT_LIST_HEAD(&request->client_list); | ||
1625 | } | 1721 | } |
1626 | 1722 | ||
1627 | /* Associate any objects on the flushing list matching the write | ||
1628 | * domain we're flushing with our flush. | ||
1629 | */ | ||
1630 | if (flush_domains != 0) | ||
1631 | i915_gem_process_flushing_list(dev, flush_domains, seqno, ring); | ||
1632 | |||
1633 | if (!dev_priv->mm.suspended) { | 1723 | if (!dev_priv->mm.suspended) { |
1634 | mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD); | 1724 | mod_timer(&dev_priv->hangcheck_timer, |
1725 | jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); | ||
1635 | if (was_empty) | 1726 | if (was_empty) |
1636 | queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); | 1727 | queue_delayed_work(dev_priv->wq, |
1728 | &dev_priv->mm.retire_work, HZ); | ||
1637 | } | 1729 | } |
1638 | return seqno; | 1730 | return seqno; |
1639 | } | 1731 | } |
@@ -1644,91 +1736,105 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv, | |||
1644 | * Ensures that all commands in the ring are finished | 1736 | * Ensures that all commands in the ring are finished |
1645 | * before signalling the CPU | 1737 | * before signalling the CPU |
1646 | */ | 1738 | */ |
1647 | static uint32_t | 1739 | static void |
1648 | i915_retire_commands(struct drm_device *dev, struct intel_ring_buffer *ring) | 1740 | i915_retire_commands(struct drm_device *dev, struct intel_ring_buffer *ring) |
1649 | { | 1741 | { |
1650 | uint32_t flush_domains = 0; | 1742 | uint32_t flush_domains = 0; |
1651 | 1743 | ||
1652 | /* The sampler always gets flushed on i965 (sigh) */ | 1744 | /* The sampler always gets flushed on i965 (sigh) */ |
1653 | if (IS_I965G(dev)) | 1745 | if (INTEL_INFO(dev)->gen >= 4) |
1654 | flush_domains |= I915_GEM_DOMAIN_SAMPLER; | 1746 | flush_domains |= I915_GEM_DOMAIN_SAMPLER; |
1655 | 1747 | ||
1656 | ring->flush(dev, ring, | 1748 | ring->flush(dev, ring, |
1657 | I915_GEM_DOMAIN_COMMAND, flush_domains); | 1749 | I915_GEM_DOMAIN_COMMAND, flush_domains); |
1658 | return flush_domains; | ||
1659 | } | 1750 | } |
1660 | 1751 | ||
1661 | /** | 1752 | static inline void |
1662 | * Moves buffers associated only with the given active seqno from the active | 1753 | i915_gem_request_remove_from_client(struct drm_i915_gem_request *request) |
1663 | * to inactive list, potentially freeing them. | ||
1664 | */ | ||
1665 | static void | ||
1666 | i915_gem_retire_request(struct drm_device *dev, | ||
1667 | struct drm_i915_gem_request *request) | ||
1668 | { | 1754 | { |
1669 | drm_i915_private_t *dev_priv = dev->dev_private; | 1755 | struct drm_i915_file_private *file_priv = request->file_priv; |
1670 | 1756 | ||
1671 | trace_i915_gem_request_retire(dev, request->seqno); | 1757 | if (!file_priv) |
1758 | return; | ||
1672 | 1759 | ||
1673 | /* Move any buffers on the active list that are no longer referenced | 1760 | spin_lock(&file_priv->mm.lock); |
1674 | * by the ringbuffer to the flushing/inactive lists as appropriate. | 1761 | list_del(&request->client_list); |
1675 | */ | 1762 | request->file_priv = NULL; |
1676 | spin_lock(&dev_priv->mm.active_list_lock); | 1763 | spin_unlock(&file_priv->mm.lock); |
1677 | while (!list_empty(&request->ring->active_list)) { | 1764 | } |
1678 | struct drm_gem_object *obj; | ||
1679 | struct drm_i915_gem_object *obj_priv; | ||
1680 | 1765 | ||
1681 | obj_priv = list_first_entry(&request->ring->active_list, | 1766 | static void i915_gem_reset_ring_lists(struct drm_i915_private *dev_priv, |
1682 | struct drm_i915_gem_object, | 1767 | struct intel_ring_buffer *ring) |
1683 | list); | 1768 | { |
1684 | obj = &obj_priv->base; | 1769 | while (!list_empty(&ring->request_list)) { |
1770 | struct drm_i915_gem_request *request; | ||
1685 | 1771 | ||
1686 | /* If the seqno being retired doesn't match the oldest in the | 1772 | request = list_first_entry(&ring->request_list, |
1687 | * list, then the oldest in the list must still be newer than | 1773 | struct drm_i915_gem_request, |
1688 | * this seqno. | 1774 | list); |
1689 | */ | ||
1690 | if (obj_priv->last_rendering_seqno != request->seqno) | ||
1691 | goto out; | ||
1692 | 1775 | ||
1693 | #if WATCH_LRU | 1776 | list_del(&request->list); |
1694 | DRM_INFO("%s: retire %d moves to inactive list %p\n", | 1777 | i915_gem_request_remove_from_client(request); |
1695 | __func__, request->seqno, obj); | 1778 | kfree(request); |
1696 | #endif | 1779 | } |
1697 | 1780 | ||
1698 | if (obj->write_domain != 0) | 1781 | while (!list_empty(&ring->active_list)) { |
1699 | i915_gem_object_move_to_flushing(obj); | 1782 | struct drm_i915_gem_object *obj_priv; |
1700 | else { | 1783 | |
1701 | /* Take a reference on the object so it won't be | 1784 | obj_priv = list_first_entry(&ring->active_list, |
1702 | * freed while the spinlock is held. The list | 1785 | struct drm_i915_gem_object, |
1703 | * protection for this spinlock is safe when breaking | 1786 | ring_list); |
1704 | * the lock like this since the next thing we do | 1787 | |
1705 | * is just get the head of the list again. | 1788 | obj_priv->base.write_domain = 0; |
1706 | */ | 1789 | list_del_init(&obj_priv->gpu_write_list); |
1707 | drm_gem_object_reference(obj); | 1790 | i915_gem_object_move_to_inactive(&obj_priv->base); |
1708 | i915_gem_object_move_to_inactive(obj); | ||
1709 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
1710 | drm_gem_object_unreference(obj); | ||
1711 | spin_lock(&dev_priv->mm.active_list_lock); | ||
1712 | } | ||
1713 | } | 1791 | } |
1714 | out: | ||
1715 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
1716 | } | 1792 | } |
1717 | 1793 | ||
1718 | /** | 1794 | void i915_gem_reset(struct drm_device *dev) |
1719 | * Returns true if seq1 is later than seq2. | ||
1720 | */ | ||
1721 | bool | ||
1722 | i915_seqno_passed(uint32_t seq1, uint32_t seq2) | ||
1723 | { | 1795 | { |
1724 | return (int32_t)(seq1 - seq2) >= 0; | 1796 | struct drm_i915_private *dev_priv = dev->dev_private; |
1725 | } | 1797 | struct drm_i915_gem_object *obj_priv; |
1798 | int i; | ||
1726 | 1799 | ||
1727 | uint32_t | 1800 | i915_gem_reset_ring_lists(dev_priv, &dev_priv->render_ring); |
1728 | i915_get_gem_seqno(struct drm_device *dev, | 1801 | i915_gem_reset_ring_lists(dev_priv, &dev_priv->bsd_ring); |
1729 | struct intel_ring_buffer *ring) | 1802 | i915_gem_reset_ring_lists(dev_priv, &dev_priv->blt_ring); |
1730 | { | 1803 | |
1731 | return ring->get_gem_seqno(dev, ring); | 1804 | /* Remove anything from the flushing lists. The GPU cache is likely |
1805 | * to be lost on reset along with the data, so simply move the | ||
1806 | * lost bo to the inactive list. | ||
1807 | */ | ||
1808 | while (!list_empty(&dev_priv->mm.flushing_list)) { | ||
1809 | obj_priv = list_first_entry(&dev_priv->mm.flushing_list, | ||
1810 | struct drm_i915_gem_object, | ||
1811 | mm_list); | ||
1812 | |||
1813 | obj_priv->base.write_domain = 0; | ||
1814 | list_del_init(&obj_priv->gpu_write_list); | ||
1815 | i915_gem_object_move_to_inactive(&obj_priv->base); | ||
1816 | } | ||
1817 | |||
1818 | /* Move everything out of the GPU domains to ensure we do any | ||
1819 | * necessary invalidation upon reuse. | ||
1820 | */ | ||
1821 | list_for_each_entry(obj_priv, | ||
1822 | &dev_priv->mm.inactive_list, | ||
1823 | mm_list) | ||
1824 | { | ||
1825 | obj_priv->base.read_domains &= ~I915_GEM_GPU_DOMAINS; | ||
1826 | } | ||
1827 | |||
1828 | /* The fence registers are invalidated so clear them out */ | ||
1829 | for (i = 0; i < 16; i++) { | ||
1830 | struct drm_i915_fence_reg *reg; | ||
1831 | |||
1832 | reg = &dev_priv->fence_regs[i]; | ||
1833 | if (!reg->obj) | ||
1834 | continue; | ||
1835 | |||
1836 | i915_gem_clear_fence_reg(reg->obj); | ||
1837 | } | ||
1732 | } | 1838 | } |
1733 | 1839 | ||
1734 | /** | 1840 | /** |
@@ -1741,38 +1847,58 @@ i915_gem_retire_requests_ring(struct drm_device *dev, | |||
1741 | drm_i915_private_t *dev_priv = dev->dev_private; | 1847 | drm_i915_private_t *dev_priv = dev->dev_private; |
1742 | uint32_t seqno; | 1848 | uint32_t seqno; |
1743 | 1849 | ||
1744 | if (!ring->status_page.page_addr | 1850 | if (!ring->status_page.page_addr || |
1745 | || list_empty(&ring->request_list)) | 1851 | list_empty(&ring->request_list)) |
1746 | return; | 1852 | return; |
1747 | 1853 | ||
1748 | seqno = i915_get_gem_seqno(dev, ring); | 1854 | WARN_ON(i915_verify_lists(dev)); |
1749 | 1855 | ||
1856 | seqno = ring->get_seqno(dev, ring); | ||
1750 | while (!list_empty(&ring->request_list)) { | 1857 | while (!list_empty(&ring->request_list)) { |
1751 | struct drm_i915_gem_request *request; | 1858 | struct drm_i915_gem_request *request; |
1752 | uint32_t retiring_seqno; | ||
1753 | 1859 | ||
1754 | request = list_first_entry(&ring->request_list, | 1860 | request = list_first_entry(&ring->request_list, |
1755 | struct drm_i915_gem_request, | 1861 | struct drm_i915_gem_request, |
1756 | list); | 1862 | list); |
1757 | retiring_seqno = request->seqno; | ||
1758 | 1863 | ||
1759 | if (i915_seqno_passed(seqno, retiring_seqno) || | 1864 | if (!i915_seqno_passed(seqno, request->seqno)) |
1760 | atomic_read(&dev_priv->mm.wedged)) { | 1865 | break; |
1761 | i915_gem_retire_request(dev, request); | 1866 | |
1867 | trace_i915_gem_request_retire(dev, request->seqno); | ||
1868 | |||
1869 | list_del(&request->list); | ||
1870 | i915_gem_request_remove_from_client(request); | ||
1871 | kfree(request); | ||
1872 | } | ||
1873 | |||
1874 | /* Move any buffers on the active list that are no longer referenced | ||
1875 | * by the ringbuffer to the flushing/inactive lists as appropriate. | ||
1876 | */ | ||
1877 | while (!list_empty(&ring->active_list)) { | ||
1878 | struct drm_gem_object *obj; | ||
1879 | struct drm_i915_gem_object *obj_priv; | ||
1880 | |||
1881 | obj_priv = list_first_entry(&ring->active_list, | ||
1882 | struct drm_i915_gem_object, | ||
1883 | ring_list); | ||
1762 | 1884 | ||
1763 | list_del(&request->list); | 1885 | if (!i915_seqno_passed(seqno, obj_priv->last_rendering_seqno)) |
1764 | list_del(&request->client_list); | ||
1765 | kfree(request); | ||
1766 | } else | ||
1767 | break; | 1886 | break; |
1887 | |||
1888 | obj = &obj_priv->base; | ||
1889 | if (obj->write_domain != 0) | ||
1890 | i915_gem_object_move_to_flushing(obj); | ||
1891 | else | ||
1892 | i915_gem_object_move_to_inactive(obj); | ||
1768 | } | 1893 | } |
1769 | 1894 | ||
1770 | if (unlikely (dev_priv->trace_irq_seqno && | 1895 | if (unlikely (dev_priv->trace_irq_seqno && |
1771 | i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) { | 1896 | i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) { |
1772 | |||
1773 | ring->user_irq_put(dev, ring); | 1897 | ring->user_irq_put(dev, ring); |
1774 | dev_priv->trace_irq_seqno = 0; | 1898 | dev_priv->trace_irq_seqno = 0; |
1775 | } | 1899 | } |
1900 | |||
1901 | WARN_ON(i915_verify_lists(dev)); | ||
1776 | } | 1902 | } |
1777 | 1903 | ||
1778 | void | 1904 | void |
@@ -1790,16 +1916,16 @@ i915_gem_retire_requests(struct drm_device *dev) | |||
1790 | */ | 1916 | */ |
1791 | list_for_each_entry_safe(obj_priv, tmp, | 1917 | list_for_each_entry_safe(obj_priv, tmp, |
1792 | &dev_priv->mm.deferred_free_list, | 1918 | &dev_priv->mm.deferred_free_list, |
1793 | list) | 1919 | mm_list) |
1794 | i915_gem_free_object_tail(&obj_priv->base); | 1920 | i915_gem_free_object_tail(&obj_priv->base); |
1795 | } | 1921 | } |
1796 | 1922 | ||
1797 | i915_gem_retire_requests_ring(dev, &dev_priv->render_ring); | 1923 | i915_gem_retire_requests_ring(dev, &dev_priv->render_ring); |
1798 | if (HAS_BSD(dev)) | 1924 | i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring); |
1799 | i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring); | 1925 | i915_gem_retire_requests_ring(dev, &dev_priv->blt_ring); |
1800 | } | 1926 | } |
1801 | 1927 | ||
1802 | void | 1928 | static void |
1803 | i915_gem_retire_work_handler(struct work_struct *work) | 1929 | i915_gem_retire_work_handler(struct work_struct *work) |
1804 | { | 1930 | { |
1805 | drm_i915_private_t *dev_priv; | 1931 | drm_i915_private_t *dev_priv; |
@@ -1809,20 +1935,25 @@ i915_gem_retire_work_handler(struct work_struct *work) | |||
1809 | mm.retire_work.work); | 1935 | mm.retire_work.work); |
1810 | dev = dev_priv->dev; | 1936 | dev = dev_priv->dev; |
1811 | 1937 | ||
1812 | mutex_lock(&dev->struct_mutex); | 1938 | /* Come back later if the device is busy... */ |
1939 | if (!mutex_trylock(&dev->struct_mutex)) { | ||
1940 | queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); | ||
1941 | return; | ||
1942 | } | ||
1943 | |||
1813 | i915_gem_retire_requests(dev); | 1944 | i915_gem_retire_requests(dev); |
1814 | 1945 | ||
1815 | if (!dev_priv->mm.suspended && | 1946 | if (!dev_priv->mm.suspended && |
1816 | (!list_empty(&dev_priv->render_ring.request_list) || | 1947 | (!list_empty(&dev_priv->render_ring.request_list) || |
1817 | (HAS_BSD(dev) && | 1948 | !list_empty(&dev_priv->bsd_ring.request_list) || |
1818 | !list_empty(&dev_priv->bsd_ring.request_list)))) | 1949 | !list_empty(&dev_priv->blt_ring.request_list))) |
1819 | queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); | 1950 | queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, HZ); |
1820 | mutex_unlock(&dev->struct_mutex); | 1951 | mutex_unlock(&dev->struct_mutex); |
1821 | } | 1952 | } |
1822 | 1953 | ||
1823 | int | 1954 | int |
1824 | i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | 1955 | i915_do_wait_request(struct drm_device *dev, uint32_t seqno, |
1825 | int interruptible, struct intel_ring_buffer *ring) | 1956 | bool interruptible, struct intel_ring_buffer *ring) |
1826 | { | 1957 | { |
1827 | drm_i915_private_t *dev_priv = dev->dev_private; | 1958 | drm_i915_private_t *dev_priv = dev->dev_private; |
1828 | u32 ier; | 1959 | u32 ier; |
@@ -1831,9 +1962,16 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | |||
1831 | BUG_ON(seqno == 0); | 1962 | BUG_ON(seqno == 0); |
1832 | 1963 | ||
1833 | if (atomic_read(&dev_priv->mm.wedged)) | 1964 | if (atomic_read(&dev_priv->mm.wedged)) |
1834 | return -EIO; | 1965 | return -EAGAIN; |
1835 | 1966 | ||
1836 | if (!i915_seqno_passed(ring->get_gem_seqno(dev, ring), seqno)) { | 1967 | if (ring->outstanding_lazy_request) { |
1968 | seqno = i915_add_request(dev, NULL, NULL, ring); | ||
1969 | if (seqno == 0) | ||
1970 | return -ENOMEM; | ||
1971 | } | ||
1972 | BUG_ON(seqno == dev_priv->next_seqno); | ||
1973 | |||
1974 | if (!i915_seqno_passed(ring->get_seqno(dev, ring), seqno)) { | ||
1837 | if (HAS_PCH_SPLIT(dev)) | 1975 | if (HAS_PCH_SPLIT(dev)) |
1838 | ier = I915_READ(DEIER) | I915_READ(GTIER); | 1976 | ier = I915_READ(DEIER) | I915_READ(GTIER); |
1839 | else | 1977 | else |
@@ -1852,12 +1990,12 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | |||
1852 | if (interruptible) | 1990 | if (interruptible) |
1853 | ret = wait_event_interruptible(ring->irq_queue, | 1991 | ret = wait_event_interruptible(ring->irq_queue, |
1854 | i915_seqno_passed( | 1992 | i915_seqno_passed( |
1855 | ring->get_gem_seqno(dev, ring), seqno) | 1993 | ring->get_seqno(dev, ring), seqno) |
1856 | || atomic_read(&dev_priv->mm.wedged)); | 1994 | || atomic_read(&dev_priv->mm.wedged)); |
1857 | else | 1995 | else |
1858 | wait_event(ring->irq_queue, | 1996 | wait_event(ring->irq_queue, |
1859 | i915_seqno_passed( | 1997 | i915_seqno_passed( |
1860 | ring->get_gem_seqno(dev, ring), seqno) | 1998 | ring->get_seqno(dev, ring), seqno) |
1861 | || atomic_read(&dev_priv->mm.wedged)); | 1999 | || atomic_read(&dev_priv->mm.wedged)); |
1862 | 2000 | ||
1863 | ring->user_irq_put(dev, ring); | 2001 | ring->user_irq_put(dev, ring); |
@@ -1866,11 +2004,12 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | |||
1866 | trace_i915_gem_request_wait_end(dev, seqno); | 2004 | trace_i915_gem_request_wait_end(dev, seqno); |
1867 | } | 2005 | } |
1868 | if (atomic_read(&dev_priv->mm.wedged)) | 2006 | if (atomic_read(&dev_priv->mm.wedged)) |
1869 | ret = -EIO; | 2007 | ret = -EAGAIN; |
1870 | 2008 | ||
1871 | if (ret && ret != -ERESTARTSYS) | 2009 | if (ret && ret != -ERESTARTSYS) |
1872 | DRM_ERROR("%s returns %d (awaiting %d at %d)\n", | 2010 | DRM_ERROR("%s returns %d (awaiting %d at %d, next %d)\n", |
1873 | __func__, ret, seqno, ring->get_gem_seqno(dev, ring)); | 2011 | __func__, ret, seqno, ring->get_seqno(dev, ring), |
2012 | dev_priv->next_seqno); | ||
1874 | 2013 | ||
1875 | /* Directly dispatch request retiring. While we have the work queue | 2014 | /* Directly dispatch request retiring. While we have the work queue |
1876 | * to handle this, the waiter on a request often wants an associated | 2015 | * to handle this, the waiter on a request often wants an associated |
@@ -1889,27 +2028,48 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno, | |||
1889 | */ | 2028 | */ |
1890 | static int | 2029 | static int |
1891 | i915_wait_request(struct drm_device *dev, uint32_t seqno, | 2030 | i915_wait_request(struct drm_device *dev, uint32_t seqno, |
1892 | struct intel_ring_buffer *ring) | 2031 | struct intel_ring_buffer *ring) |
1893 | { | 2032 | { |
1894 | return i915_do_wait_request(dev, seqno, 1, ring); | 2033 | return i915_do_wait_request(dev, seqno, 1, ring); |
1895 | } | 2034 | } |
1896 | 2035 | ||
1897 | static void | 2036 | static void |
2037 | i915_gem_flush_ring(struct drm_device *dev, | ||
2038 | struct drm_file *file_priv, | ||
2039 | struct intel_ring_buffer *ring, | ||
2040 | uint32_t invalidate_domains, | ||
2041 | uint32_t flush_domains) | ||
2042 | { | ||
2043 | ring->flush(dev, ring, invalidate_domains, flush_domains); | ||
2044 | i915_gem_process_flushing_list(dev, flush_domains, ring); | ||
2045 | } | ||
2046 | |||
2047 | static void | ||
1898 | i915_gem_flush(struct drm_device *dev, | 2048 | i915_gem_flush(struct drm_device *dev, |
2049 | struct drm_file *file_priv, | ||
1899 | uint32_t invalidate_domains, | 2050 | uint32_t invalidate_domains, |
1900 | uint32_t flush_domains) | 2051 | uint32_t flush_domains, |
2052 | uint32_t flush_rings) | ||
1901 | { | 2053 | { |
1902 | drm_i915_private_t *dev_priv = dev->dev_private; | 2054 | drm_i915_private_t *dev_priv = dev->dev_private; |
2055 | |||
1903 | if (flush_domains & I915_GEM_DOMAIN_CPU) | 2056 | if (flush_domains & I915_GEM_DOMAIN_CPU) |
1904 | drm_agp_chipset_flush(dev); | 2057 | drm_agp_chipset_flush(dev); |
1905 | dev_priv->render_ring.flush(dev, &dev_priv->render_ring, | 2058 | |
1906 | invalidate_domains, | 2059 | if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) { |
1907 | flush_domains); | 2060 | if (flush_rings & RING_RENDER) |
1908 | 2061 | i915_gem_flush_ring(dev, file_priv, | |
1909 | if (HAS_BSD(dev)) | 2062 | &dev_priv->render_ring, |
1910 | dev_priv->bsd_ring.flush(dev, &dev_priv->bsd_ring, | 2063 | invalidate_domains, flush_domains); |
1911 | invalidate_domains, | 2064 | if (flush_rings & RING_BSD) |
1912 | flush_domains); | 2065 | i915_gem_flush_ring(dev, file_priv, |
2066 | &dev_priv->bsd_ring, | ||
2067 | invalidate_domains, flush_domains); | ||
2068 | if (flush_rings & RING_BLT) | ||
2069 | i915_gem_flush_ring(dev, file_priv, | ||
2070 | &dev_priv->blt_ring, | ||
2071 | invalidate_domains, flush_domains); | ||
2072 | } | ||
1913 | } | 2073 | } |
1914 | 2074 | ||
1915 | /** | 2075 | /** |
@@ -1917,7 +2077,8 @@ i915_gem_flush(struct drm_device *dev, | |||
1917 | * safe to unbind from the GTT or access from the CPU. | 2077 | * safe to unbind from the GTT or access from the CPU. |
1918 | */ | 2078 | */ |
1919 | static int | 2079 | static int |
1920 | i915_gem_object_wait_rendering(struct drm_gem_object *obj) | 2080 | i915_gem_object_wait_rendering(struct drm_gem_object *obj, |
2081 | bool interruptible) | ||
1921 | { | 2082 | { |
1922 | struct drm_device *dev = obj->dev; | 2083 | struct drm_device *dev = obj->dev; |
1923 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 2084 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
@@ -1932,13 +2093,11 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj) | |||
1932 | * it. | 2093 | * it. |
1933 | */ | 2094 | */ |
1934 | if (obj_priv->active) { | 2095 | if (obj_priv->active) { |
1935 | #if WATCH_BUF | 2096 | ret = i915_do_wait_request(dev, |
1936 | DRM_INFO("%s: object %p wait for seqno %08x\n", | 2097 | obj_priv->last_rendering_seqno, |
1937 | __func__, obj, obj_priv->last_rendering_seqno); | 2098 | interruptible, |
1938 | #endif | 2099 | obj_priv->ring); |
1939 | ret = i915_wait_request(dev, | 2100 | if (ret) |
1940 | obj_priv->last_rendering_seqno, obj_priv->ring); | ||
1941 | if (ret != 0) | ||
1942 | return ret; | 2101 | return ret; |
1943 | } | 2102 | } |
1944 | 2103 | ||
@@ -1952,14 +2111,10 @@ int | |||
1952 | i915_gem_object_unbind(struct drm_gem_object *obj) | 2111 | i915_gem_object_unbind(struct drm_gem_object *obj) |
1953 | { | 2112 | { |
1954 | struct drm_device *dev = obj->dev; | 2113 | struct drm_device *dev = obj->dev; |
1955 | drm_i915_private_t *dev_priv = dev->dev_private; | 2114 | struct drm_i915_private *dev_priv = dev->dev_private; |
1956 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 2115 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
1957 | int ret = 0; | 2116 | int ret = 0; |
1958 | 2117 | ||
1959 | #if WATCH_BUF | ||
1960 | DRM_INFO("%s:%d %p\n", __func__, __LINE__, obj); | ||
1961 | DRM_INFO("gtt_space %p\n", obj_priv->gtt_space); | ||
1962 | #endif | ||
1963 | if (obj_priv->gtt_space == NULL) | 2118 | if (obj_priv->gtt_space == NULL) |
1964 | return 0; | 2119 | return 0; |
1965 | 2120 | ||
@@ -1984,33 +2139,27 @@ i915_gem_object_unbind(struct drm_gem_object *obj) | |||
1984 | * should be safe and we need to cleanup or else we might | 2139 | * should be safe and we need to cleanup or else we might |
1985 | * cause memory corruption through use-after-free. | 2140 | * cause memory corruption through use-after-free. |
1986 | */ | 2141 | */ |
2142 | if (ret) { | ||
2143 | i915_gem_clflush_object(obj); | ||
2144 | obj->read_domains = obj->write_domain = I915_GEM_DOMAIN_CPU; | ||
2145 | } | ||
1987 | 2146 | ||
1988 | /* release the fence reg _after_ flushing */ | 2147 | /* release the fence reg _after_ flushing */ |
1989 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) | 2148 | if (obj_priv->fence_reg != I915_FENCE_REG_NONE) |
1990 | i915_gem_clear_fence_reg(obj); | 2149 | i915_gem_clear_fence_reg(obj); |
1991 | 2150 | ||
1992 | if (obj_priv->agp_mem != NULL) { | 2151 | drm_unbind_agp(obj_priv->agp_mem); |
1993 | drm_unbind_agp(obj_priv->agp_mem); | 2152 | drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE); |
1994 | drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE); | ||
1995 | obj_priv->agp_mem = NULL; | ||
1996 | } | ||
1997 | 2153 | ||
1998 | i915_gem_object_put_pages(obj); | 2154 | i915_gem_object_put_pages(obj); |
1999 | BUG_ON(obj_priv->pages_refcount); | 2155 | BUG_ON(obj_priv->pages_refcount); |
2000 | 2156 | ||
2001 | if (obj_priv->gtt_space) { | 2157 | i915_gem_info_remove_gtt(dev_priv, obj->size); |
2002 | atomic_dec(&dev->gtt_count); | 2158 | list_del_init(&obj_priv->mm_list); |
2003 | atomic_sub(obj->size, &dev->gtt_memory); | ||
2004 | |||
2005 | drm_mm_put_block(obj_priv->gtt_space); | ||
2006 | obj_priv->gtt_space = NULL; | ||
2007 | } | ||
2008 | 2159 | ||
2009 | /* Remove ourselves from the LRU list if present. */ | 2160 | drm_mm_put_block(obj_priv->gtt_space); |
2010 | spin_lock(&dev_priv->mm.active_list_lock); | 2161 | obj_priv->gtt_space = NULL; |
2011 | if (!list_empty(&obj_priv->list)) | 2162 | obj_priv->gtt_offset = 0; |
2012 | list_del_init(&obj_priv->list); | ||
2013 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
2014 | 2163 | ||
2015 | if (i915_gem_object_is_purgeable(obj_priv)) | 2164 | if (i915_gem_object_is_purgeable(obj_priv)) |
2016 | i915_gem_object_truncate(obj); | 2165 | i915_gem_object_truncate(obj); |
@@ -2020,48 +2169,50 @@ i915_gem_object_unbind(struct drm_gem_object *obj) | |||
2020 | return ret; | 2169 | return ret; |
2021 | } | 2170 | } |
2022 | 2171 | ||
2172 | static int i915_ring_idle(struct drm_device *dev, | ||
2173 | struct intel_ring_buffer *ring) | ||
2174 | { | ||
2175 | if (list_empty(&ring->gpu_write_list)) | ||
2176 | return 0; | ||
2177 | |||
2178 | i915_gem_flush_ring(dev, NULL, ring, | ||
2179 | I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); | ||
2180 | return i915_wait_request(dev, | ||
2181 | i915_gem_next_request_seqno(dev, ring), | ||
2182 | ring); | ||
2183 | } | ||
2184 | |||
2023 | int | 2185 | int |
2024 | i915_gpu_idle(struct drm_device *dev) | 2186 | i915_gpu_idle(struct drm_device *dev) |
2025 | { | 2187 | { |
2026 | drm_i915_private_t *dev_priv = dev->dev_private; | 2188 | drm_i915_private_t *dev_priv = dev->dev_private; |
2027 | bool lists_empty; | 2189 | bool lists_empty; |
2028 | uint32_t seqno1, seqno2; | ||
2029 | int ret; | 2190 | int ret; |
2030 | 2191 | ||
2031 | spin_lock(&dev_priv->mm.active_list_lock); | ||
2032 | lists_empty = (list_empty(&dev_priv->mm.flushing_list) && | 2192 | lists_empty = (list_empty(&dev_priv->mm.flushing_list) && |
2033 | list_empty(&dev_priv->render_ring.active_list) && | 2193 | list_empty(&dev_priv->render_ring.active_list) && |
2034 | (!HAS_BSD(dev) || | 2194 | list_empty(&dev_priv->bsd_ring.active_list) && |
2035 | list_empty(&dev_priv->bsd_ring.active_list))); | 2195 | list_empty(&dev_priv->blt_ring.active_list)); |
2036 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
2037 | |||
2038 | if (lists_empty) | 2196 | if (lists_empty) |
2039 | return 0; | 2197 | return 0; |
2040 | 2198 | ||
2041 | /* Flush everything onto the inactive list. */ | 2199 | /* Flush everything onto the inactive list. */ |
2042 | i915_gem_flush(dev, I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS); | 2200 | ret = i915_ring_idle(dev, &dev_priv->render_ring); |
2043 | seqno1 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS, | 2201 | if (ret) |
2044 | &dev_priv->render_ring); | 2202 | return ret; |
2045 | if (seqno1 == 0) | ||
2046 | return -ENOMEM; | ||
2047 | ret = i915_wait_request(dev, seqno1, &dev_priv->render_ring); | ||
2048 | |||
2049 | if (HAS_BSD(dev)) { | ||
2050 | seqno2 = i915_add_request(dev, NULL, I915_GEM_GPU_DOMAINS, | ||
2051 | &dev_priv->bsd_ring); | ||
2052 | if (seqno2 == 0) | ||
2053 | return -ENOMEM; | ||
2054 | 2203 | ||
2055 | ret = i915_wait_request(dev, seqno2, &dev_priv->bsd_ring); | 2204 | ret = i915_ring_idle(dev, &dev_priv->bsd_ring); |
2056 | if (ret) | 2205 | if (ret) |
2057 | return ret; | 2206 | return ret; |
2058 | } | ||
2059 | 2207 | ||
2208 | ret = i915_ring_idle(dev, &dev_priv->blt_ring); | ||
2209 | if (ret) | ||
2210 | return ret; | ||
2060 | 2211 | ||
2061 | return ret; | 2212 | return 0; |
2062 | } | 2213 | } |
2063 | 2214 | ||
2064 | int | 2215 | static int |
2065 | i915_gem_object_get_pages(struct drm_gem_object *obj, | 2216 | i915_gem_object_get_pages(struct drm_gem_object *obj, |
2066 | gfp_t gfpmask) | 2217 | gfp_t gfpmask) |
2067 | { | 2218 | { |
@@ -2241,7 +2392,8 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
2241 | I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); | 2392 | I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); |
2242 | } | 2393 | } |
2243 | 2394 | ||
2244 | static int i915_find_fence_reg(struct drm_device *dev) | 2395 | static int i915_find_fence_reg(struct drm_device *dev, |
2396 | bool interruptible) | ||
2245 | { | 2397 | { |
2246 | struct drm_i915_fence_reg *reg = NULL; | 2398 | struct drm_i915_fence_reg *reg = NULL; |
2247 | struct drm_i915_gem_object *obj_priv = NULL; | 2399 | struct drm_i915_gem_object *obj_priv = NULL; |
@@ -2286,7 +2438,7 @@ static int i915_find_fence_reg(struct drm_device *dev) | |||
2286 | * private reference to obj like the other callers of put_fence_reg | 2438 | * private reference to obj like the other callers of put_fence_reg |
2287 | * (set_tiling ioctl) do. */ | 2439 | * (set_tiling ioctl) do. */ |
2288 | drm_gem_object_reference(obj); | 2440 | drm_gem_object_reference(obj); |
2289 | ret = i915_gem_object_put_fence_reg(obj); | 2441 | ret = i915_gem_object_put_fence_reg(obj, interruptible); |
2290 | drm_gem_object_unreference(obj); | 2442 | drm_gem_object_unreference(obj); |
2291 | if (ret != 0) | 2443 | if (ret != 0) |
2292 | return ret; | 2444 | return ret; |
@@ -2308,7 +2460,8 @@ static int i915_find_fence_reg(struct drm_device *dev) | |||
2308 | * and tiling format. | 2460 | * and tiling format. |
2309 | */ | 2461 | */ |
2310 | int | 2462 | int |
2311 | i915_gem_object_get_fence_reg(struct drm_gem_object *obj) | 2463 | i915_gem_object_get_fence_reg(struct drm_gem_object *obj, |
2464 | bool interruptible) | ||
2312 | { | 2465 | { |
2313 | struct drm_device *dev = obj->dev; | 2466 | struct drm_device *dev = obj->dev; |
2314 | struct drm_i915_private *dev_priv = dev->dev_private; | 2467 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -2343,7 +2496,7 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj) | |||
2343 | break; | 2496 | break; |
2344 | } | 2497 | } |
2345 | 2498 | ||
2346 | ret = i915_find_fence_reg(dev); | 2499 | ret = i915_find_fence_reg(dev, interruptible); |
2347 | if (ret < 0) | 2500 | if (ret < 0) |
2348 | return ret; | 2501 | return ret; |
2349 | 2502 | ||
@@ -2421,15 +2574,19 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj) | |||
2421 | * i915_gem_object_put_fence_reg - waits on outstanding fenced access | 2574 | * i915_gem_object_put_fence_reg - waits on outstanding fenced access |
2422 | * to the buffer to finish, and then resets the fence register. | 2575 | * to the buffer to finish, and then resets the fence register. |
2423 | * @obj: tiled object holding a fence register. | 2576 | * @obj: tiled object holding a fence register. |
2577 | * @bool: whether the wait upon the fence is interruptible | ||
2424 | * | 2578 | * |
2425 | * Zeroes out the fence register itself and clears out the associated | 2579 | * Zeroes out the fence register itself and clears out the associated |
2426 | * data structures in dev_priv and obj_priv. | 2580 | * data structures in dev_priv and obj_priv. |
2427 | */ | 2581 | */ |
2428 | int | 2582 | int |
2429 | i915_gem_object_put_fence_reg(struct drm_gem_object *obj) | 2583 | i915_gem_object_put_fence_reg(struct drm_gem_object *obj, |
2584 | bool interruptible) | ||
2430 | { | 2585 | { |
2431 | struct drm_device *dev = obj->dev; | 2586 | struct drm_device *dev = obj->dev; |
2587 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
2432 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 2588 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
2589 | struct drm_i915_fence_reg *reg; | ||
2433 | 2590 | ||
2434 | if (obj_priv->fence_reg == I915_FENCE_REG_NONE) | 2591 | if (obj_priv->fence_reg == I915_FENCE_REG_NONE) |
2435 | return 0; | 2592 | return 0; |
@@ -2444,20 +2601,23 @@ i915_gem_object_put_fence_reg(struct drm_gem_object *obj) | |||
2444 | * therefore we must wait for any outstanding access to complete | 2601 | * therefore we must wait for any outstanding access to complete |
2445 | * before clearing the fence. | 2602 | * before clearing the fence. |
2446 | */ | 2603 | */ |
2447 | if (!IS_I965G(dev)) { | 2604 | reg = &dev_priv->fence_regs[obj_priv->fence_reg]; |
2605 | if (reg->gpu) { | ||
2448 | int ret; | 2606 | int ret; |
2449 | 2607 | ||
2450 | ret = i915_gem_object_flush_gpu_write_domain(obj); | 2608 | ret = i915_gem_object_flush_gpu_write_domain(obj, true); |
2451 | if (ret != 0) | 2609 | if (ret) |
2452 | return ret; | 2610 | return ret; |
2453 | 2611 | ||
2454 | ret = i915_gem_object_wait_rendering(obj); | 2612 | ret = i915_gem_object_wait_rendering(obj, interruptible); |
2455 | if (ret != 0) | 2613 | if (ret) |
2456 | return ret; | 2614 | return ret; |
2615 | |||
2616 | reg->gpu = false; | ||
2457 | } | 2617 | } |
2458 | 2618 | ||
2459 | i915_gem_object_flush_gtt_write_domain(obj); | 2619 | i915_gem_object_flush_gtt_write_domain(obj); |
2460 | i915_gem_clear_fence_reg (obj); | 2620 | i915_gem_clear_fence_reg(obj); |
2461 | 2621 | ||
2462 | return 0; | 2622 | return 0; |
2463 | } | 2623 | } |
@@ -2490,7 +2650,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2490 | /* If the object is bigger than the entire aperture, reject it early | 2650 | /* If the object is bigger than the entire aperture, reject it early |
2491 | * before evicting everything in a vain attempt to find space. | 2651 | * before evicting everything in a vain attempt to find space. |
2492 | */ | 2652 | */ |
2493 | if (obj->size > dev->gtt_total) { | 2653 | if (obj->size > dev_priv->mm.gtt_total) { |
2494 | DRM_ERROR("Attempting to bind an object larger than the aperture\n"); | 2654 | DRM_ERROR("Attempting to bind an object larger than the aperture\n"); |
2495 | return -E2BIG; | 2655 | return -E2BIG; |
2496 | } | 2656 | } |
@@ -2498,19 +2658,13 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2498 | search_free: | 2658 | search_free: |
2499 | free_space = drm_mm_search_free(&dev_priv->mm.gtt_space, | 2659 | free_space = drm_mm_search_free(&dev_priv->mm.gtt_space, |
2500 | obj->size, alignment, 0); | 2660 | obj->size, alignment, 0); |
2501 | if (free_space != NULL) { | 2661 | if (free_space != NULL) |
2502 | obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size, | 2662 | obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size, |
2503 | alignment); | 2663 | alignment); |
2504 | if (obj_priv->gtt_space != NULL) | ||
2505 | obj_priv->gtt_offset = obj_priv->gtt_space->start; | ||
2506 | } | ||
2507 | if (obj_priv->gtt_space == NULL) { | 2664 | if (obj_priv->gtt_space == NULL) { |
2508 | /* If the gtt is empty and we're still having trouble | 2665 | /* If the gtt is empty and we're still having trouble |
2509 | * fitting our object in, we're out of memory. | 2666 | * fitting our object in, we're out of memory. |
2510 | */ | 2667 | */ |
2511 | #if WATCH_LRU | ||
2512 | DRM_INFO("%s: GTT full, evicting something\n", __func__); | ||
2513 | #endif | ||
2514 | ret = i915_gem_evict_something(dev, obj->size, alignment); | 2668 | ret = i915_gem_evict_something(dev, obj->size, alignment); |
2515 | if (ret) | 2669 | if (ret) |
2516 | return ret; | 2670 | return ret; |
@@ -2518,10 +2672,6 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2518 | goto search_free; | 2672 | goto search_free; |
2519 | } | 2673 | } |
2520 | 2674 | ||
2521 | #if WATCH_BUF | ||
2522 | DRM_INFO("Binding object of size %zd at 0x%08x\n", | ||
2523 | obj->size, obj_priv->gtt_offset); | ||
2524 | #endif | ||
2525 | ret = i915_gem_object_get_pages(obj, gfpmask); | 2675 | ret = i915_gem_object_get_pages(obj, gfpmask); |
2526 | if (ret) { | 2676 | if (ret) { |
2527 | drm_mm_put_block(obj_priv->gtt_space); | 2677 | drm_mm_put_block(obj_priv->gtt_space); |
@@ -2553,7 +2703,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2553 | obj_priv->agp_mem = drm_agp_bind_pages(dev, | 2703 | obj_priv->agp_mem = drm_agp_bind_pages(dev, |
2554 | obj_priv->pages, | 2704 | obj_priv->pages, |
2555 | obj->size >> PAGE_SHIFT, | 2705 | obj->size >> PAGE_SHIFT, |
2556 | obj_priv->gtt_offset, | 2706 | obj_priv->gtt_space->start, |
2557 | obj_priv->agp_type); | 2707 | obj_priv->agp_type); |
2558 | if (obj_priv->agp_mem == NULL) { | 2708 | if (obj_priv->agp_mem == NULL) { |
2559 | i915_gem_object_put_pages(obj); | 2709 | i915_gem_object_put_pages(obj); |
@@ -2566,11 +2716,10 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2566 | 2716 | ||
2567 | goto search_free; | 2717 | goto search_free; |
2568 | } | 2718 | } |
2569 | atomic_inc(&dev->gtt_count); | ||
2570 | atomic_add(obj->size, &dev->gtt_memory); | ||
2571 | 2719 | ||
2572 | /* keep track of bounds object by adding it to the inactive list */ | 2720 | /* keep track of bounds object by adding it to the inactive list */ |
2573 | list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list); | 2721 | list_add_tail(&obj_priv->mm_list, &dev_priv->mm.inactive_list); |
2722 | i915_gem_info_add_gtt(dev_priv, obj->size); | ||
2574 | 2723 | ||
2575 | /* Assert that the object is not currently in any GPU domain. As it | 2724 | /* Assert that the object is not currently in any GPU domain. As it |
2576 | * wasn't in the GTT, there shouldn't be any way it could have been in | 2725 | * wasn't in the GTT, there shouldn't be any way it could have been in |
@@ -2579,6 +2728,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
2579 | BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS); | 2728 | BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS); |
2580 | BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS); | 2729 | BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS); |
2581 | 2730 | ||
2731 | obj_priv->gtt_offset = obj_priv->gtt_space->start; | ||
2582 | trace_i915_gem_object_bind(obj, obj_priv->gtt_offset); | 2732 | trace_i915_gem_object_bind(obj, obj_priv->gtt_offset); |
2583 | 2733 | ||
2584 | return 0; | 2734 | return 0; |
@@ -2603,25 +2753,30 @@ i915_gem_clflush_object(struct drm_gem_object *obj) | |||
2603 | 2753 | ||
2604 | /** Flushes any GPU write domain for the object if it's dirty. */ | 2754 | /** Flushes any GPU write domain for the object if it's dirty. */ |
2605 | static int | 2755 | static int |
2606 | i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj) | 2756 | i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj, |
2757 | bool pipelined) | ||
2607 | { | 2758 | { |
2608 | struct drm_device *dev = obj->dev; | 2759 | struct drm_device *dev = obj->dev; |
2609 | uint32_t old_write_domain; | 2760 | uint32_t old_write_domain; |
2610 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | ||
2611 | 2761 | ||
2612 | if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) | 2762 | if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) |
2613 | return 0; | 2763 | return 0; |
2614 | 2764 | ||
2615 | /* Queue the GPU write cache flushing we need. */ | 2765 | /* Queue the GPU write cache flushing we need. */ |
2616 | old_write_domain = obj->write_domain; | 2766 | old_write_domain = obj->write_domain; |
2617 | i915_gem_flush(dev, 0, obj->write_domain); | 2767 | i915_gem_flush_ring(dev, NULL, |
2618 | if (i915_add_request(dev, NULL, obj->write_domain, obj_priv->ring) == 0) | 2768 | to_intel_bo(obj)->ring, |
2619 | return -ENOMEM; | 2769 | 0, obj->write_domain); |
2770 | BUG_ON(obj->write_domain); | ||
2620 | 2771 | ||
2621 | trace_i915_gem_object_change_domain(obj, | 2772 | trace_i915_gem_object_change_domain(obj, |
2622 | obj->read_domains, | 2773 | obj->read_domains, |
2623 | old_write_domain); | 2774 | old_write_domain); |
2624 | return 0; | 2775 | |
2776 | if (pipelined) | ||
2777 | return 0; | ||
2778 | |||
2779 | return i915_gem_object_wait_rendering(obj, true); | ||
2625 | } | 2780 | } |
2626 | 2781 | ||
2627 | /** Flushes the GTT write domain for the object if it's dirty. */ | 2782 | /** Flushes the GTT write domain for the object if it's dirty. */ |
@@ -2665,26 +2820,6 @@ i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj) | |||
2665 | old_write_domain); | 2820 | old_write_domain); |
2666 | } | 2821 | } |
2667 | 2822 | ||
2668 | int | ||
2669 | i915_gem_object_flush_write_domain(struct drm_gem_object *obj) | ||
2670 | { | ||
2671 | int ret = 0; | ||
2672 | |||
2673 | switch (obj->write_domain) { | ||
2674 | case I915_GEM_DOMAIN_GTT: | ||
2675 | i915_gem_object_flush_gtt_write_domain(obj); | ||
2676 | break; | ||
2677 | case I915_GEM_DOMAIN_CPU: | ||
2678 | i915_gem_object_flush_cpu_write_domain(obj); | ||
2679 | break; | ||
2680 | default: | ||
2681 | ret = i915_gem_object_flush_gpu_write_domain(obj); | ||
2682 | break; | ||
2683 | } | ||
2684 | |||
2685 | return ret; | ||
2686 | } | ||
2687 | |||
2688 | /** | 2823 | /** |
2689 | * Moves a single object to the GTT read, and possibly write domain. | 2824 | * Moves a single object to the GTT read, and possibly write domain. |
2690 | * | 2825 | * |
@@ -2702,32 +2837,28 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) | |||
2702 | if (obj_priv->gtt_space == NULL) | 2837 | if (obj_priv->gtt_space == NULL) |
2703 | return -EINVAL; | 2838 | return -EINVAL; |
2704 | 2839 | ||
2705 | ret = i915_gem_object_flush_gpu_write_domain(obj); | 2840 | ret = i915_gem_object_flush_gpu_write_domain(obj, false); |
2706 | if (ret != 0) | 2841 | if (ret != 0) |
2707 | return ret; | 2842 | return ret; |
2708 | 2843 | ||
2709 | /* Wait on any GPU rendering and flushing to occur. */ | 2844 | i915_gem_object_flush_cpu_write_domain(obj); |
2710 | ret = i915_gem_object_wait_rendering(obj); | 2845 | |
2711 | if (ret != 0) | 2846 | if (write) { |
2712 | return ret; | 2847 | ret = i915_gem_object_wait_rendering(obj, true); |
2848 | if (ret) | ||
2849 | return ret; | ||
2850 | } | ||
2713 | 2851 | ||
2714 | old_write_domain = obj->write_domain; | 2852 | old_write_domain = obj->write_domain; |
2715 | old_read_domains = obj->read_domains; | 2853 | old_read_domains = obj->read_domains; |
2716 | 2854 | ||
2717 | /* If we're writing through the GTT domain, then CPU and GPU caches | ||
2718 | * will need to be invalidated at next use. | ||
2719 | */ | ||
2720 | if (write) | ||
2721 | obj->read_domains &= I915_GEM_DOMAIN_GTT; | ||
2722 | |||
2723 | i915_gem_object_flush_cpu_write_domain(obj); | ||
2724 | |||
2725 | /* It should now be out of any other write domains, and we can update | 2855 | /* It should now be out of any other write domains, and we can update |
2726 | * the domain values for our changes. | 2856 | * the domain values for our changes. |
2727 | */ | 2857 | */ |
2728 | BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); | 2858 | BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); |
2729 | obj->read_domains |= I915_GEM_DOMAIN_GTT; | 2859 | obj->read_domains |= I915_GEM_DOMAIN_GTT; |
2730 | if (write) { | 2860 | if (write) { |
2861 | obj->read_domains = I915_GEM_DOMAIN_GTT; | ||
2731 | obj->write_domain = I915_GEM_DOMAIN_GTT; | 2862 | obj->write_domain = I915_GEM_DOMAIN_GTT; |
2732 | obj_priv->dirty = 1; | 2863 | obj_priv->dirty = 1; |
2733 | } | 2864 | } |
@@ -2744,51 +2875,36 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write) | |||
2744 | * wait, as in modesetting process we're not supposed to be interrupted. | 2875 | * wait, as in modesetting process we're not supposed to be interrupted. |
2745 | */ | 2876 | */ |
2746 | int | 2877 | int |
2747 | i915_gem_object_set_to_display_plane(struct drm_gem_object *obj) | 2878 | i915_gem_object_set_to_display_plane(struct drm_gem_object *obj, |
2879 | bool pipelined) | ||
2748 | { | 2880 | { |
2749 | struct drm_device *dev = obj->dev; | ||
2750 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 2881 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
2751 | uint32_t old_write_domain, old_read_domains; | 2882 | uint32_t old_read_domains; |
2752 | int ret; | 2883 | int ret; |
2753 | 2884 | ||
2754 | /* Not valid to be called on unbound objects. */ | 2885 | /* Not valid to be called on unbound objects. */ |
2755 | if (obj_priv->gtt_space == NULL) | 2886 | if (obj_priv->gtt_space == NULL) |
2756 | return -EINVAL; | 2887 | return -EINVAL; |
2757 | 2888 | ||
2758 | ret = i915_gem_object_flush_gpu_write_domain(obj); | 2889 | ret = i915_gem_object_flush_gpu_write_domain(obj, true); |
2759 | if (ret) | 2890 | if (ret) |
2760 | return ret; | 2891 | return ret; |
2761 | 2892 | ||
2762 | /* Wait on any GPU rendering and flushing to occur. */ | 2893 | /* Currently, we are always called from an non-interruptible context. */ |
2763 | if (obj_priv->active) { | 2894 | if (!pipelined) { |
2764 | #if WATCH_BUF | 2895 | ret = i915_gem_object_wait_rendering(obj, false); |
2765 | DRM_INFO("%s: object %p wait for seqno %08x\n", | 2896 | if (ret) |
2766 | __func__, obj, obj_priv->last_rendering_seqno); | ||
2767 | #endif | ||
2768 | ret = i915_do_wait_request(dev, | ||
2769 | obj_priv->last_rendering_seqno, | ||
2770 | 0, | ||
2771 | obj_priv->ring); | ||
2772 | if (ret != 0) | ||
2773 | return ret; | 2897 | return ret; |
2774 | } | 2898 | } |
2775 | 2899 | ||
2776 | i915_gem_object_flush_cpu_write_domain(obj); | 2900 | i915_gem_object_flush_cpu_write_domain(obj); |
2777 | 2901 | ||
2778 | old_write_domain = obj->write_domain; | ||
2779 | old_read_domains = obj->read_domains; | 2902 | old_read_domains = obj->read_domains; |
2780 | 2903 | obj->read_domains |= I915_GEM_DOMAIN_GTT; | |
2781 | /* It should now be out of any other write domains, and we can update | ||
2782 | * the domain values for our changes. | ||
2783 | */ | ||
2784 | BUG_ON((obj->write_domain & ~I915_GEM_DOMAIN_GTT) != 0); | ||
2785 | obj->read_domains = I915_GEM_DOMAIN_GTT; | ||
2786 | obj->write_domain = I915_GEM_DOMAIN_GTT; | ||
2787 | obj_priv->dirty = 1; | ||
2788 | 2904 | ||
2789 | trace_i915_gem_object_change_domain(obj, | 2905 | trace_i915_gem_object_change_domain(obj, |
2790 | old_read_domains, | 2906 | old_read_domains, |
2791 | old_write_domain); | 2907 | obj->write_domain); |
2792 | 2908 | ||
2793 | return 0; | 2909 | return 0; |
2794 | } | 2910 | } |
@@ -2805,12 +2921,7 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
2805 | uint32_t old_write_domain, old_read_domains; | 2921 | uint32_t old_write_domain, old_read_domains; |
2806 | int ret; | 2922 | int ret; |
2807 | 2923 | ||
2808 | ret = i915_gem_object_flush_gpu_write_domain(obj); | 2924 | ret = i915_gem_object_flush_gpu_write_domain(obj, false); |
2809 | if (ret) | ||
2810 | return ret; | ||
2811 | |||
2812 | /* Wait on any GPU rendering and flushing to occur. */ | ||
2813 | ret = i915_gem_object_wait_rendering(obj); | ||
2814 | if (ret != 0) | 2925 | if (ret != 0) |
2815 | return ret; | 2926 | return ret; |
2816 | 2927 | ||
@@ -2821,6 +2932,12 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
2821 | */ | 2932 | */ |
2822 | i915_gem_object_set_to_full_cpu_read_domain(obj); | 2933 | i915_gem_object_set_to_full_cpu_read_domain(obj); |
2823 | 2934 | ||
2935 | if (write) { | ||
2936 | ret = i915_gem_object_wait_rendering(obj, true); | ||
2937 | if (ret) | ||
2938 | return ret; | ||
2939 | } | ||
2940 | |||
2824 | old_write_domain = obj->write_domain; | 2941 | old_write_domain = obj->write_domain; |
2825 | old_read_domains = obj->read_domains; | 2942 | old_read_domains = obj->read_domains; |
2826 | 2943 | ||
@@ -2840,7 +2957,7 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
2840 | * need to be invalidated at next use. | 2957 | * need to be invalidated at next use. |
2841 | */ | 2958 | */ |
2842 | if (write) { | 2959 | if (write) { |
2843 | obj->read_domains &= I915_GEM_DOMAIN_CPU; | 2960 | obj->read_domains = I915_GEM_DOMAIN_CPU; |
2844 | obj->write_domain = I915_GEM_DOMAIN_CPU; | 2961 | obj->write_domain = I915_GEM_DOMAIN_CPU; |
2845 | } | 2962 | } |
2846 | 2963 | ||
@@ -2963,26 +3080,18 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write) | |||
2963 | * drm_agp_chipset_flush | 3080 | * drm_agp_chipset_flush |
2964 | */ | 3081 | */ |
2965 | static void | 3082 | static void |
2966 | i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) | 3083 | i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj, |
3084 | struct intel_ring_buffer *ring) | ||
2967 | { | 3085 | { |
2968 | struct drm_device *dev = obj->dev; | 3086 | struct drm_device *dev = obj->dev; |
2969 | drm_i915_private_t *dev_priv = dev->dev_private; | 3087 | struct drm_i915_private *dev_priv = dev->dev_private; |
2970 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 3088 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
2971 | uint32_t invalidate_domains = 0; | 3089 | uint32_t invalidate_domains = 0; |
2972 | uint32_t flush_domains = 0; | 3090 | uint32_t flush_domains = 0; |
2973 | uint32_t old_read_domains; | 3091 | uint32_t old_read_domains; |
2974 | 3092 | ||
2975 | BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU); | ||
2976 | BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU); | ||
2977 | |||
2978 | intel_mark_busy(dev, obj); | 3093 | intel_mark_busy(dev, obj); |
2979 | 3094 | ||
2980 | #if WATCH_BUF | ||
2981 | DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n", | ||
2982 | __func__, obj, | ||
2983 | obj->read_domains, obj->pending_read_domains, | ||
2984 | obj->write_domain, obj->pending_write_domain); | ||
2985 | #endif | ||
2986 | /* | 3095 | /* |
2987 | * If the object isn't moving to a new write domain, | 3096 | * If the object isn't moving to a new write domain, |
2988 | * let the object stay in multiple read domains | 3097 | * let the object stay in multiple read domains |
@@ -3009,13 +3118,8 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) | |||
3009 | * stale data. That is, any new read domains. | 3118 | * stale data. That is, any new read domains. |
3010 | */ | 3119 | */ |
3011 | invalidate_domains |= obj->pending_read_domains & ~obj->read_domains; | 3120 | invalidate_domains |= obj->pending_read_domains & ~obj->read_domains; |
3012 | if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) { | 3121 | if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) |
3013 | #if WATCH_BUF | ||
3014 | DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n", | ||
3015 | __func__, flush_domains, invalidate_domains); | ||
3016 | #endif | ||
3017 | i915_gem_clflush_object(obj); | 3122 | i915_gem_clflush_object(obj); |
3018 | } | ||
3019 | 3123 | ||
3020 | old_read_domains = obj->read_domains; | 3124 | old_read_domains = obj->read_domains; |
3021 | 3125 | ||
@@ -3029,21 +3133,12 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj) | |||
3029 | obj->pending_write_domain = obj->write_domain; | 3133 | obj->pending_write_domain = obj->write_domain; |
3030 | obj->read_domains = obj->pending_read_domains; | 3134 | obj->read_domains = obj->pending_read_domains; |
3031 | 3135 | ||
3032 | if (flush_domains & I915_GEM_GPU_DOMAINS) { | ||
3033 | if (obj_priv->ring == &dev_priv->render_ring) | ||
3034 | dev_priv->flush_rings |= FLUSH_RENDER_RING; | ||
3035 | else if (obj_priv->ring == &dev_priv->bsd_ring) | ||
3036 | dev_priv->flush_rings |= FLUSH_BSD_RING; | ||
3037 | } | ||
3038 | |||
3039 | dev->invalidate_domains |= invalidate_domains; | 3136 | dev->invalidate_domains |= invalidate_domains; |
3040 | dev->flush_domains |= flush_domains; | 3137 | dev->flush_domains |= flush_domains; |
3041 | #if WATCH_BUF | 3138 | if (flush_domains & I915_GEM_GPU_DOMAINS) |
3042 | DRM_INFO("%s: read %08x write %08x invalidate %08x flush %08x\n", | 3139 | dev_priv->mm.flush_rings |= obj_priv->ring->id; |
3043 | __func__, | 3140 | if (invalidate_domains & I915_GEM_GPU_DOMAINS) |
3044 | obj->read_domains, obj->write_domain, | 3141 | dev_priv->mm.flush_rings |= ring->id; |
3045 | dev->invalidate_domains, dev->flush_domains); | ||
3046 | #endif | ||
3047 | 3142 | ||
3048 | trace_i915_gem_object_change_domain(obj, | 3143 | trace_i915_gem_object_change_domain(obj, |
3049 | old_read_domains, | 3144 | old_read_domains, |
@@ -3106,12 +3201,7 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, | |||
3106 | if (offset == 0 && size == obj->size) | 3201 | if (offset == 0 && size == obj->size) |
3107 | return i915_gem_object_set_to_cpu_domain(obj, 0); | 3202 | return i915_gem_object_set_to_cpu_domain(obj, 0); |
3108 | 3203 | ||
3109 | ret = i915_gem_object_flush_gpu_write_domain(obj); | 3204 | ret = i915_gem_object_flush_gpu_write_domain(obj, false); |
3110 | if (ret) | ||
3111 | return ret; | ||
3112 | |||
3113 | /* Wait on any GPU rendering and flushing to occur. */ | ||
3114 | ret = i915_gem_object_wait_rendering(obj); | ||
3115 | if (ret != 0) | 3205 | if (ret != 0) |
3116 | return ret; | 3206 | return ret; |
3117 | i915_gem_object_flush_gtt_write_domain(obj); | 3207 | i915_gem_object_flush_gtt_write_domain(obj); |
@@ -3164,66 +3254,42 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj, | |||
3164 | * Pin an object to the GTT and evaluate the relocations landing in it. | 3254 | * Pin an object to the GTT and evaluate the relocations landing in it. |
3165 | */ | 3255 | */ |
3166 | static int | 3256 | static int |
3167 | i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | 3257 | i915_gem_execbuffer_relocate(struct drm_i915_gem_object *obj, |
3168 | struct drm_file *file_priv, | 3258 | struct drm_file *file_priv, |
3169 | struct drm_i915_gem_exec_object2 *entry, | 3259 | struct drm_i915_gem_exec_object2 *entry) |
3170 | struct drm_i915_gem_relocation_entry *relocs) | ||
3171 | { | 3260 | { |
3172 | struct drm_device *dev = obj->dev; | 3261 | struct drm_device *dev = obj->base.dev; |
3173 | drm_i915_private_t *dev_priv = dev->dev_private; | 3262 | drm_i915_private_t *dev_priv = dev->dev_private; |
3174 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 3263 | struct drm_i915_gem_relocation_entry __user *user_relocs; |
3175 | int i, ret; | 3264 | struct drm_gem_object *target_obj = NULL; |
3176 | void __iomem *reloc_page; | 3265 | uint32_t target_handle = 0; |
3177 | bool need_fence; | 3266 | int i, ret = 0; |
3178 | |||
3179 | need_fence = entry->flags & EXEC_OBJECT_NEEDS_FENCE && | ||
3180 | obj_priv->tiling_mode != I915_TILING_NONE; | ||
3181 | |||
3182 | /* Check fence reg constraints and rebind if necessary */ | ||
3183 | if (need_fence && | ||
3184 | !i915_gem_object_fence_offset_ok(obj, | ||
3185 | obj_priv->tiling_mode)) { | ||
3186 | ret = i915_gem_object_unbind(obj); | ||
3187 | if (ret) | ||
3188 | return ret; | ||
3189 | } | ||
3190 | 3267 | ||
3191 | /* Choose the GTT offset for our buffer and put it there. */ | 3268 | user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; |
3192 | ret = i915_gem_object_pin(obj, (uint32_t) entry->alignment); | 3269 | for (i = 0; i < entry->relocation_count; i++) { |
3193 | if (ret) | 3270 | struct drm_i915_gem_relocation_entry reloc; |
3194 | return ret; | 3271 | uint32_t target_offset; |
3195 | 3272 | ||
3196 | /* | 3273 | if (__copy_from_user_inatomic(&reloc, |
3197 | * Pre-965 chips need a fence register set up in order to | 3274 | user_relocs+i, |
3198 | * properly handle blits to/from tiled surfaces. | 3275 | sizeof(reloc))) { |
3199 | */ | 3276 | ret = -EFAULT; |
3200 | if (need_fence) { | 3277 | break; |
3201 | ret = i915_gem_object_get_fence_reg(obj); | ||
3202 | if (ret != 0) { | ||
3203 | i915_gem_object_unpin(obj); | ||
3204 | return ret; | ||
3205 | } | 3278 | } |
3206 | } | ||
3207 | 3279 | ||
3208 | entry->offset = obj_priv->gtt_offset; | 3280 | if (reloc.target_handle != target_handle) { |
3281 | drm_gem_object_unreference(target_obj); | ||
3209 | 3282 | ||
3210 | /* Apply the relocations, using the GTT aperture to avoid cache | 3283 | target_obj = drm_gem_object_lookup(dev, file_priv, |
3211 | * flushing requirements. | 3284 | reloc.target_handle); |
3212 | */ | 3285 | if (target_obj == NULL) { |
3213 | for (i = 0; i < entry->relocation_count; i++) { | 3286 | ret = -ENOENT; |
3214 | struct drm_i915_gem_relocation_entry *reloc= &relocs[i]; | 3287 | break; |
3215 | struct drm_gem_object *target_obj; | 3288 | } |
3216 | struct drm_i915_gem_object *target_obj_priv; | 3289 | |
3217 | uint32_t reloc_val, reloc_offset; | 3290 | target_handle = reloc.target_handle; |
3218 | uint32_t __iomem *reloc_entry; | ||
3219 | |||
3220 | target_obj = drm_gem_object_lookup(obj->dev, file_priv, | ||
3221 | reloc->target_handle); | ||
3222 | if (target_obj == NULL) { | ||
3223 | i915_gem_object_unpin(obj); | ||
3224 | return -ENOENT; | ||
3225 | } | 3291 | } |
3226 | target_obj_priv = to_intel_bo(target_obj); | 3292 | target_offset = to_intel_bo(target_obj)->gtt_offset; |
3227 | 3293 | ||
3228 | #if WATCH_RELOC | 3294 | #if WATCH_RELOC |
3229 | DRM_INFO("%s: obj %p offset %08x target %d " | 3295 | DRM_INFO("%s: obj %p offset %08x target %d " |
@@ -3231,267 +3297,266 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj, | |||
3231 | "presumed %08x delta %08x\n", | 3297 | "presumed %08x delta %08x\n", |
3232 | __func__, | 3298 | __func__, |
3233 | obj, | 3299 | obj, |
3234 | (int) reloc->offset, | 3300 | (int) reloc.offset, |
3235 | (int) reloc->target_handle, | 3301 | (int) reloc.target_handle, |
3236 | (int) reloc->read_domains, | 3302 | (int) reloc.read_domains, |
3237 | (int) reloc->write_domain, | 3303 | (int) reloc.write_domain, |
3238 | (int) target_obj_priv->gtt_offset, | 3304 | (int) target_offset, |
3239 | (int) reloc->presumed_offset, | 3305 | (int) reloc.presumed_offset, |
3240 | reloc->delta); | 3306 | reloc.delta); |
3241 | #endif | 3307 | #endif |
3242 | 3308 | ||
3243 | /* The target buffer should have appeared before us in the | 3309 | /* The target buffer should have appeared before us in the |
3244 | * exec_object list, so it should have a GTT space bound by now. | 3310 | * exec_object list, so it should have a GTT space bound by now. |
3245 | */ | 3311 | */ |
3246 | if (target_obj_priv->gtt_space == NULL) { | 3312 | if (target_offset == 0) { |
3247 | DRM_ERROR("No GTT space found for object %d\n", | 3313 | DRM_ERROR("No GTT space found for object %d\n", |
3248 | reloc->target_handle); | 3314 | reloc.target_handle); |
3249 | drm_gem_object_unreference(target_obj); | 3315 | ret = -EINVAL; |
3250 | i915_gem_object_unpin(obj); | 3316 | break; |
3251 | return -EINVAL; | ||
3252 | } | 3317 | } |
3253 | 3318 | ||
3254 | /* Validate that the target is in a valid r/w GPU domain */ | 3319 | /* Validate that the target is in a valid r/w GPU domain */ |
3255 | if (reloc->write_domain & (reloc->write_domain - 1)) { | 3320 | if (reloc.write_domain & (reloc.write_domain - 1)) { |
3256 | DRM_ERROR("reloc with multiple write domains: " | 3321 | DRM_ERROR("reloc with multiple write domains: " |
3257 | "obj %p target %d offset %d " | 3322 | "obj %p target %d offset %d " |
3258 | "read %08x write %08x", | 3323 | "read %08x write %08x", |
3259 | obj, reloc->target_handle, | 3324 | obj, reloc.target_handle, |
3260 | (int) reloc->offset, | 3325 | (int) reloc.offset, |
3261 | reloc->read_domains, | 3326 | reloc.read_domains, |
3262 | reloc->write_domain); | 3327 | reloc.write_domain); |
3263 | drm_gem_object_unreference(target_obj); | 3328 | ret = -EINVAL; |
3264 | i915_gem_object_unpin(obj); | 3329 | break; |
3265 | return -EINVAL; | ||
3266 | } | 3330 | } |
3267 | if (reloc->write_domain & I915_GEM_DOMAIN_CPU || | 3331 | if (reloc.write_domain & I915_GEM_DOMAIN_CPU || |
3268 | reloc->read_domains & I915_GEM_DOMAIN_CPU) { | 3332 | reloc.read_domains & I915_GEM_DOMAIN_CPU) { |
3269 | DRM_ERROR("reloc with read/write CPU domains: " | 3333 | DRM_ERROR("reloc with read/write CPU domains: " |
3270 | "obj %p target %d offset %d " | 3334 | "obj %p target %d offset %d " |
3271 | "read %08x write %08x", | 3335 | "read %08x write %08x", |
3272 | obj, reloc->target_handle, | 3336 | obj, reloc.target_handle, |
3273 | (int) reloc->offset, | 3337 | (int) reloc.offset, |
3274 | reloc->read_domains, | 3338 | reloc.read_domains, |
3275 | reloc->write_domain); | 3339 | reloc.write_domain); |
3276 | drm_gem_object_unreference(target_obj); | 3340 | ret = -EINVAL; |
3277 | i915_gem_object_unpin(obj); | 3341 | break; |
3278 | return -EINVAL; | ||
3279 | } | 3342 | } |
3280 | if (reloc->write_domain && target_obj->pending_write_domain && | 3343 | if (reloc.write_domain && target_obj->pending_write_domain && |
3281 | reloc->write_domain != target_obj->pending_write_domain) { | 3344 | reloc.write_domain != target_obj->pending_write_domain) { |
3282 | DRM_ERROR("Write domain conflict: " | 3345 | DRM_ERROR("Write domain conflict: " |
3283 | "obj %p target %d offset %d " | 3346 | "obj %p target %d offset %d " |
3284 | "new %08x old %08x\n", | 3347 | "new %08x old %08x\n", |
3285 | obj, reloc->target_handle, | 3348 | obj, reloc.target_handle, |
3286 | (int) reloc->offset, | 3349 | (int) reloc.offset, |
3287 | reloc->write_domain, | 3350 | reloc.write_domain, |
3288 | target_obj->pending_write_domain); | 3351 | target_obj->pending_write_domain); |
3289 | drm_gem_object_unreference(target_obj); | 3352 | ret = -EINVAL; |
3290 | i915_gem_object_unpin(obj); | 3353 | break; |
3291 | return -EINVAL; | ||
3292 | } | 3354 | } |
3293 | 3355 | ||
3294 | target_obj->pending_read_domains |= reloc->read_domains; | 3356 | target_obj->pending_read_domains |= reloc.read_domains; |
3295 | target_obj->pending_write_domain |= reloc->write_domain; | 3357 | target_obj->pending_write_domain |= reloc.write_domain; |
3296 | 3358 | ||
3297 | /* If the relocation already has the right value in it, no | 3359 | /* If the relocation already has the right value in it, no |
3298 | * more work needs to be done. | 3360 | * more work needs to be done. |
3299 | */ | 3361 | */ |
3300 | if (target_obj_priv->gtt_offset == reloc->presumed_offset) { | 3362 | if (target_offset == reloc.presumed_offset) |
3301 | drm_gem_object_unreference(target_obj); | ||
3302 | continue; | 3363 | continue; |
3303 | } | ||
3304 | 3364 | ||
3305 | /* Check that the relocation address is valid... */ | 3365 | /* Check that the relocation address is valid... */ |
3306 | if (reloc->offset > obj->size - 4) { | 3366 | if (reloc.offset > obj->base.size - 4) { |
3307 | DRM_ERROR("Relocation beyond object bounds: " | 3367 | DRM_ERROR("Relocation beyond object bounds: " |
3308 | "obj %p target %d offset %d size %d.\n", | 3368 | "obj %p target %d offset %d size %d.\n", |
3309 | obj, reloc->target_handle, | 3369 | obj, reloc.target_handle, |
3310 | (int) reloc->offset, (int) obj->size); | 3370 | (int) reloc.offset, (int) obj->base.size); |
3311 | drm_gem_object_unreference(target_obj); | 3371 | ret = -EINVAL; |
3312 | i915_gem_object_unpin(obj); | 3372 | break; |
3313 | return -EINVAL; | ||
3314 | } | 3373 | } |
3315 | if (reloc->offset & 3) { | 3374 | if (reloc.offset & 3) { |
3316 | DRM_ERROR("Relocation not 4-byte aligned: " | 3375 | DRM_ERROR("Relocation not 4-byte aligned: " |
3317 | "obj %p target %d offset %d.\n", | 3376 | "obj %p target %d offset %d.\n", |
3318 | obj, reloc->target_handle, | 3377 | obj, reloc.target_handle, |
3319 | (int) reloc->offset); | 3378 | (int) reloc.offset); |
3320 | drm_gem_object_unreference(target_obj); | 3379 | ret = -EINVAL; |
3321 | i915_gem_object_unpin(obj); | 3380 | break; |
3322 | return -EINVAL; | ||
3323 | } | 3381 | } |
3324 | 3382 | ||
3325 | /* and points to somewhere within the target object. */ | 3383 | /* and points to somewhere within the target object. */ |
3326 | if (reloc->delta >= target_obj->size) { | 3384 | if (reloc.delta >= target_obj->size) { |
3327 | DRM_ERROR("Relocation beyond target object bounds: " | 3385 | DRM_ERROR("Relocation beyond target object bounds: " |
3328 | "obj %p target %d delta %d size %d.\n", | 3386 | "obj %p target %d delta %d size %d.\n", |
3329 | obj, reloc->target_handle, | 3387 | obj, reloc.target_handle, |
3330 | (int) reloc->delta, (int) target_obj->size); | 3388 | (int) reloc.delta, (int) target_obj->size); |
3331 | drm_gem_object_unreference(target_obj); | 3389 | ret = -EINVAL; |
3332 | i915_gem_object_unpin(obj); | 3390 | break; |
3333 | return -EINVAL; | ||
3334 | } | ||
3335 | |||
3336 | ret = i915_gem_object_set_to_gtt_domain(obj, 1); | ||
3337 | if (ret != 0) { | ||
3338 | drm_gem_object_unreference(target_obj); | ||
3339 | i915_gem_object_unpin(obj); | ||
3340 | return -EINVAL; | ||
3341 | } | 3391 | } |
3342 | 3392 | ||
3343 | /* Map the page containing the relocation we're going to | 3393 | reloc.delta += target_offset; |
3344 | * perform. | 3394 | if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) { |
3345 | */ | 3395 | uint32_t page_offset = reloc.offset & ~PAGE_MASK; |
3346 | reloc_offset = obj_priv->gtt_offset + reloc->offset; | 3396 | char *vaddr; |
3347 | reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, | ||
3348 | (reloc_offset & | ||
3349 | ~(PAGE_SIZE - 1))); | ||
3350 | reloc_entry = (uint32_t __iomem *)(reloc_page + | ||
3351 | (reloc_offset & (PAGE_SIZE - 1))); | ||
3352 | reloc_val = target_obj_priv->gtt_offset + reloc->delta; | ||
3353 | |||
3354 | #if WATCH_BUF | ||
3355 | DRM_INFO("Applied relocation: %p@0x%08x %08x -> %08x\n", | ||
3356 | obj, (unsigned int) reloc->offset, | ||
3357 | readl(reloc_entry), reloc_val); | ||
3358 | #endif | ||
3359 | writel(reloc_val, reloc_entry); | ||
3360 | io_mapping_unmap_atomic(reloc_page); | ||
3361 | |||
3362 | /* The updated presumed offset for this entry will be | ||
3363 | * copied back out to the user. | ||
3364 | */ | ||
3365 | reloc->presumed_offset = target_obj_priv->gtt_offset; | ||
3366 | |||
3367 | drm_gem_object_unreference(target_obj); | ||
3368 | } | ||
3369 | |||
3370 | #if WATCH_BUF | ||
3371 | if (0) | ||
3372 | i915_gem_dump_object(obj, 128, __func__, ~0); | ||
3373 | #endif | ||
3374 | return 0; | ||
3375 | } | ||
3376 | 3397 | ||
3377 | /* Throttle our rendering by waiting until the ring has completed our requests | 3398 | vaddr = kmap_atomic(obj->pages[reloc.offset >> PAGE_SHIFT]); |
3378 | * emitted over 20 msec ago. | 3399 | *(uint32_t *)(vaddr + page_offset) = reloc.delta; |
3379 | * | 3400 | kunmap_atomic(vaddr); |
3380 | * Note that if we were to use the current jiffies each time around the loop, | 3401 | } else { |
3381 | * we wouldn't escape the function with any frames outstanding if the time to | 3402 | uint32_t __iomem *reloc_entry; |
3382 | * render a frame was over 20ms. | 3403 | void __iomem *reloc_page; |
3383 | * | ||
3384 | * This should get us reasonable parallelism between CPU and GPU but also | ||
3385 | * relatively low latency when blocking on a particular request to finish. | ||
3386 | */ | ||
3387 | static int | ||
3388 | i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file_priv) | ||
3389 | { | ||
3390 | struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv; | ||
3391 | int ret = 0; | ||
3392 | unsigned long recent_enough = jiffies - msecs_to_jiffies(20); | ||
3393 | |||
3394 | mutex_lock(&dev->struct_mutex); | ||
3395 | while (!list_empty(&i915_file_priv->mm.request_list)) { | ||
3396 | struct drm_i915_gem_request *request; | ||
3397 | 3404 | ||
3398 | request = list_first_entry(&i915_file_priv->mm.request_list, | 3405 | ret = i915_gem_object_set_to_gtt_domain(&obj->base, 1); |
3399 | struct drm_i915_gem_request, | 3406 | if (ret) |
3400 | client_list); | 3407 | break; |
3401 | 3408 | ||
3402 | if (time_after_eq(request->emitted_jiffies, recent_enough)) | 3409 | /* Map the page containing the relocation we're going to perform. */ |
3403 | break; | 3410 | reloc.offset += obj->gtt_offset; |
3411 | reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping, | ||
3412 | reloc.offset & PAGE_MASK); | ||
3413 | reloc_entry = (uint32_t __iomem *) | ||
3414 | (reloc_page + (reloc.offset & ~PAGE_MASK)); | ||
3415 | iowrite32(reloc.delta, reloc_entry); | ||
3416 | io_mapping_unmap_atomic(reloc_page); | ||
3417 | } | ||
3404 | 3418 | ||
3405 | ret = i915_wait_request(dev, request->seqno, request->ring); | 3419 | /* and update the user's relocation entry */ |
3406 | if (ret != 0) | 3420 | reloc.presumed_offset = target_offset; |
3407 | break; | 3421 | if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset, |
3422 | &reloc.presumed_offset, | ||
3423 | sizeof(reloc.presumed_offset))) { | ||
3424 | ret = -EFAULT; | ||
3425 | break; | ||
3426 | } | ||
3408 | } | 3427 | } |
3409 | mutex_unlock(&dev->struct_mutex); | ||
3410 | 3428 | ||
3429 | drm_gem_object_unreference(target_obj); | ||
3411 | return ret; | 3430 | return ret; |
3412 | } | 3431 | } |
3413 | 3432 | ||
3414 | static int | 3433 | static int |
3415 | i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object2 *exec_list, | 3434 | i915_gem_execbuffer_pin(struct drm_device *dev, |
3416 | uint32_t buffer_count, | 3435 | struct drm_file *file, |
3417 | struct drm_i915_gem_relocation_entry **relocs) | 3436 | struct drm_gem_object **object_list, |
3437 | struct drm_i915_gem_exec_object2 *exec_list, | ||
3438 | int count) | ||
3418 | { | 3439 | { |
3419 | uint32_t reloc_count = 0, reloc_index = 0, i; | 3440 | struct drm_i915_private *dev_priv = dev->dev_private; |
3420 | int ret; | 3441 | int ret, i, retry; |
3421 | 3442 | ||
3422 | *relocs = NULL; | 3443 | /* attempt to pin all of the buffers into the GTT */ |
3423 | for (i = 0; i < buffer_count; i++) { | 3444 | for (retry = 0; retry < 2; retry++) { |
3424 | if (reloc_count + exec_list[i].relocation_count < reloc_count) | 3445 | ret = 0; |
3425 | return -EINVAL; | 3446 | for (i = 0; i < count; i++) { |
3426 | reloc_count += exec_list[i].relocation_count; | 3447 | struct drm_i915_gem_exec_object2 *entry = &exec_list[i]; |
3427 | } | 3448 | struct drm_i915_gem_object *obj= to_intel_bo(object_list[i]); |
3449 | bool need_fence = | ||
3450 | entry->flags & EXEC_OBJECT_NEEDS_FENCE && | ||
3451 | obj->tiling_mode != I915_TILING_NONE; | ||
3452 | |||
3453 | /* Check fence reg constraints and rebind if necessary */ | ||
3454 | if (need_fence && | ||
3455 | !i915_gem_object_fence_offset_ok(&obj->base, | ||
3456 | obj->tiling_mode)) { | ||
3457 | ret = i915_gem_object_unbind(&obj->base); | ||
3458 | if (ret) | ||
3459 | break; | ||
3460 | } | ||
3428 | 3461 | ||
3429 | *relocs = drm_calloc_large(reloc_count, sizeof(**relocs)); | 3462 | ret = i915_gem_object_pin(&obj->base, entry->alignment); |
3430 | if (*relocs == NULL) { | 3463 | if (ret) |
3431 | DRM_ERROR("failed to alloc relocs, count %d\n", reloc_count); | 3464 | break; |
3432 | return -ENOMEM; | ||
3433 | } | ||
3434 | 3465 | ||
3435 | for (i = 0; i < buffer_count; i++) { | 3466 | /* |
3436 | struct drm_i915_gem_relocation_entry __user *user_relocs; | 3467 | * Pre-965 chips need a fence register set up in order |
3468 | * to properly handle blits to/from tiled surfaces. | ||
3469 | */ | ||
3470 | if (need_fence) { | ||
3471 | ret = i915_gem_object_get_fence_reg(&obj->base, true); | ||
3472 | if (ret) { | ||
3473 | i915_gem_object_unpin(&obj->base); | ||
3474 | break; | ||
3475 | } | ||
3437 | 3476 | ||
3438 | user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr; | 3477 | dev_priv->fence_regs[obj->fence_reg].gpu = true; |
3478 | } | ||
3439 | 3479 | ||
3440 | ret = copy_from_user(&(*relocs)[reloc_index], | 3480 | entry->offset = obj->gtt_offset; |
3441 | user_relocs, | ||
3442 | exec_list[i].relocation_count * | ||
3443 | sizeof(**relocs)); | ||
3444 | if (ret != 0) { | ||
3445 | drm_free_large(*relocs); | ||
3446 | *relocs = NULL; | ||
3447 | return -EFAULT; | ||
3448 | } | 3481 | } |
3449 | 3482 | ||
3450 | reloc_index += exec_list[i].relocation_count; | 3483 | while (i--) |
3484 | i915_gem_object_unpin(object_list[i]); | ||
3485 | |||
3486 | if (ret == 0) | ||
3487 | break; | ||
3488 | |||
3489 | if (ret != -ENOSPC || retry) | ||
3490 | return ret; | ||
3491 | |||
3492 | ret = i915_gem_evict_everything(dev); | ||
3493 | if (ret) | ||
3494 | return ret; | ||
3451 | } | 3495 | } |
3452 | 3496 | ||
3453 | return 0; | 3497 | return 0; |
3454 | } | 3498 | } |
3455 | 3499 | ||
3500 | /* Throttle our rendering by waiting until the ring has completed our requests | ||
3501 | * emitted over 20 msec ago. | ||
3502 | * | ||
3503 | * Note that if we were to use the current jiffies each time around the loop, | ||
3504 | * we wouldn't escape the function with any frames outstanding if the time to | ||
3505 | * render a frame was over 20ms. | ||
3506 | * | ||
3507 | * This should get us reasonable parallelism between CPU and GPU but also | ||
3508 | * relatively low latency when blocking on a particular request to finish. | ||
3509 | */ | ||
3456 | static int | 3510 | static int |
3457 | i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object2 *exec_list, | 3511 | i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file) |
3458 | uint32_t buffer_count, | ||
3459 | struct drm_i915_gem_relocation_entry *relocs) | ||
3460 | { | 3512 | { |
3461 | uint32_t reloc_count = 0, i; | 3513 | struct drm_i915_private *dev_priv = dev->dev_private; |
3462 | int ret = 0; | 3514 | struct drm_i915_file_private *file_priv = file->driver_priv; |
3463 | 3515 | unsigned long recent_enough = jiffies - msecs_to_jiffies(20); | |
3464 | if (relocs == NULL) | 3516 | struct drm_i915_gem_request *request; |
3465 | return 0; | 3517 | struct intel_ring_buffer *ring = NULL; |
3518 | u32 seqno = 0; | ||
3519 | int ret; | ||
3466 | 3520 | ||
3467 | for (i = 0; i < buffer_count; i++) { | 3521 | spin_lock(&file_priv->mm.lock); |
3468 | struct drm_i915_gem_relocation_entry __user *user_relocs; | 3522 | list_for_each_entry(request, &file_priv->mm.request_list, client_list) { |
3469 | int unwritten; | 3523 | if (time_after_eq(request->emitted_jiffies, recent_enough)) |
3524 | break; | ||
3470 | 3525 | ||
3471 | user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr; | 3526 | ring = request->ring; |
3527 | seqno = request->seqno; | ||
3528 | } | ||
3529 | spin_unlock(&file_priv->mm.lock); | ||
3472 | 3530 | ||
3473 | unwritten = copy_to_user(user_relocs, | 3531 | if (seqno == 0) |
3474 | &relocs[reloc_count], | 3532 | return 0; |
3475 | exec_list[i].relocation_count * | ||
3476 | sizeof(*relocs)); | ||
3477 | 3533 | ||
3478 | if (unwritten) { | 3534 | ret = 0; |
3479 | ret = -EFAULT; | 3535 | if (!i915_seqno_passed(ring->get_seqno(dev, ring), seqno)) { |
3480 | goto err; | 3536 | /* And wait for the seqno passing without holding any locks and |
3481 | } | 3537 | * causing extra latency for others. This is safe as the irq |
3538 | * generation is designed to be run atomically and so is | ||
3539 | * lockless. | ||
3540 | */ | ||
3541 | ring->user_irq_get(dev, ring); | ||
3542 | ret = wait_event_interruptible(ring->irq_queue, | ||
3543 | i915_seqno_passed(ring->get_seqno(dev, ring), seqno) | ||
3544 | || atomic_read(&dev_priv->mm.wedged)); | ||
3545 | ring->user_irq_put(dev, ring); | ||
3482 | 3546 | ||
3483 | reloc_count += exec_list[i].relocation_count; | 3547 | if (ret == 0 && atomic_read(&dev_priv->mm.wedged)) |
3548 | ret = -EIO; | ||
3484 | } | 3549 | } |
3485 | 3550 | ||
3486 | err: | 3551 | if (ret == 0) |
3487 | drm_free_large(relocs); | 3552 | queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); |
3488 | 3553 | ||
3489 | return ret; | 3554 | return ret; |
3490 | } | 3555 | } |
3491 | 3556 | ||
3492 | static int | 3557 | static int |
3493 | i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer2 *exec, | 3558 | i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec, |
3494 | uint64_t exec_offset) | 3559 | uint64_t exec_offset) |
3495 | { | 3560 | { |
3496 | uint32_t exec_start, exec_len; | 3561 | uint32_t exec_start, exec_len; |
3497 | 3562 | ||
@@ -3508,44 +3573,32 @@ i915_gem_check_execbuffer (struct drm_i915_gem_execbuffer2 *exec, | |||
3508 | } | 3573 | } |
3509 | 3574 | ||
3510 | static int | 3575 | static int |
3511 | i915_gem_wait_for_pending_flip(struct drm_device *dev, | 3576 | validate_exec_list(struct drm_i915_gem_exec_object2 *exec, |
3512 | struct drm_gem_object **object_list, | 3577 | int count) |
3513 | int count) | ||
3514 | { | 3578 | { |
3515 | drm_i915_private_t *dev_priv = dev->dev_private; | 3579 | int i; |
3516 | struct drm_i915_gem_object *obj_priv; | ||
3517 | DEFINE_WAIT(wait); | ||
3518 | int i, ret = 0; | ||
3519 | 3580 | ||
3520 | for (;;) { | 3581 | for (i = 0; i < count; i++) { |
3521 | prepare_to_wait(&dev_priv->pending_flip_queue, | 3582 | char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; |
3522 | &wait, TASK_INTERRUPTIBLE); | 3583 | size_t length = exec[i].relocation_count * sizeof(struct drm_i915_gem_relocation_entry); |
3523 | for (i = 0; i < count; i++) { | ||
3524 | obj_priv = to_intel_bo(object_list[i]); | ||
3525 | if (atomic_read(&obj_priv->pending_flip) > 0) | ||
3526 | break; | ||
3527 | } | ||
3528 | if (i == count) | ||
3529 | break; | ||
3530 | 3584 | ||
3531 | if (!signal_pending(current)) { | 3585 | if (!access_ok(VERIFY_READ, ptr, length)) |
3532 | mutex_unlock(&dev->struct_mutex); | 3586 | return -EFAULT; |
3533 | schedule(); | 3587 | |
3534 | mutex_lock(&dev->struct_mutex); | 3588 | /* we may also need to update the presumed offsets */ |
3535 | continue; | 3589 | if (!access_ok(VERIFY_WRITE, ptr, length)) |
3536 | } | 3590 | return -EFAULT; |
3537 | ret = -ERESTARTSYS; | 3591 | |
3538 | break; | 3592 | if (fault_in_pages_readable(ptr, length)) |
3593 | return -EFAULT; | ||
3539 | } | 3594 | } |
3540 | finish_wait(&dev_priv->pending_flip_queue, &wait); | ||
3541 | 3595 | ||
3542 | return ret; | 3596 | return 0; |
3543 | } | 3597 | } |
3544 | 3598 | ||
3545 | 3599 | static int | |
3546 | int | ||
3547 | i915_gem_do_execbuffer(struct drm_device *dev, void *data, | 3600 | i915_gem_do_execbuffer(struct drm_device *dev, void *data, |
3548 | struct drm_file *file_priv, | 3601 | struct drm_file *file, |
3549 | struct drm_i915_gem_execbuffer2 *args, | 3602 | struct drm_i915_gem_execbuffer2 *args, |
3550 | struct drm_i915_gem_exec_object2 *exec_list) | 3603 | struct drm_i915_gem_exec_object2 *exec_list) |
3551 | { | 3604 | { |
@@ -3554,26 +3607,47 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3554 | struct drm_gem_object *batch_obj; | 3607 | struct drm_gem_object *batch_obj; |
3555 | struct drm_i915_gem_object *obj_priv; | 3608 | struct drm_i915_gem_object *obj_priv; |
3556 | struct drm_clip_rect *cliprects = NULL; | 3609 | struct drm_clip_rect *cliprects = NULL; |
3557 | struct drm_i915_gem_relocation_entry *relocs = NULL; | 3610 | struct drm_i915_gem_request *request = NULL; |
3558 | int ret = 0, ret2, i, pinned = 0; | 3611 | int ret, i, flips; |
3559 | uint64_t exec_offset; | 3612 | uint64_t exec_offset; |
3560 | uint32_t seqno, flush_domains, reloc_index; | ||
3561 | int pin_tries, flips; | ||
3562 | 3613 | ||
3563 | struct intel_ring_buffer *ring = NULL; | 3614 | struct intel_ring_buffer *ring = NULL; |
3564 | 3615 | ||
3616 | ret = i915_gem_check_is_wedged(dev); | ||
3617 | if (ret) | ||
3618 | return ret; | ||
3619 | |||
3620 | ret = validate_exec_list(exec_list, args->buffer_count); | ||
3621 | if (ret) | ||
3622 | return ret; | ||
3623 | |||
3565 | #if WATCH_EXEC | 3624 | #if WATCH_EXEC |
3566 | DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", | 3625 | DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n", |
3567 | (int) args->buffers_ptr, args->buffer_count, args->batch_len); | 3626 | (int) args->buffers_ptr, args->buffer_count, args->batch_len); |
3568 | #endif | 3627 | #endif |
3569 | if (args->flags & I915_EXEC_BSD) { | 3628 | switch (args->flags & I915_EXEC_RING_MASK) { |
3629 | case I915_EXEC_DEFAULT: | ||
3630 | case I915_EXEC_RENDER: | ||
3631 | ring = &dev_priv->render_ring; | ||
3632 | break; | ||
3633 | case I915_EXEC_BSD: | ||
3570 | if (!HAS_BSD(dev)) { | 3634 | if (!HAS_BSD(dev)) { |
3571 | DRM_ERROR("execbuf with wrong flag\n"); | 3635 | DRM_ERROR("execbuf with invalid ring (BSD)\n"); |
3572 | return -EINVAL; | 3636 | return -EINVAL; |
3573 | } | 3637 | } |
3574 | ring = &dev_priv->bsd_ring; | 3638 | ring = &dev_priv->bsd_ring; |
3575 | } else { | 3639 | break; |
3576 | ring = &dev_priv->render_ring; | 3640 | case I915_EXEC_BLT: |
3641 | if (!HAS_BLT(dev)) { | ||
3642 | DRM_ERROR("execbuf with invalid ring (BLT)\n"); | ||
3643 | return -EINVAL; | ||
3644 | } | ||
3645 | ring = &dev_priv->blt_ring; | ||
3646 | break; | ||
3647 | default: | ||
3648 | DRM_ERROR("execbuf with unknown ring: %d\n", | ||
3649 | (int)(args->flags & I915_EXEC_RING_MASK)); | ||
3650 | return -EINVAL; | ||
3577 | } | 3651 | } |
3578 | 3652 | ||
3579 | if (args->buffer_count < 1) { | 3653 | if (args->buffer_count < 1) { |
@@ -3608,20 +3682,15 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3608 | } | 3682 | } |
3609 | } | 3683 | } |
3610 | 3684 | ||
3611 | ret = i915_gem_get_relocs_from_user(exec_list, args->buffer_count, | 3685 | request = kzalloc(sizeof(*request), GFP_KERNEL); |
3612 | &relocs); | 3686 | if (request == NULL) { |
3613 | if (ret != 0) | 3687 | ret = -ENOMEM; |
3614 | goto pre_mutex_err; | 3688 | goto pre_mutex_err; |
3689 | } | ||
3615 | 3690 | ||
3616 | mutex_lock(&dev->struct_mutex); | 3691 | ret = i915_mutex_lock_interruptible(dev); |
3617 | 3692 | if (ret) | |
3618 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
3619 | |||
3620 | if (atomic_read(&dev_priv->mm.wedged)) { | ||
3621 | mutex_unlock(&dev->struct_mutex); | ||
3622 | ret = -EIO; | ||
3623 | goto pre_mutex_err; | 3693 | goto pre_mutex_err; |
3624 | } | ||
3625 | 3694 | ||
3626 | if (dev_priv->mm.suspended) { | 3695 | if (dev_priv->mm.suspended) { |
3627 | mutex_unlock(&dev->struct_mutex); | 3696 | mutex_unlock(&dev->struct_mutex); |
@@ -3630,9 +3699,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3630 | } | 3699 | } |
3631 | 3700 | ||
3632 | /* Look up object handles */ | 3701 | /* Look up object handles */ |
3633 | flips = 0; | ||
3634 | for (i = 0; i < args->buffer_count; i++) { | 3702 | for (i = 0; i < args->buffer_count; i++) { |
3635 | object_list[i] = drm_gem_object_lookup(dev, file_priv, | 3703 | object_list[i] = drm_gem_object_lookup(dev, file, |
3636 | exec_list[i].handle); | 3704 | exec_list[i].handle); |
3637 | if (object_list[i] == NULL) { | 3705 | if (object_list[i] == NULL) { |
3638 | DRM_ERROR("Invalid object handle %d at index %d\n", | 3706 | DRM_ERROR("Invalid object handle %d at index %d\n", |
@@ -3653,75 +3721,22 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3653 | goto err; | 3721 | goto err; |
3654 | } | 3722 | } |
3655 | obj_priv->in_execbuffer = true; | 3723 | obj_priv->in_execbuffer = true; |
3656 | flips += atomic_read(&obj_priv->pending_flip); | ||
3657 | } | 3724 | } |
3658 | 3725 | ||
3659 | if (flips > 0) { | 3726 | /* Move the objects en-masse into the GTT, evicting if necessary. */ |
3660 | ret = i915_gem_wait_for_pending_flip(dev, object_list, | 3727 | ret = i915_gem_execbuffer_pin(dev, file, |
3661 | args->buffer_count); | 3728 | object_list, exec_list, |
3662 | if (ret) | 3729 | args->buffer_count); |
3663 | goto err; | 3730 | if (ret) |
3664 | } | 3731 | goto err; |
3665 | |||
3666 | /* Pin and relocate */ | ||
3667 | for (pin_tries = 0; ; pin_tries++) { | ||
3668 | ret = 0; | ||
3669 | reloc_index = 0; | ||
3670 | |||
3671 | for (i = 0; i < args->buffer_count; i++) { | ||
3672 | object_list[i]->pending_read_domains = 0; | ||
3673 | object_list[i]->pending_write_domain = 0; | ||
3674 | ret = i915_gem_object_pin_and_relocate(object_list[i], | ||
3675 | file_priv, | ||
3676 | &exec_list[i], | ||
3677 | &relocs[reloc_index]); | ||
3678 | if (ret) | ||
3679 | break; | ||
3680 | pinned = i + 1; | ||
3681 | reloc_index += exec_list[i].relocation_count; | ||
3682 | } | ||
3683 | /* success */ | ||
3684 | if (ret == 0) | ||
3685 | break; | ||
3686 | |||
3687 | /* error other than GTT full, or we've already tried again */ | ||
3688 | if (ret != -ENOSPC || pin_tries >= 1) { | ||
3689 | if (ret != -ERESTARTSYS) { | ||
3690 | unsigned long long total_size = 0; | ||
3691 | int num_fences = 0; | ||
3692 | for (i = 0; i < args->buffer_count; i++) { | ||
3693 | obj_priv = to_intel_bo(object_list[i]); | ||
3694 | |||
3695 | total_size += object_list[i]->size; | ||
3696 | num_fences += | ||
3697 | exec_list[i].flags & EXEC_OBJECT_NEEDS_FENCE && | ||
3698 | obj_priv->tiling_mode != I915_TILING_NONE; | ||
3699 | } | ||
3700 | DRM_ERROR("Failed to pin buffer %d of %d, total %llu bytes, %d fences: %d\n", | ||
3701 | pinned+1, args->buffer_count, | ||
3702 | total_size, num_fences, | ||
3703 | ret); | ||
3704 | DRM_ERROR("%d objects [%d pinned], " | ||
3705 | "%d object bytes [%d pinned], " | ||
3706 | "%d/%d gtt bytes\n", | ||
3707 | atomic_read(&dev->object_count), | ||
3708 | atomic_read(&dev->pin_count), | ||
3709 | atomic_read(&dev->object_memory), | ||
3710 | atomic_read(&dev->pin_memory), | ||
3711 | atomic_read(&dev->gtt_memory), | ||
3712 | dev->gtt_total); | ||
3713 | } | ||
3714 | goto err; | ||
3715 | } | ||
3716 | |||
3717 | /* unpin all of our buffers */ | ||
3718 | for (i = 0; i < pinned; i++) | ||
3719 | i915_gem_object_unpin(object_list[i]); | ||
3720 | pinned = 0; | ||
3721 | 3732 | ||
3722 | /* evict everyone we can from the aperture */ | 3733 | /* The objects are in their final locations, apply the relocations. */ |
3723 | ret = i915_gem_evict_everything(dev); | 3734 | for (i = 0; i < args->buffer_count; i++) { |
3724 | if (ret && ret != -ENOSPC) | 3735 | struct drm_i915_gem_object *obj = to_intel_bo(object_list[i]); |
3736 | obj->base.pending_read_domains = 0; | ||
3737 | obj->base.pending_write_domain = 0; | ||
3738 | ret = i915_gem_execbuffer_relocate(obj, file, &exec_list[i]); | ||
3739 | if (ret) | ||
3725 | goto err; | 3740 | goto err; |
3726 | } | 3741 | } |
3727 | 3742 | ||
@@ -3734,33 +3749,29 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3734 | } | 3749 | } |
3735 | batch_obj->pending_read_domains |= I915_GEM_DOMAIN_COMMAND; | 3750 | batch_obj->pending_read_domains |= I915_GEM_DOMAIN_COMMAND; |
3736 | 3751 | ||
3737 | /* Sanity check the batch buffer, prior to moving objects */ | 3752 | /* Sanity check the batch buffer */ |
3738 | exec_offset = exec_list[args->buffer_count - 1].offset; | 3753 | exec_offset = to_intel_bo(batch_obj)->gtt_offset; |
3739 | ret = i915_gem_check_execbuffer (args, exec_offset); | 3754 | ret = i915_gem_check_execbuffer(args, exec_offset); |
3740 | if (ret != 0) { | 3755 | if (ret != 0) { |
3741 | DRM_ERROR("execbuf with invalid offset/length\n"); | 3756 | DRM_ERROR("execbuf with invalid offset/length\n"); |
3742 | goto err; | 3757 | goto err; |
3743 | } | 3758 | } |
3744 | 3759 | ||
3745 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
3746 | |||
3747 | /* Zero the global flush/invalidate flags. These | 3760 | /* Zero the global flush/invalidate flags. These |
3748 | * will be modified as new domains are computed | 3761 | * will be modified as new domains are computed |
3749 | * for each object | 3762 | * for each object |
3750 | */ | 3763 | */ |
3751 | dev->invalidate_domains = 0; | 3764 | dev->invalidate_domains = 0; |
3752 | dev->flush_domains = 0; | 3765 | dev->flush_domains = 0; |
3753 | dev_priv->flush_rings = 0; | 3766 | dev_priv->mm.flush_rings = 0; |
3754 | 3767 | ||
3755 | for (i = 0; i < args->buffer_count; i++) { | 3768 | for (i = 0; i < args->buffer_count; i++) { |
3756 | struct drm_gem_object *obj = object_list[i]; | 3769 | struct drm_gem_object *obj = object_list[i]; |
3757 | 3770 | ||
3758 | /* Compute new gpu domains and update invalidate/flush */ | 3771 | /* Compute new gpu domains and update invalidate/flush */ |
3759 | i915_gem_object_set_to_gpu_domain(obj); | 3772 | i915_gem_object_set_to_gpu_domain(obj, ring); |
3760 | } | 3773 | } |
3761 | 3774 | ||
3762 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
3763 | |||
3764 | if (dev->invalidate_domains | dev->flush_domains) { | 3775 | if (dev->invalidate_domains | dev->flush_domains) { |
3765 | #if WATCH_EXEC | 3776 | #if WATCH_EXEC |
3766 | DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", | 3777 | DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n", |
@@ -3768,38 +3779,21 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3768 | dev->invalidate_domains, | 3779 | dev->invalidate_domains, |
3769 | dev->flush_domains); | 3780 | dev->flush_domains); |
3770 | #endif | 3781 | #endif |
3771 | i915_gem_flush(dev, | 3782 | i915_gem_flush(dev, file, |
3772 | dev->invalidate_domains, | 3783 | dev->invalidate_domains, |
3773 | dev->flush_domains); | 3784 | dev->flush_domains, |
3774 | if (dev_priv->flush_rings & FLUSH_RENDER_RING) | 3785 | dev_priv->mm.flush_rings); |
3775 | (void)i915_add_request(dev, file_priv, | ||
3776 | dev->flush_domains, | ||
3777 | &dev_priv->render_ring); | ||
3778 | if (dev_priv->flush_rings & FLUSH_BSD_RING) | ||
3779 | (void)i915_add_request(dev, file_priv, | ||
3780 | dev->flush_domains, | ||
3781 | &dev_priv->bsd_ring); | ||
3782 | } | 3786 | } |
3783 | 3787 | ||
3784 | for (i = 0; i < args->buffer_count; i++) { | 3788 | for (i = 0; i < args->buffer_count; i++) { |
3785 | struct drm_gem_object *obj = object_list[i]; | 3789 | struct drm_gem_object *obj = object_list[i]; |
3786 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | ||
3787 | uint32_t old_write_domain = obj->write_domain; | 3790 | uint32_t old_write_domain = obj->write_domain; |
3788 | |||
3789 | obj->write_domain = obj->pending_write_domain; | 3791 | obj->write_domain = obj->pending_write_domain; |
3790 | if (obj->write_domain) | ||
3791 | list_move_tail(&obj_priv->gpu_write_list, | ||
3792 | &dev_priv->mm.gpu_write_list); | ||
3793 | else | ||
3794 | list_del_init(&obj_priv->gpu_write_list); | ||
3795 | |||
3796 | trace_i915_gem_object_change_domain(obj, | 3792 | trace_i915_gem_object_change_domain(obj, |
3797 | obj->read_domains, | 3793 | obj->read_domains, |
3798 | old_write_domain); | 3794 | old_write_domain); |
3799 | } | 3795 | } |
3800 | 3796 | ||
3801 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
3802 | |||
3803 | #if WATCH_COHERENCY | 3797 | #if WATCH_COHERENCY |
3804 | for (i = 0; i < args->buffer_count; i++) { | 3798 | for (i = 0; i < args->buffer_count; i++) { |
3805 | i915_gem_object_check_coherency(object_list[i], | 3799 | i915_gem_object_check_coherency(object_list[i], |
@@ -3814,9 +3808,38 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3814 | ~0); | 3808 | ~0); |
3815 | #endif | 3809 | #endif |
3816 | 3810 | ||
3811 | /* Check for any pending flips. As we only maintain a flip queue depth | ||
3812 | * of 1, we can simply insert a WAIT for the next display flip prior | ||
3813 | * to executing the batch and avoid stalling the CPU. | ||
3814 | */ | ||
3815 | flips = 0; | ||
3816 | for (i = 0; i < args->buffer_count; i++) { | ||
3817 | if (object_list[i]->write_domain) | ||
3818 | flips |= atomic_read(&to_intel_bo(object_list[i])->pending_flip); | ||
3819 | } | ||
3820 | if (flips) { | ||
3821 | int plane, flip_mask; | ||
3822 | |||
3823 | for (plane = 0; flips >> plane; plane++) { | ||
3824 | if (((flips >> plane) & 1) == 0) | ||
3825 | continue; | ||
3826 | |||
3827 | if (plane) | ||
3828 | flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; | ||
3829 | else | ||
3830 | flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; | ||
3831 | |||
3832 | intel_ring_begin(dev, ring, 2); | ||
3833 | intel_ring_emit(dev, ring, | ||
3834 | MI_WAIT_FOR_EVENT | flip_mask); | ||
3835 | intel_ring_emit(dev, ring, MI_NOOP); | ||
3836 | intel_ring_advance(dev, ring); | ||
3837 | } | ||
3838 | } | ||
3839 | |||
3817 | /* Exec the batchbuffer */ | 3840 | /* Exec the batchbuffer */ |
3818 | ret = ring->dispatch_gem_execbuffer(dev, ring, args, | 3841 | ret = ring->dispatch_gem_execbuffer(dev, ring, args, |
3819 | cliprects, exec_offset); | 3842 | cliprects, exec_offset); |
3820 | if (ret) { | 3843 | if (ret) { |
3821 | DRM_ERROR("dispatch failed %d\n", ret); | 3844 | DRM_ERROR("dispatch failed %d\n", ret); |
3822 | goto err; | 3845 | goto err; |
@@ -3826,38 +3849,21 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, | |||
3826 | * Ensure that the commands in the batch buffer are | 3849 | * Ensure that the commands in the batch buffer are |
3827 | * finished before the interrupt fires | 3850 | * finished before the interrupt fires |
3828 | */ | 3851 | */ |
3829 | flush_domains = i915_retire_commands(dev, ring); | 3852 | i915_retire_commands(dev, ring); |
3830 | |||
3831 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
3832 | 3853 | ||
3833 | /* | ||
3834 | * Get a seqno representing the execution of the current buffer, | ||
3835 | * which we can wait on. We would like to mitigate these interrupts, | ||
3836 | * likely by only creating seqnos occasionally (so that we have | ||
3837 | * *some* interrupts representing completion of buffers that we can | ||
3838 | * wait on when trying to clear up gtt space). | ||
3839 | */ | ||
3840 | seqno = i915_add_request(dev, file_priv, flush_domains, ring); | ||
3841 | BUG_ON(seqno == 0); | ||
3842 | for (i = 0; i < args->buffer_count; i++) { | 3854 | for (i = 0; i < args->buffer_count; i++) { |
3843 | struct drm_gem_object *obj = object_list[i]; | 3855 | struct drm_gem_object *obj = object_list[i]; |
3844 | obj_priv = to_intel_bo(obj); | ||
3845 | 3856 | ||
3846 | i915_gem_object_move_to_active(obj, seqno, ring); | 3857 | i915_gem_object_move_to_active(obj, ring); |
3847 | #if WATCH_LRU | 3858 | if (obj->write_domain) |
3848 | DRM_INFO("%s: move to exec list %p\n", __func__, obj); | 3859 | list_move_tail(&to_intel_bo(obj)->gpu_write_list, |
3849 | #endif | 3860 | &ring->gpu_write_list); |
3850 | } | 3861 | } |
3851 | #if WATCH_LRU | ||
3852 | i915_dump_lru(dev, __func__); | ||
3853 | #endif | ||
3854 | 3862 | ||
3855 | i915_verify_inactive(dev, __FILE__, __LINE__); | 3863 | i915_add_request(dev, file, request, ring); |
3864 | request = NULL; | ||
3856 | 3865 | ||
3857 | err: | 3866 | err: |
3858 | for (i = 0; i < pinned; i++) | ||
3859 | i915_gem_object_unpin(object_list[i]); | ||
3860 | |||
3861 | for (i = 0; i < args->buffer_count; i++) { | 3867 | for (i = 0; i < args->buffer_count; i++) { |
3862 | if (object_list[i]) { | 3868 | if (object_list[i]) { |
3863 | obj_priv = to_intel_bo(object_list[i]); | 3869 | obj_priv = to_intel_bo(object_list[i]); |
@@ -3869,22 +3875,9 @@ err: | |||
3869 | mutex_unlock(&dev->struct_mutex); | 3875 | mutex_unlock(&dev->struct_mutex); |
3870 | 3876 | ||
3871 | pre_mutex_err: | 3877 | pre_mutex_err: |
3872 | /* Copy the updated relocations out regardless of current error | ||
3873 | * state. Failure to update the relocs would mean that the next | ||
3874 | * time userland calls execbuf, it would do so with presumed offset | ||
3875 | * state that didn't match the actual object state. | ||
3876 | */ | ||
3877 | ret2 = i915_gem_put_relocs_to_user(exec_list, args->buffer_count, | ||
3878 | relocs); | ||
3879 | if (ret2 != 0) { | ||
3880 | DRM_ERROR("Failed to copy relocations back out: %d\n", ret2); | ||
3881 | |||
3882 | if (ret == 0) | ||
3883 | ret = ret2; | ||
3884 | } | ||
3885 | |||
3886 | drm_free_large(object_list); | 3878 | drm_free_large(object_list); |
3887 | kfree(cliprects); | 3879 | kfree(cliprects); |
3880 | kfree(request); | ||
3888 | 3881 | ||
3889 | return ret; | 3882 | return ret; |
3890 | } | 3883 | } |
@@ -3941,7 +3934,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
3941 | exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr; | 3934 | exec2_list[i].relocs_ptr = exec_list[i].relocs_ptr; |
3942 | exec2_list[i].alignment = exec_list[i].alignment; | 3935 | exec2_list[i].alignment = exec_list[i].alignment; |
3943 | exec2_list[i].offset = exec_list[i].offset; | 3936 | exec2_list[i].offset = exec_list[i].offset; |
3944 | if (!IS_I965G(dev)) | 3937 | if (INTEL_INFO(dev)->gen < 4) |
3945 | exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE; | 3938 | exec2_list[i].flags = EXEC_OBJECT_NEEDS_FENCE; |
3946 | else | 3939 | else |
3947 | exec2_list[i].flags = 0; | 3940 | exec2_list[i].flags = 0; |
@@ -4038,12 +4031,12 @@ int | |||
4038 | i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) | 4031 | i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) |
4039 | { | 4032 | { |
4040 | struct drm_device *dev = obj->dev; | 4033 | struct drm_device *dev = obj->dev; |
4034 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
4041 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 4035 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
4042 | int ret; | 4036 | int ret; |
4043 | 4037 | ||
4044 | BUG_ON(obj_priv->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT); | 4038 | BUG_ON(obj_priv->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT); |
4045 | 4039 | WARN_ON(i915_verify_lists(dev)); | |
4046 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
4047 | 4040 | ||
4048 | if (obj_priv->gtt_space != NULL) { | 4041 | if (obj_priv->gtt_space != NULL) { |
4049 | if (alignment == 0) | 4042 | if (alignment == 0) |
@@ -4071,14 +4064,13 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) | |||
4071 | * remove it from the inactive list | 4064 | * remove it from the inactive list |
4072 | */ | 4065 | */ |
4073 | if (obj_priv->pin_count == 1) { | 4066 | if (obj_priv->pin_count == 1) { |
4074 | atomic_inc(&dev->pin_count); | 4067 | i915_gem_info_add_pin(dev_priv, obj->size); |
4075 | atomic_add(obj->size, &dev->pin_memory); | 4068 | if (!obj_priv->active) |
4076 | if (!obj_priv->active && | 4069 | list_move_tail(&obj_priv->mm_list, |
4077 | (obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) | 4070 | &dev_priv->mm.pinned_list); |
4078 | list_del_init(&obj_priv->list); | ||
4079 | } | 4071 | } |
4080 | i915_verify_inactive(dev, __FILE__, __LINE__); | ||
4081 | 4072 | ||
4073 | WARN_ON(i915_verify_lists(dev)); | ||
4082 | return 0; | 4074 | return 0; |
4083 | } | 4075 | } |
4084 | 4076 | ||
@@ -4089,7 +4081,7 @@ i915_gem_object_unpin(struct drm_gem_object *obj) | |||
4089 | drm_i915_private_t *dev_priv = dev->dev_private; | 4081 | drm_i915_private_t *dev_priv = dev->dev_private; |
4090 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); | 4082 | struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); |
4091 | 4083 | ||
4092 | i915_verify_inactive(dev, __FILE__, __LINE__); | 4084 | WARN_ON(i915_verify_lists(dev)); |
4093 | obj_priv->pin_count--; | 4085 | obj_priv->pin_count--; |
4094 | BUG_ON(obj_priv->pin_count < 0); | 4086 | BUG_ON(obj_priv->pin_count < 0); |
4095 | BUG_ON(obj_priv->gtt_space == NULL); | 4087 | BUG_ON(obj_priv->gtt_space == NULL); |
@@ -4099,14 +4091,12 @@ i915_gem_object_unpin(struct drm_gem_object *obj) | |||
4099 | * the inactive list | 4091 | * the inactive list |
4100 | */ | 4092 | */ |
4101 | if (obj_priv->pin_count == 0) { | 4093 | if (obj_priv->pin_count == 0) { |
4102 | if (!obj_priv->active && | 4094 | if (!obj_priv->active) |
4103 | (obj->write_domain & I915_GEM_GPU_DOMAINS) == 0) | 4095 | list_move_tail(&obj_priv->mm_list, |
4104 | list_move_tail(&obj_priv->list, | ||
4105 | &dev_priv->mm.inactive_list); | 4096 | &dev_priv->mm.inactive_list); |
4106 | atomic_dec(&dev->pin_count); | 4097 | i915_gem_info_remove_pin(dev_priv, obj->size); |
4107 | atomic_sub(obj->size, &dev->pin_memory); | ||
4108 | } | 4098 | } |
4109 | i915_verify_inactive(dev, __FILE__, __LINE__); | 4099 | WARN_ON(i915_verify_lists(dev)); |
4110 | } | 4100 | } |
4111 | 4101 | ||
4112 | int | 4102 | int |
@@ -4118,41 +4108,36 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, | |||
4118 | struct drm_i915_gem_object *obj_priv; | 4108 | struct drm_i915_gem_object *obj_priv; |
4119 | int ret; | 4109 | int ret; |
4120 | 4110 | ||
4121 | mutex_lock(&dev->struct_mutex); | 4111 | ret = i915_mutex_lock_interruptible(dev); |
4112 | if (ret) | ||
4113 | return ret; | ||
4122 | 4114 | ||
4123 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 4115 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
4124 | if (obj == NULL) { | 4116 | if (obj == NULL) { |
4125 | DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n", | 4117 | ret = -ENOENT; |
4126 | args->handle); | 4118 | goto unlock; |
4127 | mutex_unlock(&dev->struct_mutex); | ||
4128 | return -ENOENT; | ||
4129 | } | 4119 | } |
4130 | obj_priv = to_intel_bo(obj); | 4120 | obj_priv = to_intel_bo(obj); |
4131 | 4121 | ||
4132 | if (obj_priv->madv != I915_MADV_WILLNEED) { | 4122 | if (obj_priv->madv != I915_MADV_WILLNEED) { |
4133 | DRM_ERROR("Attempting to pin a purgeable buffer\n"); | 4123 | DRM_ERROR("Attempting to pin a purgeable buffer\n"); |
4134 | drm_gem_object_unreference(obj); | 4124 | ret = -EINVAL; |
4135 | mutex_unlock(&dev->struct_mutex); | 4125 | goto out; |
4136 | return -EINVAL; | ||
4137 | } | 4126 | } |
4138 | 4127 | ||
4139 | if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { | 4128 | if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { |
4140 | DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", | 4129 | DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", |
4141 | args->handle); | 4130 | args->handle); |
4142 | drm_gem_object_unreference(obj); | 4131 | ret = -EINVAL; |
4143 | mutex_unlock(&dev->struct_mutex); | 4132 | goto out; |
4144 | return -EINVAL; | ||
4145 | } | 4133 | } |
4146 | 4134 | ||
4147 | obj_priv->user_pin_count++; | 4135 | obj_priv->user_pin_count++; |
4148 | obj_priv->pin_filp = file_priv; | 4136 | obj_priv->pin_filp = file_priv; |
4149 | if (obj_priv->user_pin_count == 1) { | 4137 | if (obj_priv->user_pin_count == 1) { |
4150 | ret = i915_gem_object_pin(obj, args->alignment); | 4138 | ret = i915_gem_object_pin(obj, args->alignment); |
4151 | if (ret != 0) { | 4139 | if (ret) |
4152 | drm_gem_object_unreference(obj); | 4140 | goto out; |
4153 | mutex_unlock(&dev->struct_mutex); | ||
4154 | return ret; | ||
4155 | } | ||
4156 | } | 4141 | } |
4157 | 4142 | ||
4158 | /* XXX - flush the CPU caches for pinned objects | 4143 | /* XXX - flush the CPU caches for pinned objects |
@@ -4160,10 +4145,11 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, | |||
4160 | */ | 4145 | */ |
4161 | i915_gem_object_flush_cpu_write_domain(obj); | 4146 | i915_gem_object_flush_cpu_write_domain(obj); |
4162 | args->offset = obj_priv->gtt_offset; | 4147 | args->offset = obj_priv->gtt_offset; |
4148 | out: | ||
4163 | drm_gem_object_unreference(obj); | 4149 | drm_gem_object_unreference(obj); |
4150 | unlock: | ||
4164 | mutex_unlock(&dev->struct_mutex); | 4151 | mutex_unlock(&dev->struct_mutex); |
4165 | 4152 | return ret; | |
4166 | return 0; | ||
4167 | } | 4153 | } |
4168 | 4154 | ||
4169 | int | 4155 | int |
@@ -4173,24 +4159,24 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data, | |||
4173 | struct drm_i915_gem_pin *args = data; | 4159 | struct drm_i915_gem_pin *args = data; |
4174 | struct drm_gem_object *obj; | 4160 | struct drm_gem_object *obj; |
4175 | struct drm_i915_gem_object *obj_priv; | 4161 | struct drm_i915_gem_object *obj_priv; |
4162 | int ret; | ||
4176 | 4163 | ||
4177 | mutex_lock(&dev->struct_mutex); | 4164 | ret = i915_mutex_lock_interruptible(dev); |
4165 | if (ret) | ||
4166 | return ret; | ||
4178 | 4167 | ||
4179 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 4168 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
4180 | if (obj == NULL) { | 4169 | if (obj == NULL) { |
4181 | DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n", | 4170 | ret = -ENOENT; |
4182 | args->handle); | 4171 | goto unlock; |
4183 | mutex_unlock(&dev->struct_mutex); | ||
4184 | return -ENOENT; | ||
4185 | } | 4172 | } |
4186 | |||
4187 | obj_priv = to_intel_bo(obj); | 4173 | obj_priv = to_intel_bo(obj); |
4174 | |||
4188 | if (obj_priv->pin_filp != file_priv) { | 4175 | if (obj_priv->pin_filp != file_priv) { |
4189 | DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n", | 4176 | DRM_ERROR("Not pinned by caller in i915_gem_pin_ioctl(): %d\n", |
4190 | args->handle); | 4177 | args->handle); |
4191 | drm_gem_object_unreference(obj); | 4178 | ret = -EINVAL; |
4192 | mutex_unlock(&dev->struct_mutex); | 4179 | goto out; |
4193 | return -EINVAL; | ||
4194 | } | 4180 | } |
4195 | obj_priv->user_pin_count--; | 4181 | obj_priv->user_pin_count--; |
4196 | if (obj_priv->user_pin_count == 0) { | 4182 | if (obj_priv->user_pin_count == 0) { |
@@ -4198,9 +4184,11 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data, | |||
4198 | i915_gem_object_unpin(obj); | 4184 | i915_gem_object_unpin(obj); |
4199 | } | 4185 | } |
4200 | 4186 | ||
4187 | out: | ||
4201 | drm_gem_object_unreference(obj); | 4188 | drm_gem_object_unreference(obj); |
4189 | unlock: | ||
4202 | mutex_unlock(&dev->struct_mutex); | 4190 | mutex_unlock(&dev->struct_mutex); |
4203 | return 0; | 4191 | return ret; |
4204 | } | 4192 | } |
4205 | 4193 | ||
4206 | int | 4194 | int |
@@ -4210,22 +4198,24 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
4210 | struct drm_i915_gem_busy *args = data; | 4198 | struct drm_i915_gem_busy *args = data; |
4211 | struct drm_gem_object *obj; | 4199 | struct drm_gem_object *obj; |
4212 | struct drm_i915_gem_object *obj_priv; | 4200 | struct drm_i915_gem_object *obj_priv; |
4201 | int ret; | ||
4202 | |||
4203 | ret = i915_mutex_lock_interruptible(dev); | ||
4204 | if (ret) | ||
4205 | return ret; | ||
4213 | 4206 | ||
4214 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 4207 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
4215 | if (obj == NULL) { | 4208 | if (obj == NULL) { |
4216 | DRM_ERROR("Bad handle in i915_gem_busy_ioctl(): %d\n", | 4209 | ret = -ENOENT; |
4217 | args->handle); | 4210 | goto unlock; |
4218 | return -ENOENT; | ||
4219 | } | 4211 | } |
4220 | 4212 | obj_priv = to_intel_bo(obj); | |
4221 | mutex_lock(&dev->struct_mutex); | ||
4222 | 4213 | ||
4223 | /* Count all active objects as busy, even if they are currently not used | 4214 | /* Count all active objects as busy, even if they are currently not used |
4224 | * by the gpu. Users of this interface expect objects to eventually | 4215 | * by the gpu. Users of this interface expect objects to eventually |
4225 | * become non-busy without any further actions, therefore emit any | 4216 | * become non-busy without any further actions, therefore emit any |
4226 | * necessary flushes here. | 4217 | * necessary flushes here. |
4227 | */ | 4218 | */ |
4228 | obj_priv = to_intel_bo(obj); | ||
4229 | args->busy = obj_priv->active; | 4219 | args->busy = obj_priv->active; |
4230 | if (args->busy) { | 4220 | if (args->busy) { |
4231 | /* Unconditionally flush objects, even when the gpu still uses this | 4221 | /* Unconditionally flush objects, even when the gpu still uses this |
@@ -4233,10 +4223,10 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
4233 | * use this buffer rather sooner than later, so issuing the required | 4223 | * use this buffer rather sooner than later, so issuing the required |
4234 | * flush earlier is beneficial. | 4224 | * flush earlier is beneficial. |
4235 | */ | 4225 | */ |
4236 | if (obj->write_domain) { | 4226 | if (obj->write_domain & I915_GEM_GPU_DOMAINS) |
4237 | i915_gem_flush(dev, 0, obj->write_domain); | 4227 | i915_gem_flush_ring(dev, file_priv, |
4238 | (void)i915_add_request(dev, file_priv, obj->write_domain, obj_priv->ring); | 4228 | obj_priv->ring, |
4239 | } | 4229 | 0, obj->write_domain); |
4240 | 4230 | ||
4241 | /* Update the active list for the hardware's current position. | 4231 | /* Update the active list for the hardware's current position. |
4242 | * Otherwise this only updates on a delayed timer or when irqs | 4232 | * Otherwise this only updates on a delayed timer or when irqs |
@@ -4249,8 +4239,9 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
4249 | } | 4239 | } |
4250 | 4240 | ||
4251 | drm_gem_object_unreference(obj); | 4241 | drm_gem_object_unreference(obj); |
4242 | unlock: | ||
4252 | mutex_unlock(&dev->struct_mutex); | 4243 | mutex_unlock(&dev->struct_mutex); |
4253 | return 0; | 4244 | return ret; |
4254 | } | 4245 | } |
4255 | 4246 | ||
4256 | int | 4247 | int |
@@ -4267,6 +4258,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, | |||
4267 | struct drm_i915_gem_madvise *args = data; | 4258 | struct drm_i915_gem_madvise *args = data; |
4268 | struct drm_gem_object *obj; | 4259 | struct drm_gem_object *obj; |
4269 | struct drm_i915_gem_object *obj_priv; | 4260 | struct drm_i915_gem_object *obj_priv; |
4261 | int ret; | ||
4270 | 4262 | ||
4271 | switch (args->madv) { | 4263 | switch (args->madv) { |
4272 | case I915_MADV_DONTNEED: | 4264 | case I915_MADV_DONTNEED: |
@@ -4276,22 +4268,20 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, | |||
4276 | return -EINVAL; | 4268 | return -EINVAL; |
4277 | } | 4269 | } |
4278 | 4270 | ||
4271 | ret = i915_mutex_lock_interruptible(dev); | ||
4272 | if (ret) | ||
4273 | return ret; | ||
4274 | |||
4279 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 4275 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
4280 | if (obj == NULL) { | 4276 | if (obj == NULL) { |
4281 | DRM_ERROR("Bad handle in i915_gem_madvise_ioctl(): %d\n", | 4277 | ret = -ENOENT; |
4282 | args->handle); | 4278 | goto unlock; |
4283 | return -ENOENT; | ||
4284 | } | 4279 | } |
4285 | |||
4286 | mutex_lock(&dev->struct_mutex); | ||
4287 | obj_priv = to_intel_bo(obj); | 4280 | obj_priv = to_intel_bo(obj); |
4288 | 4281 | ||
4289 | if (obj_priv->pin_count) { | 4282 | if (obj_priv->pin_count) { |
4290 | drm_gem_object_unreference(obj); | 4283 | ret = -EINVAL; |
4291 | mutex_unlock(&dev->struct_mutex); | 4284 | goto out; |
4292 | |||
4293 | DRM_ERROR("Attempted i915_gem_madvise_ioctl() on a pinned object\n"); | ||
4294 | return -EINVAL; | ||
4295 | } | 4285 | } |
4296 | 4286 | ||
4297 | if (obj_priv->madv != __I915_MADV_PURGED) | 4287 | if (obj_priv->madv != __I915_MADV_PURGED) |
@@ -4304,15 +4294,17 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, | |||
4304 | 4294 | ||
4305 | args->retained = obj_priv->madv != __I915_MADV_PURGED; | 4295 | args->retained = obj_priv->madv != __I915_MADV_PURGED; |
4306 | 4296 | ||
4297 | out: | ||
4307 | drm_gem_object_unreference(obj); | 4298 | drm_gem_object_unreference(obj); |
4299 | unlock: | ||
4308 | mutex_unlock(&dev->struct_mutex); | 4300 | mutex_unlock(&dev->struct_mutex); |
4309 | 4301 | return ret; | |
4310 | return 0; | ||
4311 | } | 4302 | } |
4312 | 4303 | ||
4313 | struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev, | 4304 | struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev, |
4314 | size_t size) | 4305 | size_t size) |
4315 | { | 4306 | { |
4307 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
4316 | struct drm_i915_gem_object *obj; | 4308 | struct drm_i915_gem_object *obj; |
4317 | 4309 | ||
4318 | obj = kzalloc(sizeof(*obj), GFP_KERNEL); | 4310 | obj = kzalloc(sizeof(*obj), GFP_KERNEL); |
@@ -4324,18 +4316,19 @@ struct drm_gem_object * i915_gem_alloc_object(struct drm_device *dev, | |||
4324 | return NULL; | 4316 | return NULL; |
4325 | } | 4317 | } |
4326 | 4318 | ||
4319 | i915_gem_info_add_obj(dev_priv, size); | ||
4320 | |||
4327 | obj->base.write_domain = I915_GEM_DOMAIN_CPU; | 4321 | obj->base.write_domain = I915_GEM_DOMAIN_CPU; |
4328 | obj->base.read_domains = I915_GEM_DOMAIN_CPU; | 4322 | obj->base.read_domains = I915_GEM_DOMAIN_CPU; |
4329 | 4323 | ||
4330 | obj->agp_type = AGP_USER_MEMORY; | 4324 | obj->agp_type = AGP_USER_MEMORY; |
4331 | obj->base.driver_private = NULL; | 4325 | obj->base.driver_private = NULL; |
4332 | obj->fence_reg = I915_FENCE_REG_NONE; | 4326 | obj->fence_reg = I915_FENCE_REG_NONE; |
4333 | INIT_LIST_HEAD(&obj->list); | 4327 | INIT_LIST_HEAD(&obj->mm_list); |
4328 | INIT_LIST_HEAD(&obj->ring_list); | ||
4334 | INIT_LIST_HEAD(&obj->gpu_write_list); | 4329 | INIT_LIST_HEAD(&obj->gpu_write_list); |
4335 | obj->madv = I915_MADV_WILLNEED; | 4330 | obj->madv = I915_MADV_WILLNEED; |
4336 | 4331 | ||
4337 | trace_i915_gem_object_create(&obj->base); | ||
4338 | |||
4339 | return &obj->base; | 4332 | return &obj->base; |
4340 | } | 4333 | } |
4341 | 4334 | ||
@@ -4355,7 +4348,7 @@ static void i915_gem_free_object_tail(struct drm_gem_object *obj) | |||
4355 | 4348 | ||
4356 | ret = i915_gem_object_unbind(obj); | 4349 | ret = i915_gem_object_unbind(obj); |
4357 | if (ret == -ERESTARTSYS) { | 4350 | if (ret == -ERESTARTSYS) { |
4358 | list_move(&obj_priv->list, | 4351 | list_move(&obj_priv->mm_list, |
4359 | &dev_priv->mm.deferred_free_list); | 4352 | &dev_priv->mm.deferred_free_list); |
4360 | return; | 4353 | return; |
4361 | } | 4354 | } |
@@ -4364,6 +4357,7 @@ static void i915_gem_free_object_tail(struct drm_gem_object *obj) | |||
4364 | i915_gem_free_mmap_offset(obj); | 4357 | i915_gem_free_mmap_offset(obj); |
4365 | 4358 | ||
4366 | drm_gem_object_release(obj); | 4359 | drm_gem_object_release(obj); |
4360 | i915_gem_info_remove_obj(dev_priv, obj->size); | ||
4367 | 4361 | ||
4368 | kfree(obj_priv->page_cpu_valid); | 4362 | kfree(obj_priv->page_cpu_valid); |
4369 | kfree(obj_priv->bit_17); | 4363 | kfree(obj_priv->bit_17); |
@@ -4394,10 +4388,7 @@ i915_gem_idle(struct drm_device *dev) | |||
4394 | 4388 | ||
4395 | mutex_lock(&dev->struct_mutex); | 4389 | mutex_lock(&dev->struct_mutex); |
4396 | 4390 | ||
4397 | if (dev_priv->mm.suspended || | 4391 | if (dev_priv->mm.suspended) { |
4398 | (dev_priv->render_ring.gem_object == NULL) || | ||
4399 | (HAS_BSD(dev) && | ||
4400 | dev_priv->bsd_ring.gem_object == NULL)) { | ||
4401 | mutex_unlock(&dev->struct_mutex); | 4392 | mutex_unlock(&dev->struct_mutex); |
4402 | return 0; | 4393 | return 0; |
4403 | } | 4394 | } |
@@ -4422,7 +4413,7 @@ i915_gem_idle(struct drm_device *dev) | |||
4422 | * And not confound mm.suspended! | 4413 | * And not confound mm.suspended! |
4423 | */ | 4414 | */ |
4424 | dev_priv->mm.suspended = 1; | 4415 | dev_priv->mm.suspended = 1; |
4425 | del_timer(&dev_priv->hangcheck_timer); | 4416 | del_timer_sync(&dev_priv->hangcheck_timer); |
4426 | 4417 | ||
4427 | i915_kernel_lost_context(dev); | 4418 | i915_kernel_lost_context(dev); |
4428 | i915_gem_cleanup_ringbuffer(dev); | 4419 | i915_gem_cleanup_ringbuffer(dev); |
@@ -4502,36 +4493,34 @@ i915_gem_init_ringbuffer(struct drm_device *dev) | |||
4502 | drm_i915_private_t *dev_priv = dev->dev_private; | 4493 | drm_i915_private_t *dev_priv = dev->dev_private; |
4503 | int ret; | 4494 | int ret; |
4504 | 4495 | ||
4505 | dev_priv->render_ring = render_ring; | ||
4506 | |||
4507 | if (!I915_NEED_GFX_HWS(dev)) { | ||
4508 | dev_priv->render_ring.status_page.page_addr | ||
4509 | = dev_priv->status_page_dmah->vaddr; | ||
4510 | memset(dev_priv->render_ring.status_page.page_addr, | ||
4511 | 0, PAGE_SIZE); | ||
4512 | } | ||
4513 | |||
4514 | if (HAS_PIPE_CONTROL(dev)) { | 4496 | if (HAS_PIPE_CONTROL(dev)) { |
4515 | ret = i915_gem_init_pipe_control(dev); | 4497 | ret = i915_gem_init_pipe_control(dev); |
4516 | if (ret) | 4498 | if (ret) |
4517 | return ret; | 4499 | return ret; |
4518 | } | 4500 | } |
4519 | 4501 | ||
4520 | ret = intel_init_ring_buffer(dev, &dev_priv->render_ring); | 4502 | ret = intel_init_render_ring_buffer(dev); |
4521 | if (ret) | 4503 | if (ret) |
4522 | goto cleanup_pipe_control; | 4504 | goto cleanup_pipe_control; |
4523 | 4505 | ||
4524 | if (HAS_BSD(dev)) { | 4506 | if (HAS_BSD(dev)) { |
4525 | dev_priv->bsd_ring = bsd_ring; | 4507 | ret = intel_init_bsd_ring_buffer(dev); |
4526 | ret = intel_init_ring_buffer(dev, &dev_priv->bsd_ring); | ||
4527 | if (ret) | 4508 | if (ret) |
4528 | goto cleanup_render_ring; | 4509 | goto cleanup_render_ring; |
4529 | } | 4510 | } |
4530 | 4511 | ||
4512 | if (HAS_BLT(dev)) { | ||
4513 | ret = intel_init_blt_ring_buffer(dev); | ||
4514 | if (ret) | ||
4515 | goto cleanup_bsd_ring; | ||
4516 | } | ||
4517 | |||
4531 | dev_priv->next_seqno = 1; | 4518 | dev_priv->next_seqno = 1; |
4532 | 4519 | ||
4533 | return 0; | 4520 | return 0; |
4534 | 4521 | ||
4522 | cleanup_bsd_ring: | ||
4523 | intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); | ||
4535 | cleanup_render_ring: | 4524 | cleanup_render_ring: |
4536 | intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); | 4525 | intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); |
4537 | cleanup_pipe_control: | 4526 | cleanup_pipe_control: |
@@ -4546,8 +4535,8 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev) | |||
4546 | drm_i915_private_t *dev_priv = dev->dev_private; | 4535 | drm_i915_private_t *dev_priv = dev->dev_private; |
4547 | 4536 | ||
4548 | intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); | 4537 | intel_cleanup_ring_buffer(dev, &dev_priv->render_ring); |
4549 | if (HAS_BSD(dev)) | 4538 | intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); |
4550 | intel_cleanup_ring_buffer(dev, &dev_priv->bsd_ring); | 4539 | intel_cleanup_ring_buffer(dev, &dev_priv->blt_ring); |
4551 | if (HAS_PIPE_CONTROL(dev)) | 4540 | if (HAS_PIPE_CONTROL(dev)) |
4552 | i915_gem_cleanup_pipe_control(dev); | 4541 | i915_gem_cleanup_pipe_control(dev); |
4553 | } | 4542 | } |
@@ -4576,15 +4565,15 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data, | |||
4576 | return ret; | 4565 | return ret; |
4577 | } | 4566 | } |
4578 | 4567 | ||
4579 | spin_lock(&dev_priv->mm.active_list_lock); | 4568 | BUG_ON(!list_empty(&dev_priv->mm.active_list)); |
4580 | BUG_ON(!list_empty(&dev_priv->render_ring.active_list)); | 4569 | BUG_ON(!list_empty(&dev_priv->render_ring.active_list)); |
4581 | BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.active_list)); | 4570 | BUG_ON(!list_empty(&dev_priv->bsd_ring.active_list)); |
4582 | spin_unlock(&dev_priv->mm.active_list_lock); | 4571 | BUG_ON(!list_empty(&dev_priv->blt_ring.active_list)); |
4583 | |||
4584 | BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); | 4572 | BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); |
4585 | BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); | 4573 | BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); |
4586 | BUG_ON(!list_empty(&dev_priv->render_ring.request_list)); | 4574 | BUG_ON(!list_empty(&dev_priv->render_ring.request_list)); |
4587 | BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.request_list)); | 4575 | BUG_ON(!list_empty(&dev_priv->bsd_ring.request_list)); |
4576 | BUG_ON(!list_empty(&dev_priv->blt_ring.request_list)); | ||
4588 | mutex_unlock(&dev->struct_mutex); | 4577 | mutex_unlock(&dev->struct_mutex); |
4589 | 4578 | ||
4590 | ret = drm_irq_install(dev); | 4579 | ret = drm_irq_install(dev); |
@@ -4626,28 +4615,34 @@ i915_gem_lastclose(struct drm_device *dev) | |||
4626 | DRM_ERROR("failed to idle hardware: %d\n", ret); | 4615 | DRM_ERROR("failed to idle hardware: %d\n", ret); |
4627 | } | 4616 | } |
4628 | 4617 | ||
4618 | static void | ||
4619 | init_ring_lists(struct intel_ring_buffer *ring) | ||
4620 | { | ||
4621 | INIT_LIST_HEAD(&ring->active_list); | ||
4622 | INIT_LIST_HEAD(&ring->request_list); | ||
4623 | INIT_LIST_HEAD(&ring->gpu_write_list); | ||
4624 | } | ||
4625 | |||
4629 | void | 4626 | void |
4630 | i915_gem_load(struct drm_device *dev) | 4627 | i915_gem_load(struct drm_device *dev) |
4631 | { | 4628 | { |
4632 | int i; | 4629 | int i; |
4633 | drm_i915_private_t *dev_priv = dev->dev_private; | 4630 | drm_i915_private_t *dev_priv = dev->dev_private; |
4634 | 4631 | ||
4635 | spin_lock_init(&dev_priv->mm.active_list_lock); | 4632 | INIT_LIST_HEAD(&dev_priv->mm.active_list); |
4636 | INIT_LIST_HEAD(&dev_priv->mm.flushing_list); | 4633 | INIT_LIST_HEAD(&dev_priv->mm.flushing_list); |
4637 | INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list); | ||
4638 | INIT_LIST_HEAD(&dev_priv->mm.inactive_list); | 4634 | INIT_LIST_HEAD(&dev_priv->mm.inactive_list); |
4635 | INIT_LIST_HEAD(&dev_priv->mm.pinned_list); | ||
4639 | INIT_LIST_HEAD(&dev_priv->mm.fence_list); | 4636 | INIT_LIST_HEAD(&dev_priv->mm.fence_list); |
4640 | INIT_LIST_HEAD(&dev_priv->mm.deferred_free_list); | 4637 | INIT_LIST_HEAD(&dev_priv->mm.deferred_free_list); |
4641 | INIT_LIST_HEAD(&dev_priv->render_ring.active_list); | 4638 | init_ring_lists(&dev_priv->render_ring); |
4642 | INIT_LIST_HEAD(&dev_priv->render_ring.request_list); | 4639 | init_ring_lists(&dev_priv->bsd_ring); |
4643 | if (HAS_BSD(dev)) { | 4640 | init_ring_lists(&dev_priv->blt_ring); |
4644 | INIT_LIST_HEAD(&dev_priv->bsd_ring.active_list); | ||
4645 | INIT_LIST_HEAD(&dev_priv->bsd_ring.request_list); | ||
4646 | } | ||
4647 | for (i = 0; i < 16; i++) | 4641 | for (i = 0; i < 16; i++) |
4648 | INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); | 4642 | INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list); |
4649 | INIT_DELAYED_WORK(&dev_priv->mm.retire_work, | 4643 | INIT_DELAYED_WORK(&dev_priv->mm.retire_work, |
4650 | i915_gem_retire_work_handler); | 4644 | i915_gem_retire_work_handler); |
4645 | init_completion(&dev_priv->error_completion); | ||
4651 | spin_lock(&shrink_list_lock); | 4646 | spin_lock(&shrink_list_lock); |
4652 | list_add(&dev_priv->mm.shrink_list, &shrink_list); | 4647 | list_add(&dev_priv->mm.shrink_list, &shrink_list); |
4653 | spin_unlock(&shrink_list_lock); | 4648 | spin_unlock(&shrink_list_lock); |
@@ -4666,21 +4661,30 @@ i915_gem_load(struct drm_device *dev) | |||
4666 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) | 4661 | if (!drm_core_check_feature(dev, DRIVER_MODESET)) |
4667 | dev_priv->fence_reg_start = 3; | 4662 | dev_priv->fence_reg_start = 3; |
4668 | 4663 | ||
4669 | if (IS_I965G(dev) || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) | 4664 | if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) |
4670 | dev_priv->num_fence_regs = 16; | 4665 | dev_priv->num_fence_regs = 16; |
4671 | else | 4666 | else |
4672 | dev_priv->num_fence_regs = 8; | 4667 | dev_priv->num_fence_regs = 8; |
4673 | 4668 | ||
4674 | /* Initialize fence registers to zero */ | 4669 | /* Initialize fence registers to zero */ |
4675 | if (IS_I965G(dev)) { | 4670 | switch (INTEL_INFO(dev)->gen) { |
4671 | case 6: | ||
4672 | for (i = 0; i < 16; i++) | ||
4673 | I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), 0); | ||
4674 | break; | ||
4675 | case 5: | ||
4676 | case 4: | ||
4676 | for (i = 0; i < 16; i++) | 4677 | for (i = 0; i < 16; i++) |
4677 | I915_WRITE64(FENCE_REG_965_0 + (i * 8), 0); | 4678 | I915_WRITE64(FENCE_REG_965_0 + (i * 8), 0); |
4678 | } else { | 4679 | break; |
4679 | for (i = 0; i < 8; i++) | 4680 | case 3: |
4680 | I915_WRITE(FENCE_REG_830_0 + (i * 4), 0); | ||
4681 | if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) | 4681 | if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) |
4682 | for (i = 0; i < 8; i++) | 4682 | for (i = 0; i < 8; i++) |
4683 | I915_WRITE(FENCE_REG_945_8 + (i * 4), 0); | 4683 | I915_WRITE(FENCE_REG_945_8 + (i * 4), 0); |
4684 | case 2: | ||
4685 | for (i = 0; i < 8; i++) | ||
4686 | I915_WRITE(FENCE_REG_830_0 + (i * 4), 0); | ||
4687 | break; | ||
4684 | } | 4688 | } |
4685 | i915_gem_detect_bit_6_swizzle(dev); | 4689 | i915_gem_detect_bit_6_swizzle(dev); |
4686 | init_waitqueue_head(&dev_priv->pending_flip_queue); | 4690 | init_waitqueue_head(&dev_priv->pending_flip_queue); |
@@ -4690,8 +4694,8 @@ i915_gem_load(struct drm_device *dev) | |||
4690 | * Create a physically contiguous memory object for this object | 4694 | * Create a physically contiguous memory object for this object |
4691 | * e.g. for cursor + overlay regs | 4695 | * e.g. for cursor + overlay regs |
4692 | */ | 4696 | */ |
4693 | int i915_gem_init_phys_object(struct drm_device *dev, | 4697 | static int i915_gem_init_phys_object(struct drm_device *dev, |
4694 | int id, int size, int align) | 4698 | int id, int size, int align) |
4695 | { | 4699 | { |
4696 | drm_i915_private_t *dev_priv = dev->dev_private; | 4700 | drm_i915_private_t *dev_priv = dev->dev_private; |
4697 | struct drm_i915_gem_phys_object *phys_obj; | 4701 | struct drm_i915_gem_phys_object *phys_obj; |
@@ -4723,7 +4727,7 @@ kfree_obj: | |||
4723 | return ret; | 4727 | return ret; |
4724 | } | 4728 | } |
4725 | 4729 | ||
4726 | void i915_gem_free_phys_object(struct drm_device *dev, int id) | 4730 | static void i915_gem_free_phys_object(struct drm_device *dev, int id) |
4727 | { | 4731 | { |
4728 | drm_i915_private_t *dev_priv = dev->dev_private; | 4732 | drm_i915_private_t *dev_priv = dev->dev_private; |
4729 | struct drm_i915_gem_phys_object *phys_obj; | 4733 | struct drm_i915_gem_phys_object *phys_obj; |
@@ -4868,18 +4872,25 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj, | |||
4868 | return 0; | 4872 | return 0; |
4869 | } | 4873 | } |
4870 | 4874 | ||
4871 | void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv) | 4875 | void i915_gem_release(struct drm_device *dev, struct drm_file *file) |
4872 | { | 4876 | { |
4873 | struct drm_i915_file_private *i915_file_priv = file_priv->driver_priv; | 4877 | struct drm_i915_file_private *file_priv = file->driver_priv; |
4874 | 4878 | ||
4875 | /* Clean up our request list when the client is going away, so that | 4879 | /* Clean up our request list when the client is going away, so that |
4876 | * later retire_requests won't dereference our soon-to-be-gone | 4880 | * later retire_requests won't dereference our soon-to-be-gone |
4877 | * file_priv. | 4881 | * file_priv. |
4878 | */ | 4882 | */ |
4879 | mutex_lock(&dev->struct_mutex); | 4883 | spin_lock(&file_priv->mm.lock); |
4880 | while (!list_empty(&i915_file_priv->mm.request_list)) | 4884 | while (!list_empty(&file_priv->mm.request_list)) { |
4881 | list_del_init(i915_file_priv->mm.request_list.next); | 4885 | struct drm_i915_gem_request *request; |
4882 | mutex_unlock(&dev->struct_mutex); | 4886 | |
4887 | request = list_first_entry(&file_priv->mm.request_list, | ||
4888 | struct drm_i915_gem_request, | ||
4889 | client_list); | ||
4890 | list_del(&request->client_list); | ||
4891 | request->file_priv = NULL; | ||
4892 | } | ||
4893 | spin_unlock(&file_priv->mm.lock); | ||
4883 | } | 4894 | } |
4884 | 4895 | ||
4885 | static int | 4896 | static int |
@@ -4888,12 +4899,10 @@ i915_gpu_is_active(struct drm_device *dev) | |||
4888 | drm_i915_private_t *dev_priv = dev->dev_private; | 4899 | drm_i915_private_t *dev_priv = dev->dev_private; |
4889 | int lists_empty; | 4900 | int lists_empty; |
4890 | 4901 | ||
4891 | spin_lock(&dev_priv->mm.active_list_lock); | ||
4892 | lists_empty = list_empty(&dev_priv->mm.flushing_list) && | 4902 | lists_empty = list_empty(&dev_priv->mm.flushing_list) && |
4893 | list_empty(&dev_priv->render_ring.active_list); | 4903 | list_empty(&dev_priv->render_ring.active_list) && |
4894 | if (HAS_BSD(dev)) | 4904 | list_empty(&dev_priv->bsd_ring.active_list) && |
4895 | lists_empty &= list_empty(&dev_priv->bsd_ring.active_list); | 4905 | list_empty(&dev_priv->blt_ring.active_list); |
4896 | spin_unlock(&dev_priv->mm.active_list_lock); | ||
4897 | 4906 | ||
4898 | return !lists_empty; | 4907 | return !lists_empty; |
4899 | } | 4908 | } |
@@ -4915,7 +4924,7 @@ i915_gem_shrink(struct shrinker *shrink, int nr_to_scan, gfp_t gfp_mask) | |||
4915 | if (mutex_trylock(&dev->struct_mutex)) { | 4924 | if (mutex_trylock(&dev->struct_mutex)) { |
4916 | list_for_each_entry(obj_priv, | 4925 | list_for_each_entry(obj_priv, |
4917 | &dev_priv->mm.inactive_list, | 4926 | &dev_priv->mm.inactive_list, |
4918 | list) | 4927 | mm_list) |
4919 | cnt++; | 4928 | cnt++; |
4920 | mutex_unlock(&dev->struct_mutex); | 4929 | mutex_unlock(&dev->struct_mutex); |
4921 | } | 4930 | } |
@@ -4941,7 +4950,7 @@ rescan: | |||
4941 | 4950 | ||
4942 | list_for_each_entry_safe(obj_priv, next_obj, | 4951 | list_for_each_entry_safe(obj_priv, next_obj, |
4943 | &dev_priv->mm.inactive_list, | 4952 | &dev_priv->mm.inactive_list, |
4944 | list) { | 4953 | mm_list) { |
4945 | if (i915_gem_object_is_purgeable(obj_priv)) { | 4954 | if (i915_gem_object_is_purgeable(obj_priv)) { |
4946 | i915_gem_object_unbind(&obj_priv->base); | 4955 | i915_gem_object_unbind(&obj_priv->base); |
4947 | if (--nr_to_scan <= 0) | 4956 | if (--nr_to_scan <= 0) |
@@ -4970,7 +4979,7 @@ rescan: | |||
4970 | 4979 | ||
4971 | list_for_each_entry_safe(obj_priv, next_obj, | 4980 | list_for_each_entry_safe(obj_priv, next_obj, |
4972 | &dev_priv->mm.inactive_list, | 4981 | &dev_priv->mm.inactive_list, |
4973 | list) { | 4982 | mm_list) { |
4974 | if (nr_to_scan > 0) { | 4983 | if (nr_to_scan > 0) { |
4975 | i915_gem_object_unbind(&obj_priv->base); | 4984 | i915_gem_object_unbind(&obj_priv->base); |
4976 | nr_to_scan--; | 4985 | nr_to_scan--; |