Skip to content

Commit c3e6b2c

Browse files
abajkdavem330
authored andcommitted
net: lantiq_xrx200: add ingress SG DMA support
This patch adds support for scatter gather DMA. DMA in PMAC splits the packet into several buffers when the MTU on the CPU port is less than the MTU of the switch. The first buffer starts at an offset of NET_IP_ALIGN. In subsequent buffers, dma ignores the offset. Thanks to this patch, the user can still connect to the device in such a situation. For normal configurations, the patch has no effect on performance. Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 7a71c8a commit c3e6b2c

File tree

1 file changed

+40
-7
lines changed

1 file changed

+40
-7
lines changed

drivers/net/ethernet/lantiq_xrx200.c

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
#define XRX200_DMA_TX 1
2828
#define XRX200_DMA_BURST_LEN 8
2929

30+
#define XRX200_DMA_PACKET_COMPLETE 0
31+
#define XRX200_DMA_PACKET_IN_PROGRESS 1
32+
3033
/* cpu port mac */
3134
#define PMAC_RX_IPG 0x0024
3235
#define PMAC_RX_IPG_MASK 0xf
@@ -62,6 +65,9 @@ struct xrx200_chan {
6265
struct ltq_dma_channel dma;
6366
struct sk_buff *skb[LTQ_DESC_NUM];
6467

68+
struct sk_buff *skb_head;
69+
struct sk_buff *skb_tail;
70+
6571
struct xrx200_priv *priv;
6672
};
6773

@@ -205,7 +211,8 @@ static int xrx200_hw_receive(struct xrx200_chan *ch)
205211
struct xrx200_priv *priv = ch->priv;
206212
struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
207213
struct sk_buff *skb = ch->skb[ch->dma.desc];
208-
int len = (desc->ctl & LTQ_DMA_SIZE_MASK);
214+
u32 ctl = desc->ctl;
215+
int len = (ctl & LTQ_DMA_SIZE_MASK);
209216
struct net_device *net_dev = priv->net_dev;
210217
int ret;
211218

@@ -221,12 +228,36 @@ static int xrx200_hw_receive(struct xrx200_chan *ch)
221228
}
222229

223230
skb_put(skb, len);
224-
skb->protocol = eth_type_trans(skb, net_dev);
225-
netif_receive_skb(skb);
226-
net_dev->stats.rx_packets++;
227-
net_dev->stats.rx_bytes += len;
228231

229-
return 0;
232+
/* add buffers to skb via skb->frag_list */
233+
if (ctl & LTQ_DMA_SOP) {
234+
ch->skb_head = skb;
235+
ch->skb_tail = skb;
236+
} else if (ch->skb_head) {
237+
if (ch->skb_head == ch->skb_tail)
238+
skb_shinfo(ch->skb_tail)->frag_list = skb;
239+
else
240+
ch->skb_tail->next = skb;
241+
ch->skb_tail = skb;
242+
skb_reserve(ch->skb_tail, -NET_IP_ALIGN);
243+
ch->skb_head->len += skb->len;
244+
ch->skb_head->data_len += skb->len;
245+
ch->skb_head->truesize += skb->truesize;
246+
}
247+
248+
if (ctl & LTQ_DMA_EOP) {
249+
ch->skb_head->protocol = eth_type_trans(ch->skb_head, net_dev);
250+
netif_receive_skb(ch->skb_head);
251+
net_dev->stats.rx_packets++;
252+
net_dev->stats.rx_bytes += ch->skb_head->len;
253+
ch->skb_head = NULL;
254+
ch->skb_tail = NULL;
255+
ret = XRX200_DMA_PACKET_COMPLETE;
256+
} else {
257+
ret = XRX200_DMA_PACKET_IN_PROGRESS;
258+
}
259+
260+
return ret;
230261
}
231262

232263
static int xrx200_poll_rx(struct napi_struct *napi, int budget)
@@ -241,7 +272,9 @@ static int xrx200_poll_rx(struct napi_struct *napi, int budget)
241272

242273
if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
243274
ret = xrx200_hw_receive(ch);
244-
if (ret)
275+
if (ret == XRX200_DMA_PACKET_IN_PROGRESS)
276+
continue;
277+
if (ret != XRX200_DMA_PACKET_COMPLETE)
245278
return ret;
246279
rx++;
247280
} else {

0 commit comments

Comments
 (0)