0201bfeda3ef5d9e672dbbe7298bdba67d561523
[openwrt/staging/ldir.git] /
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