[PATCH] xfree86: use udev to provide device enumeration for kms devices (v2)

Peter Hutterer peter.hutterer at who-t.net
Wed May 9 18:34:58 PDT 2012


On Wed, May 09, 2012 at 12:10:11PM +0100, Dave Airlie wrote:
> From: Dave Airlie <airlied at 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.
> 
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
>  config/config-backends.h                     |    1 +
>  config/config.c                              |    8 +
>  config/udev.c                                |   49 +++++
>  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          |  264 ++++++++++++++++++++++++++
>  hw/xfree86/common/xf86platformBus.h          |   52 +++++
>  hw/xfree86/common/xf86str.h                  |   15 ++
>  hw/xfree86/os-support/linux/Makefile.am      |    2 +-
>  hw/xfree86/os-support/linux/lnx_platform.c   |   87 +++++++++
>  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                            |   16 ++
>  include/xorg-config.h.in                     |    3 +
>  include/xorg-server.h.in                     |    3 +
>  22 files changed, 599 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..07e920e 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)
>  {
> diff --git a/config/udev.c b/config/udev.c
> index 1995184..a2d5aad 100644
> --- a/config/udev.c
> +++ b/config/udev.c
> @@ -366,3 +366,52 @@ config_udev_fini(void)
>      udev_monitor = NULL;
>      udev_unref(udev);
>  }
> +
> +#ifdef CONFIG_UDEV_KMS
> +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;
> +    struct config_odev_attribute attribs[3];



> +
> +    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);
> +        int probe = TRUE;
> +
> +        if (!path || !syspath)
> +            probe = FALSE;
> +	if (strcmp(udev_device_get_subsystem(udev_device), "drm"))
> +            probe = FALSE;
> +        if (strncmp(sysname, "card", 4))
> +            probe = FALSE;
> +
> +	attribs[0].attrib_id = ODEV_ATTRIB_PATH;
> +	attribs[0].attrib = path;
> +	attribs[1].attrib_id = ODEV_ATTRIB_SYSPATH;
> +	attribs[1].attrib = syspath;
> +	attribs[2].attrib_id = ODEV_ATTRIB_SYSNAME;
> +	attribs[2].attrib = sysname;

indentation is messed up here, should be spaces, not tabs.

> +
> +        if (probe)
> +            probe_callback(3, attribs);

any reason you didn't just add the whole attribs[]... block into if (probe)?
right now you're setting them but not actually using them if probe is false.
using "else if" on the strcmps above also skips multiple probe assignments.
(alternatively, you could just have a goto to the unref statement instead of
probe = FALSE)

> +        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..16943e3 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..44fe03f
> --- /dev/null
> +++ b/hw/xfree86/common/xf86platformBus.c
> @@ -0,0 +1,264 @@
> +/*
> + * 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 <airlied at 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(int nattribs, struct config_odev_attribute *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].nattribs = nattribs;
> +    xf86_platform_devices[xf86_num_platform_devices].attribs = calloc(nattribs, sizeof(struct config_odev_attribute));
> +    if (!xf86_platform_devices[xf86_num_platform_devices].attribs)
> +        return -1;
> +
> +    memcpy(xf86_platform_devices[xf86_num_platform_devices].attribs, attribs, nattribs * sizeof(struct config_odev_attribute));
> +    xf86_num_platform_devices++;
> +    return 0;
> +}
> +
> +int
> +xf86_add_platform_device_attrib(int index, int attrib_id, char *attrib_str)
> +{
> +    struct xf86_platform_device *device = &xf86_platform_devices[index];
> +    device->attribs = realloc(device->attribs, (device->nattribs + 1) * sizeof(struct config_odev_attribute));
> +    if (!device->attribs)
> +        return -1;
> +    device->attribs[device->nattribs].attrib_id = attrib_id;
> +    device->attribs[device->nattribs].attrib = strdup(attrib_str);
> +    device->nattribs++;
> +    return 0;
> +}
> +
> +char *
> +xf86_get_platform_attrib(int index, int attrib_id)
> +{
> +    struct xf86_platform_device *device = &xf86_platform_devices[index];
> +    int i;
> +    for (i = 0; i < device->nattribs; i++) {
> +        if (device->attribs[i].attrib_id == attrib_id)
> +            return device->attribs[i].attrib;
> +    }
> +    return NULL;
> +}

might be worth writing simple tests for them?

also, I'd probably use a linked list for the attributes. seems easier than
reallocing.
then you can have a generic API for adding/removing attributes (that passes
the list as first argument) and one xf86-specific one that works on
xf86_platform_devices.

> +
> +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..7ea33d8
> --- /dev/null
> +++ b/hw/xfree86/common/xf86platformBus.h
> @@ -0,0 +1,52 @@
> +/*
> + * 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 <airlied at redhat.com>
> + */
> +#ifndef XF86_PLATFORM_BUS_H
> +#define XF86_PLATFORM_BUS_H
> +
> +#include "hotplug.h"
> +
> +struct xf86_platform_device {
> +    int nattribs;
> +    struct config_odev_attribute *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(int nattribs, struct config_odev_attribute *attribs);
> +
> +extern int
> +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..928eaa5
> --- /dev/null
> +++ b/hw/xfree86/os-support/linux/lnx_platform.c
> @@ -0,0 +1,87 @@
> +#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 void
> +get_drm_info(int nattribs, struct config_odev_attribute attribs[])
> +{
> +    drmSetVersion sv;
> +    char *buf;
> +    int fd;
> +    char *path = NULL;
> +    int i;
> +
> +    /* find the path attrib */
> +    for (i = 0; i < nattribs; i++) {
> +        if (attribs[i].attrib_id == ODEV_ATTRIB_PATH)
> +            path = attribs[i].attrib;
> +    }
> +
> +    if (!path)
> +        return;
> +
> +    fd = open(path, O_RDWR, O_CLOEXEC);
> +    if (fd == -1)
> +        return;
> +
> +    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;
> +    }
> +
> +    xf86_add_platform_device(nattribs, attribs);
> +
> +    buf = drmGetBusid(fd);
> +    xf86_add_platform_device_attrib(xf86_num_platform_devices - 1,
> +                                    ODEV_ATTRIB_BUSID, buf);
> +    drmFreeBusid(buf);
> +    close(fd);
> +
> +}
> +
> +void
> +xf86PlatformDeviceProbe(int nattribs, struct config_odev_attribute attribs[])
> +{
> +    int i;
> +    char *path = NULL;
> +
> +    for (i = 0; i < nattribs; i++) {
> +        if (attribs[i].attrib_id == ODEV_ATTRIB_PATH)
> +            path = attribs[i].attrib;
> +    }
> +    if (!path)
> +        return;
> +
> +    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)
> +        return;
> +
> +    LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n",
> +               path);
> +
> +    get_drm_info(nattribs, 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..3fe36aa
> --- /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(int nattribs, struct config_odev_attribute attribs[])
> +{
> +
> +}
> +#endif
> diff --git a/hw/xfree86/os-support/xf86_OSproc.h b/hw/xfree86/os-support/xf86_OSproc.h
> index e171146..29bf97e 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(int nattribs, struct config_odev_attribute 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..98eb7be 100644
> --- a/include/hotplug.h
> +++ b/include/hotplug.h
> @@ -30,4 +30,20 @@ extern _X_EXPORT void config_pre_init(void);
>  extern _X_EXPORT void config_init(void);
>  extern _X_EXPORT void config_fini(void);
>  
> +struct config_odev_attribute
> +{
> +    int attrib_id;
> +    char *attrib;
> +};

bikeshedding, but it seems weird that we have "InputAttributes" but "struct
config_odev_attribute".

Cheers,
  Peter

> +
> +#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)(int nattribs, struct config_odev_attribute 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 at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel
> 


More information about the xorg-devel mailing list