Skip to content

Commit 36cb625

Browse files
committed
drm/vc4: Use runtime PM to power cycle the device when the GPU hangs.
This gets us functional GPU reset again, like we had until a refactor at merge time. Tested with a little patch to stuff in a broken binner job every 100 frames. Signed-off-by: Eric Anholt <[email protected]>
1 parent 001bdb5 commit 36cb625

File tree

3 files changed

+26
-18
lines changed

3 files changed

+26
-18
lines changed

drivers/gpu/drm/vc4/vc4_drv.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ struct vc4_dev {
9191
struct vc4_bo *overflow_mem;
9292
struct work_struct overflow_mem_work;
9393

94+
int power_refcount;
95+
96+
/* Mutex controlling the power refcount. */
97+
struct mutex power_lock;
98+
9499
struct {
95100
struct timer_list timer;
96101
struct work_struct reset_work;
@@ -439,7 +444,6 @@ void vc4_plane_async_set_fb(struct drm_plane *plane,
439444
extern struct platform_driver vc4_v3d_driver;
440445
int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused);
441446
int vc4_v3d_debugfs_regs(struct seq_file *m, void *unused);
442-
int vc4_v3d_set_power(struct vc4_dev *vc4, bool on);
443447

444448
/* vc4_validate.c */
445449
int

drivers/gpu/drm/vc4/vc4_gem.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,16 @@ vc4_reset(struct drm_device *dev)
229229
struct vc4_dev *vc4 = to_vc4_dev(dev);
230230

231231
DRM_INFO("Resetting GPU.\n");
232-
vc4_v3d_set_power(vc4, false);
233-
vc4_v3d_set_power(vc4, true);
232+
233+
mutex_lock(&vc4->power_lock);
234+
if (vc4->power_refcount) {
235+
/* Power the device off and back on the by dropping the
236+
* reference on runtime PM.
237+
*/
238+
pm_runtime_put_sync_suspend(&vc4->v3d->pdev->dev);
239+
pm_runtime_get_sync(&vc4->v3d->pdev->dev);
240+
}
241+
mutex_unlock(&vc4->power_lock);
234242

235243
vc4_irq_reset(dev);
236244

@@ -641,7 +649,10 @@ vc4_complete_exec(struct drm_device *dev, struct vc4_exec_info *exec)
641649
}
642650
mutex_unlock(&dev->struct_mutex);
643651

644-
pm_runtime_put(&vc4->v3d->pdev->dev);
652+
mutex_lock(&vc4->power_lock);
653+
if (--vc4->power_refcount == 0)
654+
pm_runtime_put(&vc4->v3d->pdev->dev);
655+
mutex_unlock(&vc4->power_lock);
645656

646657
kfree(exec);
647658
}
@@ -783,7 +794,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
783794
struct vc4_dev *vc4 = to_vc4_dev(dev);
784795
struct drm_vc4_submit_cl *args = data;
785796
struct vc4_exec_info *exec;
786-
int ret;
797+
int ret = 0;
787798

788799
if ((args->flags & ~VC4_SUBMIT_CL_USE_CLEAR_COLOR) != 0) {
789800
DRM_ERROR("Unknown flags: 0x%02x\n", args->flags);
@@ -796,7 +807,10 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
796807
return -ENOMEM;
797808
}
798809

799-
ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
810+
mutex_lock(&vc4->power_lock);
811+
if (vc4->power_refcount++ == 0)
812+
ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev);
813+
mutex_unlock(&vc4->power_lock);
800814
if (ret < 0) {
801815
kfree(exec);
802816
return ret;
@@ -856,6 +870,8 @@ vc4_gem_init(struct drm_device *dev)
856870
(unsigned long)dev);
857871

858872
INIT_WORK(&vc4->job_done_work, vc4_job_done_work);
873+
874+
mutex_init(&vc4->power_lock);
859875
}
860876

861877
void

drivers/gpu/drm/vc4/vc4_v3d.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -145,18 +145,6 @@ int vc4_v3d_debugfs_ident(struct seq_file *m, void *unused)
145145
}
146146
#endif /* CONFIG_DEBUG_FS */
147147

148-
int
149-
vc4_v3d_set_power(struct vc4_dev *vc4, bool on)
150-
{
151-
/* XXX: This interface is needed for GPU reset, and the way to
152-
* do it is to turn our power domain off and back on. We
153-
* can't just reset from within the driver, because the reset
154-
* bits are in the power domain's register area, and get set
155-
* during the poweron process.
156-
*/
157-
return 0;
158-
}
159-
160148
static void vc4_v3d_init_hw(struct drm_device *dev)
161149
{
162150
struct vc4_dev *vc4 = to_vc4_dev(dev);

0 commit comments

Comments
 (0)