diff options
author | Thomas Hellström <thomas@shipmail.org> | 2008-10-29 10:57:03 +0000 |
---|---|---|
committer | Thomas Hellström <thomas@shipmail.org> | 2008-10-29 10:57:03 +0000 |
commit | e8349f9a6d820b31f13f4bff9517526dd8948ce4 (patch) | |
tree | a93a466b216d115eca844ff5d4073134751dd8d7 | |
parent | 6c8df98ccf9eb73a03893e86dfc03f413aa1bc70 (diff) |
Make screen setup and takedown reasonably error safe
-rw-r--r-- | src/via_accel.c | 2 | ||||
-rw-r--r-- | src/via_driver.c | 181 | ||||
-rw-r--r-- | src/via_driver.h | 1 |
3 files changed, 142 insertions, 42 deletions
diff --git a/src/via_accel.c b/src/via_accel.c index b6a5433..63a8399 100644 --- a/src/via_accel.c +++ b/src/via_accel.c @@ -1500,7 +1500,6 @@ viaInitAccel(ScreenPtr pScreen) * VIAInitLinear. */ - pVia->NoAccel = TRUE; goto out_err0; } @@ -1510,6 +1509,7 @@ viaInitAccel(ScreenPtr pScreen) return TRUE; out_err0: + pVia->NoAccel = TRUE; driDeleteBuffers(1, &pVia->exaMem.buf); return FALSE; diff --git a/src/via_driver.c b/src/via_driver.c index 53e4940..2e97444 100644 --- a/src/via_driver.c +++ b/src/via_driver.c @@ -29,6 +29,8 @@ #include "config.h" #endif +#include <signal.h> + #include "xf86RAC.h" #include "shadowfb.h" @@ -1878,9 +1880,18 @@ VIALeaveVT(int scrnIndex, int flags) VIAPtr pVia = VIAPTR(pScrn); DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "VIALeaveVT\n")); + ErrorF("Leavevt\n"); vgaHWBlankScreen(pScrn, FALSE); + /* + * A segfault happened during the screen setup process. + * Just restore the console screen. + */ + + if (!pVia->haveScreen) + goto out_restore; + #ifdef XF86DRI if (pVia->directRenderingEnabled) { volatile struct drm_via_sarea *saPriv = (struct drm_via_sarea *) @@ -1942,6 +1953,8 @@ VIALeaveVT(int scrnIndex, int flags) * 3D engine. */ + out_restore: + if (pVia->Chipset != VIA_K8M890 && pVia->Chipset != VIA_P4M900) hwp->writeSeq(hwp, 0x1A, pVia->SavedReg.SR1A | 0x40); @@ -2430,7 +2443,19 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) int ret; unsigned int displaySize; + pVia->haveScreen = FALSE; + + + /* + * FIXME: pScrn->pScreen should really be NULL during the screen setup + * process. It's set to pScreen by the server code after ScreenInit. + * Should remove all references to pScrn->pScreen from driver screen setup + * functions. + */ + pScrn->pScreen = pScreen; + + DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VIAScreenInit\n")); pScrn->memPhysBase = 0; @@ -2451,13 +2476,13 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) vgaHWBlankScreen(pScrn, FALSE); if (!ViaVbeSetMode(pScrn, pScrn->currentMode)) { vgaHWBlankScreen(pScrn, TRUE); - return FALSE; + goto out_err0; } } else { vgaHWBlankScreen(pScrn, FALSE); if (!VIAWriteMode(pScrn, pScrn->currentMode)) { vgaHWBlankScreen(pScrn, TRUE); - return FALSE; + goto out_err0; } } pVia->FirstInit = FALSE; @@ -2493,7 +2518,7 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (pVia->mainPool == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "This driver currently requires DRM to operate.\n"); - return FALSE; + goto out_err1; } ret = driGenBuffers(pVia->mainPool, "Scanouts", VIA_SCANOUT_NUM, pVia->scanout.bufs, 0, @@ -2504,7 +2529,7 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (ret) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed allocating scanout buffers.\n"); - return FALSE; + goto out_err2; } if (pVia->IsSecondary) { @@ -2531,7 +2556,7 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed allocating display video RAM: \"%s\".\n", strerror(-ret)); - return FALSE; + goto out_err3; } pVia->front.buf = driBOReference(pVia->scanout.bufs[VIA_SCANOUT_DISPLAY]); @@ -2542,7 +2567,7 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed mapping display video RAM: \"%s\".\n", strerror(-ret)); - return FALSE; + goto out_err3; } driBOUnmap(pVia->scanout.bufs[VIA_SCANOUT_DISPLAY]); @@ -2560,22 +2585,23 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (pScrn->bitsPerPixel > 8 && !pVia->IsSecondary) { if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits, pScrn->defaultVisual)) - return FALSE; + goto out_err3; if (!miSetPixmapDepths()) - return FALSE; + goto out_err3; } else { if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), pScrn->rgbBits, pScrn->defaultVisual)) - return FALSE; + goto out_err3; if (!miSetPixmapDepths()) - return FALSE; + goto out_err3; } DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Visuals set up\n")); if (!VIAInternalScreenInit(scrnIndex, pScreen)) - return FALSE; + goto out_err4; + xf86SetBlackWhitePixels(pScreen); DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- B & W\n")); @@ -2601,7 +2627,7 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #endif if (!pVia->NoAccel) { - viaInitAccel(pScreen); + viaInitAccel(pScreen); } miInitializeBackingStore(pScreen); @@ -2628,13 +2654,13 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) ViaShadowFBInit(pScrn, pScreen); if (!miCreateDefColormap(pScreen)) - return FALSE; + goto out_err5; DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Def Color map set up\n")); if (!xf86HandleColormaps(pScreen, 256, 8, VIALoadPalette, NULL, CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR)) - return FALSE; + goto out_err5; DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Palette loaded\n")); @@ -2698,9 +2724,70 @@ VIAScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } #endif - DEBUG(xf86DrvMsg(pScrn->scrnIndex, X_INFO, "- Done\n")); + + pVia->haveScreen = TRUE; + return TRUE; + out_err5: + if (pVia->DGAModes) + xfree(pVia->DGAModes); + pVia->DGAModes = NULL; + if (!pVia->NoAccel) + viaExitAccel(pScreen); + out_err4: + if (pVia->ShadowPtr) + xfree(pVia->ShadowPtr); + pVia->ShadowPtr = NULL; + out_err3: + driBOUnReference(pVia->front.buf); + pVia->front.buf = NULL; + driDeleteBuffers(VIA_SCANOUT_NUM, pVia->scanout.bufs); + out_err2: + if (!pVia->IsSecondary) { + pVia->mainPool->takeDown(pVia->mainPool); + pVia->mainPool = NULL; + } + out_err1: +#ifdef XF86DRI + if (pVia->directRenderingEnabled) { + if (pScrn->vtSema) { + struct drm_via_vt vt; + + vt.enter = 0; + + if (drmCommandWrite(pVia->drmFD, DRM_VIA_VT, + &vt, sizeof(vt)) < 0) + ErrorF("Failed DRM VT leave.\n"); + else + pVia->vtNotified = FALSE; + } + VIADRICloseScreen(pScreen); + } + pVia->directRenderingEnabled = FALSE; +#endif + out_err0: + + if (pScrn->vtSema) { + if (pVia->Chipset != VIA_K8M890 && pVia->Chipset != VIA_P4M900) + hwp->writeSeq(hwp, 0x1A, pVia->SavedReg.SR1A | 0x40); + + VIASETREG(VIA_REG_TRANSET, 0x00000000); + VIASETREG(VIA_REG_TRANSPACE, 0xCCCCCCCC); + (void )VIAGETREG(VIA_REG_TRANSET); + + if (pVia->pVbe && pVia->vbeSR) + ViaVbeSaveRestore(pScrn, MODE_RESTORE); + else + VIARestore(pScrn); + } + + pScrn->vtSema = FALSE; + pVia->haveScreen = FALSE; + vgaHWLock(hwp); + VIAUnmapMem(pScrn); + + return FALSE; } @@ -2727,6 +2814,8 @@ VIAInternalScreenInit(int scrnIndex, ScreenPtr pScreen) if (pVia->shadowFB) { pVia->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); pVia->ShadowPtr = xalloc(pVia->ShadowPitch * height); + if (!pVia->ShadowPtr) + return FALSE; displayWidth = pVia->ShadowPitch / (pScrn->bitsPerPixel >> 3); FBStart = pVia->ShadowPtr; } else { @@ -2766,8 +2855,6 @@ VIAWriteMode(ScrnInfoPtr pScrn, DisplayModePtr mode) pVia->OverlaySupported = FALSE; - pScrn->vtSema = TRUE; - if (!pVia->pVbe) { if (!vgaHWInit(pScrn, mode)) @@ -2778,10 +2865,14 @@ VIAWriteMode(ScrnInfoPtr pScrn, DisplayModePtr mode) else ViaModeSecondary(pScrn, mode); + pScrn->vtSema = TRUE; + } else { - if (!ViaVbeSetMode(pScrn, mode)) + if (!ViaVbeSetMode(pScrn, mode)) return FALSE; + + pScrn->vtSema = TRUE; /* * FIXME: pVia->IsSecondary is not working here. We should be able @@ -2820,6 +2911,11 @@ VIACloseScreen(int scrnIndex, ScreenPtr pScreen) DEBUG(xf86DrvMsg(scrnIndex, X_INFO, "VIACloseScreen\n")); + /* + * Always make sure this function mimics the + * error takedown in viaScreenInit. + */ + /* Is the display currently visible? */ if (pScrn->vtSema) { vgaHWBlankScreen(pScrn, FALSE); @@ -2828,27 +2924,41 @@ VIACloseScreen(int scrnIndex, ScreenPtr pScreen) if (pVia->directRenderingEnabled) DRILock(screenInfo.screens[scrnIndex], 0); #endif - /* Wait for hardware engine to idle before exiting graphical mode. */ - viaAccelSync(pScrn); + } + + if (!pVia->IsSecondary) { + /* Turn off all video activities. */ + viaExitVideo(pScrn); + VIAHideCursor(pScrn); + } - if (!pVia->IsSecondary) { - /* Turn off all video activities. */ - viaExitVideo(pScrn); + if (pVia->DGAModes) + xfree(pVia->DGAModes); + pVia->DGAModes = NULL; - VIAHideCursor(pScrn); - } + if (!pVia->NoAccel) { + viaAccelSync(pScrn); + viaExitAccel(pScreen); + } + if (pVia->CursorInfoRec) { + xf86DestroyCursorInfoRec(pVia->CursorInfoRec); + pVia->CursorInfoRec = NULL; } + if (pVia->ShadowPtr) + xfree(pVia->ShadowPtr); + pVia->ShadowPtr = NULL; + driBOUnReference(pVia->front.buf); - viaExitAccel(pScreen); + pVia->front.buf = NULL; driDeleteBuffers(VIA_SCANOUT_NUM, pVia->scanout.bufs); + if (pVia->mainPool && !pVia->IsSecondary) { pVia->mainPool->takeDown(pVia->mainPool); pVia->mainPool = NULL; } - - + #ifdef XF86DRI if (pVia->directRenderingEnabled) { if (pScrn->vtSema) { @@ -2863,22 +2973,10 @@ VIACloseScreen(int scrnIndex, ScreenPtr pScreen) pVia->vtNotified = FALSE; } VIADRICloseScreen(pScreen); + pVia->directRenderingEnabled = FALSE; } #endif - if (pVia->CursorInfoRec) { - xf86DestroyCursorInfoRec(pVia->CursorInfoRec); - pVia->CursorInfoRec = NULL; - } - if (pVia->ShadowPtr) { - xfree(pVia->ShadowPtr); - pVia->ShadowPtr = NULL; - } - if (pVia->DGAModes) { - xfree(pVia->DGAModes); - pVia->DGAModes = NULL; - } - if (pScrn->vtSema) { /* A soft reset avoids a 3D hang after X restart. */ @@ -2898,6 +2996,7 @@ VIACloseScreen(int scrnIndex, ScreenPtr pScreen) VIAUnmapMem(pScrn); } pScrn->vtSema = FALSE; + pVia->haveScreen = FALSE; pScreen->CloseScreen = pVia->CloseScreen; return (*pScreen->CloseScreen) (scrnIndex, pScreen); diff --git a/src/via_driver.h b/src/via_driver.h index 957049a..43e6d5d 100644 --- a/src/via_driver.h +++ b/src/via_driver.h @@ -244,6 +244,7 @@ typedef struct _VIA { xf86CursorInfoPtr CursorInfoRec; int Bpp, Bpl; + Bool haveScreen; Bool FirstInit; unsigned long videoRambytes; int videoRamKbytes; |