Skip to content

Commit

Permalink
Merge branch 'm7530-sw-fallback'
Browse files Browse the repository at this point in the history
DENG Qingfang says:

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

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

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 4, 2021
2 parents 8eceea4 + 73c447c commit d851798
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 30 deletions.
88 changes: 61 additions & 27 deletions drivers/net/dsa/mt7530.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_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
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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.
*/
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
MT7530_PORT_MATRIX_MODE);
if (dsa_to_port(ds, port)->bridge_dev)
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
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))) {
Expand All @@ -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.
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand All @@ -1617,23 +1642,22 @@ 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);

/* 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);

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -2116,15 +2141,19 @@ 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)
return ret;
} 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,
Expand Down Expand Up @@ -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)) {
Expand All @@ -2290,15 +2322,17 @@ 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 */
mt7530_rmw(priv, MT7530_PVC_P(i), PVC_EG_TAG_MASK,
PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
}

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

/* Flush the FDB table */
Expand Down
14 changes: 11 additions & 3 deletions drivers/net/dsa/mt7530.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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))
Expand All @@ -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,
Expand Down Expand Up @@ -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))
Expand Down

0 comments on commit d851798

Please sign in to comment.