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 tag 'mlx5-updates-2022-07-17' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
mlx5-updates-2022-07-17

1) Add resiliency for lost completions for PTP TX port timestamp

2) Report Header-data split state via ethtool

3) Decouple HTB code from main regular TX code

* tag 'mlx5-updates-2022-07-17' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux:
net/mlx5: CT: Remove warning of ignore_flow_level support for non PF
net/mlx5e: Add resiliency for PTP TX port timestamp
net/mlx5: Expose ts_cqe_metadata_size2wqe_counter
net/mlx5e: HTB, move htb functions to a new file
net/mlx5e: HTB, change functions name to follow convention
net/mlx5e: HTB, remove priv from htb function calls
net/mlx5e: HTB, hide and dynamically allocate mlx5e_htb structure
net/mlx5e: HTB, move stats and max_sqs to priv
net/mlx5e: HTB, move section comment to the right place
net/mlx5e: HTB, move ids to selq_params struct
net/mlx5e: HTB, reduce visibility of htb functions
net/mlx5e: Fix mqprio_rl handling on devlink reload
net/mlx5e: Report header-data split state through ethtool
====================

Link: https://lore.kernel.org/r/20220719203529.51151-1-saeed@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+1157 -861
+2 -1
drivers/net/ethernet/mellanox/mlx5/core/Makefile
··· 28 28 en_selftest.o en/port.o en/monitor_stats.o en/health.o \ 29 29 en/reporter_tx.o en/reporter_rx.o en/params.o en/xsk/pool.o \ 30 30 en/xsk/setup.o en/xsk/rx.o en/xsk/tx.o en/devlink.o en/ptp.o \ 31 - en/qos.o en/trap.o en/fs_tt_redirect.o en/selq.o lib/crypto.o 31 + en/qos.o en/htb.o en/trap.o en/fs_tt_redirect.o en/selq.o \ 32 + lib/crypto.o 32 33 33 34 # 34 35 # Netdev extra
+8 -12
drivers/net/ethernet/mellanox/mlx5/core/en.h
··· 321 321 u8 num_tc; 322 322 struct netdev_tc_txq tc_to_txq[TC_MAX_QUEUE]; 323 323 struct { 324 - struct mlx5e_mqprio_rl *rl; 324 + u64 max_rate[TC_MAX_QUEUE]; 325 + u32 hw_id[TC_MAX_QUEUE]; 325 326 } channel; 326 327 } mqprio; 327 328 bool rx_cqe_compress_def; ··· 899 898 cpumask_var_t cpumask; 900 899 }; 901 900 902 - struct mlx5e_htb { 903 - DECLARE_HASHTABLE(qos_tc2node, order_base_2(MLX5E_QOS_MAX_LEAF_NODES)); 904 - DECLARE_BITMAP(qos_used_qids, MLX5E_QOS_MAX_LEAF_NODES); 905 - struct mlx5e_sq_stats **qos_sq_stats; 906 - u16 max_qos_sqs; 907 - u16 maj_id; 908 - u16 defcls; 909 - }; 910 - 911 901 struct mlx5e_trap; 902 + struct mlx5e_htb; 912 903 913 904 struct mlx5e_priv { 914 905 /* priv data path fields - start */ ··· 938 945 struct mlx5e_channel_stats **channel_stats; 939 946 struct mlx5e_channel_stats trap_stats; 940 947 struct mlx5e_ptp_stats ptp_stats; 948 + struct mlx5e_sq_stats **htb_qos_sq_stats; 949 + u16 htb_max_qos_sqs; 941 950 u16 stats_nch; 942 951 u16 max_nch; 943 952 u8 max_opened_tc; ··· 971 976 struct mlx5e_hv_vhca_stats_agent stats_agent; 972 977 #endif 973 978 struct mlx5e_scratchpad scratchpad; 974 - struct mlx5e_htb htb; 979 + struct mlx5e_htb *htb; 975 980 struct mlx5e_mqprio_rl *mqprio_rl; 976 981 }; 977 982 ··· 1176 1181 void mlx5e_ethtool_get_ethtool_stats(struct mlx5e_priv *priv, 1177 1182 struct ethtool_stats *stats, u64 *data); 1178 1183 void mlx5e_ethtool_get_ringparam(struct mlx5e_priv *priv, 1179 - struct ethtool_ringparam *param); 1184 + struct ethtool_ringparam *param, 1185 + struct kernel_ethtool_ringparam *kernel_param); 1180 1186 int mlx5e_ethtool_set_ringparam(struct mlx5e_priv *priv, 1181 1187 struct ethtool_ringparam *param); 1182 1188 void mlx5e_ethtool_get_channels(struct mlx5e_priv *priv,
+722
drivers/net/ethernet/mellanox/mlx5/core/en/htb.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB 2 + /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 + 4 + #include <net/pkt_cls.h> 5 + #include "htb.h" 6 + #include "en.h" 7 + #include "../qos.h" 8 + 9 + struct mlx5e_qos_node { 10 + struct hlist_node hnode; 11 + struct mlx5e_qos_node *parent; 12 + u64 rate; 13 + u32 bw_share; 14 + u32 max_average_bw; 15 + u32 hw_id; 16 + u32 classid; /* 16-bit, except root. */ 17 + u16 qid; 18 + }; 19 + 20 + struct mlx5e_htb { 21 + DECLARE_HASHTABLE(qos_tc2node, order_base_2(MLX5E_QOS_MAX_LEAF_NODES)); 22 + DECLARE_BITMAP(qos_used_qids, MLX5E_QOS_MAX_LEAF_NODES); 23 + struct mlx5_core_dev *mdev; 24 + struct net_device *netdev; 25 + struct mlx5e_priv *priv; 26 + struct mlx5e_selq *selq; 27 + }; 28 + 29 + #define MLX5E_QOS_QID_INNER 0xffff 30 + #define MLX5E_HTB_CLASSID_ROOT 0xffffffff 31 + 32 + /* Software representation of the QoS tree */ 33 + 34 + int mlx5e_htb_enumerate_leaves(struct mlx5e_htb *htb, mlx5e_fp_htb_enumerate callback, void *data) 35 + { 36 + struct mlx5e_qos_node *node = NULL; 37 + int bkt, err; 38 + 39 + hash_for_each(htb->qos_tc2node, bkt, node, hnode) { 40 + if (node->qid == MLX5E_QOS_QID_INNER) 41 + continue; 42 + err = callback(data, node->qid, node->hw_id); 43 + if (err) 44 + return err; 45 + } 46 + return 0; 47 + } 48 + 49 + int mlx5e_htb_cur_leaf_nodes(struct mlx5e_htb *htb) 50 + { 51 + int last; 52 + 53 + last = find_last_bit(htb->qos_used_qids, mlx5e_qos_max_leaf_nodes(htb->mdev)); 54 + return last == mlx5e_qos_max_leaf_nodes(htb->mdev) ? 0 : last + 1; 55 + } 56 + 57 + static int mlx5e_htb_find_unused_qos_qid(struct mlx5e_htb *htb) 58 + { 59 + int size = mlx5e_qos_max_leaf_nodes(htb->mdev); 60 + struct mlx5e_priv *priv = htb->priv; 61 + int res; 62 + 63 + WARN_ONCE(!mutex_is_locked(&priv->state_lock), "%s: state_lock is not held\n", __func__); 64 + res = find_first_zero_bit(htb->qos_used_qids, size); 65 + 66 + return res == size ? -ENOSPC : res; 67 + } 68 + 69 + static struct mlx5e_qos_node * 70 + mlx5e_htb_node_create_leaf(struct mlx5e_htb *htb, u16 classid, u16 qid, 71 + struct mlx5e_qos_node *parent) 72 + { 73 + struct mlx5e_qos_node *node; 74 + 75 + node = kzalloc(sizeof(*node), GFP_KERNEL); 76 + if (!node) 77 + return ERR_PTR(-ENOMEM); 78 + 79 + node->parent = parent; 80 + 81 + node->qid = qid; 82 + __set_bit(qid, htb->qos_used_qids); 83 + 84 + node->classid = classid; 85 + hash_add_rcu(htb->qos_tc2node, &node->hnode, classid); 86 + 87 + mlx5e_update_tx_netdev_queues(htb->priv); 88 + 89 + return node; 90 + } 91 + 92 + static struct mlx5e_qos_node *mlx5e_htb_node_create_root(struct mlx5e_htb *htb) 93 + { 94 + struct mlx5e_qos_node *node; 95 + 96 + node = kzalloc(sizeof(*node), GFP_KERNEL); 97 + if (!node) 98 + return ERR_PTR(-ENOMEM); 99 + 100 + node->qid = MLX5E_QOS_QID_INNER; 101 + node->classid = MLX5E_HTB_CLASSID_ROOT; 102 + hash_add_rcu(htb->qos_tc2node, &node->hnode, node->classid); 103 + 104 + return node; 105 + } 106 + 107 + static struct mlx5e_qos_node *mlx5e_htb_node_find(struct mlx5e_htb *htb, u32 classid) 108 + { 109 + struct mlx5e_qos_node *node = NULL; 110 + 111 + hash_for_each_possible(htb->qos_tc2node, node, hnode, classid) { 112 + if (node->classid == classid) 113 + break; 114 + } 115 + 116 + return node; 117 + } 118 + 119 + static struct mlx5e_qos_node *mlx5e_htb_node_find_rcu(struct mlx5e_htb *htb, u32 classid) 120 + { 121 + struct mlx5e_qos_node *node = NULL; 122 + 123 + hash_for_each_possible_rcu(htb->qos_tc2node, node, hnode, classid) { 124 + if (node->classid == classid) 125 + break; 126 + } 127 + 128 + return node; 129 + } 130 + 131 + static void mlx5e_htb_node_delete(struct mlx5e_htb *htb, struct mlx5e_qos_node *node) 132 + { 133 + hash_del_rcu(&node->hnode); 134 + if (node->qid != MLX5E_QOS_QID_INNER) { 135 + __clear_bit(node->qid, htb->qos_used_qids); 136 + mlx5e_update_tx_netdev_queues(htb->priv); 137 + } 138 + /* Make sure this qid is no longer selected by mlx5e_select_queue, so 139 + * that mlx5e_reactivate_qos_sq can safely restart the netdev TX queue. 140 + */ 141 + synchronize_net(); 142 + kfree(node); 143 + } 144 + 145 + /* TX datapath API */ 146 + 147 + int mlx5e_htb_get_txq_by_classid(struct mlx5e_htb *htb, u16 classid) 148 + { 149 + struct mlx5e_qos_node *node; 150 + u16 qid; 151 + int res; 152 + 153 + rcu_read_lock(); 154 + 155 + node = mlx5e_htb_node_find_rcu(htb, classid); 156 + if (!node) { 157 + res = -ENOENT; 158 + goto out; 159 + } 160 + qid = READ_ONCE(node->qid); 161 + if (qid == MLX5E_QOS_QID_INNER) { 162 + res = -EINVAL; 163 + goto out; 164 + } 165 + res = mlx5e_qid_from_qos(&htb->priv->channels, qid); 166 + 167 + out: 168 + rcu_read_unlock(); 169 + return res; 170 + } 171 + 172 + /* HTB TC handlers */ 173 + 174 + static int 175 + mlx5e_htb_root_add(struct mlx5e_htb *htb, u16 htb_maj_id, u16 htb_defcls, 176 + struct netlink_ext_ack *extack) 177 + { 178 + struct mlx5e_priv *priv = htb->priv; 179 + struct mlx5e_qos_node *root; 180 + bool opened; 181 + int err; 182 + 183 + qos_dbg(htb->mdev, "TC_HTB_CREATE handle %04x:, default :%04x\n", htb_maj_id, htb_defcls); 184 + 185 + mlx5e_selq_prepare_htb(htb->selq, htb_maj_id, htb_defcls); 186 + 187 + opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 188 + if (opened) { 189 + err = mlx5e_qos_alloc_queues(priv, &priv->channels); 190 + if (err) 191 + goto err_cancel_selq; 192 + } 193 + 194 + root = mlx5e_htb_node_create_root(htb); 195 + if (IS_ERR(root)) { 196 + err = PTR_ERR(root); 197 + goto err_free_queues; 198 + } 199 + 200 + err = mlx5_qos_create_root_node(htb->mdev, &root->hw_id); 201 + if (err) { 202 + NL_SET_ERR_MSG_MOD(extack, "Firmware error. Try upgrading firmware."); 203 + goto err_sw_node_delete; 204 + } 205 + 206 + mlx5e_selq_apply(htb->selq); 207 + 208 + return 0; 209 + 210 + err_sw_node_delete: 211 + mlx5e_htb_node_delete(htb, root); 212 + 213 + err_free_queues: 214 + if (opened) 215 + mlx5e_qos_close_all_queues(&priv->channels); 216 + err_cancel_selq: 217 + mlx5e_selq_cancel(htb->selq); 218 + return err; 219 + } 220 + 221 + static int mlx5e_htb_root_del(struct mlx5e_htb *htb) 222 + { 223 + struct mlx5e_priv *priv = htb->priv; 224 + struct mlx5e_qos_node *root; 225 + int err; 226 + 227 + qos_dbg(htb->mdev, "TC_HTB_DESTROY\n"); 228 + 229 + /* Wait until real_num_tx_queues is updated for mlx5e_select_queue, 230 + * so that we can safely switch to its non-HTB non-PTP fastpath. 231 + */ 232 + synchronize_net(); 233 + 234 + mlx5e_selq_prepare_htb(htb->selq, 0, 0); 235 + mlx5e_selq_apply(htb->selq); 236 + 237 + root = mlx5e_htb_node_find(htb, MLX5E_HTB_CLASSID_ROOT); 238 + if (!root) { 239 + qos_err(htb->mdev, "Failed to find the root node in the QoS tree\n"); 240 + return -ENOENT; 241 + } 242 + err = mlx5_qos_destroy_node(htb->mdev, root->hw_id); 243 + if (err) 244 + qos_err(htb->mdev, "Failed to destroy root node %u, err = %d\n", 245 + root->hw_id, err); 246 + mlx5e_htb_node_delete(htb, root); 247 + 248 + mlx5e_qos_deactivate_all_queues(&priv->channels); 249 + mlx5e_qos_close_all_queues(&priv->channels); 250 + 251 + return err; 252 + } 253 + 254 + static int mlx5e_htb_convert_rate(struct mlx5e_htb *htb, u64 rate, 255 + struct mlx5e_qos_node *parent, u32 *bw_share) 256 + { 257 + u64 share = 0; 258 + 259 + while (parent->classid != MLX5E_HTB_CLASSID_ROOT && !parent->max_average_bw) 260 + parent = parent->parent; 261 + 262 + if (parent->max_average_bw) 263 + share = div64_u64(div_u64(rate * 100, BYTES_IN_MBIT), 264 + parent->max_average_bw); 265 + else 266 + share = 101; 267 + 268 + *bw_share = share == 0 ? 1 : share > 100 ? 0 : share; 269 + 270 + qos_dbg(htb->mdev, "Convert: rate %llu, parent ceil %llu -> bw_share %u\n", 271 + rate, (u64)parent->max_average_bw * BYTES_IN_MBIT, *bw_share); 272 + 273 + return 0; 274 + } 275 + 276 + static void mlx5e_htb_convert_ceil(struct mlx5e_htb *htb, u64 ceil, u32 *max_average_bw) 277 + { 278 + /* Hardware treats 0 as "unlimited", set at least 1. */ 279 + *max_average_bw = max_t(u32, div_u64(ceil, BYTES_IN_MBIT), 1); 280 + 281 + qos_dbg(htb->mdev, "Convert: ceil %llu -> max_average_bw %u\n", 282 + ceil, *max_average_bw); 283 + } 284 + 285 + int 286 + mlx5e_htb_leaf_alloc_queue(struct mlx5e_htb *htb, u16 classid, 287 + u32 parent_classid, u64 rate, u64 ceil, 288 + struct netlink_ext_ack *extack) 289 + { 290 + struct mlx5e_qos_node *node, *parent; 291 + struct mlx5e_priv *priv = htb->priv; 292 + int qid; 293 + int err; 294 + 295 + qos_dbg(htb->mdev, "TC_HTB_LEAF_ALLOC_QUEUE classid %04x, parent %04x, rate %llu, ceil %llu\n", 296 + classid, parent_classid, rate, ceil); 297 + 298 + qid = mlx5e_htb_find_unused_qos_qid(htb); 299 + if (qid < 0) { 300 + NL_SET_ERR_MSG_MOD(extack, "Maximum amount of leaf classes is reached."); 301 + return qid; 302 + } 303 + 304 + parent = mlx5e_htb_node_find(htb, parent_classid); 305 + if (!parent) 306 + return -EINVAL; 307 + 308 + node = mlx5e_htb_node_create_leaf(htb, classid, qid, parent); 309 + if (IS_ERR(node)) 310 + return PTR_ERR(node); 311 + 312 + node->rate = rate; 313 + mlx5e_htb_convert_rate(htb, rate, node->parent, &node->bw_share); 314 + mlx5e_htb_convert_ceil(htb, ceil, &node->max_average_bw); 315 + 316 + err = mlx5_qos_create_leaf_node(htb->mdev, node->parent->hw_id, 317 + node->bw_share, node->max_average_bw, 318 + &node->hw_id); 319 + if (err) { 320 + NL_SET_ERR_MSG_MOD(extack, "Firmware error when creating a leaf node."); 321 + qos_err(htb->mdev, "Failed to create a leaf node (class %04x), err = %d\n", 322 + classid, err); 323 + mlx5e_htb_node_delete(htb, node); 324 + return err; 325 + } 326 + 327 + if (test_bit(MLX5E_STATE_OPENED, &priv->state)) { 328 + err = mlx5e_open_qos_sq(priv, &priv->channels, node->qid, node->hw_id); 329 + if (err) { 330 + NL_SET_ERR_MSG_MOD(extack, "Error creating an SQ."); 331 + qos_warn(htb->mdev, "Failed to create a QoS SQ (class %04x), err = %d\n", 332 + classid, err); 333 + } else { 334 + mlx5e_activate_qos_sq(priv, node->qid, node->hw_id); 335 + } 336 + } 337 + 338 + return mlx5e_qid_from_qos(&priv->channels, node->qid); 339 + } 340 + 341 + int 342 + mlx5e_htb_leaf_to_inner(struct mlx5e_htb *htb, u16 classid, u16 child_classid, 343 + u64 rate, u64 ceil, struct netlink_ext_ack *extack) 344 + { 345 + struct mlx5e_qos_node *node, *child; 346 + struct mlx5e_priv *priv = htb->priv; 347 + int err, tmp_err; 348 + u32 new_hw_id; 349 + u16 qid; 350 + 351 + qos_dbg(htb->mdev, "TC_HTB_LEAF_TO_INNER classid %04x, upcoming child %04x, rate %llu, ceil %llu\n", 352 + classid, child_classid, rate, ceil); 353 + 354 + node = mlx5e_htb_node_find(htb, classid); 355 + if (!node) 356 + return -ENOENT; 357 + 358 + err = mlx5_qos_create_inner_node(htb->mdev, node->parent->hw_id, 359 + node->bw_share, node->max_average_bw, 360 + &new_hw_id); 361 + if (err) { 362 + NL_SET_ERR_MSG_MOD(extack, "Firmware error when creating an inner node."); 363 + qos_err(htb->mdev, "Failed to create an inner node (class %04x), err = %d\n", 364 + classid, err); 365 + return err; 366 + } 367 + 368 + /* Intentionally reuse the qid for the upcoming first child. */ 369 + child = mlx5e_htb_node_create_leaf(htb, child_classid, node->qid, node); 370 + if (IS_ERR(child)) { 371 + err = PTR_ERR(child); 372 + goto err_destroy_hw_node; 373 + } 374 + 375 + child->rate = rate; 376 + mlx5e_htb_convert_rate(htb, rate, node, &child->bw_share); 377 + mlx5e_htb_convert_ceil(htb, ceil, &child->max_average_bw); 378 + 379 + err = mlx5_qos_create_leaf_node(htb->mdev, new_hw_id, child->bw_share, 380 + child->max_average_bw, &child->hw_id); 381 + if (err) { 382 + NL_SET_ERR_MSG_MOD(extack, "Firmware error when creating a leaf node."); 383 + qos_err(htb->mdev, "Failed to create a leaf node (class %04x), err = %d\n", 384 + classid, err); 385 + goto err_delete_sw_node; 386 + } 387 + 388 + /* No fail point. */ 389 + 390 + qid = node->qid; 391 + /* Pairs with mlx5e_htb_get_txq_by_classid. */ 392 + WRITE_ONCE(node->qid, MLX5E_QOS_QID_INNER); 393 + 394 + if (test_bit(MLX5E_STATE_OPENED, &priv->state)) { 395 + mlx5e_deactivate_qos_sq(priv, qid); 396 + mlx5e_close_qos_sq(priv, qid); 397 + } 398 + 399 + err = mlx5_qos_destroy_node(htb->mdev, node->hw_id); 400 + if (err) /* Not fatal. */ 401 + qos_warn(htb->mdev, "Failed to destroy leaf node %u (class %04x), err = %d\n", 402 + node->hw_id, classid, err); 403 + 404 + node->hw_id = new_hw_id; 405 + 406 + if (test_bit(MLX5E_STATE_OPENED, &priv->state)) { 407 + err = mlx5e_open_qos_sq(priv, &priv->channels, child->qid, child->hw_id); 408 + if (err) { 409 + NL_SET_ERR_MSG_MOD(extack, "Error creating an SQ."); 410 + qos_warn(htb->mdev, "Failed to create a QoS SQ (class %04x), err = %d\n", 411 + classid, err); 412 + } else { 413 + mlx5e_activate_qos_sq(priv, child->qid, child->hw_id); 414 + } 415 + } 416 + 417 + return 0; 418 + 419 + err_delete_sw_node: 420 + child->qid = MLX5E_QOS_QID_INNER; 421 + mlx5e_htb_node_delete(htb, child); 422 + 423 + err_destroy_hw_node: 424 + tmp_err = mlx5_qos_destroy_node(htb->mdev, new_hw_id); 425 + if (tmp_err) /* Not fatal. */ 426 + qos_warn(htb->mdev, "Failed to roll back creation of an inner node %u (class %04x), err = %d\n", 427 + new_hw_id, classid, tmp_err); 428 + return err; 429 + } 430 + 431 + static struct mlx5e_qos_node *mlx5e_htb_node_find_by_qid(struct mlx5e_htb *htb, u16 qid) 432 + { 433 + struct mlx5e_qos_node *node = NULL; 434 + int bkt; 435 + 436 + hash_for_each(htb->qos_tc2node, bkt, node, hnode) 437 + if (node->qid == qid) 438 + break; 439 + 440 + return node; 441 + } 442 + 443 + int mlx5e_htb_leaf_del(struct mlx5e_htb *htb, u16 *classid, 444 + struct netlink_ext_ack *extack) 445 + { 446 + struct mlx5e_priv *priv = htb->priv; 447 + struct mlx5e_qos_node *node; 448 + struct netdev_queue *txq; 449 + u16 qid, moved_qid; 450 + bool opened; 451 + int err; 452 + 453 + qos_dbg(htb->mdev, "TC_HTB_LEAF_DEL classid %04x\n", *classid); 454 + 455 + node = mlx5e_htb_node_find(htb, *classid); 456 + if (!node) 457 + return -ENOENT; 458 + 459 + /* Store qid for reuse. */ 460 + qid = node->qid; 461 + 462 + opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 463 + if (opened) { 464 + txq = netdev_get_tx_queue(htb->netdev, 465 + mlx5e_qid_from_qos(&priv->channels, qid)); 466 + mlx5e_deactivate_qos_sq(priv, qid); 467 + mlx5e_close_qos_sq(priv, qid); 468 + } 469 + 470 + err = mlx5_qos_destroy_node(htb->mdev, node->hw_id); 471 + if (err) /* Not fatal. */ 472 + qos_warn(htb->mdev, "Failed to destroy leaf node %u (class %04x), err = %d\n", 473 + node->hw_id, *classid, err); 474 + 475 + mlx5e_htb_node_delete(htb, node); 476 + 477 + moved_qid = mlx5e_htb_cur_leaf_nodes(htb); 478 + 479 + if (moved_qid == 0) { 480 + /* The last QoS SQ was just destroyed. */ 481 + if (opened) 482 + mlx5e_reactivate_qos_sq(priv, qid, txq); 483 + return 0; 484 + } 485 + moved_qid--; 486 + 487 + if (moved_qid < qid) { 488 + /* The highest QoS SQ was just destroyed. */ 489 + WARN(moved_qid != qid - 1, "Gaps in queue numeration: destroyed queue %u, the highest queue is %u", 490 + qid, moved_qid); 491 + if (opened) 492 + mlx5e_reactivate_qos_sq(priv, qid, txq); 493 + return 0; 494 + } 495 + 496 + WARN(moved_qid == qid, "Can't move node with qid %u to itself", qid); 497 + qos_dbg(htb->mdev, "Moving QoS SQ %u to %u\n", moved_qid, qid); 498 + 499 + node = mlx5e_htb_node_find_by_qid(htb, moved_qid); 500 + WARN(!node, "Could not find a node with qid %u to move to queue %u", 501 + moved_qid, qid); 502 + 503 + /* Stop traffic to the old queue. */ 504 + WRITE_ONCE(node->qid, MLX5E_QOS_QID_INNER); 505 + __clear_bit(moved_qid, priv->htb->qos_used_qids); 506 + 507 + if (opened) { 508 + txq = netdev_get_tx_queue(htb->netdev, 509 + mlx5e_qid_from_qos(&priv->channels, moved_qid)); 510 + mlx5e_deactivate_qos_sq(priv, moved_qid); 511 + mlx5e_close_qos_sq(priv, moved_qid); 512 + } 513 + 514 + /* Prevent packets from the old class from getting into the new one. */ 515 + mlx5e_reset_qdisc(htb->netdev, moved_qid); 516 + 517 + __set_bit(qid, htb->qos_used_qids); 518 + WRITE_ONCE(node->qid, qid); 519 + 520 + if (test_bit(MLX5E_STATE_OPENED, &priv->state)) { 521 + err = mlx5e_open_qos_sq(priv, &priv->channels, node->qid, node->hw_id); 522 + if (err) { 523 + NL_SET_ERR_MSG_MOD(extack, "Error creating an SQ."); 524 + qos_warn(htb->mdev, "Failed to create a QoS SQ (class %04x) while moving qid %u to %u, err = %d\n", 525 + node->classid, moved_qid, qid, err); 526 + } else { 527 + mlx5e_activate_qos_sq(priv, node->qid, node->hw_id); 528 + } 529 + } 530 + 531 + mlx5e_update_tx_netdev_queues(priv); 532 + if (opened) 533 + mlx5e_reactivate_qos_sq(priv, moved_qid, txq); 534 + 535 + *classid = node->classid; 536 + return 0; 537 + } 538 + 539 + int 540 + mlx5e_htb_leaf_del_last(struct mlx5e_htb *htb, u16 classid, bool force, 541 + struct netlink_ext_ack *extack) 542 + { 543 + struct mlx5e_qos_node *node, *parent; 544 + struct mlx5e_priv *priv = htb->priv; 545 + u32 old_hw_id, new_hw_id; 546 + int err, saved_err = 0; 547 + u16 qid; 548 + 549 + qos_dbg(htb->mdev, "TC_HTB_LEAF_DEL_LAST%s classid %04x\n", 550 + force ? "_FORCE" : "", classid); 551 + 552 + node = mlx5e_htb_node_find(htb, classid); 553 + if (!node) 554 + return -ENOENT; 555 + 556 + err = mlx5_qos_create_leaf_node(htb->mdev, node->parent->parent->hw_id, 557 + node->parent->bw_share, 558 + node->parent->max_average_bw, 559 + &new_hw_id); 560 + if (err) { 561 + NL_SET_ERR_MSG_MOD(extack, "Firmware error when creating a leaf node."); 562 + qos_err(htb->mdev, "Failed to create a leaf node (class %04x), err = %d\n", 563 + classid, err); 564 + if (!force) 565 + return err; 566 + saved_err = err; 567 + } 568 + 569 + /* Store qid for reuse and prevent clearing the bit. */ 570 + qid = node->qid; 571 + /* Pairs with mlx5e_htb_get_txq_by_classid. */ 572 + WRITE_ONCE(node->qid, MLX5E_QOS_QID_INNER); 573 + 574 + if (test_bit(MLX5E_STATE_OPENED, &priv->state)) { 575 + mlx5e_deactivate_qos_sq(priv, qid); 576 + mlx5e_close_qos_sq(priv, qid); 577 + } 578 + 579 + /* Prevent packets from the old class from getting into the new one. */ 580 + mlx5e_reset_qdisc(htb->netdev, qid); 581 + 582 + err = mlx5_qos_destroy_node(htb->mdev, node->hw_id); 583 + if (err) /* Not fatal. */ 584 + qos_warn(htb->mdev, "Failed to destroy leaf node %u (class %04x), err = %d\n", 585 + node->hw_id, classid, err); 586 + 587 + parent = node->parent; 588 + mlx5e_htb_node_delete(htb, node); 589 + 590 + node = parent; 591 + WRITE_ONCE(node->qid, qid); 592 + 593 + /* Early return on error in force mode. Parent will still be an inner 594 + * node to be deleted by a following delete operation. 595 + */ 596 + if (saved_err) 597 + return saved_err; 598 + 599 + old_hw_id = node->hw_id; 600 + node->hw_id = new_hw_id; 601 + 602 + if (test_bit(MLX5E_STATE_OPENED, &priv->state)) { 603 + err = mlx5e_open_qos_sq(priv, &priv->channels, node->qid, node->hw_id); 604 + if (err) { 605 + NL_SET_ERR_MSG_MOD(extack, "Error creating an SQ."); 606 + qos_warn(htb->mdev, "Failed to create a QoS SQ (class %04x), err = %d\n", 607 + classid, err); 608 + } else { 609 + mlx5e_activate_qos_sq(priv, node->qid, node->hw_id); 610 + } 611 + } 612 + 613 + err = mlx5_qos_destroy_node(htb->mdev, old_hw_id); 614 + if (err) /* Not fatal. */ 615 + qos_warn(htb->mdev, "Failed to destroy leaf node %u (class %04x), err = %d\n", 616 + node->hw_id, classid, err); 617 + 618 + return 0; 619 + } 620 + 621 + static int 622 + mlx5e_htb_update_children(struct mlx5e_htb *htb, struct mlx5e_qos_node *node, 623 + struct netlink_ext_ack *extack) 624 + { 625 + struct mlx5e_qos_node *child; 626 + int err = 0; 627 + int bkt; 628 + 629 + hash_for_each(htb->qos_tc2node, bkt, child, hnode) { 630 + u32 old_bw_share = child->bw_share; 631 + int err_one; 632 + 633 + if (child->parent != node) 634 + continue; 635 + 636 + mlx5e_htb_convert_rate(htb, child->rate, node, &child->bw_share); 637 + if (child->bw_share == old_bw_share) 638 + continue; 639 + 640 + err_one = mlx5_qos_update_node(htb->mdev, child->hw_id, child->bw_share, 641 + child->max_average_bw, child->hw_id); 642 + if (!err && err_one) { 643 + err = err_one; 644 + 645 + NL_SET_ERR_MSG_MOD(extack, "Firmware error when modifying a child node."); 646 + qos_err(htb->mdev, "Failed to modify a child node (class %04x), err = %d\n", 647 + node->classid, err); 648 + } 649 + } 650 + 651 + return err; 652 + } 653 + 654 + int 655 + mlx5e_htb_node_modify(struct mlx5e_htb *htb, u16 classid, u64 rate, u64 ceil, 656 + struct netlink_ext_ack *extack) 657 + { 658 + u32 bw_share, max_average_bw; 659 + struct mlx5e_qos_node *node; 660 + bool ceil_changed = false; 661 + int err; 662 + 663 + qos_dbg(htb->mdev, "TC_HTB_LEAF_MODIFY classid %04x, rate %llu, ceil %llu\n", 664 + classid, rate, ceil); 665 + 666 + node = mlx5e_htb_node_find(htb, classid); 667 + if (!node) 668 + return -ENOENT; 669 + 670 + node->rate = rate; 671 + mlx5e_htb_convert_rate(htb, rate, node->parent, &bw_share); 672 + mlx5e_htb_convert_ceil(htb, ceil, &max_average_bw); 673 + 674 + err = mlx5_qos_update_node(htb->mdev, node->parent->hw_id, bw_share, 675 + max_average_bw, node->hw_id); 676 + if (err) { 677 + NL_SET_ERR_MSG_MOD(extack, "Firmware error when modifying a node."); 678 + qos_err(htb->mdev, "Failed to modify a node (class %04x), err = %d\n", 679 + classid, err); 680 + return err; 681 + } 682 + 683 + if (max_average_bw != node->max_average_bw) 684 + ceil_changed = true; 685 + 686 + node->bw_share = bw_share; 687 + node->max_average_bw = max_average_bw; 688 + 689 + if (ceil_changed) 690 + err = mlx5e_htb_update_children(htb, node, extack); 691 + 692 + return err; 693 + } 694 + 695 + struct mlx5e_htb *mlx5e_htb_alloc(void) 696 + { 697 + return kvzalloc(sizeof(struct mlx5e_htb), GFP_KERNEL); 698 + } 699 + 700 + void mlx5e_htb_free(struct mlx5e_htb *htb) 701 + { 702 + kvfree(htb); 703 + } 704 + 705 + int mlx5e_htb_init(struct mlx5e_htb *htb, struct tc_htb_qopt_offload *htb_qopt, 706 + struct net_device *netdev, struct mlx5_core_dev *mdev, 707 + struct mlx5e_selq *selq, struct mlx5e_priv *priv) 708 + { 709 + htb->mdev = mdev; 710 + htb->netdev = netdev; 711 + htb->selq = selq; 712 + htb->priv = priv; 713 + hash_init(htb->qos_tc2node); 714 + return mlx5e_htb_root_add(htb, htb_qopt->parent_classid, htb_qopt->classid, 715 + htb_qopt->extack); 716 + } 717 + 718 + void mlx5e_htb_cleanup(struct mlx5e_htb *htb) 719 + { 720 + mlx5e_htb_root_del(htb); 721 + } 722 +
+46
drivers/net/ethernet/mellanox/mlx5/core/en/htb.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ 2 + /* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ 3 + 4 + #ifndef __MLX5E_EN_HTB_H_ 5 + #define __MLX5E_EN_HTB_H_ 6 + 7 + #include "qos.h" 8 + 9 + #define MLX5E_QOS_MAX_LEAF_NODES 256 10 + 11 + struct mlx5e_selq; 12 + struct mlx5e_htb; 13 + 14 + typedef int (*mlx5e_fp_htb_enumerate)(void *data, u16 qid, u32 hw_id); 15 + int mlx5e_htb_enumerate_leaves(struct mlx5e_htb *htb, mlx5e_fp_htb_enumerate callback, void *data); 16 + 17 + int mlx5e_htb_cur_leaf_nodes(struct mlx5e_htb *htb); 18 + 19 + /* TX datapath API */ 20 + int mlx5e_htb_get_txq_by_classid(struct mlx5e_htb *htb, u16 classid); 21 + 22 + /* HTB TC handlers */ 23 + 24 + int 25 + mlx5e_htb_leaf_alloc_queue(struct mlx5e_htb *htb, u16 classid, 26 + u32 parent_classid, u64 rate, u64 ceil, 27 + struct netlink_ext_ack *extack); 28 + int 29 + mlx5e_htb_leaf_to_inner(struct mlx5e_htb *htb, u16 classid, u16 child_classid, 30 + u64 rate, u64 ceil, struct netlink_ext_ack *extack); 31 + int mlx5e_htb_leaf_del(struct mlx5e_htb *htb, u16 *classid, 32 + struct netlink_ext_ack *extack); 33 + int 34 + mlx5e_htb_leaf_del_last(struct mlx5e_htb *htb, u16 classid, bool force, 35 + struct netlink_ext_ack *extack); 36 + int 37 + mlx5e_htb_node_modify(struct mlx5e_htb *htb, u16 classid, u64 rate, u64 ceil, 38 + struct netlink_ext_ack *extack); 39 + struct mlx5e_htb *mlx5e_htb_alloc(void); 40 + void mlx5e_htb_free(struct mlx5e_htb *htb); 41 + int mlx5e_htb_init(struct mlx5e_htb *htb, struct tc_htb_qopt_offload *htb_qopt, 42 + struct net_device *netdev, struct mlx5_core_dev *mdev, 43 + struct mlx5e_selq *selq, struct mlx5e_priv *priv); 44 + void mlx5e_htb_cleanup(struct mlx5e_htb *htb); 45 + #endif 46 +
+35 -2
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c
··· 79 79 memset(skb->cb, 0, sizeof(struct mlx5e_skb_cb_hwtstamp)); 80 80 } 81 81 82 + #define PTP_WQE_CTR2IDX(val) ((val) & ptpsq->ts_cqe_ctr_mask) 83 + 84 + static bool mlx5e_ptp_ts_cqe_drop(struct mlx5e_ptpsq *ptpsq, u16 skb_cc, u16 skb_id) 85 + { 86 + return (ptpsq->ts_cqe_ctr_mask && (skb_cc != skb_id)); 87 + } 88 + 89 + static void mlx5e_ptp_skb_fifo_ts_cqe_resync(struct mlx5e_ptpsq *ptpsq, u16 skb_cc, u16 skb_id) 90 + { 91 + struct skb_shared_hwtstamps hwts = {}; 92 + struct sk_buff *skb; 93 + 94 + ptpsq->cq_stats->resync_event++; 95 + 96 + while (skb_cc != skb_id) { 97 + skb = mlx5e_skb_fifo_pop(&ptpsq->skb_fifo); 98 + hwts.hwtstamp = mlx5e_skb_cb_get_hwts(skb)->cqe_hwtstamp; 99 + skb_tstamp_tx(skb, &hwts); 100 + ptpsq->cq_stats->resync_cqe++; 101 + skb_cc = PTP_WQE_CTR2IDX(ptpsq->skb_fifo_cc); 102 + } 103 + } 104 + 82 105 static void mlx5e_ptp_handle_ts_cqe(struct mlx5e_ptpsq *ptpsq, 83 106 struct mlx5_cqe64 *cqe, 84 107 int budget) 85 108 { 86 - struct sk_buff *skb = mlx5e_skb_fifo_pop(&ptpsq->skb_fifo); 109 + u16 skb_id = PTP_WQE_CTR2IDX(be16_to_cpu(cqe->wqe_counter)); 110 + u16 skb_cc = PTP_WQE_CTR2IDX(ptpsq->skb_fifo_cc); 87 111 struct mlx5e_txqsq *sq = &ptpsq->txqsq; 112 + struct sk_buff *skb; 88 113 ktime_t hwtstamp; 89 114 90 115 if (unlikely(MLX5E_RX_ERR_CQE(cqe))) { 116 + skb = mlx5e_skb_fifo_pop(&ptpsq->skb_fifo); 91 117 ptpsq->cq_stats->err_cqe++; 92 118 goto out; 93 119 } 94 120 121 + if (mlx5e_ptp_ts_cqe_drop(ptpsq, skb_cc, skb_id)) 122 + mlx5e_ptp_skb_fifo_ts_cqe_resync(ptpsq, skb_cc, skb_id); 123 + 124 + skb = mlx5e_skb_fifo_pop(&ptpsq->skb_fifo); 95 125 hwtstamp = mlx5e_cqe_ts_to_ns(sq->ptp_cyc2time, sq->clock, get_cqe_ts(cqe)); 96 126 mlx5e_skb_cb_hwtstamp_handler(skb, MLX5E_SKB_CB_PORT_HWTSTAMP, 97 127 hwtstamp, ptpsq->cq_stats); ··· 271 241 static int mlx5e_ptp_alloc_traffic_db(struct mlx5e_ptpsq *ptpsq, int numa) 272 242 { 273 243 int wq_sz = mlx5_wq_cyc_get_size(&ptpsq->txqsq.wq); 244 + struct mlx5_core_dev *mdev = ptpsq->txqsq.mdev; 274 245 275 246 ptpsq->skb_fifo.fifo = kvzalloc_node(array_size(wq_sz, sizeof(*ptpsq->skb_fifo.fifo)), 276 247 GFP_KERNEL, numa); ··· 281 250 ptpsq->skb_fifo.pc = &ptpsq->skb_fifo_pc; 282 251 ptpsq->skb_fifo.cc = &ptpsq->skb_fifo_cc; 283 252 ptpsq->skb_fifo.mask = wq_sz - 1; 284 - 253 + if (MLX5_CAP_GEN_2(mdev, ts_cqe_metadata_size2wqe_counter)) 254 + ptpsq->ts_cqe_ctr_mask = 255 + (1 << MLX5_CAP_GEN_2(mdev, ts_cqe_metadata_size2wqe_counter)) - 1; 285 256 return 0; 286 257 } 287 258
+1
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h
··· 17 17 u16 skb_fifo_pc; 18 18 struct mlx5e_skb_fifo skb_fifo; 19 19 struct mlx5e_ptp_cq_stats *cq_stats; 20 + u16 ts_cqe_ctr_mask; 20 21 }; 21 22 22 23 enum {
+109 -704
drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
··· 2 2 /* Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. */ 3 3 #include <net/sch_generic.h> 4 4 5 + #include <net/pkt_cls.h> 5 6 #include "en.h" 6 7 #include "params.h" 7 8 #include "../qos.h" 9 + #include "en/htb.h" 8 10 9 - #define BYTES_IN_MBIT 125000 11 + struct qos_sq_callback_params { 12 + struct mlx5e_priv *priv; 13 + struct mlx5e_channels *chs; 14 + }; 10 15 11 16 int mlx5e_qos_bytes_rate_check(struct mlx5_core_dev *mdev, u64 nbytes) 12 17 { ··· 33 28 return min(MLX5E_QOS_MAX_LEAF_NODES, mlx5_qos_max_leaf_nodes(mdev)); 34 29 } 35 30 36 - int mlx5e_qos_cur_leaf_nodes(struct mlx5e_priv *priv) 37 - { 38 - int last = find_last_bit(priv->htb.qos_used_qids, mlx5e_qos_max_leaf_nodes(priv->mdev)); 39 - 40 - return last == mlx5e_qos_max_leaf_nodes(priv->mdev) ? 0 : last + 1; 41 - } 42 - 43 - /* Software representation of the QoS tree (internal to this file) */ 44 - 45 - static int mlx5e_find_unused_qos_qid(struct mlx5e_priv *priv) 46 - { 47 - int size = mlx5e_qos_max_leaf_nodes(priv->mdev); 48 - int res; 49 - 50 - WARN_ONCE(!mutex_is_locked(&priv->state_lock), "%s: state_lock is not held\n", __func__); 51 - res = find_first_zero_bit(priv->htb.qos_used_qids, size); 52 - 53 - return res == size ? -ENOSPC : res; 54 - } 55 - 56 - struct mlx5e_qos_node { 57 - struct hlist_node hnode; 58 - struct mlx5e_qos_node *parent; 59 - u64 rate; 60 - u32 bw_share; 61 - u32 max_average_bw; 62 - u32 hw_id; 63 - u32 classid; /* 16-bit, except root. */ 64 - u16 qid; 65 - }; 66 - 67 - #define MLX5E_QOS_QID_INNER 0xffff 68 - #define MLX5E_HTB_CLASSID_ROOT 0xffffffff 69 - 70 - static struct mlx5e_qos_node * 71 - mlx5e_sw_node_create_leaf(struct mlx5e_priv *priv, u16 classid, u16 qid, 72 - struct mlx5e_qos_node *parent) 73 - { 74 - struct mlx5e_qos_node *node; 75 - 76 - node = kzalloc(sizeof(*node), GFP_KERNEL); 77 - if (!node) 78 - return ERR_PTR(-ENOMEM); 79 - 80 - node->parent = parent; 81 - 82 - node->qid = qid; 83 - __set_bit(qid, priv->htb.qos_used_qids); 84 - 85 - node->classid = classid; 86 - hash_add_rcu(priv->htb.qos_tc2node, &node->hnode, classid); 87 - 88 - mlx5e_update_tx_netdev_queues(priv); 89 - 90 - return node; 91 - } 92 - 93 - static struct mlx5e_qos_node *mlx5e_sw_node_create_root(struct mlx5e_priv *priv) 94 - { 95 - struct mlx5e_qos_node *node; 96 - 97 - node = kzalloc(sizeof(*node), GFP_KERNEL); 98 - if (!node) 99 - return ERR_PTR(-ENOMEM); 100 - 101 - node->qid = MLX5E_QOS_QID_INNER; 102 - node->classid = MLX5E_HTB_CLASSID_ROOT; 103 - hash_add_rcu(priv->htb.qos_tc2node, &node->hnode, node->classid); 104 - 105 - return node; 106 - } 107 - 108 - static struct mlx5e_qos_node *mlx5e_sw_node_find(struct mlx5e_priv *priv, u32 classid) 109 - { 110 - struct mlx5e_qos_node *node = NULL; 111 - 112 - hash_for_each_possible(priv->htb.qos_tc2node, node, hnode, classid) { 113 - if (node->classid == classid) 114 - break; 115 - } 116 - 117 - return node; 118 - } 119 - 120 - static struct mlx5e_qos_node *mlx5e_sw_node_find_rcu(struct mlx5e_priv *priv, u32 classid) 121 - { 122 - struct mlx5e_qos_node *node = NULL; 123 - 124 - hash_for_each_possible_rcu(priv->htb.qos_tc2node, node, hnode, classid) { 125 - if (node->classid == classid) 126 - break; 127 - } 128 - 129 - return node; 130 - } 131 - 132 - static void mlx5e_sw_node_delete(struct mlx5e_priv *priv, struct mlx5e_qos_node *node) 133 - { 134 - hash_del_rcu(&node->hnode); 135 - if (node->qid != MLX5E_QOS_QID_INNER) { 136 - __clear_bit(node->qid, priv->htb.qos_used_qids); 137 - mlx5e_update_tx_netdev_queues(priv); 138 - } 139 - /* Make sure this qid is no longer selected by mlx5e_select_queue, so 140 - * that mlx5e_reactivate_qos_sq can safely restart the netdev TX queue. 141 - */ 142 - synchronize_net(); 143 - kfree(node); 144 - } 145 - 146 31 /* TX datapath API */ 147 32 148 - static u16 mlx5e_qid_from_qos(struct mlx5e_channels *chs, u16 qid) 33 + u16 mlx5e_qid_from_qos(struct mlx5e_channels *chs, u16 qid) 149 34 { 150 35 /* These channel params are safe to access from the datapath, because: 151 - * 1. This function is called only after checking priv->htb.maj_id != 0, 36 + * 1. This function is called only after checking selq->htb_maj_id != 0, 152 37 * and the number of queues can't change while HTB offload is active. 153 - * 2. When priv->htb.maj_id becomes 0, synchronize_rcu waits for 38 + * 2. When selq->htb_maj_id becomes 0, synchronize_rcu waits for 154 39 * mlx5e_select_queue to finish while holding priv->state_lock, 155 40 * preventing other code from changing the number of queues. 156 41 */ ··· 49 154 return (chs->params.num_channels + is_ptp) * mlx5e_get_dcb_num_tc(&chs->params) + qid; 50 155 } 51 156 52 - int mlx5e_get_txq_by_classid(struct mlx5e_priv *priv, u16 classid) 53 - { 54 - struct mlx5e_qos_node *node; 55 - u16 qid; 56 - int res; 57 - 58 - rcu_read_lock(); 59 - 60 - node = mlx5e_sw_node_find_rcu(priv, classid); 61 - if (!node) { 62 - res = -ENOENT; 63 - goto out; 64 - } 65 - qid = READ_ONCE(node->qid); 66 - if (qid == MLX5E_QOS_QID_INNER) { 67 - res = -EINVAL; 68 - goto out; 69 - } 70 - res = mlx5e_qid_from_qos(&priv->channels, qid); 71 - 72 - out: 73 - rcu_read_unlock(); 74 - return res; 75 - } 157 + /* SQ lifecycle */ 76 158 77 159 static struct mlx5e_txqsq *mlx5e_get_qos_sq(struct mlx5e_priv *priv, int qid) 78 160 { ··· 66 194 return mlx5e_state_dereference(priv, qos_sqs[qid]); 67 195 } 68 196 69 - /* SQ lifecycle */ 70 - 71 - static int mlx5e_open_qos_sq(struct mlx5e_priv *priv, struct mlx5e_channels *chs, 72 - struct mlx5e_qos_node *node) 197 + int mlx5e_open_qos_sq(struct mlx5e_priv *priv, struct mlx5e_channels *chs, 198 + u16 node_qid, u32 hw_id) 73 199 { 74 200 struct mlx5e_create_cq_param ccp = {}; 75 201 struct mlx5e_txqsq __rcu **qos_sqs; ··· 80 210 81 211 params = &chs->params; 82 212 83 - txq_ix = mlx5e_qid_from_qos(chs, node->qid); 213 + txq_ix = mlx5e_qid_from_qos(chs, node_qid); 84 214 85 - WARN_ON(node->qid > priv->htb.max_qos_sqs); 86 - if (node->qid == priv->htb.max_qos_sqs) { 215 + WARN_ON(node_qid > priv->htb_max_qos_sqs); 216 + if (node_qid == priv->htb_max_qos_sqs) { 87 217 struct mlx5e_sq_stats *stats, **stats_list = NULL; 88 218 89 - if (priv->htb.max_qos_sqs == 0) { 219 + if (priv->htb_max_qos_sqs == 0) { 90 220 stats_list = kvcalloc(mlx5e_qos_max_leaf_nodes(priv->mdev), 91 221 sizeof(*stats_list), 92 222 GFP_KERNEL); ··· 99 229 return -ENOMEM; 100 230 } 101 231 if (stats_list) 102 - WRITE_ONCE(priv->htb.qos_sq_stats, stats_list); 103 - WRITE_ONCE(priv->htb.qos_sq_stats[node->qid], stats); 104 - /* Order max_qos_sqs increment after writing the array pointer. 232 + WRITE_ONCE(priv->htb_qos_sq_stats, stats_list); 233 + WRITE_ONCE(priv->htb_qos_sq_stats[node_qid], stats); 234 + /* Order htb_max_qos_sqs increment after writing the array pointer. 105 235 * Pairs with smp_load_acquire in en_stats.c. 106 236 */ 107 - smp_store_release(&priv->htb.max_qos_sqs, priv->htb.max_qos_sqs + 1); 237 + smp_store_release(&priv->htb_max_qos_sqs, priv->htb_max_qos_sqs + 1); 108 238 } 109 239 110 - ix = node->qid % params->num_channels; 111 - qid = node->qid / params->num_channels; 240 + ix = node_qid % params->num_channels; 241 + qid = node_qid / params->num_channels; 112 242 c = chs->c[ix]; 113 243 114 244 qos_sqs = mlx5e_state_dereference(priv, c->qos_sqs); ··· 127 257 if (err) 128 258 goto err_free_sq; 129 259 err = mlx5e_open_txqsq(c, priv->tisn[c->lag_port][0], txq_ix, params, 130 - &param_sq, sq, 0, node->hw_id, 131 - priv->htb.qos_sq_stats[node->qid]); 260 + &param_sq, sq, 0, hw_id, 261 + priv->htb_qos_sq_stats[node_qid]); 132 262 if (err) 133 263 goto err_close_cq; 134 264 ··· 143 273 return err; 144 274 } 145 275 146 - static void mlx5e_activate_qos_sq(struct mlx5e_priv *priv, struct mlx5e_qos_node *node) 276 + static int mlx5e_open_qos_sq_cb_wrapper(void *data, u16 node_qid, u32 hw_id) 147 277 { 278 + struct qos_sq_callback_params *cb_params = data; 279 + 280 + return mlx5e_open_qos_sq(cb_params->priv, cb_params->chs, node_qid, hw_id); 281 + } 282 + 283 + int mlx5e_activate_qos_sq(void *data, u16 node_qid, u32 hw_id) 284 + { 285 + struct mlx5e_priv *priv = data; 148 286 struct mlx5e_txqsq *sq; 149 287 u16 qid; 150 288 151 - sq = mlx5e_get_qos_sq(priv, node->qid); 289 + sq = mlx5e_get_qos_sq(priv, node_qid); 152 290 153 - qid = mlx5e_qid_from_qos(&priv->channels, node->qid); 291 + qid = mlx5e_qid_from_qos(&priv->channels, node_qid); 154 292 155 293 /* If it's a new queue, it will be marked as started at this point. 156 294 * Stop it before updating txq2sq. ··· 173 295 */ 174 296 smp_wmb(); 175 297 176 - qos_dbg(priv->mdev, "Activate QoS SQ qid %u\n", node->qid); 298 + qos_dbg(priv->mdev, "Activate QoS SQ qid %u\n", node_qid); 177 299 mlx5e_activate_txqsq(sq); 300 + 301 + return 0; 178 302 } 179 303 180 - static void mlx5e_deactivate_qos_sq(struct mlx5e_priv *priv, u16 qid) 304 + void mlx5e_deactivate_qos_sq(struct mlx5e_priv *priv, u16 qid) 181 305 { 182 306 struct mlx5e_txqsq *sq; 183 307 ··· 199 319 smp_wmb(); 200 320 } 201 321 202 - static void mlx5e_close_qos_sq(struct mlx5e_priv *priv, u16 qid) 322 + void mlx5e_close_qos_sq(struct mlx5e_priv *priv, u16 qid) 203 323 { 204 324 struct mlx5e_txqsq __rcu **qos_sqs; 205 325 struct mlx5e_params *params; ··· 249 369 kvfree(qos_sqs); 250 370 } 251 371 252 - static void mlx5e_qos_close_all_queues(struct mlx5e_channels *chs) 372 + void mlx5e_qos_close_all_queues(struct mlx5e_channels *chs) 253 373 { 254 374 int i; 255 375 ··· 257 377 mlx5e_qos_close_queues(chs->c[i]); 258 378 } 259 379 260 - static int mlx5e_qos_alloc_queues(struct mlx5e_priv *priv, struct mlx5e_channels *chs) 380 + int mlx5e_qos_alloc_queues(struct mlx5e_priv *priv, struct mlx5e_channels *chs) 261 381 { 262 382 u16 qos_sqs_size; 263 383 int i; ··· 293 413 294 414 int mlx5e_qos_open_queues(struct mlx5e_priv *priv, struct mlx5e_channels *chs) 295 415 { 296 - struct mlx5e_qos_node *node = NULL; 297 - int bkt, err; 298 - 299 - if (!priv->htb.maj_id) 300 - return 0; 416 + struct qos_sq_callback_params callback_params; 417 + int err; 301 418 302 419 err = mlx5e_qos_alloc_queues(priv, chs); 303 420 if (err) 304 421 return err; 305 422 306 - hash_for_each(priv->htb.qos_tc2node, bkt, node, hnode) { 307 - if (node->qid == MLX5E_QOS_QID_INNER) 308 - continue; 309 - err = mlx5e_open_qos_sq(priv, chs, node); 310 - if (err) { 311 - mlx5e_qos_close_all_queues(chs); 312 - return err; 313 - } 423 + callback_params.priv = priv; 424 + callback_params.chs = chs; 425 + 426 + err = mlx5e_htb_enumerate_leaves(priv->htb, mlx5e_open_qos_sq_cb_wrapper, &callback_params); 427 + if (err) { 428 + mlx5e_qos_close_all_queues(chs); 429 + return err; 314 430 } 315 431 316 432 return 0; ··· 314 438 315 439 void mlx5e_qos_activate_queues(struct mlx5e_priv *priv) 316 440 { 317 - struct mlx5e_qos_node *node = NULL; 318 - int bkt; 319 - 320 - hash_for_each(priv->htb.qos_tc2node, bkt, node, hnode) { 321 - if (node->qid == MLX5E_QOS_QID_INNER) 322 - continue; 323 - mlx5e_activate_qos_sq(priv, node); 324 - } 441 + mlx5e_htb_enumerate_leaves(priv->htb, mlx5e_activate_qos_sq, priv); 325 442 } 326 443 327 444 void mlx5e_qos_deactivate_queues(struct mlx5e_channel *c) ··· 343 474 } 344 475 } 345 476 346 - static void mlx5e_qos_deactivate_all_queues(struct mlx5e_channels *chs) 477 + void mlx5e_qos_deactivate_all_queues(struct mlx5e_channels *chs) 347 478 { 348 479 int i; 349 480 ··· 351 482 mlx5e_qos_deactivate_queues(chs->c[i]); 352 483 } 353 484 354 - /* HTB API */ 355 - 356 - int mlx5e_htb_root_add(struct mlx5e_priv *priv, u16 htb_maj_id, u16 htb_defcls, 357 - struct netlink_ext_ack *extack) 358 - { 359 - struct mlx5e_qos_node *root; 360 - bool opened; 361 - int err; 362 - 363 - qos_dbg(priv->mdev, "TC_HTB_CREATE handle %04x:, default :%04x\n", htb_maj_id, htb_defcls); 364 - 365 - if (!mlx5_qos_is_supported(priv->mdev)) { 366 - NL_SET_ERR_MSG_MOD(extack, 367 - "Missing QoS capabilities. Try disabling SRIOV or use a supported device."); 368 - return -EOPNOTSUPP; 369 - } 370 - 371 - opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 372 - if (opened) { 373 - mlx5e_selq_prepare(&priv->selq, &priv->channels.params, true); 374 - 375 - err = mlx5e_qos_alloc_queues(priv, &priv->channels); 376 - if (err) 377 - goto err_cancel_selq; 378 - } 379 - 380 - root = mlx5e_sw_node_create_root(priv); 381 - if (IS_ERR(root)) { 382 - err = PTR_ERR(root); 383 - goto err_free_queues; 384 - } 385 - 386 - err = mlx5_qos_create_root_node(priv->mdev, &root->hw_id); 387 - if (err) { 388 - NL_SET_ERR_MSG_MOD(extack, "Firmware error. Try upgrading firmware."); 389 - goto err_sw_node_delete; 390 - } 391 - 392 - WRITE_ONCE(priv->htb.defcls, htb_defcls); 393 - /* Order maj_id after defcls - pairs with 394 - * mlx5e_select_queue/mlx5e_select_htb_queues. 395 - */ 396 - smp_store_release(&priv->htb.maj_id, htb_maj_id); 397 - 398 - if (opened) 399 - mlx5e_selq_apply(&priv->selq); 400 - 401 - return 0; 402 - 403 - err_sw_node_delete: 404 - mlx5e_sw_node_delete(priv, root); 405 - 406 - err_free_queues: 407 - if (opened) 408 - mlx5e_qos_close_all_queues(&priv->channels); 409 - err_cancel_selq: 410 - mlx5e_selq_cancel(&priv->selq); 411 - return err; 412 - } 413 - 414 - int mlx5e_htb_root_del(struct mlx5e_priv *priv) 415 - { 416 - struct mlx5e_qos_node *root; 417 - int err; 418 - 419 - qos_dbg(priv->mdev, "TC_HTB_DESTROY\n"); 420 - 421 - /* Wait until real_num_tx_queues is updated for mlx5e_select_queue, 422 - * so that we can safely switch to its non-HTB non-PTP fastpath. 423 - */ 424 - synchronize_net(); 425 - 426 - mlx5e_selq_prepare(&priv->selq, &priv->channels.params, false); 427 - mlx5e_selq_apply(&priv->selq); 428 - 429 - WRITE_ONCE(priv->htb.maj_id, 0); 430 - 431 - root = mlx5e_sw_node_find(priv, MLX5E_HTB_CLASSID_ROOT); 432 - if (!root) { 433 - qos_err(priv->mdev, "Failed to find the root node in the QoS tree\n"); 434 - return -ENOENT; 435 - } 436 - err = mlx5_qos_destroy_node(priv->mdev, root->hw_id); 437 - if (err) 438 - qos_err(priv->mdev, "Failed to destroy root node %u, err = %d\n", 439 - root->hw_id, err); 440 - mlx5e_sw_node_delete(priv, root); 441 - 442 - mlx5e_qos_deactivate_all_queues(&priv->channels); 443 - mlx5e_qos_close_all_queues(&priv->channels); 444 - 445 - return err; 446 - } 447 - 448 - static int mlx5e_htb_convert_rate(struct mlx5e_priv *priv, u64 rate, 449 - struct mlx5e_qos_node *parent, u32 *bw_share) 450 - { 451 - u64 share = 0; 452 - 453 - while (parent->classid != MLX5E_HTB_CLASSID_ROOT && !parent->max_average_bw) 454 - parent = parent->parent; 455 - 456 - if (parent->max_average_bw) 457 - share = div64_u64(div_u64(rate * 100, BYTES_IN_MBIT), 458 - parent->max_average_bw); 459 - else 460 - share = 101; 461 - 462 - *bw_share = share == 0 ? 1 : share > 100 ? 0 : share; 463 - 464 - qos_dbg(priv->mdev, "Convert: rate %llu, parent ceil %llu -> bw_share %u\n", 465 - rate, (u64)parent->max_average_bw * BYTES_IN_MBIT, *bw_share); 466 - 467 - return 0; 468 - } 469 - 470 - static void mlx5e_htb_convert_ceil(struct mlx5e_priv *priv, u64 ceil, u32 *max_average_bw) 471 - { 472 - /* Hardware treats 0 as "unlimited", set at least 1. */ 473 - *max_average_bw = max_t(u32, div_u64(ceil, BYTES_IN_MBIT), 1); 474 - 475 - qos_dbg(priv->mdev, "Convert: ceil %llu -> max_average_bw %u\n", 476 - ceil, *max_average_bw); 477 - } 478 - 479 - int mlx5e_htb_leaf_alloc_queue(struct mlx5e_priv *priv, u16 classid, 480 - u32 parent_classid, u64 rate, u64 ceil, 481 - struct netlink_ext_ack *extack) 482 - { 483 - struct mlx5e_qos_node *node, *parent; 484 - int qid; 485 - int err; 486 - 487 - qos_dbg(priv->mdev, "TC_HTB_LEAF_ALLOC_QUEUE classid %04x, parent %04x, rate %llu, ceil %llu\n", 488 - classid, parent_classid, rate, ceil); 489 - 490 - qid = mlx5e_find_unused_qos_qid(priv); 491 - if (qid < 0) { 492 - NL_SET_ERR_MSG_MOD(extack, "Maximum amount of leaf classes is reached."); 493 - return qid; 494 - } 495 - 496 - parent = mlx5e_sw_node_find(priv, parent_classid); 497 - if (!parent) 498 - return -EINVAL; 499 - 500 - node = mlx5e_sw_node_create_leaf(priv, classid, qid, parent); 501 - if (IS_ERR(node)) 502 - return PTR_ERR(node); 503 - 504 - node->rate = rate; 505 - mlx5e_htb_convert_rate(priv, rate, node->parent, &node->bw_share); 506 - mlx5e_htb_convert_ceil(priv, ceil, &node->max_average_bw); 507 - 508 - err = mlx5_qos_create_leaf_node(priv->mdev, node->parent->hw_id, 509 - node->bw_share, node->max_average_bw, 510 - &node->hw_id); 511 - if (err) { 512 - NL_SET_ERR_MSG_MOD(extack, "Firmware error when creating a leaf node."); 513 - qos_err(priv->mdev, "Failed to create a leaf node (class %04x), err = %d\n", 514 - classid, err); 515 - mlx5e_sw_node_delete(priv, node); 516 - return err; 517 - } 518 - 519 - if (test_bit(MLX5E_STATE_OPENED, &priv->state)) { 520 - err = mlx5e_open_qos_sq(priv, &priv->channels, node); 521 - if (err) { 522 - NL_SET_ERR_MSG_MOD(extack, "Error creating an SQ."); 523 - qos_warn(priv->mdev, "Failed to create a QoS SQ (class %04x), err = %d\n", 524 - classid, err); 525 - } else { 526 - mlx5e_activate_qos_sq(priv, node); 527 - } 528 - } 529 - 530 - return mlx5e_qid_from_qos(&priv->channels, node->qid); 531 - } 532 - 533 - int mlx5e_htb_leaf_to_inner(struct mlx5e_priv *priv, u16 classid, u16 child_classid, 534 - u64 rate, u64 ceil, struct netlink_ext_ack *extack) 535 - { 536 - struct mlx5e_qos_node *node, *child; 537 - int err, tmp_err; 538 - u32 new_hw_id; 539 - u16 qid; 540 - 541 - qos_dbg(priv->mdev, "TC_HTB_LEAF_TO_INNER classid %04x, upcoming child %04x, rate %llu, ceil %llu\n", 542 - classid, child_classid, rate, ceil); 543 - 544 - node = mlx5e_sw_node_find(priv, classid); 545 - if (!node) 546 - return -ENOENT; 547 - 548 - err = mlx5_qos_create_inner_node(priv->mdev, node->parent->hw_id, 549 - node->bw_share, node->max_average_bw, 550 - &new_hw_id); 551 - if (err) { 552 - NL_SET_ERR_MSG_MOD(extack, "Firmware error when creating an inner node."); 553 - qos_err(priv->mdev, "Failed to create an inner node (class %04x), err = %d\n", 554 - classid, err); 555 - return err; 556 - } 557 - 558 - /* Intentionally reuse the qid for the upcoming first child. */ 559 - child = mlx5e_sw_node_create_leaf(priv, child_classid, node->qid, node); 560 - if (IS_ERR(child)) { 561 - err = PTR_ERR(child); 562 - goto err_destroy_hw_node; 563 - } 564 - 565 - child->rate = rate; 566 - mlx5e_htb_convert_rate(priv, rate, node, &child->bw_share); 567 - mlx5e_htb_convert_ceil(priv, ceil, &child->max_average_bw); 568 - 569 - err = mlx5_qos_create_leaf_node(priv->mdev, new_hw_id, child->bw_share, 570 - child->max_average_bw, &child->hw_id); 571 - if (err) { 572 - NL_SET_ERR_MSG_MOD(extack, "Firmware error when creating a leaf node."); 573 - qos_err(priv->mdev, "Failed to create a leaf node (class %04x), err = %d\n", 574 - classid, err); 575 - goto err_delete_sw_node; 576 - } 577 - 578 - /* No fail point. */ 579 - 580 - qid = node->qid; 581 - /* Pairs with mlx5e_get_txq_by_classid. */ 582 - WRITE_ONCE(node->qid, MLX5E_QOS_QID_INNER); 583 - 584 - if (test_bit(MLX5E_STATE_OPENED, &priv->state)) { 585 - mlx5e_deactivate_qos_sq(priv, qid); 586 - mlx5e_close_qos_sq(priv, qid); 587 - } 588 - 589 - err = mlx5_qos_destroy_node(priv->mdev, node->hw_id); 590 - if (err) /* Not fatal. */ 591 - qos_warn(priv->mdev, "Failed to destroy leaf node %u (class %04x), err = %d\n", 592 - node->hw_id, classid, err); 593 - 594 - node->hw_id = new_hw_id; 595 - 596 - if (test_bit(MLX5E_STATE_OPENED, &priv->state)) { 597 - err = mlx5e_open_qos_sq(priv, &priv->channels, child); 598 - if (err) { 599 - NL_SET_ERR_MSG_MOD(extack, "Error creating an SQ."); 600 - qos_warn(priv->mdev, "Failed to create a QoS SQ (class %04x), err = %d\n", 601 - classid, err); 602 - } else { 603 - mlx5e_activate_qos_sq(priv, child); 604 - } 605 - } 606 - 607 - return 0; 608 - 609 - err_delete_sw_node: 610 - child->qid = MLX5E_QOS_QID_INNER; 611 - mlx5e_sw_node_delete(priv, child); 612 - 613 - err_destroy_hw_node: 614 - tmp_err = mlx5_qos_destroy_node(priv->mdev, new_hw_id); 615 - if (tmp_err) /* Not fatal. */ 616 - qos_warn(priv->mdev, "Failed to roll back creation of an inner node %u (class %04x), err = %d\n", 617 - new_hw_id, classid, tmp_err); 618 - return err; 619 - } 620 - 621 - static struct mlx5e_qos_node *mlx5e_sw_node_find_by_qid(struct mlx5e_priv *priv, u16 qid) 622 - { 623 - struct mlx5e_qos_node *node = NULL; 624 - int bkt; 625 - 626 - hash_for_each(priv->htb.qos_tc2node, bkt, node, hnode) 627 - if (node->qid == qid) 628 - break; 629 - 630 - return node; 631 - } 632 - 633 - static void mlx5e_reactivate_qos_sq(struct mlx5e_priv *priv, u16 qid, struct netdev_queue *txq) 485 + void mlx5e_reactivate_qos_sq(struct mlx5e_priv *priv, u16 qid, struct netdev_queue *txq) 634 486 { 635 487 qos_dbg(priv->mdev, "Reactivate QoS SQ qid %u\n", qid); 636 488 netdev_tx_reset_queue(txq); 637 489 netif_tx_start_queue(txq); 638 490 } 639 491 640 - static void mlx5e_reset_qdisc(struct net_device *dev, u16 qid) 492 + void mlx5e_reset_qdisc(struct net_device *dev, u16 qid) 641 493 { 642 494 struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, qid); 643 495 struct Qdisc *qdisc = dev_queue->qdisc_sleeping; ··· 371 781 spin_unlock_bh(qdisc_lock(qdisc)); 372 782 } 373 783 374 - int mlx5e_htb_leaf_del(struct mlx5e_priv *priv, u16 *classid, 375 - struct netlink_ext_ack *extack) 784 + int mlx5e_htb_setup_tc(struct mlx5e_priv *priv, struct tc_htb_qopt_offload *htb_qopt) 376 785 { 377 - struct mlx5e_qos_node *node; 378 - struct netdev_queue *txq; 379 - u16 qid, moved_qid; 380 - bool opened; 381 - int err; 786 + struct mlx5e_htb *htb = priv->htb; 787 + int res; 382 788 383 - qos_dbg(priv->mdev, "TC_HTB_LEAF_DEL classid %04x\n", *classid); 789 + if (!htb && htb_qopt->command != TC_HTB_CREATE) 790 + return -EINVAL; 384 791 385 - node = mlx5e_sw_node_find(priv, *classid); 386 - if (!node) 387 - return -ENOENT; 388 - 389 - /* Store qid for reuse. */ 390 - qid = node->qid; 391 - 392 - opened = test_bit(MLX5E_STATE_OPENED, &priv->state); 393 - if (opened) { 394 - txq = netdev_get_tx_queue(priv->netdev, 395 - mlx5e_qid_from_qos(&priv->channels, qid)); 396 - mlx5e_deactivate_qos_sq(priv, qid); 397 - mlx5e_close_qos_sq(priv, qid); 398 - } 399 - 400 - err = mlx5_qos_destroy_node(priv->mdev, node->hw_id); 401 - if (err) /* Not fatal. */ 402 - qos_warn(priv->mdev, "Failed to destroy leaf node %u (class %04x), err = %d\n", 403 - node->hw_id, *classid, err); 404 - 405 - mlx5e_sw_node_delete(priv, node); 406 - 407 - moved_qid = mlx5e_qos_cur_leaf_nodes(priv); 408 - 409 - if (moved_qid == 0) { 410 - /* The last QoS SQ was just destroyed. */ 411 - if (opened) 412 - mlx5e_reactivate_qos_sq(priv, qid, txq); 792 + switch (htb_qopt->command) { 793 + case TC_HTB_CREATE: 794 + if (!mlx5_qos_is_supported(priv->mdev)) { 795 + NL_SET_ERR_MSG_MOD(htb_qopt->extack, 796 + "Missing QoS capabilities. Try disabling SRIOV or use a supported device."); 797 + return -EOPNOTSUPP; 798 + } 799 + priv->htb = mlx5e_htb_alloc(); 800 + htb = priv->htb; 801 + if (!htb) 802 + return -ENOMEM; 803 + res = mlx5e_htb_init(htb, htb_qopt, priv->netdev, priv->mdev, &priv->selq, priv); 804 + if (res) { 805 + mlx5e_htb_free(htb); 806 + priv->htb = NULL; 807 + } 808 + return res; 809 + case TC_HTB_DESTROY: 810 + mlx5e_htb_cleanup(htb); 811 + mlx5e_htb_free(htb); 812 + priv->htb = NULL; 413 813 return 0; 414 - } 415 - moved_qid--; 416 - 417 - if (moved_qid < qid) { 418 - /* The highest QoS SQ was just destroyed. */ 419 - WARN(moved_qid != qid - 1, "Gaps in queue numeration: destroyed queue %u, the highest queue is %u", 420 - qid, moved_qid); 421 - if (opened) 422 - mlx5e_reactivate_qos_sq(priv, qid, txq); 814 + case TC_HTB_LEAF_ALLOC_QUEUE: 815 + res = mlx5e_htb_leaf_alloc_queue(htb, htb_qopt->classid, htb_qopt->parent_classid, 816 + htb_qopt->rate, htb_qopt->ceil, htb_qopt->extack); 817 + if (res < 0) 818 + return res; 819 + htb_qopt->qid = res; 423 820 return 0; 821 + case TC_HTB_LEAF_TO_INNER: 822 + return mlx5e_htb_leaf_to_inner(htb, htb_qopt->parent_classid, htb_qopt->classid, 823 + htb_qopt->rate, htb_qopt->ceil, htb_qopt->extack); 824 + case TC_HTB_LEAF_DEL: 825 + return mlx5e_htb_leaf_del(htb, &htb_qopt->classid, htb_qopt->extack); 826 + case TC_HTB_LEAF_DEL_LAST: 827 + case TC_HTB_LEAF_DEL_LAST_FORCE: 828 + return mlx5e_htb_leaf_del_last(htb, htb_qopt->classid, 829 + htb_qopt->command == TC_HTB_LEAF_DEL_LAST_FORCE, 830 + htb_qopt->extack); 831 + case TC_HTB_NODE_MODIFY: 832 + return mlx5e_htb_node_modify(htb, htb_qopt->classid, htb_qopt->rate, htb_qopt->ceil, 833 + htb_qopt->extack); 834 + case TC_HTB_LEAF_QUERY_QUEUE: 835 + res = mlx5e_htb_get_txq_by_classid(htb, htb_qopt->classid); 836 + if (res < 0) 837 + return res; 838 + htb_qopt->qid = res; 839 + return 0; 840 + default: 841 + return -EOPNOTSUPP; 424 842 } 425 - 426 - WARN(moved_qid == qid, "Can't move node with qid %u to itself", qid); 427 - qos_dbg(priv->mdev, "Moving QoS SQ %u to %u\n", moved_qid, qid); 428 - 429 - node = mlx5e_sw_node_find_by_qid(priv, moved_qid); 430 - WARN(!node, "Could not find a node with qid %u to move to queue %u", 431 - moved_qid, qid); 432 - 433 - /* Stop traffic to the old queue. */ 434 - WRITE_ONCE(node->qid, MLX5E_QOS_QID_INNER); 435 - __clear_bit(moved_qid, priv->htb.qos_used_qids); 436 - 437 - if (opened) { 438 - txq = netdev_get_tx_queue(priv->netdev, 439 - mlx5e_qid_from_qos(&priv->channels, moved_qid)); 440 - mlx5e_deactivate_qos_sq(priv, moved_qid); 441 - mlx5e_close_qos_sq(priv, moved_qid); 442 - } 443 - 444 - /* Prevent packets from the old class from getting into the new one. */ 445 - mlx5e_reset_qdisc(priv->netdev, moved_qid); 446 - 447 - __set_bit(qid, priv->htb.qos_used_qids); 448 - WRITE_ONCE(node->qid, qid); 449 - 450 - if (test_bit(MLX5E_STATE_OPENED, &priv->state)) { 451 - err = mlx5e_open_qos_sq(priv, &priv->channels, node); 452 - if (err) { 453 - NL_SET_ERR_MSG_MOD(extack, "Error creating an SQ."); 454 - qos_warn(priv->mdev, "Failed to create a QoS SQ (class %04x) while moving qid %u to %u, err = %d\n", 455 - node->classid, moved_qid, qid, err); 456 - } else { 457 - mlx5e_activate_qos_sq(priv, node); 458 - } 459 - } 460 - 461 - mlx5e_update_tx_netdev_queues(priv); 462 - if (opened) 463 - mlx5e_reactivate_qos_sq(priv, moved_qid, txq); 464 - 465 - *classid = node->classid; 466 - return 0; 467 - } 468 - 469 - int mlx5e_htb_leaf_del_last(struct mlx5e_priv *priv, u16 classid, bool force, 470 - struct netlink_ext_ack *extack) 471 - { 472 - struct mlx5e_qos_node *node, *parent; 473 - u32 old_hw_id, new_hw_id; 474 - int err, saved_err = 0; 475 - u16 qid; 476 - 477 - qos_dbg(priv->mdev, "TC_HTB_LEAF_DEL_LAST%s classid %04x\n", 478 - force ? "_FORCE" : "", classid); 479 - 480 - node = mlx5e_sw_node_find(priv, classid); 481 - if (!node) 482 - return -ENOENT; 483 - 484 - err = mlx5_qos_create_leaf_node(priv->mdev, node->parent->parent->hw_id, 485 - node->parent->bw_share, 486 - node->parent->max_average_bw, 487 - &new_hw_id); 488 - if (err) { 489 - NL_SET_ERR_MSG_MOD(extack, "Firmware error when creating a leaf node."); 490 - qos_err(priv->mdev, "Failed to create a leaf node (class %04x), err = %d\n", 491 - classid, err); 492 - if (!force) 493 - return err; 494 - saved_err = err; 495 - } 496 - 497 - /* Store qid for reuse and prevent clearing the bit. */ 498 - qid = node->qid; 499 - /* Pairs with mlx5e_get_txq_by_classid. */ 500 - WRITE_ONCE(node->qid, MLX5E_QOS_QID_INNER); 501 - 502 - if (test_bit(MLX5E_STATE_OPENED, &priv->state)) { 503 - mlx5e_deactivate_qos_sq(priv, qid); 504 - mlx5e_close_qos_sq(priv, qid); 505 - } 506 - 507 - /* Prevent packets from the old class from getting into the new one. */ 508 - mlx5e_reset_qdisc(priv->netdev, qid); 509 - 510 - err = mlx5_qos_destroy_node(priv->mdev, node->hw_id); 511 - if (err) /* Not fatal. */ 512 - qos_warn(priv->mdev, "Failed to destroy leaf node %u (class %04x), err = %d\n", 513 - node->hw_id, classid, err); 514 - 515 - parent = node->parent; 516 - mlx5e_sw_node_delete(priv, node); 517 - 518 - node = parent; 519 - WRITE_ONCE(node->qid, qid); 520 - 521 - /* Early return on error in force mode. Parent will still be an inner 522 - * node to be deleted by a following delete operation. 523 - */ 524 - if (saved_err) 525 - return saved_err; 526 - 527 - old_hw_id = node->hw_id; 528 - node->hw_id = new_hw_id; 529 - 530 - if (test_bit(MLX5E_STATE_OPENED, &priv->state)) { 531 - err = mlx5e_open_qos_sq(priv, &priv->channels, node); 532 - if (err) { 533 - NL_SET_ERR_MSG_MOD(extack, "Error creating an SQ."); 534 - qos_warn(priv->mdev, "Failed to create a QoS SQ (class %04x), err = %d\n", 535 - classid, err); 536 - } else { 537 - mlx5e_activate_qos_sq(priv, node); 538 - } 539 - } 540 - 541 - err = mlx5_qos_destroy_node(priv->mdev, old_hw_id); 542 - if (err) /* Not fatal. */ 543 - qos_warn(priv->mdev, "Failed to destroy leaf node %u (class %04x), err = %d\n", 544 - node->hw_id, classid, err); 545 - 546 - return 0; 547 - } 548 - 549 - static int mlx5e_qos_update_children(struct mlx5e_priv *priv, struct mlx5e_qos_node *node, 550 - struct netlink_ext_ack *extack) 551 - { 552 - struct mlx5e_qos_node *child; 553 - int err = 0; 554 - int bkt; 555 - 556 - hash_for_each(priv->htb.qos_tc2node, bkt, child, hnode) { 557 - u32 old_bw_share = child->bw_share; 558 - int err_one; 559 - 560 - if (child->parent != node) 561 - continue; 562 - 563 - mlx5e_htb_convert_rate(priv, child->rate, node, &child->bw_share); 564 - if (child->bw_share == old_bw_share) 565 - continue; 566 - 567 - err_one = mlx5_qos_update_node(priv->mdev, child->hw_id, child->bw_share, 568 - child->max_average_bw, child->hw_id); 569 - if (!err && err_one) { 570 - err = err_one; 571 - 572 - NL_SET_ERR_MSG_MOD(extack, "Firmware error when modifying a child node."); 573 - qos_err(priv->mdev, "Failed to modify a child node (class %04x), err = %d\n", 574 - node->classid, err); 575 - } 576 - } 577 - 578 - return err; 579 - } 580 - 581 - int mlx5e_htb_node_modify(struct mlx5e_priv *priv, u16 classid, u64 rate, u64 ceil, 582 - struct netlink_ext_ack *extack) 583 - { 584 - u32 bw_share, max_average_bw; 585 - struct mlx5e_qos_node *node; 586 - bool ceil_changed = false; 587 - int err; 588 - 589 - qos_dbg(priv->mdev, "TC_HTB_LEAF_MODIFY classid %04x, rate %llu, ceil %llu\n", 590 - classid, rate, ceil); 591 - 592 - node = mlx5e_sw_node_find(priv, classid); 593 - if (!node) 594 - return -ENOENT; 595 - 596 - node->rate = rate; 597 - mlx5e_htb_convert_rate(priv, rate, node->parent, &bw_share); 598 - mlx5e_htb_convert_ceil(priv, ceil, &max_average_bw); 599 - 600 - err = mlx5_qos_update_node(priv->mdev, node->parent->hw_id, bw_share, 601 - max_average_bw, node->hw_id); 602 - if (err) { 603 - NL_SET_ERR_MSG_MOD(extack, "Firmware error when modifying a node."); 604 - qos_err(priv->mdev, "Failed to modify a node (class %04x), err = %d\n", 605 - classid, err); 606 - return err; 607 - } 608 - 609 - if (max_average_bw != node->max_average_bw) 610 - ceil_changed = true; 611 - 612 - node->bw_share = bw_share; 613 - node->max_average_bw = max_average_bw; 614 - 615 - if (ceil_changed) 616 - err = mlx5e_qos_update_children(priv, node, extack); 617 - 618 - return err; 619 843 } 620 844 621 845 struct mlx5e_mqprio_rl { ··· 515 1111 *hw_id = rl->leaves_id[tc]; 516 1112 return 0; 517 1113 } 1114 +
+18 -19
drivers/net/ethernet/mellanox/mlx5/core/en/qos.h
··· 6 6 7 7 #include <linux/mlx5/driver.h> 8 8 9 - #define MLX5E_QOS_MAX_LEAF_NODES 256 9 + #define BYTES_IN_MBIT 125000 10 10 11 11 struct mlx5e_priv; 12 + struct mlx5e_htb; 12 13 struct mlx5e_channels; 13 14 struct mlx5e_channel; 15 + struct tc_htb_qopt_offload; 14 16 15 17 int mlx5e_qos_bytes_rate_check(struct mlx5_core_dev *mdev, u64 nbytes); 16 18 int mlx5e_qos_max_leaf_nodes(struct mlx5_core_dev *mdev); 17 - int mlx5e_qos_cur_leaf_nodes(struct mlx5e_priv *priv); 18 - 19 - /* TX datapath API */ 20 - int mlx5e_get_txq_by_classid(struct mlx5e_priv *priv, u16 classid); 21 19 22 20 /* SQ lifecycle */ 21 + int mlx5e_open_qos_sq(struct mlx5e_priv *priv, struct mlx5e_channels *chs, 22 + u16 node_qid, u32 hw_id); 23 + int mlx5e_activate_qos_sq(void *data, u16 node_qid, u32 hw_id); 24 + void mlx5e_deactivate_qos_sq(struct mlx5e_priv *priv, u16 qid); 25 + void mlx5e_close_qos_sq(struct mlx5e_priv *priv, u16 qid); 26 + void mlx5e_reactivate_qos_sq(struct mlx5e_priv *priv, u16 qid, struct netdev_queue *txq); 27 + void mlx5e_reset_qdisc(struct net_device *dev, u16 qid); 28 + 23 29 int mlx5e_qos_open_queues(struct mlx5e_priv *priv, struct mlx5e_channels *chs); 24 30 void mlx5e_qos_activate_queues(struct mlx5e_priv *priv); 25 31 void mlx5e_qos_deactivate_queues(struct mlx5e_channel *c); 32 + void mlx5e_qos_deactivate_all_queues(struct mlx5e_channels *chs); 26 33 void mlx5e_qos_close_queues(struct mlx5e_channel *c); 34 + void mlx5e_qos_close_all_queues(struct mlx5e_channels *chs); 35 + int mlx5e_qos_alloc_queues(struct mlx5e_priv *priv, struct mlx5e_channels *chs); 36 + 37 + /* TX datapath API */ 38 + u16 mlx5e_qid_from_qos(struct mlx5e_channels *chs, u16 qid); 27 39 28 40 /* HTB API */ 29 - int mlx5e_htb_root_add(struct mlx5e_priv *priv, u16 htb_maj_id, u16 htb_defcls, 30 - struct netlink_ext_ack *extack); 31 - int mlx5e_htb_root_del(struct mlx5e_priv *priv); 32 - int mlx5e_htb_leaf_alloc_queue(struct mlx5e_priv *priv, u16 classid, 33 - u32 parent_classid, u64 rate, u64 ceil, 34 - struct netlink_ext_ack *extack); 35 - int mlx5e_htb_leaf_to_inner(struct mlx5e_priv *priv, u16 classid, u16 child_classid, 36 - u64 rate, u64 ceil, struct netlink_ext_ack *extack); 37 - int mlx5e_htb_leaf_del(struct mlx5e_priv *priv, u16 *classid, 38 - struct netlink_ext_ack *extack); 39 - int mlx5e_htb_leaf_del_last(struct mlx5e_priv *priv, u16 classid, bool force, 40 - struct netlink_ext_ack *extack); 41 - int mlx5e_htb_node_modify(struct mlx5e_priv *priv, u16 classid, u64 rate, u64 ceil, 42 - struct netlink_ext_ack *extack); 41 + int mlx5e_htb_setup_tc(struct mlx5e_priv *priv, struct tc_htb_qopt_offload *htb); 43 42 44 43 /* MQPRIO TX rate limit */ 45 44 struct mlx5e_mqprio_rl;
+43 -8
drivers/net/ethernet/mellanox/mlx5/core/en/selq.c
··· 7 7 #include <linux/rcupdate.h> 8 8 #include "en.h" 9 9 #include "en/ptp.h" 10 + #include "en/htb.h" 10 11 11 12 struct mlx5e_selq_params { 12 13 unsigned int num_regular_queues; ··· 20 19 bool is_ptp : 1; 21 20 }; 22 21 }; 22 + u16 htb_maj_id; 23 + u16 htb_defcls; 23 24 }; 24 25 25 26 int mlx5e_selq_init(struct mlx5e_selq *selq, struct mutex *state_lock) ··· 47 44 .num_tcs = 1, 48 45 .is_htb = false, 49 46 .is_ptp = false, 47 + .htb_maj_id = 0, 48 + .htb_defcls = 0, 50 49 }; 51 50 rcu_assign_pointer(selq->active, init_params); 52 51 ··· 69 64 selq->standby = NULL; 70 65 } 71 66 72 - void mlx5e_selq_prepare(struct mlx5e_selq *selq, struct mlx5e_params *params, bool htb) 67 + void mlx5e_selq_prepare_params(struct mlx5e_selq *selq, struct mlx5e_params *params) 73 68 { 69 + struct mlx5e_selq_params *selq_active; 70 + 74 71 lockdep_assert_held(selq->state_lock); 75 72 WARN_ON_ONCE(selq->is_prepared); 76 73 77 74 selq->is_prepared = true; 78 75 76 + selq_active = rcu_dereference_protected(selq->active, 77 + lockdep_is_held(selq->state_lock)); 78 + *selq->standby = *selq_active; 79 79 selq->standby->num_channels = params->num_channels; 80 80 selq->standby->num_tcs = mlx5e_get_dcb_num_tc(params); 81 81 selq->standby->num_regular_queues = 82 82 selq->standby->num_channels * selq->standby->num_tcs; 83 - selq->standby->is_htb = htb; 84 83 selq->standby->is_ptp = MLX5E_GET_PFLAG(params, MLX5E_PFLAG_TX_PORT_TS); 84 + } 85 + 86 + bool mlx5e_selq_is_htb_enabled(struct mlx5e_selq *selq) 87 + { 88 + struct mlx5e_selq_params *selq_active = 89 + rcu_dereference_protected(selq->active, lockdep_is_held(selq->state_lock)); 90 + 91 + return selq_active->htb_maj_id; 92 + } 93 + 94 + void mlx5e_selq_prepare_htb(struct mlx5e_selq *selq, u16 htb_maj_id, u16 htb_defcls) 95 + { 96 + struct mlx5e_selq_params *selq_active; 97 + 98 + lockdep_assert_held(selq->state_lock); 99 + WARN_ON_ONCE(selq->is_prepared); 100 + 101 + selq->is_prepared = true; 102 + 103 + selq_active = rcu_dereference_protected(selq->active, 104 + lockdep_is_held(selq->state_lock)); 105 + *selq->standby = *selq_active; 106 + selq->standby->is_htb = htb_maj_id; 107 + selq->standby->htb_maj_id = htb_maj_id; 108 + selq->standby->htb_defcls = htb_defcls; 85 109 } 86 110 87 111 void mlx5e_selq_apply(struct mlx5e_selq *selq) ··· 171 137 return selq->num_regular_queues + up; 172 138 } 173 139 174 - static int mlx5e_select_htb_queue(struct mlx5e_priv *priv, struct sk_buff *skb) 140 + static int mlx5e_select_htb_queue(struct mlx5e_priv *priv, struct sk_buff *skb, 141 + struct mlx5e_selq_params *selq) 175 142 { 176 143 u16 classid; 177 144 178 145 /* Order maj_id before defcls - pairs with mlx5e_htb_root_add. */ 179 - if ((TC_H_MAJ(skb->priority) >> 16) == smp_load_acquire(&priv->htb.maj_id)) 146 + if ((TC_H_MAJ(skb->priority) >> 16) == selq->htb_maj_id) 180 147 classid = TC_H_MIN(skb->priority); 181 148 else 182 - classid = READ_ONCE(priv->htb.defcls); 149 + classid = selq->htb_defcls; 183 150 184 151 if (!classid) 185 152 return 0; 186 153 187 - return mlx5e_get_txq_by_classid(priv, classid); 154 + return mlx5e_htb_get_txq_by_classid(priv->htb, classid); 188 155 } 189 156 190 157 u16 mlx5e_select_queue(struct net_device *dev, struct sk_buff *skb, ··· 222 187 up * selq->num_channels; 223 188 } 224 189 225 - if (unlikely(selq->is_htb)) { 190 + if (unlikely(selq->htb_maj_id)) { 226 191 /* num_tcs == 1, shortcut for PTP */ 227 192 228 - txq_ix = mlx5e_select_htb_queue(priv, skb); 193 + txq_ix = mlx5e_select_htb_queue(priv, skb, selq); 229 194 if (txq_ix > 0) 230 195 return txq_ix; 231 196
+3 -1
drivers/net/ethernet/mellanox/mlx5/core/en/selq.h
··· 21 21 22 22 int mlx5e_selq_init(struct mlx5e_selq *selq, struct mutex *state_lock); 23 23 void mlx5e_selq_cleanup(struct mlx5e_selq *selq); 24 - void mlx5e_selq_prepare(struct mlx5e_selq *selq, struct mlx5e_params *params, bool htb); 24 + void mlx5e_selq_prepare_params(struct mlx5e_selq *selq, struct mlx5e_params *params); 25 + void mlx5e_selq_prepare_htb(struct mlx5e_selq *selq, u16 htb_maj_id, u16 htb_defcls); 26 + bool mlx5e_selq_is_htb_enabled(struct mlx5e_selq *selq); 25 27 void mlx5e_selq_apply(struct mlx5e_selq *selq); 26 28 void mlx5e_selq_cancel(struct mlx5e_selq *selq); 27 29
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c
··· 36 36 int err; 37 37 38 38 if (!MLX5_CAP_FLOWTABLE_TYPE(priv->mdev, ignore_flow_level, table_type)) { 39 - if (priv->mdev->coredev_type != MLX5_COREDEV_VF) 39 + if (priv->mdev->coredev_type == MLX5_COREDEV_PF) 40 40 mlx5_core_warn(priv->mdev, "firmware level support is missing\n"); 41 41 err = -EOPNOTSUPP; 42 42 goto err_check;
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
··· 2062 2062 /* Ignore_flow_level support isn't supported by default for VFs and so post_act 2063 2063 * won't be supported. Skip showing error msg. 2064 2064 */ 2065 - if (priv->mdev->coredev_type != MLX5_COREDEV_VF) 2065 + if (priv->mdev->coredev_type == MLX5_COREDEV_PF) 2066 2066 err_msg = "post action is missing"; 2067 2067 err = -EOPNOTSUPP; 2068 2068 goto out_err;
+12 -4
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
··· 30 30 * SOFTWARE. 31 31 */ 32 32 33 + #include <linux/ethtool_netlink.h> 34 + 33 35 #include "en.h" 34 36 #include "en/port.h" 35 37 #include "en/params.h" ··· 307 305 } 308 306 309 307 void mlx5e_ethtool_get_ringparam(struct mlx5e_priv *priv, 310 - struct ethtool_ringparam *param) 308 + struct ethtool_ringparam *param, 309 + struct kernel_ethtool_ringparam *kernel_param) 311 310 { 312 311 param->rx_max_pending = 1 << MLX5E_PARAMS_MAXIMUM_LOG_RQ_SIZE; 313 312 param->tx_max_pending = 1 << MLX5E_PARAMS_MAXIMUM_LOG_SQ_SIZE; 314 313 param->rx_pending = 1 << priv->channels.params.log_rq_mtu_frames; 315 314 param->tx_pending = 1 << priv->channels.params.log_sq_size; 315 + 316 + kernel_param->tcp_data_split = 317 + (priv->channels.params.packet_merge.type == MLX5E_PACKET_MERGE_SHAMPO) ? 318 + ETHTOOL_TCP_DATA_SPLIT_ENABLED : 319 + ETHTOOL_TCP_DATA_SPLIT_DISABLED; 316 320 } 317 321 318 322 static void mlx5e_get_ringparam(struct net_device *dev, ··· 328 320 { 329 321 struct mlx5e_priv *priv = netdev_priv(dev); 330 322 331 - mlx5e_ethtool_get_ringparam(priv, param); 323 + mlx5e_ethtool_get_ringparam(priv, param, kernel_param); 332 324 } 333 325 334 326 int mlx5e_ethtool_set_ringparam(struct mlx5e_priv *priv, ··· 459 451 * because the numeration of the QoS SQs will change, while per-queue 460 452 * qdiscs are attached. 461 453 */ 462 - if (priv->htb.maj_id) { 454 + if (mlx5e_selq_is_htb_enabled(&priv->selq)) { 463 455 err = -EINVAL; 464 456 netdev_err(priv->netdev, "%s: HTB offload is active, cannot change the number of channels\n", 465 457 __func__); ··· 2075 2067 * the numeration of the QoS SQs will change, while per-queue qdiscs are 2076 2068 * attached. 2077 2069 */ 2078 - if (priv->htb.maj_id) { 2070 + if (mlx5e_selq_is_htb_enabled(&priv->selq)) { 2079 2071 netdev_err(priv->netdev, "%s: HTB offload is active, cannot change the PTP state\n", 2080 2072 __func__); 2081 2073 return -EINVAL;
+129 -99
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
··· 31 31 */ 32 32 33 33 #include <net/tc_act/tc_gact.h> 34 - #include <net/pkt_cls.h> 35 34 #include <linux/mlx5/fs.h> 36 35 #include <net/vxlan.h> 37 36 #include <net/geneve.h> ··· 63 64 #include "en/devlink.h" 64 65 #include "lib/mlx5.h" 65 66 #include "en/ptp.h" 67 + #include "en/htb.h" 66 68 #include "qos.h" 67 69 #include "en/trap.h" 68 70 ··· 1912 1912 { 1913 1913 int tc; 1914 1914 1915 - if (params->mqprio.mode != TC_MQPRIO_MODE_CHANNEL || 1916 - !params->mqprio.channel.rl) { 1915 + if (params->mqprio.mode != TC_MQPRIO_MODE_CHANNEL) { 1917 1916 *hw_id = 0; 1918 1917 return 0; 1919 1918 } ··· 1921 1922 if (tc < 0) 1922 1923 return tc; 1923 1924 1924 - return mlx5e_mqprio_rl_get_node_hw_id(params->mqprio.channel.rl, tc, hw_id); 1925 + if (tc >= params->mqprio.num_tc) { 1926 + WARN(1, "Unexpected TCs configuration. tc %d is out of range of %u", 1927 + tc, params->mqprio.num_tc); 1928 + return -EINVAL; 1929 + } 1930 + 1931 + *hw_id = params->mqprio.channel.hw_id[tc]; 1932 + return 0; 1925 1933 } 1926 1934 1927 1935 static int mlx5e_open_sqs(struct mlx5e_channel *c, ··· 2389 2383 goto err_close_channels; 2390 2384 } 2391 2385 2392 - err = mlx5e_qos_open_queues(priv, chs); 2393 - if (err) 2394 - goto err_close_ptp; 2386 + if (priv->htb) { 2387 + err = mlx5e_qos_open_queues(priv, chs); 2388 + if (err) 2389 + goto err_close_ptp; 2390 + } 2395 2391 2396 2392 mlx5e_health_channels_update(priv); 2397 2393 kvfree(cparam); ··· 2575 2567 2576 2568 int mlx5e_update_tx_netdev_queues(struct mlx5e_priv *priv) 2577 2569 { 2578 - int qos_queues, nch, ntc, num_txqs, err; 2570 + int nch, ntc, num_txqs, err; 2571 + int qos_queues = 0; 2579 2572 2580 - qos_queues = mlx5e_qos_cur_leaf_nodes(priv); 2573 + if (priv->htb) 2574 + qos_queues = mlx5e_htb_cur_leaf_nodes(priv->htb); 2581 2575 2582 2576 nch = priv->channels.params.num_channels; 2583 2577 ntc = mlx5e_get_dcb_num_tc(&priv->channels.params); ··· 2624 2614 if (err) { 2625 2615 netdev_warn(netdev, "netif_set_real_num_rx_queues failed, %d\n", err); 2626 2616 goto err_txqs; 2627 - } 2628 - if (priv->mqprio_rl != priv->channels.params.mqprio.channel.rl) { 2629 - if (priv->mqprio_rl) { 2630 - mlx5e_mqprio_rl_cleanup(priv->mqprio_rl); 2631 - mlx5e_mqprio_rl_free(priv->mqprio_rl); 2632 - } 2633 - priv->mqprio_rl = priv->channels.params.mqprio.channel.rl; 2634 2617 } 2635 2618 2636 2619 return 0; ··· 2727 2724 { 2728 2725 mlx5e_build_txq_maps(priv); 2729 2726 mlx5e_activate_channels(&priv->channels); 2730 - mlx5e_qos_activate_queues(priv); 2727 + if (priv->htb) 2728 + mlx5e_qos_activate_queues(priv); 2731 2729 mlx5e_xdp_tx_enable(priv); 2732 2730 2733 2731 /* dev_watchdog() wants all TX queues to be started when the carrier is ··· 2845 2841 2846 2842 new_chs.params = *params; 2847 2843 2848 - mlx5e_selq_prepare(&priv->selq, &new_chs.params, !!priv->htb.maj_id); 2844 + mlx5e_selq_prepare_params(&priv->selq, &new_chs.params); 2849 2845 2850 2846 err = mlx5e_open_channels(priv, &new_chs); 2851 2847 if (err) ··· 2901 2897 struct mlx5e_priv *priv = netdev_priv(netdev); 2902 2898 int err; 2903 2899 2904 - mlx5e_selq_prepare(&priv->selq, &priv->channels.params, !!priv->htb.maj_id); 2900 + mlx5e_selq_prepare_params(&priv->selq, &priv->channels.params); 2905 2901 2906 2902 set_bit(MLX5E_STATE_OPENED, &priv->state); 2907 2903 ··· 3139 3135 3140 3136 static void mlx5e_cleanup_nic_tx(struct mlx5e_priv *priv) 3141 3137 { 3138 + if (priv->mqprio_rl) { 3139 + mlx5e_mqprio_rl_cleanup(priv->mqprio_rl); 3140 + mlx5e_mqprio_rl_free(priv->mqprio_rl); 3141 + priv->mqprio_rl = NULL; 3142 + } 3142 3143 mlx5e_destroy_tises(priv); 3143 3144 } 3144 3145 ··· 3212 3203 { 3213 3204 params->mqprio.mode = TC_MQPRIO_MODE_DCB; 3214 3205 params->mqprio.num_tc = num_tc; 3215 - params->mqprio.channel.rl = NULL; 3216 3206 mlx5e_mqprio_build_default_tc_to_txq(params->mqprio.tc_to_txq, num_tc, 3217 3207 params->num_channels); 3218 3208 } 3219 3209 3210 + static void mlx5e_mqprio_rl_update_params(struct mlx5e_params *params, 3211 + struct mlx5e_mqprio_rl *rl) 3212 + { 3213 + int tc; 3214 + 3215 + for (tc = 0; tc < TC_MAX_QUEUE; tc++) { 3216 + u32 hw_id = 0; 3217 + 3218 + if (rl) 3219 + mlx5e_mqprio_rl_get_node_hw_id(rl, tc, &hw_id); 3220 + params->mqprio.channel.hw_id[tc] = hw_id; 3221 + } 3222 + } 3223 + 3220 3224 static void mlx5e_params_mqprio_channel_set(struct mlx5e_params *params, 3221 - struct tc_mqprio_qopt *qopt, 3225 + struct tc_mqprio_qopt_offload *mqprio, 3222 3226 struct mlx5e_mqprio_rl *rl) 3223 3227 { 3228 + int tc; 3229 + 3224 3230 params->mqprio.mode = TC_MQPRIO_MODE_CHANNEL; 3225 - params->mqprio.num_tc = qopt->num_tc; 3226 - params->mqprio.channel.rl = rl; 3227 - mlx5e_mqprio_build_tc_to_txq(params->mqprio.tc_to_txq, qopt); 3231 + params->mqprio.num_tc = mqprio->qopt.num_tc; 3232 + 3233 + for (tc = 0; tc < TC_MAX_QUEUE; tc++) 3234 + params->mqprio.channel.max_rate[tc] = mqprio->max_rate[tc]; 3235 + 3236 + mlx5e_mqprio_rl_update_params(params, rl); 3237 + mlx5e_mqprio_build_tc_to_txq(params->mqprio.tc_to_txq, &mqprio->qopt); 3228 3238 } 3229 3239 3230 3240 static void mlx5e_params_mqprio_reset(struct mlx5e_params *params) ··· 3268 3240 3269 3241 err = mlx5e_safe_switch_params(priv, &new_params, 3270 3242 mlx5e_num_channels_changed_ctx, NULL, true); 3243 + 3244 + if (!err && priv->mqprio_rl) { 3245 + mlx5e_mqprio_rl_cleanup(priv->mqprio_rl); 3246 + mlx5e_mqprio_rl_free(priv->mqprio_rl); 3247 + priv->mqprio_rl = NULL; 3248 + } 3271 3249 3272 3250 priv->max_opened_tc = max_t(u8, priv->max_opened_tc, 3273 3251 mlx5e_get_dcb_num_tc(&priv->channels.params)); ··· 3333 3299 return 0; 3334 3300 } 3335 3301 3336 - static bool mlx5e_mqprio_rate_limit(struct tc_mqprio_qopt_offload *mqprio) 3302 + static bool mlx5e_mqprio_rate_limit(u8 num_tc, u64 max_rate[]) 3337 3303 { 3338 3304 int tc; 3339 3305 3340 - for (tc = 0; tc < mqprio->qopt.num_tc; tc++) 3341 - if (mqprio->max_rate[tc]) 3306 + for (tc = 0; tc < num_tc; tc++) 3307 + if (max_rate[tc]) 3342 3308 return true; 3343 3309 return false; 3310 + } 3311 + 3312 + static struct mlx5e_mqprio_rl *mlx5e_mqprio_rl_create(struct mlx5_core_dev *mdev, 3313 + u8 num_tc, u64 max_rate[]) 3314 + { 3315 + struct mlx5e_mqprio_rl *rl; 3316 + int err; 3317 + 3318 + if (!mlx5e_mqprio_rate_limit(num_tc, max_rate)) 3319 + return NULL; 3320 + 3321 + rl = mlx5e_mqprio_rl_alloc(); 3322 + if (!rl) 3323 + return ERR_PTR(-ENOMEM); 3324 + 3325 + err = mlx5e_mqprio_rl_init(rl, mdev, num_tc, max_rate); 3326 + if (err) { 3327 + mlx5e_mqprio_rl_free(rl); 3328 + return ERR_PTR(err); 3329 + } 3330 + 3331 + return rl; 3344 3332 } 3345 3333 3346 3334 static int mlx5e_setup_tc_mqprio_channel(struct mlx5e_priv *priv, ··· 3378 3322 if (err) 3379 3323 return err; 3380 3324 3381 - rl = NULL; 3382 - if (mlx5e_mqprio_rate_limit(mqprio)) { 3383 - rl = mlx5e_mqprio_rl_alloc(); 3384 - if (!rl) 3385 - return -ENOMEM; 3386 - err = mlx5e_mqprio_rl_init(rl, priv->mdev, mqprio->qopt.num_tc, 3387 - mqprio->max_rate); 3388 - if (err) { 3389 - mlx5e_mqprio_rl_free(rl); 3390 - return err; 3391 - } 3392 - } 3325 + rl = mlx5e_mqprio_rl_create(priv->mdev, mqprio->qopt.num_tc, mqprio->max_rate); 3326 + if (IS_ERR(rl)) 3327 + return PTR_ERR(rl); 3393 3328 3394 3329 new_params = priv->channels.params; 3395 - mlx5e_params_mqprio_channel_set(&new_params, &mqprio->qopt, rl); 3330 + mlx5e_params_mqprio_channel_set(&new_params, mqprio, rl); 3396 3331 3397 3332 nch_changed = mlx5e_get_dcb_num_tc(&priv->channels.params) > 1; 3398 3333 preactivate = nch_changed ? mlx5e_num_channels_changed_ctx : 3399 3334 mlx5e_update_netdev_queues_ctx; 3400 3335 err = mlx5e_safe_switch_params(priv, &new_params, preactivate, NULL, true); 3401 - if (err && rl) { 3402 - mlx5e_mqprio_rl_cleanup(rl); 3403 - mlx5e_mqprio_rl_free(rl); 3336 + if (err) { 3337 + if (rl) { 3338 + mlx5e_mqprio_rl_cleanup(rl); 3339 + mlx5e_mqprio_rl_free(rl); 3340 + } 3341 + return err; 3404 3342 } 3405 3343 3406 - return err; 3344 + if (priv->mqprio_rl) { 3345 + mlx5e_mqprio_rl_cleanup(priv->mqprio_rl); 3346 + mlx5e_mqprio_rl_free(priv->mqprio_rl); 3347 + } 3348 + priv->mqprio_rl = rl; 3349 + 3350 + return 0; 3407 3351 } 3408 3352 3409 3353 static int mlx5e_setup_tc_mqprio(struct mlx5e_priv *priv, ··· 3412 3356 /* MQPRIO is another toplevel qdisc that can't be attached 3413 3357 * simultaneously with the offloaded HTB. 3414 3358 */ 3415 - if (WARN_ON(priv->htb.maj_id)) 3359 + if (WARN_ON(mlx5e_selq_is_htb_enabled(&priv->selq))) 3416 3360 return -EINVAL; 3417 3361 3418 3362 switch (mqprio->mode) { ··· 3420 3364 return mlx5e_setup_tc_mqprio_dcb(priv, &mqprio->qopt); 3421 3365 case TC_MQPRIO_MODE_CHANNEL: 3422 3366 return mlx5e_setup_tc_mqprio_channel(priv, mqprio); 3423 - default: 3424 - return -EOPNOTSUPP; 3425 - } 3426 - } 3427 - 3428 - static int mlx5e_setup_tc_htb(struct mlx5e_priv *priv, struct tc_htb_qopt_offload *htb) 3429 - { 3430 - int res; 3431 - 3432 - switch (htb->command) { 3433 - case TC_HTB_CREATE: 3434 - return mlx5e_htb_root_add(priv, htb->parent_classid, htb->classid, 3435 - htb->extack); 3436 - case TC_HTB_DESTROY: 3437 - return mlx5e_htb_root_del(priv); 3438 - case TC_HTB_LEAF_ALLOC_QUEUE: 3439 - res = mlx5e_htb_leaf_alloc_queue(priv, htb->classid, htb->parent_classid, 3440 - htb->rate, htb->ceil, htb->extack); 3441 - if (res < 0) 3442 - return res; 3443 - htb->qid = res; 3444 - return 0; 3445 - case TC_HTB_LEAF_TO_INNER: 3446 - return mlx5e_htb_leaf_to_inner(priv, htb->parent_classid, htb->classid, 3447 - htb->rate, htb->ceil, htb->extack); 3448 - case TC_HTB_LEAF_DEL: 3449 - return mlx5e_htb_leaf_del(priv, &htb->classid, htb->extack); 3450 - case TC_HTB_LEAF_DEL_LAST: 3451 - case TC_HTB_LEAF_DEL_LAST_FORCE: 3452 - return mlx5e_htb_leaf_del_last(priv, htb->classid, 3453 - htb->command == TC_HTB_LEAF_DEL_LAST_FORCE, 3454 - htb->extack); 3455 - case TC_HTB_NODE_MODIFY: 3456 - return mlx5e_htb_node_modify(priv, htb->classid, htb->rate, htb->ceil, 3457 - htb->extack); 3458 - case TC_HTB_LEAF_QUERY_QUEUE: 3459 - res = mlx5e_get_txq_by_classid(priv, htb->classid); 3460 - if (res < 0) 3461 - return res; 3462 - htb->qid = res; 3463 - return 0; 3464 3367 default: 3465 3368 return -EOPNOTSUPP; 3466 3369 } ··· 3458 3443 return err; 3459 3444 case TC_SETUP_QDISC_HTB: 3460 3445 mutex_lock(&priv->state_lock); 3461 - err = mlx5e_setup_tc_htb(priv, type_data); 3446 + err = mlx5e_htb_setup_tc(priv, type_data); 3462 3447 mutex_unlock(&priv->state_lock); 3463 3448 return err; 3464 3449 default: ··· 3678 3663 static int set_feature_hw_tc(struct net_device *netdev, bool enable) 3679 3664 { 3680 3665 struct mlx5e_priv *priv = netdev_priv(netdev); 3666 + int err = 0; 3681 3667 3682 3668 #if IS_ENABLED(CONFIG_MLX5_CLS_ACT) 3683 3669 if (!enable && mlx5e_tc_num_filters(priv, MLX5_TC_FLAG(NIC_OFFLOAD))) { ··· 3688 3672 } 3689 3673 #endif 3690 3674 3691 - if (!enable && priv->htb.maj_id) { 3675 + mutex_lock(&priv->state_lock); 3676 + if (!enable && mlx5e_selq_is_htb_enabled(&priv->selq)) { 3692 3677 netdev_err(netdev, "Active HTB offload, can't turn hw_tc_offload off\n"); 3693 - return -EINVAL; 3678 + err = -EINVAL; 3694 3679 } 3680 + mutex_unlock(&priv->state_lock); 3695 3681 3696 - return 0; 3682 + return err; 3697 3683 } 3698 3684 3699 3685 static int set_feature_rx_all(struct net_device *netdev, bool enable) ··· 5120 5102 priv->rx_res = NULL; 5121 5103 } 5122 5104 5105 + static void mlx5e_set_mqprio_rl(struct mlx5e_priv *priv) 5106 + { 5107 + struct mlx5e_params *params; 5108 + struct mlx5e_mqprio_rl *rl; 5109 + 5110 + params = &priv->channels.params; 5111 + if (params->mqprio.mode != TC_MQPRIO_MODE_CHANNEL) 5112 + return; 5113 + 5114 + rl = mlx5e_mqprio_rl_create(priv->mdev, params->mqprio.num_tc, 5115 + params->mqprio.channel.max_rate); 5116 + if (IS_ERR(rl)) 5117 + rl = NULL; 5118 + priv->mqprio_rl = rl; 5119 + mlx5e_mqprio_rl_update_params(params, rl); 5120 + } 5121 + 5123 5122 static int mlx5e_init_nic_tx(struct mlx5e_priv *priv) 5124 5123 { 5125 5124 int err; ··· 5147 5112 return err; 5148 5113 } 5149 5114 5115 + mlx5e_set_mqprio_rl(priv); 5150 5116 mlx5e_dcbnl_initialize(priv); 5151 5117 return 0; 5152 5118 } ··· 5321 5285 if (err) 5322 5286 goto err_free_cpumask; 5323 5287 5324 - hash_init(priv->htb.qos_tc2node); 5325 5288 INIT_WORK(&priv->update_carrier_work, mlx5e_update_carrier_work); 5326 5289 INIT_WORK(&priv->set_rx_mode_work, mlx5e_set_rx_mode_work); 5327 5290 INIT_WORK(&priv->tx_timeout_work, mlx5e_tx_timeout_work); ··· 5377 5342 mutex_unlock(&priv->state_lock); 5378 5343 free_cpumask_var(priv->scratchpad.cpumask); 5379 5344 5380 - for (i = 0; i < priv->htb.max_qos_sqs; i++) 5381 - kfree(priv->htb.qos_sq_stats[i]); 5382 - kvfree(priv->htb.qos_sq_stats); 5383 - 5384 - if (priv->mqprio_rl) { 5385 - mlx5e_mqprio_rl_cleanup(priv->mqprio_rl); 5386 - mlx5e_mqprio_rl_free(priv->mqprio_rl); 5387 - } 5345 + for (i = 0; i < priv->htb_max_qos_sqs; i++) 5346 + kfree(priv->htb_qos_sq_stats[i]); 5347 + kvfree(priv->htb_qos_sq_stats); 5388 5348 5389 5349 memset(priv, 0, sizeof(*priv)); 5390 5350 }
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
··· 229 229 { 230 230 struct mlx5e_priv *priv = netdev_priv(dev); 231 231 232 - mlx5e_ethtool_get_ringparam(priv, param); 232 + mlx5e_ethtool_get_ringparam(priv, param, kernel_param); 233 233 } 234 234 235 235 static int
+8 -6
drivers/net/ethernet/mellanox/mlx5/core/en_stats.c
··· 474 474 int i; 475 475 476 476 /* Pairs with smp_store_release in mlx5e_open_qos_sq. */ 477 - max_qos_sqs = smp_load_acquire(&priv->htb.max_qos_sqs); 478 - stats = READ_ONCE(priv->htb.qos_sq_stats); 477 + max_qos_sqs = smp_load_acquire(&priv->htb_max_qos_sqs); 478 + stats = READ_ONCE(priv->htb_qos_sq_stats); 479 479 480 480 for (i = 0; i < max_qos_sqs; i++) { 481 481 mlx5e_stats_grp_sw_update_stats_sq(s, READ_ONCE(stats[i])); ··· 2100 2100 { MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, err_cqe) }, 2101 2101 { MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, abort) }, 2102 2102 { MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, abort_abs_diff_ns) }, 2103 + { MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, resync_cqe) }, 2104 + { MLX5E_DECLARE_PTP_CQ_STAT(struct mlx5e_ptp_cq_stats, resync_event) }, 2103 2105 }; 2104 2106 2105 2107 static const struct counter_desc ptp_rq_stats_desc[] = { ··· 2186 2184 static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(qos) 2187 2185 { 2188 2186 /* Pairs with smp_store_release in mlx5e_open_qos_sq. */ 2189 - return NUM_QOS_SQ_STATS * smp_load_acquire(&priv->htb.max_qos_sqs); 2187 + return NUM_QOS_SQ_STATS * smp_load_acquire(&priv->htb_max_qos_sqs); 2190 2188 } 2191 2189 2192 2190 static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(qos) 2193 2191 { 2194 2192 /* Pairs with smp_store_release in mlx5e_open_qos_sq. */ 2195 - u16 max_qos_sqs = smp_load_acquire(&priv->htb.max_qos_sqs); 2193 + u16 max_qos_sqs = smp_load_acquire(&priv->htb_max_qos_sqs); 2196 2194 int i, qid; 2197 2195 2198 2196 for (qid = 0; qid < max_qos_sqs; qid++) ··· 2210 2208 int i, qid; 2211 2209 2212 2210 /* Pairs with smp_store_release in mlx5e_open_qos_sq. */ 2213 - max_qos_sqs = smp_load_acquire(&priv->htb.max_qos_sqs); 2214 - stats = READ_ONCE(priv->htb.qos_sq_stats); 2211 + max_qos_sqs = smp_load_acquire(&priv->htb_max_qos_sqs); 2212 + stats = READ_ONCE(priv->htb_qos_sq_stats); 2215 2213 2216 2214 for (qid = 0; qid < max_qos_sqs; qid++) { 2217 2215 struct mlx5e_sq_stats *s = READ_ONCE(stats[qid]);
+2
drivers/net/ethernet/mellanox/mlx5/core/en_stats.h
··· 453 453 u64 err_cqe; 454 454 u64 abort; 455 455 u64 abort_abs_diff_ns; 456 + u64 resync_cqe; 457 + u64 resync_event; 456 458 }; 457 459 458 460 struct mlx5e_stats {
+10
drivers/net/ethernet/mellanox/mlx5/core/en_tx.c
··· 631 631 mlx5e_tx_mpwqe_session_complete(sq); 632 632 } 633 633 634 + static void mlx5e_cqe_ts_id_eseg(struct mlx5e_ptpsq *ptpsq, struct sk_buff *skb, 635 + struct mlx5_wqe_eth_seg *eseg) 636 + { 637 + if (ptpsq->ts_cqe_ctr_mask && unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) 638 + eseg->flow_table_metadata = cpu_to_be32(ptpsq->skb_fifo_pc & 639 + ptpsq->ts_cqe_ctr_mask); 640 + } 641 + 634 642 static void mlx5e_txwqe_build_eseg(struct mlx5e_priv *priv, struct mlx5e_txqsq *sq, 635 643 struct sk_buff *skb, struct mlx5e_accel_tx_state *accel, 636 644 struct mlx5_wqe_eth_seg *eseg, u16 ihs) 637 645 { 638 646 mlx5e_accel_tx_eseg(priv, skb, eseg, ihs); 639 647 mlx5e_txwqe_build_eseg_csum(sq, skb, accel, eseg); 648 + if (unlikely(sq->ptpsq)) 649 + mlx5e_cqe_ts_id_eseg(sq->ptpsq, skb, eseg); 640 650 } 641 651 642 652 netdev_tx_t mlx5e_xmit(struct sk_buff *skb, struct net_device *dev)
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
··· 83 83 { 84 84 struct mlx5e_priv *priv = mlx5i_epriv(dev); 85 85 86 - mlx5e_ethtool_get_ringparam(priv, param); 86 + mlx5e_ethtool_get_ringparam(priv, param, kernel_param); 87 87 } 88 88 89 89 static int mlx5i_set_channels(struct net_device *dev,
+5 -1
include/linux/mlx5/mlx5_ifc.h
··· 1833 1833 u8 sw_vhca_id[0xe]; 1834 1834 u8 reserved_at_230[0x10]; 1835 1835 1836 - u8 reserved_at_240[0x5c0]; 1836 + u8 reserved_at_240[0xb]; 1837 + u8 ts_cqe_metadata_size2wqe_counter[0x5]; 1838 + u8 reserved_at_250[0x10]; 1839 + 1840 + u8 reserved_at_260[0x5a0]; 1837 1841 }; 1838 1842 1839 1843 enum mlx5_ifc_flow_destination_type {