The driver never sets dev->max_mtu, so the MTU is stuck at ETH_DATA_LEN. One descriptor reaches as far as the packet ready threshold, so derive the maximum from it. The threshold registers are 8 bit in units of 16 bytes and want a multiple of the 256 byte burst size. A descriptor is one page and also holds skb_shared_info behind the frame. On 4K pages the page is the tighter limit and leaves 3564 bytes. That includes room for a VLAN tag so a VLAN interface can run at the parent MTU. Resize the buffers and rewrite the registers in place. The PHY keeps running and the link stays up. A failed allocation retries at the previous size. If that fails too, take the interface down. Running on rings that were never allocated is worse. Suggested-by: Dave Stevenson Link: https://github.com/raspberrypi/linux/issues/5561 Signed-off-by: Nicolai Buchwitz Tested-by: Pierre-Marin Leclercq --- drivers/net/ethernet/broadcom/genet/bcmgenet.c | 87 +++++++++++++++++++++++++- drivers/net/ethernet/broadcom/genet/bcmgenet.h | 11 +++- 2 files changed, 92 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 75d1006a35c5..3e2ebd9a2cc5 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -79,6 +79,12 @@ ENET_THLD_MAX * ENET_THLD_UNIT, \ ENET_THLD_PAGE_LEN) +/* Largest MTU that fits one descriptor, with room for a VLAN tag so a VLAN + * interface can use the parent MTU. + */ +#define ENET_MAX_MTU (ENET_THLD_MAX_LEN - GENET_RBUF_ALIGN - \ + ETH_HLEN - VLAN_HLEN) + /* Tx/Rx DMA register offset, skip 256 descriptors */ #define WORDS_PER_BD(p) (p->hw_params->words_per_bd) #define DMA_DESC_SIZE (WORDS_PER_BD(priv) * sizeof(u32)) @@ -2667,7 +2673,7 @@ static void bcmgenet_set_mtu_regs(struct bcmgenet_priv *priv, unsigned int mtu) { u32 thld = bcmgenet_pkt_rdy_thld(mtu); - bcmgenet_umac_writel(priv, ENET_MAX_FRAME_LEN, UMAC_MAX_FRAME_LEN); + bcmgenet_umac_writel(priv, ENET_MAX_FRAME_LEN(mtu), UMAC_MAX_FRAME_LEN); /* GENET v1 maps other registers at these offsets */ if (GENET_IS_V1(priv)) @@ -2801,7 +2807,7 @@ static void bcmgenet_init_tx_ring(struct bcmgenet_priv *priv, /* Set flow period for ring != 0 */ if (index) - flow_period_val = ENET_MAX_FRAME_LEN << 16; + flow_period_val = ENET_MAX_FRAME_LEN(priv->dev->mtu) << 16; bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_PROD_INDEX); bcmgenet_tdma_ring_writel(priv, index, 0, TDMA_CONS_INDEX); @@ -3494,6 +3500,7 @@ static int bcmgenet_open(struct net_device *dev) bcmgenet_netif_start(dev, true); + priv->datapath_up = true; netif_tx_start_all_queues(dev); return 0; @@ -3552,7 +3559,11 @@ static int bcmgenet_close(struct net_device *dev) netif_dbg(priv, ifdown, dev, "bcmgenet_close\n"); - bcmgenet_netif_stop(dev, false); + /* A failed MTU change can have torn the datapath down already */ + if (priv->datapath_up) { + bcmgenet_netif_stop(dev, false); + priv->datapath_up = false; + } /* Really kill the PHY state machine and disconnect from it */ phy_disconnect(dev->phydev); @@ -3800,6 +3811,71 @@ static int bcmgenet_change_carrier(struct net_device *dev, bool new_carrier) return 0; } +static int bcmgenet_change_mtu(struct net_device *dev, int new_mtu) +{ + struct bcmgenet_priv *priv = netdev_priv(dev); + unsigned int old_mtu = dev->mtu; + int ret; + + if (!netif_running(dev)) { + WRITE_ONCE(dev->mtu, new_mtu); + priv->rx_buf_len = bcmgenet_rx_buf_len(new_mtu); + return 0; + } + + /* The watchdog trips on an idle queue once the rings are gone */ + netif_device_detach(dev); + + /* Only the buffers and the MTU registers change, leave the PHY up */ + bcmgenet_netif_stop(dev, false); + priv->datapath_up = false; + + WRITE_ONCE(dev->mtu, new_mtu); + priv->rx_buf_len = bcmgenet_rx_buf_len(new_mtu); + bcmgenet_set_mtu_regs(priv, new_mtu); + + ret = bcmgenet_init_dma(priv, true); + if (ret) { + /* Retry the size that was allocated a moment ago */ + WRITE_ONCE(dev->mtu, old_mtu); + priv->rx_buf_len = bcmgenet_rx_buf_len(old_mtu); + bcmgenet_set_mtu_regs(priv, old_mtu); + if (bcmgenet_init_dma(priv, true)) { + /* Nothing left to run on. Take the interface down so + * that close and suspend do not tear it down twice. + */ + netdev_err(dev, "failed to restore MTU %u, closing\n", + old_mtu); + netif_close(dev); + + /* Mark the device present again, __dev_open() + * refuses a detached one. The queues stay stopped + * because the interface is down by now. + */ + netif_device_attach(dev); + return ret; + } + } + + bcmgenet_hfb_restore(priv); + bcmgenet_netif_start(dev, false); + + /* bcmgenet_netif_start() only restores the link interrupt */ + if (bcmgenet_has_mdio_intr(priv)) + bcmgenet_intrl2_0_writel(priv, UMAC_IRQ_MDIO_EVENT, + INTRL2_CPU_MASK_CLEAR); + + /* A link event latched while the interrupts were off is gone. Internal + * PHYs on GENET v1-v4 are not polled, so resync the state machine. + */ + phy_mac_interrupt(dev->phydev); + + priv->datapath_up = true; + netif_device_attach(dev); + + return ret; +} + static const struct net_device_ops bcmgenet_netdev_ops = { .ndo_open = bcmgenet_open, .ndo_stop = bcmgenet_close, @@ -3811,6 +3887,7 @@ static const struct net_device_ops bcmgenet_netdev_ops = { .ndo_set_features = bcmgenet_set_features, .ndo_get_stats64 = bcmgenet_get_stats64, .ndo_change_carrier = bcmgenet_change_carrier, + .ndo_change_mtu = bcmgenet_change_mtu, }; /* GENET hardware parameters/characteristics */ @@ -4164,7 +4241,11 @@ static int bcmgenet_probe(struct platform_device *pdev) /* Mii wait queue */ init_waitqueue_head(&priv->wq); bcmgenet_hfb_init(priv); + + /* v1 cannot program the thresholds, so it stays at the default MTU */ priv->rx_buf_len = bcmgenet_rx_buf_len(dev->mtu); + if (!GENET_IS_V1(priv)) + dev->max_mtu = ENET_MAX_MTU; INIT_WORK(&priv->bcmgenet_irq_work, bcmgenet_irq_task); priv->clk_wol = devm_clk_get_optional(&priv->pdev->dev, "enet-wol"); diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index 6444bac168c3..75cfbccfd4ce 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -31,9 +31,13 @@ #define ENET_BRCM_TAG_LEN 6 #define ENET_PAD 8 -/* Longest frame the MAC must accept for the default MTU */ -#define ENET_MAX_FRAME_LEN (ETH_DATA_LEN + ETH_HLEN + VLAN_HLEN + \ - ENET_BRCM_TAG_LEN + ETH_FCS_LEN + ENET_PAD) +/* Longest frame the MAC must accept for a given MTU. ENET_PAD is slack the + * driver has always carried, it rounded the default up to 1536 from 1528. + */ +#define ENET_FRAME_OVERHEAD (ETH_HLEN + VLAN_HLEN + ENET_BRCM_TAG_LEN + \ + ETH_FCS_LEN + ENET_PAD) +#define ENET_MAX_FRAME_LEN(mtu) ((mtu) + ENET_FRAME_OVERHEAD) + #define DMA_MAX_BURST_LENGTH 0x10 /* misc. configuration */ @@ -627,6 +631,7 @@ struct bcmgenet_priv { unsigned autoneg_pause:1; unsigned tx_pause:1; unsigned rx_pause:1; + unsigned datapath_up:1; /* MDIO bus variables */ wait_queue_head_t wq; -- 2.53.0