diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/Kconfig | 1 | ||||
-rw-r--r-- | drivers/base/core.c | 15 | ||||
-rw-r--r-- | drivers/base/cpu.c | 8 | ||||
-rw-r--r-- | drivers/base/dd.c | 8 | ||||
-rw-r--r-- | drivers/base/firmware_class.c | 8 | ||||
-rw-r--r-- | drivers/base/isa.c | 2 | ||||
-rw-r--r-- | drivers/base/platform.c | 2 | ||||
-rw-r--r-- | drivers/base/power/main.c | 41 | ||||
-rw-r--r-- | drivers/base/power/wakeirq.c | 14 | ||||
-rw-r--r-- | drivers/base/power/wakeup.c | 7 | ||||
-rw-r--r-- | drivers/base/regmap/regcache-rbtree.c | 7 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-debugfs.c | 6 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 2 |
13 files changed, 87 insertions, 34 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 602cbb04bee8..a4e8a2d26f6e 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -239,7 +239,6 @@ source "drivers/base/regmap/Kconfig" config DMA_SHARED_BUFFER bool default n - select ANON_INODES help This option enables the framework for buffer-sharing between multiple drivers. A buffer is associated with a file using driver diff --git a/drivers/base/core.c b/drivers/base/core.c index 146d8c081695..014b892263c5 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -715,6 +715,7 @@ void device_initialize(struct device *dev) device_pm_init(dev); set_dev_node(dev, -1); #ifdef CONFIG_GENERIC_MSI_IRQ + raw_spin_lock_init(&dev->msi_lock); INIT_LIST_HEAD(&dev->msi_list); #endif } @@ -2349,17 +2350,23 @@ static inline bool fwnode_is_primary(struct fwnode_handle *fwnode) */ void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode) { - if (fwnode) { - struct fwnode_handle *fn = dev->fwnode; + struct device *parent = dev->parent; + struct fwnode_handle *fn = dev->fwnode; + if (fwnode) { if (fwnode_is_primary(fn)) fn = fn->secondary; fwnode->secondary = fn; dev->fwnode = fwnode; } else { - dev->fwnode = fwnode_is_primary(dev->fwnode) ? - dev->fwnode->secondary : NULL; + if (fwnode_is_primary(fn)) { + dev->fwnode = fn->secondary; + if (!(parent && fn == parent->fwnode)) + fn->secondary = NULL; + } else { + dev->fwnode = NULL; + } } } EXPORT_SYMBOL_GPL(set_primary_fwnode); diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 2a5aad29c8a3..128bbe8da649 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -724,6 +724,12 @@ ssize_t __weak cpu_show_itlb_multihit(struct device *dev, return sprintf(buf, "Not affected\n"); } +ssize_t __weak cpu_show_srbds(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "Not affected\n"); +} + static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL); static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL); static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL); @@ -732,6 +738,7 @@ static DEVICE_ATTR(l1tf, 0444, cpu_show_l1tf, NULL); static DEVICE_ATTR(mds, 0444, cpu_show_mds, NULL); static DEVICE_ATTR(tsx_async_abort, 0444, cpu_show_tsx_async_abort, NULL); static DEVICE_ATTR(itlb_multihit, 0444, cpu_show_itlb_multihit, NULL); +static DEVICE_ATTR(srbds, 0444, cpu_show_srbds, NULL); static struct attribute *cpu_root_vulnerabilities_attrs[] = { &dev_attr_meltdown.attr, @@ -742,6 +749,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = { &dev_attr_mds.attr, &dev_attr_tsx_async_abort.attr, &dev_attr_itlb_multihit.attr, + &dev_attr_srbds.attr, NULL }; diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 0ab3a8d36ad4..cc6bf344b5c4 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -309,7 +309,11 @@ static int really_probe(struct device *dev, struct device_driver *drv) atomic_inc(&probe_count); pr_debug("bus: '%s': %s: probing driver %s with device %s\n", drv->bus->name, __func__, drv->name, dev_name(dev)); - WARN_ON(!list_empty(&dev->devres_head)); + if (!list_empty(&dev->devres_head)) { + dev_crit(dev, "Resources present before probing\n"); + ret = -EBUSY; + goto done; + } dev->driver = drv; @@ -386,7 +390,7 @@ probe_failed: ret = 0; done: atomic_dec(&probe_count); - wake_up(&probe_waitqueue); + wake_up_all(&probe_waitqueue); return ret; } diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index c1093c0d4dea..991d07b219cb 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -1303,15 +1303,17 @@ static int assign_firmware_buf(struct firmware *fw, struct device *device, /* called from request_firmware() and request_firmware_work_func() */ static int _request_firmware(struct fw_desc *desc) { - struct firmware *fw; + struct firmware *fw = NULL; long timeout; int ret; if (!desc->firmware_p) return -EINVAL; - if (!desc->name || desc->name[0] == '\0') - return -EINVAL; + if (!desc->name || desc->name[0] == '\0') { + ret = -EINVAL; + goto out; + } ret = _request_firmware_prepare(&fw, desc); if (ret <= 0) /* error or already assigned */ diff --git a/drivers/base/isa.c b/drivers/base/isa.c index 901d8185309e..372d10af2600 100644 --- a/drivers/base/isa.c +++ b/drivers/base/isa.c @@ -180,4 +180,4 @@ static int __init isa_bus_init(void) return error; } -device_initcall(isa_bus_init); +postcore_initcall(isa_bus_init); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 0ed3d8381840..d757beb36040 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -658,6 +658,8 @@ int __init_or_module __platform_driver_probe(struct platform_driver *drv, /* temporary section violation during probe() */ drv->probe = probe; retval = code = __platform_driver_register(drv, module); + if (retval) + return retval; /* * Fixup that section violation, being paranoid about code scanning diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 4192e46eda37..63100949e50d 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -1058,11 +1058,13 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a } error = dpm_run_callback(callback, dev, state, info); - if (!error) + if (!error) { dev->power.is_noirq_suspended = true; - else + } else { + log_suspend_abort_reason("Callback failed on %s in %pF returned %d", + dev_name(dev), callback, error); async_error = error; - + } Complete: complete_all(&dev->power.completion); TRACE_SUSPEND(error); @@ -1205,10 +1207,13 @@ static int __device_suspend_late(struct device *dev, pm_message_t state, bool as } error = dpm_run_callback(callback, dev, state, info); - if (!error) + if (!error) { dev->power.is_late_suspended = true; - else + } else { + log_suspend_abort_reason("Callback failed on %s in %pF returned %d", + dev_name(dev), callback, error); async_error = error; + } Complete: TRACE_SUSPEND(error); @@ -1351,7 +1356,6 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) pm_callback_t callback = NULL; char *info = NULL; int error = 0; - char suspend_abort[MAX_SUSPEND_ABORT_LEN]; DECLARE_DPM_WATCHDOG_ON_STACK(wd); TRACE_DEVICE(dev); @@ -1365,18 +1369,19 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) } /* - * If a device configured to wake up the system from sleep states - * has been suspended at run time and there's a resume request pending - * for it, this is equivalent to the device signaling wakeup, so the - * system suspend operation should be aborted. + * Wait for possible runtime PM transitions of the device in progress + * to complete and if there's a runtime resume request pending for it, + * resume it before proceeding with invoking the system-wide suspend + * callbacks for it. + * + * If the system-wide suspend callbacks below change the configuration + * of the device, they must disable runtime PM for it or otherwise + * ensure that its runtime-resume callbacks will not be confused by that + * change in case they are invoked going forward. */ - if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) - pm_wakeup_event(dev, 0); + pm_runtime_barrier(dev); if (pm_wakeup_pending()) { - pm_get_active_wakeup_sources(suspend_abort, - MAX_SUSPEND_ABORT_LEN); - log_suspend_abort_reason(suspend_abort); dev->power.direct_complete = false; async_error = -EBUSY; goto Complete; @@ -1463,6 +1468,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) spin_unlock_irq(&parent->power.lock); } + } else { + log_suspend_abort_reason("Callback failed on %s in %pF returned %d", + dev_name(dev), callback, error); } device_unlock(dev); @@ -1666,6 +1674,9 @@ int dpm_prepare(pm_message_t state) printk(KERN_INFO "PM: Device %s not prepared " "for power transition: code %d\n", dev_name(dev), error); + log_suspend_abort_reason("Device %s not prepared " + "for power transition: code %d", + dev_name(dev), error); put_device(dev); break; } diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c index feba1b211898..8c05e7a5e777 100644 --- a/drivers/base/power/wakeirq.c +++ b/drivers/base/power/wakeirq.c @@ -319,8 +319,13 @@ void dev_pm_arm_wake_irq(struct wake_irq *wirq) if (!wirq) return; - if (device_may_wakeup(wirq->dev)) + if (device_may_wakeup(wirq->dev)) { + if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED && + !pm_runtime_status_suspended(wirq->dev)) + enable_irq(wirq->irq); + enable_irq_wake(wirq->irq); + } } /** @@ -335,6 +340,11 @@ void dev_pm_disarm_wake_irq(struct wake_irq *wirq) if (!wirq) return; - if (device_may_wakeup(wirq->dev)) + if (device_may_wakeup(wirq->dev)) { disable_irq_wake(wirq->irq); + + if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED && + !pm_runtime_status_suspended(wirq->dev)) + disable_irq_nosync(wirq->irq); + } } diff --git a/drivers/base/power/wakeup.c b/drivers/base/power/wakeup.c index 37658ff761ed..5f3bd234c4be 100644 --- a/drivers/base/power/wakeup.c +++ b/drivers/base/power/wakeup.c @@ -16,6 +16,7 @@ #include <linux/debugfs.h> #include <linux/pm_wakeirq.h> #include <linux/types.h> +#include <linux/wakeup_reason.h> #include <trace/events/power.h> #include "power.h" @@ -884,6 +885,7 @@ bool pm_wakeup_pending(void) { unsigned long flags; bool ret = false; + char suspend_abort[MAX_SUSPEND_ABORT_LEN]; spin_lock_irqsave(&events_lock, flags); if (events_check_enabled) { @@ -897,7 +899,10 @@ bool pm_wakeup_pending(void) if (ret) { pr_info("PM: Wakeup pending, aborting suspend\n"); - pm_print_active_wakeup_sources(); + pm_get_active_wakeup_sources(suspend_abort, + MAX_SUSPEND_ABORT_LEN); + log_suspend_abort_reason(suspend_abort); + pr_info("PM: %s\n", suspend_abort); } return ret || pm_abort_suspend; diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 56486d92c4e7..f868dda30da0 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c @@ -296,14 +296,14 @@ static int regcache_rbtree_insert_to_block(struct regmap *map, if (!blk) return -ENOMEM; + rbnode->block = blk; + if (BITS_TO_LONGS(blklen) > BITS_TO_LONGS(rbnode->blklen)) { present = krealloc(rbnode->cache_present, BITS_TO_LONGS(blklen) * sizeof(*present), GFP_KERNEL); - if (!present) { - kfree(blk); + if (!present) return -ENOMEM; - } memset(present + BITS_TO_LONGS(rbnode->blklen), 0, (BITS_TO_LONGS(blklen) - BITS_TO_LONGS(rbnode->blklen)) @@ -320,7 +320,6 @@ static int regcache_rbtree_insert_to_block(struct regmap *map, } /* update the rbnode block, its size and the base register */ - rbnode->block = blk; rbnode->blklen = blklen; rbnode->base_reg = base_reg; rbnode->cache_present = present; diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 3120bdc84fce..52d6bf710e74 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -194,6 +194,9 @@ static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from, if (*ppos < 0 || !count) return -EINVAL; + if (count > (PAGE_SIZE << (MAX_ORDER - 1))) + count = PAGE_SIZE << (MAX_ORDER - 1); + buf = kmalloc(count, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -402,6 +405,9 @@ static ssize_t regmap_reg_ranges_read_file(struct file *file, if (*ppos < 0 || !count) return -EINVAL; + if (count > (PAGE_SIZE << (MAX_ORDER - 1))) + count = PAGE_SIZE << (MAX_ORDER - 1); + buf = kmalloc(count, GFP_KERNEL); if (!buf) return -ENOMEM; diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 6b96ebb9b440..a9ca3cee3990 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -1106,7 +1106,7 @@ static int dev_get_regmap_match(struct device *dev, void *res, void *data) /* If the user didn't specify a name match any */ if (data) - return (*r)->name == data; + return !strcmp((*r)->name, data); else return 1; } |