Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'mlx5-updates-2020-02-27' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
mlx5-updates-2020-02-27

mlx5 misc updates and minor cleanups:

1) Use per vport tables for mirroring
2) Improve log messages for SW steering (DR)
3) Add devlink fdb_large_groups parameter
4) E-Switch, Allow goto earlier chain
5) Don't allow forwarding between uplink representors
6) Add support for devlink-port in non-representors mode
7) Minor misc cleanups
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+519 -129
+6
Documentation/networking/devlink/mlx5.rst
··· 37 37 * ``smfs`` Software managed flow steering. In SMFS mode, the HW 38 38 steering entities are created and manage through the driver without 39 39 firmware intervention. 40 + * - ``fdb_large_groups`` 41 + - u32 42 + - driverinit 43 + - Control the number of large groups (size > 1) in the FDB table. 44 + 45 + * The default value is 15, and the range is between 1 and 1024. 40 46 41 47 The ``mlx5`` driver supports reloading via ``DEVLINK_CMD_RELOAD`` 42 48
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/Makefile
··· 25 25 en_tx.o en_rx.o en_dim.o en_txrx.o en/xdp.o en_stats.o \ 26 26 en_selftest.o en/port.o en/monitor_stats.o en/health.o \ 27 27 en/reporter_tx.o en/reporter_rx.o en/params.o en/xsk/umem.o \ 28 - en/xsk/setup.o en/xsk/rx.o en/xsk/tx.o 28 + en/xsk/setup.o en/xsk/rx.o en/xsk/tx.o en/devlink.o 29 29 30 30 # 31 31 # Netdev extra
+33 -7
drivers/net/ethernet/mellanox/mlx5/core/devlink.c
··· 190 190 return 0; 191 191 } 192 192 193 - enum mlx5_devlink_param_id { 194 - MLX5_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, 195 - MLX5_DEVLINK_PARAM_FLOW_STEERING_MODE, 196 - }; 197 - 198 193 static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id, 199 194 union devlink_param_value val, 200 195 struct netlink_ext_ack *extack) ··· 205 210 return 0; 206 211 } 207 212 213 + #ifdef CONFIG_MLX5_ESWITCH 214 + static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id, 215 + union devlink_param_value val, 216 + struct netlink_ext_ack *extack) 217 + { 218 + int group_num = val.vu32; 219 + 220 + if (group_num < 1 || group_num > 1024) { 221 + NL_SET_ERR_MSG_MOD(extack, 222 + "Unsupported group number, supported range is 1-1024"); 223 + return -EOPNOTSUPP; 224 + } 225 + 226 + return 0; 227 + } 228 + #endif 229 + 208 230 static const struct devlink_param mlx5_devlink_params[] = { 209 - DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_FLOW_STEERING_MODE, 231 + DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_FLOW_STEERING_MODE, 210 232 "flow_steering_mode", DEVLINK_PARAM_TYPE_STRING, 211 233 BIT(DEVLINK_PARAM_CMODE_RUNTIME), 212 234 mlx5_devlink_fs_mode_get, mlx5_devlink_fs_mode_set, 213 235 mlx5_devlink_fs_mode_validate), 214 236 DEVLINK_PARAM_GENERIC(ENABLE_ROCE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 215 237 NULL, NULL, mlx5_devlink_enable_roce_validate), 238 + #ifdef CONFIG_MLX5_ESWITCH 239 + DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 240 + "fdb_large_groups", DEVLINK_PARAM_TYPE_U32, 241 + BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), 242 + NULL, NULL, 243 + mlx5_devlink_large_group_num_validate), 244 + #endif 216 245 }; 217 246 218 247 static void mlx5_devlink_set_params_init_values(struct devlink *devlink) ··· 249 230 else 250 231 strcpy(value.vstr, "smfs"); 251 232 devlink_param_driverinit_value_set(devlink, 252 - MLX5_DEVLINK_PARAM_FLOW_STEERING_MODE, 233 + MLX5_DEVLINK_PARAM_ID_FLOW_STEERING_MODE, 253 234 value); 254 235 255 236 value.vbool = MLX5_CAP_GEN(dev, roce); 256 237 devlink_param_driverinit_value_set(devlink, 257 238 DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE, 258 239 value); 240 + 241 + #ifdef CONFIG_MLX5_ESWITCH 242 + value.vu32 = ESW_OFFLOADS_DEFAULT_NUM_GROUPS; 243 + devlink_param_driverinit_value_set(devlink, 244 + MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 245 + value); 246 + #endif 259 247 } 260 248 261 249 int mlx5_devlink_register(struct devlink *devlink, struct device *dev)
+6
drivers/net/ethernet/mellanox/mlx5/core/devlink.h
··· 6 6 7 7 #include <net/devlink.h> 8 8 9 + enum mlx5_devlink_param_id { 10 + MLX5_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, 11 + MLX5_DEVLINK_PARAM_ID_FLOW_STEERING_MODE, 12 + MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 13 + }; 14 + 9 15 struct devlink *mlx5_devlink_alloc(void); 10 16 void mlx5_devlink_free(struct devlink *devlink); 11 17 int mlx5_devlink_register(struct devlink *devlink, struct device *dev);
+1
drivers/net/ethernet/mellanox/mlx5/core/en.h
··· 880 880 #endif 881 881 struct devlink_health_reporter *tx_reporter; 882 882 struct devlink_health_reporter *rx_reporter; 883 + struct devlink_port dl_phy_port; 883 884 struct mlx5e_xsk xsk; 884 885 #if IS_ENABLED(CONFIG_PCI_HYPERV_INTERFACE) 885 886 struct mlx5e_hv_vhca_stats_agent stats_agent;
+38
drivers/net/ethernet/mellanox/mlx5/core/en/devlink.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 + /* Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. */ 3 + 4 + #include "en/devlink.h" 5 + 6 + int mlx5e_devlink_phy_port_register(struct net_device *dev) 7 + { 8 + struct mlx5e_priv *priv; 9 + struct devlink *devlink; 10 + int err; 11 + 12 + priv = netdev_priv(dev); 13 + devlink = priv_to_devlink(priv->mdev); 14 + 15 + devlink_port_attrs_set(&priv->dl_phy_port, 16 + DEVLINK_PORT_FLAVOUR_PHYSICAL, 17 + PCI_FUNC(priv->mdev->pdev->devfn), 18 + false, 0, 19 + NULL, 0); 20 + err = devlink_port_register(devlink, &priv->dl_phy_port, 1); 21 + if (err) 22 + return err; 23 + devlink_port_type_eth_set(&priv->dl_phy_port, dev); 24 + return 0; 25 + } 26 + 27 + void mlx5e_devlink_phy_port_unregister(struct mlx5e_priv *priv) 28 + { 29 + devlink_port_unregister(&priv->dl_phy_port); 30 + } 31 + 32 + struct devlink_port *mlx5e_get_devlink_phy_port(struct net_device *dev) 33 + { 34 + struct mlx5e_priv *priv = netdev_priv(dev); 35 + 36 + return &priv->dl_phy_port; 37 + } 38 +
+15
drivers/net/ethernet/mellanox/mlx5/core/en/devlink.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ 2 + /* Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. */ 3 + 4 + #ifndef __MLX5E_EN_DEVLINK_H 5 + #define __MLX5E_EN_DEVLINK_H 6 + 7 + #include <net/devlink.h> 8 + #include "en.h" 9 + 10 + int mlx5e_devlink_phy_port_register(struct net_device *dev); 11 + void mlx5e_devlink_phy_port_unregister(struct mlx5e_priv *priv); 12 + struct devlink_port *mlx5e_get_devlink_phy_port(struct net_device *dev); 13 + 14 + #endif 15 +
+11
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
··· 63 63 #include "en/xsk/rx.h" 64 64 #include "en/xsk/tx.h" 65 65 #include "en/hv_vhca_stats.h" 66 + #include "en/devlink.h" 66 67 #include "lib/mlx5.h" 67 68 68 69 ··· 4606 4605 .ndo_set_vf_link_state = mlx5e_set_vf_link_state, 4607 4606 .ndo_get_vf_stats = mlx5e_get_vf_stats, 4608 4607 #endif 4608 + .ndo_get_devlink_port = mlx5e_get_devlink_phy_port, 4609 4609 }; 4610 4610 4611 4611 static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev) ··· 5473 5471 goto err_detach; 5474 5472 } 5475 5473 5474 + err = mlx5e_devlink_phy_port_register(netdev); 5475 + if (err) { 5476 + mlx5_core_err(mdev, "mlx5e_devlink_phy_port_register failed, %d\n", err); 5477 + goto err_unregister_netdev; 5478 + } 5479 + 5476 5480 #ifdef CONFIG_MLX5_CORE_EN_DCB 5477 5481 mlx5e_dcbnl_init_app(priv); 5478 5482 #endif 5479 5483 return priv; 5480 5484 5485 + err_unregister_netdev: 5486 + unregister_netdev(netdev); 5481 5487 err_detach: 5482 5488 mlx5e_detach(mdev, priv); 5483 5489 err_destroy_netdev: ··· 5507 5497 #ifdef CONFIG_MLX5_CORE_EN_DCB 5508 5498 mlx5e_dcbnl_delete_app(priv); 5509 5499 #endif 5500 + mlx5e_devlink_phy_port_unregister(priv); 5510 5501 unregister_netdev(priv->netdev); 5511 5502 mlx5e_detach(mdev, vpriv); 5512 5503 mlx5e_destroy_netdev(priv);
+24 -14
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
··· 192 192 193 193 err = mlx5_eswitch_get_vport_stats(esw, rep->vport, &vf_stats); 194 194 if (err) { 195 - pr_warn("vport %d error %d reading stats\n", rep->vport, err); 195 + netdev_warn(priv->netdev, "vport %d error %d reading stats\n", 196 + rep->vport, err); 196 197 return; 197 198 } 198 199 ··· 1423 1422 return 0; 1424 1423 } 1425 1424 1426 - static struct devlink_port *mlx5e_get_devlink_port(struct net_device *dev) 1425 + static struct devlink_port *mlx5e_rep_get_devlink_port(struct net_device *dev) 1427 1426 { 1428 1427 struct mlx5e_priv *priv = netdev_priv(dev); 1429 1428 struct mlx5e_rep_priv *rpriv = priv->ppriv; ··· 1436 1435 .ndo_stop = mlx5e_rep_close, 1437 1436 .ndo_start_xmit = mlx5e_xmit, 1438 1437 .ndo_setup_tc = mlx5e_rep_setup_tc, 1439 - .ndo_get_devlink_port = mlx5e_get_devlink_port, 1438 + .ndo_get_devlink_port = mlx5e_rep_get_devlink_port, 1440 1439 .ndo_get_stats64 = mlx5e_rep_get_stats, 1441 1440 .ndo_has_offload_stats = mlx5e_rep_has_offload_stats, 1442 1441 .ndo_get_offload_stats = mlx5e_rep_get_offload_stats, ··· 1449 1448 .ndo_start_xmit = mlx5e_xmit, 1450 1449 .ndo_set_mac_address = mlx5e_uplink_rep_set_mac, 1451 1450 .ndo_setup_tc = mlx5e_rep_setup_tc, 1452 - .ndo_get_devlink_port = mlx5e_get_devlink_port, 1451 + .ndo_get_devlink_port = mlx5e_rep_get_devlink_port, 1453 1452 .ndo_get_stats64 = mlx5e_get_stats, 1454 1453 .ndo_has_offload_stats = mlx5e_rep_has_offload_stats, 1455 1454 .ndo_get_offload_stats = mlx5e_rep_get_offload_stats, ··· 1464 1463 .ndo_set_vf_vlan = mlx5e_uplink_rep_set_vf_vlan, 1465 1464 .ndo_set_features = mlx5e_set_features, 1466 1465 }; 1466 + 1467 + bool mlx5e_eswitch_uplink_rep(struct net_device *netdev) 1468 + { 1469 + return netdev->netdev_ops == &mlx5e_netdev_ops_uplink_rep; 1470 + } 1467 1471 1468 1472 bool mlx5e_eswitch_rep(struct net_device *netdev) 1469 1473 { ··· 2032 2026 &mlx5e_uplink_rep_profile : &mlx5e_rep_profile; 2033 2027 netdev = mlx5e_create_netdev(dev, profile, nch, rpriv); 2034 2028 if (!netdev) { 2035 - pr_warn("Failed to create representor netdev for vport %d\n", 2036 - rep->vport); 2029 + mlx5_core_warn(dev, 2030 + "Failed to create representor netdev for vport %d\n", 2031 + rep->vport); 2037 2032 kfree(rpriv); 2038 2033 return -EINVAL; 2039 2034 } ··· 2052 2045 2053 2046 err = mlx5e_attach_netdev(netdev_priv(netdev)); 2054 2047 if (err) { 2055 - pr_warn("Failed to attach representor netdev for vport %d\n", 2056 - rep->vport); 2048 + netdev_warn(netdev, 2049 + "Failed to attach representor netdev for vport %d\n", 2050 + rep->vport); 2057 2051 goto err_destroy_mdev_resources; 2058 2052 } 2059 2053 2060 2054 err = mlx5e_rep_neigh_init(rpriv); 2061 2055 if (err) { 2062 - pr_warn("Failed to initialized neighbours handling for vport %d\n", 2063 - rep->vport); 2056 + netdev_warn(netdev, 2057 + "Failed to initialized neighbours handling for vport %d\n", 2058 + rep->vport); 2064 2059 goto err_detach_netdev; 2065 2060 } 2066 2061 2067 2062 err = register_devlink_port(dev, rpriv); 2068 2063 if (err) { 2069 - esw_warn(dev, "Failed to register devlink port %d\n", 2070 - rep->vport); 2064 + netdev_warn(netdev, "Failed to register devlink port %d\n", 2065 + rep->vport); 2071 2066 goto err_neigh_cleanup; 2072 2067 } 2073 2068 2074 2069 err = register_netdev(netdev); 2075 2070 if (err) { 2076 - pr_warn("Failed to register representor netdev for vport %d\n", 2077 - rep->vport); 2071 + netdev_warn(netdev, 2072 + "Failed to register representor netdev for vport %d\n", 2073 + rep->vport); 2078 2074 goto err_devlink_cleanup; 2079 2075 } 2080 2076
+1
drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
··· 200 200 void mlx5e_rep_queue_neigh_stats_work(struct mlx5e_priv *priv); 201 201 202 202 bool mlx5e_eswitch_rep(struct net_device *netdev); 203 + bool mlx5e_eswitch_uplink_rep(struct net_device *netdev); 203 204 204 205 #else /* CONFIG_MLX5_ESWITCH */ 205 206 static inline bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv) { return false; }
+69 -46
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
··· 1076 1076 static struct mlx5_flow_handle * 1077 1077 mlx5e_tc_offload_to_slow_path(struct mlx5_eswitch *esw, 1078 1078 struct mlx5e_tc_flow *flow, 1079 - struct mlx5_flow_spec *spec, 1080 - struct mlx5_esw_flow_attr *slow_attr) 1079 + struct mlx5_flow_spec *spec) 1081 1080 { 1081 + struct mlx5_esw_flow_attr slow_attr; 1082 1082 struct mlx5_flow_handle *rule; 1083 1083 1084 - memcpy(slow_attr, flow->esw_attr, sizeof(*slow_attr)); 1085 - slow_attr->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 1086 - slow_attr->split_count = 0; 1087 - slow_attr->flags |= MLX5_ESW_ATTR_FLAG_SLOW_PATH; 1084 + memcpy(&slow_attr, flow->esw_attr, sizeof(slow_attr)); 1085 + slow_attr.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 1086 + slow_attr.split_count = 0; 1087 + slow_attr.flags |= MLX5_ESW_ATTR_FLAG_SLOW_PATH; 1088 1088 1089 - rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, slow_attr); 1089 + rule = mlx5e_tc_offload_fdb_rules(esw, flow, spec, &slow_attr); 1090 1090 if (!IS_ERR(rule)) 1091 1091 flow_flag_set(flow, SLOW); 1092 1092 ··· 1095 1095 1096 1096 static void 1097 1097 mlx5e_tc_unoffload_from_slow_path(struct mlx5_eswitch *esw, 1098 - struct mlx5e_tc_flow *flow, 1099 - struct mlx5_esw_flow_attr *slow_attr) 1098 + struct mlx5e_tc_flow *flow) 1100 1099 { 1101 - memcpy(slow_attr, flow->esw_attr, sizeof(*slow_attr)); 1102 - slow_attr->action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 1103 - slow_attr->split_count = 0; 1104 - slow_attr->flags |= MLX5_ESW_ATTR_FLAG_SLOW_PATH; 1105 - mlx5e_tc_unoffload_fdb_rules(esw, flow, slow_attr); 1100 + struct mlx5_esw_flow_attr slow_attr; 1101 + 1102 + memcpy(&slow_attr, flow->esw_attr, sizeof(slow_attr)); 1103 + slow_attr.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 1104 + slow_attr.split_count = 0; 1105 + slow_attr.flags |= MLX5_ESW_ATTR_FLAG_SLOW_PATH; 1106 + mlx5e_tc_unoffload_fdb_rules(esw, flow, &slow_attr); 1106 1107 flow_flag_clear(flow, SLOW); 1107 1108 } 1108 1109 ··· 1174 1173 int out_index; 1175 1174 1176 1175 if (!mlx5_esw_chains_prios_supported(esw) && attr->prio != 1) { 1177 - NL_SET_ERR_MSG(extack, "E-switch priorities unsupported, upgrade FW"); 1176 + NL_SET_ERR_MSG_MOD(extack, 1177 + "E-switch priorities unsupported, upgrade FW"); 1178 1178 return -EOPNOTSUPP; 1179 1179 } 1180 1180 ··· 1186 1184 */ 1187 1185 max_chain = mlx5_esw_chains_get_chain_range(esw); 1188 1186 if (!mlx5e_is_ft_flow(flow) && attr->chain > max_chain) { 1189 - NL_SET_ERR_MSG(extack, "Requested chain is out of supported range"); 1187 + NL_SET_ERR_MSG_MOD(extack, 1188 + "Requested chain is out of supported range"); 1190 1189 return -EOPNOTSUPP; 1191 1190 } 1192 1191 1193 1192 max_prio = mlx5_esw_chains_get_prio_range(esw); 1194 1193 if (attr->prio > max_prio) { 1195 - NL_SET_ERR_MSG(extack, "Requested priority is out of supported range"); 1194 + NL_SET_ERR_MSG_MOD(extack, 1195 + "Requested priority is out of supported range"); 1196 1196 return -EOPNOTSUPP; 1197 1197 } 1198 1198 ··· 1241 1237 * (1) there's no error 1242 1238 * (2) there's an encap action and we don't have valid neigh 1243 1239 */ 1244 - if (!encap_valid) { 1245 - /* continue with goto slow path rule instead */ 1246 - struct mlx5_esw_flow_attr slow_attr; 1247 - 1248 - flow->rule[0] = mlx5e_tc_offload_to_slow_path(esw, flow, &parse_attr->spec, &slow_attr); 1249 - } else { 1240 + if (!encap_valid) 1241 + flow->rule[0] = mlx5e_tc_offload_to_slow_path(esw, flow, &parse_attr->spec); 1242 + else 1250 1243 flow->rule[0] = mlx5e_tc_offload_fdb_rules(esw, flow, &parse_attr->spec, attr); 1251 - } 1252 1244 1253 1245 if (IS_ERR(flow->rule[0])) 1254 1246 return PTR_ERR(flow->rule[0]); ··· 1272 1272 { 1273 1273 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1274 1274 struct mlx5_esw_flow_attr *attr = flow->esw_attr; 1275 - struct mlx5_esw_flow_attr slow_attr; 1276 1275 int out_index; 1277 1276 1278 1277 if (flow_flag_test(flow, NOT_READY)) { ··· 1282 1283 1283 1284 if (mlx5e_is_offloaded_flow(flow)) { 1284 1285 if (flow_flag_test(flow, SLOW)) 1285 - mlx5e_tc_unoffload_from_slow_path(esw, flow, &slow_attr); 1286 + mlx5e_tc_unoffload_from_slow_path(esw, flow); 1286 1287 else 1287 1288 mlx5e_tc_unoffload_fdb_rules(esw, flow, attr); 1288 1289 } ··· 1311 1312 struct list_head *flow_list) 1312 1313 { 1313 1314 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1314 - struct mlx5_esw_flow_attr slow_attr, *esw_attr; 1315 + struct mlx5_esw_flow_attr *esw_attr; 1315 1316 struct mlx5_flow_handle *rule; 1316 1317 struct mlx5_flow_spec *spec; 1317 1318 struct mlx5e_tc_flow *flow; ··· 1364 1365 continue; 1365 1366 } 1366 1367 1367 - mlx5e_tc_unoffload_from_slow_path(esw, flow, &slow_attr); 1368 + mlx5e_tc_unoffload_from_slow_path(esw, flow); 1368 1369 flow->rule[0] = rule; 1369 1370 /* was unset when slow path rule removed */ 1370 1371 flow_flag_set(flow, OFFLOADED); ··· 1376 1377 struct list_head *flow_list) 1377 1378 { 1378 1379 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 1379 - struct mlx5_esw_flow_attr slow_attr; 1380 1380 struct mlx5_flow_handle *rule; 1381 1381 struct mlx5_flow_spec *spec; 1382 1382 struct mlx5e_tc_flow *flow; ··· 1387 1389 spec = &flow->esw_attr->parse_attr->spec; 1388 1390 1389 1391 /* update from encap rule to slow path rule */ 1390 - rule = mlx5e_tc_offload_to_slow_path(esw, flow, spec, &slow_attr); 1392 + rule = mlx5e_tc_offload_to_slow_path(esw, flow, spec); 1391 1393 /* mark the flow's encap dest as non-valid */ 1392 1394 flow->esw_attr->dests[flow->tmp_efi_index].flags &= ~MLX5_ESW_DEST_ENCAP_VALID; 1393 1395 ··· 2558 2560 2559 2561 static int parse_tc_pedit_action(struct mlx5e_priv *priv, 2560 2562 const struct flow_action_entry *act, int namespace, 2561 - struct mlx5e_tc_flow_parse_attr *parse_attr, 2562 2563 struct pedit_headers_action *hdrs, 2563 2564 struct netlink_ext_ack *extack) 2564 2565 { ··· 2833 2836 return -EOPNOTSUPP; 2834 2837 } 2835 2838 2836 - err = parse_tc_pedit_action(priv, &pedit_act, namespace, parse_attr, 2837 - hdrs, NULL); 2839 + err = parse_tc_pedit_action(priv, &pedit_act, namespace, hdrs, NULL); 2838 2840 *action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR; 2839 2841 2840 2842 return err; ··· 2895 2899 case FLOW_ACTION_MANGLE: 2896 2900 case FLOW_ACTION_ADD: 2897 2901 err = parse_tc_pedit_action(priv, act, MLX5_FLOW_NAMESPACE_KERNEL, 2898 - parse_attr, hdrs, extack); 2902 + hdrs, extack); 2899 2903 if (err) 2900 2904 return err; 2901 2905 ··· 3339 3343 case FLOW_ACTION_MANGLE: 3340 3344 case FLOW_ACTION_ADD: 3341 3345 err = parse_tc_pedit_action(priv, act, MLX5_FLOW_NAMESPACE_FDB, 3342 - parse_attr, hdrs, extack); 3346 + hdrs, extack); 3343 3347 if (err) 3344 3348 return err; 3345 3349 ··· 3377 3381 if (attr->out_count >= MLX5_MAX_FLOW_FWD_VPORTS) { 3378 3382 NL_SET_ERR_MSG_MOD(extack, 3379 3383 "can't support more output ports, can't offload forwarding"); 3380 - pr_err("can't support more than %d output ports, can't offload forwarding\n", 3381 - attr->out_count); 3384 + netdev_warn(priv->netdev, 3385 + "can't support more than %d output ports, can't offload forwarding\n", 3386 + attr->out_count); 3382 3387 return -EOPNOTSUPP; 3383 3388 } 3384 3389 ··· 3402 3405 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 3403 3406 struct net_device *uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH); 3404 3407 struct net_device *uplink_upper; 3408 + struct mlx5e_rep_priv *rep_priv; 3405 3409 3406 3410 if (is_duplicated_output_device(priv->netdev, 3407 3411 out_dev, ··· 3438 3440 return err; 3439 3441 } 3440 3442 3443 + /* Don't allow forwarding between uplink. 3444 + * 3445 + * Input vport was stored esw_attr->in_rep. 3446 + * In LAG case, *priv* is the private data of 3447 + * uplink which may be not the input vport. 3448 + */ 3449 + rep_priv = mlx5e_rep_to_rep_priv(attr->in_rep); 3450 + if (mlx5e_eswitch_uplink_rep(rep_priv->netdev) && 3451 + mlx5e_eswitch_uplink_rep(out_dev)) { 3452 + NL_SET_ERR_MSG_MOD(extack, 3453 + "devices are both uplink, can't offload forwarding"); 3454 + pr_err("devices %s %s are both uplink, can't offload forwarding\n", 3455 + priv->netdev->name, out_dev->name); 3456 + return -EOPNOTSUPP; 3457 + } 3458 + 3441 3459 if (!mlx5e_is_valid_eswitch_fwd_dev(priv, out_dev)) { 3442 3460 NL_SET_ERR_MSG_MOD(extack, 3443 3461 "devices are not on same switch HW, can't offload forwarding"); 3444 - pr_err("devices %s %s not on same switch HW, can't offload forwarding\n", 3445 - priv->netdev->name, out_dev->name); 3462 + netdev_warn(priv->netdev, 3463 + "devices %s %s not on same switch HW, can't offload forwarding\n", 3464 + priv->netdev->name, 3465 + out_dev->name); 3446 3466 return -EOPNOTSUPP; 3447 3467 } 3448 3468 ··· 3479 3463 } else { 3480 3464 NL_SET_ERR_MSG_MOD(extack, 3481 3465 "devices are not on same switch HW, can't offload forwarding"); 3482 - pr_err("devices %s %s not on same switch HW, can't offload forwarding\n", 3483 - priv->netdev->name, out_dev->name); 3466 + netdev_warn(priv->netdev, 3467 + "devices %s %s not on same switch HW, can't offload forwarding\n", 3468 + priv->netdev->name, 3469 + out_dev->name); 3484 3470 return -EINVAL; 3485 3471 } 3486 3472 } ··· 3534 3516 NL_SET_ERR_MSG_MOD(extack, "Goto action is not supported"); 3535 3517 return -EOPNOTSUPP; 3536 3518 } 3537 - if (dest_chain <= attr->chain) { 3538 - NL_SET_ERR_MSG(extack, "Goto earlier chain isn't supported"); 3519 + if (!mlx5_esw_chains_backwards_supported(esw) && 3520 + dest_chain <= attr->chain) { 3521 + NL_SET_ERR_MSG_MOD(extack, 3522 + "Goto earlier chain isn't supported"); 3539 3523 return -EOPNOTSUPP; 3540 3524 } 3541 3525 if (dest_chain > max_chain) { 3542 - NL_SET_ERR_MSG(extack, "Requested destination chain is out of supported range"); 3526 + NL_SET_ERR_MSG_MOD(extack, 3527 + "Requested destination chain is out of supported range"); 3543 3528 return -EOPNOTSUPP; 3544 3529 } 3545 3530 action |= MLX5_FLOW_CONTEXT_ACTION_COUNT; ··· 3592 3571 3593 3572 if (attr->dest_chain) { 3594 3573 if (attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) { 3595 - NL_SET_ERR_MSG(extack, "Mirroring goto chain rules isn't supported"); 3574 + NL_SET_ERR_MSG_MOD(extack, 3575 + "Mirroring goto chain rules isn't supported"); 3596 3576 return -EOPNOTSUPP; 3597 3577 } 3598 3578 attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; ··· 3601 3579 3602 3580 if (!(attr->action & 3603 3581 (MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_DROP))) { 3604 - NL_SET_ERR_MSG(extack, "Rule must have at least one forward/drop action"); 3582 + NL_SET_ERR_MSG_MOD(extack, 3583 + "Rule must have at least one forward/drop action"); 3605 3584 return -EOPNOTSUPP; 3606 3585 } 3607 3586
+22
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
··· 39 39 #include "lib/eq.h" 40 40 #include "eswitch.h" 41 41 #include "fs_core.h" 42 + #include "devlink.h" 42 43 #include "ecpf.h" 43 44 44 45 enum { ··· 2007 2006 esw_disable_vport(esw, vport); 2008 2007 } 2009 2008 2009 + static void mlx5_eswitch_get_devlink_param(struct mlx5_eswitch *esw) 2010 + { 2011 + struct devlink *devlink = priv_to_devlink(esw->dev); 2012 + union devlink_param_value val; 2013 + int err; 2014 + 2015 + err = devlink_param_driverinit_value_get(devlink, 2016 + MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM, 2017 + &val); 2018 + if (!err) { 2019 + esw->params.large_group_num = val.vu32; 2020 + } else { 2021 + esw_warn(esw->dev, 2022 + "Devlink can't get param fdb_large_groups, uses default (%d).\n", 2023 + ESW_OFFLOADS_DEFAULT_NUM_GROUPS); 2024 + esw->params.large_group_num = ESW_OFFLOADS_DEFAULT_NUM_GROUPS; 2025 + } 2026 + } 2027 + 2010 2028 int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode) 2011 2029 { 2012 2030 int err; ··· 2041 2021 2042 2022 if (!MLX5_CAP_ESW_EGRESS_ACL(esw->dev, ft_support)) 2043 2023 esw_warn(esw->dev, "engress ACL is not supported by FW\n"); 2024 + 2025 + mlx5_eswitch_get_devlink_param(esw); 2044 2026 2045 2027 esw_create_tsar(esw); 2046 2028
+14
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
··· 55 55 56 56 #ifdef CONFIG_MLX5_ESWITCH 57 57 58 + #define ESW_OFFLOADS_DEFAULT_NUM_GROUPS 15 59 + 58 60 #define MLX5_MAX_UC_PER_VPORT(dev) \ 59 61 (1 << MLX5_CAP_GEN(dev, log_max_current_uc_list)) 60 62 ··· 185 183 int vlan_push_pop_refcount; 186 184 187 185 struct mlx5_esw_chains_priv *esw_chains_priv; 186 + struct { 187 + DECLARE_HASHTABLE(table, 8); 188 + /* Protects vports.table */ 189 + struct mutex lock; 190 + } vports; 191 + 188 192 } offloads; 189 193 }; 190 194 u32 flags; ··· 263 255 u16 manager_vport; 264 256 u16 first_host_vport; 265 257 struct mlx5_esw_functions esw_funcs; 258 + struct { 259 + u32 large_group_num; 260 + } params; 266 261 }; 267 262 268 263 void esw_offloads_disable(struct mlx5_eswitch *esw); ··· 633 622 void 634 623 esw_vport_destroy_offloads_acl_tables(struct mlx5_eswitch *esw, 635 624 struct mlx5_vport *vport); 625 + 626 + int mlx5_esw_vport_tbl_get(struct mlx5_eswitch *esw); 627 + void mlx5_esw_vport_tbl_put(struct mlx5_eswitch *esw); 636 628 637 629 #else /* CONFIG_MLX5_ESWITCH */ 638 630 /* eswitch API stubs */
+198 -10
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
··· 50 50 #define MLX5_ESW_MISS_FLOWS (2) 51 51 #define UPLINK_REP_INDEX 0 52 52 53 + /* Per vport tables */ 54 + 55 + #define MLX5_ESW_VPORT_TABLE_SIZE 128 56 + 57 + /* This struct is used as a key to the hash table and we need it to be packed 58 + * so hash result is consistent 59 + */ 60 + struct mlx5_vport_key { 61 + u32 chain; 62 + u16 prio; 63 + u16 vport; 64 + u16 vhca_id; 65 + } __packed; 66 + 67 + struct mlx5_vport_table { 68 + struct hlist_node hlist; 69 + struct mlx5_flow_table *fdb; 70 + u32 num_rules; 71 + struct mlx5_vport_key key; 72 + }; 73 + 74 + #define MLX5_ESW_VPORT_TBL_NUM_GROUPS 4 75 + 76 + static struct mlx5_flow_table * 77 + esw_vport_tbl_create(struct mlx5_eswitch *esw, struct mlx5_flow_namespace *ns) 78 + { 79 + struct mlx5_flow_table_attr ft_attr = {}; 80 + struct mlx5_flow_table *fdb; 81 + 82 + ft_attr.autogroup.max_num_groups = MLX5_ESW_VPORT_TBL_NUM_GROUPS; 83 + ft_attr.max_fte = MLX5_ESW_VPORT_TABLE_SIZE; 84 + ft_attr.prio = FDB_PER_VPORT; 85 + fdb = mlx5_create_auto_grouped_flow_table(ns, &ft_attr); 86 + if (IS_ERR(fdb)) { 87 + esw_warn(esw->dev, "Failed to create per vport FDB Table err %ld\n", 88 + PTR_ERR(fdb)); 89 + } 90 + 91 + return fdb; 92 + } 93 + 94 + static u32 flow_attr_to_vport_key(struct mlx5_eswitch *esw, 95 + struct mlx5_esw_flow_attr *attr, 96 + struct mlx5_vport_key *key) 97 + { 98 + key->vport = attr->in_rep->vport; 99 + key->chain = attr->chain; 100 + key->prio = attr->prio; 101 + key->vhca_id = MLX5_CAP_GEN(esw->dev, vhca_id); 102 + return jhash(key, sizeof(*key), 0); 103 + } 104 + 105 + /* caller must hold vports.lock */ 106 + static struct mlx5_vport_table * 107 + esw_vport_tbl_lookup(struct mlx5_eswitch *esw, struct mlx5_vport_key *skey, u32 key) 108 + { 109 + struct mlx5_vport_table *e; 110 + 111 + hash_for_each_possible(esw->fdb_table.offloads.vports.table, e, hlist, key) 112 + if (!memcmp(&e->key, skey, sizeof(*skey))) 113 + return e; 114 + 115 + return NULL; 116 + } 117 + 118 + static void 119 + esw_vport_tbl_put(struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *attr) 120 + { 121 + struct mlx5_vport_table *e; 122 + struct mlx5_vport_key key; 123 + u32 hkey; 124 + 125 + mutex_lock(&esw->fdb_table.offloads.vports.lock); 126 + hkey = flow_attr_to_vport_key(esw, attr, &key); 127 + e = esw_vport_tbl_lookup(esw, &key, hkey); 128 + if (!e || --e->num_rules) 129 + goto out; 130 + 131 + hash_del(&e->hlist); 132 + mlx5_destroy_flow_table(e->fdb); 133 + kfree(e); 134 + out: 135 + mutex_unlock(&esw->fdb_table.offloads.vports.lock); 136 + } 137 + 138 + static struct mlx5_flow_table * 139 + esw_vport_tbl_get(struct mlx5_eswitch *esw, struct mlx5_esw_flow_attr *attr) 140 + { 141 + struct mlx5_core_dev *dev = esw->dev; 142 + struct mlx5_flow_namespace *ns; 143 + struct mlx5_flow_table *fdb; 144 + struct mlx5_vport_table *e; 145 + struct mlx5_vport_key skey; 146 + u32 hkey; 147 + 148 + mutex_lock(&esw->fdb_table.offloads.vports.lock); 149 + hkey = flow_attr_to_vport_key(esw, attr, &skey); 150 + e = esw_vport_tbl_lookup(esw, &skey, hkey); 151 + if (e) { 152 + e->num_rules++; 153 + goto out; 154 + } 155 + 156 + e = kzalloc(sizeof(*e), GFP_KERNEL); 157 + if (!e) { 158 + fdb = ERR_PTR(-ENOMEM); 159 + goto err_alloc; 160 + } 161 + 162 + ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB); 163 + if (!ns) { 164 + esw_warn(dev, "Failed to get FDB namespace\n"); 165 + fdb = ERR_PTR(-ENOENT); 166 + goto err_ns; 167 + } 168 + 169 + fdb = esw_vport_tbl_create(esw, ns); 170 + if (IS_ERR(fdb)) 171 + goto err_ns; 172 + 173 + e->fdb = fdb; 174 + e->num_rules = 1; 175 + e->key = skey; 176 + hash_add(esw->fdb_table.offloads.vports.table, &e->hlist, hkey); 177 + out: 178 + mutex_unlock(&esw->fdb_table.offloads.vports.lock); 179 + return e->fdb; 180 + 181 + err_ns: 182 + kfree(e); 183 + err_alloc: 184 + mutex_unlock(&esw->fdb_table.offloads.vports.lock); 185 + return fdb; 186 + } 187 + 188 + int mlx5_esw_vport_tbl_get(struct mlx5_eswitch *esw) 189 + { 190 + struct mlx5_esw_flow_attr attr = {}; 191 + struct mlx5_eswitch_rep rep = {}; 192 + struct mlx5_flow_table *fdb; 193 + struct mlx5_vport *vport; 194 + int i; 195 + 196 + attr.prio = 1; 197 + attr.in_rep = &rep; 198 + mlx5_esw_for_all_vports(esw, i, vport) { 199 + attr.in_rep->vport = vport->vport; 200 + fdb = esw_vport_tbl_get(esw, &attr); 201 + if (!fdb) 202 + goto out; 203 + } 204 + return 0; 205 + 206 + out: 207 + mlx5_esw_vport_tbl_put(esw); 208 + return PTR_ERR(fdb); 209 + } 210 + 211 + void mlx5_esw_vport_tbl_put(struct mlx5_eswitch *esw) 212 + { 213 + struct mlx5_esw_flow_attr attr = {}; 214 + struct mlx5_eswitch_rep rep = {}; 215 + struct mlx5_vport *vport; 216 + int i; 217 + 218 + attr.prio = 1; 219 + attr.in_rep = &rep; 220 + mlx5_esw_for_all_vports(esw, i, vport) { 221 + attr.in_rep->vport = vport->vport; 222 + esw_vport_tbl_put(esw, &attr); 223 + } 224 + } 225 + 226 + /* End: Per vport tables */ 227 + 53 228 static struct mlx5_eswitch_rep *mlx5_eswitch_get_rep(struct mlx5_eswitch *esw, 54 229 u16 vport_num) 55 230 { ··· 366 191 i++; 367 192 } 368 193 369 - mlx5_eswitch_set_rule_source_port(esw, spec, attr); 370 - 371 194 if (attr->outer_match_level != MLX5_MATCH_NONE) 372 195 spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS; 373 196 if (attr->inner_match_level != MLX5_MATCH_NONE) ··· 374 201 if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) 375 202 flow_act.modify_hdr = attr->modify_hdr; 376 203 377 - fdb = mlx5_esw_chains_get_table(esw, attr->chain, attr->prio, 378 - !!split); 204 + if (split) { 205 + fdb = esw_vport_tbl_get(esw, attr); 206 + } else { 207 + fdb = mlx5_esw_chains_get_table(esw, attr->chain, attr->prio, 208 + 0); 209 + mlx5_eswitch_set_rule_source_port(esw, spec, attr); 210 + } 379 211 if (IS_ERR(fdb)) { 380 212 rule = ERR_CAST(fdb); 381 213 goto err_esw_get; ··· 399 221 return rule; 400 222 401 223 err_add_rule: 402 - mlx5_esw_chains_put_table(esw, attr->chain, attr->prio, !!split); 224 + if (split) 225 + esw_vport_tbl_put(esw, attr); 226 + else 227 + mlx5_esw_chains_put_table(esw, attr->chain, attr->prio, 0); 403 228 err_esw_get: 404 229 if (!(attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH) && attr->dest_chain) 405 230 mlx5_esw_chains_put_table(esw, attr->dest_chain, 1, 0); ··· 428 247 goto err_get_fast; 429 248 } 430 249 431 - fwd_fdb = mlx5_esw_chains_get_table(esw, attr->chain, attr->prio, 1); 250 + fwd_fdb = esw_vport_tbl_get(esw, attr); 432 251 if (IS_ERR(fwd_fdb)) { 433 252 rule = ERR_CAST(fwd_fdb); 434 253 goto err_get_fwd; ··· 466 285 467 286 return rule; 468 287 add_err: 469 - mlx5_esw_chains_put_table(esw, attr->chain, attr->prio, 1); 288 + esw_vport_tbl_put(esw, attr); 470 289 err_get_fwd: 471 290 mlx5_esw_chains_put_table(esw, attr->chain, attr->prio, 0); 472 291 err_get_fast: ··· 493 312 atomic64_dec(&esw->offloads.num_flows); 494 313 495 314 if (fwd_rule) { 496 - mlx5_esw_chains_put_table(esw, attr->chain, attr->prio, 1); 315 + esw_vport_tbl_put(esw, attr); 497 316 mlx5_esw_chains_put_table(esw, attr->chain, attr->prio, 0); 498 317 } else { 499 - mlx5_esw_chains_put_table(esw, attr->chain, attr->prio, 500 - !!split); 318 + if (split) 319 + esw_vport_tbl_put(esw, attr); 320 + else 321 + mlx5_esw_chains_put_table(esw, attr->chain, attr->prio, 322 + 0); 501 323 if (attr->dest_chain) 502 324 mlx5_esw_chains_put_table(esw, attr->dest_chain, 1, 0); 503 325 } ··· 2107 1923 if (err) 2108 1924 goto create_fg_err; 2109 1925 1926 + mutex_init(&esw->fdb_table.offloads.vports.lock); 1927 + hash_init(esw->fdb_table.offloads.vports.table); 1928 + 2110 1929 return 0; 2111 1930 2112 1931 create_fg_err: ··· 2126 1939 2127 1940 static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw) 2128 1941 { 1942 + mutex_destroy(&esw->fdb_table.offloads.vports.lock); 2129 1943 esw_destroy_vport_rx_group(esw); 2130 1944 esw_destroy_offloads_table(esw); 2131 1945 esw_destroy_offloads_fdb_tables(esw);
+10 -10
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.c
··· 21 21 #define fdb_ignore_flow_level_supported(esw) \ 22 22 (MLX5_CAP_ESW_FLOWTABLE_FDB((esw)->dev, ignore_flow_level)) 23 23 24 - #define ESW_OFFLOADS_NUM_GROUPS 4 25 - 26 24 /* Firmware currently has 4 pool of 4 sizes that it supports (ESW_POOLS), 27 25 * and a virtual memory region of 16M (ESW_SIZE), this region is duplicated 28 26 * for each flow table pool. We can allocate up to 16M of each pool, ··· 95 97 bool mlx5_esw_chains_prios_supported(struct mlx5_eswitch *esw) 96 98 { 97 99 return esw->fdb_table.flags & ESW_FDB_CHAINS_AND_PRIOS_SUPPORTED; 100 + } 101 + 102 + bool mlx5_esw_chains_backwards_supported(struct mlx5_eswitch *esw) 103 + { 104 + return fdb_ignore_flow_level_supported(esw); 98 105 } 99 106 100 107 u32 mlx5_esw_chains_get_chain_range(struct mlx5_eswitch *esw) ··· 237 234 } 238 235 239 236 ft_attr.autogroup.num_reserved_entries = 2; 240 - ft_attr.autogroup.max_num_groups = ESW_OFFLOADS_NUM_GROUPS; 237 + ft_attr.autogroup.max_num_groups = esw->params.large_group_num; 241 238 fdb = mlx5_create_auto_grouped_flow_table(ns, &ft_attr); 242 239 if (IS_ERR(fdb)) { 243 240 esw_warn(esw->dev, ··· 640 637 641 638 esw_debug(dev, 642 639 "Init esw offloads chains, max counters(%d), groups(%d), max flow table size(%d)\n", 643 - max_flow_counter, ESW_OFFLOADS_NUM_GROUPS, fdb_max); 640 + max_flow_counter, esw->params.large_group_num, fdb_max); 644 641 645 642 mlx5_esw_chains_init_sz_pool(esw); 646 643 ··· 707 704 708 705 /* Open level 1 for split rules now if prios isn't supported */ 709 706 if (!mlx5_esw_chains_prios_supported(esw)) { 710 - ft = mlx5_esw_chains_get_table(esw, 0, 1, 1); 711 - 712 - if (IS_ERR(ft)) { 713 - err = PTR_ERR(ft); 707 + err = mlx5_esw_vport_tbl_get(esw); 708 + if (err) 714 709 goto level_1_err; 715 - } 716 710 } 717 711 718 712 return 0; ··· 725 725 mlx5_esw_chains_close(struct mlx5_eswitch *esw) 726 726 { 727 727 if (!mlx5_esw_chains_prios_supported(esw)) 728 - mlx5_esw_chains_put_table(esw, 0, 1, 1); 728 + mlx5_esw_vport_tbl_put(esw); 729 729 mlx5_esw_chains_put_table(esw, 0, 1, 0); 730 730 mlx5_esw_chains_put_table(esw, mlx5_esw_chains_get_ft_chain(esw), 1, 0); 731 731 }
+2
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_chains.h
··· 6 6 7 7 bool 8 8 mlx5_esw_chains_prios_supported(struct mlx5_eswitch *esw); 9 + bool 10 + mlx5_esw_chains_backwards_supported(struct mlx5_eswitch *esw); 9 11 u32 10 12 mlx5_esw_chains_get_prio_range(struct mlx5_eswitch *esw); 11 13 u32
+2 -2
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c
··· 181 181 static bool mlx5_eswitch_offload_is_uplink_port(const struct mlx5_eswitch *esw, 182 182 const struct mlx5_flow_spec *spec) 183 183 { 184 - u32 port_mask, port_value; 184 + u16 port_mask, port_value; 185 185 186 186 if (MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source)) 187 187 return spec->flow_context.flow_source == ··· 191 191 misc_parameters.source_port); 192 192 port_value = MLX5_GET(fte_match_param, spec->match_value, 193 193 misc_parameters.source_port); 194 - return (port_mask & port_value & 0xffff) == MLX5_VPORT_UPLINK; 194 + return (port_mask & port_value) == MLX5_VPORT_UPLINK; 195 195 } 196 196 197 197 bool
+11
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
··· 2700 2700 goto out_err; 2701 2701 } 2702 2702 2703 + /* We put this priority last, knowing that nothing will get here 2704 + * unless explicitly forwarded to. This is possible because the 2705 + * slow path tables have catch all rules and nothing gets passed 2706 + * those tables. 2707 + */ 2708 + maj_prio = fs_create_prio(&steering->fdb_root_ns->ns, FDB_PER_VPORT, 1); 2709 + if (IS_ERR(maj_prio)) { 2710 + err = PTR_ERR(maj_prio); 2711 + goto out_err; 2712 + } 2713 + 2703 2714 set_prio_attrs(steering->fdb_root_ns); 2704 2715 return 0; 2705 2716
+5 -5
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
··· 672 672 dest_action = action; 673 673 if (!action->dest_tbl.is_fw_tbl) { 674 674 if (action->dest_tbl.tbl->dmn != dmn) { 675 - mlx5dr_dbg(dmn, 675 + mlx5dr_err(dmn, 676 676 "Destination table belongs to a different domain\n"); 677 677 goto out_invalid_arg; 678 678 } ··· 703 703 action->dest_tbl.fw_tbl.rx_icm_addr = 704 704 output.sw_owner_icm_root_0; 705 705 } else { 706 - mlx5dr_dbg(dmn, 706 + mlx5dr_err(dmn, 707 707 "Failed mlx5_cmd_query_flow_table ret: %d\n", 708 708 ret); 709 709 return ret; ··· 772 772 773 773 /* Check action duplication */ 774 774 if (++action_type_set[action_type] > max_actions_type) { 775 - mlx5dr_dbg(dmn, "Action type %d supports only max %d time(s)\n", 775 + mlx5dr_err(dmn, "Action type %d supports only max %d time(s)\n", 776 776 action_type, max_actions_type); 777 777 goto out_invalid_arg; 778 778 } ··· 781 781 if (dr_action_validate_and_get_next_state(action_domain, 782 782 action_type, 783 783 &state)) { 784 - mlx5dr_dbg(dmn, "Invalid action sequence provided\n"); 784 + mlx5dr_err(dmn, "Invalid action sequence provided\n"); 785 785 return -EOPNOTSUPP; 786 786 } 787 787 } ··· 797 797 rx_rule && recalc_cs_required && dest_action) { 798 798 ret = dr_action_handle_cs_recalc(dmn, dest_action, &attr.final_icm_addr); 799 799 if (ret) { 800 - mlx5dr_dbg(dmn, 800 + mlx5dr_err(dmn, 801 801 "Failed to handle checksum recalculation err %d\n", 802 802 ret); 803 803 return ret;
+10 -7
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
··· 59 59 60 60 ret = mlx5_core_alloc_pd(dmn->mdev, &dmn->pdn); 61 61 if (ret) { 62 - mlx5dr_dbg(dmn, "Couldn't allocate PD\n"); 62 + mlx5dr_err(dmn, "Couldn't allocate PD, ret: %d", ret); 63 63 return ret; 64 64 } 65 65 ··· 192 192 193 193 ret = dr_domain_query_vports(dmn); 194 194 if (ret) { 195 - mlx5dr_dbg(dmn, "Failed to query vports caps\n"); 195 + mlx5dr_err(dmn, "Failed to query vports caps (err: %d)", ret); 196 196 goto free_vports_caps; 197 197 } 198 198 ··· 213 213 int ret; 214 214 215 215 if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) { 216 - mlx5dr_dbg(dmn, "Failed to allocate domain, bad link type\n"); 216 + mlx5dr_err(dmn, "Failed to allocate domain, bad link type\n"); 217 217 return -EOPNOTSUPP; 218 218 } 219 219 ··· 257 257 dmn->info.tx.ste_type = MLX5DR_STE_TYPE_TX; 258 258 vport_cap = mlx5dr_get_vport_cap(&dmn->info.caps, 0); 259 259 if (!vport_cap) { 260 - mlx5dr_dbg(dmn, "Failed to get esw manager vport\n"); 260 + mlx5dr_err(dmn, "Failed to get esw manager vport\n"); 261 261 return -ENOENT; 262 262 } 263 263 ··· 268 268 dmn->info.tx.drop_icm_addr = dmn->info.caps.esw_tx_drop_address; 269 269 break; 270 270 default: 271 - mlx5dr_dbg(dmn, "Invalid domain\n"); 271 + mlx5dr_err(dmn, "Invalid domain\n"); 272 272 ret = -EINVAL; 273 273 break; 274 274 } ··· 300 300 mutex_init(&dmn->mutex); 301 301 302 302 if (dr_domain_caps_init(mdev, dmn)) { 303 - mlx5dr_dbg(dmn, "Failed init domain, no caps\n"); 303 + mlx5dr_err(dmn, "Failed init domain, no caps\n"); 304 304 goto free_domain; 305 305 } 306 306 ··· 348 348 mutex_lock(&dmn->mutex); 349 349 ret = mlx5dr_send_ring_force_drain(dmn); 350 350 mutex_unlock(&dmn->mutex); 351 - if (ret) 351 + if (ret) { 352 + mlx5dr_err(dmn, "Force drain failed flags: %d, ret: %d\n", 353 + flags, ret); 352 354 return ret; 355 + } 353 356 } 354 357 355 358 if (flags & MLX5DR_DOMAIN_SYNC_FLAGS_HW)
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_icm_pool.c
··· 468 468 err = mlx5dr_cmd_sync_steering(pool->dmn->mdev); 469 469 if (err) { 470 470 dr_icm_chill_buckets_abort(pool, bucket, buckets); 471 - mlx5dr_dbg(pool->dmn, "Sync_steering failed\n"); 471 + mlx5dr_err(pool->dmn, "Sync_steering failed\n"); 472 472 chunk = NULL; 473 473 goto out; 474 474 }
+6 -6
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_matcher.c
··· 388 388 mlx5dr_ste_build_empty_always_hit(&sb[idx++], rx); 389 389 390 390 if (idx == 0) { 391 - mlx5dr_dbg(dmn, "Cannot generate any valid rules from mask\n"); 391 + mlx5dr_err(dmn, "Cannot generate any valid rules from mask\n"); 392 392 return -EINVAL; 393 393 } 394 394 395 395 /* Check that all mask fields were consumed */ 396 396 for (i = 0; i < sizeof(struct mlx5dr_match_param); i++) { 397 397 if (((u8 *)&mask)[i] != 0) { 398 - mlx5dr_info(dmn, "Mask contains unsupported parameters\n"); 398 + mlx5dr_err(dmn, "Mask contains unsupported parameters\n"); 399 399 return -EOPNOTSUPP; 400 400 } 401 401 } ··· 563 563 dr_matcher_set_ste_builders(matcher, nic_matcher, DR_RULE_IPV6, DR_RULE_IPV6); 564 564 565 565 if (!nic_matcher->ste_builder) { 566 - mlx5dr_dbg(dmn, "Cannot generate IPv4 or IPv6 rules with given mask\n"); 566 + mlx5dr_err(dmn, "Cannot generate IPv4 or IPv6 rules with given mask\n"); 567 567 return -EINVAL; 568 568 } 569 569 ··· 634 634 int ret; 635 635 636 636 if (matcher->match_criteria >= DR_MATCHER_CRITERIA_MAX) { 637 - mlx5dr_info(dmn, "Invalid match criteria attribute\n"); 637 + mlx5dr_err(dmn, "Invalid match criteria attribute\n"); 638 638 return -EINVAL; 639 639 } 640 640 641 641 if (mask) { 642 642 if (mask->match_sz > sizeof(struct mlx5dr_match_param)) { 643 - mlx5dr_info(dmn, "Invalid match size attribute\n"); 643 + mlx5dr_err(dmn, "Invalid match size attribute\n"); 644 644 return -EINVAL; 645 645 } 646 646 mlx5dr_ste_copy_param(matcher->match_criteria, ··· 671 671 672 672 struct mlx5dr_matcher * 673 673 mlx5dr_matcher_create(struct mlx5dr_table *tbl, 674 - u16 priority, 674 + u32 priority, 675 675 u8 match_criteria_enable, 676 676 struct mlx5dr_match_parameters *mask) 677 677 {
+9 -9
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c
··· 826 826 ste_location, send_ste_list); 827 827 if (!new_htbl) { 828 828 mlx5dr_htbl_put(cur_htbl); 829 - mlx5dr_info(dmn, "failed creating rehash table, htbl-log_size: %d\n", 830 - cur_htbl->chunk_size); 829 + mlx5dr_err(dmn, "Failed creating rehash table, htbl-log_size: %d\n", 830 + cur_htbl->chunk_size); 831 831 } else { 832 832 cur_htbl = new_htbl; 833 833 } ··· 877 877 if (!value_size || 878 878 (value_size > sizeof(struct mlx5dr_match_param) || 879 879 (value_size % sizeof(u32)))) { 880 - mlx5dr_dbg(matcher->tbl->dmn, "Rule parameters length is incorrect\n"); 880 + mlx5dr_err(matcher->tbl->dmn, "Rule parameters length is incorrect\n"); 881 881 return false; 882 882 } 883 883 ··· 888 888 e_idx = min(s_idx + sizeof(param->outer), value_size); 889 889 890 890 if (!dr_rule_cmp_value_to_mask(mask_p, param_p, s_idx, e_idx)) { 891 - mlx5dr_dbg(matcher->tbl->dmn, "Rule outer parameters contains a value not specified by mask\n"); 891 + mlx5dr_err(matcher->tbl->dmn, "Rule outer parameters contains a value not specified by mask\n"); 892 892 return false; 893 893 } 894 894 } ··· 898 898 e_idx = min(s_idx + sizeof(param->misc), value_size); 899 899 900 900 if (!dr_rule_cmp_value_to_mask(mask_p, param_p, s_idx, e_idx)) { 901 - mlx5dr_dbg(matcher->tbl->dmn, "Rule misc parameters contains a value not specified by mask\n"); 901 + mlx5dr_err(matcher->tbl->dmn, "Rule misc parameters contains a value not specified by mask\n"); 902 902 return false; 903 903 } 904 904 } ··· 908 908 e_idx = min(s_idx + sizeof(param->inner), value_size); 909 909 910 910 if (!dr_rule_cmp_value_to_mask(mask_p, param_p, s_idx, e_idx)) { 911 - mlx5dr_dbg(matcher->tbl->dmn, "Rule inner parameters contains a value not specified by mask\n"); 911 + mlx5dr_err(matcher->tbl->dmn, "Rule inner parameters contains a value not specified by mask\n"); 912 912 return false; 913 913 } 914 914 } ··· 918 918 e_idx = min(s_idx + sizeof(param->misc2), value_size); 919 919 920 920 if (!dr_rule_cmp_value_to_mask(mask_p, param_p, s_idx, e_idx)) { 921 - mlx5dr_dbg(matcher->tbl->dmn, "Rule misc2 parameters contains a value not specified by mask\n"); 921 + mlx5dr_err(matcher->tbl->dmn, "Rule misc2 parameters contains a value not specified by mask\n"); 922 922 return false; 923 923 } 924 924 } ··· 928 928 e_idx = min(s_idx + sizeof(param->misc3), value_size); 929 929 930 930 if (!dr_rule_cmp_value_to_mask(mask_p, param_p, s_idx, e_idx)) { 931 - mlx5dr_dbg(matcher->tbl->dmn, "Rule misc3 parameters contains a value not specified by mask\n"); 931 + mlx5dr_err(matcher->tbl->dmn, "Rule misc3 parameters contains a value not specified by mask\n"); 932 932 return false; 933 933 } 934 934 } ··· 1221 1221 dr_rule_remove_action_members(rule); 1222 1222 free_rule: 1223 1223 kfree(rule); 1224 - mlx5dr_info(dmn, "Failed creating rule\n"); 1224 + mlx5dr_err(dmn, "Failed creating rule\n"); 1225 1225 return NULL; 1226 1226 } 1227 1227
+12 -4
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c
··· 136 136 err = mlx5_wq_qp_create(mdev, &wqp, temp_qpc, &dr_qp->wq, 137 137 &dr_qp->wq_ctrl); 138 138 if (err) { 139 - mlx5_core_info(mdev, "Can't create QP WQ\n"); 139 + mlx5_core_warn(mdev, "Can't create QP WQ\n"); 140 140 goto err_wq; 141 141 } 142 142 ··· 651 651 652 652 /* Init */ 653 653 ret = dr_modify_qp_rst2init(dmn->mdev, dr_qp, port); 654 - if (ret) 654 + if (ret) { 655 + mlx5dr_err(dmn, "Failed modify QP rst2init\n"); 655 656 return ret; 657 + } 656 658 657 659 /* RTR */ 658 660 ret = mlx5dr_cmd_query_gid(dmn->mdev, port, gid_index, &rtr_attr.dgid_attr); ··· 669 667 rtr_attr.udp_src_port = dmn->info.caps.roce_min_src_udp; 670 668 671 669 ret = dr_cmd_modify_qp_init2rtr(dmn->mdev, dr_qp, &rtr_attr); 672 - if (ret) 670 + if (ret) { 671 + mlx5dr_err(dmn, "Failed modify QP init2rtr\n"); 673 672 return ret; 673 + } 674 674 675 675 /* RTS */ 676 676 rts_attr.timeout = 14; ··· 680 676 rts_attr.rnr_retry = 7; 681 677 682 678 ret = dr_cmd_modify_qp_rtr2rts(dmn->mdev, dr_qp, &rts_attr); 683 - if (ret) 679 + if (ret) { 680 + mlx5dr_err(dmn, "Failed modify QP rtr2rts\n"); 684 681 return ret; 682 + } 685 683 686 684 return 0; 687 685 } ··· 867 861 cq_size = QUEUE_SIZE + 1; 868 862 dmn->send_ring->cq = dr_create_cq(dmn->mdev, dmn->uar, cq_size); 869 863 if (!dmn->send_ring->cq) { 864 + mlx5dr_err(dmn, "Failed creating CQ\n"); 870 865 ret = -ENOMEM; 871 866 goto free_send_ring; 872 867 } ··· 879 872 880 873 dmn->send_ring->qp = dr_create_rc_qp(dmn->mdev, &init_attr); 881 874 if (!dmn->send_ring->qp) { 875 + mlx5dr_err(dmn, "Failed creating QP\n"); 882 876 ret = -ENOMEM; 883 877 goto clean_cq; 884 878 }
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c
··· 728 728 { 729 729 if (!value && (match_criteria & DR_MATCHER_CRITERIA_MISC)) { 730 730 if (mask->misc.source_port && mask->misc.source_port != 0xffff) { 731 - mlx5dr_dbg(dmn, "Partial mask source_port is not supported\n"); 731 + mlx5dr_err(dmn, "Partial mask source_port is not supported\n"); 732 732 return -EINVAL; 733 733 } 734 734 }
+6 -2
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_table.c
··· 128 128 DR_CHUNK_SIZE_1, 129 129 MLX5DR_STE_LU_TYPE_DONT_CARE, 130 130 0); 131 - if (!nic_tbl->s_anchor) 131 + if (!nic_tbl->s_anchor) { 132 + mlx5dr_err(dmn, "Failed allocating htbl\n"); 132 133 return -ENOMEM; 134 + } 133 135 134 136 info.type = CONNECT_MISS; 135 137 info.miss_icm_addr = nic_dmn->default_icm_addr; 136 138 ret = mlx5dr_ste_htbl_init_and_postsend(dmn, nic_dmn, 137 139 nic_tbl->s_anchor, 138 140 &info, true); 139 - if (ret) 141 + if (ret) { 142 + mlx5dr_err(dmn, "Failed int and send htbl\n"); 140 143 goto free_s_anchor; 144 + } 141 145 142 146 mlx5dr_htbl_get(nic_tbl->s_anchor); 143 147
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
··· 705 705 struct mlx5dr_matcher_rx_tx rx; 706 706 struct mlx5dr_matcher_rx_tx tx; 707 707 struct list_head matcher_list; 708 - u16 prio; 708 + u32 prio; 709 709 struct mlx5dr_match_param mask; 710 710 u8 match_criteria; 711 711 refcount_t refcount;
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
··· 140 140 struct mlx5_flow_group *fg) 141 141 { 142 142 struct mlx5dr_matcher *matcher; 143 - u16 priority = MLX5_GET(create_flow_group_in, in, 143 + u32 priority = MLX5_GET(create_flow_group_in, in, 144 144 start_flow_index); 145 145 u8 match_criteria_enable = MLX5_GET(create_flow_group_in, 146 146 in,
+2 -2
drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
··· 59 59 60 60 struct mlx5dr_matcher * 61 61 mlx5dr_matcher_create(struct mlx5dr_table *table, 62 - u16 priority, 62 + u32 priority, 63 63 u8 match_criteria_enable, 64 64 struct mlx5dr_match_parameters *mask); 65 65 ··· 151 151 152 152 static inline struct mlx5dr_matcher * 153 153 mlx5dr_matcher_create(struct mlx5dr_table *table, 154 - u16 priority, 154 + u32 priority, 155 155 u8 match_criteria_enable, 156 156 struct mlx5dr_match_parameters *mask) { return NULL; } 157 157
+1
include/linux/mlx5/fs.h
··· 84 84 FDB_TC_OFFLOAD, 85 85 FDB_FT_OFFLOAD, 86 86 FDB_SLOW_PATH, 87 + FDB_PER_VPORT, 87 88 }; 88 89 89 90 struct mlx5_pkt_reformat;