[PATCH libdrm v3 3/5] xf86drm: Add platform and host1x bus support

walter harms wharms at bfs.de
Wed Jan 18 15:00:20 UTC 2017



Am 18.01.2017 10:02, schrieb Thierry Reding:
> From: Thierry Reding <treding at nvidia.com>
> 
> ARM SoCs usually have their DRM/KMS devices on the platform bus, so add
> support for that to enable these devices to be used with the drmDevice
> infrastructure.
> 
> NVIDIA Tegra SoCs have an additional level in the hierarchy and DRM/KMS
> devices can also be on the host1x bus. This is mostly equivalent to the
> platform bus.
> 
> v3:
> - guard Linux-specific sysfs parsing code with #ifdef __linux__
> 
> v2:
> - be careful not to overflow the full name
> - read compatible strings into device info
> 
> Signed-off-by: Thierry Reding <treding at nvidia.com>
> ---
>  xf86drm.c | 300 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  xf86drm.h |  30 ++++++-
>  2 files changed, 328 insertions(+), 2 deletions(-)
> 
> diff --git a/xf86drm.c b/xf86drm.c
> index d83674e638c4..3c6ec1cc9e00 100644
> --- a/xf86drm.c
> +++ b/xf86drm.c
> @@ -2953,6 +2953,12 @@ static int drmParseSubsystemType(int maj, int min)
>      if (strncmp(name, "/usb", 4) == 0)
>          return DRM_BUS_USB;
>  
> +    if (strncmp(name, "/platform", 9) == 0)
> +        return DRM_BUS_PLATFORM;
> +
> +    if (strncmp(name, "/host1x", 7) == 0)
> +        return DRM_BUS_HOST1X;
> +
>      return -EINVAL;
>  #elif defined(__OpenBSD__)
>      return DRM_BUS_PCI;
> @@ -3043,6 +3049,12 @@ static int drmCompareBusInfo(drmDevicePtr a, drmDevicePtr b)
>      case DRM_BUS_USB:
>          return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo));
>  
> +    case DRM_BUS_PLATFORM:
> +        return memcmp(a->businfo.platform, b->businfo.platform, sizeof(drmPlatformBusInfo));
> +
> +    case DRM_BUS_HOST1X:
> +        return memcmp(a->businfo.host1x, b->businfo.host1x, sizeof(drmHost1xBusInfo));
> +
>      default:
>          break;
>      }
> @@ -3187,11 +3199,55 @@ static int drmParsePciDeviceInfo(int maj, int min,
>  #endif
>  }
>  
> +static void drmFreePlatformDevice(drmDevicePtr device)
> +{
> +    if (device->deviceinfo.platform) {

to save 2 indent level and improve readability :

if (! device->deviceinfo.platform ||
    ! device->deviceinfo.platform->compatible)
	return;

> +        if (device->deviceinfo.platform->compatible) {
> +            char **compatible = device->deviceinfo.platform->compatible;
> +
> +            while (*compatible) {
> +                free(*compatible);
> +                compatible++;
> +            }
> +
> +            free(device->deviceinfo.platform->compatible);
> +        }
> +    }
> +}
> +
> +static void drmFreeHost1xDevice(drmDevicePtr device)
> +{
> +    if (device->deviceinfo.host1x) {
> +        if (device->deviceinfo.host1x->compatible) {
> +            char **compatible = device->deviceinfo.host1x->compatible;
> +
> +            while (*compatible) {
> +                free(*compatible);
> +                compatible++;
> +            }
> +
> +            free(device->deviceinfo.host1x->compatible);
> +        }
> +    }
> +}
> +
>  void drmFreeDevice(drmDevicePtr *device)
>  {
>      if (device == NULL)
>          return;
>  
> +    if (*device) {
> +        switch ((*device)->bustype) {
> +        case DRM_BUS_PLATFORM:
> +            drmFreePlatformDevice(*device);
> +            break;
> +
> +        case DRM_BUS_HOST1X:
> +            drmFreeHost1xDevice(*device);
> +            break;
> +        }
> +    }
> +
>      free(*device);
>      *device = NULL;
>  }
> @@ -3393,6 +3449,220 @@ free_device:
>      return ret;
>  }
>  
> +static int drmParsePlatformBusInfo(int maj, int min, drmPlatformBusInfoPtr info)
> +{
> +#ifdef __linux__
> +    char path[PATH_MAX + 1], *name;
> +
> +    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
> +
> +    name = sysfs_uevent_get(path, "OF_FULLNAME");
> +    if (!name)
> +        return -ENOENT;
> +
> +    strncpy(info->fullname, name, DRM_PLATFORM_DEVICE_NAME_LEN);
> +    info->fullname[DRM_PLATFORM_DEVICE_NAME_LEN - 1] = '\0';
> +    free(name);
> +
> +    return 0;
> +#else
> +#warning "Missing implementation of drmParsePlatformBusInfo"
> +    return -EINVAL;
> +#endif
> +}
> +
> +static int drmParsePlatformDeviceInfo(int maj, int min,
> +                                      drmPlatformDeviceInfoPtr info)
> +{
> +#ifdef __linux__
> +    char path[PATH_MAX + 1], *value;
> +    unsigned int count, i;
> +    int err;
> +
> +    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
> +
> +    value = sysfs_uevent_get(path, "OF_COMPATIBLE_N");
> +    if (!value)
> +        return -ENOENT;
> +
> +    sscanf(value, "%u", &count);
> +    free(value);
> +
> +    info->compatible = calloc(count + 1, sizeof(*info->compatible));
> +    if (!info->compatible)
> +        return -ENOMEM;
> +
> +    for (i = 0; i < count; i++) {
> +        value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i);
> +        if (!value) {
> +            err = -ENOENT;
> +            goto free;
> +        }
> +
> +        info->compatible[i] = value;
> +    }
> +
> +    return 0;
> +
> +free:
> +    while (i--)
> +        free(info->compatible[i]);
> +
> +    free(info->compatible);
> +    return err;
> +#else
> +#warning "Missing implementation of drmParsePlatformDeviceInfo"
> +    return -EINVAL;
> +#endif
> +}
> +
> +static int drmProcessPlatformDevice(drmDevicePtr *device,
> +                                    const char *node, int node_type,
> +                                    int maj, int min, bool fetch_deviceinfo,
> +                                    uint32_t flags)
> +{
> +    drmDevicePtr dev;
> +    char *ptr;
> +    int ret;
> +
> +    dev = drmDeviceAlloc(node_type, node, sizeof(drmPlatformBusInfo),
> +                         sizeof(drmPlatformDeviceInfo), &ptr);
> +    if (!dev)
> +        return -ENOMEM;
> +
> +    dev->bustype = DRM_BUS_PLATFORM;
> +
> +    dev->businfo.platform = (drmPlatformBusInfoPtr)ptr;
> +
> +    ret = drmParsePlatformBusInfo(maj, min, dev->businfo.platform);
> +    if (ret < 0)
> +        goto free_device;
> +
> +    if (fetch_deviceinfo) {
> +        ptr += sizeof(drmPlatformBusInfo);
> +        dev->deviceinfo.platform = (drmPlatformDeviceInfoPtr)ptr;
> +
> +        ret = drmParsePlatformDeviceInfo(maj, min, dev->deviceinfo.platform);
> +        if (ret < 0)
> +            goto free_device;
> +    }
> +
> +    *device = dev;
> +
> +    return 0;
> +
> +free_device:
> +    free(dev);
> +    return ret;
> +}
> +
> +static int drmParseHost1xBusInfo(int maj, int min, drmHost1xBusInfoPtr info)
> +{
> +#ifdef __linux__
> +    char path[PATH_MAX + 1], *name;
> +
> +    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
> +
> +    name = sysfs_uevent_get(path, "OF_FULLNAME");
> +    if (!name)
> +        return -ENOENT;
> +
> +    strncpy(info->fullname, name, DRM_HOST1X_DEVICE_NAME_LEN);
> +    info->fullname[DRM_HOST1X_DEVICE_NAME_LEN - 1] = '\0';
> +    free(name);
> +
> +    return 0;
> +#else
> +#warning "Missing implementation of drmParseHost1xBusInfo"
> +    return -EINVAL;
> +#endif
> +}
> +
> +static int drmParseHost1xDeviceInfo(int maj, int min,
> +                                    drmHost1xDeviceInfoPtr info)
> +{
> +#ifdef __linux__
> +    char path[PATH_MAX + 1], *value;
> +    unsigned int count, i;
> +    int err;
> +
> +    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
> +
> +    value = sysfs_uevent_get(path, "OF_COMPATIBLE_N");
> +    if (!value)
> +        return -ENOENT;
> +
> +    sscanf(value, "%u", &count);
> +    free(value);
> +
> +    info->compatible = calloc(count + 1, sizeof(*info->compatible));
> +    if (!info->compatible)
> +        return -ENOMEM;
> +
> +    for (i = 0; i < count; i++) {
> +        value = sysfs_uevent_get(path, "OF_COMPATIBLE_%u", i);
> +        if (!value) {
> +            err = -ENOENT;
> +            goto free;
> +        }
> +
> +        info->compatible[i] = value;
> +    }
> +
> +    return 0;
> +
> +free:
> +    while (i--)
> +        free(info->compatible[i]);
> +
> +    free(info->compatible);
> +    return err;
> +#else
> +#warning "Missing implementation of drmParseHost1xDeviceInfo"
> +    return -EINVAL;
> +#endif
> +}
> +
> +static int drmProcessHost1xDevice(drmDevicePtr *device,
> +                                  const char *node, int node_type,
> +                                  int maj, int min, bool fetch_deviceinfo,
> +                                  uint32_t flags)
> +{
> +    drmDevicePtr dev;
> +    char *ptr;
> +    int ret;
> +
> +    dev = drmDeviceAlloc(node_type, node, sizeof(drmHost1xBusInfo),
> +                         sizeof(drmHost1xDeviceInfo), &ptr);
> +    if (!dev)
> +        return -ENOMEM;
> +
> +    dev->bustype = DRM_BUS_HOST1X;
> +
> +    dev->businfo.host1x = (drmHost1xBusInfoPtr)ptr;
> +
> +    ret = drmParseHost1xBusInfo(maj, min, dev->businfo.host1x);
> +    if (ret < 0)
> +        goto free_device;
> +
> +    if (fetch_deviceinfo) {
> +        ptr += sizeof(drmHost1xBusInfo);
> +        dev->deviceinfo.host1x = (drmHost1xDeviceInfoPtr)ptr;
> +
> +        ret = drmParseHost1xDeviceInfo(maj, min, dev->deviceinfo.host1x);
> +        if (ret < 0)
> +            goto free_device;
> +    }
> +
> +    *device = dev;
> +

do you assume that fetch_deviceinfo may change dev ?

re,
 wh

> +    return 0;
> +
> +free_device:
> +    free(dev);
> +    return ret;
> +}
> +
>  /* Consider devices located on the same bus as duplicate and fold the respective
>   * entries into a single one.
>   *
> @@ -3576,6 +3846,20 @@ int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
>  
>              break;
>  
> +        case DRM_BUS_PLATFORM:
> +            ret = drmProcessPlatformDevice(&d, node, node_type, maj, min, true, flags);
> +            if (ret)
> +                goto free_devices;
> +
> +            break;
> +
> +        case DRM_BUS_HOST1X:
> +            ret = drmProcessHost1xDevice(&d, node, node_type, maj, min, true, flags);
> +            if (ret)
> +                goto free_devices;
> +
> +            break;
> +
>          default:
>              continue;
>          }
> @@ -3716,6 +4000,22 @@ int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices)
>  
>              break;
>  
> +        case DRM_BUS_PLATFORM:
> +            ret = drmProcessPlatformDevice(&device, node, node_type, maj, min,
> +                                           devices != NULL, flags);
> +            if (ret)
> +                goto free_devices;
> +
> +            break;
> +
> +        case DRM_BUS_HOST1X:
> +            ret = drmProcessHost1xDevice(&device, node, node_type, maj, min,
> +                                         devices != NULL, flags);
> +            if (ret)
> +                goto free_devices;
> +
> +            break;
> +
>          default:
>              continue;
>          }
> diff --git a/xf86drm.h b/xf86drm.h
> index 65d5321950fc..0d927018f1f7 100644
> --- a/xf86drm.h
> +++ b/xf86drm.h
> @@ -766,8 +766,10 @@ extern int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle);
>  extern char *drmGetPrimaryDeviceNameFromFd(int fd);
>  extern char *drmGetRenderDeviceNameFromFd(int fd);
>  
> -#define DRM_BUS_PCI   0
> -#define DRM_BUS_USB   1
> +#define DRM_BUS_PCI       0
> +#define DRM_BUS_USB       1
> +#define DRM_BUS_PLATFORM  2
> +#define DRM_BUS_HOST1X    3
>  
>  typedef struct _drmPciBusInfo {
>      uint16_t domain;
> @@ -794,6 +796,26 @@ typedef struct _drmUsbDeviceInfo {
>      uint16_t product;
>  } drmUsbDeviceInfo, *drmUsbDeviceInfoPtr;
>  
> +#define DRM_PLATFORM_DEVICE_NAME_LEN 512
> +
> +typedef struct _drmPlatformBusInfo {
> +    char fullname[DRM_PLATFORM_DEVICE_NAME_LEN];
> +} drmPlatformBusInfo, *drmPlatformBusInfoPtr;
> +
> +typedef struct _drmPlatformDeviceInfo {
> +    char **compatible; /* NULL terminated list of compatible strings */
> +} drmPlatformDeviceInfo, *drmPlatformDeviceInfoPtr;
> +
> +#define DRM_HOST1X_DEVICE_NAME_LEN 512
> +
> +typedef struct _drmHost1xBusInfo {
> +    char fullname[DRM_HOST1X_DEVICE_NAME_LEN];
> +} drmHost1xBusInfo, *drmHost1xBusInfoPtr;
> +
> +typedef struct _drmHost1xDeviceInfo {
> +    char **compatible; /* NULL terminated list of compatible strings */
> +} drmHost1xDeviceInfo, *drmHost1xDeviceInfoPtr;
> +
>  typedef struct _drmDevice {
>      char **nodes; /* DRM_NODE_MAX sized array */
>      int available_nodes; /* DRM_NODE_* bitmask */
> @@ -801,10 +823,14 @@ typedef struct _drmDevice {
>      union {
>          drmPciBusInfoPtr pci;
>          drmUsbBusInfoPtr usb;
> +        drmPlatformBusInfoPtr platform;
> +        drmHost1xBusInfoPtr host1x;
>      } businfo;
>      union {
>          drmPciDeviceInfoPtr pci;
>          drmUsbDeviceInfoPtr usb;
> +        drmPlatformDeviceInfoPtr platform;
> +        drmHost1xDeviceInfoPtr host1x;
>      } deviceinfo;
>  } drmDevice, *drmDevicePtr;
>  


More information about the xorg-devel mailing list