[PATCH 07/31] xfree86: add platform bus hotplug support (v2)

Dave Airlie airlied at gmail.com
Wed Jun 20 07:00:22 PDT 2012


From: Dave Airlie <airlied at 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 <airlied at 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



More information about the xorg-devel mailing list