aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2013-09-19 19:06:48 -0400
committerDave Airlie <airlied@redhat.com>2013-09-19 19:06:48 -0400
commit6ddf2ed6e00396883b3123032ccb4416205aac7c (patch)
treeaa544e6288bfc4c9aba53df49be798bb2226ffe8 /drivers/gpu/drm
parent9808cc946943e4c260ff270f8b2e7884dd6968f8 (diff)
parent7e60353a1f5335ecd63b1c54897c2aa75874aaee (diff)
Merge branch 'msm-fixes-3.12' of git://people.freedesktop.org/~robclark/linux into drm-fixes
A couple small msm fixes. Plus drop of set_need_resched(). * 'msm-fixes-3.12' of git://people.freedesktop.org/~robclark/linux: drm/msm: drop unnecessary set_need_resched() drm/msm: fix potential NULL pointer dereference drm/msm: workaround for missing irq drm/msm: return -EBUSY if bo still active drm/msm: fix return value check in ERR_PTR() drm/msm: fix cmdstream size check drm/msm: hangcheck harder drm/msm: handle read vs write fences
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c10
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c50
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h8
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c34
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h2
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c24
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c24
7 files changed, 107 insertions, 45 deletions
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index a60584763b61..a0b9d8a95b16 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -124,6 +124,8 @@ void adreno_recover(struct msm_gpu *gpu)
124 124
125 /* reset completed fence seqno, just discard anything pending: */ 125 /* reset completed fence seqno, just discard anything pending: */
126 adreno_gpu->memptrs->fence = gpu->submitted_fence; 126 adreno_gpu->memptrs->fence = gpu->submitted_fence;
127 adreno_gpu->memptrs->rptr = 0;
128 adreno_gpu->memptrs->wptr = 0;
127 129
128 gpu->funcs->pm_resume(gpu); 130 gpu->funcs->pm_resume(gpu);
129 ret = gpu->funcs->hw_init(gpu); 131 ret = gpu->funcs->hw_init(gpu);
@@ -229,7 +231,7 @@ void adreno_idle(struct msm_gpu *gpu)
229 return; 231 return;
230 } while(time_before(jiffies, t)); 232 } while(time_before(jiffies, t));
231 233
232 DRM_ERROR("timeout waiting for %s to drain ringbuffer!\n", gpu->name); 234 DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name);
233 235
234 /* TODO maybe we need to reset GPU here to recover from hang? */ 236 /* TODO maybe we need to reset GPU here to recover from hang? */
235} 237}
@@ -256,11 +258,17 @@ void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords)
256{ 258{
257 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); 259 struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
258 uint32_t freedwords; 260 uint32_t freedwords;
261 unsigned long t = jiffies + ADRENO_IDLE_TIMEOUT;
259 do { 262 do {
260 uint32_t size = gpu->rb->size / 4; 263 uint32_t size = gpu->rb->size / 4;
261 uint32_t wptr = get_wptr(gpu->rb); 264 uint32_t wptr = get_wptr(gpu->rb);
262 uint32_t rptr = adreno_gpu->memptrs->rptr; 265 uint32_t rptr = adreno_gpu->memptrs->rptr;
263 freedwords = (rptr + (size - 1) - wptr) % size; 266 freedwords = (rptr + (size - 1) - wptr) % size;
267
268 if (time_after(jiffies, t)) {
269 DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name);
270 break;
271 }
264 } while(freedwords < ndwords); 272 } while(freedwords < ndwords);
265} 273}
266 274
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 864c9773636b..008d772384c7 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -499,25 +499,41 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
499 struct timespec *timeout) 499 struct timespec *timeout)
500{ 500{
501 struct msm_drm_private *priv = dev->dev_private; 501 struct msm_drm_private *priv = dev->dev_private;
502 unsigned long timeout_jiffies = timespec_to_jiffies(timeout);
503 unsigned long start_jiffies = jiffies;
504 unsigned long remaining_jiffies;
505 int ret; 502 int ret;
506 503
507 if (time_after(start_jiffies, timeout_jiffies)) 504 if (!priv->gpu)
508 remaining_jiffies = 0; 505 return 0;
509 else 506
510 remaining_jiffies = timeout_jiffies - start_jiffies; 507 if (fence > priv->gpu->submitted_fence) {
511 508 DRM_ERROR("waiting on invalid fence: %u (of %u)\n",
512 ret = wait_event_interruptible_timeout(priv->fence_event, 509 fence, priv->gpu->submitted_fence);
513 priv->completed_fence >= fence, 510 return -EINVAL;
514 remaining_jiffies); 511 }
515 if (ret == 0) { 512
516 DBG("timeout waiting for fence: %u (completed: %u)", 513 if (!timeout) {
517 fence, priv->completed_fence); 514 /* no-wait: */
518 ret = -ETIMEDOUT; 515 ret = fence_completed(dev, fence) ? 0 : -EBUSY;
519 } else if (ret != -ERESTARTSYS) { 516 } else {
520 ret = 0; 517 unsigned long timeout_jiffies = timespec_to_jiffies(timeout);
518 unsigned long start_jiffies = jiffies;
519 unsigned long remaining_jiffies;
520
521 if (time_after(start_jiffies, timeout_jiffies))
522 remaining_jiffies = 0;
523 else
524 remaining_jiffies = timeout_jiffies - start_jiffies;
525
526 ret = wait_event_interruptible_timeout(priv->fence_event,
527 fence_completed(dev, fence),
528 remaining_jiffies);
529
530 if (ret == 0) {
531 DBG("timeout waiting for fence: %u (completed: %u)",
532 fence, priv->completed_fence);
533 ret = -ETIMEDOUT;
534 } else if (ret != -ERESTARTSYS) {
535 ret = 0;
536 }
521 } 537 }
522 538
523 return ret; 539 return ret;
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 80d75094bf0a..df8f1d084bc1 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -153,7 +153,7 @@ void *msm_gem_vaddr(struct drm_gem_object *obj);
153int msm_gem_queue_inactive_work(struct drm_gem_object *obj, 153int msm_gem_queue_inactive_work(struct drm_gem_object *obj,
154 struct work_struct *work); 154 struct work_struct *work);
155void msm_gem_move_to_active(struct drm_gem_object *obj, 155void msm_gem_move_to_active(struct drm_gem_object *obj,
156 struct msm_gpu *gpu, uint32_t fence); 156 struct msm_gpu *gpu, bool write, uint32_t fence);
157void msm_gem_move_to_inactive(struct drm_gem_object *obj); 157void msm_gem_move_to_inactive(struct drm_gem_object *obj);
158int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, 158int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
159 struct timespec *timeout); 159 struct timespec *timeout);
@@ -191,6 +191,12 @@ u32 msm_readl(const void __iomem *addr);
191#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) 191#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
192#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) 192#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
193 193
194static inline bool fence_completed(struct drm_device *dev, uint32_t fence)
195{
196 struct msm_drm_private *priv = dev->dev_private;
197 return priv->completed_fence >= fence;
198}
199
194static inline int align_pitch(int width, int bpp) 200static inline int align_pitch(int width, int bpp)
195{ 201{
196 int bytespp = (bpp + 7) / 8; 202 int bytespp = (bpp + 7) / 8;
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 6b5a6c8c7658..29eacfa29cfb 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -40,9 +40,9 @@ static struct page **get_pages(struct drm_gem_object *obj)
40 } 40 }
41 41
42 msm_obj->sgt = drm_prime_pages_to_sg(p, npages); 42 msm_obj->sgt = drm_prime_pages_to_sg(p, npages);
43 if (!msm_obj->sgt) { 43 if (IS_ERR(msm_obj->sgt)) {
44 dev_err(dev->dev, "failed to allocate sgt\n"); 44 dev_err(dev->dev, "failed to allocate sgt\n");
45 return ERR_PTR(-ENOMEM); 45 return ERR_CAST(msm_obj->sgt);
46 } 46 }
47 47
48 msm_obj->pages = p; 48 msm_obj->pages = p;
@@ -159,7 +159,6 @@ out_unlock:
159out: 159out:
160 switch (ret) { 160 switch (ret) {
161 case -EAGAIN: 161 case -EAGAIN:
162 set_need_resched();
163 case 0: 162 case 0:
164 case -ERESTARTSYS: 163 case -ERESTARTSYS:
165 case -EINTR: 164 case -EINTR:
@@ -393,11 +392,14 @@ int msm_gem_queue_inactive_work(struct drm_gem_object *obj,
393} 392}
394 393
395void msm_gem_move_to_active(struct drm_gem_object *obj, 394void msm_gem_move_to_active(struct drm_gem_object *obj,
396 struct msm_gpu *gpu, uint32_t fence) 395 struct msm_gpu *gpu, bool write, uint32_t fence)
397{ 396{
398 struct msm_gem_object *msm_obj = to_msm_bo(obj); 397 struct msm_gem_object *msm_obj = to_msm_bo(obj);
399 msm_obj->gpu = gpu; 398 msm_obj->gpu = gpu;
400 msm_obj->fence = fence; 399 if (write)
400 msm_obj->write_fence = fence;
401 else
402 msm_obj->read_fence = fence;
401 list_del_init(&msm_obj->mm_list); 403 list_del_init(&msm_obj->mm_list);
402 list_add_tail(&msm_obj->mm_list, &gpu->active_list); 404 list_add_tail(&msm_obj->mm_list, &gpu->active_list);
403} 405}
@@ -411,7 +413,8 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj)
411 WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 413 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
412 414
413 msm_obj->gpu = NULL; 415 msm_obj->gpu = NULL;
414 msm_obj->fence = 0; 416 msm_obj->read_fence = 0;
417 msm_obj->write_fence = 0;
415 list_del_init(&msm_obj->mm_list); 418 list_del_init(&msm_obj->mm_list);
416 list_add_tail(&msm_obj->mm_list, &priv->inactive_list); 419 list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
417 420
@@ -433,8 +436,18 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
433 struct msm_gem_object *msm_obj = to_msm_bo(obj); 436 struct msm_gem_object *msm_obj = to_msm_bo(obj);
434 int ret = 0; 437 int ret = 0;
435 438
436 if (is_active(msm_obj) && !(op & MSM_PREP_NOSYNC)) 439 if (is_active(msm_obj)) {
437 ret = msm_wait_fence_interruptable(dev, msm_obj->fence, timeout); 440 uint32_t fence = 0;
441
442 if (op & MSM_PREP_READ)
443 fence = msm_obj->write_fence;
444 if (op & MSM_PREP_WRITE)
445 fence = max(fence, msm_obj->read_fence);
446 if (op & MSM_PREP_NOSYNC)
447 timeout = NULL;
448
449 ret = msm_wait_fence_interruptable(dev, fence, timeout);
450 }
438 451
439 /* TODO cache maintenance */ 452 /* TODO cache maintenance */
440 453
@@ -455,9 +468,10 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
455 uint64_t off = drm_vma_node_start(&obj->vma_node); 468 uint64_t off = drm_vma_node_start(&obj->vma_node);
456 469
457 WARN_ON(!mutex_is_locked(&dev->struct_mutex)); 470 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
458 seq_printf(m, "%08x: %c(%d) %2d (%2d) %08llx %p %d\n", 471 seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %d\n",
459 msm_obj->flags, is_active(msm_obj) ? 'A' : 'I', 472 msm_obj->flags, is_active(msm_obj) ? 'A' : 'I',
460 msm_obj->fence, obj->name, obj->refcount.refcount.counter, 473 msm_obj->read_fence, msm_obj->write_fence,
474 obj->name, obj->refcount.refcount.counter,
461 off, msm_obj->vaddr, obj->size); 475 off, msm_obj->vaddr, obj->size);
462} 476}
463 477
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index d746f13d283c..0676f32e2c6a 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -36,7 +36,7 @@ struct msm_gem_object {
36 */ 36 */
37 struct list_head mm_list; 37 struct list_head mm_list;
38 struct msm_gpu *gpu; /* non-null if active */ 38 struct msm_gpu *gpu; /* non-null if active */
39 uint32_t fence; 39 uint32_t read_fence, write_fence;
40 40
41 /* Transiently in the process of submit ioctl, objects associated 41 /* Transiently in the process of submit ioctl, objects associated
42 * with the submit are on submit->bo_list.. this only lasts for 42 * with the submit are on submit->bo_list.. this only lasts for
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 3e1ef3a00f60..5281d4bc37f7 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -78,7 +78,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
78 } 78 }
79 79
80 if (submit_bo.flags & BO_INVALID_FLAGS) { 80 if (submit_bo.flags & BO_INVALID_FLAGS) {
81 DBG("invalid flags: %x", submit_bo.flags); 81 DRM_ERROR("invalid flags: %x\n", submit_bo.flags);
82 ret = -EINVAL; 82 ret = -EINVAL;
83 goto out_unlock; 83 goto out_unlock;
84 } 84 }
@@ -92,7 +92,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
92 */ 92 */
93 obj = idr_find(&file->object_idr, submit_bo.handle); 93 obj = idr_find(&file->object_idr, submit_bo.handle);
94 if (!obj) { 94 if (!obj) {
95 DBG("invalid handle %u at index %u", submit_bo.handle, i); 95 DRM_ERROR("invalid handle %u at index %u\n", submit_bo.handle, i);
96 ret = -EINVAL; 96 ret = -EINVAL;
97 goto out_unlock; 97 goto out_unlock;
98 } 98 }
@@ -100,7 +100,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
100 msm_obj = to_msm_bo(obj); 100 msm_obj = to_msm_bo(obj);
101 101
102 if (!list_empty(&msm_obj->submit_entry)) { 102 if (!list_empty(&msm_obj->submit_entry)) {
103 DBG("handle %u at index %u already on submit list", 103 DRM_ERROR("handle %u at index %u already on submit list\n",
104 submit_bo.handle, i); 104 submit_bo.handle, i);
105 ret = -EINVAL; 105 ret = -EINVAL;
106 goto out_unlock; 106 goto out_unlock;
@@ -216,8 +216,9 @@ static int submit_bo(struct msm_gem_submit *submit, uint32_t idx,
216 struct msm_gem_object **obj, uint32_t *iova, bool *valid) 216 struct msm_gem_object **obj, uint32_t *iova, bool *valid)
217{ 217{
218 if (idx >= submit->nr_bos) { 218 if (idx >= submit->nr_bos) {
219 DBG("invalid buffer index: %u (out of %u)", idx, submit->nr_bos); 219 DRM_ERROR("invalid buffer index: %u (out of %u)\n",
220 return EINVAL; 220 idx, submit->nr_bos);
221 return -EINVAL;
221 } 222 }
222 223
223 if (obj) 224 if (obj)
@@ -239,7 +240,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
239 int ret; 240 int ret;
240 241
241 if (offset % 4) { 242 if (offset % 4) {
242 DBG("non-aligned cmdstream buffer: %u", offset); 243 DRM_ERROR("non-aligned cmdstream buffer: %u\n", offset);
243 return -EINVAL; 244 return -EINVAL;
244 } 245 }
245 246
@@ -266,7 +267,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
266 return -EFAULT; 267 return -EFAULT;
267 268
268 if (submit_reloc.submit_offset % 4) { 269 if (submit_reloc.submit_offset % 4) {
269 DBG("non-aligned reloc offset: %u", 270 DRM_ERROR("non-aligned reloc offset: %u\n",
270 submit_reloc.submit_offset); 271 submit_reloc.submit_offset);
271 return -EINVAL; 272 return -EINVAL;
272 } 273 }
@@ -276,7 +277,7 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
276 277
277 if ((off >= (obj->base.size / 4)) || 278 if ((off >= (obj->base.size / 4)) ||
278 (off < last_offset)) { 279 (off < last_offset)) {
279 DBG("invalid offset %u at reloc %u", off, i); 280 DRM_ERROR("invalid offset %u at reloc %u\n", off, i);
280 return -EINVAL; 281 return -EINVAL;
281 } 282 }
282 283
@@ -374,14 +375,15 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
374 goto out; 375 goto out;
375 376
376 if (submit_cmd.size % 4) { 377 if (submit_cmd.size % 4) {
377 DBG("non-aligned cmdstream buffer size: %u", 378 DRM_ERROR("non-aligned cmdstream buffer size: %u\n",
378 submit_cmd.size); 379 submit_cmd.size);
379 ret = -EINVAL; 380 ret = -EINVAL;
380 goto out; 381 goto out;
381 } 382 }
382 383
383 if (submit_cmd.size >= msm_obj->base.size) { 384 if ((submit_cmd.size + submit_cmd.submit_offset) >=
384 DBG("invalid cmdstream size: %u", submit_cmd.size); 385 msm_obj->base.size) {
386 DRM_ERROR("invalid cmdstream size: %u\n", submit_cmd.size);
385 ret = -EINVAL; 387 ret = -EINVAL;
386 goto out; 388 goto out;
387 } 389 }
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index e1e1ec9321ff..3bab937965d1 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -29,13 +29,14 @@
29static void bs_init(struct msm_gpu *gpu, struct platform_device *pdev) 29static void bs_init(struct msm_gpu *gpu, struct platform_device *pdev)
30{ 30{
31 struct drm_device *dev = gpu->dev; 31 struct drm_device *dev = gpu->dev;
32 struct kgsl_device_platform_data *pdata = pdev->dev.platform_data; 32 struct kgsl_device_platform_data *pdata;
33 33
34 if (!pdev) { 34 if (!pdev) {
35 dev_err(dev->dev, "could not find dtv pdata\n"); 35 dev_err(dev->dev, "could not find dtv pdata\n");
36 return; 36 return;
37 } 37 }
38 38
39 pdata = pdev->dev.platform_data;
39 if (pdata->bus_scale_table) { 40 if (pdata->bus_scale_table) {
40 gpu->bsc = msm_bus_scale_register_client(pdata->bus_scale_table); 41 gpu->bsc = msm_bus_scale_register_client(pdata->bus_scale_table);
41 DBG("bus scale client: %08x", gpu->bsc); 42 DBG("bus scale client: %08x", gpu->bsc);
@@ -230,6 +231,8 @@ static void hangcheck_timer_reset(struct msm_gpu *gpu)
230static void hangcheck_handler(unsigned long data) 231static void hangcheck_handler(unsigned long data)
231{ 232{
232 struct msm_gpu *gpu = (struct msm_gpu *)data; 233 struct msm_gpu *gpu = (struct msm_gpu *)data;
234 struct drm_device *dev = gpu->dev;
235 struct msm_drm_private *priv = dev->dev_private;
233 uint32_t fence = gpu->funcs->last_fence(gpu); 236 uint32_t fence = gpu->funcs->last_fence(gpu);
234 237
235 if (fence != gpu->hangcheck_fence) { 238 if (fence != gpu->hangcheck_fence) {
@@ -237,14 +240,22 @@ static void hangcheck_handler(unsigned long data)
237 gpu->hangcheck_fence = fence; 240 gpu->hangcheck_fence = fence;
238 } else if (fence < gpu->submitted_fence) { 241 } else if (fence < gpu->submitted_fence) {
239 /* no progress and not done.. hung! */ 242 /* no progress and not done.. hung! */
240 struct msm_drm_private *priv = gpu->dev->dev_private;
241 gpu->hangcheck_fence = fence; 243 gpu->hangcheck_fence = fence;
244 dev_err(dev->dev, "%s: hangcheck detected gpu lockup!\n",
245 gpu->name);
246 dev_err(dev->dev, "%s: completed fence: %u\n",
247 gpu->name, fence);
248 dev_err(dev->dev, "%s: submitted fence: %u\n",
249 gpu->name, gpu->submitted_fence);
242 queue_work(priv->wq, &gpu->recover_work); 250 queue_work(priv->wq, &gpu->recover_work);
243 } 251 }
244 252
245 /* if still more pending work, reset the hangcheck timer: */ 253 /* if still more pending work, reset the hangcheck timer: */
246 if (gpu->submitted_fence > gpu->hangcheck_fence) 254 if (gpu->submitted_fence > gpu->hangcheck_fence)
247 hangcheck_timer_reset(gpu); 255 hangcheck_timer_reset(gpu);
256
257 /* workaround for missing irq: */
258 queue_work(priv->wq, &gpu->retire_work);
248} 259}
249 260
250/* 261/*
@@ -265,7 +276,8 @@ static void retire_worker(struct work_struct *work)
265 obj = list_first_entry(&gpu->active_list, 276 obj = list_first_entry(&gpu->active_list,
266 struct msm_gem_object, mm_list); 277 struct msm_gem_object, mm_list);
267 278
268 if (obj->fence <= fence) { 279 if ((obj->read_fence <= fence) &&
280 (obj->write_fence <= fence)) {
269 /* move to inactive: */ 281 /* move to inactive: */
270 msm_gem_move_to_inactive(&obj->base); 282 msm_gem_move_to_inactive(&obj->base);
271 msm_gem_put_iova(&obj->base, gpu->id); 283 msm_gem_put_iova(&obj->base, gpu->id);
@@ -321,7 +333,11 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
321 submit->gpu->id, &iova); 333 submit->gpu->id, &iova);
322 } 334 }
323 335
324 msm_gem_move_to_active(&msm_obj->base, gpu, submit->fence); 336 if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
337 msm_gem_move_to_active(&msm_obj->base, gpu, false, submit->fence);
338
339 if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
340 msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);
325 } 341 }
326 hangcheck_timer_reset(gpu); 342 hangcheck_timer_reset(gpu);
327 mutex_unlock(&dev->struct_mutex); 343 mutex_unlock(&dev->struct_mutex);