diff options
-rw-r--r-- | drivers/net/dsa/ocelot/felix.c | 19 | ||||
-rw-r--r-- | drivers/net/ethernet/mscc/ocelot.c | 45 | ||||
-rw-r--r-- | include/soc/mscc/ocelot.h | 7 |
3 files changed, 61 insertions, 10 deletions
diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 69546383a382..e2effeaa685e 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -532,6 +532,7 @@ static int felix_setup(struct dsa_switch *ds) ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports, 0)), ANA_PGID_PGID, PGID_UC); + ds->mtu_enforcement_ingress = true; /* It looks like the MAC/PCS interrupt register - PM0_IEVENT (0x8040) * isn't instantiated for the Felix PF. * In-band AN may take a few ms to complete, so we need to poll. @@ -609,6 +610,22 @@ static bool felix_txtstamp(struct dsa_switch *ds, int port, return false; } +static int felix_change_mtu(struct dsa_switch *ds, int port, int new_mtu) +{ + struct ocelot *ocelot = ds->priv; + + ocelot_port_set_maxlen(ocelot, port, new_mtu); + + return 0; +} + +static int felix_get_max_mtu(struct dsa_switch *ds, int port) +{ + struct ocelot *ocelot = ds->priv; + + return ocelot_get_max_mtu(ocelot, port); +} + static int felix_cls_flower_add(struct dsa_switch *ds, int port, struct flow_cls_offload *cls, bool ingress) { @@ -664,6 +681,8 @@ static const struct dsa_switch_ops felix_switch_ops = { .port_hwtstamp_set = felix_hwtstamp_set, .port_rxtstamp = felix_rxtstamp, .port_txtstamp = felix_txtstamp, + .port_change_mtu = felix_change_mtu, + .port_max_mtu = felix_get_max_mtu, .cls_flower_add = felix_cls_flower_add, .cls_flower_del = felix_cls_flower_del, .cls_flower_stats = felix_cls_flower_stats, diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index dc0e27328661..b4731df186f4 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -2185,13 +2185,25 @@ static int ocelot_init_timestamp(struct ocelot *ocelot) /* Configure the maximum SDU (L2 payload) on RX to the value specified in @sdu. * The length of VLAN tags is accounted for automatically via DEV_MAC_TAGS_CFG. + * In the special case that it's the NPI port that we're configuring, the + * length of the tag and optional prefix needs to be accounted for privately, + * in order to be able to sustain communication at the requested @sdu. */ -static void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu) +void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu) { struct ocelot_port *ocelot_port = ocelot->ports[port]; int maxlen = sdu + ETH_HLEN + ETH_FCS_LEN; int atop_wm; + if (port == ocelot->npi) { + maxlen += OCELOT_TAG_LEN; + + if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_SHORT) + maxlen += OCELOT_SHORT_PREFIX_LEN; + else if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_LONG) + maxlen += OCELOT_LONG_PREFIX_LEN; + } + ocelot_port_writel(ocelot_port, maxlen, DEV_MAC_MAXLEN_CFG); /* Set Pause WM hysteresis @@ -2209,6 +2221,24 @@ static void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu) SYS_ATOP, port); ocelot_write(ocelot, ocelot_wm_enc(atop_wm), SYS_ATOP_TOT_CFG); } +EXPORT_SYMBOL(ocelot_port_set_maxlen); + +int ocelot_get_max_mtu(struct ocelot *ocelot, int port) +{ + int max_mtu = 65535 - ETH_HLEN - ETH_FCS_LEN; + + if (port == ocelot->npi) { + max_mtu -= OCELOT_TAG_LEN; + + if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_SHORT) + max_mtu -= OCELOT_SHORT_PREFIX_LEN; + else if (ocelot->inj_prefix == OCELOT_TAG_PREFIX_LONG) + max_mtu -= OCELOT_LONG_PREFIX_LEN; + } + + return max_mtu; +} +EXPORT_SYMBOL(ocelot_get_max_mtu); void ocelot_init_port(struct ocelot *ocelot, int port) { @@ -2318,6 +2348,10 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi, { int cpu = ocelot->num_phys_ports; + ocelot->npi = npi; + ocelot->inj_prefix = injection; + ocelot->xtr_prefix = extraction; + /* The unicast destination PGID for the CPU port module is unused */ ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu); /* Instead set up a multicast destination PGID for traffic copied to @@ -2330,19 +2364,10 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi, ANA_PORT_PORT_CFG, cpu); if (npi >= 0 && npi < ocelot->num_phys_ports) { - int sdu = ETH_DATA_LEN + OCELOT_TAG_LEN; - ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M | QSYS_EXT_CPU_CFG_EXT_CPU_PORT(npi), QSYS_EXT_CPU_CFG); - if (injection == OCELOT_TAG_PREFIX_SHORT) - sdu += OCELOT_SHORT_PREFIX_LEN; - else if (injection == OCELOT_TAG_PREFIX_LONG) - sdu += OCELOT_LONG_PREFIX_LEN; - - ocelot_port_set_maxlen(ocelot, npi, sdu); - /* Enable NPI port */ ocelot_write_rix(ocelot, QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE | diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 007b584cc431..eadbc2ddfcb5 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -517,6 +517,11 @@ struct ocelot { */ u8 num_phys_ports; + int npi; + + enum ocelot_tag_prefix inj_prefix; + enum ocelot_tag_prefix xtr_prefix; + u32 *lags; struct list_head multicast; @@ -611,6 +616,8 @@ int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts); int ocelot_port_add_txtstamp_skb(struct ocelot_port *ocelot_port, struct sk_buff *skb); void ocelot_get_txtstamp(struct ocelot *ocelot); +void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu); +int ocelot_get_max_mtu(struct ocelot *ocelot, int port); int ocelot_cls_flower_replace(struct ocelot *ocelot, int port, struct flow_cls_offload *f, bool ingress); int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port, |