xfree86: add platform bus hotplug support (v3)
This provides add/remove support for platform devices at xfree86 ddx level. v2: cleanup properly if no driver found. v3: load the modesetting driver before checking driver list. Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
b27cf30995
commit
ef6686480a
|
@ -376,4 +376,107 @@ xf86platformProbeDev(DriverPtr drvp)
|
|||
return foundScreen;
|
||||
}
|
||||
|
||||
int
|
||||
xf86platformAddDevice(int index)
|
||||
{
|
||||
int i, old_screens, scr_index;
|
||||
DriverPtr drvp = NULL;
|
||||
int entity;
|
||||
screenLayoutPtr layout;
|
||||
static char *hotplug_driver_name = "modesetting";
|
||||
|
||||
/* force load the driver for now */
|
||||
xf86LoadOneModule(hotplug_driver_name, NULL);
|
||||
|
||||
for (i = 0; i < xf86NumDrivers; i++) {
|
||||
if (!xf86DriverList[i])
|
||||
continue;
|
||||
|
||||
if (!strcmp(xf86DriverList[i]->driverName, hotplug_driver_name)) {
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue
Block a user