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>
This commit is contained in:
Simon Glass 2021-02-03 06:01:06 -07:00
parent 8d6f2d359e
commit 1d97269756
2 changed files with 122 additions and 1 deletions

View File

@ -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])))

View File

@ -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())