summaryrefslogtreecommitdiff
path: root/linux-core
diff options
context:
space:
mode:
authorLeif Delgass <ldelgass@users.sourceforge.net>2003-04-26 22:28:56 +0000
committerLeif Delgass <ldelgass@users.sourceforge.net>2003-04-26 22:28:56 +0000
commitf2a0c5438dc83171de1007a68e4f98e35b5a8fbe (patch)
treef886e31d758dda4c3460465d0f6be13921efbe58 /linux-core
parenta79adaab72bde726ce4c08184997f34b31014d9e (diff)
Ensure driver has been initialized (dev_private != NULL) before installing
irq handler in DRM(irq_install). Modify all drivers to ensure irq handler is removed before cleanup and cleanup is called at takedown. Remove unused buffer private struct fields in i810, i830. Check for lock on init/cleanup in all drivers except i810/i830. The current DDX for i810 and i830 doesn't hold the lock on kernel init (FIXME?).
Diffstat (limited to 'linux-core')
-rw-r--r--linux-core/drm_dma.c7
-rw-r--r--linux-core/i810_dma.c12
-rw-r--r--linux-core/i810_drv.h3
-rw-r--r--linux-core/i830_dma.c22
-rw-r--r--linux-core/i830_drv.h3
-rw-r--r--linux-core/i830_irq.c41
6 files changed, 66 insertions, 22 deletions
diff --git a/linux-core/drm_dma.c b/linux-core/drm_dma.c
index 7c1785b4..34ab5322 100644
--- a/linux-core/drm_dma.c
+++ b/linux-core/drm_dma.c
@@ -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-core/i810_dma.c b/linux-core/i810_dma.c
index 30b7dfcf..8e0e8f45 100644
--- a/linux-core/i810_dma.c
+++ b/linux-core/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-core/i810_drv.h b/linux-core/i810_drv.h
index 27166449..aa82c647 100644
--- a/linux-core/i810_drv.h
+++ b/linux-core/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-core/i830_dma.c b/linux-core/i830_dma.c
index d206d5b5..af9c1cb7 100644
--- a/linux-core/i830_dma.c
+++ b/linux-core/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-core/i830_drv.h b/linux-core/i830_drv.h
index 6b172ece..b611c133 100644
--- a/linux-core/i830_drv.h
+++ b/linux-core/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-core/i830_irq.c b/linux-core/i830_irq.c
index cedafc0d..1fcd9f0a 100644
--- a/linux-core/i830_irq.c
+++ b/linux-core/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 );
+}