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 'net-mlx5-qos-refactor-esw-qos-to-support-new-features'

Tariq Toukan says:

====================
net/mlx5: qos: Refactor esw qos to support new features

This patch series by Cosmin and Carolina prepares the mlx5 qos infra for
the upcoming feature of cross E-Switch scheduling.

Noop cleanups:
net/mlx5: qos: Flesh out element_attributes in mlx5_ifc.h
net/mlx5: qos: Rename vport 'tsar' into 'sched_elem'.
net/mlx5: qos: Consistently name vport vars as 'vport'
net/mlx5: qos: Refactor and document bw_share calculation
net/mlx5: qos: Rename rate group 'list' as 'parent_entry'

Refactor the code with the goal of moving groups out of E-Switches:
net/mlx5: qos: Maintain rate group vport members in a list
net/mlx5: qos: Always create group0
net/mlx5: qos: Drop 'esw' param from vport qos functions
net/mlx5: qos: Store the eswitch in a mlx5_esw_rate_group

Move groups from an E-Switch into an mlx5_qos_domain:
net/mlx5: qos: Store rate groups in a qos domain

Refactor locking to use a new mutex in the qos domain:
net/mlx5: qos: Refactor locking to a qos domain mutex

In follow-up patchsets, we'll allow qos domains to be shared
between E-Switches of the same NIC.

The two top patches are simple enhancements.
====================

Link: https://patch.msgid.link/20241008183222.137702-1-tariqt@nvidia.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+549 -378
+21 -18
drivers/net/ethernet/mellanox/mlx5/core/esw/diag/qos_tracepoint.h
··· 11 11 #include "eswitch.h" 12 12 13 13 TRACE_EVENT(mlx5_esw_vport_qos_destroy, 14 - TP_PROTO(const struct mlx5_vport *vport), 15 - TP_ARGS(vport), 16 - TP_STRUCT__entry(__string(devname, dev_name(vport->dev->device)) 14 + TP_PROTO(const struct mlx5_core_dev *dev, const struct mlx5_vport *vport), 15 + TP_ARGS(dev, vport), 16 + TP_STRUCT__entry(__string(devname, dev_name(dev->device)) 17 17 __field(unsigned short, vport_id) 18 - __field(unsigned int, tsar_ix) 18 + __field(unsigned int, sched_elem_ix) 19 19 ), 20 20 TP_fast_assign(__assign_str(devname); 21 21 __entry->vport_id = vport->vport; 22 - __entry->tsar_ix = vport->qos.esw_tsar_ix; 22 + __entry->sched_elem_ix = vport->qos.esw_sched_elem_ix; 23 23 ), 24 - TP_printk("(%s) vport=%hu tsar_ix=%u\n", 25 - __get_str(devname), __entry->vport_id, __entry->tsar_ix 24 + TP_printk("(%s) vport=%hu sched_elem_ix=%u\n", 25 + __get_str(devname), __entry->vport_id, __entry->sched_elem_ix 26 26 ) 27 27 ); 28 28 29 29 DECLARE_EVENT_CLASS(mlx5_esw_vport_qos_template, 30 - TP_PROTO(const struct mlx5_vport *vport, u32 bw_share, u32 max_rate), 31 - TP_ARGS(vport, bw_share, max_rate), 32 - TP_STRUCT__entry(__string(devname, dev_name(vport->dev->device)) 30 + TP_PROTO(const struct mlx5_core_dev *dev, const struct mlx5_vport *vport, 31 + u32 bw_share, u32 max_rate), 32 + TP_ARGS(dev, vport, bw_share, max_rate), 33 + TP_STRUCT__entry(__string(devname, dev_name(dev->device)) 33 34 __field(unsigned short, vport_id) 34 - __field(unsigned int, tsar_ix) 35 + __field(unsigned int, sched_elem_ix) 35 36 __field(unsigned int, bw_share) 36 37 __field(unsigned int, max_rate) 37 38 __field(void *, group) 38 39 ), 39 40 TP_fast_assign(__assign_str(devname); 40 41 __entry->vport_id = vport->vport; 41 - __entry->tsar_ix = vport->qos.esw_tsar_ix; 42 + __entry->sched_elem_ix = vport->qos.esw_sched_elem_ix; 42 43 __entry->bw_share = bw_share; 43 44 __entry->max_rate = max_rate; 44 45 __entry->group = vport->qos.group; 45 46 ), 46 - TP_printk("(%s) vport=%hu tsar_ix=%u bw_share=%u, max_rate=%u group=%p\n", 47 - __get_str(devname), __entry->vport_id, __entry->tsar_ix, 47 + TP_printk("(%s) vport=%hu sched_elem_ix=%u bw_share=%u, max_rate=%u group=%p\n", 48 + __get_str(devname), __entry->vport_id, __entry->sched_elem_ix, 48 49 __entry->bw_share, __entry->max_rate, __entry->group 49 50 ) 50 51 ); 51 52 52 53 DEFINE_EVENT(mlx5_esw_vport_qos_template, mlx5_esw_vport_qos_create, 53 - TP_PROTO(const struct mlx5_vport *vport, u32 bw_share, u32 max_rate), 54 - TP_ARGS(vport, bw_share, max_rate) 54 + TP_PROTO(const struct mlx5_core_dev *dev, const struct mlx5_vport *vport, 55 + u32 bw_share, u32 max_rate), 56 + TP_ARGS(dev, vport, bw_share, max_rate) 55 57 ); 56 58 57 59 DEFINE_EVENT(mlx5_esw_vport_qos_template, mlx5_esw_vport_qos_config, 58 - TP_PROTO(const struct mlx5_vport *vport, u32 bw_share, u32 max_rate), 59 - TP_ARGS(vport, bw_share, max_rate) 60 + TP_PROTO(const struct mlx5_core_dev *dev, const struct mlx5_vport *vport, 61 + u32 bw_share, u32 max_rate), 62 + TP_ARGS(dev, vport, bw_share, max_rate) 60 63 ); 61 64 62 65 DECLARE_EVENT_CLASS(mlx5_esw_group_qos_template,
+1 -5
drivers/net/ethernet/mellanox/mlx5/core/esw/legacy.c
··· 513 513 u32 max_rate, u32 min_rate) 514 514 { 515 515 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 516 - int err; 517 516 518 517 if (!mlx5_esw_allowed(esw)) 519 518 return -EPERM; 520 519 if (IS_ERR(evport)) 521 520 return PTR_ERR(evport); 522 521 523 - mutex_lock(&esw->state_lock); 524 - err = mlx5_esw_qos_set_vport_rate(esw, evport, max_rate, min_rate); 525 - mutex_unlock(&esw->state_lock); 526 - return err; 522 + return mlx5_esw_qos_set_vport_rate(evport, max_rate, min_rate); 527 523 }
+376 -296
drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
··· 11 11 /* Minimum supported BW share value by the HW is 1 Mbit/sec */ 12 12 #define MLX5_MIN_BW_SHARE 1 13 13 14 - #define MLX5_RATE_TO_BW_SHARE(rate, divider, limit) \ 15 - min_t(u32, max_t(u32, DIV_ROUND_UP(rate, divider), MLX5_MIN_BW_SHARE), limit) 14 + /* Holds rate groups associated with an E-Switch. */ 15 + struct mlx5_qos_domain { 16 + /* Serializes access to all qos changes in the qos domain. */ 17 + struct mutex lock; 18 + /* List of all mlx5_esw_rate_groups. */ 19 + struct list_head groups; 20 + }; 21 + 22 + static void esw_qos_lock(struct mlx5_eswitch *esw) 23 + { 24 + mutex_lock(&esw->qos.domain->lock); 25 + } 26 + 27 + static void esw_qos_unlock(struct mlx5_eswitch *esw) 28 + { 29 + mutex_unlock(&esw->qos.domain->lock); 30 + } 31 + 32 + static void esw_assert_qos_lock_held(struct mlx5_eswitch *esw) 33 + { 34 + lockdep_assert_held(&esw->qos.domain->lock); 35 + } 36 + 37 + static struct mlx5_qos_domain *esw_qos_domain_alloc(void) 38 + { 39 + struct mlx5_qos_domain *qos_domain; 40 + 41 + qos_domain = kzalloc(sizeof(*qos_domain), GFP_KERNEL); 42 + if (!qos_domain) 43 + return NULL; 44 + 45 + mutex_init(&qos_domain->lock); 46 + INIT_LIST_HEAD(&qos_domain->groups); 47 + 48 + return qos_domain; 49 + } 50 + 51 + static int esw_qos_domain_init(struct mlx5_eswitch *esw) 52 + { 53 + esw->qos.domain = esw_qos_domain_alloc(); 54 + 55 + return esw->qos.domain ? 0 : -ENOMEM; 56 + } 57 + 58 + static void esw_qos_domain_release(struct mlx5_eswitch *esw) 59 + { 60 + kfree(esw->qos.domain); 61 + esw->qos.domain = NULL; 62 + } 16 63 17 64 struct mlx5_esw_rate_group { 18 65 u32 tsar_ix; 66 + /* Bandwidth parameters. */ 19 67 u32 max_rate; 20 68 u32 min_rate; 69 + /* A computed value indicating relative min_rate between group members. */ 21 70 u32 bw_share; 22 - struct list_head list; 71 + /* Membership in the qos domain 'groups' list. */ 72 + struct list_head parent_entry; 73 + /* The eswitch this group belongs to. */ 74 + struct mlx5_eswitch *esw; 75 + /* Vport members of this group.*/ 76 + struct list_head members; 23 77 }; 24 78 25 - static int esw_qos_tsar_config(struct mlx5_core_dev *dev, u32 *sched_ctx, 26 - u32 tsar_ix, u32 max_rate, u32 bw_share) 79 + static void esw_qos_vport_set_group(struct mlx5_vport *vport, struct mlx5_esw_rate_group *group) 27 80 { 81 + list_del_init(&vport->qos.group_entry); 82 + vport->qos.group = group; 83 + list_add_tail(&vport->qos.group_entry, &group->members); 84 + } 85 + 86 + static int esw_qos_sched_elem_config(struct mlx5_core_dev *dev, u32 sched_elem_ix, 87 + u32 max_rate, u32 bw_share) 88 + { 89 + u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {}; 28 90 u32 bitmask = 0; 29 91 30 92 if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling)) ··· 100 38 return mlx5_modify_scheduling_element_cmd(dev, 101 39 SCHEDULING_HIERARCHY_E_SWITCH, 102 40 sched_ctx, 103 - tsar_ix, 41 + sched_elem_ix, 104 42 bitmask); 105 43 } 106 44 107 - static int esw_qos_group_config(struct mlx5_eswitch *esw, struct mlx5_esw_rate_group *group, 45 + static int esw_qos_group_config(struct mlx5_esw_rate_group *group, 108 46 u32 max_rate, u32 bw_share, struct netlink_ext_ack *extack) 109 47 { 110 - u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {}; 111 - struct mlx5_core_dev *dev = esw->dev; 48 + struct mlx5_core_dev *dev = group->esw->dev; 112 49 int err; 113 50 114 - err = esw_qos_tsar_config(dev, sched_ctx, 115 - group->tsar_ix, 116 - max_rate, bw_share); 51 + err = esw_qos_sched_elem_config(dev, group->tsar_ix, max_rate, bw_share); 117 52 if (err) 118 53 NL_SET_ERR_MSG_MOD(extack, "E-Switch modify group TSAR element failed"); 119 54 ··· 119 60 return err; 120 61 } 121 62 122 - static int esw_qos_vport_config(struct mlx5_eswitch *esw, 123 - struct mlx5_vport *vport, 63 + static int esw_qos_vport_config(struct mlx5_vport *vport, 124 64 u32 max_rate, u32 bw_share, 125 65 struct netlink_ext_ack *extack) 126 66 { 127 - u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {}; 128 - struct mlx5_core_dev *dev = esw->dev; 67 + struct mlx5_core_dev *dev = vport->qos.group->esw->dev; 129 68 int err; 130 69 131 - if (!vport->qos.enabled) 132 - return -EIO; 133 - 134 - err = esw_qos_tsar_config(dev, sched_ctx, vport->qos.esw_tsar_ix, 135 - max_rate, bw_share); 70 + err = esw_qos_sched_elem_config(dev, vport->qos.esw_sched_elem_ix, max_rate, bw_share); 136 71 if (err) { 137 - esw_warn(esw->dev, 138 - "E-Switch modify TSAR vport element failed (vport=%d,err=%d)\n", 72 + esw_warn(dev, 73 + "E-Switch modify vport scheduling element failed (vport=%d,err=%d)\n", 139 74 vport->vport, err); 140 - NL_SET_ERR_MSG_MOD(extack, "E-Switch modify TSAR vport element failed"); 75 + NL_SET_ERR_MSG_MOD(extack, "E-Switch modify vport scheduling element failed"); 141 76 return err; 142 77 } 143 78 144 - trace_mlx5_esw_vport_qos_config(vport, bw_share, max_rate); 79 + trace_mlx5_esw_vport_qos_config(dev, vport, bw_share, max_rate); 145 80 146 81 return 0; 147 82 } 148 83 149 - static u32 esw_qos_calculate_min_rate_divider(struct mlx5_eswitch *esw, 150 - struct mlx5_esw_rate_group *group, 151 - bool group_level) 84 + static u32 esw_qos_calculate_group_min_rate_divider(struct mlx5_esw_rate_group *group) 152 85 { 153 - u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share); 154 - struct mlx5_vport *evport; 86 + u32 fw_max_bw_share = MLX5_CAP_QOS(group->esw->dev, max_tsar_bw_share); 87 + struct mlx5_vport *vport; 155 88 u32 max_guarantee = 0; 156 - unsigned long i; 157 89 158 - if (group_level) { 159 - struct mlx5_esw_rate_group *group; 160 - 161 - list_for_each_entry(group, &esw->qos.groups, list) { 162 - if (group->min_rate < max_guarantee) 163 - continue; 164 - max_guarantee = group->min_rate; 165 - } 166 - } else { 167 - mlx5_esw_for_each_vport(esw, i, evport) { 168 - if (!evport->enabled || !evport->qos.enabled || 169 - evport->qos.group != group || evport->qos.min_rate < max_guarantee) 170 - continue; 171 - max_guarantee = evport->qos.min_rate; 172 - } 90 + /* Find max min_rate across all vports in this group. 91 + * This will correspond to fw_max_bw_share in the final bw_share calculation. 92 + */ 93 + list_for_each_entry(vport, &group->members, qos.group_entry) { 94 + if (vport->qos.min_rate > max_guarantee) 95 + max_guarantee = vport->qos.min_rate; 173 96 } 174 97 175 98 if (max_guarantee) 176 99 return max_t(u32, max_guarantee / fw_max_bw_share, 1); 177 100 178 - /* If vports min rate divider is 0 but their group has bw_share configured, then 179 - * need to set bw_share for vports to minimal value. 101 + /* If vports max min_rate divider is 0 but their group has bw_share 102 + * configured, then set bw_share for vports to minimal value. 180 103 */ 181 - if (!group_level && !max_guarantee && group && group->bw_share) 104 + if (group->bw_share) 182 105 return 1; 106 + 107 + /* A divider of 0 sets bw_share for all group vports to 0, 108 + * effectively disabling min guarantees. 109 + */ 110 + return 0; 111 + } 112 + 113 + static u32 esw_qos_calculate_min_rate_divider(struct mlx5_eswitch *esw) 114 + { 115 + u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share); 116 + struct mlx5_esw_rate_group *group; 117 + u32 max_guarantee = 0; 118 + 119 + /* Find max min_rate across all esw groups. 120 + * This will correspond to fw_max_bw_share in the final bw_share calculation. 121 + */ 122 + list_for_each_entry(group, &esw->qos.domain->groups, parent_entry) { 123 + if (group->esw == esw && group->tsar_ix != esw->qos.root_tsar_ix && 124 + group->min_rate > max_guarantee) 125 + max_guarantee = group->min_rate; 126 + } 127 + 128 + if (max_guarantee) 129 + return max_t(u32, max_guarantee / fw_max_bw_share, 1); 130 + 131 + /* If no group has min_rate configured, a divider of 0 sets all 132 + * groups' bw_share to 0, effectively disabling min guarantees. 133 + */ 183 134 return 0; 184 135 } 185 136 186 137 static u32 esw_qos_calc_bw_share(u32 min_rate, u32 divider, u32 fw_max) 187 138 { 188 - if (divider) 189 - return MLX5_RATE_TO_BW_SHARE(min_rate, divider, fw_max); 190 - 191 - return 0; 139 + if (!divider) 140 + return 0; 141 + return min_t(u32, max_t(u32, DIV_ROUND_UP(min_rate, divider), MLX5_MIN_BW_SHARE), fw_max); 192 142 } 193 143 194 - static int esw_qos_normalize_vports_min_rate(struct mlx5_eswitch *esw, 195 - struct mlx5_esw_rate_group *group, 196 - struct netlink_ext_ack *extack) 144 + static int esw_qos_normalize_group_min_rate(struct mlx5_esw_rate_group *group, 145 + struct netlink_ext_ack *extack) 197 146 { 198 - u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share); 199 - u32 divider = esw_qos_calculate_min_rate_divider(esw, group, false); 200 - struct mlx5_vport *evport; 201 - unsigned long i; 147 + u32 fw_max_bw_share = MLX5_CAP_QOS(group->esw->dev, max_tsar_bw_share); 148 + u32 divider = esw_qos_calculate_group_min_rate_divider(group); 149 + struct mlx5_vport *vport; 202 150 u32 bw_share; 203 151 int err; 204 152 205 - mlx5_esw_for_each_vport(esw, i, evport) { 206 - if (!evport->enabled || !evport->qos.enabled || evport->qos.group != group) 207 - continue; 208 - bw_share = esw_qos_calc_bw_share(evport->qos.min_rate, divider, fw_max_bw_share); 153 + list_for_each_entry(vport, &group->members, qos.group_entry) { 154 + bw_share = esw_qos_calc_bw_share(vport->qos.min_rate, divider, fw_max_bw_share); 209 155 210 - if (bw_share == evport->qos.bw_share) 156 + if (bw_share == vport->qos.bw_share) 211 157 continue; 212 158 213 - err = esw_qos_vport_config(esw, evport, evport->qos.max_rate, bw_share, extack); 159 + err = esw_qos_vport_config(vport, vport->qos.max_rate, bw_share, extack); 214 160 if (err) 215 161 return err; 216 162 217 - evport->qos.bw_share = bw_share; 163 + vport->qos.bw_share = bw_share; 218 164 } 219 165 220 166 return 0; 221 167 } 222 168 223 - static int esw_qos_normalize_groups_min_rate(struct mlx5_eswitch *esw, u32 divider, 224 - struct netlink_ext_ack *extack) 169 + static int esw_qos_normalize_min_rate(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack) 225 170 { 226 171 u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share); 172 + u32 divider = esw_qos_calculate_min_rate_divider(esw); 227 173 struct mlx5_esw_rate_group *group; 228 174 u32 bw_share; 229 175 int err; 230 176 231 - list_for_each_entry(group, &esw->qos.groups, list) { 177 + list_for_each_entry(group, &esw->qos.domain->groups, parent_entry) { 178 + if (group->esw != esw || group->tsar_ix == esw->qos.root_tsar_ix) 179 + continue; 232 180 bw_share = esw_qos_calc_bw_share(group->min_rate, divider, fw_max_bw_share); 233 181 234 182 if (bw_share == group->bw_share) 235 183 continue; 236 184 237 - err = esw_qos_group_config(esw, group, group->max_rate, bw_share, extack); 185 + err = esw_qos_group_config(group, group->max_rate, bw_share, extack); 238 186 if (err) 239 187 return err; 240 188 ··· 250 184 /* All the group's vports need to be set with default bw_share 251 185 * to enable them with QOS 252 186 */ 253 - err = esw_qos_normalize_vports_min_rate(esw, group, extack); 187 + err = esw_qos_normalize_group_min_rate(group, extack); 254 188 255 189 if (err) 256 190 return err; ··· 259 193 return 0; 260 194 } 261 195 262 - static int esw_qos_set_vport_min_rate(struct mlx5_eswitch *esw, struct mlx5_vport *evport, 196 + static int esw_qos_set_vport_min_rate(struct mlx5_vport *vport, 263 197 u32 min_rate, struct netlink_ext_ack *extack) 264 198 { 199 + struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 265 200 u32 fw_max_bw_share, previous_min_rate; 266 201 bool min_rate_supported; 267 202 int err; 268 203 269 - lockdep_assert_held(&esw->state_lock); 270 - fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share); 271 - min_rate_supported = MLX5_CAP_QOS(esw->dev, esw_bw_share) && 204 + esw_assert_qos_lock_held(esw); 205 + fw_max_bw_share = MLX5_CAP_QOS(vport->dev, max_tsar_bw_share); 206 + min_rate_supported = MLX5_CAP_QOS(vport->dev, esw_bw_share) && 272 207 fw_max_bw_share >= MLX5_MIN_BW_SHARE; 273 208 if (min_rate && !min_rate_supported) 274 209 return -EOPNOTSUPP; 275 - if (min_rate == evport->qos.min_rate) 210 + if (min_rate == vport->qos.min_rate) 276 211 return 0; 277 212 278 - previous_min_rate = evport->qos.min_rate; 279 - evport->qos.min_rate = min_rate; 280 - err = esw_qos_normalize_vports_min_rate(esw, evport->qos.group, extack); 213 + previous_min_rate = vport->qos.min_rate; 214 + vport->qos.min_rate = min_rate; 215 + err = esw_qos_normalize_group_min_rate(vport->qos.group, extack); 281 216 if (err) 282 - evport->qos.min_rate = previous_min_rate; 217 + vport->qos.min_rate = previous_min_rate; 283 218 284 219 return err; 285 220 } 286 221 287 - static int esw_qos_set_vport_max_rate(struct mlx5_eswitch *esw, struct mlx5_vport *evport, 222 + static int esw_qos_set_vport_max_rate(struct mlx5_vport *vport, 288 223 u32 max_rate, struct netlink_ext_ack *extack) 289 224 { 225 + struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 290 226 u32 act_max_rate = max_rate; 291 227 bool max_rate_supported; 292 228 int err; 293 229 294 - lockdep_assert_held(&esw->state_lock); 295 - max_rate_supported = MLX5_CAP_QOS(esw->dev, esw_rate_limit); 230 + esw_assert_qos_lock_held(esw); 231 + max_rate_supported = MLX5_CAP_QOS(vport->dev, esw_rate_limit); 296 232 297 233 if (max_rate && !max_rate_supported) 298 234 return -EOPNOTSUPP; 299 - if (max_rate == evport->qos.max_rate) 235 + if (max_rate == vport->qos.max_rate) 300 236 return 0; 301 237 302 - /* If parent group has rate limit need to set to group 303 - * value when new max rate is 0. 304 - */ 305 - if (evport->qos.group && !max_rate) 306 - act_max_rate = evport->qos.group->max_rate; 238 + /* Use parent group limit if new max rate is 0. */ 239 + if (!max_rate) 240 + act_max_rate = vport->qos.group->max_rate; 307 241 308 - err = esw_qos_vport_config(esw, evport, act_max_rate, evport->qos.bw_share, extack); 242 + err = esw_qos_vport_config(vport, act_max_rate, vport->qos.bw_share, extack); 309 243 310 244 if (!err) 311 - evport->qos.max_rate = max_rate; 245 + vport->qos.max_rate = max_rate; 312 246 313 247 return err; 314 248 } 315 249 316 - static int esw_qos_set_group_min_rate(struct mlx5_eswitch *esw, struct mlx5_esw_rate_group *group, 250 + static int esw_qos_set_group_min_rate(struct mlx5_esw_rate_group *group, 317 251 u32 min_rate, struct netlink_ext_ack *extack) 318 252 { 319 - u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share); 320 - struct mlx5_core_dev *dev = esw->dev; 321 - u32 previous_min_rate, divider; 253 + struct mlx5_eswitch *esw = group->esw; 254 + u32 previous_min_rate; 322 255 int err; 323 256 324 - if (!(MLX5_CAP_QOS(dev, esw_bw_share) && fw_max_bw_share >= MLX5_MIN_BW_SHARE)) 257 + if (!MLX5_CAP_QOS(esw->dev, esw_bw_share) || 258 + MLX5_CAP_QOS(esw->dev, max_tsar_bw_share) < MLX5_MIN_BW_SHARE) 325 259 return -EOPNOTSUPP; 326 260 327 261 if (min_rate == group->min_rate) ··· 329 263 330 264 previous_min_rate = group->min_rate; 331 265 group->min_rate = min_rate; 332 - divider = esw_qos_calculate_min_rate_divider(esw, group, true); 333 - err = esw_qos_normalize_groups_min_rate(esw, divider, extack); 266 + err = esw_qos_normalize_min_rate(esw, extack); 334 267 if (err) { 335 - group->min_rate = previous_min_rate; 336 268 NL_SET_ERR_MSG_MOD(extack, "E-Switch group min rate setting failed"); 337 269 338 270 /* Attempt restoring previous configuration */ 339 - divider = esw_qos_calculate_min_rate_divider(esw, group, true); 340 - if (esw_qos_normalize_groups_min_rate(esw, divider, extack)) 271 + group->min_rate = previous_min_rate; 272 + if (esw_qos_normalize_min_rate(esw, extack)) 341 273 NL_SET_ERR_MSG_MOD(extack, "E-Switch BW share restore failed"); 342 274 } 343 275 344 276 return err; 345 277 } 346 278 347 - static int esw_qos_set_group_max_rate(struct mlx5_eswitch *esw, 348 - struct mlx5_esw_rate_group *group, 279 + static int esw_qos_set_group_max_rate(struct mlx5_esw_rate_group *group, 349 280 u32 max_rate, struct netlink_ext_ack *extack) 350 281 { 351 282 struct mlx5_vport *vport; 352 - unsigned long i; 353 283 int err; 354 284 355 285 if (group->max_rate == max_rate) 356 286 return 0; 357 287 358 - err = esw_qos_group_config(esw, group, max_rate, group->bw_share, extack); 288 + err = esw_qos_group_config(group, max_rate, group->bw_share, extack); 359 289 if (err) 360 290 return err; 361 291 362 292 group->max_rate = max_rate; 363 293 364 - /* Any unlimited vports in the group should be set 365 - * with the value of the group. 366 - */ 367 - mlx5_esw_for_each_vport(esw, i, vport) { 368 - if (!vport->enabled || !vport->qos.enabled || 369 - vport->qos.group != group || vport->qos.max_rate) 294 + /* Any unlimited vports in the group should be set with the value of the group. */ 295 + list_for_each_entry(vport, &group->members, qos.group_entry) { 296 + if (vport->qos.max_rate) 370 297 continue; 371 298 372 - err = esw_qos_vport_config(esw, vport, max_rate, vport->qos.bw_share, extack); 299 + err = esw_qos_vport_config(vport, max_rate, vport->qos.bw_share, extack); 373 300 if (err) 374 301 NL_SET_ERR_MSG_MOD(extack, 375 302 "E-Switch vport implicit rate limit setting failed"); ··· 371 312 return err; 372 313 } 373 314 374 - static bool esw_qos_element_type_supported(struct mlx5_core_dev *dev, int type) 375 - { 376 - switch (type) { 377 - case SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR: 378 - return MLX5_CAP_QOS(dev, esw_element_type) & 379 - ELEMENT_TYPE_CAP_MASK_TSAR; 380 - case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT: 381 - return MLX5_CAP_QOS(dev, esw_element_type) & 382 - ELEMENT_TYPE_CAP_MASK_VPORT; 383 - case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT_TC: 384 - return MLX5_CAP_QOS(dev, esw_element_type) & 385 - ELEMENT_TYPE_CAP_MASK_VPORT_TC; 386 - case SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC: 387 - return MLX5_CAP_QOS(dev, esw_element_type) & 388 - ELEMENT_TYPE_CAP_MASK_PARA_VPORT_TC; 389 - } 390 - return false; 391 - } 392 - 393 - static int esw_qos_vport_create_sched_element(struct mlx5_eswitch *esw, 394 - struct mlx5_vport *vport, 315 + static int esw_qos_vport_create_sched_element(struct mlx5_vport *vport, 395 316 u32 max_rate, u32 bw_share) 396 317 { 397 318 u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {}; 398 319 struct mlx5_esw_rate_group *group = vport->qos.group; 399 - struct mlx5_core_dev *dev = esw->dev; 400 - u32 parent_tsar_ix; 401 - void *vport_elem; 320 + struct mlx5_core_dev *dev = group->esw->dev; 321 + void *attr; 402 322 int err; 403 323 404 - if (!esw_qos_element_type_supported(dev, SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT)) 324 + if (!mlx5_qos_element_type_supported(dev, 325 + SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT, 326 + SCHEDULING_HIERARCHY_E_SWITCH)) 405 327 return -EOPNOTSUPP; 406 328 407 - parent_tsar_ix = group ? group->tsar_ix : esw->qos.root_tsar_ix; 408 329 MLX5_SET(scheduling_context, sched_ctx, element_type, 409 330 SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT); 410 - vport_elem = MLX5_ADDR_OF(scheduling_context, sched_ctx, element_attributes); 411 - MLX5_SET(vport_element, vport_elem, vport_number, vport->vport); 412 - MLX5_SET(scheduling_context, sched_ctx, parent_element_id, parent_tsar_ix); 331 + attr = MLX5_ADDR_OF(scheduling_context, sched_ctx, element_attributes); 332 + MLX5_SET(vport_element, attr, vport_number, vport->vport); 333 + MLX5_SET(scheduling_context, sched_ctx, parent_element_id, group->tsar_ix); 413 334 MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_rate); 414 335 MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share); 415 336 416 337 err = mlx5_create_scheduling_element_cmd(dev, 417 338 SCHEDULING_HIERARCHY_E_SWITCH, 418 339 sched_ctx, 419 - &vport->qos.esw_tsar_ix); 340 + &vport->qos.esw_sched_elem_ix); 420 341 if (err) { 421 - esw_warn(esw->dev, "E-Switch create TSAR vport element failed (vport=%d,err=%d)\n", 342 + esw_warn(dev, 343 + "E-Switch create vport scheduling element failed (vport=%d,err=%d)\n", 422 344 vport->vport, err); 423 345 return err; 424 346 } ··· 407 367 return 0; 408 368 } 409 369 410 - static int esw_qos_update_group_scheduling_element(struct mlx5_eswitch *esw, 411 - struct mlx5_vport *vport, 370 + static int esw_qos_update_group_scheduling_element(struct mlx5_vport *vport, 412 371 struct mlx5_esw_rate_group *curr_group, 413 372 struct mlx5_esw_rate_group *new_group, 414 373 struct netlink_ext_ack *extack) ··· 415 376 u32 max_rate; 416 377 int err; 417 378 418 - err = mlx5_destroy_scheduling_element_cmd(esw->dev, 379 + err = mlx5_destroy_scheduling_element_cmd(curr_group->esw->dev, 419 380 SCHEDULING_HIERARCHY_E_SWITCH, 420 - vport->qos.esw_tsar_ix); 381 + vport->qos.esw_sched_elem_ix); 421 382 if (err) { 422 - NL_SET_ERR_MSG_MOD(extack, "E-Switch destroy TSAR vport element failed"); 383 + NL_SET_ERR_MSG_MOD(extack, "E-Switch destroy vport scheduling element failed"); 423 384 return err; 424 385 } 425 386 426 - vport->qos.group = new_group; 387 + esw_qos_vport_set_group(vport, new_group); 388 + /* Use new group max rate if vport max rate is unlimited. */ 427 389 max_rate = vport->qos.max_rate ? vport->qos.max_rate : new_group->max_rate; 428 - 429 - /* If vport is unlimited, we set the group's value. 430 - * Therefore, if the group is limited it will apply to 431 - * the vport as well and if not, vport will remain unlimited. 432 - */ 433 - err = esw_qos_vport_create_sched_element(esw, vport, max_rate, vport->qos.bw_share); 390 + err = esw_qos_vport_create_sched_element(vport, max_rate, vport->qos.bw_share); 434 391 if (err) { 435 392 NL_SET_ERR_MSG_MOD(extack, "E-Switch vport group set failed."); 436 393 goto err_sched; ··· 435 400 return 0; 436 401 437 402 err_sched: 438 - vport->qos.group = curr_group; 403 + esw_qos_vport_set_group(vport, curr_group); 439 404 max_rate = vport->qos.max_rate ? vport->qos.max_rate : curr_group->max_rate; 440 - if (esw_qos_vport_create_sched_element(esw, vport, max_rate, vport->qos.bw_share)) 441 - esw_warn(esw->dev, "E-Switch vport group restore failed (vport=%d)\n", 405 + if (esw_qos_vport_create_sched_element(vport, max_rate, vport->qos.bw_share)) 406 + esw_warn(curr_group->esw->dev, "E-Switch vport group restore failed (vport=%d)\n", 442 407 vport->vport); 443 408 444 409 return err; 445 410 } 446 411 447 - static int esw_qos_vport_update_group(struct mlx5_eswitch *esw, 448 - struct mlx5_vport *vport, 412 + static int esw_qos_vport_update_group(struct mlx5_vport *vport, 449 413 struct mlx5_esw_rate_group *group, 450 414 struct netlink_ext_ack *extack) 451 415 { 416 + struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 452 417 struct mlx5_esw_rate_group *new_group, *curr_group; 453 418 int err; 454 419 455 - if (!vport->enabled) 456 - return -EINVAL; 457 - 420 + esw_assert_qos_lock_held(esw); 458 421 curr_group = vport->qos.group; 459 422 new_group = group ?: esw->qos.group0; 460 423 if (curr_group == new_group) 461 424 return 0; 462 425 463 - err = esw_qos_update_group_scheduling_element(esw, vport, curr_group, new_group, extack); 426 + err = esw_qos_update_group_scheduling_element(vport, curr_group, new_group, extack); 464 427 if (err) 465 428 return err; 466 429 467 430 /* Recalculate bw share weights of old and new groups */ 468 431 if (vport->qos.bw_share || new_group->bw_share) { 469 - esw_qos_normalize_vports_min_rate(esw, curr_group, extack); 470 - esw_qos_normalize_vports_min_rate(esw, new_group, extack); 432 + esw_qos_normalize_group_min_rate(curr_group, extack); 433 + esw_qos_normalize_group_min_rate(new_group, extack); 471 434 } 472 435 473 436 return 0; 437 + } 438 + 439 + static struct mlx5_esw_rate_group * 440 + __esw_qos_alloc_rate_group(struct mlx5_eswitch *esw, u32 tsar_ix) 441 + { 442 + struct mlx5_esw_rate_group *group; 443 + 444 + group = kzalloc(sizeof(*group), GFP_KERNEL); 445 + if (!group) 446 + return NULL; 447 + 448 + group->esw = esw; 449 + group->tsar_ix = tsar_ix; 450 + INIT_LIST_HEAD(&group->members); 451 + list_add_tail(&group->parent_entry, &esw->qos.domain->groups); 452 + return group; 453 + } 454 + 455 + static void __esw_qos_free_rate_group(struct mlx5_esw_rate_group *group) 456 + { 457 + list_del(&group->parent_entry); 458 + kfree(group); 474 459 } 475 460 476 461 static struct mlx5_esw_rate_group * ··· 498 443 { 499 444 u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {}; 500 445 struct mlx5_esw_rate_group *group; 501 - __be32 *attr; 502 - u32 divider; 503 - int err; 504 - 505 - group = kzalloc(sizeof(*group), GFP_KERNEL); 506 - if (!group) 507 - return ERR_PTR(-ENOMEM); 446 + int tsar_ix, err; 447 + void *attr; 508 448 509 449 MLX5_SET(scheduling_context, tsar_ctx, element_type, 510 450 SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR); 511 - 512 - attr = MLX5_ADDR_OF(scheduling_context, tsar_ctx, element_attributes); 513 - *attr = cpu_to_be32(TSAR_ELEMENT_TSAR_TYPE_DWRR << 16); 514 - 515 451 MLX5_SET(scheduling_context, tsar_ctx, parent_element_id, 516 452 esw->qos.root_tsar_ix); 453 + attr = MLX5_ADDR_OF(scheduling_context, tsar_ctx, element_attributes); 454 + MLX5_SET(tsar_element, attr, tsar_type, TSAR_ELEMENT_TSAR_TYPE_DWRR); 517 455 err = mlx5_create_scheduling_element_cmd(esw->dev, 518 456 SCHEDULING_HIERARCHY_E_SWITCH, 519 457 tsar_ctx, 520 - &group->tsar_ix); 458 + &tsar_ix); 521 459 if (err) { 522 460 NL_SET_ERR_MSG_MOD(extack, "E-Switch create TSAR for group failed"); 523 - goto err_sched_elem; 461 + return ERR_PTR(err); 524 462 } 525 463 526 - list_add_tail(&group->list, &esw->qos.groups); 464 + group = __esw_qos_alloc_rate_group(esw, tsar_ix); 465 + if (!group) { 466 + NL_SET_ERR_MSG_MOD(extack, "E-Switch alloc group failed"); 467 + err = -ENOMEM; 468 + goto err_alloc_group; 469 + } 527 470 528 - divider = esw_qos_calculate_min_rate_divider(esw, group, true); 529 - if (divider) { 530 - err = esw_qos_normalize_groups_min_rate(esw, divider, extack); 531 - if (err) { 532 - NL_SET_ERR_MSG_MOD(extack, "E-Switch groups normalization failed"); 533 - goto err_min_rate; 534 - } 471 + err = esw_qos_normalize_min_rate(esw, extack); 472 + if (err) { 473 + NL_SET_ERR_MSG_MOD(extack, "E-Switch groups normalization failed"); 474 + goto err_min_rate; 535 475 } 536 476 trace_mlx5_esw_group_qos_create(esw->dev, group, group->tsar_ix); 537 477 538 478 return group; 539 479 540 480 err_min_rate: 541 - list_del(&group->list); 481 + __esw_qos_free_rate_group(group); 482 + err_alloc_group: 542 483 if (mlx5_destroy_scheduling_element_cmd(esw->dev, 543 484 SCHEDULING_HIERARCHY_E_SWITCH, 544 - group->tsar_ix)) 485 + tsar_ix)) 545 486 NL_SET_ERR_MSG_MOD(extack, "E-Switch destroy TSAR for group failed"); 546 - err_sched_elem: 547 - kfree(group); 548 487 return ERR_PTR(err); 549 488 } 550 489 ··· 551 502 struct mlx5_esw_rate_group *group; 552 503 int err; 553 504 505 + esw_assert_qos_lock_held(esw); 554 506 if (!MLX5_CAP_QOS(esw->dev, log_esw_max_sched_depth)) 555 507 return ERR_PTR(-EOPNOTSUPP); 556 508 ··· 566 516 return group; 567 517 } 568 518 569 - static int __esw_qos_destroy_rate_group(struct mlx5_eswitch *esw, 570 - struct mlx5_esw_rate_group *group, 519 + static int __esw_qos_destroy_rate_group(struct mlx5_esw_rate_group *group, 571 520 struct netlink_ext_ack *extack) 572 521 { 573 - u32 divider; 522 + struct mlx5_eswitch *esw = group->esw; 574 523 int err; 575 524 576 - list_del(&group->list); 577 - 578 - divider = esw_qos_calculate_min_rate_divider(esw, NULL, true); 579 - err = esw_qos_normalize_groups_min_rate(esw, divider, extack); 580 - if (err) 581 - NL_SET_ERR_MSG_MOD(extack, "E-Switch groups' normalization failed"); 525 + trace_mlx5_esw_group_qos_destroy(esw->dev, group, group->tsar_ix); 582 526 583 527 err = mlx5_destroy_scheduling_element_cmd(esw->dev, 584 528 SCHEDULING_HIERARCHY_E_SWITCH, 585 529 group->tsar_ix); 586 530 if (err) 587 531 NL_SET_ERR_MSG_MOD(extack, "E-Switch destroy TSAR_ID failed"); 532 + __esw_qos_free_rate_group(group); 588 533 589 - trace_mlx5_esw_group_qos_destroy(esw->dev, group, group->tsar_ix); 534 + err = esw_qos_normalize_min_rate(esw, extack); 535 + if (err) 536 + NL_SET_ERR_MSG_MOD(extack, "E-Switch groups normalization failed"); 590 537 591 - kfree(group); 592 - 593 - return err; 594 - } 595 - 596 - static int esw_qos_destroy_rate_group(struct mlx5_eswitch *esw, 597 - struct mlx5_esw_rate_group *group, 598 - struct netlink_ext_ack *extack) 599 - { 600 - int err; 601 - 602 - err = __esw_qos_destroy_rate_group(esw, group, extack); 603 - esw_qos_put(esw); 604 538 605 539 return err; 606 540 } ··· 593 559 { 594 560 u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {}; 595 561 struct mlx5_core_dev *dev = esw->dev; 596 - __be32 *attr; 562 + void *attr; 597 563 int err; 598 564 599 565 if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling)) 600 566 return -EOPNOTSUPP; 601 567 602 - if (!esw_qos_element_type_supported(dev, SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR) || 603 - !(MLX5_CAP_QOS(dev, esw_tsar_type) & TSAR_TYPE_CAP_MASK_DWRR)) 568 + if (!mlx5_qos_element_type_supported(dev, 569 + SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR, 570 + SCHEDULING_HIERARCHY_E_SWITCH) || 571 + !mlx5_qos_tsar_type_supported(dev, 572 + TSAR_ELEMENT_TSAR_TYPE_DWRR, 573 + SCHEDULING_HIERARCHY_E_SWITCH)) 604 574 return -EOPNOTSUPP; 605 575 606 576 MLX5_SET(scheduling_context, tsar_ctx, element_type, 607 577 SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR); 608 578 609 579 attr = MLX5_ADDR_OF(scheduling_context, tsar_ctx, element_attributes); 610 - *attr = cpu_to_be32(TSAR_ELEMENT_TSAR_TYPE_DWRR << 16); 580 + MLX5_SET(tsar_element, attr, tsar_type, TSAR_ELEMENT_TSAR_TYPE_DWRR); 611 581 612 582 err = mlx5_create_scheduling_element_cmd(dev, 613 583 SCHEDULING_HIERARCHY_E_SWITCH, ··· 622 584 return err; 623 585 } 624 586 625 - INIT_LIST_HEAD(&esw->qos.groups); 626 587 if (MLX5_CAP_QOS(dev, log_esw_max_sched_depth)) { 627 588 esw->qos.group0 = __esw_qos_create_rate_group(esw, extack); 628 - if (IS_ERR(esw->qos.group0)) { 629 - esw_warn(dev, "E-Switch create rate group 0 failed (%ld)\n", 630 - PTR_ERR(esw->qos.group0)); 631 - err = PTR_ERR(esw->qos.group0); 632 - goto err_group0; 633 - } 589 + } else { 590 + /* The eswitch doesn't support scheduling groups. 591 + * Create a software-only group0 using the root TSAR to attach vport QoS to. 592 + */ 593 + if (!__esw_qos_alloc_rate_group(esw, esw->qos.root_tsar_ix)) 594 + esw->qos.group0 = ERR_PTR(-ENOMEM); 595 + } 596 + if (IS_ERR(esw->qos.group0)) { 597 + err = PTR_ERR(esw->qos.group0); 598 + esw_warn(dev, "E-Switch create rate group 0 failed (%d)\n", err); 599 + goto err_group0; 634 600 } 635 601 refcount_set(&esw->qos.refcnt, 1); 636 602 ··· 652 610 { 653 611 int err; 654 612 655 - if (esw->qos.group0) 656 - __esw_qos_destroy_rate_group(esw, esw->qos.group0, NULL); 613 + if (esw->qos.group0->tsar_ix != esw->qos.root_tsar_ix) 614 + __esw_qos_destroy_rate_group(esw->qos.group0, NULL); 615 + else 616 + __esw_qos_free_rate_group(esw->qos.group0); 617 + esw->qos.group0 = NULL; 657 618 658 619 err = mlx5_destroy_scheduling_element_cmd(esw->dev, 659 620 SCHEDULING_HIERARCHY_E_SWITCH, ··· 669 624 { 670 625 int err = 0; 671 626 672 - lockdep_assert_held(&esw->state_lock); 673 - 627 + esw_assert_qos_lock_held(esw); 674 628 if (!refcount_inc_not_zero(&esw->qos.refcnt)) { 675 629 /* esw_qos_create() set refcount to 1 only on success. 676 630 * No need to decrement on failure. ··· 682 638 683 639 static void esw_qos_put(struct mlx5_eswitch *esw) 684 640 { 685 - lockdep_assert_held(&esw->state_lock); 641 + esw_assert_qos_lock_held(esw); 686 642 if (refcount_dec_and_test(&esw->qos.refcnt)) 687 643 esw_qos_destroy(esw); 688 644 } 689 645 690 - static int esw_qos_vport_enable(struct mlx5_eswitch *esw, struct mlx5_vport *vport, 646 + static int esw_qos_vport_enable(struct mlx5_vport *vport, 691 647 u32 max_rate, u32 bw_share, struct netlink_ext_ack *extack) 692 648 { 649 + struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 693 650 int err; 694 651 695 - lockdep_assert_held(&esw->state_lock); 652 + esw_assert_qos_lock_held(esw); 696 653 if (vport->qos.enabled) 697 654 return 0; 698 655 ··· 701 656 if (err) 702 657 return err; 703 658 704 - vport->qos.group = esw->qos.group0; 659 + INIT_LIST_HEAD(&vport->qos.group_entry); 660 + esw_qos_vport_set_group(vport, esw->qos.group0); 705 661 706 - err = esw_qos_vport_create_sched_element(esw, vport, max_rate, bw_share); 662 + err = esw_qos_vport_create_sched_element(vport, max_rate, bw_share); 707 663 if (err) 708 664 goto err_out; 709 665 710 666 vport->qos.enabled = true; 711 - trace_mlx5_esw_vport_qos_create(vport, bw_share, max_rate); 667 + trace_mlx5_esw_vport_qos_create(vport->dev, vport, bw_share, max_rate); 712 668 713 669 return 0; 714 670 ··· 719 673 return err; 720 674 } 721 675 722 - void mlx5_esw_qos_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport) 676 + void mlx5_esw_qos_vport_disable(struct mlx5_vport *vport) 723 677 { 678 + struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 679 + struct mlx5_core_dev *dev; 724 680 int err; 725 681 726 682 lockdep_assert_held(&esw->state_lock); 683 + esw_qos_lock(esw); 727 684 if (!vport->qos.enabled) 728 - return; 729 - WARN(vport->qos.group && vport->qos.group != esw->qos.group0, 685 + goto unlock; 686 + WARN(vport->qos.group != esw->qos.group0, 730 687 "Disabling QoS on port before detaching it from group"); 731 688 732 - err = mlx5_destroy_scheduling_element_cmd(esw->dev, 689 + dev = vport->qos.group->esw->dev; 690 + err = mlx5_destroy_scheduling_element_cmd(dev, 733 691 SCHEDULING_HIERARCHY_E_SWITCH, 734 - vport->qos.esw_tsar_ix); 692 + vport->qos.esw_sched_elem_ix); 735 693 if (err) 736 - esw_warn(esw->dev, "E-Switch destroy TSAR vport element failed (vport=%d,err=%d)\n", 694 + esw_warn(dev, 695 + "E-Switch destroy vport scheduling element failed (vport=%d,err=%d)\n", 737 696 vport->vport, err); 738 697 739 698 memset(&vport->qos, 0, sizeof(vport->qos)); 740 - trace_mlx5_esw_vport_qos_destroy(vport); 699 + trace_mlx5_esw_vport_qos_destroy(dev, vport); 741 700 742 701 esw_qos_put(esw); 702 + unlock: 703 + esw_qos_unlock(esw); 743 704 } 744 705 745 - int mlx5_esw_qos_set_vport_rate(struct mlx5_eswitch *esw, struct mlx5_vport *vport, 746 - u32 max_rate, u32 min_rate) 706 + int mlx5_esw_qos_set_vport_rate(struct mlx5_vport *vport, u32 max_rate, u32 min_rate) 747 707 { 708 + struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 748 709 int err; 749 710 750 - lockdep_assert_held(&esw->state_lock); 751 - err = esw_qos_vport_enable(esw, vport, 0, 0, NULL); 711 + esw_qos_lock(esw); 712 + err = esw_qos_vport_enable(vport, 0, 0, NULL); 752 713 if (err) 753 - return err; 714 + goto unlock; 754 715 755 - err = esw_qos_set_vport_min_rate(esw, vport, min_rate, NULL); 716 + err = esw_qos_set_vport_min_rate(vport, min_rate, NULL); 756 717 if (!err) 757 - err = esw_qos_set_vport_max_rate(esw, vport, max_rate, NULL); 758 - 718 + err = esw_qos_set_vport_max_rate(vport, max_rate, NULL); 719 + unlock: 720 + esw_qos_unlock(esw); 759 721 return err; 722 + } 723 + 724 + bool mlx5_esw_qos_get_vport_rate(struct mlx5_vport *vport, u32 *max_rate, u32 *min_rate) 725 + { 726 + struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 727 + bool enabled; 728 + 729 + esw_qos_lock(esw); 730 + enabled = vport->qos.enabled; 731 + if (enabled) { 732 + *max_rate = vport->qos.max_rate; 733 + *min_rate = vport->qos.min_rate; 734 + } 735 + esw_qos_unlock(esw); 736 + return enabled; 760 737 } 761 738 762 739 static u32 mlx5_esw_qos_lag_link_speed_get_locked(struct mlx5_core_dev *mdev) ··· 869 800 return err; 870 801 } 871 802 872 - mutex_lock(&esw->state_lock); 803 + esw_qos_lock(esw); 873 804 if (!vport->qos.enabled) { 874 805 /* Eswitch QoS wasn't enabled yet. Enable it and vport QoS. */ 875 - err = esw_qos_vport_enable(esw, vport, rate_mbps, vport->qos.bw_share, NULL); 806 + err = esw_qos_vport_enable(vport, rate_mbps, vport->qos.bw_share, NULL); 876 807 } else { 877 - MLX5_SET(scheduling_context, ctx, max_average_bw, rate_mbps); 808 + struct mlx5_core_dev *dev = vport->qos.group->esw->dev; 878 809 810 + MLX5_SET(scheduling_context, ctx, max_average_bw, rate_mbps); 879 811 bitmask = MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW; 880 - err = mlx5_modify_scheduling_element_cmd(esw->dev, 812 + err = mlx5_modify_scheduling_element_cmd(dev, 881 813 SCHEDULING_HIERARCHY_E_SWITCH, 882 814 ctx, 883 - vport->qos.esw_tsar_ix, 815 + vport->qos.esw_sched_elem_ix, 884 816 bitmask); 885 817 } 886 - mutex_unlock(&esw->state_lock); 818 + esw_qos_unlock(esw); 887 819 888 820 return err; 889 821 } ··· 922 852 return 0; 923 853 } 924 854 855 + int mlx5_esw_qos_init(struct mlx5_eswitch *esw) 856 + { 857 + return esw_qos_domain_init(esw); 858 + } 859 + 860 + void mlx5_esw_qos_cleanup(struct mlx5_eswitch *esw) 861 + { 862 + if (esw->qos.domain) 863 + esw_qos_domain_release(esw); 864 + } 865 + 925 866 /* Eswitch devlink rate API */ 926 867 927 868 int mlx5_esw_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void *priv, ··· 950 869 if (err) 951 870 return err; 952 871 953 - mutex_lock(&esw->state_lock); 954 - err = esw_qos_vport_enable(esw, vport, 0, 0, extack); 872 + esw_qos_lock(esw); 873 + err = esw_qos_vport_enable(vport, 0, 0, extack); 955 874 if (err) 956 875 goto unlock; 957 876 958 - err = esw_qos_set_vport_min_rate(esw, vport, tx_share, extack); 877 + err = esw_qos_set_vport_min_rate(vport, tx_share, extack); 959 878 unlock: 960 - mutex_unlock(&esw->state_lock); 879 + esw_qos_unlock(esw); 961 880 return err; 962 881 } 963 882 ··· 976 895 if (err) 977 896 return err; 978 897 979 - mutex_lock(&esw->state_lock); 980 - err = esw_qos_vport_enable(esw, vport, 0, 0, extack); 898 + esw_qos_lock(esw); 899 + err = esw_qos_vport_enable(vport, 0, 0, extack); 981 900 if (err) 982 901 goto unlock; 983 902 984 - err = esw_qos_set_vport_max_rate(esw, vport, tx_max, extack); 903 + err = esw_qos_set_vport_max_rate(vport, tx_max, extack); 985 904 unlock: 986 - mutex_unlock(&esw->state_lock); 905 + esw_qos_unlock(esw); 987 906 return err; 988 907 } 989 908 990 909 int mlx5_esw_devlink_rate_node_tx_share_set(struct devlink_rate *rate_node, void *priv, 991 910 u64 tx_share, struct netlink_ext_ack *extack) 992 911 { 993 - struct mlx5_core_dev *dev = devlink_priv(rate_node->devlink); 994 - struct mlx5_eswitch *esw = dev->priv.eswitch; 995 912 struct mlx5_esw_rate_group *group = priv; 913 + struct mlx5_eswitch *esw = group->esw; 996 914 int err; 997 915 998 - err = esw_qos_devlink_rate_to_mbps(dev, "tx_share", &tx_share, extack); 916 + err = esw_qos_devlink_rate_to_mbps(esw->dev, "tx_share", &tx_share, extack); 999 917 if (err) 1000 918 return err; 1001 919 1002 - mutex_lock(&esw->state_lock); 1003 - err = esw_qos_set_group_min_rate(esw, group, tx_share, extack); 1004 - mutex_unlock(&esw->state_lock); 920 + esw_qos_lock(esw); 921 + err = esw_qos_set_group_min_rate(group, tx_share, extack); 922 + esw_qos_unlock(esw); 1005 923 return err; 1006 924 } 1007 925 1008 926 int mlx5_esw_devlink_rate_node_tx_max_set(struct devlink_rate *rate_node, void *priv, 1009 927 u64 tx_max, struct netlink_ext_ack *extack) 1010 928 { 1011 - struct mlx5_core_dev *dev = devlink_priv(rate_node->devlink); 1012 - struct mlx5_eswitch *esw = dev->priv.eswitch; 1013 929 struct mlx5_esw_rate_group *group = priv; 930 + struct mlx5_eswitch *esw = group->esw; 1014 931 int err; 1015 932 1016 - err = esw_qos_devlink_rate_to_mbps(dev, "tx_max", &tx_max, extack); 933 + err = esw_qos_devlink_rate_to_mbps(esw->dev, "tx_max", &tx_max, extack); 1017 934 if (err) 1018 935 return err; 1019 936 1020 - mutex_lock(&esw->state_lock); 1021 - err = esw_qos_set_group_max_rate(esw, group, tx_max, extack); 1022 - mutex_unlock(&esw->state_lock); 937 + esw_qos_lock(esw); 938 + err = esw_qos_set_group_max_rate(group, tx_max, extack); 939 + esw_qos_unlock(esw); 1023 940 return err; 1024 941 } 1025 942 ··· 1032 953 if (IS_ERR(esw)) 1033 954 return PTR_ERR(esw); 1034 955 1035 - mutex_lock(&esw->state_lock); 956 + esw_qos_lock(esw); 1036 957 if (esw->mode != MLX5_ESWITCH_OFFLOADS) { 1037 958 NL_SET_ERR_MSG_MOD(extack, 1038 959 "Rate node creation supported only in switchdev mode"); ··· 1048 969 1049 970 *priv = group; 1050 971 unlock: 1051 - mutex_unlock(&esw->state_lock); 972 + esw_qos_unlock(esw); 1052 973 return err; 1053 974 } 1054 975 ··· 1056 977 struct netlink_ext_ack *extack) 1057 978 { 1058 979 struct mlx5_esw_rate_group *group = priv; 1059 - struct mlx5_eswitch *esw; 980 + struct mlx5_eswitch *esw = group->esw; 1060 981 int err; 1061 982 1062 - esw = mlx5_devlink_eswitch_get(rate_node->devlink); 1063 - if (IS_ERR(esw)) 1064 - return PTR_ERR(esw); 1065 - 1066 - mutex_lock(&esw->state_lock); 1067 - err = esw_qos_destroy_rate_group(esw, group, extack); 1068 - mutex_unlock(&esw->state_lock); 983 + esw_qos_lock(esw); 984 + err = __esw_qos_destroy_rate_group(group, extack); 985 + esw_qos_put(esw); 986 + esw_qos_unlock(esw); 1069 987 return err; 1070 988 } 1071 989 1072 - int mlx5_esw_qos_vport_update_group(struct mlx5_eswitch *esw, 1073 - struct mlx5_vport *vport, 990 + int mlx5_esw_qos_vport_update_group(struct mlx5_vport *vport, 1074 991 struct mlx5_esw_rate_group *group, 1075 992 struct netlink_ext_ack *extack) 1076 993 { 994 + struct mlx5_eswitch *esw = vport->dev->priv.eswitch; 1077 995 int err = 0; 1078 996 1079 - mutex_lock(&esw->state_lock); 997 + if (group && group->esw != esw) { 998 + NL_SET_ERR_MSG_MOD(extack, "Cross E-Switch scheduling is not supported"); 999 + return -EOPNOTSUPP; 1000 + } 1001 + 1002 + esw_qos_lock(esw); 1080 1003 if (!vport->qos.enabled && !group) 1081 1004 goto unlock; 1082 1005 1083 - err = esw_qos_vport_enable(esw, vport, 0, 0, extack); 1006 + err = esw_qos_vport_enable(vport, 0, 0, extack); 1084 1007 if (!err) 1085 - err = esw_qos_vport_update_group(esw, vport, group, extack); 1008 + err = esw_qos_vport_update_group(vport, group, extack); 1086 1009 unlock: 1087 - mutex_unlock(&esw->state_lock); 1010 + esw_qos_unlock(esw); 1088 1011 return err; 1089 1012 } 1090 1013 ··· 1099 1018 struct mlx5_vport *vport = priv; 1100 1019 1101 1020 if (!parent) 1102 - return mlx5_esw_qos_vport_update_group(vport->dev->priv.eswitch, 1103 - vport, NULL, extack); 1021 + return mlx5_esw_qos_vport_update_group(vport, NULL, extack); 1104 1022 1105 1023 group = parent_priv; 1106 - return mlx5_esw_qos_vport_update_group(vport->dev->priv.eswitch, vport, group, extack); 1024 + return mlx5_esw_qos_vport_update_group(vport, group, extack); 1107 1025 }
+6 -3
drivers/net/ethernet/mellanox/mlx5/core/esw/qos.h
··· 6 6 7 7 #ifdef CONFIG_MLX5_ESWITCH 8 8 9 - int mlx5_esw_qos_set_vport_rate(struct mlx5_eswitch *esw, struct mlx5_vport *evport, 10 - u32 max_rate, u32 min_rate); 11 - void mlx5_esw_qos_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport); 9 + int mlx5_esw_qos_init(struct mlx5_eswitch *esw); 10 + void mlx5_esw_qos_cleanup(struct mlx5_eswitch *esw); 11 + 12 + int mlx5_esw_qos_set_vport_rate(struct mlx5_vport *evport, u32 max_rate, u32 min_rate); 13 + bool mlx5_esw_qos_get_vport_rate(struct mlx5_vport *vport, u32 *max_rate, u32 *min_rate); 14 + void mlx5_esw_qos_vport_disable(struct mlx5_vport *vport); 12 15 13 16 int mlx5_esw_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void *priv, 14 17 u64 tx_share, struct netlink_ext_ack *extack);
+16 -6
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
··· 894 894 vport_num, 1, 895 895 MLX5_VPORT_ADMIN_STATE_DOWN); 896 896 897 - mlx5_esw_qos_vport_disable(esw, vport); 897 + mlx5_esw_qos_vport_disable(vport); 898 898 esw_vport_cleanup_acl(esw, vport); 899 899 } 900 900 ··· 1481 1481 MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE); 1482 1482 mlx5_eq_notifier_register(esw->dev, &esw->nb); 1483 1483 1484 + err = mlx5_esw_qos_init(esw); 1485 + if (err) 1486 + goto err_qos_init; 1487 + 1484 1488 if (esw->mode == MLX5_ESWITCH_LEGACY) { 1485 1489 err = esw_legacy_enable(esw); 1486 1490 } else { ··· 1493 1489 } 1494 1490 1495 1491 if (err) 1496 - goto abort; 1492 + goto err_esw_enable; 1497 1493 1498 1494 esw->fdb_table.flags |= MLX5_ESW_FDB_CREATED; 1499 1495 ··· 1507 1503 1508 1504 return 0; 1509 1505 1510 - abort: 1506 + err_esw_enable: 1507 + mlx5_esw_qos_cleanup(esw); 1508 + err_qos_init: 1509 + mlx5_eq_notifier_unregister(esw->dev, &esw->nb); 1511 1510 mlx5_esw_acls_ns_cleanup(esw); 1512 1511 return err; 1513 1512 } ··· 1638 1631 1639 1632 if (esw->mode == MLX5_ESWITCH_OFFLOADS) 1640 1633 devl_rate_nodes_destroy(devlink); 1634 + mlx5_esw_qos_cleanup(esw); 1641 1635 } 1642 1636 1643 1637 void mlx5_eswitch_disable(struct mlx5_eswitch *esw) ··· 2068 2060 u16 vport, struct ifla_vf_info *ivi) 2069 2061 { 2070 2062 struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); 2063 + u32 max_rate, min_rate; 2071 2064 2072 2065 if (IS_ERR(evport)) 2073 2066 return PTR_ERR(evport); ··· 2083 2074 ivi->qos = evport->info.qos; 2084 2075 ivi->spoofchk = evport->info.spoofchk; 2085 2076 ivi->trusted = evport->info.trusted; 2086 - if (evport->qos.enabled) { 2087 - ivi->min_tx_rate = evport->qos.min_rate; 2088 - ivi->max_tx_rate = evport->qos.max_rate; 2077 + 2078 + if (mlx5_esw_qos_get_vport_rate(evport, &max_rate, &min_rate)) { 2079 + ivi->max_tx_rate = max_rate; 2080 + ivi->min_tx_rate = min_rate; 2089 2081 } 2090 2082 mutex_unlock(&esw->state_lock); 2091 2083
+19 -13
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
··· 212 212 213 213 struct mlx5_vport_info info; 214 214 215 + /* Protected with the E-Switch qos domain lock. */ 215 216 struct { 216 - bool enabled; 217 - u32 esw_tsar_ix; 218 - u32 bw_share; 217 + /* Initially false, set to true whenever any QoS features are used. */ 218 + bool enabled; 219 + u32 esw_sched_elem_ix; 219 220 u32 min_rate; 220 221 u32 max_rate; 222 + /* A computed value indicating relative min_rate between vports in a group. */ 223 + u32 bw_share; 221 224 struct mlx5_esw_rate_group *group; 225 + struct list_head group_entry; 222 226 } qos; 223 227 224 228 u16 vport; ··· 337 333 }; 338 334 339 335 struct dentry; 336 + struct mlx5_qos_domain; 340 337 341 338 struct mlx5_eswitch { 342 339 struct mlx5_core_dev *dev; ··· 364 359 struct rw_semaphore mode_lock; 365 360 atomic64_t user_count; 366 361 362 + /* Protected with the E-Switch qos domain lock. */ 367 363 struct { 368 - u32 root_tsar_ix; 369 - struct mlx5_esw_rate_group *group0; 370 - struct list_head groups; /* Protected by esw->state_lock */ 371 - 372 - /* Protected by esw->state_lock. 373 - * Initially 0, meaning no QoS users and QoS is disabled. 374 - */ 364 + /* Initially 0, meaning no QoS users and QoS is disabled. */ 375 365 refcount_t refcnt; 366 + u32 root_tsar_ix; 367 + struct mlx5_qos_domain *domain; 368 + /* Contains all vports with QoS enabled but no explicit group. 369 + * Cannot be NULL if QoS is enabled, but may be a fake group 370 + * referencing the root TSAR if the esw doesn't support groups. 371 + */ 372 + struct mlx5_esw_rate_group *group0; 376 373 } qos; 377 374 378 375 struct mlx5_esw_bridge_offloads *br_offloads; ··· 434 427 u16 vport_num, bool setting); 435 428 int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport, 436 429 u32 max_rate, u32 min_rate); 437 - int mlx5_esw_qos_vport_update_group(struct mlx5_eswitch *esw, 438 - struct mlx5_vport *vport, 430 + int mlx5_esw_qos_vport_update_group(struct mlx5_vport *vport, 439 431 struct mlx5_esw_rate_group *group, 440 432 struct netlink_ext_ack *extack); 441 433 int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting); ··· 812 806 void mlx5_esw_offloads_sf_devlink_port_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport); 813 807 814 808 int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, struct mlx5_vport *vport); 815 - void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_eswitch *esw, struct mlx5_vport *vport); 809 + void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_vport *vport); 816 810 struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u16 vport_num); 817 811 818 812 int mlx5_esw_sf_max_hpf_functions(struct mlx5_core_dev *dev, u16 *max_sfs, u16 *sf_base_id);
+2 -2
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
··· 2617 2617 return err; 2618 2618 2619 2619 load_err: 2620 - mlx5_esw_offloads_devlink_port_unregister(esw, vport); 2620 + mlx5_esw_offloads_devlink_port_unregister(vport); 2621 2621 return err; 2622 2622 } 2623 2623 ··· 2628 2628 2629 2629 mlx5_esw_offloads_rep_unload(esw, vport->vport); 2630 2630 2631 - mlx5_esw_offloads_devlink_port_unregister(esw, vport); 2631 + mlx5_esw_offloads_devlink_port_unregister(vport); 2632 2632 } 2633 2633 2634 2634 static int esw_set_slave_root_fdb(struct mlx5_core_dev *master,
+2
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
··· 224 224 int mlx5_core_sriov_set_msix_vec_count(struct pci_dev *vf, int msix_vec_count); 225 225 int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id); 226 226 int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id); 227 + bool mlx5_qos_element_type_supported(struct mlx5_core_dev *dev, int type, u8 hierarchy); 228 + bool mlx5_qos_tsar_type_supported(struct mlx5_core_dev *dev, int type, u8 hierarchy); 227 229 int mlx5_create_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy, 228 230 void *context, u32 *element_id); 229 231 int mlx5_modify_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy,
+9 -3
drivers/net/ethernet/mellanox/mlx5/core/qos.c
··· 28 28 { 29 29 u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0}; 30 30 31 - if (!(MLX5_CAP_QOS(mdev, nic_element_type) & ELEMENT_TYPE_CAP_MASK_QUEUE_GROUP)) 31 + if (!mlx5_qos_element_type_supported(mdev, 32 + SCHEDULING_CONTEXT_ELEMENT_TYPE_QUEUE_GROUP, 33 + SCHEDULING_HIERARCHY_NIC)) 32 34 return -EOPNOTSUPP; 33 35 34 36 MLX5_SET(scheduling_context, sched_ctx, parent_element_id, parent_id); ··· 49 47 u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {0}; 50 48 void *attr; 51 49 52 - if (!(MLX5_CAP_QOS(mdev, nic_element_type) & ELEMENT_TYPE_CAP_MASK_TSAR) || 53 - !(MLX5_CAP_QOS(mdev, nic_tsar_type) & TSAR_TYPE_CAP_MASK_DWRR)) 50 + if (!mlx5_qos_element_type_supported(mdev, 51 + SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR, 52 + SCHEDULING_HIERARCHY_NIC) || 53 + !mlx5_qos_tsar_type_supported(mdev, 54 + TSAR_ELEMENT_TSAR_TYPE_DWRR, 55 + SCHEDULING_HIERARCHY_NIC)) 54 56 return -EOPNOTSUPP; 55 57 56 58 MLX5_SET(scheduling_context, sched_ctx, parent_element_id, parent_id);
+58
drivers/net/ethernet/mellanox/mlx5/core/rl.c
··· 34 34 #include <linux/mlx5/driver.h> 35 35 #include "mlx5_core.h" 36 36 37 + bool mlx5_qos_tsar_type_supported(struct mlx5_core_dev *dev, int type, u8 hierarchy) 38 + { 39 + int cap; 40 + 41 + switch (hierarchy) { 42 + case SCHEDULING_HIERARCHY_E_SWITCH: 43 + cap = MLX5_CAP_QOS(dev, esw_tsar_type); 44 + break; 45 + case SCHEDULING_HIERARCHY_NIC: 46 + cap = MLX5_CAP_QOS(dev, nic_tsar_type); 47 + break; 48 + default: 49 + return false; 50 + } 51 + 52 + switch (type) { 53 + case TSAR_ELEMENT_TSAR_TYPE_DWRR: 54 + return cap & TSAR_TYPE_CAP_MASK_DWRR; 55 + case TSAR_ELEMENT_TSAR_TYPE_ROUND_ROBIN: 56 + return cap & TSAR_TYPE_CAP_MASK_ROUND_ROBIN; 57 + case TSAR_ELEMENT_TSAR_TYPE_ETS: 58 + return cap & TSAR_TYPE_CAP_MASK_ETS; 59 + } 60 + 61 + return false; 62 + } 63 + 64 + bool mlx5_qos_element_type_supported(struct mlx5_core_dev *dev, int type, u8 hierarchy) 65 + { 66 + int cap; 67 + 68 + switch (hierarchy) { 69 + case SCHEDULING_HIERARCHY_E_SWITCH: 70 + cap = MLX5_CAP_QOS(dev, esw_element_type); 71 + break; 72 + case SCHEDULING_HIERARCHY_NIC: 73 + cap = MLX5_CAP_QOS(dev, nic_element_type); 74 + break; 75 + default: 76 + return false; 77 + } 78 + 79 + switch (type) { 80 + case SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR: 81 + return cap & ELEMENT_TYPE_CAP_MASK_TSAR; 82 + case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT: 83 + return cap & ELEMENT_TYPE_CAP_MASK_VPORT; 84 + case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT_TC: 85 + return cap & ELEMENT_TYPE_CAP_MASK_VPORT_TC; 86 + case SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC: 87 + return cap & ELEMENT_TYPE_CAP_MASK_PARA_VPORT_TC; 88 + case SCHEDULING_CONTEXT_ELEMENT_TYPE_QUEUE_GROUP: 89 + return cap & ELEMENT_TYPE_CAP_MASK_QUEUE_GROUP; 90 + } 91 + 92 + return false; 93 + } 94 + 37 95 /* Scheduling element fw management */ 38 96 int mlx5_create_scheduling_element_cmd(struct mlx5_core_dev *dev, u8 hierarchy, 39 97 void *ctx, u32 *element_id)
+37 -30
include/linux/mlx5/mlx5_ifc.h
··· 4105 4105 ELEMENT_TYPE_CAP_MASK_QUEUE_GROUP = 1 << 4, 4106 4106 }; 4107 4107 4108 + enum { 4109 + TSAR_ELEMENT_TSAR_TYPE_DWRR = 0x0, 4110 + TSAR_ELEMENT_TSAR_TYPE_ROUND_ROBIN = 0x1, 4111 + TSAR_ELEMENT_TSAR_TYPE_ETS = 0x2, 4112 + }; 4113 + 4114 + enum { 4115 + TSAR_TYPE_CAP_MASK_DWRR = 1 << 0, 4116 + TSAR_TYPE_CAP_MASK_ROUND_ROBIN = 1 << 1, 4117 + TSAR_TYPE_CAP_MASK_ETS = 1 << 2, 4118 + }; 4119 + 4120 + struct mlx5_ifc_tsar_element_bits { 4121 + u8 reserved_at_0[0x8]; 4122 + u8 tsar_type[0x8]; 4123 + u8 reserved_at_10[0x10]; 4124 + }; 4125 + 4126 + struct mlx5_ifc_vport_element_bits { 4127 + u8 reserved_at_0[0x10]; 4128 + u8 vport_number[0x10]; 4129 + }; 4130 + 4131 + struct mlx5_ifc_vport_tc_element_bits { 4132 + u8 traffic_class[0x4]; 4133 + u8 reserved_at_4[0xc]; 4134 + u8 vport_number[0x10]; 4135 + }; 4136 + 4137 + union mlx5_ifc_element_attributes_bits { 4138 + struct mlx5_ifc_tsar_element_bits tsar; 4139 + struct mlx5_ifc_vport_element_bits vport; 4140 + struct mlx5_ifc_vport_tc_element_bits vport_tc; 4141 + u8 reserved_at_0[0x20]; 4142 + }; 4143 + 4108 4144 struct mlx5_ifc_scheduling_context_bits { 4109 4145 u8 element_type[0x8]; 4110 4146 u8 reserved_at_8[0x18]; 4111 4147 4112 - u8 element_attributes[0x20]; 4148 + union mlx5_ifc_element_attributes_bits element_attributes; 4113 4149 4114 4150 u8 parent_element_id[0x20]; 4115 4151 ··· 4832 4796 u8 reserved_at_10[0x10]; 4833 4797 4834 4798 u8 reserved_at_20[0x60]; 4835 - }; 4836 - 4837 - struct mlx5_ifc_vport_tc_element_bits { 4838 - u8 traffic_class[0x4]; 4839 - u8 reserved_at_4[0xc]; 4840 - u8 vport_number[0x10]; 4841 - }; 4842 - 4843 - struct mlx5_ifc_vport_element_bits { 4844 - u8 reserved_at_0[0x10]; 4845 - u8 vport_number[0x10]; 4846 - }; 4847 - 4848 - enum { 4849 - TSAR_ELEMENT_TSAR_TYPE_DWRR = 0x0, 4850 - TSAR_ELEMENT_TSAR_TYPE_ROUND_ROBIN = 0x1, 4851 - TSAR_ELEMENT_TSAR_TYPE_ETS = 0x2, 4852 - }; 4853 - 4854 - enum { 4855 - TSAR_TYPE_CAP_MASK_DWRR = 1 << 0, 4856 - TSAR_TYPE_CAP_MASK_ROUND_ROBIN = 1 << 1, 4857 - TSAR_TYPE_CAP_MASK_ETS = 1 << 2, 4858 - }; 4859 - 4860 - struct mlx5_ifc_tsar_element_bits { 4861 - u8 reserved_at_0[0x8]; 4862 - u8 tsar_type[0x8]; 4863 - u8 reserved_at_10[0x10]; 4864 4799 }; 4865 4800 4866 4801 enum {