summaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorRob Herring <robh@kernel.org>2016-08-11 11:20:58 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-08-31 09:13:55 -0400
commitbea5b158ff0da9c7246ff391f754f5f38e34577a (patch)
tree0e8ea972b4548c148751a5db6b7ca4f2608e3d77 /drivers/base
parentcebf8fd16900fdfd58c0028617944f808f97fe50 (diff)
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: Arnd Bergmann <arnd@arndb.de> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Rob Herring <robh@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/Kconfig10
-rw-r--r--drivers/base/dd.c21
2 files changed, 31 insertions, 0 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 98504ec99c7d..fdf44cac08e6 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -212,6 +212,16 @@ config DEBUG_DEVRES
212 212
213 If you are unsure about this, Say N here. 213 If you are unsure about this, Say N here.
214 214
215config DEBUG_TEST_DRIVER_REMOVE
216 bool "Test driver remove calls during probe"
217 depends on DEBUG_KERNEL
218 help
219 Say Y here if you want the Driver core to test driver remove functions
220 by calling probe, remove, probe. This tests the remove path without
221 having to unbind the driver or unload the driver module.
222
223 If you are unsure about this, say N here.
224
215config SYS_HYPERVISOR 225config SYS_HYPERVISOR
216 bool 226 bool
217 default n 227 default n
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 16688f50729c..4910e6db2a34 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -329,6 +329,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
329{ 329{
330 int ret = -EPROBE_DEFER; 330 int ret = -EPROBE_DEFER;
331 int local_trigger_count = atomic_read(&deferred_trigger_count); 331 int local_trigger_count = atomic_read(&deferred_trigger_count);
332 bool test_remove = IS_ENABLED(CONFIG_DEBUG_TEST_DRIVER_REMOVE);
332 333
333 if (defer_all_probes) { 334 if (defer_all_probes) {
334 /* 335 /*
@@ -346,6 +347,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
346 drv->bus->name, __func__, drv->name, dev_name(dev)); 347 drv->bus->name, __func__, drv->name, dev_name(dev));
347 WARN_ON(!list_empty(&dev->devres_head)); 348 WARN_ON(!list_empty(&dev->devres_head));
348 349
350re_probe:
349 dev->driver = drv; 351 dev->driver = drv;
350 352
351 /* If using pinctrl, bind pins now before probing */ 353 /* If using pinctrl, bind pins now before probing */
@@ -383,6 +385,25 @@ static int really_probe(struct device *dev, struct device_driver *drv)
383 goto probe_failed; 385 goto probe_failed;
384 } 386 }
385 387
388 if (test_remove) {
389 test_remove = false;
390
391 if (dev->bus && dev->bus->remove)
392 dev->bus->remove(dev);
393 else if (drv->remove)
394 drv->remove(dev);
395
396 devres_release_all(dev);
397 driver_sysfs_remove(dev);
398 dev->driver = NULL;
399 dev_set_drvdata(dev, NULL);
400 if (dev->pm_domain && dev->pm_domain->dismiss)
401 dev->pm_domain->dismiss(dev);
402 pm_runtime_reinit(dev);
403
404 goto re_probe;
405 }
406
386 pinctrl_init_done(dev); 407 pinctrl_init_done(dev);
387 408
388 if (dev->pm_domain && dev->pm_domain->sync) 409 if (dev->pm_domain && dev->pm_domain->sync)