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-support-setting-a-parent-for-a-devlink-rate-node'

Tariq Toukan says:

====================
mlx5: Support setting a parent for a devlink rate node

This series by Carolina adds mlx5 support for the setting of a parent to
devlink rate nodes.

By introducing a hierarchical level to scheduling nodes, these changes
allow for more granular control over bandwidth allocation and isolation
of Virtual Functions.

Function renaming for parent setting on leafs:
- net/mlx5: Rename devlink rate parent set function for leaf nodes

Add support for hierarchy level tracking:
- net/mlx5: Introduce hierarchy level tracking on scheduling nodes
- net/mlx5: Preserve rate settings when creating a rate node

Support setting parent for rate nodes:
- net/mlx5: Add support for setting parent of nodes
====================

Link: https://patch.msgid.link/1741642016-44918-1-git-send-email-tariqt@nvidia.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+143 -18
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/devlink.c
··· 327 327 .rate_node_tx_max_set = mlx5_esw_devlink_rate_node_tx_max_set, 328 328 .rate_node_new = mlx5_esw_devlink_rate_node_new, 329 329 .rate_node_del = mlx5_esw_devlink_rate_node_del, 330 - .rate_leaf_parent_set = mlx5_esw_devlink_rate_parent_set, 330 + .rate_leaf_parent_set = mlx5_esw_devlink_rate_leaf_parent_set, 331 + .rate_node_parent_set = mlx5_esw_devlink_rate_node_parent_set, 331 332 #endif 332 333 #ifdef CONFIG_MLX5_SF_MANAGER 333 334 .port_new = mlx5_devlink_sf_port_new,
+133 -13
drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
··· 90 90 struct list_head children; 91 91 /* Valid only if this node is associated with a vport. */ 92 92 struct mlx5_vport *vport; 93 + /* Level in the hierarchy. The root node level is 1. */ 94 + u8 level; 93 95 }; 96 + 97 + static void esw_qos_node_attach_to_parent(struct mlx5_esw_sched_node *node) 98 + { 99 + if (!node->parent) { 100 + /* Root children are assigned a depth level of 2. */ 101 + node->level = 2; 102 + list_add_tail(&node->entry, &node->esw->qos.domain->nodes); 103 + } else { 104 + node->level = node->parent->level + 1; 105 + list_add_tail(&node->entry, &node->parent->children); 106 + } 107 + } 94 108 95 109 static void 96 110 esw_qos_node_set_parent(struct mlx5_esw_sched_node *node, struct mlx5_esw_sched_node *parent) 97 111 { 98 112 list_del_init(&node->entry); 99 113 node->parent = parent; 100 - list_add_tail(&node->entry, &parent->children); 101 - node->esw = parent->esw; 114 + if (parent) 115 + node->esw = parent->esw; 116 + esw_qos_node_attach_to_parent(node); 102 117 } 103 118 104 119 void mlx5_esw_qos_vport_qos_free(struct mlx5_vport *vport) ··· 320 305 return 0; 321 306 } 322 307 323 - static int esw_qos_create_node_sched_elem(struct mlx5_core_dev *dev, u32 parent_element_id, 324 - u32 *tsar_ix) 308 + static int 309 + esw_qos_create_node_sched_elem(struct mlx5_core_dev *dev, u32 parent_element_id, 310 + u32 max_rate, u32 bw_share, u32 *tsar_ix) 325 311 { 326 312 u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {}; 327 313 void *attr; ··· 339 323 SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR); 340 324 MLX5_SET(scheduling_context, tsar_ctx, parent_element_id, 341 325 parent_element_id); 326 + MLX5_SET(scheduling_context, tsar_ctx, max_average_bw, max_rate); 327 + MLX5_SET(scheduling_context, tsar_ctx, bw_share, bw_share); 342 328 attr = MLX5_ADDR_OF(scheduling_context, tsar_ctx, element_attributes); 343 329 MLX5_SET(tsar_element, attr, tsar_type, TSAR_ELEMENT_TSAR_TYPE_DWRR); 344 330 ··· 376 358 __esw_qos_alloc_node(struct mlx5_eswitch *esw, u32 tsar_ix, enum sched_node_type type, 377 359 struct mlx5_esw_sched_node *parent) 378 360 { 379 - struct list_head *parent_children; 380 361 struct mlx5_esw_sched_node *node; 381 362 382 363 node = kzalloc(sizeof(*node), GFP_KERNEL); ··· 387 370 node->type = type; 388 371 node->parent = parent; 389 372 INIT_LIST_HEAD(&node->children); 390 - parent_children = parent ? &parent->children : &esw->qos.domain->nodes; 391 - list_add_tail(&node->entry, parent_children); 373 + esw_qos_node_attach_to_parent(node); 392 374 393 375 return node; 394 376 } ··· 412 396 u32 tsar_ix; 413 397 int err; 414 398 415 - err = esw_qos_create_node_sched_elem(esw->dev, esw->qos.root_tsar_ix, &tsar_ix); 399 + err = esw_qos_create_node_sched_elem(esw->dev, esw->qos.root_tsar_ix, 0, 400 + 0, &tsar_ix); 416 401 if (err) { 417 402 NL_SET_ERR_MSG_MOD(extack, "E-Switch create TSAR for node failed"); 418 403 return ERR_PTR(err); ··· 480 463 if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling)) 481 464 return -EOPNOTSUPP; 482 465 483 - err = esw_qos_create_node_sched_elem(esw->dev, 0, &esw->qos.root_tsar_ix); 466 + err = esw_qos_create_node_sched_elem(esw->dev, 0, 0, 0, 467 + &esw->qos.root_tsar_ix); 484 468 if (err) { 485 469 esw_warn(dev, "E-Switch create root TSAR failed (%d)\n", err); 486 470 return err; ··· 1004 986 return err; 1005 987 } 1006 988 1007 - int mlx5_esw_devlink_rate_parent_set(struct devlink_rate *devlink_rate, 1008 - struct devlink_rate *parent, 1009 - void *priv, void *parent_priv, 1010 - struct netlink_ext_ack *extack) 989 + int mlx5_esw_devlink_rate_leaf_parent_set(struct devlink_rate *devlink_rate, 990 + struct devlink_rate *parent, 991 + void *priv, void *parent_priv, 992 + struct netlink_ext_ack *extack) 1011 993 { 1012 994 struct mlx5_esw_sched_node *node; 1013 995 struct mlx5_vport *vport = priv; ··· 1017 999 1018 1000 node = parent_priv; 1019 1001 return mlx5_esw_qos_vport_update_parent(vport, node, extack); 1002 + } 1003 + 1004 + static int 1005 + mlx5_esw_qos_node_validate_set_parent(struct mlx5_esw_sched_node *node, 1006 + struct mlx5_esw_sched_node *parent, 1007 + struct netlink_ext_ack *extack) 1008 + { 1009 + u8 new_level, max_level; 1010 + 1011 + if (parent && parent->esw != node->esw) { 1012 + NL_SET_ERR_MSG_MOD(extack, 1013 + "Cannot assign node to another E-Switch"); 1014 + return -EOPNOTSUPP; 1015 + } 1016 + 1017 + if (!list_empty(&node->children)) { 1018 + NL_SET_ERR_MSG_MOD(extack, 1019 + "Cannot reassign a node that contains rate objects"); 1020 + return -EOPNOTSUPP; 1021 + } 1022 + 1023 + new_level = parent ? parent->level + 1 : 2; 1024 + max_level = 1 << MLX5_CAP_QOS(node->esw->dev, log_esw_max_sched_depth); 1025 + if (new_level > max_level) { 1026 + NL_SET_ERR_MSG_MOD(extack, 1027 + "Node hierarchy depth exceeds the maximum supported level"); 1028 + return -EOPNOTSUPP; 1029 + } 1030 + 1031 + return 0; 1032 + } 1033 + 1034 + static int esw_qos_vports_node_update_parent(struct mlx5_esw_sched_node *node, 1035 + struct mlx5_esw_sched_node *parent, 1036 + struct netlink_ext_ack *extack) 1037 + { 1038 + struct mlx5_esw_sched_node *curr_parent = node->parent; 1039 + struct mlx5_eswitch *esw = node->esw; 1040 + u32 parent_ix; 1041 + int err; 1042 + 1043 + parent_ix = parent ? parent->ix : node->esw->qos.root_tsar_ix; 1044 + mlx5_destroy_scheduling_element_cmd(esw->dev, 1045 + SCHEDULING_HIERARCHY_E_SWITCH, 1046 + node->ix); 1047 + err = esw_qos_create_node_sched_elem(esw->dev, parent_ix, 1048 + node->max_rate, 0, &node->ix); 1049 + if (err) { 1050 + NL_SET_ERR_MSG_MOD(extack, 1051 + "Failed to create a node under the new hierarchy."); 1052 + if (esw_qos_create_node_sched_elem(esw->dev, curr_parent->ix, 1053 + node->max_rate, 1054 + node->bw_share, 1055 + &node->ix)) 1056 + esw_warn(esw->dev, "Node restore QoS failed\n"); 1057 + 1058 + return err; 1059 + } 1060 + esw_qos_node_set_parent(node, parent); 1061 + 1062 + return 0; 1063 + } 1064 + 1065 + static int mlx5_esw_qos_node_update_parent(struct mlx5_esw_sched_node *node, 1066 + struct mlx5_esw_sched_node *parent, 1067 + struct netlink_ext_ack *extack) 1068 + { 1069 + struct mlx5_esw_sched_node *curr_parent; 1070 + struct mlx5_eswitch *esw = node->esw; 1071 + int err; 1072 + 1073 + err = mlx5_esw_qos_node_validate_set_parent(node, parent, extack); 1074 + if (err) 1075 + return err; 1076 + 1077 + esw_qos_lock(esw); 1078 + curr_parent = node->parent; 1079 + err = esw_qos_vports_node_update_parent(node, parent, extack); 1080 + if (err) 1081 + goto out; 1082 + 1083 + esw_qos_normalize_min_rate(esw, curr_parent, extack); 1084 + esw_qos_normalize_min_rate(esw, parent, extack); 1085 + 1086 + out: 1087 + esw_qos_unlock(esw); 1088 + 1089 + return err; 1090 + } 1091 + 1092 + int mlx5_esw_devlink_rate_node_parent_set(struct devlink_rate *devlink_rate, 1093 + struct devlink_rate *parent, 1094 + void *priv, void *parent_priv, 1095 + struct netlink_ext_ack *extack) 1096 + { 1097 + struct mlx5_esw_sched_node *node = priv, *parent_node; 1098 + 1099 + if (!parent) 1100 + return mlx5_esw_qos_node_update_parent(node, NULL, extack); 1101 + 1102 + parent_node = parent_priv; 1103 + return mlx5_esw_qos_node_update_parent(node, parent_node, extack); 1020 1104 }
+8 -4
drivers/net/ethernet/mellanox/mlx5/core/esw/qos.h
··· 29 29 struct netlink_ext_ack *extack); 30 30 int mlx5_esw_devlink_rate_node_del(struct devlink_rate *rate_node, void *priv, 31 31 struct netlink_ext_ack *extack); 32 - int mlx5_esw_devlink_rate_parent_set(struct devlink_rate *devlink_rate, 33 - struct devlink_rate *parent, 34 - void *priv, void *parent_priv, 35 - struct netlink_ext_ack *extack); 32 + int mlx5_esw_devlink_rate_leaf_parent_set(struct devlink_rate *devlink_rate, 33 + struct devlink_rate *parent, 34 + void *priv, void *parent_priv, 35 + struct netlink_ext_ack *extack); 36 + int mlx5_esw_devlink_rate_node_parent_set(struct devlink_rate *devlink_rate, 37 + struct devlink_rate *parent, 38 + void *priv, void *parent_priv, 39 + struct netlink_ext_ack *extack); 36 40 #endif 37 41 38 42 #endif