214 lines
6.9 KiB
Diff
214 lines
6.9 KiB
Diff
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
|
|
@@ -2656,7 +2656,7 @@ bnx2_alloc_rx_page(struct bnx2 *bp, stru
|
|
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)];
|
|
- struct page *page = alloc_page(GFP_ATOMIC);
|
|
+ struct page *page = netdev_alloc_page(bp->dev);
|
|
|
|
if (!page)
|
|
return -ENOMEM;
|
|
@@ -2686,7 +2686,7 @@ bnx2_free_rx_page(struct bnx2 *bp, struc
|
|
pci_unmap_page(bp->pdev, pci_unmap_addr(rx_pg, mapping), PAGE_SIZE,
|
|
PCI_DMA_FROMDEVICE);
|
|
|
|
- __free_page(page);
|
|
+ netdev_free_page(bp->dev, page);
|
|
rx_pg->page = NULL;
|
|
}
|
|
|
|
@@ -3019,7 +3019,7 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2
|
|
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,
|
|
@@ -3036,9 +3036,6 @@ bnx2_rx_skb(struct bnx2 *bp, struct bnx2
|
|
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
|
|
@@ -241,7 +241,7 @@ static void e1000_alloc_rx_buffers_ps(st
|
|
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;
|
|
@@ -834,11 +834,8 @@ static bool e1000_clean_rx_irq_ps(struct
|
|
pci_unmap_page(pdev, ps_page->dma, PAGE_SIZE,
|
|
PCI_DMA_FROMDEVICE);
|
|
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
|
|
@@ -5251,7 +5251,7 @@ static bool igb_clean_rx_irq_adv(struct
|
|
PAGE_SIZE / 2, PCI_DMA_FROMDEVICE);
|
|
buffer_info->page_dma = 0;
|
|
|
|
- skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags++,
|
|
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags++,
|
|
buffer_info->page,
|
|
buffer_info->page_offset,
|
|
length);
|
|
@@ -5261,10 +5261,6 @@ static bool igb_clean_rx_irq_adv(struct
|
|
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
|
|
@@ -696,6 +696,7 @@ static void ixgbe_alloc_rx_buffers(struc
|
|
int cleaned_count)
|
|
{
|
|
struct pci_dev *pdev = adapter->pdev;
|
|
+ struct net_device *netdev = adapter->netdev;
|
|
union ixgbe_adv_rx_desc *rx_desc;
|
|
struct ixgbe_rx_buffer *bi;
|
|
unsigned int i;
|
|
@@ -709,7 +710,7 @@ static void ixgbe_alloc_rx_buffers(struc
|
|
if (!bi->page_dma &&
|
|
(rx_ring->flags & IXGBE_RING_RX_PS_ENABLED)) {
|
|
if (!bi->page) {
|
|
- bi->page = alloc_page(GFP_ATOMIC);
|
|
+ bi->page = netdev_alloc_page(netdev);
|
|
if (!bi->page) {
|
|
adapter->alloc_rx_page_failed++;
|
|
goto no_buffers;
|
|
@@ -896,10 +897,10 @@ static bool ixgbe_clean_rx_irq(struct ix
|
|
pci_unmap_page(pdev, rx_buffer_info->page_dma,
|
|
PAGE_SIZE / 2, PCI_DMA_FROMDEVICE);
|
|
rx_buffer_info->page_dma = 0;
|
|
- skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags,
|
|
- rx_buffer_info->page,
|
|
- rx_buffer_info->page_offset,
|
|
- upper_len);
|
|
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
|
|
+ rx_buffer_info->page,
|
|
+ rx_buffer_info->page_offset,
|
|
+ upper_len);
|
|
|
|
if ((rx_ring->rx_buf_len > (PAGE_SIZE / 2)) ||
|
|
(page_count(rx_buffer_info->page) != 1))
|
|
@@ -907,9 +908,6 @@ static bool ixgbe_clean_rx_irq(struct ix
|
|
else
|
|
get_page(rx_buffer_info->page);
|
|
|
|
- skb->len += upper_len;
|
|
- skb->data_len += upper_len;
|
|
- skb->truesize += upper_len;
|
|
}
|
|
|
|
i++;
|
|
--- a/drivers/net/sky2.c
|
|
+++ b/drivers/net/sky2.c
|
|
@@ -1344,7 +1344,7 @@ static struct sk_buff *sky2_rx_alloc(str
|
|
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;
|
|
@@ -2304,8 +2304,8 @@ static struct sk_buff *receive_copy(stru
|
|
}
|
|
|
|
/* 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;
|
|
@@ -2322,15 +2322,11 @@ static void skb_put_frags(struct sk_buff
|
|
|
|
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;
|
|
}
|
|
}
|
|
@@ -2358,7 +2354,7 @@ static struct sk_buff *receive_new(struc
|
|
*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;
|
|
--- a/include/linux/skbuff.h
|
|
+++ b/include/linux/skbuff.h
|
|
@@ -1069,6 +1069,9 @@ static inline void skb_fill_page_desc(st
|
|
extern void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page,
|
|
int off, int size);
|
|
|
|
+extern void skb_add_rx_frag(struct sk_buff *skb, int i, struct page *page,
|
|
+ int off, int size);
|
|
+
|
|
#define SKB_PAGE_ASSERT(skb) BUG_ON(skb_shinfo(skb)->nr_frags)
|
|
#define SKB_FRAG_ASSERT(skb) BUG_ON(skb_has_frags(skb))
|
|
#define SKB_LINEAR_ASSERT(skb) BUG_ON(skb_is_nonlinear(skb))
|