net: phylink: avoid resolving link state too early
During testing on Armada 388 platforms, it was found with a certain
module configuration that it was possible to trigger a kernel oops
during the module load process, caused by the phylink resolver being
triggered for a currently disabled interface.
This problem was introduced by changing the way the SFP registration
works, which now can result in the sfp link down notification being
called during phylink_create().
Fixes: b5bfc21af5
("net: sfp: do not probe SFP module before we're attached")
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
a7603ac1fc
Коммит
87454b6edc
|
@ -474,6 +474,17 @@ static void phylink_run_resolve(struct phylink *pl)
|
|||
queue_work(system_power_efficient_wq, &pl->resolve);
|
||||
}
|
||||
|
||||
static void phylink_run_resolve_and_disable(struct phylink *pl, int bit)
|
||||
{
|
||||
unsigned long state = pl->phylink_disable_state;
|
||||
|
||||
set_bit(bit, &pl->phylink_disable_state);
|
||||
if (state == 0) {
|
||||
queue_work(system_power_efficient_wq, &pl->resolve);
|
||||
flush_work(&pl->resolve);
|
||||
}
|
||||
}
|
||||
|
||||
static void phylink_fixed_poll(struct timer_list *t)
|
||||
{
|
||||
struct phylink *pl = container_of(t, struct phylink, link_poll);
|
||||
|
@ -924,9 +935,7 @@ void phylink_stop(struct phylink *pl)
|
|||
if (pl->link_an_mode == MLO_AN_FIXED && !IS_ERR(pl->link_gpio))
|
||||
del_timer_sync(&pl->link_poll);
|
||||
|
||||
set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
|
||||
queue_work(system_power_efficient_wq, &pl->resolve);
|
||||
flush_work(&pl->resolve);
|
||||
phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phylink_stop);
|
||||
|
||||
|
@ -1632,9 +1641,7 @@ static void phylink_sfp_link_down(void *upstream)
|
|||
|
||||
ASSERT_RTNL();
|
||||
|
||||
set_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state);
|
||||
queue_work(system_power_efficient_wq, &pl->resolve);
|
||||
flush_work(&pl->resolve);
|
||||
phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_LINK);
|
||||
}
|
||||
|
||||
static void phylink_sfp_link_up(void *upstream)
|
||||
|
|
Загрузка…
Ссылка в новой задаче