diff options
Diffstat (limited to 'shared')
-rw-r--r-- | shared/drm.h | 2 | ||||
-rw-r--r-- | shared/radeon.h | 34 | ||||
-rw-r--r-- | shared/radeon_cp.c | 39 | ||||
-rw-r--r-- | shared/radeon_drv.h | 1 | ||||
-rw-r--r-- | shared/radeon_mem.c | 10 | ||||
-rw-r--r-- | shared/radeon_state.c | 201 |
6 files changed, 152 insertions, 135 deletions
diff --git a/shared/drm.h b/shared/drm.h index d3c9f1580..d1d669437 100644 --- a/shared/drm.h +++ b/shared/drm.h @@ -348,7 +348,7 @@ typedef struct drm_irq_busid { typedef enum { _DRM_VBLANK_ABSOLUTE = 0x0, /* Wait for specific vblank sequence number */ _DRM_VBLANK_RELATIVE = 0x1, /* Wait for given number of vblanks */ - _DRM_VBLANK_SIGNAL = 0x80000000 /* Send signal instead of blocking */ + _DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */ } drm_vblank_seq_type_t; #define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL diff --git a/shared/radeon.h b/shared/radeon.h index fe71687a1..2b5131a9f 100644 --- a/shared/radeon.h +++ b/shared/radeon.h @@ -51,7 +51,7 @@ #define DRIVER_DATE "20020828" #define DRIVER_MAJOR 1 -#define DRIVER_MINOR 7 +#define DRIVER_MINOR 8 #define DRIVER_PATCHLEVEL 0 /* Interface history: @@ -77,6 +77,7 @@ * and R200_PP_CUBIC_OFFSET_F1_[0..5]. * Added packets R200_EMIT_PP_CUBIC_FACES_[0..5] and * R200_EMIT_PP_CUBIC_OFFSETS_[0..5]. (brian) + * 1.8 - Remove need to call cleanup ioctls on last client exit (keith) */ #define DRIVER_IOCTLS \ [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = { radeon_cp_buffers, 1, 0 }, \ @@ -105,11 +106,6 @@ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_WAIT)] = { radeon_irq_wait, 1, 0 }, -#define USE_IRQS 1 -#if USE_IRQS -#define __HAVE_DMA_IRQ 1 -#define __HAVE_VBL_IRQ 1 -#define __HAVE_SHARED_IRQ 1 /* When a client dies: * - Check for and clean up flipped page state @@ -117,35 +113,35 @@ * * DRM infrastructure takes care of reclaiming dma buffers. */ -#define DRIVER_PRERELEASE() do { \ +#define DRIVER_PRERELEASE() \ +do { \ if ( dev->dev_private ) { \ drm_radeon_private_t *dev_priv = dev->dev_private; \ if ( dev_priv->page_flipping ) { \ radeon_do_cleanup_pageflip( dev ); \ } \ radeon_mem_release( dev_priv->agp_heap ); \ + radeon_mem_release( dev_priv->fb_heap ); \ } \ } while (0) -/* On unloading the module: - * - Free memory heap structure - * - Remove mappings made at startup and free dev_private. +/* When the last client dies, shut down the CP and free dev->dev_priv. */ -#define DRIVER_PRETAKEDOWN() do { \ - if ( dev->dev_private ) { \ - drm_radeon_private_t *dev_priv = dev->dev_private; \ - radeon_mem_takedown( &(dev_priv->agp_heap) ); \ - radeon_do_cleanup_cp( dev ); \ - } \ +#define __HAVE_RELEASE 1 +#define DRIVER_RELEASE() \ +do { \ + if ( dev->open_count == 1) \ + radeon_do_release( dev ); \ } while (0) -#else -#define __HAVE_DMA_IRQ 0 -#endif + /* DMA customization: */ #define __HAVE_DMA 1 +#define __HAVE_DMA_IRQ 1 +#define __HAVE_VBL_IRQ 1 +#define __HAVE_SHARED_IRQ 1 /* Buffer customization: diff --git a/shared/radeon_cp.c b/shared/radeon_cp.c index 7c869c029..6994fe9eb 100644 --- a/shared/radeon_cp.c +++ b/shared/radeon_cp.c @@ -1354,6 +1354,9 @@ int radeon_cp_stop( DRM_IOCTL_ARGS ) DRM_COPY_FROM_USER_IOCTL( stop, (drm_radeon_cp_stop_t *)data, sizeof(stop) ); + if (!dev_priv->cp_running) + return 0; + /* Flush any pending CP commands. This ensures any outstanding * commands are exectuted by the engine before we turn it off. */ @@ -1381,6 +1384,39 @@ int radeon_cp_stop( DRM_IOCTL_ARGS ) return 0; } + +void radeon_do_release( drm_device_t *dev ) +{ + drm_radeon_private_t *dev_priv = dev->dev_private; + int ret; + + if (dev_priv) { + if (dev_priv->cp_running) { + /* Stop the cp */ + while ((ret = radeon_do_cp_idle( dev_priv )) != 0) { + DRM_DEBUG("radeon_do_cp_idle %d\n", ret); +#ifdef __linux__ + schedule(); +#else + tsleep(&ret, PZERO, "rdnrel", 1); +#endif + } + radeon_do_cp_stop( dev_priv ); + radeon_do_engine_reset( dev ); + } + + /* Disable *all* interrupts */ + RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); + + /* Free memory heap structures */ + radeon_mem_takedown( &(dev_priv->agp_heap) ); + radeon_mem_takedown( &(dev_priv->fb_heap) ); + + /* deallocate kernel resources */ + radeon_do_cleanup_cp( dev ); + } +} + /* Just reset the CP ring. Called as part of an X Server engine reset. */ int radeon_cp_reset( DRM_IOCTL_ARGS ) @@ -1412,9 +1448,6 @@ int radeon_cp_idle( DRM_IOCTL_ARGS ) LOCK_TEST_WITH_RETURN( dev ); -/* if (dev->irq) */ -/* radeon_emit_and_wait_irq( dev ); */ - return radeon_do_cp_idle( dev_priv ); } diff --git a/shared/radeon_drv.h b/shared/radeon_drv.h index 65f3c9265..22c5d04fa 100644 --- a/shared/radeon_drv.h +++ b/shared/radeon_drv.h @@ -193,6 +193,7 @@ extern int radeon_emit_and_wait_irq(drm_device_t *dev); extern int radeon_wait_irq(drm_device_t *dev, int swi_nr); extern int radeon_emit_irq(drm_device_t *dev); +extern void radeon_do_release(drm_device_t *dev); /* Flags for stats.boxes */ diff --git a/shared/radeon_mem.c b/shared/radeon_mem.c index 5c07c1afe..7ca10753a 100644 --- a/shared/radeon_mem.c +++ b/shared/radeon_mem.c @@ -130,16 +130,6 @@ static void free_block( struct mem_block *p ) } } -static void print_heap( struct mem_block *heap ) -{ - struct mem_block *p; - - for (p = heap->next ; p != heap ; p = p->next) - DRM_DEBUG("0x%x..0x%x (0x%x) -- owner %d\n", - p->start, p->start + p->size, - p->size, p->pid); -} - /* Initialize. How to check for an uninitialized heap? */ static int init_heap(struct mem_block **heap, int start, int size) diff --git a/shared/radeon_state.c b/shared/radeon_state.c index 7b480a7e9..1fe007b30 100644 --- a/shared/radeon_state.c +++ b/shared/radeon_state.c @@ -1074,19 +1074,30 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev, const u8 *data; int size, dwords, tex_width, blit_width; u32 y, height; - int ret = 0, i; + int i; RING_LOCALS; dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD; - /* FIXME: Be smarter about this... + /* Flush the pixel cache. This ensures no pixel data gets mixed + * up with the texture data from the host data blit, otherwise + * part of the texture image may be corrupted. */ - buf = radeon_freelist_get( dev ); - if ( !buf ) return DRM_ERR(EAGAIN); + BEGIN_RING( 4 ); + RADEON_FLUSH_CACHE(); + RADEON_WAIT_UNTIL_IDLE(); + ADVANCE_RING(); + +#ifdef __BIG_ENDIAN + /* The Mesa texture functions provide the data in little endian as the + * chip wants it, but we need to compensate for the fact that the CP + * ring gets byte-swapped + */ + BEGIN_RING( 2 ); + OUT_RING_REG( RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT ); + ADVANCE_RING(); +#endif - DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n", - tex->offset >> 10, tex->pitch, tex->format, - image->x, image->y, image->width, image->height ); /* The compiler won't optimize away a division by a variable, * even if the only legal values are powers of two. Thus, we'll @@ -1120,127 +1131,113 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev, return DRM_ERR(EINVAL); } - DRM_DEBUG( " tex=%dx%d blit=%d\n", - tex_width, tex->height, blit_width ); - - /* Flush the pixel cache. This ensures no pixel data gets mixed - * up with the texture data from the host data blit, otherwise - * part of the texture image may be corrupted. - */ - BEGIN_RING( 4 ); - - RADEON_FLUSH_CACHE(); - RADEON_WAIT_UNTIL_IDLE(); - - ADVANCE_RING(); - -#ifdef __BIG_ENDIAN - /* The Mesa texture functions provide the data in little endian as the - * chip wants it, but we need to compensate for the fact that the CP - * ring gets byte-swapped - */ - BEGIN_RING( 2 ); - OUT_RING_REG( RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT ); - ADVANCE_RING(); -#endif - - /* Make a copy of the parameters in case we have to update them - * for a multi-pass texture blit. - */ - y = image->y; - height = image->height; - data = (const u8 *)image->data; - - size = height * blit_width; + DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width ); - if ( size > RADEON_MAX_TEXTURE_SIZE ) { - /* Texture image is too large, do a multipass upload */ - ret = DRM_ERR(EAGAIN); + do { + DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n", + tex->offset >> 10, tex->pitch, tex->format, + image->x, image->y, image->width, image->height ); - /* Adjust the blit size to fit the indirect buffer */ - height = RADEON_MAX_TEXTURE_SIZE / blit_width; + /* Make a copy of the parameters in case we have to + * update them for a multi-pass texture blit. + */ + y = image->y; + height = image->height; + data = (const u8 *)image->data; + size = height * blit_width; + if ( size > RADEON_MAX_TEXTURE_SIZE ) { + height = RADEON_MAX_TEXTURE_SIZE / blit_width; + size = height * blit_width; + } else if ( size < 4 && size > 0 ) { + size = 4; + } else if ( size == 0 ) { + return 0; + } + /* Update the input parameters for next time */ image->y += height; image->height -= height; - image->data = (const char *)image->data + size; + image->data += size; - if ( DRM_COPY_TO_USER( tex->image, image, sizeof(*image) ) ) { - DRM_ERROR( "EFAULT on tex->image\n" ); - return DRM_ERR(EFAULT); + buf = radeon_freelist_get( dev ); + if ( 0 && !buf ) { + radeon_do_cp_idle( dev_priv ); + buf = radeon_freelist_get( dev ); + } + if ( !buf ) { + DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n"); + DRM_COPY_TO_USER( tex->image, image, sizeof(*image) ); + return DRM_ERR(EAGAIN); } - } else if ( size < 4 && size > 0 ) { - size = 4; - } - dwords = size / 4; - /* Dispatch the indirect buffer. - */ - buffer = (u32 *)((char *)dev_priv->buffers->handle + buf->offset); - - buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 ); - buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_NONE | - (format << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP3_S | - RADEON_DP_SRC_SOURCE_HOST_DATA | - RADEON_GMC_CLR_CMP_CNTL_DIS | - RADEON_GMC_WR_MSK_DIS); - - buffer[2] = (tex->pitch << 22) | (tex->offset >> 10); - buffer[3] = 0xffffffff; - buffer[4] = 0xffffffff; - buffer[5] = (y << 16) | image->x; - buffer[6] = (height << 16) | image->width; - buffer[7] = dwords; - - buffer += 8; - - if ( tex_width >= 32 ) { - /* Texture image width is larger than the minimum, so we - * can upload it directly. - */ - if ( DRM_COPY_FROM_USER( buffer, data, dwords * sizeof(u32) ) ) { - DRM_ERROR( "EFAULT on data, %d dwords\n", dwords ); - return DRM_ERR(EFAULT); - } - } else { - /* Texture image width is less than the minimum, so we - * need to pad out each image scanline to the minimum - * width. + /* Dispatch the indirect buffer. */ - for ( i = 0 ; i < tex->height ; i++ ) { - if ( DRM_COPY_FROM_USER( buffer, data, tex_width ) ) { - DRM_ERROR( "EFAULT on pad, %d bytes\n", - tex_width ); + buffer = (u32*)((char*)dev_priv->buffers->handle + buf->offset); + dwords = size / 4; + buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 ); + buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_NONE | + (format << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP3_S | + RADEON_DP_SRC_SOURCE_HOST_DATA | + RADEON_GMC_CLR_CMP_CNTL_DIS | + RADEON_GMC_WR_MSK_DIS); + + buffer[2] = (tex->pitch << 22) | (tex->offset >> 10); + buffer[3] = 0xffffffff; + buffer[4] = 0xffffffff; + buffer[5] = (y << 16) | image->x; + buffer[6] = (height << 16) | image->width; + buffer[7] = dwords; + buffer += 8; + + if ( tex_width >= 32 ) { + /* Texture image width is larger than the minimum, so we + * can upload it directly. + */ + if ( DRM_COPY_FROM_USER( buffer, data, + dwords * sizeof(u32) ) ) { + DRM_ERROR( "EFAULT on data, %d dwords\n", + dwords ); return DRM_ERR(EFAULT); } - buffer += 8; - data += tex_width; + } else { + /* Texture image width is less than the minimum, so we + * need to pad out each image scanline to the minimum + * width. + */ + for ( i = 0 ; i < tex->height ; i++ ) { + if ( DRM_COPY_FROM_USER( buffer, data, + tex_width ) ) { + DRM_ERROR( "EFAULT on pad, %d bytes\n", + tex_width ); + return DRM_ERR(EFAULT); + } + buffer += 8; + data += tex_width; + } } - } - buf->pid = DRM_CURRENTPID; - buf->used = (dwords + 8) * sizeof(u32); + buf->pid = DRM_CURRENTPID; + buf->used = (dwords + 8) * sizeof(u32); + radeon_cp_dispatch_indirect( dev, buf, 0, buf->used ); + radeon_cp_discard_buffer( dev, buf ); - radeon_cp_dispatch_indirect( dev, buf, 0, buf->used ); - radeon_cp_discard_buffer( dev, buf ); + } while (image->height > 0); /* Flush the pixel cache after the blit completes. This ensures * the texture data is written out to memory before rendering * continues. */ BEGIN_RING( 4 ); - RADEON_FLUSH_CACHE(); RADEON_WAIT_UNTIL_2D_IDLE(); - ADVANCE_RING(); - - return ret; + return 0; } |