From a878b91019809b1f2276bebefd6c96567431c316 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 21 Jan 2014 12:51:00 +0000 Subject: [PATCH 01/29] scripts/dtc: Update shipped files to build with bison 2.7.12 Preparation patch before updating to upstream dtc version 1.4.0. This change only contains the changes caused by a new version of bison on the shipped files. There are no functional changes. The shipped files were build on an Ubuntu 13.10 system Signed-off-by: Grant Likely --- scripts/dtc/dtc-parser.tab.c_shipped | 469 +++++++++++---------------- scripts/dtc/dtc-parser.tab.h_shipped | 36 +- 2 files changed, 222 insertions(+), 283 deletions(-) diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped index ee1d8c3042fb..c8769d550cfb 100644 --- a/scripts/dtc/dtc-parser.tab.c_shipped +++ b/scripts/dtc/dtc-parser.tab.c_shipped @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.5. */ +/* A Bison parser, made by GNU Bison 2.7.12-4996. */ /* Bison implementation for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -44,7 +44,7 @@ #define YYBISON 1 /* Bison version. */ -#define YYBISON_VERSION "2.5" +#define YYBISON_VERSION "2.7.12-4996" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -58,14 +58,11 @@ /* Pull parsers. */ #define YYPULL 1 -/* Using locations. */ -#define YYLSP_NEEDED 0 /* Copy the first part of user declarations. */ - -/* Line 268 of yacc.c */ +/* Line 371 of yacc.c */ #line 21 "dtc-parser.y" #include @@ -85,14 +82,16 @@ extern int treesource_error; static unsigned long long eval_literal(const char *s, int base, int bits); static unsigned char eval_char_literal(const char *s); +/* Line 371 of yacc.c */ +#line 87 "dtc-parser.tab.c" -/* Line 268 of yacc.c */ -#line 91 "dtc-parser.tab.c" - -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif +# ifndef YY_NULL +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULL nullptr +# else +# define YY_NULL 0 +# endif +# endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE @@ -102,11 +101,17 @@ static unsigned char eval_char_literal(const char *s); # define YYERROR_VERBOSE 0 #endif -/* Enabling the token table. */ -#ifndef YYTOKEN_TABLE -# define YYTOKEN_TABLE 0 +/* In a future release of Bison, this section will be replaced + by #include "dtc-parser.tab.h". */ +#ifndef YY_YY_DTC_PARSER_TAB_H_INCLUDED +# define YY_YY_DTC_PARSER_TAB_H_INCLUDED +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; #endif - /* Tokens. */ #ifndef YYTOKENTYPE @@ -140,12 +145,10 @@ static unsigned char eval_char_literal(const char *s); #endif - #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { - -/* Line 293 of yacc.c */ +/* Line 387 of yacc.c */ #line 40 "dtc-parser.y" char *propnodename; @@ -168,21 +171,36 @@ typedef union YYSTYPE uint64_t integer; - -/* Line 293 of yacc.c */ -#line 174 "dtc-parser.tab.c" +/* Line 387 of yacc.c */ +#line 176 "dtc-parser.tab.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif +extern YYSTYPE yylval; + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + +#endif /* !YY_YY_DTC_PARSER_TAB_H_INCLUDED */ /* Copy the second part of user declarations. */ - -/* Line 343 of yacc.c */ -#line 186 "dtc-parser.tab.c" +/* Line 390 of yacc.c */ +#line 204 "dtc-parser.tab.c" #ifdef short # undef short @@ -235,24 +253,33 @@ typedef short int yytype_int16; # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ -# define YY_(msgid) dgettext ("bison-runtime", msgid) +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) # endif # endif # ifndef YY_ -# define YY_(msgid) msgid +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef __attribute__ +/* This feature is available in gcc versions 2.5 and later. */ +# if (! defined __GNUC__ || __GNUC__ < 2 \ + || (__GNUC__ == 2 && __GNUC_MINOR__ < 5)) +# define __attribute__(Spec) /* empty */ # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ -# define YYUSE(e) ((void) (e)) +# define YYUSE(E) ((void) (E)) #else -# define YYUSE(e) /* empty */ +# define YYUSE(E) /* empty */ #endif + /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint -# define YYID(n) (n) +# define YYID(N) (N) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) @@ -288,6 +315,7 @@ YYID (yyi) # if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif @@ -379,20 +407,20 @@ union yyalloc #endif #if defined YYCOPY_NEEDED && YYCOPY_NEEDED -/* Copy COUNT objects from FROM to TO. The source and destination do +/* Copy COUNT objects from SRC to DST. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) # else -# define YYCOPY(To, From, Count) \ - do \ - { \ - YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ while (YYID (0)) # endif # endif @@ -513,7 +541,7 @@ static const yytype_uint16 yyrline[] = }; #endif -#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +#if YYDEBUG || YYERROR_VERBOSE || 0 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = @@ -530,7 +558,7 @@ static const char *const yytname[] = "integer_expr", "integer_trinary", "integer_or", "integer_and", "integer_bitor", "integer_bitxor", "integer_bitand", "integer_eq", "integer_rela", "integer_shift", "integer_add", "integer_mul", - "integer_unary", "bytestring", "subnodes", "subnode", 0 + "integer_unary", "bytestring", "subnodes", "subnode", YY_NULL }; #endif @@ -655,10 +683,10 @@ static const yytype_uint8 yytable[] = 137, 0, 73, 139 }; -#define yypact_value_is_default(yystate) \ - ((yystate) == (-78)) +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-78))) -#define yytable_value_is_error(yytable_value) \ +#define yytable_value_is_error(Yytable_value) \ YYID (0) static const yytype_int16 yycheck[] = @@ -727,62 +755,35 @@ static const yytype_uint8 yystos[] = #define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) - +/* Error token number */ #define YYTERROR 1 #define YYERRCODE 256 -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) -#endif - - /* This macro is provided for backward compatibility. */ - #ifndef YY_LOCATION_PRINT # define YY_LOCATION_PRINT(File, Loc) ((void) 0) #endif /* YYLEX -- calling `yylex' with the right arguments. */ - #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else @@ -832,6 +833,8 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) YYSTYPE const * const yyvaluep; #endif { + FILE *yyo = yyoutput; + YYUSE (yyo); if (!yyvaluep) return; # ifdef YYPRINT @@ -840,11 +843,7 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep) # else YYUSE (yyoutput); # endif - switch (yytype) - { - default: - break; - } + YYUSE (yytype); } @@ -1083,12 +1082,11 @@ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yytype_int16 *yyssp, int yytoken) { - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); + YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]); YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ - const char *yyformat = 0; + const char *yyformat = YY_NULL; /* Arguments of yyformat. */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; /* Number of reported tokens (one for the "unexpected", one per @@ -1148,11 +1146,13 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, break; } yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - if (! (yysize <= yysize1 - && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } } } } @@ -1172,10 +1172,12 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, # undef YYCASE_ } - yysize1 = yysize + yystrlen (yyformat); - if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) - return 2; - yysize = yysize1; + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } if (*yymsg_alloc < yysize) { @@ -1231,36 +1233,26 @@ yydestruct (yymsg, yytype, yyvaluep) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - switch (yytype) - { - - default: - break; - } + YYUSE (yytype); } -/* Prevent warnings from -Wmissing-prototypes. */ -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ /* The lookahead symbol. */ int yychar; + +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + /* The semantic value of the lookahead symbol. */ -YYSTYPE yylval; +YYSTYPE yylval YY_INITIAL_VALUE(yyval_default); /* Number of syntax errors so far. */ int yynerrs; @@ -1300,7 +1292,7 @@ yyparse () `yyss': related to states. `yyvs': related to semantic values. - Refer to the stacks thru separate pointers, to allow yyoverflow + Refer to the stacks through separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ @@ -1318,7 +1310,7 @@ yyparse () int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ - int yytoken; + int yytoken = 0; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; @@ -1336,9 +1328,8 @@ yyparse () Keep to zero when no symbol should be popped. */ int yylen = 0; - yytoken = 0; - yyss = yyssa; - yyvs = yyvsa; + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); @@ -1347,14 +1338,6 @@ yyparse () yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ - - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ - yyssp = yyss; - yyvsp = yyvs; - goto yysetstate; /*------------------------------------------------------------. @@ -1495,7 +1478,9 @@ yybackup: yychar = YYEMPTY; yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END goto yynewstate; @@ -1532,8 +1517,7 @@ yyreduce: switch (yyn) { case 2: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 110 "dtc-parser.y" { the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node), @@ -1542,8 +1526,7 @@ yyreduce: break; case 3: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 118 "dtc-parser.y" { (yyval.re) = NULL; @@ -1551,8 +1534,7 @@ yyreduce: break; case 4: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 122 "dtc-parser.y" { (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re)); @@ -1560,8 +1542,7 @@ yyreduce: break; case 5: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 129 "dtc-parser.y" { (yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].integer), (yyvsp[(3) - (4)].integer)); @@ -1569,8 +1550,7 @@ yyreduce: break; case 6: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 133 "dtc-parser.y" { add_label(&(yyvsp[(2) - (2)].re)->labels, (yyvsp[(1) - (2)].labelref)); @@ -1579,8 +1559,7 @@ yyreduce: break; case 7: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 141 "dtc-parser.y" { (yyval.node) = name_node((yyvsp[(2) - (2)].node), ""); @@ -1588,8 +1567,7 @@ yyreduce: break; case 8: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 145 "dtc-parser.y" { (yyval.node) = merge_nodes((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node)); @@ -1597,8 +1575,7 @@ yyreduce: break; case 9: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 149 "dtc-parser.y" { struct node *target = get_node_by_ref((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].labelref)); @@ -1612,8 +1589,7 @@ yyreduce: break; case 10: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 159 "dtc-parser.y" { struct node *target = get_node_by_ref((yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].labelref)); @@ -1628,8 +1604,7 @@ yyreduce: break; case 11: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 173 "dtc-parser.y" { (yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist)); @@ -1637,8 +1612,7 @@ yyreduce: break; case 12: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 180 "dtc-parser.y" { (yyval.proplist) = NULL; @@ -1646,8 +1620,7 @@ yyreduce: break; case 13: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 184 "dtc-parser.y" { (yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist)); @@ -1655,8 +1628,7 @@ yyreduce: break; case 14: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 191 "dtc-parser.y" { (yyval.prop) = build_property((yyvsp[(1) - (4)].propnodename), (yyvsp[(3) - (4)].data)); @@ -1664,8 +1636,7 @@ yyreduce: break; case 15: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 195 "dtc-parser.y" { (yyval.prop) = build_property((yyvsp[(1) - (2)].propnodename), empty_data); @@ -1673,8 +1644,7 @@ yyreduce: break; case 16: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 199 "dtc-parser.y" { (yyval.prop) = build_property_delete((yyvsp[(2) - (3)].propnodename)); @@ -1682,8 +1652,7 @@ yyreduce: break; case 17: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 203 "dtc-parser.y" { add_label(&(yyvsp[(2) - (2)].prop)->labels, (yyvsp[(1) - (2)].labelref)); @@ -1692,8 +1661,7 @@ yyreduce: break; case 18: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 211 "dtc-parser.y" { (yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data)); @@ -1701,8 +1669,7 @@ yyreduce: break; case 19: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 215 "dtc-parser.y" { (yyval.data) = data_merge((yyvsp[(1) - (3)].data), (yyvsp[(2) - (3)].array).data); @@ -1710,8 +1677,7 @@ yyreduce: break; case 20: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 219 "dtc-parser.y" { (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data)); @@ -1719,8 +1685,7 @@ yyreduce: break; case 21: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 223 "dtc-parser.y" { (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref)); @@ -1728,8 +1693,7 @@ yyreduce: break; case 22: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 227 "dtc-parser.y" { FILE *f = srcfile_relative_open((yyvsp[(4) - (9)].data).val, NULL); @@ -1750,8 +1714,7 @@ yyreduce: break; case 23: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 244 "dtc-parser.y" { FILE *f = srcfile_relative_open((yyvsp[(4) - (5)].data).val, NULL); @@ -1765,8 +1728,7 @@ yyreduce: break; case 24: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 254 "dtc-parser.y" { (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref)); @@ -1774,8 +1736,7 @@ yyreduce: break; case 25: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 261 "dtc-parser.y" { (yyval.data) = empty_data; @@ -1783,8 +1744,7 @@ yyreduce: break; case 26: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 265 "dtc-parser.y" { (yyval.data) = (yyvsp[(1) - (2)].data); @@ -1792,8 +1752,7 @@ yyreduce: break; case 27: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 269 "dtc-parser.y" { (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref)); @@ -1801,8 +1760,7 @@ yyreduce: break; case 28: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 276 "dtc-parser.y" { (yyval.array).data = empty_data; @@ -1821,8 +1779,7 @@ yyreduce: break; case 29: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 291 "dtc-parser.y" { (yyval.array).data = empty_data; @@ -1831,8 +1788,7 @@ yyreduce: break; case 30: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 296 "dtc-parser.y" { if ((yyvsp[(1) - (2)].array).bits < 64) { @@ -1856,8 +1812,7 @@ yyreduce: break; case 31: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 316 "dtc-parser.y" { uint64_t val = ~0ULL >> (64 - (yyvsp[(1) - (2)].array).bits); @@ -1875,8 +1830,7 @@ yyreduce: break; case 32: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 330 "dtc-parser.y" { (yyval.array).data = data_add_marker((yyvsp[(1) - (2)].array).data, LABEL, (yyvsp[(2) - (2)].labelref)); @@ -1884,8 +1838,7 @@ yyreduce: break; case 33: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 337 "dtc-parser.y" { (yyval.integer) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64); @@ -1893,8 +1846,7 @@ yyreduce: break; case 34: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 341 "dtc-parser.y" { (yyval.integer) = eval_char_literal((yyvsp[(1) - (1)].literal)); @@ -1902,8 +1854,7 @@ yyreduce: break; case 35: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 345 "dtc-parser.y" { (yyval.integer) = (yyvsp[(2) - (3)].integer); @@ -1911,162 +1862,139 @@ yyreduce: break; case 38: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 356 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (5)].integer) ? (yyvsp[(3) - (5)].integer) : (yyvsp[(5) - (5)].integer); } break; case 40: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 361 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) || (yyvsp[(3) - (3)].integer); } break; case 42: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 366 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) && (yyvsp[(3) - (3)].integer); } break; case 44: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 371 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) | (yyvsp[(3) - (3)].integer); } break; case 46: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 376 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) ^ (yyvsp[(3) - (3)].integer); } break; case 48: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 381 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) & (yyvsp[(3) - (3)].integer); } break; case 50: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 386 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) == (yyvsp[(3) - (3)].integer); } break; case 51: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 387 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) != (yyvsp[(3) - (3)].integer); } break; case 53: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 392 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) < (yyvsp[(3) - (3)].integer); } break; case 54: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 393 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) > (yyvsp[(3) - (3)].integer); } break; case 55: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 394 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) <= (yyvsp[(3) - (3)].integer); } break; case 56: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 395 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) >= (yyvsp[(3) - (3)].integer); } break; case 57: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 399 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) << (yyvsp[(3) - (3)].integer); } break; case 58: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 400 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) >> (yyvsp[(3) - (3)].integer); } break; case 60: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 405 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) + (yyvsp[(3) - (3)].integer); } break; case 61: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 406 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) - (yyvsp[(3) - (3)].integer); } break; case 63: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 411 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) * (yyvsp[(3) - (3)].integer); } break; case 64: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 412 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) / (yyvsp[(3) - (3)].integer); } break; case 65: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 413 "dtc-parser.y" { (yyval.integer) = (yyvsp[(1) - (3)].integer) % (yyvsp[(3) - (3)].integer); } break; case 68: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 419 "dtc-parser.y" { (yyval.integer) = -(yyvsp[(2) - (2)].integer); } break; case 69: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 420 "dtc-parser.y" { (yyval.integer) = ~(yyvsp[(2) - (2)].integer); } break; case 70: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 421 "dtc-parser.y" { (yyval.integer) = !(yyvsp[(2) - (2)].integer); } break; case 71: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 426 "dtc-parser.y" { (yyval.data) = empty_data; @@ -2074,8 +2002,7 @@ yyreduce: break; case 72: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 430 "dtc-parser.y" { (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte)); @@ -2083,8 +2010,7 @@ yyreduce: break; case 73: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 434 "dtc-parser.y" { (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref)); @@ -2092,8 +2018,7 @@ yyreduce: break; case 74: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 441 "dtc-parser.y" { (yyval.nodelist) = NULL; @@ -2101,8 +2026,7 @@ yyreduce: break; case 75: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 445 "dtc-parser.y" { (yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist)); @@ -2110,8 +2034,7 @@ yyreduce: break; case 76: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 449 "dtc-parser.y" { print_error("syntax error: properties must precede subnodes"); @@ -2120,8 +2043,7 @@ yyreduce: break; case 77: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 457 "dtc-parser.y" { (yyval.node) = name_node((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].propnodename)); @@ -2129,8 +2051,7 @@ yyreduce: break; case 78: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 461 "dtc-parser.y" { (yyval.node) = name_node(build_node_delete(), (yyvsp[(2) - (3)].propnodename)); @@ -2138,8 +2059,7 @@ yyreduce: break; case 79: - -/* Line 1806 of yacc.c */ +/* Line 1787 of yacc.c */ #line 465 "dtc-parser.y" { add_label(&(yyvsp[(2) - (2)].node)->labels, (yyvsp[(1) - (2)].labelref)); @@ -2148,9 +2068,8 @@ yyreduce: break; - -/* Line 1806 of yacc.c */ -#line 2154 "dtc-parser.tab.c" +/* Line 1787 of yacc.c */ +#line 2073 "dtc-parser.tab.c" default: break; } /* User semantic actions sometimes alter yychar, and that requires @@ -2313,7 +2232,9 @@ yyerrlab1: YY_STACK_PRINT (yyss, yyssp); } + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END /* Shift the error token. */ @@ -2337,7 +2258,7 @@ yyabortlab: yyresult = 1; goto yyreturn; -#if !defined(yyoverflow) || YYERROR_VERBOSE +#if !defined yyoverflow || YYERROR_VERBOSE /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ @@ -2379,8 +2300,7 @@ yyreturn: } - -/* Line 2067 of yacc.c */ +/* Line 2050 of yacc.c */ #line 471 "dtc-parser.y" @@ -2444,4 +2364,3 @@ static unsigned char eval_char_literal(const char *s) return c; } - diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped index 25d3b88c6132..b2e7a86cd85e 100644 --- a/scripts/dtc/dtc-parser.tab.h_shipped +++ b/scripts/dtc/dtc-parser.tab.h_shipped @@ -1,8 +1,8 @@ -/* A Bison parser, made by GNU Bison 2.5. */ +/* A Bison parser, made by GNU Bison 2.7.12-4996. */ /* Bison interface for Yacc-like parsers in C - Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. + Copyright (C) 1984, 1989-1990, 2000-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,6 +30,15 @@ This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ +#ifndef YY_YY_DTC_PARSER_TAB_H_INCLUDED +# define YY_YY_DTC_PARSER_TAB_H_INCLUDED +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG +extern int yydebug; +#endif /* Tokens. */ #ifndef YYTOKENTYPE @@ -63,12 +72,10 @@ #endif - #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { - -/* Line 2068 of yacc.c */ +/* Line 2053 of yacc.c */ #line 40 "dtc-parser.y" char *propnodename; @@ -91,9 +98,8 @@ typedef union YYSTYPE uint64_t integer; - -/* Line 2068 of yacc.c */ -#line 97 "dtc-parser.tab.h" +/* Line 2053 of yacc.c */ +#line 103 "dtc-parser.tab.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ @@ -102,4 +108,18 @@ typedef union YYSTYPE extern YYSTYPE yylval; +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ +#endif /* !YY_YY_DTC_PARSER_TAB_H_INCLUDED */ From 73ab39b14cdf6b83da6817166f6c8a9dcc25e392 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 21 Jan 2014 12:54:49 +0000 Subject: [PATCH 02/29] scripts/dtc: Update to upstream version v1.4.0 Update to the latest version of dtc with the following notable enhancements and bug fixes: * fdtput: expand fdt if value does not fit * dtc/fdt{get, put}/convert-dtsv0-lexer: convert to new usage helpers * libfdt: Add fdt_next_subnode() to permit easy subnode iteration * utilfdt_read: pass back up the length of data read * util_version: new helper for displaying version info * die: constify format string arg * utilfdt_read_err: use xmalloc funcs * Export fdt_stringlist_contains() * dtc: Drop the '-S is deprecated' warning * dtc/libfdt: sparse fixes * dtc/libfdt: introduce fdt types for annotation by endian checkers * Fix util_is_printable_string * dtc: srcpos_verror() should print to stderr * libfdt: Added missing functions to shared library Shipped bison/flex generated files were built on an Ubuntu 13.10 system. Signed-off-by: Grant Likely --- scripts/dtc/dtc.c | 119 ++++++++++++++++---------------- scripts/dtc/dtc.h | 1 - scripts/dtc/srcpos.c | 6 +- scripts/dtc/util.c | 141 ++++++++++++++++++++++++++++++++++---- scripts/dtc/util.h | 107 +++++++++++++++++++++++++++-- scripts/dtc/version_gen.h | 2 +- 6 files changed, 294 insertions(+), 82 deletions(-) diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c index a375683c1534..e3c96536fd9d 100644 --- a/scripts/dtc/dtc.c +++ b/scripts/dtc/dtc.c @@ -21,8 +21,6 @@ #include "dtc.h" #include "srcpos.h" -#include "version_gen.h" - /* * Command line options */ @@ -49,55 +47,60 @@ static void fill_fullpaths(struct node *tree, const char *prefix) fill_fullpaths(child, tree->fullpath); } -static void __attribute__ ((noreturn)) usage(void) -{ - fprintf(stderr, "Usage:\n"); - fprintf(stderr, "\tdtc [options] \n"); - fprintf(stderr, "\nOptions:\n"); - fprintf(stderr, "\t-h\n"); - fprintf(stderr, "\t\tThis help text\n"); - fprintf(stderr, "\t-q\n"); - fprintf(stderr, "\t\tQuiet: -q suppress warnings, -qq errors, -qqq all\n"); - fprintf(stderr, "\t-I \n"); - fprintf(stderr, "\t\tInput formats are:\n"); - fprintf(stderr, "\t\t\tdts - device tree source text\n"); - fprintf(stderr, "\t\t\tdtb - device tree blob\n"); - fprintf(stderr, "\t\t\tfs - /proc/device-tree style directory\n"); - fprintf(stderr, "\t-o \n"); - fprintf(stderr, "\t-O \n"); - fprintf(stderr, "\t\tOutput formats are:\n"); - fprintf(stderr, "\t\t\tdts - device tree source text\n"); - fprintf(stderr, "\t\t\tdtb - device tree blob\n"); - fprintf(stderr, "\t\t\tasm - assembler source\n"); - fprintf(stderr, "\t-V \n"); - fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION); - fprintf(stderr, "\t-d \n"); - fprintf(stderr, "\t-R \n"); - fprintf(stderr, "\t\tMake space for reserve map entries (relevant for \n\t\tdtb and asm output only)\n"); - fprintf(stderr, "\t-S \n"); - fprintf(stderr, "\t\tMake the blob at least long (extra space)\n"); - fprintf(stderr, "\t-p \n"); - fprintf(stderr, "\t\tAdd padding to the blob of long (extra space)\n"); - fprintf(stderr, "\t-b \n"); - fprintf(stderr, "\t\tSet the physical boot cpu\n"); - fprintf(stderr, "\t-f\n"); - fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n"); - fprintf(stderr, "\t-i\n"); - fprintf(stderr, "\t\tAdd a path to search for include files\n"); - fprintf(stderr, "\t-s\n"); - fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n"); - fprintf(stderr, "\t-v\n"); - fprintf(stderr, "\t\tPrint DTC version and exit\n"); - fprintf(stderr, "\t-H \n"); - fprintf(stderr, "\t\tphandle formats are:\n"); - fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n"); - fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n"); - fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n"); - fprintf(stderr, "\t-W [no-]\n"); - fprintf(stderr, "\t-E [no-]\n"); - fprintf(stderr, "\t\t\tenable or disable warnings and errors\n"); - exit(3); -} +/* Usage related data. */ +static const char usage_synopsis[] = "dtc [options] "; +static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv"; +static struct option const usage_long_opts[] = { + {"quiet", no_argument, NULL, 'q'}, + {"in-format", a_argument, NULL, 'I'}, + {"out", a_argument, NULL, 'o'}, + {"out-format", a_argument, NULL, 'O'}, + {"out-version", a_argument, NULL, 'V'}, + {"out-dependency", a_argument, NULL, 'd'}, + {"reserve", a_argument, NULL, 'R'}, + {"space", a_argument, NULL, 'S'}, + {"pad", a_argument, NULL, 'p'}, + {"boot-cpu", a_argument, NULL, 'b'}, + {"force", no_argument, NULL, 'f'}, + {"include", a_argument, NULL, 'i'}, + {"sort", no_argument, NULL, 's'}, + {"phandle", a_argument, NULL, 'H'}, + {"warning", a_argument, NULL, 'W'}, + {"error", a_argument, NULL, 'E'}, + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'v'}, + {NULL, no_argument, NULL, 0x0}, +}; +static const char * const usage_opts_help[] = { + "\n\tQuiet: -q suppress warnings, -qq errors, -qqq all", + "\n\tInput formats are:\n" + "\t\tdts - device tree source text\n" + "\t\tdtb - device tree blob\n" + "\t\tfs - /proc/device-tree style directory", + "\n\tOutput file", + "\n\tOutput formats are:\n" + "\t\tdts - device tree source text\n" + "\t\tdtb - device tree blob\n" + "\t\tasm - assembler source", + "\n\tBlob version to produce, defaults to %d (for dtb and asm output)", //, DEFAULT_FDT_VERSION); + "\n\tOutput dependency file", + "\n\ttMake space for reserve map entries (for dtb and asm output)", + "\n\tMake the blob at least long (extra space)", + "\n\tAdd padding to the blob of long (extra space)", + "\n\tSet the physical boot cpu", + "\n\tTry to produce output even if the input tree has errors", + "\n\tAdd a path to search for include files", + "\n\tSort nodes and properties before outputting (useful for comparing trees)", + "\n\tValid phandle formats are:\n" + "\t\tlegacy - \"linux,phandle\" properties only\n" + "\t\tepapr - \"phandle\" properties only\n" + "\t\tboth - Both \"linux,phandle\" and \"phandle\" properties", + "\n\tEnable/disable warnings (prefix with \"no-\")", + "\n\tEnable/disable errors (prefix with \"no-\")", + "\n\tPrint this help and exit", + "\n\tPrint version and exit", + NULL, +}; int main(int argc, char *argv[]) { @@ -118,8 +121,7 @@ int main(int argc, char *argv[]) minsize = 0; padsize = 0; - while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:")) - != EOF) { + while ((opt = util_getopt_long()) != EOF) { switch (opt) { case 'I': inform = optarg; @@ -158,8 +160,7 @@ int main(int argc, char *argv[]) srcfile_add_search_path(optarg); break; case 'v': - printf("Version: %s\n", DTC_VERSION); - exit(0); + util_version(); case 'H': if (streq(optarg, "legacy")) phandle_format = PHANDLE_LEGACY; @@ -185,13 +186,14 @@ int main(int argc, char *argv[]) break; case 'h': + usage(NULL); default: - usage(); + usage("unknown option"); } } if (argc > (optind+1)) - usage(); + usage("missing files"); else if (argc < (optind+1)) arg = "-"; else @@ -201,9 +203,6 @@ int main(int argc, char *argv[]) if (minsize && padsize) die("Can't set both -p and -S\n"); - if (minsize) - fprintf(stderr, "DTC: Use of \"-S\" is deprecated; it will be removed soon, use \"-p\" instead\n"); - if (depname) { depfile = fopen(depname, "w"); if (!depfile) diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h index 3e42a071070e..264a20cf66a8 100644 --- a/scripts/dtc/dtc.h +++ b/scripts/dtc/dtc.h @@ -66,7 +66,6 @@ typedef uint32_t cell_t; #define strneq(a, b, n) (strncmp((a), (b), (n)) == 0) #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) /* Data blobs */ enum markertype { diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c index 246ab4bc0d9d..c20bc5315bc1 100644 --- a/scripts/dtc/srcpos.c +++ b/scripts/dtc/srcpos.c @@ -297,9 +297,9 @@ srcpos_verror(struct srcpos *pos, char const *fmt, va_list va) srcstr = srcpos_string(pos); - fprintf(stdout, "Error: %s ", srcstr); - vfprintf(stdout, fmt, va); - fprintf(stdout, "\n"); + fprintf(stderr, "Error: %s ", srcstr); + vfprintf(stderr, fmt, va); + fprintf(stderr, "\n"); } void diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c index 2422c34e11df..3055c16e980d 100644 --- a/scripts/dtc/util.c +++ b/scripts/dtc/util.c @@ -34,6 +34,7 @@ #include "libfdt.h" #include "util.h" +#include "version_gen.h" char *xstrdup(const char *s) { @@ -72,7 +73,7 @@ char *join_path(const char *path, const char *name) int util_is_printable_string(const void *data, int len) { const char *s = data; - const char *ss; + const char *ss, *se; /* zero length is not */ if (len == 0) @@ -82,13 +83,19 @@ int util_is_printable_string(const void *data, int len) if (s[len - 1] != '\0') return 0; - ss = s; - while (*s && isprint(*s)) - s++; + se = s + len; - /* not zero, or not done yet */ - if (*s != '\0' || (s + 1 - ss) < len) - return 0; + while (s < se) { + ss = s; + while (s < se && *s && isprint(*s)) + s++; + + /* not zero, or not done yet */ + if (*s != '\0' || s == ss) + return 0; + + s++; + } return 1; } @@ -191,7 +198,7 @@ char get_escape_char(const char *s, int *i) return val; } -int utilfdt_read_err(const char *filename, char **buffp) +int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len) { int fd = 0; /* assume stdin */ char *buf = NULL; @@ -206,12 +213,12 @@ int utilfdt_read_err(const char *filename, char **buffp) } /* Loop until we have read everything */ - buf = malloc(bufsize); + buf = xmalloc(bufsize); do { /* Expand the buffer to hold the next chunk */ if (offset == bufsize) { bufsize *= 2; - buf = realloc(buf, bufsize); + buf = xrealloc(buf, bufsize); if (!buf) { ret = ENOMEM; break; @@ -232,13 +239,20 @@ int utilfdt_read_err(const char *filename, char **buffp) free(buf); else *buffp = buf; + *len = bufsize; return ret; } -char *utilfdt_read(const char *filename) +int utilfdt_read_err(const char *filename, char **buffp) +{ + off_t len; + return utilfdt_read_err_len(filename, buffp, &len); +} + +char *utilfdt_read_len(const char *filename, off_t *len) { char *buff; - int ret = utilfdt_read_err(filename, &buff); + int ret = utilfdt_read_err_len(filename, &buff, len); if (ret) { fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename, @@ -249,6 +263,12 @@ char *utilfdt_read(const char *filename) return buff; } +char *utilfdt_read(const char *filename) +{ + off_t len; + return utilfdt_read_len(filename, &len); +} + int utilfdt_write_err(const char *filename, const void *blob) { int fd = 1; /* assume stdout */ @@ -329,3 +349,100 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size) return -1; return 0; } + +void utilfdt_print_data(const char *data, int len) +{ + int i; + const char *p = data; + const char *s; + + /* no data, don't print */ + if (len == 0) + return; + + if (util_is_printable_string(data, len)) { + printf(" = "); + + s = data; + do { + printf("\"%s\"", s); + s += strlen(s) + 1; + if (s < data + len) + printf(", "); + } while (s < data + len); + + } else if ((len % 4) == 0) { + const uint32_t *cell = (const uint32_t *)data; + + printf(" = <"); + for (i = 0; i < len; i += 4) + printf("0x%08x%s", fdt32_to_cpu(cell[i]), + i < (len - 4) ? " " : ""); + printf(">"); + } else { + printf(" = ["); + for (i = 0; i < len; i++) + printf("%02x%s", *p++, i < len - 1 ? " " : ""); + printf("]"); + } +} + +void util_version(void) +{ + printf("Version: %s\n", DTC_VERSION); + exit(0); +} + +void util_usage(const char *errmsg, const char *synopsis, + const char *short_opts, struct option const long_opts[], + const char * const opts_help[]) +{ + FILE *fp = errmsg ? stderr : stdout; + const char a_arg[] = ""; + size_t a_arg_len = strlen(a_arg) + 1; + size_t i; + int optlen; + + fprintf(fp, + "Usage: %s\n" + "\n" + "Options: -[%s]\n", synopsis, short_opts); + + /* prescan the --long opt length to auto-align */ + optlen = 0; + for (i = 0; long_opts[i].name; ++i) { + /* +1 is for space between --opt and help text */ + int l = strlen(long_opts[i].name) + 1; + if (long_opts[i].has_arg == a_argument) + l += a_arg_len; + if (optlen < l) + optlen = l; + } + + for (i = 0; long_opts[i].name; ++i) { + /* helps when adding new applets or options */ + assert(opts_help[i] != NULL); + + /* first output the short flag if it has one */ + if (long_opts[i].val > '~') + fprintf(fp, " "); + else + fprintf(fp, " -%c, ", long_opts[i].val); + + /* then the long flag */ + if (long_opts[i].has_arg == no_argument) + fprintf(fp, "--%-*s", optlen, long_opts[i].name); + else + fprintf(fp, "--%s %s%*s", long_opts[i].name, a_arg, + (int)(optlen - strlen(long_opts[i].name) - a_arg_len), ""); + + /* finally the help text */ + fprintf(fp, "%s\n", opts_help[i]); + } + + if (errmsg) { + fprintf(fp, "\nError: %s\n", errmsg); + exit(EXIT_FAILURE); + } else + exit(EXIT_SUCCESS); +} diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h index c8eb45d9f04b..8f40b4499359 100644 --- a/scripts/dtc/util.h +++ b/scripts/dtc/util.h @@ -2,6 +2,7 @@ #define _UTIL_H #include +#include /* * Copyright 2011 The Chromium Authors, All Rights Reserved. @@ -23,7 +24,9 @@ * USA */ -static inline void __attribute__((noreturn)) die(char * str, ...) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +static inline void __attribute__((noreturn)) die(const char *str, ...) { va_list ap; @@ -57,12 +60,14 @@ extern char *xstrdup(const char *s); extern char *join_path(const char *path, const char *name); /** - * Check a string of a given length to see if it is all printable and - * has a valid terminator. + * Check a property of a given length to see if it is all printable and + * has a valid terminator. The property can contain either a single string, + * or multiple strings each of non-zero length. * * @param data The string to check * @param len The string length including terminator - * @return 1 if a valid printable string, 0 if not */ + * @return 1 if a valid printable string, 0 if not + */ int util_is_printable_string(const void *data, int len); /* @@ -82,6 +87,13 @@ char get_escape_char(const char *s, int *i); */ char *utilfdt_read(const char *filename); +/** + * Like utilfdt_read(), but also passes back the size of the file read. + * + * @param len If non-NULL, the amount of data we managed to read + */ +char *utilfdt_read_len(const char *filename, off_t *len); + /** * Read a device tree file into a buffer. Does not report errors, but only * returns them. The value returned can be passed to strerror() to obtain @@ -93,6 +105,12 @@ char *utilfdt_read(const char *filename); */ int utilfdt_read_err(const char *filename, char **buffp); +/** + * Like utilfdt_read_err(), but also passes back the size of the file read. + * + * @param len If non-NULL, the amount of data we managed to read + */ +int utilfdt_read_err_len(const char *filename, char **buffp, off_t *len); /** * Write a device tree buffer to a file. This will report any errors on @@ -148,6 +166,85 @@ int utilfdt_decode_type(const char *fmt, int *type, int *size); #define USAGE_TYPE_MSG \ "\ts=string, i=int, u=unsigned, x=hex\n" \ "\tOptional modifier prefix:\n" \ - "\t\thh or b=byte, h=2 byte, l=4 byte (default)\n"; + "\t\thh or b=byte, h=2 byte, l=4 byte (default)"; + +/** + * Print property data in a readable format to stdout + * + * Properties that look like strings will be printed as strings. Otherwise + * the data will be displayed either as cells (if len is a multiple of 4 + * bytes) or bytes. + * + * If len is 0 then this function does nothing. + * + * @param data Pointers to property data + * @param len Length of property data + */ +void utilfdt_print_data(const char *data, int len); + +/** + * Show source version and exit + */ +void util_version(void) __attribute__((noreturn)); + +/** + * Show usage and exit + * + * This helps standardize the output of various utils. You most likely want + * to use the usage() helper below rather than call this. + * + * @param errmsg If non-NULL, an error message to display + * @param synopsis The initial example usage text (and possible examples) + * @param short_opts The string of short options + * @param long_opts The structure of long options + * @param opts_help An array of help strings (should align with long_opts) + */ +void util_usage(const char *errmsg, const char *synopsis, + const char *short_opts, struct option const long_opts[], + const char * const opts_help[]) __attribute__((noreturn)); + +/** + * Show usage and exit + * + * If you name all your usage variables with usage_xxx, then you can call this + * help macro rather than expanding all arguments yourself. + * + * @param errmsg If non-NULL, an error message to display + */ +#define usage(errmsg) \ + util_usage(errmsg, usage_synopsis, usage_short_opts, \ + usage_long_opts, usage_opts_help) + +/** + * Call getopt_long() with standard options + * + * Since all util code runs getopt in the same way, provide a helper. + */ +#define util_getopt_long() getopt_long(argc, argv, usage_short_opts, \ + usage_long_opts, NULL) + +/* Helper for aligning long_opts array */ +#define a_argument required_argument + +/* Helper for usage_short_opts string constant */ +#define USAGE_COMMON_SHORT_OPTS "hV" + +/* Helper for usage_long_opts option array */ +#define USAGE_COMMON_LONG_OPTS \ + {"help", no_argument, NULL, 'h'}, \ + {"version", no_argument, NULL, 'V'}, \ + {NULL, no_argument, NULL, 0x0} + +/* Helper for usage_opts_help array */ +#define USAGE_COMMON_OPTS_HELP \ + "Print this help and exit", \ + "Print version and exit", \ + NULL + +/* Helper for getopt case statements */ +#define case_USAGE_COMMON_FLAGS \ + case 'h': usage(NULL); \ + case 'V': util_version(); \ + case '?': usage("unknown option"); #endif /* _UTIL_H */ diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index 6158b867df99..e0b82fe8e7de 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.2.0-g37c0b6a0" +#define DTC_VERSION "DTC 1.4.0" From c8a3e6a866f91f82b4d04809aa30de2f4d928756 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 21 Jan 2014 13:41:52 +0000 Subject: [PATCH 03/29] scripts/dtc: Add a script to update to mainline dtc source A very simple script that automates pulling in a newer version of DTC. Not particularly robust, but a whole lot better than doing it by hand every time. Signed-off-by: Grant Likely --- scripts/dtc/update-dtc-source.sh | 54 ++++++++++++++++++++++++++++++++ scripts/dtc/version_gen.h | 2 +- 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100755 scripts/dtc/update-dtc-source.sh diff --git a/scripts/dtc/update-dtc-source.sh b/scripts/dtc/update-dtc-source.sh new file mode 100755 index 000000000000..feb01ef26be4 --- /dev/null +++ b/scripts/dtc/update-dtc-source.sh @@ -0,0 +1,54 @@ +#!/bin/sh +# Simple script to update the version of DTC carried by the Linux kernel +# +# This script assumes that the dtc and the linux git trees are in the +# same directory. After building dtc in the dtc directory, it copies the +# source files and generated source files into the scripts/dtc directory +# in the kernel and creates a git commit updating them to the new +# version. +# +# Usage: from the top level Linux source tree, run: +# $ ./scripts/dtc/update-dtc-source.sh +# +# The script will change into the dtc tree, build and test dtc, copy the +# relevant files into the kernel tree and create a git commit. The commit +# message will need to be modified to reflect the version of DTC being +# imported +# +# TODO: +# This script is pretty basic, but it is seldom used so a few manual tasks +# aren't a big deal. If anyone is interested in making it more robust, the +# the following would be nice: +# * Actually fail to complete if any testcase fails. +# - The dtc "make check" target needs to return a failure +# * Extract the version number from the dtc repo for the commit message +# * Build dtc in the kernel tree +# * run 'make check" on dtc built from the kernel tree + +set -ev + +DTC_UPSTREAM_PATH=`pwd`/../dtc +DTC_LINUX_PATH=`pwd`/scripts/dtc + +DTC_SOURCE="checks.c data.c dtc.c dtc.h flattree.c fstree.c livetree.c srcpos.c \ + srcpos.h treesource.c util.c util.h version_gen.h Makefile.dtc \ + dtc-lexer.l dtc-parser.y" +DTC_GENERATED="dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h" + +# Build DTC +cd $DTC_UPSTREAM_PATH +make clean +make check + +# Copy the files into the Linux tree +cd $DTC_LINUX_PATH +for f in $DTC_SOURCE; do + cp ${DTC_UPSTREAM_PATH}/${f} ${f} + git add ${f} +done +for f in $DTC_GENERATED; do + cp ${DTC_UPSTREAM_PATH}/$f ${f}_shipped + git add ${f}_shipped +done + +git commit -e -v -m "scripts/dtc: Update to upstream version [CHANGEME]" diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index e0b82fe8e7de..54d4e904433a 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.4.0" +#define DTC_VERSION "DTC 1.4.0-dirty" From cf4c9eb5a451ba26246477dd3168e98b7a5c1b1c Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 15 Nov 2013 06:23:32 +0000 Subject: [PATCH 04/29] of: make of_get_phy_mode parse 'phy-connection-type' Per the ePAPR v1.1 specification, 'phy-connection-type' is the canonical property name for describing an Ethernet to PHY connection type. Make sure that of_get_phy_mode() also attempts to parse that property and update the comments mentioning 'phy-mode' to also include 'phy-connection-type'. Signed-off-by: Florian Fainelli Signed-off-by: Grant Likely --- drivers/of/of_net.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/of/of_net.c b/drivers/of/of_net.c index a208a457558c..a3df3428dac6 100644 --- a/drivers/of/of_net.c +++ b/drivers/of/of_net.c @@ -13,8 +13,8 @@ /** * It maps 'enum phy_interface_t' found in include/linux/phy.h - * into the device tree binding of 'phy-mode', so that Ethernet - * device driver can get phy interface from device tree. + * into the device tree binding of 'phy-mode' or 'phy-connection-type', + * so that Ethernet device driver can get phy interface from device tree. */ static const char *phy_modes[] = { [PHY_INTERFACE_MODE_NA] = "", @@ -37,8 +37,9 @@ static const char *phy_modes[] = { * of_get_phy_mode - Get phy mode for given device_node * @np: Pointer to the given device_node * - * The function gets phy interface string from property 'phy-mode', - * and return its index in phy_modes table, or errno in error case. + * The function gets phy interface string from property 'phy-mode' or + * 'phy-connection-type', and return its index in phy_modes table, or errno in + * error case. */ int of_get_phy_mode(struct device_node *np) { @@ -46,6 +47,8 @@ int of_get_phy_mode(struct device_node *np) int err, i; err = of_property_read_string(np, "phy-mode", &pm); + if (err < 0) + err = of_property_read_string(np, "phy-connection-type", &pm); if (err < 0) return err; From 588453c69dace39351129a038dd2796608f74bb3 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Fri, 8 Nov 2013 17:03:56 +0200 Subject: [PATCH 05/29] of: Introduce device tree node flag helpers. Helper functions for working with device node flags. Signed-off-by: Pantelis Antoniou Signed-off-by: Grant Likely --- include/linux/of.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/linux/of.h b/include/linux/of.h index 70c64ba17fa5..3d0593943f47 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -114,6 +114,26 @@ static inline void of_node_set_flag(struct device_node *n, unsigned long flag) set_bit(flag, &n->_flags); } +static inline void of_node_clear_flag(struct device_node *n, unsigned long flag) +{ + clear_bit(flag, &n->_flags); +} + +static inline int of_property_check_flag(struct property *p, unsigned long flag) +{ + return test_bit(flag, &p->_flags); +} + +static inline void of_property_set_flag(struct property *p, unsigned long flag) +{ + set_bit(flag, &p->_flags); +} + +static inline void of_property_clear_flag(struct property *p, unsigned long flag) +{ + clear_bit(flag, &p->_flags); +} + extern struct device_node *of_find_all_nodes(struct device_node *prev); /* From e3963fd60a83967573f6330c9db134bd581da746 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Fri, 8 Nov 2013 17:03:57 +0200 Subject: [PATCH 06/29] of: Clear detach flag on attach When attaching a node always clear the detach flag. Without this change the sequence detach, attach fails. Signed-off-by: Pantelis Antoniou Signed-off-by: Grant Likely --- drivers/of/base.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index ff85450d5683..87038d80b473 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1692,6 +1692,7 @@ int of_attach_node(struct device_node *np) np->allnext = of_allnodes; np->parent->child = np; of_allnodes = np; + of_node_clear_flag(np, OF_DETACHED); raw_spin_unlock_irqrestore(&devtree_lock, flags); of_add_proc_dt_entry(np); From 62664f67775fad840cf6f68d6b5f428817bef6c5 Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Wed, 22 Jan 2014 13:57:39 +0800 Subject: [PATCH 07/29] of: add __of_add_property() without lock operations There two places will use the same code for adding one new property to the DT node. Adding __of_add_property() and prepare for fixing of_update_property()'s bug. Signed-off-by: Xiubo Li Signed-off-by: Grant Likely --- drivers/of/base.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 87038d80b473..6ad3dc976b18 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1492,12 +1492,32 @@ static int of_property_notify(int action, struct device_node *np, } #endif +/** + * __of_add_property - Add a property to a node without lock operations + */ +static int __of_add_property(struct device_node *np, struct property *prop) +{ + struct property **next; + + prop->next = NULL; + next = &np->properties; + while (*next) { + if (strcmp(prop->name, (*next)->name) == 0) + /* duplicate ! don't insert it */ + return -EEXIST; + + next = &(*next)->next; + } + *next = prop; + + return 0; +} + /** * of_add_property - Add a property to a node */ int of_add_property(struct device_node *np, struct property *prop) { - struct property **next; unsigned long flags; int rc; @@ -1505,27 +1525,17 @@ int of_add_property(struct device_node *np, struct property *prop) if (rc) return rc; - prop->next = NULL; raw_spin_lock_irqsave(&devtree_lock, flags); - next = &np->properties; - while (*next) { - if (strcmp(prop->name, (*next)->name) == 0) { - /* duplicate ! don't insert it */ - raw_spin_unlock_irqrestore(&devtree_lock, flags); - return -1; - } - next = &(*next)->next; - } - *next = prop; + rc = __of_add_property(np, prop); raw_spin_unlock_irqrestore(&devtree_lock, flags); #ifdef CONFIG_PROC_DEVICETREE /* try to add to proc as well if it was initialized */ - if (np->pde) + if (!rc && np->pde) proc_device_tree_add_prop(np->pde, prop); #endif /* CONFIG_PROC_DEVICETREE */ - return 0; + return rc; } /** From 02ed594e7113644c06ae3a89bc9215d839510efc Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Wed, 22 Jan 2014 13:57:40 +0800 Subject: [PATCH 08/29] of: fix of_update_property() The of_update_property() is intented to update a property in a node and if the property does not exist, will add it. The second search of the property is possibly won't be found, that maybe removed by other thread just before the second search begain. Using the __of_find_property() and __of_add_property() instead and move them into lock operations. Signed-off-by: Xiubo Li Cc: Pantelis Antoniou Signed-off-by: Grant Likely --- drivers/of/base.c | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 6ad3dc976b18..239e3da9e728 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1597,7 +1597,7 @@ int of_update_property(struct device_node *np, struct property *newprop) { struct property **next, *oldprop; unsigned long flags; - int rc, found = 0; + int rc = 0; rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); if (rc) @@ -1606,36 +1606,28 @@ int of_update_property(struct device_node *np, struct property *newprop) if (!newprop->name) return -EINVAL; - oldprop = of_find_property(np, newprop->name, NULL); - if (!oldprop) - return of_add_property(np, newprop); - raw_spin_lock_irqsave(&devtree_lock, flags); - next = &np->properties; - while (*next) { - if (*next == oldprop) { - /* found the node */ - newprop->next = oldprop->next; - *next = newprop; - oldprop->next = np->deadprops; - np->deadprops = oldprop; - found = 1; - break; - } - next = &(*next)->next; + oldprop = __of_find_property(np, newprop->name, NULL); + if (!oldprop) { + /* add the node */ + rc = __of_add_property(np, newprop); + } else { + /* replace the node */ + next = &oldprop; + newprop->next = oldprop->next; + *next = newprop; + oldprop->next = np->deadprops; + np->deadprops = oldprop; } raw_spin_unlock_irqrestore(&devtree_lock, flags); - if (!found) - return -ENODEV; - #ifdef CONFIG_PROC_DEVICETREE /* try to add to proc as well if it was initialized */ - if (np->pde) + if (!rc && np->pde) proc_device_tree_update_prop(np->pde, newprop, oldprop); #endif /* CONFIG_PROC_DEVICETREE */ - return 0; + return rc; } #if defined(CONFIG_OF_DYNAMIC) From b66548e2a9baf65ccebeb3750f0ab9ddbef500f6 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Fri, 17 Jan 2014 12:08:30 +0100 Subject: [PATCH 09/29] of: Increase MAX_PHANDLE_ARGS arm-smmu driver uses of_parse_phandle_with_args when parsing DT information to determine stream IDs for a master device. Thus the number of stream IDs per master device is bound by MAX_PHANDLE_ARGS. To support Calxeda ECX-2000 hardware arm-smmu driver requires a slightly higher value for MAX_PHANDLE_ARGS as this hardware has 10 stream IDs for one master device. Increasing it to 16 seems a reasonable choice. Cc: Grant Likely Cc: Rob Herring Cc: devicetree@vger.kernel.org Cc: Andreas Herrmann Acked-by: Rob Herring Signed-off-by: Andreas Herrmann Signed-off-by: Grant Likely --- include/linux/of.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/of.h b/include/linux/of.h index 3d0593943f47..0ea516ed22c0 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -67,7 +67,7 @@ struct device_node { #endif }; -#define MAX_PHANDLE_ARGS 8 +#define MAX_PHANDLE_ARGS 16 struct of_phandle_args { struct device_node *np; int args_count; From 25a31579ea19dce7947fc11295fbed2e460a83cb Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Wed, 19 Feb 2014 23:14:55 +0100 Subject: [PATCH 10/29] of: Allows to use the PCI translator without the PCI core Translating an address from a PCI node of the device-tree into a CPU physical address doesn't require the core PCI support. Those translations are just related to the device tree itself. The use case to translate an address from a PCI node without actually using the PCI core support is when one needs to access the PCI controller without accessing any PCI devices. Marvell SoCs, such as Kirkwood, Dove or Armada XP for instance, come with an IP of a PCI controller. In the registers of this controller are stored the ID and the revision of a SoC. With this patch it will be possible to read the SoC ID of a board without any PCI device and then without the PCI core support. Signed-off-by: Gregory CLEMENT Tested-by: Ezequiel Garcia Reviewed-by: Ezequiel Garcia Signed-off-by: Grant Likely --- drivers/of/Kconfig | 4 ++++ drivers/of/address.c | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index c6973f101a3e..ffdcb11f75fb 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -44,6 +44,10 @@ config OF_DYNAMIC config OF_ADDRESS def_bool y depends on !SPARC + select OF_ADDRESS_PCI if PCI + +config OF_ADDRESS_PCI + bool config OF_IRQ def_bool y diff --git a/drivers/of/address.c b/drivers/of/address.c index d3dd41c840f1..fe44c74ff4bd 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -91,7 +91,7 @@ static unsigned int of_bus_default_get_flags(const __be32 *addr) return IORESOURCE_MEM; } -#ifdef CONFIG_PCI +#ifdef CONFIG_OF_ADDRESS_PCI /* * PCI bus specific translator */ @@ -165,7 +165,9 @@ static int of_bus_pci_translate(__be32 *addr, u64 offset, int na) { return of_bus_default_translate(addr + 1, offset, na - 1); } +#endif /* CONFIG_OF_ADDRESS_PCI */ +#ifdef CONFIG_PCI const __be32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, unsigned int *flags) { @@ -355,7 +357,7 @@ static unsigned int of_bus_isa_get_flags(const __be32 *addr) */ static struct of_bus of_busses[] = { -#ifdef CONFIG_PCI +#ifdef CONFIG_OF_ADDRESS_PCI /* PCI */ { .name = "pci", @@ -366,7 +368,7 @@ static struct of_bus of_busses[] = { .translate = of_bus_pci_translate, .get_flags = of_bus_pci_get_flags, }, -#endif /* CONFIG_PCI */ +#endif /* CONFIG_OF_ADDRESS_PCI */ /* ISA */ { .name = "isa", From c8a4c63f8c136d3368625d640f2dd1cb505f1fea Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Wed, 19 Feb 2014 23:14:56 +0100 Subject: [PATCH 11/29] ARM: mvebu: Allows to get the SoC ID even without PCI enabled The address translation of a PCI node don't require anymore the PCI support in the kernel. This translation is mandatory to be able to read the SoC ID which is stored in the PCI controller of the mvebu SoCs. This patch selects the symbol needed to get only this translation for all the mvebu platforms. Signed-off-by: Gregory CLEMENT Tested-by: Ezequiel Garcia Reviewed-by: Ezequiel Garcia Signed-off-by: Grant Likely --- arch/arm/mach-mvebu/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 5e269d7263ce..df9e7d270810 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -16,6 +16,7 @@ config ARCH_MVEBU select ARCH_REQUIRE_GPIOLIB select MIGHT_HAVE_PCI select PCI_QUIRKS if PCI + select OF_ADDRESS_PCI if ARCH_MVEBU From f4d4ffc03efc864645b990e1d579bbe1b8e358a4 Mon Sep 17 00:00:00 2001 From: Jason Cooper Date: Sun, 1 Dec 2013 23:56:28 +0000 Subject: [PATCH 12/29] kbuild: dtbs_install: new make target Unlike other build products in the Linux kernel, there is no 'make *install' mechanism to put devicetree blobs in a standard place. This commit adds a new 'dtbs_install' make target which copies all of the dtbs into the INSTALL_DTBS_PATH directory. INSTALL_DTBS_PATH can be set before calling make to change the default install directory. If not set then it defaults to: $INSTALL_PATH/dtbs/$KERNELRELEASE. This is done to keep dtbs from different kernel versions separate until things have settled down. Once the dtbs are stable, and not so strongly linked to the kernel version, the devicetree files will most likely move to their own repo. Users will need to upgrade install scripts at that time. v7: (reworked by Grant Likely) - Moved rules from arch/arm/Makefile to arch/arm/boot/dts/Makefile so that each dtb install could have a separate target and be reported as part of the make output. - Fixed dependency problem to ensure $KERNELRELEASE is calculated before attempting to install - Removed option to call external script. Copying the files should be sufficient and a build system can post-process the install directory. Despite the fact an external script is used for installing the kernel, I don't think that is a pattern that should be encouraged. I would rather see buildroot type tools post process the install directory to rename or move dtb files after installing to a staging directory. - Plus it is easy to add a hook after the fact without blocking the rest of this feature. - Move the helper targets into scripts/Makefile.lib with the rest of the common dtb rules Signed-off-by: Jason Cooper Signed-off-by: Grant Likely Cc: Michal Marek Cc: Russell King Cc: Rob Herring --- Makefile | 7 +++++++ arch/arm/Makefile | 7 ++++--- arch/arm/boot/dts/Makefile | 4 +++- scripts/Makefile.lib | 12 ++++++++++++ 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 606ef7c4a544..90556da6959d 100644 --- a/Makefile +++ b/Makefile @@ -726,6 +726,13 @@ export KBUILD_IMAGE ?= vmlinux # images. Default is /boot, but you can set it to other values export INSTALL_PATH ?= /boot +# +# INSTALL_DTBS_PATH specifies a prefix for relocations required by build roots. +# Like INSTALL_MOD_PATH, it isn't defined in the Makefile, but can be passed as +# an argument if needed. Otherwise it defaults to the kernel install path +# +export INSTALL_DTBS_PATH ?= $(INSTALL_PATH)/dtbs/$(KERNELRELEASE) + # # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory # relocations required by build roots. This is not defined in the diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 08a9ef58d9c3..fddf4beaee45 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -310,9 +310,9 @@ $(INSTALL_TARGETS): %.dtb: | scripts $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@ -PHONY += dtbs -dtbs: scripts - $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) dtbs +PHONY += dtbs dtbs_install +dtbs dtbs_install: prepare scripts + $(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $@ # We use MRPROPER_FILES and CLEAN_FILES now archclean: @@ -331,6 +331,7 @@ define archhelp echo ' bootpImage - Combined zImage and initial RAM disk' echo ' (supply initrd image via make variable INITRD=)' echo '* dtbs - Build device tree blobs for enabled boards' + echo ' dtbs_install - Install dtbs to $(INSTALL_DTBS_PATH)' echo ' install - Install uncompressed kernel' echo ' zinstall - Install compressed kernel' echo ' uinstall - Install U-Boot wrapped compressed kernel' diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile index b9d6a8b485e0..649c8e345ac5 100644 --- a/arch/arm/boot/dts/Makefile +++ b/arch/arm/boot/dts/Makefile @@ -321,7 +321,7 @@ dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb \ zynq-zc706.dtb \ zynq-zed.dtb -targets += dtbs +targets += dtbs dtbs_install targets += $(dtb-y) endif @@ -331,3 +331,5 @@ dtbs: $(addprefix $(obj)/, $(dtb-y)) $(Q)rm -f $(obj)/../*.dtb clean-files := *.dtb + +dtbs_install: $(addsuffix _dtbinst_, $(dtb-y)) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 49392ecbef17..d0c17a55a2f5 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -273,6 +273,18 @@ $(obj)/%.dtb: $(src)/%.dts FORCE dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp) +# Helper targets for Installing DTBs into the boot directory +quiet_cmd_dtb_install = INSTALL $< + cmd_dtb_install = cp $< $(2) + +_dtbinst_pre_: + $(Q)if [ -d $(INSTALL_DTBS_PATH).old ]; then rm -rf $(INSTALL_DTBS_PATH).old; fi + $(Q)if [ -d $(INSTALL_DTBS_PATH) ]; then mv $(INSTALL_DTBS_PATH) $(INSTALL_DTBS_PATH).old; fi + $(Q)mkdir -p $(INSTALL_DTBS_PATH) + +%.dtb_dtbinst_: $(obj)/%.dtb _dtbinst_pre_ + $(call cmd,dtb_install,$(INSTALL_DTBS_PATH)) + # Bzip2 # --------------------------------------------------------------------------- From a3dbeb5b45af5b6113385db89fce2a8279278e8b Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 4 Mar 2014 16:07:17 +0800 Subject: [PATCH 13/29] Revert "of: fix of_update_property()" This reverts commit 02ed594e7113644c06ae3a89bc9215d839510efc. The change is completely broken. It attempt to get the previous item in a linked list by grabbing the address of a stack variable. Outright wrong. Signed-off-by: Grant Likely --- drivers/of/base.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 239e3da9e728..a63e77694d0f 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1597,7 +1597,7 @@ int of_update_property(struct device_node *np, struct property *newprop) { struct property **next, *oldprop; unsigned long flags; - int rc = 0; + int rc, found = 0; rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); if (rc) @@ -1606,28 +1606,36 @@ int of_update_property(struct device_node *np, struct property *newprop) if (!newprop->name) return -EINVAL; + oldprop = of_find_property(np, newprop->name, NULL); + if (!oldprop) + return of_add_property(np, newprop); + raw_spin_lock_irqsave(&devtree_lock, flags); - oldprop = __of_find_property(np, newprop->name, NULL); - if (!oldprop) { - /* add the node */ - rc = __of_add_property(np, newprop); - } else { - /* replace the node */ - next = &oldprop; - newprop->next = oldprop->next; - *next = newprop; - oldprop->next = np->deadprops; - np->deadprops = oldprop; + next = &np->properties; + while (*next) { + if (*next == oldprop) { + /* found the node */ + newprop->next = oldprop->next; + *next = newprop; + oldprop->next = np->deadprops; + np->deadprops = oldprop; + found = 1; + break; + } + next = &(*next)->next; } raw_spin_unlock_irqrestore(&devtree_lock, flags); + if (!found) + return -ENODEV; + #ifdef CONFIG_PROC_DEVICETREE /* try to add to proc as well if it was initialized */ if (!rc && np->pde) proc_device_tree_update_prop(np->pde, newprop, oldprop); #endif /* CONFIG_PROC_DEVICETREE */ - return rc; + return 0; } #if defined(CONFIG_OF_DYNAMIC) From f08ad1deaaf83b7e7369716949b34dadc530be01 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 28 Feb 2014 14:42:46 +0100 Subject: [PATCH 14/29] of: document bindings for reserved-memory nodes Reserved memory nodes allow for the reservation of static (fixed address) regions, or dynamically allocated regions for a specific purpose. [joshc: Based on binding document proposed (in non-patch form) here: http://lkml.kernel.org/g/20131030134702.19B57C402A0@trevor.secretlab.ca adapted to support #memory-region-cells] Signed-off-by: Josh Cartwright [mszyprow: removed #memory-region-cells property] Signed-off-by: Marek Szyprowski [grant.likely: removed residual #memory-region-cells example] Signed-off-by: Grant Likely --- .../reserved-memory/reserved-memory.txt | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt diff --git a/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt new file mode 100644 index 000000000000..3da0ebdba8d9 --- /dev/null +++ b/Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt @@ -0,0 +1,133 @@ +*** Reserved memory regions *** + +Reserved memory is specified as a node under the /reserved-memory node. +The operating system shall exclude reserved memory from normal usage +one can create child nodes describing particular reserved (excluded from +normal use) memory regions. Such memory regions are usually designed for +the special usage by various device drivers. + +Parameters for each memory region can be encoded into the device tree +with the following nodes: + +/reserved-memory node +--------------------- +#address-cells, #size-cells (required) - standard definition + - Should use the same values as the root node +ranges (required) - standard definition + - Should be empty + +/reserved-memory/ child nodes +----------------------------- +Each child of the reserved-memory node specifies one or more regions of +reserved memory. Each child node may either use a 'reg' property to +specify a specific range of reserved memory, or a 'size' property with +optional constraints to request a dynamically allocated block of memory. + +Following the generic-names recommended practice, node names should +reflect the purpose of the node (ie. "framebuffer" or "dma-pool"). Unit +address (@
) should be appended to the name if the node is a +static allocation. + +Properties: +Requires either a) or b) below. +a) static allocation + reg (required) - standard definition +b) dynamic allocation + size (required) - length based on parent's #size-cells + - Size in bytes of memory to reserve. + alignment (optional) - length based on parent's #size-cells + - Address boundary for alignment of allocation. + alloc-ranges (optional) - prop-encoded-array (address, length pairs). + - Specifies regions of memory that are + acceptable to allocate from. + +If both reg and size are present, then the reg property takes precedence +and size is ignored. + +Additional properties: +compatible (optional) - standard definition + - may contain the following strings: + - shared-dma-pool: This indicates a region of memory meant to be + used as a shared pool of DMA buffers for a set of devices. It can + be used by an operating system to instanciate the necessary pool + management subsystem if necessary. + - vendor specific string in the form ,[-] +no-map (optional) - empty property + - Indicates the operating system must not create a virtual mapping + of the region as part of its standard mapping of system memory, + nor permit speculative access to it under any circumstances other + than under the control of the device driver using the region. +reusable (optional) - empty property + - The operating system can use the memory in this region with the + limitation that the device driver(s) owning the region need to be + able to reclaim it back. Typically that means that the operating + system can use that region to store volatile or cached data that + can be otherwise regenerated or migrated elsewhere. + +Linux implementation note: +- If a "linux,cma-default" property is present, then Linux will use the + region for the default pool of the contiguous memory allocator. + +Device node references to reserved memory +----------------------------------------- +Regions in the /reserved-memory node may be referenced by other device +nodes by adding a memory-region property to the device node. + +memory-region (optional) - phandle, specifier pairs to children of /reserved-memory + +Example +------- +This example defines 3 contiguous regions are defined for Linux kernel: +one default of all device drivers (named linux,cma@72000000 and 64MiB in size), +one dedicated to the framebuffer device (named framebuffer@78000000, 8MiB), and +one for multimedia processing (named multimedia-memory@77000000, 64MiB). + +/ { + #address-cells = <1>; + #size-cells = <1>; + + memory { + reg = <0x40000000 0x40000000>; + }; + + reserved-memory { + #address-cells = <1>; + #size-cells = <1>; + ranges; + + /* global autoconfigured region for contiguous allocations */ + linux,cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x4000000>; + alignment = <0x2000>; + linux,cma-default; + }; + + display_reserved: framebuffer@78000000 { + reg = <0x78000000 0x800000>; + }; + + multimedia_reserved: multimedia@77000000 { + compatible = "acme,multimedia-memory"; + reg = <0x77000000 0x4000000>; + }; + }; + + /* ... */ + + fb0: video@12300000 { + memory-region = <&display_reserved>; + /* ... */ + }; + + scaler: scaler@12500000 { + memory-region = <&multimedia_reserved>; + /* ... */ + }; + + codec: codec@12600000 { + memory-region = <&multimedia_reserved>; + /* ... */ + }; +}; From e8d9d1f5485b52ec3c4d7af839e6914438f6c285 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 28 Feb 2014 14:42:47 +0100 Subject: [PATCH 15/29] drivers: of: add initialization code for static reserved memory This patch adds support for static (defined by 'reg' property) reserved memory regions declared in device tree. Memory blocks can be reliably reserved only during early boot. This must happen before the whole memory management subsystem is initialized, because we need to ensure that the given contiguous blocks are not yet allocated by kernel. Also it must happen before kernel mappings for the whole low memory are created, to ensure that there will be no mappings (for reserved blocks). Typically, all this happens before device tree structures are unflattened, so we need to get reserved memory layout directly from fdt. Based on previous code provided by Josh Cartwright Signed-off-by: Marek Szyprowski Signed-off-by: Grant Likely --- drivers/of/fdt.c | 131 +++++++++++++++++++++++++++++++++++++++++ include/linux/of_fdt.h | 4 ++ 2 files changed, 135 insertions(+) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 758b4f8b30b7..819e11209718 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -439,6 +440,118 @@ struct boot_param_header *initial_boot_params; #ifdef CONFIG_OF_EARLY_FLATTREE +/** + * res_mem_reserve_reg() - reserve all memory described in 'reg' property + */ +static int __init __reserved_mem_reserve_reg(unsigned long node, + const char *uname) +{ + int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); + phys_addr_t base, size; + unsigned long len; + __be32 *prop; + int nomap; + + prop = of_get_flat_dt_prop(node, "reg", &len); + if (!prop) + return -ENOENT; + + if (len && len % t_len != 0) { + pr_err("Reserved memory: invalid reg property in '%s', skipping node.\n", + uname); + return -EINVAL; + } + + nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; + + while (len >= t_len) { + base = dt_mem_next_cell(dt_root_addr_cells, &prop); + size = dt_mem_next_cell(dt_root_size_cells, &prop); + + if (base && size && + early_init_dt_reserve_memory_arch(base, size, nomap) == 0) + pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n", + uname, &base, (unsigned long)size / SZ_1M); + else + pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %ld MiB\n", + uname, &base, (unsigned long)size / SZ_1M); + + len -= t_len; + } + return 0; +} + +/** + * __reserved_mem_check_root() - check if #size-cells, #address-cells provided + * in /reserved-memory matches the values supported by the current implementation, + * also check if ranges property has been provided + */ +static int __reserved_mem_check_root(unsigned long node) +{ + __be32 *prop; + + prop = of_get_flat_dt_prop(node, "#size-cells", NULL); + if (!prop || be32_to_cpup(prop) != dt_root_size_cells) + return -EINVAL; + + prop = of_get_flat_dt_prop(node, "#address-cells", NULL); + if (!prop || be32_to_cpup(prop) != dt_root_addr_cells) + return -EINVAL; + + prop = of_get_flat_dt_prop(node, "ranges", NULL); + if (!prop) + return -EINVAL; + return 0; +} + +/** + * fdt_scan_reserved_mem() - scan a single FDT node for reserved memory + */ +static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, + int depth, void *data) +{ + static int found; + const char *status; + + if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) { + if (__reserved_mem_check_root(node) != 0) { + pr_err("Reserved memory: unsupported node format, ignoring\n"); + /* break scan */ + return 1; + } + found = 1; + /* scan next node */ + return 0; + } else if (!found) { + /* scan next node */ + return 0; + } else if (found && depth < 2) { + /* scanning of /reserved-memory has been finished */ + return 1; + } + + status = of_get_flat_dt_prop(node, "status", NULL); + if (status && strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0) + return 0; + + __reserved_mem_reserve_reg(node, uname); + + /* scan next node */ + return 0; +} + +/** + * early_init_fdt_scan_reserved_mem() - create reserved memory regions + * + * This function grabs memory from early allocator for device exclusive use + * defined in device tree structures. It should be called by arch specific code + * once the early allocator (i.e. memblock) has been fully activated. + */ +void __init early_init_fdt_scan_reserved_mem(void) +{ + of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); +} + /** * of_scan_flat_dt - scan flattened tree blob and call callback on each. * @it: callback function @@ -856,6 +969,16 @@ void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) memblock_add(base, size); } +int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, + phys_addr_t size, bool nomap) +{ + if (memblock_is_region_reserved(base, size)) + return -EBUSY; + if (nomap) + return memblock_remove(base, size); + return memblock_reserve(base, size); +} + /* * called from unflatten_device_tree() to bootstrap devicetree itself * Architectures can override this definition if memblock isn't used @@ -864,6 +987,14 @@ void * __init __weak early_init_dt_alloc_memory_arch(u64 size, u64 align) { return __va(memblock_alloc(size, align)); } +#else +int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, + phys_addr_t size, bool nomap) +{ + pr_err("Reserved memory not supported, ignoring range 0x%llx - 0x%llx%s\n", + base, size, nomap ? " (nomap)" : ""); + return -ENOSYS; +} #endif bool __init early_init_dt_scan(void *params) diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h index 2b77058a7335..ddd7219af8ac 100644 --- a/include/linux/of_fdt.h +++ b/include/linux/of_fdt.h @@ -98,7 +98,10 @@ extern int early_init_dt_scan_chosen(unsigned long node, const char *uname, int depth, void *data); extern int early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data); +extern void early_init_fdt_scan_reserved_mem(void); extern void early_init_dt_add_memory_arch(u64 base, u64 size); +extern int early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, + bool no_map); extern void * early_init_dt_alloc_memory_arch(u64 size, u64 align); extern u64 dt_mem_next_cell(int s, __be32 **cellp); @@ -118,6 +121,7 @@ extern void unflatten_and_copy_device_tree(void); extern void early_init_devtree(void *); extern void early_get_first_memblock_info(void *, phys_addr_t *); #else /* CONFIG_OF_FLATTREE */ +static inline void early_init_fdt_scan_reserved_mem(void) {} static inline const char *of_flat_dt_get_machine_name(void) { return NULL; } static inline void unflatten_device_tree(void) {} static inline void unflatten_and_copy_device_tree(void) {} From 3f0c8206644836e4f10a6b9fc47cda6a9a372f9b Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 28 Feb 2014 14:42:48 +0100 Subject: [PATCH 16/29] drivers: of: add initialization code for dynamic reserved memory This patch adds support for dynamically allocated reserved memory regions declared in device tree. Such regions are defined by 'size', 'alignment' and 'alloc-ranges' properties. Based on previous code provided by Josh Cartwright Signed-off-by: Marek Szyprowski Signed-off-by: Grant Likely --- drivers/of/Kconfig | 6 + drivers/of/Makefile | 1 + drivers/of/fdt.c | 13 ++- drivers/of/of_reserved_mem.c | 188 ++++++++++++++++++++++++++++++++ include/linux/of_reserved_mem.h | 21 ++++ 5 files changed, 227 insertions(+), 2 deletions(-) create mode 100644 drivers/of/of_reserved_mem.c create mode 100644 include/linux/of_reserved_mem.h diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index ffdcb11f75fb..c144b8f990ff 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -79,4 +79,10 @@ config OF_MTD depends on MTD def_bool y +config OF_RESERVED_MEM + depends on OF_EARLY_FLATTREE + bool + help + Helpers to allow for reservation of memory regions + endmenu # OF diff --git a/drivers/of/Makefile b/drivers/of/Makefile index efd05102c405..ed9660adad77 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_OF_MDIO) += of_mdio.o obj-$(CONFIG_OF_PCI) += of_pci.o obj-$(CONFIG_OF_PCI_IRQ) += of_pci_irq.o obj-$(CONFIG_OF_MTD) += of_mtd.o +obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 819e11209718..510c0d8de8a0 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -450,7 +451,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, phys_addr_t base, size; unsigned long len; __be32 *prop; - int nomap; + int nomap, first = 1; prop = of_get_flat_dt_prop(node, "reg", &len); if (!prop) @@ -477,6 +478,10 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, uname, &base, (unsigned long)size / SZ_1M); len -= t_len; + if (first) { + fdt_reserved_mem_save_node(node, uname, base, size); + first = 0; + } } return 0; } @@ -512,6 +517,7 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, { static int found; const char *status; + int err; if (!found && depth == 1 && strcmp(uname, "reserved-memory") == 0) { if (__reserved_mem_check_root(node) != 0) { @@ -534,7 +540,9 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, if (status && strcmp(status, "okay") != 0 && strcmp(status, "ok") != 0) return 0; - __reserved_mem_reserve_reg(node, uname); + err = __reserved_mem_reserve_reg(node, uname); + if (err == -ENOENT && of_get_flat_dt_prop(node, "size", NULL)) + fdt_reserved_mem_save_node(node, uname, 0, 0); /* scan next node */ return 0; @@ -550,6 +558,7 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, void __init early_init_fdt_scan_reserved_mem(void) { of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); + fdt_init_reserved_mem(); } /** diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c new file mode 100644 index 000000000000..69b811779585 --- /dev/null +++ b/drivers/of/of_reserved_mem.c @@ -0,0 +1,188 @@ +/* + * Device tree based initialization code for reserved memory. + * + * Copyright (c) 2013, The Linux Foundation. All Rights Reserved. + * Copyright (c) 2013,2014 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Author: Marek Szyprowski + * Author: Josh Cartwright + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License or (at your optional) any later version of the license. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define MAX_RESERVED_REGIONS 16 +static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; +static int reserved_mem_count; + +#if defined(CONFIG_HAVE_MEMBLOCK) +#include +int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, + phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, + phys_addr_t *res_base) +{ + /* + * We use __memblock_alloc_base() because memblock_alloc_base() + * panic()s on allocation failure. + */ + phys_addr_t base = __memblock_alloc_base(size, align, end); + if (!base) + return -ENOMEM; + + /* + * Check if the allocated region fits in to start..end window + */ + if (base < start) { + memblock_free(base, size); + return -ENOMEM; + } + + *res_base = base; + if (nomap) + return memblock_remove(base, size); + return 0; +} +#else +int __init __weak early_init_dt_alloc_reserved_memory_arch(phys_addr_t size, + phys_addr_t align, phys_addr_t start, phys_addr_t end, bool nomap, + phys_addr_t *res_base) +{ + pr_err("Reserved memory not supported, ignoring region 0x%llx%s\n", + size, nomap ? " (nomap)" : ""); + return -ENOSYS; +} +#endif + +/** + * res_mem_save_node() - save fdt node for second pass initialization + */ +void __init fdt_reserved_mem_save_node(unsigned long node, const char *uname, + phys_addr_t base, phys_addr_t size) +{ + struct reserved_mem *rmem = &reserved_mem[reserved_mem_count]; + + if (reserved_mem_count == ARRAY_SIZE(reserved_mem)) { + pr_err("Reserved memory: not enough space all defined regions.\n"); + return; + } + + rmem->fdt_node = node; + rmem->name = uname; + rmem->base = base; + rmem->size = size; + + reserved_mem_count++; + return; +} + +/** + * res_mem_alloc_size() - allocate reserved memory described by 'size', 'align' + * and 'alloc-ranges' properties + */ +static int __init __reserved_mem_alloc_size(unsigned long node, + const char *uname, phys_addr_t *res_base, phys_addr_t *res_size) +{ + int t_len = (dt_root_addr_cells + dt_root_size_cells) * sizeof(__be32); + phys_addr_t start = 0, end = 0; + phys_addr_t base = 0, align = 0, size; + unsigned long len; + __be32 *prop; + int nomap; + int ret; + + prop = of_get_flat_dt_prop(node, "size", &len); + if (!prop) + return -EINVAL; + + if (len != dt_root_size_cells * sizeof(__be32)) { + pr_err("Reserved memory: invalid size property in '%s' node.\n", + uname); + return -EINVAL; + } + size = dt_mem_next_cell(dt_root_size_cells, &prop); + + nomap = of_get_flat_dt_prop(node, "no-map", NULL) != NULL; + + prop = of_get_flat_dt_prop(node, "alignment", &len); + if (prop) { + if (len != dt_root_addr_cells * sizeof(__be32)) { + pr_err("Reserved memory: invalid alignment property in '%s' node.\n", + uname); + return -EINVAL; + } + align = dt_mem_next_cell(dt_root_addr_cells, &prop); + } + + prop = of_get_flat_dt_prop(node, "alloc-ranges", &len); + if (prop) { + + if (len % t_len != 0) { + pr_err("Reserved memory: invalid alloc-ranges property in '%s', skipping node.\n", + uname); + return -EINVAL; + } + + base = 0; + + while (len > 0) { + start = dt_mem_next_cell(dt_root_addr_cells, &prop); + end = start + dt_mem_next_cell(dt_root_size_cells, + &prop); + + ret = early_init_dt_alloc_reserved_memory_arch(size, + align, start, end, nomap, &base); + if (ret == 0) { + pr_debug("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", + uname, &base, + (unsigned long)size / SZ_1M); + break; + } + len -= t_len; + } + + } else { + ret = early_init_dt_alloc_reserved_memory_arch(size, align, + 0, 0, nomap, &base); + if (ret == 0) + pr_debug("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", + uname, &base, (unsigned long)size / SZ_1M); + } + + if (base == 0) { + pr_info("Reserved memory: failed to allocate memory for node '%s'\n", + uname); + return -ENOMEM; + } + + *res_base = base; + *res_size = size; + + return 0; +} + +/** + * fdt_init_reserved_mem - allocate and init all saved reserved memory regions + */ +void __init fdt_init_reserved_mem(void) +{ + int i; + for (i = 0; i < reserved_mem_count; i++) { + struct reserved_mem *rmem = &reserved_mem[i]; + unsigned long node = rmem->fdt_node; + int err = 0; + + if (rmem->size == 0) + err = __reserved_mem_alloc_size(node, rmem->name, + &rmem->base, &rmem->size); + } +} diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h new file mode 100644 index 000000000000..89226ed7d954 --- /dev/null +++ b/include/linux/of_reserved_mem.h @@ -0,0 +1,21 @@ +#ifndef __OF_RESERVED_MEM_H +#define __OF_RESERVED_MEM_H + +struct reserved_mem { + const char *name; + unsigned long fdt_node; + phys_addr_t base; + phys_addr_t size; +}; + +#ifdef CONFIG_OF_RESERVED_MEM +void fdt_init_reserved_mem(void); +void fdt_reserved_mem_save_node(unsigned long node, const char *uname, + phys_addr_t base, phys_addr_t size); +#else +static inline void fdt_init_reserved_mem(void) { } +static inline void fdt_reserved_mem_save_node(unsigned long node, + const char *uname, phys_addr_t base, phys_addr_t size) { } +#endif + +#endif /* __OF_RESERVED_MEM_H */ From f618c4703a14672d27bc2ca5d132a844363d6f5f Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 28 Feb 2014 14:42:49 +0100 Subject: [PATCH 17/29] drivers: of: add support for custom reserved memory drivers Add support for custom reserved memory drivers. Call their init() function for each reserved region and prepare for using operations provided by them with by the reserved_mem->ops array. Based on previous code provided by Josh Cartwright Signed-off-by: Marek Szyprowski Signed-off-by: Grant Likely --- drivers/of/of_reserved_mem.c | 29 ++++++++++++++++++++++++++++ include/asm-generic/vmlinux.lds.h | 11 +++++++++++ include/linux/of_reserved_mem.h | 32 +++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index 69b811779585..daaaf935911d 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -170,6 +170,33 @@ static int __init __reserved_mem_alloc_size(unsigned long node, return 0; } +static const struct of_device_id __rmem_of_table_sentinel + __used __section(__reservedmem_of_table_end); + +/** + * res_mem_init_node() - call region specific reserved memory init code + */ +static int __init __reserved_mem_init_node(struct reserved_mem *rmem) +{ + extern const struct of_device_id __reservedmem_of_table[]; + const struct of_device_id *i; + + for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) { + reservedmem_of_init_fn initfn = i->data; + const char *compat = i->compatible; + + if (!of_flat_dt_is_compatible(rmem->fdt_node, compat)) + continue; + + if (initfn(rmem, rmem->fdt_node, rmem->name) == 0) { + pr_info("Reserved memory: initialized node %s, compatible id %s\n", + rmem->name, compat); + return 0; + } + } + return -ENOENT; +} + /** * fdt_init_reserved_mem - allocate and init all saved reserved memory regions */ @@ -184,5 +211,7 @@ void __init fdt_init_reserved_mem(void) if (rmem->size == 0) err = __reserved_mem_alloc_size(node, rmem->name, &rmem->base, &rmem->size); + if (err == 0) + __reserved_mem_init_node(rmem); } } diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index bc2121fa9132..f10f64fcc815 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -167,6 +167,16 @@ #define CLK_OF_TABLES() #endif +#ifdef CONFIG_OF_RESERVED_MEM +#define RESERVEDMEM_OF_TABLES() \ + . = ALIGN(8); \ + VMLINUX_SYMBOL(__reservedmem_of_table) = .; \ + *(__reservedmem_of_table) \ + *(__reservedmem_of_table_end) +#else +#define RESERVEDMEM_OF_TABLES() +#endif + #define KERNEL_DTB() \ STRUCT_ALIGN(); \ VMLINUX_SYMBOL(__dtb_start) = .; \ @@ -490,6 +500,7 @@ TRACE_SYSCALLS() \ MEM_DISCARD(init.rodata) \ CLK_OF_TABLES() \ + RESERVEDMEM_OF_TABLES() \ CLKSRC_OF_TABLES() \ KERNEL_DTB() \ IRQCHIP_OF_MATCH_TABLE() diff --git a/include/linux/of_reserved_mem.h b/include/linux/of_reserved_mem.h index 89226ed7d954..9b1fbb7f29fc 100644 --- a/include/linux/of_reserved_mem.h +++ b/include/linux/of_reserved_mem.h @@ -1,21 +1,53 @@ #ifndef __OF_RESERVED_MEM_H #define __OF_RESERVED_MEM_H +struct device; +struct of_phandle_args; +struct reserved_mem_ops; + struct reserved_mem { const char *name; unsigned long fdt_node; + const struct reserved_mem_ops *ops; phys_addr_t base; phys_addr_t size; + void *priv; }; +struct reserved_mem_ops { + void (*device_init)(struct reserved_mem *rmem, + struct device *dev); + void (*device_release)(struct reserved_mem *rmem, + struct device *dev); +}; + +typedef int (*reservedmem_of_init_fn)(struct reserved_mem *rmem, + unsigned long node, const char *uname); + #ifdef CONFIG_OF_RESERVED_MEM void fdt_init_reserved_mem(void); void fdt_reserved_mem_save_node(unsigned long node, const char *uname, phys_addr_t base, phys_addr_t size); + +#define RESERVEDMEM_OF_DECLARE(name, compat, init) \ + static const struct of_device_id __reservedmem_of_table_##name \ + __used __section(__reservedmem_of_table) \ + = { .compatible = compat, \ + .data = (init == (reservedmem_of_init_fn)NULL) ? \ + init : init } + #else static inline void fdt_init_reserved_mem(void) { } static inline void fdt_reserved_mem_save_node(unsigned long node, const char *uname, phys_addr_t base, phys_addr_t size) { } + +#define RESERVEDMEM_OF_DECLARE(name, compat, init) \ + static const struct of_device_id __reservedmem_of_table_##name \ + __attribute__((unused)) \ + = { .compatible = compat, \ + .data = (init == (reservedmem_of_init_fn)NULL) ? \ + init : init } + #endif #endif /* __OF_RESERVED_MEM_H */ From bcedb5f9bd74662968fc1b4cb22f24abb4b7723d Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 28 Feb 2014 14:42:54 +0100 Subject: [PATCH 18/29] arm: add support for reserved memory defined by device tree Enable reserved memory initialization from device tree. Signed-off-by: Marek Szyprowski Signed-off-by: Grant Likely --- arch/arm/Kconfig | 1 + arch/arm/mm/init.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e25419817791..d0262bea8020 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1918,6 +1918,7 @@ config USE_OF select IRQ_DOMAIN select OF select OF_EARLY_FLATTREE + select OF_RESERVED_MEM help Include support for flattened device tree machine descriptions. diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 804d61566a53..2a77ba8796ae 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -323,6 +323,8 @@ void __init arm_memblock_init(struct meminfo *mi, if (mdesc->reserve) mdesc->reserve(); + early_init_fdt_scan_reserved_mem(); + /* * reserve memory for DMA contigouos allocations, * must come from DMA area inside low memory From 75b57ecf9d1d1e17d099ab13b8f48e6e038676be Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 20 Feb 2014 18:02:11 +0000 Subject: [PATCH 19/29] of: Make device nodes kobjects so they show up in sysfs Device tree nodes are already treated as objects, and we already want to expose them to userspace which is done using the /proc filesystem today. Right now the kernel has to do a lot of work to keep the /proc view in sync with the in-kernel representation. If device_nodes are switched to be kobjects then the device tree code can be a whole lot simpler. It also turns out that switching to using /sysfs from /proc results in smaller code and data size, and the userspace ABI won't change if /proc/device-tree symlinks to /sys/firmware/devicetree/base. v7: Add missing sysfs_bin_attr_init() v6: Add __of_add_property() early init fixes from Pantelis v5: Rename firmware/ofw to firmware/devicetree Fix updating property values in sysfs v4: Fixed build error on Powerpc Fixed handling of dynamic nodes on powerpc v3: Fixed handling of duplicate attribute and child node names v2: switch to using sysfs bin_attributes which solve the problem of reporting incorrect property size. Signed-off-by: Grant Likely Tested-by: Sascha Hauer Cc: Rob Herring Cc: Benjamin Herrenschmidt Cc: David S. Miller Cc: Nathan Fontenot Cc: Pantelis Antoniou --- Documentation/ABI/testing/sysfs-firmware-ofw | 28 +++ arch/powerpc/platforms/pseries/dlpar.c | 2 - arch/powerpc/platforms/pseries/reconfig.c | 2 - arch/powerpc/sysdev/msi_bitmap.c | 2 +- drivers/of/base.c | 174 ++++++++++++++++++- drivers/of/fdt.c | 3 +- drivers/of/pdt.c | 4 +- drivers/of/testcase-data/tests-phandle.dtsi | 3 + include/linux/of.h | 9 +- 9 files changed, 209 insertions(+), 18 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-firmware-ofw diff --git a/Documentation/ABI/testing/sysfs-firmware-ofw b/Documentation/ABI/testing/sysfs-firmware-ofw new file mode 100644 index 000000000000..f562b188e71d --- /dev/null +++ b/Documentation/ABI/testing/sysfs-firmware-ofw @@ -0,0 +1,28 @@ +What: /sys/firmware/devicetree/* +Date: November 2013 +Contact: Grant Likely +Description: + When using OpenFirmware or a Flattened Device Tree to enumerate + hardware, the device tree structure will be exposed in this + directory. + + It is possible for multiple device-tree directories to exist. + Some device drivers use a separate detached device tree which + have no attachment to the system tree and will appear in a + different subdirectory under /sys/firmware/devicetree. + + Userspace must not use the /sys/firmware/devicetree/base + path directly, but instead should follow /proc/device-tree + symlink. It is possible that the absolute path will change + in the future, but the symlink is the stable ABI. + + The /proc/device-tree symlink replaces the devicetree /proc + filesystem support, and has largely the same semantics and + should be compatible with existing userspace. + + The contents of /sys/firmware/devicetree/ is a + hierarchy of directories, one per device tree node. The + directory name is the resolved path component name (node + name plus address). Properties are represented as files + in the directory. The contents of each file is the exact + binary data from the device tree. diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index a8fe5aa3d34f..022b38e6a80b 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c @@ -11,7 +11,6 @@ */ #include -#include #include #include #include @@ -87,7 +86,6 @@ static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa, } of_node_set_flag(dn, OF_DYNAMIC); - kref_init(&dn->kref); return dn; } diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index f93cdf55628c..0435bb65d0aa 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -12,7 +12,6 @@ */ #include -#include #include #include #include @@ -70,7 +69,6 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist np->properties = proplist; of_node_set_flag(np, OF_DYNAMIC); - kref_init(&np->kref); np->parent = derive_parent(path); if (IS_ERR(np->parent)) { diff --git a/arch/powerpc/sysdev/msi_bitmap.c b/arch/powerpc/sysdev/msi_bitmap.c index 0968b66b4cf9..8ba60424be95 100644 --- a/arch/powerpc/sysdev/msi_bitmap.c +++ b/arch/powerpc/sysdev/msi_bitmap.c @@ -202,7 +202,7 @@ void __init test_of_node(void) /* There should really be a struct device_node allocator */ memset(&of_node, 0, sizeof(of_node)); - kref_init(&of_node.kref); + kref_init(&of_node.kobj.kref); of_node.full_name = node_name; check(0 == msi_bitmap_alloc(&bmp, size, &of_node)); diff --git a/drivers/of/base.c b/drivers/of/base.c index 48594f334151..3b70a468c8ab 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "of_private.h" @@ -35,6 +36,12 @@ struct device_node *of_chosen; struct device_node *of_aliases; static struct device_node *of_stdout; +static struct kset *of_kset; + +/* + * Used to protect the of_aliases; but also overloaded to hold off addition of + * nodes to sysfs + */ DEFINE_MUTEX(of_aliases_mutex); /* use when traversing tree through the allnext, child, sibling, @@ -92,14 +99,14 @@ int __weak of_node_to_nid(struct device_node *np) struct device_node *of_node_get(struct device_node *node) { if (node) - kref_get(&node->kref); + kobject_get(&node->kobj); return node; } EXPORT_SYMBOL(of_node_get); -static inline struct device_node *kref_to_device_node(struct kref *kref) +static inline struct device_node *kobj_to_device_node(struct kobject *kobj) { - return container_of(kref, struct device_node, kref); + return container_of(kobj, struct device_node, kobj); } /** @@ -109,16 +116,15 @@ static inline struct device_node *kref_to_device_node(struct kref *kref) * In of_node_put() this function is passed to kref_put() * as the destructor. */ -static void of_node_release(struct kref *kref) +static void of_node_release(struct kobject *kobj) { - struct device_node *node = kref_to_device_node(kref); + struct device_node *node = kobj_to_device_node(kobj); struct property *prop = node->properties; /* We should never be releasing nodes that haven't been detached. */ if (!of_node_check_flag(node, OF_DETACHED)) { pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name); dump_stack(); - kref_init(&node->kref); return; } @@ -151,11 +157,140 @@ static void of_node_release(struct kref *kref) void of_node_put(struct device_node *node) { if (node) - kref_put(&node->kref, of_node_release); + kobject_put(&node->kobj); } EXPORT_SYMBOL(of_node_put); +#else +static void of_node_release(struct kobject *kobj) +{ + /* Without CONFIG_OF_DYNAMIC, no nodes gets freed */ +} #endif /* CONFIG_OF_DYNAMIC */ +struct kobj_type of_node_ktype = { + .release = of_node_release, +}; + +static ssize_t of_node_property_read(struct file *filp, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, + loff_t offset, size_t count) +{ + struct property *pp = container_of(bin_attr, struct property, attr); + return memory_read_from_buffer(buf, count, &offset, pp->value, pp->length); +} + +static const char *safe_name(struct kobject *kobj, const char *orig_name) +{ + const char *name = orig_name; + struct kernfs_node *kn; + int i = 0; + + /* don't be a hero. After 16 tries give up */ + while (i < 16 && (kn = sysfs_get_dirent(kobj->sd, name))) { + sysfs_put(kn); + if (name != orig_name) + kfree(name); + name = kasprintf(GFP_KERNEL, "%s#%i", orig_name, ++i); + } + + if (name != orig_name) + pr_warn("device-tree: Duplicate name in %s, renamed to \"%s\"\n", + kobject_name(kobj), name); + return name; +} + +static int __of_add_property_sysfs(struct device_node *np, struct property *pp) +{ + int rc; + + /* Important: Don't leak passwords */ + bool secure = strncmp(pp->name, "security-", 9) == 0; + + sysfs_bin_attr_init(&pp->attr); + pp->attr.attr.name = safe_name(&np->kobj, pp->name); + pp->attr.attr.mode = secure ? S_IRUSR : S_IRUGO; + pp->attr.size = secure ? 0 : pp->length; + pp->attr.read = of_node_property_read; + + rc = sysfs_create_bin_file(&np->kobj, &pp->attr); + WARN(rc, "error adding attribute %s to node %s\n", pp->name, np->full_name); + return rc; +} + +static int __of_node_add(struct device_node *np) +{ + const char *name; + struct property *pp; + int rc; + + np->kobj.kset = of_kset; + if (!np->parent) { + /* Nodes without parents are new top level trees */ + rc = kobject_add(&np->kobj, NULL, safe_name(&of_kset->kobj, "base")); + } else { + name = safe_name(&np->parent->kobj, kbasename(np->full_name)); + if (!name || !name[0]) + return -EINVAL; + + rc = kobject_add(&np->kobj, &np->parent->kobj, "%s", name); + } + if (rc) + return rc; + + for_each_property_of_node(np, pp) + __of_add_property_sysfs(np, pp); + + return 0; +} + +int of_node_add(struct device_node *np) +{ + int rc = 0; + kobject_init(&np->kobj, &of_node_ktype); + mutex_lock(&of_aliases_mutex); + if (of_kset) + rc = __of_node_add(np); + mutex_unlock(&of_aliases_mutex); + return rc; +} + +#if defined(CONFIG_OF_DYNAMIC) +static void of_node_remove(struct device_node *np) +{ + struct property *pp; + + for_each_property_of_node(np, pp) + sysfs_remove_bin_file(&np->kobj, &pp->attr); + + kobject_del(&np->kobj); +} +#endif + +static int __init of_init(void) +{ + struct device_node *np; + + /* Create the kset, and register existing nodes */ + mutex_lock(&of_aliases_mutex); + of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj); + if (!of_kset) { + mutex_unlock(&of_aliases_mutex); + return -ENOMEM; + } + for_each_of_allnodes(np) + __of_node_add(np); + mutex_unlock(&of_aliases_mutex); + +#if !defined(CONFIG_PROC_DEVICETREE) + /* Symlink to the new tree when PROC_DEVICETREE is disabled */ + if (of_allnodes) + proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base"); +#endif /* CONFIG_PROC_DEVICETREE */ + + return 0; +} +core_initcall(of_init); + static struct property *__of_find_property(const struct device_node *np, const char *name, int *lenp) { @@ -1546,6 +1681,14 @@ int of_add_property(struct device_node *np, struct property *prop) raw_spin_lock_irqsave(&devtree_lock, flags); rc = __of_add_property(np, prop); raw_spin_unlock_irqrestore(&devtree_lock, flags); + if (rc) + return rc; + + /* at early boot, bail hear and defer setup to of_init() */ + if (!of_kset) + return 0; + + __of_add_property_sysfs(np, prop); #ifdef CONFIG_PROC_DEVICETREE /* try to add to proc as well if it was initialized */ @@ -1593,6 +1736,12 @@ int of_remove_property(struct device_node *np, struct property *prop) if (!found) return -ENODEV; + /* at early boot, bail hear and defer setup to of_init() */ + if (!of_kset) + return 0; + + sysfs_remove_bin_file(&np->kobj, &prop->attr); + #ifdef CONFIG_PROC_DEVICETREE /* try to remove the proc node as well */ if (np->pde) @@ -1643,13 +1792,20 @@ int of_update_property(struct device_node *np, struct property *newprop) next = &(*next)->next; } raw_spin_unlock_irqrestore(&devtree_lock, flags); + if (rc) + return rc; + + /* Update the sysfs attribute */ + if (oldprop) + sysfs_remove_bin_file(&np->kobj, &oldprop->attr); + __of_add_property_sysfs(np, newprop); if (!found) return -ENODEV; #ifdef CONFIG_PROC_DEVICETREE /* try to add to proc as well if it was initialized */ - if (!rc && np->pde) + if (np->pde) proc_device_tree_update_prop(np->pde, newprop, oldprop); #endif /* CONFIG_PROC_DEVICETREE */ @@ -1723,6 +1879,7 @@ int of_attach_node(struct device_node *np) of_node_clear_flag(np, OF_DETACHED); raw_spin_unlock_irqrestore(&devtree_lock, flags); + of_node_add(np); of_add_proc_dt_entry(np); return 0; } @@ -1795,6 +1952,7 @@ int of_detach_node(struct device_node *np) raw_spin_unlock_irqrestore(&devtree_lock, flags); of_remove_proc_dt_entry(np); + of_node_remove(np); return rc; } #endif /* defined(CONFIG_OF_DYNAMIC) */ diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 758b4f8b30b7..96ad1ab7f9d6 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -232,7 +232,6 @@ static void * unflatten_dt_node(struct boot_param_header *blob, dad->next->sibling = np; dad->next = np; } - kref_init(&np->kref); } /* process properties */ while (1) { @@ -327,6 +326,8 @@ static void * unflatten_dt_node(struct boot_param_header *blob, np->name = ""; if (!np->type) np->type = ""; + + of_node_add(np); } while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) { if (tag == OF_DT_NOP) diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c index 7b666736c168..e64fa3d3da5f 100644 --- a/drivers/of/pdt.c +++ b/drivers/of/pdt.c @@ -179,8 +179,6 @@ static struct device_node * __init of_pdt_create_node(phandle node, of_pdt_incr_unique_id(dp); dp->parent = parent; - kref_init(&dp->kref); - dp->name = of_pdt_get_one_property(node, "name"); dp->type = of_pdt_get_one_property(node, "device_type"); dp->phandle = node; @@ -215,6 +213,7 @@ static struct device_node * __init of_pdt_build_tree(struct device_node *parent, *nextp = &dp->allnext; dp->full_name = of_pdt_build_full_name(dp); + of_node_add(dp); dp->child = of_pdt_build_tree(dp, of_pdt_prom_ops->getchild(node), nextp); @@ -245,6 +244,7 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops) of_allnodes->path_component_name = ""; #endif of_allnodes->full_name = "/"; + of_node_add(of_allnodes); nextp = &of_allnodes->allnext; of_allnodes->child = of_pdt_build_tree(of_allnodes, diff --git a/drivers/of/testcase-data/tests-phandle.dtsi b/drivers/of/testcase-data/tests-phandle.dtsi index 0007d3cd7dc2..788a4c24b8f5 100644 --- a/drivers/of/testcase-data/tests-phandle.dtsi +++ b/drivers/of/testcase-data/tests-phandle.dtsi @@ -1,6 +1,9 @@ / { testcase-data { + security-password = "password"; + duplicate-name = "duplicate"; + duplicate-name { }; phandle-tests { provider0: provider0 { #phandle-cells = <0>; diff --git a/include/linux/of.h b/include/linux/of.h index b3d0f6d86e3b..bd45be5bd565 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -37,6 +37,7 @@ struct property { struct property *next; unsigned long _flags; unsigned int unique_id; + struct bin_attribute attr; }; #if defined(CONFIG_SPARC) @@ -57,7 +58,7 @@ struct device_node { struct device_node *next; /* next device of same type */ struct device_node *allnext; /* next in list of all nodes */ struct proc_dir_entry *pde; /* this node's proc directory */ - struct kref kref; + struct kobject kobj; unsigned long _flags; void *data; #if defined(CONFIG_SPARC) @@ -74,6 +75,8 @@ struct of_phandle_args { uint32_t args[MAX_PHANDLE_ARGS]; }; +extern int of_node_add(struct device_node *node); + #ifdef CONFIG_OF_DYNAMIC extern struct device_node *of_node_get(struct device_node *node); extern void of_node_put(struct device_node *node); @@ -187,6 +190,8 @@ static inline const char *of_node_full_name(const struct device_node *np) return np ? np->full_name : ""; } +#define for_each_of_allnodes(dn) \ + for (dn = of_allnodes; dn; dn = dn->allnext) extern struct device_node *of_find_node_by_name(struct device_node *from, const char *name); extern struct device_node *of_find_node_by_type(struct device_node *from, From 7e66c5c74f7348a96d5a3671f8cda4a478242679 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Fri, 15 Nov 2013 17:19:09 +0000 Subject: [PATCH 20/29] of/selftest: Add self tests for manipulation of properties Adds a few simple test cases to ensure that addition, update and removal of device tree node properties works correctly. Signed-off-by: Grant Likely Cc: Rob Herring Cc: Benjamin Herrenschmidt Cc: David S. Miller Cc: Nathan Fontenot Cc: Pantelis Antoniou --- drivers/of/selftest.c | 62 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c index 6643d1920985..ae4450070503 100644 --- a/drivers/of/selftest.c +++ b/drivers/of/selftest.c @@ -30,6 +30,67 @@ static struct selftest_results { } \ } +static void __init of_selftest_dynamic(void) +{ + struct device_node *np; + struct property *prop; + + np = of_find_node_by_path("/testcase-data"); + if (!np) { + pr_err("missing testcase data\n"); + return; + } + + /* Array of 4 properties for the purpose of testing */ + prop = kzalloc(sizeof(*prop) * 4, GFP_KERNEL); + if (!prop) { + selftest(0, "kzalloc() failed\n"); + return; + } + + /* Add a new property - should pass*/ + prop->name = "new-property"; + prop->value = "new-property-data"; + prop->length = strlen(prop->value); + selftest(of_add_property(np, prop) == 0, "Adding a new property failed\n"); + + /* Try to add an existing property - should fail */ + prop++; + prop->name = "new-property"; + prop->value = "new-property-data-should-fail"; + prop->length = strlen(prop->value); + selftest(of_add_property(np, prop) != 0, + "Adding an existing property should have failed\n"); + + /* Try to modify an existing property - should pass */ + prop->value = "modify-property-data-should-pass"; + prop->length = strlen(prop->value); + selftest(of_update_property(np, prop) == 0, + "Updating an existing property should have passed\n"); + + /* Try to modify non-existent property - should pass*/ + prop++; + prop->name = "modify-property"; + prop->value = "modify-missing-property-data-should-pass"; + prop->length = strlen(prop->value); + selftest(of_update_property(np, prop) == 0, + "Updating a missing property should have passed\n"); + + /* Remove property - should pass */ + selftest(of_remove_property(np, prop) == 0, + "Removing a property should have passed\n"); + + /* Adding very large property - should pass */ + prop++; + prop->name = "large-property-PAGE_SIZEx8"; + prop->length = PAGE_SIZE * 8; + prop->value = kzalloc(prop->length, GFP_KERNEL); + selftest(prop->value != NULL, "Unable to allocate large buffer\n"); + if (prop->value) + selftest(of_add_property(np, prop) == 0, + "Adding a large property should have passed\n"); +} + static void __init of_selftest_parse_phandle_with_args(void) { struct device_node *np; @@ -378,6 +439,7 @@ static int __init of_selftest(void) of_node_put(np); pr_info("start of selftest - you will see error messages\n"); + of_selftest_dynamic(); of_selftest_parse_phandle_with_args(); of_selftest_property_match_string(); of_selftest_parse_interrupts(); From 8357041a69b368991d1b04d9f1d297f8d71e1314 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 6 Nov 2012 21:03:27 +0000 Subject: [PATCH 21/29] of: remove /proc/device-tree The same data is now available in sysfs, so we can remove the code that exports it in /proc and replace it with a symlink to the sysfs version. Tested on versatile qemu model and mpc5200 eval board. More testing would be appreciated. v5: Fixed up conflicts with mainline changes Signed-off-by: Grant Likely Cc: Rob Herring Cc: Benjamin Herrenschmidt Cc: David S. Miller Cc: Nathan Fontenot Cc: Pantelis Antoniou --- drivers/of/Kconfig | 8 -- drivers/of/base.c | 52 +-------- fs/proc/Makefile | 1 - fs/proc/internal.h | 7 -- fs/proc/proc_devtree.c | 241 ----------------------------------------- fs/proc/root.c | 3 - include/linux/of.h | 11 -- 7 files changed, 1 insertion(+), 322 deletions(-) delete mode 100644 fs/proc/proc_devtree.c diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index ffdcb11f75fb..a46ac1b00032 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -7,14 +7,6 @@ config OF menu "Device Tree and Open Firmware support" depends on OF -config PROC_DEVICETREE - bool "Support for device tree in /proc" - depends on PROC_FS && !SPARC - help - This option adds a device-tree directory under /proc which contains - an image of the device tree that the kernel copies from Open - Firmware or other boot firmware. If unsure, say Y here. - config OF_SELFTEST bool "Device Tree Runtime self tests" depends on OF_IRQ diff --git a/drivers/of/base.c b/drivers/of/base.c index 3b70a468c8ab..ed3e70b84957 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -281,11 +281,9 @@ static int __init of_init(void) __of_node_add(np); mutex_unlock(&of_aliases_mutex); -#if !defined(CONFIG_PROC_DEVICETREE) - /* Symlink to the new tree when PROC_DEVICETREE is disabled */ + /* Symlink in /proc as required by userspace ABI */ if (of_allnodes) proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base"); -#endif /* CONFIG_PROC_DEVICETREE */ return 0; } @@ -1690,12 +1688,6 @@ int of_add_property(struct device_node *np, struct property *prop) __of_add_property_sysfs(np, prop); -#ifdef CONFIG_PROC_DEVICETREE - /* try to add to proc as well if it was initialized */ - if (!rc && np->pde) - proc_device_tree_add_prop(np->pde, prop); -#endif /* CONFIG_PROC_DEVICETREE */ - return rc; } @@ -1742,12 +1734,6 @@ int of_remove_property(struct device_node *np, struct property *prop) sysfs_remove_bin_file(&np->kobj, &prop->attr); -#ifdef CONFIG_PROC_DEVICETREE - /* try to remove the proc node as well */ - if (np->pde) - proc_device_tree_remove_prop(np->pde, prop); -#endif /* CONFIG_PROC_DEVICETREE */ - return 0; } @@ -1803,12 +1789,6 @@ int of_update_property(struct device_node *np, struct property *newprop) if (!found) return -ENODEV; -#ifdef CONFIG_PROC_DEVICETREE - /* try to add to proc as well if it was initialized */ - if (np->pde) - proc_device_tree_update_prop(np->pde, newprop, oldprop); -#endif /* CONFIG_PROC_DEVICETREE */ - return 0; } @@ -1843,22 +1823,6 @@ int of_reconfig_notify(unsigned long action, void *p) return notifier_to_errno(rc); } -#ifdef CONFIG_PROC_DEVICETREE -static void of_add_proc_dt_entry(struct device_node *dn) -{ - struct proc_dir_entry *ent; - - ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde); - if (ent) - proc_device_tree_add_node(dn, ent); -} -#else -static void of_add_proc_dt_entry(struct device_node *dn) -{ - return; -} -#endif - /** * of_attach_node - Plug a device node into the tree and global list. */ @@ -1880,22 +1844,9 @@ int of_attach_node(struct device_node *np) raw_spin_unlock_irqrestore(&devtree_lock, flags); of_node_add(np); - of_add_proc_dt_entry(np); return 0; } -#ifdef CONFIG_PROC_DEVICETREE -static void of_remove_proc_dt_entry(struct device_node *dn) -{ - proc_remove(dn->pde); -} -#else -static void of_remove_proc_dt_entry(struct device_node *dn) -{ - return; -} -#endif - /** * of_detach_node - "Unplug" a node from the device tree. * @@ -1951,7 +1902,6 @@ int of_detach_node(struct device_node *np) of_node_set_flag(np, OF_DETACHED); raw_spin_unlock_irqrestore(&devtree_lock, flags); - of_remove_proc_dt_entry(np); of_node_remove(np); return rc; } diff --git a/fs/proc/Makefile b/fs/proc/Makefile index ab30716584f5..239493ec718e 100644 --- a/fs/proc/Makefile +++ b/fs/proc/Makefile @@ -27,6 +27,5 @@ proc-$(CONFIG_PROC_SYSCTL) += proc_sysctl.o proc-$(CONFIG_NET) += proc_net.o proc-$(CONFIG_PROC_KCORE) += kcore.o proc-$(CONFIG_PROC_VMCORE) += vmcore.o -proc-$(CONFIG_PROC_DEVICETREE) += proc_devtree.o proc-$(CONFIG_PRINTK) += kmsg.o proc-$(CONFIG_PROC_PAGE_MONITOR) += page.o diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 651d09a11dde..3ab6d14e71c5 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -210,13 +210,6 @@ extern struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry extern int proc_fill_super(struct super_block *); extern void proc_entry_rundown(struct proc_dir_entry *); -/* - * proc_devtree.c - */ -#ifdef CONFIG_PROC_DEVICETREE -extern void proc_device_tree_init(void); -#endif - /* * proc_namespaces.c */ diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c deleted file mode 100644 index c82dd5147845..000000000000 --- a/fs/proc/proc_devtree.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * proc_devtree.c - handles /proc/device-tree - * - * Copyright 1997 Paul Mackerras - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "internal.h" - -static inline void set_node_proc_entry(struct device_node *np, - struct proc_dir_entry *de) -{ - np->pde = de; -} - -static struct proc_dir_entry *proc_device_tree; - -/* - * Supply data on a read from /proc/device-tree/node/property. - */ -static int property_proc_show(struct seq_file *m, void *v) -{ - struct property *pp = m->private; - - seq_write(m, pp->value, pp->length); - return 0; -} - -static int property_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, property_proc_show, __PDE_DATA(inode)); -} - -static const struct file_operations property_proc_fops = { - .owner = THIS_MODULE, - .open = property_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* - * For a node with a name like "gc@10", we make symlinks called "gc" - * and "@10" to it. - */ - -/* - * Add a property to a node - */ -static struct proc_dir_entry * -__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp, - const char *name) -{ - struct proc_dir_entry *ent; - - /* - * Unfortunately proc_register puts each new entry - * at the beginning of the list. So we rearrange them. - */ - ent = proc_create_data(name, - strncmp(name, "security-", 9) ? S_IRUGO : S_IRUSR, - de, &property_proc_fops, pp); - if (ent == NULL) - return NULL; - - if (!strncmp(name, "security-", 9)) - proc_set_size(ent, 0); /* don't leak number of password chars */ - else - proc_set_size(ent, pp->length); - - return ent; -} - - -void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop) -{ - __proc_device_tree_add_prop(pde, prop, prop->name); -} - -void proc_device_tree_remove_prop(struct proc_dir_entry *pde, - struct property *prop) -{ - remove_proc_entry(prop->name, pde); -} - -void proc_device_tree_update_prop(struct proc_dir_entry *pde, - struct property *newprop, - struct property *oldprop) -{ - struct proc_dir_entry *ent; - - if (!oldprop) { - proc_device_tree_add_prop(pde, newprop); - return; - } - - for (ent = pde->subdir; ent != NULL; ent = ent->next) - if (ent->data == oldprop) - break; - if (ent == NULL) { - pr_warn("device-tree: property \"%s\" does not exist\n", - oldprop->name); - } else { - ent->data = newprop; - ent->size = newprop->length; - } -} - -/* - * Various dodgy firmware might give us nodes and/or properties with - * conflicting names. That's generally ok, except for exporting via /proc, - * so munge names here to ensure they're unique. - */ - -static int duplicate_name(struct proc_dir_entry *de, const char *name) -{ - struct proc_dir_entry *ent; - int found = 0; - - spin_lock(&proc_subdir_lock); - - for (ent = de->subdir; ent != NULL; ent = ent->next) { - if (strcmp(ent->name, name) == 0) { - found = 1; - break; - } - } - - spin_unlock(&proc_subdir_lock); - - return found; -} - -static const char *fixup_name(struct device_node *np, struct proc_dir_entry *de, - const char *name) -{ - char *fixed_name; - int fixup_len = strlen(name) + 2 + 1; /* name + #x + \0 */ - int i = 1, size; - -realloc: - fixed_name = kmalloc(fixup_len, GFP_KERNEL); - if (fixed_name == NULL) { - pr_err("device-tree: Out of memory trying to fixup " - "name \"%s\"\n", name); - return name; - } - -retry: - size = snprintf(fixed_name, fixup_len, "%s#%d", name, i); - size++; /* account for NULL */ - - if (size > fixup_len) { - /* We ran out of space, free and reallocate. */ - kfree(fixed_name); - fixup_len = size; - goto realloc; - } - - if (duplicate_name(de, fixed_name)) { - /* Multiple duplicates. Retry with a different offset. */ - i++; - goto retry; - } - - pr_warn("device-tree: Duplicate name in %s, renamed to \"%s\"\n", - np->full_name, fixed_name); - - return fixed_name; -} - -/* - * Process a node, adding entries for its children and its properties. - */ -void proc_device_tree_add_node(struct device_node *np, - struct proc_dir_entry *de) -{ - struct property *pp; - struct proc_dir_entry *ent; - struct device_node *child; - const char *p; - - set_node_proc_entry(np, de); - for (child = NULL; (child = of_get_next_child(np, child));) { - /* Use everything after the last slash, or the full name */ - p = kbasename(child->full_name); - - if (duplicate_name(de, p)) - p = fixup_name(np, de, p); - - ent = proc_mkdir(p, de); - if (ent == NULL) - break; - proc_device_tree_add_node(child, ent); - } - of_node_put(child); - - for (pp = np->properties; pp != NULL; pp = pp->next) { - p = pp->name; - - if (strchr(p, '/')) - continue; - - if (duplicate_name(de, p)) - p = fixup_name(np, de, p); - - ent = __proc_device_tree_add_prop(de, pp, p); - if (ent == NULL) - break; - } -} - -/* - * Called on initialization to set up the /proc/device-tree subtree - */ -void __init proc_device_tree_init(void) -{ - struct device_node *root; - - proc_device_tree = proc_mkdir("device-tree", NULL); - if (proc_device_tree == NULL) - return; - root = of_find_node_by_path("/"); - if (root == NULL) { - remove_proc_entry("device-tree", NULL); - pr_debug("/proc/device-tree: can't find root\n"); - return; - } - proc_device_tree_add_node(root, proc_device_tree); - of_node_put(root); -} diff --git a/fs/proc/root.c b/fs/proc/root.c index 87dbcbef7fe4..7bbeb5257af1 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -183,9 +183,6 @@ void __init proc_root_init(void) proc_mkdir("openprom", NULL); #endif proc_tty_init(); -#ifdef CONFIG_PROC_DEVICETREE - proc_device_tree_init(); -#endif proc_mkdir("bus", NULL); proc_sys_init(); } diff --git a/include/linux/of.h b/include/linux/of.h index bd45be5bd565..257994a420f3 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -57,7 +57,6 @@ struct device_node { struct device_node *sibling; struct device_node *next; /* next device of same type */ struct device_node *allnext; /* next in list of all nodes */ - struct proc_dir_entry *pde; /* this node's proc directory */ struct kobject kobj; unsigned long _flags; void *data; @@ -658,14 +657,4 @@ static inline int of_get_available_child_count(const struct device_node *np) return num; } -#if defined(CONFIG_PROC_FS) && defined(CONFIG_PROC_DEVICETREE) -extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); -extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); -extern void proc_device_tree_remove_prop(struct proc_dir_entry *pde, - struct property *prop); -extern void proc_device_tree_update_prop(struct proc_dir_entry *pde, - struct property *newprop, - struct property *oldprop); -#endif - #endif /* _LINUX_OF_H */ From 76ac30056c664c6ea07f2c4ebeeed341b64bd186 Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Thu, 27 Feb 2014 21:04:54 +0100 Subject: [PATCH 22/29] of: add vendor prefix for SMSC Add a vendor prefix for Standard Microsystems Corporation, now part of Microchip. Signed-off-by: Florian Vaussard Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 40ce2df0e0e9..7187c71f2e41 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -80,6 +80,7 @@ sil Silicon Image silabs Silicon Laboratories simtek sirf SiRF Technology, Inc. +smsc Standard Microsystems Corporation snps Synopsys, Inc. spansion Spansion Inc. st STMicroelectronics From 6f976267da0e2c873c4b4aaacaf08266d1d1797d Mon Sep 17 00:00:00 2001 From: Florian Vaussard Date: Fri, 7 Mar 2014 13:38:37 +0100 Subject: [PATCH 23/29] of: add missing major vendors Looking at the current vendor strings used in the kernel's .dts/.dtsi files, some vendors are used a high number of times without being documented. Document the ones that are used more than 10 times. Note: a few inconsistencies were found, and thus not documented. Here is the list: - mrvl: duplicates "marvell" - st-ericsson: duplicates "ste" _and_ "stericsson" - pci8086: seems to be a unfortunate alias for "intel" - pnpPNP: used on PowerPC? Signed-off-by: Florian Vaussard Signed-off-by: Rob Herring --- .../devicetree/bindings/vendor-prefixes.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 7187c71f2e41..95465d57eb31 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -3,6 +3,7 @@ Device tree binding vendor prefix registry. Keep list in alphabetical order. This isn't an exhaustive list, but you should add new prefixes to it before using them to avoid name-space collisions. +abilis Abilis Systems active-semi Active-Semi International Inc ad Avionic Design GmbH adi Analog Devices, Inc. @@ -11,14 +12,17 @@ ak Asahi Kasei Corp. allwinner Allwinner Technology Co., Ltd. altr Altera Corp. amcc Applied Micro Circuits Corporation (APM, formally AMCC) +amd Advanced Micro Devices (AMD), Inc. amstaos AMS-Taos Inc. apm Applied Micro Circuits Corporation (APM) arm ARM Ltd. +armadeus ARMadeus Systems SARL atmel Atmel Corporation auo AU Optronics Corporation avago Avago Technologies bosch Bosch Sensortec GmbH brcm Broadcom Corporation +calxeda Calxeda capella Capella Microsystems, Inc cavium Cavium, Inc. cdns Cadence Design Systems Inc. @@ -26,8 +30,10 @@ chrp Common Hardware Reference Platform chunghwa Chunghwa Picture Tubes Ltd. cirrus Cirrus Logic, Inc. cortina Cortina Systems, Inc. +crystalfontz Crystalfontz America, Inc. dallas Maxim Integrated Products (formerly Dallas Semiconductor) davicom DAVICOM Semiconductor, Inc. +dlink D-Link Systems, Inc. denx Denx Software Engineering edt Emerging Display Technologies emmicro EM Microelectronic @@ -37,7 +43,9 @@ est ESTeem Wireless Modems fsl Freescale Semiconductor GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc. gef GE Fanuc Intelligent Platforms Embedded Systems, Inc. +globalscale Globalscale Technologies, Inc. gmt Global Mixed-mode Technology, Inc. +google Google, Inc. gumstix Gumstix, Inc. haoyu Haoyu Microelectronic Co. Ltd. hisilicon Hisilicon Limited. @@ -46,9 +54,12 @@ hp Hewlett Packard ibm International Business Machines (IBM) idt Integrated Device Technologies, Inc. img Imagination Technologies Ltd. +intel Intel Corporation intercontrol Inter Control Group isl Intersil karo Ka-Ro electronics GmbH +lacie LaCie +lantiq Lantiq Semiconductor lg LG Corporation linux Linux-specific binding lsi LSI Corp. (LSI Logic) @@ -56,12 +67,16 @@ marvell Marvell Technology Group Ltd. maxim Maxim Integrated Products microchip Microchip Technology Inc. mosaixtech Mosaix Technologies, Inc. +moxa Moxa national National Semiconductor neonode Neonode Inc. +netgear NETGEAR nintendo Nintendo +nokia Nokia nvidia NVIDIA nxp NXP Semiconductors onnn ON Semiconductor Corp. +opencores OpenCores.org panasonic Panasonic Corporation phytec PHYTEC Messtechnik GmbH picochip Picochip Ltd @@ -95,4 +110,5 @@ via VIA Technologies, Inc. winbond Winbond Electronics corp. wlf Wolfson Microelectronics wm Wondermedia Technologies, Inc. +xes Extreme Engineering Solutions (X-ES) xlnx Xilinx From 9bf14b7c540ae9ca7747af3a0c0d8470ef77b6ce Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 28 Feb 2014 14:42:55 +0100 Subject: [PATCH 24/29] arm64: add support for reserved memory defined by device tree Enable reserved memory initialization from device tree. Signed-off-by: Marek Szyprowski Acked-by: Catalin Marinas Signed-off-by: Grant Likely --- arch/arm64/Kconfig | 1 + arch/arm64/mm/init.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 27bbcfc7202a..6abf15407dca 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -43,6 +43,7 @@ config ARM64 select NO_BOOTMEM select OF select OF_EARLY_FLATTREE + select OF_RESERVED_MEM select PERF_USE_VMALLOC select POWER_RESET select POWER_SUPPLY diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index d0b4c2efda90..3fb8d50dfdaa 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -160,6 +160,7 @@ void __init arm64_memblock_init(void) memblock_reserve(base, size); } + early_init_fdt_scan_reserved_mem(); dma_contiguous_reserve(0); memblock_allow_resize(); From 708b7eef12f945a510ba5ac3b4007d7ae4796d55 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Fri, 28 Feb 2014 14:42:56 +0100 Subject: [PATCH 25/29] powerpc: add support for reserved memory defined by device tree Enable reserved memory initialization from device tree. Signed-off-by: Marek Szyprowski Signed-off-by: Grant Likely --- arch/powerpc/Kconfig | 1 + arch/powerpc/kernel/prom.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 957bf344c0f5..3b6617fed8fc 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -90,6 +90,7 @@ config PPC select BINFMT_ELF select OF select OF_EARLY_FLATTREE + select OF_RESERVED_MEM select HAVE_FTRACE_MCOUNT_RECORD select HAVE_DYNAMIC_FTRACE select HAVE_FUNCTION_TRACER diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index f58c0d3aaeb4..591986215801 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -588,6 +589,8 @@ static void __init early_reserve_mem_dt(void) memblock_reserve(base, size); } } + + early_init_fdt_scan_reserved_mem(); } static void __init early_reserve_mem(void) From 2040b52768ebab6e7bd73af0dc63703269c62f17 Mon Sep 17 00:00:00 2001 From: Josh Cartwright Date: Thu, 13 Mar 2014 16:36:36 -0500 Subject: [PATCH 26/29] of: only scan for reserved mem when fdt present When the reserved memory patches hit -next, several legacy (non-DT) boot failures were detected and bisected down to that commit. There needs to be some sanity checking whether a DT is even present before parsing the reserved ranges. Reported-by: Kevin Hilman Signed-off-by: Josh Cartwright Tested-by: Kevin Hilman Signed-off-by: Grant Likely --- drivers/of/fdt.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 510c0d8de8a0..501bc83f8cdf 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -557,6 +557,9 @@ static int __init __fdt_scan_reserved_mem(unsigned long node, const char *uname, */ void __init early_init_fdt_scan_reserved_mem(void) { + if (!initial_boot_params) + return; + of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); fdt_init_reserved_mem(); } From 0829f6d1f69e4f2fae4062987ae6531a9af1a2e3 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Fri, 13 Dec 2013 20:08:59 +0200 Subject: [PATCH 27/29] of: device_node kobject lifecycle fixes After the move to having device nodes be proper kobjects the lifecycle of the node needs to be controlled better. At first convert of_add_node() in the unflattened functions to of_init_node() which initializes the kobject so that of_node_get/put work correctly even before of_init is called. Afterwards introduce of_node_is_initialized & of_node_is_attached that query the underlying kobject about the state (attached means kobj is visible in sysfs) Using that make sure the lifecycle of the tree is correct at all times. Signed-off-by: Pantelis Antoniou [grant.likely: moved of_node_init() calls, fixed up locking, and dropped __of_populate() hunks] Signed-off-by: Grant Likely --- drivers/of/base.c | 35 ++++++++++++++++++++++++++--------- drivers/of/fdt.c | 3 +-- drivers/of/pdt.c | 3 +-- include/linux/of.h | 19 +++++++++++++++++++ 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index ed3e70b84957..418a4ff9d97c 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -246,10 +246,19 @@ static int __of_node_add(struct device_node *np) int of_node_add(struct device_node *np) { int rc = 0; - kobject_init(&np->kobj, &of_node_ktype); + + BUG_ON(!of_node_is_initialized(np)); + + /* + * Grab the mutex here so that in a race condition between of_init() and + * of_node_add(), node addition will still be consistent. + */ mutex_lock(&of_aliases_mutex); if (of_kset) rc = __of_node_add(np); + else + /* This scenario may be perfectly valid, but report it anyway */ + pr_info("of_node_add(%s) before of_init()\n", np->full_name); mutex_unlock(&of_aliases_mutex); return rc; } @@ -259,10 +268,17 @@ static void of_node_remove(struct device_node *np) { struct property *pp; - for_each_property_of_node(np, pp) - sysfs_remove_bin_file(&np->kobj, &pp->attr); + BUG_ON(!of_node_is_initialized(np)); - kobject_del(&np->kobj); + /* only remove properties if on sysfs */ + if (of_node_is_attached(np)) { + for_each_property_of_node(np, pp) + sysfs_remove_bin_file(&np->kobj, &pp->attr); + kobject_del(&np->kobj); + } + + /* finally remove the kobj_init ref */ + of_node_put(np); } #endif @@ -1631,6 +1647,10 @@ static int of_property_notify(int action, struct device_node *np, { struct of_prop_reconfig pr; + /* only call notifiers if the node is attached */ + if (!of_node_is_attached(np)) + return 0; + pr.dn = np; pr.prop = prop; return of_reconfig_notify(action, &pr); @@ -1682,11 +1702,8 @@ int of_add_property(struct device_node *np, struct property *prop) if (rc) return rc; - /* at early boot, bail hear and defer setup to of_init() */ - if (!of_kset) - return 0; - - __of_add_property_sysfs(np, prop); + if (of_node_is_attached(np)) + __of_add_property_sysfs(np, prop); return rc; } diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 96ad1ab7f9d6..70ccc36513e7 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -202,6 +202,7 @@ static void * unflatten_dt_node(struct boot_param_header *blob, __alignof__(struct device_node)); if (allnextpp) { char *fn; + of_node_init(np); np->full_name = fn = ((char *)np) + sizeof(*np); if (new_format) { /* rebuild full path for new format */ @@ -326,8 +327,6 @@ static void * unflatten_dt_node(struct boot_param_header *blob, np->name = ""; if (!np->type) np->type = ""; - - of_node_add(np); } while (tag == OF_DT_BEGIN_NODE || tag == OF_DT_NOP) { if (tag == OF_DT_NOP) diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c index e64fa3d3da5f..36b4035881b0 100644 --- a/drivers/of/pdt.c +++ b/drivers/of/pdt.c @@ -176,6 +176,7 @@ static struct device_node * __init of_pdt_create_node(phandle node, return NULL; dp = prom_early_alloc(sizeof(*dp)); + of_node_init(dp); of_pdt_incr_unique_id(dp); dp->parent = parent; @@ -213,7 +214,6 @@ static struct device_node * __init of_pdt_build_tree(struct device_node *parent, *nextp = &dp->allnext; dp->full_name = of_pdt_build_full_name(dp); - of_node_add(dp); dp->child = of_pdt_build_tree(dp, of_pdt_prom_ops->getchild(node), nextp); @@ -244,7 +244,6 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops) of_allnodes->path_component_name = ""; #endif of_allnodes->full_name = "/"; - of_node_add(of_allnodes); nextp = &of_allnodes->allnext; of_allnodes->child = of_pdt_build_tree(of_allnodes, diff --git a/include/linux/of.h b/include/linux/of.h index 257994a420f3..a8b9dad90c64 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -76,6 +76,25 @@ struct of_phandle_args { extern int of_node_add(struct device_node *node); +/* initialize a node */ +extern struct kobj_type of_node_ktype; +static inline void of_node_init(struct device_node *node) +{ + kobject_init(&node->kobj, &of_node_ktype); +} + +/* true when node is initialized */ +static inline int of_node_is_initialized(struct device_node *node) +{ + return node && node->kobj.state_initialized; +} + +/* true when node is attached (i.e. present on sysfs) */ +static inline int of_node_is_attached(struct device_node *node) +{ + return node && node->kobj.state_in_sysfs; +} + #ifdef CONFIG_OF_DYNAMIC extern struct device_node *of_node_get(struct device_node *node); extern void of_node_put(struct device_node *node); From 676e1b2fcd9dbb47a59baac13d089621d22c68b8 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Thu, 27 Mar 2014 17:11:23 -0700 Subject: [PATCH 28/29] of: Add support for ePAPR "stdout-path" property ePAPR 1.1 defines the "stdout-path" property for specifying the console device, but Linux currently only handles the older "linux,stdout-path" property. This patch adds parsing for the new property name. Signed-off-by: Grant Likely --- drivers/of/base.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index 418a4ff9d97c..be2861d69b02 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1955,9 +1955,9 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) of_chosen = of_find_node_by_path("/chosen@0"); if (of_chosen) { - const char *name; - - name = of_get_property(of_chosen, "linux,stdout-path", NULL); + const char *name = of_get_property(of_chosen, "stdout-path", NULL); + if (!name) + name = of_get_property(of_chosen, "linux,stdout-path", NULL); if (name) of_stdout = of_find_node_by_path(name); } From a0e7398357f297dd22d043fb2d5aa1c44d61ca10 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Tue, 1 Apr 2014 21:33:35 +0100 Subject: [PATCH 29/29] dt: Remove dangling "select PROC_DEVICETREE" CONFIG_PROC_DEVICETREE has been removed from the tree. This commit removes a dangling select of the config symbol. Signed-off-by: Grant Likely Cc: Paul Bolle Cc: Rob Herring --- arch/arm/mach-omap2/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index 0af7ca02314d..07d4bb098a49 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -104,7 +104,6 @@ config ARCH_OMAP2PLUS select MACH_OMAP_GENERIC select OMAP_DM_TIMER select PINCTRL - select PROC_DEVICETREE if PROC_FS select SOC_BUS select SPARSE_IRQ select TI_PRIV_EDMA