From 2e359b00a11715c7a89d7448e6e4cb4d84543520 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Sun, 11 Sep 2022 04:07:03 +0300 Subject: net: dsa: propagate extack to port_lag_join Drivers could refuse to offload a LAG configuration for a variety of reasons, mainly having to do with its TX type. Additionally, since DSA masters may now also be LAG interfaces, and this will translate into a call to port_lag_join on the CPU ports, there may be extra restrictions there. Propagate the netlink extack to this DSA method in order for drivers to give a meaningful error message back to the user. Signed-off-by: Vladimir Oltean Signed-off-by: Paolo Abeni --- drivers/net/dsa/mv88e6xxx/chip.c | 27 +++++++++++++++++++-------- drivers/net/dsa/ocelot/felix.c | 5 +++-- drivers/net/dsa/qca/qca8k-common.c | 23 +++++++++++++++++------ drivers/net/dsa/qca/qca8k.h | 3 ++- 4 files changed, 41 insertions(+), 17 deletions(-) (limited to 'drivers/net/dsa') diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 6f4ea39ab466..5f178faa110f 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -6593,14 +6593,17 @@ out: static bool mv88e6xxx_lag_can_offload(struct dsa_switch *ds, struct dsa_lag lag, - struct netdev_lag_upper_info *info) + struct netdev_lag_upper_info *info, + struct netlink_ext_ack *extack) { struct mv88e6xxx_chip *chip = ds->priv; struct dsa_port *dp; int members = 0; - if (!mv88e6xxx_has_lag(chip)) + if (!mv88e6xxx_has_lag(chip)) { + NL_SET_ERR_MSG_MOD(extack, "Chip does not support LAG offload"); return false; + } if (!lag.id) return false; @@ -6609,14 +6612,20 @@ static bool mv88e6xxx_lag_can_offload(struct dsa_switch *ds, /* Includes the port joining the LAG */ members++; - if (members > 8) + if (members > 8) { + NL_SET_ERR_MSG_MOD(extack, + "Cannot offload more than 8 LAG ports"); return false; + } /* We could potentially relax this to include active * backup in the future. */ - if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) + if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) { + NL_SET_ERR_MSG_MOD(extack, + "Can only offload LAG using hash TX type"); return false; + } /* Ideally we would also validate that the hash type matches * the hardware. Alas, this is always set to unknown on team @@ -6769,12 +6778,13 @@ static int mv88e6xxx_port_lag_change(struct dsa_switch *ds, int port) static int mv88e6xxx_port_lag_join(struct dsa_switch *ds, int port, struct dsa_lag lag, - struct netdev_lag_upper_info *info) + struct netdev_lag_upper_info *info, + struct netlink_ext_ack *extack) { struct mv88e6xxx_chip *chip = ds->priv; int err, id; - if (!mv88e6xxx_lag_can_offload(ds, lag, info)) + if (!mv88e6xxx_lag_can_offload(ds, lag, info, extack)) return -EOPNOTSUPP; /* DSA LAG IDs are one-based */ @@ -6827,12 +6837,13 @@ static int mv88e6xxx_crosschip_lag_change(struct dsa_switch *ds, int sw_index, static int mv88e6xxx_crosschip_lag_join(struct dsa_switch *ds, int sw_index, int port, struct dsa_lag lag, - struct netdev_lag_upper_info *info) + struct netdev_lag_upper_info *info, + struct netlink_ext_ack *extack) { struct mv88e6xxx_chip *chip = ds->priv; int err; - if (!mv88e6xxx_lag_can_offload(ds, lag, info)) + if (!mv88e6xxx_lag_can_offload(ds, lag, info, extack)) return -EOPNOTSUPP; mv88e6xxx_reg_lock(chip); diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index c73ef5f7aa64..82dcc21a7172 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -861,11 +861,12 @@ static void felix_bridge_leave(struct dsa_switch *ds, int port, static int felix_lag_join(struct dsa_switch *ds, int port, struct dsa_lag lag, - struct netdev_lag_upper_info *info) + struct netdev_lag_upper_info *info, + struct netlink_ext_ack *extack) { struct ocelot *ocelot = ds->priv; - return ocelot_port_lag_join(ocelot, port, lag.dev, info); + return ocelot_port_lag_join(ocelot, port, lag.dev, info, extack); } static int felix_lag_leave(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/qca/qca8k-common.c b/drivers/net/dsa/qca/qca8k-common.c index bba95613e218..fb45b598847b 100644 --- a/drivers/net/dsa/qca/qca8k-common.c +++ b/drivers/net/dsa/qca/qca8k-common.c @@ -1017,7 +1017,8 @@ int qca8k_port_vlan_del(struct dsa_switch *ds, int port, static bool qca8k_lag_can_offload(struct dsa_switch *ds, struct dsa_lag lag, - struct netdev_lag_upper_info *info) + struct netdev_lag_upper_info *info, + struct netlink_ext_ack *extack) { struct dsa_port *dp; int members = 0; @@ -1029,15 +1030,24 @@ static bool qca8k_lag_can_offload(struct dsa_switch *ds, /* Includes the port joining the LAG */ members++; - if (members > QCA8K_NUM_PORTS_FOR_LAG) + if (members > QCA8K_NUM_PORTS_FOR_LAG) { + NL_SET_ERR_MSG_MOD(extack, + "Cannot offload more than 4 LAG ports"); return false; + } - if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) + if (info->tx_type != NETDEV_LAG_TX_TYPE_HASH) { + NL_SET_ERR_MSG_MOD(extack, + "Can only offload LAG using hash TX type"); return false; + } if (info->hash_type != NETDEV_LAG_HASH_L2 && - info->hash_type != NETDEV_LAG_HASH_L23) + info->hash_type != NETDEV_LAG_HASH_L23) { + NL_SET_ERR_MSG_MOD(extack, + "Can only offload L2 or L2+L3 TX hash"); return false; + } return true; } @@ -1160,11 +1170,12 @@ static int qca8k_lag_refresh_portmap(struct dsa_switch *ds, int port, } int qca8k_port_lag_join(struct dsa_switch *ds, int port, struct dsa_lag lag, - struct netdev_lag_upper_info *info) + struct netdev_lag_upper_info *info, + struct netlink_ext_ack *extack) { int ret; - if (!qca8k_lag_can_offload(ds, lag, info)) + if (!qca8k_lag_can_offload(ds, lag, info, extack)) return -EOPNOTSUPP; ret = qca8k_lag_setup_hash(ds, lag, info); diff --git a/drivers/net/dsa/qca/qca8k.h b/drivers/net/dsa/qca/qca8k.h index e36ecc9777f4..0b7a5cb12321 100644 --- a/drivers/net/dsa/qca/qca8k.h +++ b/drivers/net/dsa/qca/qca8k.h @@ -512,7 +512,8 @@ int qca8k_port_vlan_del(struct dsa_switch *ds, int port, /* Common port LAG function */ int qca8k_port_lag_join(struct dsa_switch *ds, int port, struct dsa_lag lag, - struct netdev_lag_upper_info *info); + struct netdev_lag_upper_info *info, + struct netlink_ext_ack *extack); int qca8k_port_lag_leave(struct dsa_switch *ds, int port, struct dsa_lag lag); -- cgit v1.2.3-59-g8ed1b