Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bea5b158 authored by Rob Herring's avatar Rob Herring Committed by Greg Kroah-Hartman
Browse files

driver core: add test of driver remove calls during probe

In recent discussions on ksummit-discuss[1], it was suggested to do a
sequence of probe, remove, probe for testing driver remove paths. This
adds a kconfig option for said test.

[1] https://lists.linuxfoundation.org/pipermail/ksummit-discuss/2016-August/003459.html



Suggested-by: default avatarArnd Bergmann <arnd@arndb.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent cebf8fd1
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -212,6 +212,16 @@ config DEBUG_DEVRES

	  If you are unsure about this, Say N here.

config DEBUG_TEST_DRIVER_REMOVE
	bool "Test driver remove calls during probe"
	depends on DEBUG_KERNEL
	help
	  Say Y here if you want the Driver core to test driver remove functions
	  by calling probe, remove, probe. This tests the remove path without
	  having to unbind the driver or unload the driver module.

	  If you are unsure about this, say N here.

config SYS_HYPERVISOR
	bool
	default n
+21 −0
Original line number Diff line number Diff line
@@ -329,6 +329,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
{
	int ret = -EPROBE_DEFER;
	int local_trigger_count = atomic_read(&deferred_trigger_count);
	bool test_remove = IS_ENABLED(CONFIG_DEBUG_TEST_DRIVER_REMOVE);

	if (defer_all_probes) {
		/*
@@ -346,6 +347,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
		 drv->bus->name, __func__, drv->name, dev_name(dev));
	WARN_ON(!list_empty(&dev->devres_head));

re_probe:
	dev->driver = drv;

	/* If using pinctrl, bind pins now before probing */
@@ -383,6 +385,25 @@ static int really_probe(struct device *dev, struct device_driver *drv)
			goto probe_failed;
	}

	if (test_remove) {
		test_remove = false;

		if (dev->bus && dev->bus->remove)
			dev->bus->remove(dev);
		else if (drv->remove)
			drv->remove(dev);

		devres_release_all(dev);
		driver_sysfs_remove(dev);
		dev->driver = NULL;
		dev_set_drvdata(dev, NULL);
		if (dev->pm_domain && dev->pm_domain->dismiss)
			dev->pm_domain->dismiss(dev);
		pm_runtime_reinit(dev);

		goto re_probe;
	}

	pinctrl_init_done(dev);

	if (dev->pm_domain && dev->pm_domain->sync)