Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

driver core: add deferring probe reason to devices_deferred property

/sys/kernel/debug/devices_deferred property contains list of deferred devices.
This list does not contain reason why the driver deferred probe, the patch
improves it.
The natural place to set the reason is dev_err_probe function introduced
recently, ie. if dev_err_probe will be called with -EPROBE_DEFER instead of
printk the message will be attached to a deferred device and printed when user
reads devices_deferred property.

Signed-off-by: Andrzej Hajda <a.hajda@samsung.com>
Reviewed-by: Mark Brown <broonie@kernel.org>
Reviewed-by: Javier Martinez Canillas <javierm@redhat.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Reviewed-by: Rafael J. Wysocki <rafael@kernel.org>
Link: https://lore.kernel.org/r/20200713144324.23654-3-a.hajda@samsung.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Andrzej Hajda and committed by
Greg Kroah-Hartman
d090b70e a787e540

+31 -3
+3
drivers/base/base.h
··· 93 93 struct klist_node knode_class; 94 94 struct list_head deferred_probe; 95 95 struct device_driver *async_driver; 96 + char *deferred_probe_reason; 96 97 struct device *device; 97 98 u8 dead:1; 98 99 }; ··· 135 134 extern void driver_detach(struct device_driver *drv); 136 135 extern int driver_probe_device(struct device_driver *drv, struct device *dev); 137 136 extern void driver_deferred_probe_del(struct device *dev); 137 + extern void device_set_deferred_probe_reason(const struct device *dev, 138 + struct va_format *vaf); 138 139 static inline int driver_match_device(struct device_driver *drv, 139 140 struct device *dev) 140 141 {
+6 -2
drivers/base/core.c
··· 4213 4213 * This helper implements common pattern present in probe functions for error 4214 4214 * checking: print debug or error message depending if the error value is 4215 4215 * -EPROBE_DEFER and propagate error upwards. 4216 + * In case of -EPROBE_DEFER it sets also defer probe reason, which can be 4217 + * checked later by reading devices_deferred debugfs attribute. 4216 4218 * It replaces code sequence: 4217 4219 * if (err != -EPROBE_DEFER) 4218 4220 * dev_err(dev, ...); ··· 4236 4234 vaf.fmt = fmt; 4237 4235 vaf.va = &args; 4238 4236 4239 - if (err != -EPROBE_DEFER) 4237 + if (err != -EPROBE_DEFER) { 4240 4238 dev_err(dev, "error %d: %pV", err, &vaf); 4241 - else 4239 + } else { 4240 + device_set_deferred_probe_reason(dev, &vaf); 4242 4241 dev_dbg(dev, "error %d: %pV", err, &vaf); 4242 + } 4243 4243 4244 4244 va_end(args); 4245 4245
+22 -1
drivers/base/dd.c
··· 27 27 #include <linux/async.h> 28 28 #include <linux/pm_runtime.h> 29 29 #include <linux/pinctrl/devinfo.h> 30 + #include <linux/slab.h> 30 31 31 32 #include "base.h" 32 33 #include "power/power.h" ··· 137 136 if (!list_empty(&dev->p->deferred_probe)) { 138 137 dev_dbg(dev, "Removed from deferred list\n"); 139 138 list_del_init(&dev->p->deferred_probe); 139 + kfree(dev->p->deferred_probe_reason); 140 + dev->p->deferred_probe_reason = NULL; 140 141 } 141 142 mutex_unlock(&deferred_probe_mutex); 142 143 } ··· 209 206 driver_deferred_probe_trigger(); 210 207 } 211 208 209 + /** 210 + * device_set_deferred_probe_reason() - Set defer probe reason message for device 211 + * @dev: the pointer to the struct device 212 + * @vaf: the pointer to va_format structure with message 213 + */ 214 + void device_set_deferred_probe_reason(const struct device *dev, struct va_format *vaf) 215 + { 216 + const char *drv = dev_driver_string(dev); 217 + 218 + mutex_lock(&deferred_probe_mutex); 219 + 220 + kfree(dev->p->deferred_probe_reason); 221 + dev->p->deferred_probe_reason = kasprintf(GFP_KERNEL, "%s: %pV", drv, vaf); 222 + 223 + mutex_unlock(&deferred_probe_mutex); 224 + } 225 + 212 226 /* 213 227 * deferred_devs_show() - Show the devices in the deferred probe pending list. 214 228 */ ··· 236 216 mutex_lock(&deferred_probe_mutex); 237 217 238 218 list_for_each_entry(curr, &deferred_probe_pending_list, deferred_probe) 239 - seq_printf(s, "%s\n", dev_name(curr->device)); 219 + seq_printf(s, "%s\t%s", dev_name(curr->device), 220 + curr->device->p->deferred_probe_reason ?: "\n"); 240 221 241 222 mutex_unlock(&deferred_probe_mutex); 242 223