Commit d175a2f8 authored by Linus Torvalds's avatar Linus Torvalds

Update to DRI CVS tree

parent 48452f9f
...@@ -30,14 +30,20 @@ ...@@ -30,14 +30,20 @@
#define __NO_VERSION__ #define __NO_VERSION__
#include "drmP.h" #include "drmP.h"
#if PAGE_SIZE == 8192 #if PAGE_SIZE == 65536
# define ATI_PCIGART_TABLE_ORDER 0
# define ATI_PCIGART_TABLE_PAGES (1 << 0)
#elif PAGE_SIZE == 16384
# define ATI_PCIGART_TABLE_ORDER 1
# define ATI_PCIGART_TABLE_PAGES (1 << 1)
#elif PAGE_SIZE == 8192
# define ATI_PCIGART_TABLE_ORDER 2 # define ATI_PCIGART_TABLE_ORDER 2
# define ATI_PCIGART_TABLE_PAGES (1 << 2) # define ATI_PCIGART_TABLE_PAGES (1 << 2)
#elif PAGE_SIZE == 4096 #elif PAGE_SIZE == 4096
# define ATI_PCIGART_TABLE_ORDER 3 # define ATI_PCIGART_TABLE_ORDER 3
# define ATI_PCIGART_TABLE_PAGES (1 << 3) # define ATI_PCIGART_TABLE_PAGES (1 << 3)
#else #else
# error - PAGE_SIZE not 8K or 4K # error - PAGE_SIZE not 64K, 16K, 8K or 4K
#endif #endif
# define ATI_MAX_PCIGART_PAGES 8192 /* 32 MB aperture, 4K pages */ # define ATI_MAX_PCIGART_PAGES 8192 /* 32 MB aperture, 4K pages */
......
...@@ -345,6 +345,19 @@ typedef struct drm_irq_busid { ...@@ -345,6 +345,19 @@ typedef struct drm_irq_busid {
int funcnum; int funcnum;
} drm_irq_busid_t; } drm_irq_busid_t;
typedef enum {
_DRM_VBLANK_ABSOLUTE = 0x0, /* Wait for specific vblank sequence number */
_DRM_VBLANK_RELATIVE = 0x1 /* Wait for given number of vblanks */
} drm_vblank_seq_type_t;
typedef struct drm_radeon_vbl_wait {
drm_vblank_seq_type_t type;
unsigned int sequence;
long tval_sec;
long tval_usec;
} drm_wait_vblank_t;
typedef struct drm_agp_mode { typedef struct drm_agp_mode {
unsigned long mode; unsigned long mode;
} drm_agp_mode_t; } drm_agp_mode_t;
...@@ -439,6 +452,8 @@ typedef struct drm_scatter_gather { ...@@ -439,6 +452,8 @@ typedef struct drm_scatter_gather {
#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t) #define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t)
#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t) #define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t)
#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t)
/* Device specfic ioctls should only be in their respective headers /* Device specfic ioctls should only be in their respective headers
* The device specific ioctl range is 0x40 to 0x79. */ * The device specific ioctl range is 0x40 to 0x79. */
#define DRM_COMMAND_BASE 0x40 #define DRM_COMMAND_BASE 0x40
......
...@@ -576,6 +576,10 @@ typedef struct drm_device { ...@@ -576,6 +576,10 @@ typedef struct drm_device {
int last_context; /* Last current context */ int last_context; /* Last current context */
unsigned long last_switch; /* jiffies at last context switch */ unsigned long last_switch; /* jiffies at last context switch */
struct work_struct work; struct work_struct work;
#if __HAVE_VBL_IRQ
wait_queue_head_t vbl_queue;
atomic_t vbl_received;
#endif
cycles_t ctx_start; cycles_t ctx_start;
cycles_t lck_start; cycles_t lck_start;
#if __HAVE_DMA_HISTOGRAM #if __HAVE_DMA_HISTOGRAM
...@@ -808,6 +812,14 @@ extern int DRM(irq_install)( drm_device_t *dev, int irq ); ...@@ -808,6 +812,14 @@ extern int DRM(irq_install)( drm_device_t *dev, int irq );
extern int DRM(irq_uninstall)( drm_device_t *dev ); extern int DRM(irq_uninstall)( drm_device_t *dev );
extern void DRM(dma_service)( int irq, void *device, extern void DRM(dma_service)( int irq, void *device,
struct pt_regs *regs ); struct pt_regs *regs );
extern void DRM(driver_irq_preinstall)( drm_device_t *dev );
extern void DRM(driver_irq_postinstall)( drm_device_t *dev );
extern void DRM(driver_irq_uninstall)( drm_device_t *dev );
#if __HAVE_VBL_IRQ
extern int DRM(wait_vblank)(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg);
extern int DRM(vblank_wait)(drm_device_t *dev, unsigned int *vbl_seq);
#endif
#if __HAVE_DMA_IRQ_BH #if __HAVE_DMA_IRQ_BH
extern void DRM(dma_immediate_bh)( void *dev ); extern void DRM(dma_immediate_bh)( void *dev );
#endif #endif
......
...@@ -535,8 +535,12 @@ int DRM(irq_install)( drm_device_t *dev, int irq ) ...@@ -535,8 +535,12 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
INIT_WORK(&dev->work, DRM(dma_immediate_bh), dev); INIT_WORK(&dev->work, DRM(dma_immediate_bh), dev);
#endif #endif
#if __HAVE_VBL_IRQ
init_waitqueue_head(&dev->vbl_queue);
#endif
/* Before installing handler */ /* Before installing handler */
DRIVER_PREINSTALL(); DRM(driver_irq_preinstall)(dev);
/* Install handler */ /* Install handler */
ret = request_irq( dev->irq, DRM(dma_service), ret = request_irq( dev->irq, DRM(dma_service),
...@@ -549,7 +553,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq ) ...@@ -549,7 +553,7 @@ int DRM(irq_install)( drm_device_t *dev, int irq )
} }
/* After installing handler */ /* After installing handler */
DRIVER_POSTINSTALL(); DRM(driver_irq_postinstall)(dev);
return 0; return 0;
} }
...@@ -568,7 +572,7 @@ int DRM(irq_uninstall)( drm_device_t *dev ) ...@@ -568,7 +572,7 @@ int DRM(irq_uninstall)( drm_device_t *dev )
DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq ); DRM_DEBUG( "%s: irq=%d\n", __FUNCTION__, irq );
DRIVER_UNINSTALL(); DRM(driver_irq_uninstall)( dev );
free_irq( irq, dev ); free_irq( irq, dev );
...@@ -595,6 +599,40 @@ int DRM(control)( struct inode *inode, struct file *filp, ...@@ -595,6 +599,40 @@ int DRM(control)( struct inode *inode, struct file *filp,
} }
} }
#if __HAVE_VBL_IRQ
int DRM(wait_vblank)( DRM_IOCTL_ARGS )
{
drm_file_t *priv = filp->private_data;
drm_device_t *dev = priv->dev;
drm_wait_vblank_t vblwait;
struct timeval now;
int ret;
if (!dev->irq)
return -EINVAL;
DRM_COPY_FROM_USER_IOCTL( vblwait, (drm_wait_vblank_t *)data,
sizeof(vblwait) );
if ( vblwait.type == _DRM_VBLANK_RELATIVE ) {
vblwait.sequence += atomic_read( &dev->vbl_received );
}
ret = DRM(vblank_wait)( dev, &vblwait.sequence );
do_gettimeofday( &now );
vblwait.tval_sec = now.tv_sec;
vblwait.tval_usec = now.tv_usec;
DRM_COPY_TO_USER_IOCTL( (drm_wait_vblank_t *)data, vblwait,
sizeof(vblwait) );
return ret;
}
#endif /* __HAVE_VBL_IRQ */
#else #else
int DRM(control)( struct inode *inode, struct file *filp, int DRM(control)( struct inode *inode, struct file *filp,
......
...@@ -222,6 +222,10 @@ static drm_ioctl_desc_t DRM(ioctls)[] = { ...@@ -222,6 +222,10 @@ static drm_ioctl_desc_t DRM(ioctls)[] = {
[DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free), 1, 1 }, [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = { DRM(sg_free), 1, 1 },
#endif #endif
#if __HAVE_VBL_IRQ
[DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = { DRM(wait_vblank), 0, 0 },
#endif
DRIVER_IOCTLS DRIVER_IOCTLS
}; };
......
...@@ -44,16 +44,47 @@ ...@@ -44,16 +44,47 @@
#define DRM_MALLOC(x) kmalloc(x, GFP_KERNEL) #define DRM_MALLOC(x) kmalloc(x, GFP_KERNEL)
#define DRM_FREE(x) kfree(x) #define DRM_FREE(x) kfree(x)
#define DRM_GETSAREA() \ #define DRM_GETSAREA() \
do { \ do { \
struct list_head *list; \ struct list_head *list; \
list_for_each( list, &dev->maplist->head ) { \ list_for_each( list, &dev->maplist->head ) { \
drm_map_list_t *entry = (drm_map_list_t *)list; \ drm_map_list_t *entry = (drm_map_list_t *)list; \
if ( entry->map && \ if ( entry->map && \
entry->map->type == _DRM_SHM && \ entry->map->type == _DRM_SHM && \
(entry->map->flags & _DRM_CONTAINS_LOCK) ) { \ (entry->map->flags & _DRM_CONTAINS_LOCK) ) { \
dev_priv->sarea = entry->map; \ dev_priv->sarea = entry->map; \
break; \ break; \
} \ } \
} \ } \
} while (0) } 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 )
...@@ -100,6 +100,13 @@ ...@@ -100,6 +100,13 @@
[DRM_IOCTL_NR(DRM_IOCTL_RADEON_IRQ_EMIT)] = { radeon_irq_emit, 1, 0 }, \ [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 }, [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: /* When a client dies:
* - Check for and clean up flipped page state * - Check for and clean up flipped page state
* - Free any alloced agp memory. * - Free any alloced agp memory.
...@@ -128,57 +135,15 @@ ...@@ -128,57 +135,15 @@
} \ } \
} while (0) } while (0)
#else
#define __HAVE_DMA_IRQ 0
#endif
/* DMA customization: /* DMA customization:
*/ */
#define __HAVE_DMA 1 #define __HAVE_DMA 1
#define __HAVE_DMA_IRQ 1
#define __HAVE_DMA_IRQ_BH 1
#define __HAVE_SHARED_IRQ 1
#define DRIVER_PREINSTALL() do { \
drm_radeon_private_t *dev_priv = \
(drm_radeon_private_t *)dev->dev_private; \
u32 tmp; \
\
/* Clear bit if it's already high: */ \
tmp = RADEON_READ( RADEON_GEN_INT_STATUS ); \
tmp = tmp & RADEON_SW_INT_TEST_ACK; \
RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp ); \
\
/* Disable *all* interrupts */ \
RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); \
} while (0)
#ifdef __linux__
#define IWH(x) init_waitqueue_head(x)
#else
#define IWH(x)
#endif
#define DRIVER_POSTINSTALL() do { \
drm_radeon_private_t *dev_priv = \
(drm_radeon_private_t *)dev->dev_private; \
\
atomic_set(&dev_priv->irq_received, 0); \
atomic_set(&dev_priv->irq_emitted, 0); \
IWH(&dev_priv->irq_queue); \
\
/* Turn on SW_INT only */ \
RADEON_WRITE( RADEON_GEN_INT_CNTL, \
RADEON_SW_INT_ENABLE ); \
} while (0)
#define DRIVER_UNINSTALL() do { \
drm_radeon_private_t *dev_priv = \
(drm_radeon_private_t *)dev->dev_private; \
if ( dev_priv ) { \
/* Disable *all* interrupts */ \
RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); \
} \
} while (0)
/* Buffer customization: /* Buffer customization:
*/ */
#define DRIVER_BUF_PRIV_T drm_radeon_buf_priv_t #define DRIVER_BUF_PRIV_T drm_radeon_buf_priv_t
......
...@@ -517,7 +517,7 @@ typedef struct drm_radeon_indirect { ...@@ -517,7 +517,7 @@ typedef struct drm_radeon_indirect {
#define RADEON_PARAM_LAST_FRAME 2 #define RADEON_PARAM_LAST_FRAME 2
#define RADEON_PARAM_LAST_DISPATCH 3 #define RADEON_PARAM_LAST_DISPATCH 3
#define RADEON_PARAM_LAST_CLEAR 4 #define RADEON_PARAM_LAST_CLEAR 4
#define RADEON_PARAM_IRQ_ACTIVE 5 #define RADEON_PARAM_IRQ_NR 5
#define RADEON_PARAM_AGP_BASE 6 /* card offset of agp base */ #define RADEON_PARAM_AGP_BASE 6 /* card offset of agp base */
typedef struct drm_radeon_getparam { typedef struct drm_radeon_getparam {
......
...@@ -139,9 +139,9 @@ typedef struct drm_radeon_private { ...@@ -139,9 +139,9 @@ typedef struct drm_radeon_private {
struct mem_block *agp_heap; struct mem_block *agp_heap;
struct mem_block *fb_heap; struct mem_block *fb_heap;
wait_queue_head_t irq_queue; /* SW interrupt */
atomic_t irq_received; wait_queue_head_t swi_queue;
atomic_t irq_emitted; atomic_t swi_emitted;
} drm_radeon_private_t; } drm_radeon_private_t;
...@@ -187,11 +187,12 @@ extern int radeon_mem_init_heap( DRM_IOCTL_ARGS ); ...@@ -187,11 +187,12 @@ extern int radeon_mem_init_heap( DRM_IOCTL_ARGS );
extern void radeon_mem_takedown( struct mem_block **heap ); extern void radeon_mem_takedown( struct mem_block **heap );
extern void radeon_mem_release( struct mem_block *heap ); extern void radeon_mem_release( struct mem_block *heap );
/* radeon_irq.c */
extern int radeon_irq_emit( DRM_IOCTL_ARGS ); extern int radeon_irq_emit( DRM_IOCTL_ARGS );
extern int radeon_irq_wait( DRM_IOCTL_ARGS ); extern int radeon_irq_wait( DRM_IOCTL_ARGS );
extern int radeon_emit_and_wait_irq(drm_device_t *dev); extern int radeon_emit_and_wait_irq(drm_device_t *dev);
extern int radeon_wait_irq(drm_device_t *dev, int irq_nr); extern int radeon_wait_irq(drm_device_t *dev, int swi_nr);
extern int radeon_emit_irq(drm_device_t *dev); extern int radeon_emit_irq(drm_device_t *dev);
...@@ -271,11 +272,15 @@ extern int radeon_emit_irq(drm_device_t *dev); ...@@ -271,11 +272,15 @@ extern int radeon_emit_irq(drm_device_t *dev);
#define RADEON_GEN_INT_CNTL 0x0040 #define RADEON_GEN_INT_CNTL 0x0040
# define RADEON_CRTC_VBLANK_MASK (1 << 0)
# define RADEON_GUI_IDLE_INT_ENABLE (1 << 19) # define RADEON_GUI_IDLE_INT_ENABLE (1 << 19)
# define RADEON_SW_INT_ENABLE (1 << 25) # define RADEON_SW_INT_ENABLE (1 << 25)
#define RADEON_GEN_INT_STATUS 0x0044 #define RADEON_GEN_INT_STATUS 0x0044
# define RADEON_CRTC_VBLANK_STAT (1 << 0)
# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0)
# define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19) # define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19)
# define RADEON_SW_INT_TEST (1 << 25)
# define RADEON_SW_INT_TEST_ACK (1 << 25) # define RADEON_SW_INT_TEST_ACK (1 << 25)
# define RADEON_SW_INT_FIRE (1 << 26) # define RADEON_SW_INT_FIRE (1 << 26)
...@@ -632,6 +637,7 @@ extern int radeon_emit_irq(drm_device_t *dev); ...@@ -632,6 +637,7 @@ extern int radeon_emit_irq(drm_device_t *dev);
#define RADEON_LAST_FRAME_REG RADEON_SCRATCH_REG0 #define RADEON_LAST_FRAME_REG RADEON_SCRATCH_REG0
#define RADEON_LAST_DISPATCH_REG RADEON_SCRATCH_REG1 #define RADEON_LAST_DISPATCH_REG RADEON_SCRATCH_REG1
#define RADEON_LAST_CLEAR_REG RADEON_SCRATCH_REG2 #define RADEON_LAST_CLEAR_REG RADEON_SCRATCH_REG2
#define RADEON_LAST_SWI_REG RADEON_SCRATCH_REG3
#define RADEON_LAST_DISPATCH 1 #define RADEON_LAST_DISPATCH 1
#define RADEON_MAX_VB_AGE 0x7fffffff #define RADEON_MAX_VB_AGE 0x7fffffff
......
/* radeon_mem.c -- Simple agp/fb memory manager for radeon -*- linux-c -*- /* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*-
* *
* Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
* *
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
* *
* Authors: * Authors:
* Keith Whitwell <keith@tungstengraphics.com> * Keith Whitwell <keith@tungstengraphics.com>
* Michel Dänzer <michel@daenzer.net>
*/ */
#include "radeon.h" #include "radeon.h"
...@@ -58,110 +59,117 @@ void DRM(dma_service)( DRM_IRQ_ARGS ) ...@@ -58,110 +59,117 @@ void DRM(dma_service)( DRM_IRQ_ARGS )
drm_device_t *dev = (drm_device_t *) arg; drm_device_t *dev = (drm_device_t *) arg;
drm_radeon_private_t *dev_priv = drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *)dev->dev_private; (drm_radeon_private_t *)dev->dev_private;
u32 temp; u32 stat;
/* Need to wait for fifo to drain? stat = RADEON_READ(RADEON_GEN_INT_STATUS);
*/ if (!stat)
temp = RADEON_READ(RADEON_GEN_INT_STATUS); return;
temp = temp & RADEON_SW_INT_TEST_ACK;
if (temp == 0) return;
RADEON_WRITE(RADEON_GEN_INT_STATUS, temp);
atomic_inc(&dev_priv->irq_received);
#ifdef __linux__
schedule_work(&dev->work);
#endif /* __linux__ */
#ifdef __FreeBSD__
taskqueue_enqueue(taskqueue_swi, &dev->task);
#endif /* __FreeBSD__ */
}
void DRM(dma_immediate_bh)( DRM_TASKQUEUE_ARGS ) /* SW interrupt */
{ if (stat & RADEON_SW_INT_TEST) {
drm_device_t *dev = (drm_device_t *) arg; DRM_WAKEUP( &dev_priv->swi_queue );
drm_radeon_private_t *dev_priv = }
(drm_radeon_private_t *)dev->dev_private;
#ifdef __linux__ #if __HAVE_VBL_IRQ
wake_up_interruptible(&dev_priv->irq_queue); /* VBLANK interrupt */
#endif /* __linux__ */ if (stat & RADEON_CRTC_VBLANK_STAT) {
#ifdef __FreeBSD__ atomic_inc(&dev->vbl_received);
wakeup( &dev_priv->irq_queue ); DRM_WAKEUP(&dev->vbl_queue);
}
#endif #endif
/* 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)
{
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) int radeon_emit_irq(drm_device_t *dev)
{ {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
unsigned int ret;
RING_LOCALS; RING_LOCALS;
atomic_inc(&dev_priv->irq_emitted); atomic_inc(&dev_priv->swi_emitted);
ret = atomic_read(&dev_priv->swi_emitted);
BEGIN_RING(2); BEGIN_RING( 4 );
OUT_RING( CP_PACKET0( RADEON_GEN_INT_STATUS, 0 ) ); OUT_RING_REG( RADEON_LAST_SWI_REG, ret );
OUT_RING( RADEON_SW_INT_FIRE ); OUT_RING_REG( RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE );
ADVANCE_RING(); ADVANCE_RING();
COMMIT_RING(); COMMIT_RING();
return atomic_read(&dev_priv->irq_emitted); return ret;
} }
int radeon_wait_irq(drm_device_t *dev, int irq_nr) int radeon_wait_irq(drm_device_t *dev, int swi_nr)
{ {
drm_radeon_private_t *dev_priv = drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *)dev->dev_private; (drm_radeon_private_t *)dev->dev_private;
#ifdef __linux__
DECLARE_WAITQUEUE(entry, current);
unsigned long end = jiffies + HZ*3;
#endif /* __linux__ */
int ret = 0; int ret = 0;
if (atomic_read(&dev_priv->irq_received) >= irq_nr) if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr)
return 0; return 0;
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
#ifdef __linux__ /* This is a hack to work around mysterious freezes on certain
add_wait_queue(&dev_priv->irq_queue, &entry); * systems:
*/
for (;;) { radeon_acknowledge_irqs( dev_priv );
current->state = TASK_INTERRUPTIBLE;
if (atomic_read(&dev_priv->irq_received) >= irq_nr) DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ,
break; RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr );
if((signed)(end - jiffies) <= 0) {
ret = -EBUSY; /* Lockup? Missed irq? */
break;
}
schedule_timeout(HZ*3);
if (signal_pending(current)) {
ret = -EINTR;
break;
}
}
current->state = TASK_RUNNING;
remove_wait_queue(&dev_priv->irq_queue, &entry);
return ret;
#endif /* __linux__ */
#ifdef __FreeBSD__
ret = tsleep( &dev_priv->irq_queue, PZERO | PCATCH, \
"rdnirq", 3*hz );
if ( (ret == EWOULDBLOCK) || (ret == EINTR) )
return DRM_ERR(EBUSY);
return ret; return ret;
#endif /* __FreeBSD__ */
} }
int radeon_emit_and_wait_irq(drm_device_t *dev) int radeon_emit_and_wait_irq(drm_device_t *dev)
{ {
return radeon_wait_irq( dev, radeon_emit_irq(dev) ); return radeon_wait_irq( dev, radeon_emit_irq(dev) );
} }
#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;
unsigned int cur_vblank;
int ret = 0;
if ( !dev_priv ) {
DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ );
return DRM_ERR(EINVAL);
}
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...
*/
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. /* Needs the lock as it touches the ring.
*/ */
int radeon_irq_emit( DRM_IOCTL_ARGS ) int radeon_irq_emit( DRM_IOCTL_ARGS )
...@@ -211,3 +219,38 @@ int radeon_irq_wait( DRM_IOCTL_ARGS ) ...@@ -211,3 +219,38 @@ int radeon_irq_wait( DRM_IOCTL_ARGS )
return radeon_wait_irq( dev, irqwait.irq_seq ); return radeon_wait_irq( dev, irqwait.irq_seq );
} }
/* drm_dma.h hooks
*/
void DRM(driver_irq_preinstall)( drm_device_t *dev ) {
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *)dev->dev_private;
/* Disable *all* interrupts */
RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
/* Clear bits if they're already high */
radeon_acknowledge_irqs( dev_priv );
}
void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *)dev->dev_private;
atomic_set(&dev_priv->swi_emitted, 0);
DRM_INIT_WAITQUEUE( &dev_priv->swi_queue );
/* Turn on SW and VBL ints */
RADEON_WRITE( RADEON_GEN_INT_CNTL,
RADEON_CRTC_VBLANK_MASK |
RADEON_SW_INT_ENABLE );
}
void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
drm_radeon_private_t *dev_priv =
(drm_radeon_private_t *)dev->dev_private;
if ( dev_priv ) {
/* Disable *all* interrupts */
RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
}
}
...@@ -118,7 +118,7 @@ static void free_block( struct mem_block *p ) ...@@ -118,7 +118,7 @@ static void free_block( struct mem_block *p )
p->size += q->size; p->size += q->size;
p->next = q->next; p->next = q->next;
p->next->prev = p; p->next->prev = p;
DRM_FREE(p); DRM_FREE(q);
} }
if (p->prev->pid == 0) { if (p->prev->pid == 0) {
......
...@@ -1283,7 +1283,6 @@ int radeon_cp_clear( DRM_IOCTL_ARGS ) ...@@ -1283,7 +1283,6 @@ int radeon_cp_clear( DRM_IOCTL_ARGS )
} }
/* Not sure why this isn't set all the time: /* Not sure why this isn't set all the time:
*/ */
static int radeon_do_init_pageflip( drm_device_t *dev ) static int radeon_do_init_pageflip( drm_device_t *dev )
...@@ -2172,8 +2171,8 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS ) ...@@ -2172,8 +2171,8 @@ int radeon_cp_getparam( DRM_IOCTL_ARGS )
dev_priv->stats.last_clear_reads++; dev_priv->stats.last_clear_reads++;
value = GET_SCRATCH( 2 ); value = GET_SCRATCH( 2 );
break; break;
case RADEON_PARAM_IRQ_ACTIVE: case RADEON_PARAM_IRQ_NR:
value = dev->irq ? 1 : 0; value = dev->irq;
break; break;
case RADEON_PARAM_AGP_BASE: case RADEON_PARAM_AGP_BASE:
value = dev_priv->agp_vm_start; value = dev_priv->agp_vm_start;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment