svn commit: r337086 - stable/11/sys/ofed/drivers/infiniband/core

Hans Petter Selasky hselasky at FreeBSD.org
Thu Aug 2 08:23:55 UTC 2018


Author: hselasky
Date: Thu Aug  2 08:23:54 2018
New Revision: 337086
URL: https://svnweb.freebsd.org/changeset/base/337086

Log:
  MFC r336381:
  Fix kernel crash during fail to initialize device in ibcore.
  
  This patch fixes the kernel crash that occurs during ib_dealloc_device()
  called due to provider driver fails with an error after
  ib_alloc_device() and before it can register using ib_register_device().
  
  This crashed seen in tha lab as below which can occur with any IB device
  which fails to perform its device initialization before invoking
  ib_register_device().
  
  This patch avoids touching cache and port immutable structures if device
  is not yet initialized.
  It also releases related memory when cache and port immutable data
  structure initialization fails during register_device() state.
  
  Linux commit:
  4be3a4fa51f432ef045546d16f25c68a1ab525b9
  
  Sponsored by:		Mellanox Technologies

Modified:
  stable/11/sys/ofed/drivers/infiniband/core/ib_device.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/ofed/drivers/infiniband/core/ib_device.c
==============================================================================
--- stable/11/sys/ofed/drivers/infiniband/core/ib_device.c	Thu Aug  2 08:22:53 2018	(r337085)
+++ stable/11/sys/ofed/drivers/infiniband/core/ib_device.c	Thu Aug  2 08:23:54 2018	(r337086)
@@ -174,8 +174,16 @@ static void ib_device_release(struct device *device)
 {
 	struct ib_device *dev = container_of(device, struct ib_device, dev);
 
-	ib_cache_release_one(dev);
-	kfree(dev->port_immutable);
+	WARN_ON(dev->reg_state == IB_DEV_REGISTERED);
+	if (dev->reg_state == IB_DEV_UNREGISTERED) {
+		/*
+		 * In IB_DEV_UNINITIALIZED state, cache or port table
+		 * is not even created. Free cache and port table only when
+		 * device reaches UNREGISTERED state.
+		 */
+		ib_cache_release_one(dev);
+		kfree(dev->port_immutable);
+	}
 	kfree(dev);
 }
 
@@ -347,23 +355,21 @@ int ib_register_device(struct ib_device *device,
 	ret = ib_cache_setup_one(device);
 	if (ret) {
 		pr_warn("Couldn't set up InfiniBand P_Key/GID cache\n");
-		goto out;
+		goto port_cleanup;
 	}
 
 	memset(&device->attrs, 0, sizeof(device->attrs));
 	ret = device->query_device(device, &device->attrs, &uhw);
 	if (ret) {
 		pr_warn("Couldn't query the device attributes\n");
-		ib_cache_cleanup_one(device);
-		goto out;
+		goto cache_cleanup;
 	}
 
 	ret = ib_device_register_sysfs(device, port_callback);
 	if (ret) {
 		pr_warn("Couldn't register device %s with driver model\n",
 			device->name);
-		ib_cache_cleanup_one(device);
-		goto out;
+		goto cache_cleanup;
 	}
 
 	device->reg_state = IB_DEV_REGISTERED;
@@ -375,6 +381,14 @@ int ib_register_device(struct ib_device *device,
 	down_write(&lists_rwsem);
 	list_add_tail(&device->core_list, &device_list);
 	up_write(&lists_rwsem);
+	mutex_unlock(&device_mutex);
+	return 0;
+
+cache_cleanup:
+	ib_cache_cleanup_one(device);
+	ib_cache_release_one(device);
+port_cleanup:
+	kfree(device->port_immutable);
 out:
 	mutex_unlock(&device_mutex);
 	return ret;


More information about the svn-src-all mailing list