All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH libdrm v2 0/4] xf86drm: Add USB, platform and host1x bus support
@ 2017-01-12 22:04 Thierry Reding
  2017-01-12 22:04 ` [PATCH libdrm v2 1/4] xf86drm: Factor out drmDeviceAlloc() Thierry Reding
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Thierry Reding @ 2017-01-12 22:04 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: xorg-devel-go0+a7rfsptAfugRpC6u6w

From: Thierry Reding <treding@nvidia.com>

This series enables support for USB, platform and host1x busses in the
drmDevice infrastructure. The goal is to make use of these in Mesa for PRIME
support (via the DRI_PRIME environment variable) for devices on one of these
busses.

Changes in v2:
- add USB, platform and host1x bus support to tests/drmdevice
- make sure not to overflow path names and device fullnames
- read compatible strings into platform/host1x device info

I've tested both platform and host1x bus support on Tegra and also verified
that there aren't any leaks by running tests/drmdevice through valgrind.

Since I don't have any UDL devices myself I'm adding the X.Org development
mailing list on Cc, as suggested by Emil Velikov, in the hopes that someone
with access to that hardware will be generous enough to give these a run.

Thierry

Thierry Reding (4):
  xf86drm: Factor out drmDeviceAlloc()
  xf86drm: Add USB support
  xf86drm: Add platform and host1x bus support
  tests/drmdevice: Add USB, platform and host1x support

 tests/drmdevice.c |  37 ++++
 xf86drm.c         | 521 +++++++++++++++++++++++++++++++++++++++++++++++++++---
 xf86drm.h         |  41 ++++-
 3 files changed, 571 insertions(+), 28 deletions(-)

-- 
2.11.0

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH libdrm v2 1/4] xf86drm: Factor out drmDeviceAlloc()
  2017-01-12 22:04 [PATCH libdrm v2 0/4] xf86drm: Add USB, platform and host1x bus support Thierry Reding
@ 2017-01-12 22:04 ` Thierry Reding
       [not found] ` <20170112220429.28139-1-thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2017-01-12 22:04 ` [PATCH libdrm v2 3/4] xf86drm: Add platform and host1x bus support Thierry Reding
  2 siblings, 0 replies; 8+ messages in thread
From: Thierry Reding @ 2017-01-12 22:04 UTC (permalink / raw)
  To: dri-devel; +Cc: xorg-devel

From: Thierry Reding <treding@nvidia.com>

Subsequent patches will add support for other bus types to drmDevice and
they will duplicate a lot of the code to allocate a drmDevice. Factor
out the common code so it can be reused.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 xf86drm.c | 78 +++++++++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 51 insertions(+), 27 deletions(-)

diff --git a/xf86drm.c b/xf86drm.c
index b8b2cfe5412b..c123650a1e23 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -3157,57 +3157,81 @@ void drmFreeDevices(drmDevicePtr devices[], int count)
             drmFreeDevice(&devices[i]);
 }
 
+static drmDevicePtr drmDeviceAlloc(unsigned int type, const char *node,
+                                   size_t bus_size, size_t device_size,
+                                   char **ptrp)
+{
+    size_t max_node_length, extra, size;
+    drmDevicePtr device;
+    unsigned int i;
+    char *ptr;
+
+    max_node_length = ALIGN(drmGetMaxNodeName(), sizeof(void *));
+    extra = DRM_NODE_MAX * (sizeof(void *) + max_node_length);
+
+    size = sizeof(*device) + extra + bus_size + device_size;
+
+    device = calloc(1, size);
+    if (!device)
+        return NULL;
+
+    device->available_nodes = 1 << type;
+
+    ptr = (char *)device + sizeof(*device);
+    device->nodes = (char **)ptr;
+
+    ptr += DRM_NODE_MAX * sizeof(void *);
+
+    for (i = 0; i < DRM_NODE_MAX; i++) {
+        device->nodes[i] = ptr;
+        ptr += max_node_length;
+    }
+
+    memcpy(device->nodes[type], node, max_node_length);
+
+    *ptrp = ptr;
+
+    return device;
+}
+
 static int drmProcessPciDevice(drmDevicePtr *device,
                                const char *node, int node_type,
                                int maj, int min, bool fetch_deviceinfo,
                                uint32_t flags)
 {
-    const int max_node_str = ALIGN(drmGetMaxNodeName(), sizeof(void *));
-    int ret, i;
+    drmDevicePtr dev;
     char *addr;
+    int ret;
 
-    *device = calloc(1, sizeof(drmDevice) +
-                     (DRM_NODE_MAX * (sizeof(void *) + max_node_str)) +
-                     sizeof(drmPciBusInfo) +
-                     sizeof(drmPciDeviceInfo));
-    if (!*device)
+    dev = drmDeviceAlloc(node_type, node, sizeof(drmPciBusInfo),
+                         sizeof(drmPciDeviceInfo), &addr);
+    if (!dev)
         return -ENOMEM;
 
-    addr = (char*)*device;
+    dev->bustype = DRM_BUS_PCI;
 
-    (*device)->bustype = DRM_BUS_PCI;
-    (*device)->available_nodes = 1 << node_type;
+    dev->businfo.pci = (drmPciBusInfoPtr)addr;
 
-    addr += sizeof(drmDevice);
-    (*device)->nodes = (char**)addr;
-
-    addr += DRM_NODE_MAX * sizeof(void *);
-    for (i = 0; i < DRM_NODE_MAX; i++) {
-        (*device)->nodes[i] = addr;
-        addr += max_node_str;
-    }
-    memcpy((*device)->nodes[node_type], node, max_node_str);
-
-    (*device)->businfo.pci = (drmPciBusInfoPtr)addr;
-
-    ret = drmParsePciBusInfo(maj, min, (*device)->businfo.pci);
+    ret = drmParsePciBusInfo(maj, min, dev->businfo.pci);
     if (ret)
         goto free_device;
 
     // Fetch the device info if the user has requested it
     if (fetch_deviceinfo) {
         addr += sizeof(drmPciBusInfo);
-        (*device)->deviceinfo.pci = (drmPciDeviceInfoPtr)addr;
+        dev->deviceinfo.pci = (drmPciDeviceInfoPtr)addr;
 
-        ret = drmParsePciDeviceInfo(maj, min, (*device)->deviceinfo.pci, flags);
+        ret = drmParsePciDeviceInfo(maj, min, dev->deviceinfo.pci, flags);
         if (ret)
             goto free_device;
     }
+
+    *device = dev;
+
     return 0;
 
 free_device:
-    free(*device);
-    *device = NULL;
+    free(dev);
     return ret;
 }
 
-- 
2.11.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH libdrm v2 2/4] xf86drm: Add USB support
       [not found] ` <20170112220429.28139-1-thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2017-01-12 22:04   ` Thierry Reding
       [not found]     ` <20170112220429.28139-3-thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2017-01-12 22:04   ` [PATCH libdrm v2 4/4] tests/drmdevice: Add USB, platform and host1x support Thierry Reding
  1 sibling, 1 reply; 8+ messages in thread
From: Thierry Reding @ 2017-01-12 22:04 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: Thierry Reding, xorg-devel-go0+a7rfsptAfugRpC6u6w

Allow DRM/KMS devices hosted on USB to be detected by the drmDevice
infrastructure.

v2:
- make sysfs_uevent_get() more flexible using a format string

Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
---
 xf86drm.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 xf86drm.h |  13 +++++
 2 files changed, 176 insertions(+)

diff --git a/xf86drm.c b/xf86drm.c
index c123650a1e23..27cd6eb5193e 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -2906,6 +2906,9 @@ static int drmParseSubsystemType(int maj, int min)
     if (strncmp(name, "/pci", 4) == 0)
         return DRM_BUS_PCI;
 
+    if (strncmp(name, "/usb", 4) == 0)
+        return DRM_BUS_USB;
+
     return -EINVAL;
 #elif defined(__OpenBSD__)
     return DRM_BUS_PCI;
@@ -2992,6 +2995,10 @@ static int drmCompareBusInfo(drmDevicePtr a, drmDevicePtr b)
     switch (a->bustype) {
     case DRM_BUS_PCI:
         return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo));
+
+    case DRM_BUS_USB:
+        return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo));
+
     default:
         break;
     }
@@ -3235,6 +3242,145 @@ free_device:
     return ret;
 }
 
+static char * DRM_PRINTFLIKE(2, 3)
+sysfs_uevent_get(const char *path, const char *fmt, ...)
+{
+    char filename[PATH_MAX + 1], *key, *line = NULL, *value = NULL;
+    size_t size = 0, len;
+    ssize_t num;
+    va_list ap;
+    FILE *fp;
+
+    va_start(ap, fmt);
+    num = vasprintf(&key, fmt, ap);
+    va_end(ap);
+    len = num;
+
+    snprintf(filename, sizeof(filename), "%s/uevent", path);
+
+    fp = fopen(filename, "r");
+    if (!fp) {
+        free(key);
+        return NULL;
+    }
+
+    while ((num = getline(&line, &size, fp)) >= 0) {
+        if ((strncmp(line, key, len) == 0) && (line[len] == '=')) {
+            char *start = line + len + 1, *end = line + num - 1;
+
+            if (*end != '\n')
+                end++;
+
+            value = strndup(start, end - start);
+            break;
+        }
+    }
+
+    free(line);
+    fclose(fp);
+
+    free(key);
+
+    return value;
+}
+
+static int drmParseUsbBusInfo(int maj, int min, drmUsbBusInfoPtr info)
+{
+    char path[PATH_MAX + 1], *value;
+    unsigned int bus, dev;
+    int ret;
+
+    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+
+    value = sysfs_uevent_get(path, "BUSNUM");
+    if (!value)
+        return -ENOENT;
+
+    ret = sscanf(value, "%03u", &bus);
+    free(value);
+
+    if (ret <= 0)
+        return -errno;
+
+    value = sysfs_uevent_get(path, "DEVNUM");
+    if (!value)
+        return -ENOENT;
+
+    ret = sscanf(value, "%03u", &dev);
+    free(value);
+
+    if (ret <= 0)
+        return -errno;
+
+    info->bus = bus;
+    info->dev = dev;
+
+    return 0;
+}
+
+static int drmParseUsbDeviceInfo(int maj, int min, drmUsbDeviceInfoPtr info)
+{
+    char path[PATH_MAX + 1], *value;
+    unsigned int vendor, product;
+    int ret;
+
+    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
+
+    value = sysfs_uevent_get(path, "PRODUCT");
+    if (!value)
+        return -ENOENT;
+
+    ret = sscanf(value, "%x/%x", &vendor, &product);
+    free(value);
+
+    if (ret <= 0)
+        return -errno;
+
+    info->vendor = vendor;
+    info->product = product;
+
+    return 0;
+}
+
+static int drmProcessUsbDevice(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(drmUsbBusInfo),
+                         sizeof(drmUsbDeviceInfo), &ptr);
+    if (!dev)
+        return -ENOMEM;
+
+    dev->bustype = DRM_BUS_USB;
+
+    dev->businfo.usb = (drmUsbBusInfoPtr)ptr;
+
+    ret = drmParseUsbBusInfo(maj, min, dev->businfo.usb);
+    if (ret < 0)
+        goto free_device;
+
+    if (fetch_deviceinfo) {
+        ptr += sizeof(drmUsbBusInfo);
+        dev->deviceinfo.usb = (drmUsbDeviceInfoPtr)ptr;
+
+        ret = drmParseUsbDeviceInfo(maj, min, dev->deviceinfo.usb);
+        if (ret < 0)
+            goto free_device;
+    }
+
+    *device = dev;
+
+    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.
  *
@@ -3410,6 +3556,14 @@ int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
                 continue;
 
             break;
+
+        case DRM_BUS_USB:
+            ret = drmProcessUsbDevice(&d, node, node_type, maj, min, true, flags);
+            if (ret)
+                goto free_devices;
+
+            break;
+
         default:
             continue;
         }
@@ -3541,6 +3695,15 @@ int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices)
                 continue;
 
             break;
+
+        case DRM_BUS_USB:
+            ret = drmProcessUsbDevice(&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 b340fc46cd44..65d5321950fc 100644
--- a/xf86drm.h
+++ b/xf86drm.h
@@ -767,6 +767,7 @@ extern char *drmGetPrimaryDeviceNameFromFd(int fd);
 extern char *drmGetRenderDeviceNameFromFd(int fd);
 
 #define DRM_BUS_PCI   0
+#define DRM_BUS_USB   1
 
 typedef struct _drmPciBusInfo {
     uint16_t domain;
@@ -783,15 +784,27 @@ typedef struct _drmPciDeviceInfo {
     uint8_t revision_id;
 } drmPciDeviceInfo, *drmPciDeviceInfoPtr;
 
+typedef struct _drmUsbBusInfo {
+    uint8_t bus;
+    uint8_t dev;
+} drmUsbBusInfo, *drmUsbBusInfoPtr;
+
+typedef struct _drmUsbDeviceInfo {
+    uint16_t vendor;
+    uint16_t product;
+} drmUsbDeviceInfo, *drmUsbDeviceInfoPtr;
+
 typedef struct _drmDevice {
     char **nodes; /* DRM_NODE_MAX sized array */
     int available_nodes; /* DRM_NODE_* bitmask */
     int bustype;
     union {
         drmPciBusInfoPtr pci;
+        drmUsbBusInfoPtr usb;
     } businfo;
     union {
         drmPciDeviceInfoPtr pci;
+        drmUsbDeviceInfoPtr usb;
     } deviceinfo;
 } drmDevice, *drmDevicePtr;
 
-- 
2.11.0

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH libdrm v2 3/4] xf86drm: Add platform and host1x bus support
  2017-01-12 22:04 [PATCH libdrm v2 0/4] xf86drm: Add USB, platform and host1x bus support Thierry Reding
  2017-01-12 22:04 ` [PATCH libdrm v2 1/4] xf86drm: Factor out drmDeviceAlloc() Thierry Reding
       [not found] ` <20170112220429.28139-1-thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2017-01-12 22:04 ` Thierry Reding
  2 siblings, 0 replies; 8+ messages in thread
From: Thierry Reding @ 2017-01-12 22:04 UTC (permalink / raw)
  To: dri-devel; +Cc: xorg-devel

From: Thierry Reding <treding@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.

v2:
- be careful not to overflow the full name
- read compatible strings into device info

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 xf86drm.c | 280 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 xf86drm.h |  30 ++++++-
 2 files changed, 308 insertions(+), 2 deletions(-)

diff --git a/xf86drm.c b/xf86drm.c
index 27cd6eb5193e..69e1ecd47be3 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -2909,6 +2909,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;
@@ -2999,6 +3005,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;
     }
@@ -3143,11 +3155,55 @@ static int drmParsePciDeviceInfo(int maj, int min,
 #endif
 }
 
+static void drmFreePlatformDevice(drmDevicePtr device)
+{
+    if (device->deviceinfo.platform) {
+        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;
 }
@@ -3381,6 +3437,200 @@ free_device:
     return ret;
 }
 
+static int drmParsePlatformBusInfo(int maj, int min, drmPlatformBusInfoPtr info)
+{
+    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;
+}
+
+static int drmParsePlatformDeviceInfo(int maj, int min,
+                                      drmPlatformDeviceInfoPtr info)
+{
+    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;
+}
+
+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)
+{
+    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;
+}
+
+static int drmParseHost1xDeviceInfo(int maj, int min,
+                                    drmHost1xDeviceInfoPtr info)
+{
+    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;
+}
+
+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;
+
+    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.
  *
@@ -3564,6 +3814,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;
         }
@@ -3704,6 +3968,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;
 
-- 
2.11.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH libdrm v2 4/4] tests/drmdevice: Add USB, platform and host1x support
       [not found] ` <20170112220429.28139-1-thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  2017-01-12 22:04   ` [PATCH libdrm v2 2/4] xf86drm: Add USB support Thierry Reding
@ 2017-01-12 22:04   ` Thierry Reding
  1 sibling, 0 replies; 8+ messages in thread
From: Thierry Reding @ 2017-01-12 22:04 UTC (permalink / raw)
  To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
  Cc: xorg-devel-go0+a7rfsptAfugRpC6u6w

From: Thierry Reding <treding@nvidia.com>

Extend the drmdevice test with support for the newly added USB, platform
and host1x busses.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 tests/drmdevice.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/tests/drmdevice.c b/tests/drmdevice.c
index 8c4f091a9972..9dd5098a211f 100644
--- a/tests/drmdevice.c
+++ b/tests/drmdevice.c
@@ -62,6 +62,43 @@ print_device_info(drmDevicePtr device, int i, bool print_revision)
         else
             printf("\t\t\trevision_id\tIGNORED\n");
 
+    } else if (device->bustype == DRM_BUS_USB) {
+        printf("\t\tusb\n");
+        printf("\t\t\tbus\t%03u\n", device->businfo.usb->bus);
+        printf("\t\t\tdev\t%03u\n", device->businfo.usb->dev);
+
+        printf("\tdeviceinfo\n");
+        printf("\t\tusb\n");
+        printf("\t\t\tvendor\t%04x\n", device->deviceinfo.usb->vendor);
+        printf("\t\t\tproduct\t%04x\n", device->deviceinfo.usb->product);
+    } else if (device->bustype == DRM_BUS_PLATFORM) {
+        char **compatible = device->deviceinfo.platform->compatible;
+
+        printf("\t\tplatform\n");
+        printf("\t\t\tfullname\t%s\n", device->businfo.platform->fullname);
+
+        printf("\tdeviceinfo\n");
+        printf("\t\tplatform\n");
+        printf("\t\t\tcompatible\n");
+
+        while (*compatible) {
+            printf("\t\t\t\t%s\n", *compatible);
+            compatible++;
+        }
+    } else if (device->bustype == DRM_BUS_HOST1X) {
+        char **compatible = device->deviceinfo.platform->compatible;
+
+        printf("\t\thost1x\n");
+        printf("\t\t\tfullname\t%s\n", device->businfo.host1x->fullname);
+
+        printf("\tdeviceinfo\n");
+        printf("\t\tplatform\n");
+        printf("\t\t\tcompatible\n");
+
+        while (*compatible) {
+            printf("\t\t\t\t%s\n", *compatible);
+            compatible++;
+        }
     } else {
         printf("Unknown/unhandled bustype\n");
     }
-- 
2.11.0

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH libdrm v2 2/4] xf86drm: Add USB support
       [not found]     ` <20170112220429.28139-3-thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
@ 2017-01-13 12:11       ` Mark Kettenis
  2017-01-16 14:38         ` Emil Velikov
  0 siblings, 1 reply; 8+ messages in thread
From: Mark Kettenis @ 2017-01-13 12:11 UTC (permalink / raw)
  Cc: thierry.reding-Re5JQEeQqe8AvxtiuMwx3w,
	xorg-devel-go0+a7rfsptAfugRpC6u6w,
	dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW

> From: Thierry Reding <thierry.reding@gmail.com>
> Date: Thu, 12 Jan 2017 23:04:27 +0100
> 
> Allow DRM/KMS devices hosted on USB to be detected by the drmDevice
> infrastructure.
> 
> v2:
> - make sysfs_uevent_get() more flexible using a format string
> 
> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>

All this sysfs parsing stuff is highly Linux-specific and should
probably be #ifdef __linux__.  Returning -EINVAL on non-Linux
platforms for usb and host1x should be fine.

Cheers,

Mark

> ---
>  xf86drm.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  xf86drm.h |  13 +++++
>  2 files changed, 176 insertions(+)
> 
> diff --git a/xf86drm.c b/xf86drm.c
> index c123650a1e23..27cd6eb5193e 100644
> --- a/xf86drm.c
> +++ b/xf86drm.c
> @@ -2906,6 +2906,9 @@ static int drmParseSubsystemType(int maj, int min)
>      if (strncmp(name, "/pci", 4) == 0)
>          return DRM_BUS_PCI;
>  
> +    if (strncmp(name, "/usb", 4) == 0)
> +        return DRM_BUS_USB;
> +
>      return -EINVAL;
>  #elif defined(__OpenBSD__)
>      return DRM_BUS_PCI;
> @@ -2992,6 +2995,10 @@ static int drmCompareBusInfo(drmDevicePtr a, drmDevicePtr b)
>      switch (a->bustype) {
>      case DRM_BUS_PCI:
>          return memcmp(a->businfo.pci, b->businfo.pci, sizeof(drmPciBusInfo));
> +
> +    case DRM_BUS_USB:
> +        return memcmp(a->businfo.usb, b->businfo.usb, sizeof(drmUsbBusInfo));
> +
>      default:
>          break;
>      }
> @@ -3235,6 +3242,145 @@ free_device:
>      return ret;
>  }
>  
> +static char * DRM_PRINTFLIKE(2, 3)
> +sysfs_uevent_get(const char *path, const char *fmt, ...)
> +{
> +    char filename[PATH_MAX + 1], *key, *line = NULL, *value = NULL;
> +    size_t size = 0, len;
> +    ssize_t num;
> +    va_list ap;
> +    FILE *fp;
> +
> +    va_start(ap, fmt);
> +    num = vasprintf(&key, fmt, ap);
> +    va_end(ap);
> +    len = num;
> +
> +    snprintf(filename, sizeof(filename), "%s/uevent", path);
> +
> +    fp = fopen(filename, "r");
> +    if (!fp) {
> +        free(key);
> +        return NULL;
> +    }
> +
> +    while ((num = getline(&line, &size, fp)) >= 0) {
> +        if ((strncmp(line, key, len) == 0) && (line[len] == '=')) {
> +            char *start = line + len + 1, *end = line + num - 1;
> +
> +            if (*end != '\n')
> +                end++;
> +
> +            value = strndup(start, end - start);
> +            break;
> +        }
> +    }
> +
> +    free(line);
> +    fclose(fp);
> +
> +    free(key);
> +
> +    return value;
> +}
> +
> +static int drmParseUsbBusInfo(int maj, int min, drmUsbBusInfoPtr info)
> +{
> +    char path[PATH_MAX + 1], *value;
> +    unsigned int bus, dev;
> +    int ret;
> +
> +    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
> +
> +    value = sysfs_uevent_get(path, "BUSNUM");
> +    if (!value)
> +        return -ENOENT;
> +
> +    ret = sscanf(value, "%03u", &bus);
> +    free(value);
> +
> +    if (ret <= 0)
> +        return -errno;
> +
> +    value = sysfs_uevent_get(path, "DEVNUM");
> +    if (!value)
> +        return -ENOENT;
> +
> +    ret = sscanf(value, "%03u", &dev);
> +    free(value);
> +
> +    if (ret <= 0)
> +        return -errno;
> +
> +    info->bus = bus;
> +    info->dev = dev;
> +
> +    return 0;
> +}
> +
> +static int drmParseUsbDeviceInfo(int maj, int min, drmUsbDeviceInfoPtr info)
> +{
> +    char path[PATH_MAX + 1], *value;
> +    unsigned int vendor, product;
> +    int ret;
> +
> +    snprintf(path, sizeof(path), "/sys/dev/char/%d:%d/device", maj, min);
> +
> +    value = sysfs_uevent_get(path, "PRODUCT");
> +    if (!value)
> +        return -ENOENT;
> +
> +    ret = sscanf(value, "%x/%x", &vendor, &product);
> +    free(value);
> +
> +    if (ret <= 0)
> +        return -errno;
> +
> +    info->vendor = vendor;
> +    info->product = product;
> +
> +    return 0;
> +}
> +
> +static int drmProcessUsbDevice(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(drmUsbBusInfo),
> +                         sizeof(drmUsbDeviceInfo), &ptr);
> +    if (!dev)
> +        return -ENOMEM;
> +
> +    dev->bustype = DRM_BUS_USB;
> +
> +    dev->businfo.usb = (drmUsbBusInfoPtr)ptr;
> +
> +    ret = drmParseUsbBusInfo(maj, min, dev->businfo.usb);
> +    if (ret < 0)
> +        goto free_device;
> +
> +    if (fetch_deviceinfo) {
> +        ptr += sizeof(drmUsbBusInfo);
> +        dev->deviceinfo.usb = (drmUsbDeviceInfoPtr)ptr;
> +
> +        ret = drmParseUsbDeviceInfo(maj, min, dev->deviceinfo.usb);
> +        if (ret < 0)
> +            goto free_device;
> +    }
> +
> +    *device = dev;
> +
> +    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.
>   *
> @@ -3410,6 +3556,14 @@ int drmGetDevice2(int fd, uint32_t flags, drmDevicePtr *device)
>                  continue;
>  
>              break;
> +
> +        case DRM_BUS_USB:
> +            ret = drmProcessUsbDevice(&d, node, node_type, maj, min, true, flags);
> +            if (ret)
> +                goto free_devices;
> +
> +            break;
> +
>          default:
>              continue;
>          }
> @@ -3541,6 +3695,15 @@ int drmGetDevices2(uint32_t flags, drmDevicePtr devices[], int max_devices)
>                  continue;
>  
>              break;
> +
> +        case DRM_BUS_USB:
> +            ret = drmProcessUsbDevice(&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 b340fc46cd44..65d5321950fc 100644
> --- a/xf86drm.h
> +++ b/xf86drm.h
> @@ -767,6 +767,7 @@ extern char *drmGetPrimaryDeviceNameFromFd(int fd);
>  extern char *drmGetRenderDeviceNameFromFd(int fd);
>  
>  #define DRM_BUS_PCI   0
> +#define DRM_BUS_USB   1
>  
>  typedef struct _drmPciBusInfo {
>      uint16_t domain;
> @@ -783,15 +784,27 @@ typedef struct _drmPciDeviceInfo {
>      uint8_t revision_id;
>  } drmPciDeviceInfo, *drmPciDeviceInfoPtr;
>  
> +typedef struct _drmUsbBusInfo {
> +    uint8_t bus;
> +    uint8_t dev;
> +} drmUsbBusInfo, *drmUsbBusInfoPtr;
> +
> +typedef struct _drmUsbDeviceInfo {
> +    uint16_t vendor;
> +    uint16_t product;
> +} drmUsbDeviceInfo, *drmUsbDeviceInfoPtr;
> +
>  typedef struct _drmDevice {
>      char **nodes; /* DRM_NODE_MAX sized array */
>      int available_nodes; /* DRM_NODE_* bitmask */
>      int bustype;
>      union {
>          drmPciBusInfoPtr pci;
> +        drmUsbBusInfoPtr usb;
>      } businfo;
>      union {
>          drmPciDeviceInfoPtr pci;
> +        drmUsbDeviceInfoPtr usb;
>      } deviceinfo;
>  } drmDevice, *drmDevicePtr;
>  
> -- 
> 2.11.0
> 
> _______________________________________________
> xorg-devel@lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: https://lists.x.org/mailman/listinfo/xorg-devel
> 
> 
_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: https://lists.x.org/mailman/listinfo/xorg-devel

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH libdrm v2 2/4] xf86drm: Add USB support
  2017-01-13 12:11       ` Mark Kettenis
@ 2017-01-16 14:38         ` Emil Velikov
  2017-01-18  8:56           ` Thierry Reding
  0 siblings, 1 reply; 8+ messages in thread
From: Emil Velikov @ 2017-01-16 14:38 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: ML xorg-devel, ML dri-devel

On 13 January 2017 at 12:11, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
>> From: Thierry Reding <thierry.reding@gmail.com>
>> Date: Thu, 12 Jan 2017 23:04:27 +0100
>>
>> Allow DRM/KMS devices hosted on USB to be detected by the drmDevice
>> infrastructure.
>>
>> v2:
>> - make sysfs_uevent_get() more flexible using a format string
>>
>> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
>
> All this sysfs parsing stuff is highly Linux-specific and should
> probably be #ifdef __linux__.  Returning -EINVAL on non-Linux
> platforms for usb and host1x should be fine.
>
Nicely spotted. Thierry with the above the series is
Reviewed-by: Emil Velikov <emil.velikov@collabora.com>

Can you land these in the next few days - I would love to have a
libdrm release and use drmGetDevice[s]2 in mesa.

Thanks
Emil
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH libdrm v2 2/4] xf86drm: Add USB support
  2017-01-16 14:38         ` Emil Velikov
@ 2017-01-18  8:56           ` Thierry Reding
  0 siblings, 0 replies; 8+ messages in thread
From: Thierry Reding @ 2017-01-18  8:56 UTC (permalink / raw)
  To: Emil Velikov; +Cc: ML xorg-devel, ML dri-devel, Mark Kettenis


[-- Attachment #1.1: Type: text/plain, Size: 1286 bytes --]

On Mon, Jan 16, 2017 at 02:38:39PM +0000, Emil Velikov wrote:
> On 13 January 2017 at 12:11, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
> >> From: Thierry Reding <thierry.reding@gmail.com>
> >> Date: Thu, 12 Jan 2017 23:04:27 +0100
> >>
> >> Allow DRM/KMS devices hosted on USB to be detected by the drmDevice
> >> infrastructure.
> >>
> >> v2:
> >> - make sysfs_uevent_get() more flexible using a format string
> >>
> >> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
> >
> > All this sysfs parsing stuff is highly Linux-specific and should
> > probably be #ifdef __linux__.  Returning -EINVAL on non-Linux
> > platforms for usb and host1x should be fine.
> >
> Nicely spotted. Thierry with the above the series is
> Reviewed-by: Emil Velikov <emil.velikov@collabora.com>
> 
> Can you land these in the next few days - I would love to have a
> libdrm release and use drmGetDevice[s]2 in mesa.

Can do. I've thrown in another cleanup patch to reuse the new
sysfs_uevent_get() function (now also #ifdef __linux__) for the Linux-
specific PCI bus/device info. tests/drmdevice results are identical and
valgrind doesn't flag any leaks. I'll send out the series once more just
to be sure, but I think it should now be all fine.

Thanks,
Thierry

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-01-18  8:56 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-12 22:04 [PATCH libdrm v2 0/4] xf86drm: Add USB, platform and host1x bus support Thierry Reding
2017-01-12 22:04 ` [PATCH libdrm v2 1/4] xf86drm: Factor out drmDeviceAlloc() Thierry Reding
     [not found] ` <20170112220429.28139-1-thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-01-12 22:04   ` [PATCH libdrm v2 2/4] xf86drm: Add USB support Thierry Reding
     [not found]     ` <20170112220429.28139-3-thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2017-01-13 12:11       ` Mark Kettenis
2017-01-16 14:38         ` Emil Velikov
2017-01-18  8:56           ` Thierry Reding
2017-01-12 22:04   ` [PATCH libdrm v2 4/4] tests/drmdevice: Add USB, platform and host1x support Thierry Reding
2017-01-12 22:04 ` [PATCH libdrm v2 3/4] xf86drm: Add platform and host1x bus support Thierry Reding

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.