merger mtu/802.1q related fixes: bcm63xx integrated ethernet mac supports receiving and sending frames bigger than 1500 bytes, this patch adds support for changing MTU.
This patch also fixes the reception of 802.1q frames for default MTU which were reported as oversized. SVN-Revision: 16302
This commit is contained in:
parent
0efe367787
commit
d2b2ce325a
2 changed files with 76 additions and 11 deletions
|
@ -27,6 +27,7 @@
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/if_vlan.h>
|
||||||
|
|
||||||
#include <bcm63xx_dev_enet.h>
|
#include <bcm63xx_dev_enet.h>
|
||||||
#include "bcm63xx_enet.h"
|
#include "bcm63xx_enet.h"
|
||||||
|
@ -189,18 +190,18 @@ static int bcm_enet_refill_rx(struct net_device *dev)
|
||||||
desc = &priv->rx_desc_cpu[desc_idx];
|
desc = &priv->rx_desc_cpu[desc_idx];
|
||||||
|
|
||||||
if (!priv->rx_skb[desc_idx]) {
|
if (!priv->rx_skb[desc_idx]) {
|
||||||
skb = netdev_alloc_skb(dev, BCMENET_MAX_RX_SIZE);
|
skb = netdev_alloc_skb(dev, priv->rx_skb_size);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
break;
|
break;
|
||||||
priv->rx_skb[desc_idx] = skb;
|
priv->rx_skb[desc_idx] = skb;
|
||||||
|
|
||||||
p = dma_map_single(&priv->pdev->dev, skb->data,
|
p = dma_map_single(&priv->pdev->dev, skb->data,
|
||||||
BCMENET_MAX_RX_SIZE,
|
priv->rx_skb_size,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
desc->address = p;
|
desc->address = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
len_stat = BCMENET_MAX_RX_SIZE << DMADESC_LENGTH_SHIFT;
|
len_stat = priv->rx_skb_size << DMADESC_LENGTH_SHIFT;
|
||||||
len_stat |= DMADESC_OWNER_MASK;
|
len_stat |= DMADESC_OWNER_MASK;
|
||||||
if (priv->rx_dirty_desc == priv->rx_ring_size - 1) {
|
if (priv->rx_dirty_desc == priv->rx_ring_size - 1) {
|
||||||
len_stat |= DMADESC_WRAP_MASK;
|
len_stat |= DMADESC_WRAP_MASK;
|
||||||
|
@ -337,7 +338,7 @@ static int bcm_enet_receive_queue(struct net_device *dev, int budget)
|
||||||
skb = nskb;
|
skb = nskb;
|
||||||
} else {
|
} else {
|
||||||
dma_unmap_single(&priv->pdev->dev, desc->address,
|
dma_unmap_single(&priv->pdev->dev, desc->address,
|
||||||
BCMENET_MAX_RX_SIZE, DMA_FROM_DEVICE);
|
priv->rx_skb_size, DMA_FROM_DEVICE);
|
||||||
priv->rx_skb[desc_idx] = NULL;
|
priv->rx_skb[desc_idx] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -949,8 +950,8 @@ static int bcm_enet_open(struct net_device *dev)
|
||||||
enet_dma_writel(priv, 0, ENETDMA_SRAM4_REG(priv->tx_chan));
|
enet_dma_writel(priv, 0, ENETDMA_SRAM4_REG(priv->tx_chan));
|
||||||
|
|
||||||
/* set max rx/tx length */
|
/* set max rx/tx length */
|
||||||
enet_writel(priv, BCMENET_MAX_RX_SIZE, ENET_RXMAXLEN_REG);
|
enet_writel(priv, priv->hw_mtu, ENET_RXMAXLEN_REG);
|
||||||
enet_writel(priv, BCMENET_MAX_TX_SIZE, ENET_TXMAXLEN_REG);
|
enet_writel(priv, priv->hw_mtu, ENET_TXMAXLEN_REG);
|
||||||
|
|
||||||
/* set dma maximum burst len */
|
/* set dma maximum burst len */
|
||||||
enet_dma_writel(priv, BCMENET_DMA_MAXBURST,
|
enet_dma_writel(priv, BCMENET_DMA_MAXBURST,
|
||||||
|
@ -1016,7 +1017,7 @@ out:
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
desc = &priv->rx_desc_cpu[i];
|
desc = &priv->rx_desc_cpu[i];
|
||||||
dma_unmap_single(kdev, desc->address, BCMENET_MAX_RX_SIZE,
|
dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
kfree_skb(priv->rx_skb[i]);
|
kfree_skb(priv->rx_skb[i]);
|
||||||
}
|
}
|
||||||
|
@ -1116,7 +1117,7 @@ static int bcm_enet_stop(struct net_device *dev)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
desc = &priv->rx_desc_cpu[i];
|
desc = &priv->rx_desc_cpu[i];
|
||||||
dma_unmap_single(kdev, desc->address, BCMENET_MAX_RX_SIZE,
|
dma_unmap_single(kdev, desc->address, priv->rx_skb_size,
|
||||||
DMA_FROM_DEVICE);
|
DMA_FROM_DEVICE);
|
||||||
kfree_skb(priv->rx_skb[i]);
|
kfree_skb(priv->rx_skb[i]);
|
||||||
}
|
}
|
||||||
|
@ -1505,6 +1506,55 @@ static int bcm_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* calculate actual hardware mtu
|
||||||
|
*/
|
||||||
|
static int compute_hw_mtu(struct bcm_enet_priv *priv, int mtu)
|
||||||
|
{
|
||||||
|
int actual_mtu;
|
||||||
|
|
||||||
|
actual_mtu = mtu;
|
||||||
|
|
||||||
|
/* add ethernet header + vlan tag size */
|
||||||
|
actual_mtu += VLAN_ETH_HLEN;
|
||||||
|
|
||||||
|
if (actual_mtu < 64 || actual_mtu > BCMENET_MAX_MTU)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* setup maximum size before we get overflow mark in
|
||||||
|
* descriptor, note that this will not prevent reception of
|
||||||
|
* big frames, they will be split into multiple buffers
|
||||||
|
* anyway
|
||||||
|
*/
|
||||||
|
priv->hw_mtu = actual_mtu;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* align rx buffer size to dma burst len, account FCS since
|
||||||
|
* it's appended
|
||||||
|
*/
|
||||||
|
priv->rx_skb_size = ALIGN(actual_mtu + ETH_FCS_LEN,
|
||||||
|
BCMENET_DMA_MAXBURST * 4);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* adjust mtu, can't be called while device is running
|
||||||
|
*/
|
||||||
|
static int bcm_enet_change_mtu(struct net_device *dev, int new_mtu)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (netif_running(dev))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
ret = compute_hw_mtu(netdev_priv(dev), new_mtu);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
dev->mtu = new_mtu;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* preinit hardware to allow mii operation while device is down
|
* preinit hardware to allow mii operation while device is down
|
||||||
*/
|
*/
|
||||||
|
@ -1582,6 +1632,10 @@ static int __devinit bcm_enet_probe(struct platform_device *pdev)
|
||||||
priv = netdev_priv(dev);
|
priv = netdev_priv(dev);
|
||||||
memset(priv, 0, sizeof(*priv));
|
memset(priv, 0, sizeof(*priv));
|
||||||
|
|
||||||
|
ret = compute_hw_mtu(priv, dev->mtu);
|
||||||
|
if (ret)
|
||||||
|
goto out;
|
||||||
|
|
||||||
iomem_size = res_mem->end - res_mem->start + 1;
|
iomem_size = res_mem->end - res_mem->start + 1;
|
||||||
if (!request_mem_region(res_mem->start, iomem_size, "bcm63xx_enet")) {
|
if (!request_mem_region(res_mem->start, iomem_size, "bcm63xx_enet")) {
|
||||||
ret = -EBUSY;
|
ret = -EBUSY;
|
||||||
|
@ -1721,6 +1775,7 @@ static int __devinit bcm_enet_probe(struct platform_device *pdev)
|
||||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||||
dev->poll_controller = bcm_enet_netpoll;
|
dev->poll_controller = bcm_enet_netpoll;
|
||||||
#endif
|
#endif
|
||||||
|
dev->change_mtu = bcm_enet_change_mtu;
|
||||||
|
|
||||||
SET_ETHTOOL_OPS(dev, &bcm_enet_ethtool_ops);
|
SET_ETHTOOL_OPS(dev, &bcm_enet_ethtool_ops);
|
||||||
|
|
||||||
|
@ -1754,6 +1809,7 @@ err:
|
||||||
enet_writel(priv, 0, ENET_MIISC_REG);
|
enet_writel(priv, 0, ENET_MIISC_REG);
|
||||||
iounmap(priv->base);
|
iounmap(priv->base);
|
||||||
}
|
}
|
||||||
|
out:
|
||||||
free_netdev(dev);
|
free_netdev(dev);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,12 @@
|
||||||
* not overflow the fifo */
|
* not overflow the fifo */
|
||||||
#define BCMENET_TX_FIFO_TRESH 32
|
#define BCMENET_TX_FIFO_TRESH 32
|
||||||
|
|
||||||
/* maximum rx/tx packet size */
|
/*
|
||||||
#define BCMENET_MAX_RX_SIZE (ETH_FRAME_LEN + 4)
|
* hardware maximum rx/tx packet size including FCS, max mtu is
|
||||||
#define BCMENET_MAX_TX_SIZE (ETH_FRAME_LEN + 4)
|
* actually 2047, but if we set max rx size register to 2047 we won't
|
||||||
|
* get overflow information if packet size is 2048 or above
|
||||||
|
*/
|
||||||
|
#define BCMENET_MAX_MTU 2046
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* rx/tx dma descriptor
|
* rx/tx dma descriptor
|
||||||
|
@ -202,6 +205,9 @@ struct bcm_enet_priv {
|
||||||
/* next dirty rx descriptor to refill */
|
/* next dirty rx descriptor to refill */
|
||||||
int rx_dirty_desc;
|
int rx_dirty_desc;
|
||||||
|
|
||||||
|
/* size of allocated rx skbs */
|
||||||
|
unsigned int rx_skb_size;
|
||||||
|
|
||||||
/* list of skb given to hw for rx */
|
/* list of skb given to hw for rx */
|
||||||
struct sk_buff **rx_skb;
|
struct sk_buff **rx_skb;
|
||||||
|
|
||||||
|
@ -289,6 +295,9 @@ struct bcm_enet_priv {
|
||||||
|
|
||||||
/* platform device reference */
|
/* platform device reference */
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
|
|
||||||
|
/* maximum hardware transmit/receive size */
|
||||||
|
unsigned int hw_mtu;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* ! BCM63XX_ENET_H_ */
|
#endif /* ! BCM63XX_ENET_H_ */
|
||||||
|
|
Loading…
Reference in a new issue