diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2009-04-16 05:02:07 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-04-16 05:02:07 -0400 |
commit | 76620aafd66f0004829764940c5466144969cffc (patch) | |
tree | 38041e6938121b5611546c582cd23f289db047b0 /drivers/net/sfc/rx.c | |
parent | 861ab44059350e5cab350238606cf8814abab93b (diff) |
gro: New frags interface to avoid copying shinfo
It turns out that copying a 16-byte area at ~800k times a second
can be really expensive :) This patch redesigns the frags GRO
interface to avoid copying that area twice.
The two disciples of the frags interface have been converted.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc/rx.c')
-rw-r--r-- | drivers/net/sfc/rx.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index 66d7fe3db3e6..01f9432c31ef 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c | |||
@@ -450,17 +450,27 @@ static void efx_rx_packet_lro(struct efx_channel *channel, | |||
450 | 450 | ||
451 | /* Pass the skb/page into the LRO engine */ | 451 | /* Pass the skb/page into the LRO engine */ |
452 | if (rx_buf->page) { | 452 | if (rx_buf->page) { |
453 | struct napi_gro_fraginfo info; | 453 | struct sk_buff *skb = napi_get_frags(napi); |
454 | 454 | ||
455 | info.frags[0].page = rx_buf->page; | 455 | if (!skb) { |
456 | info.frags[0].page_offset = efx_rx_buf_offset(rx_buf); | 456 | put_page(rx_buf->page); |
457 | info.frags[0].size = rx_buf->len; | 457 | goto out; |
458 | info.nr_frags = 1; | 458 | } |
459 | info.ip_summed = CHECKSUM_UNNECESSARY; | 459 | |
460 | info.len = rx_buf->len; | 460 | skb_shinfo(skb)->frags[0].page = rx_buf->page; |
461 | skb_shinfo(skb)->frags[0].page_offset = | ||
462 | efx_rx_buf_offset(rx_buf); | ||
463 | skb_shinfo(skb)->frags[0].size = rx_buf->len; | ||
464 | skb_shinfo(skb)->nr_frags = 1; | ||
465 | |||
466 | skb->len = rx_buf->len; | ||
467 | skb->data_len = rx_buf->len; | ||
468 | skb->truesize += rx_buf->len; | ||
469 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
461 | 470 | ||
462 | napi_gro_frags(napi, &info); | 471 | napi_gro_frags(napi); |
463 | 472 | ||
473 | out: | ||
464 | EFX_BUG_ON_PARANOID(rx_buf->skb); | 474 | EFX_BUG_ON_PARANOID(rx_buf->skb); |
465 | rx_buf->page = NULL; | 475 | rx_buf->page = NULL; |
466 | } else { | 476 | } else { |