mirror of
https://github.com/torvalds/linux.git
synced 2025-11-02 01:29:02 +02:00
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>
This commit is contained in:
parent
a1ce636f56
commit
3b9a19e089
3 changed files with 17 additions and 6 deletions
|
|
@ -654,7 +654,8 @@ int main(int ac, char **av)
|
||||||
conf_set_all_new_symbols(def_default);
|
conf_set_all_new_symbols(def_default);
|
||||||
break;
|
break;
|
||||||
case randconfig:
|
case randconfig:
|
||||||
conf_set_all_new_symbols(def_random);
|
/* Really nothing to do in this loop */
|
||||||
|
while (conf_set_all_new_symbols(def_random)) ;
|
||||||
break;
|
break;
|
||||||
case defconfig:
|
case defconfig:
|
||||||
conf_set_all_new_symbols(def_default);
|
conf_set_all_new_symbols(def_default);
|
||||||
|
|
|
||||||
|
|
@ -1040,7 +1040,7 @@ void conf_set_changed_callback(void (*fn)(void))
|
||||||
conf_changed_callback = fn;
|
conf_changed_callback = fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void randomize_choice_values(struct symbol *csym)
|
static bool randomize_choice_values(struct symbol *csym)
|
||||||
{
|
{
|
||||||
struct property *prop;
|
struct property *prop;
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
|
|
@ -1053,7 +1053,7 @@ static void randomize_choice_values(struct symbol *csym)
|
||||||
* In both cases stop.
|
* In both cases stop.
|
||||||
*/
|
*/
|
||||||
if (csym->curr.tri != yes)
|
if (csym->curr.tri != yes)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
prop = sym_get_choice_prop(csym);
|
prop = sym_get_choice_prop(csym);
|
||||||
|
|
||||||
|
|
@ -1084,6 +1084,8 @@ static void randomize_choice_values(struct symbol *csym)
|
||||||
csym->flags |= SYMBOL_DEF_USER;
|
csym->flags |= SYMBOL_DEF_USER;
|
||||||
/* clear VALID to get value calculated */
|
/* clear VALID to get value calculated */
|
||||||
csym->flags &= ~(SYMBOL_VALID);
|
csym->flags &= ~(SYMBOL_VALID);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_all_choice_values(struct symbol *csym)
|
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);
|
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;
|
struct symbol *sym, *csym;
|
||||||
int i, cnt, pby, pty, ptm; /* pby: probability of boolean = y
|
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 );
|
exit( 1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool has_changed = false;
|
||||||
|
|
||||||
for_all_symbols(i, sym) {
|
for_all_symbols(i, sym) {
|
||||||
if (sym_has_value(sym) || (sym->flags & SYMBOL_VALID))
|
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)) {
|
switch (sym_get_type(sym)) {
|
||||||
case S_BOOLEAN:
|
case S_BOOLEAN:
|
||||||
case S_TRISTATE:
|
case S_TRISTATE:
|
||||||
|
has_changed = true;
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case def_yes:
|
case def_yes:
|
||||||
sym->def[S_DEF_USER].tri = 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);
|
sym_calc_value(csym);
|
||||||
if (mode == def_random)
|
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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ const char *conf_get_autoconfig_name(void);
|
||||||
char *conf_get_default_confname(void);
|
char *conf_get_default_confname(void);
|
||||||
void sym_set_change_count(int count);
|
void sym_set_change_count(int count);
|
||||||
void sym_add_change_count(int count);
|
void sym_add_change_count(int count);
|
||||||
void conf_set_all_new_symbols(enum conf_def_mode mode);
|
bool conf_set_all_new_symbols(enum conf_def_mode mode);
|
||||||
void set_all_choice_values(struct symbol *csym);
|
void set_all_choice_values(struct symbol *csym);
|
||||||
|
|
||||||
struct conf_printer {
|
struct conf_printer {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue