summaryrefslogtreecommitdiff
path: root/drivers/base/firmware_class.c
diff options
context:
space:
mode:
authorVikram Mulukutla <markivx@codeaurora.org>2013-08-05 11:17:29 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:07:34 -0700
commite7c870ae4ce5e077b5b481a9478002c17fafb488 (patch)
treea7071e62025a0efe62d6e87a909c7863aeb82a45 /drivers/base/firmware_class.c
parent7fcfead52c1d285f541ebac49577ff2fa33eaa06 (diff)
firmware_class: Provide infrastructure to make fw caching optional
Some low memory systems with complex peripherals cannot afford to have the relatively large firmware images taking up valuable memory during suspend and resume. Change the internal implementation of firmware_class to disallow caching based on a configurable option. In the near future, variants of request_firmware will take advantage of this configurability. Change-Id: I44be7ce3b308b642fb018086def99fcb800a1109 Signed-off-by: Vikram Mulukutla <markivx@codeaurora.org> [joshc: reworked to use opt_flags instead of 'nocache' bool in fw_desc] Signed-off-by: Josh Cartwright <joshc@codeaurora.org> [vmulukut: adjusted for upstream additions to opt_flags] Signed-off-by: Vikram Mulukutla <markivx@codeaurora.org>
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r--drivers/base/firmware_class.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index abb939640bcc..a389eb5fde22 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -111,6 +111,7 @@ static inline long firmware_loading_timeout(void)
#define FW_OPT_FALLBACK 0
#endif
#define FW_OPT_NO_WARN (1U << 3)
+#define FW_OPT_NOCACHE (1U << 4)
struct firmware_cache {
/* firmware_buf instance will be added into the below list */
@@ -1072,6 +1073,14 @@ _request_firmware_prepare(struct firmware **firmware_p, struct fw_desc *desc)
return 0; /* assigned */
}
+ if (desc->opt_flags & FW_OPT_NOCACHE) {
+ buf = __allocate_fw_buf(desc->name, NULL);
+ if (!buf)
+ return -ENOMEM;
+ firmware->priv = buf;
+ return 1;
+ }
+
ret = fw_lookup_and_allocate_buf(desc->name, &fw_cache, &buf);
/*
@@ -1111,15 +1120,19 @@ static int assign_firmware_buf(struct firmware *fw, struct device *device,
* device may has been deleted already, but the problem
* should be fixed in devres or driver core.
*/
- /* don't cache firmware handled without uevent */
- if (device && (opt_flags & FW_OPT_UEVENT))
+ /* don't cache firmware handled without uevent, or when explicitly
+ * disabled
+ */
+ if (device && (opt_flags & FW_OPT_UEVENT)
+ && !(opt_flags & FW_OPT_NOCACHE))
fw_add_devm_name(device, buf->fw_id);
/*
* After caching firmware image is started, let it piggyback
* on request firmware.
*/
- if (buf->fwc->state == FW_LOADER_START_CACHE) {
+ if (!(opt_flags & FW_OPT_NOCACHE)
+ && (buf->fwc->state == FW_LOADER_START_CACHE)) {
if (fw_cache_piggyback_on_request(buf->fw_id))
kref_get(&buf->ref);
}
@@ -1299,7 +1312,8 @@ int
_request_firmware_nowait(
struct module *module, bool uevent,
const char *name, struct device *device, gfp_t gfp, void *context,
- void (*cont)(const struct firmware *fw, void *context))
+ void (*cont)(const struct firmware *fw, void *context),
+ bool nocache)
{
struct fw_desc *desc;
@@ -1318,6 +1332,8 @@ _request_firmware_nowait(
desc->opt_flags |= FW_OPT_UEVENT;
else
desc->opt_flags |= FW_OPT_USERHELPER;
+ if (nocache)
+ desc->opt_flags |= FW_OPT_NOCACHE;
if (!try_module_get(module)) {
kfree(desc);
@@ -1360,7 +1376,7 @@ request_firmware_nowait(
void (*cont)(const struct firmware *fw, void *context))
{
return _request_firmware_nowait(module, uevent, name, device, gfp,
- context, cont);
+ context, cont, false);
}
EXPORT_SYMBOL(request_firmware_nowait);