Commit b4a21fc2 authored by Stephen Boyd's avatar Stephen Boyd Committed by Mark Brown

regmap: Allocate buffers with GFP_ATOMIC when fast_io == true

If a regmap is using fast_io, allocate the scratch buffer in
regmap_bulk_write() with GFP_ATOMIC instead of GFP_KERNEL.
Otherwise we may schedule while atomic.
Reported-by: default avatarAbhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: default avatarStephen Boyd <sboyd@codeaurora.org>
Signed-off-by: default avatarMark Brown <broonie@kernel.org>
parent 6ff33f39
...@@ -59,6 +59,7 @@ struct regmap { ...@@ -59,6 +59,7 @@ struct regmap {
regmap_lock lock; regmap_lock lock;
regmap_unlock unlock; regmap_unlock unlock;
void *lock_arg; /* This is passed to lock/unlock functions */ void *lock_arg; /* This is passed to lock/unlock functions */
gfp_t alloc_flags;
struct device *dev; /* Device we do I/O on */ struct device *dev; /* Device we do I/O on */
void *work_buf; /* Scratch buffer used to format I/O */ void *work_buf; /* Scratch buffer used to format I/O */
......
...@@ -561,6 +561,16 @@ struct regmap *__regmap_init(struct device *dev, ...@@ -561,6 +561,16 @@ struct regmap *__regmap_init(struct device *dev,
} }
map->lock_arg = map; map->lock_arg = map;
} }
/*
* When we write in fast-paths with regmap_bulk_write() don't allocate
* scratch buffers with sleeping allocations.
*/
if ((bus && bus->fast_io) || config->fast_io)
map->alloc_flags = GFP_ATOMIC;
else
map->alloc_flags = GFP_KERNEL;
map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8); map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8);
map->format.pad_bytes = config->pad_bits / 8; map->format.pad_bytes = config->pad_bits / 8;
map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8); map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8);
...@@ -1786,7 +1796,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, ...@@ -1786,7 +1796,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
if (!val_count) if (!val_count)
return -EINVAL; return -EINVAL;
wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL); wval = kmemdup(val, val_count * val_bytes, map->alloc_flags);
if (!wval) { if (!wval) {
dev_err(map->dev, "Error in memory allocation\n"); dev_err(map->dev, "Error in memory allocation\n");
return -ENOMEM; return -ENOMEM;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment