summaryrefslogtreecommitdiff
path: root/scripts/kconfig/confdata.c
diff options
context:
space:
mode:
authorYann E. MORIN <yann.morin.1998@free.fr>2013-04-29 00:36:38 +0400
committerYann E. MORIN <yann.morin.1998@free.fr>2013-06-24 22:03:30 +0400
commit3b9a19e08960e5cdad5253998637653e592a3c29 (patch)
tree2293b53b7f29ff79f67fa7245ea027a36bda91fc /scripts/kconfig/confdata.c
parenta1ce636f560336ba007bfabb15b167ff31b592cf (diff)
downloadlinux-3b9a19e08960e5cdad5253998637653e592a3c29.tar.xz
kconfig: loop as long as we changed some symbols in randconfig
Because of choice-in-a-choice constructs, it can happen that not all symbols are assigned a value during randconfig, leading in rare cases to this situation: ---8<--- choice-in-choice.in choice bool "A/B/C" config A bool "A" config B bool "B" if B choice bool "E/F" config E bool "E" config F bool "F" endchoice endif # B config C bool "C" endchoice ---8<--- $ ./scripts/kconfig/conf --randconfig choice-in-choice.in [--SNIP--] $ ./scripts/kconfig/conf --silentoldconfig choice-in-choice.in </dev/null [--SNIP--] A/B/C 1. A (A) > 2. B (B) 3. C (C) choice[1-3]: 2 E/F > 1. E (E) (NEW) 2. F (F) (NEW) choice[1-2]: aborted! Console input/output is redirected. Run 'make oldconfig' to update configuration. Fix this by looping in randconfig for as long as some symbol gets assigned a value. Note: this was spotted with the USB EHCI Debug Device Gadget (USB_G_DBGP), which uses this choice-in-a-choice construct, and exhibits this problem. The example above is just a stripped-down minimalist test-case. Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Diffstat (limited to 'scripts/kconfig/confdata.c')
-rw-r--r--scripts/kconfig/confdata.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index d36bc1f1d563..c55c227af463 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -1040,7 +1040,7 @@ void conf_set_changed_callback(void (*fn)(void))
conf_changed_callback = fn;
}
-static void randomize_choice_values(struct symbol *csym)
+static bool randomize_choice_values(struct symbol *csym)
{
struct property *prop;
struct symbol *sym;
@@ -1053,7 +1053,7 @@ static void randomize_choice_values(struct symbol *csym)
* In both cases stop.
*/
if (csym->curr.tri != yes)
- return;
+ return false;
prop = sym_get_choice_prop(csym);
@@ -1084,6 +1084,8 @@ static void randomize_choice_values(struct symbol *csym)
csym->flags |= SYMBOL_DEF_USER;
/* clear VALID to get value calculated */
csym->flags &= ~(SYMBOL_VALID);
+
+ return true;
}
void set_all_choice_values(struct symbol *csym)
@@ -1106,7 +1108,7 @@ void set_all_choice_values(struct symbol *csym)
csym->flags &= ~(SYMBOL_VALID | SYMBOL_NEED_SET_CHOICE_VALUES);
}
-void conf_set_all_new_symbols(enum conf_def_mode mode)
+bool conf_set_all_new_symbols(enum conf_def_mode mode)
{
struct symbol *sym, *csym;
int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y
@@ -1154,6 +1156,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
exit( 1 );
}
}
+ bool has_changed = false;
for_all_symbols(i, sym) {
if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
@@ -1161,6 +1164,7 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
switch (sym_get_type(sym)) {
case S_BOOLEAN:
case S_TRISTATE:
+ has_changed = true;
switch (mode) {
case def_yes:
sym->def[S_DEF_USER].tri = yes;
@@ -1219,6 +1223,12 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
sym_calc_value(csym);
if (mode == def_random)
- randomize_choice_values(csym);
+ has_changed = randomize_choice_values(csym);
+ else {
+ set_all_choice_values(csym);
+ has_changed = true;
+ }
}
+
+ return has_changed;
}