aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2014-03-18 07:58:33 -0400
committerMark Brown <broonie@linaro.org>2014-03-18 08:37:25 -0400
commit4999e9621a58fa03fe18aa2ea55838bd2e755190 (patch)
tree60746ff9efb1582daa7ed1ab5c80c9d23617fbc6 /drivers/base
parent56fb1c74f3bda1c0100fc3e9a7888c229174f9a4 (diff)
regmap: Fix possible sleep-in-atomic in regmap_bulk_write()
regmap deploys the spinlock for the protection when set up in fast_io mode. This may lead to sleep-in-atomic by memory allocation with GFP_KERNEL in regmap_bulk_write(). This patch fixes it by moving the allocation out of the lock. [Fix excessively large locked region -- broonie] Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/regmap/regmap.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index e5a5509160fe..35077374f38b 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1520,12 +1520,12 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
1520 if (reg % map->reg_stride) 1520 if (reg % map->reg_stride)
1521 return -EINVAL; 1521 return -EINVAL;
1522 1522
1523 map->lock(map->lock_arg);
1524 /* 1523 /*
1525 * Some devices don't support bulk write, for 1524 * Some devices don't support bulk write, for
1526 * them we have a series of single write operations. 1525 * them we have a series of single write operations.
1527 */ 1526 */
1528 if (!map->bus || map->use_single_rw) { 1527 if (!map->bus || map->use_single_rw) {
1528 map->lock(map->lock_arg);
1529 for (i = 0; i < val_count; i++) { 1529 for (i = 0; i < val_count; i++) {
1530 unsigned int ival; 1530 unsigned int ival;
1531 1531
@@ -1554,24 +1554,25 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
1554 if (ret != 0) 1554 if (ret != 0)
1555 goto out; 1555 goto out;
1556 } 1556 }
1557out:
1558 map->unlock(map->lock_arg);
1557 } else { 1559 } else {
1558 void *wval; 1560 void *wval;
1559 1561
1560 wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL); 1562 wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL);
1561 if (!wval) { 1563 if (!wval) {
1562 ret = -ENOMEM;
1563 dev_err(map->dev, "Error in memory allocation\n"); 1564 dev_err(map->dev, "Error in memory allocation\n");
1564 goto out; 1565 return -ENOMEM;
1565 } 1566 }
1566 for (i = 0; i < val_count * val_bytes; i += val_bytes) 1567 for (i = 0; i < val_count * val_bytes; i += val_bytes)
1567 map->format.parse_inplace(wval + i); 1568 map->format.parse_inplace(wval + i);
1568 1569
1570 map->lock(map->lock_arg);
1569 ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count); 1571 ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count);
1572 map->unlock(map->lock_arg);
1570 1573
1571 kfree(wval); 1574 kfree(wval);
1572 } 1575 }
1573out:
1574 map->unlock(map->lock_arg);
1575 return ret; 1576 return ret;
1576} 1577}
1577EXPORT_SYMBOL_GPL(regmap_bulk_write); 1578EXPORT_SYMBOL_GPL(regmap_bulk_write);