switch (state) { case BR_STATE_DISABLED:
bpdus = 0;
fallthrough; case BR_STATE_BLOCKING: case BR_STATE_LISTENING:
val = XRS_PORT_DISABLED; break; case BR_STATE_LEARNING:
val = XRS_PORT_LEARNING; break; case BR_STATE_FORWARDING:
val = XRS_PORT_FORWARDING; break; default:
dev_err(ds->dev, "invalid STP state: %d\n", state); return;
}
regmap_fields_write(priv->ps_forward, port, val);
/* Enable/disable inbound policy added by xrs700x_port_add_bpdu_ipf() * which allows BPDU forwarding to the CPU port when the front facing * port is in disabled/learning state.
*/
regmap_update_bits(priv->regmap, XRS_ETH_ADDR_CFG(port, 0), 1, bpdus);
/* Add an inbound policy filter which matches the BPDU destination MAC * and forwards to the CPU port. Leave the policy disabled, it will be * enabled as needed.
*/ staticint xrs700x_port_add_bpdu_ipf(struct dsa_switch *ds, int port)
{ struct xrs700x *priv = ds->priv; unsignedint val = 0; int i = 0; int ret;
/* Compare all 48 bits of the destination MAC address. */
ret = regmap_write(priv->regmap, XRS_ETH_ADDR_CFG(port, 0), 48 << 2); if (ret) return ret;
/* match BPDU destination 01:80:c2:00:00:00 */ for (i = 0; i < sizeof(eth_stp_addr); i += 2) {
ret = regmap_write(priv->regmap, XRS_ETH_ADDR_0(port, 0) + i,
eth_stp_addr[i] |
(eth_stp_addr[i + 1] << 8)); if (ret) return ret;
}
/* Mirror BPDU to CPU port */ for (i = 0; i < ds->num_ports; i++) { if (dsa_is_cpu_port(ds, i))
val |= BIT(i);
}
ret = regmap_write(priv->regmap, XRS_ETH_ADDR_FWD_MIRROR(port, 0), val); if (ret) return ret;
ret = regmap_write(priv->regmap, XRS_ETH_ADDR_FWD_ALLOW(port, 0), 0); if (ret) return ret;
return 0;
}
/* Add an inbound policy filter which matches the HSR/PRP supervision MAC * range and forwards to the CPU port without discarding duplicates. * This is required to correctly populate the HSR/PRP node_table. * Leave the policy disabled, it will be enabled as needed.
*/ staticint xrs700x_port_add_hsrsup_ipf(struct dsa_switch *ds, int port, int fwdport)
{ struct xrs700x *priv = ds->priv; unsignedint val = 0; int i = 0; int ret;
/* Compare 40 bits of the destination MAC address. */
ret = regmap_write(priv->regmap, XRS_ETH_ADDR_CFG(port, 1), 40 << 2); if (ret) return ret;
/* match HSR/PRP supervision destination 01:15:4e:00:01:XX */ for (i = 0; i < sizeof(eth_hsrsup_addr); i += 2) {
ret = regmap_write(priv->regmap, XRS_ETH_ADDR_0(port, 1) + i,
eth_hsrsup_addr[i] |
(eth_hsrsup_addr[i + 1] << 8)); if (ret) return ret;
}
/* Mirror HSR/PRP supervision to CPU port */ for (i = 0; i < ds->num_ports; i++) { if (dsa_is_cpu_port(ds, i))
val |= BIT(i);
}
ret = regmap_write(priv->regmap, XRS_ETH_ADDR_FWD_MIRROR(port, 1), val); if (ret) return ret;
if (fwdport >= 0)
val |= BIT(fwdport);
/* Allow must be set prevent duplicate discard */
ret = regmap_write(priv->regmap, XRS_ETH_ADDR_FWD_ALLOW(port, 1), val); if (ret) return ret;
return 0;
}
staticint xrs700x_port_setup(struct dsa_switch *ds, int port)
{ bool cpu_port = dsa_is_cpu_port(ds, port); struct xrs700x *priv = ds->priv; unsignedint val = 0; int ret, i;
staticvoid xrs700x_mac_link_up(struct phylink_config *config, struct phy_device *phydev, unsignedint mode, phy_interface_t interface, int speed, int duplex, bool tx_pause, bool rx_pause)
{ struct dsa_port *dp = dsa_phylink_to_port(config); struct xrs700x *priv = dp->ds->priv; int port = dp->index; unsignedint val;
switch (speed) { case SPEED_1000:
val = XRS_PORT_SPEED_1000; break; case SPEED_100:
val = XRS_PORT_SPEED_100; break; case SPEED_10:
val = XRS_PORT_SPEED_10; break; default: return;
}
regmap_write(priv->regmap, XRS_HSR_CFG(partner->index),
val | XRS_HSR_CFG_LANID_A);
regmap_write(priv->regmap, XRS_HSR_CFG(port),
val | XRS_HSR_CFG_LANID_B);
/* Clear bits for both redundant ports (HSR only) and the CPU port to * enable forwarding.
*/
val = GENMASK(ds->num_ports - 1, 0); if (ver == HSR_V1) {
val &= ~BIT(partner->index);
val &= ~BIT(port);
fwd = true;
}
val &= ~BIT(dsa_upstream_port(ds, port));
regmap_write(priv->regmap, XRS_PORT_FWD_MASK(partner->index), val);
regmap_write(priv->regmap, XRS_PORT_FWD_MASK(port), val);
/* Enable inbound policy which allows HSR/PRP supervision forwarding * to the CPU port without discarding duplicates. Continue to * forward to redundant ports when in HSR mode while discarding * duplicates.
*/
ret = xrs700x_port_add_hsrsup_ipf(ds, partner->index, fwd ? port : -1); if (ret) return ret;
ret = xrs700x_port_add_hsrsup_ipf(ds, port, fwd ? partner->index : -1); if (ret) return ret;
/* Clear bit for the CPU port to enable forwarding. */
val = GENMASK(ds->num_ports - 1, 0);
val &= ~BIT(dsa_upstream_port(ds, port));
regmap_write(priv->regmap, XRS_PORT_FWD_MASK(partner->index), val);
regmap_write(priv->regmap, XRS_PORT_FWD_MASK(port), val);
/* Disable inbound policy added by xrs700x_port_add_hsrsup_ipf() * which allows HSR/PRP supervision forwarding to the CPU port without * discarding duplicates.
*/
regmap_update_bits(priv->regmap,
XRS_ETH_ADDR_CFG(partner->index, 1), 1, 0);
regmap_update_bits(priv->regmap, XRS_ETH_ADDR_CFG(port, 1), 1, 0);
hsr_pair[0] = port;
hsr_pair[1] = partner->index; for (i = 0; i < ARRAY_SIZE(hsr_pair); i++) {
user = dsa_to_port(ds, hsr_pair[i])->user;
user->features &= ~XRS7000X_SUPPORTED_HSR_FEATURES;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.