[PATCH] radeon: Fix 3 regressions (was: glxgears crashes radeon driver)

Jean Delvare khali at linux-fr.org
Mon May 10 06:22:46 PDT 2010


Yes, it's me again ;)

On Sun, 9 May 2010 22:58:30 +0200, Jean Delvare wrote:
> Bisection says that the faulty commit is:
> http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=b4fe945405e477cded91772b4fec854705443dd5
> 
> It doesn't revert cleanly from 2.6.34-rc6+, I'll try a manual revert
> tomorrow. My device is a Radeon 9200, so r200, if it helps.

I can confirm that manually reverting the patch above helps somewhat.
The crash is gone. Now I get an essentially black image in glxgears,
which may be a different bug.

(gdb) file drivers/gpu/drm/radeon/radeon.o
Reading symbols from /home/khali/src/linux-2.6.34-rc6/drivers/gpu/drm/radeon/radeon.o...done.
(gdb) list *(radeon_cp_cmdbuf+0x15e)
0xa58e is in radeon_cp_cmdbuf (drivers/gpu/drm/radeon/radeon_state.c:2921).
2916	
2917			drm_radeon_cmd_header_t *header;
2918			header = drm_buffer_read_object(cmdbuf->buffer,
2919					sizeof(stack_header), &stack_header);
2920	
2921			switch (header->header.cmd_type) {
2922			case RADEON_CMD_PACKET:
2923				DRM_DEBUG("RADEON_CMD_PACKET\n");
2924				if (radeon_emit_packets
2925				    (dev_priv, file_priv, *header, cmdbuf)) {
(gdb) 

I took a look at the above commit and found 3 bugs in it, one of which
is directly responsible for my crash. Candidate patch below.

Note 1: Why one would call radeon_cp_cmdbuf() with an empty buffer is
beyond me, but hey, what do I know about graphics drivers.
Note 2: Even with this patch, glxgears is all black unless I move the
window around, so there's one more bug to track. I guess I'm up for one
more bisection afternoon.

* * * * *

From: Jean Delvare <khali at linux-fr.org>
Subject: radeon: Fix 3 regressions

Commit b4fe945405e477cded91772b4fec854705443dd5 introduced 3 bugs,
fix them:

* Use the right command dword for second packet offset in
  RADEON_CNTL_PAINT/BITBLT_MULTI.
* Don't leak memory if drm_buffer_copy_from_user() fails.
* Don't call drm_buffer_unprocessed() unless drm_buffer_alloc() and
  drm_buffer_copy_from_user() have been called successfully first.

Signed-off-by: Jean Delvare <khali at linux-fr.org>
Cc: Pauli Nieminen <suokkos at gmail.com>
Cc: Dave Airlie <airlied at redhat.com>
---
I can certainly provide 3 separate patches for clarity if you prefer.

 drivers/gpu/drm/radeon/radeon_state.c |   19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

--- linux-2.6.34-rc6.orig/drivers/gpu/drm/radeon/radeon_state.c	2010-05-10 09:20:07.000000000 +0200
+++ linux-2.6.34-rc6/drivers/gpu/drm/radeon/radeon_state.c	2010-05-10 15:19:19.000000000 +0200
@@ -424,7 +424,7 @@ static __inline__ int radeon_check_and_f
 		if ((*cmd & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) &&
 		    (*cmd & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) {
 			u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3);
-			offset = *cmd << 10;
+			offset = *cmd3 << 10;
 			if (radeon_check_and_fixup_offset
 			    (dev_priv, file_priv, &offset)) {
 				DRM_ERROR("Invalid second packet offset\n");
@@ -2895,9 +2895,12 @@ static int radeon_cp_cmdbuf(struct drm_d
 			return rv;
 		rv = drm_buffer_copy_from_user(cmdbuf->buffer, buffer,
 						cmdbuf->bufsz);
-		if (rv)
+		if (rv) {
+			drm_buffer_free(cmdbuf->buffer);
 			return rv;
-	}
+		}
+	} else
+		goto done;
 
 	orig_nbox = cmdbuf->nbox;
 
@@ -2905,8 +2908,7 @@ static int radeon_cp_cmdbuf(struct drm_d
 		int temp;
 		temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf);
 
-		if (cmdbuf->bufsz != 0)
-			drm_buffer_free(cmdbuf->buffer);
+		drm_buffer_free(cmdbuf->buffer);
 
 		return temp;
 	}
@@ -3012,16 +3014,15 @@ static int radeon_cp_cmdbuf(struct drm_d
 		}
 	}
 
-	if (cmdbuf->bufsz != 0)
-		drm_buffer_free(cmdbuf->buffer);
+	drm_buffer_free(cmdbuf->buffer);
 
+      done:
 	DRM_DEBUG("DONE\n");
 	COMMIT_RING();
 	return 0;
 
       err:
-	if (cmdbuf->bufsz != 0)
-		drm_buffer_free(cmdbuf->buffer);
+	drm_buffer_free(cmdbuf->buffer);
 	return -EINVAL;
 }
 

-- 
Jean Delvare


More information about the dri-devel mailing list