Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 418d77ca authored by Russell King's avatar Russell King Committed by Greg Kroah-Hartman
Browse files

net: phylink: avoid resolving link state too early



commit 87454b6edc1b0143fdb3d9853285477e95af74a4 upstream.

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: b5bfc21af5cb ("net: sfp: do not probe SFP module before we're attached")
Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Cc: Sasha Levin <sashal@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 81bafd09
Loading
Loading
Loading
Loading
+13 −6
Original line number Diff line number Diff line
@@ -487,6 +487,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 const struct sfp_upstream_ops sfp_phylink_ops;

static int phylink_register_sfp(struct phylink *pl, struct device_node *np)
@@ -776,9 +787,7 @@ void phylink_stop(struct phylink *pl)
	if (pl->sfp_bus)
		sfp_upstream_stop(pl->sfp_bus);

	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);

@@ -1433,9 +1442,7 @@ static void phylink_sfp_link_down(void *upstream)

	WARN_ON(!lockdep_rtnl_is_held());

	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)