Skip to content

Commit

Permalink
net: switchdev: remove the transaction structure from port object not…
Browse files Browse the repository at this point in the history
…ifiers

Since the introduction of the switchdev API, port objects were
transmitted to drivers for offloading using a two-step transactional
model, with a prepare phase that was supposed to catch all errors, and a
commit phase that was supposed to never fail.

Some classes of failures can never be avoided, like hardware access, or
memory allocation. In the latter case, merely attempting to move the
memory allocation to the preparation phase makes it impossible to avoid
memory leaks, since commit 91cf8ec ("switchdev: Remove unused
transaction item queue") which has removed the unused mechanism of
passing on the allocated memory between one phase and another.

It is time we admit that separating the preparation from the commit
phase is something that is best left for the driver to decide, and not
something that should be baked into the API, especially since there are
no switchdev callers that depend on this.

This patch removes the struct switchdev_trans member from switchdev port
object notifier structures, and converts drivers to not look at this
member.

Where driver conversion is trivial (like in the case of the Marvell
Prestera driver, NXP DPAA2 switch, TI CPSW, and Rocker drivers), it is
done in this patch.

Where driver conversion needs more attention (DSA, Mellanox Spectrum),
the conversion is left for subsequent patches and here we only fake the
prepare/commit phases at a lower level, just not in the switchdev
notifier itself.

Where the code has a natural structure that is best left alone as a
preparation and a commit phase (as in the case of the Ocelot switch),
that structure is left in place, just made to not depend upon the
switchdev transactional model.

Signed-off-by: Vladimir Oltean <[email protected]>
Reviewed-by: Florian Fainelli <[email protected]>
Acked-by: Linus Walleij <[email protected]>
Acked-by: Jiri Pirko <[email protected]>
Reviewed-by: Ido Schimmel <[email protected]>
Signed-off-by: Jakub Kicinski <[email protected]>
  • Loading branch information
vladimiroltean authored and kuba-moo committed Jan 12, 2021
1 parent 3e85f58 commit ffb68fc
Show file tree
Hide file tree
Showing 12 changed files with 98 additions and 208 deletions.
7 changes: 1 addition & 6 deletions drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,6 @@ prestera_bridge_port_vlan_del(struct prestera_port *port,

static int prestera_port_vlans_add(struct prestera_port *port,
const struct switchdev_obj_port_vlan *vlan,
struct switchdev_trans *trans,
struct netlink_ext_ack *extack)
{
bool flag_untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
Expand All @@ -1034,9 +1033,6 @@ static int prestera_port_vlans_add(struct prestera_port *port,
if (netif_is_bridge_master(dev))
return 0;

if (switchdev_trans_ph_commit(trans))
return 0;

br_port = prestera_bridge_port_by_dev(sw->swdev, dev);
if (WARN_ON(!br_port))
return -EINVAL;
Expand All @@ -1052,7 +1048,6 @@ static int prestera_port_vlans_add(struct prestera_port *port,

static int prestera_port_obj_add(struct net_device *dev,
const struct switchdev_obj *obj,
struct switchdev_trans *trans,
struct netlink_ext_ack *extack)
{
struct prestera_port *port = netdev_priv(dev);
Expand All @@ -1061,7 +1056,7 @@ static int prestera_port_obj_add(struct net_device *dev,
switch (obj->id) {
case SWITCHDEV_OBJ_ID_PORT_VLAN:
vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
return prestera_port_vlans_add(port, vlan, trans, extack);
return prestera_port_vlans_add(port, vlan, extack);
default:
return -EOPNOTSUPP;
}
Expand Down
52 changes: 32 additions & 20 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1704,8 +1704,7 @@ static int mlxsw_sp_port_remove_from_mid(struct mlxsw_sp_port *mlxsw_sp_port,
}

static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
const struct switchdev_obj_port_mdb *mdb,
struct switchdev_trans *trans)
const struct switchdev_obj_port_mdb *mdb)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct net_device *orig_dev = mdb->obj.orig_dev;
Expand All @@ -1717,9 +1716,6 @@ static int mlxsw_sp_port_mdb_add(struct mlxsw_sp_port *mlxsw_sp_port,
u16 fid_index;
int err = 0;

if (switchdev_trans_ph_commit(trans))
return 0;

bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
if (!bridge_port)
return 0;
Expand Down Expand Up @@ -1801,32 +1797,38 @@ mlxsw_sp_port_mrouter_update_mdb(struct mlxsw_sp_port *mlxsw_sp_port,

static int mlxsw_sp_port_obj_add(struct net_device *dev,
const struct switchdev_obj *obj,
struct switchdev_trans *trans,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
const struct switchdev_obj_port_vlan *vlan;
struct switchdev_trans trans;
int err = 0;

switch (obj->id) {
case SWITCHDEV_OBJ_ID_PORT_VLAN:
vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
err = mlxsw_sp_port_vlans_add(mlxsw_sp_port, vlan, trans,

trans.ph_prepare = true;
err = mlxsw_sp_port_vlans_add(mlxsw_sp_port, vlan, &trans,
extack);

if (switchdev_trans_ph_prepare(trans)) {
/* The event is emitted before the changes are actually
* applied to the bridge. Therefore schedule the respin
* call for later, so that the respin logic sees the
* updated bridge state.
*/
mlxsw_sp_span_respin(mlxsw_sp_port->mlxsw_sp);
}
/* The event is emitted before the changes are actually
* applied to the bridge. Therefore schedule the respin
* call for later, so that the respin logic sees the
* updated bridge state.
*/
mlxsw_sp_span_respin(mlxsw_sp_port->mlxsw_sp);

if (err)
break;

trans.ph_prepare = false;
err = mlxsw_sp_port_vlans_add(mlxsw_sp_port, vlan, &trans,
extack);
break;
case SWITCHDEV_OBJ_ID_PORT_MDB:
err = mlxsw_sp_port_mdb_add(mlxsw_sp_port,
SWITCHDEV_OBJ_PORT_MDB(obj),
trans);
SWITCHDEV_OBJ_PORT_MDB(obj));
break;
default:
err = -EOPNOTSUPP;
Expand Down Expand Up @@ -3386,13 +3388,13 @@ mlxsw_sp_switchdev_vxlan_vlan_del(struct mlxsw_sp *mlxsw_sp,
static int
mlxsw_sp_switchdev_vxlan_vlans_add(struct net_device *vxlan_dev,
struct switchdev_notifier_port_obj_info *
port_obj_info)
port_obj_info,
struct switchdev_trans *trans)
{
struct switchdev_obj_port_vlan *vlan =
SWITCHDEV_OBJ_PORT_VLAN(port_obj_info->obj);
bool flag_untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
bool flag_pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
struct switchdev_trans *trans = port_obj_info->trans;
struct mlxsw_sp_bridge_device *bridge_device;
struct netlink_ext_ack *extack;
struct mlxsw_sp *mlxsw_sp;
Expand Down Expand Up @@ -3462,12 +3464,22 @@ mlxsw_sp_switchdev_handle_vxlan_obj_add(struct net_device *vxlan_dev,
struct switchdev_notifier_port_obj_info *
port_obj_info)
{
struct switchdev_trans trans;
int err = 0;

switch (port_obj_info->obj->id) {
case SWITCHDEV_OBJ_ID_PORT_VLAN:
trans.ph_prepare = true;
err = mlxsw_sp_switchdev_vxlan_vlans_add(vxlan_dev,
port_obj_info,
&trans);
if (err)
break;

trans.ph_prepare = false;
err = mlxsw_sp_switchdev_vxlan_vlans_add(vxlan_dev,
port_obj_info);
port_obj_info,
&trans);
break;
default:
break;
Expand Down
25 changes: 8 additions & 17 deletions drivers/net/ethernet/mscc/ocelot_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -890,33 +890,27 @@ static int ocelot_port_attr_set(struct net_device *dev,
}

static int ocelot_port_obj_add_vlan(struct net_device *dev,
const struct switchdev_obj_port_vlan *vlan,
struct switchdev_trans *trans)
const struct switchdev_obj_port_vlan *vlan)
{
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
int ret;

if (switchdev_trans_ph_prepare(trans))
ret = ocelot_vlan_vid_prepare(dev, vlan->vid, pvid, untagged);
else
ret = ocelot_vlan_vid_add(dev, vlan->vid, pvid, untagged);
ret = ocelot_vlan_vid_prepare(dev, vlan->vid, pvid, untagged);
if (ret)
return ret;

return ret;
return ocelot_vlan_vid_add(dev, vlan->vid, pvid, untagged);
}

static int ocelot_port_obj_add_mdb(struct net_device *dev,
const struct switchdev_obj_port_mdb *mdb,
struct switchdev_trans *trans)
const struct switchdev_obj_port_mdb *mdb)
{
struct ocelot_port_private *priv = netdev_priv(dev);
struct ocelot_port *ocelot_port = &priv->port;
struct ocelot *ocelot = ocelot_port->ocelot;
int port = priv->chip_port;

if (switchdev_trans_ph_prepare(trans))
return 0;

return ocelot_port_mdb_add(ocelot, port, mdb);
}

Expand All @@ -933,20 +927,17 @@ static int ocelot_port_obj_del_mdb(struct net_device *dev,

static int ocelot_port_obj_add(struct net_device *dev,
const struct switchdev_obj *obj,
struct switchdev_trans *trans,
struct netlink_ext_ack *extack)
{
int ret = 0;

switch (obj->id) {
case SWITCHDEV_OBJ_ID_PORT_VLAN:
ret = ocelot_port_obj_add_vlan(dev,
SWITCHDEV_OBJ_PORT_VLAN(obj),
trans);
SWITCHDEV_OBJ_PORT_VLAN(obj));
break;
case SWITCHDEV_OBJ_ID_PORT_MDB:
ret = ocelot_port_obj_add_mdb(dev, SWITCHDEV_OBJ_PORT_MDB(obj),
trans);
ret = ocelot_port_obj_add_mdb(dev, SWITCHDEV_OBJ_PORT_MDB(obj));
break;
default:
return -EOPNOTSUPP;
Expand Down
15 changes: 4 additions & 11 deletions drivers/net/ethernet/rocker/rocker_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1638,17 +1638,13 @@ rocker_world_port_attr_bridge_ageing_time_set(struct rocker_port *rocker_port,

static int
rocker_world_port_obj_vlan_add(struct rocker_port *rocker_port,
const struct switchdev_obj_port_vlan *vlan,
struct switchdev_trans *trans)
const struct switchdev_obj_port_vlan *vlan)
{
struct rocker_world_ops *wops = rocker_port->rocker->wops;

if (!wops->port_obj_vlan_add)
return -EOPNOTSUPP;

if (switchdev_trans_ph_prepare(trans))
return 0;

return wops->port_obj_vlan_add(rocker_port, vlan);
}

Expand Down Expand Up @@ -2102,17 +2098,15 @@ static int rocker_port_attr_set(struct net_device *dev,
}

static int rocker_port_obj_add(struct net_device *dev,
const struct switchdev_obj *obj,
struct switchdev_trans *trans)
const struct switchdev_obj *obj)
{
struct rocker_port *rocker_port = netdev_priv(dev);
int err = 0;

switch (obj->id) {
case SWITCHDEV_OBJ_ID_PORT_VLAN:
err = rocker_world_port_obj_vlan_add(rocker_port,
SWITCHDEV_OBJ_PORT_VLAN(obj),
trans);
SWITCHDEV_OBJ_PORT_VLAN(obj));
break;
default:
err = -EOPNOTSUPP;
Expand Down Expand Up @@ -2847,8 +2841,7 @@ rocker_switchdev_port_obj_event(unsigned long event, struct net_device *netdev,

switch (event) {
case SWITCHDEV_PORT_OBJ_ADD:
err = rocker_port_obj_add(netdev, port_obj_info->obj,
port_obj_info->trans);
err = rocker_port_obj_add(netdev, port_obj_info->obj);
break;
case SWITCHDEV_PORT_OBJ_DEL:
err = rocker_port_obj_del(netdev, port_obj_info->obj);
Expand Down
17 changes: 4 additions & 13 deletions drivers/net/ethernet/ti/cpsw_switchdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,8 +253,7 @@ static int cpsw_port_vlan_del(struct cpsw_priv *priv, u16 vid,
}

static int cpsw_port_vlans_add(struct cpsw_priv *priv,
const struct switchdev_obj_port_vlan *vlan,
struct switchdev_trans *trans)
const struct switchdev_obj_port_vlan *vlan)
{
bool untag = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
struct net_device *orig_dev = vlan->obj.orig_dev;
Expand All @@ -267,15 +266,11 @@ static int cpsw_port_vlans_add(struct cpsw_priv *priv,
if (cpu_port && !(vlan->flags & BRIDGE_VLAN_INFO_BRENTRY))
return 0;

if (switchdev_trans_ph_prepare(trans))
return 0;

return cpsw_port_vlan_add(priv, untag, pvid, vlan->vid, orig_dev);
}

static int cpsw_port_mdb_add(struct cpsw_priv *priv,
struct switchdev_obj_port_mdb *mdb,
struct switchdev_trans *trans)
struct switchdev_obj_port_mdb *mdb)

{
struct net_device *orig_dev = mdb->obj.orig_dev;
Expand All @@ -284,9 +279,6 @@ static int cpsw_port_mdb_add(struct cpsw_priv *priv,
int port_mask;
int err;

if (switchdev_trans_ph_prepare(trans))
return 0;

if (cpu_port)
port_mask = BIT(HOST_PORT_NUM);
else
Expand Down Expand Up @@ -325,7 +317,6 @@ static int cpsw_port_mdb_del(struct cpsw_priv *priv,

static int cpsw_port_obj_add(struct net_device *ndev,
const struct switchdev_obj *obj,
struct switchdev_trans *trans,
struct netlink_ext_ack *extack)
{
struct switchdev_obj_port_vlan *vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
Expand All @@ -338,11 +329,11 @@ static int cpsw_port_obj_add(struct net_device *ndev,

switch (obj->id) {
case SWITCHDEV_OBJ_ID_PORT_VLAN:
err = cpsw_port_vlans_add(priv, vlan, trans);
err = cpsw_port_vlans_add(priv, vlan);
break;
case SWITCHDEV_OBJ_ID_PORT_MDB:
case SWITCHDEV_OBJ_ID_HOST_MDB:
err = cpsw_port_mdb_add(priv, mdb, trans);
err = cpsw_port_mdb_add(priv, mdb);
break;
default:
err = -EOPNOTSUPP;
Expand Down
Loading

0 comments on commit ffb68fc

Please sign in to comment.