diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/memory.c | 4 | ||||
-rw-r--r-- | drivers/base/power/domain.c | 36 | ||||
-rw-r--r-- | drivers/base/power/domain_governor.c | 3 | ||||
-rw-r--r-- | drivers/base/power/wakeirq.c | 6 | ||||
-rw-r--r-- | drivers/base/regmap/regcache-flat.c | 2 | ||||
-rw-r--r-- | drivers/base/regmap/regcache-lzo.c | 6 | ||||
-rw-r--r-- | drivers/base/regmap/regcache-rbtree.c | 9 | ||||
-rw-r--r-- | drivers/base/regmap/regcache.c | 41 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-irq.c | 13 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 118 |
10 files changed, 194 insertions, 44 deletions
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 2804aed3f416..25425d3f2575 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -303,6 +303,10 @@ static int memory_subsys_offline(struct device *dev) if (mem->state == MEM_OFFLINE) return 0; + /* Can't offline block with non-present sections */ + if (mem->section_count != sections_per_block) + return -EINVAL; + return memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE); } diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index e03b1ad25a90..65f50eccd49b 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -390,6 +390,7 @@ static int pm_genpd_runtime_suspend(struct device *dev) struct generic_pm_domain *genpd; bool (*stop_ok)(struct device *__dev); struct gpd_timing_data *td = &dev_gpd_data(dev)->td; + bool runtime_pm = pm_runtime_enabled(dev); ktime_t time_start; s64 elapsed_ns; int ret; @@ -400,12 +401,19 @@ static int pm_genpd_runtime_suspend(struct device *dev) if (IS_ERR(genpd)) return -EINVAL; + /* + * A runtime PM centric subsystem/driver may re-use the runtime PM + * callbacks for other purposes than runtime PM. In those scenarios + * runtime PM is disabled. Under these circumstances, we shall skip + * validating/measuring the PM QoS latency. + */ stop_ok = genpd->gov ? genpd->gov->stop_ok : NULL; - if (stop_ok && !stop_ok(dev)) + if (runtime_pm && stop_ok && !stop_ok(dev)) return -EBUSY; /* Measure suspend latency. */ - time_start = ktime_get(); + if (runtime_pm) + time_start = ktime_get(); ret = genpd_save_dev(genpd, dev); if (ret) @@ -418,13 +426,15 @@ static int pm_genpd_runtime_suspend(struct device *dev) } /* Update suspend latency value if the measured time exceeds it. */ - elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); - if (elapsed_ns > td->suspend_latency_ns) { - td->suspend_latency_ns = elapsed_ns; - dev_dbg(dev, "suspend latency exceeded, %lld ns\n", - elapsed_ns); - genpd->max_off_time_changed = true; - td->constraint_changed = true; + if (runtime_pm) { + elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); + if (elapsed_ns > td->suspend_latency_ns) { + td->suspend_latency_ns = elapsed_ns; + dev_dbg(dev, "suspend latency exceeded, %lld ns\n", + elapsed_ns); + genpd->max_off_time_changed = true; + td->constraint_changed = true; + } } /* @@ -453,6 +463,7 @@ static int pm_genpd_runtime_resume(struct device *dev) { struct generic_pm_domain *genpd; struct gpd_timing_data *td = &dev_gpd_data(dev)->td; + bool runtime_pm = pm_runtime_enabled(dev); ktime_t time_start; s64 elapsed_ns; int ret; @@ -479,14 +490,14 @@ static int pm_genpd_runtime_resume(struct device *dev) out: /* Measure resume latency. */ - if (timed) + if (timed && runtime_pm) time_start = ktime_get(); genpd_start_dev(genpd, dev); genpd_restore_dev(genpd, dev); /* Update resume latency value if the measured time exceeds it. */ - if (timed) { + if (timed && runtime_pm) { elapsed_ns = ktime_to_ns(ktime_sub(ktime_get(), time_start)); if (elapsed_ns > td->resume_latency_ns) { td->resume_latency_ns = elapsed_ns; @@ -1775,10 +1786,10 @@ int genpd_dev_pm_attach(struct device *dev) } pd = of_genpd_get_from_provider(&pd_args); + of_node_put(pd_args.np); if (IS_ERR(pd)) { dev_dbg(dev, "%s() failed to find PM domain: %ld\n", __func__, PTR_ERR(pd)); - of_node_put(dev->of_node); return -EPROBE_DEFER; } @@ -1796,7 +1807,6 @@ int genpd_dev_pm_attach(struct device *dev) if (ret < 0) { dev_err(dev, "failed to add to PM domain %s: %d", pd->name, ret); - of_node_put(dev->of_node); goto out; } diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c index e60dd12e23aa..1e937ac5f456 100644 --- a/drivers/base/power/domain_governor.c +++ b/drivers/base/power/domain_governor.c @@ -160,9 +160,6 @@ static bool default_power_down_ok(struct dev_pm_domain *pd) struct gpd_timing_data *td; s64 constraint_ns; - if (!pdd->dev->driver) - continue; - /* * Check if the device is allowed to be off long enough for the * domain to turn off and on (that's how much time it will diff --git a/drivers/base/power/wakeirq.c b/drivers/base/power/wakeirq.c index eb6e67451dec..0d77cd6fd8d1 100644 --- a/drivers/base/power/wakeirq.c +++ b/drivers/base/power/wakeirq.c @@ -68,6 +68,9 @@ int dev_pm_set_wake_irq(struct device *dev, int irq) struct wake_irq *wirq; int err; + if (irq < 0) + return -EINVAL; + wirq = kzalloc(sizeof(*wirq), GFP_KERNEL); if (!wirq) return -ENOMEM; @@ -167,6 +170,9 @@ int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq) struct wake_irq *wirq; int err; + if (irq < 0) + return -EINVAL; + wirq = kzalloc(sizeof(*wirq), GFP_KERNEL); if (!wirq) return -ENOMEM; diff --git a/drivers/base/regmap/regcache-flat.c b/drivers/base/regmap/regcache-flat.c index 0246f44ded74..686c9e0b930e 100644 --- a/drivers/base/regmap/regcache-flat.c +++ b/drivers/base/regmap/regcache-flat.c @@ -21,7 +21,7 @@ static int regcache_flat_init(struct regmap *map) int i; unsigned int *cache; - map->cache = kzalloc(sizeof(unsigned int) * (map->max_register + 1), + map->cache = kcalloc(map->max_register + 1, sizeof(unsigned int), GFP_KERNEL); if (!map->cache) return -ENOMEM; diff --git a/drivers/base/regmap/regcache-lzo.c b/drivers/base/regmap/regcache-lzo.c index 736e0d378567..6f77d7319fc6 100644 --- a/drivers/base/regmap/regcache-lzo.c +++ b/drivers/base/regmap/regcache-lzo.c @@ -139,7 +139,7 @@ static int regcache_lzo_init(struct regmap *map) ret = 0; blkcount = regcache_lzo_block_count(map); - map->cache = kzalloc(blkcount * sizeof *lzo_blocks, + map->cache = kcalloc(blkcount, sizeof(*lzo_blocks), GFP_KERNEL); if (!map->cache) return -ENOMEM; @@ -152,8 +152,8 @@ static int regcache_lzo_init(struct regmap *map) * that register. */ bmp_size = map->num_reg_defaults_raw; - sync_bmp = kmalloc(BITS_TO_LONGS(bmp_size) * sizeof(long), - GFP_KERNEL); + sync_bmp = kmalloc_array(BITS_TO_LONGS(bmp_size), sizeof(long), + GFP_KERNEL); if (!sync_bmp) { ret = -ENOMEM; goto err; diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 56486d92c4e7..9d7ced559cba 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c @@ -361,13 +361,14 @@ regcache_rbtree_node_alloc(struct regmap *map, unsigned int reg) rbnode->base_reg = reg; } - rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size, - GFP_KERNEL); + rbnode->block = kmalloc_array(rbnode->blklen, map->cache_word_size, + GFP_KERNEL); if (!rbnode->block) goto err_free; - rbnode->cache_present = kzalloc(BITS_TO_LONGS(rbnode->blklen) * - sizeof(*rbnode->cache_present), GFP_KERNEL); + rbnode->cache_present = kcalloc(BITS_TO_LONGS(rbnode->blklen), + sizeof(*rbnode->cache_present), + GFP_KERNEL); if (!rbnode->cache_present) goto err_free_block; diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 4c07802986b2..348be3a35410 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c @@ -100,15 +100,25 @@ int regcache_init(struct regmap *map, const struct regmap_config *config) int i; void *tmp_buf; - for (i = 0; i < config->num_reg_defaults; i++) - if (config->reg_defaults[i].reg % map->reg_stride) - return -EINVAL; - if (map->cache_type == REGCACHE_NONE) { + if (config->reg_defaults || config->num_reg_defaults_raw) + dev_warn(map->dev, + "No cache used with register defaults set!\n"); + map->cache_bypass = true; return 0; } + if (config->reg_defaults && !config->num_reg_defaults) { + dev_err(map->dev, + "Register defaults are set without the number!\n"); + return -EINVAL; + } + + for (i = 0; i < config->num_reg_defaults; i++) + if (config->reg_defaults[i].reg % map->reg_stride) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(cache_types); i++) if (cache_types[i]->type == map->cache_type) break; @@ -138,8 +148,6 @@ int regcache_init(struct regmap *map, const struct regmap_config *config) * a copy of it. */ if (config->reg_defaults) { - if (!map->num_reg_defaults) - return -EINVAL; tmp_buf = kmemdup(config->reg_defaults, map->num_reg_defaults * sizeof(struct reg_default), GFP_KERNEL); if (!tmp_buf) @@ -535,19 +543,30 @@ bool regcache_set_val(struct regmap *map, void *base, unsigned int idx, switch (map->cache_word_size) { case 1: { u8 *cache = base; + cache[idx] = val; break; } case 2: { u16 *cache = base; + cache[idx] = val; break; } case 4: { u32 *cache = base; + + cache[idx] = val; + break; + } +#ifdef CONFIG_64BIT + case 8: { + u64 *cache = base; + cache[idx] = val; break; } +#endif default: BUG(); } @@ -568,16 +587,26 @@ unsigned int regcache_get_val(struct regmap *map, const void *base, switch (map->cache_word_size) { case 1: { const u8 *cache = base; + return cache[idx]; } case 2: { const u16 *cache = base; + return cache[idx]; } case 4: { const u32 *cache = base; + + return cache[idx]; + } +#ifdef CONFIG_64BIT + case 8: { + const u64 *cache = base; + return cache[idx]; } +#endif default: BUG(); } diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index dbe7a0d15a26..9b0d202414d0 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -438,23 +438,23 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, if (!d) return -ENOMEM; - d->status_buf = kzalloc(sizeof(unsigned int) * chip->num_regs, + d->status_buf = kcalloc(chip->num_regs, sizeof(unsigned int), GFP_KERNEL); if (!d->status_buf) goto err_alloc; - d->mask_buf = kzalloc(sizeof(unsigned int) * chip->num_regs, + d->mask_buf = kcalloc(chip->num_regs, sizeof(unsigned int), GFP_KERNEL); if (!d->mask_buf) goto err_alloc; - d->mask_buf_def = kzalloc(sizeof(unsigned int) * chip->num_regs, + d->mask_buf_def = kcalloc(chip->num_regs, sizeof(unsigned int), GFP_KERNEL); if (!d->mask_buf_def) goto err_alloc; if (chip->wake_base) { - d->wake_buf = kzalloc(sizeof(unsigned int) * chip->num_regs, + d->wake_buf = kcalloc(chip->num_regs, sizeof(unsigned int), GFP_KERNEL); if (!d->wake_buf) goto err_alloc; @@ -491,8 +491,9 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, if (!map->use_single_read && map->reg_stride == 1 && d->irq_reg_stride == 1) { - d->status_reg_buf = kmalloc(map->format.val_bytes * - chip->num_regs, GFP_KERNEL); + d->status_reg_buf = kmalloc_array(chip->num_regs, + map->format.val_bytes, + GFP_KERNEL); if (!d->status_reg_buf) goto err_alloc; } diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 4ac63c0e50c7..ee54e841de4a 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -245,6 +245,28 @@ static void regmap_format_32_native(void *buf, unsigned int val, *(u32 *)buf = val << shift; } +#ifdef CONFIG_64BIT +static void regmap_format_64_be(void *buf, unsigned int val, unsigned int shift) +{ + __be64 *b = buf; + + b[0] = cpu_to_be64((u64)val << shift); +} + +static void regmap_format_64_le(void *buf, unsigned int val, unsigned int shift) +{ + __le64 *b = buf; + + b[0] = cpu_to_le64((u64)val << shift); +} + +static void regmap_format_64_native(void *buf, unsigned int val, + unsigned int shift) +{ + *(u64 *)buf = (u64)val << shift; +} +#endif + static void regmap_parse_inplace_noop(void *buf) { } @@ -332,6 +354,41 @@ static unsigned int regmap_parse_32_native(const void *buf) return *(u32 *)buf; } +#ifdef CONFIG_64BIT +static unsigned int regmap_parse_64_be(const void *buf) +{ + const __be64 *b = buf; + + return be64_to_cpu(b[0]); +} + +static unsigned int regmap_parse_64_le(const void *buf) +{ + const __le64 *b = buf; + + return le64_to_cpu(b[0]); +} + +static void regmap_parse_64_be_inplace(void *buf) +{ + __be64 *b = buf; + + b[0] = be64_to_cpu(b[0]); +} + +static void regmap_parse_64_le_inplace(void *buf) +{ + __le64 *b = buf; + + b[0] = le64_to_cpu(b[0]); +} + +static unsigned int regmap_parse_64_native(const void *buf) +{ + return *(u64 *)buf; +} +#endif + static void regmap_lock_mutex(void *__map) { struct regmap *map = __map; @@ -712,6 +769,21 @@ struct regmap *__regmap_init(struct device *dev, } break; +#ifdef CONFIG_64BIT + case 64: + switch (reg_endian) { + case REGMAP_ENDIAN_BIG: + map->format.format_reg = regmap_format_64_be; + break; + case REGMAP_ENDIAN_NATIVE: + map->format.format_reg = regmap_format_64_native; + break; + default: + goto err_map; + } + break; +#endif + default: goto err_map; } @@ -771,6 +843,28 @@ struct regmap *__regmap_init(struct device *dev, goto err_map; } break; +#ifdef CONFIG_64BIT + case 64: + switch (val_endian) { + case REGMAP_ENDIAN_BIG: + map->format.format_val = regmap_format_64_be; + map->format.parse_val = regmap_parse_64_be; + map->format.parse_inplace = regmap_parse_64_be_inplace; + break; + case REGMAP_ENDIAN_LITTLE: + map->format.format_val = regmap_format_64_le; + map->format.parse_val = regmap_parse_64_le; + map->format.parse_inplace = regmap_parse_64_le_inplace; + break; + case REGMAP_ENDIAN_NATIVE: + map->format.format_val = regmap_format_64_native; + map->format.parse_val = regmap_parse_64_native; + break; + default: + goto err_map; + } + break; +#endif } if (map->format.format_write) { @@ -1513,7 +1607,7 @@ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val) { int ret; - if (reg % map->reg_stride) + if (!IS_ALIGNED(reg, map->reg_stride)) return -EINVAL; map->lock(map->lock_arg); @@ -1540,7 +1634,7 @@ int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val) { int ret; - if (reg % map->reg_stride) + if (!IS_ALIGNED(reg, map->reg_stride)) return -EINVAL; map->lock(map->lock_arg); @@ -1714,7 +1808,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, if (map->bus && !map->format.parse_inplace) return -EINVAL; - if (reg % map->reg_stride) + if (!IS_ALIGNED(reg, map->reg_stride)) return -EINVAL; /* @@ -1983,7 +2077,7 @@ static int _regmap_multi_reg_write(struct regmap *map, int reg = regs[i].reg; if (!map->writeable_reg(map->dev, reg)) return -EINVAL; - if (reg % map->reg_stride) + if (!IS_ALIGNED(reg, map->reg_stride)) return -EINVAL; } @@ -2133,7 +2227,7 @@ int regmap_raw_write_async(struct regmap *map, unsigned int reg, if (val_len % map->format.val_bytes) return -EINVAL; - if (reg % map->reg_stride) + if (!IS_ALIGNED(reg, map->reg_stride)) return -EINVAL; map->lock(map->lock_arg); @@ -2260,7 +2354,7 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val) { int ret; - if (reg % map->reg_stride) + if (!IS_ALIGNED(reg, map->reg_stride)) return -EINVAL; map->lock(map->lock_arg); @@ -2296,7 +2390,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, return -EINVAL; if (val_len % map->format.val_bytes) return -EINVAL; - if (reg % map->reg_stride) + if (!IS_ALIGNED(reg, map->reg_stride)) return -EINVAL; if (val_count == 0) return -EINVAL; @@ -2414,7 +2508,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, size_t val_bytes = map->format.val_bytes; bool vol = regmap_volatile_range(map, reg, val_count); - if (reg % map->reg_stride) + if (!IS_ALIGNED(reg, map->reg_stride)) return -EINVAL; if (map->bus && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) { @@ -2488,11 +2582,19 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, * we assume that the values are native * endian. */ +#ifdef CONFIG_64BIT + u64 *u64 = val; +#endif u32 *u32 = val; u16 *u16 = val; u8 *u8 = val; switch (map->format.val_bytes) { +#ifdef CONFIG_64BIT + case 8: + u64[i] = ival; + break; +#endif case 4: u32[i] = ival; break; |