aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm/msm_gpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/msm/msm_gpu.c')
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c52
1 files changed, 48 insertions, 4 deletions
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 4a0dce587745..8f70d9248ac5 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -24,7 +24,7 @@
24 * Power Management: 24 * Power Management:
25 */ 25 */
26 26
27#ifdef CONFIG_MSM_BUS_SCALING 27#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
28#include <mach/board.h> 28#include <mach/board.h>
29static void bs_init(struct msm_gpu *gpu) 29static void bs_init(struct msm_gpu *gpu)
30{ 30{
@@ -265,6 +265,8 @@ static void inactive_start(struct msm_gpu *gpu)
265 * Hangcheck detection for locked gpu: 265 * Hangcheck detection for locked gpu:
266 */ 266 */
267 267
268static void retire_submits(struct msm_gpu *gpu, uint32_t fence);
269
268static void recover_worker(struct work_struct *work) 270static void recover_worker(struct work_struct *work)
269{ 271{
270 struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work); 272 struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work);
@@ -274,8 +276,19 @@ static void recover_worker(struct work_struct *work)
274 276
275 mutex_lock(&dev->struct_mutex); 277 mutex_lock(&dev->struct_mutex);
276 if (msm_gpu_active(gpu)) { 278 if (msm_gpu_active(gpu)) {
279 struct msm_gem_submit *submit;
280 uint32_t fence = gpu->funcs->last_fence(gpu);
281
282 /* retire completed submits, plus the one that hung: */
283 retire_submits(gpu, fence + 1);
284
277 inactive_cancel(gpu); 285 inactive_cancel(gpu);
278 gpu->funcs->recover(gpu); 286 gpu->funcs->recover(gpu);
287
288 /* replay the remaining submits after the one that hung: */
289 list_for_each_entry(submit, &gpu->submit_list, node) {
290 gpu->funcs->submit(gpu, submit, NULL);
291 }
279 } 292 }
280 mutex_unlock(&dev->struct_mutex); 293 mutex_unlock(&dev->struct_mutex);
281 294
@@ -418,6 +431,27 @@ out:
418 * Cmdstream submission/retirement: 431 * Cmdstream submission/retirement:
419 */ 432 */
420 433
434static void retire_submits(struct msm_gpu *gpu, uint32_t fence)
435{
436 struct drm_device *dev = gpu->dev;
437
438 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
439
440 while (!list_empty(&gpu->submit_list)) {
441 struct msm_gem_submit *submit;
442
443 submit = list_first_entry(&gpu->submit_list,
444 struct msm_gem_submit, node);
445
446 if (submit->fence <= fence) {
447 list_del(&submit->node);
448 kfree(submit);
449 } else {
450 break;
451 }
452 }
453}
454
421static void retire_worker(struct work_struct *work) 455static void retire_worker(struct work_struct *work)
422{ 456{
423 struct msm_gpu *gpu = container_of(work, struct msm_gpu, retire_work); 457 struct msm_gpu *gpu = container_of(work, struct msm_gpu, retire_work);
@@ -428,6 +462,8 @@ static void retire_worker(struct work_struct *work)
428 462
429 mutex_lock(&dev->struct_mutex); 463 mutex_lock(&dev->struct_mutex);
430 464
465 retire_submits(gpu, fence);
466
431 while (!list_empty(&gpu->active_list)) { 467 while (!list_empty(&gpu->active_list)) {
432 struct msm_gem_object *obj; 468 struct msm_gem_object *obj;
433 469
@@ -467,21 +503,22 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
467 struct msm_drm_private *priv = dev->dev_private; 503 struct msm_drm_private *priv = dev->dev_private;
468 int i, ret; 504 int i, ret;
469 505
506 WARN_ON(!mutex_is_locked(&dev->struct_mutex));
507
470 submit->fence = ++priv->next_fence; 508 submit->fence = ++priv->next_fence;
471 509
472 gpu->submitted_fence = submit->fence; 510 gpu->submitted_fence = submit->fence;
473 511
474 inactive_cancel(gpu); 512 inactive_cancel(gpu);
475 513
514 list_add_tail(&submit->node, &gpu->submit_list);
515
476 msm_rd_dump_submit(submit); 516 msm_rd_dump_submit(submit);
477 517
478 gpu->submitted_fence = submit->fence; 518 gpu->submitted_fence = submit->fence;
479 519
480 update_sw_cntrs(gpu); 520 update_sw_cntrs(gpu);
481 521
482 ret = gpu->funcs->submit(gpu, submit, ctx);
483 priv->lastctx = ctx;
484
485 for (i = 0; i < submit->nr_bos; i++) { 522 for (i = 0; i < submit->nr_bos; i++) {
486 struct msm_gem_object *msm_obj = submit->bos[i].obj; 523 struct msm_gem_object *msm_obj = submit->bos[i].obj;
487 524
@@ -505,6 +542,10 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
505 if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE) 542 if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
506 msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence); 543 msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);
507 } 544 }
545
546 ret = gpu->funcs->submit(gpu, submit, ctx);
547 priv->lastctx = ctx;
548
508 hangcheck_timer_reset(gpu); 549 hangcheck_timer_reset(gpu);
509 550
510 return ret; 551 return ret;
@@ -522,6 +563,7 @@ static irqreturn_t irq_handler(int irq, void *data)
522 563
523static const char *clk_names[] = { 564static const char *clk_names[] = {
524 "src_clk", "core_clk", "iface_clk", "mem_clk", "mem_iface_clk", 565 "src_clk", "core_clk", "iface_clk", "mem_clk", "mem_iface_clk",
566 "alt_mem_iface_clk",
525}; 567};
526 568
527int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, 569int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
@@ -544,6 +586,8 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
544 INIT_WORK(&gpu->inactive_work, inactive_worker); 586 INIT_WORK(&gpu->inactive_work, inactive_worker);
545 INIT_WORK(&gpu->recover_work, recover_worker); 587 INIT_WORK(&gpu->recover_work, recover_worker);
546 588
589 INIT_LIST_HEAD(&gpu->submit_list);
590
547 setup_timer(&gpu->inactive_timer, inactive_handler, 591 setup_timer(&gpu->inactive_timer, inactive_handler,
548 (unsigned long)gpu); 592 (unsigned long)gpu);
549 setup_timer(&gpu->hangcheck_timer, hangcheck_handler, 593 setup_timer(&gpu->hangcheck_timer, hangcheck_handler,