1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
5 #include <linux/slab.h>
6 #include <linux/netdevice.h>
9 struct mlx5e_selq_params {
10 unsigned int num_regular_queues;
11 unsigned int num_channels;
17 int mlx5e_selq_init(struct mlx5e_selq *selq, struct mutex *state_lock)
19 struct mlx5e_selq_params *init_params;
21 selq->state_lock = state_lock;
23 selq->standby = kvzalloc(sizeof(*selq->standby), GFP_KERNEL);
27 init_params = kvzalloc(sizeof(*selq->active), GFP_KERNEL);
29 kvfree(selq->standby);
33 /* Assign dummy values, so that mlx5e_select_queue won't crash. */
34 *init_params = (struct mlx5e_selq_params) {
35 .num_regular_queues = 1,
41 rcu_assign_pointer(selq->active, init_params);
46 void mlx5e_selq_cleanup(struct mlx5e_selq *selq)
48 WARN_ON_ONCE(selq->is_prepared);
50 kvfree(selq->standby);
52 selq->is_prepared = true;
54 mlx5e_selq_apply(selq);
56 kvfree(selq->standby);
60 void mlx5e_selq_prepare(struct mlx5e_selq *selq, struct mlx5e_params *params, bool htb)
62 lockdep_assert_held(selq->state_lock);
63 WARN_ON_ONCE(selq->is_prepared);
65 selq->is_prepared = true;
67 selq->standby->num_channels = params->num_channels;
68 selq->standby->num_tcs = mlx5e_get_dcb_num_tc(params);
69 selq->standby->num_regular_queues =
70 selq->standby->num_channels * selq->standby->num_tcs;
71 selq->standby->is_htb = htb;
72 selq->standby->is_ptp = MLX5E_GET_PFLAG(params, MLX5E_PFLAG_TX_PORT_TS);
75 void mlx5e_selq_apply(struct mlx5e_selq *selq)
77 struct mlx5e_selq_params *old_params;
79 WARN_ON_ONCE(!selq->is_prepared);
81 selq->is_prepared = false;
83 old_params = rcu_replace_pointer(selq->active, selq->standby,
84 lockdep_is_held(selq->state_lock));
85 synchronize_net(); /* Wait until ndo_select_queue starts emitting correct values. */
86 selq->standby = old_params;
89 void mlx5e_selq_cancel(struct mlx5e_selq *selq)
91 lockdep_assert_held(selq->state_lock);
92 WARN_ON_ONCE(!selq->is_prepared);
94 selq->is_prepared = false;