diff options
-rw-r--r-- | bsd-core/drm_dma.c | 1 | ||||
-rw-r--r-- | bsd-core/drm_os_freebsd.h | 17 | ||||
-rw-r--r-- | bsd/drm_dma.h | 1 | ||||
-rw-r--r-- | bsd/drm_os_freebsd.h | 17 | ||||
-rw-r--r-- | linux-core/drm_os_linux.h | 55 | ||||
-rw-r--r-- | linux/drm_os_linux.h | 55 | ||||
-rw-r--r-- | shared-core/radeon_cp.c | 2 | ||||
-rw-r--r-- | shared-core/radeon_irq.c | 116 | ||||
-rw-r--r-- | shared/radeon.h | 14 | ||||
-rw-r--r-- | shared/radeon_cp.c | 2 | ||||
-rw-r--r-- | shared/radeon_irq.c | 116 |
11 files changed, 197 insertions, 199 deletions
diff --git a/bsd-core/drm_dma.c b/bsd-core/drm_dma.c index 25d7eb6e..4593a712 100644 --- a/bsd-core/drm_dma.c +++ b/bsd-core/drm_dma.c @@ -597,7 +597,6 @@ int DRM(control)( DRM_IOCTL_ARGS ) } #if __HAVE_VBL_IRQ - int DRM(wait_vblank)( DRM_IOCTL_ARGS ) { DRM_DEVICE; diff --git a/bsd-core/drm_os_freebsd.h b/bsd-core/drm_os_freebsd.h index 70ca60a6..a0ec9e3c 100644 --- a/bsd-core/drm_os_freebsd.h +++ b/bsd-core/drm_os_freebsd.h @@ -139,6 +139,21 @@ do { \ } \ } while (0) +#define DRM_HZ hz + +#define DRM_WAIT_ON( ret, queue, timeout, condition ) \ +do { \ + if (condition) \ + break; \ + ret = tsleep( &(queue), PZERO | PCATCH, "rdnirq", (timeout) ); \ + if ( (ret == EWOULDBLOCK) || (ret == EINTR) ) \ + return DRM_ERR(EBUSY); \ +} while (1) + +#define DRM_WAKEUP( queue ) wakeup( queue ) +#define DRM_WAKEUP_INT( queue ) wakeup( queue ) +#define DRM_INIT_WAITQUEUE( queue ) do {} while (0) + #define DRM_COPY_TO_USER_IOCTL(user, kern, size) \ if ( IOCPARM_LEN(cmd) != size) \ return EINVAL; \ @@ -173,8 +188,6 @@ do { \ __asm __volatile("" : : : "memory"); \ } while (0) -#define DRM_WAKEUP(w) wakeup(w) -#define DRM_WAKEUP_INT(w) wakeup(w) #define PAGE_ALIGN(addr) round_page(addr) diff --git a/bsd/drm_dma.h b/bsd/drm_dma.h index 25d7eb6e..4593a712 100644 --- a/bsd/drm_dma.h +++ b/bsd/drm_dma.h @@ -597,7 +597,6 @@ int DRM(control)( DRM_IOCTL_ARGS ) } #if __HAVE_VBL_IRQ - int DRM(wait_vblank)( DRM_IOCTL_ARGS ) { DRM_DEVICE; diff --git a/bsd/drm_os_freebsd.h b/bsd/drm_os_freebsd.h index 70ca60a6..a0ec9e3c 100644 --- a/bsd/drm_os_freebsd.h +++ b/bsd/drm_os_freebsd.h @@ -139,6 +139,21 @@ do { \ } \ } while (0) +#define DRM_HZ hz + +#define DRM_WAIT_ON( ret, queue, timeout, condition ) \ +do { \ + if (condition) \ + break; \ + ret = tsleep( &(queue), PZERO | PCATCH, "rdnirq", (timeout) ); \ + if ( (ret == EWOULDBLOCK) || (ret == EINTR) ) \ + return DRM_ERR(EBUSY); \ +} while (1) + +#define DRM_WAKEUP( queue ) wakeup( queue ) +#define DRM_WAKEUP_INT( queue ) wakeup( queue ) +#define DRM_INIT_WAITQUEUE( queue ) do {} while (0) + #define DRM_COPY_TO_USER_IOCTL(user, kern, size) \ if ( IOCPARM_LEN(cmd) != size) \ return EINVAL; \ @@ -173,8 +188,6 @@ do { \ __asm __volatile("" : : : "memory"); \ } while (0) -#define DRM_WAKEUP(w) wakeup(w) -#define DRM_WAKEUP_INT(w) wakeup(w) #define PAGE_ALIGN(addr) round_page(addr) diff --git a/linux-core/drm_os_linux.h b/linux-core/drm_os_linux.h index cb304398..cf003137 100644 --- a/linux-core/drm_os_linux.h +++ b/linux-core/drm_os_linux.h @@ -44,16 +44,47 @@ #define DRM_MALLOC(x) kmalloc(x, GFP_KERNEL) #define DRM_FREE(x) kfree(x) -#define DRM_GETSAREA() \ -do { \ - struct list_head *list; \ - list_for_each( list, &dev->maplist->head ) { \ - drm_map_list_t *entry = (drm_map_list_t *)list; \ - if ( entry->map && \ - entry->map->type == _DRM_SHM && \ - (entry->map->flags & _DRM_CONTAINS_LOCK) ) { \ - dev_priv->sarea = entry->map; \ - break; \ - } \ - } \ +#define DRM_GETSAREA() \ +do { \ + struct list_head *list; \ + list_for_each( list, &dev->maplist->head ) { \ + drm_map_list_t *entry = (drm_map_list_t *)list; \ + if ( entry->map && \ + entry->map->type == _DRM_SHM && \ + (entry->map->flags & _DRM_CONTAINS_LOCK) ) { \ + dev_priv->sarea = entry->map; \ + break; \ + } \ + } \ } while (0) + +#define DRM_HZ HZ + +#define DRM_WAIT_ON( ret, queue, timeout, condition ) \ +do { \ + DECLARE_WAITQUEUE(entry, current); \ + unsigned long end = jiffies + (timeout); \ + add_wait_queue(&(queue), &entry); \ + \ + for (;;) { \ + current->state = TASK_INTERRUPTIBLE; \ + if (condition) \ + break; \ + if((signed)(end - jiffies) <= 0) { \ + ret = -EBUSY; \ + break; \ + } \ + schedule_timeout(max(HZ/100,1)); \ + if (signal_pending(current)) { \ + ret = -EINTR; \ + break; \ + } \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&(queue), &entry); \ +} while (0) + + +#define DRM_WAKEUP( queue ) wake_up_interruptible( queue ) +#define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue ) + diff --git a/linux/drm_os_linux.h b/linux/drm_os_linux.h index cb304398..cf003137 100644 --- a/linux/drm_os_linux.h +++ b/linux/drm_os_linux.h @@ -44,16 +44,47 @@ #define DRM_MALLOC(x) kmalloc(x, GFP_KERNEL) #define DRM_FREE(x) kfree(x) -#define DRM_GETSAREA() \ -do { \ - struct list_head *list; \ - list_for_each( list, &dev->maplist->head ) { \ - drm_map_list_t *entry = (drm_map_list_t *)list; \ - if ( entry->map && \ - entry->map->type == _DRM_SHM && \ - (entry->map->flags & _DRM_CONTAINS_LOCK) ) { \ - dev_priv->sarea = entry->map; \ - break; \ - } \ - } \ +#define DRM_GETSAREA() \ +do { \ + struct list_head *list; \ + list_for_each( list, &dev->maplist->head ) { \ + drm_map_list_t *entry = (drm_map_list_t *)list; \ + if ( entry->map && \ + entry->map->type == _DRM_SHM && \ + (entry->map->flags & _DRM_CONTAINS_LOCK) ) { \ + dev_priv->sarea = entry->map; \ + break; \ + } \ + } \ } while (0) + +#define DRM_HZ HZ + +#define DRM_WAIT_ON( ret, queue, timeout, condition ) \ +do { \ + DECLARE_WAITQUEUE(entry, current); \ + unsigned long end = jiffies + (timeout); \ + add_wait_queue(&(queue), &entry); \ + \ + for (;;) { \ + current->state = TASK_INTERRUPTIBLE; \ + if (condition) \ + break; \ + if((signed)(end - jiffies) <= 0) { \ + ret = -EBUSY; \ + break; \ + } \ + schedule_timeout(max(HZ/100,1)); \ + if (signal_pending(current)) { \ + ret = -EINTR; \ + break; \ + } \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&(queue), &entry); \ +} while (0) + + +#define DRM_WAKEUP( queue ) wake_up_interruptible( queue ) +#define DRM_INIT_WAITQUEUE( queue ) init_waitqueue_head( queue ) + diff --git a/shared-core/radeon_cp.c b/shared-core/radeon_cp.c index c0fb63ef..60da1e41 100644 --- a/shared-core/radeon_cp.c +++ b/shared-core/radeon_cp.c @@ -1018,7 +1018,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) } dev_priv->is_r200 = (init->func == RADEON_INIT_R200_CP); - dev_priv->do_boxes = 0; + dev_priv->do_boxes = 1; dev_priv->cp_mode = init->cp_mode; /* We don't support anything other than bus-mastering ring mode, diff --git a/shared-core/radeon_irq.c b/shared-core/radeon_irq.c index 19872e9a..ee28872a 100644 --- a/shared-core/radeon_irq.c +++ b/shared-core/radeon_irq.c @@ -59,42 +59,36 @@ void DRM(dma_service)( DRM_IRQ_ARGS ) drm_device_t *dev = (drm_device_t *) arg; drm_radeon_private_t *dev_priv = (drm_radeon_private_t *)dev->dev_private; - u32 stat, ack = 0; + u32 stat; - /* Need to wait for fifo to drain? - */ stat = RADEON_READ(RADEON_GEN_INT_STATUS); + if (!stat) + return; /* SW interrupt */ if (stat & RADEON_SW_INT_TEST) { - ack |= RADEON_SW_INT_TEST_ACK; -#ifdef __linux__ - wake_up_interruptible(&dev_priv->swi_queue); -#endif -#ifdef __FreeBSD__ - wakeup(&dev->vbl_queue); -#endif + DRM_WAKEUP( &dev_priv->swi_queue ); } +#if __HAVE_VBL_IRQ /* VBLANK interrupt */ if (stat & RADEON_CRTC_VBLANK_STAT) { - ack |= RADEON_CRTC_VBLANK_STAT_ACK; atomic_inc(&dev->vbl_received); -#ifdef __linux__ - wake_up_interruptible(&dev->vbl_queue); -#endif -#ifdef __FreeBSD__ - wakeup(&dev->vbl_queue); -#endif + DRM_WAKEUP(&dev->vbl_queue); } +#endif - if (ack) - RADEON_WRITE(RADEON_GEN_INT_STATUS, ack); + /* Acknowledge all the bits in GEN_INT_STATUS -- seem to get + * more than we asked for... + */ + RADEON_WRITE(RADEON_GEN_INT_STATUS, stat); } static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv) { - RADEON_WRITE( RADEON_GEN_INT_STATUS, RADEON_READ( RADEON_GEN_INT_STATUS ) ); + u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS ); + if (tmp) + RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp ); } int radeon_emit_irq(drm_device_t *dev) @@ -120,52 +114,22 @@ int radeon_wait_irq(drm_device_t *dev, int swi_nr) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *)dev->dev_private; -#ifdef __linux__ - DECLARE_WAITQUEUE(entry, current); - unsigned long end = jiffies + HZ*3; -#endif /* __linux__ */ int ret = 0; if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr) return 0; + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + /* This is a hack to work around mysterious freezes on certain + * systems: + */ radeon_acknowledge_irqs( dev_priv ); -#ifdef __linux__ - add_wait_queue(&dev_priv->swi_queue, &entry); - - for (;;) { - current->state = TASK_INTERRUPTIBLE; - if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr) - break; - if((signed)(end - jiffies) <= 0) { - ret = -EBUSY; /* Lockup? Missed irq? */ - break; - } - schedule_timeout(max(HZ/100,1)); - if (signal_pending(current)) { - ret = -EINTR; - break; - } - } + DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ, + RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr ); - current->state = TASK_RUNNING; - remove_wait_queue(&dev_priv->swi_queue, &entry); return ret; -#endif /* __linux__ */ - -#ifdef __FreeBSD__ - for (;;) { - if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr) - break; - ret = tsleep( &dev_priv->swi_queue, PZERO | PCATCH, \ - "rdnirq", 3*hz ); - if (ret) - break; - } - return ret; -#endif /* __FreeBSD__ */ } int radeon_emit_and_wait_irq(drm_device_t *dev) @@ -174,7 +138,8 @@ int radeon_emit_and_wait_irq(drm_device_t *dev) } -int radeon_vblank_wait(drm_device_t *dev, unsigned int *sequence) +#if __HAVE_VBL_IRQ +int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *)dev->dev_private; @@ -186,34 +151,23 @@ int radeon_vblank_wait(drm_device_t *dev, unsigned int *sequence) return DRM_ERR(EINVAL); } - /* Assume that the user has missed the current sequence number by about - * a day rather than she wants to wait for years using vertical blanks :) + radeon_acknowledge_irqs( dev_priv ); + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + /* Assume that the user has missed the current sequence number + * by about a day rather than she wants to wait for years + * using vertical blanks... */ - while ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) ) - + ~*sequence + 1 ) > (1<<23) ) { - dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - - radeon_acknowledge_irqs( dev_priv ); - -#ifdef __linux__ - interruptible_sleep_on( &dev->vbl_queue ); - - if (signal_pending(current)) { - ret = -EINTR; - break; - } -#endif /* __linux__ */ -#ifdef __FreeBSD__ - ret = tsleep( &dev->vbl_queue, 3*hz, "rdnvbl", PZERO | PCATCH); - if (ret) - break; -#endif /* __FreeBSD__ */ - } + DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, + ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) ) + + ~*sequence + 1 ) > (1<<23) ) ); *sequence = cur_vblank; return ret; } +#endif /* Needs the lock as it touches the ring. @@ -284,9 +238,7 @@ void DRM(driver_irq_postinstall)( drm_device_t *dev ) { (drm_radeon_private_t *)dev->dev_private; atomic_set(&dev_priv->swi_emitted, 0); -#ifdef __linux__ - init_waitqueue_head(&dev_priv->swi_queue); -#endif + DRM_INIT_WAITQUEUE( &dev_priv->swi_queue ); /* Turn on SW and VBL ints */ RADEON_WRITE( RADEON_GEN_INT_CNTL, diff --git a/shared/radeon.h b/shared/radeon.h index aa613c40..05760855 100644 --- a/shared/radeon.h +++ b/shared/radeon.h @@ -100,6 +100,13 @@ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 }, \ [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 * - Free any alloced agp memory. @@ -128,13 +135,14 @@ } \ } 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 c0fb63ef..60da1e41 100644 --- a/shared/radeon_cp.c +++ b/shared/radeon_cp.c @@ -1018,7 +1018,7 @@ static int radeon_do_init_cp( drm_device_t *dev, drm_radeon_init_t *init ) } dev_priv->is_r200 = (init->func == RADEON_INIT_R200_CP); - dev_priv->do_boxes = 0; + dev_priv->do_boxes = 1; dev_priv->cp_mode = init->cp_mode; /* We don't support anything other than bus-mastering ring mode, diff --git a/shared/radeon_irq.c b/shared/radeon_irq.c index 19872e9a..ee28872a 100644 --- a/shared/radeon_irq.c +++ b/shared/radeon_irq.c @@ -59,42 +59,36 @@ void DRM(dma_service)( DRM_IRQ_ARGS ) drm_device_t *dev = (drm_device_t *) arg; drm_radeon_private_t *dev_priv = (drm_radeon_private_t *)dev->dev_private; - u32 stat, ack = 0; + u32 stat; - /* Need to wait for fifo to drain? - */ stat = RADEON_READ(RADEON_GEN_INT_STATUS); + if (!stat) + return; /* SW interrupt */ if (stat & RADEON_SW_INT_TEST) { - ack |= RADEON_SW_INT_TEST_ACK; -#ifdef __linux__ - wake_up_interruptible(&dev_priv->swi_queue); -#endif -#ifdef __FreeBSD__ - wakeup(&dev->vbl_queue); -#endif + DRM_WAKEUP( &dev_priv->swi_queue ); } +#if __HAVE_VBL_IRQ /* VBLANK interrupt */ if (stat & RADEON_CRTC_VBLANK_STAT) { - ack |= RADEON_CRTC_VBLANK_STAT_ACK; atomic_inc(&dev->vbl_received); -#ifdef __linux__ - wake_up_interruptible(&dev->vbl_queue); -#endif -#ifdef __FreeBSD__ - wakeup(&dev->vbl_queue); -#endif + DRM_WAKEUP(&dev->vbl_queue); } +#endif - if (ack) - RADEON_WRITE(RADEON_GEN_INT_STATUS, ack); + /* Acknowledge all the bits in GEN_INT_STATUS -- seem to get + * more than we asked for... + */ + RADEON_WRITE(RADEON_GEN_INT_STATUS, stat); } static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv) { - RADEON_WRITE( RADEON_GEN_INT_STATUS, RADEON_READ( RADEON_GEN_INT_STATUS ) ); + u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS ); + if (tmp) + RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp ); } int radeon_emit_irq(drm_device_t *dev) @@ -120,52 +114,22 @@ int radeon_wait_irq(drm_device_t *dev, int swi_nr) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *)dev->dev_private; -#ifdef __linux__ - DECLARE_WAITQUEUE(entry, current); - unsigned long end = jiffies + HZ*3; -#endif /* __linux__ */ int ret = 0; if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr) return 0; + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + /* This is a hack to work around mysterious freezes on certain + * systems: + */ radeon_acknowledge_irqs( dev_priv ); -#ifdef __linux__ - add_wait_queue(&dev_priv->swi_queue, &entry); - - for (;;) { - current->state = TASK_INTERRUPTIBLE; - if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr) - break; - if((signed)(end - jiffies) <= 0) { - ret = -EBUSY; /* Lockup? Missed irq? */ - break; - } - schedule_timeout(max(HZ/100,1)); - if (signal_pending(current)) { - ret = -EINTR; - break; - } - } + DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ, + RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr ); - current->state = TASK_RUNNING; - remove_wait_queue(&dev_priv->swi_queue, &entry); return ret; -#endif /* __linux__ */ - -#ifdef __FreeBSD__ - for (;;) { - if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr) - break; - ret = tsleep( &dev_priv->swi_queue, PZERO | PCATCH, \ - "rdnirq", 3*hz ); - if (ret) - break; - } - return ret; -#endif /* __FreeBSD__ */ } int radeon_emit_and_wait_irq(drm_device_t *dev) @@ -174,7 +138,8 @@ int radeon_emit_and_wait_irq(drm_device_t *dev) } -int radeon_vblank_wait(drm_device_t *dev, unsigned int *sequence) +#if __HAVE_VBL_IRQ +int DRM(vblank_wait)(drm_device_t *dev, unsigned int *sequence) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *)dev->dev_private; @@ -186,34 +151,23 @@ int radeon_vblank_wait(drm_device_t *dev, unsigned int *sequence) return DRM_ERR(EINVAL); } - /* Assume that the user has missed the current sequence number by about - * a day rather than she wants to wait for years using vertical blanks :) + radeon_acknowledge_irqs( dev_priv ); + + dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; + + /* Assume that the user has missed the current sequence number + * by about a day rather than she wants to wait for years + * using vertical blanks... */ - while ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) ) - + ~*sequence + 1 ) > (1<<23) ) { - dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - - radeon_acknowledge_irqs( dev_priv ); - -#ifdef __linux__ - interruptible_sleep_on( &dev->vbl_queue ); - - if (signal_pending(current)) { - ret = -EINTR; - break; - } -#endif /* __linux__ */ -#ifdef __FreeBSD__ - ret = tsleep( &dev->vbl_queue, 3*hz, "rdnvbl", PZERO | PCATCH); - if (ret) - break; -#endif /* __FreeBSD__ */ - } + DRM_WAIT_ON( ret, dev->vbl_queue, 3*DRM_HZ, + ( ( ( cur_vblank = atomic_read(&dev->vbl_received ) ) + + ~*sequence + 1 ) > (1<<23) ) ); *sequence = cur_vblank; return ret; } +#endif /* Needs the lock as it touches the ring. @@ -284,9 +238,7 @@ void DRM(driver_irq_postinstall)( drm_device_t *dev ) { (drm_radeon_private_t *)dev->dev_private; atomic_set(&dev_priv->swi_emitted, 0); -#ifdef __linux__ - init_waitqueue_head(&dev_priv->swi_queue); -#endif + DRM_INIT_WAITQUEUE( &dev_priv->swi_queue ); /* Turn on SW and VBL ints */ RADEON_WRITE( RADEON_GEN_INT_CNTL, |