diff options
| author | Stephen Boyd <sboyd@codeaurora.org> | 2015-09-11 19:37:05 -0400 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2015-09-14 14:49:26 -0400 |
| commit | b4a21fc275e99fc63c77b30da92ee497f8a7bdb6 (patch) | |
| tree | 0402fddcd4ae52a6a6d358dae0d6581df881a4ac /drivers/base/regmap | |
| parent | 6ff33f3902c3b1c5d0db6b1e2c70b6d76fba357f (diff) | |
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>
Diffstat (limited to 'drivers/base/regmap')
| -rw-r--r-- | drivers/base/regmap/internal.h | 1 | ||||
| -rw-r--r-- | drivers/base/regmap/regmap.c | 12 |
2 files changed, 12 insertions, 1 deletions
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index cc557886ab23..f3b1445da0a5 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
| @@ -59,6 +59,7 @@ struct regmap { | |||
| 59 | regmap_lock lock; | 59 | regmap_lock lock; |
| 60 | regmap_unlock unlock; | 60 | regmap_unlock unlock; |
| 61 | void *lock_arg; /* This is passed to lock/unlock functions */ | 61 | void *lock_arg; /* This is passed to lock/unlock functions */ |
| 62 | gfp_t alloc_flags; | ||
| 62 | 63 | ||
| 63 | struct device *dev; /* Device we do I/O on */ | 64 | struct device *dev; /* Device we do I/O on */ |
| 64 | void *work_buf; /* Scratch buffer used to format I/O */ | 65 | void *work_buf; /* Scratch buffer used to format I/O */ |
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index afaf56200674..0b51190c13df 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
| @@ -561,6 +561,16 @@ struct regmap *__regmap_init(struct device *dev, | |||
| 561 | } | 561 | } |
| 562 | map->lock_arg = map; | 562 | map->lock_arg = map; |
| 563 | } | 563 | } |
| 564 | |||
| 565 | /* | ||
| 566 | * When we write in fast-paths with regmap_bulk_write() don't allocate | ||
| 567 | * scratch buffers with sleeping allocations. | ||
| 568 | */ | ||
| 569 | if ((bus && bus->fast_io) || config->fast_io) | ||
| 570 | map->alloc_flags = GFP_ATOMIC; | ||
| 571 | else | ||
| 572 | map->alloc_flags = GFP_KERNEL; | ||
| 573 | |||
| 564 | map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8); | 574 | map->format.reg_bytes = DIV_ROUND_UP(config->reg_bits, 8); |
| 565 | map->format.pad_bytes = config->pad_bits / 8; | 575 | map->format.pad_bytes = config->pad_bits / 8; |
| 566 | map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8); | 576 | map->format.val_bytes = DIV_ROUND_UP(config->val_bits, 8); |
| @@ -1786,7 +1796,7 @@ out: | |||
| 1786 | if (!val_count) | 1796 | if (!val_count) |
| 1787 | return -EINVAL; | 1797 | return -EINVAL; |
| 1788 | 1798 | ||
| 1789 | wval = kmemdup(val, val_count * val_bytes, GFP_KERNEL); | 1799 | wval = kmemdup(val, val_count * val_bytes, map->alloc_flags); |
| 1790 | if (!wval) { | 1800 | if (!wval) { |
| 1791 | dev_err(map->dev, "Error in memory allocation\n"); | 1801 | dev_err(map->dev, "Error in memory allocation\n"); |
| 1792 | return -ENOMEM; | 1802 | return -ENOMEM; |
