mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-23 04:54:01 +08:00
devlink: Add param set command
Add param set command to set value for a parameter. Value can be set to any of the supported configuration modes. Signed-off-by: Moshe Shemesh <moshe@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
45f05def5c
commit
e3b7ca18ad
@ -328,6 +328,7 @@ struct devlink_param_gset_ctx {
|
|||||||
* configuration modes
|
* configuration modes
|
||||||
* @set: set parameter value, used for runtime and permanent
|
* @set: set parameter value, used for runtime and permanent
|
||||||
* configuration modes
|
* configuration modes
|
||||||
|
* @validate: validate input value is applicable (within value range, etc.)
|
||||||
*
|
*
|
||||||
* This struct should be used by the driver to fill the data for
|
* This struct should be used by the driver to fill the data for
|
||||||
* a parameter it registers.
|
* a parameter it registers.
|
||||||
@ -342,6 +343,9 @@ struct devlink_param {
|
|||||||
struct devlink_param_gset_ctx *ctx);
|
struct devlink_param_gset_ctx *ctx);
|
||||||
int (*set)(struct devlink *devlink, u32 id,
|
int (*set)(struct devlink *devlink, u32 id,
|
||||||
struct devlink_param_gset_ctx *ctx);
|
struct devlink_param_gset_ctx *ctx);
|
||||||
|
int (*validate)(struct devlink *devlink, u32 id,
|
||||||
|
union devlink_param_value val,
|
||||||
|
struct netlink_ext_ack *extack);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct devlink_param_item {
|
struct devlink_param_item {
|
||||||
|
@ -79,6 +79,7 @@ enum devlink_command {
|
|||||||
DEVLINK_CMD_RELOAD,
|
DEVLINK_CMD_RELOAD,
|
||||||
|
|
||||||
DEVLINK_CMD_PARAM_GET, /* can dump */
|
DEVLINK_CMD_PARAM_GET, /* can dump */
|
||||||
|
DEVLINK_CMD_PARAM_SET,
|
||||||
|
|
||||||
/* add new commands above here */
|
/* add new commands above here */
|
||||||
__DEVLINK_CMD_MAX,
|
__DEVLINK_CMD_MAX,
|
||||||
|
@ -2661,6 +2661,15 @@ static int devlink_param_get(struct devlink *devlink,
|
|||||||
return param->get(devlink, param->id, ctx);
|
return param->get(devlink, param->id, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int devlink_param_set(struct devlink *devlink,
|
||||||
|
const struct devlink_param *param,
|
||||||
|
struct devlink_param_gset_ctx *ctx)
|
||||||
|
{
|
||||||
|
if (!param->set)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
return param->set(devlink, param->id, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
devlink_param_type_to_nla_type(enum devlink_param_type param_type)
|
devlink_param_type_to_nla_type(enum devlink_param_type param_type)
|
||||||
{
|
{
|
||||||
@ -2847,6 +2856,69 @@ out:
|
|||||||
return msg->len;
|
return msg->len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
devlink_param_type_get_from_info(struct genl_info *info,
|
||||||
|
enum devlink_param_type *param_type)
|
||||||
|
{
|
||||||
|
if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE])
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
|
||||||
|
case NLA_U8:
|
||||||
|
*param_type = DEVLINK_PARAM_TYPE_U8;
|
||||||
|
break;
|
||||||
|
case NLA_U16:
|
||||||
|
*param_type = DEVLINK_PARAM_TYPE_U16;
|
||||||
|
break;
|
||||||
|
case NLA_U32:
|
||||||
|
*param_type = DEVLINK_PARAM_TYPE_U32;
|
||||||
|
break;
|
||||||
|
case NLA_STRING:
|
||||||
|
*param_type = DEVLINK_PARAM_TYPE_STRING;
|
||||||
|
break;
|
||||||
|
case NLA_FLAG:
|
||||||
|
*param_type = DEVLINK_PARAM_TYPE_BOOL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
devlink_param_value_get_from_info(const struct devlink_param *param,
|
||||||
|
struct genl_info *info,
|
||||||
|
union devlink_param_value *value)
|
||||||
|
{
|
||||||
|
if (param->type != DEVLINK_PARAM_TYPE_BOOL &&
|
||||||
|
!info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (param->type) {
|
||||||
|
case DEVLINK_PARAM_TYPE_U8:
|
||||||
|
value->vu8 = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
|
||||||
|
break;
|
||||||
|
case DEVLINK_PARAM_TYPE_U16:
|
||||||
|
value->vu16 = nla_get_u16(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
|
||||||
|
break;
|
||||||
|
case DEVLINK_PARAM_TYPE_U32:
|
||||||
|
value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
|
||||||
|
break;
|
||||||
|
case DEVLINK_PARAM_TYPE_STRING:
|
||||||
|
if (nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) >
|
||||||
|
DEVLINK_PARAM_MAX_STRING_VALUE)
|
||||||
|
return -EINVAL;
|
||||||
|
value->vstr = nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
|
||||||
|
break;
|
||||||
|
case DEVLINK_PARAM_TYPE_BOOL:
|
||||||
|
value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ?
|
||||||
|
true : false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct devlink_param_item *
|
static struct devlink_param_item *
|
||||||
devlink_param_get_from_info(struct devlink *devlink,
|
devlink_param_get_from_info(struct devlink *devlink,
|
||||||
struct genl_info *info)
|
struct genl_info *info)
|
||||||
@ -2887,6 +2959,58 @@ static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb,
|
|||||||
return genlmsg_reply(msg, info);
|
return genlmsg_reply(msg, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb,
|
||||||
|
struct genl_info *info)
|
||||||
|
{
|
||||||
|
struct devlink *devlink = info->user_ptr[0];
|
||||||
|
enum devlink_param_type param_type;
|
||||||
|
struct devlink_param_gset_ctx ctx;
|
||||||
|
enum devlink_param_cmode cmode;
|
||||||
|
struct devlink_param_item *param_item;
|
||||||
|
const struct devlink_param *param;
|
||||||
|
union devlink_param_value value;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
param_item = devlink_param_get_from_info(devlink, info);
|
||||||
|
if (!param_item)
|
||||||
|
return -EINVAL;
|
||||||
|
param = param_item->param;
|
||||||
|
err = devlink_param_type_get_from_info(info, ¶m_type);
|
||||||
|
if (err)
|
||||||
|
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);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE])
|
||||||
|
return -EINVAL;
|
||||||
|
cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
|
||||||
|
if (!devlink_param_cmode_is_supported(param, cmode))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
|
||||||
|
param_item->driverinit_value = value;
|
||||||
|
param_item->driverinit_value_valid = true;
|
||||||
|
} else {
|
||||||
|
if (!param->set)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
ctx.val = value;
|
||||||
|
ctx.cmode = cmode;
|
||||||
|
err = devlink_param_set(devlink, param, &ctx);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int devlink_param_register_one(struct devlink *devlink,
|
static int devlink_param_register_one(struct devlink *devlink,
|
||||||
const struct devlink_param *param)
|
const struct devlink_param *param)
|
||||||
{
|
{
|
||||||
@ -2942,6 +3066,9 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
|
|||||||
[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 },
|
[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 },
|
||||||
[DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64},
|
[DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64},
|
||||||
[DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64},
|
[DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64},
|
||||||
|
[DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING },
|
||||||
|
[DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 },
|
||||||
|
[DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct genl_ops devlink_nl_ops[] = {
|
static const struct genl_ops devlink_nl_ops[] = {
|
||||||
@ -3133,6 +3260,13 @@ static const struct genl_ops devlink_nl_ops[] = {
|
|||||||
.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
|
.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
|
||||||
/* can be retrieved by unprivileged users */
|
/* can be retrieved by unprivileged users */
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.cmd = DEVLINK_CMD_PARAM_SET,
|
||||||
|
.doit = devlink_nl_cmd_param_set_doit,
|
||||||
|
.policy = devlink_nl_policy,
|
||||||
|
.flags = GENL_ADMIN_PERM,
|
||||||
|
.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct genl_family devlink_nl_family __ro_after_init = {
|
static struct genl_family devlink_nl_family __ro_after_init = {
|
||||||
|
Loading…
Reference in New Issue
Block a user