From c0416148852843e0dfa14c9219541543cbd6a41d Mon Sep 17 00:00:00 2001 From: Christopher James Halse Rogers Date: Wed, 24 Mar 2010 19:11:29 +1100 Subject: [PATCH] Refuse to bind to a device which has kernel modesetting active. Trying to program a VESA mode while kernel modesetting is active can result in an improperly driven screen. Fixes http://bugs.freedesktop.org/show_bug.cgi?id=26878 Signed-off-by: Christopher James Halse Rogers --- configure.ac | 7 +++++++ src/Makefile.am | 2 +- src/vesa.c | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletions(-) diff --git a/configure.ac b/configure.ac index 51d9d33..b5227c2 100644 --- a/configure.ac +++ b/configure.ac @@ -98,6 +98,13 @@ AM_CONDITIONAL(XSERVER_LIBPCIACCESS, test "x$XSERVER_LIBPCIACCESS" = xyes) # Checks for header files. AC_HEADER_STDC +if test "x$XSERVER_LIBPCIACCESS" = xyes; then + PKG_CHECK_MODULES(LIBDRM, [libdrm > 2.4.3 xf86driproto], HAVE_KMS="yes", HAVE_KMS="no") + if test "x$HAVE_KMS" = xyes; then + AC_DEFINE(HAVE_KMS, 1, [Have kernel modesetting]) + fi +fi + DRIVER_NAME=vesa AC_SUBST([DRIVER_NAME]) diff --git a/src/Makefile.am b/src/Makefile.am index dc702f0..aae7e4c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,7 +25,7 @@ # _ladir passes a dummy rpath to libtool so the thing will actually link # TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc. -AM_CFLAGS = $(XORG_CFLAGS) $(PCIACCESS_CFLAGS) +AM_CFLAGS = $(XORG_CFLAGS) $(PCIACCESS_CFLAGS) $(LIBDRM_CFLAGS) vesa_drv_la_LTLIBRARIES = vesa_drv.la vesa_drv_la_LDFLAGS = -module -avoid-version diff --git a/src/vesa.c b/src/vesa.c index 034a019..8c46f7b 100644 --- a/src/vesa.c +++ b/src/vesa.c @@ -65,6 +65,10 @@ #include #endif +#ifdef HAVE_KMS +#include +#include +#endif /* Mandatory functions */ static const OptionInfoRec * VESAAvailableOptions(int chipid, int busid); @@ -106,6 +110,9 @@ static void SaveFonts(ScrnInfoPtr pScrn); static void RestoreFonts(ScrnInfoPtr pScrn); static Bool VESASaveRestore(ScrnInfoPtr pScrn, vbeSaveRestoreFunction function); +#ifdef HAVE_KMS +static Bool VESAKernelModesettingEnabled (struct pci_device *device); +#endif static void * VESAWindowLinear(ScreenPtr pScreen, CARD32 row, CARD32 offset, int mode, @@ -317,6 +324,24 @@ VESASetModeParameters(vbeInfoPtr pVbe, DisplayModePtr vbemode, (double)(ddcmode->HTotal * ddcmode->VTotal)); } +#ifdef HAVE_KMS +static Bool VESAKernelModesettingEnabled (struct pci_device *device) +{ + char *busIdString; + int ret; + + if (!xf86LoaderCheckSymbol("DRICreatePCIBusID")) + return FALSE; + + busIdString = DRICreatePCIBusID(device); + + ret = drmCheckModesettingSupported(busIdString); + xfree(busIdString); + + return (ret == 0); +} +#endif //HAVE_KMS + static ModeStatus VESAValidMode(int scrn, DisplayModePtr p, Bool flag, int pass) { @@ -428,6 +453,16 @@ VESAPciProbe(DriverPtr drv, int entity_num, struct pci_device *dev, { ScrnInfoPtr pScrn; +#ifdef HAVE_KMS + /* Trying to bring up a VESA mode while kernel modesetting is enabled + results in badness */ + if (VESAKernelModesettingEnabled (dev)) { + xf86Msg (X_ERROR, + "VESA: Kernel modesetting driver in use, refusing to load\n"); + return FALSE; + } +#endif + pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, NULL, NULL, NULL, NULL, NULL, NULL); if (pScrn != NULL) { -- 1.7.0