b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | From 14b3b46a67f78ade99eafcbf320105615e948569 Mon Sep 17 00:00:00 2001 |
| 2 | From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl> |
| 3 | Date: Fri, 12 Feb 2021 16:21:35 +0100 |
| 4 | Subject: [PATCH] net: broadcom: bcm4908_enet: set MTU on open & on request |
| 5 | MIME-Version: 1.0 |
| 6 | Content-Type: text/plain; charset=UTF-8 |
| 7 | Content-Transfer-Encoding: 8bit |
| 8 | |
| 9 | Hardware comes up with default max frame size set to 1518. When using it |
| 10 | with switch it results in actual Ethernet MTU 1492: |
| 11 | 1518 - 14 (Ethernet header) - 4 (Broadcom's tag) - 4 (802.1q) - 4 (FCS) |
| 12 | |
| 13 | Above means hardware in its default state can't handle standard Ethernet |
| 14 | traffic (MTU 1500). |
| 15 | |
| 16 | Define maximum possible Ethernet overhead and always set MAC max frame |
| 17 | length accordingly. This change fixes handling Ethernet frames of length |
| 18 | 1506 - 1514. |
| 19 | |
| 20 | Signed-off-by: Rafał Miłecki <rafal@milecki.pl> |
| 21 | Signed-off-by: David S. Miller <davem@davemloft.net> |
| 22 | --- |
| 23 | drivers/net/ethernet/broadcom/bcm4908_enet.c | 31 ++++++++++++++++---- |
| 24 | 1 file changed, 25 insertions(+), 6 deletions(-) |
| 25 | |
| 26 | --- a/drivers/net/ethernet/broadcom/bcm4908_enet.c |
| 27 | +++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c |
| 28 | @@ -5,6 +5,7 @@ |
| 29 | |
| 30 | #include <linux/delay.h> |
| 31 | #include <linux/etherdevice.h> |
| 32 | +#include <linux/if_vlan.h> |
| 33 | #include <linux/interrupt.h> |
| 34 | #include <linux/module.h> |
| 35 | #include <linux/of.h> |
| 36 | @@ -29,9 +30,10 @@ |
| 37 | ENET_DMA_CH_CFG_INT_BUFF_DONE) |
| 38 | #define ENET_DMA_MAX_BURST_LEN 8 /* in 64 bit words */ |
| 39 | |
| 40 | -#define ENET_MTU_MIN 60 |
| 41 | -#define ENET_MTU_MAX 1500 /* Is it possible to support 2044? */ |
| 42 | -#define ENET_MTU_MAX_EXTRA_SIZE 32 /* L2 */ |
| 43 | +#define ENET_MTU_MAX ETH_DATA_LEN /* Is it possible to support 2044? */ |
| 44 | +#define BRCM_MAX_TAG_LEN 6 |
| 45 | +#define ENET_MAX_ETH_OVERHEAD (ETH_HLEN + BRCM_MAX_TAG_LEN + VLAN_HLEN + \ |
| 46 | + ETH_FCS_LEN + 4) /* 32 */ |
| 47 | |
| 48 | struct bcm4908_enet_dma_ring_bd { |
| 49 | __le32 ctl; |
| 50 | @@ -135,6 +137,11 @@ static void bcm4908_enet_intrs_ack(struc |
| 51 | enet_write(enet, ENET_DMA_CH_RX_CFG + ENET_DMA_CH_CFG_INT_STAT, ENET_DMA_INT_DEFAULTS); |
| 52 | } |
| 53 | |
| 54 | +static void bcm4908_enet_set_mtu(struct bcm4908_enet *enet, int mtu) |
| 55 | +{ |
| 56 | + enet_umac_write(enet, UMAC_MAX_FRAME_LEN, mtu + ENET_MAX_ETH_OVERHEAD); |
| 57 | +} |
| 58 | + |
| 59 | /*** |
| 60 | * DMA |
| 61 | */ |
| 62 | @@ -246,7 +253,7 @@ static int bcm4908_enet_dma_alloc_rx_buf |
| 63 | u32 tmp; |
| 64 | int err; |
| 65 | |
| 66 | - slot->len = ENET_MTU_MAX + ENET_MTU_MAX_EXTRA_SIZE; |
| 67 | + slot->len = ENET_MTU_MAX + ENET_MAX_ETH_OVERHEAD; |
| 68 | |
| 69 | slot->skb = netdev_alloc_skb(enet->netdev, slot->len); |
| 70 | if (!slot->skb) |
| 71 | @@ -374,6 +381,8 @@ static void bcm4908_enet_gmac_init(struc |
| 72 | { |
| 73 | u32 cmd; |
| 74 | |
| 75 | + bcm4908_enet_set_mtu(enet, enet->netdev->mtu); |
| 76 | + |
| 77 | cmd = enet_umac_read(enet, UMAC_CMD); |
| 78 | enet_umac_write(enet, UMAC_CMD, cmd | CMD_SW_RESET); |
| 79 | enet_umac_write(enet, UMAC_CMD, cmd & ~CMD_SW_RESET); |
| 80 | @@ -559,7 +568,7 @@ static int bcm4908_enet_poll(struct napi |
| 81 | |
| 82 | len = (ctl & DMA_CTL_LEN_DESC_BUFLENGTH) >> DMA_CTL_LEN_DESC_BUFLENGTH_SHIFT; |
| 83 | |
| 84 | - if (len < ENET_MTU_MIN || |
| 85 | + if (len < ETH_ZLEN || |
| 86 | (ctl & (DMA_CTL_STATUS_SOP | DMA_CTL_STATUS_EOP)) != (DMA_CTL_STATUS_SOP | DMA_CTL_STATUS_EOP)) { |
| 87 | enet->netdev->stats.rx_dropped++; |
| 88 | break; |
| 89 | @@ -583,11 +592,21 @@ static int bcm4908_enet_poll(struct napi |
| 90 | return handled; |
| 91 | } |
| 92 | |
| 93 | +static int bcm4908_enet_change_mtu(struct net_device *netdev, int new_mtu) |
| 94 | +{ |
| 95 | + struct bcm4908_enet *enet = netdev_priv(netdev); |
| 96 | + |
| 97 | + bcm4908_enet_set_mtu(enet, new_mtu); |
| 98 | + |
| 99 | + return 0; |
| 100 | +} |
| 101 | + |
| 102 | static const struct net_device_ops bcm4908_enet_netdev_ops = { |
| 103 | .ndo_open = bcm4908_enet_open, |
| 104 | .ndo_stop = bcm4908_enet_stop, |
| 105 | .ndo_start_xmit = bcm4908_enet_start_xmit, |
| 106 | .ndo_set_mac_address = eth_mac_addr, |
| 107 | + .ndo_change_mtu = bcm4908_enet_change_mtu, |
| 108 | }; |
| 109 | |
| 110 | static int bcm4908_enet_probe(struct platform_device *pdev) |
| 111 | @@ -625,7 +644,7 @@ static int bcm4908_enet_probe(struct pla |
| 112 | eth_hw_addr_random(netdev); |
| 113 | netdev->netdev_ops = &bcm4908_enet_netdev_ops; |
| 114 | netdev->min_mtu = ETH_ZLEN; |
| 115 | - netdev->mtu = ENET_MTU_MAX; |
| 116 | + netdev->mtu = ETH_DATA_LEN; |
| 117 | netdev->max_mtu = ENET_MTU_MAX; |
| 118 | netif_napi_add(netdev, &enet->napi, bcm4908_enet_poll, 64); |
| 119 | |