Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'net-dsa-marvell-mtu-reporting'

Vladimir Oltean says:

====================
Fix MTU reporting for Marvell DSA switches where we can't change it

As explained in patch 2, the driver doesn't know how to change the MTU
on MV88E6165, MV88E6191, MV88E6220, MV88E6250 and MV88E6290, and there
is a regression where it actually reports an MTU value below the
Ethernet standard (1500).

Fixing that shows another issue where DSA is unprepared to be told that
a switch supports an MTU of only 1500, and still errors out. That is
addressed by patch 1.

Testing was not done on "real" hardware, but on a different Marvell DSA
switch, with code modified such that the driver doesn't know how to
change the MTU on that, either.

A key assumption is that these switches don't need any MTU configuration
to pass full MTU-sized, DSA-tagged packets, which seems like a
reasonable assumption to make. My 6390 and 6190 switches, with
.port_set_jumbo_size commented out, certainly don't seem to have any
problem passing MTU-sized traffic, as can be seen in this iperf3 session
captured with tcpdump on the DSA master:

$MAC > $MAC, Marvell DSA mode Forward, dev 2, port 8, untagged, VID 1000,
FPri 0, ethertype IPv4 (0x0800), length 1518:
10.0.0.69.49590 > 10.0.0.1.5201: Flags [.], seq 81088:82536,
ack 1, win 502, options [nop,nop,TS val 2221498829 ecr 3012859850],
length 1448

I don't want to go all the way and say that the adjustment made by
commit b9c587fed61c ("dsa: mv88e6xxx: Include tagger overhead when
setting MTU for DSA and CPU ports") is completely unnecessary, just that
there's an equally good chance that the switches with unknown MTU
configuration procedure "just work".
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+17 -8
+12 -4
drivers/net/dsa/mv88e6xxx/chip.c
··· 3549 3549 return 10240 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN; 3550 3550 else if (chip->info->ops->set_max_frame_size) 3551 3551 return 1632 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN; 3552 - return 1522 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN; 3552 + return ETH_DATA_LEN; 3553 3553 } 3554 3554 3555 3555 static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) 3556 3556 { 3557 3557 struct mv88e6xxx_chip *chip = ds->priv; 3558 3558 int ret = 0; 3559 + 3560 + /* For families where we don't know how to alter the MTU, 3561 + * just accept any value up to ETH_DATA_LEN 3562 + */ 3563 + if (!chip->info->ops->port_set_jumbo_size && 3564 + !chip->info->ops->set_max_frame_size) { 3565 + if (new_mtu > ETH_DATA_LEN) 3566 + return -EINVAL; 3567 + 3568 + return 0; 3569 + } 3559 3570 3560 3571 if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port)) 3561 3572 new_mtu += EDSA_HLEN; ··· 3576 3565 ret = chip->info->ops->port_set_jumbo_size(chip, port, new_mtu); 3577 3566 else if (chip->info->ops->set_max_frame_size) 3578 3567 ret = chip->info->ops->set_max_frame_size(chip, new_mtu); 3579 - else 3580 - if (new_mtu > 1522) 3581 - ret = -EINVAL; 3582 3568 mv88e6xxx_reg_unlock(chip); 3583 3569 3584 3570 return ret;
+5 -4
net/dsa/slave.c
··· 1933 1933 int new_master_mtu; 1934 1934 int old_master_mtu; 1935 1935 int mtu_limit; 1936 + int overhead; 1936 1937 int cpu_mtu; 1937 1938 int err; 1938 1939 ··· 1962 1961 largest_mtu = slave_mtu; 1963 1962 } 1964 1963 1965 - mtu_limit = min_t(int, master->max_mtu, dev->max_mtu); 1964 + overhead = dsa_tag_protocol_overhead(cpu_dp->tag_ops); 1965 + mtu_limit = min_t(int, master->max_mtu, dev->max_mtu + overhead); 1966 1966 old_master_mtu = master->mtu; 1967 - new_master_mtu = largest_mtu + dsa_tag_protocol_overhead(cpu_dp->tag_ops); 1967 + new_master_mtu = largest_mtu + overhead; 1968 1968 if (new_master_mtu > mtu_limit) 1969 1969 return -ERANGE; 1970 1970 ··· 2000 1998 2001 1999 out_port_failed: 2002 2000 if (new_master_mtu != old_master_mtu) 2003 - dsa_port_mtu_change(cpu_dp, old_master_mtu - 2004 - dsa_tag_protocol_overhead(cpu_dp->tag_ops)); 2001 + dsa_port_mtu_change(cpu_dp, old_master_mtu - overhead); 2005 2002 out_cpu_failed: 2006 2003 if (new_master_mtu != old_master_mtu) 2007 2004 dev_set_mtu(master, old_master_mtu);