From: Dave Airlie <airl...@redhat.com> This provides add/remove support for platform devices at xfree86 ddx level.
v2: cleanup properly if no driver found. Signed-off-by: Dave Airlie <airl...@redhat.com> --- hw/xfree86/common/xf86platformBus.c | 99 ++++++++++++++++++++++++++++ hw/xfree86/common/xf86platformBus.h | 5 ++ hw/xfree86/os-support/linux/lnx_platform.c | 49 ++++++++++++++ 3 files changed, 153 insertions(+) diff --git a/hw/xfree86/common/xf86platformBus.c b/hw/xfree86/common/xf86platformBus.c index 9fd755a..a3380d2 100644 --- a/hw/xfree86/common/xf86platformBus.c +++ b/hw/xfree86/common/xf86platformBus.c @@ -376,4 +376,103 @@ xf86platformProbeDev(DriverPtr drvp) return foundScreen; } +int +xf86platformAddDevice(int index) +{ + int i, old_screens, scr_index; + DriverPtr drvp = NULL; + int entity; + screenLayoutPtr layout; + + for (i = 0; i < xf86NumDrivers; i++) { + if (!xf86DriverList[i]) + continue; + + if (!strcmp(xf86DriverList[i]->driverName, "modesetting")) { + drvp = xf86DriverList[i]; + break; + } + } + if (i == xf86NumDrivers) + return -1; + + old_screens = xf86NumGPUScreens; + entity = xf86ClaimPlatformSlot(&xf86_platform_devices[index], + drvp, 0, 0, 0); + if (!drvp->platformProbe(drvp, entity, PLATFORM_PROBE_GPU_SCREEN, &xf86_platform_devices[index], 0)) { + xf86UnclaimPlatformSlot(&xf86_platform_devices[index], NULL); + } + if (old_screens == xf86NumGPUScreens) + return -1; + i = old_screens; + + for (layout = xf86ConfigLayout.screens; layout->screen != NULL; + layout++) { + xf86GPUScreens[i]->confScreen = layout->screen; + break; + } + + if (xf86GPUScreens[i]->PreInit && + xf86GPUScreens[i]->PreInit(xf86GPUScreens[i], 0)) + xf86GPUScreens[i]->configured = TRUE; + + if (!xf86GPUScreens[i]->configured) { + ErrorF("hotplugged device %d didn't configure\n", i); + xf86DeleteScreen(xf86GPUScreens[i]); + return -1; + } + + scr_index = AddGPUScreen(xf86GPUScreens[i]->ScreenInit, 0, NULL); + + dixSetPrivate(&xf86GPUScreens[i]->pScreen->devPrivates, + xf86ScreenKey, xf86GPUScreens[i]); + + CreateScratchPixmapsForScreen(xf86GPUScreens[i]->pScreen); + + return 0; +} + +void +xf86platformRemoveDevice(int index) +{ + EntityPtr entity; + int ent_num, i, j; + Bool found; + + for (ent_num = 0; ent_num < xf86NumEntities; ent_num++) { + entity = xf86Entities[ent_num]; + if (entity->bus.type == BUS_PLATFORM && + entity->bus.id.plat == &xf86_platform_devices[index]) + break; + } + if (ent_num == xf86NumEntities) + goto out; + + found = FALSE; + for (i = 0; i < xf86NumGPUScreens; i++) { + for (j = 0; j < xf86GPUScreens[i]->numEntities; j++) + if (xf86GPUScreens[i]->entityList[j] == ent_num) { + found = TRUE; + break; + } + if (found) + break; + } + if (!found) { + ErrorF("failed to find screen to remove\n"); + goto out; + } + + xf86GPUScreens[i]->pScreen->CloseScreen(xf86GPUScreens[i]->pScreen); + + RemoveGPUScreen(xf86GPUScreens[i]->pScreen); + xf86DeleteScreen(xf86GPUScreens[i]); + + xf86UnclaimPlatformSlot(&xf86_platform_devices[index], NULL); + + xf86_remove_platform_device(index); + + out: + return; +} #endif diff --git a/hw/xfree86/common/xf86platformBus.h b/hw/xfree86/common/xf86platformBus.h index 15a3022..49afc24 100644 --- a/hw/xfree86/common/xf86platformBus.h +++ b/hw/xfree86/common/xf86platformBus.h @@ -47,6 +47,11 @@ xf86_remove_platform_device(int dev_index); extern Bool xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_str); +extern int +xf86platformAddDevice(int index); +extern void +xf86platformRemoveDevice(int index); + extern _X_EXPORT char * xf86_get_platform_device_attrib(struct xf86_platform_device *device, int attrib_id); extern _X_EXPORT Bool diff --git a/hw/xfree86/os-support/linux/lnx_platform.c b/hw/xfree86/os-support/linux/lnx_platform.c index 9c63ee5..76f5583 100644 --- a/hw/xfree86/os-support/linux/lnx_platform.c +++ b/hw/xfree86/os-support/linux/lnx_platform.c @@ -15,6 +15,8 @@ #include "xf86platformBus.h" #include "xf86Bus.h" +#include "hotplug.h" + static Bool get_drm_info(struct OdevAttributes *attribs, char *path) { @@ -127,4 +129,51 @@ out_free: config_odev_free_attribute_list(attribs); } +void NewGPUDeviceRequest(struct OdevAttributes *attribs) +{ + int old_num = xf86_num_platform_devices; + int ret; + xf86PlatformDeviceProbe(attribs); + + if (old_num == xf86_num_platform_devices) + return; + + ret = xf86platformAddDevice(xf86_num_platform_devices-1); + if (ret == -1) + xf86_remove_platform_device(xf86_num_platform_devices-1); + + ErrorF("xf86: found device %d\n", xf86_num_platform_devices); + return; +} + +void DeleteGPUDeviceRequest(struct OdevAttributes *attribs) +{ + struct OdevAttribute *attrib; + int index; + char *syspath = NULL; + + xorg_list_for_each_entry(attrib, &attribs->list, member) { + if (attrib->attrib_id == ODEV_ATTRIB_SYSPATH) { + syspath = attrib->attrib_name; + break; + } + } + + for (index = 0; index < xf86_num_platform_devices; index++) { + char *dspath; + dspath = xf86_get_platform_attrib(index, ODEV_ATTRIB_SYSPATH); + if (!strcmp(syspath, dspath)) + break; + } + + if (index == xf86_num_platform_devices) + goto out; + + ErrorF("xf86: remove device %d %s\n", index, syspath); + + xf86platformRemoveDevice(index); +out: + config_odev_free_attribute_list(attribs); +} + #endif -- 1.7.10.2 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel