aboutsummaryrefslogtreecommitdiffstats
path: root/fs/exec.c
diff options
context:
space:
mode:
authorStephen Boyd <stephen.boyd@linaro.org>2016-08-02 17:04:28 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-08-02 19:35:10 -0400
commita098ecd2fa7db8fa4fcc178a43627b29b226edb9 (patch)
tree55c25372dd873c23f00fe32744451cdf49f78f78 /fs/exec.c
parent0e742e927571946e08e877d3629e6efd4891ed95 (diff)
firmware: support loading into a pre-allocated buffer
Some systems are memory constrained but they need to load very large firmwares. The firmware subsystem allows drivers to request this firmware be loaded from the filesystem, but this requires that the entire firmware be loaded into kernel memory first before it's provided to the driver. This can lead to a situation where we map the firmware twice, once to load the firmware into kernel memory and once to copy the firmware into the final resting place. This creates needless memory pressure and delays loading because we have to copy from kernel memory to somewhere else. Let's add a request_firmware_into_buf() API that allows drivers to request firmware be loaded directly into a pre-allocated buffer. This skips the intermediate step of allocating a buffer in kernel memory to hold the firmware image while it's read from the filesystem. It also requires that drivers know how much memory they'll require before requesting the firmware and negates any benefits of firmware caching because the firmware layer doesn't manage the buffer lifetime. For a 16MB buffer, about half the time is spent performing a memcpy from the buffer to the final resting place. I see loading times go from 0.081171 seconds to 0.047696 seconds after applying this patch. Plus the vmalloc pressure is reduced. This is based on a patch from Vikram Mulukutla on codeaurora.org: https://www.codeaurora.org/cgit/quic/la/kernel/msm-3.18/commit/drivers/base/firmware_class.c?h=rel/msm-3.18&id=0a328c5f6cd999f5c591f172216835636f39bcb5 Link: http://lkml.kernel.org/r/20160607164741.31849-4-stephen.boyd@linaro.org Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org> Cc: Mimi Zohar <zohar@linux.vnet.ibm.com> Cc: Vikram Mulukutla <markivx@codeaurora.org> Cc: Mark Brown <broonie@kernel.org> Cc: Ming Lei <ming.lei@canonical.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/exec.c')
-rw-r--r--fs/exec.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/fs/exec.c b/fs/exec.c
index ca239fc86d8d..a1789cd684bf 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -866,7 +866,8 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size,
866 goto out; 866 goto out;
867 } 867 }
868 868
869 *buf = vmalloc(i_size); 869 if (id != READING_FIRMWARE_PREALLOC_BUFFER)
870 *buf = vmalloc(i_size);
870 if (!*buf) { 871 if (!*buf) {
871 ret = -ENOMEM; 872 ret = -ENOMEM;
872 goto out; 873 goto out;
@@ -897,8 +898,10 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size,
897 898
898out_free: 899out_free:
899 if (ret < 0) { 900 if (ret < 0) {
900 vfree(*buf); 901 if (id != READING_FIRMWARE_PREALLOC_BUFFER) {
901 *buf = NULL; 902 vfree(*buf);
903 *buf = NULL;
904 }
902 } 905 }
903 906
904out: 907out: