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

driver core: Add device probe log helper dev_warn_probe()

Some drivers can still provide their functionality to a certain extent
even when some of their resource acquisitions eventually fail. In such
cases, emitting errors isn't the desired action, but warnings should be
emitted instead.

To solve this, introduce dev_warn_probe() as a new device probe log helper,
which behaves identically as the already existing dev_err_probe(), while it
produces warnings instead of errors. The intended use is with the resources
that are actually optional for a particular driver.

While there, copyedit the kerneldoc for dev_err_probe() a bit, to simplify
its wording a bit, and reuse it as the kerneldoc for dev_warn_probe(), with
the necessary wording adjustments, of course.

Signed-off-by: Dragan Simic <dsimic@manjaro.org>
Tested-by: Hélène Vulquin <oss@helene.moe>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://patch.msgid.link/2be0a28538bb2a3d1bcc91e2ca1f2d0dc09146d9.1727601608.git.dsimic@manjaro.org
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Dragan Simic and committed by
Mark Brown
36e69b16 7d46b8d8

+103 -29
+102 -29
drivers/base/core.c
··· 4980 4980 4981 4981 #endif 4982 4982 4983 + static void __dev_probe_failed(const struct device *dev, int err, bool fatal, 4984 + const char *fmt, va_list vargsp) 4985 + { 4986 + struct va_format vaf; 4987 + va_list vargs; 4988 + 4989 + /* 4990 + * On x86_64 and possibly on other architectures, va_list is actually a 4991 + * size-1 array containing a structure. As a result, function parameter 4992 + * vargsp decays from T[1] to T*, and &vargsp has type T** rather than 4993 + * T(*)[1], which is expected by its assignment to vaf.va below. 4994 + * 4995 + * One standard way to solve this mess is by creating a copy in a local 4996 + * variable of type va_list and then using a pointer to that local copy 4997 + * instead, which is the approach employed here. 4998 + */ 4999 + va_copy(vargs, vargsp); 5000 + 5001 + vaf.fmt = fmt; 5002 + vaf.va = &vargs; 5003 + 5004 + switch (err) { 5005 + case -EPROBE_DEFER: 5006 + device_set_deferred_probe_reason(dev, &vaf); 5007 + dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf); 5008 + break; 5009 + 5010 + case -ENOMEM: 5011 + /* Don't print anything on -ENOMEM, there's already enough output */ 5012 + break; 5013 + 5014 + default: 5015 + /* Log fatal final failures as errors, otherwise produce warnings */ 5016 + if (fatal) 5017 + dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf); 5018 + else 5019 + dev_warn(dev, "error %pe: %pV", ERR_PTR(err), &vaf); 5020 + break; 5021 + } 5022 + 5023 + va_end(vargs); 5024 + } 5025 + 4983 5026 /** 4984 5027 * dev_err_probe - probe error check and log helper 4985 5028 * @dev: the pointer to the struct device ··· 5035 4992 * -EPROBE_DEFER and propagate error upwards. 5036 4993 * In case of -EPROBE_DEFER it sets also defer probe reason, which can be 5037 4994 * checked later by reading devices_deferred debugfs attribute. 5038 - * It replaces code sequence:: 4995 + * It replaces the following code sequence:: 5039 4996 * 5040 4997 * if (err != -EPROBE_DEFER) 5041 4998 * dev_err(dev, ...); ··· 5047 5004 * 5048 5005 * return dev_err_probe(dev, err, ...); 5049 5006 * 5050 - * Using this helper in your probe function is totally fine even if @err is 5051 - * known to never be -EPROBE_DEFER. 5007 + * Using this helper in your probe function is totally fine even if @err 5008 + * is known to never be -EPROBE_DEFER. 5052 5009 * The benefit compared to a normal dev_err() is the standardized format 5053 - * of the error code, it being emitted symbolically (i.e. you get "EAGAIN" 5054 - * instead of "-35") and the fact that the error code is returned which allows 5055 - * more compact error paths. 5010 + * of the error code, which is emitted symbolically (i.e. you get "EAGAIN" 5011 + * instead of "-35"), and having the error code returned allows more 5012 + * compact error paths. 5056 5013 * 5057 5014 * Returns @err. 5058 5015 */ 5059 5016 int dev_err_probe(const struct device *dev, int err, const char *fmt, ...) 5060 5017 { 5061 - struct va_format vaf; 5062 - va_list args; 5018 + va_list vargs; 5063 5019 5064 - va_start(args, fmt); 5065 - vaf.fmt = fmt; 5066 - vaf.va = &args; 5020 + va_start(vargs, fmt); 5067 5021 5068 - switch (err) { 5069 - case -EPROBE_DEFER: 5070 - device_set_deferred_probe_reason(dev, &vaf); 5071 - dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf); 5072 - break; 5022 + /* Use dev_err() for logging when err doesn't equal -EPROBE_DEFER */ 5023 + __dev_probe_failed(dev, err, true, fmt, vargs); 5073 5024 5074 - case -ENOMEM: 5075 - /* 5076 - * We don't print anything on -ENOMEM, there is already enough 5077 - * output. 5078 - */ 5079 - break; 5080 - 5081 - default: 5082 - dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf); 5083 - break; 5084 - } 5085 - 5086 - va_end(args); 5025 + va_end(vargs); 5087 5026 5088 5027 return err; 5089 5028 } 5090 5029 EXPORT_SYMBOL_GPL(dev_err_probe); 5030 + 5031 + /** 5032 + * dev_warn_probe - probe error check and log helper 5033 + * @dev: the pointer to the struct device 5034 + * @err: error value to test 5035 + * @fmt: printf-style format string 5036 + * @...: arguments as specified in the format string 5037 + * 5038 + * This helper implements common pattern present in probe functions for error 5039 + * checking: print debug or warning message depending if the error value is 5040 + * -EPROBE_DEFER and propagate error upwards. 5041 + * In case of -EPROBE_DEFER it sets also defer probe reason, which can be 5042 + * checked later by reading devices_deferred debugfs attribute. 5043 + * It replaces the following code sequence:: 5044 + * 5045 + * if (err != -EPROBE_DEFER) 5046 + * dev_warn(dev, ...); 5047 + * else 5048 + * dev_dbg(dev, ...); 5049 + * return err; 5050 + * 5051 + * with:: 5052 + * 5053 + * return dev_warn_probe(dev, err, ...); 5054 + * 5055 + * Using this helper in your probe function is totally fine even if @err 5056 + * is known to never be -EPROBE_DEFER. 5057 + * The benefit compared to a normal dev_warn() is the standardized format 5058 + * of the error code, which is emitted symbolically (i.e. you get "EAGAIN" 5059 + * instead of "-35"), and having the error code returned allows more 5060 + * compact error paths. 5061 + * 5062 + * Returns @err. 5063 + */ 5064 + int dev_warn_probe(const struct device *dev, int err, const char *fmt, ...) 5065 + { 5066 + va_list vargs; 5067 + 5068 + va_start(vargs, fmt); 5069 + 5070 + /* Use dev_warn() for logging when err doesn't equal -EPROBE_DEFER */ 5071 + __dev_probe_failed(dev, err, false, fmt, vargs); 5072 + 5073 + va_end(vargs); 5074 + 5075 + return err; 5076 + } 5077 + EXPORT_SYMBOL_GPL(dev_warn_probe); 5091 5078 5092 5079 static inline bool fwnode_is_primary(struct fwnode_handle *fwnode) 5093 5080 {
+1
include/linux/dev_printk.h
··· 276 276 dev_driver_string(dev), dev_name(dev), ## arg) 277 277 278 278 __printf(3, 4) int dev_err_probe(const struct device *dev, int err, const char *fmt, ...); 279 + __printf(3, 4) int dev_warn_probe(const struct device *dev, int err, const char *fmt, ...); 279 280 280 281 /* Simple helper for dev_err_probe() when ERR_PTR() is to be returned. */ 281 282 #define dev_err_ptr_probe(dev, ___err, fmt, ...) \