During probe every time driver gets resource it should usually check for error printk some message if it is not -EPROBE_DEFER and return the error. This pattern is simple but requires adding few lines after any resource acquisition code, as a result it is often omitted or implemented only partially. dev_err_probe helps to replace such code sequences with simple call, so code: if (err != -EPROBE_DEFER) dev_err(dev, ...); return err; becomes: return dev_err_probe(dev, err, ...);
Unified · Split
| @@ -4203,6 +4203,48 @@ define_dev_printk_level(_dev_info, KERN_INFO); · 4202 unmodified lines | |||
| 4203 | 4203 | ||
| 4204 | #endif | 4204 | #endif |
| 4205 | 4205 | ||
| 4206 | /** | ||
| 4207 | * dev_err_probe - probe error check and log helper | ||
| 4208 | * @dev: the pointer to the struct device | ||
| 4209 | * @err: error value to test | ||
| 4210 | * @fmt: printf-style format string | ||
| 4211 | * @...: arguments as specified in the format string | ||
| 4212 | * | ||
| 4213 | * This helper implements common pattern present in probe functions for error | ||
| 4214 | * checking: print debug or error message depending if the error value is | ||
| 4215 | * -EPROBE_DEFER and propagate error upwards. | ||
| 4216 | * It replaces code sequence: | ||
| 4217 | * if (err != -EPROBE_DEFER) | ||
| 4218 | * dev_err(dev, ...); | ||
| 4219 | * else | ||
| 4220 | * dev_dbg(dev, ...); | ||
| 4221 | * return err; | ||
| 4222 | * with | ||
| 4223 | * return dev_err_probe(dev, err, ...); | ||
| 4224 | * | ||
| 4225 | * Returns @err. | ||
| 4226 | * | ||
| 4227 | */ | ||
| 4228 | int dev_err_probe(const struct device *dev, int err, const char *fmt, ...) | ||
| 4229 | { | ||
| 4230 | struct va_format vaf; | ||
| 4231 | va_list args; | ||
| 4232 | |||
| 4233 | va_start(args, fmt); | ||
| 4234 | vaf.fmt = fmt; | ||
| 4235 | vaf.va = &args; | ||
| 4236 | |||
| 4237 | if (err != -EPROBE_DEFER) | ||
| 4238 | dev_err(dev, "error %d: %pV", err, &vaf); | ||
| 4239 | else | ||
| 4240 | dev_dbg(dev, "error %d: %pV", err, &vaf); | ||
| 4241 | |||
| 4242 | va_end(args); | ||
| 4243 | |||
| 4244 | return err; | ||
| 4245 | } | ||
| 4246 | EXPORT_SYMBOL_GPL(dev_err_probe); | ||
| 4247 | |||
| 4206 | static inline bool fwnode_is_primary(struct fwnode_handle *fwnode) | 4248 | static inline bool fwnode_is_primary(struct fwnode_handle *fwnode) |
| 4207 | { | 4249 | { |
| 4208 | return fwnode && !IS_ERR(fwnode->secondary); | 4250 | return fwnode && !IS_ERR(fwnode->secondary); |
| @@ -962,6 +962,9 @@ void device_link_remove(void *consumer, struct device *supplier); · 961 unmodified lines | |||
| 962 | void device_links_supplier_sync_state_pause(void); | 962 | void device_links_supplier_sync_state_pause(void); |
| 963 | void device_links_supplier_sync_state_resume(void); | 963 | void device_links_supplier_sync_state_resume(void); |
| 964 | 964 | ||
| 965 | extern __printf(3, 4) | ||
| 966 | int dev_err_probe(const struct device *dev, int err, const char *fmt, ...); | ||
| 967 | |||
| 965 | /* Create alias, so I can be autoloaded. */ | 968 | /* Create alias, so I can be autoloaded. */ |
| 966 | #define MODULE_ALIAS_CHARDEV(major,minor) \ | 969 | #define MODULE_ALIAS_CHARDEV(major,minor) \ |
| 967 | MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor)) | 970 | MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor)) |