Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 30 Mar 2018 19:18:33 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r331810 - in stable/11/sys/dev/mlx5: . mlx5_core
Message-ID:  <201803301918.w2UJIXJ9099530@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Fri Mar 30 19:18:33 2018
New Revision: 331810
URL: https://svnweb.freebsd.org/changeset/base/331810

Log:
  MFC r331445:
  Add support for fast unload in shutdown flow in mlx5core.
  
  This patch accumulates the following Linux commits:
  
  - 8812c24d28f4972c4f2b9998bf30b1f2a1b62adf
    net/mlx5: Add fast unload support in shutdown flow
  - 59211bd3b6329c3e5f4a90ac3d7f87ffa7867073
    net/mlx5: Split the load/unload flow into hardware and software flows
  - 4525abeaae54560254a1bb8970b3d4c225d32ef4
    net/mlx5: Expose command polling interface
  
  Submitted by:	Matthew Finlay <matt@mellanox.com>
  Sponsored by:	Mellanox Technologies

Modified:
  stable/11/sys/dev/mlx5/driver.h
  stable/11/sys/dev/mlx5/mlx5_core/mlx5_cmd.c
  stable/11/sys/dev/mlx5/mlx5_core/mlx5_core.h
  stable/11/sys/dev/mlx5/mlx5_core/mlx5_fw.c
  stable/11/sys/dev/mlx5/mlx5_core/mlx5_health.c
  stable/11/sys/dev/mlx5/mlx5_core/mlx5_main.c
  stable/11/sys/dev/mlx5/mlx5_ifc.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/mlx5/driver.h
==============================================================================
--- stable/11/sys/dev/mlx5/driver.h	Fri Mar 30 19:17:09 2018	(r331809)
+++ stable/11/sys/dev/mlx5/driver.h	Fri Mar 30 19:18:33 2018	(r331810)
@@ -779,6 +779,7 @@ struct mlx5_cmd_work_ent {
 	u64			ts2;
 	u16			op;
 	u8			busy;
+	bool			polling;
 };
 
 struct mlx5_pas {
@@ -866,6 +867,7 @@ static inline u32 mlx5_base_mkey(const u32 key)
 	return key & 0xffffff00u;
 }
 
+void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force);
 int mlx5_cmd_init(struct mlx5_core_dev *dev);
 void mlx5_cmd_cleanup(struct mlx5_core_dev *dev);
 void mlx5_cmd_use_events(struct mlx5_core_dev *dev);
@@ -877,6 +879,8 @@ int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in,
 int mlx5_cmd_exec_cb(struct mlx5_core_dev *dev, void *in, int in_size,
 		     void *out, int out_size, mlx5_cmd_cbk_t callback,
 		     void *context);
+int mlx5_cmd_exec_polling(struct mlx5_core_dev *dev, void *in, int in_size,
+			  void *out, int out_size);
 int mlx5_cmd_alloc_uar(struct mlx5_core_dev *dev, u32 *uarn);
 int mlx5_cmd_free_uar(struct mlx5_core_dev *dev, u32 uarn);
 int mlx5_alloc_uuars(struct mlx5_core_dev *dev, struct mlx5_uuar_info *uuari);

Modified: stable/11/sys/dev/mlx5/mlx5_core/mlx5_cmd.c
==============================================================================
--- stable/11/sys/dev/mlx5/mlx5_core/mlx5_cmd.c	Fri Mar 30 19:17:09 2018	(r331809)
+++ stable/11/sys/dev/mlx5/mlx5_core/mlx5_cmd.c	Fri Mar 30 19:18:33 2018	(r331810)
@@ -859,6 +859,7 @@ static void cmd_work_handler(struct work_struct *work)
         unsigned long cb_timeout = msecs_to_jiffies(MLX5_CMD_TIMEOUT_MSEC);
 	struct mlx5_cmd_layout *lay;
 	struct semaphore *sem;
+	bool poll_cmd = ent->polling;
 
 	sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem;
 	down(sem);
@@ -897,7 +898,7 @@ static void cmd_work_handler(struct work_struct *work)
 	iowrite32be(1 << ent->idx, &dev->iseg->cmd_dbell);
 	mmiowb();
 	/* if not in polling don't use ent after this point*/
-	if (cmd->mode == CMD_MODE_POLLING) {
+	if (cmd->mode == CMD_MODE_POLLING || poll_cmd) {
 		poll_timeout(ent);
 		/* make sure we read the descriptor after ownership is SW */
 		mlx5_cmd_comp_handler(dev, 1U << ent->idx);
@@ -940,7 +941,7 @@ static int wait_func(struct mlx5_core_dev *dev, struct
 	struct mlx5_cmd *cmd = &dev->cmd;
 	int err;
 
-	if (cmd->mode == CMD_MODE_POLLING) {
+	if (cmd->mode == CMD_MODE_POLLING || ent->polling) {
 		wait_for_completion(&ent->done);
 		err = ent->ret;
 	} else if (!wait_for_completion_timeout(&ent->done, timeout)) {
@@ -969,7 +970,8 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, 
 			   int uin_size,
 			   struct mlx5_cmd_msg *out, void *uout, int uout_size,
 			   mlx5_cmd_cbk_t callback,
-			   void *context, int page_queue, u8 *status)
+			   void *context, int page_queue, u8 *status,
+			   bool force_polling)
 {
 	struct mlx5_cmd *cmd = &dev->cmd;
 	struct mlx5_cmd_work_ent *ent;
@@ -986,6 +988,8 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, 
 	if (IS_ERR(ent))
 		return PTR_ERR(ent);
 
+	ent->polling = force_polling;
+
 	if (!callback)
 		init_completion(&ent->done);
 
@@ -1260,7 +1264,8 @@ static int is_manage_pages(void *in)
 static int cmd_exec_helper(struct mlx5_core_dev *dev,
 			   void *in, int in_size,
 			   void *out, int out_size,
-			   mlx5_cmd_cbk_t callback, void *context)
+			   mlx5_cmd_cbk_t callback, void *context,
+			   bool force_polling)
 {
 	struct mlx5_cmd_msg *inb;
 	struct mlx5_cmd_msg *outb;
@@ -1300,7 +1305,7 @@ static int cmd_exec_helper(struct mlx5_core_dev *dev,
 	}
 
 	err = mlx5_cmd_invoke(dev, inb, in_size, outb, out, out_size, callback,
-			      context, pages_queue, &status);
+			      context, pages_queue, &status, force_polling);
 	if (err) {
 		if (err == -ETIMEDOUT)
 			return err;
@@ -1331,7 +1336,7 @@ int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in,
 {
 	int err;
 
-	err = cmd_exec_helper(dev, in, in_size, out, out_size, NULL, NULL);
+	err = cmd_exec_helper(dev, in, in_size, out, out_size, NULL, NULL, false);
 	return err ? : mlx5_cmd_check(dev, in, out);
 }
 EXPORT_SYMBOL(mlx5_cmd_exec);
@@ -1340,9 +1345,19 @@ int mlx5_cmd_exec_cb(struct mlx5_core_dev *dev, void *
 		     void *out, int out_size, mlx5_cmd_cbk_t callback,
 		     void *context)
 {
-	return cmd_exec_helper(dev, in, in_size, out, out_size, callback, context);
+	return cmd_exec_helper(dev, in, in_size, out, out_size, callback, context, false);
 }
 EXPORT_SYMBOL(mlx5_cmd_exec_cb);
+
+int mlx5_cmd_exec_polling(struct mlx5_core_dev *dev, void *in, int in_size,
+			  void *out, int out_size)
+{
+	int err;
+
+	err = cmd_exec_helper(dev, in, in_size, out, out_size, NULL, NULL, true);
+	return err ? : mlx5_cmd_check(dev, in, out);
+}
+EXPORT_SYMBOL(mlx5_cmd_exec_polling);
 
 static void destroy_msg_cache(struct mlx5_core_dev *dev)
 {

Modified: stable/11/sys/dev/mlx5/mlx5_core/mlx5_core.h
==============================================================================
--- stable/11/sys/dev/mlx5/mlx5_core/mlx5_core.h	Fri Mar 30 19:17:09 2018	(r331809)
+++ stable/11/sys/dev/mlx5/mlx5_core/mlx5_core.h	Fri Mar 30 19:18:33 2018	(r331810)
@@ -70,9 +70,10 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev);
 int mlx5_query_board_id(struct mlx5_core_dev *dev);
 int mlx5_cmd_init_hca(struct mlx5_core_dev *dev);
 int mlx5_cmd_teardown_hca(struct mlx5_core_dev *dev);
+int mlx5_cmd_force_teardown_hca(struct mlx5_core_dev *dev);
 void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
 		     unsigned long param);
-void mlx5_enter_error_state(struct mlx5_core_dev *dev);
+void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force);
 void mlx5_disable_device(struct mlx5_core_dev *dev);
 void mlx5_recover_device(struct mlx5_core_dev *dev);
 

Modified: stable/11/sys/dev/mlx5/mlx5_core/mlx5_fw.c
==============================================================================
--- stable/11/sys/dev/mlx5/mlx5_core/mlx5_fw.c	Fri Mar 30 19:17:09 2018	(r331809)
+++ stable/11/sys/dev/mlx5/mlx5_core/mlx5_fw.c	Fri Mar 30 19:18:33 2018	(r331810)
@@ -218,6 +218,34 @@ int mlx5_cmd_teardown_hca(struct mlx5_core_dev *dev)
 	return mlx5_cmd_exec(dev, in,  sizeof(in), out, sizeof(out));
 }
 
+int mlx5_cmd_force_teardown_hca(struct mlx5_core_dev *dev)
+{
+	u32 out[MLX5_ST_SZ_DW(teardown_hca_out)] = {0};
+	u32 in[MLX5_ST_SZ_DW(teardown_hca_in)] = {0};
+	int force_state;
+	int ret;
+
+	if (!MLX5_CAP_GEN(dev, force_teardown)) {
+		mlx5_core_dbg(dev, "force teardown is not supported in the firmware\n");
+		return -EOPNOTSUPP;
+	}
+
+	MLX5_SET(teardown_hca_in, in, opcode, MLX5_CMD_OP_TEARDOWN_HCA);
+	MLX5_SET(teardown_hca_in, in, profile, MLX5_TEARDOWN_HCA_IN_PROFILE_FORCE_CLOSE);
+
+	ret = mlx5_cmd_exec_polling(dev, in, sizeof(in), out, sizeof(out));
+	if (ret)
+		return ret;
+
+	force_state = MLX5_GET(teardown_hca_out, out, force_state);
+	if (force_state == MLX5_TEARDOWN_HCA_OUT_FORCE_STATE_FAIL)  {
+		mlx5_core_err(dev, "teardown with force mode failed\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
 int mlx5_core_set_dc_cnak_trace(struct mlx5_core_dev *dev, int enable,
 				u64 addr)
 {

Modified: stable/11/sys/dev/mlx5/mlx5_core/mlx5_health.c
==============================================================================
--- stable/11/sys/dev/mlx5/mlx5_core/mlx5_health.c	Fri Mar 30 19:17:09 2018	(r331809)
+++ stable/11/sys/dev/mlx5/mlx5_core/mlx5_health.c	Fri Mar 30 19:18:33 2018	(r331810)
@@ -90,7 +90,7 @@ static int in_fatal(struct mlx5_core_dev *dev)
 	return 0;
 }
 
-void mlx5_enter_error_state(struct mlx5_core_dev *dev)
+void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force)
 {
 	mutex_lock(&dev->intf_state_mutex);
 	if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
@@ -99,7 +99,7 @@ void mlx5_enter_error_state(struct mlx5_core_dev *dev)
 	}
 
 	mlx5_core_err(dev, "start\n");
-	if (pci_channel_offline(dev->pdev) || in_fatal(dev)) {
+	if (pci_channel_offline(dev->pdev) || in_fatal(dev) || force) {
 		dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
 		mlx5_trigger_cmd_completions(dev);
 	}

Modified: stable/11/sys/dev/mlx5/mlx5_core/mlx5_main.c
==============================================================================
--- stable/11/sys/dev/mlx5/mlx5_core/mlx5_main.c	Fri Mar 30 19:17:09 2018	(r331809)
+++ stable/11/sys/dev/mlx5/mlx5_core/mlx5_main.c	Fri Mar 30 19:18:33 2018	(r331810)
@@ -868,11 +868,65 @@ static void mlx5_pci_close(struct mlx5_core_dev *dev, 
 	mlx5_pci_disable_device(dev);
 }
 
-static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
+static int mlx5_init_once(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
 {
 	struct pci_dev *pdev = dev->pdev;
 	int err;
 
+	err = mlx5_query_hca_caps(dev);
+	if (err) {
+		dev_err(&pdev->dev, "query hca failed\n");
+		goto out;
+	}
+
+	err = mlx5_query_board_id(dev);
+	if (err) {
+		dev_err(&pdev->dev, "query board id failed\n");
+		goto out;
+	}
+
+	err = mlx5_eq_init(dev);
+	if (err) {
+		dev_err(&pdev->dev, "failed to initialize eq\n");
+		goto out;
+	}
+
+	MLX5_INIT_DOORBELL_LOCK(&priv->cq_uar_lock);
+
+	err = mlx5_init_cq_table(dev);
+	if (err) {
+		dev_err(&pdev->dev, "failed to initialize cq table\n");
+		goto err_eq_cleanup;
+	}
+
+	mlx5_init_qp_table(dev);
+	mlx5_init_srq_table(dev);
+	mlx5_init_mr_table(dev);
+
+	return 0;
+
+err_eq_cleanup:
+	mlx5_eq_cleanup(dev);
+
+out:
+	return err;
+}
+
+static void mlx5_cleanup_once(struct mlx5_core_dev *dev)
+{
+	mlx5_cleanup_mr_table(dev);
+	mlx5_cleanup_srq_table(dev);
+	mlx5_cleanup_qp_table(dev);
+	mlx5_cleanup_cq_table(dev);
+	mlx5_eq_cleanup(dev);
+}
+
+static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
+			 bool boot)
+{
+	struct pci_dev *pdev = dev->pdev;
+	int err;
+
 	mutex_lock(&dev->intf_state_mutex);
 	if (test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
 		dev_warn(&dev->pdev->dev, "%s: interface is up, NOP\n",
@@ -900,12 +954,10 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, st
 		goto err_cmd_cleanup;
 	}
 
-	mlx5_pagealloc_init(dev);
-
 	err = mlx5_core_enable_hca(dev);
 	if (err) {
 		device_printf((&pdev->dev)->bsddev, "ERR: ""enable hca failed\n");
-		goto err_pagealloc_cleanup;
+		goto err_cmd_cleanup;
 	}
 
 	err = mlx5_core_set_issi(dev);
@@ -958,34 +1010,21 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, st
 
 	mlx5_start_health_poll(dev);
 
-	err = mlx5_query_hca_caps(dev);
-	if (err) {
-		device_printf((&pdev->dev)->bsddev, "ERR: ""query hca failed\n");
+	if (boot && mlx5_init_once(dev, priv)) {
+		dev_err(&pdev->dev, "sw objs init failed\n");
 		goto err_stop_poll;
 	}
 
-	err = mlx5_query_board_id(dev);
-	if (err) {
-		device_printf((&pdev->dev)->bsddev, "ERR: ""query board id failed\n");
-		goto err_stop_poll;
-	}
-
 	err = mlx5_enable_msix(dev);
 	if (err) {
 		device_printf((&pdev->dev)->bsddev, "ERR: ""enable msix failed\n");
-		goto err_stop_poll;
+		goto err_cleanup_once;
 	}
 
-	err = mlx5_eq_init(dev);
-	if (err) {
-		device_printf((&pdev->dev)->bsddev, "ERR: ""failed to initialize eq\n");
-		goto disable_msix;
-	}
-
 	err = mlx5_alloc_uuars(dev, &priv->uuari);
 	if (err) {
 		device_printf((&pdev->dev)->bsddev, "ERR: ""Failed allocating uar, aborting\n");
-		goto err_eq_cleanup;
+		goto err_disable_msix;
 	}
 
 	err = mlx5_start_eqs(dev);
@@ -1003,23 +1042,16 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, st
 	if (map_bf_area(dev))
 		device_printf((&pdev->dev)->bsddev, "ERR: ""Failed to map blue flame area\n");
 
-	MLX5_INIT_DOORBELL_LOCK(&priv->cq_uar_lock);
-
-	mlx5_init_cq_table(dev);
-	mlx5_init_qp_table(dev);
-	mlx5_init_srq_table(dev);
-	mlx5_init_mr_table(dev);
-
 	err = mlx5_init_fs(dev);
 	if (err) {
 		mlx5_core_err(dev, "flow steering init %d\n", err);
-		goto err_init_tables;
+		goto err_free_comp_eqs;
 	}
 
 	err = mlx5_register_device(dev);
 	if (err) {
 		dev_err(&pdev->dev, "mlx5_register_device failed %d\n", err);
-		goto err_reg_dev;
+		goto err_fs;
 	}
 
 	mlx5_fwdump_prep(dev);
@@ -1031,13 +1063,11 @@ out:
 	mutex_unlock(&dev->intf_state_mutex);
 	return 0;
 
-err_reg_dev:
+err_fs:
 	mlx5_cleanup_fs(dev);
-err_init_tables:
-	mlx5_cleanup_mr_table(dev);
-	mlx5_cleanup_srq_table(dev);
-	mlx5_cleanup_qp_table(dev);
-	mlx5_cleanup_cq_table(dev);
+
+err_free_comp_eqs:
+	free_comp_eqs(dev);
 	unmap_bf_area(dev);
 
 err_stop_eqs:
@@ -1046,12 +1076,13 @@ err_stop_eqs:
 err_free_uar:
 	mlx5_free_uuars(dev, &priv->uuari);
 
-err_eq_cleanup:
-	mlx5_eq_cleanup(dev);
-
-disable_msix:
+err_disable_msix:
 	mlx5_disable_msix(dev);
 
+err_cleanup_once:
+	if (boot)
+		mlx5_cleanup_once(dev);
+
 err_stop_poll:
 	mlx5_stop_health_poll(dev);
 	if (mlx5_cmd_teardown_hca(dev)) {
@@ -1068,9 +1099,6 @@ err_pagealloc_stop:
 err_disable_hca:
 	mlx5_core_disable_hca(dev);
 
-err_pagealloc_cleanup:
-	mlx5_pagealloc_cleanup(dev);
-
 err_cmd_cleanup:
 	mlx5_cmd_cleanup(dev);
 
@@ -1081,13 +1109,16 @@ out_err:
 	return err;
 }
 
-static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv)
+static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
+			   bool cleanup)
 {
 	int err = 0;
 
 	mutex_lock(&dev->intf_state_mutex);
 	if (test_bit(MLX5_INTERFACE_STATE_DOWN, &dev->intf_state)) {
 		dev_warn(&dev->pdev->dev, "%s: interface is down, NOP\n", __func__);
+                if (cleanup)
+                        mlx5_cleanup_once(dev);
 		goto out;
 	}
 
@@ -1095,17 +1126,14 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, 
 	mlx5_unregister_device(dev);
 
 	mlx5_cleanup_fs(dev);
-	mlx5_cleanup_mr_table(dev);
-	mlx5_cleanup_srq_table(dev);
-	mlx5_cleanup_qp_table(dev);
-	mlx5_cleanup_cq_table(dev);
 	unmap_bf_area(dev);
 	mlx5_wait_for_reclaim_vfs_pages(dev);
 	free_comp_eqs(dev);
 	mlx5_stop_eqs(dev);
 	mlx5_free_uuars(dev, &priv->uuari);
-	mlx5_eq_cleanup(dev);
 	mlx5_disable_msix(dev);
+        if (cleanup)
+                mlx5_cleanup_once(dev);
 	mlx5_stop_health_poll(dev);
 	err = mlx5_cmd_teardown_hca(dev);
 	if (err) {
@@ -1115,7 +1143,6 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, 
 	mlx5_pagealloc_stop(dev);
 	mlx5_reclaim_startup_pages(dev);
 	mlx5_core_disable_hca(dev);
-	mlx5_pagealloc_cleanup(dev);
 	mlx5_cmd_cleanup(dev);
 
 out:
@@ -1184,7 +1211,9 @@ static int init_one(struct pci_dev *pdev,
                 goto close_pci;
         }
 
-	err = mlx5_load_one(dev, priv);
+	mlx5_pagealloc_init(dev);
+
+	err = mlx5_load_one(dev, priv, true);
 	if (err) {
 		device_printf((&pdev->dev)->bsddev, "ERR: ""mlx5_register_device failed %d\n", err);
 		goto clean_health;
@@ -1193,6 +1222,7 @@ static int init_one(struct pci_dev *pdev,
 	return 0;
 
 clean_health:
+	mlx5_pagealloc_cleanup(dev);
         mlx5_health_cleanup(dev);
 close_pci:
         mlx5_pci_close(dev, priv);
@@ -1206,12 +1236,13 @@ static void remove_one(struct pci_dev *pdev)
 	struct mlx5_core_dev *dev  = pci_get_drvdata(pdev);
 	struct mlx5_priv *priv = &dev->priv;
 
-	if (mlx5_unload_one(dev, priv)) {
+	if (mlx5_unload_one(dev, priv, true)) {
 		dev_err(&dev->pdev->dev, "mlx5_unload_one failed\n");
 		mlx5_health_cleanup(dev);
 		return;
 	}
 
+	mlx5_pagealloc_cleanup(dev);
 	mlx5_health_cleanup(dev);
 	mlx5_pci_close(dev, priv);
 	pci_set_drvdata(pdev, NULL);
@@ -1225,8 +1256,8 @@ static pci_ers_result_t mlx5_pci_err_detected(struct p
 	struct mlx5_priv *priv = &dev->priv;
 
 	dev_info(&pdev->dev, "%s was called\n", __func__);
-	mlx5_enter_error_state(dev);
-	mlx5_unload_one(dev, priv);
+	mlx5_enter_error_state(dev, false);
+	mlx5_unload_one(dev, priv, false);
 	if (state) {
 		pci_save_state(pdev->dev.bsddev);
 		mlx5_drain_health_wq(dev);
@@ -1310,7 +1341,7 @@ static void mlx5_pci_resume(struct pci_dev *pdev)
 	pci_save_state(pdev->dev.bsddev);
 	wait_vital(pdev);
 
-	err = mlx5_load_one(dev, priv);
+	err = mlx5_load_one(dev, priv, false);
 	if (err)
 		dev_err(&pdev->dev, "%s: mlx5_load_one failed with error code: %d\n"
 			, __func__, err);
@@ -1324,13 +1355,41 @@ static const struct pci_error_handlers mlx5_err_handle
 	.resume		= mlx5_pci_resume
 };
 
+static int mlx5_try_fast_unload(struct mlx5_core_dev *dev)
+{
+	int err;
+
+	if (!MLX5_CAP_GEN(dev, force_teardown)) {
+		mlx5_core_dbg(dev, "force teardown is not supported in the firmware\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (dev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+		mlx5_core_dbg(dev, "Device in internal error state, giving up\n");
+		return -EAGAIN;
+	}
+
+	err = mlx5_cmd_force_teardown_hca(dev);
+	if (err) {
+		mlx5_core_dbg(dev, "Firmware couldn't do fast unload error: %d\n", err);
+		return err;
+	}
+
+	mlx5_enter_error_state(dev, true);
+
+	return 0;
+}
+
 static void shutdown_one(struct pci_dev *pdev)
 {
 	struct mlx5_core_dev *dev  = pci_get_drvdata(pdev);
 	struct mlx5_priv *priv = &dev->priv;
+	int err;
 
 	set_bit(MLX5_INTERFACE_STATE_SHUTDOWN, &dev->intf_state);
-	mlx5_unload_one(dev, priv);
+	err = mlx5_try_fast_unload(dev);
+	if (err)
+	        mlx5_unload_one(dev, priv, false);
 	mlx5_pci_disable_device(dev);
 }
 

Modified: stable/11/sys/dev/mlx5/mlx5_ifc.h
==============================================================================
--- stable/11/sys/dev/mlx5/mlx5_ifc.h	Fri Mar 30 19:17:09 2018	(r331809)
+++ stable/11/sys/dev/mlx5/mlx5_ifc.h	Fri Mar 30 19:18:33 2018	(r331810)
@@ -941,7 +941,8 @@ struct mlx5_ifc_cmd_hca_cap_bits {
 	u8         max_indirection[0x8];
 	u8         reserved_8[0x1];
 	u8         log_max_mrw_sz[0x7];
-	u8         reserved_9[0x2];
+	u8	   force_teardown[0x1];
+	u8         reserved_9[0x1];
 	u8         log_max_bsf_list_size[0x6];
 	u8         reserved_10[0x2];
 	u8         log_max_klm_list_size[0x6];
@@ -3149,18 +3150,25 @@ struct mlx5_ifc_icmd_access_reg_in_bits {
 	u8         register_data[0][0x20];
 };
 
+enum {
+	MLX5_TEARDOWN_HCA_OUT_FORCE_STATE_SUCCESS = 0x0,
+	MLX5_TEARDOWN_HCA_OUT_FORCE_STATE_FAIL = 0x1,
+};
+
 struct mlx5_ifc_teardown_hca_out_bits {
 	u8         status[0x8];
 	u8         reserved_0[0x18];
 
 	u8         syndrome[0x20];
 
-	u8         reserved_1[0x40];
+	u8         reserved_1[0x3f];
+
+	u8	   force_state[0x1];
 };
 
 enum {
 	MLX5_TEARDOWN_HCA_IN_PROFILE_GRACEFUL_CLOSE  = 0x0,
-	MLX5_TEARDOWN_HCA_IN_PROFILE_PANIC_CLOSE     = 0x1,
+	MLX5_TEARDOWN_HCA_IN_PROFILE_FORCE_CLOSE     = 0x1,
 };
 
 struct mlx5_ifc_teardown_hca_in_bits {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803301918.w2UJIXJ9099530>