From: Peter Zijlstra 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 Signed-off-by: Jiri Bohac Signed-off-by: Suresh Jayaraman --- 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 @@ -2676,7 +2676,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); + struct page *page = __netdev_alloc_page(bp->dev, gfp); if (!page) return -ENOMEM; @@ -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); - __free_page(page); + netdev_free_page(bp->dev, page); rx_pg->page = NULL; } @@ -3041,7 +3041,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, @@ -3059,9 +3059,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 @@ -604,7 +604,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; @@ -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); 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 @@ -5594,7 +5594,7 @@ static bool igb_clean_rx_irq_adv(struct PAGE_SIZE / 2, DMA_FROM_DEVICE); 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); @@ -5604,10 +5604,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 @@ -1243,10 +1244,10 @@ static bool ixgbe_clean_rx_irq(struct ix PAGE_SIZE / 2, DMA_FROM_DEVICE); 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 ((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 else rx_buffer_info->page = NULL; - skb->len += upper_len; - skb->data_len += upper_len; - skb->truesize += upper_len; } i++; --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1394,7 +1394,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; @@ -2353,8 +2353,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; @@ -2371,15 +2371,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; } } @@ -2407,7 +2403,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;