@ -53,26 +53,28 @@ struct check {
struct check * * prereq ;
} ;
# define CHECK_ENTRY(_ nm, _ fn, _ d, _w , _ e, ...) \
static struct check * _ nm# # _prereqs [ ] = { __VA_ARGS__ } ; \
static struct check _ nm = { \
. name = # _ nm, \
. fn = ( _ fn) , \
. data = ( _ d) , \
. warn = ( _ w) , \
. error = ( _ e) , \
# define CHECK_ENTRY(nm_ , fn_ , d_ , w _, e_ , ...) \
static struct check * nm_ # # _prereqs [ ] = { __VA_ARGS__ } ; \
static struct check nm_ = { \
. name = # nm_ , \
. fn = ( fn_ ) , \
. data = ( d_ ) , \
. warn = ( w_ ) , \
. error = ( e_ ) , \
. status = UNCHECKED , \
. num_prereqs = ARRAY_SIZE ( _ nm# # _prereqs ) , \
. prereq = _ nm# # _prereqs , \
. num_prereqs = ARRAY_SIZE ( nm_ # # _prereqs ) , \
. prereq = nm_ # # _prereqs , \
} ;
# define WARNING(_nm, _fn, _d, ...) \
CHECK_ENTRY ( _nm , _fn , _d , true , false , __VA_ARGS__ )
# define ERROR(_nm, _fn, _d, ...) \
CHECK_ENTRY ( _nm , _fn , _d , false , true , __VA_ARGS__ )
# define CHECK(_nm, _fn, _d, ...) \
CHECK_ENTRY ( _nm , _fn , _d , false , false , __VA_ARGS__ )
static inline void PRINTF ( 3 , 4 ) check_msg ( struct check * c , struct dt_info * dti ,
# define WARNING(nm_, fn_, d_, ...) \
CHECK_ENTRY ( nm_ , fn_ , d_ , true , false , __VA_ARGS__ )
# define ERROR(nm_, fn_, d_, ...) \
CHECK_ENTRY ( nm_ , fn_ , d_ , false , true , __VA_ARGS__ )
# define CHECK(nm_, fn_, d_, ...) \
CHECK_ENTRY ( nm_ , fn_ , d_ , false , false , __VA_ARGS__ )
static inline void PRINTF ( 5 , 6 ) check_msg ( struct check * c , struct dt_info * dti ,
struct node * node ,
struct property * prop ,
const char * fmt , . . . )
{
va_list ap ;
@ -83,19 +85,33 @@ static inline void PRINTF(3, 4) check_msg(struct check *c, struct dt_info *dti,
fprintf ( stderr , " %s: %s (%s): " ,
strcmp ( dti - > outname , " - " ) ? dti - > outname : " <stdout> " ,
( c - > error ) ? " ERROR " : " Warning " , c - > name ) ;
if ( node ) {
fprintf ( stderr , " %s " , node - > fullpath ) ;
if ( prop )
fprintf ( stderr , " :%s " , prop - > name ) ;
fputs ( " : " , stderr ) ;
}
vfprintf ( stderr , fmt , ap ) ;
fprintf ( stderr , " \n " ) ;
}
va_end ( ap ) ;
}
# define FAIL(c, dti, ...) \
# define FAIL(c, dti, node, ...) \
do { \
TRACE ( ( c ) , " \t \t FAILED at %s:%d " , __FILE__ , __LINE__ ) ; \
( c ) - > status = FAILED ; \
check_msg ( ( c ) , dti , node , NULL , __VA_ARGS__ ) ; \
} while ( 0 )
# define FAIL_PROP(c, dti, node, prop, ...) \
do { \
TRACE ( ( c ) , " \t \t FAILED at %s:%d " , __FILE__ , __LINE__ ) ; \
( c ) - > status = FAILED ; \
check_msg ( ( c ) , dti , __VA_ARGS__ ) ; \
check_msg ( ( c ) , dti , node , prop , __VA_ARGS__ ) ; \
} while ( 0 )
static void check_nodes_props ( struct check * c , struct dt_info * dti , struct node * node )
{
struct node * child ;
@ -126,7 +142,7 @@ static bool run_check(struct check *c, struct dt_info *dti)
error = error | | run_check ( prq , dti ) ;
if ( prq - > status ! = PASSED ) {
c - > status = PREREQ ;
check_msg ( c , dti , " Failed prerequisite '%s' " ,
check_msg ( c , dti , NULL , NULL , " Failed prerequisite '%s' " ,
c - > prereq [ i ] - > name ) ;
}
}
@ -156,7 +172,7 @@ out:
static inline void check_always_fail ( struct check * c , struct dt_info * dti ,
struct node * node )
{
FAIL ( c , dti , " always_fail check " ) ;
FAIL ( c , dti , node , " always_fail check " ) ;
}
CHECK ( always_fail , check_always_fail , NULL ) ;
@ -171,14 +187,42 @@ static void check_is_string(struct check *c, struct dt_info *dti,
return ; /* Not present, assumed ok */
if ( ! data_is_one_string ( prop - > val ) )
FAIL ( c , dti , " \" %s \" property in %s is not a string " ,
propname , node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop , " property is not a string " ) ;
}
# define WARNING_IF_NOT_STRING(nm, propname) \
WARNING ( nm , check_is_string , ( propname ) )
# define ERROR_IF_NOT_STRING(nm, propname) \
ERROR ( nm , check_is_string , ( propname ) )
static void check_is_string_list ( struct check * c , struct dt_info * dti ,
struct node * node )
{
int rem , l ;
struct property * prop ;
char * propname = c - > data ;
char * str ;
prop = get_property ( node , propname ) ;
if ( ! prop )
return ; /* Not present, assumed ok */
str = prop - > val . val ;
rem = prop - > val . len ;
while ( rem > 0 ) {
l = strnlen ( str , rem ) ;
if ( l = = rem ) {
FAIL_PROP ( c , dti , node , prop , " property is not a string list " ) ;
break ;
}
rem - = l + 1 ;
str + = l + 1 ;
}
}
# define WARNING_IF_NOT_STRING_LIST(nm, propname) \
WARNING ( nm , check_is_string_list , ( propname ) )
# define ERROR_IF_NOT_STRING_LIST(nm, propname) \
ERROR ( nm , check_is_string_list , ( propname ) )
static void check_is_cell ( struct check * c , struct dt_info * dti ,
struct node * node )
{
@ -190,8 +234,7 @@ static void check_is_cell(struct check *c, struct dt_info *dti,
return ; /* Not present, assumed ok */
if ( prop - > val . len ! = sizeof ( cell_t ) )
FAIL ( c , dti , " \" %s \" property in %s is not a single cell " ,
propname , node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop , " property is not a single cell " ) ;
}
# define WARNING_IF_NOT_CELL(nm, propname) \
WARNING ( nm , check_is_cell , ( propname ) )
@ -212,8 +255,7 @@ static void check_duplicate_node_names(struct check *c, struct dt_info *dti,
child2 ;
child2 = child2 - > next_sibling )
if ( streq ( child - > name , child2 - > name ) )
FAIL ( c , dti , " Duplicate node name %s " ,
child - > fullpath ) ;
FAIL ( c , dti , node , " Duplicate node name " ) ;
}
ERROR ( duplicate_node_names , check_duplicate_node_names , NULL ) ;
@ -227,8 +269,7 @@ static void check_duplicate_property_names(struct check *c, struct dt_info *dti,
if ( prop2 - > deleted )
continue ;
if ( streq ( prop - > name , prop2 - > name ) )
FAIL ( c , dti , " Duplicate property name %s in %s " ,
prop - > name , node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop , " Duplicate property name " ) ;
}
}
}
@ -246,8 +287,8 @@ static void check_node_name_chars(struct check *c, struct dt_info *dti,
int n = strspn ( node - > name , c - > data ) ;
if ( n < strlen ( node - > name ) )
FAIL ( c , dti , " Bad character '%c' in node %s " ,
node - > name [ n ] , node - > fullpath ) ;
FAIL ( c , dti , node , " Bad character '%c' in node name " ,
node - > name [ n ] ) ;
}
ERROR ( node_name_chars , check_node_name_chars , PROPNODECHARS " @ " ) ;
@ -257,8 +298,8 @@ static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
int n = strspn ( node - > name , c - > data ) ;
if ( n < node - > basenamelen )
FAIL ( c , dti , " Character '%c' not recommended in node %s " ,
node - > name [ n ] , node - > fullpath ) ;
FAIL ( c , dti , node , " Character '%c' not recommended in node name " ,
node - > name [ n ] ) ;
}
CHECK ( node_name_chars_strict , check_node_name_chars_strict , PROPNODECHARSSTRICT ) ;
@ -266,8 +307,7 @@ static void check_node_name_format(struct check *c, struct dt_info *dti,
struct node * node )
{
if ( strchr ( get_unitname ( node ) , ' @ ' ) )
FAIL ( c , dti , " Node %s has multiple '@' characters in name " ,
node - > fullpath ) ;
FAIL ( c , dti , node , " multiple '@' characters in node name " ) ;
}
ERROR ( node_name_format , check_node_name_format , NULL , & node_name_chars ) ;
@ -285,12 +325,10 @@ static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
if ( prop ) {
if ( ! unitname [ 0 ] )
FAIL ( c , dti , " Node %s has a reg or ranges property, but no unit name " ,
node - > fullpath ) ;
FAIL ( c , dti , node , " node has a reg or ranges property, but no unit name " ) ;
} else {
if ( unitname [ 0 ] )
FAIL ( c , dti , " Node %s has a unit name, but no reg property " ,
node - > fullpath ) ;
FAIL ( c , dti , node , " node has a unit name, but no reg property " ) ;
}
}
WARNING ( unit_address_vs_reg , check_unit_address_vs_reg , NULL ) ;
@ -304,8 +342,8 @@ static void check_property_name_chars(struct check *c, struct dt_info *dti,
int n = strspn ( prop - > name , c - > data ) ;
if ( n < strlen ( prop - > name ) )
FAIL ( c , dti , " Bad character '%c' in property name \" %s \" , node %s " ,
prop - > name [ n ] , prop - > name , node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop , " Bad character '%c' in property name " ,
prop - > name [ n ] ) ;
}
}
ERROR ( property_name_chars , check_property_name_chars , PROPNODECHARS ) ;
@ -336,8 +374,8 @@ static void check_property_name_chars_strict(struct check *c,
n = strspn ( name , c - > data ) ;
}
if ( n < strlen ( name ) )
FAIL ( c , dti , " Character '%c' not recommended in property name \" %s \" , node %s " ,
name [ n ] , prop - > name , node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop , " Character '%c' not recommended in property name " ,
name [ n ] ) ;
}
}
CHECK ( property_name_chars_strict , check_property_name_chars_strict , PROPNODECHARSSTRICT ) ;
@ -370,7 +408,7 @@ static void check_duplicate_label(struct check *c, struct dt_info *dti,
return ;
if ( ( othernode ! = node ) | | ( otherprop ! = prop ) | | ( othermark ! = mark ) )
FAIL ( c , dti , " Duplicate label '%s' on " DESCLABEL_FMT
FAIL ( c , dti , node , " Duplicate label '%s' on " DESCLABEL_FMT
" and " DESCLABEL_FMT ,
label , DESCLABEL_ARGS ( node , prop , mark ) ,
DESCLABEL_ARGS ( othernode , otherprop , othermark ) ) ;
@ -410,8 +448,8 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
return 0 ;
if ( prop - > val . len ! = sizeof ( cell_t ) ) {
FAIL ( c , dti , " %s has bad length (%d) %s property" ,
node - > fullpath , prop - > val . len , prop - > name ) ;
FAIL_PROP ( c , dti , node , prop , " bad length (%d) %s property " ,
prop - > val . len , prop - > name ) ;
return 0 ;
}
@ -422,8 +460,8 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
/* "Set this node's phandle equal to some
* other node ' s phandle " . That's nonsensical
* by construction . */ {
FAIL ( c , dti , " %s in %s is a reference to another node" ,
prop - > name , node - > fullpath ) ;
FAIL ( c , dti , node , " %s is a reference to another node " ,
prop - > name ) ;
}
/* But setting this node's phandle equal to its own
* phandle is allowed - that means allocate a unique
@ -436,8 +474,8 @@ static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
phandle = propval_cell ( prop ) ;
if ( ( phandle = = 0 ) | | ( phandle = = - 1 ) ) {
FAIL ( c , dti , " %s has bad value (0x%x) in %s property" ,
node - > fullpath , phandle , prop - > name ) ;
FAIL_PROP ( c , dti , node , prop , " bad value (0x%x) in %s property " ,
phandle , prop - > name ) ;
return 0 ;
}
@ -463,16 +501,16 @@ static void check_explicit_phandles(struct check *c, struct dt_info *dti,
return ;
if ( linux_phandle & & phandle & & ( phandle ! = linux_phandle ) )
FAIL ( c , dti , " %s has mismatching 'phandle' and 'linux,phandle'"
" properties " , node - > fullpath ) ;
FAIL ( c , dti , node , " mismatching 'phandle' and 'linux,phandle' "
" properties " ) ;
if ( linux_phandle & & ! phandle )
phandle = linux_phandle ;
other = get_node_by_phandle ( root , phandle ) ;
if ( other & & ( other ! = node ) ) {
FAIL ( c , dti , " %s has duplicated phandle 0x%x (seen before at %s)" ,
node - > fullpath , phandle , other - > fullpath ) ;
FAIL ( c , dti , node , " duplicated phandle 0x%x (seen before at %s) " ,
phandle , other - > fullpath ) ;
return ;
}
@ -496,8 +534,8 @@ static void check_name_properties(struct check *c, struct dt_info *dti,
if ( ( prop - > val . len ! = node - > basenamelen + 1 )
| | ( memcmp ( prop - > val . val , node - > name , node - > basenamelen ) ! = 0 ) ) {
FAIL ( c , dti , " \" name \" property in %s is incorrect ( \" %s \" instead "
" of base node name) " , node - > fullpath , prop - > val . val ) ;
FAIL ( c , dti , node , " \" name \" property is incorrect ( \" %s \" instead "
" of base node name) " , prop - > val . val ) ;
} else {
/* The name property is correct, and therefore redundant.
* Delete it */
@ -531,7 +569,7 @@ static void fixup_phandle_references(struct check *c, struct dt_info *dti,
refnode = get_node_by_ref ( dt , m - > ref ) ;
if ( ! refnode ) {
if ( ! ( dti - > dtsflags & DTSF_PLUGIN ) )
FAIL ( c , dti , " Reference to non-existent node or "
FAIL ( c , dti , node , " Reference to non-existent node or "
" label \" %s \" \n " , m - > ref ) ;
else /* mark the entry as unresolved */
* ( ( fdt32_t * ) ( prop - > val . val + m - > offset ) ) =
@ -563,7 +601,7 @@ static void fixup_path_references(struct check *c, struct dt_info *dti,
refnode = get_node_by_ref ( dt , m - > ref ) ;
if ( ! refnode ) {
FAIL ( c , dti , " Reference to non-existent node or label \" %s \" \n " ,
FAIL ( c , dti , node , " Reference to non-existent node or label \" %s \" \n " ,
m - > ref ) ;
continue ;
}
@ -586,6 +624,45 @@ WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
WARNING_IF_NOT_STRING ( device_type_is_string , " device_type " ) ;
WARNING_IF_NOT_STRING ( model_is_string , " model " ) ;
WARNING_IF_NOT_STRING ( status_is_string , " status " ) ;
WARNING_IF_NOT_STRING ( label_is_string , " label " ) ;
WARNING_IF_NOT_STRING_LIST ( compatible_is_string_list , " compatible " ) ;
static void check_names_is_string_list ( struct check * c , struct dt_info * dti ,
struct node * node )
{
struct property * prop ;
for_each_property ( node , prop ) {
const char * s = strrchr ( prop - > name , ' - ' ) ;
if ( ! s | | ! streq ( s , " -names " ) )
continue ;
c - > data = prop - > name ;
check_is_string_list ( c , dti , node ) ;
}
}
WARNING ( names_is_string_list , check_names_is_string_list , NULL ) ;
static void check_alias_paths ( struct check * c , struct dt_info * dti ,
struct node * node )
{
struct property * prop ;
if ( ! streq ( node - > name , " aliases " ) )
return ;
for_each_property ( node , prop ) {
if ( ! prop - > val . val | | ! get_node_by_path ( dti - > dt , prop - > val . val ) ) {
FAIL_PROP ( c , dti , node , prop , " aliases property is not a valid node (%s) " ,
prop - > val . val ) ;
continue ;
}
if ( strspn ( prop - > name , LOWERCASE DIGITS " - " ) ! = strlen ( prop - > name ) )
FAIL ( c , dti , node , " aliases property name must include only lowercase and '-' " ) ;
}
}
WARNING ( alias_paths , check_alias_paths , NULL ) ;
static void fixup_addr_size_cells ( struct check * c , struct dt_info * dti ,
struct node * node )
@ -622,21 +699,21 @@ static void check_reg_format(struct check *c, struct dt_info *dti,
return ; /* No "reg", that's fine */
if ( ! node - > parent ) {
FAIL ( c , dti , " Root node has a \" reg \" property " ) ;
FAIL ( c , dti , node , " Root node has a \" reg \" property " ) ;
return ;
}
if ( prop - > val . len = = 0 )
FAIL ( c , dti , " \" reg \" property in %s is empty " , node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop , " property is empty " ) ;
addr_cells = node_addr_cells ( node - > parent ) ;
size_cells = node_size_cells ( node - > parent ) ;
entrylen = ( addr_cells + size_cells ) * sizeof ( cell_t ) ;
if ( ! entrylen | | ( prop - > val . len % entrylen ) ! = 0 )
FAIL ( c , dti , " \" reg \" property in %s has invalid length (%d bytes) "
" (#address-cells == %d, #size-cells == %d) " ,
node - > fullpath , prop - > val . len , addr_cells , size_cells ) ;
FAIL_PROP ( c , dti , node , prop , " property has invalid length (%d bytes) "
" (#address-cells == %d, #size-cells == %d) " ,
prop - > val . len , addr_cells , size_cells ) ;
}
WARNING ( reg_format , check_reg_format , NULL , & addr_size_cells ) ;
@ -651,7 +728,7 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
return ;
if ( ! node - > parent ) {
FAIL ( c , dti , " Root node has a \" ranges \" property " ) ;
FAIL_PROP ( c , dti , node , prop , " Root node has a \" ranges \" property " ) ;
return ;
}
@ -663,20 +740,20 @@ static void check_ranges_format(struct check *c, struct dt_info *dti,
if ( prop - > val . len = = 0 ) {
if ( p_addr_cells ! = c_addr_cells )
FAIL ( c , dti , " %s has empty \" ranges \" property but its "
" #address-cells (%d) differs from %s (%d) " ,
node - > fullpath , c_addr_cells , node - > parent - > fullpath ,
p_addr_cells ) ;
FAIL_PROP ( c , dti , node , prop , " empty \" ranges \" property but its "
" #address-cells (%d) differs from %s (%d) " ,
c_addr_cells , node - > parent - > fullpath ,
p_addr_cells ) ;
if ( p_size_cells ! = c_size_cells )
FAIL ( c , dti , " %s has empty \" ranges \" property but its "
" #size-cells (%d) differs from %s (%d) " ,
node - > fullpath , c_size_cells , node - > parent - > fullpath ,
p_size_cells ) ;
FAIL_PROP ( c , dti , node , prop , " empty \" ranges \" property but its "
" #size-cells (%d) differs from %s (%d) " ,
c_size_cells , node - > parent - > fullpath ,
p_size_cells ) ;
} else if ( ( prop - > val . len % entrylen ) ! = 0 ) {
FAIL ( c , dti , " \" ranges \" property in %s has invalid length (%d bytes) "
" (parent #address-cells == %d, child #address-cells == %d, "
" #size-cells == %d) " , node - > fullpath , prop - > val . len ,
p_addr_cells , c_addr_cells , c_size_cells ) ;
FAIL_PROP ( c , dti , node , prop , " \" ranges \" property has invalid length (%d bytes) "
" (parent #address-cells == %d, child #address-cells == %d, "
" #size-cells == %d) " , prop - > val . len ,
p_addr_cells , c_addr_cells , c_size_cells ) ;
}
}
WARNING ( ranges_format , check_ranges_format , NULL , & addr_size_cells ) ;
@ -696,41 +773,33 @@ static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *
node - > bus = & pci_bus ;
if ( ! strneq ( node - > name , " pci " , node - > basenamelen ) & &
! strneq ( node - > name , " pcie " , node - > basenamelen ) )
FAIL ( c , dti , " Node %s node name is not \" pci \" or \" pcie \" " ,
node - > fullpath ) ;
if ( ! strprefixeq ( node - > name , node - > basenamelen , " pci " ) & &
! strprefixeq ( node - > name , node - > basenamelen , " pcie " ) )
FAIL ( c , dti , node , " node name is not \" pci \" or \" pcie \" " ) ;
prop = get_property ( node , " ranges " ) ;
if ( ! prop )
FAIL ( c , dti , " Node %s missing ranges for PCI bridge (or not a bridge) " ,
node - > fullpath ) ;
FAIL ( c , dti , node , " missing ranges for PCI bridge (or not a bridge) " ) ;
if ( node_addr_cells ( node ) ! = 3 )
FAIL ( c , dti , " Node %s incorrect #address-cells for PCI bridge " ,
node - > fullpath ) ;
FAIL ( c , dti , node , " incorrect #address-cells for PCI bridge " ) ;
if ( node_size_cells ( node ) ! = 2 )
FAIL ( c , dti , " Node %s incorrect #size-cells for PCI bridge " ,
node - > fullpath ) ;
FAIL ( c , dti , node , " incorrect #size-cells for PCI bridge " ) ;
prop = get_property ( node , " bus-range " ) ;
if ( ! prop ) {
FAIL ( c , dti , " Node %s missing bus-range for PCI bridge " ,
node - > fullpath ) ;
FAIL ( c , dti , node , " missing bus-range for PCI bridge " ) ;
return ;
}
if ( prop - > val . len ! = ( sizeof ( cell_t ) * 2 ) ) {
FAIL ( c , dti , " Node %s bus-range must be 2 cells " ,
node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop , " value must be 2 cells " ) ;
return ;
}
cells = ( cell_t * ) prop - > val . val ;
if ( fdt32_to_cpu ( cells [ 0 ] ) > fdt32_to_cpu ( cells [ 1 ] ) )
FAIL ( c , dti , " Node %s bus-range 1st cell must be less than or equal to 2nd cell " ,
node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop , " 1st cell must be less than or equal to 2nd cell " ) ;
if ( fdt32_to_cpu ( cells [ 1 ] ) > 0xff )
FAIL ( c , dti , " Node %s bus-range maximum bus number must be less than 256 " ,
node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop , " maximum bus number must be less than 256 " ) ;
}
WARNING ( pci_bridge , check_pci_bridge , NULL ,
& device_type_is_string , & addr_size_cells ) ;
@ -760,8 +829,8 @@ static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struc
max_bus = fdt32_to_cpu ( cells [ 0 ] ) ;
}
if ( ( bus_num < min_bus ) | | ( bus_num > max_bus ) )
FAIL ( c , dti , " Node %s PCI bus number %d out of range, expected (%d - %d)" ,
node - > fullpath , bus_num , min_bus , max_bus ) ;
FAIL_PROP ( c , dti , node , prop , " PCI bus number %d out of range, expected (%d - %d) " ,
bus_num , min_bus , max_bus ) ;
}
WARNING ( pci_device_bus_num , check_pci_device_bus_num , NULL , & reg_format , & pci_bridge ) ;
@ -778,25 +847,22 @@ static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct no
prop = get_property ( node , " reg " ) ;
if ( ! prop ) {
FAIL ( c , dti , " Node %s missing PCI reg property " , node - > fullpath ) ;
FAIL ( c , dti , node , " missing PCI reg property " ) ;
return ;
}
cells = ( cell_t * ) prop - > val . val ;
if ( cells [ 1 ] | | cells [ 2 ] )
FAIL ( c , dti , " Node %s PCI reg config space address cells 2 and 3 must be 0 " ,
node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop , " PCI reg config space address cells 2 and 3 must be 0 " ) ;
reg = fdt32_to_cpu ( cells [ 0 ] ) ;
dev = ( reg & 0xf800 ) > > 11 ;
func = ( reg & 0x700 ) > > 8 ;
if ( reg & 0xff000000 )
FAIL ( c , dti , " Node %s PCI reg address is not configuration space " ,
node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop , " PCI reg address is not configuration space " ) ;
if ( reg & 0x000000ff )
FAIL ( c , dti , " Node %s PCI reg config space address register number must be 0 " ,
node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop , " PCI reg config space address register number must be 0 " ) ;
if ( func = = 0 ) {
snprintf ( unit_addr , sizeof ( unit_addr ) , " %x " , dev ) ;
@ -808,8 +874,8 @@ static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct no
if ( streq ( unitname , unit_addr ) )
return ;
FAIL ( c , dti , " Node %s PCI unit address format error, expected \" %s \" " ,
node - > fullpath , unit_addr ) ;
FAIL ( c , dti , node , " PCI unit address format error, expected \" %s \" " ,
unit_addr ) ;
}
WARNING ( pci_device_reg , check_pci_device_reg , NULL , & reg_format , & pci_bridge ) ;
@ -828,7 +894,7 @@ static bool node_is_compatible(struct node *node, const char *compat)
for ( str = prop - > val . val , end = str + prop - > val . len ; str < end ;
str + = strnlen ( str , end - str ) + 1 ) {
if ( strn eq ( str , compat , end - str ) )
if ( strprefix eq ( str , end - str , compat ) )
return true ;
}
return false ;
@ -865,7 +931,7 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no
if ( ! cells ) {
if ( node - > parent - > parent & & ! ( node - > bus = = & simple_bus ) )
FAIL ( c , dti , " Node %s missing or empty reg/ranges property " , node - > fullpath ) ;
FAIL ( c , dti , node , " missing or empty reg/ranges property " ) ;
return ;
}
@ -875,8 +941,8 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no
snprintf ( unit_addr , sizeof ( unit_addr ) , " % " PRIx64 , reg ) ;
if ( ! streq ( unitname , unit_addr ) )
FAIL ( c , dti , " Node %s simple-bus unit address format error, expected \" %s \" " ,
node - > fullpath , unit_addr ) ;
FAIL ( c , dti , node , " simple-bus unit address format error, expected \" %s \" " ,
unit_addr ) ;
}
WARNING ( simple_bus_reg , check_simple_bus_reg , NULL , & reg_format , & simple_bus_bridge ) ;
@ -892,14 +958,12 @@ static void check_unit_address_format(struct check *c, struct dt_info *dti,
return ;
if ( ! strncmp ( unitname , " 0x " , 2 ) ) {
FAIL ( c , dti , " Node %s unit name should not have leading \" 0x \" " ,
node - > fullpath ) ;
FAIL ( c , dti , node , " unit name should not have leading \" 0x \" " ) ;
/* skip over 0x for next test */
unitname + = 2 ;
}
if ( unitname [ 0 ] = = ' 0 ' & & isxdigit ( unitname [ 1 ] ) )
FAIL ( c , dti , " Node %s unit name should not have leading 0s " ,
node - > fullpath ) ;
FAIL ( c , dti , node , " unit name should not have leading 0s " ) ;
}
WARNING ( unit_address_format , check_unit_address_format , NULL ,
& node_name_format , & pci_bridge , & simple_bus_bridge ) ;
@ -922,16 +986,38 @@ static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti,
return ;
if ( node - > parent - > addr_cells = = - 1 )
FAIL ( c , dti , " Relying on default #address-cells value for %s " ,
node - > fullpath ) ;
FAIL ( c , dti , node , " Relying on default #address-cells value " ) ;
if ( node - > parent - > size_cells = = - 1 )
FAIL ( c , dti , " Relying on default #size-cells value for %s " ,
node - > fullpath ) ;
FAIL ( c , dti , node , " Relying on default #size-cells value " ) ;
}
WARNING ( avoid_default_addr_size , check_avoid_default_addr_size , NULL ,
& addr_size_cells ) ;
static void check_avoid_unnecessary_addr_size ( struct check * c , struct dt_info * dti ,
struct node * node )
{
struct property * prop ;
struct node * child ;
bool has_reg = false ;
if ( ! node - > parent | | node - > addr_cells < 0 | | node - > size_cells < 0 )
return ;
if ( get_property ( node , " ranges " ) | | ! node - > children )
return ;
for_each_child ( node , child ) {
prop = get_property ( child , " reg " ) ;
if ( prop )
has_reg = true ;
}
if ( ! has_reg )
FAIL ( c , dti , node , " unnecessary #address-cells/#size-cells without \" ranges \" or child \" reg \" property " ) ;
}
WARNING ( avoid_unnecessary_addr_size , check_avoid_unnecessary_addr_size , NULL , & avoid_default_addr_size ) ;
static void check_obsolete_chosen_interrupt_controller ( struct check * c ,
struct dt_info * dti ,
struct node * node )
@ -950,12 +1036,61 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
prop = get_property ( chosen , " interrupt-controller " ) ;
if ( prop )
FAIL ( c , dti , " /chosen has obsolete \" interrupt-controller \" "
" property " ) ;
FAIL_PROP ( c , dti , node , prop ,
" /chosen has obsolete \" interrupt-controller \ " property" ) ;
}
WARNING ( obsolete_chosen_interrupt_controller ,
check_obsolete_chosen_interrupt_controller , NULL ) ;
static void check_chosen_node_is_root ( struct check * c , struct dt_info * dti ,
struct node * node )
{
if ( ! streq ( node - > name , " chosen " ) )
return ;
if ( node - > parent ! = dti - > dt )
FAIL ( c , dti , node , " chosen node must be at root node " ) ;
}
WARNING ( chosen_node_is_root , check_chosen_node_is_root , NULL ) ;
static void check_chosen_node_bootargs ( struct check * c , struct dt_info * dti ,
struct node * node )
{
struct property * prop ;
if ( ! streq ( node - > name , " chosen " ) )
return ;
prop = get_property ( node , " bootargs " ) ;
if ( ! prop )
return ;
c - > data = prop - > name ;
check_is_string ( c , dti , node ) ;
}
WARNING ( chosen_node_bootargs , check_chosen_node_bootargs , NULL ) ;
static void check_chosen_node_stdout_path ( struct check * c , struct dt_info * dti ,
struct node * node )
{
struct property * prop ;
if ( ! streq ( node - > name , " chosen " ) )
return ;
prop = get_property ( node , " stdout-path " ) ;
if ( ! prop ) {
prop = get_property ( node , " linux,stdout-path " ) ;
if ( ! prop )
return ;
FAIL_PROP ( c , dti , node , prop , " Use 'stdout-path' instead " ) ;
}
c - > data = prop - > name ;
check_is_string ( c , dti , node ) ;
}
WARNING ( chosen_node_stdout_path , check_chosen_node_stdout_path , NULL ) ;
struct provider {
const char * prop_name ;
const char * cell_name ;
@ -972,8 +1107,9 @@ static void check_property_phandle_args(struct check *c,
int cell , cellsize = 0 ;
if ( prop - > val . len % sizeof ( cell_t ) ) {
FAIL ( c , dti , " property '%s' size (%d) is invalid, expected multiple of %zu in node %s " ,
prop - > name , prop - > val . len , sizeof ( cell_t ) , node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop ,
" property size (%d) is invalid, expected multiple of %zu " ,
prop - > val . len , sizeof ( cell_t ) ) ;
return ;
}
@ -1004,14 +1140,16 @@ static void check_property_phandle_args(struct check *c,
break ;
}
if ( ! m )
FAIL ( c , dti , " Property '%s', cell %d is not a phandle reference in %s " ,
prop - > name , cell , node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop ,
" cell %d is not a phandle reference " ,
cell ) ;
}
provider_node = get_node_by_phandle ( root , phandle ) ;
if ( ! provider_node ) {
FAIL ( c , dti , " Could not get phandle node for %s:%s(cell %d) " ,
node - > fullpath , prop - > name , cell ) ;
FAIL_PROP ( c , dti , node , prop ,
" Could not get phandle node for (cell %d) " ,
cell ) ;
break ;
}
@ -1021,16 +1159,17 @@ static void check_property_phandle_args(struct check *c,
} else if ( provider - > optional ) {
cellsize = 0 ;
} else {
FAIL ( c , dti , " Missing property '%s' in node %s or bad phandle (referred from %s: %s[%d]) " ,
FAIL ( c , dti , node , " Missing property '%s' in node %s or bad phandle (referred from %s[%d]) " ,
provider - > cell_name ,
provider_node - > fullpath ,
node - > fullpath , prop - > name , cell ) ;
prop - > name , cell ) ;
break ;
}
if ( prop - > val . len < ( ( cell + cellsize + 1 ) * sizeof ( cell_t ) ) ) {
FAIL ( c , dti , " %s property size (%d) too small for cell size %d in %s " ,
prop - > name , prop - > val . len , cellsize , node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop ,
" property size (%d) too small for cell size %d " ,
prop - > val . len , cellsize ) ;
}
}
}
@ -1066,7 +1205,7 @@ WARNING_PROPERTY_PHANDLE_CELLS(phys, "phys", "#phy-cells");
WARNING_PROPERTY_PHANDLE_CELLS ( power_domains , " power-domains " , " #power-domain-cells " ) ;
WARNING_PROPERTY_PHANDLE_CELLS ( pwms , " pwms " , " #pwm-cells " ) ;
WARNING_PROPERTY_PHANDLE_CELLS ( resets , " resets " , " #reset-cells " ) ;
WARNING_PROPERTY_PHANDLE_CELLS ( sound_dais , " sound-dais " , " #sound-dai-cells " ) ;
WARNING_PROPERTY_PHANDLE_CELLS ( sound_dai , " sound-dai " , " #sound-dai-cells " ) ;
WARNING_PROPERTY_PHANDLE_CELLS ( thermal_sensors , " thermal-sensors " , " #thermal-sensor-cells " ) ;
static bool prop_is_gpio ( struct property * prop )
@ -1132,8 +1271,8 @@ static void check_deprecated_gpio_property(struct check *c,
if ( ! streq ( str , " gpio " ) )
continue ;
FAIL ( c , dti , " '[*-]gpio' is deprecated, use '[*-]gpios' instead for %s:%s " ,
node - > fullpath , prop - > name ) ;
FAIL_PROP ( c , dti , node , prop ,
" '[*-]gpio' is deprecated, use '[*-]gpios' instead " ) ;
}
}
@ -1167,9 +1306,8 @@ static void check_interrupts_property(struct check *c,
return ;
if ( irq_prop - > val . len % sizeof ( cell_t ) )
FAIL ( c , dti , " property '%s' size (%d) is invalid, expected multiple of %zu in node %s " ,
irq_prop - > name , irq_prop - > val . len , sizeof ( cell_t ) ,
node - > fullpath ) ;
FAIL_PROP ( c , dti , node , irq_prop , " size (%d) is invalid, expected multiple of %zu " ,
irq_prop - > val . len , sizeof ( cell_t ) ) ;
while ( parent & & ! prop ) {
if ( parent ! = node & & node_is_interrupt_provider ( parent ) ) {
@ -1187,14 +1325,12 @@ static void check_interrupts_property(struct check *c,
irq_node = get_node_by_phandle ( root , phandle ) ;
if ( ! irq_node ) {
FAIL ( c , dti , " Bad interrupt-parent phandle for %s " ,
node - > fullpath ) ;
FAIL_PROP ( c , dti , parent , prop , " Bad phandle " ) ;
return ;
}
if ( ! node_is_interrupt_provider ( irq_node ) )
FAIL ( c , dti ,
" Missing interrupt-controller or interrupt-map property in %s " ,
irq_node - > fullpath ) ;
FAIL ( c , dti , irq_node ,
" Missing interrupt-controller or interrupt-map property " ) ;
break ;
}
@ -1203,23 +1339,21 @@ static void check_interrupts_property(struct check *c,
}
if ( ! irq_node ) {
FAIL ( c , dti , " Missing interrupt-parent for %s " , node - > fullpath ) ;
FAIL ( c , dti , node , " Missing interrupt-parent " ) ;
return ;
}
prop = get_property ( irq_node , " #interrupt-cells " ) ;
if ( ! prop ) {
FAIL ( c , dti , " Missing #interrupt-cells in interrupt-parent %s " ,
irq_node - > fullpath ) ;
FAIL ( c , dti , irq_node , " Missing #interrupt-cells in interrupt-parent " ) ;
return ;
}
irq_cells = propval_cell ( prop ) ;
if ( irq_prop - > val . len % ( irq_cells * sizeof ( cell_t ) ) ) {
FAIL ( c , dti ,
" interrupts size is (%d), expected multiple of %d in %s " ,
irq_prop - > val . len , ( int ) ( irq_cells * sizeof ( cell_t ) ) ,
node - > fullpath ) ;
FAIL_PROP ( c , dti , node , prop ,
" size is (%d), expected multiple of %d " ,
irq_prop - > val . len , ( int ) ( irq_cells * sizeof ( cell_t ) ) ) ;
}
}
WARNING ( interrupts_property , check_interrupts_property , & phandle_references ) ;
@ -1236,6 +1370,9 @@ static struct check *check_table[] = {
& address_cells_is_cell , & size_cells_is_cell , & interrupt_cells_is_cell ,
& device_type_is_string , & model_is_string , & status_is_string ,
& label_is_string ,
& compatible_is_string_list , & names_is_string_list ,
& property_name_chars_strict ,
& node_name_chars_strict ,
@ -1253,7 +1390,9 @@ static struct check *check_table[] = {
& simple_bus_reg ,
& avoid_default_addr_size ,
& avoid_unnecessary_addr_size ,
& obsolete_chosen_interrupt_controller ,
& chosen_node_is_root , & chosen_node_bootargs , & chosen_node_stdout_path ,
& clocks_property ,
& cooling_device_property ,
@ -1269,13 +1408,15 @@ static struct check *check_table[] = {
& power_domains_property ,
& pwms_property ,
& resets_property ,
& sound_dais _property ,
& sound_dai_property ,
& thermal_sensors_property ,
& deprecated_gpio_property ,
& gpios_property ,
& interrupts_property ,
& alias_paths ,
& always_fail ,
} ;