Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dt: dt-extract-compatibles: Add flag for driver matching compatibles

Add a new flag, '--driver-match', to the dt-extract-compatibles script
that causes it to only print out compatibles that are expected to match
a driver. This output can then be used by tests to detect device probe
failures.

In order to filter the compatibles down to only ones that will match to
a driver, the following is considered:
- A compatible needs to show up in a driver's of_match_table for it to
be matched to a driver
- Compatibles that are used in both of_match_table and OF_DECLARE type
macros can't be expected to match to a driver and so are ignored.
One exception is CLK_OF_DECLARE_DRIVER, since it indicates that a
driver will also later probe, so compatibles in this macro are not
ignored.

Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com>
Link: https://lore.kernel.org/r/20230828211424.2964562-3-nfraprado@collabora.com
Signed-off-by: Rob Herring <robh@kernel.org>

authored by

Nícolas F. R. A. Prado and committed by
Rob Herring
365ba0c7 eb2139fc

+48 -9
+48 -9
scripts/dtc/dt-extract-compatibles
··· 7 7 import argparse 8 8 9 9 10 - def parse_of_declare_macros(data): 10 + def parse_of_declare_macros(data, include_driver_macros=True): 11 11 """ Find all compatible strings in OF_DECLARE() style macros """ 12 12 compat_list = [] 13 13 # CPU_METHOD_OF_DECLARE does not have a compatible string 14 - for m in re.finditer(r'(?<!CPU_METHOD_)(IRQCHIP|OF)_(DECLARE|MATCH)(_DRIVER)?\(.*?\)', data): 14 + if include_driver_macros: 15 + re_macros = r'(?<!CPU_METHOD_)(IRQCHIP|OF)_(DECLARE|MATCH)(_DRIVER)?\(.*?\)' 16 + else: 17 + re_macros = r'(?<!CPU_METHOD_)(IRQCHIP|OF)_(DECLARE|MATCH)\(.*?\)' 18 + for m in re.finditer(re_macros, data): 15 19 try: 16 20 compat = re.search(r'"(.*?)"', m[0])[1] 17 21 except: ··· 26 22 return compat_list 27 23 28 24 29 - def parse_of_device_id(data): 25 + def parse_of_device_id(data, match_table_list=None): 30 26 """ Find all compatible strings in of_device_id structs """ 31 27 compat_list = [] 32 - for m in re.finditer(r'of_device_id(\s+\S+)?\s+\S+\[\](\s+\S+)?\s*=\s*({.*?);', data): 33 - compat_list += re.findall(r'\.compatible\s+=\s+"(\S+)"', m[3]) 28 + for m in re.finditer(r'of_device_id(\s+\S+)?\s+(\S+)\[\](\s+\S+)?\s*=\s*({.*?);', data): 29 + if match_table_list is not None and m[2] not in match_table_list: 30 + continue 31 + compat_list += re.findall(r'\.compatible\s+=\s+"(\S+)"', m[4]) 34 32 35 33 return compat_list 36 34 37 35 38 - def parse_compatibles(file): 36 + def parse_of_match_table(data): 37 + """ Find all driver's of_match_table """ 38 + match_table_list = [] 39 + for m in re.finditer(r'\.of_match_table\s+=\s+(of_match_ptr\()?([a-zA-Z0-9_-]+)', data): 40 + match_table_list.append(m[2]) 41 + 42 + return match_table_list 43 + 44 + 45 + def parse_compatibles(file, compat_ignore_list): 39 46 with open(file, 'r', encoding='utf-8') as f: 40 47 data = f.read().replace('\n', '') 41 48 42 - compat_list = parse_of_declare_macros(data) 43 - compat_list += parse_of_device_id(data) 49 + if compat_ignore_list is not None: 50 + # For a compatible in the DT to be matched to a driver it needs to show 51 + # up in a driver's of_match_table 52 + match_table_list = parse_of_match_table(data) 53 + compat_list = parse_of_device_id(data, match_table_list) 54 + 55 + compat_list = [compat for compat in compat_list if compat not in compat_ignore_list] 56 + else: 57 + compat_list = parse_of_declare_macros(data) 58 + compat_list += parse_of_device_id(data) 44 59 45 60 return compat_list 61 + 62 + def parse_compatibles_to_ignore(file): 63 + with open(file, 'r', encoding='utf-8') as f: 64 + data = f.read().replace('\n', '') 65 + 66 + # Compatibles that show up in OF_DECLARE macros can't be expected to 67 + # match a driver, except for the _DRIVER ones. 68 + return parse_of_declare_macros(data, include_driver_macros=False) 69 + 46 70 47 71 def print_compat(filename, compatibles): 48 72 if not compatibles: ··· 95 63 ap = argparse.ArgumentParser() 96 64 ap.add_argument("cfile", type=str, nargs='*', help="C source files or directories to parse") 97 65 ap.add_argument('-H', '--with-filename', help="Print filename with compatibles", action="store_true") 66 + ap.add_argument('-d', '--driver-match', help="Only print compatibles that should match to a driver", action="store_true") 98 67 args = ap.parse_args() 99 68 100 69 show_filename = args.with_filename 70 + compat_ignore_list = None 71 + 72 + if args.driver_match: 73 + compat_ignore_list = [] 74 + for f in files_to_parse(args.cfile): 75 + compat_ignore_list.extend(parse_compatibles_to_ignore(f)) 101 76 102 77 for f in files_to_parse(args.cfile): 103 - compat_list = parse_compatibles(f) 78 + compat_list = parse_compatibles(f, compat_ignore_list) 104 79 print_compat(f, compat_list)