]> err.no Git - linux-2.6/commitdiff
drm/r300: fix bug in r300 userspace hardware wait emission
authorDave Airlie <airlied@linux.ie>
Sat, 29 Mar 2008 21:51:49 +0000 (07:51 +1000)
committerDave Airlie <airlied@linux.ie>
Sat, 29 Mar 2008 21:51:49 +0000 (07:51 +1000)
This interface was originally designed wrong, confusing bit-fields and
integers, major brown paper bag going back many years...

But userspace only ever used 4 values so fix the interface for new
users and fix the implementation to deal with the 4 values userspace
has ever emitted (0x1, 0x2, 0x3, 0x6).

Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/char/drm/r300_cmdbuf.c
drivers/char/drm/radeon_drm.h

index 0f4afc44245c60ffc9e67cce44aaf209ce58a7a7..f535812e40573d69d8c057495563560ecb65f288 100644 (file)
@@ -729,6 +729,47 @@ static void r300_discard_buffer(struct drm_device * dev, struct drm_buf * buf)
        buf->used = 0;
 }
 
+static void r300_cmd_wait(drm_radeon_private_t * dev_priv,
+                         drm_r300_cmd_header_t header)
+{
+       u32 wait_until;
+       RING_LOCALS;
+
+       if (!header.wait.flags)
+               return;
+
+       wait_until = 0;
+
+       switch(header.wait.flags) {
+       case R300_WAIT_2D:
+               wait_until = RADEON_WAIT_2D_IDLE;
+               break;
+       case R300_WAIT_3D:
+               wait_until = RADEON_WAIT_3D_IDLE;
+               break;
+       case R300_NEW_WAIT_2D_3D:
+               wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_3D_IDLE;
+               break;
+       case R300_NEW_WAIT_2D_2D_CLEAN:
+               wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
+               break;
+       case R300_NEW_WAIT_3D_3D_CLEAN:
+               wait_until = RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
+               break;
+       case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN:
+               wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN;
+               wait_until |= RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN;
+               break;
+       default:
+               return;
+       }
+
+       BEGIN_RING(2);
+       OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
+       OUT_RING(wait_until);
+       ADVANCE_RING();
+}
+
 static int r300_scratch(drm_radeon_private_t *dev_priv,
                        drm_radeon_kcmd_buffer_t *cmdbuf,
                        drm_r300_cmd_header_t header)
@@ -909,19 +950,8 @@ int r300_do_cp_cmdbuf(struct drm_device *dev,
                        break;
 
                case R300_CMD_WAIT:
-                       /* simple enough, we can do it here */
                        DRM_DEBUG("R300_CMD_WAIT\n");
-                       if (header.wait.flags == 0)
-                               break;  /* nothing to do */
-
-                       {
-                               RING_LOCALS;
-
-                               BEGIN_RING(2);
-                               OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0));
-                               OUT_RING((header.wait.flags & 0xf) << 14);
-                               ADVANCE_RING();
-                       }
+                       r300_cmd_wait(dev_priv, header);
                        break;
 
                case R300_CMD_SCRATCH:
index 71e5b21fad2c3c8cb99ee57630c30bad5ac0bd63..aab82e121e07935a4f169f1bb36a43d1eba1479e 100644 (file)
@@ -225,8 +225,20 @@ typedef union {
 #define R300_CMD_WAIT                  7
 #      define R300_WAIT_2D             0x1
 #      define R300_WAIT_3D             0x2
+/* these two defines are DOING IT WRONG - however
+ * we have userspace which relies on using these.
+ * The wait interface is backwards compat new 
+ * code should use the NEW_WAIT defines below
+ * THESE ARE NOT BIT FIELDS
+ */
 #      define R300_WAIT_2D_CLEAN       0x3
 #      define R300_WAIT_3D_CLEAN       0x4
+
+#      define R300_NEW_WAIT_2D_3D      0x3
+#      define R300_NEW_WAIT_2D_2D_CLEAN        0x4
+#      define R300_NEW_WAIT_3D_3D_CLEAN        0x6
+#      define R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN    0x8
+
 #define R300_CMD_SCRATCH               8
 
 typedef union {