mlxsw: spectrum_router: Use the available router pointer for netevent handling
authorPetr Machata <petrm@nvidia.com>
Fri, 9 Jun 2023 17:32:09 +0000 (19:32 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 12 Jun 2023 08:49:30 +0000 (09:49 +0100)
This code handles NETEVENT_DELAY_PROBE_TIME_UPDATE, which is invoked every
time the delay_probe_time changes. mlxsw router currently only maintains
one timer, so the last delay_probe_time set wins.

Currently, mlxsw uses mlxsw_sp_port_lower_dev_hold() to find a reference to
the router. This is no longer necessary. But as a side effect, this makes
sure that only updates to "interesting netdevices" (ones that have a
physical netdevice lower) are projected.

Retain that side effect by calling mlxsw_sp_port_dev_lower_find_rcu() and
punting if there is none. Then just proceed using the router pointer that's
already at hand in the helper.

Note that previously, the code took and put a reference of the netdevice.
Because the mlxsw_sp pointer is now obtained from the notifier block, the
port pointer (non-) NULL-ness is all that's relevant, and the reference
does not need to be taken anymore.

Signed-off-by: Petr Machata <petrm@nvidia.com>
Reviewed-by: Amit Cohen <amcohen@nvidia.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c

index 7b1877c..9d34fc8 100644 (file)
@@ -2766,13 +2766,22 @@ static int mlxsw_sp_router_schedule_work(struct net *net,
        return NOTIFY_DONE;
 }
 
+static bool mlxsw_sp_dev_lower_is_port(struct net_device *dev)
+{
+       struct mlxsw_sp_port *mlxsw_sp_port;
+
+       rcu_read_lock();
+       mlxsw_sp_port = mlxsw_sp_port_dev_lower_find_rcu(dev);
+       rcu_read_unlock();
+       return !!mlxsw_sp_port;
+}
+
 static int mlxsw_sp_router_netevent_event(struct notifier_block *nb,
                                          unsigned long event, void *ptr)
 {
        struct mlxsw_sp_netevent_work *net_work;
        struct mlxsw_sp_port *mlxsw_sp_port;
        struct mlxsw_sp_router *router;
-       struct mlxsw_sp *mlxsw_sp;
        unsigned long interval;
        struct neigh_parms *p;
        struct neighbour *n;
@@ -2791,15 +2800,11 @@ static int mlxsw_sp_router_netevent_event(struct notifier_block *nb,
                /* We are in atomic context and can't take RTNL mutex,
                 * so use RCU variant to walk the device chain.
                 */
-               mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(p->dev);
-               if (!mlxsw_sp_port)
+               if (!mlxsw_sp_dev_lower_is_port(p->dev))
                        return NOTIFY_DONE;
 
-               mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
                interval = jiffies_to_msecs(NEIGH_VAR(p, DELAY_PROBE_TIME));
-               mlxsw_sp->router->neighs_update.interval = interval;
-
-               mlxsw_sp_port_dev_put(mlxsw_sp_port);
+               router->neighs_update.interval = interval;
                break;
        case NETEVENT_NEIGH_UPDATE:
                n = ptr;