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: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Stephen Boyd
2015-09-11 16:37:05 -07:00
committed by Mark Brown
parent 6ff33f3902
commit b4a21fc275
2 changed files with 12 additions and 1 deletions

View File

@ -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 */

View File

@ -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 @@ out:
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;