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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'mlx5-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux

Tariq Toukan says:

====================
mlx5-next updates 2026-03-17

The following pull-request contains common mlx5 updates

* 'mlx5-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux:
net/mlx5: Expose MLX5_UMR_ALIGN definition
{net/RDMA}/mlx5: Add LAG demux table API and vport demux rules
net/mlx5: Add VHCA RX flow destination support for FW steering
net/mlx5: LAG, replace mlx5_get_dev_index with LAG sequence number
net/mlx5: E-switch, modify peer miss rule index to vhca_id
net/mlx5: LAG, use xa_alloc to manage LAG device indices
net/mlx5: LAG, replace pf array with xarray
net/mlx5: Add silent mode set/query and VHCA RX IFC bits
net/mlx5: Add IFC bits for shared headroom pool PBMC support
net/mlx5: Expose TLP emulation capabilities
net/mlx5: Add TLP emulation device capabilities
====================

Link: https://patch.msgid.link/20260317075844.12066-1-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+898 -219
+20 -4
drivers/infiniband/hw/mlx5/ib_rep.c
··· 3 3 * Copyright (c) 2018 Mellanox Technologies. All rights reserved. 4 4 */ 5 5 6 + #include <linux/mlx5/lag.h> 6 7 #include <linux/mlx5/vport.h> 7 8 #include "ib_rep.h" 8 9 #include "srq.h" 9 10 10 11 static int 11 12 mlx5_ib_set_vport_rep(struct mlx5_core_dev *dev, 13 + struct mlx5_core_dev *rep_dev, 12 14 struct mlx5_eswitch_rep *rep, 13 15 int vport_index) 14 16 { 15 17 struct mlx5_ib_dev *ibdev; 16 18 struct net_device *ndev; 19 + int ret; 17 20 18 21 ibdev = mlx5_eswitch_uplink_get_proto_dev(dev->priv.eswitch, REP_IB); 19 22 if (!ibdev) ··· 26 23 rep->rep_data[REP_IB].priv = ibdev; 27 24 ndev = mlx5_ib_get_rep_netdev(rep->esw, rep->vport); 28 25 29 - return ib_device_set_netdev(&ibdev->ib_dev, ndev, vport_index + 1); 26 + ret = ib_device_set_netdev(&ibdev->ib_dev, ndev, vport_index + 1); 27 + if (ret) 28 + return ret; 29 + 30 + /* Only Vports that are not native to the LAG master eswitch need to add 31 + * demux rule. 32 + */ 33 + if (mlx5_eswitch_get_total_vports(dev) > vport_index) 34 + return 0; 35 + 36 + return mlx5_lag_demux_rule_add(rep_dev, rep->vport, vport_index); 30 37 } 31 38 32 39 static void mlx5_ib_register_peer_vport_reps(struct mlx5_core_dev *mdev); ··· 143 130 144 131 if (mlx5_lag_is_master(peer_dev)) 145 132 lag_master = peer_dev; 146 - else if (!mlx5_lag_is_mpesw(dev)) 133 + else if (!mlx5_lag_is_mpesw(peer_dev)) 147 134 /* Only 1 ib port is the representor for all uplinks */ 148 135 peer_n_ports--; 149 136 150 - if (mlx5_get_dev_index(peer_dev) < mlx5_get_dev_index(dev)) 137 + if (mlx5_lag_get_dev_seq(peer_dev) < 138 + mlx5_lag_get_dev_seq(dev)) 151 139 vport_index += peer_n_ports; 152 140 } 153 141 } ··· 157 143 if (rep->vport == MLX5_VPORT_UPLINK && !new_uplink) 158 144 profile = &raw_eth_profile; 159 145 else 160 - return mlx5_ib_set_vport_rep(lag_master, rep, vport_index); 146 + return mlx5_ib_set_vport_rep(lag_master, dev, rep, vport_index); 161 147 162 148 if (mlx5_lag_is_shared_fdb(dev)) { 163 149 ret = mlx5_ib_take_transport(lag_master); ··· 244 230 return; 245 231 vport_index = i; 246 232 } 233 + 234 + mlx5_lag_demux_rule_del(mdev, vport_index); 247 235 248 236 port = &dev->port[vport_index]; 249 237
+11 -10
drivers/infiniband/hw/mlx5/main.c
··· 26 26 #include <linux/mlx5/fs.h> 27 27 #include <linux/mlx5/eswitch.h> 28 28 #include <linux/mlx5/driver.h> 29 + #include <linux/mlx5/lag.h> 29 30 #include <linux/list.h> 30 31 #include <rdma/ib_smi.h> 31 32 #include <rdma/ib_umem_odp.h> ··· 3679 3678 3680 3679 static int mlx5_eth_lag_init(struct mlx5_ib_dev *dev) 3681 3680 { 3681 + struct mlx5_flow_table_attr ft_attr = {}; 3682 3682 struct mlx5_core_dev *mdev = dev->mdev; 3683 - struct mlx5_flow_namespace *ns = mlx5_get_flow_namespace(mdev, 3684 - MLX5_FLOW_NAMESPACE_LAG); 3685 - struct mlx5_flow_table *ft; 3683 + struct mlx5_flow_namespace *ns; 3686 3684 int err; 3687 3685 3686 + ns = mlx5_get_flow_namespace(mdev, MLX5_FLOW_NAMESPACE_LAG); 3688 3687 if (!ns || !mlx5_lag_is_active(mdev)) 3689 3688 return 0; 3690 3689 ··· 3692 3691 if (err) 3693 3692 return err; 3694 3693 3695 - ft = mlx5_create_lag_demux_flow_table(ns, 0, 0); 3696 - if (IS_ERR(ft)) { 3697 - err = PTR_ERR(ft); 3694 + ft_attr.level = 0; 3695 + ft_attr.prio = 0; 3696 + ft_attr.max_fte = dev->num_ports; 3697 + 3698 + err = mlx5_lag_demux_init(mdev, &ft_attr); 3699 + if (err) 3698 3700 goto err_destroy_vport_lag; 3699 - } 3700 3701 3701 3702 mlx5e_lag_event_register(dev); 3702 - dev->flow_db->lag_demux_ft = ft; 3703 3703 dev->lag_ports = mlx5_lag_get_num_ports(mdev); 3704 3704 dev->lag_active = true; 3705 3705 return 0; ··· 3718 3716 dev->lag_active = false; 3719 3717 3720 3718 mlx5e_lag_event_unregister(dev); 3721 - mlx5_destroy_flow_table(dev->flow_db->lag_demux_ft); 3722 - dev->flow_db->lag_demux_ft = NULL; 3719 + mlx5_lag_demux_cleanup(mdev); 3723 3720 3724 3721 mlx5_cmd_destroy_vport_lag(mdev); 3725 3722 }
-1
drivers/infiniband/hw/mlx5/mlx5_ib.h
··· 306 306 struct mlx5_ib_flow_prio rdma_rx[MLX5_IB_NUM_FLOW_FT]; 307 307 struct mlx5_ib_flow_prio rdma_tx[MLX5_IB_NUM_FLOW_FT]; 308 308 struct mlx5_ib_flow_prio opfcs[MLX5_IB_OPCOUNTER_MAX]; 309 - struct mlx5_flow_table *lag_demux_ft; 310 309 struct mlx5_ib_flow_prio *rdma_transport_rx[MLX5_RDMA_TRANSPORT_BYPASS_PRIO]; 311 310 struct mlx5_ib_flow_prio *rdma_transport_tx[MLX5_RDMA_TRANSPORT_BYPASS_PRIO]; 312 311 /* Protect flow steering bypass flow tables
-1
drivers/infiniband/hw/mlx5/mr.c
··· 51 51 }; 52 52 53 53 #define MLX5_MR_CACHE_PERSISTENT_ENTRY_MIN_DESCS 4 54 - #define MLX5_UMR_ALIGN 2048 55 54 56 55 static void 57 56 create_mkey_callback(int status, struct mlx5_async_work *context);
+3
drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.c
··· 282 282 case MLX5_FLOW_DESTINATION_TYPE_NONE: 283 283 trace_seq_printf(p, "none\n"); 284 284 break; 285 + case MLX5_FLOW_DESTINATION_TYPE_VHCA_RX: 286 + trace_seq_printf(p, "rx_vhca_id=%u\n", dst->vhca.id); 287 + break; 285 288 } 286 289 287 290 trace_seq_putc(p, 0);
+5 -4
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
··· 35 35 #include <net/sch_generic.h> 36 36 #include <net/pkt_cls.h> 37 37 #include <linux/mlx5/fs.h> 38 + #include <linux/mlx5/lag.h> 38 39 #include <linux/mlx5/device.h> 39 40 #include <linux/rhashtable.h> 40 41 #include <linux/refcount.h> ··· 2132 2131 mutex_unlock(&esw->offloads.peer_mutex); 2133 2132 2134 2133 list_for_each_entry_safe(peer_flow, tmp, &flow->peer_flows, peer_flows) { 2135 - if (peer_index != mlx5_get_dev_index(peer_flow->priv->mdev)) 2134 + if (peer_index != mlx5_lag_get_dev_seq(peer_flow->priv->mdev)) 2136 2135 continue; 2137 2136 2138 2137 list_del(&peer_flow->peer_flows); ··· 2155 2154 2156 2155 devcom = flow->priv->mdev->priv.eswitch->devcom; 2157 2156 mlx5_devcom_for_each_peer_entry(devcom, peer_esw, pos) { 2158 - i = mlx5_get_dev_index(peer_esw->dev); 2157 + i = mlx5_lag_get_dev_seq(peer_esw->dev); 2159 2158 mlx5e_tc_del_fdb_peer_flow(flow, i); 2160 2159 } 2161 2160 } ··· 4585 4584 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; 4586 4585 struct mlx5_esw_flow_attr *attr = flow->attr->esw_attr; 4587 4586 struct mlx5e_tc_flow_parse_attr *parse_attr; 4588 - int i = mlx5_get_dev_index(peer_esw->dev); 4587 + int i = mlx5_lag_get_dev_seq(peer_esw->dev); 4589 4588 struct mlx5e_rep_priv *peer_urpriv; 4590 4589 struct mlx5e_tc_flow *peer_flow; 4591 4590 struct mlx5_core_dev *in_mdev; ··· 5526 5525 devcom = esw->devcom; 5527 5526 5528 5527 mlx5_devcom_for_each_peer_entry(devcom, peer_esw, pos) { 5529 - i = mlx5_get_dev_index(peer_esw->dev); 5528 + i = mlx5_lag_get_dev_seq(peer_esw->dev); 5530 5529 list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows[i], peer[i]) 5531 5530 mlx5e_tc_del_fdb_peers_flow(flow); 5532 5531 }
+13 -1
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
··· 273 273 struct mlx5_flow_group *send_to_vport_grp; 274 274 struct mlx5_flow_group *send_to_vport_meta_grp; 275 275 struct mlx5_flow_group *peer_miss_grp; 276 - struct mlx5_flow_handle **peer_miss_rules[MLX5_MAX_PORTS]; 276 + struct xarray peer_miss_rules; 277 277 struct mlx5_flow_group *miss_grp; 278 278 struct mlx5_flow_handle **send_to_vport_meta_rules; 279 279 struct mlx5_flow_handle *miss_rule_uni; ··· 942 942 u16 vport_num); 943 943 bool mlx5_esw_host_functions_enabled(const struct mlx5_core_dev *dev); 944 944 void mlx5_eswitch_safe_aux_devs_remove(struct mlx5_core_dev *dev); 945 + struct mlx5_flow_group * 946 + mlx5_esw_lag_demux_fg_create(struct mlx5_eswitch *esw, 947 + struct mlx5_flow_table *ft); 948 + struct mlx5_flow_handle * 949 + mlx5_esw_lag_demux_rule_create(struct mlx5_eswitch *esw, u16 vport_num, 950 + struct mlx5_flow_table *lag_ft); 945 951 #else /* CONFIG_MLX5_ESWITCH */ 946 952 /* eswitch API stubs */ 947 953 static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } ··· 1033 1027 1034 1028 static inline void 1035 1029 mlx5_eswitch_safe_aux_devs_remove(struct mlx5_core_dev *dev) {} 1030 + static inline struct mlx5_flow_handle * 1031 + mlx5_esw_lag_demux_rule_create(struct mlx5_eswitch *esw, u16 vport_num, 1032 + struct mlx5_flow_table *lag_ft) 1033 + { 1034 + return ERR_PTR(-EOPNOTSUPP); 1035 + } 1036 1036 1037 1037 #endif /* CONFIG_MLX5_ESWITCH */ 1038 1038
+90 -13
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
··· 1190 1190 struct mlx5_flow_handle *flow; 1191 1191 struct mlx5_vport *peer_vport; 1192 1192 struct mlx5_flow_spec *spec; 1193 - int err, pfindex; 1193 + int err; 1194 1194 unsigned long i; 1195 1195 void *misc; 1196 1196 ··· 1270 1270 } 1271 1271 } 1272 1272 1273 - pfindex = mlx5_get_dev_index(peer_dev); 1274 - if (pfindex >= MLX5_MAX_PORTS) { 1275 - esw_warn(esw->dev, "Peer dev index(%d) is over the max num defined(%d)\n", 1276 - pfindex, MLX5_MAX_PORTS); 1277 - err = -EINVAL; 1273 + err = xa_insert(&esw->fdb_table.offloads.peer_miss_rules, 1274 + MLX5_CAP_GEN(peer_dev, vhca_id), flows, GFP_KERNEL); 1275 + if (err) 1278 1276 goto add_ec_vf_flow_err; 1279 - } 1280 - esw->fdb_table.offloads.peer_miss_rules[pfindex] = flows; 1281 1277 1282 1278 kvfree(spec); 1283 1279 return 0; ··· 1315 1319 struct mlx5_core_dev *peer_dev) 1316 1320 { 1317 1321 struct mlx5_eswitch *peer_esw = peer_dev->priv.eswitch; 1318 - u16 peer_index = mlx5_get_dev_index(peer_dev); 1322 + u16 peer_vhca_id = MLX5_CAP_GEN(peer_dev, vhca_id); 1319 1323 struct mlx5_flow_handle **flows; 1320 1324 struct mlx5_vport *peer_vport; 1321 1325 unsigned long i; 1322 1326 1323 - flows = esw->fdb_table.offloads.peer_miss_rules[peer_index]; 1327 + flows = xa_erase(&esw->fdb_table.offloads.peer_miss_rules, 1328 + peer_vhca_id); 1324 1329 if (!flows) 1325 1330 return; 1326 1331 ··· 1347 1350 } 1348 1351 1349 1352 kvfree(flows); 1350 - esw->fdb_table.offloads.peer_miss_rules[peer_index] = NULL; 1351 1353 } 1352 1354 1353 1355 static int esw_add_fdb_miss_rule(struct mlx5_eswitch *esw) ··· 1454 1458 tag, (int)PTR_ERR(flow_rule)); 1455 1459 1456 1460 return flow_rule; 1461 + } 1462 + 1463 + struct mlx5_flow_group * 1464 + mlx5_esw_lag_demux_fg_create(struct mlx5_eswitch *esw, 1465 + struct mlx5_flow_table *ft) 1466 + { 1467 + int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); 1468 + struct mlx5_flow_group *fg; 1469 + void *match_criteria; 1470 + void *flow_group_in; 1471 + 1472 + if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) 1473 + return ERR_PTR(-EOPNOTSUPP); 1474 + 1475 + if (IS_ERR(ft)) 1476 + return ERR_CAST(ft); 1477 + 1478 + flow_group_in = kvzalloc(inlen, GFP_KERNEL); 1479 + if (!flow_group_in) 1480 + return ERR_PTR(-ENOMEM); 1481 + 1482 + match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, 1483 + match_criteria); 1484 + MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, 1485 + MLX5_MATCH_MISC_PARAMETERS_2); 1486 + MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0); 1487 + MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 1488 + ft->max_fte - 1); 1489 + 1490 + MLX5_SET(fte_match_param, match_criteria, 1491 + misc_parameters_2.metadata_reg_c_0, 1492 + mlx5_eswitch_get_vport_metadata_mask()); 1493 + 1494 + fg = mlx5_create_flow_group(ft, flow_group_in); 1495 + kvfree(flow_group_in); 1496 + if (IS_ERR(fg)) 1497 + esw_warn(esw->dev, "Can't create LAG demux flow group\n"); 1498 + 1499 + return fg; 1500 + } 1501 + 1502 + struct mlx5_flow_handle * 1503 + mlx5_esw_lag_demux_rule_create(struct mlx5_eswitch *esw, u16 vport_num, 1504 + struct mlx5_flow_table *lag_ft) 1505 + { 1506 + struct mlx5_flow_spec *spec = kvzalloc(sizeof(*spec), GFP_KERNEL); 1507 + struct mlx5_flow_destination dest = {}; 1508 + struct mlx5_flow_act flow_act = {}; 1509 + struct mlx5_flow_handle *ret; 1510 + void *misc; 1511 + 1512 + if (!spec) 1513 + return ERR_PTR(-ENOMEM); 1514 + 1515 + if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) { 1516 + kvfree(spec); 1517 + return ERR_PTR(-EOPNOTSUPP); 1518 + } 1519 + 1520 + misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, 1521 + misc_parameters_2); 1522 + MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, 1523 + mlx5_eswitch_get_vport_metadata_mask()); 1524 + spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2; 1525 + 1526 + misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, 1527 + misc_parameters_2); 1528 + MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, 1529 + mlx5_eswitch_get_vport_metadata_for_match(esw, vport_num)); 1530 + 1531 + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; 1532 + dest.type = MLX5_FLOW_DESTINATION_TYPE_VHCA_RX; 1533 + dest.vhca.id = MLX5_CAP_GEN(esw->dev, vhca_id); 1534 + 1535 + ret = mlx5_add_flow_rules(lag_ft, spec, &flow_act, &dest, 1); 1536 + kvfree(spec); 1537 + return ret; 1457 1538 } 1458 1539 1459 1540 #define MAX_PF_SQ 256 ··· 2121 2048 2122 2049 if (IS_ERR(g)) { 2123 2050 err = PTR_ERR(g); 2124 - mlx5_core_warn(esw->dev, "Failed to create vport rx group err %d\n", err); 2051 + esw_warn(esw->dev, "Failed to create vport rx group err %d\n", 2052 + err); 2125 2053 goto out; 2126 2054 } 2127 2055 ··· 2167 2093 2168 2094 if (IS_ERR(g)) { 2169 2095 err = PTR_ERR(g); 2170 - mlx5_core_warn(esw->dev, "Failed to create vport rx drop group err %d\n", err); 2096 + esw_warn(esw->dev, 2097 + "Failed to create vport rx drop group err %d\n", err); 2171 2098 goto out; 2172 2099 } 2173 2100 ··· 3322 3247 return; 3323 3248 3324 3249 xa_init(&esw->paired); 3250 + xa_init(&esw->fdb_table.offloads.peer_miss_rules); 3325 3251 esw->num_peers = 0; 3326 3252 esw->devcom = mlx5_devcom_register_component(esw->dev->priv.devc, 3327 3253 MLX5_DEVCOM_ESW_OFFLOADS, ··· 3350 3274 3351 3275 mlx5_devcom_unregister_component(esw->devcom); 3352 3276 xa_destroy(&esw->paired); 3277 + xa_destroy(&esw->fdb_table.offloads.peer_miss_rules); 3353 3278 esw->devcom = NULL; 3354 3279 } 3355 3280
+5 -1
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
··· 716 716 id = dst->dest_attr.ft->id; 717 717 ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_TABLE_TYPE; 718 718 break; 719 + case MLX5_FLOW_DESTINATION_TYPE_VHCA_RX: 720 + id = dst->dest_attr.vhca.id; 721 + ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_VHCA_RX; 722 + break; 719 723 default: 720 724 id = dst->dest_attr.tir_num; 721 725 ifc_type = MLX5_IFC_FLOW_DESTINATION_TYPE_TIR; ··· 1187 1183 { 1188 1184 u32 in[MLX5_ST_SZ_DW(set_l2_table_entry_in)] = {}; 1189 1185 1190 - if (silent_mode && !MLX5_CAP_GEN(dev, silent_mode)) 1186 + if (silent_mode && !MLX5_CAP_GEN(dev, silent_mode_set)) 1191 1187 return -EOPNOTSUPP; 1192 1188 1193 1189 MLX5_SET(set_l2_table_entry_in, in, opcode, MLX5_CMD_OP_SET_L2_TABLE_ENTRY);
+7 -10
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
··· 503 503 type == MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER || 504 504 type == MLX5_FLOW_DESTINATION_TYPE_TIR || 505 505 type == MLX5_FLOW_DESTINATION_TYPE_RANGE || 506 - type == MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE; 506 + type == MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE || 507 + type == MLX5_FLOW_DESTINATION_TYPE_VHCA_RX; 507 508 } 508 509 509 510 static bool check_valid_spec(const struct mlx5_flow_spec *spec) ··· 1438 1437 1439 1438 struct mlx5_flow_table* 1440 1439 mlx5_create_lag_demux_flow_table(struct mlx5_flow_namespace *ns, 1441 - int prio, u32 level) 1440 + struct mlx5_flow_table_attr *ft_attr) 1442 1441 { 1443 - struct mlx5_flow_table_attr ft_attr = {}; 1444 - 1445 - ft_attr.level = level; 1446 - ft_attr.prio = prio; 1447 - ft_attr.max_fte = 1; 1448 - 1449 - return __mlx5_create_flow_table(ns, &ft_attr, FS_FT_OP_MOD_LAG_DEMUX, 0); 1442 + return __mlx5_create_flow_table(ns, ft_attr, FS_FT_OP_MOD_LAG_DEMUX, 0); 1450 1443 } 1451 1444 EXPORT_SYMBOL(mlx5_create_lag_demux_flow_table); 1452 1445 ··· 1885 1890 d1->range.hit_ft == d2->range.hit_ft && 1886 1891 d1->range.miss_ft == d2->range.miss_ft && 1887 1892 d1->range.min == d2->range.min && 1888 - d1->range.max == d2->range.max)) 1893 + d1->range.max == d2->range.max) || 1894 + (d1->type == MLX5_FLOW_DESTINATION_TYPE_VHCA_RX && 1895 + d1->vhca.id == d2->vhca.id)) 1889 1896 return true; 1890 1897 } 1891 1898
+6
drivers/net/ethernet/mellanox/mlx5/core/fw.c
··· 255 255 return err; 256 256 } 257 257 258 + if (MLX5_CAP_GEN(dev, tlp_device_emulation_manager)) { 259 + err = mlx5_core_get_caps_mode(dev, MLX5_CAP_TLP_EMULATION, HCA_CAP_OPMOD_GET_CUR); 260 + if (err) 261 + return err; 262 + } 263 + 258 264 if (MLX5_CAP_GEN(dev, ipsec_offload)) { 259 265 err = mlx5_core_get_caps_mode(dev, MLX5_CAP_IPSEC, HCA_CAP_OPMOD_GET_CUR); 260 266 if (err)
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c
··· 145 145 ldev = mlx5_lag_dev(dev); 146 146 mutex_lock(&ldev->lock); 147 147 mlx5_ldev_for_each(i, 0, ldev) 148 - seq_printf(file, "%s\n", dev_name(ldev->pf[i].dev->device)); 148 + seq_printf(file, "%s\n", 149 + dev_name(mlx5_lag_pf(ldev, i)->dev->device)); 149 150 mutex_unlock(&ldev->lock); 150 151 151 152 return 0;
+572 -132
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
··· 35 35 #include <linux/mlx5/driver.h> 36 36 #include <linux/mlx5/eswitch.h> 37 37 #include <linux/mlx5/vport.h> 38 + #include <linux/mlx5/lag.h> 38 39 #include "lib/mlx5.h" 39 40 #include "lib/devcom.h" 40 41 #include "mlx5_core.h" ··· 233 232 static void mlx5_ldev_free(struct kref *ref) 234 233 { 235 234 struct mlx5_lag *ldev = container_of(ref, struct mlx5_lag, ref); 235 + struct lag_func *pf; 236 236 struct net *net; 237 237 int i; 238 238 ··· 243 241 } 244 242 245 243 mlx5_ldev_for_each(i, 0, ldev) { 246 - if (ldev->pf[i].dev && 247 - ldev->pf[i].port_change_nb.nb.notifier_call) { 248 - struct mlx5_nb *nb = &ldev->pf[i].port_change_nb; 244 + pf = mlx5_lag_pf(ldev, i); 245 + if (pf->port_change_nb.nb.notifier_call) { 246 + struct mlx5_nb *nb = &pf->port_change_nb; 249 247 250 - mlx5_eq_notifier_unregister(ldev->pf[i].dev, nb); 248 + mlx5_eq_notifier_unregister(pf->dev, nb); 251 249 } 250 + xa_erase(&ldev->pfs, i); 251 + kfree(pf); 252 252 } 253 + xa_destroy(&ldev->pfs); 253 254 254 255 mlx5_lag_mp_cleanup(ldev); 255 256 cancel_delayed_work_sync(&ldev->bond_work); ··· 289 284 290 285 kref_init(&ldev->ref); 291 286 mutex_init(&ldev->lock); 287 + xa_init_flags(&ldev->pfs, XA_FLAGS_ALLOC); 292 288 INIT_DELAYED_WORK(&ldev->bond_work, mlx5_do_bond_work); 293 289 INIT_WORK(&ldev->speed_update_work, mlx5_mpesw_speed_update_work); 294 290 ··· 315 309 int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev, 316 310 struct net_device *ndev) 317 311 { 312 + struct lag_func *pf; 318 313 int i; 319 314 320 - mlx5_ldev_for_each(i, 0, ldev) 321 - if (ldev->pf[i].netdev == ndev) 315 + mlx5_ldev_for_each(i, 0, ldev) { 316 + pf = mlx5_lag_pf(ldev, i); 317 + if (pf->netdev == ndev) 322 318 return i; 319 + } 323 320 324 321 return -ENOENT; 325 322 } 326 323 327 - int mlx5_lag_get_dev_index_by_seq(struct mlx5_lag *ldev, int seq) 324 + static int mlx5_lag_get_master_idx(struct mlx5_lag *ldev) 328 325 { 329 - int i, num = 0; 326 + unsigned long idx = 0; 327 + void *entry; 330 328 331 329 if (!ldev) 332 330 return -ENOENT; 333 331 332 + entry = xa_find(&ldev->pfs, &idx, U8_MAX, MLX5_LAG_XA_MARK_MASTER); 333 + if (!entry) 334 + return -ENOENT; 335 + 336 + return (int)idx; 337 + } 338 + 339 + int mlx5_lag_get_dev_index_by_seq(struct mlx5_lag *ldev, int seq) 340 + { 341 + int master_idx, i, num = 0; 342 + 343 + if (!ldev) 344 + return -ENOENT; 345 + 346 + master_idx = mlx5_lag_get_master_idx(ldev); 347 + 348 + /* If seq 0 is requested and there's a primary PF, return it */ 349 + if (master_idx >= 0) { 350 + if (seq == 0) 351 + return master_idx; 352 + num++; 353 + } 354 + 334 355 mlx5_ldev_for_each(i, 0, ldev) { 356 + /* Skip the primary PF in the loop */ 357 + if (i == master_idx) 358 + continue; 359 + 335 360 if (num == seq) 336 361 return i; 337 362 num++; 338 363 } 339 364 return -ENOENT; 365 + } 366 + 367 + /* Reverse of mlx5_lag_get_dev_index_by_seq: given a device, return its 368 + * sequence number in the LAG. Master is always 0, others numbered 369 + * sequentially starting from 1. 370 + */ 371 + int mlx5_lag_get_dev_seq(struct mlx5_core_dev *dev) 372 + { 373 + struct mlx5_lag *ldev = mlx5_lag_dev(dev); 374 + int master_idx, i, num = 1; 375 + struct lag_func *pf; 376 + 377 + if (!ldev) 378 + return -ENOENT; 379 + 380 + master_idx = mlx5_lag_get_master_idx(ldev); 381 + if (master_idx < 0) 382 + return -ENOENT; 383 + 384 + pf = mlx5_lag_pf(ldev, master_idx); 385 + if (pf && pf->dev == dev) 386 + return 0; 387 + 388 + mlx5_ldev_for_each(i, 0, ldev) { 389 + if (i == master_idx) 390 + continue; 391 + pf = mlx5_lag_pf(ldev, i); 392 + if (pf->dev == dev) 393 + return num; 394 + num++; 395 + } 396 + return -ENOENT; 397 + } 398 + EXPORT_SYMBOL(mlx5_lag_get_dev_seq); 399 + 400 + /* Devcom events for LAG master marking */ 401 + #define LAG_DEVCOM_PAIR (0) 402 + #define LAG_DEVCOM_UNPAIR (1) 403 + 404 + static void mlx5_lag_mark_master(struct mlx5_lag *ldev) 405 + { 406 + int lowest_dev_idx = INT_MAX; 407 + struct lag_func *pf; 408 + int master_xa_idx = -1; 409 + int dev_idx; 410 + int i; 411 + 412 + mlx5_ldev_for_each(i, 0, ldev) { 413 + pf = mlx5_lag_pf(ldev, i); 414 + dev_idx = mlx5_get_dev_index(pf->dev); 415 + if (dev_idx < lowest_dev_idx) { 416 + lowest_dev_idx = dev_idx; 417 + master_xa_idx = i; 418 + } 419 + } 420 + 421 + if (master_xa_idx >= 0) 422 + xa_set_mark(&ldev->pfs, master_xa_idx, MLX5_LAG_XA_MARK_MASTER); 423 + } 424 + 425 + static void mlx5_lag_clear_master(struct mlx5_lag *ldev) 426 + { 427 + unsigned long idx = 0; 428 + void *entry; 429 + 430 + entry = xa_find(&ldev->pfs, &idx, U8_MAX, MLX5_LAG_XA_MARK_MASTER); 431 + if (!entry) 432 + return; 433 + 434 + xa_clear_mark(&ldev->pfs, idx, MLX5_LAG_XA_MARK_MASTER); 435 + } 436 + 437 + /* Devcom event handler to manage LAG master marking */ 438 + static int mlx5_lag_devcom_event(int event, void *my_data, void *event_data) 439 + { 440 + struct mlx5_core_dev *dev = my_data; 441 + struct mlx5_lag *ldev; 442 + int idx; 443 + 444 + ldev = mlx5_lag_dev(dev); 445 + if (!ldev) 446 + return 0; 447 + 448 + mutex_lock(&ldev->lock); 449 + switch (event) { 450 + case LAG_DEVCOM_PAIR: 451 + /* No need to mark more than once */ 452 + idx = mlx5_lag_get_master_idx(ldev); 453 + if (idx >= 0) 454 + break; 455 + /* Check if all LAG ports are now registered */ 456 + if (mlx5_lag_num_devs(ldev) == ldev->ports) 457 + mlx5_lag_mark_master(ldev); 458 + break; 459 + 460 + case LAG_DEVCOM_UNPAIR: 461 + /* Clear master mark when a device is removed */ 462 + mlx5_lag_clear_master(ldev); 463 + break; 464 + } 465 + mutex_unlock(&ldev->lock); 466 + return 0; 340 467 } 341 468 342 469 int mlx5_lag_num_devs(struct mlx5_lag *ldev) ··· 488 349 489 350 int mlx5_lag_num_netdevs(struct mlx5_lag *ldev) 490 351 { 352 + struct lag_func *pf; 491 353 int i, num = 0; 492 354 493 355 if (!ldev) 494 356 return 0; 495 357 496 - mlx5_ldev_for_each(i, 0, ldev) 497 - if (ldev->pf[i].netdev) 358 + mlx5_ldev_for_each(i, 0, ldev) { 359 + pf = mlx5_lag_pf(ldev, i); 360 + if (pf->netdev) 498 361 num++; 362 + } 499 363 return num; 500 364 } 501 365 ··· 542 400 543 401 /* Use native mapping by default where each port's buckets 544 402 * point the native port: 1 1 1 .. 1 2 2 2 ... 2 3 3 3 ... 3 etc 403 + * ports[] values are 1-indexed device indices for FW. 545 404 */ 546 405 mlx5_ldev_for_each(i, 0, ldev) { 547 406 for (j = 0; j < buckets; j++) { 548 407 idx = i * buckets + j; 549 - ports[idx] = i + 1; 408 + ports[idx] = mlx5_lag_xa_to_dev_idx(ldev, i) + 1; 550 409 } 551 410 } 552 411 ··· 559 416 /* Go over the disabled ports and for each assign a random active port */ 560 417 for (i = 0; i < disabled_ports_num; i++) { 561 418 for (j = 0; j < buckets; j++) { 419 + int rand_xa_idx; 420 + 562 421 get_random_bytes(&rand, 4); 563 - ports[disabled[i] * buckets + j] = enabled[rand % enabled_ports_num] + 1; 422 + rand_xa_idx = enabled[rand % enabled_ports_num]; 423 + ports[disabled[i] * buckets + j] = 424 + mlx5_lag_xa_to_dev_idx(ldev, rand_xa_idx) + 1; 564 425 } 565 426 } 566 427 } 567 428 568 429 static bool mlx5_lag_has_drop_rule(struct mlx5_lag *ldev) 569 430 { 431 + struct lag_func *pf; 570 432 int i; 571 433 572 - mlx5_ldev_for_each(i, 0, ldev) 573 - if (ldev->pf[i].has_drop) 434 + mlx5_ldev_for_each(i, 0, ldev) { 435 + pf = mlx5_lag_pf(ldev, i); 436 + if (pf->has_drop) 574 437 return true; 438 + } 575 439 return false; 576 440 } 577 441 578 442 static void mlx5_lag_drop_rule_cleanup(struct mlx5_lag *ldev) 579 443 { 444 + struct lag_func *pf; 580 445 int i; 581 446 582 447 mlx5_ldev_for_each(i, 0, ldev) { 583 - if (!ldev->pf[i].has_drop) 448 + pf = mlx5_lag_pf(ldev, i); 449 + if (!pf->has_drop) 584 450 continue; 585 451 586 - mlx5_esw_acl_ingress_vport_drop_rule_destroy(ldev->pf[i].dev->priv.eswitch, 452 + mlx5_esw_acl_ingress_vport_drop_rule_destroy(pf->dev->priv.eswitch, 587 453 MLX5_VPORT_UPLINK); 588 - ldev->pf[i].has_drop = false; 454 + pf->has_drop = false; 589 455 } 590 456 } 591 457 ··· 603 451 { 604 452 u8 disabled_ports[MLX5_MAX_PORTS] = {}; 605 453 struct mlx5_core_dev *dev; 454 + struct lag_func *pf; 606 455 int disabled_index; 607 456 int num_disabled; 608 457 int err; ··· 621 468 622 469 for (i = 0; i < num_disabled; i++) { 623 470 disabled_index = disabled_ports[i]; 624 - dev = ldev->pf[disabled_index].dev; 471 + pf = mlx5_lag_pf(ldev, disabled_index); 472 + dev = pf->dev; 625 473 err = mlx5_esw_acl_ingress_vport_drop_rule_create(dev->priv.eswitch, 626 474 MLX5_VPORT_UPLINK); 627 475 if (!err) 628 - ldev->pf[disabled_index].has_drop = true; 476 + pf->has_drop = true; 629 477 else 630 478 mlx5_core_err(dev, 631 479 "Failed to create lag drop rule, error: %d", err); ··· 658 504 if (idx < 0) 659 505 return -EINVAL; 660 506 661 - dev0 = ldev->pf[idx].dev; 507 + dev0 = mlx5_lag_pf(ldev, idx)->dev; 662 508 if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &ldev->mode_flags)) { 663 509 ret = mlx5_lag_port_sel_modify(ldev, ports); 664 510 if (ret || ··· 675 521 static struct net_device *mlx5_lag_active_backup_get_netdev(struct mlx5_core_dev *dev) 676 522 { 677 523 struct net_device *ndev = NULL; 524 + struct lag_func *pf; 678 525 struct mlx5_lag *ldev; 679 526 unsigned long flags; 680 527 int i, last_idx; ··· 686 531 if (!ldev) 687 532 goto unlock; 688 533 689 - mlx5_ldev_for_each(i, 0, ldev) 534 + mlx5_ldev_for_each(i, 0, ldev) { 535 + pf = mlx5_lag_pf(ldev, i); 690 536 if (ldev->tracker.netdev_state[i].tx_enabled) 691 - ndev = ldev->pf[i].netdev; 537 + ndev = pf->netdev; 538 + } 692 539 if (!ndev) { 693 540 last_idx = mlx5_lag_get_dev_index_by_seq(ldev, ldev->ports - 1); 694 541 if (last_idx < 0) 695 542 goto unlock; 696 - ndev = ldev->pf[last_idx].netdev; 543 + pf = mlx5_lag_pf(ldev, last_idx); 544 + ndev = pf->netdev; 697 545 } 698 546 699 547 dev_hold(ndev); ··· 721 563 if (first_idx < 0) 722 564 return; 723 565 724 - dev0 = ldev->pf[first_idx].dev; 566 + dev0 = mlx5_lag_pf(ldev, first_idx)->dev; 725 567 mlx5_infer_tx_affinity_mapping(tracker, ldev, ldev->buckets, ports); 726 568 727 569 mlx5_ldev_for_each(i, 0, ldev) { ··· 773 615 mode == MLX5_LAG_MODE_MULTIPATH) 774 616 return 0; 775 617 776 - dev0 = ldev->pf[first_idx].dev; 618 + dev0 = mlx5_lag_pf(ldev, first_idx)->dev; 777 619 778 620 if (!MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table)) { 779 621 if (ldev->ports > 2) ··· 819 661 820 662 static int mlx5_lag_create_single_fdb(struct mlx5_lag *ldev) 821 663 { 822 - int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 664 + int master_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 823 665 struct mlx5_eswitch *master_esw; 824 666 struct mlx5_core_dev *dev0; 825 667 int i, j; 826 668 int err; 827 669 828 - if (first_idx < 0) 670 + if (master_idx < 0) 829 671 return -EINVAL; 830 672 831 - dev0 = ldev->pf[first_idx].dev; 673 + dev0 = mlx5_lag_pf(ldev, master_idx)->dev; 832 674 master_esw = dev0->priv.eswitch; 833 - mlx5_ldev_for_each(i, first_idx + 1, ldev) { 834 - struct mlx5_eswitch *slave_esw = ldev->pf[i].dev->priv.eswitch; 675 + mlx5_ldev_for_each(i, 0, ldev) { 676 + struct mlx5_eswitch *slave_esw; 677 + 678 + if (i == master_idx) 679 + continue; 680 + 681 + slave_esw = mlx5_lag_pf(ldev, i)->dev->priv.eswitch; 835 682 836 683 err = mlx5_eswitch_offloads_single_fdb_add_one(master_esw, 837 684 slave_esw, ldev->ports); ··· 845 682 } 846 683 return 0; 847 684 err: 848 - mlx5_ldev_for_each_reverse(j, i, first_idx + 1, ldev) 685 + mlx5_ldev_for_each_reverse(j, i, 0, ldev) { 686 + if (j == master_idx) 687 + continue; 849 688 mlx5_eswitch_offloads_single_fdb_del_one(master_esw, 850 - ldev->pf[j].dev->priv.eswitch); 689 + mlx5_lag_pf(ldev, j)->dev->priv.eswitch); 690 + } 851 691 return err; 852 692 } 853 693 ··· 859 693 enum mlx5_lag_mode mode, 860 694 unsigned long flags) 861 695 { 862 - bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags); 863 696 int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 697 + bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags); 864 698 u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {}; 865 699 struct mlx5_core_dev *dev0; 866 700 int err; ··· 868 702 if (first_idx < 0) 869 703 return -EINVAL; 870 704 871 - dev0 = ldev->pf[first_idx].dev; 705 + dev0 = mlx5_lag_pf(ldev, first_idx)->dev; 872 706 if (tracker) 873 707 mlx5_lag_print_mapping(dev0, ldev, tracker, flags); 874 708 mlx5_core_info(dev0, "shared_fdb:%d mode:%s\n", ··· 906 740 enum mlx5_lag_mode mode, 907 741 bool shared_fdb) 908 742 { 909 - int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 910 743 bool roce_lag = mode == MLX5_LAG_MODE_ROCE; 911 744 struct mlx5_core_dev *dev0; 912 745 unsigned long flags = 0; 746 + int master_idx; 913 747 int err; 914 748 915 - if (first_idx < 0) 749 + master_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 750 + if (master_idx < 0) 916 751 return -EINVAL; 917 752 918 - dev0 = ldev->pf[first_idx].dev; 753 + dev0 = mlx5_lag_pf(ldev, master_idx)->dev; 919 754 err = mlx5_lag_set_flags(ldev, mode, tracker, shared_fdb, &flags); 920 755 if (err) 921 756 return err; ··· 960 793 961 794 int mlx5_deactivate_lag(struct mlx5_lag *ldev) 962 795 { 963 - int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 796 + int master_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 964 797 u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {}; 965 798 bool roce_lag = __mlx5_lag_is_roce(ldev); 966 799 unsigned long flags = ldev->mode_flags; ··· 969 802 int err; 970 803 int i; 971 804 972 - if (first_idx < 0) 805 + if (master_idx < 0) 973 806 return -EINVAL; 974 807 975 - dev0 = ldev->pf[first_idx].dev; 808 + dev0 = mlx5_lag_pf(ldev, master_idx)->dev; 976 809 master_esw = dev0->priv.eswitch; 977 810 ldev->mode = MLX5_LAG_MODE_NONE; 978 811 ldev->mode_flags = 0; 979 812 mlx5_lag_mp_reset(ldev); 980 813 981 814 if (test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags)) { 982 - mlx5_ldev_for_each(i, first_idx + 1, ldev) 815 + mlx5_ldev_for_each(i, 0, ldev) { 816 + if (i == master_idx) 817 + continue; 983 818 mlx5_eswitch_offloads_single_fdb_del_one(master_esw, 984 - ldev->pf[i].dev->priv.eswitch); 819 + mlx5_lag_pf(ldev, i)->dev->priv.eswitch); 820 + } 985 821 clear_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags); 986 822 } 987 823 ··· 1014 844 1015 845 bool mlx5_lag_check_prereq(struct mlx5_lag *ldev) 1016 846 { 1017 - int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 847 + int master_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 1018 848 #ifdef CONFIG_MLX5_ESWITCH 1019 849 struct mlx5_core_dev *dev; 1020 850 u8 mode; 1021 851 #endif 852 + struct lag_func *pf; 1022 853 bool roce_support; 1023 854 int i; 1024 855 1025 - if (first_idx < 0 || mlx5_lag_num_devs(ldev) != ldev->ports) 856 + if (master_idx < 0 || mlx5_lag_num_devs(ldev) != ldev->ports) 1026 857 return false; 1027 858 1028 859 #ifdef CONFIG_MLX5_ESWITCH 1029 860 mlx5_ldev_for_each(i, 0, ldev) { 1030 - dev = ldev->pf[i].dev; 861 + pf = mlx5_lag_pf(ldev, i); 862 + dev = pf->dev; 1031 863 if (mlx5_eswitch_num_vfs(dev->priv.eswitch) && !is_mdev_switchdev_mode(dev)) 1032 864 return false; 1033 865 } 1034 866 1035 - dev = ldev->pf[first_idx].dev; 867 + pf = mlx5_lag_pf(ldev, master_idx); 868 + dev = pf->dev; 1036 869 mode = mlx5_eswitch_mode(dev); 1037 - mlx5_ldev_for_each(i, 0, ldev) 1038 - if (mlx5_eswitch_mode(ldev->pf[i].dev) != mode) 870 + mlx5_ldev_for_each(i, 0, ldev) { 871 + pf = mlx5_lag_pf(ldev, i); 872 + if (mlx5_eswitch_mode(pf->dev) != mode) 1039 873 return false; 874 + } 1040 875 1041 876 #else 1042 - mlx5_ldev_for_each(i, 0, ldev) 1043 - if (mlx5_sriov_is_enabled(ldev->pf[i].dev)) 877 + mlx5_ldev_for_each(i, 0, ldev) { 878 + pf = mlx5_lag_pf(ldev, i); 879 + if (mlx5_sriov_is_enabled(pf->dev)) 1044 880 return false; 881 + } 1045 882 #endif 1046 - roce_support = mlx5_get_roce_state(ldev->pf[first_idx].dev); 1047 - mlx5_ldev_for_each(i, first_idx + 1, ldev) 1048 - if (mlx5_get_roce_state(ldev->pf[i].dev) != roce_support) 883 + pf = mlx5_lag_pf(ldev, master_idx); 884 + roce_support = mlx5_get_roce_state(pf->dev); 885 + mlx5_ldev_for_each(i, 0, ldev) { 886 + if (i == master_idx) 887 + continue; 888 + pf = mlx5_lag_pf(ldev, i); 889 + if (mlx5_get_roce_state(pf->dev) != roce_support) 1049 890 return false; 891 + } 1050 892 1051 893 return true; 1052 894 } 1053 895 1054 896 void mlx5_lag_add_devices(struct mlx5_lag *ldev) 1055 897 { 898 + struct lag_func *pf; 1056 899 int i; 1057 900 1058 901 mlx5_ldev_for_each(i, 0, ldev) { 1059 - if (ldev->pf[i].dev->priv.flags & 1060 - MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV) 902 + pf = mlx5_lag_pf(ldev, i); 903 + if (pf->dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV) 1061 904 continue; 1062 905 1063 - ldev->pf[i].dev->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 1064 - mlx5_rescan_drivers_locked(ldev->pf[i].dev); 906 + pf->dev->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 907 + mlx5_rescan_drivers_locked(pf->dev); 1065 908 } 1066 909 } 1067 910 1068 911 void mlx5_lag_remove_devices(struct mlx5_lag *ldev) 1069 912 { 913 + struct lag_func *pf; 1070 914 int i; 1071 915 1072 916 mlx5_ldev_for_each(i, 0, ldev) { 1073 - if (ldev->pf[i].dev->priv.flags & 1074 - MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV) 917 + pf = mlx5_lag_pf(ldev, i); 918 + if (pf->dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV) 1075 919 continue; 1076 920 1077 - ldev->pf[i].dev->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 1078 - mlx5_rescan_drivers_locked(ldev->pf[i].dev); 921 + pf->dev->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 922 + mlx5_rescan_drivers_locked(pf->dev); 1079 923 } 1080 924 } 1081 925 ··· 1105 921 if (idx < 0) 1106 922 return; 1107 923 1108 - dev0 = ldev->pf[idx].dev; 924 + dev0 = mlx5_lag_pf(ldev, idx)->dev; 1109 925 roce_lag = __mlx5_lag_is_roce(ldev); 1110 926 1111 927 if (shared_fdb) { ··· 1115 931 dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 1116 932 mlx5_rescan_drivers_locked(dev0); 1117 933 } 1118 - mlx5_ldev_for_each(i, idx + 1, ldev) 1119 - mlx5_nic_vport_disable_roce(ldev->pf[i].dev); 934 + mlx5_ldev_for_each(i, 0, ldev) { 935 + if (i == idx) 936 + continue; 937 + mlx5_nic_vport_disable_roce(mlx5_lag_pf(ldev, i)->dev); 938 + } 1120 939 } 1121 940 1122 941 err = mlx5_deactivate_lag(ldev); ··· 1131 944 1132 945 if (shared_fdb) 1133 946 mlx5_ldev_for_each(i, 0, ldev) 1134 - if (!(ldev->pf[i].dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) 1135 - mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); 947 + if (!(mlx5_lag_pf(ldev, i)->dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) 948 + mlx5_eswitch_reload_ib_reps(mlx5_lag_pf(ldev, i)->dev->priv.eswitch); 1136 949 } 1137 950 1138 951 bool mlx5_lag_shared_fdb_supported(struct mlx5_lag *ldev) 1139 952 { 1140 - int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 1141 953 struct mlx5_core_dev *dev; 954 + bool ret = false; 955 + int idx; 1142 956 int i; 1143 957 958 + idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 1144 959 if (idx < 0) 1145 960 return false; 1146 961 1147 - mlx5_ldev_for_each(i, idx + 1, ldev) { 1148 - dev = ldev->pf[i].dev; 962 + mlx5_ldev_for_each(i, 0, ldev) { 963 + if (i == idx) 964 + continue; 965 + dev = mlx5_lag_pf(ldev, i)->dev; 1149 966 if (is_mdev_switchdev_mode(dev) && 1150 967 mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) && 1151 968 MLX5_CAP_GEN(dev, lag_native_fdb_selection) && ··· 1160 969 return false; 1161 970 } 1162 971 1163 - dev = ldev->pf[idx].dev; 972 + dev = mlx5_lag_pf(ldev, idx)->dev; 1164 973 if (is_mdev_switchdev_mode(dev) && 1165 974 mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) && 1166 975 mlx5_esw_offloads_devcom_is_ready(dev->priv.eswitch) && 1167 976 MLX5_CAP_ESW(dev, esw_shared_ingress_acl) && 1168 977 mlx5_eswitch_get_npeers(dev->priv.eswitch) == MLX5_CAP_GEN(dev, num_lag_ports) - 1) 1169 - return true; 978 + ret = true; 1170 979 1171 - return false; 980 + return ret; 1172 981 } 1173 982 1174 983 static bool mlx5_lag_is_roce_lag(struct mlx5_lag *ldev) 1175 984 { 1176 985 bool roce_lag = true; 986 + struct lag_func *pf; 1177 987 int i; 1178 988 1179 - mlx5_ldev_for_each(i, 0, ldev) 1180 - roce_lag = roce_lag && !mlx5_sriov_is_enabled(ldev->pf[i].dev); 989 + mlx5_ldev_for_each(i, 0, ldev) { 990 + pf = mlx5_lag_pf(ldev, i); 991 + roce_lag = roce_lag && !mlx5_sriov_is_enabled(pf->dev); 992 + } 1181 993 1182 994 #ifdef CONFIG_MLX5_ESWITCH 1183 - mlx5_ldev_for_each(i, 0, ldev) 1184 - roce_lag = roce_lag && is_mdev_legacy_mode(ldev->pf[i].dev); 995 + mlx5_ldev_for_each(i, 0, ldev) { 996 + pf = mlx5_lag_pf(ldev, i); 997 + roce_lag = roce_lag && is_mdev_legacy_mode(pf->dev); 998 + } 1185 999 #endif 1186 1000 1187 1001 return roce_lag; ··· 1210 1014 int (*get_speed)(struct mlx5_core_dev *, u32 *)) 1211 1015 { 1212 1016 struct mlx5_core_dev *pf_mdev; 1017 + struct lag_func *pf; 1213 1018 int pf_idx; 1214 1019 u32 speed; 1215 1020 int ret; 1216 1021 1217 1022 *sum_speed = 0; 1218 1023 mlx5_ldev_for_each(pf_idx, 0, ldev) { 1219 - pf_mdev = ldev->pf[pf_idx].dev; 1024 + pf = mlx5_lag_pf(ldev, pf_idx); 1025 + if (!pf) 1026 + continue; 1027 + pf_mdev = pf->dev; 1220 1028 if (!pf_mdev) 1221 1029 continue; 1222 1030 ··· 1286 1086 void mlx5_lag_set_vports_agg_speed(struct mlx5_lag *ldev) 1287 1087 { 1288 1088 struct mlx5_core_dev *mdev; 1089 + struct lag_func *pf; 1289 1090 u32 speed; 1290 1091 int pf_idx; 1291 1092 ··· 1306 1105 speed = speed / MLX5_MAX_TX_SPEED_UNIT; 1307 1106 1308 1107 mlx5_ldev_for_each(pf_idx, 0, ldev) { 1309 - mdev = ldev->pf[pf_idx].dev; 1108 + pf = mlx5_lag_pf(ldev, pf_idx); 1109 + if (!pf) 1110 + continue; 1111 + mdev = pf->dev; 1310 1112 if (!mdev) 1311 1113 continue; 1312 1114 ··· 1320 1116 void mlx5_lag_reset_vports_speed(struct mlx5_lag *ldev) 1321 1117 { 1322 1118 struct mlx5_core_dev *mdev; 1119 + struct lag_func *pf; 1323 1120 u32 speed; 1324 1121 int pf_idx; 1325 1122 int ret; 1326 1123 1327 1124 mlx5_ldev_for_each(pf_idx, 0, ldev) { 1328 - mdev = ldev->pf[pf_idx].dev; 1125 + pf = mlx5_lag_pf(ldev, pf_idx); 1126 + if (!pf) 1127 + continue; 1128 + mdev = pf->dev; 1329 1129 if (!mdev) 1330 1130 continue; 1331 1131 ··· 1360 1152 if (idx < 0) 1361 1153 return; 1362 1154 1363 - dev0 = ldev->pf[idx].dev; 1155 + dev0 = mlx5_lag_pf(ldev, idx)->dev; 1364 1156 if (!mlx5_lag_is_ready(ldev)) { 1365 1157 do_bond = false; 1366 1158 } else { ··· 1390 1182 mlx5_lag_add_devices(ldev); 1391 1183 if (shared_fdb) { 1392 1184 mlx5_ldev_for_each(i, 0, ldev) 1393 - mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); 1185 + mlx5_eswitch_reload_ib_reps(mlx5_lag_pf(ldev, i)->dev->priv.eswitch); 1394 1186 } 1395 1187 1396 1188 return; 1397 - } else if (roce_lag) { 1189 + } 1190 + 1191 + if (roce_lag) { 1192 + struct mlx5_core_dev *dev; 1193 + 1398 1194 dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 1399 1195 mlx5_rescan_drivers_locked(dev0); 1400 - mlx5_ldev_for_each(i, idx + 1, ldev) { 1401 - if (mlx5_get_roce_state(ldev->pf[i].dev)) 1402 - mlx5_nic_vport_enable_roce(ldev->pf[i].dev); 1196 + mlx5_ldev_for_each(i, 0, ldev) { 1197 + if (i == idx) 1198 + continue; 1199 + dev = mlx5_lag_pf(ldev, i)->dev; 1200 + if (mlx5_get_roce_state(dev)) 1201 + mlx5_nic_vport_enable_roce(dev); 1403 1202 } 1404 1203 } else if (shared_fdb) { 1405 1204 int i; ··· 1415 1200 mlx5_rescan_drivers_locked(dev0); 1416 1201 1417 1202 mlx5_ldev_for_each(i, 0, ldev) { 1418 - err = mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); 1203 + err = mlx5_eswitch_reload_ib_reps(mlx5_lag_pf(ldev, i)->dev->priv.eswitch); 1419 1204 if (err) 1420 1205 break; 1421 1206 } ··· 1426 1211 mlx5_deactivate_lag(ldev); 1427 1212 mlx5_lag_add_devices(ldev); 1428 1213 mlx5_ldev_for_each(i, 0, ldev) 1429 - mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); 1214 + mlx5_eswitch_reload_ib_reps(mlx5_lag_pf(ldev, i)->dev->priv.eswitch); 1430 1215 mlx5_core_err(dev0, "Failed to enable lag\n"); 1431 1216 return; 1432 1217 } ··· 1458 1243 struct mlx5_devcom_comp_dev *mlx5_lag_get_devcom_comp(struct mlx5_lag *ldev) 1459 1244 { 1460 1245 struct mlx5_devcom_comp_dev *devcom = NULL; 1246 + struct lag_func *pf; 1461 1247 int i; 1462 1248 1463 1249 mutex_lock(&ldev->lock); 1464 1250 i = mlx5_get_next_ldev_func(ldev, 0); 1465 - if (i < MLX5_MAX_PORTS) 1466 - devcom = ldev->pf[i].dev->priv.hca_devcom_comp; 1251 + if (i < MLX5_MAX_PORTS) { 1252 + pf = mlx5_lag_pf(ldev, i); 1253 + devcom = pf->dev->priv.hca_devcom_comp; 1254 + } 1467 1255 mutex_unlock(&ldev->lock); 1468 1256 return devcom; 1469 1257 } 1258 + 1259 + static int mlx5_lag_demux_ft_fg_init(struct mlx5_core_dev *dev, 1260 + struct mlx5_flow_table_attr *ft_attr, 1261 + struct mlx5_lag *ldev) 1262 + { 1263 + #ifdef CONFIG_MLX5_ESWITCH 1264 + struct mlx5_flow_namespace *ns; 1265 + struct mlx5_flow_group *fg; 1266 + int err; 1267 + 1268 + ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_LAG); 1269 + if (!ns) 1270 + return 0; 1271 + 1272 + ldev->lag_demux_ft = mlx5_create_flow_table(ns, ft_attr); 1273 + if (IS_ERR(ldev->lag_demux_ft)) 1274 + return PTR_ERR(ldev->lag_demux_ft); 1275 + 1276 + fg = mlx5_esw_lag_demux_fg_create(dev->priv.eswitch, 1277 + ldev->lag_demux_ft); 1278 + if (IS_ERR(fg)) { 1279 + err = PTR_ERR(fg); 1280 + mlx5_destroy_flow_table(ldev->lag_demux_ft); 1281 + ldev->lag_demux_ft = NULL; 1282 + return err; 1283 + } 1284 + 1285 + ldev->lag_demux_fg = fg; 1286 + return 0; 1287 + #else 1288 + return -EOPNOTSUPP; 1289 + #endif 1290 + } 1291 + 1292 + static int mlx5_lag_demux_fw_init(struct mlx5_core_dev *dev, 1293 + struct mlx5_flow_table_attr *ft_attr, 1294 + struct mlx5_lag *ldev) 1295 + { 1296 + struct mlx5_flow_namespace *ns; 1297 + int err; 1298 + 1299 + ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_LAG); 1300 + if (!ns) 1301 + return 0; 1302 + 1303 + ldev->lag_demux_fg = NULL; 1304 + ft_attr->max_fte = 1; 1305 + ldev->lag_demux_ft = mlx5_create_lag_demux_flow_table(ns, ft_attr); 1306 + if (IS_ERR(ldev->lag_demux_ft)) { 1307 + err = PTR_ERR(ldev->lag_demux_ft); 1308 + ldev->lag_demux_ft = NULL; 1309 + return err; 1310 + } 1311 + 1312 + return 0; 1313 + } 1314 + 1315 + int mlx5_lag_demux_init(struct mlx5_core_dev *dev, 1316 + struct mlx5_flow_table_attr *ft_attr) 1317 + { 1318 + struct mlx5_lag *ldev; 1319 + 1320 + if (!ft_attr) 1321 + return -EINVAL; 1322 + 1323 + ldev = mlx5_lag_dev(dev); 1324 + if (!ldev) 1325 + return -ENODEV; 1326 + 1327 + xa_init(&ldev->lag_demux_rules); 1328 + 1329 + if (mlx5_get_sd(dev)) 1330 + return mlx5_lag_demux_ft_fg_init(dev, ft_attr, ldev); 1331 + 1332 + return mlx5_lag_demux_fw_init(dev, ft_attr, ldev); 1333 + } 1334 + EXPORT_SYMBOL(mlx5_lag_demux_init); 1335 + 1336 + void mlx5_lag_demux_cleanup(struct mlx5_core_dev *dev) 1337 + { 1338 + struct mlx5_flow_handle *rule; 1339 + struct mlx5_lag *ldev; 1340 + unsigned long vport_num; 1341 + 1342 + ldev = mlx5_lag_dev(dev); 1343 + if (!ldev) 1344 + return; 1345 + 1346 + xa_for_each(&ldev->lag_demux_rules, vport_num, rule) 1347 + mlx5_del_flow_rules(rule); 1348 + xa_destroy(&ldev->lag_demux_rules); 1349 + 1350 + if (ldev->lag_demux_fg) 1351 + mlx5_destroy_flow_group(ldev->lag_demux_fg); 1352 + if (ldev->lag_demux_ft) 1353 + mlx5_destroy_flow_table(ldev->lag_demux_ft); 1354 + ldev->lag_demux_fg = NULL; 1355 + ldev->lag_demux_ft = NULL; 1356 + } 1357 + EXPORT_SYMBOL(mlx5_lag_demux_cleanup); 1358 + 1359 + int mlx5_lag_demux_rule_add(struct mlx5_core_dev *vport_dev, u16 vport_num, 1360 + int index) 1361 + { 1362 + struct mlx5_flow_handle *rule; 1363 + struct mlx5_lag *ldev; 1364 + int err; 1365 + 1366 + ldev = mlx5_lag_dev(vport_dev); 1367 + if (!ldev || !ldev->lag_demux_fg) 1368 + return 0; 1369 + 1370 + if (xa_load(&ldev->lag_demux_rules, index)) 1371 + return 0; 1372 + 1373 + rule = mlx5_esw_lag_demux_rule_create(vport_dev->priv.eswitch, 1374 + vport_num, ldev->lag_demux_ft); 1375 + if (IS_ERR(rule)) { 1376 + err = PTR_ERR(rule); 1377 + mlx5_core_warn(vport_dev, 1378 + "Failed to create LAG demux rule for vport %u, err %d\n", 1379 + vport_num, err); 1380 + return err; 1381 + } 1382 + 1383 + err = xa_err(xa_store(&ldev->lag_demux_rules, index, rule, 1384 + GFP_KERNEL)); 1385 + if (err) { 1386 + mlx5_del_flow_rules(rule); 1387 + mlx5_core_warn(vport_dev, 1388 + "Failed to store LAG demux rule for vport %u, err %d\n", 1389 + vport_num, err); 1390 + } 1391 + 1392 + return err; 1393 + } 1394 + EXPORT_SYMBOL(mlx5_lag_demux_rule_add); 1395 + 1396 + void mlx5_lag_demux_rule_del(struct mlx5_core_dev *dev, int index) 1397 + { 1398 + struct mlx5_flow_handle *rule; 1399 + struct mlx5_lag *ldev; 1400 + 1401 + ldev = mlx5_lag_dev(dev); 1402 + if (!ldev || !ldev->lag_demux_fg) 1403 + return; 1404 + 1405 + rule = xa_erase(&ldev->lag_demux_rules, index); 1406 + if (rule) 1407 + mlx5_del_flow_rules(rule); 1408 + } 1409 + EXPORT_SYMBOL(mlx5_lag_demux_rule_del); 1470 1410 1471 1411 static void mlx5_queue_bond_work(struct mlx5_lag *ldev, unsigned long delay) 1472 1412 { ··· 1667 1297 struct netdev_lag_upper_info *lag_upper_info = NULL; 1668 1298 bool is_bonded, is_in_lag, mode_supported; 1669 1299 bool has_inactive = 0; 1300 + struct lag_func *pf; 1670 1301 struct slave *slave; 1671 1302 u8 bond_status = 0; 1672 1303 int num_slaves = 0; ··· 1688 1317 rcu_read_lock(); 1689 1318 for_each_netdev_in_bond_rcu(upper, ndev_tmp) { 1690 1319 mlx5_ldev_for_each(i, 0, ldev) { 1691 - if (ldev->pf[i].netdev == ndev_tmp) { 1320 + pf = mlx5_lag_pf(ldev, i); 1321 + if (pf->netdev == ndev_tmp) { 1692 1322 idx++; 1693 1323 break; 1694 1324 } ··· 1909 1537 struct mlx5_core_dev *dev, 1910 1538 struct net_device *netdev) 1911 1539 { 1912 - unsigned int fn = mlx5_get_dev_index(dev); 1913 - unsigned long flags; 1914 - 1915 - spin_lock_irqsave(&lag_lock, flags); 1916 - ldev->pf[fn].netdev = netdev; 1917 - ldev->tracker.netdev_state[fn].link_up = 0; 1918 - ldev->tracker.netdev_state[fn].tx_enabled = 0; 1919 - spin_unlock_irqrestore(&lag_lock, flags); 1920 - } 1921 - 1922 - static void mlx5_ldev_remove_netdev(struct mlx5_lag *ldev, 1923 - struct net_device *netdev) 1924 - { 1540 + struct lag_func *pf; 1925 1541 unsigned long flags; 1926 1542 int i; 1927 1543 1928 1544 spin_lock_irqsave(&lag_lock, flags); 1545 + /* Find pf entry by matching dev pointer */ 1929 1546 mlx5_ldev_for_each(i, 0, ldev) { 1930 - if (ldev->pf[i].netdev == netdev) { 1931 - ldev->pf[i].netdev = NULL; 1547 + pf = mlx5_lag_pf(ldev, i); 1548 + if (pf->dev == dev) { 1549 + pf->netdev = netdev; 1550 + ldev->tracker.netdev_state[i].link_up = 0; 1551 + ldev->tracker.netdev_state[i].tx_enabled = 0; 1932 1552 break; 1933 1553 } 1934 1554 } 1935 1555 spin_unlock_irqrestore(&lag_lock, flags); 1936 1556 } 1937 1557 1938 - static void mlx5_ldev_add_mdev(struct mlx5_lag *ldev, 1558 + static void mlx5_ldev_remove_netdev(struct mlx5_lag *ldev, 1559 + struct net_device *netdev) 1560 + { 1561 + struct lag_func *pf; 1562 + unsigned long flags; 1563 + int i; 1564 + 1565 + spin_lock_irqsave(&lag_lock, flags); 1566 + mlx5_ldev_for_each(i, 0, ldev) { 1567 + pf = mlx5_lag_pf(ldev, i); 1568 + if (pf->netdev == netdev) { 1569 + pf->netdev = NULL; 1570 + break; 1571 + } 1572 + } 1573 + spin_unlock_irqrestore(&lag_lock, flags); 1574 + } 1575 + 1576 + static int mlx5_ldev_add_mdev(struct mlx5_lag *ldev, 1939 1577 struct mlx5_core_dev *dev) 1940 1578 { 1941 - unsigned int fn = mlx5_get_dev_index(dev); 1579 + struct lag_func *pf; 1580 + u32 idx; 1581 + int err; 1942 1582 1943 - ldev->pf[fn].dev = dev; 1583 + pf = kzalloc_obj(*pf); 1584 + if (!pf) 1585 + return -ENOMEM; 1586 + 1587 + err = xa_alloc(&ldev->pfs, &idx, pf, XA_LIMIT(0, MLX5_MAX_PORTS - 1), 1588 + GFP_KERNEL); 1589 + if (err) { 1590 + kfree(pf); 1591 + return err; 1592 + } 1593 + 1594 + pf->idx = idx; 1595 + pf->dev = dev; 1944 1596 dev->priv.lag = ldev; 1945 1597 1946 - MLX5_NB_INIT(&ldev->pf[fn].port_change_nb, 1598 + MLX5_NB_INIT(&pf->port_change_nb, 1947 1599 mlx5_lag_mpesw_port_change_event, PORT_CHANGE); 1948 - mlx5_eq_notifier_register(dev, &ldev->pf[fn].port_change_nb); 1600 + mlx5_eq_notifier_register(dev, &pf->port_change_nb); 1601 + 1602 + return 0; 1949 1603 } 1950 1604 1951 1605 static void mlx5_ldev_remove_mdev(struct mlx5_lag *ldev, 1952 1606 struct mlx5_core_dev *dev) 1953 1607 { 1954 - int fn; 1608 + struct lag_func *pf; 1609 + int i; 1955 1610 1956 - fn = mlx5_get_dev_index(dev); 1957 - if (ldev->pf[fn].dev != dev) 1611 + mlx5_ldev_for_each(i, 0, ldev) { 1612 + pf = mlx5_lag_pf(ldev, i); 1613 + if (pf->dev == dev) 1614 + break; 1615 + } 1616 + if (i >= MLX5_MAX_PORTS) 1958 1617 return; 1959 1618 1960 - if (ldev->pf[fn].port_change_nb.nb.notifier_call) 1961 - mlx5_eq_notifier_unregister(dev, &ldev->pf[fn].port_change_nb); 1619 + if (pf->port_change_nb.nb.notifier_call) 1620 + mlx5_eq_notifier_unregister(dev, &pf->port_change_nb); 1962 1621 1963 - ldev->pf[fn].dev = NULL; 1622 + pf->dev = NULL; 1964 1623 dev->priv.lag = NULL; 1624 + xa_erase(&ldev->pfs, pf->idx); 1625 + kfree(pf); 1965 1626 } 1966 1627 1967 1628 /* Must be called with HCA devcom component lock held */ ··· 2003 1598 struct mlx5_devcom_comp_dev *pos = NULL; 2004 1599 struct mlx5_lag *ldev = NULL; 2005 1600 struct mlx5_core_dev *tmp_dev; 1601 + int err; 2006 1602 2007 1603 tmp_dev = mlx5_devcom_get_next_peer_data(dev->priv.hca_devcom_comp, &pos); 2008 1604 if (tmp_dev) ··· 2015 1609 mlx5_core_err(dev, "Failed to alloc lag dev\n"); 2016 1610 return 0; 2017 1611 } 2018 - mlx5_ldev_add_mdev(ldev, dev); 1612 + err = mlx5_ldev_add_mdev(ldev, dev); 1613 + if (err) { 1614 + mlx5_core_err(dev, "Failed to add mdev to lag dev\n"); 1615 + mlx5_ldev_put(ldev); 1616 + return 0; 1617 + } 2019 1618 return 0; 2020 1619 } 2021 1620 ··· 2030 1619 return -EAGAIN; 2031 1620 } 2032 1621 mlx5_ldev_get(ldev); 2033 - mlx5_ldev_add_mdev(ldev, dev); 1622 + err = mlx5_ldev_add_mdev(ldev, dev); 1623 + if (err) { 1624 + mlx5_ldev_put(ldev); 1625 + mutex_unlock(&ldev->lock); 1626 + return err; 1627 + } 2034 1628 mutex_unlock(&ldev->lock); 2035 1629 2036 1630 return 0; ··· 2063 1647 dev->priv.hca_devcom_comp = 2064 1648 mlx5_devcom_register_component(dev->priv.devc, 2065 1649 MLX5_DEVCOM_HCA_PORTS, 2066 - &attr, NULL, dev); 1650 + &attr, mlx5_lag_devcom_event, 1651 + dev); 2067 1652 if (!dev->priv.hca_devcom_comp) { 2068 1653 mlx5_core_err(dev, 2069 1654 "Failed to register devcom HCA component."); ··· 2095 1678 } 2096 1679 mlx5_ldev_remove_mdev(ldev, dev); 2097 1680 mutex_unlock(&ldev->lock); 1681 + /* Send devcom event to notify peers that a device is being removed */ 1682 + mlx5_devcom_send_event(dev->priv.hca_devcom_comp, 1683 + LAG_DEVCOM_UNPAIR, LAG_DEVCOM_UNPAIR, dev); 2098 1684 mlx5_lag_unregister_hca_devcom_comp(dev); 2099 1685 mlx5_ldev_put(ldev); 2100 1686 } ··· 2121 1701 msleep(100); 2122 1702 goto recheck; 2123 1703 } 1704 + /* Send devcom event to notify peers that a device was added */ 1705 + mlx5_devcom_send_event(dev->priv.hca_devcom_comp, 1706 + LAG_DEVCOM_PAIR, LAG_DEVCOM_UNPAIR, dev); 2124 1707 mlx5_ldev_add_debugfs(dev); 2125 1708 } 2126 1709 ··· 2169 1746 2170 1747 int mlx5_get_pre_ldev_func(struct mlx5_lag *ldev, int start_idx, int end_idx) 2171 1748 { 1749 + struct lag_func *pf; 2172 1750 int i; 2173 1751 2174 - for (i = start_idx; i >= end_idx; i--) 2175 - if (ldev->pf[i].dev) 1752 + for (i = start_idx; i >= end_idx; i--) { 1753 + pf = xa_load(&ldev->pfs, i); 1754 + if (pf && pf->dev) 2176 1755 return i; 1756 + } 2177 1757 return -1; 2178 1758 } 2179 1759 2180 1760 int mlx5_get_next_ldev_func(struct mlx5_lag *ldev, int start_idx) 2181 1761 { 2182 - int i; 1762 + struct lag_func *pf; 1763 + unsigned long idx; 2183 1764 2184 - for (i = start_idx; i < MLX5_MAX_PORTS; i++) 2185 - if (ldev->pf[i].dev) 2186 - return i; 1765 + xa_for_each_start(&ldev->pfs, idx, pf, start_idx) 1766 + if (pf->dev) 1767 + return idx; 2187 1768 return MLX5_MAX_PORTS; 2188 1769 } 2189 1770 ··· 2241 1814 { 2242 1815 struct mlx5_lag *ldev; 2243 1816 unsigned long flags; 1817 + struct lag_func *pf; 2244 1818 bool res = false; 2245 1819 int idx; 2246 1820 2247 1821 spin_lock_irqsave(&lag_lock, flags); 2248 1822 ldev = mlx5_lag_dev(dev); 2249 1823 idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 2250 - res = ldev && __mlx5_lag_is_active(ldev) && idx >= 0 && dev == ldev->pf[idx].dev; 1824 + if (ldev && __mlx5_lag_is_active(ldev) && idx >= 0) { 1825 + pf = mlx5_lag_pf(ldev, idx); 1826 + res = pf && dev == pf->dev; 1827 + } 2251 1828 spin_unlock_irqrestore(&lag_lock, flags); 2252 1829 2253 1830 return res; ··· 2330 1899 { 2331 1900 struct mlx5_lag *ldev; 2332 1901 unsigned long flags; 1902 + struct lag_func *pf; 2333 1903 u8 port = 0; 2334 1904 int i; 2335 1905 ··· 2340 1908 goto unlock; 2341 1909 2342 1910 mlx5_ldev_for_each(i, 0, ldev) { 2343 - if (ldev->pf[i].netdev == slave) { 1911 + pf = mlx5_lag_pf(ldev, i); 1912 + if (pf->netdev == slave) { 2344 1913 port = i; 2345 1914 break; 2346 1915 } ··· 2372 1939 struct mlx5_core_dev *peer_dev = NULL; 2373 1940 struct mlx5_lag *ldev; 2374 1941 unsigned long flags; 1942 + struct lag_func *pf; 2375 1943 int idx; 2376 1944 2377 1945 spin_lock_irqsave(&lag_lock, flags); ··· 2382 1948 2383 1949 if (*i == MLX5_MAX_PORTS) 2384 1950 goto unlock; 2385 - mlx5_ldev_for_each(idx, *i, ldev) 2386 - if (ldev->pf[idx].dev != dev) 1951 + mlx5_ldev_for_each(idx, *i, ldev) { 1952 + pf = mlx5_lag_pf(ldev, idx); 1953 + if (pf->dev != dev) 2387 1954 break; 1955 + } 2388 1956 2389 1957 if (idx == MLX5_MAX_PORTS) { 2390 1958 *i = idx; ··· 2394 1958 } 2395 1959 *i = idx + 1; 2396 1960 2397 - peer_dev = ldev->pf[idx].dev; 1961 + pf = mlx5_lag_pf(ldev, idx); 1962 + peer_dev = pf->dev; 2398 1963 2399 1964 unlock: 2400 1965 spin_unlock_irqrestore(&lag_lock, flags); ··· 2413 1976 int ret = 0, i, j, idx = 0; 2414 1977 struct mlx5_lag *ldev; 2415 1978 unsigned long flags; 1979 + struct lag_func *pf; 2416 1980 int num_ports; 2417 1981 void *out; 2418 1982 ··· 2433 1995 ldev = mlx5_lag_dev(dev); 2434 1996 if (ldev && __mlx5_lag_is_active(ldev)) { 2435 1997 num_ports = ldev->ports; 2436 - mlx5_ldev_for_each(i, 0, ldev) 2437 - mdev[idx++] = ldev->pf[i].dev; 1998 + mlx5_ldev_for_each(i, 0, ldev) { 1999 + pf = mlx5_lag_pf(ldev, i); 2000 + mdev[idx++] = pf->dev; 2001 + } 2438 2002 } else { 2439 2003 num_ports = 1; 2440 2004 mdev[MLX5_LAG_P1] = dev;
+48 -1
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
··· 5 5 #define __MLX5_LAG_H__ 6 6 7 7 #include <linux/debugfs.h> 8 + #include <linux/errno.h> 9 + #include <linux/xarray.h> 10 + #include <linux/mlx5/fs.h> 8 11 9 12 #define MLX5_LAG_MAX_HASH_BUCKETS 16 13 + /* XArray mark for the LAG master device 14 + * (device with lowest mlx5_get_dev_index). 15 + * Note: XA_MARK_0 is reserved by XA_FLAGS_ALLOC for free-slot tracking. 16 + */ 17 + #define MLX5_LAG_XA_MARK_MASTER XA_MARK_1 18 + 10 19 #include "mlx5_core.h" 11 20 #include "mp.h" 12 21 #include "port_sel.h" ··· 48 39 struct mlx5_core_dev *dev; 49 40 struct net_device *netdev; 50 41 bool has_drop; 42 + unsigned int idx; /* xarray index assigned by LAG */ 51 43 struct mlx5_nb port_change_nb; 52 44 }; 53 45 ··· 74 64 int mode_changes_in_progress; 75 65 u8 v2p_map[MLX5_MAX_PORTS * MLX5_LAG_MAX_HASH_BUCKETS]; 76 66 struct kref ref; 77 - struct lag_func pf[MLX5_MAX_PORTS]; 67 + struct xarray pfs; 78 68 struct lag_tracker tracker; 79 69 struct workqueue_struct *wq; 80 70 struct delayed_work bond_work; ··· 86 76 /* Protect lag fields/state changes */ 87 77 struct mutex lock; 88 78 struct lag_mpesw lag_mpesw; 79 + struct mlx5_flow_table *lag_demux_ft; 80 + struct mlx5_flow_group *lag_demux_fg; 81 + struct xarray lag_demux_rules; 89 82 }; 90 83 91 84 static inline struct mlx5_lag * 92 85 mlx5_lag_dev(struct mlx5_core_dev *dev) 93 86 { 94 87 return dev->priv.lag; 88 + } 89 + 90 + static inline struct lag_func * 91 + mlx5_lag_pf(struct mlx5_lag *ldev, unsigned int idx) 92 + { 93 + return xa_load(&ldev->pfs, idx); 94 + } 95 + 96 + /* Get device index (mlx5_get_dev_index) from xarray index */ 97 + static inline int mlx5_lag_xa_to_dev_idx(struct mlx5_lag *ldev, int xa_idx) 98 + { 99 + struct lag_func *pf = mlx5_lag_pf(ldev, xa_idx); 100 + 101 + return pf ? mlx5_get_dev_index(pf->dev) : -ENOENT; 102 + } 103 + 104 + /* Find lag_func by device index (reverse lookup from mlx5_get_dev_index) */ 105 + static inline struct lag_func * 106 + mlx5_lag_pf_by_dev_idx(struct mlx5_lag *ldev, int dev_idx) 107 + { 108 + struct lag_func *pf; 109 + unsigned long idx; 110 + 111 + xa_for_each(&ldev->pfs, idx, pf) { 112 + if (mlx5_get_dev_index(pf->dev) == dev_idx) 113 + return pf; 114 + } 115 + return NULL; 95 116 } 96 117 97 118 static inline bool ··· 139 98 140 99 bool mlx5_lag_shared_fdb_supported(struct mlx5_lag *ldev); 141 100 bool mlx5_lag_check_prereq(struct mlx5_lag *ldev); 101 + int mlx5_lag_demux_init(struct mlx5_core_dev *dev, 102 + struct mlx5_flow_table_attr *ft_attr); 103 + void mlx5_lag_demux_cleanup(struct mlx5_core_dev *dev); 104 + int mlx5_lag_demux_rule_add(struct mlx5_core_dev *dev, u16 vport_num, 105 + int vport_index); 106 + void mlx5_lag_demux_rule_del(struct mlx5_core_dev *dev, int vport_index); 142 107 void mlx5_modify_lag(struct mlx5_lag *ldev, 143 108 struct lag_tracker *tracker); 144 109 int mlx5_activate_lag(struct mlx5_lag *ldev,
+10 -10
drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
··· 29 29 if (ldev->ports > MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS) 30 30 return false; 31 31 32 - return mlx5_esw_multipath_prereq(ldev->pf[idx0].dev, 33 - ldev->pf[idx1].dev); 32 + return mlx5_esw_multipath_prereq(mlx5_lag_pf(ldev, idx0)->dev, 33 + mlx5_lag_pf(ldev, idx1)->dev); 34 34 } 35 35 36 36 bool mlx5_lag_is_multipath(struct mlx5_core_dev *dev) ··· 80 80 tracker.netdev_state[idx1].link_up = true; 81 81 break; 82 82 default: 83 - mlx5_core_warn(ldev->pf[idx0].dev, 83 + mlx5_core_warn(mlx5_lag_pf(ldev, idx0)->dev, 84 84 "Invalid affinity port %d", port); 85 85 return; 86 86 } 87 87 88 88 if (tracker.netdev_state[idx0].tx_enabled) 89 - mlx5_notifier_call_chain(ldev->pf[idx0].dev->priv.events, 89 + mlx5_notifier_call_chain(mlx5_lag_pf(ldev, idx0)->dev->priv.events, 90 90 MLX5_DEV_EVENT_PORT_AFFINITY, 91 91 (void *)0); 92 92 93 93 if (tracker.netdev_state[idx1].tx_enabled) 94 - mlx5_notifier_call_chain(ldev->pf[idx1].dev->priv.events, 94 + mlx5_notifier_call_chain(mlx5_lag_pf(ldev, idx1)->dev->priv.events, 95 95 MLX5_DEV_EVENT_PORT_AFFINITY, 96 96 (void *)0); 97 97 ··· 146 146 fib_dev = fib_info_nh(fi, i)->fib_nh_dev; 147 147 ldev_idx = mlx5_lag_dev_get_netdev_idx(ldev, fib_dev); 148 148 if (ldev_idx >= 0) 149 - return ldev->pf[ldev_idx].netdev; 149 + return mlx5_lag_pf(ldev, ldev_idx)->netdev; 150 150 } 151 151 152 152 return NULL; ··· 178 178 mp->fib.dst_len <= fen_info->dst_len && 179 179 !(mp->fib.dst_len == fen_info->dst_len && 180 180 fi->fib_priority < mp->fib.priority)) { 181 - mlx5_core_dbg(ldev->pf[idx].dev, 181 + mlx5_core_dbg(mlx5_lag_pf(ldev, idx)->dev, 182 182 "Multipath entry with lower priority was rejected\n"); 183 183 return; 184 184 } ··· 194 194 } 195 195 196 196 if (nh_dev0 == nh_dev1) { 197 - mlx5_core_warn(ldev->pf[idx].dev, 197 + mlx5_core_warn(mlx5_lag_pf(ldev, idx)->dev, 198 198 "Multipath offload doesn't support routes with multiple nexthops of the same device"); 199 199 return; 200 200 } ··· 203 203 if (__mlx5_lag_is_active(ldev)) { 204 204 mlx5_ldev_for_each(i, 0, ldev) { 205 205 dev_idx++; 206 - if (ldev->pf[i].netdev == nh_dev0) 206 + if (mlx5_lag_pf(ldev, i)->netdev == nh_dev0) 207 207 break; 208 208 } 209 209 mlx5_lag_set_port_affinity(ldev, dev_idx); ··· 240 240 /* nh added/removed */ 241 241 if (event == FIB_EVENT_NH_DEL) { 242 242 mlx5_ldev_for_each(i, 0, ldev) { 243 - if (ldev->pf[i].netdev == fib_nh->fib_nh_dev) 243 + if (mlx5_lag_pf(ldev, i)->netdev == fib_nh->fib_nh_dev) 244 244 break; 245 245 dev_idx++; 246 246 }
+7 -8
drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
··· 16 16 int i; 17 17 18 18 mlx5_ldev_for_each(i, 0, ldev) { 19 - dev = ldev->pf[i].dev; 19 + dev = mlx5_lag_pf(ldev, i)->dev; 20 20 esw = dev->priv.eswitch; 21 21 pf_metadata = ldev->lag_mpesw.pf_metadata[i]; 22 22 if (!pf_metadata) ··· 37 37 int i, err; 38 38 39 39 mlx5_ldev_for_each(i, 0, ldev) { 40 - dev = ldev->pf[i].dev; 40 + dev = mlx5_lag_pf(ldev, i)->dev; 41 41 esw = dev->priv.eswitch; 42 42 pf_metadata = mlx5_esw_match_metadata_alloc(esw); 43 43 if (!pf_metadata) { ··· 53 53 } 54 54 55 55 mlx5_ldev_for_each(i, 0, ldev) { 56 - dev = ldev->pf[i].dev; 56 + dev = mlx5_lag_pf(ldev, i)->dev; 57 57 mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_MULTIPORT_ESW, 58 58 (void *)0); 59 59 } ··· 67 67 68 68 static int mlx5_lag_enable_mpesw(struct mlx5_lag *ldev) 69 69 { 70 + int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 70 71 struct mlx5_core_dev *dev0; 71 72 int err; 72 - int idx; 73 73 int i; 74 74 75 75 if (ldev->mode == MLX5_LAG_MODE_MPESW) ··· 78 78 if (ldev->mode != MLX5_LAG_MODE_NONE) 79 79 return -EINVAL; 80 80 81 - idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1); 82 81 if (idx < 0) 83 82 return -EINVAL; 84 83 85 - dev0 = ldev->pf[idx].dev; 84 + dev0 = mlx5_lag_pf(ldev, idx)->dev; 86 85 if (mlx5_eswitch_mode(dev0) != MLX5_ESWITCH_OFFLOADS || 87 86 !MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table) || 88 87 !MLX5_CAP_GEN(dev0, create_lag_when_not_master_up) || ··· 104 105 dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; 105 106 mlx5_rescan_drivers_locked(dev0); 106 107 mlx5_ldev_for_each(i, 0, ldev) { 107 - err = mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); 108 + err = mlx5_eswitch_reload_ib_reps(mlx5_lag_pf(ldev, i)->dev->priv.eswitch); 108 109 if (err) 109 110 goto err_rescan_drivers; 110 111 } ··· 120 121 err_add_devices: 121 122 mlx5_lag_add_devices(ldev); 122 123 mlx5_ldev_for_each(i, 0, ldev) 123 - mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch); 124 + mlx5_eswitch_reload_ib_reps(mlx5_lag_pf(ldev, i)->dev->priv.eswitch); 124 125 mlx5_mpesw_metadata_cleanup(ldev); 125 126 return err; 126 127 }
+18 -10
drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
··· 50 50 if (first_idx < 0) 51 51 return -EINVAL; 52 52 53 - dev = ldev->pf[first_idx].dev; 53 + dev = mlx5_lag_pf(ldev, first_idx)->dev; 54 54 ft_attr.max_fte = ldev->ports * ldev->buckets; 55 55 ft_attr.level = MLX5_LAG_FT_LEVEL_DEFINER; 56 56 ··· 84 84 idx = i * ldev->buckets + j; 85 85 affinity = ports[idx]; 86 86 87 - dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[affinity - 1].dev, 88 - vhca_id); 87 + /* affinity is 1-indexed device index, 88 + * use reverse lookup. 89 + */ 90 + dest.vport.vhca_id = 91 + MLX5_CAP_GEN(mlx5_lag_pf_by_dev_idx(ldev, affinity - 1)->dev, 92 + vhca_id); 89 93 lag_definer->rules[idx] = mlx5_add_flow_rules(lag_definer->ft, 90 94 NULL, &flow_act, 91 95 &dest, 1); ··· 311 307 if (first_idx < 0) 312 308 return ERR_PTR(-EINVAL); 313 309 314 - dev = ldev->pf[first_idx].dev; 310 + dev = mlx5_lag_pf(ldev, first_idx)->dev; 315 311 lag_definer = kzalloc_obj(*lag_definer); 316 312 if (!lag_definer) 317 313 return ERR_PTR(-ENOMEM); ··· 360 356 if (first_idx < 0) 361 357 return; 362 358 363 - dev = ldev->pf[first_idx].dev; 364 - mlx5_ldev_for_each(i, first_idx, ldev) { 359 + dev = mlx5_lag_pf(ldev, first_idx)->dev; 360 + mlx5_ldev_for_each(i, 0, ldev) { 365 361 for (j = 0; j < ldev->buckets; j++) { 366 362 idx = i * ldev->buckets + j; 367 363 mlx5_del_flow_rules(lag_definer->rules[idx]); ··· 524 520 if (first_idx < 0) 525 521 return -EINVAL; 526 522 527 - dev = ldev->pf[first_idx].dev; 523 + dev = mlx5_lag_pf(ldev, first_idx)->dev; 528 524 mlx5_lag_set_outer_ttc_params(ldev, &ttc_params); 529 525 port_sel->outer.ttc = mlx5_create_ttc_table(dev, &ttc_params); 530 526 return PTR_ERR_OR_ZERO(port_sel->outer.ttc); ··· 540 536 if (first_idx < 0) 541 537 return -EINVAL; 542 538 543 - dev = ldev->pf[first_idx].dev; 539 + dev = mlx5_lag_pf(ldev, first_idx)->dev; 544 540 mlx5_lag_set_inner_ttc_params(ldev, &ttc_params); 545 541 port_sel->inner.ttc = mlx5_create_inner_ttc_table(dev, &ttc_params); 546 542 return PTR_ERR_OR_ZERO(port_sel->inner.ttc); ··· 598 594 if (ldev->v2p_map[idx] == ports[idx]) 599 595 continue; 600 596 601 - dest.vport.vhca_id = MLX5_CAP_GEN(ldev->pf[ports[idx] - 1].dev, 602 - vhca_id); 597 + /* ports[] contains 1-indexed device indices, 598 + * use reverse lookup. 599 + */ 600 + dest.vport.vhca_id = 601 + MLX5_CAP_GEN(mlx5_lag_pf_by_dev_idx(ldev, ports[idx] - 1)->dev, 602 + vhca_id); 603 603 err = mlx5_modify_rule_destination(def->rules[idx], &dest, NULL); 604 604 if (err) 605 605 return err;
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/lib/sd.c
··· 107 107 /* Disconnect secondaries from the network */ 108 108 if (!MLX5_CAP_GEN(dev, eswitch_manager)) 109 109 return false; 110 - if (!MLX5_CAP_GEN(dev, silent_mode)) 110 + if (!MLX5_CAP_GEN(dev, silent_mode_set)) 111 111 return false; 112 112 113 113 /* RX steering from primary to secondaries */
+1
drivers/net/ethernet/mellanox/mlx5/core/main.c
··· 1779 1779 MLX5_CAP_CRYPTO, 1780 1780 MLX5_CAP_SHAMPO, 1781 1781 MLX5_CAP_ADV_RDMA, 1782 + MLX5_CAP_TLP_EMULATION, 1782 1783 }; 1783 1784 1784 1785 static void mlx5_hca_caps_free(struct mlx5_core_dev *dev)
+10
include/linux/mlx5/device.h
··· 293 293 MLX5_UMR_INLINE = (1 << 7), 294 294 }; 295 295 296 + #define MLX5_UMR_ALIGN (2048) 296 297 #define MLX5_UMR_FLEX_ALIGNMENT 0x40 297 298 #define MLX5_UMR_MTT_NUM_ENTRIES_ALIGNMENT (MLX5_UMR_FLEX_ALIGNMENT / sizeof(struct mlx5_mtt)) 298 299 #define MLX5_UMR_KLM_NUM_ENTRIES_ALIGNMENT (MLX5_UMR_FLEX_ALIGNMENT / sizeof(struct mlx5_klm)) ··· 1260 1259 MLX5_CAP_PORT_SELECTION = 0x25, 1261 1260 MLX5_CAP_ADV_VIRTUALIZATION = 0x26, 1262 1261 MLX5_CAP_ADV_RDMA = 0x28, 1262 + MLX5_CAP_TLP_EMULATION = 0x2a, 1263 1263 /* NUM OF CAP Types */ 1264 1264 MLX5_CAP_NUM 1265 1265 }; ··· 1482 1480 #define MLX5_CAP64_DEV_VDPA_EMULATION(mdev, cap)\ 1483 1481 MLX5_GET64(virtio_emulation_cap, \ 1484 1482 (mdev)->caps.hca[MLX5_CAP_VDPA_EMULATION]->cur, cap) 1483 + 1484 + #define MLX5_CAP_DEV_TLP_EMULATION(mdev, cap)\ 1485 + MLX5_GET(tlp_dev_emu_capabilities, \ 1486 + (mdev)->caps.hca[MLX5_CAP_TLP_EMULATION]->cur, cap) 1487 + 1488 + #define MLX5_CAP64_DEV_TLP_EMULATION(mdev, cap)\ 1489 + MLX5_GET64(tlp_dev_emu_capabilities, \ 1490 + (mdev)->caps.hca[MLX5_CAP_TLP_EMULATION]->cur, cap) 1485 1491 1486 1492 #define MLX5_CAP_IPSEC(mdev, cap)\ 1487 1493 MLX5_GET(ipsec_cap, (mdev)->caps.hca[MLX5_CAP_IPSEC]->cur, cap)
+7 -3
include/linux/mlx5/fs.h
··· 55 55 MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE_NUM, 56 56 MLX5_FLOW_DESTINATION_TYPE_RANGE, 57 57 MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE, 58 + MLX5_FLOW_DESTINATION_TYPE_VHCA_RX, 58 59 }; 59 60 60 61 enum { ··· 191 190 struct mlx5_flow_table *ft; 192 191 struct mlx5_fc *counter; 193 192 struct { 193 + u16 id; 194 + } vhca; 195 + struct { 194 196 u16 num; 195 197 u16 vhca_id; 196 198 struct mlx5_pkt_reformat *pkt_reformat; ··· 252 248 struct mlx5_flow_table * 253 249 mlx5_create_vport_flow_table(struct mlx5_flow_namespace *ns, 254 250 struct mlx5_flow_table_attr *ft_attr, u16 vport); 255 - struct mlx5_flow_table *mlx5_create_lag_demux_flow_table( 256 - struct mlx5_flow_namespace *ns, 257 - int prio, u32 level); 251 + struct mlx5_flow_table * 252 + mlx5_create_lag_demux_flow_table(struct mlx5_flow_namespace *ns, 253 + struct mlx5_flow_table_attr *ft_attr); 258 254 int mlx5_destroy_flow_table(struct mlx5_flow_table *ft); 259 255 260 256 /* inbox should be set with the following values:
+21
include/linux/mlx5/lag.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ 2 + /* Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 + 4 + #ifndef __MLX5_LAG_API_H__ 5 + #define __MLX5_LAG_API_H__ 6 + 7 + #include <linux/types.h> 8 + 9 + struct mlx5_core_dev; 10 + struct mlx5_flow_table; 11 + struct mlx5_flow_table_attr; 12 + 13 + int mlx5_lag_demux_init(struct mlx5_core_dev *dev, 14 + struct mlx5_flow_table_attr *ft_attr); 15 + void mlx5_lag_demux_cleanup(struct mlx5_core_dev *dev); 16 + int mlx5_lag_demux_rule_add(struct mlx5_core_dev *dev, u16 vport_num, 17 + int vport_index); 18 + void mlx5_lag_demux_rule_del(struct mlx5_core_dev *dev, int vport_index); 19 + int mlx5_lag_get_dev_seq(struct mlx5_core_dev *dev); 20 + 21 + #endif /* __MLX5_LAG_API_H__ */
+41 -8
include/linux/mlx5/mlx5_ifc.h
··· 469 469 u8 table_miss_action_domain[0x1]; 470 470 u8 termination_table[0x1]; 471 471 u8 reformat_and_fwd_to_table[0x1]; 472 - u8 reserved_at_1a[0x2]; 472 + u8 forward_vhca_rx[0x1]; 473 + u8 reserved_at_1b[0x1]; 473 474 u8 ipsec_encrypt[0x1]; 474 475 u8 ipsec_decrypt[0x1]; 475 476 u8 sw_owner_v2[0x1]; ··· 1390 1389 u8 reserved_at_1c0[0x640]; 1391 1390 }; 1392 1391 1392 + struct mlx5_ifc_tlp_dev_emu_capabilities_bits { 1393 + u8 reserved_at_0[0x20]; 1394 + 1395 + u8 reserved_at_20[0x13]; 1396 + u8 log_tlp_rsp_gw_page_stride[0x5]; 1397 + u8 reserved_at_38[0x8]; 1398 + 1399 + u8 reserved_at_40[0xc0]; 1400 + 1401 + u8 reserved_at_100[0xc]; 1402 + u8 tlp_rsp_gw_num_pages[0x4]; 1403 + u8 reserved_at_110[0x10]; 1404 + 1405 + u8 reserved_at_120[0xa0]; 1406 + 1407 + u8 tlp_rsp_gw_pages_bar_offset[0x40]; 1408 + 1409 + u8 reserved_at_200[0x600]; 1410 + }; 1411 + 1393 1412 enum { 1394 1413 MLX5_ATOMIC_CAPS_ATOMIC_SIZE_QP_1_BYTE = 0x0, 1395 1414 MLX5_ATOMIC_CAPS_ATOMIC_SIZE_QP_2_BYTES = 0x2, ··· 1982 1961 u8 log_max_rqt[0x5]; 1983 1962 u8 reserved_at_390[0x3]; 1984 1963 u8 log_max_rqt_size[0x5]; 1985 - u8 reserved_at_398[0x1]; 1964 + u8 tlp_device_emulation_manager[0x1]; 1986 1965 u8 vnic_env_cnt_bar_uar_access[0x1]; 1987 1966 u8 vnic_env_cnt_odp_page_fault[0x1]; 1988 1967 u8 log_max_tis_per_sq[0x5]; ··· 2013 1992 u8 disable_local_lb_mc[0x1]; 2014 1993 u8 log_min_hairpin_wq_data_sz[0x5]; 2015 1994 u8 reserved_at_3e8[0x1]; 2016 - u8 silent_mode[0x1]; 1995 + u8 silent_mode_set[0x1]; 2017 1996 u8 vhca_state[0x1]; 2018 1997 u8 log_max_vlan_list[0x5]; 2019 1998 u8 reserved_at_3f0[0x3]; 2020 1999 u8 log_max_current_mc_list[0x5]; 2021 - u8 reserved_at_3f8[0x3]; 2000 + u8 reserved_at_3f8[0x1]; 2001 + u8 silent_mode_query[0x1]; 2002 + u8 reserved_at_3fa[0x1]; 2022 2003 u8 log_max_current_uc_list[0x5]; 2023 2004 2024 2005 u8 general_obj_types[0x40]; ··· 2282 2259 MLX5_IFC_FLOW_DESTINATION_TYPE_VPORT = 0x0, 2283 2260 MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_TABLE = 0x1, 2284 2261 MLX5_IFC_FLOW_DESTINATION_TYPE_TIR = 0x2, 2262 + MLX5_IFC_FLOW_DESTINATION_TYPE_VHCA_RX = 0x4, 2285 2263 MLX5_IFC_FLOW_DESTINATION_TYPE_FLOW_SAMPLER = 0x6, 2286 2264 MLX5_IFC_FLOW_DESTINATION_TYPE_UPLINK = 0x8, 2287 2265 MLX5_IFC_FLOW_DESTINATION_TYPE_TABLE_TYPE = 0xA, ··· 3854 3830 struct mlx5_ifc_tls_cap_bits tls_cap; 3855 3831 struct mlx5_ifc_device_mem_cap_bits device_mem_cap; 3856 3832 struct mlx5_ifc_virtio_emulation_cap_bits virtio_emulation_cap; 3833 + struct mlx5_ifc_tlp_dev_emu_capabilities_bits tlp_dev_emu_capabilities; 3857 3834 struct mlx5_ifc_macsec_cap_bits macsec_cap; 3858 3835 struct mlx5_ifc_crypto_cap_bits crypto_cap; 3859 3836 struct mlx5_ifc_ipsec_cap_bits ipsec_cap; ··· 6269 6244 6270 6245 u8 reserved_at_40[0xa0]; 6271 6246 6272 - u8 reserved_at_e0[0x13]; 6247 + u8 reserved_at_e0[0x11]; 6248 + u8 silent_mode[0x1]; 6249 + u8 reserved_at_f2[0x1]; 6273 6250 u8 vlan_valid[0x1]; 6274 6251 u8 vlan[0xc]; 6275 6252 ··· 6287 6260 u8 reserved_at_20[0x10]; 6288 6261 u8 op_mod[0x10]; 6289 6262 6290 - u8 reserved_at_40[0x60]; 6263 + u8 reserved_at_40[0x40]; 6264 + 6265 + u8 silent_mode_query[0x1]; 6266 + u8 reserved_at_81[0x1f]; 6291 6267 6292 6268 u8 reserved_at_a0[0x8]; 6293 6269 u8 table_index[0x18]; ··· 10854 10824 u8 fec_200G_per_lane_in_pplm[0x1]; 10855 10825 u8 reserved_at_1e[0x2a]; 10856 10826 u8 fec_100G_per_lane_in_pplm[0x1]; 10857 - u8 reserved_at_49[0xa]; 10827 + u8 reserved_at_49[0x2]; 10828 + u8 shp_pbmc_pbsr_support[0x1]; 10829 + u8 reserved_at_4c[0x7]; 10858 10830 u8 buffer_ownership[0x1]; 10859 10831 u8 resereved_at_54[0x14]; 10860 10832 u8 fec_50G_per_lane_in_pplm[0x1]; ··· 12101 12069 u8 port_buffer_size[0x10]; 12102 12070 12103 12071 struct mlx5_ifc_bufferx_reg_bits buffer[10]; 12072 + struct mlx5_ifc_bufferx_reg_bits shared_headroom_pool; 12104 12073 12105 - u8 reserved_at_2e0[0x80]; 12074 + u8 reserved_at_320[0x40]; 12106 12075 }; 12107 12076 12108 12077 struct mlx5_ifc_sbpr_reg_bits {