From becc53e876ea136d60219f1fbcce56e5c2e82636 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Apr 12 2013 00:18:55 +0000 Subject: fix bug with GPU hotplugging while VT switched --- diff --git a/xorg-x11-server.spec b/xorg-x11-server.spec index 0b2c2ed..0a24628 100644 --- a/xorg-x11-server.spec +++ b/xorg-x11-server.spec @@ -42,7 +42,7 @@ Summary: X.Org X11 X server Name: xorg-x11-server Version: 1.14.0 -Release: 3%{?gitdate:.%{gitdate}}%{dist} +Release: 4%{?gitdate:.%{gitdate}}%{dist} URL: http://www.x.org License: MIT Group: User Interface/X @@ -118,6 +118,9 @@ Patch7070: 0001-randr-report-changes-when-we-disconnect-a-GPU-slave.patch Patch7071: 0001-os-use-libunwind-to-generate-backtraces.patch %endif +# upstream submitted +Patch7072: xserver-1.14.0-fix-gpu-hotplug-vt-switch.patch + %global moduledir %{_libdir}/xorg/modules %global drimoduledir %{_libdir}/dri %global sdkdir %{_includedir}/xorg @@ -590,6 +593,9 @@ rm -rf $RPM_BUILD_ROOT %{xserver_source_dir} %changelog +* Fri Apr 12 2013 Dave Airlie 1.14.0-4 +- fix bug with GPU hotplugging while VT switched + * Fri Mar 22 2013 Dan HorĂ¡k 1.14.0-3 - libunwind exists only on selected arches diff --git a/xserver-1.14.0-fix-gpu-hotplug-vt-switch.patch b/xserver-1.14.0-fix-gpu-hotplug-vt-switch.patch new file mode 100644 index 0000000..c467208 --- /dev/null +++ b/xserver-1.14.0-fix-gpu-hotplug-vt-switch.patch @@ -0,0 +1,293 @@ +From 5e9e979fae229480d1a4af4f247c0251cb2852f9 Mon Sep 17 00:00:00 2001 +From: Fedora X Ninjas +Date: Fri, 12 Apr 2013 10:16:21 +1000 +Subject: [PATCH] fix GPU hotplugging while VT switched. + +Backports 3 patches from upstream into one. +--- + hw/xfree86/common/xf86.h | 1 + + hw/xfree86/common/xf86Events.c | 15 +++++++++- + hw/xfree86/common/xf86Init.c | 2 +- + hw/xfree86/common/xf86Xinput.c | 2 +- + hw/xfree86/common/xf86platformBus.c | 19 +++++++++++++ + hw/xfree86/common/xf86platformBus.h | 4 +++ + hw/xfree86/os-support/linux/lnx_platform.c | 45 ++++++++++++++++++++++++++---- + hw/xfree86/os-support/solaris/sun_init.c | 2 +- + hw/xfree86/os-support/xf86_OSproc.h | 3 ++ + include/hotplug.h | 1 + + 10 files changed, 85 insertions(+), 9 deletions(-) + +diff --git a/hw/xfree86/common/xf86.h b/hw/xfree86/common/xf86.h +index 1514c26..828d958 100644 +--- a/hw/xfree86/common/xf86.h ++++ b/hw/xfree86/common/xf86.h +@@ -243,6 +243,7 @@ extern _X_EXPORT void xf86InterceptSigIll(void (*sigillhandler) (void)); + extern _X_EXPORT Bool xf86EnableVTSwitch(Bool new); + extern _X_EXPORT void xf86ProcessActionEvent(ActionEvent action, void *arg); + extern _X_EXPORT void xf86PrintBacktrace(void); ++extern _X_EXPORT Bool xf86VTOwner(void); + + /* xf86Helper.c */ + +diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c +index d92174e..7a35250 100644 +--- a/hw/xfree86/common/xf86Events.c ++++ b/hw/xfree86/common/xf86Events.c +@@ -84,6 +84,7 @@ + #include "dpmsproc.h" + #endif + ++#include "xf86platformBus.h" + /* + * This is a toggling variable: + * FALSE = No VT switching keys have been pressed last time around +@@ -428,7 +429,7 @@ xf86VTSwitch(void) + * Since all screens are currently all in the same state it is sufficient + * check the first. This might change in future. + */ +- if (xf86Screens[0]->vtSema) { ++ if (xf86VTOwner()) { + + DebugF("xf86VTSwitch: Leaving, xf86Exiting is %s\n", + BOOLTOSTRING((dispatchException & DE_TERMINATE) ? TRUE : FALSE)); +@@ -561,6 +562,9 @@ xf86VTSwitch(void) + for (ih = InputHandlers; ih; ih = ih->next) + xf86EnableInputHandler(ih); + ++ /* check for any new output devices */ ++ xf86platformVTProbe(); ++ + OsReleaseSIGIO(); + } + } +@@ -769,3 +773,12 @@ DDXRingBell(int volume, int pitch, int duration) + { + xf86OSRingBell(volume, pitch, duration); + } ++ ++Bool ++xf86VTOwner(void) ++{ ++ /* at system startup xf86Screens[0] won't be set - but we will own the VT */ ++ if (xf86NumScreens == 0) ++ return TRUE; ++ return xf86Screens[0]->vtSema; ++} +diff --git a/hw/xfree86/common/xf86Init.c b/hw/xfree86/common/xf86Init.c +index a34d7c1..142ce95 100644 +--- a/hw/xfree86/common/xf86Init.c ++++ b/hw/xfree86/common/xf86Init.c +@@ -829,7 +829,7 @@ InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) + if (serverGeneration != 1) { + xf86Resetting = TRUE; + /* All screens are in the same state, so just check the first */ +- if (!xf86Screens[0]->vtSema) { ++ if (!xf86VTOwner()) { + #ifdef HAS_USL_VTS + ioctl(xf86Info.consoleFd, VT_RELDISP, VT_ACKACQ); + #endif +diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c +index bee407b..26c03c6 100644 +--- a/hw/xfree86/common/xf86Xinput.c ++++ b/hw/xfree86/common/xf86Xinput.c +@@ -870,7 +870,7 @@ xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) + } + + /* Enable it if it's properly initialised and we're currently in the VT */ +- if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema) { ++ if (enable && dev->inited && dev->startup && xf86VTOwner()) { + OsBlockSignals(); + EnableDevice(dev, TRUE); + if (!dev->enabled) { +diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c +index 4ccb005..0b0f846 100644 +--- a/hw/xfree86/common/xf86platformBus.c ++++ b/hw/xfree86/common/xf86platformBus.c +@@ -114,6 +114,11 @@ xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_ + return NULL; + } + ++Bool ++xf86_get_platform_device_unowned(int index) ++{ ++ return xf86_platform_devices[index].attribs->unowned; ++} + + /* + * xf86IsPrimaryPlatform() -- return TRUE if primary device +@@ -502,4 +507,18 @@ xf86platformRemoveDevice(int index) + out: + return; + } ++ ++/* called on return from VT switch to find any new devices */ ++void xf86platformVTProbe(void) ++{ ++ int i; ++ ++ for (i = 0; i < xf86_num_platform_devices; i++) { ++ if (xf86_platform_devices[i].attribs->unowned == FALSE) ++ continue; ++ ++ xf86_platform_devices[i].attribs->unowned = FALSE; ++ xf86PlatformReprobeDevice(i, xf86_platform_devices[i].attribs); ++ } ++} + #endif +diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h +index 49afc24..4e17578 100644 +--- a/hw/xfree86/common/xf86platformBus.h ++++ b/hw/xfree86/common/xf86platformBus.h +@@ -46,6 +46,8 @@ extern int + xf86_remove_platform_device(int dev_index); + extern Bool + xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_str); ++extern Bool ++xf86_get_platform_device_unowned(int index); + + extern int + xf86platformAddDevice(int index); +@@ -59,6 +61,8 @@ xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *bu + + extern _X_EXPORT int + xf86PlatformMatchDriver(char *matches[], int nmatches); ++ ++extern void xf86platformVTProbe(void); + #endif + + #endif +diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c +index 76f5583..21768ee 100644 +--- a/hw/xfree86/os-support/linux/lnx_platform.c ++++ b/hw/xfree86/os-support/linux/lnx_platform.c +@@ -18,7 +18,7 @@ + #include "hotplug.h" + + static Bool +-get_drm_info(struct OdevAttributes *attribs, char *path) ++get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index) + { + drmSetVersion sv; + char *buf; +@@ -37,10 +37,14 @@ get_drm_info(struct OdevAttributes *attribs, char *path) + return FALSE; + } + +- xf86_add_platform_device(attribs); ++ /* for a delayed probe we've already added the device */ ++ if (delayed_index == -1) { ++ xf86_add_platform_device(attribs); ++ delayed_index = xf86_num_platform_devices - 1; ++ } + + buf = drmGetBusid(fd); +- xf86_add_platform_device_attrib(xf86_num_platform_devices - 1, ++ xf86_add_platform_device_attrib(delayed_index, + ODEV_ATTRIB_BUSID, buf); + drmFreeBusid(buf); + close(fd); +@@ -89,6 +93,23 @@ xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *bu + } + + void ++xf86PlatformReprobeDevice(int index, struct OdevAttributes *attribs) ++{ ++ Bool ret; ++ char *dpath; ++ dpath = xf86_get_platform_attrib(index, ODEV_ATTRIB_PATH); ++ ++ ret = get_drm_info(attribs, dpath, index); ++ if (ret == FALSE) { ++ xf86_remove_platform_device(index); ++ return; ++ } ++ ret = xf86platformAddDevice(index); ++ if (ret == -1) ++ xf86_remove_platform_device(index); ++} ++ ++void + xf86PlatformDeviceProbe(struct OdevAttributes *attribs) + { + struct OdevAttribute *attrib; +@@ -119,7 +140,15 @@ xf86PlatformDeviceProbe(struct OdevAttributes *attribs) + LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", + path); + +- ret = get_drm_info(attribs, path); ++ if (!xf86VTOwner()) { ++ /* if we don't currently own the VT then don't probe the device, ++ just mark it as unowned for later use */ ++ attribs->unowned = TRUE; ++ xf86_add_platform_device(attribs); ++ return; ++ } ++ ++ ret = get_drm_info(attribs, path, -1); + if (ret == FALSE) + goto out_free; + +@@ -138,6 +167,9 @@ void NewGPUDeviceRequest(struct OdevAttributes *attribs) + if (old_num == xf86_num_platform_devices) + return; + ++ if (xf86_get_platform_device_unowned(xf86_num_platform_devices - 1) == TRUE) ++ return; ++ + ret = xf86platformAddDevice(xf86_num_platform_devices-1); + if (ret == -1) + xf86_remove_platform_device(xf86_num_platform_devices-1); +@@ -171,7 +203,10 @@ void DeleteGPUDeviceRequest(struct OdevAttributes *attribs) + + ErrorF("xf86: remove device %d %s\n", index, syspath); + +- xf86platformRemoveDevice(index); ++ if (xf86_get_platform_device_unowned(index) == TRUE) ++ xf86_remove_platform_device(index); ++ else ++ xf86platformRemoveDevice(index); + out: + config_odev_free_attribute_list(attribs); + } +diff --git a/hw/xfree86/os-support/solaris/sun_init.c b/hw/xfree86/os-support/solaris/sun_init.c +index 4b75a98..68527a5 100644 +--- a/hw/xfree86/os-support/solaris/sun_init.c ++++ b/hw/xfree86/os-support/solaris/sun_init.c +@@ -274,7 +274,7 @@ xf86OpenConsole(void) + * this is to make sure we don't continue until the activate + * signal is received. + */ +- if (!xf86Screens[0]->vtSema) ++ if (!xf86VTOwner()) + sleep(5); + } + #endif /* HAS_USL_VTS */ +diff --git a/hw/xfree86/os-support/xf86_OSproc.h b/hw/xfree86/os-support/xf86_OSproc.h +index ea2b16e..6be5946 100644 +--- a/hw/xfree86/os-support/xf86_OSproc.h ++++ b/hw/xfree86/os-support/xf86_OSproc.h +@@ -223,6 +223,9 @@ extern _X_EXPORT void xf86InitVidMem(void); + #include "hotplug.h" + void + xf86PlatformDeviceProbe(struct OdevAttributes *attribs); ++ ++void ++xf86PlatformReprobeDevice(int index, struct OdevAttributes *attribs); + #endif + + _XFUNCPROTOEND +diff --git a/include/hotplug.h b/include/hotplug.h +index 2a95b45..29a22c4 100644 +--- a/include/hotplug.h ++++ b/include/hotplug.h +@@ -40,6 +40,7 @@ struct OdevAttribute { + + struct OdevAttributes { + struct xorg_list list; ++ Bool unowned; + }; + + struct OdevAttributes * +-- +1.8.2 +