0286-drm-vc4-Fix-spurious-GPU-resets-due-to-BO-reuse.patch 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. From cc502edf8c0515a8b3c410d4bfda002a4db88e4f Mon Sep 17 00:00:00 2001
  2. From: Eric Anholt <eric@anholt.net>
  3. Date: Mon, 8 Feb 2016 11:19:14 -0800
  4. Subject: [PATCH 286/381] drm/vc4: Fix spurious GPU resets due to BO reuse.
  5. We were tracking the "where are the head pointers pointing" globally,
  6. so if another job reused the same BOs and execution was at the same
  7. point as last time we checked, we'd stop and trigger a reset even
  8. though the GPU had made progress.
  9. Signed-off-by: Eric Anholt <eric@anholt.net>
  10. (cherry picked from commit c4ce60dc30912df09b2438f1e5594eae1ef64d1e)
  11. ---
  12. drivers/gpu/drm/vc4/vc4_drv.h | 6 +++++-
  13. drivers/gpu/drm/vc4/vc4_gem.c | 19 ++++++++++++++-----
  14. 2 files changed, 19 insertions(+), 6 deletions(-)
  15. --- a/drivers/gpu/drm/vc4/vc4_drv.h
  16. +++ b/drivers/gpu/drm/vc4/vc4_drv.h
  17. @@ -93,7 +93,6 @@ struct vc4_dev {
  18. struct work_struct overflow_mem_work;
  19. struct {
  20. - uint32_t last_ct0ca, last_ct1ca;
  21. struct timer_list timer;
  22. struct work_struct reset_work;
  23. } hangcheck;
  24. @@ -203,6 +202,11 @@ struct vc4_exec_info {
  25. /* Sequence number for this bin/render job. */
  26. uint64_t seqno;
  27. + /* Last current addresses the hardware was processing when the
  28. + * hangcheck timer checked on us.
  29. + */
  30. + uint32_t last_ct0ca, last_ct1ca;
  31. +
  32. /* Kernel-space copy of the ioctl arguments */
  33. struct drm_vc4_submit_cl *args;
  34. --- a/drivers/gpu/drm/vc4/vc4_gem.c
  35. +++ b/drivers/gpu/drm/vc4/vc4_gem.c
  36. @@ -271,10 +271,17 @@ vc4_hangcheck_elapsed(unsigned long data
  37. struct drm_device *dev = (struct drm_device *)data;
  38. struct vc4_dev *vc4 = to_vc4_dev(dev);
  39. uint32_t ct0ca, ct1ca;
  40. + unsigned long irqflags;
  41. + struct vc4_exec_info *exec;
  42. +
  43. + spin_lock_irqsave(&vc4->job_lock, irqflags);
  44. + exec = vc4_first_job(vc4);
  45. /* If idle, we can stop watching for hangs. */
  46. - if (list_empty(&vc4->job_list))
  47. + if (!exec) {
  48. + spin_unlock_irqrestore(&vc4->job_lock, irqflags);
  49. return;
  50. + }
  51. ct0ca = V3D_READ(V3D_CTNCA(0));
  52. ct1ca = V3D_READ(V3D_CTNCA(1));
  53. @@ -282,14 +289,16 @@ vc4_hangcheck_elapsed(unsigned long data
  54. /* If we've made any progress in execution, rearm the timer
  55. * and wait.
  56. */
  57. - if (ct0ca != vc4->hangcheck.last_ct0ca ||
  58. - ct1ca != vc4->hangcheck.last_ct1ca) {
  59. - vc4->hangcheck.last_ct0ca = ct0ca;
  60. - vc4->hangcheck.last_ct1ca = ct1ca;
  61. + if (ct0ca != exec->last_ct0ca || ct1ca != exec->last_ct1ca) {
  62. + exec->last_ct0ca = ct0ca;
  63. + exec->last_ct1ca = ct1ca;
  64. + spin_unlock_irqrestore(&vc4->job_lock, irqflags);
  65. vc4_queue_hangcheck(dev);
  66. return;
  67. }
  68. + spin_unlock_irqrestore(&vc4->job_lock, irqflags);
  69. +
  70. /* We've gone too long with no progress, reset. This has to
  71. * be done from a work struct, since resetting can sleep and
  72. * this timer hook isn't allowed to.