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

Change-Id: I9a6db7203a4d745dd194a002ff04e2819aaf29cb
---
 .../ethernet/mellanox/mlx5/core/fw_reset.c    | 72 ++++++++++++++++++-
 1 file changed, 71 insertions(+), 1 deletion(-)

--- a/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
@@ -8,7 +8,9 @@
 enum {
 	MLX5_FW_RESET_FLAGS_RESET_REQUESTED,
 	MLX5_FW_RESET_FLAGS_NACK_RESET_REQUEST,
+#ifdef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
 	MLX5_FW_RESET_FLAGS_PENDING_COMP,
+#endif
 	MLX5_FW_RESET_FLAGS_DROP_NEW_REQUESTS
 };
 
@@ -23,8 +25,10 @@ struct mlx5_fw_reset {
 	struct work_struct reset_abort_work;
 	unsigned long reset_flags;
 	struct timer_list timer;
+#ifdef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
 	struct completion done;
 	int ret;
+#endif
 };
 
 void mlx5_fw_reset_enable_remote_dev_reset_set(struct mlx5_core_dev *dev, bool enable)
@@ -84,6 +88,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)
 {
@@ -135,12 +140,14 @@ int mlx5_fw_reset_set_reset_sync(struct
 	NL_SET_ERR_MSG_MOD(extack, "Sync reset command failed");
 	return mlx5_cmd_check(dev, err, in, out);
 }
+#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)
 {
 	struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
@@ -149,12 +156,18 @@ 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 //forward port
+		mlx5_unload_one(dev);
+		if (mlx5_health_wait_pci_up(dev))
+			mlx5_core_err(dev, "reset reload flow aborted, PCI reads still not working\n");
+#endif
 		mlx5_load_one(dev, false);
 		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)
 {
@@ -183,22 +196,45 @@ 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 //forward port
 	int err;
+#endif
 
 	mlx5_sync_reset_clear_reset_requested(dev, false);
 	mlx5_enter_error_state(dev, true);
+#ifndef HAVE_DEVL_TRAP_GROUPS_REGISTER //forward port
 	mlx5_unload_one(dev);
 	err = mlx5_health_wait_pci_up(dev);
-	if (err)
+	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 //forward port
 	fw_reset->ret = err;
+#endif
 	mlx5_fw_reset_complete_reload(dev);
+#else /* HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION */
+	mlx5_load_one(dev, false);
+#endif /* HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION */
 }
 
 #define MLX5_RESET_POLL_INTERVAL	(HZ / 10)
+#ifdef HAVE_TIMER_SETUP
 static void poll_sync_reset(struct timer_list *t)
+#else
+static void poll_sync_reset(unsigned long data)
+#endif
 {
+#ifdef HAVE_TIMER_SETUP
 	struct mlx5_fw_reset *fw_reset = from_timer(fw_reset, t, timer);
+#else
+	struct mlx5_fw_reset *fw_reset = (struct mlx5_fw_reset *)data;
+#endif
 	struct mlx5_core_dev *dev = fw_reset->dev;
 	u32 fatal_error;
 
@@ -224,7 +260,13 @@ static void mlx5_start_sync_reset_poll(s
 {
 	struct mlx5_fw_reset *fw_reset = dev->priv.fw_reset;
 
+#ifdef HAVE_TIMER_SETUP
 	timer_setup(&fw_reset->timer, poll_sync_reset, 0);
+#else
+	init_timer(&fw_reset->timer);
+	fw_reset->timer.data = (unsigned long)fw_reset;
+	fw_reset->timer.function = poll_sync_reset;
+#endif
 	fw_reset->timer.expires = round_jiffies(jiffies + MLX5_RESET_POLL_INTERVAL);
 	add_timer(&fw_reset->timer);
 }
@@ -288,6 +330,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)
 {
@@ -440,6 +486,20 @@ static int mlx5_reset_pci_topology(struc
 	return 0;
 }
 
+#ifndef HAVE_PCIE_FIND_ROOT_PORT
+static inline struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
+{
+	while (dev) {
+		if (pci_is_pcie(dev) &&
+		    pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
+			return dev;
+		dev = pci_upstream_bridge(dev);
+	}
+
+	return NULL;
+}
+#endif
+
 static int mlx5_pci_link_toggle_ecpf(struct mlx5_core_dev *dev)
 {
 	struct pci_dev *root_port;
@@ -638,10 +698,16 @@ static void mlx5_sync_reset_now_event(st
 	}
 
 	mlx5_enter_error_state(dev, true);
+#ifndef HAVE_DEVL_TRAP_GROUPS_REGISTER //forward port
 	mlx5_unload_one(dev);
+#endif
 done:
+#ifdef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
 	fw_reset->ret = err;
 	mlx5_fw_reset_complete_reload(dev);
+#else
+	mlx5_load_one(dev, false);
+#endif
 }
 
 static void mlx5_sync_reset_abort_event(struct work_struct *work)
@@ -697,6 +763,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);
@@ -715,6 +782,7 @@ 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)
 {
@@ -762,7 +830,9 @@ int mlx5_fw_reset_init(struct mlx5_core_
 	INIT_WORK(&fw_reset->reset_now_work, mlx5_sync_reset_now_event);
 	INIT_WORK(&fw_reset->reset_abort_work, mlx5_sync_reset_abort_event);
 
+#ifdef HAVE_DEVLINK_RELOAD_DOWN_SUPPORT_RELOAD_ACTION
 	init_completion(&fw_reset->done);
+#endif
 	return 0;
 }
 
