Skip to content

Commit 36e69b1

Browse files
Dragan Simicbroonie
authored andcommitted
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 <[email protected]> Tested-by: Hélène Vulquin <[email protected]> Acked-by: Greg Kroah-Hartman <[email protected]> Link: https://patch.msgid.link/2be0a28538bb2a3d1bcc91e2ca1f2d0dc09146d9.1727601608.git.dsimic@manjaro.org Signed-off-by: Mark Brown <[email protected]>
1 parent 7d46b8d commit 36e69b1

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
@@ -4980,6 +4980,49 @@ define_dev_printk_level(_dev_info, KERN_INFO);
49804980

49814981
#endif
49824982

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+
49835026
/**
49845027
* dev_err_probe - probe error check and log helper
49855028
* @dev: the pointer to the struct device
@@ -4992,7 +5035,7 @@ define_dev_printk_level(_dev_info, KERN_INFO);
49925035
* -EPROBE_DEFER and propagate error upwards.
49935036
* In case of -EPROBE_DEFER it sets also defer probe reason, which can be
49945037
* checked later by reading devices_deferred debugfs attribute.
4995-
* It replaces code sequence::
5038+
* It replaces the following code sequence::
49965039
*
49975040
* if (err != -EPROBE_DEFER)
49985041
* dev_err(dev, ...);
@@ -5004,47 +5047,77 @@ define_dev_printk_level(_dev_info, KERN_INFO);
50045047
*
50055048
* return dev_err_probe(dev, err, ...);
50065049
*
5007-
* Using this helper in your probe function is totally fine even if @err is
5008-
* known to never be -EPROBE_DEFER.
5050+
* Using this helper in your probe function is totally fine even if @err
5051+
* is known to never be -EPROBE_DEFER.
50095052
* The benefit compared to a normal dev_err() is the standardized format
5010-
* of the error code, it being emitted symbolically (i.e. you get "EAGAIN"
5011-
* instead of "-35") and the fact that the error code is returned which allows
5012-
* more compact error paths.
5053+
* of the error code, which is emitted symbolically (i.e. you get "EAGAIN"
5054+
* instead of "-35"), and having the error code returned allows more
5055+
* compact error paths.
50135056
*
50145057
* Returns @err.
50155058
*/
50165059
int dev_err_probe(const struct device *dev, int err, const char *fmt, ...)
50175060
{
5018-
struct va_format vaf;
5019-
va_list args;
5061+
va_list vargs;
50205062

5021-
va_start(args, fmt);
5022-
vaf.fmt = fmt;
5023-
vaf.va = &args;
5063+
va_start(vargs, fmt);
50245064

5025-
switch (err) {
5026-
case -EPROBE_DEFER:
5027-
device_set_deferred_probe_reason(dev, &vaf);
5028-
dev_dbg(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
5029-
break;
5065+
/* Use dev_err() for logging when err doesn't equal -EPROBE_DEFER */
5066+
__dev_probe_failed(dev, err, true, fmt, vargs);
50305067

5031-
case -ENOMEM:
5032-
/*
5033-
* We don't print anything on -ENOMEM, there is already enough
5034-
* output.
5035-
*/
5036-
break;
5068+
va_end(vargs);
50375069

5038-
default:
5039-
dev_err(dev, "error %pe: %pV", ERR_PTR(err), &vaf);
5040-
break;
5041-
}
5070+
return err;
5071+
}
5072+
EXPORT_SYMBOL_GPL(dev_err_probe);
50425073

5043-
va_end(args);
5074+
/**
5075+
* dev_warn_probe - probe error check and log helper
5076+
* @dev: the pointer to the struct device
5077+
* @err: error value to test
5078+
* @fmt: printf-style format string
5079+
* @...: arguments as specified in the format string
5080+
*
5081+
* This helper implements common pattern present in probe functions for error
5082+
* checking: print debug or warning message depending if the error value is
5083+
* -EPROBE_DEFER and propagate error upwards.
5084+
* In case of -EPROBE_DEFER it sets also defer probe reason, which can be
5085+
* checked later by reading devices_deferred debugfs attribute.
5086+
* It replaces the following code sequence::
5087+
*
5088+
* if (err != -EPROBE_DEFER)
5089+
* dev_warn(dev, ...);
5090+
* else
5091+
* dev_dbg(dev, ...);
5092+
* return err;
5093+
*
5094+
* with::
5095+
*
5096+
* return dev_warn_probe(dev, err, ...);
5097+
*
5098+
* Using this helper in your probe function is totally fine even if @err
5099+
* is known to never be -EPROBE_DEFER.
5100+
* The benefit compared to a normal dev_warn() is the standardized format
5101+
* of the error code, which is emitted symbolically (i.e. you get "EAGAIN"
5102+
* instead of "-35"), and having the error code returned allows more
5103+
* compact error paths.
5104+
*
5105+
* Returns @err.
5106+
*/
5107+
int dev_warn_probe(const struct device *dev, int err, const char *fmt, ...)
5108+
{
5109+
va_list vargs;
5110+
5111+
va_start(vargs, fmt);
5112+
5113+
/* Use dev_warn() for logging when err doesn't equal -EPROBE_DEFER */
5114+
__dev_probe_failed(dev, err, false, fmt, vargs);
5115+
5116+
va_end(vargs);
50445117

50455118
return err;
50465119
}
5047-
EXPORT_SYMBOL_GPL(dev_err_probe);
5120+
EXPORT_SYMBOL_GPL(dev_warn_probe);
50485121

50495122
static inline bool fwnode_is_primary(struct fwnode_handle *fwnode)
50505123
{

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)