From mboxrd@z Thu Jan 1 00:00:00 1970 From: Simon Glass Date: Wed, 3 Feb 2021 06:01:06 -0700 Subject: [PATCH v2 18/33] dtoc: Warn of duplicate drivers In-Reply-To: <20210203130121.2478810-1-sjg@chromium.org> References: <20210203130121.2478810-1-sjg@chromium.org> Message-ID: <20210203130121.2478810-19-sjg@chromium.org> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 --- (no changes since v1) tools/dtoc/src_scan.py | 28 ++++++++++- tools/dtoc/test_src_scan.py | 95 +++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 1 deletion(-) diff --git a/tools/dtoc/src_scan.py b/tools/dtoc/src_scan.py index 9d161a2cbc7..fb78536e003 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. [''] + 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 245b7302fd6..598ff256a60 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()) -- 2.30.0.365.g02bc693789-goog