Skip to content

Commit 1488fc2

Browse files
abajkkuba-moo
authored andcommitted
net: lantiq_xrx200: increase buffer reservation
If the user sets a lower mtu on the CPU port than on the switch, then DMA inserts a few more bytes into the buffer than expected. In the worst case, it may exceed the size of the buffer. The experiments showed that the buffer should be a multiple of the burst length value. This patch rounds the length of the rx buffer upwards and fixes this bug. The reservation of FCS space in the buffer has been removed as PMAC strips the FCS. Fixes: 998ac35 ("net: lantiq: add support for jumbo frames") Reported-by: Thomas Nixon <tom@tomn.co.uk> Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 14193d5 commit 1488fc2

1 file changed

Lines changed: 24 additions & 10 deletions

File tree

drivers/net/ethernet/lantiq_xrx200.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ struct xrx200_priv {
7171
struct xrx200_chan chan_tx;
7272
struct xrx200_chan chan_rx;
7373

74+
u16 rx_buf_size;
75+
7476
struct net_device *net_dev;
7577
struct device *dev;
7678

@@ -97,6 +99,16 @@ static void xrx200_pmac_mask(struct xrx200_priv *priv, u32 clear, u32 set,
9799
xrx200_pmac_w32(priv, val, offset);
98100
}
99101

102+
static int xrx200_max_frame_len(int mtu)
103+
{
104+
return VLAN_ETH_HLEN + mtu;
105+
}
106+
107+
static int xrx200_buffer_size(int mtu)
108+
{
109+
return round_up(xrx200_max_frame_len(mtu), 4 * XRX200_DMA_BURST_LEN);
110+
}
111+
100112
/* drop all the packets from the DMA ring */
101113
static void xrx200_flush_dma(struct xrx200_chan *ch)
102114
{
@@ -109,8 +121,7 @@ static void xrx200_flush_dma(struct xrx200_chan *ch)
109121
break;
110122

111123
desc->ctl = LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
112-
(ch->priv->net_dev->mtu + VLAN_ETH_HLEN +
113-
ETH_FCS_LEN);
124+
ch->priv->rx_buf_size;
114125
ch->dma.desc++;
115126
ch->dma.desc %= LTQ_DESC_NUM;
116127
}
@@ -158,21 +169,21 @@ static int xrx200_close(struct net_device *net_dev)
158169

159170
static int xrx200_alloc_skb(struct xrx200_chan *ch)
160171
{
161-
int len = ch->priv->net_dev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
162172
struct sk_buff *skb = ch->skb[ch->dma.desc];
173+
struct xrx200_priv *priv = ch->priv;
163174
dma_addr_t mapping;
164175
int ret = 0;
165176

166-
ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(ch->priv->net_dev,
167-
len);
177+
ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(priv->net_dev,
178+
priv->rx_buf_size);
168179
if (!ch->skb[ch->dma.desc]) {
169180
ret = -ENOMEM;
170181
goto skip;
171182
}
172183

173-
mapping = dma_map_single(ch->priv->dev, ch->skb[ch->dma.desc]->data,
174-
len, DMA_FROM_DEVICE);
175-
if (unlikely(dma_mapping_error(ch->priv->dev, mapping))) {
184+
mapping = dma_map_single(priv->dev, ch->skb[ch->dma.desc]->data,
185+
priv->rx_buf_size, DMA_FROM_DEVICE);
186+
if (unlikely(dma_mapping_error(priv->dev, mapping))) {
176187
dev_kfree_skb_any(ch->skb[ch->dma.desc]);
177188
ch->skb[ch->dma.desc] = skb;
178189
ret = -ENOMEM;
@@ -184,7 +195,7 @@ static int xrx200_alloc_skb(struct xrx200_chan *ch)
184195
wmb();
185196
skip:
186197
ch->dma.desc_base[ch->dma.desc].ctl =
187-
LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | len;
198+
LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | priv->rx_buf_size;
188199

189200
return ret;
190201
}
@@ -356,6 +367,7 @@ xrx200_change_mtu(struct net_device *net_dev, int new_mtu)
356367
int ret = 0;
357368

358369
net_dev->mtu = new_mtu;
370+
priv->rx_buf_size = xrx200_buffer_size(new_mtu);
359371

360372
if (new_mtu <= old_mtu)
361373
return ret;
@@ -375,6 +387,7 @@ xrx200_change_mtu(struct net_device *net_dev, int new_mtu)
375387
ret = xrx200_alloc_skb(ch_rx);
376388
if (ret) {
377389
net_dev->mtu = old_mtu;
390+
priv->rx_buf_size = xrx200_buffer_size(old_mtu);
378391
break;
379392
}
380393
dev_kfree_skb_any(skb);
@@ -505,7 +518,8 @@ static int xrx200_probe(struct platform_device *pdev)
505518
net_dev->netdev_ops = &xrx200_netdev_ops;
506519
SET_NETDEV_DEV(net_dev, dev);
507520
net_dev->min_mtu = ETH_ZLEN;
508-
net_dev->max_mtu = XRX200_DMA_DATA_LEN - VLAN_ETH_HLEN - ETH_FCS_LEN;
521+
net_dev->max_mtu = XRX200_DMA_DATA_LEN - xrx200_max_frame_len(0);
522+
priv->rx_buf_size = xrx200_buffer_size(ETH_DATA_LEN);
509523

510524
/* load the memory ranges */
511525
priv->pmac_reg = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);

0 commit comments

Comments
 (0)