Commit 1ba569fc authored by David S. Miller's avatar David S. Miller

Merge branch 'devlink-move-reload-fail-indication-to-devlink-core-and-expose-to-user'

Jiri Pirko says:

====================
net: devlink: move reload fail indication to devlink core and expose to user

First two patches are dependencies of the last one. That moves devlink
reload failure indication to the devlink code, so the drivers do not
have to track it themselves. Currently it is only mlxsw, but I will send
a follow-up patchset that introduces this in netdevsim too.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c6af0c22 2670ac26
...@@ -210,7 +210,7 @@ static void mlx4_handle_error_state(struct mlx4_dev_persistent *persist) ...@@ -210,7 +210,7 @@ static void mlx4_handle_error_state(struct mlx4_dev_persistent *persist)
mutex_lock(&persist->interface_state_mutex); mutex_lock(&persist->interface_state_mutex);
if (persist->interface_state & MLX4_INTERFACE_STATE_UP && if (persist->interface_state & MLX4_INTERFACE_STATE_UP &&
!(persist->interface_state & MLX4_INTERFACE_STATE_DELETION)) { !(persist->interface_state & MLX4_INTERFACE_STATE_DELETION)) {
err = mlx4_restart_one(persist->pdev, false, NULL); err = mlx4_restart_one(persist->pdev);
mlx4_info(persist->dev, "mlx4_restart_one was ended, ret=%d\n", mlx4_info(persist->dev, "mlx4_restart_one was ended, ret=%d\n",
err); err);
} }
......
...@@ -3931,26 +3931,43 @@ static void mlx4_devlink_param_load_driverinit_values(struct devlink *devlink) ...@@ -3931,26 +3931,43 @@ static void mlx4_devlink_param_load_driverinit_values(struct devlink *devlink)
} }
} }
static int mlx4_devlink_reload(struct devlink *devlink, static void mlx4_restart_one_down(struct pci_dev *pdev);
static int mlx4_restart_one_up(struct pci_dev *pdev, bool reload,
struct devlink *devlink);
static int mlx4_devlink_reload_down(struct devlink *devlink,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct mlx4_priv *priv = devlink_priv(devlink); struct mlx4_priv *priv = devlink_priv(devlink);
struct mlx4_dev *dev = &priv->dev; struct mlx4_dev *dev = &priv->dev;
struct mlx4_dev_persistent *persist = dev->persist; struct mlx4_dev_persistent *persist = dev->persist;
int err;
if (persist->num_vfs) if (persist->num_vfs)
mlx4_warn(persist->dev, "Reload performed on PF, will cause reset on operating Virtual Functions\n"); mlx4_warn(persist->dev, "Reload performed on PF, will cause reset on operating Virtual Functions\n");
err = mlx4_restart_one(persist->pdev, true, devlink); mlx4_restart_one_down(persist->pdev);
return 0;
}
static int mlx4_devlink_reload_up(struct devlink *devlink,
struct netlink_ext_ack *extack)
{
struct mlx4_priv *priv = devlink_priv(devlink);
struct mlx4_dev *dev = &priv->dev;
struct mlx4_dev_persistent *persist = dev->persist;
int err;
err = mlx4_restart_one_up(persist->pdev, true, devlink);
if (err) if (err)
mlx4_err(persist->dev, "mlx4_restart_one failed, ret=%d\n", err); mlx4_err(persist->dev, "mlx4_restart_one_up failed, ret=%d\n",
err);
return err; return err;
} }
static const struct devlink_ops mlx4_devlink_ops = { static const struct devlink_ops mlx4_devlink_ops = {
.port_type_set = mlx4_devlink_port_type_set, .port_type_set = mlx4_devlink_port_type_set,
.reload = mlx4_devlink_reload, .reload_down = mlx4_devlink_reload_down,
.reload_up = mlx4_devlink_reload_up,
}; };
static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static int mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
...@@ -4163,7 +4180,13 @@ static int restore_current_port_types(struct mlx4_dev *dev, ...@@ -4163,7 +4180,13 @@ static int restore_current_port_types(struct mlx4_dev *dev,
return err; return err;
} }
int mlx4_restart_one(struct pci_dev *pdev, bool reload, struct devlink *devlink) static void mlx4_restart_one_down(struct pci_dev *pdev)
{
mlx4_unload_one(pdev);
}
static int mlx4_restart_one_up(struct pci_dev *pdev, bool reload,
struct devlink *devlink)
{ {
struct mlx4_dev_persistent *persist = pci_get_drvdata(pdev); struct mlx4_dev_persistent *persist = pci_get_drvdata(pdev);
struct mlx4_dev *dev = persist->dev; struct mlx4_dev *dev = persist->dev;
...@@ -4175,7 +4198,6 @@ int mlx4_restart_one(struct pci_dev *pdev, bool reload, struct devlink *devlink) ...@@ -4175,7 +4198,6 @@ int mlx4_restart_one(struct pci_dev *pdev, bool reload, struct devlink *devlink)
total_vfs = dev->persist->num_vfs; total_vfs = dev->persist->num_vfs;
memcpy(nvfs, dev->persist->nvfs, sizeof(dev->persist->nvfs)); memcpy(nvfs, dev->persist->nvfs, sizeof(dev->persist->nvfs));
mlx4_unload_one(pdev);
if (reload) if (reload)
mlx4_devlink_param_load_driverinit_values(devlink); mlx4_devlink_param_load_driverinit_values(devlink);
err = mlx4_load_one(pdev, pci_dev_data, total_vfs, nvfs, priv, 1); err = mlx4_load_one(pdev, pci_dev_data, total_vfs, nvfs, priv, 1);
...@@ -4194,6 +4216,12 @@ int mlx4_restart_one(struct pci_dev *pdev, bool reload, struct devlink *devlink) ...@@ -4194,6 +4216,12 @@ int mlx4_restart_one(struct pci_dev *pdev, bool reload, struct devlink *devlink)
return err; return err;
} }
int mlx4_restart_one(struct pci_dev *pdev)
{
mlx4_restart_one_down(pdev);
return mlx4_restart_one_up(pdev, false, NULL);
}
#define MLX_SP(id) { PCI_VDEVICE(MELLANOX, id), MLX4_PCI_DEV_FORCE_SENSE_PORT } #define MLX_SP(id) { PCI_VDEVICE(MELLANOX, id), MLX4_PCI_DEV_FORCE_SENSE_PORT }
#define MLX_VF(id) { PCI_VDEVICE(MELLANOX, id), MLX4_PCI_DEV_IS_VF } #define MLX_VF(id) { PCI_VDEVICE(MELLANOX, id), MLX4_PCI_DEV_IS_VF }
#define MLX_GN(id) { PCI_VDEVICE(MELLANOX, id), 0 } #define MLX_GN(id) { PCI_VDEVICE(MELLANOX, id), 0 }
......
...@@ -1043,8 +1043,7 @@ int mlx4_catas_init(struct mlx4_dev *dev); ...@@ -1043,8 +1043,7 @@ int mlx4_catas_init(struct mlx4_dev *dev);
void mlx4_catas_end(struct mlx4_dev *dev); void mlx4_catas_end(struct mlx4_dev *dev);
int mlx4_crdump_init(struct mlx4_dev *dev); int mlx4_crdump_init(struct mlx4_dev *dev);
void mlx4_crdump_end(struct mlx4_dev *dev); void mlx4_crdump_end(struct mlx4_dev *dev);
int mlx4_restart_one(struct pci_dev *pdev, bool reload, int mlx4_restart_one(struct pci_dev *pdev);
struct devlink *devlink);
int mlx4_register_device(struct mlx4_dev *dev); int mlx4_register_device(struct mlx4_dev *dev);
void mlx4_unregister_device(struct mlx4_dev *dev); void mlx4_unregister_device(struct mlx4_dev *dev);
void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type, void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type,
......
...@@ -80,7 +80,6 @@ struct mlxsw_core { ...@@ -80,7 +80,6 @@ struct mlxsw_core {
struct mlxsw_thermal *thermal; struct mlxsw_thermal *thermal;
struct mlxsw_core_port *ports; struct mlxsw_core_port *ports;
unsigned int max_ports; unsigned int max_ports;
bool reload_fail;
bool fw_flash_in_progress; bool fw_flash_in_progress;
unsigned long driver_priv[0]; unsigned long driver_priv[0];
/* driver_priv has to be always the last item */ /* driver_priv has to be always the last item */
...@@ -984,23 +983,29 @@ mlxsw_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req, ...@@ -984,23 +983,29 @@ mlxsw_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
return 0; return 0;
} }
static int mlxsw_devlink_core_bus_device_reload(struct devlink *devlink, static int
mlxsw_devlink_core_bus_device_reload_down(struct devlink *devlink,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct mlxsw_core *mlxsw_core = devlink_priv(devlink); struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
int err;
if (!(mlxsw_core->bus->features & MLXSW_BUS_F_RESET)) if (!(mlxsw_core->bus->features & MLXSW_BUS_F_RESET))
return -EOPNOTSUPP; return -EOPNOTSUPP;
mlxsw_core_bus_device_unregister(mlxsw_core, true); mlxsw_core_bus_device_unregister(mlxsw_core, true);
err = mlxsw_core_bus_device_register(mlxsw_core->bus_info, return 0;
}
static int
mlxsw_devlink_core_bus_device_reload_up(struct devlink *devlink,
struct netlink_ext_ack *extack)
{
struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
return mlxsw_core_bus_device_register(mlxsw_core->bus_info,
mlxsw_core->bus, mlxsw_core->bus,
mlxsw_core->bus_priv, true, mlxsw_core->bus_priv, true,
devlink); devlink);
mlxsw_core->reload_fail = !!err;
return err;
} }
static int mlxsw_devlink_flash_update(struct devlink *devlink, static int mlxsw_devlink_flash_update(struct devlink *devlink,
...@@ -1066,7 +1071,8 @@ mlxsw_devlink_trap_group_init(struct devlink *devlink, ...@@ -1066,7 +1071,8 @@ mlxsw_devlink_trap_group_init(struct devlink *devlink,
} }
static const struct devlink_ops mlxsw_devlink_ops = { static const struct devlink_ops mlxsw_devlink_ops = {
.reload = mlxsw_devlink_core_bus_device_reload, .reload_down = mlxsw_devlink_core_bus_device_reload_down,
.reload_up = mlxsw_devlink_core_bus_device_reload_up,
.port_type_set = mlxsw_devlink_port_type_set, .port_type_set = mlxsw_devlink_port_type_set,
.port_split = mlxsw_devlink_port_split, .port_split = mlxsw_devlink_port_split,
.port_unsplit = mlxsw_devlink_port_unsplit, .port_unsplit = mlxsw_devlink_port_unsplit,
...@@ -1243,7 +1249,7 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core, ...@@ -1243,7 +1249,7 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
{ {
struct devlink *devlink = priv_to_devlink(mlxsw_core); struct devlink *devlink = priv_to_devlink(mlxsw_core);
if (mlxsw_core->reload_fail) { if (devlink_is_reload_failed(devlink)) {
if (!reload) if (!reload)
/* Only the parts that were not de-initialized in the /* Only the parts that were not de-initialized in the
* failed reload attempt need to be de-initialized. * failed reload attempt need to be de-initialized.
......
...@@ -521,7 +521,13 @@ static void nsim_dev_traps_exit(struct devlink *devlink) ...@@ -521,7 +521,13 @@ static void nsim_dev_traps_exit(struct devlink *devlink)
kfree(nsim_dev->trap_data); kfree(nsim_dev->trap_data);
} }
static int nsim_dev_reload(struct devlink *devlink, static int nsim_dev_reload_down(struct devlink *devlink,
struct netlink_ext_ack *extack)
{
return 0;
}
static int nsim_dev_reload_up(struct devlink *devlink,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
enum nsim_resource_id res_ids[] = { enum nsim_resource_id res_ids[] = {
...@@ -638,7 +644,8 @@ nsim_dev_devlink_trap_action_set(struct devlink *devlink, ...@@ -638,7 +644,8 @@ nsim_dev_devlink_trap_action_set(struct devlink *devlink,
} }
static const struct devlink_ops nsim_dev_devlink_ops = { static const struct devlink_ops nsim_dev_devlink_ops = {
.reload = nsim_dev_reload, .reload_down = nsim_dev_reload_down,
.reload_up = nsim_dev_reload_up,
.flash_update = nsim_dev_flash_update, .flash_update = nsim_dev_flash_update,
.trap_init = nsim_dev_devlink_trap_init, .trap_init = nsim_dev_devlink_trap_init,
.trap_action_set = nsim_dev_devlink_trap_action_set, .trap_action_set = nsim_dev_devlink_trap_action_set,
......
...@@ -38,6 +38,7 @@ struct devlink { ...@@ -38,6 +38,7 @@ struct devlink {
struct device *dev; struct device *dev;
possible_net_t _net; possible_net_t _net;
struct mutex lock; struct mutex lock;
bool reload_failed;
char priv[0] __aligned(NETDEV_ALIGN); char priv[0] __aligned(NETDEV_ALIGN);
}; };
...@@ -642,7 +643,10 @@ enum devlink_trap_group_generic_id { ...@@ -642,7 +643,10 @@ enum devlink_trap_group_generic_id {
} }
struct devlink_ops { struct devlink_ops {
int (*reload)(struct devlink *devlink, struct netlink_ext_ack *extack); int (*reload_down)(struct devlink *devlink,
struct netlink_ext_ack *extack);
int (*reload_up)(struct devlink *devlink,
struct netlink_ext_ack *extack);
int (*port_type_set)(struct devlink_port *devlink_port, int (*port_type_set)(struct devlink_port *devlink_port,
enum devlink_port_type port_type); enum devlink_port_type port_type);
int (*port_split)(struct devlink *devlink, unsigned int port_index, int (*port_split)(struct devlink *devlink, unsigned int port_index,
...@@ -942,6 +946,8 @@ void ...@@ -942,6 +946,8 @@ void
devlink_health_reporter_state_update(struct devlink_health_reporter *reporter, devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
enum devlink_health_reporter_state state); enum devlink_health_reporter_state state);
bool devlink_is_reload_failed(const struct devlink *devlink);
void devlink_flash_update_begin_notify(struct devlink *devlink); void devlink_flash_update_begin_notify(struct devlink *devlink);
void devlink_flash_update_end_notify(struct devlink *devlink); void devlink_flash_update_end_notify(struct devlink *devlink);
void devlink_flash_update_status_notify(struct devlink *devlink, void devlink_flash_update_status_notify(struct devlink *devlink,
......
...@@ -419,6 +419,8 @@ enum devlink_attr { ...@@ -419,6 +419,8 @@ enum devlink_attr {
DEVLINK_ATTR_TRAP_METADATA, /* nested */ DEVLINK_ATTR_TRAP_METADATA, /* nested */
DEVLINK_ATTR_TRAP_GROUP_NAME, /* string */ DEVLINK_ATTR_TRAP_GROUP_NAME, /* string */
DEVLINK_ATTR_RELOAD_FAILED, /* u8 0 or 1 */
/* add new attributes above here, update the policy in devlink.c */ /* add new attributes above here, update the policy in devlink.c */
__DEVLINK_ATTR_MAX, __DEVLINK_ATTR_MAX,
......
...@@ -471,6 +471,8 @@ static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink, ...@@ -471,6 +471,8 @@ static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
if (devlink_nl_put_handle(msg, devlink)) if (devlink_nl_put_handle(msg, devlink))
goto nla_put_failure; goto nla_put_failure;
if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_FAILED, devlink->reload_failed))
goto nla_put_failure;
genlmsg_end(msg, hdr); genlmsg_end(msg, hdr);
return 0; return 0;
...@@ -2672,12 +2674,32 @@ devlink_resources_validate(struct devlink *devlink, ...@@ -2672,12 +2674,32 @@ devlink_resources_validate(struct devlink *devlink,
return err; return err;
} }
static bool devlink_reload_supported(struct devlink *devlink)
{
return devlink->ops->reload_down && devlink->ops->reload_up;
}
static void devlink_reload_failed_set(struct devlink *devlink,
bool reload_failed)
{
if (devlink->reload_failed == reload_failed)
return;
devlink->reload_failed = reload_failed;
devlink_notify(devlink, DEVLINK_CMD_NEW);
}
bool devlink_is_reload_failed(const struct devlink *devlink)
{
return devlink->reload_failed;
}
EXPORT_SYMBOL_GPL(devlink_is_reload_failed);
static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
{ {
struct devlink *devlink = info->user_ptr[0]; struct devlink *devlink = info->user_ptr[0];
int err; int err;
if (!devlink->ops->reload) if (!devlink_reload_supported(devlink))
return -EOPNOTSUPP; return -EOPNOTSUPP;
err = devlink_resources_validate(devlink, NULL, info); err = devlink_resources_validate(devlink, NULL, info);
...@@ -2685,7 +2707,12 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) ...@@ -2685,7 +2707,12 @@ static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed"); NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed");
return err; return err;
} }
return devlink->ops->reload(devlink, info->extack); err = devlink->ops->reload_down(devlink, info->extack);
if (err)
return err;
err = devlink->ops->reload_up(devlink, info->extack);
devlink_reload_failed_set(devlink, !!err);
return err;
} }
static int devlink_nl_flash_update_fill(struct sk_buff *msg, static int devlink_nl_flash_update_fill(struct sk_buff *msg,
...@@ -7150,7 +7177,7 @@ __devlink_param_driverinit_value_set(struct devlink *devlink, ...@@ -7150,7 +7177,7 @@ __devlink_param_driverinit_value_set(struct devlink *devlink,
int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id, int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
union devlink_param_value *init_val) union devlink_param_value *init_val)
{ {
if (!devlink->ops->reload) if (!devlink_reload_supported(devlink))
return -EOPNOTSUPP; return -EOPNOTSUPP;
return __devlink_param_driverinit_value_get(&devlink->param_list, return __devlink_param_driverinit_value_get(&devlink->param_list,
...@@ -7197,7 +7224,7 @@ int devlink_port_param_driverinit_value_get(struct devlink_port *devlink_port, ...@@ -7197,7 +7224,7 @@ int devlink_port_param_driverinit_value_get(struct devlink_port *devlink_port,
{ {
struct devlink *devlink = devlink_port->devlink; struct devlink *devlink = devlink_port->devlink;
if (!devlink->ops->reload) if (!devlink_reload_supported(devlink))
return -EOPNOTSUPP; return -EOPNOTSUPP;
return __devlink_param_driverinit_value_get(&devlink_port->param_list, return __devlink_param_driverinit_value_get(&devlink_port->param_list,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment