Commit 0b912fc9 authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller

net: dsa: felix: support changing the MTU

Changing the MTU for this switch means altering the
DEV_GMII:MAC_CFG_STATUS:MAC_MAXLEN_CFG field MAX_LEN, which in turn
limits the size of frames that can be received.

Special accounting needs to be done for the DSA CPU port (NPI port in
hardware terms). The NPI port configuration needs to be held inside the
private ocelot structure, since it is now accessed from multiple places.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fb77ffc6
...@@ -532,6 +532,7 @@ static int felix_setup(struct dsa_switch *ds) ...@@ -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(GENMASK(ocelot->num_phys_ports, 0)),
ANA_PGID_PGID, PGID_UC); ANA_PGID_PGID, PGID_UC);
ds->mtu_enforcement_ingress = true;
/* It looks like the MAC/PCS interrupt register - PM0_IEVENT (0x8040) /* It looks like the MAC/PCS interrupt register - PM0_IEVENT (0x8040)
* isn't instantiated for the Felix PF. * isn't instantiated for the Felix PF.
* In-band AN may take a few ms to complete, so we need to poll. * 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, ...@@ -609,6 +610,22 @@ static bool felix_txtstamp(struct dsa_switch *ds, int port,
return false; 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, static int felix_cls_flower_add(struct dsa_switch *ds, int port,
struct flow_cls_offload *cls, bool ingress) struct flow_cls_offload *cls, bool ingress)
{ {
...@@ -664,6 +681,8 @@ static const struct dsa_switch_ops felix_switch_ops = { ...@@ -664,6 +681,8 @@ static const struct dsa_switch_ops felix_switch_ops = {
.port_hwtstamp_set = felix_hwtstamp_set, .port_hwtstamp_set = felix_hwtstamp_set,
.port_rxtstamp = felix_rxtstamp, .port_rxtstamp = felix_rxtstamp,
.port_txtstamp = felix_txtstamp, .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_add = felix_cls_flower_add,
.cls_flower_del = felix_cls_flower_del, .cls_flower_del = felix_cls_flower_del,
.cls_flower_stats = felix_cls_flower_stats, .cls_flower_stats = felix_cls_flower_stats,
......
...@@ -2185,13 +2185,25 @@ static int ocelot_init_timestamp(struct ocelot *ocelot) ...@@ -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. /* 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. * 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]; struct ocelot_port *ocelot_port = ocelot->ports[port];
int maxlen = sdu + ETH_HLEN + ETH_FCS_LEN; int maxlen = sdu + ETH_HLEN + ETH_FCS_LEN;
int atop_wm; 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); ocelot_port_writel(ocelot_port, maxlen, DEV_MAC_MAXLEN_CFG);
/* Set Pause WM hysteresis /* Set Pause WM hysteresis
...@@ -2209,6 +2221,24 @@ static void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu) ...@@ -2209,6 +2221,24 @@ static void ocelot_port_set_maxlen(struct ocelot *ocelot, int port, size_t sdu)
SYS_ATOP, port); SYS_ATOP, port);
ocelot_write(ocelot, ocelot_wm_enc(atop_wm), SYS_ATOP_TOT_CFG); 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) void ocelot_init_port(struct ocelot *ocelot, int port)
{ {
...@@ -2318,6 +2348,10 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi, ...@@ -2318,6 +2348,10 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
{ {
int cpu = ocelot->num_phys_ports; 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 */ /* The unicast destination PGID for the CPU port module is unused */
ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu); ocelot_write_rix(ocelot, 0, ANA_PGID_PGID, cpu);
/* Instead set up a multicast destination PGID for traffic copied to /* Instead set up a multicast destination PGID for traffic copied to
...@@ -2330,19 +2364,10 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi, ...@@ -2330,19 +2364,10 @@ void ocelot_configure_cpu(struct ocelot *ocelot, int npi,
ANA_PORT_PORT_CFG, cpu); ANA_PORT_PORT_CFG, cpu);
if (npi >= 0 && npi < ocelot->num_phys_ports) { 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 | ocelot_write(ocelot, QSYS_EXT_CPU_CFG_EXT_CPUQ_MSK_M |
QSYS_EXT_CPU_CFG_EXT_CPU_PORT(npi), QSYS_EXT_CPU_CFG_EXT_CPU_PORT(npi),
QSYS_EXT_CPU_CFG); 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 */ /* Enable NPI port */
ocelot_write_rix(ocelot, ocelot_write_rix(ocelot,
QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE | QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE |
......
...@@ -517,6 +517,11 @@ struct ocelot { ...@@ -517,6 +517,11 @@ struct ocelot {
*/ */
u8 num_phys_ports; u8 num_phys_ports;
int npi;
enum ocelot_tag_prefix inj_prefix;
enum ocelot_tag_prefix xtr_prefix;
u32 *lags; u32 *lags;
struct list_head multicast; struct list_head multicast;
...@@ -611,6 +616,8 @@ int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts); ...@@ -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, int ocelot_port_add_txtstamp_skb(struct ocelot_port *ocelot_port,
struct sk_buff *skb); struct sk_buff *skb);
void ocelot_get_txtstamp(struct ocelot *ocelot); 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, int ocelot_cls_flower_replace(struct ocelot *ocelot, int port,
struct flow_cls_offload *f, bool ingress); struct flow_cls_offload *f, bool ingress);
int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port, int ocelot_cls_flower_destroy(struct ocelot *ocelot, int port,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment