summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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())