• Vladimir Oltean's avatar
    net: dsa: felix: implement port flushing on .phylink_mac_link_down · eb4733d7
    Vladimir Oltean authored
    There are several issues which may be seen when the link goes down while
    forwarding traffic, all of which can be attributed to the fact that the
    port flushing procedure from the reference manual was not closely
    followed.
    
    With flow control enabled on both the ingress port and the egress port,
    it may happen when a link goes down that Ethernet packets are in flight.
    In flow control mode, frames are held back and not dropped. When there
    is enough traffic in flight (example: iperf3 TCP), then the ingress port
    might enter congestion and never exit that state. This is a problem,
    because it is the egress port's link that went down, and that has caused
    the inability of the ingress port to send packets to any other port.
    This is solved by flushing the egress port's queues when it goes down.
    
    There is also a problem when performing stream splitting for
    IEEE 802.1CB traffic (not yet upstream, but a sort of multicast,
    basically). There, if one port from the destination ports mask goes
    down, splitting the stream towards the other destinations will no longer
    be performed. This can be traced down to this line:
    
    	ocelot_port_writel(ocelot_port, 0, DEV_MAC_ENA_CFG);
    
    which should have been instead, as per the reference manual:
    
    	ocelot_port_rmwl(ocelot_port, 0, DEV_MAC_ENA_CFG_RX_ENA,
    			 DEV_MAC_ENA_CFG);
    
    Basically only DEV_MAC_ENA_CFG_RX_ENA should be disabled, but not
    DEV_MAC_ENA_CFG_TX_ENA - I don't have further insight into why that is
    the case, but apparently multicasting to several ports will cause issues
    if at least one of them doesn't have DEV_MAC_ENA_CFG_TX_ENA set.
    
    I am not sure what the state of the Ocelot VSC7514 driver is, but
    probably not as bad as Felix/Seville, since VSC7514 uses phylib and has
    the following in ocelot_adjust_link:
    
    	if (!phydev->link)
    		return;
    
    therefore the port is not really put down when the link is lost, unlike
    the DSA drivers which use .phylink_mac_link_down for that.
    
    Nonetheless, I put ocelot_port_flush() in the common ocelot.c because it
    needs to access some registers from drivers/net/ethernet/mscc/ocelot_rew.h
    which are not exported in include/soc/mscc/ and a bugfix patch should
    probably not move headers around.
    
    Fixes: bdeced75 ("net: dsa: felix: Add PCS operations for PHYLINK")
    Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    eb4733d7
ocelot.c 45.6 KB