scripts: check_init_priorities: rework the error messages

The current error messages are a bit cryptic, rework them to make them
more meaningful:

- add an extra message on the first error to explain what the errors
  refer to.
- rework the error message to be more explicit.
- rework the priority string print to use a LEVEL+offset format to
  somehow highlight that the number is the offset from the level, not
  the actual priority.
- print the init function name in addition to the devicetree path.

Signed-off-by: Fabio Baltieri <fabiobaltieri@google.com>
This commit is contained in:
Fabio Baltieri 2023-10-27 10:47:37 +00:00 committed by Carles Cufí
commit dd178ce311
3 changed files with 30 additions and 21 deletions

View file

@ -77,7 +77,7 @@ class Priority:
_DEVICE_INIT_LEVELS[self._level], self._priority)
def __str__(self):
return "%s %d" % (_DEVICE_INIT_LEVELS[self._level], self._priority)
return "%s+%d" % (_DEVICE_INIT_LEVELS[self._level], self._priority)
def __lt__(self, other):
return self._level_priority < other._level_priority
@ -214,7 +214,7 @@ class ZephyrInitLevels:
ordinal = self._device_ord_from_name(arg1_name)
if ordinal:
prio = Priority(level, priority)
self.devices[ordinal] = prio
self.devices[ordinal] = (prio, arg0_name)
addr += size
priority += 1
@ -267,8 +267,8 @@ class Validator():
self.log.info(f"Swapped priority: {dev_compat}, {dep_compat}")
dev_ord, dep_ord = dep_ord, dev_ord
dev_prio = self._obj.devices.get(dev_ord, None)
dep_prio = self._obj.devices.get(dep_ord, None)
dev_prio, dev_init = self._obj.devices.get(dev_ord, (None, None))
dep_prio, dep_init = self._obj.devices.get(dep_ord, (None, None))
if not dev_prio or not dep_prio:
return
@ -277,12 +277,18 @@ class Validator():
raise ValueError(f"{dev_node.path} and {dep_node.path} have the "
f"same priority: {dev_prio}")
elif dev_prio < dep_prio:
if not self.errors:
self.log.error("Device initialization priority validation failed, "
"the sequence of initialization calls does not match "
"the devicetree dependencies.")
self.errors += 1
self.log.error(
f"{dev_node.path} {dev_prio} < {dep_node.path} {dep_prio}")
f"{dev_node.path} <{dev_init}> is initialized before its dependency "
f"{dep_node.path} <{dep_init}> ({dev_prio} < {dep_prio})")
else:
self.log.info(
f"{dev_node.path} {dev_prio} > {dep_node.path} {dep_prio}")
f"{dev_node.path} <{dev_init}> {dev_prio} > "
f"{dep_node.path} <{dep_init}> {dep_prio}")
def check_edt(self):
"""Scan through all known devices and validate the init priorities."""

View file

@ -49,7 +49,7 @@ class TestPriority(unittest.TestCase):
def test_priority_strings(self):
prio = check_init_priorities.Priority("POST_KERNEL", 12)
self.assertEqual(str(prio), "POST_KERNEL 12")
self.assertEqual(str(prio), "POST_KERNEL+12")
self.assertEqual(repr(prio), "<Priority POST_KERNEL 12>")
class testZephyrInitLevels(unittest.TestCase):
@ -236,8 +236,8 @@ class testZephyrInitLevels(unittest.TestCase):
"SMP": [],
})
self.assertDictEqual(obj.devices, {
11: check_init_priorities.Priority("PRE_KERNEL_2", 0),
22: check_init_priorities.Priority("PRE_KERNEL_2", 1),
11: (check_init_priorities.Priority("PRE_KERNEL_2", 0), "i0"),
22: (check_init_priorities.Priority("PRE_KERNEL_2", 1), "i1"),
})
class testValidator(unittest.TestCase):
@ -280,10 +280,10 @@ class testValidator(unittest.TestCase):
validator._ord2node[1]._binding = None
validator._ord2node[2]._binding = None
validator._obj.devices = {1: 10}
validator._obj.devices = {1: (10, "i1")}
validator._check_dep(1, 2)
validator._obj.devices = {2: 20}
validator._obj.devices = {2: (20, "i2")}
validator._check_dep(1, 2)
self.assertFalse(validator.log.info.called)
@ -303,13 +303,15 @@ class testValidator(unittest.TestCase):
validator._ord2node[2]._binding = None
validator._ord2node[2].path = "/2"
validator._obj.devices = {1: 10, 2: 20}
validator._obj.devices = {1: (10, "i1"), 2: (20, "i2")}
validator._check_dep(2, 1)
validator._check_dep(1, 2)
validator.log.info.assert_called_once_with("/2 20 > /1 10")
validator.log.error.assert_called_once_with("/1 10 < /2 20")
validator.log.info.assert_called_once_with("/2 <i2> 20 > /1 <i1> 10")
validator.log.error.assert_has_calls([
mock.call("/1 <i1> is initialized before its dependency /2 <i2> (10 < 20)")
])
self.assertEqual(validator.errors, 1)
@mock.patch("check_init_priorities.Validator.__init__", return_value=None)
@ -325,7 +327,7 @@ class testValidator(unittest.TestCase):
validator._ord2node[2]._binding = None
validator._ord2node[2].path = "/2"
validator._obj.devices = {1: 10, 2: 10}
validator._obj.devices = {1: (10, "i1"), 2: (10, "i2")}
with self.assertRaises(ValueError):
validator._check_dep(1, 2)
@ -347,13 +349,13 @@ class testValidator(unittest.TestCase):
validator._ord2node[3]._binding.compatible = "compat-3"
validator._ord2node[3].path = "/3"
validator._obj.devices = {1: 20, 3: 10}
validator._obj.devices = {1: (20, "i1"), 3: (10, "i3")}
validator._check_dep(3, 1)
self.assertListEqual(validator.log.info.call_args_list, [
mock.call("Swapped priority: compat-3, compat-1"),
mock.call("/3 20 > /1 10"),
mock.call("/3 <i1> 20 > /1 <i3> 10"),
])
self.assertEqual(validator.errors, 0)

View file

@ -8,10 +8,11 @@
import sys
REFERENCE_OUTPUT = [
"ERROR: /i2c@11112222/test-i2c-dev@10 PRE_KERNEL_1 0 < /gpio@ffff PRE_KERNEL_1 1",
"ERROR: /i2c@11112222/test-i2c-dev@10 PRE_KERNEL_1 0 < /i2c@11112222 PRE_KERNEL_1 2",
"INFO: /i2c@11112222/test-i2c-dev@11 PRE_KERNEL_1 3 > /gpio@ffff PRE_KERNEL_1 1",
"INFO: /i2c@11112222/test-i2c-dev@11 PRE_KERNEL_1 3 > /i2c@11112222 PRE_KERNEL_1 2",
"ERROR: Device initialization priority validation failed, the sequence of initialization calls does not match the devicetree dependencies.",
"ERROR: /i2c@11112222/test-i2c-dev@10 <NULL> is initialized before its dependency /gpio@ffff <NULL> (PRE_KERNEL_1+0 < PRE_KERNEL_1+1)",
"ERROR: /i2c@11112222/test-i2c-dev@10 <NULL> is initialized before its dependency /i2c@11112222 <NULL> (PRE_KERNEL_1+0 < PRE_KERNEL_1+2)",
"INFO: /i2c@11112222/test-i2c-dev@11 <NULL> PRE_KERNEL_1+3 > /gpio@ffff <NULL> PRE_KERNEL_1+1",
"INFO: /i2c@11112222/test-i2c-dev@11 <NULL> PRE_KERNEL_1+3 > /i2c@11112222 <NULL> PRE_KERNEL_1+2",
]
if len(sys.argv) != 2: