Commit bae33f2b authored by Vladimir Oltean's avatar Vladimir Oltean Committed by Jakub Kicinski
Browse files

net: switchdev: remove the transaction structure from port attributes



Since the introduction of the switchdev API, port attributes 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 91cf8ece ("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
attribute notifier structures, and converts drivers to not look at this
member.

In part, this patch contains a revert of my previous commit 2e554a7a
("net: dsa: propagate switchdev vlan_filtering prepare phase to
drivers").

For the most part, the conversion was trivial except for:
- Rocker's world implementation based on Broadcom OF-DPA had an odd
  implementation of ofdpa_port_attr_bridge_flags_set. The conversion was
  done mechanically, by pasting the implementation twice, then only
  keeping the code that would get executed during prepare phase on top,
  then only keeping the code that gets executed during the commit phase
  on bottom, then simplifying the resulting code until this was obtained.
- DSA's offloading of STP state, bridge flags, VLAN filtering and
  multicast router could be converted right away. But the ageing time
  could not, so a shim was introduced and this was left for a further
  commit.

Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Acked-by: default avatarJiri Pirko <jiri@nvidia.com>
Reviewed-by: Kurt Kanzenbach <kurt@linutronix.de> # hellcreek
Reviewed-by: Linus Walleij <linus.walleij@linaro.org> # RTL8366RB
Reviewed-by: default avatarIdo Schimmel <idosch@nvidia.com>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent cf6def51
Loading
Loading
Loading
Loading
+1 −5
Original line number Diff line number Diff line
@@ -1374,14 +1374,10 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
}
EXPORT_SYMBOL(b53_phylink_mac_link_up);

int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
		       struct switchdev_trans *trans)
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
{
	struct b53_device *dev = ds->priv;

	if (switchdev_trans_ph_prepare(trans))
		return 0;

	b53_enable_vlan(dev, dev->vlan_enabled, vlan_filtering);

	return 0;
+1 −2
Original line number Diff line number Diff line
@@ -348,8 +348,7 @@ void b53_phylink_mac_link_up(struct dsa_switch *ds, int port,
			     struct phy_device *phydev,
			     int speed, int duplex,
			     bool tx_pause, bool rx_pause);
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
		       struct switchdev_trans *trans);
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering);
int b53_vlan_prepare(struct dsa_switch *ds, int port,
		     const struct switchdev_obj_port_vlan *vlan);
void b53_vlan_add(struct dsa_switch *ds, int port,
+1 −2
Original line number Diff line number Diff line
@@ -190,8 +190,7 @@ static void dsa_loop_port_stp_state_set(struct dsa_switch *ds, int port,
}

static int dsa_loop_port_vlan_filtering(struct dsa_switch *ds, int port,
					bool vlan_filtering,
					struct switchdev_trans *trans)
					bool vlan_filtering)
{
	dev_dbg(ds->dev, "%s: port: %d, vlan_filtering: %d\n",
		__func__, port, vlan_filtering);
+1 −5
Original line number Diff line number Diff line
@@ -858,14 +858,10 @@ static int hellcreek_fdb_dump(struct dsa_switch *ds, int port,
}

static int hellcreek_vlan_filtering(struct dsa_switch *ds, int port,
				    bool vlan_filtering,
				    struct switchdev_trans *trans)
				    bool vlan_filtering)
{
	struct hellcreek *hellcreek = ds->priv;

	if (switchdev_trans_ph_prepare(trans))
		return 0;

	dev_dbg(hellcreek->dev, "%s VLAN filtering on port %d\n",
		vlan_filtering ? "Enable" : "Disable", port);

+5 −21
Original line number Diff line number Diff line
@@ -727,24 +727,15 @@ static int gswip_pce_load_microcode(struct gswip_priv *priv)
}

static int gswip_port_vlan_filtering(struct dsa_switch *ds, int port,
				     bool vlan_filtering,
				     struct switchdev_trans *trans)
				     bool vlan_filtering)
{
	struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev;
	struct gswip_priv *priv = ds->priv;

	/* Do not allow changing the VLAN filtering options while in bridge */
	if (switchdev_trans_ph_prepare(trans)) {
		struct net_device *bridge = dsa_to_port(ds, port)->bridge_dev;

		if (!bridge)
			return 0;

		if (!!(priv->port_vlan_filter & BIT(port)) != vlan_filtering)
	if (bridge && !!(priv->port_vlan_filter & BIT(port)) != vlan_filtering)
		return -EIO;

		return 0;
	}

	if (vlan_filtering) {
		/* Use port based VLAN tag */
		gswip_switch_mask(priv,
@@ -781,15 +772,8 @@ static int gswip_setup(struct dsa_switch *ds)

	/* disable port fetch/store dma on all ports */
	for (i = 0; i < priv->hw_info->max_ports; i++) {
		struct switchdev_trans trans;

		/* Skip the prepare phase, this shouldn't return an error
		 * during setup.
		 */
		trans.ph_prepare = false;

		gswip_port_disable(ds, i);
		gswip_port_vlan_filtering(ds, i, false, &trans);
		gswip_port_vlan_filtering(ds, i, false);
	}

	/* enable Switch */
Loading