Skip to content

Commit dc64cc7

Browse files
Moshe Shemeshkuba-moo
authored andcommitted
devlink: Add devlink reload limit option
Add reload limit to demand restrictions on reload actions. Reload limits supported: no_reset: No reset allowed, no down time allowed, no link flap and no configuration is lost. By default reload limit is unspecified and so no constraints on reload actions are required. Some combinations of action and limit are invalid. For example, driver can not reinitialize its entities without any downtime. The no_reset reload limit will have usecase in this patchset to implement restricted fw_activate on mlx5. Have the uapi parameter of reload limit ready for future support of multiselection. Signed-off-by: Moshe Shemesh <[email protected]> Reviewed-by: Jiri Pirko <[email protected]> Signed-off-by: Jakub Kicinski <[email protected]>
1 parent ccdf072 commit dc64cc7

File tree

7 files changed

+119
-13
lines changed

7 files changed

+119
-13
lines changed

drivers/net/ethernet/mellanox/mlx4/main.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3947,6 +3947,7 @@ static int mlx4_restart_one_up(struct pci_dev *pdev, bool reload,
39473947

39483948
static int mlx4_devlink_reload_down(struct devlink *devlink, bool netns_change,
39493949
enum devlink_reload_action action,
3950+
enum devlink_reload_limit limit,
39503951
struct netlink_ext_ack *extack)
39513952
{
39523953
struct mlx4_priv *priv = devlink_priv(devlink);
@@ -3964,7 +3965,8 @@ static int mlx4_devlink_reload_down(struct devlink *devlink, bool netns_change,
39643965
}
39653966

39663967
static int mlx4_devlink_reload_up(struct devlink *devlink, enum devlink_reload_action action,
3967-
u32 *actions_performed, struct netlink_ext_ack *extack)
3968+
enum devlink_reload_limit limit, u32 *actions_performed,
3969+
struct netlink_ext_ack *extack)
39683970
{
39693971
struct mlx4_priv *priv = devlink_priv(devlink);
39703972
struct mlx4_dev *dev = &priv->dev;

drivers/net/ethernet/mellanox/mlx5/core/devlink.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ mlx5_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
8686

8787
static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
8888
enum devlink_reload_action action,
89+
enum devlink_reload_limit limit,
8990
struct netlink_ext_ack *extack)
9091
{
9192
struct mlx5_core_dev *dev = devlink_priv(devlink);
@@ -95,7 +96,8 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
9596
}
9697

9798
static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_action action,
98-
u32 *actions_performed, struct netlink_ext_ack *extack)
99+
enum devlink_reload_limit limit, u32 *actions_performed,
100+
struct netlink_ext_ack *extack)
99101
{
100102
struct mlx5_core_dev *dev = devlink_priv(devlink);
101103

drivers/net/ethernet/mellanox/mlxsw/core.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1415,6 +1415,7 @@ mlxsw_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
14151415
static int
14161416
mlxsw_devlink_core_bus_device_reload_down(struct devlink *devlink,
14171417
bool netns_change, enum devlink_reload_action action,
1418+
enum devlink_reload_limit limit,
14181419
struct netlink_ext_ack *extack)
14191420
{
14201421
struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
@@ -1428,7 +1429,8 @@ mlxsw_devlink_core_bus_device_reload_down(struct devlink *devlink,
14281429

14291430
static int
14301431
mlxsw_devlink_core_bus_device_reload_up(struct devlink *devlink, enum devlink_reload_action action,
1431-
u32 *actions_performed, struct netlink_ext_ack *extack)
1432+
enum devlink_reload_limit limit, u32 *actions_performed,
1433+
struct netlink_ext_ack *extack)
14321434
{
14331435
struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
14341436

drivers/net/netdevsim/dev.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,8 @@ static int nsim_dev_reload_create(struct nsim_dev *nsim_dev,
701701
static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev);
702702

703703
static int nsim_dev_reload_down(struct devlink *devlink, bool netns_change,
704-
enum devlink_reload_action action, struct netlink_ext_ack *extack)
704+
enum devlink_reload_action action, enum devlink_reload_limit limit,
705+
struct netlink_ext_ack *extack)
705706
{
706707
struct nsim_dev *nsim_dev = devlink_priv(devlink);
707708

@@ -718,7 +719,8 @@ static int nsim_dev_reload_down(struct devlink *devlink, bool netns_change,
718719
}
719720

720721
static int nsim_dev_reload_up(struct devlink *devlink, enum devlink_reload_action action,
721-
u32 *actions_performed, struct netlink_ext_ack *extack)
722+
enum devlink_reload_limit limit, u32 *actions_performed,
723+
struct netlink_ext_ack *extack)
722724
{
723725
struct nsim_dev *nsim_dev = devlink_priv(devlink);
724726

include/net/devlink.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,10 +1151,14 @@ struct devlink_ops {
11511151
*/
11521152
u32 supported_flash_update_params;
11531153
unsigned long reload_actions;
1154+
unsigned long reload_limits;
11541155
int (*reload_down)(struct devlink *devlink, bool netns_change,
1155-
enum devlink_reload_action action, struct netlink_ext_ack *extack);
1156+
enum devlink_reload_action action,
1157+
enum devlink_reload_limit limit,
1158+
struct netlink_ext_ack *extack);
11561159
int (*reload_up)(struct devlink *devlink, enum devlink_reload_action action,
1157-
u32 *actions_performed, struct netlink_ext_ack *extack);
1160+
enum devlink_reload_limit limit, u32 *actions_performed,
1161+
struct netlink_ext_ack *extack);
11581162
int (*port_type_set)(struct devlink_port *devlink_port,
11591163
enum devlink_port_type port_type);
11601164
int (*port_split)(struct devlink *devlink, unsigned int port_index,

include/uapi/linux/devlink.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,19 @@ enum devlink_reload_action {
311311
DEVLINK_RELOAD_ACTION_MAX = __DEVLINK_RELOAD_ACTION_MAX - 1
312312
};
313313

314+
enum devlink_reload_limit {
315+
DEVLINK_RELOAD_LIMIT_UNSPEC, /* unspecified, no constraints */
316+
DEVLINK_RELOAD_LIMIT_NO_RESET, /* No reset allowed, no down time allowed,
317+
* no link flap and no configuration is lost.
318+
*/
319+
320+
/* Add new reload limit above */
321+
__DEVLINK_RELOAD_LIMIT_MAX,
322+
DEVLINK_RELOAD_LIMIT_MAX = __DEVLINK_RELOAD_LIMIT_MAX - 1
323+
};
324+
325+
#define DEVLINK_RELOAD_LIMITS_VALID_MASK (BIT(__DEVLINK_RELOAD_LIMIT_MAX) - 1)
326+
314327
enum devlink_attr {
315328
/* don't change the order or add anything between, this is ABI! */
316329
DEVLINK_ATTR_UNSPEC,
@@ -505,6 +518,7 @@ enum devlink_attr {
505518

506519
DEVLINK_ATTR_RELOAD_ACTION, /* u8 */
507520
DEVLINK_ATTR_RELOAD_ACTIONS_PERFORMED, /* bitfield32 */
521+
DEVLINK_ATTR_RELOAD_LIMITS, /* bitfield32 */
508522

509523
/* add new attributes above here, update the policy in devlink.c */
510524

net/core/devlink.c

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -479,12 +479,44 @@ static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
479479
return 0;
480480
}
481481

482+
struct devlink_reload_combination {
483+
enum devlink_reload_action action;
484+
enum devlink_reload_limit limit;
485+
};
486+
487+
static const struct devlink_reload_combination devlink_reload_invalid_combinations[] = {
488+
{
489+
/* can't reinitialize driver with no down time */
490+
.action = DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
491+
.limit = DEVLINK_RELOAD_LIMIT_NO_RESET,
492+
},
493+
};
494+
495+
static bool
496+
devlink_reload_combination_is_invalid(enum devlink_reload_action action,
497+
enum devlink_reload_limit limit)
498+
{
499+
int i;
500+
501+
for (i = 0; i < ARRAY_SIZE(devlink_reload_invalid_combinations); i++)
502+
if (devlink_reload_invalid_combinations[i].action == action &&
503+
devlink_reload_invalid_combinations[i].limit == limit)
504+
return true;
505+
return false;
506+
}
507+
482508
static bool
483509
devlink_reload_action_is_supported(struct devlink *devlink, enum devlink_reload_action action)
484510
{
485511
return test_bit(action, &devlink->ops->reload_actions);
486512
}
487513

514+
static bool
515+
devlink_reload_limit_is_supported(struct devlink *devlink, enum devlink_reload_limit limit)
516+
{
517+
return test_bit(limit, &devlink->ops->reload_limits);
518+
}
519+
488520
static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
489521
enum devlink_command cmd, u32 portid,
490522
u32 seq, int flags)
@@ -2990,22 +3022,22 @@ bool devlink_is_reload_failed(const struct devlink *devlink)
29903022
EXPORT_SYMBOL_GPL(devlink_is_reload_failed);
29913023

29923024
static int devlink_reload(struct devlink *devlink, struct net *dest_net,
2993-
enum devlink_reload_action action, u32 *actions_performed,
2994-
struct netlink_ext_ack *extack)
3025+
enum devlink_reload_action action, enum devlink_reload_limit limit,
3026+
u32 *actions_performed, struct netlink_ext_ack *extack)
29953027
{
29963028
int err;
29973029

29983030
if (!devlink->reload_enabled)
29993031
return -EOPNOTSUPP;
30003032

3001-
err = devlink->ops->reload_down(devlink, !!dest_net, action, extack);
3033+
err = devlink->ops->reload_down(devlink, !!dest_net, action, limit, extack);
30023034
if (err)
30033035
return err;
30043036

30053037
if (dest_net && !net_eq(dest_net, devlink_net(devlink)))
30063038
devlink_reload_netns_change(devlink, dest_net);
30073039

3008-
err = devlink->ops->reload_up(devlink, action, actions_performed, extack);
3040+
err = devlink->ops->reload_up(devlink, action, limit, actions_performed, extack);
30093041
devlink_reload_failed_set(devlink, !!err);
30103042
if (err)
30113043
return err;
@@ -3050,6 +3082,7 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
30503082
{
30513083
struct devlink *devlink = info->user_ptr[0];
30523084
enum devlink_reload_action action;
3085+
enum devlink_reload_limit limit;
30533086
struct net *dest_net = NULL;
30543087
u32 actions_performed;
30553088
int err;
@@ -3082,15 +3115,46 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
30823115
return -EOPNOTSUPP;
30833116
}
30843117

3085-
err = devlink_reload(devlink, dest_net, action, &actions_performed, info->extack);
3118+
limit = DEVLINK_RELOAD_LIMIT_UNSPEC;
3119+
if (info->attrs[DEVLINK_ATTR_RELOAD_LIMITS]) {
3120+
struct nla_bitfield32 limits;
3121+
u32 limits_selected;
3122+
3123+
limits = nla_get_bitfield32(info->attrs[DEVLINK_ATTR_RELOAD_LIMITS]);
3124+
limits_selected = limits.value & limits.selector;
3125+
if (!limits_selected) {
3126+
NL_SET_ERR_MSG_MOD(info->extack, "Invalid limit selected");
3127+
return -EINVAL;
3128+
}
3129+
for (limit = 0 ; limit <= DEVLINK_RELOAD_LIMIT_MAX ; limit++)
3130+
if (limits_selected & BIT(limit))
3131+
break;
3132+
/* UAPI enables multiselection, but currently it is not used */
3133+
if (limits_selected != BIT(limit)) {
3134+
NL_SET_ERR_MSG_MOD(info->extack,
3135+
"Multiselection of limit is not supported");
3136+
return -EOPNOTSUPP;
3137+
}
3138+
if (!devlink_reload_limit_is_supported(devlink, limit)) {
3139+
NL_SET_ERR_MSG_MOD(info->extack,
3140+
"Requested limit is not supported by the driver");
3141+
return -EOPNOTSUPP;
3142+
}
3143+
if (devlink_reload_combination_is_invalid(action, limit)) {
3144+
NL_SET_ERR_MSG_MOD(info->extack,
3145+
"Requested limit is invalid for this action");
3146+
return -EINVAL;
3147+
}
3148+
}
3149+
err = devlink_reload(devlink, dest_net, action, limit, &actions_performed, info->extack);
30863150

30873151
if (dest_net)
30883152
put_net(dest_net);
30893153

30903154
if (err)
30913155
return err;
30923156
/* For backward compatibility generate reply only if attributes used by user */
3093-
if (!info->attrs[DEVLINK_ATTR_RELOAD_ACTION])
3157+
if (!info->attrs[DEVLINK_ATTR_RELOAD_ACTION] && !info->attrs[DEVLINK_ATTR_RELOAD_LIMITS])
30943158
return 0;
30953159

30963160
return devlink_nl_reload_actions_performed_snd(devlink, actions_performed,
@@ -7347,6 +7411,7 @@ static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
73477411
[DEVLINK_ATTR_PORT_FUNCTION] = { .type = NLA_NESTED },
73487412
[DEVLINK_ATTR_RELOAD_ACTION] = NLA_POLICY_RANGE(NLA_U8, DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
73497413
DEVLINK_RELOAD_ACTION_MAX),
7414+
[DEVLINK_ATTR_RELOAD_LIMITS] = NLA_POLICY_BITFIELD32(DEVLINK_RELOAD_LIMITS_VALID_MASK),
73507415
};
73517416

73527417
static const struct genl_small_ops devlink_nl_ops[] = {
@@ -7682,6 +7747,9 @@ static struct genl_family devlink_nl_family __ro_after_init = {
76827747

76837748
static bool devlink_reload_actions_valid(const struct devlink_ops *ops)
76847749
{
7750+
const struct devlink_reload_combination *comb;
7751+
int i;
7752+
76857753
if (!devlink_reload_supported(ops)) {
76867754
if (WARN_ON(ops->reload_actions))
76877755
return false;
@@ -7692,6 +7760,17 @@ static bool devlink_reload_actions_valid(const struct devlink_ops *ops)
76927760
ops->reload_actions & BIT(DEVLINK_RELOAD_ACTION_UNSPEC) ||
76937761
ops->reload_actions >= BIT(__DEVLINK_RELOAD_ACTION_MAX)))
76947762
return false;
7763+
7764+
if (WARN_ON(ops->reload_limits & BIT(DEVLINK_RELOAD_LIMIT_UNSPEC) ||
7765+
ops->reload_limits >= BIT(__DEVLINK_RELOAD_LIMIT_MAX)))
7766+
return false;
7767+
7768+
for (i = 0; i < ARRAY_SIZE(devlink_reload_invalid_combinations); i++) {
7769+
comb = &devlink_reload_invalid_combinations[i];
7770+
if (ops->reload_actions == BIT(comb->action) &&
7771+
ops->reload_limits == BIT(comb->limit))
7772+
return false;
7773+
}
76957774
return true;
76967775
}
76977776

@@ -10056,6 +10135,7 @@ static void __net_exit devlink_pernet_pre_exit(struct net *net)
1005610135
continue;
1005710136
err = devlink_reload(devlink, &init_net,
1005810137
DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
10138+
DEVLINK_RELOAD_LIMIT_UNSPEC,
1005910139
&actions_performed, NULL);
1006010140
if (err && err != -EOPNOTSUPP)
1006110141
pr_warn("Failed to reload devlink instance into init_net\n");

0 commit comments

Comments
 (0)