device driver: fix oops in radeon driver due to incorrect value from hardware
Subsystems (2)
PATCH 1/1 device driver: fix oops in radeon driver due to incorrect value from hardware
Added a check for the radeon ring buffer write index in r600.c which reads 0xffffffff on resume. This results in an Oops during radeon_ring_write. Masking the value averts this.
This problem is not seen to be fixed in 3.0 r600.c as well.
Detailed analysis of the problem can be found at -
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/820746/
---
BUG: unable to handle kernel paging request at fa501ffc - Oops at r600_cp_start+0x48/0x380 in r600_cp_resume+0x345/0x580 [radeon]
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600.c 2011-08-08 05:29:21.744417857 +0530 renamed from drivers/gpu/drm/radeon/r600.c.orig 2011-08-05 15:39:40.824612700 +0530 +2 -0
@@ -2218,6 +2218,8 @@ int r600_cp_resume(struct radeon_device rdev->cp.rptr = RREG32(CP_RB_RPTR); rdev->cp.wptr = RREG32(CP_RB_WPTR); + /* protect against crazy HW on resume */ + rdev->cp.wptr &= rdev->cp.ptr_mask; r600_cp_start(rdev); rdev->cp.ready = true;
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or
(b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or
(c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it.
(d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved.
Quoted 24 lines · Mayank Rungta
Added a check for the radeon ring buffer write index in
r600.cwhich reads0xffffffffon resume. This results in an Oops duringradeon_ring_write. Masking the value averts this.This problem is not seen to be fixed in 3.0
r600.cas well.Detailed analysis of the problem can be found at -
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/820746/
---
BUG: unable to handle kernel paging request at fa501ffc - Oops at r600_cp_start+0x48/0x380 in r600_cp_resume+0x345/0x580 [radeon]
drivers/gpu/drm/radeon/r600.c--- linux-2.6.38/drivers/gpu/drm/radeon/r600.c.orig 2011-08-05
15:39:40.824612700 +0530
+++linux-2.6.38/drivers/gpu/drm/radeon/r600.c2011-08-08
05:29:21.744417857 +0530
drivers/gpu/drm/radeon/r600.c 2011-08-08 05:29:21.744417857 +0530 int r600_cp_resume(struct radeon_device · line 2222
Quoted 5 lines
drivers/gpu/drm/radeon/r600.c 2011-08-08 05:29:21.744417857 +0530 renamed from drivers/gpu/drm/radeon/r600.c.orig 2011-08-05 15:39:40.824612700 +0530 +2
-0@@ -2218,6 +2218,8 @@ int r600_cp_resume(struct radeon_device rdev->cp.rptr = RREG32(CP_RB_RPTR); rdev->cp.wptr = RREG32(CP_RB_WPTR); + /* protect against crazy HW on resume */ + rdev->cp.wptr &= rdev->cp.ptr_mask;
The indentation of the lines you're adding doesn't match the surrounding lines.
Although the same workaround is already in r100.c, I wonder if we shouldn't rather try and eliminate all reads from the CP_RB_WPTR register, at least other than for debugging purposes. Alex, what do you think?
Otherwise, this should probably be added in evergreen.c as well.
Review int r600_cp_resume(struct radeon_device · line 2224
Quoted 3 lines
(quoted diff) +0
-0Developer's Certificate of Origin 1.1
No need to include all this text, just the *-by: tags are enough.
Signature · 6 lines
Earthling Michel Dänzer | http://www.amd.com Libre software enthusiast | Debian, X and DRI developer _______________________________________________ dri-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/dri-devel
Quoted 26 lines · Michel Dänzer
Quoted 25 lines · Mayank Rungta
Added a check for the radeon ring buffer write index in
r600.cwhich reads0xffffffffon resume. This results in an Oops duringradeon_ring_write. Masking the value averts this.This problem is not seen to be fixed in 3.0
r600.cas well.Detailed analysis of the problem can be found at -
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/820746/
---
BUG: unable to handle kernel paging request at fa501ffc - Oops at r600_cp_start+0x48/0x380 in r600_cp_resume+0x345/0x580 [radeon]
drivers/gpu/drm/radeon/r600.c--- linux-2.6.38/drivers/gpu/drm/radeon/r600.c.orig 2011-08-05
15:39:40.824612700 +0530
+++linux-2.6.38/drivers/gpu/drm/radeon/r600.c2011-08-08
05:29:21.744417857 +0530(quoted diff) +0
-0@@ -2218,6 +2218,8 @@ int r600_cp_resume(struct radeon_device
Quoted 7 lines
drivers/gpu/drm/radeon/r600.c 2011-08-08 05:29:21.744417857 +0530 int r600_cp_resume(struct radeon_device
Quoted 4 lines
drivers/gpu/drm/radeon/r600.c 2011-08-08 05:29:21.744417857 +0530 renamed from drivers/gpu/drm/radeon/r600.c.orig 2011-08-05 15:39:40.824612700 +0530 +2
-0rdev->cp.rptr = RREG32(CP_RB_RPTR); rdev->cp.wptr = RREG32(CP_RB_WPTR); + /* protect against crazy HW on resume */ + rdev->cp.wptr&= rdev->cp.ptr_mask;The indentation of the lines you're adding doesn't match the surrounding lines.
Sorry. This looked fine in the mail I sent. I shall be careful in future.
Quoted 7 lines
Although the same workaround is already in
r100.c, I wonder if we shouldn't rather try and eliminate all reads from theCP_RB_WPTRregister, at least other than for debugging purposes. Alex, what do you think?
Quoted 9 lines
Otherwise, this should probably be added in
evergreen.cas well.Review int r600_cp_resume(struct radeon_device · line 2224
Quoted 3 lines
(quoted diff) +0
-0Developer's Certificate of Origin 1.1No need to include all this text, just the *-by: tags are enough.
Point taken.
2011/8/10 Michel Dänzer <[email protected]>:
Quoted 35 lines · Mayank Rungta
Quoted 24 lines
Added a check for the radeon ring buffer write index in
r600.cwhich reads0xffffffffon resume. This results in an Oops duringradeon_ring_write. Masking the value averts this.This problem is not seen to be fixed in 3.0
r600.cas well.Detailed analysis of the problem can be found at -
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/820746/
---
BUG: unable to handle kernel paging request at fa501ffc - Oops at r600_cp_start+0x48/0x380 in r600_cp_resume+0x345/0x580 [radeon]
drivers/gpu/drm/radeon/r600.c--- linux-2.6.38/drivers/gpu/drm/radeon/r600.c.orig 2011-08-05 15:39:40.824612700 +0530
+++linux-2.6.38/drivers/gpu/drm/radeon/r600.c2011-08-08 05:29:21.744417857 +0530drivers/gpu/drm/radeon/r600.c 2011-08-08 05:29:21.744417857 +0530 int r600_cp_resume(struct radeon_device · line 2222
Quoted 5 lines
drivers/gpu/drm/radeon/r600.c 2011-08-08 05:29:21.744417857 +0530 renamed from drivers/gpu/drm/radeon/r600.c.orig 2011-08-05 15:39:40.824612700 +0530 +2
-0@@ -2218,6 +2218,8 @@ int r600_cp_resume(struct radeon_device rdev->cp.rptr = RREG32(CP_RB_RPTR); rdev->cp.wptr = RREG32(CP_RB_WPTR); + /* protect against crazy HW on resume */ + rdev->cp.wptr &= rdev->cp.ptr_mask;The indentation of the lines you're adding doesn't match the surrounding lines.
Quoted 4 lines
Although the same workaround is already in
r100.c, I wonder if we shouldn't rather try and eliminate all reads from theCP_RB_WPTRregister, at least other than for debugging purposes. Alex, what do you think?
Either this or reset the registers to 0 or a saved value on resume rather than reading from them.
Quoted 3 lines
Otherwise, this should probably be added in
evergreen.cas well.
Yes, and ni.c as well.
Alex
Quoted 16 lines
Quoted 4 lines
Developer's Certificate of Origin 1.1
[...]
No need to include all this text, just the *-by: tags are enough.
--
Earthling Michel Dänzer | http://www.amd.com
Libre software enthusiast | Debian, X and DRI developer
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
Quoted 37 lines · Alex Deucher
2011/8/10 Michel Dänzer <[email protected]>:
Quoted 26 lines · Mayank Rungta
Quoted 25 lines
Added a check for the radeon ring buffer write index in
r600.cwhich reads0xffffffffon resume. This results in an Oops duringradeon_ring_write. Masking the value averts this.This problem is not seen to be fixed in 3.0
r600.cas well.Detailed analysis of the problem can be found at -
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/820746/
---
BUG: unable to handle kernel paging request at fa501ffc - Oops at r600_cp_start+0x48/0x380 in r600_cp_resume+0x345/0x580 [radeon]
drivers/gpu/drm/radeon/r600.c--- linux-2.6.38/drivers/gpu/drm/radeon/r600.c.orig 2011-08-05
15:39:40.824612700 +0530
+++linux-2.6.38/drivers/gpu/drm/radeon/r600.c2011-08-08
05:29:21.744417857 +0530(quoted diff) +0
-0@@ -2218,6 +2218,8 @@ int r600_cp_resume(struct radeon_deviceQuoted 9 lines
Review int r600_cp_resume(struct radeon_device · line 2222
Quoted 4 lines
(quoted diff) +2
-0rdev->cp.rptr = RREG32(CP_RB_RPTR); rdev->cp.wptr = RREG32(CP_RB_WPTR); + /* protect against crazy HW on resume */ + rdev->cp.wptr &= rdev->cp.ptr_mask;Although the same workaround is already in
r100.c, I wonder if we shouldn't rather try and eliminate all reads from theCP_RB_WPTRregister, at least other than for debugging purposes. Alex, what do you think?
Quoted 2 lines
Either this or reset the registers to 0 or a saved value on resume rather than reading from them.
The patch below is what I had in mind. Does this fix the problem above?
From c564bc8e6d449216d74ee134d5bf470221f79e8d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michel=20D=C3=A4nzer?= <[email protected]>
Date: Thu, 8 Sep 2011 11:09:39 +0200
Subject: [PATCH] drm/radeon: Don't read from CP ring write pointer registers.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Apparently this doesn't always work reliably, e.g. at resume time.
Just initialize to 0, so the ring is considered empty.
Tested with hibernation on Sumo and Cayman cards.
Should fix https://bugs.launchpad.net/ubuntu/+source/linux/+bug/820746/ .
--- drivers/gpu/drm/radeon/evergreen.c | 4 ++-- drivers/gpu/drm/radeon/ni.c | 12 ++++++------ drivers/gpu/drm/radeon/r100.c | 6 ++---- drivers/gpu/drm/radeon/r600.c | 4 ++-- 4 files changed, 12 insertions(+), 14 deletions(-)
drivers/gpu/drm/radeon/evergreen.c +2 -2
@@ -1378,7 +1378,8 @@ int evergreen_cp_resume(struct radeon_device *rdev)/* Initialize the ring buffer's read and write pointers */ WREG32 (CP_RB_CNTL , tmp |RB_RPTR_WR_ENA );WREG32 (CP_RB_RPTR_WR ,0 ); -WREG32 (CP_RB_WPTR ,0 ); + rdev->cp.wptr =0 ; +WREG32 (CP_RB_WPTR , rdev->cp.wptr);/* set the wb address wether it's enabled or not */ WREG32(CP_RB_RPTR_ADDR,
@@ -1403,7 +1404,6 @@ int evergreen_cp_resume(struct radeon_device *rdev)WREG32 (CP_DEBUG , (1 <<27 ) | (1 <<28 )); rdev->cp.rptr =RREG32 (CP_RB_RPTR ); - rdev->cp.wptr =RREG32 (CP_RB_WPTR );evergreen_cp_start (rdev); rdev->cp.ready = true;
drivers/gpu/drm/radeon/ni.c +6 -6
@@ -1182,7 +1182,8 @@ int cayman_cp_resume(struct radeon_device *rdev)/* Initialize the ring buffer's read and write pointers */ WREG32 (CP_RB0_CNTL , tmp |RB_RPTR_WR_ENA ); -WREG32 (CP_RB0_WPTR ,0 ); + rdev->cp.wptr =0 ; +WREG32 (CP_RB0_WPTR , rdev->cp.wptr);/* set the wb address wether it's enabled or not */ WREG32 (CP_RB0_RPTR_ADDR , (rdev->wb.gpu_addr +RADEON_WB_CP_RPTR_OFFSET ) &0xFFFFFFFC );
@@ -1202,7 +1203,6 @@ int cayman_cp_resume(struct radeon_device *rdev)WREG32 (CP_RB0_BASE , rdev->cp.gpu_addr >>8 ); rdev->cp.rptr =RREG32 (CP_RB0_RPTR ); - rdev->cp.wptr =RREG32 (CP_RB0_WPTR );/* ring1 - compute only */ /* Set ring buffer size */
@@ -1215,7 +1215,8 @@ int cayman_cp_resume(struct radeon_device *rdev)/* Initialize the ring buffer's read and write pointers */ WREG32 (CP_RB1_CNTL , tmp |RB_RPTR_WR_ENA ); -WREG32 (CP_RB1_WPTR ,0 ); + rdev->cp1.wptr =0 ; +WREG32 (CP_RB1_WPTR , rdev->cp1.wptr);/* set the wb address wether it's enabled or not */ WREG32 (CP_RB1_RPTR_ADDR , (rdev->wb.gpu_addr +RADEON_WB_CP1_RPTR_OFFSET ) &0xFFFFFFFC );
@@ -1227,7 +1228,6 @@ int cayman_cp_resume(struct radeon_device *rdev)WREG32 (CP_RB1_BASE , rdev->cp1.gpu_addr >>8 ); rdev->cp1.rptr =RREG32 (CP_RB1_RPTR ); - rdev->cp1.wptr =RREG32 (CP_RB1_WPTR );/* ring2 - compute only */ /* Set ring buffer size */
@@ -1240,7 +1240,8 @@ int cayman_cp_resume(struct radeon_device *rdev)/* Initialize the ring buffer's read and write pointers */ WREG32 (CP_RB2_CNTL , tmp |RB_RPTR_WR_ENA ); -WREG32 (CP_RB2_WPTR ,0 ); + rdev->cp2.wptr =0 ; +WREG32 (CP_RB2_WPTR , rdev->cp2.wptr);/* set the wb address wether it's enabled or not */ WREG32 (CP_RB2_RPTR_ADDR , (rdev->wb.gpu_addr +RADEON_WB_CP2_RPTR_OFFSET ) &0xFFFFFFFC );
@@ -1252,7 +1253,6 @@ int cayman_cp_resume(struct radeon_device *rdev)WREG32 (CP_RB2_BASE , rdev->cp2.gpu_addr >>8 ); rdev->cp2.rptr =RREG32 (CP_RB2_RPTR ); - rdev->cp2.wptr =RREG32 (CP_RB2_WPTR );/* start the rings */ cayman_cp_start (rdev);
drivers/gpu/drm/radeon/r100.c +2 -4
@@ -990,7 +990,8 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)/* Force read & write ptr to 0 */ WREG32 (RADEON_CP_RB_CNTL , tmp |RADEON_RB_RPTR_WR_ENA |RADEON_RB_NO_UPDATE );WREG32 (RADEON_CP_RB_RPTR_WR ,0 ); -WREG32 (RADEON_CP_RB_WPTR ,0 ); + rdev->cp.wptr =0 ; +WREG32 (RADEON_CP_RB_WPTR , rdev->cp.wptr);/* set the wb address whether it's enabled or not */ WREG32(R_00070C_CP_RB_RPTR_ADDR,
@@ -1007,9 +1008,6 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)WREG32 (RADEON_CP_RB_CNTL , tmp);udelay (10 ); rdev->cp.rptr =RREG32 (RADEON_CP_RB_RPTR ); - rdev->cp.wptr =RREG32 (RADEON_CP_RB_WPTR ); -/* protect against crazy HW on resume */ - rdev->cp.wptr &= rdev->cp.ptr_mask;/* Set cp mode to bus mastering & enable cp*/ WREG32(RADEON_CP_CSQ_MODE, REG_SET(RADEON_INDIRECT2_START, indirect2_start) |
drivers/gpu/drm/radeon/r600.c +2 -2
@@ -2208,7 +2208,8 @@ int r600_cp_resume(struct radeon_device *rdev)/* Initialize the ring buffer's read and write pointers */ WREG32 (CP_RB_CNTL , tmp |RB_RPTR_WR_ENA );WREG32 (CP_RB_RPTR_WR ,0 ); -WREG32 (CP_RB_WPTR ,0 ); + rdev->cp.wptr =0 ; +WREG32 (CP_RB_WPTR , rdev->cp.wptr);/* set the wb address whether it's enabled or not */ WREG32(CP_RB_RPTR_ADDR,
@@ -2233,7 +2234,6 @@ int r600_cp_resume(struct radeon_device *rdev)WREG32 (CP_DEBUG , (1 <<27 ) | (1 <<28 )); rdev->cp.rptr =RREG32 (CP_RB_RPTR ); - rdev->cp.wptr =RREG32 (CP_RB_WPTR );r600_cp_start (rdev); rdev->cp.ready = true;
Signature · 5 lines
1.7.5.4 -- Earthling Michel Dänzer | http://www.amd.com Libre software enthusiast | Debian, X and DRI developer