diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2010-06-23 07:31:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-06-25 01:13:24 -0400 |
commit | 39c9cf07077146b14ab077a0e27c869c6f0e6199 (patch) | |
tree | e30b746b36ebb36af8776658e8ce3f8bcd4e118d /drivers/net/sfc/rx.c | |
parent | 2822235278c6385191a590c63098e728d0062987 (diff) |
sfc: Record hardware RX hash on each skb where possible
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
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 | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index d9ed20ee0dc5..0fb98355a092 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c | |||
@@ -101,6 +101,19 @@ static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) | |||
101 | return PAGE_SIZE << efx->rx_buffer_order; | 101 | return PAGE_SIZE << efx->rx_buffer_order; |
102 | } | 102 | } |
103 | 103 | ||
104 | static inline u32 efx_rx_buf_hash(struct efx_rx_buffer *buf) | ||
105 | { | ||
106 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || NET_IP_ALIGN % 4 == 0 | ||
107 | return __le32_to_cpup((const __le32 *)buf->data); | ||
108 | #else | ||
109 | const u8 *data = (const u8 *)buf->data; | ||
110 | return ((u32)data[0] | | ||
111 | (u32)data[1] << 8 | | ||
112 | (u32)data[2] << 16 | | ||
113 | (u32)data[3] << 24); | ||
114 | #endif | ||
115 | } | ||
116 | |||
104 | /** | 117 | /** |
105 | * efx_init_rx_buffers_skb - create EFX_RX_BATCH skb-based RX buffers | 118 | * efx_init_rx_buffers_skb - create EFX_RX_BATCH skb-based RX buffers |
106 | * | 119 | * |
@@ -441,6 +454,7 @@ static void efx_rx_packet_lro(struct efx_channel *channel, | |||
441 | 454 | ||
442 | /* Pass the skb/page into the LRO engine */ | 455 | /* Pass the skb/page into the LRO engine */ |
443 | if (rx_buf->page) { | 456 | if (rx_buf->page) { |
457 | struct efx_nic *efx = channel->efx; | ||
444 | struct page *page = rx_buf->page; | 458 | struct page *page = rx_buf->page; |
445 | struct sk_buff *skb; | 459 | struct sk_buff *skb; |
446 | 460 | ||
@@ -453,6 +467,11 @@ static void efx_rx_packet_lro(struct efx_channel *channel, | |||
453 | return; | 467 | return; |
454 | } | 468 | } |
455 | 469 | ||
470 | if (efx->net_dev->features & NETIF_F_RXHASH) | ||
471 | skb->rxhash = efx_rx_buf_hash(rx_buf); | ||
472 | rx_buf->data += efx->type->rx_buffer_hash_size; | ||
473 | rx_buf->len -= efx->type->rx_buffer_hash_size; | ||
474 | |||
456 | skb_shinfo(skb)->frags[0].page = page; | 475 | skb_shinfo(skb)->frags[0].page = page; |
457 | skb_shinfo(skb)->frags[0].page_offset = | 476 | skb_shinfo(skb)->frags[0].page_offset = |
458 | efx_rx_buf_offset(rx_buf); | 477 | efx_rx_buf_offset(rx_buf); |
@@ -572,6 +591,10 @@ void __efx_rx_packet(struct efx_channel *channel, | |||
572 | 591 | ||
573 | skb_put(rx_buf->skb, rx_buf->len); | 592 | skb_put(rx_buf->skb, rx_buf->len); |
574 | 593 | ||
594 | if (efx->net_dev->features & NETIF_F_RXHASH) | ||
595 | rx_buf->skb->rxhash = efx_rx_buf_hash(rx_buf); | ||
596 | skb_pull(rx_buf->skb, efx->type->rx_buffer_hash_size); | ||
597 | |||
575 | /* Move past the ethernet header. rx_buf->data still points | 598 | /* Move past the ethernet header. rx_buf->data still points |
576 | * at the ethernet header */ | 599 | * at the ethernet header */ |
577 | rx_buf->skb->protocol = eth_type_trans(rx_buf->skb, | 600 | rx_buf->skb->protocol = eth_type_trans(rx_buf->skb, |