Skip to content

Commit

Permalink
ixgbe: Make pull tail function separate from rest of cleanup_headers
Browse files Browse the repository at this point in the history
This change creates a separate function for functionality similar to
pskb_pull_tail.  The main motivation for moving it to a separate function
is so that later I can just skip this function in the case where we have
already copied the buffer into skb->head.

Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Peter P Waskiewicz Jr <peter.p.waskiewicz.jr@intel.com>
  • Loading branch information
Alexander Duyck authored and Peter P Waskiewicz Jr committed Aug 16, 2012
1 parent 42073d9 commit 19861ce
Showing 1 changed file with 57 additions and 37 deletions.
94 changes: 57 additions & 37 deletions drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1457,6 +1457,61 @@ static bool ixgbe_is_non_eop(struct ixgbe_ring *rx_ring,
return true;
}

/**
* ixgbe_pull_tail - ixgbe specific version of skb_pull_tail
* @rx_ring: rx descriptor ring packet is being transacted on
* @skb: pointer to current skb being adjusted
*
* This function is an ixgbe specific version of __pskb_pull_tail. The
* main difference between this version and the original function is that
* this function can make several assumptions about the state of things
* that allow for significant optimizations versus the standard function.
* As a result we can do things like drop a frag and maintain an accurate
* truesize for the skb.
*/
static void ixgbe_pull_tail(struct ixgbe_ring *rx_ring,
struct sk_buff *skb)
{
struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
unsigned char *va;
unsigned int pull_len;

/*
* it is valid to use page_address instead of kmap since we are
* working with pages allocated out of the lomem pool per
* alloc_page(GFP_ATOMIC)
*/
va = skb_frag_address(frag);

/*
* we need the header to contain the greater of either ETH_HLEN or
* 60 bytes if the skb->len is less than 60 for skb_pad.
*/
pull_len = skb_frag_size(frag);
if (pull_len > IXGBE_RX_HDR_SIZE)
pull_len = ixgbe_get_headlen(va, IXGBE_RX_HDR_SIZE);

/* align pull length to size of long to optimize memcpy performance */
skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long)));

/* update all of the pointers */
skb_frag_size_sub(frag, pull_len);
frag->page_offset += pull_len;
skb->data_len -= pull_len;
skb->tail += pull_len;

/*
* if we sucked the frag empty then we should free it,
* if there are other frags here something is screwed up in hardware
*/
if (skb_frag_size(frag) == 0) {
BUG_ON(skb_shinfo(skb)->nr_frags != 1);
skb_shinfo(skb)->nr_frags = 0;
__skb_frag_unref(frag);
skb->truesize -= ixgbe_rx_bufsz(rx_ring);
}
}

/**
* ixgbe_dma_sync_frag - perform DMA sync for first frag of SKB
* @rx_ring: rx descriptor ring packet is being transacted on
Expand Down Expand Up @@ -1509,10 +1564,7 @@ static bool ixgbe_cleanup_headers(struct ixgbe_ring *rx_ring,
union ixgbe_adv_rx_desc *rx_desc,
struct sk_buff *skb)
{
struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[0];
struct net_device *netdev = rx_ring->netdev;
unsigned char *va;
unsigned int pull_len;

/* verify that the packet does not have any known errors */
if (unlikely(ixgbe_test_staterr(rx_desc,
Expand All @@ -1522,40 +1574,8 @@ static bool ixgbe_cleanup_headers(struct ixgbe_ring *rx_ring,
return true;
}

/*
* it is valid to use page_address instead of kmap since we are
* working with pages allocated out of the lomem pool per
* alloc_page(GFP_ATOMIC)
*/
va = skb_frag_address(frag);

/*
* we need the header to contain the greater of either ETH_HLEN or
* 60 bytes if the skb->len is less than 60 for skb_pad.
*/
pull_len = skb_frag_size(frag);
if (pull_len > IXGBE_RX_HDR_SIZE)
pull_len = ixgbe_get_headlen(va, IXGBE_RX_HDR_SIZE);

/* align pull length to size of long to optimize memcpy performance */
skb_copy_to_linear_data(skb, va, ALIGN(pull_len, sizeof(long)));

/* update all of the pointers */
skb_frag_size_sub(frag, pull_len);
frag->page_offset += pull_len;
skb->data_len -= pull_len;
skb->tail += pull_len;

/*
* if we sucked the frag empty then we should free it,
* if there are other frags here something is screwed up in hardware
*/
if (skb_frag_size(frag) == 0) {
BUG_ON(skb_shinfo(skb)->nr_frags != 1);
skb_shinfo(skb)->nr_frags = 0;
__skb_frag_unref(frag);
skb->truesize -= ixgbe_rx_bufsz(rx_ring);
}
/* place header in linear portion of buffer */
ixgbe_pull_tail(rx_ring, skb);

#ifdef IXGBE_FCOE
/* do not attempt to pad FCoE Frames as this will disrupt DDP */
Expand Down

0 comments on commit 19861ce

Please sign in to comment.