summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bsd-core/mga_drv.c1
-rw-r--r--linux-core/mga_drv.c1
-rw-r--r--shared-core/mga_dma.c57
-rw-r--r--shared-core/mga_drv.h6
-rw-r--r--shared-core/mga_irq.c2
5 files changed, 40 insertions, 27 deletions
diff --git a/bsd-core/mga_drv.c b/bsd-core/mga_drv.c
index 6034212c..efb7cc99 100644
--- a/bsd-core/mga_drv.c
+++ b/bsd-core/mga_drv.c
@@ -60,6 +60,7 @@ static void mga_configure(drm_device_t *dev)
dev->irq_uninstall = mga_driver_irq_uninstall;
dev->irq_handler = mga_driver_irq_handler;
dev->dma_ioctl = mga_dma_buffers;
+ dev->pretakedown = mga_driver_pretakedown;
dev->dma_quiescent = mga_driver_dma_quiescent;
dev->device_is_agp = mga_driver_device_is_agp;
diff --git a/linux-core/mga_drv.c b/linux-core/mga_drv.c
index c8bb042d..43877597 100644
--- a/linux-core/mga_drv.c
+++ b/linux-core/mga_drv.c
@@ -83,6 +83,7 @@ static struct drm_driver driver = {
DRIVER_IRQ_VBL,
.preinit = mga_driver_preinit,
.postcleanup = mga_driver_postcleanup,
+ .pretakedown = mga_driver_pretakedown,
.dma_quiescent = mga_driver_dma_quiescent,
.device_is_agp = mga_driver_device_is_agp,
.vblank_wait = mga_driver_vblank_wait,
diff --git a/shared-core/mga_dma.c b/shared-core/mga_dma.c
index 367c670e..4c0be4cc 100644
--- a/shared-core/mga_dma.c
+++ b/shared-core/mga_dma.c
@@ -440,38 +440,32 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
if (!dev_priv->sarea) {
DRM_ERROR("failed to find sarea!\n");
- mga_do_cleanup_dma(dev);
return DRM_ERR(EINVAL);
}
dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
if (!dev_priv->mmio) {
DRM_ERROR("failed to find mmio region!\n");
- mga_do_cleanup_dma(dev);
return DRM_ERR(EINVAL);
}
dev_priv->status = drm_core_findmap(dev, init->status_offset);
if (!dev_priv->status) {
DRM_ERROR("failed to find status page!\n");
- mga_do_cleanup_dma(dev);
return DRM_ERR(EINVAL);
}
dev_priv->warp = drm_core_findmap(dev, init->warp_offset);
if (!dev_priv->warp) {
DRM_ERROR("failed to find warp microcode region!\n");
- mga_do_cleanup_dma(dev);
return DRM_ERR(EINVAL);
}
dev_priv->primary = drm_core_findmap(dev, init->primary_offset);
if (!dev_priv->primary) {
DRM_ERROR("failed to find primary dma region!\n");
- mga_do_cleanup_dma(dev);
return DRM_ERR(EINVAL);
}
dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
if (!dev->agp_buffer_map) {
DRM_ERROR("failed to find dma buffer region!\n");
- mga_do_cleanup_dma(dev);
return DRM_ERR(EINVAL);
}
@@ -486,21 +480,18 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
if (!dev_priv->warp->handle ||
!dev_priv->primary->handle || !dev->agp_buffer_map->handle) {
DRM_ERROR("failed to ioremap agp regions!\n");
- mga_do_cleanup_dma(dev);
return DRM_ERR(ENOMEM);
}
ret = mga_warp_install_microcode(dev_priv);
if (ret < 0) {
DRM_ERROR("failed to install WARP ucode!\n");
- mga_do_cleanup_dma(dev);
return ret;
}
ret = mga_warp_init(dev_priv);
if (ret < 0) {
DRM_ERROR("failed to init WARP engine!\n");
- mga_do_cleanup_dma(dev);
return ret;
}
@@ -539,7 +530,6 @@ static int mga_do_init_dma(drm_device_t * dev, drm_mga_init_t * init)
if (mga_freelist_init(dev, dev_priv) < 0) {
DRM_ERROR("could not initialize freelist\n");
- mga_do_cleanup_dma(dev);
return DRM_ERR(ENOMEM);
}
@@ -564,10 +554,20 @@ static int mga_do_cleanup_dma(drm_device_t * dev)
drm_core_ioremapfree(dev_priv->warp, dev);
if (dev_priv->primary != NULL)
drm_core_ioremapfree(dev_priv->primary, dev);
- if (dev->agp_buffer_map != NULL) {
+ if (dev->agp_buffer_map != NULL)
drm_core_ioremapfree(dev->agp_buffer_map, dev);
- dev->agp_buffer_map = NULL;
- }
+
+ dev_priv->warp = NULL;
+ dev_priv->primary = NULL;
+ dev_priv->mmio = NULL;
+ dev_priv->status = NULL;
+ dev_priv->sarea = NULL;
+ dev_priv->sarea_priv = NULL;
+ dev->agp_buffer_map = NULL;
+
+ memset(&dev_priv->prim, 0, sizeof(dev_priv->prim));
+ dev_priv->warp_pipe = 0;
+ memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
if (dev_priv->head != NULL) {
mga_freelist_cleanup(dev);
@@ -581,6 +581,7 @@ int mga_dma_init(DRM_IOCTL_ARGS)
{
DRM_DEVICE;
drm_mga_init_t init;
+ int err;
LOCK_TEST_WITH_RETURN(dev, filp);
@@ -589,7 +590,11 @@ int mga_dma_init(DRM_IOCTL_ARGS)
switch (init.func) {
case MGA_INIT_DMA:
- return mga_do_init_dma(dev, &init);
+ err = mga_do_init_dma(dev, &init);
+ if (err) {
+ (void) mga_do_cleanup_dma(dev);
+ }
+ return err;
case MGA_CLEANUP_DMA:
return mga_do_cleanup_dma(dev);
}
@@ -717,19 +722,23 @@ int mga_dma_buffers(DRM_IOCTL_ARGS)
return ret;
}
+/**
+ * Called just before the module is unloaded.
+ */
int mga_driver_postcleanup(drm_device_t * dev)
{
- int err;
-
-
- err = mga_do_cleanup_dma(dev);
- if (!err) {
- drm_free(dev->dev_private, sizeof(drm_mga_private_t),
- DRM_MEM_DRIVER);
- dev->dev_private = NULL;
- }
+ drm_free(dev->dev_private, sizeof(drm_mga_private_t), DRM_MEM_DRIVER);
+ dev->dev_private = NULL;
+
+ return 0;
+}
- return err;
+/**
+ * Called when the last opener of the device is closed.
+ */
+void mga_driver_pretakedown(drm_device_t * dev)
+{
+ mga_do_cleanup_dma(dev);
}
int mga_driver_dma_quiescent(drm_device_t * dev)
diff --git a/shared-core/mga_drv.h b/shared-core/mga_drv.h
index e12dbd42..180c1235 100644
--- a/shared-core/mga_drv.h
+++ b/shared-core/mga_drv.h
@@ -38,11 +38,11 @@
#define DRIVER_NAME "mga"
#define DRIVER_DESC "Matrox G200/G400"
-#define DRIVER_DATE "20050520"
+#define DRIVER_DATE "20050606"
#define DRIVER_MAJOR 3
#define DRIVER_MINOR 1
-#define DRIVER_PATCHLEVEL 2
+#define DRIVER_PATCHLEVEL 3
typedef struct drm_mga_primary_buffer {
u8 *start;
@@ -108,7 +108,6 @@ typedef struct drm_mga_private {
drm_local_map_t *status;
drm_local_map_t *warp;
drm_local_map_t *primary;
- drm_local_map_t *buffers;
drm_local_map_t *agp_textures;
} drm_mga_private_t;
@@ -119,6 +118,7 @@ extern int mga_dma_flush(DRM_IOCTL_ARGS);
extern int mga_dma_reset(DRM_IOCTL_ARGS);
extern int mga_dma_buffers(DRM_IOCTL_ARGS);
extern int mga_driver_postcleanup(drm_device_t * dev);
+extern void mga_driver_pretakedown(drm_device_t * dev);
extern int mga_driver_dma_quiescent(drm_device_t * dev);
extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
diff --git a/shared-core/mga_irq.c b/shared-core/mga_irq.c
index 704652d3..99a23fe1 100644
--- a/shared-core/mga_irq.c
+++ b/shared-core/mga_irq.c
@@ -98,4 +98,6 @@ void mga_driver_irq_uninstall(drm_device_t * dev)
/* Disable *all* interrupts */
MGA_WRITE(MGA_IEN, 0);
+
+ dev->irq_enabled = 0;
}