diff options
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r-- | drivers/base/core.c | 105 |
1 files changed, 68 insertions, 37 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 5e6e00bc165..abea76c36a4 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -184,6 +184,17 @@ static void device_release(struct kobject *kobj) struct device *dev = kobj_to_dev(kobj); struct device_private *p = dev->p; + /* + * Some platform devices are driven without driver attached + * and managed resources may have been acquired. Make sure + * all resources are released. + * + * Drivers still can add resources into device after device + * is deleted but alive, so release devres here to avoid + * possible memory leak. + */ + devres_release_all(dev); + if (dev->release) dev->release(dev); else if (dev->type && dev->type->release) @@ -1196,13 +1207,6 @@ void device_del(struct device *dev) bus_remove_device(dev); driver_deferred_probe_del(dev); - /* - * Some platform devices are driven without driver attached - * and managed resources may have been acquired. Make sure - * all resources are released. - */ - devres_release_all(dev); - /* Notify the platform of the removal, in case they * need to do anything... */ @@ -1861,26 +1865,20 @@ void device_shutdown(void) */ #ifdef CONFIG_PRINTK -int __dev_printk(const char *level, const struct device *dev, - struct va_format *vaf) +static int +create_syslog_header(const struct device *dev, char *hdr, size_t hdrlen) { - char dict[128]; - const char *level_extra = ""; - size_t dictlen = 0; const char *subsys; - - if (!dev) - return printk("%s(NULL device *): %pV", level, vaf); + size_t pos = 0; if (dev->class) subsys = dev->class->name; else if (dev->bus) subsys = dev->bus->name; else - goto skip; + return 0; - dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, - "SUBSYSTEM=%s", subsys); + pos += snprintf(hdr + pos, hdrlen - pos, "SUBSYSTEM=%s", subsys); /* * Add device identifier DEVICE=: @@ -1896,32 +1894,63 @@ int __dev_printk(const char *level, const struct device *dev, c = 'b'; else c = 'c'; - dictlen++; - dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, - "DEVICE=%c%u:%u", - c, MAJOR(dev->devt), MINOR(dev->devt)); + pos++; + pos += snprintf(hdr + pos, hdrlen - pos, + "DEVICE=%c%u:%u", + c, MAJOR(dev->devt), MINOR(dev->devt)); } else if (strcmp(subsys, "net") == 0) { struct net_device *net = to_net_dev(dev); - dictlen++; - dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, - "DEVICE=n%u", net->ifindex); + pos++; + pos += snprintf(hdr + pos, hdrlen - pos, + "DEVICE=n%u", net->ifindex); } else { - dictlen++; - dictlen += snprintf(dict + dictlen, sizeof(dict) - dictlen, - "DEVICE=+%s:%s", subsys, dev_name(dev)); + pos++; + pos += snprintf(hdr + pos, hdrlen - pos, + "DEVICE=+%s:%s", subsys, dev_name(dev)); } -skip: - if (level[2]) - level_extra = &level[2]; /* skip past KERN_SOH "L" */ - return printk_emit(0, level[1] - '0', - dictlen ? dict : NULL, dictlen, - "%s %s: %s%pV", - dev_driver_string(dev), dev_name(dev), - level_extra, vaf); + return pos; +} +EXPORT_SYMBOL(create_syslog_header); + +int dev_vprintk_emit(int level, const struct device *dev, + const char *fmt, va_list args) +{ + char hdr[128]; + size_t hdrlen; + + hdrlen = create_syslog_header(dev, hdr, sizeof(hdr)); + + return vprintk_emit(0, level, hdrlen ? hdr : NULL, hdrlen, fmt, args); +} +EXPORT_SYMBOL(dev_vprintk_emit); + +int dev_printk_emit(int level, const struct device *dev, const char *fmt, ...) +{ + va_list args; + int r; + + va_start(args, fmt); + + r = dev_vprintk_emit(level, dev, fmt, args); + + va_end(args); + + return r; +} +EXPORT_SYMBOL(dev_printk_emit); + +static int __dev_printk(const char *level, const struct device *dev, + struct va_format *vaf) +{ + if (!dev) + return printk("%s(NULL device *): %pV", level, vaf); + + return dev_printk_emit(level[1] - '0', dev, + "%s %s: %pV", + dev_driver_string(dev), dev_name(dev), vaf); } -EXPORT_SYMBOL(__dev_printk); int dev_printk(const char *level, const struct device *dev, const char *fmt, ...) @@ -1936,6 +1965,7 @@ int dev_printk(const char *level, const struct device *dev, vaf.va = &args; r = __dev_printk(level, dev, &vaf); + va_end(args); return r; @@ -1955,6 +1985,7 @@ int func(const struct device *dev, const char *fmt, ...) \ vaf.va = &args; \ \ r = __dev_printk(kern_level, dev, &vaf); \ + \ va_end(args); \ \ return r; \ |