From: Valentine Fatiev <valentinef@nvidia.com>
Subject: [PATCH] BACKPORT: drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c

Change-Id: If602dfea37251d304529f4e846974997b407697b
---
 .../ethernet/mellanox/mlx5/core/fw_reset.c    | 135 ++++++++++++++++++
 1 file changed, 135 insertions(+)

--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
@@ -28,8 +28,10 @@ struct mlx5_fw_reset {
 	struct delayed_work reset_timeout_work;
 	unsigned long reset_flags;
 	struct timer_list timer;
+#ifdef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
 	struct completion done;
 	int ret;
+#endif
 };
 
 enum {
@@ -53,12 +55,22 @@ static void mlx5_set_fw_rst_ack(struct m
 	iowrite32be(BIT(MLX5_RST_ACK_BIT_NUM), &dev->iseg->initializing);
 }
 
+#if defined(HAVE_DEVLINK_PARAMS_PUBLISHED) || defined(HAVE_DEVLINK_REGISTER_GET_1_PARAMS)
 static int mlx5_fw_reset_enable_remote_dev_reset_set(struct devlink *devlink, u32 id,
+#ifdef HAVE_DEVLINK_PARAM_SET_FUNCTION_POINTER_HAS_EXTACK
+						     struct devlink_param_gset_ctx *ctx,
+						     struct netlink_ext_ack *extack)
+#else
 						     struct devlink_param_gset_ctx *ctx)
+#endif
 {
 	struct mlx5_core_dev *dev = devlink_priv(devlink);
 	struct mlx5_fw_reset *fw_reset;
 
+#if !defined(HAVE_DEVL_PARAM_DRIVERINIT_VALUE_GET) && defined(HAVE_DEVLINK_PARAM_REGISTER)
+	if (mlx5_dev_is_lightweight(dev))
+		return -EOPNOTSUPP;
+#endif
 	fw_reset = dev->priv.fw_reset;
 
 	if (ctx->val.vbool)
@@ -74,12 +86,17 @@ static int mlx5_fw_reset_enable_remote_d
 	struct mlx5_core_dev *dev = devlink_priv(devlink);
 	struct mlx5_fw_reset *fw_reset;
 
+#if !defined(HAVE_DEVL_PARAM_DRIVERINIT_VALUE_GET) && defined(HAVE_DEVLINK_PARAM_REGISTER)
+	if (mlx5_dev_is_lightweight(dev))
+		return -EOPNOTSUPP;
+#endif
 	fw_reset = dev->priv.fw_reset;
 
 	ctx->val.vbool = !test_bit(MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST,
 				   &fw_reset->reset_flags);
 	return 0;
 }
+#endif
 
 static int mlx5_reg_mfrl_set(struct mlx5_core_dev *dev, u8 reset_level,
 			     u8 reset_type_sel, u8 sync_resp, bool sync_start)
@@ -121,6 +138,7 @@ int mlx5_fw_reset_query(struct mlx5_core
 	return mlx5_reg_mfrl_query(dev, reset_level, reset_type, NULL);
 }
 
+#ifdef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
 static int mlx5_fw_reset_get_reset_state_err(struct mlx5_core_dev *dev,
 					     struct netlink_ext_ack *extack)
 {
@@ -199,12 +217,14 @@ int mlx5_fw_reset_verify_fw_complete(str
 	NL_SET_ERR_MSG_MOD(extack, "Sync reset did not complete successfully");
 	return rst_state;
 }
+#endif /* HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION */
 
 int mlx5_fw_reset_set_live_patch(struct mlx5_core_dev *dev)
 {
 	return mlx5_reg_mfrl_set(dev, MLX5_MFRL_REG_RESET_LEVEL0, 0, 0, false);
 }
 
+#ifdef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
 static void mlx5_fw_reset_complete_reload(struct mlx5_core_dev *dev, bool unloaded)
 {
 	struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
@@ -213,17 +233,20 @@ static void mlx5_fw_reset_complete_reloa
 	if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags)) {
 		complete(&fw_reset->done);
 	} else {
+#ifdef HAVE_DEVL_TRAP_GROUPS_REGISTER
 		if (!unloaded)
 			mlx5_unload_one(dev, false);
 		if (mlx5_health_wait_pci_up(dev))
 			mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n");
 		else
+#endif
 			mlx5_load_one(dev, true);
 		devlink_remote_reload_actions_performed(priv_to_devlink(dev), 0,
 							BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) |
 							BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE));
 	}
 }
+#endif
 
 static void mlx5_stop_sync_reset_poll(struct mlx5_core_dev *dev)
 {
@@ -252,11 +275,32 @@ static void mlx5_sync_reset_reload_work(
 	struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset,
 						      reset_reload_work);
 	struct mlx5_core_dev *dev = fw_reset->dev;
+#ifndef HAVE_DEVL_TRAP_GROUPS_REGISTER
+	int err;
+#endif
 
 	cancel_delayed_work(&fw_reset->reset_timeout_work);
 	mlx5_sync_reset_clear_reset_requested(dev, false);
 	mlx5_enter_error_state(dev, true);
+#ifndef HAVE_DEVL_TRAP_GROUPS_REGISTER
+	mlx5_unload_one(dev, false);
+	err = mlx5_health_wait_pci_up(dev);
+	if (err) {
+		mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n");
+#ifndef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
+		return;
+#endif
+	}
+#endif /* HAVE_DEVL_TRAP_GROUPS_REGISTER */
+
+#ifdef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
+#ifndef HAVE_DEVL_TRAP_GROUPS_REGISTER
+	fw_reset->ret = err;
+#endif
 	mlx5_fw_reset_complete_reload(dev, false);
+#else /* HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION */
+	mlx5_load_one(dev, true);
+#endif /* HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION */
 }
 
 #define MLX5_RESET_POLL_INTERVAL	(HZ / 10)
@@ -446,6 +490,10 @@ static void mlx5_sync_reset_request_even
 		mlx5_core_warn(dev, "PCI Sync FW Update Reset Ack. Device reset is expected.\n");
 }
 
+#ifndef PCI_EXP_RTCAP_CRSVIS
+#define  PCI_EXP_RTCAP_CRSVIS	0x0001	/* CRS Software Visibility capability */
+#endif
+
 static int mlx5_pci_config_hw_control(struct pci_dev *root_port,
 				      bool new_val, bool *prev_val)
 {
@@ -674,8 +722,16 @@ static int mlx5_pci_link_toggle_pf(struc
 		return pcibios_err_to_errno(err);
 
 	/* Check link */
+#ifdef HAVE_PCI_DEV_LINK_ACTIVE_REPORTING
 	if (!bridge->link_active_reporting) {
 		mlx5_core_warn(dev, "No PCI link reporting capability\n");
+#else
+	err = pci_read_config_dword(bridge, cap + PCI_EXP_LNKCAP, &reg32);
+	if (err)
+		return err;
+	if (!(reg32 & PCI_EXP_LNKCAP_DLLLARC)) {
+		mlx5_core_warn(dev, "No PCI link reporting capability (0x%08x)\n", reg32);
+#endif
 		msleep(1000);
 		goto restore;
 	}
@@ -788,9 +844,16 @@ static void mlx5_sync_reset_now_event(st
 	}
 
 	mlx5_enter_error_state(dev, true);
+#ifndef HAVE_DEVL_TRAP_GROUPS_REGISTER
+	mlx5_unload_one(dev, false);
+#endif
 done:
+#ifdef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
 	fw_reset->ret = err;
 	mlx5_fw_reset_complete_reload(dev, false);
+#else
+	mlx5_load_one(dev, true);
+#endif
 }
 
 static void mlx5_sync_reset_unload_event(struct work_struct *work)
@@ -817,9 +880,11 @@ static void mlx5_sync_reset_unload_event
 	else
 		mlx5_enter_error_state(dev, true);
 
+#ifdef HAVE_DEVL_TRAP_GROUPS_REGISTER
 	if (test_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags))
 		mlx5_unload_one_devl_locked(dev, false);
 	else
+#endif
 		mlx5_unload_one(dev, false);
 
 	mlx5_set_fw_rst_ack(dev);
@@ -845,7 +910,9 @@ static void mlx5_sync_reset_unload_event
 	if (!reset_action) {
 		mlx5_core_err(dev, "Got timeout waiting for sync reset action, state = %u\n",
 			      rst_state);
+#ifdef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
 		fw_reset->ret = -ETIMEDOUT;
+#endif
 		goto done;
 	}
 
@@ -854,12 +921,18 @@ static void mlx5_sync_reset_unload_event
 		err = mlx5_pci_link_toggle(dev);
 		if (err) {
 			mlx5_core_warn(dev, "mlx5_pci_link_toggle failed, err %d\n", err);
+#ifdef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
 			fw_reset->ret = err;
+#endif
 		}
 	}
 
 done:
+#ifdef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
 	mlx5_fw_reset_complete_reload(dev, true);
+#else /* HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION */
+	mlx5_load_one(dev, true);
+#endif /* HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION */
 }
 
 static void mlx5_sync_reset_abort_event(struct work_struct *work)
@@ -932,6 +1005,7 @@ static int fw_reset_event_notifier(struc
 	return NOTIFY_OK;
 }
 
+#ifdef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
 int mlx5_fw_reset_wait_reset_done(struct mlx5_core_dev *dev)
 {
 	unsigned long pci_sync_update_timeout = mlx5_tout_ms(dev, PCI_SYNC_UPDATE);
@@ -950,13 +1024,18 @@ int mlx5_fw_reset_wait_reset_done(struct
 	}
 	err = fw_reset->ret;
 	if (test_and_clear_bit(MLX5_FW_RESET_FLAGS_RELOAD_REQUIRED, &fw_reset->reset_flags)) {
+#ifdef HAVE_DEVL_TRAP_GROUPS_REGISTER
 		mlx5_unload_one_devl_locked(dev, false);
 		mlx5_load_one_devl_locked(dev, true);
+#else
+		mlx5_load_one(dev, true);
+#endif
 	}
 out:
 	clear_bit(MLX5_FW_RESET_FLAGS_PENDING_COMP, &fw_reset->reset_flags);
 	return err;
 }
+#endif /* HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION */
 
 void mlx5_fw_reset_events_start(struct mlx5_core_dev *dev)
 {
@@ -996,16 +1075,48 @@ void mlx5_drain_fw_reset(struct mlx5_cor
 	cancel_delayed_work(&fw_reset->reset_timeout_work);
 }
 
+#if defined(HAVE_DEVLINK_PARAMS_PUBLISHED) || defined(HAVE_DEVLINK_REGISTER_GET_1_PARAMS)
 static const struct devlink_param mlx5_fw_reset_devlink_params[] = {
+#ifdef HAVE_DEVLINK_PARAM_GENERIC_ID_ENABLE_REMOTE_DEV_RESET
 	DEVLINK_PARAM_GENERIC(ENABLE_REMOTE_DEV_RESET, BIT(DEVLINK_PARAM_CMODE_RUNTIME),
 			      mlx5_fw_reset_enable_remote_dev_reset_get,
 			      mlx5_fw_reset_enable_remote_dev_reset_set, NULL),
+#else
+	DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ENABLE_REMOTE_DEV_RESET,
+			     "enable_remote_dev_reset", DEVLINK_PARAM_TYPE_BOOL,
+			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+			     mlx5_fw_reset_enable_remote_dev_reset_get,
+			     mlx5_fw_reset_enable_remote_dev_reset_set, NULL),
+#endif
 };
 
+#ifndef HAVE_DEVL_PARAM_DRIVERINIT_VALUE_GET
+int mlx5_register_devlink_fw_params(struct mlx5_core_dev *dev)
+{
+	if (!dev->priv.fw_reset)
+		return 0;
+
+	return devlink_params_register(priv_to_devlink(dev), mlx5_fw_reset_devlink_params,
+				       ARRAY_SIZE(mlx5_fw_reset_devlink_params));
+}
+
+void mlx5_unregister_devlink_fw_params(struct mlx5_core_dev *dev)
+{
+	if (!dev->priv.fw_reset)
+		return;
+
+	devlink_params_unregister(priv_to_devlink(dev), mlx5_fw_reset_devlink_params,
+				  ARRAY_SIZE(mlx5_fw_reset_devlink_params));
+}
+#endif /* !HAVE_DEVL_PARAM_DRIVERINIT_VALUE_GET */
+#endif /* HAVE_DEVLINK_PARAMS_PUBLISHED || HAVE_DEVLINK_REGISTER_GET_1_PARAMS */
+
 int mlx5_fw_reset_init(struct mlx5_core_dev *dev)
 {
 	struct mlx5_fw_reset *fw_reset;
+#if defined(HAVE_DEVL_PARAM_DRIVERINIT_VALUE_GET) || defined(HAVE_DEVLINK_REGISTER_GET_1_PARAMS)
 	int err;
+#endif
 
 	if (!MLX5_CAP_MCAM_REG(dev, mfrl))
 		return 0;
@@ -1022,6 +1133,7 @@ int mlx5_fw_reset_init(struct mlx5_core_
 	fw_reset->dev = dev;
 	dev->priv.fw_reset = fw_reset;
 
+#ifdef HAVE_DEVL_PARAM_DRIVERINIT_VALUE_GET
 	err = devl_params_register(priv_to_devlink(dev),
 				   mlx5_fw_reset_devlink_params,
 				   ARRAY_SIZE(mlx5_fw_reset_devlink_params));
@@ -1030,6 +1142,19 @@ int mlx5_fw_reset_init(struct mlx5_core_
 		kfree(fw_reset);
 		return err;
 	}
+#else
+#ifdef HAVE_DEVLINK_REGISTER_GET_1_PARAMS
+
+	err = devlink_params_register(priv_to_devlink(dev),
+				      mlx5_fw_reset_devlink_params,
+				      ARRAY_SIZE(mlx5_fw_reset_devlink_params));
+	if (err) {
+		destroy_workqueue(fw_reset->wq);
+		kfree(fw_reset);
+		return err;
+	}
+#endif
+#endif
 
 	INIT_WORK(&fw_reset->fw_live_patch_work, mlx5_fw_live_patch_event);
 	INIT_WORK(&fw_reset->reset_request_work, mlx5_sync_reset_request_event);
@@ -1039,7 +1164,9 @@ int mlx5_fw_reset_init(struct mlx5_core_
 	INIT_WORK(&fw_reset->reset_abort_work, mlx5_sync_reset_abort_event);
 	INIT_DELAYED_WORK(&fw_reset->reset_timeout_work, mlx5_sync_reset_timeout_work);
 
+#ifdef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
 	init_completion(&fw_reset->done);
+#endif
 	return 0;
 }
 
@@ -1050,9 +1177,17 @@ void mlx5_fw_reset_cleanup(struct mlx5_c
 	if (!fw_reset)
 		return;
 
+#ifdef HAVE_DEVL_PARAM_DRIVERINIT_VALUE_GET
 	devl_params_unregister(priv_to_devlink(dev),
 			       mlx5_fw_reset_devlink_params,
 			       ARRAY_SIZE(mlx5_fw_reset_devlink_params));
+#else
+#ifdef HAVE_DEVLINK_REGISTER_GET_1_PARAMS
+	devlink_params_unregister(priv_to_devlink(dev),
+				  mlx5_fw_reset_devlink_params,
+				  ARRAY_SIZE(mlx5_fw_reset_devlink_params));
+#endif
+#endif
 	destroy_workqueue(fw_reset->wq);
 	kfree(dev->priv.fw_reset);
 }
