Commit d201bca9 authored by Linus Torvalds's avatar Linus Torvalds

DRI CVS merge: make sure to clean up irq and DMA on final close.

parent 04499b41
...@@ -63,6 +63,12 @@ ...@@ -63,6 +63,12 @@
#define __HAVE_COUNTER9 _DRM_STAT_SPECIAL #define __HAVE_COUNTER9 _DRM_STAT_SPECIAL
#define __HAVE_COUNTER10 _DRM_STAT_MISSED #define __HAVE_COUNTER10 _DRM_STAT_MISSED
/* Driver customization:
*/
#define DRIVER_PRETAKEDOWN() do { \
gamma_do_cleanup_dma( dev ); \
} while (0)
/* DMA customization: /* DMA customization:
*/ */
#define __HAVE_DMA 1 #define __HAVE_DMA 1
......
...@@ -639,6 +639,14 @@ int gamma_do_cleanup_dma( drm_device_t *dev ) ...@@ -639,6 +639,14 @@ int gamma_do_cleanup_dma( drm_device_t *dev )
{ {
DRM_DEBUG( "%s\n", __FUNCTION__ ); DRM_DEBUG( "%s\n", __FUNCTION__ );
#if _HAVE_DMA_IRQ
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
if ( dev->irq ) DRM(irq_uninstall)(dev);
#endif
if ( dev->dev_private ) { if ( dev->dev_private ) {
drm_gamma_private_t *dev_priv = dev->dev_private; drm_gamma_private_t *dev_priv = dev->dev_private;
...@@ -660,6 +668,8 @@ int gamma_dma_init( struct inode *inode, struct file *filp, ...@@ -660,6 +668,8 @@ int gamma_dma_init( struct inode *inode, struct file *filp,
drm_device_t *dev = priv->dev; drm_device_t *dev = priv->dev;
drm_gamma_init_t init; drm_gamma_init_t init;
LOCK_TEST_WITH_RETURN( dev, filp );
if ( copy_from_user( &init, (drm_gamma_init_t *)arg, sizeof(init) ) ) if ( copy_from_user( &init, (drm_gamma_init_t *)arg, sizeof(init) ) )
return -EFAULT; return -EFAULT;
...@@ -832,6 +842,8 @@ void DRM(driver_irq_postinstall)( drm_device_t *dev ) { ...@@ -832,6 +842,8 @@ void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
void DRM(driver_irq_uninstall)( drm_device_t *dev ) { void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
drm_gamma_private_t *dev_priv = drm_gamma_private_t *dev_priv =
(drm_gamma_private_t *)dev->dev_private; (drm_gamma_private_t *)dev->dev_private;
if (!dev_priv)
return;
while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3); while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3);
......
...@@ -89,6 +89,10 @@ ...@@ -89,6 +89,10 @@
i810_reclaim_buffers( filp ); \ i810_reclaim_buffers( filp ); \
} while (0) } while (0)
#define DRIVER_PRETAKEDOWN() do { \
i810_dma_cleanup( dev ); \
} while (0)
/* DMA customization: /* DMA customization:
*/ */
#define __HAVE_DMA 1 #define __HAVE_DMA 1
...@@ -104,6 +108,7 @@ ...@@ -104,6 +108,7 @@
/* Don't need an irq any more. The template code will make sure that /* Don't need an irq any more. The template code will make sure that
* a noop stub is generated for compatibility. * a noop stub is generated for compatibility.
*/ */
/* XXX: Add vblank support? */
#define __HAVE_DMA_IRQ 0 #define __HAVE_DMA_IRQ 0
/* Buffer customization: /* Buffer customization:
......
...@@ -227,11 +227,19 @@ static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d, ...@@ -227,11 +227,19 @@ static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d,
return retcode; return retcode;
} }
static int i810_dma_cleanup(drm_device_t *dev) int i810_dma_cleanup(drm_device_t *dev)
{ {
drm_device_dma_t *dma = dev->dma; drm_device_dma_t *dma = dev->dma;
if(dev->dev_private) { #if _HAVE_DMA_IRQ
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
if (dev->irq) DRM(irq_uninstall)(dev);
#endif
if (dev->dev_private) {
int i; int i;
drm_i810_private_t *dev_priv = drm_i810_private_t *dev_priv =
(drm_i810_private_t *) dev->dev_private; (drm_i810_private_t *) dev->dev_private;
......
...@@ -38,8 +38,6 @@ typedef struct drm_i810_buf_priv { ...@@ -38,8 +38,6 @@ typedef struct drm_i810_buf_priv {
int currently_mapped; int currently_mapped;
void *virtual; void *virtual;
void *kernel_virtual; void *kernel_virtual;
int map_count;
struct vm_area_struct *vma;
} drm_i810_buf_priv_t; } drm_i810_buf_priv_t;
typedef struct _drm_i810_ring_buffer{ typedef struct _drm_i810_ring_buffer{
...@@ -86,6 +84,7 @@ extern int i810_getbuf(struct inode *inode, struct file *filp, ...@@ -86,6 +84,7 @@ extern int i810_getbuf(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int i810_dma_init(struct inode *inode, struct file *filp, extern int i810_dma_init(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int i810_dma_cleanup(drm_device_t *dev);
extern int i810_flush_ioctl(struct inode *inode, struct file *filp, extern int i810_flush_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern void i810_reclaim_buffers(struct file *filp); extern void i810_reclaim_buffers(struct file *filp);
......
...@@ -90,6 +90,10 @@ ...@@ -90,6 +90,10 @@
i830_reclaim_buffers( filp ); \ i830_reclaim_buffers( filp ); \
} while (0) } while (0)
#define DRIVER_PRETAKEDOWN() do { \
i830_dma_cleanup( dev ); \
} while (0)
/* DMA customization: /* DMA customization:
*/ */
#define __HAVE_DMA 1 #define __HAVE_DMA 1
...@@ -107,45 +111,17 @@ ...@@ -107,45 +111,17 @@
* the card, but are subject to subtle interactions between bios, * the card, but are subject to subtle interactions between bios,
* hardware and the driver. * hardware and the driver.
*/ */
/* XXX: Add vblank support? */
#define USE_IRQS 0 #define USE_IRQS 0
#if USE_IRQS #if USE_IRQS
#define __HAVE_DMA_IRQ 1 #define __HAVE_DMA_IRQ 1
#define __HAVE_SHARED_IRQ 1 #define __HAVE_SHARED_IRQ 1
#define DRIVER_PREINSTALL() do { \
drm_i830_private_t *dev_priv = \
(drm_i830_private_t *)dev->dev_private; \
\
I830_WRITE16( I830REG_HWSTAM, 0xffff ); \
I830_WRITE16( I830REG_INT_MASK_R, 0x0 ); \
I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 ); \
} while (0)
#define DRIVER_POSTINSTALL() do { \
drm_i830_private_t *dev_priv = \
(drm_i830_private_t *)dev->dev_private; \
I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 ); \
atomic_set(&dev_priv->irq_received, 0); \
atomic_set(&dev_priv->irq_emitted, 0); \
init_waitqueue_head(&dev_priv->irq_queue); \
} while (0)
/* This gets called too late to be useful: dev_priv has already been
* freed.
*/
#define DRIVER_UNINSTALL() do { \
} while (0)
#else #else
#define __HAVE_DMA_IRQ 0 #define __HAVE_DMA_IRQ 0
#endif #endif
/* Buffer customization: /* Buffer customization:
*/ */
......
...@@ -227,16 +227,24 @@ static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d, ...@@ -227,16 +227,24 @@ static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d,
return retcode; return retcode;
} }
static int i830_dma_cleanup(drm_device_t *dev) int i830_dma_cleanup(drm_device_t *dev)
{ {
drm_device_dma_t *dma = dev->dma; drm_device_dma_t *dma = dev->dma;
if(dev->dev_private) { #if _HAVE_DMA_IRQ
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
if (dev->irq) DRM(irq_uninstall)(dev);
#endif
if (dev->dev_private) {
int i; int i;
drm_i830_private_t *dev_priv = drm_i830_private_t *dev_priv =
(drm_i830_private_t *) dev->dev_private; (drm_i830_private_t *) dev->dev_private;
if(dev_priv->ring.virtual_start) { if (dev_priv->ring.virtual_start) {
DRM(ioremapfree)((void *) dev_priv->ring.virtual_start, DRM(ioremapfree)((void *) dev_priv->ring.virtual_start,
dev_priv->ring.Size); dev_priv->ring.Size);
} }
...@@ -248,14 +256,6 @@ static int i830_dma_cleanup(drm_device_t *dev) ...@@ -248,14 +256,6 @@ static int i830_dma_cleanup(drm_device_t *dev)
I830_WRITE(0x02080, 0x1ffff000); I830_WRITE(0x02080, 0x1ffff000);
} }
/* Disable interrupts here because after dev_private
* is freed, it's too late.
*/
if (dev->irq) {
I830_WRITE16( I830REG_INT_MASK_R, 0xffff );
I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
}
DRM(free)(dev->dev_private, sizeof(drm_i830_private_t), DRM(free)(dev->dev_private, sizeof(drm_i830_private_t),
DRM_MEM_DRIVER); DRM_MEM_DRIVER);
dev->dev_private = NULL; dev->dev_private = NULL;
......
...@@ -38,8 +38,6 @@ typedef struct drm_i830_buf_priv { ...@@ -38,8 +38,6 @@ typedef struct drm_i830_buf_priv {
int currently_mapped; int currently_mapped;
void *virtual; void *virtual;
void *kernel_virtual; void *kernel_virtual;
int map_count;
struct vm_area_struct *vma;
} drm_i830_buf_priv_t; } drm_i830_buf_priv_t;
typedef struct _drm_i830_ring_buffer{ typedef struct _drm_i830_ring_buffer{
...@@ -99,6 +97,7 @@ extern int i830_getbuf(struct inode *inode, struct file *filp, ...@@ -99,6 +97,7 @@ extern int i830_getbuf(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int i830_dma_init(struct inode *inode, struct file *filp, extern int i830_dma_init(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern int i830_dma_cleanup(drm_device_t *dev);
extern int i830_flush_ioctl(struct inode *inode, struct file *filp, extern int i830_flush_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
extern void i830_reclaim_buffers(struct file *filp); extern void i830_reclaim_buffers(struct file *filp);
......
...@@ -42,9 +42,9 @@ void DRM(dma_service)(int irq, void *device, struct pt_regs *regs) ...@@ -42,9 +42,9 @@ void DRM(dma_service)(int irq, void *device, struct pt_regs *regs)
u16 temp; u16 temp;
temp = I830_READ16(I830REG_INT_IDENTITY_R); temp = I830_READ16(I830REG_INT_IDENTITY_R);
printk("%s: %x\n", __FUNCTION__, temp); DRM_DEBUG("%x\n", temp);
if(temp == 0) if (temp == 0)
return; return;
I830_WRITE16(I830REG_INT_IDENTITY_R, temp); I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
...@@ -175,3 +175,34 @@ int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -175,3 +175,34 @@ int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd,
return i830_wait_irq( dev, irqwait.irq_seq ); return i830_wait_irq( dev, irqwait.irq_seq );
} }
/* drm_dma.h hooks
*/
void DRM(driver_irq_preinstall)( drm_device_t *dev ) {
drm_i830_private_t *dev_priv =
(drm_i830_private_t *)dev->dev_private;
I830_WRITE16( I830REG_HWSTAM, 0xffff );
I830_WRITE16( I830REG_INT_MASK_R, 0x0 );
I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
atomic_set(&dev_priv->irq_received, 0);
atomic_set(&dev_priv->irq_emitted, 0);
init_waitqueue_head(&dev_priv->irq_queue);
}
void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
drm_i830_private_t *dev_priv =
(drm_i830_private_t *)dev->dev_private;
I830_WRITE16( I830REG_INT_ENABLE_R, 0x2 );
}
void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
drm_i830_private_t *dev_priv =
(drm_i830_private_t *)dev->dev_private;
if (!dev_priv)
return;
I830_WRITE16( I830REG_INT_MASK_R, 0xffff );
I830_WRITE16( I830REG_INT_ENABLE_R, 0x0 );
}
...@@ -72,7 +72,7 @@ ...@@ -72,7 +72,7 @@
/* Driver customization: /* Driver customization:
*/ */
#define DRIVER_PRETAKEDOWN() do { \ #define DRIVER_PRETAKEDOWN() do { \
if ( dev->dev_private ) mga_do_cleanup_dma( dev ); \ mga_do_cleanup_dma( dev ); \
} while (0) } while (0)
/* DMA customization: /* DMA customization:
......
...@@ -639,6 +639,14 @@ int mga_do_cleanup_dma( drm_device_t *dev ) ...@@ -639,6 +639,14 @@ int mga_do_cleanup_dma( drm_device_t *dev )
{ {
DRM_DEBUG( "\n" ); DRM_DEBUG( "\n" );
#if _HAVE_DMA_IRQ
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
if ( dev->irq ) DRM(irq_uninstall)(dev);
#endif
if ( dev->dev_private ) { if ( dev->dev_private ) {
drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_private_t *dev_priv = dev->dev_private;
...@@ -666,6 +674,8 @@ int mga_dma_init( DRM_IOCTL_ARGS ) ...@@ -666,6 +674,8 @@ int mga_dma_init( DRM_IOCTL_ARGS )
DRM_DEVICE; DRM_DEVICE;
drm_mga_init_t init; drm_mga_init_t init;
LOCK_TEST_WITH_RETURN( dev, filp );
DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t *)data, sizeof(init) ); DRM_COPY_FROM_USER_IOCTL( init, (drm_mga_init_t *)data, sizeof(init) );
switch ( init.func ) { switch ( init.func ) {
......
...@@ -95,8 +95,9 @@ void mga_driver_irq_postinstall( drm_device_t *dev ) { ...@@ -95,8 +95,9 @@ void mga_driver_irq_postinstall( drm_device_t *dev ) {
void mga_driver_irq_uninstall( drm_device_t *dev ) { void mga_driver_irq_uninstall( drm_device_t *dev ) {
drm_mga_private_t *dev_priv = drm_mga_private_t *dev_priv =
(drm_mga_private_t *)dev->dev_private; (drm_mga_private_t *)dev->dev_private;
if ( dev_priv ) { if (!dev_priv)
return;
/* Disable *all* interrupts */ /* Disable *all* interrupts */
MGA_WRITE( MGA_IEN, 0 ); MGA_WRITE( MGA_IEN, 0 );
}
} }
...@@ -85,7 +85,7 @@ ...@@ -85,7 +85,7 @@
} while (0) } while (0)
#define DRIVER_PRETAKEDOWN() do { \ #define DRIVER_PRETAKEDOWN() do { \
if ( dev->dev_private ) r128_do_cleanup_cce( dev ); \ r128_do_cleanup_cce( dev ); \
} while (0) } while (0)
/* DMA customization: /* DMA customization:
......
...@@ -613,6 +613,15 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) ...@@ -613,6 +613,15 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init )
int r128_do_cleanup_cce( drm_device_t *dev ) int r128_do_cleanup_cce( drm_device_t *dev )
{ {
#if _HAVE_DMA_IRQ
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
if ( dev->irq ) DRM(irq_uninstall)(dev);
#endif
if ( dev->dev_private ) { if ( dev->dev_private ) {
drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_private_t *dev_priv = dev->dev_private;
...@@ -649,6 +658,8 @@ int r128_cce_init( DRM_IOCTL_ARGS ) ...@@ -649,6 +658,8 @@ int r128_cce_init( DRM_IOCTL_ARGS )
DRM_DEBUG( "\n" ); DRM_DEBUG( "\n" );
LOCK_TEST_WITH_RETURN( dev, filp );
DRM_COPY_FROM_USER_IOCTL( init, (drm_r128_init_t *)data, sizeof(init) ); DRM_COPY_FROM_USER_IOCTL( init, (drm_r128_init_t *)data, sizeof(init) );
switch ( init.func ) { switch ( init.func ) {
......
...@@ -95,8 +95,9 @@ void r128_driver_irq_postinstall( drm_device_t *dev ) { ...@@ -95,8 +95,9 @@ void r128_driver_irq_postinstall( drm_device_t *dev ) {
void r128_driver_irq_uninstall( drm_device_t *dev ) { void r128_driver_irq_uninstall( drm_device_t *dev ) {
drm_r128_private_t *dev_priv = drm_r128_private_t *dev_priv =
(drm_r128_private_t *)dev->dev_private; (drm_r128_private_t *)dev->dev_private;
if ( dev_priv ) { if (!dev_priv)
return;
/* Disable *all* interrupts */ /* Disable *all* interrupts */
R128_WRITE( R128_GEN_INT_CNTL, 0 ); R128_WRITE( R128_GEN_INT_CNTL, 0 );
}
} }
...@@ -1266,6 +1266,14 @@ int radeon_do_cleanup_cp( drm_device_t *dev ) ...@@ -1266,6 +1266,14 @@ int radeon_do_cleanup_cp( drm_device_t *dev )
{ {
DRM_DEBUG( "\n" ); DRM_DEBUG( "\n" );
#if _HAVE_DMA_IRQ
/* Make sure interrupts are disabled here because the uninstall ioctl
* may not have been called from userspace and after dev_private
* is freed, it's too late.
*/
if ( dev->irq ) DRM(irq_uninstall)(dev);
#endif
if ( dev->dev_private ) { if ( dev->dev_private ) {
drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_private_t *dev_priv = dev->dev_private;
...@@ -1298,6 +1306,8 @@ int radeon_cp_init( DRM_IOCTL_ARGS ) ...@@ -1298,6 +1306,8 @@ int radeon_cp_init( DRM_IOCTL_ARGS )
DRM_DEVICE; DRM_DEVICE;
drm_radeon_init_t init; drm_radeon_init_t init;
LOCK_TEST_WITH_RETURN( dev, filp );
DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t *)data, sizeof(init) ); DRM_COPY_FROM_USER_IOCTL( init, (drm_radeon_init_t *)data, sizeof(init) );
switch ( init.func ) { switch ( init.func ) {
......
...@@ -250,8 +250,9 @@ void DRM(driver_irq_postinstall)( drm_device_t *dev ) { ...@@ -250,8 +250,9 @@ void DRM(driver_irq_postinstall)( drm_device_t *dev ) {
void DRM(driver_irq_uninstall)( drm_device_t *dev ) { void DRM(driver_irq_uninstall)( drm_device_t *dev ) {
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;
if ( dev_priv ) { if (!dev_priv)
return;
/* Disable *all* interrupts */ /* Disable *all* interrupts */
RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
}
} }
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