forked from Mirrors/opensbi
		
	lib: utils/fdt: Respect compatible string fallback priority
When matching drivers to DT nodes, always match all drivers against the
first compatible string before considering fallback compatible strings.
This ensures the most specific match is always selected, regardless of
the order of the drivers or match structures, as long as no compatible
string appears in multiple match structures.
Fixes: 1ccc52c427 ("lib: utils/fdt: Add helpers for generic driver initialization")
Signed-off-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
			
			
This commit is contained in:
		
				
					committed by
					
						
						Anup Patel
					
				
			
			
				
	
			
			
			
						parent
						
							b2e8e6986d
						
					
				
				
					commit
					0ffe265fd9
				
			@@ -15,21 +15,29 @@ int fdt_driver_init_by_offset(const void *fdt, int nodeoff,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	const struct fdt_driver *driver;
 | 
						const struct fdt_driver *driver;
 | 
				
			||||||
	const struct fdt_match *match;
 | 
						const struct fdt_match *match;
 | 
				
			||||||
	const void *prop;
 | 
						int compat_len, prop_len, rc;
 | 
				
			||||||
	int len, rc;
 | 
						const char *compat_str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!fdt_node_is_enabled(fdt, nodeoff))
 | 
						if (!fdt_node_is_enabled(fdt, nodeoff))
 | 
				
			||||||
		return SBI_ENODEV;
 | 
							return SBI_ENODEV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	prop = fdt_getprop(fdt, nodeoff, "compatible", &len);
 | 
						compat_str = fdt_getprop(fdt, nodeoff, "compatible", &prop_len);
 | 
				
			||||||
	if (!prop)
 | 
						if (!compat_str)
 | 
				
			||||||
		return SBI_ENODEV;
 | 
							return SBI_ENODEV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while ((driver = *drivers++)) {
 | 
						while ((compat_len = strnlen(compat_str, prop_len) + 1) <= prop_len) {
 | 
				
			||||||
		for (match = driver->match_table; match->compatible; match++) {
 | 
							for (int i = 0; (driver = drivers[i]); i++)
 | 
				
			||||||
			if (!fdt_stringlist_contains(prop, len, match->compatible))
 | 
								for (match = driver->match_table; match->compatible; match++)
 | 
				
			||||||
				continue;
 | 
									if (!memcmp(match->compatible, compat_str, compat_len))
 | 
				
			||||||
 | 
										goto found;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							compat_str += compat_len;
 | 
				
			||||||
 | 
							prop_len -= compat_len;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return SBI_ENODEV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					found:
 | 
				
			||||||
	if (driver->experimental)
 | 
						if (driver->experimental)
 | 
				
			||||||
		sbi_printf("WARNING: %s driver is experimental and may change\n",
 | 
							sbi_printf("WARNING: %s driver is experimental and may change\n",
 | 
				
			||||||
			   match->compatible);
 | 
								   match->compatible);
 | 
				
			||||||
@@ -44,10 +52,6 @@ int fdt_driver_init_by_offset(const void *fdt, int nodeoff,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return SBI_ENODEV;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int fdt_driver_init_scan(const void *fdt,
 | 
					static int fdt_driver_init_scan(const void *fdt,
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user