xf86: don't hotplug output devices while VT switched.

We don't want to hotplug output devices while we are VT switched,
as we get races between multiple X servers on the device open, and
drm device master status. This just queues device opens until we return
from VT switch.

Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Dave Airlie 2013-04-10 16:32:15 +10:00
parent 5b359cf613
commit 22cab8a28a
6 changed files with 71 additions and 5 deletions

View File

@ -84,6 +84,7 @@
#include "dpmsproc.h" #include "dpmsproc.h"
#endif #endif
#include "xf86platformBus.h"
/* /*
* This is a toggling variable: * This is a toggling variable:
* FALSE = No VT switching keys have been pressed last time around * FALSE = No VT switching keys have been pressed last time around
@ -560,6 +561,9 @@ xf86VTSwitch(void)
for (ih = InputHandlers; ih; ih = ih->next) for (ih = InputHandlers; ih; ih = ih->next)
xf86EnableInputHandler(ih); xf86EnableInputHandler(ih);
/* check for any new output devices */
xf86platformVTProbe();
OsReleaseSIGIO(); OsReleaseSIGIO();
} }
} }

View File

@ -113,6 +113,11 @@ xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_
return NULL; return NULL;
} }
Bool
xf86_get_platform_device_unowned(int index)
{
return xf86_platform_devices[index].attribs->unowned;
}
/* /*
* xf86IsPrimaryPlatform() -- return TRUE if primary device * xf86IsPrimaryPlatform() -- return TRUE if primary device
@ -498,4 +503,18 @@ xf86platformRemoveDevice(int index)
out: out:
return; 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 #endif

View File

@ -46,6 +46,8 @@ extern int
xf86_remove_platform_device(int dev_index); xf86_remove_platform_device(int dev_index);
extern Bool extern Bool
xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_str); xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_str);
extern Bool
xf86_get_platform_device_unowned(int index);
extern int extern int
xf86platformAddDevice(int index); xf86platformAddDevice(int index);
@ -59,6 +61,8 @@ xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *bu
extern _X_EXPORT int extern _X_EXPORT int
xf86PlatformMatchDriver(char *matches[], int nmatches); xf86PlatformMatchDriver(char *matches[], int nmatches);
extern void xf86platformVTProbe(void);
#endif #endif
#endif #endif

View File

@ -20,7 +20,7 @@
#include "hotplug.h" #include "hotplug.h"
static Bool static Bool
get_drm_info(struct OdevAttributes *attribs, char *path) get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
{ {
drmSetVersion sv; drmSetVersion sv;
char *buf; char *buf;
@ -60,10 +60,14 @@ get_drm_info(struct OdevAttributes *attribs, char *path)
goto out; goto out;
} }
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); buf = drmGetBusid(fd);
xf86_add_platform_device_attrib(xf86_num_platform_devices - 1, xf86_add_platform_device_attrib(delayed_index,
ODEV_ATTRIB_BUSID, buf); ODEV_ATTRIB_BUSID, buf);
drmFreeBusid(buf); drmFreeBusid(buf);
out: out:
@ -112,6 +116,23 @@ xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *bu
return FALSE; return FALSE;
} }
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 void
xf86PlatformDeviceProbe(struct OdevAttributes *attribs) xf86PlatformDeviceProbe(struct OdevAttributes *attribs)
{ {
@ -143,7 +164,15 @@ xf86PlatformDeviceProbe(struct OdevAttributes *attribs)
LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n",
path); 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) if (ret == FALSE)
goto out_free; goto out_free;
@ -162,6 +191,9 @@ void NewGPUDeviceRequest(struct OdevAttributes *attribs)
if (old_num == xf86_num_platform_devices) if (old_num == xf86_num_platform_devices)
return; return;
if (xf86_get_platform_device_unowned(xf86_num_platform_devices - 1) == TRUE)
return;
ret = xf86platformAddDevice(xf86_num_platform_devices-1); ret = xf86platformAddDevice(xf86_num_platform_devices-1);
if (ret == -1) if (ret == -1)
xf86_remove_platform_device(xf86_num_platform_devices-1); xf86_remove_platform_device(xf86_num_platform_devices-1);
@ -195,7 +227,10 @@ void DeleteGPUDeviceRequest(struct OdevAttributes *attribs)
ErrorF("xf86: remove device %d %s\n", index, syspath); 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: out:
config_odev_free_attribute_list(attribs); config_odev_free_attribute_list(attribs);
} }

View File

@ -223,6 +223,9 @@ extern _X_EXPORT void xf86InitVidMem(void);
#include "hotplug.h" #include "hotplug.h"
void void
xf86PlatformDeviceProbe(struct OdevAttributes *attribs); xf86PlatformDeviceProbe(struct OdevAttributes *attribs);
void
xf86PlatformReprobeDevice(int index, struct OdevAttributes *attribs);
#endif #endif
_XFUNCPROTOEND _XFUNCPROTOEND

View File

@ -40,6 +40,7 @@ struct OdevAttribute {
struct OdevAttributes { struct OdevAttributes {
struct xorg_list list; struct xorg_list list;
Bool unowned;
}; };
struct OdevAttributes * struct OdevAttributes *