@@ -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+
482508static bool
483509devlink_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+
488520static 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)
29903022EXPORT_SYMBOL_GPL (devlink_is_reload_failed );
29913023
29923024static 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
73527417static const struct genl_small_ops devlink_nl_ops [] = {
@@ -7682,6 +7747,9 @@ static struct genl_family devlink_nl_family __ro_after_init = {
76827747
76837748static 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