aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJerome Glisse <jglisse@redhat.com>2009-09-09 16:23:45 -0400
committerDave Airlie <airlied@redhat.com>2009-09-09 20:12:41 -0400
commit45600232b3dbb97817c9e15de848c742901893e1 (patch)
treedc8953d21cfc3d48faedcabef87e62dee3242ee1
parent5d93b135fc051be3740cbe55729fc7b86a7069d7 (diff)
drm/radeon/kms: wait for cp idle before stopping it.
If we stop CP and that it's still processing thing GPU hang might happen, this patch wait for CP idle (the wait can timeout) so we can avoid shutting down CP at bad time. This is especialy usefull when reseting the GPU as it seems GPU reset fails to properly reset CP when the CP wasn't stop after being idle. Signed-off-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/radeon/r100.c18
-rw-r--r--drivers/gpu/drm/radeon/r100d.h60
2 files changed, 78 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index 5708c07ce733..938a6936d929 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -487,6 +487,21 @@ int r100_copy_blit(struct radeon_device *rdev,
487/* 487/*
488 * CP 488 * CP
489 */ 489 */
490static int r100_cp_wait_for_idle(struct radeon_device *rdev)
491{
492 unsigned i;
493 u32 tmp;
494
495 for (i = 0; i < rdev->usec_timeout; i++) {
496 tmp = RREG32(R_000E40_RBBM_STATUS);
497 if (!G_000E40_CP_CMDSTRM_BUSY(tmp)) {
498 return 0;
499 }
500 udelay(1);
501 }
502 return -1;
503}
504
490void r100_ring_start(struct radeon_device *rdev) 505void r100_ring_start(struct radeon_device *rdev)
491{ 506{
492 int r; 507 int r;
@@ -715,6 +730,9 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
715 730
716void r100_cp_fini(struct radeon_device *rdev) 731void r100_cp_fini(struct radeon_device *rdev)
717{ 732{
733 if (r100_cp_wait_for_idle(rdev)) {
734 DRM_ERROR("Wait for CP idle timeout, shutting down CP.\n");
735 }
718 /* Disable ring */ 736 /* Disable ring */
719 rdev->cp.ready = false; 737 rdev->cp.ready = false;
720 WREG32(RADEON_CP_CSQ_CNTL, 0); 738 WREG32(RADEON_CP_CSQ_CNTL, 0);
diff --git a/drivers/gpu/drm/radeon/r100d.h b/drivers/gpu/drm/radeon/r100d.h
index 6da7d92c321c..1d951ab77dce 100644
--- a/drivers/gpu/drm/radeon/r100d.h
+++ b/drivers/gpu/drm/radeon/r100d.h
@@ -73,4 +73,64 @@
73#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1) 73#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1)
74#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) 74#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
75 75
76/* Registers */
77#define R_000E40_RBBM_STATUS 0x000E40
78#define S_000E40_CMDFIFO_AVAIL(x) (((x) & 0x7F) << 0)
79#define G_000E40_CMDFIFO_AVAIL(x) (((x) >> 0) & 0x7F)
80#define C_000E40_CMDFIFO_AVAIL 0xFFFFFF80
81#define S_000E40_HIRQ_ON_RBB(x) (((x) & 0x1) << 8)
82#define G_000E40_HIRQ_ON_RBB(x) (((x) >> 8) & 0x1)
83#define C_000E40_HIRQ_ON_RBB 0xFFFFFEFF
84#define S_000E40_CPRQ_ON_RBB(x) (((x) & 0x1) << 9)
85#define G_000E40_CPRQ_ON_RBB(x) (((x) >> 9) & 0x1)
86#define C_000E40_CPRQ_ON_RBB 0xFFFFFDFF
87#define S_000E40_CFRQ_ON_RBB(x) (((x) & 0x1) << 10)
88#define G_000E40_CFRQ_ON_RBB(x) (((x) >> 10) & 0x1)
89#define C_000E40_CFRQ_ON_RBB 0xFFFFFBFF
90#define S_000E40_HIRQ_IN_RTBUF(x) (((x) & 0x1) << 11)
91#define G_000E40_HIRQ_IN_RTBUF(x) (((x) >> 11) & 0x1)
92#define C_000E40_HIRQ_IN_RTBUF 0xFFFFF7FF
93#define S_000E40_CPRQ_IN_RTBUF(x) (((x) & 0x1) << 12)
94#define G_000E40_CPRQ_IN_RTBUF(x) (((x) >> 12) & 0x1)
95#define C_000E40_CPRQ_IN_RTBUF 0xFFFFEFFF
96#define S_000E40_CFRQ_IN_RTBUF(x) (((x) & 0x1) << 13)
97#define G_000E40_CFRQ_IN_RTBUF(x) (((x) >> 13) & 0x1)
98#define C_000E40_CFRQ_IN_RTBUF 0xFFFFDFFF
99#define S_000E40_CF_PIPE_BUSY(x) (((x) & 0x1) << 14)
100#define G_000E40_CF_PIPE_BUSY(x) (((x) >> 14) & 0x1)
101#define C_000E40_CF_PIPE_BUSY 0xFFFFBFFF
102#define S_000E40_ENG_EV_BUSY(x) (((x) & 0x1) << 15)
103#define G_000E40_ENG_EV_BUSY(x) (((x) >> 15) & 0x1)
104#define C_000E40_ENG_EV_BUSY 0xFFFF7FFF
105#define S_000E40_CP_CMDSTRM_BUSY(x) (((x) & 0x1) << 16)
106#define G_000E40_CP_CMDSTRM_BUSY(x) (((x) >> 16) & 0x1)
107#define C_000E40_CP_CMDSTRM_BUSY 0xFFFEFFFF
108#define S_000E40_E2_BUSY(x) (((x) & 0x1) << 17)
109#define G_000E40_E2_BUSY(x) (((x) >> 17) & 0x1)
110#define C_000E40_E2_BUSY 0xFFFDFFFF
111#define S_000E40_RB2D_BUSY(x) (((x) & 0x1) << 18)
112#define G_000E40_RB2D_BUSY(x) (((x) >> 18) & 0x1)
113#define C_000E40_RB2D_BUSY 0xFFFBFFFF
114#define S_000E40_RB3D_BUSY(x) (((x) & 0x1) << 19)
115#define G_000E40_RB3D_BUSY(x) (((x) >> 19) & 0x1)
116#define C_000E40_RB3D_BUSY 0xFFF7FFFF
117#define S_000E40_SE_BUSY(x) (((x) & 0x1) << 20)
118#define G_000E40_SE_BUSY(x) (((x) >> 20) & 0x1)
119#define C_000E40_SE_BUSY 0xFFEFFFFF
120#define S_000E40_RE_BUSY(x) (((x) & 0x1) << 21)
121#define G_000E40_RE_BUSY(x) (((x) >> 21) & 0x1)
122#define C_000E40_RE_BUSY 0xFFDFFFFF
123#define S_000E40_TAM_BUSY(x) (((x) & 0x1) << 22)
124#define G_000E40_TAM_BUSY(x) (((x) >> 22) & 0x1)
125#define C_000E40_TAM_BUSY 0xFFBFFFFF
126#define S_000E40_TDM_BUSY(x) (((x) & 0x1) << 23)
127#define G_000E40_TDM_BUSY(x) (((x) >> 23) & 0x1)
128#define C_000E40_TDM_BUSY 0xFF7FFFFF
129#define S_000E40_PB_BUSY(x) (((x) & 0x1) << 24)
130#define G_000E40_PB_BUSY(x) (((x) >> 24) & 0x1)
131#define C_000E40_PB_BUSY 0xFEFFFFFF
132#define S_000E40_GUI_ACTIVE(x) (((x) & 0x1) << 31)
133#define G_000E40_GUI_ACTIVE(x) (((x) >> 31) & 0x1)
134#define C_000E40_GUI_ACTIVE 0x7FFFFFFF
135
76#endif 136#endif