mirror of
https://gitlab.freedesktop.org/mesa/drm.git
synced 2025-12-28 21:30:16 +01:00
Completely re-initialize DMA settings
There were two problems. First, the 'warp' and 'primary' pointers weren't
cleared, so mga_do_cleanup_dma, which gets called multiple times, would
try to ioremapfree them multiple times. This resulted in the new error
messages to syslog. The second problem was the, since the dev_private
structure isn't reallocated and cleaned out in mga_do_init_dma, when
the server is reloaded idle-waits would wait for impossible values.
I have given this patch some more riggorous testing. This includes:
- Load module, start server, run GL app, stop server, unload module.
- Load module, start server, run GL app, stop server, unload module, reload
module, restart server, run GL app.
- Load module, start server, run GL app, stop server, restart server, run
GL app, stop server, unload module.
In all three cases, everything worked as expected. Please let me know if
there are any further regressions with this patch.
Xorg bug: 3408 Reported by: Chris Rankin
This commit is contained in:
parent
1252890ff1
commit
dfc650bd80
5 changed files with 40 additions and 27 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue