0467-drm-vc4-Use-runtime-PM-to-power-cycle-the-device-whe.patch 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. From 7aa7785c89ccb0203b5eb9a3b26d5358cb2543c0 Mon Sep 17 00:00:00 2001
  2. From: Eric Anholt <eric@anholt.net>
  3. Date: Mon, 8 Feb 2016 12:59:02 -0800
  4. Subject: [PATCH] drm/vc4: Use runtime PM to power cycle the device when the
  5. GPU hangs.
  6. This gets us functional GPU reset again, like we had until a refactor
  7. at merge time. Tested with a little patch to stuff in a broken binner
  8. job every 100 frames.
  9. Signed-off-by: Eric Anholt <eric@anholt.net>
  10. (cherry picked from commit 36cb6253f9383fd9a59ee7b8458c6232ef48577c)
  11. ---
  12. drivers/gpu/drm/vc4/vc4_drv.h | 6 +++++-
  13. drivers/gpu/drm/vc4/vc4_gem.c | 26 +++++++++++++++++++++-----
  14. 2 files changed, 26 insertions(+), 6 deletions(-)
  15. --- a/drivers/gpu/drm/vc4/vc4_drv.h
  16. +++ b/drivers/gpu/drm/vc4/vc4_drv.h
  17. @@ -104,6 +104,11 @@ struct vc4_dev {
  18. struct vc4_bo *overflow_mem;
  19. struct work_struct overflow_mem_work;
  20. + int power_refcount;
  21. +
  22. + /* Mutex controlling the power refcount. */
  23. + struct mutex power_lock;
  24. +
  25. struct {
  26. struct timer_list timer;
  27. struct work_struct reset_work;
  28. @@ -495,7 +500,6 @@ void vc4_plane_async_set_fb(struct drm_p
  29. extern struct platform_driver vc4_v3d_driver;
  30. int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused);
  31. int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused);
  32. -int vc4_v3d_set_power(struct vc4_dev *vc4, bool on);
  33. /* vc4_validate.c */
  34. int
  35. --- a/drivers/gpu/drm/vc4/vc4_gem.c
  36. +++ b/drivers/gpu/drm/vc4/vc4_gem.c
  37. @@ -261,8 +261,16 @@ vc4_reset(struct drm_device *dev)
  38. struct vc4_dev *vc4 = to_vc4_dev(dev);
  39. DRM_INFO("Resetting GPU.\n");
  40. - vc4_v3d_set_power(vc4, false);
  41. - vc4_v3d_set_power(vc4, true);
  42. +
  43. + mutex_lock(&vc4->power_lock);
  44. + if (vc4->power_refcount) {
  45. + /* Power the device off and back on the by dropping the
  46. + * reference on runtime PM.
  47. + */
  48. + pm_runtime_put_sync_suspend(&vc4->v3d->pdev->dev);
  49. + pm_runtime_get_sync(&vc4->v3d->pdev->dev);
  50. + }
  51. + mutex_unlock(&vc4->power_lock);
  52. vc4_irq_reset(dev);
  53. @@ -709,7 +717,10 @@ vc4_complete_exec(struct drm_device *dev
  54. }
  55. mutex_unlock(&dev->struct_mutex);
  56. - pm_runtime_put(&vc4->v3d->pdev->dev);
  57. + mutex_lock(&vc4->power_lock);
  58. + if (--vc4->power_refcount == 0)
  59. + pm_runtime_put(&vc4->v3d->pdev->dev);
  60. + mutex_unlock(&vc4->power_lock);
  61. kfree(exec);
  62. }
  63. @@ -851,7 +862,7 @@ vc4_submit_cl_ioctl(struct drm_device *d
  64. struct vc4_dev *vc4 = to_vc4_dev(dev);
  65. struct drm_vc4_submit_cl *args = data;
  66. struct vc4_exec_info *exec;
  67. - int ret;
  68. + int ret = 0;
  69. if ((args->flags & ~VC4_SUBMIT_CL_USE_CLEAR_COLOR) != 0) {
  70. DRM_ERROR("Unknown flags: 0x%02x\n", args->flags);
  71. @@ -864,7 +875,10 @@ vc4_submit_cl_ioctl(struct drm_device *d
  72. return -ENOMEM;
  73. }
  74. - ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
  75. + mutex_lock(&vc4->power_lock);
  76. + if (vc4->power_refcount++ == 0)
  77. + ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
  78. + mutex_unlock(&vc4->power_lock);
  79. if (ret < 0) {
  80. kfree(exec);
  81. return ret;
  82. @@ -925,6 +939,8 @@ vc4_gem_init(struct drm_device *dev)
  83. (unsigned long)dev);
  84. INIT_WORK(&vc4->job_done_work, vc4_job_done_work);
  85. +
  86. + mutex_init(&vc4->power_lock);
  87. }
  88. void