summaryrefslogtreecommitdiff
path: root/drivers/base/firmware_class.c
diff options
context:
space:
mode:
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);