Commit d8517985 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'm7530-sw-fallback'



DENG Qingfang says:

====================
mt7530 software fallback bridging fix

DSA core has gained software fallback support since commit 2f5dc00f,
but it does not work properly on mt7530. This patch series fixes the
issues.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8eceea41 73c447ca
Loading
Loading
Loading
Loading
+61 −27
Original line number Diff line number Diff line
@@ -366,8 +366,8 @@ mt7530_fdb_write(struct mt7530_priv *priv, u16 vid,
	int i;

	reg[1] |= vid & CVID_MASK;
	if (vid > 1)
	reg[1] |= ATA2_IVL;
	reg[1] |= ATA2_FID(FID_BRIDGED);
	reg[2] |= (aging & AGE_TIMER_MASK) << AGE_TIMER;
	reg[2] |= (port_mask & PORT_MAP_MASK) << PORT_MAP;
	/* STATIC_ENT indicate that entry is static wouldn't
@@ -1021,6 +1021,10 @@ mt753x_cpu_port_enable(struct dsa_switch *ds, int port)
	mt7530_write(priv, MT7530_PCR_P(port),
		     PCR_MATRIX(dsa_user_ports(priv->ds)));

	/* Set to fallback mode for independent VLAN learning */
	mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
		   MT7530_PORT_FALLBACK_MODE);

	return 0;
}

@@ -1143,7 +1147,8 @@ mt7530_stp_state_set(struct dsa_switch *ds, int port, u8 state)
		break;
	}

	mt7530_rmw(priv, MT7530_SSP_P(port), FID_PST_MASK, stp_state);
	mt7530_rmw(priv, MT7530_SSP_P(port), FID_PST_MASK(FID_BRIDGED),
		   FID_PST(FID_BRIDGED, stp_state));
}

static int
@@ -1229,6 +1234,10 @@ mt7530_port_bridge_join(struct dsa_switch *ds, int port,
			   PCR_MATRIX_MASK, PCR_MATRIX(port_bitmap));
	priv->ports[port].pm |= PCR_MATRIX(port_bitmap);

	/* Set to fallback mode for independent VLAN learning */
	mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
		   MT7530_PORT_FALLBACK_MODE);

	mutex_unlock(&priv->reg_mutex);

	return 0;
@@ -1241,16 +1250,21 @@ mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
	bool all_user_ports_removed = true;
	int i;

	/* When a port is removed from the bridge, the port would be set up
	 * back to the default as is at initial boot which is a VLAN-unaware
	 * port.
	/* This is called after .port_bridge_leave when leaving a VLAN-aware
	 * bridge. Don't set standalone ports to fallback mode.
	 */
	if (dsa_to_port(ds, port)->bridge_dev)
		mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
		   MT7530_PORT_MATRIX_MODE);
			   MT7530_PORT_FALLBACK_MODE);

	mt7530_rmw(priv, MT7530_PVC_P(port), VLAN_ATTR_MASK | PVC_EG_TAG_MASK,
		   VLAN_ATTR(MT7530_VLAN_TRANSPARENT) |
		   PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));

	/* Set PVID to 0 */
	mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK,
		   G0_PORT_VID_DEF);

	for (i = 0; i < MT7530_NUM_PORTS; i++) {
		if (dsa_is_user_port(ds, i) &&
		    dsa_port_is_vlan_filtering(dsa_to_port(ds, i))) {
@@ -1276,15 +1290,14 @@ mt7530_port_set_vlan_aware(struct dsa_switch *ds, int port)
	struct mt7530_priv *priv = ds->priv;

	/* Trapped into security mode allows packet forwarding through VLAN
	 * table lookup. CPU port is set to fallback mode to let untagged
	 * frames pass through.
	 * table lookup.
	 */
	if (dsa_is_cpu_port(ds, port))
		mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
			   MT7530_PORT_FALLBACK_MODE);
	else
	if (dsa_is_user_port(ds, port)) {
		mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
			   MT7530_PORT_SECURITY_MODE);
		mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK,
			   G0_PORT_VID(priv->ports[port].pvid));
	}

	/* Set the port as a user port which is to be able to recognize VID
	 * from incoming packets before fetching entry within the VLAN table.
@@ -1329,6 +1342,13 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
			   PCR_MATRIX(BIT(MT7530_CPU_PORT)));
	priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT));

	/* When a port is removed from the bridge, the port would be set up
	 * back to the default as is at initial boot which is a VLAN-unaware
	 * port.
	 */
	mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
		   MT7530_PORT_MATRIX_MODE);

	mutex_unlock(&priv->reg_mutex);
}

@@ -1511,7 +1531,8 @@ mt7530_hw_vlan_add(struct mt7530_priv *priv,
	/* Validate the entry with independent learning, create egress tag per
	 * VLAN and joining the port as one of the port members.
	 */
	val = IVL_MAC | VTAG_EN | PORT_MEM(new_members) | VLAN_VALID;
	val = IVL_MAC | VTAG_EN | PORT_MEM(new_members) | FID(FID_BRIDGED) |
	      VLAN_VALID;
	mt7530_write(priv, MT7530_VAWD1, val);

	/* Decide whether adding tag or not for those outgoing packets from the
@@ -1601,9 +1622,13 @@ mt7530_port_vlan_add(struct dsa_switch *ds, int port,
	mt7530_hw_vlan_update(priv, vlan->vid, &new_entry, mt7530_hw_vlan_add);

	if (pvid) {
		mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK,
			   G0_PORT_VID(vlan->vid));
		priv->ports[port].pvid = vlan->vid;

		/* Only configure PVID if VLAN filtering is enabled */
		if (dsa_port_is_vlan_filtering(dsa_to_port(ds, port)))
			mt7530_rmw(priv, MT7530_PPBV1_P(port),
				   G0_PORT_VID_MASK,
				   G0_PORT_VID(vlan->vid));
	}

	mutex_unlock(&priv->reg_mutex);
@@ -1617,11 +1642,9 @@ mt7530_port_vlan_del(struct dsa_switch *ds, int port,
{
	struct mt7530_hw_vlan_entry target_entry;
	struct mt7530_priv *priv = ds->priv;
	u16 pvid;

	mutex_lock(&priv->reg_mutex);

	pvid = priv->ports[port].pvid;
	mt7530_hw_vlan_entry_init(&target_entry, port, 0);
	mt7530_hw_vlan_update(priv, vlan->vid, &target_entry,
			      mt7530_hw_vlan_del);
@@ -1629,11 +1652,12 @@ mt7530_port_vlan_del(struct dsa_switch *ds, int port,
	/* PVID is being restored to the default whenever the PVID port
	 * is being removed from the VLAN.
	 */
	if (pvid == vlan->vid)
		pvid = G0_PORT_VID_DEF;
	if (priv->ports[port].pvid == vlan->vid) {
		priv->ports[port].pvid = G0_PORT_VID_DEF;
		mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK,
			   G0_PORT_VID_DEF);
	}

	mt7530_rmw(priv, MT7530_PPBV1_P(port), G0_PORT_VID_MASK, pvid);
	priv->ports[port].pvid = pvid;

	mutex_unlock(&priv->reg_mutex);

@@ -2046,6 +2070,7 @@ mt7530_setup(struct dsa_switch *ds)
	 * as two netdev instances.
	 */
	dn = dsa_to_port(ds, MT7530_CPU_PORT)->master->dev.of_node->parent;
	ds->assisted_learning_on_cpu_port = true;
	ds->mtu_enforcement_ingress = true;

	if (priv->id == ID_MT7530) {
@@ -2116,6 +2141,9 @@ mt7530_setup(struct dsa_switch *ds)
		mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
			   PCR_MATRIX_CLR);

		/* Disable learning by default on all ports */
		mt7530_set(priv, MT7530_PSC_P(i), SA_DIS);

		if (dsa_is_cpu_port(ds, i)) {
			ret = mt753x_cpu_port_enable(ds, i);
			if (ret)
@@ -2123,8 +2151,9 @@ mt7530_setup(struct dsa_switch *ds)
		} else {
			mt7530_port_disable(ds, i);

			/* Disable learning by default on all user ports */
			mt7530_set(priv, MT7530_PSC_P(i), SA_DIS);
			/* Set default PVID to 0 on all user ports */
			mt7530_rmw(priv, MT7530_PPBV1_P(i), G0_PORT_VID_MASK,
				   G0_PORT_VID_DEF);
		}
		/* Enable consistent egress tag */
		mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK,
@@ -2281,6 +2310,9 @@ mt7531_setup(struct dsa_switch *ds)
		mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
			   PCR_MATRIX_CLR);

		/* Disable learning by default on all ports */
		mt7530_set(priv, MT7530_PSC_P(i), SA_DIS);

		mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR);

		if (dsa_is_cpu_port(ds, i)) {
@@ -2290,8 +2322,9 @@ mt7531_setup(struct dsa_switch *ds)
		} else {
			mt7530_port_disable(ds, i);

			/* Disable learning by default on all user ports */
			mt7530_set(priv, MT7530_PSC_P(i), SA_DIS);
			/* Set default PVID to 0 on all user ports */
			mt7530_rmw(priv, MT7530_PPBV1_P(i), G0_PORT_VID_MASK,
				   G0_PORT_VID_DEF);
		}

		/* Enable consistent egress tag */
@@ -2299,6 +2332,7 @@ mt7531_setup(struct dsa_switch *ds)
			   PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
	}

	ds->assisted_learning_on_cpu_port = true;
	ds->mtu_enforcement_ingress = true;

	/* Flush the FDB table */
+11 −3
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ enum mt753x_bpdu_port_fw {
#define  STATIC_ENT			3
#define MT7530_ATA2			0x78
#define  ATA2_IVL			BIT(15)
#define  ATA2_FID(x)			(((x) & 0x7) << 12)

/* Register for address table write data */
#define MT7530_ATWD			0x7c
@@ -148,11 +149,18 @@ enum mt7530_vlan_cmd {
#define  VTAG_EN			BIT(28)
/* VLAN Member Control */
#define  PORT_MEM(x)			(((x) & 0xff) << 16)
/* Filter ID */
#define  FID(x)				(((x) & 0x7) << 1)
/* VLAN Entry Valid */
#define  VLAN_VALID			BIT(0)
#define  PORT_MEM_SHFT			16
#define  PORT_MEM_MASK			0xff

enum mt7530_fid {
	FID_STANDALONE = 0,
	FID_BRIDGED = 1,
};

#define MT7530_VAWD2			0x98
/* Egress Tag Control */
#define  ETAG_CTRL_P(p, x)		(((x) & 0x3) << ((p) << 1))
@@ -179,8 +187,8 @@ enum mt7530_vlan_egress_attr {

/* Register for port STP state control */
#define MT7530_SSP_P(x)			(0x2000 + ((x) * 0x100))
#define  FID_PST(x)			((x) & 0x3)
#define  FID_PST_MASK			FID_PST(0x3)
#define  FID_PST(fid, state)		(((state) & 0x3) << ((fid) * 2))
#define  FID_PST_MASK(fid)		FID_PST(fid, 0x3)

enum mt7530_stp_state {
	MT7530_STP_DISABLED = 0,
@@ -247,7 +255,7 @@ enum mt7530_vlan_port_attr {
#define MT7530_PPBV1_P(x)		(0x2014 + ((x) * 0x100))
#define  G0_PORT_VID(x)			(((x) & 0xfff) << 0)
#define  G0_PORT_VID_MASK		G0_PORT_VID(0xfff)
#define  G0_PORT_VID_DEF		G0_PORT_VID(1)
#define  G0_PORT_VID_DEF		G0_PORT_VID(0)

/* Register for port MAC control register */
#define MT7530_PMCR_P(x)		(0x3000 + ((x) * 0x100))