[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 11 Nov 2021 13:23:11 +0000
From: Alvin Šipraga <ALSI@...g-olufsen.dk>
To: Vladimir Oltean <vladimir.oltean@....com>,
"netdev@...r.kernel.org" <netdev@...r.kernel.org>
CC: Florian Fainelli <f.fainelli@...il.com>,
Andrew Lunn <andrew@...n.ch>,
Vivien Didelot <vivien.didelot@...il.com>,
Tobias Waldekranz <tobias@...dekranz.com>,
DENG Qingfang <dqfext@...il.com>
Subject: Re: [RFC PATCH net-next 6/6] net: dsa: eliminate dsa_switch_ops ::
port_bridge_tx_fwd_{,un}offload
On 10/26/21 18:26, Vladimir Oltean wrote:
> We don't really need new switch API for these, and with new switches
> which intend to add support for this feature, it will become cumbersome
> to maintain.
>
> Simply pass a boolean argument to ->port_bridge_join which the driver
> must set to true if it implements the TX forwarding offload feature.
>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@....com>
> ---
Reviewed-by: Alvin Šipraga <alsi@...g-olufsen.dk>
> drivers/net/dsa/b53/b53_common.c | 3 +-
> drivers/net/dsa/b53/b53_priv.h | 3 +-
> drivers/net/dsa/dsa_loop.c | 3 +-
> drivers/net/dsa/hirschmann/hellcreek.c | 3 +-
> drivers/net/dsa/lan9303-core.c | 3 +-
> drivers/net/dsa/lantiq_gswip.c | 3 +-
> drivers/net/dsa/microchip/ksz_common.c | 3 +-
> drivers/net/dsa/microchip/ksz_common.h | 2 +-
> drivers/net/dsa/mt7530.c | 2 +-
> drivers/net/dsa/mv88e6xxx/chip.c | 71 ++++++++++++--------------
> drivers/net/dsa/ocelot/felix.c | 2 +-
> drivers/net/dsa/qca8k.c | 3 +-
> drivers/net/dsa/rtl8366rb.c | 3 +-
> drivers/net/dsa/sja1105/sja1105_main.c | 22 ++++++--
> drivers/net/dsa/xrs700x/xrs700x.c | 2 +-
> include/net/dsa.h | 10 ++--
> net/dsa/dsa_priv.h | 1 +
> net/dsa/port.c | 39 ++------------
> net/dsa/switch.c | 3 +-
> 19 files changed, 81 insertions(+), 100 deletions(-)
>
> diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
> index 4e41b1a63108..3867f3d4545f 100644
> --- a/drivers/net/dsa/b53/b53_common.c
> +++ b/drivers/net/dsa/b53/b53_common.c
> @@ -1860,7 +1860,8 @@ int b53_mdb_del(struct dsa_switch *ds, int port,
> }
> EXPORT_SYMBOL(b53_mdb_del);
>
> -int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge)
> +int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge,
> + bool *tx_fwd_offload)
> {
> struct b53_device *dev = ds->priv;
> s8 cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
> diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
> index ee17f8b516ca..b41dc8ac2ca8 100644
> --- a/drivers/net/dsa/b53/b53_priv.h
> +++ b/drivers/net/dsa/b53/b53_priv.h
> @@ -324,7 +324,8 @@ void b53_get_strings(struct dsa_switch *ds, int port, u32 stringset,
> void b53_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data);
> int b53_get_sset_count(struct dsa_switch *ds, int port, int sset);
> void b53_get_ethtool_phy_stats(struct dsa_switch *ds, int port, uint64_t *data);
> -int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge);
> +int b53_br_join(struct dsa_switch *ds, int port, struct dsa_bridge bridge,
> + bool *tx_fwd_offload);
> void b53_br_leave(struct dsa_switch *ds, int port, struct dsa_bridge bridge);
> void b53_br_set_stp_state(struct dsa_switch *ds, int port, u8 state);
> void b53_br_fast_age(struct dsa_switch *ds, int port);
> diff --git a/drivers/net/dsa/dsa_loop.c b/drivers/net/dsa/dsa_loop.c
> index 70db3a9aa355..33daaf10c488 100644
> --- a/drivers/net/dsa/dsa_loop.c
> +++ b/drivers/net/dsa/dsa_loop.c
> @@ -167,7 +167,8 @@ static int dsa_loop_phy_write(struct dsa_switch *ds, int port,
> }
>
> static int dsa_loop_port_bridge_join(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge)
> + struct dsa_bridge bridge,
> + bool *tx_fwd_offload)
> {
> dev_dbg(ds->dev, "%s: port: %d, bridge: %s\n",
> __func__, port, bridge.dev->name);
> diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c
> index 17c2d13670a9..53ab5f8ae92e 100644
> --- a/drivers/net/dsa/hirschmann/hellcreek.c
> +++ b/drivers/net/dsa/hirschmann/hellcreek.c
> @@ -674,7 +674,8 @@ static int hellcreek_bridge_flags(struct dsa_switch *ds, int port,
> }
>
> static int hellcreek_port_bridge_join(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge)
> + struct dsa_bridge bridge,
> + bool *tx_fwd_offload)
> {
> struct hellcreek *hellcreek = ds->priv;
>
> diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c
> index 29d909484275..d55784d19fa4 100644
> --- a/drivers/net/dsa/lan9303-core.c
> +++ b/drivers/net/dsa/lan9303-core.c
> @@ -1103,7 +1103,8 @@ static void lan9303_port_disable(struct dsa_switch *ds, int port)
> }
>
> static int lan9303_port_bridge_join(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge)
> + struct dsa_bridge bridge,
> + bool *tx_fwd_offload)
> {
> struct lan9303 *chip = ds->priv;
>
> diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c
> index 6b9b9c712e58..6b5bef7f2a59 100644
> --- a/drivers/net/dsa/lantiq_gswip.c
> +++ b/drivers/net/dsa/lantiq_gswip.c
> @@ -1146,7 +1146,8 @@ static int gswip_vlan_remove(struct gswip_priv *priv,
> }
>
> static int gswip_port_bridge_join(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge)
> + struct dsa_bridge bridge,
> + bool *tx_fwd_offload)
> {
> struct net_device *br = bridge.dev;
> struct gswip_priv *priv = ds->priv;
> diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
> index 23784d14a5da..1d13aa56e7d1 100644
> --- a/drivers/net/dsa/microchip/ksz_common.c
> +++ b/drivers/net/dsa/microchip/ksz_common.c
> @@ -173,7 +173,8 @@ void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf)
> EXPORT_SYMBOL_GPL(ksz_get_ethtool_stats);
>
> int ksz_port_bridge_join(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge)
> + struct dsa_bridge bridge,
> + bool *tx_fwd_offload)
> {
> struct ksz_device *dev = ds->priv;
>
> diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
> index df953c2bc56e..b444df218c2d 100644
> --- a/drivers/net/dsa/microchip/ksz_common.h
> +++ b/drivers/net/dsa/microchip/ksz_common.h
> @@ -159,7 +159,7 @@ void ksz_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode,
> int ksz_sset_count(struct dsa_switch *ds, int port, int sset);
> void ksz_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *buf);
> int ksz_port_bridge_join(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge);
> + struct dsa_bridge bridge, bool *tx_fwd_offload);
> void ksz_port_bridge_leave(struct dsa_switch *ds, int port,
> struct dsa_bridge bridge);
> void ksz_port_fast_age(struct dsa_switch *ds, int port);
> diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
> index 85cc5aca7f96..dcd1a3932cfb 100644
> --- a/drivers/net/dsa/mt7530.c
> +++ b/drivers/net/dsa/mt7530.c
> @@ -1186,7 +1186,7 @@ mt7530_port_bridge_flags(struct dsa_switch *ds, int port,
>
> static int
> mt7530_port_bridge_join(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge)
> + struct dsa_bridge bridge, bool *tx_fwd_offload)
> {
> struct mt7530_priv *priv = ds->priv;
> u32 port_bitmap = BIT(MT7530_CPU_PORT);
> diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
> index 73613a667f6c..0aac71dece29 100644
> --- a/drivers/net/dsa/mv88e6xxx/chip.c
> +++ b/drivers/net/dsa/mv88e6xxx/chip.c
> @@ -2448,8 +2448,27 @@ static int mv88e6xxx_bridge_map(struct mv88e6xxx_chip *chip,
> return 0;
> }
>
> +/* Treat the software bridge as a virtual single-port switch behind the
> + * CPU and map in the PVT. First dst->last_switch elements are taken by
> + * physical switches, so start from beyond that range.
> + */
> +static int mv88e6xxx_map_virtual_bridge_to_pvt(struct dsa_switch *ds,
> + unsigned int bridge_num)
> +{
> + u8 dev = bridge_num + ds->dst->last_switch;
> + struct mv88e6xxx_chip *chip = ds->priv;
> + int err;
> +
> + mv88e6xxx_reg_lock(chip);
> + err = mv88e6xxx_pvt_map(chip, dev, 0);
> + mv88e6xxx_reg_unlock(chip);
> +
> + return err;
> +}
> +
> static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge)
> + struct dsa_bridge bridge,
> + bool *tx_fwd_offload)
> {
> struct mv88e6xxx_chip *chip = ds->priv;
> int err;
> @@ -2464,6 +2483,14 @@ static int mv88e6xxx_port_bridge_join(struct dsa_switch *ds, int port,
> if (err)
> goto unlock;
>
> + if (mv88e6xxx_has_pvt(chip)) {
> + err = mv88e6xxx_map_virtual_bridge_to_pvt(ds, bridge.num);
> + if (err)
> + goto unlock;
> +
> + *tx_fwd_offload = true;
> + }
> +
> unlock:
> mv88e6xxx_reg_unlock(chip);
>
> @@ -2478,6 +2505,10 @@ static void mv88e6xxx_port_bridge_leave(struct dsa_switch *ds, int port,
>
> mv88e6xxx_reg_lock(chip);
>
> + if (bridge.tx_fwd_offload &&
> + mv88e6xxx_map_virtual_bridge_to_pvt(ds, bridge.num))
> + dev_err(ds->dev, "failed to remap cross-chip Port VLAN\n");
> +
> if (mv88e6xxx_bridge_map(chip, bridge) ||
> mv88e6xxx_port_vlan_map(chip, port))
> dev_err(ds->dev, "failed to remap in-chip Port VLAN\n");
> @@ -2523,42 +2554,6 @@ static void mv88e6xxx_crosschip_bridge_leave(struct dsa_switch *ds,
> mv88e6xxx_reg_unlock(chip);
> }
>
> -/* Treat the software bridge as a virtual single-port switch behind the
> - * CPU and map in the PVT. First dst->last_switch elements are taken by
> - * physical switches, so start from beyond that range.
> - */
> -static int mv88e6xxx_map_virtual_bridge_to_pvt(struct dsa_switch *ds,
> - unsigned int bridge_num)
> -{
> - u8 dev = bridge_num + ds->dst->last_switch;
> - struct mv88e6xxx_chip *chip = ds->priv;
> - int err;
> -
> - mv88e6xxx_reg_lock(chip);
> - err = mv88e6xxx_pvt_map(chip, dev, 0);
> - mv88e6xxx_reg_unlock(chip);
> -
> - return err;
> -}
> -
> -static int mv88e6xxx_bridge_tx_fwd_offload(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge)
> -{
> - return mv88e6xxx_map_virtual_bridge_to_pvt(ds, bridge.num);
> -}
> -
> -static void mv88e6xxx_bridge_tx_fwd_unoffload(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge)
> -{
> - int err;
> -
> - err = mv88e6xxx_map_virtual_bridge_to_pvt(ds, bridge.num);
> - if (err) {
> - dev_err(ds->dev, "failed to remap cross-chip Port VLAN: %pe\n",
> - ERR_PTR(err));
> - }
> -}
> -
> static int mv88e6xxx_software_reset(struct mv88e6xxx_chip *chip)
> {
> if (chip->info->ops->reset)
> @@ -6278,8 +6273,6 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
> .crosschip_lag_change = mv88e6xxx_crosschip_lag_change,
> .crosschip_lag_join = mv88e6xxx_crosschip_lag_join,
> .crosschip_lag_leave = mv88e6xxx_crosschip_lag_leave,
> - .port_bridge_tx_fwd_offload = mv88e6xxx_bridge_tx_fwd_offload,
> - .port_bridge_tx_fwd_unoffload = mv88e6xxx_bridge_tx_fwd_unoffload,
> };
>
> static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
> diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
> index 8cf82fa91a6b..001213891b91 100644
> --- a/drivers/net/dsa/ocelot/felix.c
> +++ b/drivers/net/dsa/ocelot/felix.c
> @@ -698,7 +698,7 @@ static int felix_bridge_flags(struct dsa_switch *ds, int port,
> }
>
> static int felix_bridge_join(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge)
> + struct dsa_bridge bridge, bool *tx_fwd_offload)
> {
> struct ocelot *ocelot = ds->priv;
>
> diff --git a/drivers/net/dsa/qca8k.c b/drivers/net/dsa/qca8k.c
> index 3ae10f22ada9..390dad77f062 100644
> --- a/drivers/net/dsa/qca8k.c
> +++ b/drivers/net/dsa/qca8k.c
> @@ -1729,7 +1729,8 @@ qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
> }
>
> static int qca8k_port_bridge_join(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge)
> + struct dsa_bridge bridge,
> + bool *tx_fwd_offload)
> {
> struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv;
> int port_mask, cpu_port;
> diff --git a/drivers/net/dsa/rtl8366rb.c b/drivers/net/dsa/rtl8366rb.c
> index fac2333a3f5e..ecc19bd5115f 100644
> --- a/drivers/net/dsa/rtl8366rb.c
> +++ b/drivers/net/dsa/rtl8366rb.c
> @@ -1186,7 +1186,8 @@ rtl8366rb_port_disable(struct dsa_switch *ds, int port)
>
> static int
> rtl8366rb_port_bridge_join(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge)
> + struct dsa_bridge bridge,
> + bool *tx_fwd_offload)
> {
> struct realtek_smi *smi = ds->priv;
> unsigned int port_bitmap = 0;
> diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
> index 24584fe2e760..cefde41ce8d6 100644
> --- a/drivers/net/dsa/sja1105/sja1105_main.c
> +++ b/drivers/net/dsa/sja1105/sja1105_main.c
> @@ -2074,14 +2074,30 @@ static void sja1105_bridge_stp_state_set(struct dsa_switch *ds, int port,
> }
>
> static int sja1105_bridge_join(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge)
> + struct dsa_bridge bridge,
> + bool *tx_fwd_offload)
> {
> - return sja1105_bridge_member(ds, port, bridge, true);
> + int rc;
> +
> + rc = sja1105_bridge_member(ds, port, bridge, true);
> + if (rc)
> + return rc;
> +
> + rc = dsa_tag_8021q_bridge_tx_fwd_offload(ds, port, bridge);
> + if (rc) {
> + sja1105_bridge_member(ds, port, bridge, false);
> + return rc;
> + }
> +
> + *tx_fwd_offload = true;
> +
> + return 0;
> }
>
> static void sja1105_bridge_leave(struct dsa_switch *ds, int port,
> struct dsa_bridge bridge)
> {
> + dsa_tag_8021q_bridge_tx_fwd_unoffload(ds, port, bridge);
> sja1105_bridge_member(ds, port, bridge, false);
> }
>
> @@ -3230,8 +3246,6 @@ static const struct dsa_switch_ops sja1105_switch_ops = {
> .tag_8021q_vlan_add = sja1105_dsa_8021q_vlan_add,
> .tag_8021q_vlan_del = sja1105_dsa_8021q_vlan_del,
> .port_prechangeupper = sja1105_prechangeupper,
> - .port_bridge_tx_fwd_offload = dsa_tag_8021q_bridge_tx_fwd_offload,
> - .port_bridge_tx_fwd_unoffload = dsa_tag_8021q_bridge_tx_fwd_unoffload,
> };
>
> static const struct of_device_id sja1105_dt_ids[];
> diff --git a/drivers/net/dsa/xrs700x/xrs700x.c b/drivers/net/dsa/xrs700x/xrs700x.c
> index ebb55dfd9c4e..35fa19ddaf19 100644
> --- a/drivers/net/dsa/xrs700x/xrs700x.c
> +++ b/drivers/net/dsa/xrs700x/xrs700x.c
> @@ -540,7 +540,7 @@ static int xrs700x_bridge_common(struct dsa_switch *ds, int port,
> }
>
> static int xrs700x_bridge_join(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge)
> + struct dsa_bridge bridge, bool *tx_fwd_offload)
> {
> return xrs700x_bridge_common(ds, port, bridge, true);
> }
> diff --git a/include/net/dsa.h b/include/net/dsa.h
> index 5e83c64bc96a..94dc8b5ee9c8 100644
> --- a/include/net/dsa.h
> +++ b/include/net/dsa.h
> @@ -222,6 +222,7 @@ struct dsa_mall_tc_entry {
> struct dsa_bridge {
> struct net_device *dev;
> unsigned int num;
> + bool tx_fwd_offload;
> refcount_t refcount;
> };
>
> @@ -814,15 +815,10 @@ struct dsa_switch_ops {
> */
> int (*set_ageing_time)(struct dsa_switch *ds, unsigned int msecs);
> int (*port_bridge_join)(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge);
> + struct dsa_bridge bridge,
> + bool *tx_fwd_offload);
> void (*port_bridge_leave)(struct dsa_switch *ds, int port,
> struct dsa_bridge bridge);
> - /* Called right after .port_bridge_join() */
> - int (*port_bridge_tx_fwd_offload)(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge);
> - /* Called right before .port_bridge_leave() */
> - void (*port_bridge_tx_fwd_unoffload)(struct dsa_switch *ds, int port,
> - struct dsa_bridge bridge);
> void (*port_stp_state_set)(struct dsa_switch *ds, int port,
> u8 state);
> void (*port_fast_age)(struct dsa_switch *ds, int port);
> diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
> index 489712ead08f..5abe6864967a 100644
> --- a/net/dsa/dsa_priv.h
> +++ b/net/dsa/dsa_priv.h
> @@ -56,6 +56,7 @@ struct dsa_notifier_bridge_info {
> int tree_index;
> int sw_index;
> int port;
> + bool tx_fwd_offload;
> };
>
> /* DSA_NOTIFIER_FDB_* */
> diff --git a/net/dsa/port.c b/net/dsa/port.c
> index b2e66994f72c..b1113788bf9b 100644
> --- a/net/dsa/port.c
> +++ b/net/dsa/port.c
> @@ -270,37 +270,6 @@ static void dsa_port_switchdev_unsync_attrs(struct dsa_port *dp)
> */
> }
>
> -static void dsa_port_bridge_tx_fwd_unoffload(struct dsa_port *dp,
> - struct dsa_bridge bridge)
> -{
> - struct dsa_switch *ds = dp->ds;
> -
> - /* No bridge TX forwarding offload => do nothing */
> - if (!ds->ops->port_bridge_tx_fwd_unoffload || !bridge.num)
> - return;
> -
> - /* Notify the chips only once the offload has been deactivated, so
> - * that they can update their configuration accordingly.
> - */
> - ds->ops->port_bridge_tx_fwd_unoffload(ds, dp->index, bridge);
> -}
> -
> -static bool dsa_port_bridge_tx_fwd_offload(struct dsa_port *dp,
> - struct dsa_bridge bridge)
> -{
> - struct dsa_switch *ds = dp->ds;
> - int err;
> -
> - /* FDB isolation is required for TX forwarding offload */
> - if (!ds->ops->port_bridge_tx_fwd_offload || !bridge.num)
> - return false;
> -
> - /* Notify the driver */
> - err = ds->ops->port_bridge_tx_fwd_offload(ds, dp->index, bridge);
> -
> - return err ? false : true;
> -}
> -
> static int dsa_port_bridge_create(struct dsa_port *dp,
> struct net_device *br,
> struct netlink_ext_ack *extack)
> @@ -361,7 +330,6 @@ int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br,
> };
> struct net_device *dev = dp->slave;
> struct net_device *brport_dev;
> - bool tx_fwd_offload;
> int err;
>
> /* Here the interface is already bridged. Reflect the current
> @@ -378,12 +346,13 @@ int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br,
> if (err)
> goto out_rollback;
>
> - tx_fwd_offload = dsa_port_bridge_tx_fwd_offload(dp, info.bridge);
> + /* Drivers which support bridge TX forwarding should set this */
> + dp->bridge->tx_fwd_offload = info.tx_fwd_offload;
>
> err = switchdev_bridge_port_offload(brport_dev, dev, dp,
> &dsa_slave_switchdev_notifier,
> &dsa_slave_switchdev_blocking_notifier,
> - tx_fwd_offload, extack);
> + dp->bridge->tx_fwd_offload, extack);
> if (err)
> goto out_rollback_unbridge;
>
> @@ -434,8 +403,6 @@ void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br)
> */
> dsa_port_bridge_destroy(dp, br);
>
> - dsa_port_bridge_tx_fwd_unoffload(dp, info.bridge);
> -
> err = dsa_broadcast(DSA_NOTIFIER_BRIDGE_LEAVE, &info);
> if (err)
> dev_err(dp->ds->dev,
> diff --git a/net/dsa/switch.c b/net/dsa/switch.c
> index cd0630dd5417..9c92edd96961 100644
> --- a/net/dsa/switch.c
> +++ b/net/dsa/switch.c
> @@ -95,7 +95,8 @@ static int dsa_switch_bridge_join(struct dsa_switch *ds,
> if (!ds->ops->port_bridge_join)
> return -EOPNOTSUPP;
>
> - err = ds->ops->port_bridge_join(ds, info->port, info->bridge);
> + err = ds->ops->port_bridge_join(ds, info->port, info->bridge,
> + &info->tx_fwd_offload);
> if (err)
> return err;
> }
>
Powered by blists - more mailing lists