Skip to content

Commit

Permalink
drm/r300: fix bug in r300 userspace hardware wait emission
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dave Airlie committed Mar 29, 2008
1 parent af8be4e commit 0c76be3
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 12 deletions.
54 changes: 42 additions & 12 deletions drivers/char/drm/r300_cmdbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down
12 changes: 12 additions & 0 deletions drivers/char/drm/radeon_drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down

0 comments on commit 0c76be3

Please sign in to comment.