diff options
Diffstat (limited to 'linux')
-rw-r--r-- | linux/drm_dma.h | 7 | ||||
-rw-r--r-- | linux/gamma.h | 6 | ||||
-rw-r--r-- | linux/gamma_dma.c | 12 | ||||
-rw-r--r-- | linux/gamma_drv.h | 1 | ||||
-rw-r--r-- | linux/i810.h | 7 | ||||
-rw-r--r-- | linux/i810_dma.c | 12 | ||||
-rw-r--r-- | linux/i810_drv.h | 3 | ||||
-rw-r--r-- | linux/i830.h | 36 | ||||
-rw-r--r-- | linux/i830_dma.c | 22 | ||||
-rw-r--r-- | linux/i830_drv.h | 3 | ||||
-rw-r--r-- | linux/i830_irq.c | 41 |
11 files changed, 97 insertions, 53 deletions
diff --git a/linux/drm_dma.h b/linux/drm_dma.h index 7c1785b4..34ab5322 100644 --- a/linux/drm_dma.h +++ b/linux/drm_dma.h @@ -194,6 +194,13 @@ int DRM(irq_install)( drm_device_t *dev, int irq ) return -EINVAL; down( &dev->struct_sem ); + + /* Driver must have been initialized */ + if ( !dev->dev_private ) { + up( &dev->struct_sem ); + return -EINVAL; + } + if ( dev->irq ) { up( &dev->struct_sem ); return -EBUSY; diff --git a/linux/gamma.h b/linux/gamma.h index da8f52bb..54dafcfc 100644 --- a/linux/gamma.h +++ b/linux/gamma.h @@ -63,6 +63,12 @@ #define __HAVE_COUNTER9 _DRM_STAT_SPECIAL #define __HAVE_COUNTER10 _DRM_STAT_MISSED +/* Driver customization: + */ +#define DRIVER_PRETAKEDOWN() do { \ + gamma_do_cleanup_dma( dev ); \ +} while (0) + /* DMA customization: */ #define __HAVE_DMA 1 diff --git a/linux/gamma_dma.c b/linux/gamma_dma.c index 691c55a4..0aacc4e9 100644 --- a/linux/gamma_dma.c +++ b/linux/gamma_dma.c @@ -645,6 +645,14 @@ int gamma_do_cleanup_dma( drm_device_t *dev ) { 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 ) { drm_gamma_private_t *dev_priv = dev->dev_private; @@ -666,6 +674,8 @@ int gamma_dma_init( struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_gamma_init_t init; + LOCK_TEST_WITH_RETURN( dev, filp ); + if ( copy_from_user( &init, (drm_gamma_init_t *)arg, sizeof(init) ) ) return -EFAULT; @@ -838,6 +848,8 @@ void DRM(driver_irq_postinstall)( drm_device_t *dev ) { void DRM(driver_irq_uninstall)( drm_device_t *dev ) { drm_gamma_private_t *dev_priv = (drm_gamma_private_t *)dev->dev_private; + if (!dev_priv) + return; while(GAMMA_READ(GAMMA_INFIFOSPACE) < 3); diff --git a/linux/gamma_drv.h b/linux/gamma_drv.h index fc91993f..fc78a11a 100644 --- a/linux/gamma_drv.h +++ b/linux/gamma_drv.h @@ -49,6 +49,7 @@ extern int gamma_dma_init( struct inode *inode, struct file *filp, extern int gamma_dma_copy( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); +extern int gamma_do_cleanup_dma( drm_device_t *dev ); extern void gamma_dma_ready(drm_device_t *dev); extern void gamma_dma_quiescent_single(drm_device_t *dev); extern void gamma_dma_quiescent_dual(drm_device_t *dev); diff --git a/linux/i810.h b/linux/i810.h index 72cbed32..bfb760ab 100644 --- a/linux/i810.h +++ b/linux/i810.h @@ -86,7 +86,11 @@ */ #define __HAVE_RELEASE 1 #define DRIVER_RELEASE() do { \ - i810_reclaim_buffers( filp ); \ + i810_reclaim_buffers( filp ); \ +} while (0) + +#define DRIVER_PRETAKEDOWN() do { \ + i810_dma_cleanup( dev ); \ } while (0) /* DMA customization: @@ -104,6 +108,7 @@ /* Don't need an irq any more. The template code will make sure that * a noop stub is generated for compatibility. */ +/* XXX: Add vblank support? */ #define __HAVE_DMA_IRQ 0 /* Buffer customization: diff --git a/linux/i810_dma.c b/linux/i810_dma.c index 30b7dfcf..8e0e8f45 100644 --- a/linux/i810_dma.c +++ b/linux/i810_dma.c @@ -234,11 +234,19 @@ static int i810_dma_get_buffer(drm_device_t *dev, drm_i810_dma_t *d, 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; - 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; drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; diff --git a/linux/i810_drv.h b/linux/i810_drv.h index 27166449..aa82c647 100644 --- a/linux/i810_drv.h +++ b/linux/i810_drv.h @@ -38,8 +38,6 @@ typedef struct drm_i810_buf_priv { int currently_mapped; void *virtual; void *kernel_virtual; - int map_count; - struct vm_area_struct *vma; } drm_i810_buf_priv_t; typedef struct _drm_i810_ring_buffer{ @@ -86,6 +84,7 @@ extern int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int i810_dma_init(struct inode *inode, struct file *filp, 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, unsigned int cmd, unsigned long arg); extern void i810_reclaim_buffers(struct file *filp); diff --git a/linux/i830.h b/linux/i830.h index 432397a8..5775162a 100644 --- a/linux/i830.h +++ b/linux/i830.h @@ -87,7 +87,11 @@ */ #define __HAVE_RELEASE 1 #define DRIVER_RELEASE() do { \ - i830_reclaim_buffers( filp ); \ + i830_reclaim_buffers( filp ); \ +} while (0) + +#define DRIVER_PRETAKEDOWN() do { \ + i830_dma_cleanup( dev ); \ } while (0) /* DMA customization: @@ -107,45 +111,17 @@ * the card, but are subject to subtle interactions between bios, * hardware and the driver. */ +/* XXX: Add vblank support? */ #define USE_IRQS 0 - #if USE_IRQS #define __HAVE_DMA_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 #define __HAVE_DMA_IRQ 0 #endif - /* Buffer customization: */ diff --git a/linux/i830_dma.c b/linux/i830_dma.c index d206d5b5..af9c1cb7 100644 --- a/linux/i830_dma.c +++ b/linux/i830_dma.c @@ -234,16 +234,24 @@ static int i830_dma_get_buffer(drm_device_t *dev, drm_i830_dma_t *d, 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; - 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; drm_i830_private_t *dev_priv = (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, dev_priv->ring.Size); } @@ -255,14 +263,6 @@ static int i830_dma_cleanup(drm_device_t *dev) 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_MEM_DRIVER); dev->dev_private = NULL; diff --git a/linux/i830_drv.h b/linux/i830_drv.h index 6b172ece..b611c133 100644 --- a/linux/i830_drv.h +++ b/linux/i830_drv.h @@ -38,8 +38,6 @@ typedef struct drm_i830_buf_priv { int currently_mapped; void *virtual; void *kernel_virtual; - int map_count; - struct vm_area_struct *vma; } drm_i830_buf_priv_t; typedef struct _drm_i830_ring_buffer{ @@ -99,6 +97,7 @@ extern int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int i830_dma_init(struct inode *inode, struct file *filp, 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, unsigned int cmd, unsigned long arg); extern void i830_reclaim_buffers(struct file *filp); diff --git a/linux/i830_irq.c b/linux/i830_irq.c index cedafc0d..1fcd9f0a 100644 --- a/linux/i830_irq.c +++ b/linux/i830_irq.c @@ -41,12 +41,12 @@ void DRM(dma_service)(int irq, void *device, struct pt_regs *regs) drm_device_t *dev = (drm_device_t *)device; drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private; u16 temp; - + temp = I830_READ16(I830REG_INT_IDENTITY_R); - printk("%s: %x\n", __FUNCTION__, temp); - - if(temp == 0) - return; + DRM_DEBUG("%x\n", temp); + + if (temp == 0) + return; I830_WRITE16(I830REG_INT_IDENTITY_R, temp); @@ -176,3 +176,34 @@ int i830_irq_wait( struct inode *inode, struct file *filp, unsigned int cmd, 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 ); +} + +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 ); + 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_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 ); +} |