From: Mark Bloch mlx5 sets MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS when acknowledging a sync reset request. This bit blocks devlink reload and other devlink operations while the firmware reset is running, but it was kept set until after the driver reload finished. Clear the reset-in-progress bit once the reset unload flow is done and PCI access is back, before reloading the device. For a reset initiated through devlink, clear it before completing the reload waiter. For a reset reported through an asynchronous firmware event, keep the unload flow outside devl_lock, then take devl_lock before clearing the bit and reloading through the devl-locked load helper. Signed-off-by: Mark Bloch Reviewed-by: Shay Drori Reviewed-by: Moshe Shemesh Signed-off-by: Tariq Toukan --- .../ethernet/mellanox/mlx5/core/fw_reset.c | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c index 07440c58713a..7283e5b49eed 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c @@ -238,24 +238,30 @@ static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev) { struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset; struct devlink *devlink = priv_to_devlink(dev); + int err; /* if this is the driver that initiated the fw reset, devlink completed the reload */ if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) { + clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, + &fw_reset->reset_flags); complete(&fw_reset->done); - } else { - mlx5_sync_reset_unload_flow(dev, false); - if (mlx5_health_wait_pci_up(dev)) - mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n"); - else - mlx5_load_one(dev, true); - devl_lock(devlink); - devlink_remote_reload_actions_performed(devlink, 0, - BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | - BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE)); - devl_unlock(devlink); + return; } + mlx5_sync_reset_unload_flow(dev, false); + err = mlx5_health_wait_pci_up(dev); + + devl_lock(devlink); clear_bit(MLX5_FW_RESET_FLAGS_RESET_IN_PROGRESS, &fw_reset->reset_flags); + if (err) + mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n"); + else + mlx5_load_one_devl_locked(dev, true); + + devlink_remote_reload_actions_performed(devlink, 0, + BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) | + BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE)); + devl_unlock(devlink); } static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev) -- 2.44.0