diff options
author | Vladimir Oltean <vladimir.oltean@nxp.com> | 2023-01-18 01:02:33 +0200 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2023-01-18 20:52:26 -0800 |
commit | c33bfaf91c4ca6c859b1184396c0be2c1a94e745 (patch) | |
tree | 14f75d8b37ade00afe3083e2f7ab51e863fa8fe4 /drivers/net/ethernet/freescale/enetc | |
parent | 766338c79b1045866870b795882c4d42c64c9c53 (diff) |
net: enetc: set up XDP program under enetc_reconfigure()
Offloading a BPF program to the RX path of the driver suffers from the
same problems as the PTP reconfiguration - improper error checking can
leave the driver in an invalid state, and the link on the PHY is lost.
Reuse the enetc_reconfigure() procedure, but here, we need to run some
code in the middle of the ring reconfiguration procedure - while the
interface is still down. Introduce a callback which makes that possible.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/ethernet/freescale/enetc')
-rw-r--r-- | drivers/net/ethernet/freescale/enetc/enetc.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index ce3319f55573..eeff69336a80 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -2489,16 +2489,24 @@ int enetc_close(struct net_device *ndev) return 0; } -static int enetc_reconfigure(struct enetc_ndev_priv *priv, bool extended) +static int enetc_reconfigure(struct enetc_ndev_priv *priv, bool extended, + int (*cb)(struct enetc_ndev_priv *priv, void *ctx), + void *ctx) { struct enetc_bdr_resource *tx_res, *rx_res; int err; ASSERT_RTNL(); - /* If the interface is down, do nothing. */ - if (!netif_running(priv->ndev)) + /* If the interface is down, run the callback right away, + * without reconfiguration. + */ + if (!netif_running(priv->ndev)) { + if (cb) + cb(priv, ctx); + return 0; + } tx_res = enetc_alloc_tx_resources(priv); if (IS_ERR(tx_res)) { @@ -2516,6 +2524,10 @@ static int enetc_reconfigure(struct enetc_ndev_priv *priv, bool extended) enetc_clear_bdrs(priv); enetc_free_rxtx_rings(priv); + /* Interface is down, run optional callback now */ + if (cb) + cb(priv, ctx); + enetc_assign_tx_resources(priv, tx_res); enetc_assign_rx_resources(priv, rx_res); enetc_setup_bdrs(priv, extended); @@ -2586,21 +2598,11 @@ int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data) return 0; } -static int enetc_setup_xdp_prog(struct net_device *ndev, struct bpf_prog *prog, - struct netlink_ext_ack *extack) +static int enetc_reconfigure_xdp_cb(struct enetc_ndev_priv *priv, void *ctx) { - struct enetc_ndev_priv *priv = netdev_priv(ndev); - struct bpf_prog *old_prog; - bool is_up; + struct bpf_prog *old_prog, *prog = ctx; int i; - /* The buffer layout is changing, so we need to drain the old - * RX buffers and seed new ones. - */ - is_up = netif_running(ndev); - if (is_up) - dev_close(ndev); - old_prog = xchg(&priv->xdp_prog, prog); if (old_prog) bpf_prog_put(old_prog); @@ -2616,12 +2618,23 @@ static int enetc_setup_xdp_prog(struct net_device *ndev, struct bpf_prog *prog, rx_ring->buffer_offset = ENETC_RXB_PAD; } - if (is_up) - return dev_open(ndev, extack); - return 0; } +static int enetc_setup_xdp_prog(struct net_device *ndev, struct bpf_prog *prog, + struct netlink_ext_ack *extack) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + bool extended; + + extended = !!(priv->active_offloads & ENETC_F_RX_TSTAMP); + + /* The buffer layout is changing, so we need to drain the old + * RX buffers and seed new ones. + */ + return enetc_reconfigure(priv, extended, enetc_reconfigure_xdp_cb, prog); +} + int enetc_setup_bpf(struct net_device *ndev, struct netdev_bpf *bpf) { switch (bpf->command) { @@ -2755,7 +2768,7 @@ static int enetc_hwtstamp_set(struct net_device *ndev, struct ifreq *ifr) if ((new_offloads ^ priv->active_offloads) & ENETC_F_RX_TSTAMP) { bool extended = !!(new_offloads & ENETC_F_RX_TSTAMP); - err = enetc_reconfigure(priv, extended); + err = enetc_reconfigure(priv, extended, NULL, NULL); if (err) return err; } |