Merge branch 'devlink-net-mlx5-implement-swp_l4_csum_mode-via-devlink-params'

Daniel Zahka says:

====================
devlink: net/mlx5: implement swp_l4_csum_mode via devlink params

This series introduces a new devlink feature for querying param
default values, and resetting params to their default values. This
feature is then used to implement a new mlx5 driver param.

The series starts with two pure refactor patches: one that passes
through the extack to devlink_param::get() implementations. And a
second small refactor that prepares the netlink tlv handling code in
the devlink_param::get() path to better handle default parameter
values.

The third patch introduces the uapi and driver api for default
parameter values. The driver api is opt-in, and both the uapi and
driver api preserve existing behavior when not used by drivers or
userspace.

The fourth patch introduces a new mlx5 driver param, swp_l4_csum_mode,
for controlling tx csum behavior. The "l4_only" value of this param is
a dependency for PSP initialization on CX7 NICs.

Lastly, the series introduces a new driver param with cmode runtime to
netdevsim, and then uses this param in a new testcase for netdevsim
devlink params.

Here are some examples of using the default param uapi with the devlink
cli. Note the devlink cli binary I am using has changes which I am
posting in accompanying series targeting iproute2-next:

  # netdevsim
./devlink dev param show netdevsim/netdevsim0
netdevsim/netdevsim0:
  name max_macs type generic
    values:
      cmode driverinit value 32 default 32
  name test1 type driver-specific
    values:
      cmode driverinit value true default true

  # set to false
./devlink dev param set netdevsim/netdevsim0 name test1 value false cmode driverinit
./devlink dev param show netdevsim/netdevsim0
netdevsim/netdevsim0:
  name max_macs type generic
    values:
      cmode driverinit value 32 default 32
  name test1 type driver-specific
    values:
      cmode driverinit value false default true

  # set back to default
./devlink dev param set netdevsim/netdevsim0 name test1 default cmode driverinit
./devlink dev param show netdevsim/netdevsim0
netdevsim/netdevsim0:
  name max_macs type generic
    values:
      cmode driverinit value 32 default 32
  name test1 type driver-specific
    values:
      cmode driverinit value true default true

 # mlx5 params on cx7
./devlink dev param show pci/0000:01:00.0
pci/0000:01:00.0:
  name max_macs type generic
    values:
      cmode driverinit value 128 default 128
...
  name swp_l4_csum_mode type driver-specific
    values:
      cmode permanent value default default default

  # set to l4_only
./devlink dev param set pci/0000:01:00.0 name swp_l4_csum_mode value l4_only cmode permanent
./devlink dev param show pci/0000:01:00.0 name swp_l4_csum_mode
pci/0000:01:00.0:
  name swp_l4_csum_mode type driver-specific
    values:
      cmode permanent value l4_only default default

  # reset to default
./devlink dev param set pci/0000:01:00.0 name swp_l4_csum_mode default cmode permanent
./devlink dev param show pci/0000:01:00.0 name swp_l4_csum_mode
pci/0000:01:00.0:
  name swp_l4_csum_mode type driver-specific
    values:
      cmode permanent value default default default
====================

Link: https://patch.msgid.link/20251119025038.651131-1-daniel.zahka@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski
2025-11-20 19:01:24 -08:00
34 changed files with 695 additions and 93 deletions

View File

@@ -859,6 +859,14 @@ attribute-sets:
name: health-reporter-burst-period
type: u64
doc: Time (in msec) for recoveries before starting the grace period.
# TODO: fill in the attributes in between
-
name: param-reset-default
type: flag
doc: Request restoring parameter to its default value.
value: 183
-
name: dl-dev-stats
subset-of: devlink
@@ -1793,6 +1801,7 @@ operations:
- param-type
# param-value-data is missing here as the type is variable
- param-value-cmode
- param-reset-default
-
name: region-get

View File

@@ -41,6 +41,16 @@ In order for ``driverinit`` parameters to take effect, the driver must
support reloading via the ``devlink-reload`` command. This command will
request a reload of the device driver.
Default parameter values
=========================
Drivers may optionally export default values for parameters of cmode
``runtime`` and ``permanent``. For ``driverinit`` parameters, the last
value set by the driver will be used as the default value. Drivers can
also support resetting params with cmode ``runtime`` and ``permanent``
to their default values. Resetting ``driverinit`` params is supported
by devlink core without additional driver support needed.
.. _devlink_params_generic:
Generic configuration parameters

View File

@@ -218,6 +218,20 @@ parameters.
* ``balanced`` : Merges fewer CQEs, resulting in a moderate compression ratio but maintaining a balance between bandwidth savings and performance
* ``aggressive`` : Merges more CQEs into a single entry, achieving a higher compression rate and maximizing performance, particularly under high traffic loads
* - ``swp_l4_csum_mode``
- string
- permanent
- Configure how the L4 checksum is calculated by the device when using
Software Parser (SWP) hints for header locations.
* ``default`` : Use the device's default checksum calculation
mode. The driver will discover during init whether or
full_csum or l4_only is in use. Setting this value explicitly
from userspace is not allowed, but some firmware versions may
return this value on param read.
* ``full_csum`` : Calculate full checksum including the pseudo-header
* ``l4_only`` : Calculate L4-only checksum, excluding the pseudo-header
The ``mlx5`` driver supports reloading via ``DEVLINK_CMD_RELOAD``
Info versions

View File

@@ -24,7 +24,8 @@ static int otx2_cpt_dl_egrp_delete(struct devlink *dl, u32 id,
}
static int otx2_cpt_dl_uc_info(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
ctx->val.vstr[0] = '\0';
@@ -32,7 +33,8 @@ static int otx2_cpt_dl_uc_info(struct devlink *dl, u32 id,
}
static int otx2_cpt_dl_t106_mode_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct otx2_cpt_devlink *cpt_dl = devlink_priv(dl);
struct otx2_cptpf_dev *cptpf = cpt_dl->cptpf;

View File

@@ -255,7 +255,8 @@ int pdsc_dl_flash_update(struct devlink *dl,
struct devlink_flash_update_params *params,
struct netlink_ext_ack *extack);
int pdsc_dl_enable_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx);
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack);
int pdsc_dl_enable_set(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack);

View File

@@ -22,7 +22,8 @@ pdsc_viftype *pdsc_dl_find_viftype_by_id(struct pdsc *pdsc,
}
int pdsc_dl_enable_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct pdsc *pdsc = devlink_priv(dl);
struct pdsc_viftype *vt_entry;

View File

@@ -1086,7 +1086,8 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
}
static int bnxt_dl_nvm_param_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct bnxt *bp = bnxt_get_bp_from_dl(dl);
struct hwrm_nvm_get_variable_input *req;
@@ -1168,7 +1169,8 @@ static int bnxt_dl_msix_validate(struct devlink *dl, u32 id,
}
static int bnxt_remote_dev_reset_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct bnxt *bp = bnxt_get_bp_from_dl(dl);

View File

@@ -24,7 +24,8 @@ static int i40e_max_mac_per_vf_set(struct devlink *devlink,
static int i40e_max_mac_per_vf_get(struct devlink *devlink,
u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct i40e_pf *pf = devlink_priv(devlink);

View File

@@ -610,11 +610,13 @@ exit_release_res:
* @devlink: pointer to the devlink instance
* @id: the parameter ID to set
* @ctx: context to store the parameter value
* @extack: netlink extended ACK structure
*
* Return: zero on success and negative value on failure.
*/
static int ice_devlink_tx_sched_layers_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct ice_pf *pf = devlink_priv(devlink);
int err;
@@ -1349,7 +1351,8 @@ static const struct devlink_ops ice_sf_devlink_ops;
static int
ice_devlink_enable_roce_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct ice_pf *pf = devlink_priv(devlink);
struct iidc_rdma_core_dev_info *cdev;
@@ -1415,7 +1418,8 @@ ice_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
static int
ice_devlink_enable_iw_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct ice_pf *pf = devlink_priv(devlink);
struct iidc_rdma_core_dev_info *cdev;
@@ -1522,11 +1526,13 @@ static int ice_devlink_local_fwd_str_to_mode(const char *mode_str)
* @devlink: Pointer to the devlink instance.
* @id: The parameter ID to set.
* @ctx: Context to store the parameter value.
* @extack: netlink extended ACK structure
*
* Return: Zero.
*/
static int ice_devlink_local_fwd_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct ice_pf *pf = devlink_priv(devlink);
struct ice_port_info *pi;

View File

@@ -1233,7 +1233,8 @@ static int rvu_af_dl_dwrr_mtu_set(struct devlink *devlink, u32 id,
}
static int rvu_af_dl_dwrr_mtu_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
struct rvu *rvu = rvu_dl->rvu;
@@ -1259,7 +1260,8 @@ enum rvu_af_dl_param_id {
};
static int rvu_af_npc_exact_feature_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
struct rvu *rvu = rvu_dl->rvu;
@@ -1314,7 +1316,8 @@ static int rvu_af_npc_exact_feature_validate(struct devlink *devlink, u32 id,
}
static int rvu_af_dl_npc_mcam_high_zone_percent_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
struct rvu *rvu = rvu_dl->rvu;
@@ -1376,7 +1379,8 @@ static int rvu_af_dl_npc_mcam_high_zone_percent_validate(struct devlink *devlink
}
static int rvu_af_dl_npc_def_rule_cntr_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
struct rvu *rvu = rvu_dl->rvu;
@@ -1402,7 +1406,8 @@ static int rvu_af_dl_npc_def_rule_cntr_set(struct devlink *devlink, u32 id,
}
static int rvu_af_dl_nix_maxlf_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
struct rvu *rvu = rvu_dl->rvu;

View File

@@ -48,7 +48,8 @@ static int otx2_dl_mcam_count_set(struct devlink *devlink, u32 id,
}
static int otx2_dl_mcam_count_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct otx2_devlink *otx2_dl = devlink_priv(devlink);
struct otx2_nic *pfvf = otx2_dl->pfvf;
@@ -84,7 +85,8 @@ static int otx2_dl_ucast_flt_cnt_set(struct devlink *devlink, u32 id,
}
static int otx2_dl_ucast_flt_cnt_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct otx2_devlink *otx2_dl = devlink_priv(devlink);
struct otx2_nic *pfvf = otx2_dl->pfvf;

View File

@@ -174,7 +174,8 @@ MODULE_PARM_DESC(port_type_array, "Array of port types: HW_DEFAULT (0) is defaul
static atomic_t pf_loading = ATOMIC_INIT(0);
static int mlx4_devlink_ierr_reset_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
ctx->val.vbool = !!mlx4_internal_err_reset;
return 0;
@@ -189,7 +190,8 @@ static int mlx4_devlink_ierr_reset_set(struct devlink *devlink, u32 id,
}
static int mlx4_devlink_crdump_snapshot_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct mlx4_priv *priv = devlink_priv(devlink);
struct mlx4_dev *dev = &priv->dev;

View File

@@ -26,7 +26,8 @@ enum mlx5_devlink_param_id {
MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_HIGH,
MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_LOW,
MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_HIGH,
MLX5_DEVLINK_PARAM_ID_CQE_COMPRESSION_TYPE
MLX5_DEVLINK_PARAM_ID_CQE_COMPRESSION_TYPE,
MLX5_DEVLINK_PARAM_ID_SWP_L4_CSUM_MODE,
};
struct mlx5_trap_ctx {

View File

@@ -1969,7 +1969,8 @@ static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id,
}
static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);

View File

@@ -2618,7 +2618,8 @@ done:
}
static int esw_port_metadata_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);

View File

@@ -3833,7 +3833,8 @@ static int mlx5_fs_mode_set(struct devlink *devlink, u32 id,
}
static int mlx5_fs_mode_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);

View File

@@ -73,7 +73,8 @@ static int mlx5_fw_reset_enable_remote_dev_reset_set(struct devlink *devlink, u3
}
static int mlx5_fw_reset_enable_remote_dev_reset_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
struct mlx5_fw_reset *fw_reset;

View File

@@ -8,6 +8,8 @@ enum {
MLX5_CLASS_0_CTRL_ID_NV_GLOBAL_PCI_CONF = 0x80,
MLX5_CLASS_0_CTRL_ID_NV_GLOBAL_PCI_CAP = 0x81,
MLX5_CLASS_0_CTRL_ID_NV_SW_OFFLOAD_CONFIG = 0x10a,
MLX5_CLASS_0_CTRL_ID_NV_SW_OFFLOAD_CAP = 0x10b,
MLX5_CLASS_0_CTRL_ID_NV_SW_ACCELERATE_CONF = 0x11d,
MLX5_CLASS_3_CTRL_ID_NV_PF_PCI_CONF = 0x80,
};
@@ -32,6 +34,12 @@ union mlx5_ifc_config_item_type_auto_bits {
u8 reserved_at_0[0x20];
};
enum {
MLX5_ACCESS_MODE_NEXT = 0,
MLX5_ACCESS_MODE_CURRENT,
MLX5_ACCESS_MODE_DEFAULT,
};
struct mlx5_ifc_config_item_bits {
u8 valid[0x2];
u8 priority[0x2];
@@ -123,6 +131,17 @@ struct mlx5_ifc_nv_sw_offload_conf_bits {
u8 lro_log_timeout0[0x4];
};
struct mlx5_ifc_nv_sw_offload_cap_bits {
u8 reserved_at_0[0x19];
u8 swp_l4_csum_mode_l4_only[0x1];
u8 reserved_at_1a[0x6];
};
struct mlx5_ifc_nv_sw_accelerate_conf_bits {
u8 swp_l4_csum_mode[0x2];
u8 reserved_at_2[0x3e];
};
#define MNVDA_HDR_SZ \
(MLX5_ST_SZ_BYTES(mnvda_reg) - \
MLX5_BYTE_OFF(mnvda_reg, configuration_item_data))
@@ -195,12 +214,39 @@ mlx5_nv_param_read_sw_offload_conf(struct mlx5_core_dev *dev, void *mnvda,
return mlx5_nv_param_read(dev, mnvda, len);
}
static int
mlx5_nv_param_read_sw_offload_cap(struct mlx5_core_dev *dev, void *mnvda,
size_t len)
{
MLX5_SET_CFG_ITEM_TYPE(global, mnvda, type_class, 0);
MLX5_SET_CFG_ITEM_TYPE(global, mnvda, parameter_index,
MLX5_CLASS_0_CTRL_ID_NV_SW_OFFLOAD_CAP);
MLX5_SET_CFG_HDR_LEN(mnvda, nv_sw_offload_cap);
return mlx5_nv_param_read(dev, mnvda, len);
}
static int
mlx5_nv_param_read_sw_accelerate_conf(struct mlx5_core_dev *dev, void *mnvda,
size_t len, int access_mode)
{
MLX5_SET_CFG_ITEM_TYPE(global, mnvda, type_class, 0);
MLX5_SET_CFG_ITEM_TYPE(global, mnvda, parameter_index,
MLX5_CLASS_0_CTRL_ID_NV_SW_ACCELERATE_CONF);
MLX5_SET_CFG_HDR_LEN(mnvda, nv_sw_accelerate_conf);
MLX5_SET(mnvda_reg, mnvda, configuration_item_header.access_mode,
access_mode);
return mlx5_nv_param_read(dev, mnvda, len);
}
static const char *const
cqe_compress_str[] = { "balanced", "aggressive" };
static int
mlx5_nv_param_devlink_cqe_compress_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
@@ -268,6 +314,182 @@ mlx5_nv_param_devlink_cqe_compress_set(struct devlink *devlink, u32 id,
return mlx5_nv_param_write(dev, mnvda, sizeof(mnvda));
}
enum swp_l4_csum_mode {
SWP_L4_CSUM_MODE_DEFAULT = 0,
SWP_L4_CSUM_MODE_FULL_CSUM = 1,
SWP_L4_CSUM_MODE_L4_ONLY = 2,
};
static const char *const
swp_l4_csum_mode_str[] = { "default", "full_csum", "l4_only" };
static int
mlx5_swp_l4_csum_mode_get(struct devlink *devlink, u32 id,
int access_mode, u8 *value,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
void *data;
int err;
err = mlx5_nv_param_read_sw_accelerate_conf(dev, mnvda, sizeof(mnvda),
access_mode);
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"Failed to read sw_accelerate_conf mnvda reg");
return err;
}
data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
*value = MLX5_GET(nv_sw_accelerate_conf, data, swp_l4_csum_mode);
if (*value >= ARRAY_SIZE(swp_l4_csum_mode_str)) {
NL_SET_ERR_MSG_FMT_MOD(extack,
"Invalid swp_l4_csum_mode value %u read from device",
*value);
return -EINVAL;
}
return 0;
}
static int
mlx5_devlink_swp_l4_csum_mode_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
u8 value;
int err;
err = mlx5_swp_l4_csum_mode_get(devlink, id, MLX5_ACCESS_MODE_NEXT,
&value, extack);
if (err)
return err;
strscpy(ctx->val.vstr, swp_l4_csum_mode_str[value],
sizeof(ctx->val.vstr));
return 0;
}
static int
mlx5_devlink_swp_l4_csum_mode_validate(struct devlink *devlink, u32 id,
union devlink_param_value val,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
u32 cap[MLX5_ST_SZ_DW(mnvda_reg)] = {};
void *data;
int err, i;
for (i = 0; i < ARRAY_SIZE(swp_l4_csum_mode_str); i++) {
if (!strcmp(val.vstr, swp_l4_csum_mode_str[i]))
break;
}
if (i >= ARRAY_SIZE(swp_l4_csum_mode_str) ||
i == SWP_L4_CSUM_MODE_DEFAULT) {
NL_SET_ERR_MSG_MOD(extack,
"Invalid value, supported values are full_csum/l4_only");
return -EINVAL;
}
if (i == SWP_L4_CSUM_MODE_L4_ONLY) {
err = mlx5_nv_param_read_sw_offload_cap(dev, cap, sizeof(cap));
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"Failed to read sw_offload_cap");
return err;
}
data = MLX5_ADDR_OF(mnvda_reg, cap, configuration_item_data);
if (!MLX5_GET(nv_sw_offload_cap, data, swp_l4_csum_mode_l4_only)) {
NL_SET_ERR_MSG_MOD(extack,
"l4_only mode is not supported on this device");
return -EOPNOTSUPP;
}
}
return 0;
}
static int
mlx5_swp_l4_csum_mode_set(struct devlink *devlink, u32 id, u8 value,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
void *data;
int err;
err = mlx5_nv_param_read_sw_accelerate_conf(dev, mnvda, sizeof(mnvda),
MLX5_ACCESS_MODE_NEXT);
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"Failed to read sw_accelerate_conf mnvda reg");
return err;
}
data = MLX5_ADDR_OF(mnvda_reg, mnvda, configuration_item_data);
MLX5_SET(nv_sw_accelerate_conf, data, swp_l4_csum_mode, value);
err = mlx5_nv_param_write(dev, mnvda, sizeof(mnvda));
if (err)
NL_SET_ERR_MSG_MOD(extack,
"Failed to write sw_accelerate_conf mnvda reg");
return err;
}
static int
mlx5_devlink_swp_l4_csum_mode_set(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
u8 value;
if (!strcmp(ctx->val.vstr, "full_csum"))
value = SWP_L4_CSUM_MODE_FULL_CSUM;
else
value = SWP_L4_CSUM_MODE_L4_ONLY;
return mlx5_swp_l4_csum_mode_set(devlink, id, value, extack);
}
static int
mlx5_devlink_swp_l4_csum_mode_get_default(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
u8 value;
int err;
err = mlx5_swp_l4_csum_mode_get(devlink, id, MLX5_ACCESS_MODE_DEFAULT,
&value, extack);
if (err)
return err;
strscpy(ctx->val.vstr, swp_l4_csum_mode_str[value],
sizeof(ctx->val.vstr));
return 0;
}
static int
mlx5_devlink_swp_l4_csum_mode_set_default(struct devlink *devlink, u32 id,
enum devlink_param_cmode cmode,
struct netlink_ext_ack *extack)
{
u8 value;
int err;
err = mlx5_swp_l4_csum_mode_get(devlink, id, MLX5_ACCESS_MODE_DEFAULT,
&value, extack);
if (err)
return err;
return mlx5_swp_l4_csum_mode_set(devlink, id, value, extack);
}
static int mlx5_nv_param_read_global_pci_conf(struct mlx5_core_dev *dev,
void *mnvda, size_t len)
{
@@ -302,7 +524,8 @@ static int mlx5_nv_param_read_per_host_pf_conf(struct mlx5_core_dev *dev,
}
static int mlx5_devlink_enable_sriov_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
@@ -413,7 +636,8 @@ static int mlx5_devlink_enable_sriov_set(struct devlink *devlink, u32 id,
}
static int mlx5_devlink_total_vfs_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
u32 mnvda[MLX5_ST_SZ_DW(mnvda_reg)] = {};
@@ -545,6 +769,14 @@ static const struct devlink_param mlx5_nv_param_devlink_params[] = {
mlx5_nv_param_devlink_cqe_compress_get,
mlx5_nv_param_devlink_cqe_compress_set,
mlx5_nv_param_devlink_cqe_compress_validate),
DEVLINK_PARAM_DRIVER_WITH_DEFAULTS(MLX5_DEVLINK_PARAM_ID_SWP_L4_CSUM_MODE,
"swp_l4_csum_mode", DEVLINK_PARAM_TYPE_STRING,
BIT(DEVLINK_PARAM_CMODE_PERMANENT),
mlx5_devlink_swp_l4_csum_mode_get,
mlx5_devlink_swp_l4_csum_mode_set,
mlx5_devlink_swp_l4_csum_mode_validate,
mlx5_devlink_swp_l4_csum_mode_get_default,
mlx5_devlink_swp_l4_csum_mode_set_default),
};
int mlx5_nv_param_register_dl_params(struct devlink *devlink)

View File

@@ -1489,7 +1489,8 @@ mlxsw_sp_acl_tcam_vregion_rehash(struct mlxsw_sp *mlxsw_sp,
static int
mlxsw_sp_acl_tcam_region_rehash_intrvl_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
struct mlxsw_sp_acl_tcam *tcam;

View File

@@ -81,7 +81,8 @@ static const struct nfp_devlink_param_u8_arg nfp_devlink_u8_args[] = {
static int
nfp_devlink_param_u8_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
const struct nfp_devlink_param_u8_arg *arg;
struct nfp_pf *pf = devlink_priv(devlink);

View File

@@ -121,7 +121,8 @@ void qed_fw_reporters_destroy(struct devlink *devlink)
}
static int qed_dl_param_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct qed_devlink *qed_dl = devlink_priv(dl);
struct qed_dev *cdev;

View File

@@ -7531,7 +7531,8 @@ static int stmmac_dl_ts_coarse_set(struct devlink *dl, u32 id,
}
static int stmmac_dl_ts_coarse_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct stmmac_devlink_priv *dl_priv = devlink_priv(dl);
struct stmmac_priv *priv = dl_priv->stmmac_priv;

View File

@@ -3068,7 +3068,8 @@ static void am65_cpsw_init_host_port_emac(struct am65_cpsw_common *common)
}
static int am65_cpsw_dl_switch_mode_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct am65_cpsw_devlink *dl_priv = devlink_priv(dl);
struct am65_cpsw_common *common = dl_priv->common;

View File

@@ -1618,7 +1618,8 @@ static const struct devlink_ops cpsw_devlink_ops = {
};
static int cpsw_dl_switch_mode_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct cpsw_devlink *dl_priv = devlink_priv(dl);
struct cpsw_common *cpsw = dl_priv->cpsw;
@@ -1753,7 +1754,8 @@ exit:
}
static int cpsw_dl_ale_ctrl_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct cpsw_devlink *dl_priv = devlink_priv(dl);
struct cpsw_common *cpsw = dl_priv->cpsw;

View File

@@ -320,6 +320,8 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
&nsim_dev->max_macs);
debugfs_create_bool("test1", 0600, nsim_dev->ddir,
&nsim_dev->test1);
debugfs_create_u32("test2", 0600, nsim_dev->ddir,
&nsim_dev->test2);
nsim_dev->take_snapshot = debugfs_create_file("take_snapshot",
0200,
nsim_dev->ddir,
@@ -521,8 +523,53 @@ err_out:
enum nsim_devlink_param_id {
NSIM_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
NSIM_DEVLINK_PARAM_ID_TEST1,
NSIM_DEVLINK_PARAM_ID_TEST2,
};
static int
nsim_devlink_param_test2_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct nsim_dev *nsim_dev = devlink_priv(devlink);
ctx->val.vu32 = nsim_dev->test2;
return 0;
}
static int
nsim_devlink_param_test2_set(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct nsim_dev *nsim_dev = devlink_priv(devlink);
nsim_dev->test2 = ctx->val.vu32;
return 0;
}
#define NSIM_DEV_TEST2_DEFAULT 1234
static int
nsim_devlink_param_test2_get_default(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
ctx->val.vu32 = NSIM_DEV_TEST2_DEFAULT;
return 0;
}
static int
nsim_devlink_param_test2_reset_default(struct devlink *devlink, u32 id,
enum devlink_param_cmode cmode,
struct netlink_ext_ack *extack)
{
struct nsim_dev *nsim_dev = devlink_priv(devlink);
nsim_dev->test2 = NSIM_DEV_TEST2_DEFAULT;
return 0;
}
static const struct devlink_param nsim_devlink_params[] = {
DEVLINK_PARAM_GENERIC(MAX_MACS,
BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
@@ -531,6 +578,14 @@ static const struct devlink_param nsim_devlink_params[] = {
"test1", DEVLINK_PARAM_TYPE_BOOL,
BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
NULL, NULL, NULL),
DEVLINK_PARAM_DRIVER_WITH_DEFAULTS(NSIM_DEVLINK_PARAM_ID_TEST2,
"test2", DEVLINK_PARAM_TYPE_U32,
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
nsim_devlink_param_test2_get,
nsim_devlink_param_test2_set,
NULL,
nsim_devlink_param_test2_get_default,
nsim_devlink_param_test2_reset_default),
};
static void nsim_devlink_set_params_init_values(struct nsim_dev *nsim_dev,
@@ -1590,6 +1645,7 @@ int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev)
nsim_dev->fw_update_flash_chunk_time_ms = NSIM_DEV_FLASH_CHUNK_TIME_MS_DEFAULT;
nsim_dev->max_macs = NSIM_DEV_MAX_MACS_DEFAULT;
nsim_dev->test1 = NSIM_DEV_TEST1_DEFAULT;
nsim_dev->test2 = NSIM_DEV_TEST2_DEFAULT;
spin_lock_init(&nsim_dev->fa_cookie_lock);
dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev);

View File

@@ -331,6 +331,7 @@ struct nsim_dev {
u32 fw_update_flash_chunk_time_ms;
u32 max_macs;
bool test1;
u32 test2;
bool dont_allow_reload;
bool fail_reload;
struct devlink_region *dummy_region;

View File

@@ -21,7 +21,8 @@ static struct iosm_coredump_file_info list[IOSM_NOF_CD_REGION] = {
/* Get the param values for the specific param ID's */
static int ipc_devlink_get_param(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct iosm_devlink *ipc_devlink = devlink_priv(dl);

View File

@@ -479,6 +479,10 @@ struct devlink_flash_notify {
* @set: set parameter value, used for runtime and permanent
* configuration modes
* @validate: validate input value is applicable (within value range, etc.)
* @get_default: get parameter default value, used for runtime and permanent
* configuration modes
* @reset_default: reset parameter to default value, used for runtime and permanent
* configuration modes
*
* This struct should be used by the driver to fill the data for
* a parameter it registers.
@@ -490,13 +494,20 @@ struct devlink_param {
enum devlink_param_type type;
unsigned long supported_cmodes;
int (*get)(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx);
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack);
int (*set)(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack);
int (*validate)(struct devlink *devlink, u32 id,
union devlink_param_value val,
struct netlink_ext_ack *extack);
int (*get_default)(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack);
int (*reset_default)(struct devlink *devlink, u32 id,
enum devlink_param_cmode cmode,
struct netlink_ext_ack *extack);
};
struct devlink_param_item {
@@ -508,6 +519,7 @@ struct devlink_param_item {
* until reload.
*/
bool driverinit_value_new_valid;
union devlink_param_value driverinit_default;
};
enum devlink_param_generic_id {
@@ -629,6 +641,37 @@ enum devlink_param_generic_id {
.validate = _validate, \
}
#define DEVLINK_PARAM_GENERIC_WITH_DEFAULTS(_id, _cmodes, _get, _set, \
_validate, _get_default, \
_reset_default) \
{ \
.id = DEVLINK_PARAM_GENERIC_ID_##_id, \
.name = DEVLINK_PARAM_GENERIC_##_id##_NAME, \
.type = DEVLINK_PARAM_GENERIC_##_id##_TYPE, \
.generic = true, \
.supported_cmodes = _cmodes, \
.get = _get, \
.set = _set, \
.validate = _validate, \
.get_default = _get_default, \
.reset_default = _reset_default, \
}
#define DEVLINK_PARAM_DRIVER_WITH_DEFAULTS(_id, _name, _type, _cmodes, \
_get, _set, _validate, \
_get_default, _reset_default) \
{ \
.id = _id, \
.name = _name, \
.type = _type, \
.supported_cmodes = _cmodes, \
.get = _get, \
.set = _set, \
.validate = _validate, \
.get_default = _get_default, \
.reset_default = _reset_default, \
}
/* Identifier of board design */
#define DEVLINK_INFO_VERSION_GENERIC_BOARD_ID "board.id"
/* Revision of board design */

View File

@@ -1251,7 +1251,8 @@ struct dsa_switch_ops {
dsa_devlink_param_get, dsa_devlink_param_set, NULL)
int dsa_devlink_param_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx);
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack);
int dsa_devlink_param_set(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack);

View File

@@ -639,6 +639,9 @@ enum devlink_attr {
DEVLINK_ATTR_HEALTH_REPORTER_BURST_PERIOD, /* u64 */
DEVLINK_ATTR_PARAM_VALUE_DEFAULT, /* dynamic */
DEVLINK_ATTR_PARAM_RESET_DEFAULT, /* flag */
/* Add new attributes above here, update the spec in
* Documentation/netlink/specs/devlink.yaml and re-generate
* net/devlink/netlink_gen.c.

View File

@@ -301,12 +301,13 @@ static const struct nla_policy devlink_param_get_dump_nl_policy[DEVLINK_ATTR_DEV
};
/* DEVLINK_CMD_PARAM_SET - do */
static const struct nla_policy devlink_param_set_nl_policy[DEVLINK_ATTR_PARAM_VALUE_CMODE + 1] = {
static const struct nla_policy devlink_param_set_nl_policy[DEVLINK_ATTR_PARAM_RESET_DEFAULT + 1] = {
[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, },
[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, },
[DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING, },
[DEVLINK_ATTR_PARAM_TYPE] = NLA_POLICY_VALIDATE_FN(NLA_U8, &devlink_attr_param_type_validate),
[DEVLINK_ATTR_PARAM_VALUE_CMODE] = NLA_POLICY_MAX(NLA_U8, 2),
[DEVLINK_ATTR_PARAM_RESET_DEFAULT] = { .type = NLA_FLAG, },
};
/* DEVLINK_CMD_REGION_GET - do */
@@ -919,7 +920,7 @@ const struct genl_split_ops devlink_nl_ops[74] = {
.doit = devlink_nl_param_set_doit,
.post_doit = devlink_nl_post_doit,
.policy = devlink_param_set_nl_policy,
.maxattr = DEVLINK_ATTR_PARAM_VALUE_CMODE,
.maxattr = DEVLINK_ATTR_PARAM_RESET_DEFAULT,
.flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
},
{

View File

@@ -174,11 +174,12 @@ devlink_param_cmode_is_supported(const struct devlink_param *param,
static int devlink_param_get(struct devlink *devlink,
const struct devlink_param *param,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
if (!param->get)
return -EOPNOTSUPP;
return param->get(devlink, param->id, ctx);
return param->get(devlink, param->id, ctx, extack);
}
static int devlink_param_set(struct devlink *devlink,
@@ -191,50 +192,101 @@ static int devlink_param_set(struct devlink *devlink,
return param->set(devlink, param->id, ctx, extack);
}
static int devlink_param_get_default(struct devlink *devlink,
const struct devlink_param *param,
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
if (!param->get_default)
return -EOPNOTSUPP;
return param->get_default(devlink, param->id, ctx, extack);
}
static int devlink_param_reset_default(struct devlink *devlink,
const struct devlink_param *param,
enum devlink_param_cmode cmode,
struct netlink_ext_ack *extack)
{
if (!param->reset_default)
return -EOPNOTSUPP;
return param->reset_default(devlink, param->id, cmode, extack);
}
static int
devlink_nl_param_value_put(struct sk_buff *msg, enum devlink_param_type type,
int nla_type, union devlink_param_value val,
bool flag_as_u8)
{
switch (type) {
case DEVLINK_PARAM_TYPE_U8:
if (nla_put_u8(msg, nla_type, val.vu8))
return -EMSGSIZE;
break;
case DEVLINK_PARAM_TYPE_U16:
if (nla_put_u16(msg, nla_type, val.vu16))
return -EMSGSIZE;
break;
case DEVLINK_PARAM_TYPE_U32:
if (nla_put_u32(msg, nla_type, val.vu32))
return -EMSGSIZE;
break;
case DEVLINK_PARAM_TYPE_U64:
if (devlink_nl_put_u64(msg, nla_type, val.vu64))
return -EMSGSIZE;
break;
case DEVLINK_PARAM_TYPE_STRING:
if (nla_put_string(msg, nla_type, val.vstr))
return -EMSGSIZE;
break;
case DEVLINK_PARAM_TYPE_BOOL:
/* default values of type bool are encoded with u8, so that
* false can be distinguished from not present
*/
if (flag_as_u8) {
if (nla_put_u8(msg, nla_type, val.vbool))
return -EMSGSIZE;
} else {
if (val.vbool && nla_put_flag(msg, nla_type))
return -EMSGSIZE;
}
break;
}
return 0;
}
static int
devlink_nl_param_value_fill_one(struct sk_buff *msg,
enum devlink_param_type type,
enum devlink_param_cmode cmode,
union devlink_param_value val)
union devlink_param_value val,
union devlink_param_value default_val,
bool has_default)
{
struct nlattr *param_value_attr;
int err = -EMSGSIZE;
param_value_attr = nla_nest_start_noflag(msg,
DEVLINK_ATTR_PARAM_VALUE);
if (!param_value_attr)
goto nla_put_failure;
return -EMSGSIZE;
if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
goto value_nest_cancel;
switch (type) {
case DEVLINK_PARAM_TYPE_U8:
if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
err = devlink_nl_param_value_put(msg, type,
DEVLINK_ATTR_PARAM_VALUE_DATA,
val, false);
if (err)
goto value_nest_cancel;
if (has_default) {
err = devlink_nl_param_value_put(msg, type,
DEVLINK_ATTR_PARAM_VALUE_DEFAULT,
default_val, true);
if (err)
goto value_nest_cancel;
break;
case DEVLINK_PARAM_TYPE_U16:
if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
goto value_nest_cancel;
break;
case DEVLINK_PARAM_TYPE_U32:
if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
goto value_nest_cancel;
break;
case DEVLINK_PARAM_TYPE_U64:
if (devlink_nl_put_u64(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
val.vu64))
goto value_nest_cancel;
break;
case DEVLINK_PARAM_TYPE_STRING:
if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
val.vstr))
goto value_nest_cancel;
break;
case DEVLINK_PARAM_TYPE_BOOL:
if (val.vbool &&
nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
goto value_nest_cancel;
break;
}
nla_nest_end(msg, param_value_attr);
@@ -242,17 +294,19 @@ devlink_nl_param_value_fill_one(struct sk_buff *msg,
value_nest_cancel:
nla_nest_cancel(msg, param_value_attr);
nla_put_failure:
return -EMSGSIZE;
return err;
}
static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
unsigned int port_index,
struct devlink_param_item *param_item,
enum devlink_command cmd,
u32 portid, u32 seq, int flags)
u32 portid, u32 seq, int flags,
struct netlink_ext_ack *extack)
{
union devlink_param_value default_value[DEVLINK_PARAM_CMODE_MAX + 1];
union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
bool default_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
const struct devlink_param *param = param_item->param;
struct devlink_param_gset_ctx ctx;
@@ -273,12 +327,26 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
param_value[i] = param_item->driverinit_value;
else
return -EOPNOTSUPP;
if (param_item->driverinit_value_valid) {
default_value[i] = param_item->driverinit_default;
default_value_set[i] = true;
}
} else {
ctx.cmode = i;
err = devlink_param_get(devlink, param, &ctx);
err = devlink_param_get(devlink, param, &ctx, extack);
if (err)
return err;
param_value[i] = ctx.val;
err = devlink_param_get_default(devlink, param, &ctx,
extack);
if (!err) {
default_value[i] = ctx.val;
default_value_set[i] = true;
} else if (err != -EOPNOTSUPP) {
return err;
}
}
param_value_set[i] = true;
}
@@ -315,7 +383,9 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
if (!param_value_set[i])
continue;
err = devlink_nl_param_value_fill_one(msg, param->type,
i, param_value[i]);
i, param_value[i],
default_value[i],
default_value_set[i]);
if (err)
goto values_list_nest_cancel;
}
@@ -357,7 +427,7 @@ static void devlink_param_notify(struct devlink *devlink,
if (!msg)
return;
err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
0, 0, 0);
0, 0, 0, NULL);
if (err) {
nlmsg_free(msg);
return;
@@ -400,7 +470,8 @@ static int devlink_nl_param_get_dump_one(struct sk_buff *msg,
err = devlink_nl_param_fill(msg, devlink, 0, param_item,
DEVLINK_CMD_PARAM_GET,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, flags);
cb->nlh->nlmsg_seq, flags,
cb->extack);
if (err == -EOPNOTSUPP) {
err = 0;
} else if (err) {
@@ -509,8 +580,8 @@ int devlink_nl_param_get_doit(struct sk_buff *skb,
return -ENOMEM;
err = devlink_nl_param_fill(msg, devlink, 0, param_item,
DEVLINK_CMD_PARAM_GET,
info->snd_portid, info->snd_seq, 0);
DEVLINK_CMD_PARAM_GET, info->snd_portid,
info->snd_seq, 0, info->extack);
if (err) {
nlmsg_free(msg);
return err;
@@ -531,6 +602,7 @@ static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
struct devlink_param_item *param_item;
const struct devlink_param *param;
union devlink_param_value value;
bool reset_default;
int err = 0;
param_item = devlink_param_get_from_info(params, info);
@@ -542,13 +614,18 @@ static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
return err;
if (param_type != param->type)
return -EINVAL;
err = devlink_param_value_get_from_info(param, info, &value);
if (err)
return err;
if (param->validate) {
err = param->validate(devlink, param->id, value, info->extack);
reset_default = info->attrs[DEVLINK_ATTR_PARAM_RESET_DEFAULT];
if (!reset_default) {
err = devlink_param_value_get_from_info(param, info, &value);
if (err)
return err;
if (param->validate) {
err = param->validate(devlink, param->id, value,
info->extack);
if (err)
return err;
}
}
if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE))
@@ -558,6 +635,15 @@ static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
return -EOPNOTSUPP;
if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
if (reset_default) {
if (!param_item->driverinit_value_valid) {
NL_SET_ERR_MSG(info->extack,
"Default value not available");
return -EOPNOTSUPP;
}
value = param_item->driverinit_default;
}
param_item->driverinit_value_new = value;
param_item->driverinit_value_new_valid = true;
} else {
@@ -565,7 +651,12 @@ static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
return -EOPNOTSUPP;
ctx.val = value;
ctx.cmode = cmode;
err = devlink_param_set(devlink, param, &ctx, info->extack);
if (reset_default)
err = devlink_param_reset_default(devlink, param, cmode,
info->extack);
else
err = devlink_param_set(devlink, param, &ctx,
info->extack);
if (err)
return err;
}
@@ -813,6 +904,7 @@ void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
param_item->driverinit_value = init_val;
param_item->driverinit_value_valid = true;
param_item->driverinit_default = init_val;
devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
}

View File

@@ -182,7 +182,8 @@ static const struct devlink_ops dsa_devlink_ops = {
};
int dsa_devlink_param_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack)
{
struct dsa_switch *ds = dsa_devlink_to_ds(dl);

View File

@@ -3,7 +3,8 @@
lib_dir=$(dirname $0)/../../../net/forwarding
ALL_TESTS="fw_flash_test params_test regions_test reload_test \
ALL_TESTS="fw_flash_test params_test \
params_default_test regions_test reload_test \
netns_reload_test resource_test dev_info_test \
empty_reporter_test dummy_reporter_test rate_test"
NUM_NETIFS=0
@@ -78,17 +79,28 @@ fw_flash_test()
param_get()
{
local name=$1
local attr=${2:-value}
local cmode=${3:-driverinit}
cmd_jq "devlink dev param show $DL_HANDLE name $name -j" \
'.[][][].values[] | select(.cmode == "driverinit").value'
'.[][][].values[] | select(.cmode == "'"$cmode"'").'"$attr"
}
param_set()
{
local name=$1
local value=$2
local cmode=${3:-driverinit}
devlink dev param set $DL_HANDLE name $name cmode driverinit value $value
devlink dev param set $DL_HANDLE name $name cmode $cmode value $value
}
param_set_default()
{
local name=$1
local cmode=${2:-driverinit}
devlink dev param set $DL_HANDLE name $name default cmode $cmode
}
check_value()
@@ -97,12 +109,18 @@ check_value()
local phase_name=$2
local expected_param_value=$3
local expected_debugfs_value=$4
local cmode=${5:-driverinit}
local value
local attr="value"
value=$(param_get $name)
check_err $? "Failed to get $name param value"
if [[ "$phase_name" == *"default"* ]]; then
attr="default"
fi
value=$(param_get $name $attr $cmode)
check_err $? "Failed to get $name param $attr"
[ "$value" == "$expected_param_value" ]
check_err $? "Unexpected $phase_name $name param value"
check_err $? "Unexpected $phase_name $name param $attr"
value=$(<$DEBUGFS_DIR/$name)
check_err $? "Failed to get $name debugfs value"
[ "$value" == "$expected_debugfs_value" ]
@@ -135,6 +153,92 @@ params_test()
log_test "params test"
}
value_to_debugfs()
{
local value=$1
case "$value" in
true)
echo "Y"
;;
false)
echo "N"
;;
*)
echo "$value"
;;
esac
}
test_default()
{
local param_name=$1
local new_value=$2
local expected_default=$3
local cmode=${4:-driverinit}
local default_debugfs
local new_debugfs
local expected_debugfs
default_debugfs=$(value_to_debugfs $expected_default)
new_debugfs=$(value_to_debugfs $new_value)
expected_debugfs=$default_debugfs
check_value $param_name initial-default $expected_default $expected_debugfs $cmode
param_set $param_name $new_value $cmode
check_err $? "Failed to set $param_name to $new_value"
expected_debugfs=$([ "$cmode" == "runtime" ] && echo "$new_debugfs" || echo "$default_debugfs")
check_value $param_name post-set $new_value $expected_debugfs $cmode
devlink dev reload $DL_HANDLE
check_err $? "Failed to reload device"
expected_debugfs=$new_debugfs
check_value $param_name post-reload-new-value $new_value $expected_debugfs $cmode
param_set_default $param_name $cmode
check_err $? "Failed to set $param_name to default"
expected_debugfs=$([ "$cmode" == "runtime" ] && echo "$default_debugfs" || echo "$new_debugfs")
check_value $param_name post-set-default $expected_default $expected_debugfs $cmode
devlink dev reload $DL_HANDLE
check_err $? "Failed to reload device"
expected_debugfs=$default_debugfs
check_value $param_name post-reload-default $expected_default $expected_debugfs $cmode
}
params_default_test()
{
RET=0
if ! devlink dev param help 2>&1 | grep -q "value VALUE | default"; then
echo "SKIP: devlink cli missing default feature"
return
fi
# Remove side effects of previous tests. Use plain param_set, because
# param_set_default is a feature under test here.
param_set max_macs 32 driverinit
check_err $? "Failed to reset max_macs to default value"
param_set test1 true driverinit
check_err $? "Failed to reset test1 to default value"
param_set test2 1234 runtime
check_err $? "Failed to reset test2 to default value"
devlink dev reload $DL_HANDLE
check_err $? "Failed to reload device for clean state"
test_default max_macs 16 32 driverinit
test_default test1 false true driverinit
test_default test2 100 1234 runtime
log_test "params default test"
}
check_region_size()
{
local name=$1