2010-07-07 11:12:45 +00:00
|
|
|
From: Peter Zijlstra <a.p.zijlstra@chello.nl>
|
|
|
|
Subject: [PATCH 13/31] net: packet split receive api
|
|
|
|
Patch-mainline: Not yet
|
|
|
|
|
|
|
|
Add some packet-split receive hooks.
|
|
|
|
|
|
|
|
For one this allows to do NUMA node affine page allocs. Later on these hooks
|
|
|
|
will be extended to do emergency reserve allocations for fragments.
|
|
|
|
|
|
|
|
Thanks to Jiri Bohac for fixing a bug in bnx2.
|
|
|
|
|
|
|
|
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
|
|
|
|
Signed-off-by: Jiri Bohac <jbohac@suse.cz>
|
|
|
|
Signed-off-by: Suresh Jayaraman <sjayaraman@suse.de>
|
|
|
|
---
|
|
|
|
drivers/net/bnx2.c | 9 +++------
|
|
|
|
drivers/net/e1000e/netdev.c | 7 ++-----
|
|
|
|
drivers/net/igb/igb_main.c | 6 +-----
|
|
|
|
drivers/net/ixgbe/ixgbe_main.c | 14 ++++++--------
|
|
|
|
drivers/net/sky2.c | 16 ++++++----------
|
|
|
|
include/linux/skbuff.h | 3 +++
|
|
|
|
6 files changed, 21 insertions(+), 34 deletions(-)
|
|
|
|
|
|
|
|
--- a/drivers/net/bnx2.c
|
|
|
|
+++ b/drivers/net/bnx2.c
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -2676,7 +2676,7 @@ bnx2_alloc_rx_page(struct bnx2 *bp, stru
|
2010-07-07 11:12:45 +00:00
|
|
|
struct sw_pg *rx_pg = &rxr->rx_pg_ring[index];
|
|
|
|
struct rx_bd *rxbd =
|
|
|
|
&rxr->rx_pg_desc_ring[RX_RING(index)][RX_IDX(index)];
|
2011-04-19 20:09:59 +00:00
|
|
|
- struct page *page = alloc_page(gfp);
|
|
|
|
+ struct page *page = __netdev_alloc_page(bp->dev, gfp);
|
2010-07-07 11:12:45 +00:00
|
|
|
|
|
|
|
if (!page)
|
|
|
|
return -ENOMEM;
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -2706,7 +2706,7 @@ bnx2_free_rx_page(struct bnx2 *bp, struc
|
|
|
|
dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(rx_pg, mapping),
|
|
|
|
PAGE_SIZE, PCI_DMA_FROMDEVICE);
|
2010-07-07 11:12:45 +00:00
|
|
|
|
|
|
|
- __free_page(page);
|
|
|
|
+ netdev_free_page(bp->dev, page);
|
|
|
|
rx_pg->page = NULL;
|
|
|
|
}
|
|
|
|
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -3041,7 +3041,7 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2
|
2010-07-07 11:12:45 +00:00
|
|
|
if (i == pages - 1)
|
|
|
|
frag_len -= 4;
|
|
|
|
|
|
|
|
- skb_fill_page_desc(skb, i, rx_pg->page, 0, frag_len);
|
|
|
|
+ skb_add_rx_frag(skb, i, rx_pg->page, 0, frag_len);
|
|
|
|
rx_pg->page = NULL;
|
|
|
|
|
|
|
|
err = bnx2_alloc_rx_page(bp, rxr,
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -3059,9 +3059,6 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2
|
2010-07-07 11:12:45 +00:00
|
|
|
PAGE_SIZE, PCI_DMA_FROMDEVICE);
|
|
|
|
|
|
|
|
frag_size -= frag_len;
|
|
|
|
- skb->data_len += frag_len;
|
|
|
|
- skb->truesize += frag_len;
|
|
|
|
- skb->len += frag_len;
|
|
|
|
|
|
|
|
pg_prod = NEXT_RX_BD(pg_prod);
|
|
|
|
pg_cons = RX_PG_RING_IDX(NEXT_RX_BD(pg_cons));
|
|
|
|
--- a/drivers/net/e1000e/netdev.c
|
|
|
|
+++ b/drivers/net/e1000e/netdev.c
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -604,7 +604,7 @@ static void e1000_alloc_rx_buffers_ps(st
|
2010-07-07 11:12:45 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (!ps_page->page) {
|
|
|
|
- ps_page->page = alloc_page(GFP_ATOMIC);
|
|
|
|
+ ps_page->page = netdev_alloc_page(netdev);
|
|
|
|
if (!ps_page->page) {
|
|
|
|
adapter->alloc_rx_buff_failed++;
|
|
|
|
goto no_buffers;
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -1188,11 +1188,8 @@ static bool e1000_clean_rx_irq_ps(struct
|
|
|
|
dma_unmap_page(&pdev->dev, ps_page->dma, PAGE_SIZE,
|
|
|
|
DMA_FROM_DEVICE);
|
2010-07-07 11:12:45 +00:00
|
|
|
ps_page->dma = 0;
|
|
|
|
- skb_fill_page_desc(skb, j, ps_page->page, 0, length);
|
|
|
|
+ skb_add_rx_frag(skb, j, ps_page->page, 0, length);
|
|
|
|
ps_page->page = NULL;
|
|
|
|
- skb->len += length;
|
|
|
|
- skb->data_len += length;
|
|
|
|
- skb->truesize += length;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* strip the ethernet crc, problem is we're using pages now so
|
|
|
|
--- a/drivers/net/igb/igb_main.c
|
|
|
|
+++ b/drivers/net/igb/igb_main.c
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -5594,7 +5594,7 @@ static bool igb_clean_rx_irq_adv(struct
|
|
|
|
PAGE_SIZE / 2, DMA_FROM_DEVICE);
|
2010-07-07 11:12:45 +00:00
|
|
|
buffer_info->page_dma = 0;
|
|
|
|
|
2011-04-19 20:09:59 +00:00
|
|
|
- skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
|
|
|
|
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
|
2010-07-07 11:12:45 +00:00
|
|
|
buffer_info->page,
|
|
|
|
buffer_info->page_offset,
|
|
|
|
length);
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -5604,10 +5604,6 @@ static bool igb_clean_rx_irq_adv(struct
|
2010-07-07 11:12:45 +00:00
|
|
|
buffer_info->page = NULL;
|
|
|
|
else
|
|
|
|
get_page(buffer_info->page);
|
|
|
|
-
|
|
|
|
- skb->len += length;
|
|
|
|
- skb->data_len += length;
|
|
|
|
- skb->truesize += length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(staterr & E1000_RXD_STAT_EOP)) {
|
|
|
|
--- a/drivers/net/ixgbe/ixgbe_main.c
|
|
|
|
+++ b/drivers/net/ixgbe/ixgbe_main.c
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -1243,10 +1244,10 @@ static bool ixgbe_clean_rx_irq(struct ix
|
|
|
|
PAGE_SIZE / 2,
|
|
|
|
DMA_FROM_DEVICE);
|
2010-07-07 11:12:45 +00:00
|
|
|
rx_buffer_info->page_dma = 0;
|
|
|
|
- skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
|
2011-04-19 20:09:59 +00:00
|
|
|
- rx_buffer_info->page,
|
|
|
|
- rx_buffer_info->page_offset,
|
|
|
|
- upper_len);
|
2010-07-07 11:12:45 +00:00
|
|
|
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
|
|
|
|
+ rx_buffer_info->page,
|
|
|
|
+ rx_buffer_info->page_offset,
|
|
|
|
+ upper_len);
|
|
|
|
|
2011-04-19 20:09:59 +00:00
|
|
|
if ((page_count(rx_buffer_info->page) == 1) &&
|
|
|
|
(page_to_nid(rx_buffer_info->page) == current_node))
|
|
|
|
@@ -1254,9 +1255,6 @@ static bool ixgbe_clean_rx_irq(struct ix
|
2010-07-07 11:12:45 +00:00
|
|
|
else
|
2011-04-19 20:09:59 +00:00
|
|
|
rx_buffer_info->page = NULL;
|
2010-07-07 11:12:45 +00:00
|
|
|
|
|
|
|
- skb->len += upper_len;
|
|
|
|
- skb->data_len += upper_len;
|
|
|
|
- skb->truesize += upper_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
i++;
|
|
|
|
--- a/drivers/net/sky2.c
|
|
|
|
+++ b/drivers/net/sky2.c
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -1394,7 +1394,7 @@ static struct sk_buff *sky2_rx_alloc(str
|
2010-07-07 11:12:45 +00:00
|
|
|
skb_reserve(skb, NET_IP_ALIGN);
|
|
|
|
|
|
|
|
for (i = 0; i < sky2->rx_nfrags; i++) {
|
|
|
|
- struct page *page = alloc_page(GFP_ATOMIC);
|
|
|
|
+ struct page *page = netdev_alloc_page(sky2->netdev);
|
|
|
|
|
|
|
|
if (!page)
|
|
|
|
goto free_partial;
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -2353,8 +2353,8 @@ static struct sk_buff *receive_copy(stru
|
2010-07-07 11:12:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Adjust length of skb with fragments to match received data */
|
|
|
|
-static void skb_put_frags(struct sk_buff *skb, unsigned int hdr_space,
|
|
|
|
- unsigned int length)
|
|
|
|
+static void skb_put_frags(struct sky2_port *sky2, struct sk_buff *skb,
|
|
|
|
+ unsigned int hdr_space, unsigned int length)
|
|
|
|
{
|
|
|
|
int i, num_frags;
|
|
|
|
unsigned int size;
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -2371,15 +2371,11 @@ static void skb_put_frags(struct sk_buff
|
2010-07-07 11:12:45 +00:00
|
|
|
|
|
|
|
if (length == 0) {
|
|
|
|
/* don't need this page */
|
|
|
|
- __free_page(frag->page);
|
|
|
|
+ netdev_free_page(sky2->netdev, frag->page);
|
|
|
|
--skb_shinfo(skb)->nr_frags;
|
|
|
|
} else {
|
|
|
|
size = min(length, (unsigned) PAGE_SIZE);
|
|
|
|
-
|
|
|
|
- frag->size = size;
|
|
|
|
- skb->data_len += size;
|
|
|
|
- skb->truesize += size;
|
|
|
|
- skb->len += size;
|
|
|
|
+ skb_add_rx_frag(skb, i, frag->page, 0, size);
|
|
|
|
length -= size;
|
|
|
|
}
|
|
|
|
}
|
2011-04-19 20:09:59 +00:00
|
|
|
@@ -2407,7 +2403,7 @@ static struct sk_buff *receive_new(struc
|
2010-07-07 11:12:45 +00:00
|
|
|
*re = nre;
|
|
|
|
|
|
|
|
if (skb_shinfo(skb)->nr_frags)
|
|
|
|
- skb_put_frags(skb, hdr_space, length);
|
|
|
|
+ skb_put_frags(sky2, skb, hdr_space, length);
|
|
|
|
else
|
|
|
|
skb_put(skb, length);
|
|
|
|
return skb;
|