Skip to content

Commit e56d7f2

Browse files
committed
driver core: Add device probe log helper dev_warn_probe()
JIRA: https://issues.redhat.com/browse/RHEL-81536 commit 36e69b1 Author: Dragan Simic <dsimic@manjaro.org> Date: Tue, 08 Oct 2024 18:41:06 +0000 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> Signed-off-by: Mark Langsdorf <mlangsdo@redhat.com>
1 parent d42e82a commit e56d7f2

File tree

2 files changed

+102
-28
lines changed

2 files changed

+102
-28
lines changed

drivers/base/core.c

Lines changed: 101 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5016,6 +5016,49 @@ define_dev_printk_level(_dev_info, KERN_INFO);
50165016

50175017
#endif
50185018

5019+
static void __dev_probe_failed(const struct device *dev, int err, bool fatal,
5020+
const char *fmt, va_list vargsp)
5021+
{
5022+
struct va_format vaf;
5023+
va_list vargs;
5024+
5025+
/*
5026+
* On x86_64 and possibly on other architectures, va_list is actually a
5027+
* size-1 array containing a structure. As a result, function parameter
5028+
* vargsp decays from T[1] to T*, and &vargsp has type T** rather than
5029+
* T(*)[1], which is expected by its assignment to vaf.va below.
5030+
*
5031+
* One standard way to solve this mess is by creating a copy in a local
5032+
* variable of type va_list and then using a pointer to that local copy
5033+
* instead, which is the approach employed here.
5034+
*/
5035+
va_copy(vargs, vargsp);
5036+
5037+
vaf.fmt = fmt;
5038+
vaf.va = &vargs;
5039+
5040+
switch (err) {
5041+
case -EPROBE_DEFER:
5042+
device_set_deferred_probe_reason(dev, &vaf);
5043+
dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
5044+
break;
5045+
5046+
case -ENOMEM:
5047+
/* Don't print anything on -ENOMEM, there's already enough output */
5048+
break;
5049+
5050+
default:
5051+
/* Log fatal final failures as errors, otherwise produce warnings */
5052+
if (fatal)
5053+
dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
5054+
else
5055+
dev_warn(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
5056+
break;
5057+
}
5058+
5059+
va_end(vargs);
5060+
}
5061+
50195062
/**
50205063
* dev_err_probe - probe error check and log helper
50215064
* @dev: the pointer to the struct device
@@ -5028,7 +5071,7 @@ define_dev_printk_level(_dev_info, KERN_INFO);
50285071
* -EPROBE_DEFER and propagate error upwards.
50295072
* In case of -EPROBE_DEFER it sets also defer probe reason, which can be
50305073
* checked later by reading devices_deferred debugfs attribute.
5031-
* It replaces code sequence::
5074+
* It replaces the following code sequence::
50325075
*
50335076
* if (err != -EPROBE_DEFER)
50345077
* dev_err(dev, ...);
@@ -5040,47 +5083,77 @@ define_dev_printk_level(_dev_info, KERN_INFO);
50405083
*
50415084
* return dev_err_probe(dev, err, ...);
50425085
*
5043-
* Using this helper in your probe function is totally fine even if @err is
5044-
* known to never be -EPROBE_DEFER.
5086+
* Using this helper in your probe function is totally fine even if @err
5087+
* is known to never be -EPROBE_DEFER.
50455088
* The benefit compared to a normal dev_err() is the standardized format
5046-
* of the error code, it being emitted symbolically (i.e. you get "EAGAIN"
5047-
* instead of "-35") and the fact that the error code is returned which allows
5048-
* more compact error paths.
5089+
* of the error code, which is emitted symbolically (i.e. you get "EAGAIN"
5090+
* instead of "-35"), and having the error code returned allows more
5091+
* compact error paths.
50495092
*
50505093
* Returns @err.
50515094
*/
50525095
int dev_err_probe(const struct device *dev, int err, const char *fmt, ...)
50535096
{
5054-
struct va_format vaf;
5055-
va_list args;
5097+
va_list vargs;
50565098

5057-
va_start(args, fmt);
5058-
vaf.fmt = fmt;
5059-
vaf.va = &args;
5099+
va_start(vargs, fmt);
50605100

5061-
switch (err) {
5062-
case -EPROBE_DEFER:
5063-
device_set_deferred_probe_reason(dev, &vaf);
5064-
dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
5065-
break;
5101+
/* Use dev_err() for logging when err doesn't equal -EPROBE_DEFER */
5102+
__dev_probe_failed(dev, err, true, fmt, vargs);
50665103

5067-
case -ENOMEM:
5068-
/*
5069-
* We don't print anything on -ENOMEM, there is already enough
5070-
* output.
5071-
*/
5072-
break;
5104+
va_end(vargs);
50735105

5074-
default:
5075-
dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
5076-
break;
5077-
}
5106+
return err;
5107+
}
5108+
EXPORT_SYMBOL_GPL(dev_err_probe);
50785109

5079-
va_end(args);
5110+
/**
5111+
* dev_warn_probe - probe error check and log helper
5112+
* @dev: the pointer to the struct device
5113+
* @err: error value to test
5114+
* @fmt: printf-style format string
5115+
* @...: arguments as specified in the format string
5116+
*
5117+
* This helper implements common pattern present in probe functions for error
5118+
* checking: print debug or warning message depending if the error value is
5119+
* -EPROBE_DEFER and propagate error upwards.
5120+
* In case of -EPROBE_DEFER it sets also defer probe reason, which can be
5121+
* checked later by reading devices_deferred debugfs attribute.
5122+
* It replaces the following code sequence::
5123+
*
5124+
* if (err != -EPROBE_DEFER)
5125+
* dev_warn(dev, ...);
5126+
* else
5127+
* dev_dbg(dev, ...);
5128+
* return err;
5129+
*
5130+
* with::
5131+
*
5132+
* return dev_warn_probe(dev, err, ...);
5133+
*
5134+
* Using this helper in your probe function is totally fine even if @err
5135+
* is known to never be -EPROBE_DEFER.
5136+
* The benefit compared to a normal dev_warn() is the standardized format
5137+
* of the error code, which is emitted symbolically (i.e. you get "EAGAIN"
5138+
* instead of "-35"), and having the error code returned allows more
5139+
* compact error paths.
5140+
*
5141+
* Returns @err.
5142+
*/
5143+
int dev_warn_probe(const struct device *dev, int err, const char *fmt, ...)
5144+
{
5145+
va_list vargs;
5146+
5147+
va_start(vargs, fmt);
5148+
5149+
/* Use dev_warn() for logging when err doesn't equal -EPROBE_DEFER */
5150+
__dev_probe_failed(dev, err, false, fmt, vargs);
5151+
5152+
va_end(vargs);
50805153

50815154
return err;
50825155
}
5083-
EXPORT_SYMBOL_GPL(dev_err_probe);
5156+
EXPORT_SYMBOL_GPL(dev_warn_probe);
50845157

50855158
static inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
50865159
{

include/linux/dev_printk.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@ do { \
276276
dev_driver_string(dev), dev_name(dev), ## arg)
277277

278278
__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, ...);
279280

280281
/* Simple helper for dev_err_probe() when ERR_PTR() is to be returned. */
281282
#define dev_err_ptr_probe(dev, ___err, fmt, ...) \

0 commit comments

Comments
 (0)