diff options
author | Yuval Mintz <Yuval.Mintz@qlogic.com> | 2016-02-16 11:07:58 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-02-16 20:12:16 -0500 |
commit | 883ce97d25b019ce8437ba6f49e38302ca5ec23f (patch) | |
tree | 70c8ac3ffd6bcca8743cc3fc996fe641a6b8b731 /drivers/net/ethernet/broadcom | |
parent | 445204644ba6e5565d7aba85a4323b52960179db (diff) |
bnx2x: Add Geneve inner-RSS support
This adds the ability to perform RSS hashing based on encapsulated
headers for a geneve-encapsulated packet.
This also changes the Vxlan implementation in bnx2x to be uniform
for both vxlan and geneve [from configuration perspective].
Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com>
Signed-off-by: Ariel Elior <Ariel.Elior@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/broadcom')
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 19 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | 11 | ||||
-rw-r--r-- | drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | 175 |
3 files changed, 146 insertions, 59 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index cae0956186ce..7dd7490fdac1 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | |||
@@ -1277,8 +1277,7 @@ enum sp_rtnl_flag { | |||
1277 | BNX2X_SP_RTNL_HYPERVISOR_VLAN, | 1277 | BNX2X_SP_RTNL_HYPERVISOR_VLAN, |
1278 | BNX2X_SP_RTNL_TX_STOP, | 1278 | BNX2X_SP_RTNL_TX_STOP, |
1279 | BNX2X_SP_RTNL_GET_DRV_VERSION, | 1279 | BNX2X_SP_RTNL_GET_DRV_VERSION, |
1280 | BNX2X_SP_RTNL_ADD_VXLAN_PORT, | 1280 | BNX2X_SP_RTNL_CHANGE_UDP_PORT, |
1281 | BNX2X_SP_RTNL_DEL_VXLAN_PORT, | ||
1282 | }; | 1281 | }; |
1283 | 1282 | ||
1284 | enum bnx2x_iov_flag { | 1283 | enum bnx2x_iov_flag { |
@@ -1327,6 +1326,17 @@ struct bnx2x_vlan_entry { | |||
1327 | bool hw; | 1326 | bool hw; |
1328 | }; | 1327 | }; |
1329 | 1328 | ||
1329 | enum bnx2x_udp_port_type { | ||
1330 | BNX2X_UDP_PORT_VXLAN, | ||
1331 | BNX2X_UDP_PORT_GENEVE, | ||
1332 | BNX2X_UDP_PORT_MAX, | ||
1333 | }; | ||
1334 | |||
1335 | struct bnx2x_udp_tunnel { | ||
1336 | u16 dst_port; | ||
1337 | u8 count; | ||
1338 | }; | ||
1339 | |||
1330 | struct bnx2x { | 1340 | struct bnx2x { |
1331 | /* Fields used in the tx and intr/napi performance paths | 1341 | /* Fields used in the tx and intr/napi performance paths |
1332 | * are grouped together in the beginning of the structure | 1342 | * are grouped together in the beginning of the structure |
@@ -1830,9 +1840,10 @@ struct bnx2x { | |||
1830 | struct list_head vlan_reg; | 1840 | struct list_head vlan_reg; |
1831 | u16 vlan_cnt; | 1841 | u16 vlan_cnt; |
1832 | u16 vlan_credit; | 1842 | u16 vlan_credit; |
1833 | u16 vxlan_dst_port; | ||
1834 | u8 vxlan_dst_port_count; | ||
1835 | bool accept_any_vlan; | 1843 | bool accept_any_vlan; |
1844 | |||
1845 | /* Vxlan/Geneve related information */ | ||
1846 | struct bnx2x_udp_tunnel udp_tunnel_ports[BNX2X_UDP_PORT_MAX]; | ||
1836 | }; | 1847 | }; |
1837 | 1848 | ||
1838 | /* Tx queues may be less or equal to Rx queues */ | 1849 | /* Tx queues may be less or equal to Rx queues */ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h index 4cbb03f87b5a..37369865ca6d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h | |||
@@ -923,6 +923,7 @@ static inline int bnx2x_func_start(struct bnx2x *bp) | |||
923 | struct bnx2x_func_state_params func_params = {NULL}; | 923 | struct bnx2x_func_state_params func_params = {NULL}; |
924 | struct bnx2x_func_start_params *start_params = | 924 | struct bnx2x_func_start_params *start_params = |
925 | &func_params.params.start; | 925 | &func_params.params.start; |
926 | u16 port; | ||
926 | 927 | ||
927 | /* Prepare parameters for function state transitions */ | 928 | /* Prepare parameters for function state transitions */ |
928 | __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags); | 929 | __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags); |
@@ -959,8 +960,14 @@ static inline int bnx2x_func_start(struct bnx2x *bp) | |||
959 | start_params->network_cos_mode = STATIC_COS; | 960 | start_params->network_cos_mode = STATIC_COS; |
960 | else /* CHIP_IS_E1X */ | 961 | else /* CHIP_IS_E1X */ |
961 | start_params->network_cos_mode = FW_WRR; | 962 | start_params->network_cos_mode = FW_WRR; |
962 | 963 | if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].count) { | |
963 | start_params->vxlan_dst_port = bp->vxlan_dst_port; | 964 | port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].dst_port; |
965 | start_params->vxlan_dst_port = port; | ||
966 | } | ||
967 | if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].count) { | ||
968 | port = bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].dst_port; | ||
969 | start_params->geneve_dst_port = port; | ||
970 | } | ||
964 | 971 | ||
965 | start_params->inner_rss = 1; | 972 | start_params->inner_rss = 1; |
966 | 973 | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 6c4e3a69976f..5d6b2d95eb9d 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -59,7 +59,9 @@ | |||
59 | #include <linux/semaphore.h> | 59 | #include <linux/semaphore.h> |
60 | #include <linux/stringify.h> | 60 | #include <linux/stringify.h> |
61 | #include <linux/vmalloc.h> | 61 | #include <linux/vmalloc.h> |
62 | 62 | #if IS_ENABLED(CONFIG_GENEVE) | |
63 | #include <net/geneve.h> | ||
64 | #endif | ||
63 | #include "bnx2x.h" | 65 | #include "bnx2x.h" |
64 | #include "bnx2x_init.h" | 66 | #include "bnx2x_init.h" |
65 | #include "bnx2x_init_ops.h" | 67 | #include "bnx2x_init_ops.h" |
@@ -10076,11 +10078,13 @@ static void bnx2x_parity_recover(struct bnx2x *bp) | |||
10076 | } | 10078 | } |
10077 | } | 10079 | } |
10078 | 10080 | ||
10079 | #ifdef CONFIG_BNX2X_VXLAN | 10081 | #if defined(CONFIG_BNX2X_VXLAN) || IS_ENABLED(CONFIG_GENEVE) |
10080 | static int bnx2x_vxlan_port_update(struct bnx2x *bp, u16 port) | 10082 | static int bnx2x_udp_port_update(struct bnx2x *bp) |
10081 | { | 10083 | { |
10082 | struct bnx2x_func_switch_update_params *switch_update_params; | 10084 | struct bnx2x_func_switch_update_params *switch_update_params; |
10083 | struct bnx2x_func_state_params func_params = {NULL}; | 10085 | struct bnx2x_func_state_params func_params = {NULL}; |
10086 | struct bnx2x_udp_tunnel *udp_tunnel; | ||
10087 | u16 vxlan_port = 0, geneve_port = 0; | ||
10084 | int rc; | 10088 | int rc; |
10085 | 10089 | ||
10086 | switch_update_params = &func_params.params.switch_update; | 10090 | switch_update_params = &func_params.params.switch_update; |
@@ -10095,69 +10099,125 @@ static int bnx2x_vxlan_port_update(struct bnx2x *bp, u16 port) | |||
10095 | /* Function parameters */ | 10099 | /* Function parameters */ |
10096 | __set_bit(BNX2X_F_UPDATE_TUNNEL_CFG_CHNG, | 10100 | __set_bit(BNX2X_F_UPDATE_TUNNEL_CFG_CHNG, |
10097 | &switch_update_params->changes); | 10101 | &switch_update_params->changes); |
10098 | switch_update_params->vxlan_dst_port = port; | 10102 | |
10103 | if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].count) { | ||
10104 | udp_tunnel = &bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE]; | ||
10105 | geneve_port = udp_tunnel->dst_port; | ||
10106 | switch_update_params->geneve_dst_port = geneve_port; | ||
10107 | } | ||
10108 | |||
10109 | if (bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].count) { | ||
10110 | udp_tunnel = &bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN]; | ||
10111 | vxlan_port = udp_tunnel->dst_port; | ||
10112 | switch_update_params->vxlan_dst_port = vxlan_port; | ||
10113 | } | ||
10114 | |||
10115 | /* Re-enable inner-rss for the offloaded UDP tunnels */ | ||
10116 | __set_bit(BNX2X_F_UPDATE_TUNNEL_INNER_RSS, | ||
10117 | &switch_update_params->changes); | ||
10118 | |||
10099 | rc = bnx2x_func_state_change(bp, &func_params); | 10119 | rc = bnx2x_func_state_change(bp, &func_params); |
10100 | if (rc) | 10120 | if (rc) |
10101 | BNX2X_ERR("failed to change vxlan dst port to %d (rc = 0x%x)\n", | 10121 | BNX2X_ERR("failed to set UDP dst port to %04x %04x (rc = 0x%x)\n", |
10102 | port, rc); | 10122 | vxlan_port, geneve_port, rc); |
10123 | else | ||
10124 | DP(BNX2X_MSG_SP, | ||
10125 | "Configured UDP ports: Vxlan [%04x] Geneve [%04x]\n", | ||
10126 | vxlan_port, geneve_port); | ||
10127 | |||
10103 | return rc; | 10128 | return rc; |
10104 | } | 10129 | } |
10105 | 10130 | ||
10106 | static void __bnx2x_add_vxlan_port(struct bnx2x *bp, u16 port) | 10131 | static void __bnx2x_add_udp_port(struct bnx2x *bp, u16 port, |
10132 | enum bnx2x_udp_port_type type) | ||
10107 | { | 10133 | { |
10108 | if (!netif_running(bp->dev)) | 10134 | struct bnx2x_udp_tunnel *udp_port = &bp->udp_tunnel_ports[type]; |
10135 | |||
10136 | if (!netif_running(bp->dev) || !IS_PF(bp)) | ||
10137 | return; | ||
10138 | |||
10139 | if (udp_port->count && udp_port->dst_port == port) { | ||
10140 | udp_port->count++; | ||
10109 | return; | 10141 | return; |
10142 | } | ||
10110 | 10143 | ||
10111 | if (bp->vxlan_dst_port_count && bp->vxlan_dst_port == port) { | 10144 | if (udp_port->count) { |
10112 | bp->vxlan_dst_port_count++; | 10145 | DP(BNX2X_MSG_SP, |
10146 | "UDP tunnel [%d] - destination port limit reached\n", | ||
10147 | type); | ||
10113 | return; | 10148 | return; |
10114 | } | 10149 | } |
10115 | 10150 | ||
10116 | if (bp->vxlan_dst_port_count || !IS_PF(bp)) { | 10151 | udp_port->dst_port = port; |
10117 | DP(BNX2X_MSG_SP, "Vxlan destination port limit reached\n"); | 10152 | udp_port->count = 1; |
10153 | bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_CHANGE_UDP_PORT, 0); | ||
10154 | } | ||
10155 | |||
10156 | static void __bnx2x_del_udp_port(struct bnx2x *bp, u16 port, | ||
10157 | enum bnx2x_udp_port_type type) | ||
10158 | { | ||
10159 | struct bnx2x_udp_tunnel *udp_port = &bp->udp_tunnel_ports[type]; | ||
10160 | |||
10161 | if (!IS_PF(bp)) | ||
10162 | return; | ||
10163 | |||
10164 | if (!udp_port->count || udp_port->dst_port != port) { | ||
10165 | DP(BNX2X_MSG_SP, "Invalid UDP tunnel [%d] port\n", | ||
10166 | type); | ||
10118 | return; | 10167 | return; |
10119 | } | 10168 | } |
10120 | 10169 | ||
10121 | bp->vxlan_dst_port = port; | 10170 | /* Remove reference, and make certain it's no longer in use */ |
10122 | bp->vxlan_dst_port_count = 1; | 10171 | udp_port->count--; |
10123 | bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_ADD_VXLAN_PORT, 0); | 10172 | if (udp_port->count) |
10173 | return; | ||
10174 | udp_port->dst_port = 0; | ||
10175 | |||
10176 | if (netif_running(bp->dev)) | ||
10177 | bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_CHANGE_UDP_PORT, 0); | ||
10178 | else | ||
10179 | DP(BNX2X_MSG_SP, "Deleted UDP tunnel [%d] port %d\n", | ||
10180 | type, port); | ||
10124 | } | 10181 | } |
10182 | #endif | ||
10125 | 10183 | ||
10184 | #ifdef CONFIG_BNX2X_VXLAN | ||
10126 | static void bnx2x_add_vxlan_port(struct net_device *netdev, | 10185 | static void bnx2x_add_vxlan_port(struct net_device *netdev, |
10127 | sa_family_t sa_family, __be16 port) | 10186 | sa_family_t sa_family, __be16 port) |
10128 | { | 10187 | { |
10129 | struct bnx2x *bp = netdev_priv(netdev); | 10188 | struct bnx2x *bp = netdev_priv(netdev); |
10130 | u16 t_port = ntohs(port); | 10189 | u16 t_port = ntohs(port); |
10131 | 10190 | ||
10132 | __bnx2x_add_vxlan_port(bp, t_port); | 10191 | __bnx2x_add_udp_port(bp, t_port, BNX2X_UDP_PORT_VXLAN); |
10133 | } | 10192 | } |
10134 | 10193 | ||
10135 | static void __bnx2x_del_vxlan_port(struct bnx2x *bp, u16 port) | 10194 | static void bnx2x_del_vxlan_port(struct net_device *netdev, |
10195 | sa_family_t sa_family, __be16 port) | ||
10136 | { | 10196 | { |
10137 | if (!bp->vxlan_dst_port_count || bp->vxlan_dst_port != port || | 10197 | struct bnx2x *bp = netdev_priv(netdev); |
10138 | !IS_PF(bp)) { | 10198 | u16 t_port = ntohs(port); |
10139 | DP(BNX2X_MSG_SP, "Invalid vxlan port\n"); | ||
10140 | return; | ||
10141 | } | ||
10142 | bp->vxlan_dst_port_count--; | ||
10143 | if (bp->vxlan_dst_port_count) | ||
10144 | return; | ||
10145 | 10199 | ||
10146 | if (netif_running(bp->dev)) { | 10200 | __bnx2x_del_udp_port(bp, t_port, BNX2X_UDP_PORT_VXLAN); |
10147 | bnx2x_schedule_sp_rtnl(bp, BNX2X_SP_RTNL_DEL_VXLAN_PORT, 0); | 10201 | } |
10148 | } else { | 10202 | #endif |
10149 | bp->vxlan_dst_port = 0; | 10203 | |
10150 | netdev_info(bp->dev, "Deleted vxlan dest port %d", port); | 10204 | #if IS_ENABLED(CONFIG_GENEVE) |
10151 | } | 10205 | static void bnx2x_add_geneve_port(struct net_device *netdev, |
10206 | sa_family_t sa_family, __be16 port) | ||
10207 | { | ||
10208 | struct bnx2x *bp = netdev_priv(netdev); | ||
10209 | u16 t_port = ntohs(port); | ||
10210 | |||
10211 | __bnx2x_add_udp_port(bp, t_port, BNX2X_UDP_PORT_GENEVE); | ||
10152 | } | 10212 | } |
10153 | 10213 | ||
10154 | static void bnx2x_del_vxlan_port(struct net_device *netdev, | 10214 | static void bnx2x_del_geneve_port(struct net_device *netdev, |
10155 | sa_family_t sa_family, __be16 port) | 10215 | sa_family_t sa_family, __be16 port) |
10156 | { | 10216 | { |
10157 | struct bnx2x *bp = netdev_priv(netdev); | 10217 | struct bnx2x *bp = netdev_priv(netdev); |
10158 | u16 t_port = ntohs(port); | 10218 | u16 t_port = ntohs(port); |
10159 | 10219 | ||
10160 | __bnx2x_del_vxlan_port(bp, t_port); | 10220 | __bnx2x_del_udp_port(bp, t_port, BNX2X_UDP_PORT_GENEVE); |
10161 | } | 10221 | } |
10162 | #endif | 10222 | #endif |
10163 | 10223 | ||
@@ -10169,9 +10229,6 @@ static int bnx2x_close(struct net_device *dev); | |||
10169 | static void bnx2x_sp_rtnl_task(struct work_struct *work) | 10229 | static void bnx2x_sp_rtnl_task(struct work_struct *work) |
10170 | { | 10230 | { |
10171 | struct bnx2x *bp = container_of(work, struct bnx2x, sp_rtnl_task.work); | 10231 | struct bnx2x *bp = container_of(work, struct bnx2x, sp_rtnl_task.work); |
10172 | #ifdef CONFIG_BNX2X_VXLAN | ||
10173 | u16 port; | ||
10174 | #endif | ||
10175 | 10232 | ||
10176 | rtnl_lock(); | 10233 | rtnl_lock(); |
10177 | 10234 | ||
@@ -10270,23 +10327,27 @@ sp_rtnl_not_reset: | |||
10270 | &bp->sp_rtnl_state)) | 10327 | &bp->sp_rtnl_state)) |
10271 | bnx2x_update_mng_version(bp); | 10328 | bnx2x_update_mng_version(bp); |
10272 | 10329 | ||
10273 | #ifdef CONFIG_BNX2X_VXLAN | 10330 | #if defined(CONFIG_BNX2X_VXLAN) || IS_ENABLED(CONFIG_GENEVE) |
10274 | port = bp->vxlan_dst_port; | 10331 | if (test_and_clear_bit(BNX2X_SP_RTNL_CHANGE_UDP_PORT, |
10275 | if (test_and_clear_bit(BNX2X_SP_RTNL_ADD_VXLAN_PORT, | ||
10276 | &bp->sp_rtnl_state)) { | ||
10277 | if (!bnx2x_vxlan_port_update(bp, port)) | ||
10278 | netdev_info(bp->dev, "Added vxlan dest port %d", port); | ||
10279 | else | ||
10280 | bp->vxlan_dst_port = 0; | ||
10281 | } | ||
10282 | |||
10283 | if (test_and_clear_bit(BNX2X_SP_RTNL_DEL_VXLAN_PORT, | ||
10284 | &bp->sp_rtnl_state)) { | 10332 | &bp->sp_rtnl_state)) { |
10285 | if (!bnx2x_vxlan_port_update(bp, 0)) { | 10333 | if (bnx2x_udp_port_update(bp)) { |
10286 | netdev_info(bp->dev, | 10334 | /* On error, forget configuration */ |
10287 | "Deleted vxlan dest port %d", port); | 10335 | memset(bp->udp_tunnel_ports, 0, |
10288 | bp->vxlan_dst_port = 0; | 10336 | sizeof(struct bnx2x_udp_tunnel) * |
10289 | vxlan_get_rx_port(bp->dev); | 10337 | BNX2X_UDP_PORT_MAX); |
10338 | } else { | ||
10339 | /* Since we don't store additional port information, | ||
10340 | * if no port is configured for any feature ask for | ||
10341 | * information about currently configured ports. | ||
10342 | */ | ||
10343 | #ifdef CONFIG_BNX2X_VXLAN | ||
10344 | if (!bp->udp_tunnel_ports[BNX2X_UDP_PORT_VXLAN].count) | ||
10345 | vxlan_get_rx_port(bp->dev); | ||
10346 | #endif | ||
10347 | #if IS_ENABLED(CONFIG_GENEVE) | ||
10348 | if (!bp->udp_tunnel_ports[BNX2X_UDP_PORT_GENEVE].count) | ||
10349 | geneve_get_rx_port(bp->dev); | ||
10350 | #endif | ||
10290 | } | 10351 | } |
10291 | } | 10352 | } |
10292 | #endif | 10353 | #endif |
@@ -12494,6 +12555,10 @@ static int bnx2x_open(struct net_device *dev) | |||
12494 | if (IS_PF(bp)) | 12555 | if (IS_PF(bp)) |
12495 | vxlan_get_rx_port(dev); | 12556 | vxlan_get_rx_port(dev); |
12496 | #endif | 12557 | #endif |
12558 | #if IS_ENABLED(CONFIG_GENEVE) | ||
12559 | if (IS_PF(bp)) | ||
12560 | geneve_get_rx_port(dev); | ||
12561 | #endif | ||
12497 | 12562 | ||
12498 | return 0; | 12563 | return 0; |
12499 | } | 12564 | } |
@@ -13011,6 +13076,10 @@ static const struct net_device_ops bnx2x_netdev_ops = { | |||
13011 | .ndo_add_vxlan_port = bnx2x_add_vxlan_port, | 13076 | .ndo_add_vxlan_port = bnx2x_add_vxlan_port, |
13012 | .ndo_del_vxlan_port = bnx2x_del_vxlan_port, | 13077 | .ndo_del_vxlan_port = bnx2x_del_vxlan_port, |
13013 | #endif | 13078 | #endif |
13079 | #if IS_ENABLED(CONFIG_GENEVE) | ||
13080 | .ndo_add_geneve_port = bnx2x_add_geneve_port, | ||
13081 | .ndo_del_geneve_port = bnx2x_del_geneve_port, | ||
13082 | #endif | ||
13014 | }; | 13083 | }; |
13015 | 13084 | ||
13016 | static int bnx2x_set_coherency_mask(struct bnx2x *bp) | 13085 | static int bnx2x_set_coherency_mask(struct bnx2x *bp) |