On Thu, May 10, 2012 at 11:25:04AM +0100, Dave Airlie wrote: > From: Dave Airlie <airl...@redhat.com> > > On Linux in order for future hotplug work, we are required to interface > to udev to detect device creation/removal. In order to try and get > some earlier testing on this, this patch adds the ability to use > udev for device enumeration on Linux. > > At startup the list of drm/kms devices is probed and this info is > used to load drivers. > > A new driver probing method is introduced that passes the udev > device info to the driver for probing. > > The probing integrates with the pci probing code and will fallback > to the pci probe and old school probe functions in turn. > > The flags parameter to the probe function will be used later > to provide hotplug and gpu screen flags for the driver to behave > in a different way. > > This patch changes the driver ABI, all drivers should at least > be set with a NULL udev probe function after this commit. > > v2: rename to platform bus, now with 100% less udev specific, > > this version passes config_odev_attribs around which are an array > of id/string pairs, then the udev code can attach the set of attribs > it understands, the OS specific code can attach its attrib, and then > the core/drivers can lookup the required attribs. > > also add MATCH_PCI_DEVICES macro. > > This version is mainly to address concerns raised by ajax. > > v3: Address comments from Peter. > fix whitespace that snuck in. > rework to use a linked list with some core functions that > xf86 wraps. > > Signed-off-by: Dave Airlie <airl...@redhat.com> > --- > config/config-backends.h | 1 + > config/config.c | 49 +++++ > config/udev.c | 73 ++++++++ > configure.ac | 20 ++- > hw/xfree86/common/Makefile.am | 8 +- > hw/xfree86/common/xf86.h | 5 + > hw/xfree86/common/xf86Bus.c | 25 ++- > hw/xfree86/common/xf86Bus.h | 1 + > hw/xfree86/common/xf86fbBus.c | 4 + > hw/xfree86/common/xf86pciBus.c | 17 ++- > hw/xfree86/common/xf86pciBus.h | 5 + > hw/xfree86/common/xf86platformBus.c | 256 > ++++++++++++++++++++++++++ > hw/xfree86/common/xf86platformBus.h | 51 +++++ > hw/xfree86/common/xf86str.h | 15 ++ > hw/xfree86/os-support/linux/Makefile.am | 2 +- > hw/xfree86/os-support/linux/lnx_platform.c | 89 +++++++++ > hw/xfree86/os-support/shared/platform_noop.c | 17 ++ > hw/xfree86/os-support/xf86_OSproc.h | 6 + > include/dix-config.h.in | 3 + > include/hotplug.h | 33 ++++ > include/xorg-config.h.in | 3 + > include/xorg-server.h.in | 3 + > 22 files changed, 674 insertions(+), 12 deletions(-) > create mode 100644 hw/xfree86/common/xf86platformBus.c > create mode 100644 hw/xfree86/common/xf86platformBus.h > create mode 100644 hw/xfree86/os-support/linux/lnx_platform.c > create mode 100644 hw/xfree86/os-support/shared/platform_noop.c > > diff --git a/config/config-backends.h b/config/config-backends.h > index 62abc0a..6423701 100644 > --- a/config/config-backends.h > +++ b/config/config-backends.h > @@ -36,6 +36,7 @@ BOOL device_is_duplicate(const char *config_info); > int config_udev_pre_init(void); > int config_udev_init(void); > void config_udev_fini(void); > +void config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback); > #else > > #ifdef CONFIG_NEED_DBUS > diff --git a/config/config.c b/config/config.c > index 24e7ba7..8d57b34 100644 > --- a/config/config.c > +++ b/config/config.c > @@ -85,6 +85,14 @@ config_fini(void) > #endif > } > > +void > +config_odev_probe(config_odev_probe_proc_ptr probe_callback) > +{ > +#if defined(CONFIG_UDEV_KMS) > + config_udev_odev_probe(probe_callback); > +#endif > +} > + > static void > remove_device(const char *backend, DeviceIntPtr dev) > { > @@ -133,3 +141,44 @@ device_is_duplicate(const char *config_info) > > return FALSE; > } > + > +struct OdevAttributes * > +config_odev_allocate_attribute_list(void) > +{ > + struct OdevAttributes *attriblist; > + > + attriblist = malloc(sizeof(struct OdevAttributes)); > + if (!attriblist) > + return NULL; > + > + xorg_list_init(&attriblist->list); > + return attriblist; > +}
there's no matching free_attribute_list()? would be useful, so you don't have to fix all the callers if OdevAttributes ever changes. > + > +Bool > +config_odev_add_attribute(struct OdevAttributes *attribs, int attrib, > + const char *attrib_name) > +{ > + struct OdevAttribute *oa; > + > + oa = malloc(sizeof(struct OdevAttribute)); > + if (!oa) > + return FALSE; > + > + oa->attrib_id = attrib; > + oa->attrib_name = strdup(attrib_name); > + xorg_list_append(&oa->member, &attribs->list); > + return TRUE; > +} > + > +void > +config_odev_free_attributes(struct OdevAttributes *attribs) > +{ > + struct OdevAttribute *iter, *safe; > + > + xorg_list_for_each_entry_safe(iter, safe, &attribs->list, member) { > + xorg_list_del(&iter->member); > + free(iter->attrib_name); > + free(iter); > + } > +} > diff --git a/config/udev.c b/config/udev.c > index 1995184..cb2a3e6 100644 > --- a/config/udev.c > +++ b/config/udev.c > @@ -366,3 +366,76 @@ config_udev_fini(void) > udev_monitor = NULL; > udev_unref(udev); > } > + > +#ifdef CONFIG_UDEV_KMS > + > +static Bool > +config_udev_odev_setup_attribs(const char *path, const char *syspath, const > char *sysname, > + config_odev_probe_proc_ptr probe_callback) > +{ > + struct OdevAttributes *attribs = config_odev_allocate_attribute_list(); > + int ret; > + > + if (!attribs) > + return FALSE; > + > + ret = config_odev_add_attribute(attribs, ODEV_ATTRIB_PATH, path); > + if (ret) > + goto fail; > + > + ret = config_odev_add_attribute(attribs, ODEV_ATTRIB_SYSPATH, syspath); > + if (ret) > + goto fail; > + > + ret = config_odev_add_attribute(attribs, ODEV_ATTRIB_SYSNAME, sysname); > + if (ret) > + goto fail; > + > + /* ownership of attribs is passed to probe layer */ > + probe_callback(attribs); > + return TRUE; > +fail: > + config_odev_free_attributes(attribs); > + free(attribs); > + return FALSE; > +} > + > +void > +config_udev_odev_probe(config_odev_probe_proc_ptr probe_callback) > +{ > + struct udev *udev; > + struct udev_enumerate *enumerate; > + struct udev_list_entry *devices, *device; > + > + udev = udev_monitor_get_udev(udev_monitor); > + enumerate = udev_enumerate_new(udev); > + if (!enumerate) > + return; > + > + udev_enumerate_add_match_subsystem(enumerate, "drm"); > + udev_enumerate_add_match_sysname(enumerate, "card[0-9]*"); > + udev_enumerate_scan_devices(enumerate); > + devices = udev_enumerate_get_list_entry(enumerate); > + udev_list_entry_foreach(device, devices) { > + const char *syspath = udev_list_entry_get_name(device); > + struct udev_device *udev_device = udev_device_new_from_syspath(udev, > syspath); > + const char *path = udev_device_get_devnode(udev_device); > + const char *sysname = udev_device_get_sysname(udev_device); > + > + if (!path || !syspath) > + goto no_probe; > + else if (strcmp(udev_device_get_subsystem(udev_device), "drm")) > + goto no_probe; > + else if (strncmp(sysname, "card", 4)) > + goto no_probe; > + > + config_udev_odev_setup_attribs(path, syspath, sysname, > probe_callback); > + > + no_probe: > + udev_device_unref(udev_device); > + } > + udev_enumerate_unref(enumerate); > + return; > +} > +#endif > + > diff --git a/configure.ac b/configure.ac > index 97ceab1..19fae0e 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -615,6 +615,7 @@ AC_ARG_ENABLE(dbe, > AS_HELP_STRING([--disable-dbe], [Build DBE extensi > AC_ARG_ENABLE(xf86bigfont, AS_HELP_STRING([--enable-xf86bigfont], [Build > XF86 Big Font extension (default: disabled)]), [XF86BIGFONT=$enableval], > [XF86BIGFONT=no]) > AC_ARG_ENABLE(dpms, AS_HELP_STRING([--disable-dpms], [Build DPMS > extension (default: enabled)]), [DPMSExtension=$enableval], > [DPMSExtension=yes]) > AC_ARG_ENABLE(config-udev, AS_HELP_STRING([--enable-config-udev], [Build > udev support (default: auto)]), [CONFIG_UDEV=$enableval], [CONFIG_UDEV=auto]) > +AC_ARG_ENABLE(config-udev-kms, AS_HELP_STRING([--enable-config-udev-kms], > [Build udev kms support (default: auto)]), [CONFIG_UDEV_KMS=$enableval], > [CONFIG_UDEV_KMS=auto]) > AC_ARG_ENABLE(config-dbus, AS_HELP_STRING([--enable-config-dbus], [Build > D-BUS API support (default: no)]), [CONFIG_DBUS_API=$enableval], > [CONFIG_DBUS_API=no]) > AC_ARG_ENABLE(config-hal, AS_HELP_STRING([--disable-config-hal], [Build > HAL support (default: auto)]), [CONFIG_HAL=$enableval], [CONFIG_HAL=auto]) > AC_ARG_ENABLE(config-wscons, AS_HELP_STRING([--enable-config-wscons], > [Build wscons config support (default: auto)]), [CONFIG_WSCONS=$enableval], > [CONFIG_WSCONS=auto]) > @@ -704,6 +705,7 @@ case $host_os in > CONFIG_DBUS_API=no > CONFIG_HAL=no > CONFIG_UDEV=no > + CONFIG_UDEV_KMS=no > DGA=no > DRI2=no > INT10MODULE=no > @@ -838,11 +840,16 @@ AM_CONDITIONAL(CONFIG_UDEV, [test "x$CONFIG_UDEV" = > xyes]) > if test "x$CONFIG_UDEV" = xyes; then > CONFIG_DBUS_API=no > CONFIG_HAL=no > + if test "x$CONFIG_UDEV_KMS" = xauto; then > + CONFIG_UDEV_KMS="$HAVE_LIBUDEV" > + fi > if ! test "x$HAVE_LIBUDEV" = xyes; then > AC_MSG_ERROR([udev configuration API requested, but libudev is > not installed]) > fi > AC_DEFINE(CONFIG_UDEV, 1, [Use libudev for input hotplug]) > - > + if test "x$CONFIG_UDEV_KMS" = xyes; then > + AC_DEFINE(CONFIG_UDEV_KMS, 1, [Use libudev for kms enumeration]) > + fi > SAVE_LIBS=$LIBS > SAVE_CFLAGS=$CFLAGS > CFLAGS=$UDEV_CFLAGS > @@ -852,6 +859,7 @@ if test "x$CONFIG_UDEV" = xyes; then > LIBS=$SAVE_LIBS > CFLAGS=$SAVE_CFLAGS > fi > +AM_CONDITIONAL(CONFIG_UDEV_KMS, [test "x$CONFIG_UDEV_KMS" = xyes]) > > dnl HAVE_DBUS is true if we actually have the D-Bus library, whereas > dnl CONFIG_DBUS_API is true if we want to enable the D-Bus config > @@ -1099,7 +1107,7 @@ case "$DRI2,$HAVE_DRI2PROTO" in > esac > AM_CONDITIONAL(DRI2, test "x$DRI2" = xyes) > > -if test "x$DRI" = xyes || test "x$DRI2" = xyes; then > +if test "x$DRI" = xyes || test "x$DRI2" = xyes || test "x$CONFIG_UDEV_KMS" = > xyes; then > if test "x$DRM" = xyes; then > AC_DEFINE(WITH_LIBDRM, 1, [Building with libdrm support]) > PKG_CHECK_MODULES([LIBDRM], $LIBDRM) > @@ -1630,7 +1638,7 @@ if test "x$XORG" = xyes; then > > PKG_CHECK_MODULES([PCIACCESS], $LIBPCIACCESS) > SDK_REQUIRED_MODULES="$SDK_REQUIRED_MODULES $LIBPCIACCESS" > - XORG_SYS_LIBS="$XORG_SYS_LIBS $PCIACCESS_LIBS $GLX_SYS_LIBS" > + XORG_SYS_LIBS="$XORG_SYS_LIBS $PCIACCESS_LIBS $GLX_SYS_LIBS > $LIBDRM_LIBS" > XORG_CFLAGS="$XORG_CFLAGS $PCIACCESS_CFLAGS" > > AC_DEFINE(XSERVER_LIBPCIACCESS, 1, [Use libpciaccess for all pci > manipulation]) > @@ -1648,6 +1656,10 @@ if test "x$XORG" = xyes; then > fi > AC_MSG_RESULT([$PCI]) > > + if test "x$CONFIG_UDEV_KMS" = xyes; then > + AC_DEFINE(XSERVER_PLATFORM_BUS, 1, [X server supports platform > device enumeration]) > + fi > + AC_MSG_RESULT([$XSERVER_PLATFORM_BUS]) > dnl =================================================================== > dnl ==================== end of PCI configuration ===================== > dnl =================================================================== > @@ -1836,7 +1848,7 @@ AM_CONDITIONAL([SOLARIS_ASM_INLINE], [test > "x$solaris_asm_inline" = xyes]) > AM_CONDITIONAL([SOLARIS_VT], [test "x$solaris_vt" = xyes]) > AM_CONDITIONAL([DGA], [test "x$DGA" = xyes]) > AM_CONDITIONAL([XF86VIDMODE], [test "x$XF86VIDMODE" = xyes]) > - > +AM_CONDITIONAL([XORG_BUS_PLATFORM], [test "x$CONFIG_UDEV_KMS" = xyes]) > dnl XWin DDX > > AC_MSG_CHECKING([whether to build XWin DDX]) > diff --git a/hw/xfree86/common/Makefile.am b/hw/xfree86/common/Makefile.am > index 2792177..65d98e6 100644 > --- a/hw/xfree86/common/Makefile.am > +++ b/hw/xfree86/common/Makefile.am > @@ -22,9 +22,13 @@ if DGA > DGASOURCES = xf86DGA.c > endif > > +if XORG_BUS_PLATFORM > +PLATSOURCES = xf86platformBus.c > +endif > + > RANDRSOURCES = xf86RandR.c > > -BUSSOURCES = xf86fbBus.c xf86noBus.c $(PCI_SOURCES) $(SBUS_SOURCES) > +BUSSOURCES = xf86fbBus.c xf86noBus.c $(PCI_SOURCES) $(SBUS_SOURCES) > $(PLATSOURCES) > > MODEDEFSOURCES = $(srcdir)/vesamodes $(srcdir)/extramodes > > @@ -56,7 +60,7 @@ sdk_HEADERS = compiler.h fourcc.h xf86.h xf86Module.h > xf86Opt.h \ > xf86PciInfo.h xf86Priv.h xf86Privstr.h \ > xf86cmap.h xf86fbman.h xf86str.h xf86Xinput.h xisb.h \ > $(XVSDKINCS) $(XF86VMODE_SDK) xorgVersion.h \ > - xf86sbusBus.h xf86VGAarbiter.h xf86Optionstr.h > + xf86sbusBus.h xf86VGAarbiter.h xf86Optionstr.h > xf86platformBus.h > > DISTCLEANFILES = xf86Build.h > CLEANFILES = $(BUILT_SOURCES) > diff --git a/hw/xfree86/common/xf86.h b/hw/xfree86/common/xf86.h > index e6d41d6..5f7badb 100644 > --- a/hw/xfree86/common/xf86.h > +++ b/hw/xfree86/common/xf86.h > @@ -71,6 +71,11 @@ extern _X_EXPORT Bool fbSlotClaimed; > #if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) > extern _X_EXPORT Bool sbusSlotClaimed; > #endif > + > +#if defined(XSERVER_PLATFORM_BUS) > +extern _X_EXPORT int platformSlotClaimed; > +#endif > + > extern _X_EXPORT confDRIRec xf86ConfigDRI; > extern _X_EXPORT Bool xf86DRI2Enabled(void); > > diff --git a/hw/xfree86/common/xf86Bus.c b/hw/xfree86/common/xf86Bus.c > index b876434..733fe84 100644 > --- a/hw/xfree86/common/xf86Bus.c > +++ b/hw/xfree86/common/xf86Bus.c > @@ -77,8 +77,14 @@ xf86CallDriverProbe(DriverPtr drv, Bool detect_only) > { > Bool foundScreen = FALSE; > > +#ifdef XSERVER_PLATFORM_BUS > + if (drv->platformProbe != NULL) { > + foundScreen = xf86platformProbeDev(drv); > + } > +#endif > + > #ifdef XSERVER_LIBPCIACCESS > - if (drv->PciProbe != NULL) { > + if (!foundScreen && (drv->PciProbe != NULL)) { > if (xf86DoConfigure && xf86DoConfigurePass1) { > assert(detect_only); > foundScreen = xf86PciAddMatchingDev(drv); > @@ -202,6 +208,9 @@ xf86BusConfig(void) > void > xf86BusProbe(void) > { > +#ifdef XSERVER_PLATFORM_BUS > + xf86platformProbe(); > +#endif > #ifdef XSERVER_LIBPCIACCESS > xf86PciProbe(); > #endif > @@ -262,14 +271,19 @@ xf86IsEntityPrimary(int entityIndex) > { > EntityPtr pEnt = xf86Entities[entityIndex]; > > - if (primaryBus.type != pEnt->bus.type) > - return FALSE; > - > switch (pEnt->bus.type) { > case BUS_PCI: > + if (primaryBus.type != pEnt->bus.type) > + return FALSE; > return pEnt->bus.id.pci == primaryBus.id.pci; > case BUS_SBUS: > + if (primaryBus.type != pEnt->bus.type) > + return FALSE; > return pEnt->bus.id.sbus.fbNum == primaryBus.id.sbus.fbNum; > + case BUS_PLATFORM: > + if (!pEnt->bus.id.plat->pdev) > + return FALSE; > + return (MATCH_PCI_DEVICES(pEnt->bus.id.plat->pdev, > primaryBus.id.pci)); > default: > return FALSE; > } > @@ -542,6 +556,9 @@ xf86PostProbe(void) > #if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) > sbusSlotClaimed || > #endif > +#ifdef XSERVER_PLATFORM_BUS > + platformSlotClaimed || > +#endif > #ifdef XSERVER_LIBPCIACCESS > pciSlotClaimed > #else > diff --git a/hw/xfree86/common/xf86Bus.h b/hw/xfree86/common/xf86Bus.h > index abf2efd..e83ba78 100644 > --- a/hw/xfree86/common/xf86Bus.h > +++ b/hw/xfree86/common/xf86Bus.h > @@ -42,6 +42,7 @@ > #if defined(__sparc__) || defined(__sparc) > #include "xf86sbusBus.h" > #endif > +#include "xf86platformBus.h" > > typedef struct { > DriverPtr driver; > diff --git a/hw/xfree86/common/xf86fbBus.c b/hw/xfree86/common/xf86fbBus.c > index 1e51623..303b9c2 100644 > --- a/hw/xfree86/common/xf86fbBus.c > +++ b/hw/xfree86/common/xf86fbBus.c > @@ -54,6 +54,10 @@ xf86ClaimFbSlot(DriverPtr drvp, int chipset, GDevPtr dev, > Bool active) > EntityPtr p; > int num; > > +#ifdef XSERVER_PLATFORM_BUS > + if (platformSlotClaimed) > + return -1; > +#endif > #ifdef XSERVER_LIBPCIACCESS > if (pciSlotClaimed) > return -1; > diff --git a/hw/xfree86/common/xf86pciBus.c b/hw/xfree86/common/xf86pciBus.c > index d758260..38ced15 100644 > --- a/hw/xfree86/common/xf86pciBus.c > +++ b/hw/xfree86/common/xf86pciBus.c > @@ -367,7 +367,15 @@ xf86GetPciInfoForEntity(int entityIndex) > return NULL; > > p = xf86Entities[entityIndex]; > - return (p->bus.type == BUS_PCI) ? p->bus.id.pci : NULL; > + switch (p->bus.type) { > + case BUS_PCI: > + return p->bus.id.pci; > + case BUS_PLATFORM: > + return p->bus.id.plat->pdev; > + default: > + break; > + } > + return NULL; > } > > /* > @@ -400,6 +408,13 @@ xf86CheckPciSlot(const struct pci_device *d) > if ((p->bus.type == BUS_PCI) && (p->bus.id.pci == d)) { > return FALSE; > } > +#ifdef XSERVER_PLATFORM_BUS > + if ((p->bus.type == BUS_PLATFORM) && (p->bus.id.plat->pdev)) { > + struct pci_device *ud = p->bus.id.plat->pdev; > + if (MATCH_PCI_DEVICES(ud, d)) > + return FALSE; > + } > +#endif > } > return TRUE; > } > diff --git a/hw/xfree86/common/xf86pciBus.h b/hw/xfree86/common/xf86pciBus.h > index 56ec6e9..975da6c 100644 > --- a/hw/xfree86/common/xf86pciBus.h > +++ b/hw/xfree86/common/xf86pciBus.h > @@ -42,4 +42,9 @@ Bool xf86PciConfigure(void *busData, struct pci_device > *pDev); > void xf86PciConfigureNewDev(void *busData, struct pci_device *pVideo, > GDevRec * GDev, int *chipset); > > +#define MATCH_PCI_DEVICES(x, y) (((x)->domain == (y)->domain) && \ > + ((x)->bus == (y)->bus) && \ > + ((x)->func == (y)->func) && \ > + ((x)->dev == (y)->dev)) > + > #endif /* _XF86_PCI_BUS_H */ > diff --git a/hw/xfree86/common/xf86platformBus.c > b/hw/xfree86/common/xf86platformBus.c > new file mode 100644 > index 0000000..af02622 > --- /dev/null > +++ b/hw/xfree86/common/xf86platformBus.c > @@ -0,0 +1,256 @@ > +/* > + * Copyright © 2012 Red Hat. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER > + * DEALINGS IN THE SOFTWARE. > + * > + * Author: Dave Airlie <airl...@redhat.com> > + */ > + > +/* > + * This file contains the interfaces to the bus-specific code > + */ > + > +#ifdef HAVE_XORG_CONFIG_H > +#include <xorg-config.h> > +#endif > + > +#ifdef XSERVER_PLATFORM_BUS > +#include <errno.h> > + > +#include <pciaccess.h> > +#include <fcntl.h> > +#include <unistd.h> > +#include "os.h" > +#include "hotplug.h" > + > +#include "xf86.h" > +#include "xf86_OSproc.h" > +#include "xf86Priv.h" > +#include "xf86str.h" > +#include "xf86Bus.h" > +#include "Pci.h" > +#include "xf86platformBus.h" > + > +int platformSlotClaimed; > + > +int xf86_num_platform_devices; > + > +static struct xf86_platform_device *xf86_platform_devices; > + > +int > +xf86_add_platform_device(struct OdevAttributes *attribs) > +{ > + xf86_platform_devices = xnfrealloc(xf86_platform_devices, > + (sizeof(struct xf86_platform_device) > + * (xf86_num_platform_devices + 1))); > + > + xf86_platform_devices[xf86_num_platform_devices].attribs = attribs; > + xf86_num_platform_devices++; > + return 0; > +} > + > +Bool > +xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_name) > +{ > + struct xf86_platform_device *device = &xf86_platform_devices[index]; > + > + return config_odev_add_attribute(device->attribs, attrib_id, > attrib_name); > +} > + > +char * > +xf86_get_platform_attrib(int index, int attrib_id) > +{ > + struct xf86_platform_device *device = &xf86_platform_devices[index]; > + int i; > + struct OdevAttribute *oa; > + > + xorg_list_for_each_entry(oa, &device->attribs->list, member) { > + if (oa->attrib_id == attrib_id) > + return oa->attrib_name; > + } > + return NULL; > +} > + > +static void > +platform_find_pci_info(int idx) > +{ > + struct pci_slot_match devmatch; > + struct pci_device *info; > + struct pci_device_iterator *iter; > + int ret; > + char *busid; > + > + busid = xf86_get_platform_attrib(idx, ODEV_ATTRIB_BUSID); > + ret = sscanf(busid, "pci:%04x:%02x:%02x.%u", > + &devmatch.domain, &devmatch.bus, &devmatch.dev, > + &devmatch.func); > + if (ret != 4) > + return; > + > + iter = pci_slot_match_iterator_create(&devmatch); > + info = pci_device_next(iter); > + if (info) { > + xf86_platform_devices[idx].pdev = info; > + pci_device_probe(info); > + } > + pci_iterator_destroy(iter); > + > +} > + > +static Bool > +xf86_check_platform_slot(const struct xf86_platform_device *pd) > +{ > + int i; > + > + for (i = 0; i < xf86NumEntities; i++) { > + const EntityPtr u = xf86Entities[i]; > + > + if ((u->bus.type == BUS_PLATFORM) && (pd == u->bus.id.plat)) { > + return FALSE; > + } > + } > + return TRUE; > +} > + > +int > +xf86platformProbe(void) > +{ > + int i; > + Bool pci = TRUE; > + > + if (!xf86scanpci()) { > + pci = FALSE; > + } > + > + config_odev_probe(&xf86PlatformDeviceProbe); > + for (i = 0; i < xf86_num_platform_devices; i++) { > + char *busid = xf86_get_platform_attrib(i, ODEV_ATTRIB_BUSID); > + > + if (pci && !strncmp(busid, "pci:", 4)) { > + platform_find_pci_info(i); > + } > + else if (!strncmp(busid, "usb:", 4)) { > + /* place holder */ > + } > + } > + return 0; > +} > + > +static int > +xf86ClaimPlatformSlot(struct xf86_platform_device * d, DriverPtr drvp, > + int chipset, GDevPtr dev, Bool active) > +{ > + EntityPtr p = NULL; > + int num; > + > + num = xf86AllocateEntity(); > + p = xf86Entities[num]; > + p->driver = drvp; > + p->chipset = chipset; > + p->bus.type = BUS_PLATFORM; > + p->bus.id.plat = d; > + p->active = active; > + p->inUse = FALSE; > + if (dev) > + xf86AddDevToEntity(num, dev); > + > + platformSlotClaimed++; > + return num; > +} > + > +static int > +xf86UnclaimPlatformSlot(struct xf86_platform_device *d, GDevPtr dev) > +{ > + int i; > + > + for (i = 0; i < xf86NumEntities; i++) { > + const EntityPtr p = xf86Entities[i]; > + > + if ((p->bus.type == BUS_PLATFORM) && (p->bus.id.plat == d)) { > + if (dev) > + xf86RemoveDevFromEntity(i, dev); > + platformSlotClaimed--; > + p->bus.type = BUS_NONE; > + return 0; > + } > + } > + return 0; > +} > + > +#define END_OF_MATCHES(m) \ > + (((m).vendor_id == 0) && ((m).device_id == 0) && ((m).subvendor_id == 0)) > + > +int > +xf86platformProbeDev(DriverPtr drvp) > +{ > + Bool foundScreen = FALSE; > + GDevPtr *devList; > + const unsigned numDevs = xf86MatchDevice(drvp->driverName, &devList); > + int i, j, k; > + int entity; > + const struct pci_id_match *const devices = drvp->supported_devices; > + struct pci_device *pPci; > + > + for (i = 0; i < numDevs; i++) { > + for (j = 0; j < xf86_num_platform_devices; j++) { > + /* overload PCI match loading if we can use it */ > + if (xf86_platform_devices[j].pdev && devices) { > + int device_id = xf86_platform_devices[j].pdev->device_id; > + pPci = xf86_platform_devices[j].pdev; > + for (k = 0; !END_OF_MATCHES(devices[k]); k++) { > + if (PCI_ID_COMPARE(devices[k].vendor_id, pPci->vendor_id) > + && PCI_ID_COMPARE(devices[k].device_id, device_id) > + && ((devices[k].device_class_mask & > pPci->device_class) > + == devices[k].device_class)) { > + if > (xf86_check_platform_slot(&xf86_platform_devices[j])) { > + entity = > xf86ClaimPlatformSlot(&xf86_platform_devices[j], > + drvp, 0, devList[i], > devList[i]->active); > + if (entity != -1) { > + if (!drvp->platformProbe(drvp, entity, 0, > &xf86_platform_devices[j], devices[k].match_data)) { > + > xf86UnclaimPlatformSlot(&xf86_platform_devices[j], devList[i]); > + continue; > + } > + foundScreen = TRUE; > + break; > + } > + else > + > xf86UnclaimPlatformSlot(&xf86_platform_devices[j], devList[i]); > + } > + } > + } > + } > + else if (xf86_platform_devices[j].pdev && !devices) > + continue; > + else { > + if (xf86_check_platform_slot(&xf86_platform_devices[j])) { > + entity = xf86ClaimPlatformSlot(&xf86_platform_devices[j], > + drvp, 0, devList[i], > devList[i]->active); > + if (!drvp->platformProbe(drvp, entity, 0, > &xf86_platform_devices[j], 0)) { > + xf86UnclaimPlatformSlot(&xf86_platform_devices[j], > devList[i]); > + continue; > + } > + foundScreen = TRUE; > + } > + } > + } > + } > + return foundScreen; > +} > + > +#endif > diff --git a/hw/xfree86/common/xf86platformBus.h > b/hw/xfree86/common/xf86platformBus.h > new file mode 100644 > index 0000000..f152af5 > --- /dev/null > +++ b/hw/xfree86/common/xf86platformBus.h > @@ -0,0 +1,51 @@ > +/* > + * Copyright © 2012 Red Hat. > + * > + * Permission is hereby granted, free of charge, to any person obtaining a > + * copy of this software and associated documentation files (the "Software"), > + * to deal in the Software without restriction, including without limitation > + * the rights to use, copy, modify, merge, publish, distribute, sublicense, > + * and/or sell copies of the Software, and to permit persons to whom the > + * Software is furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER > + * DEALINGS IN THE SOFTWARE. > + * > + * Author: Dave Airlie <airl...@redhat.com> > + */ > +#ifndef XF86_PLATFORM_BUS_H > +#define XF86_PLATFORM_BUS_H > + > +#include "hotplug.h" > + > +struct xf86_platform_device { > + struct OdevAttributes *attribs; > + /* for PCI devices */ > + struct pci_device *pdev; > +}; > + > +#ifdef XSERVER_PLATFORM_BUS > +int xf86platformProbe(void); > +int xf86platformProbeDev(DriverPtr drvp); > + > +extern int xf86_num_platform_devices; > + > +extern char * > +xf86_get_platform_attrib(int index, int attrib_id); > +extern int > +xf86_add_platform_device(struct OdevAttributes *attribs); > + > +extern Bool > +xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_str); > + > +#endif > + > +#endif > diff --git a/hw/xfree86/common/xf86str.h b/hw/xfree86/common/xf86str.h > index 6294845..ebfd7f7 100644 > --- a/hw/xfree86/common/xf86str.h > +++ b/hw/xfree86/common/xf86str.h > @@ -311,6 +311,7 @@ struct _SymTabRec; > struct _PciChipsets; > > struct pci_device; > +struct xf86_platform_device; > > typedef struct _DriverRec { > int driverVersion; > @@ -325,9 +326,20 @@ typedef struct _DriverRec { > const struct pci_id_match *supported_devices; > Bool (*PciProbe) (struct _DriverRec * drv, int entity_num, > struct pci_device * dev, intptr_t match_data); > +#ifdef XSERVER_PLATFORM_BUS > + Bool (*platformProbe) (struct _DriverRec * drv, int entity_num, int > flags, > + struct xf86_platform_device * dev, intptr_t > match_data); > +#else > + void *platformProbe; /* place holder to non udev-kms support so struct > is right size */ > +#endif > } DriverRec, *DriverPtr; > > /* > + * platform probe flags > + * no flags are defined yet - but drivers should fail to load if a flag they > + * don't understand is passed. > + */ > +/* > * AddDriver flags > */ > #define HaveDriverFuncs 1 > @@ -343,6 +355,7 @@ typedef struct _DriverRec { > #undef BUS_NONE > #undef BUS_PCI > #undef BUS_SBUS > +#undef BUS_PLATFORM > #undef BUS_last > #endif > > @@ -350,6 +363,7 @@ typedef enum { > BUS_NONE, > BUS_PCI, > BUS_SBUS, > + BUS_PLATFORM, > BUS_last /* Keep last */ > } BusType; > > @@ -362,6 +376,7 @@ typedef struct _bus { > union { > struct pci_device *pci; > SbusBusId sbus; > + struct xf86_platform_device *plat; > } id; > } BusRec, *BusPtr; > > diff --git a/hw/xfree86/os-support/linux/Makefile.am > b/hw/xfree86/os-support/linux/Makefile.am > index 36748df..61175b3 100644 > --- a/hw/xfree86/os-support/linux/Makefile.am > +++ b/hw/xfree86/os-support/linux/Makefile.am > @@ -22,7 +22,7 @@ XORG_CFLAGS += -DHAVE_APM > endif > > liblinux_la_SOURCES = lnx_init.c lnx_video.c \ > - lnx_agp.c lnx_kmod.c lnx_bell.c \ > + lnx_agp.c lnx_kmod.c lnx_bell.c lnx_platform.c \ > $(srcdir)/../shared/bios_mmap.c \ > $(srcdir)/../shared/VTsw_usl.c \ > $(srcdir)/../shared/posix_tty.c \ > diff --git a/hw/xfree86/os-support/linux/lnx_platform.c > b/hw/xfree86/os-support/linux/lnx_platform.c > new file mode 100644 > index 0000000..4285a19 > --- /dev/null > +++ b/hw/xfree86/os-support/linux/lnx_platform.c > @@ -0,0 +1,89 @@ > +#ifdef HAVE_XORG_CONFIG_H > +#include <xorg-config.h> > +#endif > + > +#ifdef XSERVER_PLATFORM_BUS > + > +#include <xf86drm.h> > +#include <fcntl.h> > +#include <unistd.h> > + > +/* Linux platform device support */ > +#include "xf86_OSproc.h" > + > +#include "xf86.h" > +#include "xf86platformBus.h" > + > +static Bool > +get_drm_info(struct OdevAttributes *attribs, char *path) > +{ > + drmSetVersion sv; > + char *buf; > + int fd; > + > + fd = open(path, O_RDWR, O_CLOEXEC); > + if (fd == -1) > + return FALSE; > + > + sv.drm_di_major = 1; > + sv.drm_di_minor = 4; > + sv.drm_dd_major = -1; /* Don't care */ > + sv.drm_dd_minor = -1; /* Don't care */ > + if (drmSetInterfaceVersion(fd, &sv)) { > + ErrorF("setversion 1.4 failed\n"); > + return FALSE; > + } > + > + xf86_add_platform_device(attribs); > + > + buf = drmGetBusid(fd); > + xf86_add_platform_device_attrib(xf86_num_platform_devices - 1, > + ODEV_ATTRIB_BUSID, buf); > + drmFreeBusid(buf); > + close(fd); > + return TRUE; > +} > + > +void > +xf86PlatformDeviceProbe(struct OdevAttributes *attribs) > +{ > + struct OdevAttribute *attrib; > + int i; > + char *path = NULL; > + Bool ret; > + > + xorg_list_for_each_entry(attrib, &attribs->list, member) { > + if (attrib->attrib_id == ODEV_ATTRIB_PATH) { > + path = attrib->attrib_name; > + break; > + } > + } > + if (!path) > + goto out_free; > + > + for (i = 0; i < xf86_num_platform_devices; i++) { > + char *dpath; > + dpath = xf86_get_platform_attrib(i, ODEV_ATTRIB_PATH); > + > + if (!strcmp(path, dpath)) > + break; > + } > + > + if (i != xf86_num_platform_devices) > + goto out_free; > + > + LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", > + path); > + > + ret = get_drm_info(attribs, path); > + if (ret == FALSE) > + goto out_free; > + > + return; > + > +out_free: > + config_odev_free_attributes(attribs); > + free(attribs); > +} > + > +#endif > diff --git a/hw/xfree86/os-support/shared/platform_noop.c > b/hw/xfree86/os-support/shared/platform_noop.c > new file mode 100644 > index 0000000..2baf72a > --- /dev/null > +++ b/hw/xfree86/os-support/shared/platform_noop.c > @@ -0,0 +1,17 @@ > + > +#ifdef HAVE_XORG_CONFIG_H > +#include <xorg-config.h> > +#endif > + > +#ifdef XSERVER_PLATFORM_BUS > +/* noop platform device support */ > +#include "xf86_OSproc.h" > + > +#include "xf86.h" > +#include "xf86platformBus.h" > + > +void xf86PlatformDeviceProbe(struct OdevAttributes *attribs) > +{ > + > +} > +#endif > diff --git a/hw/xfree86/os-support/xf86_OSproc.h > b/hw/xfree86/os-support/xf86_OSproc.h > index e171146..2f0172e 100644 > --- a/hw/xfree86/os-support/xf86_OSproc.h > +++ b/hw/xfree86/os-support/xf86_OSproc.h > @@ -221,6 +221,12 @@ extern _X_EXPORT void xf86InitVidMem(void); > > #endif /* XF86_OS_PRIVS */ > > +#ifdef XSERVER_PLATFORM_BUS > +#include "hotplug.h" > +void > +xf86PlatformDeviceProbe(struct OdevAttributes *attribs); > +#endif > + > _XFUNCPROTOEND > #endif /* NO_OSLIB_PROTOTYPES */ > #endif /* _XF86_OSPROC_H */ > diff --git a/include/dix-config.h.in b/include/dix-config.h.in > index 3c9bbaf..77681a9 100644 > --- a/include/dix-config.h.in > +++ b/include/dix-config.h.in > @@ -390,6 +390,9 @@ > /* Use libudev for input hotplug */ > #undef CONFIG_UDEV > > +/* Use libudev for kms enumeration */ > +#undef CONFIG_UDEV_KMS > + > /* Use udev_monitor_filter_add_match_tag() */ > #undef HAVE_UDEV_MONITOR_FILTER_ADD_MATCH_TAG > > diff --git a/include/hotplug.h b/include/hotplug.h > index f3eeea2..6e3a193 100644 > --- a/include/hotplug.h > +++ b/include/hotplug.h > @@ -26,8 +26,41 @@ > #ifndef HOTPLUG_H > #define HOTPLUG_H > > +#include "list.h" > + > extern _X_EXPORT void config_pre_init(void); > extern _X_EXPORT void config_init(void); > extern _X_EXPORT void config_fini(void); > > +struct OdevAttribute > +{ > + struct xorg_list member; > + int attrib_id; > + char *attrib_name; > +}; > + > +struct OdevAttributes > +{ > + struct xorg_list list; > +}; looks like the coding style now requires { on the same line for structs. Reviewed-by: Peter Hutterer <peter.hutte...@who-t.net> otherwise Cheers, Peter > + > +struct OdevAttributes * > +config_odev_allocate_attribute_list(void); > + > +Bool > +config_odev_add_attribute(struct OdevAttributes *attribs, int attrib, > + const char *attrib_name); > + > +void > +config_odev_free_attributes(struct OdevAttributes *attribs); > + > +#define ODEV_ATTRIB_PATH 1 > +#define ODEV_ATTRIB_SYSPATH 2 > +#define ODEV_ATTRIB_SYSNAME 3 > +#define ODEV_ATTRIB_BUSID 4 > + > +#ifdef CONFIG_UDEV_KMS > +typedef void (*config_odev_probe_proc_ptr)(struct OdevAttributes *attribs); > +void config_odev_probe(config_odev_probe_proc_ptr probe_callback); > +#endif > #endif /* HOTPLUG_H */ > diff --git a/include/xorg-config.h.in b/include/xorg-config.h.in > index 2cc416a..a71b25d 100644 > --- a/include/xorg-config.h.in > +++ b/include/xorg-config.h.in > @@ -136,4 +136,7 @@ > /* Have getresuid */ > #undef HAVE_GETRESUID > > +/* Have X server platform bus support */ > +#undef XSERVER_PLATFORM_BUS > + > #endif /* _XORG_CONFIG_H_ */ > diff --git a/include/xorg-server.h.in b/include/xorg-server.h.in > index 8086f32..c0761f7 100644 > --- a/include/xorg-server.h.in > +++ b/include/xorg-server.h.in > @@ -205,6 +205,9 @@ > /* X Access Control Extension */ > #undef XACE > > +/* Have X server platform bus support */ > +#undef XSERVER_PLATFORM_BUS > + > #ifdef _LP64 > #define _XSERVER64 1 > #endif > -- > 1.7.6 _______________________________________________ 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