[igt-dev] [PATCH i-g-t v2 6/6] lib/igt_device_scan: Simulate udev drm and pci device events

Zbigniew Kempczyński zbigniew.kempczynski at intel.com
Tue Jul 12 09:57:07 UTC 2022


For all udev_*() calls used in device scan add its static counterparts.
Instead of transplanting real udev data structures (private ones) some
primitive replacement were added. Devices are added directly from code
- such implementation was a little bit faster than parsing some config
files (especially pci slot manipulation to provide some properties which
slightly differs).

Signed-off-by: Zbigniew Kempczyński <zbigniew.kempczynski at intel.com>
---
 lib/igt_device_scan.c          |   7 +
 lib/igt_device_scan_simulate.c | 450 +++++++++++++++++++++++++++++++++
 2 files changed, 457 insertions(+)
 create mode 100644 lib/igt_device_scan_simulate.c

diff --git a/lib/igt_device_scan.c b/lib/igt_device_scan.c
index 5566e028d1..f198070564 100644
--- a/lib/igt_device_scan.c
+++ b/lib/igt_device_scan.c
@@ -904,6 +904,13 @@ static void index_pci_devices(void)
  * Function sorts all found devices to keep same order of bus devices
  * for providing predictable search.
  */
+
+#ifdef SIMULATE_UDEV_DEVICES
+
+#include "igt_device_scan_simulate.c"
+
+#endif
+
 static void scan_drm_devices(void)
 {
 	struct udev *udev;
diff --git a/lib/igt_device_scan_simulate.c b/lib/igt_device_scan_simulate.c
new file mode 100644
index 0000000000..5108f55924
--- /dev/null
+++ b/lib/igt_device_scan_simulate.c
@@ -0,0 +1,450 @@
+/*
+ * Example: Skylake
+1656514333.437262: --------------------
+1656514333.437263: SYSPATH: /sys/devices/pci0000:00/0000:00:02.0/drm/card0
+1656514333.437294: SUBSYSTEM: drm
+1656514333.437377: prop: CURRENT_TAGS, val: :seat:mutter-device-disable-kms-modifiers:master-of-seat:uaccess:
+1656514333.437378: prop: DEVLINKS, val: /dev/dri/by-path/pci-0000:00:02.0-card
+1656514333.437378: prop: DEVNAME, val: /dev/dri/card0
+1656514333.437379: prop: DEVPATH, val: /devices/pci0000:00/0000:00:02.0/drm/card0
+1656514333.437379: prop: DEVTYPE, val: drm_minor
+1656514333.437380: prop: ID_FOR_SEAT, val: drm-pci-0000_00_02_0
+1656514333.437380: prop: ID_PATH, val: pci-0000:00:02.0
+1656514333.437382: prop: ID_PATH_TAG, val: pci-0000_00_02_0
+1656514333.437383: prop: MAJOR, val: 226
+1656514333.437383: prop: MINOR, val: 0
+1656514333.437383: prop: SUBSYSTEM, val: drm
+1656514333.437384: prop: TAGS, val: :seat:mutter-device-disable-kms-modifiers:master-of-seat:uaccess:
+1656514333.437384: prop: USEC_INITIALIZED, val: 31377470
+1656514333.438273: attr: dev, val: 226:0
+1656406120.387751: attr: subsystem, val: drm
+
+1656514333.440217: --------------------
+1656514333.440217: parent: 0000:00:02.0
+1656514333.440223: subsystem: pci
+1656514333.440224: syspath: /sys/devices/pci0000:00/0000:00:02.0
+1656514333.440297: prop: DEVPATH, val: /devices/pci0000:00/0000:00:02.0
+1656514333.440298: prop: DRIVER, val: i915
+1656514333.440298: prop: ID_MODEL_FROM_DATABASE, val: Iris Graphics 540
+1656514333.440299: prop: ID_PCI_CLASS_FROM_DATABASE, val: Display controller
+1656514333.440299: prop: ID_PCI_INTERFACE_FROM_DATABASE, val: VGA controller
+1656514333.440300: prop: ID_PCI_SUBCLASS_FROM_DATABASE, val: VGA compatible controller
+1656514333.440300: prop: ID_VENDOR_FROM_DATABASE, val: Intel Corporation
+1656514333.440301: prop: MODALIAS, val: pci:v00008086d00001926sv00008086sd00002063bc03sc00i00
+1656514333.440302: prop: PCI_CLASS, val: 30000
+1656514333.440302: prop: PCI_ID, val: 8086:1926
+1656514333.440303: prop: PCI_SLOT_NAME, val: 0000:00:02.0
+1656514333.440303: prop: PCI_SUBSYS_ID, val: 8086:2063
+1656514333.440304: prop: SUBSYSTEM, val: pci
+1656514333.440304: prop: SWITCHEROO_CONTROL_PRODUCT_NAME, val: Iris(R) Graphics 540
+1656514333.440305: prop: SWITCHEROO_CONTROL_VENDOR_NAME, val: Intel(R)
+1656514333.440306: prop: USEC_INITIALIZED, val: 6111540
+1656514333.440692: attr: class, val: 0x030000
+1656514333.440750: attr: device, val: 0x1926
+1656514333.441116: attr: subsystem, val: pci
+1656514333.441130: attr: subsystem_device, val: 0x2063
+1656514333.441141: attr: subsystem_vendor, val: 0x8086
+1656514333.441162: attr: vendor, val: 0x8086
+
+1656514333.441271: --------------------
+1656514333.441272: SYSPATH: /sys/devices/pci0000:00/0000:00:02.0/drm/renderD128
+1656514333.441305: SUBSYSTEM: drm
+1656514333.441390: prop: CURRENT_TAGS, val: :seat:mutter-device-disable-kms-modifiers:uaccess:
+1656514333.441391: prop: DEVLINKS, val: /dev/dri/by-path/pci-0000:00:02.0-render
+1656514333.441391: prop: DEVNAME, val: /dev/dri/renderD128
+1656514333.441392: prop: DEVPATH, val: /devices/pci0000:00/0000:00:02.0/drm/renderD128
+1656514333.441392: prop: DEVTYPE, val: drm_minor
+1656514333.441393: prop: ID_FOR_SEAT, val: drm-pci-0000_00_02_0
+1656514333.441393: prop: ID_PATH, val: pci-0000:00:02.0
+1656514333.441395: prop: ID_PATH_TAG, val: pci-0000_00_02_0
+1656514333.441395: prop: MAJOR, val: 226
+1656514333.441396: prop: MINOR, val: 128
+1656514333.441396: prop: SUBSYSTEM, val: drm
+1656514333.441396: prop: TAGS, val: :seat:mutter-device-disable-kms-modifiers:uaccess:
+1656514333.441397: prop: USEC_INITIALIZED, val: 31377515
+1656514333.441525: attr: dev, val: 226:128
+1656514333.441657: attr: subsystem, val: drm
+*/
+
+enum entry_type {
+	TYPE_DEVICE,
+	TYPE_PROP,
+	TYPE_ATTR,
+};
+
+struct udev_list_entry {
+	enum entry_type entry_type;
+	int curr;
+} _entry_dev, _entry_prop, _entry_attr;
+
+struct keyval {
+	char key[NAME_MAX];
+	char val[NAME_MAX];
+};
+
+#define MAXDEVS 16
+#define MAXPROPS 16
+#define MAXATTRS 8
+struct udev_device {
+	struct udev_device *parent;
+	char syspath[NAME_MAX];
+	char devnode[NAME_MAX];
+	char subsystem[8];
+	struct keyval prop[MAXPROPS];
+	struct udev_list_entry *prop_head;
+	struct keyval attr[MAXATTRS];
+	struct udev_list_entry *attr_head;
+	int props;
+	int attrs;
+};
+
+struct udev {
+	struct udev_device *dev[MAXDEVS];
+} _udev;
+
+struct udev_enumerate {
+	struct udev *udev;
+} _udev_enumerate;
+
+static void print_udev_device(const struct udev_device *dev)
+{
+//#define DEBUG_SCAN_SIMULATE
+#ifdef DEBUG_SCAN_SIMULATE
+	int i;
+
+	printf("[%s]\n", dev->syspath);
+
+	printf("props:\n");
+	for (i = 0; i < dev->props; i++)
+		printf("   %s: %s\n", dev->prop[i].key, dev->prop[i].val);
+
+	printf("attrs:\n");
+	for (i = 0; i < dev->attrs; i++)
+		printf("   %s: %s\n", dev->attr[i].key, dev->attr[i].val);
+#endif
+}
+
+#define __ADD_PROP(_dev, _key, args...) do { \
+	struct keyval *kv; \
+	igt_assert(dev->props <= MAXPROPS); \
+	kv = &(dev)->prop[(dev)->props]; \
+	strncpy(kv->key, (_key), NAME_MAX); \
+	snprintf(kv->val, NAME_MAX, args); \
+	(dev)->props++; \
+	} while (0)
+
+#define __ADD_ATTR(_dev, _key, args...) do { \
+	struct keyval *kv; \
+	igt_assert(dev->attrs <= MAXATTRS); \
+	kv = &(dev)->attr[(dev)->attrs]; \
+	strncpy(kv->key, (_key), NAME_MAX); \
+	snprintf(kv->val, NAME_MAX, args); \
+	(dev)->attrs++; \
+	} while (0)
+
+static struct udev_device *
+create_pci_udev_device(struct udev *udev,
+		       const char *syspath, const char *bdf,
+		       uint16_t vendor, uint16_t device, uint16_t subsystem)
+{
+	struct udev_device *dev;
+	char bus[13];
+
+	igt_assert(strlen(bdf) == 12);
+
+	dev = calloc(1, sizeof(*dev));
+	igt_assert(dev);
+
+	dev->parent = dev;
+	snprintf(dev->syspath, NAME_MAX, "%s", syspath);
+	strncpy(dev->subsystem, "pci", 4);
+
+	/* avoid compiler warning when copying less than 12 */
+	strncpy(bus, bdf, 13);
+	bus[7] = '\0';
+
+	__ADD_PROP(dev, "DEVPATH", "/devices/pci%s/%s", bus, bdf);
+	__ADD_PROP(dev, "DRIVER", "i915");
+	__ADD_PROP(dev, "PCI_CLASS", "30000");
+	__ADD_PROP(dev, "PCI_ID", "%04x:%04x", vendor, device);
+	__ADD_PROP(dev, "PCI_SLOT_NAME", "%s", bdf);
+	__ADD_PROP(dev, "PCI_SUBSYS_ID", "%04x:%04x", vendor, subsystem);
+	__ADD_PROP(dev, "SUBSYSTEM", "pci");
+
+	__ADD_ATTR(dev, "class", "0x030000");
+	__ADD_ATTR(dev, "device", "0x%04x", device);
+	__ADD_ATTR(dev, "subsystem", "pci");
+	__ADD_ATTR(dev, "subsystem_device", "0x%04x", subsystem);
+	__ADD_ATTR(dev, "subsystem_vendor", "0x%04x", vendor);
+	__ADD_ATTR(dev, "vendor", "0x%04x", vendor);
+
+	return dev;
+}
+
+static struct udev_device *
+create_drm_udev_device(struct udev *udev, struct udev_device *parent,
+		       const char *syspath, const char *bdf, int card,
+		       int major, int minor)
+{
+	struct udev_device *dev;
+	const char *name = card < 128 ? "card" : "render";
+	const char *drmname = card < 128 ? "card" : "renderD";
+	char bus[13];
+
+	igt_assert(strlen(bdf) == 12);
+
+	dev = calloc(1, sizeof(*dev));
+	igt_assert(dev);
+
+	dev->parent = parent;
+	snprintf(dev->syspath, NAME_MAX, "%s", syspath);
+	strncpy(dev->subsystem, "drm", 4);
+	snprintf(dev->devnode, NAME_MAX, "/dev/dri/%s%d", drmname, card);
+
+	/* avoid compiler warning when copying less than 12 */
+	strncpy(bus, bdf, 13);
+	bus[7] = '\0';
+
+	__ADD_PROP(dev, "DEVLINKS", "/dev/dri/by-path/pci-%s-%s", bdf, name);
+	__ADD_PROP(dev, "DEVNAME", "/dev/dri/%s%d", drmname, card);
+	__ADD_PROP(dev, "DEVPATH", "/devices/pci%s/%s/drm/%s%d", bus, bdf,
+		   drmname, card);
+	__ADD_PROP(dev, "DEVTYPE", "drm_minor");
+	__ADD_PROP(dev, "ID_PATH", "pci-%s", bdf);
+	__ADD_PROP(dev, "MAJOR", "%d", major);
+	__ADD_PROP(dev, "MINOR", "%d", minor);
+	__ADD_PROP(dev, "SUBSYSTEM", "drm");
+
+	__ADD_ATTR(dev, "dev", "%d:%d", major, minor);
+	__ADD_ATTR(dev, "subsystem", "drm");
+
+	return dev;
+}
+
+static struct udev_device **add_intel_dev(struct udev *udev, struct udev_device **dev,
+					  const char *pci_slot, uint16_t pci_device)
+{
+	struct udev_device **parent;
+	char bd[13], path[NAME_MAX];
+	static int card;
+
+	strncpy(bd, pci_slot, 13);
+	bd[7] = 0;
+
+	parent = dev;
+
+	snprintf(path, NAME_MAX, "/sys/devices/pci%s/%s", bd, pci_slot);
+	*dev++ = create_pci_udev_device(udev, path, pci_slot,
+					0x8086, pci_device, 0x2063);
+
+	snprintf(path, NAME_MAX, "/sys/devices/pci%s/%s/drm/card%d",
+		 bd, pci_slot, card);
+	*dev++ = create_drm_udev_device(udev, *parent, path, pci_slot,
+					card, 226, card);
+
+	snprintf(path, NAME_MAX, "/sys/devices/pci%s/%s/drm/renderD%d",
+		 bd, pci_slot, card + 128);
+	*dev++ = create_drm_udev_device(udev, *parent, path, pci_slot,
+					card + 128, 226, card + 128);
+
+	card++;
+
+	return dev;
+}
+
+struct udev *udev_new(void)
+{
+	struct udev *udev = &_udev;
+	struct udev_device **dev = udev->dev;
+
+	memset(dev, 0, sizeof(_udev.dev));
+
+	dev = add_intel_dev(udev, dev, "0000:00:02.0", 0x1926); /* skl */
+	dev = add_intel_dev(udev, dev, "0000:01:00.0", 0x56a1); /* dg2 */
+	dev = add_intel_dev(udev, dev, "0000:02:02.1", 0x9a40); /* tgl */
+	dev = add_intel_dev(udev, dev, "0000:03:01.0", 0x56a0); /* dg2 */
+	dev = add_intel_dev(udev, dev, "0000:04:02.0", 0x56a2); /* dg2 */
+
+	dev = udev->dev;
+	while (*dev)
+		print_udev_device(*dev++);
+
+	return &_udev;
+}
+
+struct udev_enumerate *udev_enumerate_new(struct udev *udev)
+{
+	_udev_enumerate.udev = udev;
+
+	return &_udev_enumerate;
+}
+
+int udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate,
+				       const char *subsystem)
+{
+	return 0;
+}
+
+int udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate,
+				      const char *property, const char *value)
+{
+	return 0;
+}
+
+int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate)
+{
+	return 0;
+}
+
+struct udev_list_entry *
+udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate)
+{
+
+	_entry_dev.entry_type = TYPE_DEVICE;
+	_entry_dev.curr = 0;
+
+	return &_entry_dev;
+}
+
+struct udev_list_entry *
+udev_list_entry_get_next(struct udev_list_entry *list_entry)
+{
+	int curr, currdev = _entry_dev.curr;
+
+	switch (list_entry->entry_type) {
+	case TYPE_DEVICE:
+		if (_udev.dev[++list_entry->curr])
+			return list_entry;
+		break;
+	case TYPE_PROP:
+		curr = ++list_entry->curr;
+		if (curr < _udev.dev[currdev]->props)
+			return list_entry;
+		break;
+	case TYPE_ATTR:
+		curr = ++list_entry->curr;
+		if (curr < _udev.dev[currdev]->attrs)
+			return list_entry;
+		break;
+	}
+
+	return NULL;
+}
+
+const char *udev_list_entry_get_name(struct udev_list_entry *list_entry)
+{
+	int curr, currdev = _entry_dev.curr;
+
+	switch (list_entry->entry_type) {
+	case TYPE_DEVICE:
+		return _udev.dev[list_entry->curr]->syspath;
+	case TYPE_PROP:
+		curr = _entry_prop.curr;
+		return _udev.dev[currdev]->prop[curr].key;
+	case TYPE_ATTR:
+		curr = _entry_attr.curr;
+		return _udev.dev[currdev]->attr[curr].key;
+	}
+
+	return "UNKNOWN";
+}
+
+const char *udev_list_entry_get_value(struct udev_list_entry *list_entry)
+{
+	int curr, currdev = _entry_dev.curr;
+
+	switch (list_entry->entry_type) {
+	case TYPE_DEVICE:
+		return "";
+	case TYPE_PROP:
+		curr = _entry_prop.curr;
+		return _udev.dev[currdev]->prop[curr].val;
+	case TYPE_ATTR:
+		curr = _entry_attr.curr;
+		return _udev.dev[currdev]->attr[curr].val;
+	}
+
+	return "UNKNOWN";
+}
+
+struct udev_device *udev_device_new_from_syspath(struct udev *udev,
+						 const char *syspath)
+{
+	int i;
+
+	for (i = 0; i < sizeof(udev->dev); i++) {
+		if (!udev->dev[i])
+			return NULL;
+
+		if (strcmp(udev->dev[i]->syspath, syspath) == 0)
+			return udev->dev[i];
+	}
+
+	return NULL;
+}
+
+const char *udev_device_get_subsystem(struct udev_device *udev_device)
+{
+	return udev_device->subsystem;
+}
+
+const char *udev_device_get_syspath(struct udev_device *udev_device)
+{
+	return udev_device->syspath;
+}
+
+const char *udev_device_get_devnode(struct udev_device *udev_device)
+{
+	if (udev_device->devnode[0] == '\0')
+		return NULL;
+
+	return udev_device->devnode;
+}
+
+struct udev_list_entry *
+udev_device_get_properties_list_entry(struct udev_device *udev_device)
+{
+	_entry_prop.entry_type = TYPE_PROP;
+	_entry_prop.curr = 0;
+
+	return &_entry_prop;
+}
+
+struct udev_list_entry *
+udev_device_get_sysattr_list_entry(struct udev_device *udev_device)
+{
+	_entry_attr.entry_type = TYPE_ATTR;
+	_entry_attr.curr = 0;
+
+	return &_entry_attr;
+}
+
+const char *
+udev_device_get_sysattr_value(struct udev_device *udev_device, const char *sysattr)
+{
+	for (int i = 0; i < udev_device->attrs; i++)
+		if (strcmp(udev_device->attr[i].key, sysattr) == 0)
+			return udev_device->attr[i].val;
+
+	return "UNKNOWN";
+}
+
+const char *udev_device_get_sysname(struct udev_device *udev_device)
+{
+	return udev_device->syspath;
+}
+
+struct udev_device *udev_device_get_parent(struct udev_device *udev_device)
+{
+	return udev_device->parent;
+}
+
+struct udev_enumerate *udev_enumerate_unref(struct udev_enumerate *udev_enumerate)
+{
+	return NULL;
+}
+
+struct udev_device *udev_device_unref(struct udev_device *udev_device)
+{
+	return NULL;
+}
-- 
2.34.1



More information about the igt-dev mailing list