svn commit: r338237 - head/sbin/devmatch

Warner Losh imp at FreeBSD.org
Thu Aug 23 05:06:24 UTC 2018


Author: imp
Date: Thu Aug 23 05:06:22 2018
New Revision: 338237
URL: https://svnweb.freebsd.org/changeset/base/338237

Log:
  When trying to match the nomatch event passed to us, attempt to look
  up the device described by the nomatch event in the device tree. If we
  find it, then if the device is marked as have already attached to a
  device once, then ignore the device.
  
  This keeps us from reloading the device driver when it has just been
  manually unloaded. All devies that have had a driver attach to them at
  least once no longer participate in pnp-based autoloading.
  
  Differential Revision: https://reviews.freebsd.org/D16735

Modified:
  head/sbin/devmatch/devmatch.c

Modified: head/sbin/devmatch/devmatch.c
==============================================================================
--- head/sbin/devmatch/devmatch.c	Thu Aug 23 05:06:16 2018	(r338236)
+++ head/sbin/devmatch/devmatch.c	Thu Aug 23 05:06:22 2018	(r338237)
@@ -65,6 +65,7 @@ static int verbose_flag;
 
 static void *hints;
 static void *hints_end;
+static struct devinfo_dev *root;
 
 static void *
 read_hints(const char *fn, size_t *len)
@@ -440,10 +441,50 @@ find_unmatched(struct devinfo_dev *dev, void *arg)
 	return (devinfo_foreach_device_child(dev, find_unmatched, arg));
 }
 
+struct exact_info
+{
+	const char *bus;
+	const char *loc;
+	struct devinfo_dev *dev;
+};
+
+/*
+ * Look for the exact location specified by the nomatch event.  The
+ * loc and pnpinfo run together to get the string we're looking for,
+ * so we have to synthesize the same thing that subr_bus.c is
+ * generating in devnomatch/devaddq to do the string comparison.
+ */
+static int
+find_exact_dev(struct devinfo_dev *dev, void *arg)
+{
+	struct devinfo_dev *parent;
+	char *loc;
+	struct exact_info *info;
+
+	info = arg;
+	do {
+		if (info->dev != NULL)
+			break;
+		if (!(dev->dd_flags & DF_ENABLED))
+			break;
+		parent = devinfo_handle_to_device(dev->dd_parent);
+		if (strcmp(info->bus, parent->dd_name) != 0)
+			break;
+		asprintf(&loc, "%s %s", parent->dd_pnpinfo,
+		    parent->dd_location);
+		if (strcmp(loc, info->loc) == 0)
+			info->dev = dev;
+		free(loc);
+	} while (0);
+
+	return (devinfo_foreach_device_child(dev, find_exact_dev, arg));
+}
+
 static void
 find_nomatch(char *nomatch)
 {
-	char *bus, *pnpinfo, *tmp;
+	char *bus, *pnpinfo, *tmp, *busnameunit;
+	struct exact_info info;
 
 	/*
 	 * Find our bus name. It will include the unit number. We have to search
@@ -459,6 +500,9 @@ find_nomatch(char *nomatch)
 		errx(1, "No bus found in nomatch string: '%s'", nomatch);
 	bus = tmp + 4;
 	*tmp = '\0';
+	busnameunit = strdup(bus);
+	if (busnameunit == NULL)
+		errx(1, "Can't allocate memory for strings");
 	tmp = bus + strlen(bus) - 1;
 	while (tmp > bus && isdigit(*tmp))
 		tmp--;
@@ -475,6 +519,17 @@ find_nomatch(char *nomatch)
 		errx(1, "Malformed NOMATCH string: '%s'", nomatch);
 	pnpinfo = nomatch + 4;
 
+	/*
+	 * See if we can find the devinfo_dev for this device. If we
+	 * can, and it's been attached before, we should filter it out
+	 * so that a kldunload foo doesn't cause an immediate reload.
+	 */
+	info.loc = pnpinfo;
+	info.bus = busnameunit;
+	info.dev = NULL;
+	devinfo_foreach_device_child(root, find_exact_dev, (void *)&info);
+	if (info.dev != NULL && info.dev->dd_flags & DF_ATTACHED_ONCE)
+		exit(0);
 	search_hints(bus, "", pnpinfo);
 
 	exit(0);
@@ -490,7 +545,6 @@ usage(void)
 int
 main(int argc, char **argv)
 {
-	struct devinfo_dev *root;
 	int ch;
 
 	while ((ch = getopt_long(argc, argv, "adh:p:uv",
@@ -530,12 +584,13 @@ main(int argc, char **argv)
 		exit(0);
 	}
 
-	if (nomatch_str != NULL)
-		find_nomatch(nomatch_str);
 	if (devinfo_init())
 		err(1, "devinfo_init");
 	if ((root = devinfo_handle_to_device(DEVINFO_ROOT_DEVICE)) == NULL)
 		errx(1, "can't find root device");
-	devinfo_foreach_device_child(root, find_unmatched, (void *)0);
+	if (nomatch_str != NULL)
+		find_nomatch(nomatch_str);
+	else
+		devinfo_foreach_device_child(root, find_unmatched, (void *)0);
 	devinfo_free();
 }


More information about the svn-src-head mailing list