File Index
Files and directories
Sign in
FILE

nv_param.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/mellanox/mlx5/core/lib/nv_param.c C
  1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
  2/* Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
  3
  4#include "nv_param.h"
  5#include "mlx5_core.h"
  6
  7enum {
  8	MLX5_CLASS_0_CTRL_ID_NV_GLOBAL_PCI_CONF               = 0x80,
  9	MLX5_CLASS_0_CTRL_ID_NV_GLOBAL_PCI_CAP                = 0x81,
 10	MLX5_CLASS_0_CTRL_ID_NV_SW_OFFLOAD_CONFIG             = 0x10a,
 11	MLX5_CLASS_0_CTRL_ID_NV_SW_OFFLOAD_CAP                = 0x10b,
 12	MLX5_CLASS_0_CTRL_ID_NV_SW_ACCELERATE_CONF            = 0x11d,
 13
 14	MLX5_CLASS_3_CTRL_ID_NV_PF_PCI_CONF                   = 0x80,
 15};
 16
 17struct mlx5_ifc_configuration_item_type_class_global_bits {
 18	u8         type_class[0x8];
 19	u8         parameter_index[0x18];
 20};
 21
 22struct mlx5_ifc_configuration_item_type_class_per_host_pf_bits {
 23	u8         type_class[0x8];
 24	u8         pf_index[0x6];
 25	u8         pci_bus_index[0x8];
 26	u8         parameter_index[0xa];
 27};
 28
 29union mlx5_ifc_config_item_type_auto_bits {
 30	struct mlx5_ifc_configuration_item_type_class_global_bits
 31				configuration_item_type_class_global;
 32	struct mlx5_ifc_configuration_item_type_class_per_host_pf_bits
 33				configuration_item_type_class_per_host_pf;
 34	u8 reserved_at_0[0x20];
 35};
 36
 37enum {
 38	MLX5_ACCESS_MODE_NEXT = 0,
 39	MLX5_ACCESS_MODE_CURRENT,
 40	MLX5_ACCESS_MODE_DEFAULT,
 41};
 42
 43struct mlx5_ifc_config_item_bits {
 44	u8         valid[0x2];
 45	u8         priority[0x2];
 46	u8         header_type[0x2];
 47	u8         ovr_en[0x1];
 48	u8         rd_en[0x1];
 49	u8         access_mode[0x2];
 50	u8         reserved_at_a[0x1];
 51	u8         writer_id[0x5];
 52	u8         version[0x4];
 53	u8         reserved_at_14[0x2];
 54	u8         host_id_valid[0x1];
 55	u8         length[0x9];
 56
 57	union mlx5_ifc_config_item_type_auto_bits type;
 58
 59	u8         reserved_at_40[0x10];
 60	u8         crc16[0x10];
 61};
 62
 63struct mlx5_ifc_mnvda_reg_bits {
 64	struct mlx5_ifc_config_item_bits configuration_item_header;
 65
 66	u8         configuration_item_data[64][0x20];
 67};
 68
 69struct mlx5_ifc_nv_global_pci_conf_bits {
 70	u8         sriov_valid[0x1];
 71	u8         reserved_at_1[0x10];
 72	u8         per_pf_total_vf[0x1];
 73	u8         reserved_at_12[0xe];
 74
 75	u8         sriov_en[0x1];
 76	u8         reserved_at_21[0xf];
 77	u8         total_vfs[0x10];
 78
 79	u8         reserved_at_40[0x20];
 80};
 81
 82struct mlx5_ifc_nv_global_pci_cap_bits {
 83	u8         max_vfs_per_pf_valid[0x1];
 84	u8         reserved_at_1[0x13];
 85	u8         per_pf_total_vf_supported[0x1];
 86	u8         reserved_at_15[0xb];
 87
 88	u8         sriov_support[0x1];
 89	u8         reserved_at_21[0xf];
 90	u8         max_vfs_per_pf[0x10];
 91
 92	u8         reserved_at_40[0x60];
 93};
 94
 95struct mlx5_ifc_nv_pf_pci_conf_bits {
 96	u8         reserved_at_0[0x9];
 97	u8         pf_total_vf_en[0x1];
 98	u8         reserved_at_a[0x16];
 99
100	u8         reserved_at_20[0x20];
101
102	u8         reserved_at_40[0x10];
103	u8         total_vf[0x10];
104
105	u8         reserved_at_60[0x20];
106};
107
108struct mlx5_ifc_nv_sw_offload_conf_bits {
109	u8         ip_over_vxlan_port[0x10];
110	u8         tunnel_ecn_copy_offload_disable[0x1];
111	u8         pci_atomic_mode[0x3];
112	u8         sr_enable[0x1];
113	u8         ptp_cyc2realtime[0x1];
114	u8         vector_calc_disable[0x1];
115	u8         uctx_en[0x1];
116	u8         prio_tag_required_en[0x1];
117	u8         esw_fdb_ipv4_ttl_modify_enable[0x1];
118	u8         mkey_by_name[0x1];
119	u8         ip_over_vxlan_en[0x1];
120	u8         one_qp_per_recovery[0x1];
121	u8         cqe_compression[0x3];
122	u8         tunnel_udp_entropy_proto_disable[0x1];
123	u8         reserved_at_21[0x1];
124	u8         ar_enable[0x1];
125	u8         log_max_outstanding_wqe[0x5];
126	u8         vf_migration[0x2];
127	u8         log_tx_psn_win[0x6];
128	u8         lro_log_timeout3[0x4];
129	u8         lro_log_timeout2[0x4];
130	u8         lro_log_timeout1[0x4];
131	u8         lro_log_timeout0[0x4];
132};
133
134struct mlx5_ifc_nv_sw_offload_cap_bits {
135	u8         reserved_at_0[0x19];
136	u8         swp_l4_csum_mode_l4_only[0x1];
137	u8         reserved_at_1a[0x6];
138};
139
140struct mlx5_ifc_nv_sw_accelerate_conf_bits {
141	u8         swp_l4_csum_mode[0x2];
142	u8         reserved_at_2[0x3e];
143};
144
145#define MNVDA_HDR_SZ \
146	(MLX5_ST_SZ_BYTES(mnvda_reg) - \
147	 MLX5_BYTE_OFF(mnvda_reg, configuration_item_data))
148
149#define MLX5_SET_CFG_ITEM_TYPE(_cls_name, _mnvda_ptr, _field, _val) \
150	MLX5_SET(mnvda_reg, _mnvda_ptr, \
151		 configuration_item_header.type.configuration_item_type_class_##_cls_name._field, \
152		 _val)
153
154#define MLX5_SET_CFG_HDR_LEN(_mnvda_ptr, _cls_name) \
155	MLX5_SET(mnvda_reg, _mnvda_ptr, configuration_item_header.length, \
156		 MLX5_ST_SZ_BYTES(_cls_name))
157
158#define MLX5_GET_CFG_HDR_LEN(_mnvda_ptr) \
159	MLX5_GET(mnvda_reg, _mnvda_ptr, configuration_item_header.length)
160
161static int mlx5_nv_param_read(struct mlx5_core_dev *dev, void *mnvda,
162			      size_t len)
163{
164	u32 param_idx, type_class;
165	u32 header_len;
166	void *cls_ptr;
167	int err;
168
169	if (WARN_ON(len > MLX5_ST_SZ_BYTES(mnvda_reg)) || len < MNVDA_HDR_SZ)
170		return -EINVAL; /* A caller bug */
171
172	err = mlx5_core_access_reg(dev, mnvda, len, mnvda, len, MLX5_REG_MNVDA,
173				   0, 0);
174	if (!err)
175		return 0;
176
177	cls_ptr = MLX5_ADDR_OF(mnvda_reg, mnvda,
178			       configuration_item_header.type.configuration_item_type_class_global);
179
180	type_class = MLX5_GET(configuration_item_type_class_global, cls_ptr,
181			      type_class);
182	param_idx = MLX5_GET(configuration_item_type_class_global, cls_ptr,
183			     parameter_index);
184	header_len = MLX5_GET_CFG_HDR_LEN(mnvda);
185
186	mlx5_core_warn(dev, "Failed to read mnvda reg: type_class 0x%x, param_idx 0x%x, header_len %u, err %d\n",
187		       type_class, param_idx, header_len, err);
188
189	return -EOPNOTSUPP;
190}
191
192static int mlx5_nv_param_write(struct mlx5_core_dev *dev, void *mnvda,
193			       size_t len)
194{
195	if (WARN_ON(len > MLX5_ST_SZ_BYTES(mnvda_reg)) || len < MNVDA_HDR_SZ)
196		return -EINVAL;
197
198	if (WARN_ON(MLX5_GET_CFG_HDR_LEN(mnvda) == 0))
199		return -EINVAL;
200
201	return mlx5_core_access_reg(dev, mnvda, len, mnvda, len, MLX5_REG_MNVDA,
202				    0, 1);
203}
204
205static int
206mlx5_nv_param_read_sw_offload_conf(struct mlx5_core_dev *dev, void *mnvda,
207				   size_t len)
208{
209	MLX5_SET_CFG_ITEM_TYPE(global, mnvda, type_class, 0);
210	MLX5_SET_CFG_ITEM_TYPE(global, mnvda, parameter_index,
211			       MLX5_CLASS_0_CTRL_ID_NV_SW_OFFLOAD_CONFIG);
212	MLX5_SET_CFG_HDR_LEN(mnvda, nv_sw_offload_conf);
213
214	return mlx5_nv_param_read(dev, mnvda, len);
215}
216
217static int
218mlx5_nv_param_read_sw_offload_cap(struct mlx5_core_dev *dev, void *mnvda,
219				  size_t len)
220{
221	MLX5_SET_CFG_ITEM_TYPE(global, mnvda, type_class, 0);
222	MLX5_SET_CFG_ITEM_TYPE(global, mnvda, parameter_index,
223			       MLX5_CLASS_0_CTRL_ID_NV_SW_OFFLOAD_CAP);
224	MLX5_SET_CFG_HDR_LEN(mnvda, nv_sw_offload_cap);
225
226	return mlx5_nv_param_read(dev, mnvda, len);
227}
228
229static int
230mlx5_nv_param_read_sw_accelerate_conf(struct mlx5_core_dev *dev, void *mnvda,
231				      size_t len, int access_mode)
232{
233	MLX5_SET_CFG_ITEM_TYPE(global, mnvda, type_class, 0);
234	MLX5_SET_CFG_ITEM_TYPE(global, mnvda, parameter_index,
235			       MLX5_CLASS_0_CTRL_ID_NV_SW_ACCELERATE_CONF);
236	MLX5_SET_CFG_HDR_LEN(mnvda, nv_sw_accelerate_conf);
237	MLX5_SET(mnvda_reg, mnvda, configuration_item_header.access_mode,
238		 access_mode);
239
240	return mlx5_nv_param_read(dev, mnvda, len);
241}
242
243static const char *const
244	cqe_compress_str[] = { "balanced", "aggressive" };
245
246static int
247mlx5_nv_param_devlink_cqe_compress_get(struct devlink *devlink, u32 id,
248				       struct devlink_param_gset_ctx *ctx,
249				       struct netlink_ext_ack *extack)
250{
251	struct mlx5_core_dev *dev = devlink_priv(devlink);
252	u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
253	u8 value = U8_MAX;
254	void *data;
255	int err;
256
257	err = mlx5_nv_param_read_sw_offload_conf(dev, mnvda, sizeof(mnvda));
258	if (err)
259		return err;
260
261	data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
262	value = MLX5_GET(nv_sw_offload_conf, data, cqe_compression);
263
264	if (value >= ARRAY_SIZE(cqe_compress_str))
265		return -EOPNOTSUPP;
266
267	strscpy(ctx->val.vstr, cqe_compress_str[value], sizeof(ctx->val.vstr));
268	return 0;
269}
270
271static int
272mlx5_nv_param_devlink_cqe_compress_validate(struct devlink *devlink, u32 id,
273					    union devlink_param_value val,
274					    struct netlink_ext_ack *extack)
275{
276	int i;
277
278	for (i = 0; i < ARRAY_SIZE(cqe_compress_str); i++) {
279		if (!strcmp(val.vstr, cqe_compress_str[i]))
280			return 0;
281	}
282
283	NL_SET_ERR_MSG_MOD(extack,
284			   "Invalid value, supported values are balanced/aggressive");
285	return -EOPNOTSUPP;
286}
287
288static int
289mlx5_nv_param_devlink_cqe_compress_set(struct devlink *devlink, u32 id,
290				       struct devlink_param_gset_ctx *ctx,
291				       struct netlink_ext_ack *extack)
292{
293	struct mlx5_core_dev *dev = devlink_priv(devlink);
294	u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
295	int err = 0;
296	void *data;
297	u8 value;
298
299	if (!strcmp(ctx->val.vstr, "aggressive"))
300		value = 1;
301	else /* balanced: can't be anything else already validated above */
302		value = 0;
303
304	err = mlx5_nv_param_read_sw_offload_conf(dev, mnvda, sizeof(mnvda));
305	if (err) {
306		NL_SET_ERR_MSG_MOD(extack,
307				   "Failed to read sw_offload_conf mnvda reg");
308		return err;
309	}
310
311	data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
312	MLX5_SET(nv_sw_offload_conf, data, cqe_compression, value);
313
314	return mlx5_nv_param_write(dev, mnvda, sizeof(mnvda));
315}
316
317enum swp_l4_csum_mode {
318	SWP_L4_CSUM_MODE_DEFAULT = 0,
319	SWP_L4_CSUM_MODE_FULL_CSUM = 1,
320	SWP_L4_CSUM_MODE_L4_ONLY = 2,
321};
322
323static const char *const
324	swp_l4_csum_mode_str[] = { "default", "full_csum", "l4_only" };
325
326static int
327mlx5_swp_l4_csum_mode_get(struct devlink *devlink, u32 id,
328			  int access_mode, u8 *value,
329			  struct netlink_ext_ack *extack)
330{
331	struct mlx5_core_dev *dev = devlink_priv(devlink);
332	u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
333	void *data;
334	int err;
335
336	err = mlx5_nv_param_read_sw_accelerate_conf(dev, mnvda, sizeof(mnvda),
337						    access_mode);
338	if (err) {
339		NL_SET_ERR_MSG_MOD(extack,
340				   "Failed to read sw_accelerate_conf mnvda reg");
341		return err;
342	}
343
344	data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
345	*value = MLX5_GET(nv_sw_accelerate_conf, data, swp_l4_csum_mode);
346
347	if (*value >= ARRAY_SIZE(swp_l4_csum_mode_str)) {
348		NL_SET_ERR_MSG_FMT_MOD(extack,
349				       "Invalid swp_l4_csum_mode value %u read from device",
350				       *value);
351		return -EINVAL;
352	}
353
354	return 0;
355}
356
357static int
358mlx5_devlink_swp_l4_csum_mode_get(struct devlink *devlink, u32 id,
359				  struct devlink_param_gset_ctx *ctx,
360				  struct netlink_ext_ack *extack)
361{
362	u8 value;
363	int err;
364
365	err = mlx5_swp_l4_csum_mode_get(devlink, id, MLX5_ACCESS_MODE_NEXT,
366					&value, extack);
367	if (err)
368		return err;
369
370	strscpy(ctx->val.vstr, swp_l4_csum_mode_str[value],
371		sizeof(ctx->val.vstr));
372	return 0;
373}
374
375static int
376mlx5_devlink_swp_l4_csum_mode_validate(struct devlink *devlink, u32 id,
377				       union devlink_param_value val,
378				       struct netlink_ext_ack *extack)
379{
380	struct mlx5_core_dev *dev = devlink_priv(devlink);
381	u32 cap[MLX5_ST_SZ_DW(mnvda_reg)] = {};
382	void *data;
383	int err, i;
384
385	for (i = 0; i < ARRAY_SIZE(swp_l4_csum_mode_str); i++) {
386		if (!strcmp(val.vstr, swp_l4_csum_mode_str[i]))
387			break;
388	}
389
390	if (i >= ARRAY_SIZE(swp_l4_csum_mode_str) ||
391	    i == SWP_L4_CSUM_MODE_DEFAULT) {
392		NL_SET_ERR_MSG_MOD(extack,
393				   "Invalid value, supported values are full_csum/l4_only");
394		return -EINVAL;
395	}
396
397	if (i == SWP_L4_CSUM_MODE_L4_ONLY) {
398		err = mlx5_nv_param_read_sw_offload_cap(dev, cap, sizeof(cap));
399		if (err) {
400			NL_SET_ERR_MSG_MOD(extack,
401					   "Failed to read sw_offload_cap");
402			return err;
403		}
404
405		data = MLX5_ADDR_OF(mnvda_reg, cap, configuration_item_data);
406		if (!MLX5_GET(nv_sw_offload_cap, data, swp_l4_csum_mode_l4_only)) {
407			NL_SET_ERR_MSG_MOD(extack,
408					   "l4_only mode is not supported on this device");
409			return -EOPNOTSUPP;
410		}
411	}
412
413	return 0;
414}
415
416static int
417mlx5_swp_l4_csum_mode_set(struct devlink *devlink, u32 id, u8 value,
418			  struct netlink_ext_ack *extack)
419{
420	struct mlx5_core_dev *dev = devlink_priv(devlink);
421	u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
422	void *data;
423	int err;
424
425	err = mlx5_nv_param_read_sw_accelerate_conf(dev, mnvda, sizeof(mnvda),
426						    MLX5_ACCESS_MODE_NEXT);
427	if (err) {
428		NL_SET_ERR_MSG_MOD(extack,
429				   "Failed to read sw_accelerate_conf mnvda reg");
430		return err;
431	}
432
433	data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
434	MLX5_SET(nv_sw_accelerate_conf, data, swp_l4_csum_mode, value);
435
436	err = mlx5_nv_param_write(dev, mnvda, sizeof(mnvda));
437	if (err)
438		NL_SET_ERR_MSG_MOD(extack,
439				   "Failed to write sw_accelerate_conf mnvda reg");
440
441	return err;
442}
443
444static int
445mlx5_devlink_swp_l4_csum_mode_set(struct devlink *devlink, u32 id,
446				  struct devlink_param_gset_ctx *ctx,
447				  struct netlink_ext_ack *extack)
448{
449	u8 value;
450
451	if (!strcmp(ctx->val.vstr, "full_csum"))
452		value = SWP_L4_CSUM_MODE_FULL_CSUM;
453	else
454		value = SWP_L4_CSUM_MODE_L4_ONLY;
455
456	return mlx5_swp_l4_csum_mode_set(devlink, id, value, extack);
457}
458
459static int
460mlx5_devlink_swp_l4_csum_mode_get_default(struct devlink *devlink, u32 id,
461					  struct devlink_param_gset_ctx *ctx,
462					  struct netlink_ext_ack *extack)
463{
464	u8 value;
465	int err;
466
467	err = mlx5_swp_l4_csum_mode_get(devlink, id, MLX5_ACCESS_MODE_DEFAULT,
468					&value, extack);
469	if (err)
470		return err;
471
472	strscpy(ctx->val.vstr, swp_l4_csum_mode_str[value],
473		sizeof(ctx->val.vstr));
474	return 0;
475}
476
477static int
478mlx5_devlink_swp_l4_csum_mode_set_default(struct devlink *devlink, u32 id,
479					  enum devlink_param_cmode cmode,
480					  struct netlink_ext_ack *extack)
481{
482	u8 value;
483	int err;
484
485	err = mlx5_swp_l4_csum_mode_get(devlink, id, MLX5_ACCESS_MODE_DEFAULT,
486					&value, extack);
487	if (err)
488		return err;
489
490	return mlx5_swp_l4_csum_mode_set(devlink, id, value, extack);
491}
492
493static int mlx5_nv_param_read_global_pci_conf(struct mlx5_core_dev *dev,
494					      void *mnvda, size_t len)
495{
496	MLX5_SET_CFG_ITEM_TYPE(global, mnvda, type_class, 0);
497	MLX5_SET_CFG_ITEM_TYPE(global, mnvda, parameter_index,
498			       MLX5_CLASS_0_CTRL_ID_NV_GLOBAL_PCI_CONF);
499	MLX5_SET_CFG_HDR_LEN(mnvda, nv_global_pci_conf);
500
501	return mlx5_nv_param_read(dev, mnvda, len);
502}
503
504static int mlx5_nv_param_read_global_pci_cap(struct mlx5_core_dev *dev,
505					     void *mnvda, size_t len)
506{
507	MLX5_SET_CFG_ITEM_TYPE(global, mnvda, type_class, 0);
508	MLX5_SET_CFG_ITEM_TYPE(global, mnvda, parameter_index,
509			       MLX5_CLASS_0_CTRL_ID_NV_GLOBAL_PCI_CAP);
510	MLX5_SET_CFG_HDR_LEN(mnvda, nv_global_pci_cap);
511
512	return mlx5_nv_param_read(dev, mnvda, len);
513}
514
515static int mlx5_nv_param_read_per_host_pf_conf(struct mlx5_core_dev *dev,
516					       void *mnvda, size_t len)
517{
518	MLX5_SET_CFG_ITEM_TYPE(per_host_pf, mnvda, type_class, 3);
519	MLX5_SET_CFG_ITEM_TYPE(per_host_pf, mnvda, parameter_index,
520			       MLX5_CLASS_3_CTRL_ID_NV_PF_PCI_CONF);
521	MLX5_SET_CFG_HDR_LEN(mnvda, nv_pf_pci_conf);
522
523	return mlx5_nv_param_read(dev, mnvda, len);
524}
525
526static int mlx5_devlink_enable_sriov_get(struct devlink *devlink, u32 id,
527					 struct devlink_param_gset_ctx *ctx,
528					 struct netlink_ext_ack *extack)
529{
530	struct mlx5_core_dev *dev = devlink_priv(devlink);
531	u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
532	bool sriov_en = false;
533	void *data;
534	int err;
535
536	err = mlx5_nv_param_read_global_pci_cap(dev, mnvda, sizeof(mnvda));
537	if (err)
538		return err;
539
540	data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
541	if (!MLX5_GET(nv_global_pci_cap, data, sriov_support)) {
542		ctx->val.vbool = false;
543		return 0;
544	}
545
546	memset(mnvda, 0, sizeof(mnvda));
547	err = mlx5_nv_param_read_global_pci_conf(dev, mnvda, sizeof(mnvda));
548	if (err)
549		return err;
550
551	data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
552	sriov_en = MLX5_GET(nv_global_pci_conf, data, sriov_en);
553	if (!MLX5_GET(nv_global_pci_conf, data, per_pf_total_vf)) {
554		ctx->val.vbool = sriov_en;
555		return 0;
556	}
557
558	/* SRIOV is per PF */
559	memset(mnvda, 0, sizeof(mnvda));
560	err = mlx5_nv_param_read_per_host_pf_conf(dev, mnvda, sizeof(mnvda));
561	if (err)
562		return err;
563
564	data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
565	ctx->val.vbool = sriov_en &&
566			 MLX5_GET(nv_pf_pci_conf, data, pf_total_vf_en);
567	return 0;
568}
569
570static int mlx5_devlink_enable_sriov_set(struct devlink *devlink, u32 id,
571					 struct devlink_param_gset_ctx *ctx,
572					 struct netlink_ext_ack *extack)
573{
574	struct mlx5_core_dev *dev = devlink_priv(devlink);
575	u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
576	bool per_pf_support;
577	void *cap, *data;
578	int err;
579
580	err = mlx5_nv_param_read_global_pci_cap(dev, mnvda, sizeof(mnvda));
581	if (err) {
582		NL_SET_ERR_MSG_MOD(extack,
583				   "Failed to read global PCI capability");
584		return err;
585	}
586
587	cap = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
588	per_pf_support = MLX5_GET(nv_global_pci_cap, cap,
589				  per_pf_total_vf_supported);
590
591	if (!MLX5_GET(nv_global_pci_cap, cap, sriov_support)) {
592		NL_SET_ERR_MSG_MOD(extack,
593				   "SRIOV is not supported on this device");
594		return -EOPNOTSUPP;
595	}
596
597	if (!per_pf_support) {
598		/* We don't allow global SRIOV setting on per PF devlink */
599		NL_SET_ERR_MSG_MOD(extack,
600				   "SRIOV is not per PF on this device");
601		return -EOPNOTSUPP;
602	}
603
604	memset(mnvda, 0, sizeof(mnvda));
605	err = mlx5_nv_param_read_global_pci_conf(dev, mnvda, sizeof(mnvda));
606	if (err) {
607		NL_SET_ERR_MSG_MOD(extack,
608				   "Unable to read global PCI configuration");
609		return err;
610	}
611
612	data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
613
614	/* setup per PF sriov mode */
615	MLX5_SET(nv_global_pci_conf, data, sriov_valid, 1);
616	MLX5_SET(nv_global_pci_conf, data, sriov_en, 1);
617	MLX5_SET(nv_global_pci_conf, data, per_pf_total_vf, 1);
618
619	err = mlx5_nv_param_write(dev, mnvda, sizeof(mnvda));
620	if (err) {
621		NL_SET_ERR_MSG_MOD(extack,
622				   "Unable to write global PCI configuration");
623		return err;
624	}
625
626	/* enable/disable sriov on this PF */
627	memset(mnvda, 0, sizeof(mnvda));
628	err = mlx5_nv_param_read_per_host_pf_conf(dev, mnvda, sizeof(mnvda));
629	if (err) {
630		NL_SET_ERR_MSG_MOD(extack,
631				   "Unable to read per host PF configuration");
632		return err;
633	}
634	MLX5_SET(nv_pf_pci_conf, data, pf_total_vf_en, ctx->val.vbool);
635	return mlx5_nv_param_write(dev, mnvda, sizeof(mnvda));
636}
637
638static int mlx5_devlink_total_vfs_get(struct devlink *devlink, u32 id,
639				      struct devlink_param_gset_ctx *ctx,
640				      struct netlink_ext_ack *extack)
641{
642	struct mlx5_core_dev *dev = devlink_priv(devlink);
643	u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
644	void *data;
645	int err;
646
647	data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
648
649	err = mlx5_nv_param_read_global_pci_cap(dev, mnvda, sizeof(mnvda));
650	if (err)
651		return err;
652
653	if (!MLX5_GET(nv_global_pci_cap, data, sriov_support)) {
654		ctx->val.vu32 = 0;
655		return 0;
656	}
657
658	memset(mnvda, 0, sizeof(mnvda));
659	err = mlx5_nv_param_read_global_pci_conf(dev, mnvda, sizeof(mnvda));
660	if (err)
661		return err;
662
663	if (!MLX5_GET(nv_global_pci_conf, data, per_pf_total_vf)) {
664		ctx->val.vu32 = MLX5_GET(nv_global_pci_conf, data, total_vfs);
665		return 0;
666	}
667
668	/* SRIOV is per PF */
669	memset(mnvda, 0, sizeof(mnvda));
670	err = mlx5_nv_param_read_per_host_pf_conf(dev, mnvda, sizeof(mnvda));
671	if (err)
672		return err;
673
674	ctx->val.vu32 = MLX5_GET(nv_pf_pci_conf, data, total_vf);
675
676	return 0;
677}
678
679static int mlx5_devlink_total_vfs_set(struct devlink *devlink, u32 id,
680				      struct devlink_param_gset_ctx *ctx,
681				      struct netlink_ext_ack *extack)
682{
683	struct mlx5_core_dev *dev = devlink_priv(devlink);
684	u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)];
685	void *data;
686	int err;
687
688	err = mlx5_nv_param_read_global_pci_cap(dev, mnvda, sizeof(mnvda));
689	if (err) {
690		NL_SET_ERR_MSG_MOD(extack, "Failed to read global pci cap");
691		return err;
692	}
693
694	data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
695	if (!MLX5_GET(nv_global_pci_cap, data, sriov_support)) {
696		NL_SET_ERR_MSG_MOD(extack, "Not configurable on this device");
697		return -EOPNOTSUPP;
698	}
699
700	if (!MLX5_GET(nv_global_pci_cap, data, per_pf_total_vf_supported)) {
701		/* We don't allow global SRIOV setting on per PF devlink */
702		NL_SET_ERR_MSG_MOD(extack,
703				   "SRIOV is not per PF on this device");
704		return -EOPNOTSUPP;
705	}
706
707	memset(mnvda, 0, sizeof(mnvda));
708	err = mlx5_nv_param_read_global_pci_conf(dev, mnvda, sizeof(mnvda));
709	if (err)
710		return err;
711
712	MLX5_SET(nv_global_pci_conf, data, sriov_valid, 1);
713	MLX5_SET(nv_global_pci_conf, data, per_pf_total_vf, 1);
714
715	err = mlx5_nv_param_write(dev, mnvda, sizeof(mnvda));
716	if (err)
717		return err;
718
719	memset(mnvda, 0, sizeof(mnvda));
720	err = mlx5_nv_param_read_per_host_pf_conf(dev, mnvda, sizeof(mnvda));
721	if (err)
722		return err;
723
724	data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
725	MLX5_SET(nv_pf_pci_conf, data, total_vf, ctx->val.vu32);
726	return mlx5_nv_param_write(dev, mnvda, sizeof(mnvda));
727}
728
729static int mlx5_devlink_total_vfs_validate(struct devlink *devlink, u32 id,
730					   union devlink_param_value val,
731					   struct netlink_ext_ack *extack)
732{
733	struct mlx5_core_dev *dev = devlink_priv(devlink);
734	u32 cap[MLX5_ST_SZ_DW(mnvda_reg)];
735	void *data;
736	u16 max;
737	int err;
738
739	data = MLX5_ADDR_OF(mnvda_reg, cap, configuration_item_data);
740
741	err = mlx5_nv_param_read_global_pci_cap(dev, cap, sizeof(cap));
742	if (err)
743		return err;
744
745	if (!MLX5_GET(nv_global_pci_cap, data, max_vfs_per_pf_valid))
746		return 0; /* optimistic, but set might fail later */
747
748	max = MLX5_GET(nv_global_pci_cap, data, max_vfs_per_pf);
749	if (val.vu16 > max) {
750		NL_SET_ERR_MSG_FMT_MOD(extack,
751				       "Max allowed by device is %u", max);
752		return -EINVAL;
753	}
754
755	return 0;
756}
757
758static const struct devlink_param mlx5_nv_param_devlink_params[] = {
759	DEVLINK_PARAM_GENERIC(ENABLE_SRIOV, BIT(DEVLINK_PARAM_CMODE_PERMANENT),
760			      mlx5_devlink_enable_sriov_get,
761			      mlx5_devlink_enable_sriov_set, NULL),
762	DEVLINK_PARAM_GENERIC(TOTAL_VFS, BIT(DEVLINK_PARAM_CMODE_PERMANENT),
763			      mlx5_devlink_total_vfs_get,
764			      mlx5_devlink_total_vfs_set,
765			      mlx5_devlink_total_vfs_validate),
766	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_CQE_COMPRESSION_TYPE,
767			     "cqe_compress_type", DEVLINK_PARAM_TYPE_STRING,
768			     BIT(DEVLINK_PARAM_CMODE_PERMANENT),
769			     mlx5_nv_param_devlink_cqe_compress_get,
770			     mlx5_nv_param_devlink_cqe_compress_set,
771			     mlx5_nv_param_devlink_cqe_compress_validate),
772	DEVLINK_PARAM_DRIVER_WITH_DEFAULTS(MLX5_DEVLINK_PARAM_ID_SWP_L4_CSUM_MODE,
773					   "swp_l4_csum_mode", DEVLINK_PARAM_TYPE_STRING,
774					   BIT(DEVLINK_PARAM_CMODE_PERMANENT),
775					   mlx5_devlink_swp_l4_csum_mode_get,
776					   mlx5_devlink_swp_l4_csum_mode_set,
777					   mlx5_devlink_swp_l4_csum_mode_validate,
778					   mlx5_devlink_swp_l4_csum_mode_get_default,
779					   mlx5_devlink_swp_l4_csum_mode_set_default),
780};
781
782int mlx5_nv_param_register_dl_params(struct devlink *devlink)
783{
784	if (!mlx5_core_is_pf(devlink_priv(devlink)))
785		return 0;
786
787	return devl_params_register(devlink, mlx5_nv_param_devlink_params,
788				    ARRAY_SIZE(mlx5_nv_param_devlink_params));
789}
790
791void mlx5_nv_param_unregister_dl_params(struct devlink *devlink)
792{
793	if (!mlx5_core_is_pf(devlink_priv(devlink)))
794		return;
795
796	devl_params_unregister(devlink, mlx5_nv_param_devlink_params,
797			       ARRAY_SIZE(mlx5_nv_param_devlink_params));
798}
799
~/ Read-only file preview.