Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 324371
b: refs/heads/master
c: 2887b39
h: refs/heads/master
i:
  324369: c191a2f
  324367: ad30f79
v: v3
  • Loading branch information
Ming Lei authored and Greg Kroah-Hartman committed Aug 16, 2012
1 parent d7b16cf commit b1fb9fb
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 1f2b79599ee8f5fc82cc73c6c090eb6cdff881d6
refs/heads/master: 2887b3959c8b2f6ed1f62ce95c0888aedb1ea84b
100 changes: 92 additions & 8 deletions trunk/drivers/base/firmware_class.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,21 +142,31 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name,
return buf;
}

static struct firmware_buf *__fw_lookup_buf(const char *fw_name)
{
struct firmware_buf *tmp;
struct firmware_cache *fwc = &fw_cache;

list_for_each_entry(tmp, &fwc->head, list)
if (!strcmp(tmp->fw_id, fw_name))
return tmp;
return NULL;
}

static int fw_lookup_and_allocate_buf(const char *fw_name,
struct firmware_cache *fwc,
struct firmware_buf **buf)
{
struct firmware_buf *tmp;

spin_lock(&fwc->lock);
list_for_each_entry(tmp, &fwc->head, list)
if (!strcmp(tmp->fw_id, fw_name)) {
kref_get(&tmp->ref);
spin_unlock(&fwc->lock);
*buf = tmp;
return 1;
}

tmp = __fw_lookup_buf(fw_name);
if (tmp) {
kref_get(&tmp->ref);
spin_unlock(&fwc->lock);
*buf = tmp;
return 1;
}
tmp = __allocate_fw_buf(fw_name, fwc);
if (tmp)
list_add(&tmp->list, &fwc->head);
Expand All @@ -167,6 +177,18 @@ static int fw_lookup_and_allocate_buf(const char *fw_name,
return tmp ? 0 : -ENOMEM;
}

static struct firmware_buf *fw_lookup_buf(const char *fw_name)
{
struct firmware_buf *tmp;
struct firmware_cache *fwc = &fw_cache;

spin_lock(&fwc->lock);
tmp = __fw_lookup_buf(fw_name);
spin_unlock(&fwc->lock);

return tmp;
}

static void __fw_free_buf(struct kref *ref)
{
struct firmware_buf *buf = to_fwbuf(ref);
Expand Down Expand Up @@ -852,6 +874,66 @@ request_firmware_nowait(
return 0;
}

/**
* cache_firmware - cache one firmware image in kernel memory space
* @fw_name: the firmware image name
*
* Cache firmware in kernel memory so that drivers can use it when
* system isn't ready for them to request firmware image from userspace.
* Once it returns successfully, driver can use request_firmware or its
* nowait version to get the cached firmware without any interacting
* with userspace
*
* Return 0 if the firmware image has been cached successfully
* Return !0 otherwise
*
*/
int cache_firmware(const char *fw_name)
{
int ret;
const struct firmware *fw;

pr_debug("%s: %s\n", __func__, fw_name);

ret = request_firmware(&fw, fw_name, NULL);
if (!ret)
kfree(fw);

pr_debug("%s: %s ret=%d\n", __func__, fw_name, ret);

return ret;
}

/**
* uncache_firmware - remove one cached firmware image
* @fw_name: the firmware image name
*
* Uncache one firmware image which has been cached successfully
* before.
*
* Return 0 if the firmware cache has been removed successfully
* Return !0 otherwise
*
*/
int uncache_firmware(const char *fw_name)
{
struct firmware_buf *buf;
struct firmware fw;

pr_debug("%s: %s\n", __func__, fw_name);

if (fw_get_builtin_firmware(&fw, fw_name))
return 0;

buf = fw_lookup_buf(fw_name);
if (buf) {
fw_free_buf(buf);
return 0;
}

return -EINVAL;
}

static int __init firmware_class_init(void)
{
fw_cache_init();
Expand All @@ -869,3 +951,5 @@ module_exit(firmware_class_exit);
EXPORT_SYMBOL(release_firmware);
EXPORT_SYMBOL(request_firmware);
EXPORT_SYMBOL(request_firmware_nowait);
EXPORT_SYMBOL_GPL(cache_firmware);
EXPORT_SYMBOL_GPL(uncache_firmware);
12 changes: 12 additions & 0 deletions trunk/include/linux/firmware.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ int request_firmware_nowait(
void (*cont)(const struct firmware *fw, void *context));

void release_firmware(const struct firmware *fw);
int cache_firmware(const char *name);
int uncache_firmware(const char *name);
#else
static inline int request_firmware(const struct firmware **fw,
const char *name,
Expand All @@ -65,6 +67,16 @@ static inline int request_firmware_nowait(
static inline void release_firmware(const struct firmware *fw)
{
}

static inline int cache_firmware(const char *name)
{
return -ENOENT;
}

static inline int uncache_firmware(const char *name)
{
return -EINVAL;
}
#endif

#endif

0 comments on commit b1fb9fb

Please sign in to comment.