net: dsa: don't leave dangling pointers in dp->pl when failing
authorVladimir Oltean <vladimir.oltean@nxp.com>
Thu, 29 Sep 2022 07:29:00 +0000 (09:29 +0200)
committerJakub Kicinski <kuba@kernel.org>
Sat, 1 Oct 2022 01:17:16 +0000 (18:17 -0700)
commitcf5ca4ddc37a693b17fdb653cb84b920b1185d71
treea1421c503e49d6cde71b5bc3bfb260b62c2f5c7a
parentd82acd85cc41a8e5d5e0e4c2a3f4b645def29723
net: dsa: don't leave dangling pointers in dp->pl when failing

There is a desire to simplify the dsa_port registration path with
devlink, and this involves reworking a bit how user ports which fail to
connect to their PHY (because it's missing) get reinitialized as UNUSED
devlink ports.

The desire is for the change to look something like this; basically
dsa_port_setup() has failed, we just change dp->type and call
dsa_port_setup() again.

-/* Destroy the current devlink port, and create a new one which has the UNUSED
- * flavour.
- */
-static int dsa_port_reinit_as_unused(struct dsa_port *dp)
+static int dsa_port_setup_as_unused(struct dsa_port *dp)
 {
- dsa_port_devlink_teardown(dp);
  dp->type = DSA_PORT_TYPE_UNUSED;
- return dsa_port_devlink_setup(dp);
+ return dsa_port_setup(dp);
 }

For an UNUSED port, dsa_port_setup() mostly only calls dsa_port_devlink_setup()
anyway, so we could get away with calling just that. But if we call the
full blown dsa_port_setup(dp) (which will be needed to properly set
dp->setup = true), the callee will have the tendency to go through this
code block too, and call dsa_port_disable(dp):

switch (dp->type) {
case DSA_PORT_TYPE_UNUSED:
dsa_port_disable(dp);
break;

That is not very good, because dsa_port_disable() has this hidden inside
of it:

if (dp->pl)
phylink_stop(dp->pl);

Fact is, we are not prepared to handle a call to dsa_port_disable() with
a struct dsa_port that came from a previous (and failed) call to
dsa_port_setup(). We do not clean up dp->pl, and this will make the
second call to dsa_port_setup() call phylink_stop() on a dangling dp->pl
pointer.

Solve this by creating an API for phylink destruction which is symmetric
to the phylink creation, and never leave dp->pl set to anything except
NULL or a valid phylink structure.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/dsa/dsa_priv.h
net/dsa/port.c
net/dsa/slave.c