[PATCH v1 2/2] config-tools: add topology extract_display


Yang, Yu-chu
 

From: "Yang,Yu-chu" <yu-chu.yang@...>

This mothod get connected displays and add them as child nodes to
a corresponding graphics card.

Tracked-On: #7970
Signed-off-by: Yang,Yu-chu <yu-chu.yang@...>
---
.../extractors/70-device-classes.py | 43 +++++++++++++++++--
.../board_inspector/extractors/90-sorting.py | 3 +-
2 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/misc/config_tools/board_inspector/extractors/70-device-classes.py b/misc/config_tools/board_inspector/extractors/70-device-classes.py
index dbd50519e..6ea3a6737 100644
--- a/misc/config_tools/board_inspector/extractors/70-device-classes.py
+++ b/misc/config_tools/board_inspector/extractors/70-device-classes.py
@@ -5,10 +5,13 @@

import re, os
import logging
-from extractors.helpers import add_child, get_node
+
+from pathlib import Path
+from extractors.helpers import add_child, get_node, get_bdf_from_realpath

SYS_INPUT_DEVICES_CLASS_PATH = "/sys/class/input/"
SYS_TTY_DEVICES_CLASS_PATH = "/sys/class/tty/"
+SYS_DISPLAYS_INFO_PATH = "/sys/class/drm/"

def add_child_with_file_contents(parent_node, tag, filepath, translations = {}):
try:
@@ -48,10 +51,44 @@ def extract_ttys(device_classes_node):
add_child(serial_node, "dev_path", f"/dev/{serial_dev}")
add_child_with_file_contents(serial_node, "type", f"{SYS_TTY_DEVICES_CLASS_PATH}{serial_dev}/type")

-def extract_topology(device_classes_node):
+def extract_display(board_etree):
+ display_regex = re.compile("(card[0-9])-(DP|HDMI|VGA)-.*")
+ display_types = {
+ "DP": "display port",
+ "HDMI": "HDMI",
+ "VGA": "VGA",
+ }
+ display_id = {}
+ for root in filter(lambda x: x.startswith("card"), os.listdir(SYS_DISPLAYS_INFO_PATH)):
+ displays_path = SYS_DISPLAYS_INFO_PATH + root
+ m = display_regex.match(root)
+ if m:
+ try:
+ with open(f"{displays_path}/status", "r") as f:
+ if f.read().strip() == "connected":
+ bus, device, function = \
+ get_bdf_from_realpath(f"{displays_path }/device/device")
+ adr = hex((device << 16) + function)
+ bus_node = get_node(board_etree, f"//bus[@type='pci' and @address='{hex(bus)}']")
+ if bus_node is None:
+ devices_node = get_node(board_etree, "//devices")
+ bus_node = add_child(devices_node, "bus", type="pci", address=hex(bus))
+ device_node = get_node(bus_node, f"./device[@address='{adr}']")
+ if device_node is None:
+ device_node = add_child(bus_node, "device", None, address=adr)
+ bdf = (bus, device, function)
+ if bdf not in display_id:
+ display_id[bdf] = 0
+ add_child(device_node, "display", f"{display_id[bdf]}", type=display_types[m.group(2)])
+ display_id[bdf] += 1
+ except Exception as e:
+ logging.warning(f"Failed to read the data from {displays_path}/status: {e}")
+
+def extract_topology(device_classes_node, board_etree):
extract_inputs(device_classes_node)
extract_ttys(device_classes_node)
+ extract_display(board_etree)

def extract(args, board_etree):
device_classes_node = get_node(board_etree, "//device-classes")
- extract_topology(device_classes_node)
+ extract_topology(device_classes_node, board_etree)
diff --git a/misc/config_tools/board_inspector/extractors/90-sorting.py b/misc/config_tools/board_inspector/extractors/90-sorting.py
index 480482041..49c3c0708 100644
--- a/misc/config_tools/board_inspector/extractors/90-sorting.py
+++ b/misc/config_tools/board_inspector/extractors/90-sorting.py
@@ -28,7 +28,8 @@ def getkey(child):

tags = ["vendor", "identifier", "subsystem_vendor", "subsystem_identifier", "class",
"acpi_object", "compatible_id", "acpi_uid", "aml_template", "status",
- "resource", "capability", "interrupt_pin_routing", "dependency", "bus", "device", "physfn"]
+ "resource", "capability", "interrupt_pin_routing", "dependency", "bus", "device",
+ "physfn", "display"]

if child.tag == "resource":
return (tags.index(child.tag), child.get("type"), resource_subkey(child))
--
2.25.1


Junjie Mao
 

-----Original Message-----
From: Yang, Yu-chu <yu-chu.yang@...>
Sent: Wednesday, October 5, 2022 2:26 AM
To: acrn-dev@...
Cc: Mao, Junjie <junjie.mao@...>
Subject: [PATCH v1 2/2] config-tools: add topology extract_display

From: "Yang,Yu-chu" <yu-chu.yang@...>

This mothod get connected displays and add them as child nodes to
a corresponding graphics card.

Tracked-On: #7970
Signed-off-by: Yang,Yu-chu <yu-chu.yang@...>
---
.../extractors/70-device-classes.py | 43 +++++++++++++++++--
.../board_inspector/extractors/90-sorting.py | 3 +-
2 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/misc/config_tools/board_inspector/extractors/70-device-classes.py
b/misc/config_tools/board_inspector/extractors/70-device-classes.py
index dbd50519e..6ea3a6737 100644
--- a/misc/config_tools/board_inspector/extractors/70-device-classes.py
+++ b/misc/config_tools/board_inspector/extractors/70-device-classes.py
@@ -5,10 +5,13 @@

import re, os
import logging
-from extractors.helpers import add_child, get_node
+
+from pathlib import Path
It seems you do not use the Path class in this file. If so, just remove the import above.

+from extractors.helpers import add_child, get_node, get_bdf_from_realpath

SYS_INPUT_DEVICES_CLASS_PATH = "/sys/class/input/"
SYS_TTY_DEVICES_CLASS_PATH = "/sys/class/tty/"
+SYS_DISPLAYS_INFO_PATH = "/sys/class/drm/"

def add_child_with_file_contents(parent_node, tag, filepath, translations = {}):
try:
@@ -48,10 +51,44 @@ def extract_ttys(device_classes_node):
add_child(serial_node, "dev_path", f"/dev/{serial_dev}")
add_child_with_file_contents(serial_node, "type",
f"{SYS_TTY_DEVICES_CLASS_PATH}{serial_dev}/type")

-def extract_topology(device_classes_node):
+def extract_display(board_etree):
+ display_regex = re.compile("(card[0-9])-(DP|HDMI|VGA)-.*")
+ display_types = {
+ "DP": "display port",
Why do we prefer using full names of DP while acronyms of HDMI and VGA?

+ "HDMI": "HDMI",
+ "VGA": "VGA",
+ }
+ display_id = {}
+ for root in filter(lambda x: x.startswith("card"),
os.listdir(SYS_DISPLAYS_INFO_PATH)):
+ displays_path = SYS_DISPLAYS_INFO_PATH + root
+ m = display_regex.match(root)
+ if m:
+ try:
+ with open(f"{displays_path}/status", "r") as f:
+ if f.read().strip() == "connected":
+ bus, device, function = \
+ get_bdf_from_realpath(f"{displays_path }/device/device")
+ adr = hex((device << 16) + function)
+ bus_node = get_node(board_etree, f"//bus[@type='pci' and
@address='{hex(bus)}']")
+ if bus_node is None:
+ devices_node = get_node(board_etree, "//devices")
+ bus_node = add_child(devices_node, "bus", type="pci",
address=hex(bus))
+ device_node = get_node(bus_node, f"./device[@address='{adr}']")
+ if device_node is None:
+ device_node = add_child(bus_node, "device", None, address=adr)
+ bdf = (bus, device, function)
+ if bdf not in display_id:
+ display_id[bdf] = 0
Since you need a default value for `display_id`, you can use collections.defaultdict to simplify the logic here.

+ add_child(device_node, "display", f"{display_id[bdf]}",
type=display_types[m.group(2)])
+ display_id[bdf] += 1
+ except Exception as e:
+ logging.warning(f"Failed to read the data from {displays_path}/status:
{e}")
There could be multiple reasons why an exception is thrown. In addition to failure upon access `status`, `get_bdf_from_realpath` can trigger exception as well.

Also warnings shall state the impact and potential fixes. It should be explicitly state that the impact of seeing this warning is that a specific display port won't be recognized and a display connected to it may not function with virtio-gpu.

---
Best Regards
Junjie Mao

+
+def extract_topology(device_classes_node, board_etree):
extract_inputs(device_classes_node)
extract_ttys(device_classes_node)
+ extract_display(board_etree)

def extract(args, board_etree):
device_classes_node = get_node(board_etree, "//device-classes")
- extract_topology(device_classes_node)
+ extract_topology(device_classes_node, board_etree)
diff --git a/misc/config_tools/board_inspector/extractors/90-sorting.py
b/misc/config_tools/board_inspector/extractors/90-sorting.py
index 480482041..49c3c0708 100644
--- a/misc/config_tools/board_inspector/extractors/90-sorting.py
+++ b/misc/config_tools/board_inspector/extractors/90-sorting.py
@@ -28,7 +28,8 @@ def getkey(child):

tags = ["vendor", "identifier", "subsystem_vendor", "subsystem_identifier", "class",
"acpi_object", "compatible_id", "acpi_uid", "aml_template", "status",
- "resource", "capability", "interrupt_pin_routing", "dependency", "bus",
"device", "physfn"]
+ "resource", "capability", "interrupt_pin_routing", "dependency", "bus",
"device",
+ "physfn", "display"]

if child.tag == "resource":
return (tags.index(child.tag), child.get("type"), resource_subkey(child))
--
2.25.1