Skip to content

Commit eaa59db

Browse files
committed
Add dev_warn_probe() and improve error handling in
Merge series from Dragan Simic <[email protected]>: This is a small series that introduces dev_warn_probe() function, which produces warnings on failed resource acquisitions, and improves error handling in the probe paths of Rockchip SPI drivers, by using functions dev_err_probe() and dev_warn_probe() properly in multiple places. This series also performs a bunch of small, rather trivial code cleanups, to make the code neater and a bit easier to read.
2 parents b125810 + e2fc058 commit eaa59db

File tree

3 files changed

+115
-43
lines changed

3 files changed

+115
-43
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
{

drivers/spi/spi-rockchip.c

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -773,15 +773,15 @@ static int rockchip_spi_probe(struct platform_device *pdev)
773773

774774
rs->apb_pclk = devm_clk_get_enabled(&pdev->dev, "apb_pclk");
775775
if (IS_ERR(rs->apb_pclk)) {
776-
dev_err(&pdev->dev, "Failed to get apb_pclk\n");
777-
ret = PTR_ERR(rs->apb_pclk);
776+
ret = dev_err_probe(&pdev->dev, PTR_ERR(rs->apb_pclk),
777+
"Failed to get apb_pclk\n");
778778
goto err_put_ctlr;
779779
}
780780

781781
rs->spiclk = devm_clk_get_enabled(&pdev->dev, "spiclk");
782782
if (IS_ERR(rs->spiclk)) {
783-
dev_err(&pdev->dev, "Failed to get spi_pclk\n");
784-
ret = PTR_ERR(rs->spiclk);
783+
ret = dev_err_probe(&pdev->dev, PTR_ERR(rs->spiclk),
784+
"Failed to get spi_pclk\n");
785785
goto err_put_ctlr;
786786
}
787787

@@ -817,8 +817,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
817817

818818
rs->fifo_len = get_fifo_len(rs);
819819
if (!rs->fifo_len) {
820-
dev_err(&pdev->dev, "Failed to get fifo length\n");
821-
ret = -EINVAL;
820+
ret = dev_err_probe(&pdev->dev, -EINVAL, "Failed to get fifo length\n");
822821
goto err_put_ctlr;
823822
}
824823

@@ -858,22 +857,21 @@ static int rockchip_spi_probe(struct platform_device *pdev)
858857

859858
ctlr->dma_tx = dma_request_chan(rs->dev, "tx");
860859
if (IS_ERR(ctlr->dma_tx)) {
861-
/* Check tx to see if we need defer probing driver */
862-
if (PTR_ERR(ctlr->dma_tx) == -EPROBE_DEFER) {
863-
ret = -EPROBE_DEFER;
860+
/* Check tx to see if we need to defer driver probing */
861+
ret = dev_warn_probe(rs->dev, PTR_ERR(ctlr->dma_tx),
862+
"Failed to request optional TX DMA channel\n");
863+
if (ret == -EPROBE_DEFER)
864864
goto err_disable_pm_runtime;
865-
}
866-
dev_warn(rs->dev, "Failed to request TX DMA channel\n");
867865
ctlr->dma_tx = NULL;
868866
}
869867

870868
ctlr->dma_rx = dma_request_chan(rs->dev, "rx");
871869
if (IS_ERR(ctlr->dma_rx)) {
872-
if (PTR_ERR(ctlr->dma_rx) == -EPROBE_DEFER) {
873-
ret = -EPROBE_DEFER;
870+
/* Check rx to see if we need to defer driver probing */
871+
ret = dev_warn_probe(rs->dev, PTR_ERR(ctlr->dma_rx),
872+
"Failed to request optional RX DMA channel\n");
873+
if (ret == -EPROBE_DEFER)
874874
goto err_free_dma_tx;
875-
}
876-
dev_warn(rs->dev, "Failed to request RX DMA channel\n");
877875
ctlr->dma_rx = NULL;
878876
}
879877

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)