Commit 14b3b46a authored by Rafał Miłecki's avatar Rafał Miłecki Committed by David S. Miller

net: broadcom: bcm4908_enet: set MTU on open & on request

Hardware comes up with default max frame size set to 1518. When using it
with switch it results in actual Ethernet MTU 1492:
1518 - 14 (Ethernet header) - 4 (Broadcom's tag) - 4 (802.1q) - 4 (FCS)

Above means hardware in its default state can't handle standard Ethernet
traffic (MTU 1500).

Define maximum possible Ethernet overhead and always set MAC max frame
length accordingly. This change fixes handling Ethernet frames of length
1506 - 1514.
Signed-off-by: default avatarRafał Miłecki <rafal@milecki.pl>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ec762403
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/if_vlan.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
...@@ -29,9 +30,10 @@ ...@@ -29,9 +30,10 @@
ENET_DMA_CH_CFG_INT_BUFF_DONE) ENET_DMA_CH_CFG_INT_BUFF_DONE)
#define ENET_DMA_MAX_BURST_LEN 8 /* in 64 bit words */ #define ENET_DMA_MAX_BURST_LEN 8 /* in 64 bit words */
#define ENET_MTU_MIN 60 #define ENET_MTU_MAX ETH_DATA_LEN /* Is it possible to support 2044? */
#define ENET_MTU_MAX 1500 /* Is it possible to support 2044? */ #define BRCM_MAX_TAG_LEN 6
#define ENET_MTU_MAX_EXTRA_SIZE 32 /* L2 */ #define ENET_MAX_ETH_OVERHEAD (ETH_HLEN + BRCM_MAX_TAG_LEN + VLAN_HLEN + \
ETH_FCS_LEN + 4) /* 32 */
struct bcm4908_enet_dma_ring_bd { struct bcm4908_enet_dma_ring_bd {
__le32 ctl; __le32 ctl;
...@@ -135,6 +137,11 @@ static void bcm4908_enet_intrs_ack(struct bcm4908_enet *enet) ...@@ -135,6 +137,11 @@ static void bcm4908_enet_intrs_ack(struct bcm4908_enet *enet)
enet_write(enet, ENET_DMA_CH_RX_CFG + ENET_DMA_CH_CFG_INT_STAT, ENET_DMA_INT_DEFAULTS); enet_write(enet, ENET_DMA_CH_RX_CFG + ENET_DMA_CH_CFG_INT_STAT, ENET_DMA_INT_DEFAULTS);
} }
static void bcm4908_enet_set_mtu(struct bcm4908_enet *enet, int mtu)
{
enet_umac_write(enet, UMAC_MAX_FRAME_LEN, mtu + ENET_MAX_ETH_OVERHEAD);
}
/*** /***
* DMA * DMA
*/ */
...@@ -246,7 +253,7 @@ static int bcm4908_enet_dma_alloc_rx_buf(struct bcm4908_enet *enet, unsigned int ...@@ -246,7 +253,7 @@ static int bcm4908_enet_dma_alloc_rx_buf(struct bcm4908_enet *enet, unsigned int
u32 tmp; u32 tmp;
int err; int err;
slot->len = ENET_MTU_MAX + ENET_MTU_MAX_EXTRA_SIZE; slot->len = ENET_MTU_MAX + ENET_MAX_ETH_OVERHEAD;
slot->skb = netdev_alloc_skb(enet->netdev, slot->len); slot->skb = netdev_alloc_skb(enet->netdev, slot->len);
if (!slot->skb) if (!slot->skb)
...@@ -374,6 +381,8 @@ static void bcm4908_enet_gmac_init(struct bcm4908_enet *enet) ...@@ -374,6 +381,8 @@ static void bcm4908_enet_gmac_init(struct bcm4908_enet *enet)
{ {
u32 cmd; u32 cmd;
bcm4908_enet_set_mtu(enet, enet->netdev->mtu);
cmd = enet_umac_read(enet, UMAC_CMD); cmd = enet_umac_read(enet, UMAC_CMD);
enet_umac_write(enet, UMAC_CMD, cmd | CMD_SW_RESET); enet_umac_write(enet, UMAC_CMD, cmd | CMD_SW_RESET);
enet_umac_write(enet, UMAC_CMD, cmd & ~CMD_SW_RESET); enet_umac_write(enet, UMAC_CMD, cmd & ~CMD_SW_RESET);
...@@ -559,7 +568,7 @@ static int bcm4908_enet_poll(struct napi_struct *napi, int weight) ...@@ -559,7 +568,7 @@ static int bcm4908_enet_poll(struct napi_struct *napi, int weight)
len = (ctl & DMA_CTL_LEN_DESC_BUFLENGTH) >> DMA_CTL_LEN_DESC_BUFLENGTH_SHIFT; len = (ctl & DMA_CTL_LEN_DESC_BUFLENGTH) >> DMA_CTL_LEN_DESC_BUFLENGTH_SHIFT;
if (len < ENET_MTU_MIN || if (len < ETH_ZLEN ||
(ctl & (DMA_CTL_STATUS_SOP | DMA_CTL_STATUS_EOP)) != (DMA_CTL_STATUS_SOP | DMA_CTL_STATUS_EOP)) { (ctl & (DMA_CTL_STATUS_SOP | DMA_CTL_STATUS_EOP)) != (DMA_CTL_STATUS_SOP | DMA_CTL_STATUS_EOP)) {
enet->netdev->stats.rx_dropped++; enet->netdev->stats.rx_dropped++;
break; break;
...@@ -583,11 +592,21 @@ static int bcm4908_enet_poll(struct napi_struct *napi, int weight) ...@@ -583,11 +592,21 @@ static int bcm4908_enet_poll(struct napi_struct *napi, int weight)
return handled; return handled;
} }
static int bcm4908_enet_change_mtu(struct net_device *netdev, int new_mtu)
{
struct bcm4908_enet *enet = netdev_priv(netdev);
bcm4908_enet_set_mtu(enet, new_mtu);
return 0;
}
static const struct net_device_ops bcm4908_enet_netdev_ops = { static const struct net_device_ops bcm4908_enet_netdev_ops = {
.ndo_open = bcm4908_enet_open, .ndo_open = bcm4908_enet_open,
.ndo_stop = bcm4908_enet_stop, .ndo_stop = bcm4908_enet_stop,
.ndo_start_xmit = bcm4908_enet_start_xmit, .ndo_start_xmit = bcm4908_enet_start_xmit,
.ndo_set_mac_address = eth_mac_addr, .ndo_set_mac_address = eth_mac_addr,
.ndo_change_mtu = bcm4908_enet_change_mtu,
}; };
static int bcm4908_enet_probe(struct platform_device *pdev) static int bcm4908_enet_probe(struct platform_device *pdev)
...@@ -625,7 +644,7 @@ static int bcm4908_enet_probe(struct platform_device *pdev) ...@@ -625,7 +644,7 @@ static int bcm4908_enet_probe(struct platform_device *pdev)
eth_hw_addr_random(netdev); eth_hw_addr_random(netdev);
netdev->netdev_ops = &bcm4908_enet_netdev_ops; netdev->netdev_ops = &bcm4908_enet_netdev_ops;
netdev->min_mtu = ETH_ZLEN; netdev->min_mtu = ETH_ZLEN;
netdev->mtu = ENET_MTU_MAX; netdev->mtu = ETH_DATA_LEN;
netdev->max_mtu = ENET_MTU_MAX; netdev->max_mtu = ENET_MTU_MAX;
netif_napi_add(netdev, &enet->napi, bcm4908_enet_poll, 64); netif_napi_add(netdev, &enet->napi, bcm4908_enet_poll, 64);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment