mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02: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
					
				
					 3 changed files with 139 additions and 0 deletions
				
			
		| 
						 | 
					@ -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 @@ static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg,
 | 
				
			||||||
	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 a new issue