diff options
author | Jon Mason <jon.mason@exar.com> | 2010-11-10 23:25:53 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-11-11 12:30:18 -0500 |
commit | 47f01db44b2470d9517848f6b73c75883ef5fda0 (patch) | |
tree | 1d2e1c89a787c83ce6eabc98730ac994ab00aa1f /drivers/net/vxge | |
parent | 0c6202b3278b417444a59cecc59e6e5af04db7fd (diff) |
vxge: enable rxhash
Enable RSS hashing and add ability to pass up the adapter calculated rx
hash up the network stack (if feature is available). Add the ability to
enable/disable feature via ethtool, which requires that the adapter is
not running at the time. Other miscellaneous cleanups and fixes
required to get RSS working.
Signed-off-by: Jon Mason <jon.mason@exar.com>
Signed-off-by: Ram Vepa <ram.vepa@exar.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/vxge')
-rw-r--r-- | drivers/net/vxge/vxge-config.c | 2 | ||||
-rw-r--r-- | drivers/net/vxge/vxge-config.h | 12 | ||||
-rw-r--r-- | drivers/net/vxge/vxge-ethtool.c | 35 | ||||
-rw-r--r-- | drivers/net/vxge/vxge-main.c | 54 | ||||
-rw-r--r-- | drivers/net/vxge/vxge-main.h | 18 | ||||
-rw-r--r-- | drivers/net/vxge/vxge-traffic.h | 28 |
6 files changed, 86 insertions, 63 deletions
diff --git a/drivers/net/vxge/vxge-config.c b/drivers/net/vxge/vxge-config.c index 906a3ca3676b..0a35ab1ee2e1 100644 --- a/drivers/net/vxge/vxge-config.c +++ b/drivers/net/vxge/vxge-config.c | |||
@@ -3204,6 +3204,8 @@ enum vxge_hw_status vxge_hw_vpath_rts_rth_set( | |||
3204 | VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY, | 3204 | VXGE_HW_RTS_ACCESS_STEER_CTRL_ACTION_READ_ENTRY, |
3205 | VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_GEN_CFG, | 3205 | VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_RTH_GEN_CFG, |
3206 | 0, &data0, &data1); | 3206 | 0, &data0, &data1); |
3207 | if (status != VXGE_HW_OK) | ||
3208 | goto exit; | ||
3207 | 3209 | ||
3208 | data0 &= ~(VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_BUCKET_SIZE(0xf) | | 3210 | data0 &= ~(VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_BUCKET_SIZE(0xf) | |
3209 | VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ALG_SEL(0x3)); | 3211 | VXGE_HW_RTS_ACCESS_STEER_DATA0_RTH_GEN_ALG_SEL(0x3)); |
diff --git a/drivers/net/vxge/vxge-config.h b/drivers/net/vxge/vxge-config.h index 5c00861b6c2c..5d7790558f44 100644 --- a/drivers/net/vxge/vxge-config.h +++ b/drivers/net/vxge/vxge-config.h | |||
@@ -1413,12 +1413,12 @@ enum vxge_hw_rth_algoritms { | |||
1413 | * See also: vxge_hw_vpath_rts_rth_set(), vxge_hw_vpath_rts_rth_get(). | 1413 | * See also: vxge_hw_vpath_rts_rth_set(), vxge_hw_vpath_rts_rth_get(). |
1414 | */ | 1414 | */ |
1415 | struct vxge_hw_rth_hash_types { | 1415 | struct vxge_hw_rth_hash_types { |
1416 | u8 hash_type_tcpipv4_en; | 1416 | u8 hash_type_tcpipv4_en:1, |
1417 | u8 hash_type_ipv4_en; | 1417 | hash_type_ipv4_en:1, |
1418 | u8 hash_type_tcpipv6_en; | 1418 | hash_type_tcpipv6_en:1, |
1419 | u8 hash_type_ipv6_en; | 1419 | hash_type_ipv6_en:1, |
1420 | u8 hash_type_tcpipv6ex_en; | 1420 | hash_type_tcpipv6ex_en:1, |
1421 | u8 hash_type_ipv6ex_en; | 1421 | hash_type_ipv6ex_en:1; |
1422 | }; | 1422 | }; |
1423 | 1423 | ||
1424 | void vxge_hw_device_debug_set( | 1424 | void vxge_hw_device_debug_set( |
diff --git a/drivers/net/vxge/vxge-ethtool.c b/drivers/net/vxge/vxge-ethtool.c index b67746eef923..f8fd8da4f173 100644 --- a/drivers/net/vxge/vxge-ethtool.c +++ b/drivers/net/vxge/vxge-ethtool.c | |||
@@ -1119,6 +1119,40 @@ static int vxge_ethtool_get_sset_count(struct net_device *dev, int sset) | |||
1119 | } | 1119 | } |
1120 | } | 1120 | } |
1121 | 1121 | ||
1122 | static int vxge_set_flags(struct net_device *dev, u32 data) | ||
1123 | { | ||
1124 | struct vxgedev *vdev = (struct vxgedev *)netdev_priv(dev); | ||
1125 | enum vxge_hw_status status; | ||
1126 | |||
1127 | if (data & ~ETH_FLAG_RXHASH) | ||
1128 | return -EOPNOTSUPP; | ||
1129 | |||
1130 | if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en) | ||
1131 | return 0; | ||
1132 | |||
1133 | if (netif_running(dev) || (vdev->config.rth_steering == NO_STEERING)) | ||
1134 | return -EINVAL; | ||
1135 | |||
1136 | vdev->devh->config.rth_en = !!(data & ETH_FLAG_RXHASH); | ||
1137 | |||
1138 | /* Enabling RTH requires some of the logic in vxge_device_register and a | ||
1139 | * vpath reset. Due to these restrictions, only allow modification | ||
1140 | * while the interface is down. | ||
1141 | */ | ||
1142 | status = vxge_reset_all_vpaths(vdev); | ||
1143 | if (status != VXGE_HW_OK) { | ||
1144 | vdev->devh->config.rth_en = !vdev->devh->config.rth_en; | ||
1145 | return -EFAULT; | ||
1146 | } | ||
1147 | |||
1148 | if (vdev->devh->config.rth_en) | ||
1149 | dev->features |= NETIF_F_RXHASH; | ||
1150 | else | ||
1151 | dev->features &= ~NETIF_F_RXHASH; | ||
1152 | |||
1153 | return 0; | ||
1154 | } | ||
1155 | |||
1122 | static const struct ethtool_ops vxge_ethtool_ops = { | 1156 | static const struct ethtool_ops vxge_ethtool_ops = { |
1123 | .get_settings = vxge_ethtool_gset, | 1157 | .get_settings = vxge_ethtool_gset, |
1124 | .set_settings = vxge_ethtool_sset, | 1158 | .set_settings = vxge_ethtool_sset, |
@@ -1140,6 +1174,7 @@ static const struct ethtool_ops vxge_ethtool_ops = { | |||
1140 | .phys_id = vxge_ethtool_idnic, | 1174 | .phys_id = vxge_ethtool_idnic, |
1141 | .get_sset_count = vxge_ethtool_get_sset_count, | 1175 | .get_sset_count = vxge_ethtool_get_sset_count, |
1142 | .get_ethtool_stats = vxge_get_ethtool_stats, | 1176 | .get_ethtool_stats = vxge_get_ethtool_stats, |
1177 | .set_flags = vxge_set_flags, | ||
1143 | }; | 1178 | }; |
1144 | 1179 | ||
1145 | void vxge_initialize_ethtool_ops(struct net_device *ndev) | 1180 | void vxge_initialize_ethtool_ops(struct net_device *ndev) |
diff --git a/drivers/net/vxge/vxge-main.c b/drivers/net/vxge/vxge-main.c index 813829f3d024..2f26c377e5d9 100644 --- a/drivers/net/vxge/vxge-main.c +++ b/drivers/net/vxge/vxge-main.c | |||
@@ -513,6 +513,13 @@ vxge_rx_1b_compl(struct __vxge_hw_ring *ringh, void *dtr, | |||
513 | else | 513 | else |
514 | skb_checksum_none_assert(skb); | 514 | skb_checksum_none_assert(skb); |
515 | 515 | ||
516 | /* rth_hash_type and rth_it_hit are non-zero regardless of | ||
517 | * whether rss is enabled. Only the rth_value is zero/non-zero | ||
518 | * if rss is disabled/enabled, so key off of that. | ||
519 | */ | ||
520 | if (ext_info.rth_value) | ||
521 | skb->rxhash = ext_info.rth_value; | ||
522 | |||
516 | vxge_rx_complete(ring, skb, ext_info.vlan, | 523 | vxge_rx_complete(ring, skb, ext_info.vlan, |
517 | pkt_length, &ext_info); | 524 | pkt_length, &ext_info); |
518 | 525 | ||
@@ -1689,15 +1696,6 @@ static enum vxge_hw_status vxge_rth_configure(struct vxgedev *vdev) | |||
1689 | mtable[index] = index % vdev->no_of_vpath; | 1696 | mtable[index] = index % vdev->no_of_vpath; |
1690 | } | 1697 | } |
1691 | 1698 | ||
1692 | /* Fill RTH hash types */ | ||
1693 | hash_types.hash_type_tcpipv4_en = vdev->config.rth_hash_type_tcpipv4; | ||
1694 | hash_types.hash_type_ipv4_en = vdev->config.rth_hash_type_ipv4; | ||
1695 | hash_types.hash_type_tcpipv6_en = vdev->config.rth_hash_type_tcpipv6; | ||
1696 | hash_types.hash_type_ipv6_en = vdev->config.rth_hash_type_ipv6; | ||
1697 | hash_types.hash_type_tcpipv6ex_en = | ||
1698 | vdev->config.rth_hash_type_tcpipv6ex; | ||
1699 | hash_types.hash_type_ipv6ex_en = vdev->config.rth_hash_type_ipv6ex; | ||
1700 | |||
1701 | /* set indirection table, bucket-to-vpath mapping */ | 1699 | /* set indirection table, bucket-to-vpath mapping */ |
1702 | status = vxge_hw_vpath_rts_rth_itable_set(vdev->vp_handles, | 1700 | status = vxge_hw_vpath_rts_rth_itable_set(vdev->vp_handles, |
1703 | vdev->no_of_vpath, | 1701 | vdev->no_of_vpath, |
@@ -1710,12 +1708,21 @@ static enum vxge_hw_status vxge_rth_configure(struct vxgedev *vdev) | |||
1710 | return status; | 1708 | return status; |
1711 | } | 1709 | } |
1712 | 1710 | ||
1711 | /* Fill RTH hash types */ | ||
1712 | hash_types.hash_type_tcpipv4_en = vdev->config.rth_hash_type_tcpipv4; | ||
1713 | hash_types.hash_type_ipv4_en = vdev->config.rth_hash_type_ipv4; | ||
1714 | hash_types.hash_type_tcpipv6_en = vdev->config.rth_hash_type_tcpipv6; | ||
1715 | hash_types.hash_type_ipv6_en = vdev->config.rth_hash_type_ipv6; | ||
1716 | hash_types.hash_type_tcpipv6ex_en = | ||
1717 | vdev->config.rth_hash_type_tcpipv6ex; | ||
1718 | hash_types.hash_type_ipv6ex_en = vdev->config.rth_hash_type_ipv6ex; | ||
1719 | |||
1713 | /* | 1720 | /* |
1714 | * Because the itable_set() method uses the active_table field | 1721 | * Because the itable_set() method uses the active_table field |
1715 | * for the target virtual path the RTH config should be updated | 1722 | * for the target virtual path the RTH config should be updated |
1716 | * for all VPATHs. The h/w only uses the lowest numbered VPATH | 1723 | * for all VPATHs. The h/w only uses the lowest numbered VPATH |
1717 | * when steering frames. | 1724 | * when steering frames. |
1718 | */ | 1725 | */ |
1719 | for (index = 0; index < vdev->no_of_vpath; index++) { | 1726 | for (index = 0; index < vdev->no_of_vpath; index++) { |
1720 | status = vxge_hw_vpath_rts_rth_set( | 1727 | status = vxge_hw_vpath_rts_rth_set( |
1721 | vdev->vpaths[index].handle, | 1728 | vdev->vpaths[index].handle, |
@@ -2598,6 +2605,8 @@ vxge_open(struct net_device *dev) | |||
2598 | goto out2; | 2605 | goto out2; |
2599 | } | 2606 | } |
2600 | } | 2607 | } |
2608 | printk(KERN_INFO "%s: Receive Hashing Offload %s\n", dev->name, | ||
2609 | hldev->config.rth_en ? "enabled" : "disabled"); | ||
2601 | 2610 | ||
2602 | for (i = 0; i < vdev->no_of_vpath; i++) { | 2611 | for (i = 0; i < vdev->no_of_vpath; i++) { |
2603 | vpath = &vdev->vpaths[i]; | 2612 | vpath = &vdev->vpaths[i]; |
@@ -3178,6 +3187,11 @@ static int __devinit vxge_device_register(struct __vxge_hw_device *hldev, | |||
3178 | 3187 | ||
3179 | vxge_initialize_ethtool_ops(ndev); | 3188 | vxge_initialize_ethtool_ops(ndev); |
3180 | 3189 | ||
3190 | if (vdev->config.rth_steering != NO_STEERING) { | ||
3191 | ndev->features |= NETIF_F_RXHASH; | ||
3192 | hldev->config.rth_en = VXGE_HW_RTH_ENABLE; | ||
3193 | } | ||
3194 | |||
3181 | /* Allocate memory for vpath */ | 3195 | /* Allocate memory for vpath */ |
3182 | vdev->vpaths = kzalloc((sizeof(struct vxge_vpath)) * | 3196 | vdev->vpaths = kzalloc((sizeof(struct vxge_vpath)) * |
3183 | no_of_vpath, GFP_KERNEL); | 3197 | no_of_vpath, GFP_KERNEL); |
@@ -4163,12 +4177,12 @@ vxge_probe(struct pci_dev *pdev, const struct pci_device_id *pre) | |||
4163 | ll_config->fifo_indicate_max_pkts = VXGE_FIFO_INDICATE_MAX_PKTS; | 4177 | ll_config->fifo_indicate_max_pkts = VXGE_FIFO_INDICATE_MAX_PKTS; |
4164 | ll_config->addr_learn_en = addr_learn_en; | 4178 | ll_config->addr_learn_en = addr_learn_en; |
4165 | ll_config->rth_algorithm = RTH_ALG_JENKINS; | 4179 | ll_config->rth_algorithm = RTH_ALG_JENKINS; |
4166 | ll_config->rth_hash_type_tcpipv4 = VXGE_HW_RING_HASH_TYPE_TCP_IPV4; | 4180 | ll_config->rth_hash_type_tcpipv4 = 1; |
4167 | ll_config->rth_hash_type_ipv4 = VXGE_HW_RING_HASH_TYPE_NONE; | 4181 | ll_config->rth_hash_type_ipv4 = 0; |
4168 | ll_config->rth_hash_type_tcpipv6 = VXGE_HW_RING_HASH_TYPE_NONE; | 4182 | ll_config->rth_hash_type_tcpipv6 = 0; |
4169 | ll_config->rth_hash_type_ipv6 = VXGE_HW_RING_HASH_TYPE_NONE; | 4183 | ll_config->rth_hash_type_ipv6 = 0; |
4170 | ll_config->rth_hash_type_tcpipv6ex = VXGE_HW_RING_HASH_TYPE_NONE; | 4184 | ll_config->rth_hash_type_tcpipv6ex = 0; |
4171 | ll_config->rth_hash_type_ipv6ex = VXGE_HW_RING_HASH_TYPE_NONE; | 4185 | ll_config->rth_hash_type_ipv6ex = 0; |
4172 | ll_config->rth_bkt_sz = RTH_BUCKET_SIZE; | 4186 | ll_config->rth_bkt_sz = RTH_BUCKET_SIZE; |
4173 | ll_config->tx_pause_enable = VXGE_PAUSE_CTRL_ENABLE; | 4187 | ll_config->tx_pause_enable = VXGE_PAUSE_CTRL_ENABLE; |
4174 | ll_config->rx_pause_enable = VXGE_PAUSE_CTRL_ENABLE; | 4188 | ll_config->rx_pause_enable = VXGE_PAUSE_CTRL_ENABLE; |
diff --git a/drivers/net/vxge/vxge-main.h b/drivers/net/vxge/vxge-main.h index de64536cb7d0..a4f6d864fc8e 100644 --- a/drivers/net/vxge/vxge-main.h +++ b/drivers/net/vxge/vxge-main.h | |||
@@ -145,15 +145,15 @@ struct vxge_config { | |||
145 | 145 | ||
146 | int addr_learn_en; | 146 | int addr_learn_en; |
147 | 147 | ||
148 | int rth_steering; | 148 | u32 rth_steering:2, |
149 | int rth_algorithm; | 149 | rth_algorithm:2, |
150 | int rth_hash_type_tcpipv4; | 150 | rth_hash_type_tcpipv4:1, |
151 | int rth_hash_type_ipv4; | 151 | rth_hash_type_ipv4:1, |
152 | int rth_hash_type_tcpipv6; | 152 | rth_hash_type_tcpipv6:1, |
153 | int rth_hash_type_ipv6; | 153 | rth_hash_type_ipv6:1, |
154 | int rth_hash_type_tcpipv6ex; | 154 | rth_hash_type_tcpipv6ex:1, |
155 | int rth_hash_type_ipv6ex; | 155 | rth_hash_type_ipv6ex:1, |
156 | int rth_bkt_sz; | 156 | rth_bkt_sz:8; |
157 | int rth_jhash_golden_ratio; | 157 | int rth_jhash_golden_ratio; |
158 | int tx_steering_type; | 158 | int tx_steering_type; |
159 | int fifo_indicate_max_pkts; | 159 | int fifo_indicate_max_pkts; |
diff --git a/drivers/net/vxge/vxge-traffic.h b/drivers/net/vxge/vxge-traffic.h index 9890d4d596d0..1fceee876228 100644 --- a/drivers/net/vxge/vxge-traffic.h +++ b/drivers/net/vxge/vxge-traffic.h | |||
@@ -1904,34 +1904,6 @@ enum vxge_hw_ring_tcode { | |||
1904 | VXGE_HW_RING_T_CODE_MULTI_ERR = 0xF | 1904 | VXGE_HW_RING_T_CODE_MULTI_ERR = 0xF |
1905 | }; | 1905 | }; |
1906 | 1906 | ||
1907 | /** | ||
1908 | * enum enum vxge_hw_ring_hash_type - RTH hash types | ||
1909 | * @VXGE_HW_RING_HASH_TYPE_NONE: No Hash | ||
1910 | * @VXGE_HW_RING_HASH_TYPE_TCP_IPV4: TCP IPv4 | ||
1911 | * @VXGE_HW_RING_HASH_TYPE_UDP_IPV4: UDP IPv4 | ||
1912 | * @VXGE_HW_RING_HASH_TYPE_IPV4: IPv4 | ||
1913 | * @VXGE_HW_RING_HASH_TYPE_TCP_IPV6: TCP IPv6 | ||
1914 | * @VXGE_HW_RING_HASH_TYPE_UDP_IPV6: UDP IPv6 | ||
1915 | * @VXGE_HW_RING_HASH_TYPE_IPV6: IPv6 | ||
1916 | * @VXGE_HW_RING_HASH_TYPE_TCP_IPV6_EX: TCP IPv6 extension | ||
1917 | * @VXGE_HW_RING_HASH_TYPE_UDP_IPV6_EX: UDP IPv6 extension | ||
1918 | * @VXGE_HW_RING_HASH_TYPE_IPV6_EX: IPv6 extension | ||
1919 | * | ||
1920 | * RTH hash types | ||
1921 | */ | ||
1922 | enum vxge_hw_ring_hash_type { | ||
1923 | VXGE_HW_RING_HASH_TYPE_NONE = 0x0, | ||
1924 | VXGE_HW_RING_HASH_TYPE_TCP_IPV4 = 0x1, | ||
1925 | VXGE_HW_RING_HASH_TYPE_UDP_IPV4 = 0x2, | ||
1926 | VXGE_HW_RING_HASH_TYPE_IPV4 = 0x3, | ||
1927 | VXGE_HW_RING_HASH_TYPE_TCP_IPV6 = 0x4, | ||
1928 | VXGE_HW_RING_HASH_TYPE_UDP_IPV6 = 0x5, | ||
1929 | VXGE_HW_RING_HASH_TYPE_IPV6 = 0x6, | ||
1930 | VXGE_HW_RING_HASH_TYPE_TCP_IPV6_EX = 0x7, | ||
1931 | VXGE_HW_RING_HASH_TYPE_UDP_IPV6_EX = 0x8, | ||
1932 | VXGE_HW_RING_HASH_TYPE_IPV6_EX = 0x9 | ||
1933 | }; | ||
1934 | |||
1935 | enum vxge_hw_status vxge_hw_ring_rxd_reserve( | 1907 | enum vxge_hw_status vxge_hw_ring_rxd_reserve( |
1936 | struct __vxge_hw_ring *ring_handle, | 1908 | struct __vxge_hw_ring *ring_handle, |
1937 | void **rxdh); | 1909 | void **rxdh); |