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 | |
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')
-rw-r--r-- | drivers/net/sfc/efx.c | 1 | ||||
-rw-r--r-- | drivers/net/sfc/ethtool.c | 12 | ||||
-rw-r--r-- | drivers/net/sfc/falcon.c | 4 | ||||
-rw-r--r-- | drivers/net/sfc/net_driver.h | 4 | ||||
-rw-r--r-- | drivers/net/sfc/rx.c | 23 | ||||
-rw-r--r-- | drivers/net/sfc/selftest.c | 3 | ||||
-rw-r--r-- | drivers/net/sfc/siena.c | 5 |
7 files changed, 49 insertions, 3 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index ad359110813b..d68f061a25e9 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c | |||
@@ -480,6 +480,7 @@ static void efx_init_channels(struct efx_nic *efx) | |||
480 | */ | 480 | */ |
481 | efx->rx_buffer_len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) + | 481 | efx->rx_buffer_len = (max(EFX_PAGE_IP_ALIGN, NET_IP_ALIGN) + |
482 | EFX_MAX_FRAME_LEN(efx->net_dev->mtu) + | 482 | EFX_MAX_FRAME_LEN(efx->net_dev->mtu) + |
483 | efx->type->rx_buffer_hash_size + | ||
483 | efx->type->rx_buffer_padding); | 484 | efx->type->rx_buffer_padding); |
484 | efx->rx_buffer_order = get_order(efx->rx_buffer_len + | 485 | efx->rx_buffer_order = get_order(efx->rx_buffer_len + |
485 | sizeof(struct efx_rx_page_state)); | 486 | sizeof(struct efx_rx_page_state)); |
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index dde21a890855..7693cfbf9cf4 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c | |||
@@ -546,6 +546,17 @@ static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev) | |||
546 | return efx->rx_checksum_enabled; | 546 | return efx->rx_checksum_enabled; |
547 | } | 547 | } |
548 | 548 | ||
549 | static int efx_ethtool_set_flags(struct net_device *net_dev, u32 data) | ||
550 | { | ||
551 | struct efx_nic *efx = netdev_priv(net_dev); | ||
552 | u32 supported = efx->type->offload_features & ETH_FLAG_RXHASH; | ||
553 | |||
554 | if (data & ~supported) | ||
555 | return -EOPNOTSUPP; | ||
556 | |||
557 | return ethtool_op_set_flags(net_dev, data); | ||
558 | } | ||
559 | |||
549 | static void efx_ethtool_self_test(struct net_device *net_dev, | 560 | static void efx_ethtool_self_test(struct net_device *net_dev, |
550 | struct ethtool_test *test, u64 *data) | 561 | struct ethtool_test *test, u64 *data) |
551 | { | 562 | { |
@@ -888,6 +899,7 @@ const struct ethtool_ops efx_ethtool_ops = { | |||
888 | /* Need to enable/disable TSO-IPv6 too */ | 899 | /* Need to enable/disable TSO-IPv6 too */ |
889 | .set_tso = efx_ethtool_set_tso, | 900 | .set_tso = efx_ethtool_set_tso, |
890 | .get_flags = ethtool_op_get_flags, | 901 | .get_flags = ethtool_op_get_flags, |
902 | .set_flags = efx_ethtool_set_flags, | ||
891 | .get_sset_count = efx_ethtool_get_sset_count, | 903 | .get_sset_count = efx_ethtool_get_sset_count, |
892 | .self_test = efx_ethtool_self_test, | 904 | .self_test = efx_ethtool_self_test, |
893 | .get_strings = efx_ethtool_get_strings, | 905 | .get_strings = efx_ethtool_get_strings, |
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 92d38ede6bef..5a40145f6584 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c | |||
@@ -1581,6 +1581,7 @@ static void falcon_init_rx_cfg(struct efx_nic *efx) | |||
1581 | EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_MAC_TH, data_xoff_thr); | 1581 | EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_MAC_TH, data_xoff_thr); |
1582 | EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_TX_TH, ctrl_xon_thr); | 1582 | EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_TX_TH, ctrl_xon_thr); |
1583 | EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_TX_TH, ctrl_xoff_thr); | 1583 | EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_TX_TH, ctrl_xoff_thr); |
1584 | EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_HASH_INSRT_HDR, 1); | ||
1584 | EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 1); | 1585 | EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 1); |
1585 | } | 1586 | } |
1586 | /* Always enable XOFF signal from RX FIFO. We enable | 1587 | /* Always enable XOFF signal from RX FIFO. We enable |
@@ -1861,6 +1862,7 @@ struct efx_nic_type falcon_b0_nic_type = { | |||
1861 | .evq_ptr_tbl_base = FR_BZ_EVQ_PTR_TBL, | 1862 | .evq_ptr_tbl_base = FR_BZ_EVQ_PTR_TBL, |
1862 | .evq_rptr_tbl_base = FR_BZ_EVQ_RPTR, | 1863 | .evq_rptr_tbl_base = FR_BZ_EVQ_RPTR, |
1863 | .max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH), | 1864 | .max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH), |
1865 | .rx_buffer_hash_size = 0x10, | ||
1864 | .rx_buffer_padding = 0, | 1866 | .rx_buffer_padding = 0, |
1865 | .max_interrupt_mode = EFX_INT_MODE_MSIX, | 1867 | .max_interrupt_mode = EFX_INT_MODE_MSIX, |
1866 | .phys_addr_channels = 32, /* Hardware limit is 64, but the legacy | 1868 | .phys_addr_channels = 32, /* Hardware limit is 64, but the legacy |
@@ -1868,7 +1870,7 @@ struct efx_nic_type falcon_b0_nic_type = { | |||
1868 | * channels */ | 1870 | * channels */ |
1869 | .tx_dc_base = 0x130000, | 1871 | .tx_dc_base = 0x130000, |
1870 | .rx_dc_base = 0x100000, | 1872 | .rx_dc_base = 0x100000, |
1871 | .offload_features = NETIF_F_IP_CSUM, | 1873 | .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH, |
1872 | .reset_world_flags = ETH_RESET_IRQ, | 1874 | .reset_world_flags = ETH_RESET_IRQ, |
1873 | }; | 1875 | }; |
1874 | 1876 | ||
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 9116dc977abb..bdec542e0c3d 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h | |||
@@ -847,7 +847,8 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) | |||
847 | * @evq_ptr_tbl_base: Event queue pointer table base address | 847 | * @evq_ptr_tbl_base: Event queue pointer table base address |
848 | * @evq_rptr_tbl_base: Event queue read-pointer table base address | 848 | * @evq_rptr_tbl_base: Event queue read-pointer table base address |
849 | * @max_dma_mask: Maximum possible DMA mask | 849 | * @max_dma_mask: Maximum possible DMA mask |
850 | * @rx_buffer_padding: Padding added to each RX buffer | 850 | * @rx_buffer_hash_size: Size of hash at start of RX buffer |
851 | * @rx_buffer_padding: Size of padding at end of RX buffer | ||
851 | * @max_interrupt_mode: Highest capability interrupt mode supported | 852 | * @max_interrupt_mode: Highest capability interrupt mode supported |
852 | * from &enum efx_init_mode. | 853 | * from &enum efx_init_mode. |
853 | * @phys_addr_channels: Number of channels with physically addressed | 854 | * @phys_addr_channels: Number of channels with physically addressed |
@@ -891,6 +892,7 @@ struct efx_nic_type { | |||
891 | unsigned int evq_ptr_tbl_base; | 892 | unsigned int evq_ptr_tbl_base; |
892 | unsigned int evq_rptr_tbl_base; | 893 | unsigned int evq_rptr_tbl_base; |
893 | u64 max_dma_mask; | 894 | u64 max_dma_mask; |
895 | unsigned int rx_buffer_hash_size; | ||
894 | unsigned int rx_buffer_padding; | 896 | unsigned int rx_buffer_padding; |
895 | unsigned int max_interrupt_mode; | 897 | unsigned int max_interrupt_mode; |
896 | unsigned int phys_addr_channels; | 898 | unsigned int phys_addr_channels; |
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, |
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c index 85f015f005d5..0399be21c122 100644 --- a/drivers/net/sfc/selftest.c +++ b/drivers/net/sfc/selftest.c | |||
@@ -258,6 +258,9 @@ void efx_loopback_rx_packet(struct efx_nic *efx, | |||
258 | 258 | ||
259 | payload = &state->payload; | 259 | payload = &state->payload; |
260 | 260 | ||
261 | buf_ptr += efx->type->rx_buffer_hash_size; | ||
262 | pkt_len -= efx->type->rx_buffer_hash_size; | ||
263 | |||
261 | received = (struct efx_loopback_payload *) buf_ptr; | 264 | received = (struct efx_loopback_payload *) buf_ptr; |
262 | received->ip.saddr = payload->ip.saddr; | 265 | received->ip.saddr = payload->ip.saddr; |
263 | if (state->offload_csum) | 266 | if (state->offload_csum) |
diff --git a/drivers/net/sfc/siena.c b/drivers/net/sfc/siena.c index 59d1dc6db1c6..f1741b4af1b3 100644 --- a/drivers/net/sfc/siena.c +++ b/drivers/net/sfc/siena.c | |||
@@ -331,6 +331,7 @@ static int siena_init_nic(struct efx_nic *efx) | |||
331 | 331 | ||
332 | efx_reado(efx, &temp, FR_AZ_RX_CFG); | 332 | efx_reado(efx, &temp, FR_AZ_RX_CFG); |
333 | EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_DESC_PUSH_EN, 0); | 333 | EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_DESC_PUSH_EN, 0); |
334 | EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_HASH_INSRT_HDR, 1); | ||
334 | EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_INGR_EN, 1); | 335 | EFX_SET_OWORD_FIELD(temp, FRF_BZ_RX_INGR_EN, 1); |
335 | efx_writeo(efx, &temp, FR_AZ_RX_CFG); | 336 | efx_writeo(efx, &temp, FR_AZ_RX_CFG); |
336 | 337 | ||
@@ -636,6 +637,7 @@ struct efx_nic_type siena_a0_nic_type = { | |||
636 | .evq_ptr_tbl_base = FR_BZ_EVQ_PTR_TBL, | 637 | .evq_ptr_tbl_base = FR_BZ_EVQ_PTR_TBL, |
637 | .evq_rptr_tbl_base = FR_BZ_EVQ_RPTR, | 638 | .evq_rptr_tbl_base = FR_BZ_EVQ_RPTR, |
638 | .max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH), | 639 | .max_dma_mask = DMA_BIT_MASK(FSF_AZ_TX_KER_BUF_ADDR_WIDTH), |
640 | .rx_buffer_hash_size = 0x10, | ||
639 | .rx_buffer_padding = 0, | 641 | .rx_buffer_padding = 0, |
640 | .max_interrupt_mode = EFX_INT_MODE_MSIX, | 642 | .max_interrupt_mode = EFX_INT_MODE_MSIX, |
641 | .phys_addr_channels = 32, /* Hardware limit is 64, but the legacy | 643 | .phys_addr_channels = 32, /* Hardware limit is 64, but the legacy |
@@ -643,6 +645,7 @@ struct efx_nic_type siena_a0_nic_type = { | |||
643 | * channels */ | 645 | * channels */ |
644 | .tx_dc_base = 0x88000, | 646 | .tx_dc_base = 0x88000, |
645 | .rx_dc_base = 0x68000, | 647 | .rx_dc_base = 0x68000, |
646 | .offload_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM, | 648 | .offload_features = (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | |
649 | NETIF_F_RXHASH), | ||
647 | .reset_world_flags = ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT, | 650 | .reset_world_flags = ETH_RESET_MGMT << ETH_RESET_SHARED_SHIFT, |
648 | }; | 651 | }; |