summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2021-02-03 16:01:06 +0300
committerSimon Glass <sjg@chromium.org>2021-03-22 09:23:27 +0300
commit1d97269756a60945e3b9690074d1814198ce5a4e (patch)
tree4e0e496dcb78cda515653739788a6fa5658e1d76 /tools
parent8d6f2d359e7cf5a6960d55281ee378fac7db0bbb (diff)
downloadu-boot-1d97269756a60945e3b9690074d1814198ce5a4e.tar.xz
dtoc: Warn of duplicate drivers
If drivers have the same name then we cannot distinguish them. This only matters if the driver is actually used by dtoc, but in that case, issue a warning. Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/dtoc/src_scan.py28
-rw-r--r--tools/dtoc/test_src_scan.py95
2 files changed, 122 insertions, 1 deletions
diff --git a/tools/dtoc/src_scan.py b/tools/dtoc/src_scan.py
index 9d161a2cbc..fb78536e00 100644
--- a/tools/dtoc/src_scan.py
+++ b/tools/dtoc/src_scan.py
@@ -70,6 +70,10 @@ class Driver:
phase (str): Which phase of U-Boot to use this driver
headers (list): List of header files needed for this driver (each a str)
e.g. ['<asm/cpu.h>']
+ dups (list): Driver objects with the same name as this one, that were
+ found after this one
+ warn_dups (bool): True if the duplicates are not distinguisble using
+ the phase
"""
def __init__(self, name, fname):
self.name = name
@@ -83,6 +87,8 @@ class Driver:
self.used = False
self.phase = ''
self.headers = []
+ self.dups = []
+ self.warn_dups = False
def __eq__(self, other):
return (self.name == other.name and
@@ -531,7 +537,21 @@ class Scanner:
self._driver_aliases[m_alias[2]] = m_alias[1]
# Make the updates based on what we found
- self._drivers.update(drivers)
+ for driver in drivers.values():
+ if driver.name in self._drivers:
+ orig = self._drivers[driver.name]
+ if self._phase:
+ # If the original driver matches our phase, use it
+ if orig.phase == self._phase:
+ orig.dups.append(driver)
+ continue
+
+ # Otherwise use the new driver, which is assumed to match
+ else:
+ # We have no way of distinguishing them
+ driver.warn_dups = True
+ driver.dups.append(orig)
+ self._drivers[driver.name] = driver
self._of_match.update(of_match)
def scan_driver(self, fname):
@@ -617,6 +637,8 @@ class Scanner:
This takes a list of nodes, finds the driver for each one and marks it
as used.
+ If two used drivers have the same name, issue a warning.
+
Args:
nodes (list of None): Nodes that are in use
"""
@@ -626,3 +648,7 @@ class Scanner:
driver = self._drivers.get(struct_name)
if driver:
driver.used = True
+ if driver.dups and driver.warn_dups:
+ print("Warning: Duplicate driver name '%s' (orig=%s, dups=%s)" %
+ (driver.name, driver.fname,
+ ', '.join([drv.fname for drv in driver.dups])))
diff --git a/tools/dtoc/test_src_scan.py b/tools/dtoc/test_src_scan.py
index 245b7302fd..598ff256a6 100644
--- a/tools/dtoc/test_src_scan.py
+++ b/tools/dtoc/test_src_scan.py
@@ -371,3 +371,98 @@ struct another_struct {
with test_util.capture_sys_output() as (stdout, _):
scan.scan_header(output)
self.assertIn('due to unicode error', stdout.getvalue())
+
+ def setup_dup_drivers(self, name, phase=''):
+ """Set up for a duplcate test
+
+ Returns:
+ tuple:
+ Scanner to use
+ Driver record for first driver
+ Text of second driver declaration
+ Node for driver 1
+ """
+ driver1 = '''
+static const struct udevice_id test_ids[] = {
+ { .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
+ { }
+};
+
+U_BOOT_DRIVER(%s) = {
+ .name = "testing",
+ .id = UCLASS_I2C,
+ .of_match = test_ids,
+ %s
+};
+''' % (name, 'DM_PHASE(%s)' % phase if phase else '')
+ driver2 = '''
+static const struct udevice_id test_ids[] = {
+ { .compatible = "nvidia,tegra114-dvc" },
+ { }
+};
+
+U_BOOT_DRIVER(%s) = {
+ .name = "testing",
+ .id = UCLASS_RAM,
+ .of_match = test_ids,
+};
+''' % name
+ scan = src_scan.Scanner(None, False, None, phase)
+ scan._parse_driver('file1.c', driver1)
+ self.assertIn(name, scan._drivers)
+ drv1 = scan._drivers[name]
+
+ prop = FakeProp()
+ prop.name = 'compatible'
+ prop.value = 'nvidia,tegra114-i2c'
+ node = FakeNode()
+ node.name = 'testing'
+ node.props = {'compatible': prop}
+
+ return scan, drv1, driver2, node
+
+ def test_dup_drivers(self):
+ """Test handling of duplicate drivers"""
+ name = 'nvidia_tegra114_i2c'
+ scan, drv1, driver2, node = self.setup_dup_drivers(name)
+ self.assertEqual('', drv1.phase)
+
+ # The driver should not have a duplicate yet
+ self.assertEqual([], drv1.dups)
+
+ scan._parse_driver('file2.c', driver2)
+
+ # The first driver should now be a duplicate of the second
+ drv2 = scan._drivers[name]
+ self.assertEqual('', drv2.phase)
+ self.assertEqual(1, len(drv2.dups))
+ self.assertEqual([drv1], drv2.dups)
+
+ # There is no way to distinguish them, so we should expect a warning
+ self.assertTrue(drv2.warn_dups)
+
+ # We should see a warning
+ with test_util.capture_sys_output() as (stdout, _):
+ scan.mark_used([node])
+ self.assertEqual(
+ "Warning: Duplicate driver name 'nvidia_tegra114_i2c' (orig=file2.c, dups=file1.c)",
+ stdout.getvalue().strip())
+
+ def test_dup_drivers_phase(self):
+ """Test handling of duplicate drivers but with different phases"""
+ name = 'nvidia_tegra114_i2c'
+ scan, drv1, driver2, node = self.setup_dup_drivers(name, 'spl')
+ scan._parse_driver('file2.c', driver2)
+ self.assertEqual('spl', drv1.phase)
+
+ # The second driver should now be a duplicate of the second
+ self.assertEqual(1, len(drv1.dups))
+ drv2 = drv1.dups[0]
+
+ # The phase is different, so we should not warn of dups
+ self.assertFalse(drv1.warn_dups)
+
+ # We should not see a warning
+ with test_util.capture_sys_output() as (stdout, _):
+ scan.mark_used([node])
+ self.assertEqual('', stdout.getvalue().strip())