aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/firmware_class.c
diff options
context:
space:
mode:
authorMing Lei <ming.lei@canonical.com>2012-08-04 00:01:22 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-08-16 16:24:21 -0400
commit2887b3959c8b2f6ed1f62ce95c0888aedb1ea84b (patch)
treed8706698f44593c7c0075912c6e2a4b81ebf32a6 /drivers/base/firmware_class.c
parent1f2b79599ee8f5fc82cc73c6c090eb6cdff881d6 (diff)
firmware loader: introduce cache_firmware and uncache_firmware
This patches introduce two kernel APIs of cache_firmware and uncache_firmware, both of which take the firmware file name as the only parameter. So any drivers can call cache_firmware to cache the specified firmware file into kernel memory, and can use the cached firmware in situations which can't request firmware from user space. Signed-off-by: Ming Lei <ming.lei@canonical.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base/firmware_class.c')
-rw-r--r--drivers/base/firmware_class.c100
1 files changed, 92 insertions, 8 deletions
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 848ad97e8d79..fc119ce6fdb8 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -142,6 +142,17 @@ static struct firmware_buf *__allocate_fw_buf(const char *fw_name,
142 return buf; 142 return buf;
143} 143}
144 144
145static struct firmware_buf *__fw_lookup_buf(const char *fw_name)
146{
147 struct firmware_buf *tmp;
148 struct firmware_cache *fwc = &fw_cache;
149
150 list_for_each_entry(tmp, &fwc->head, list)
151 if (!strcmp(tmp->fw_id, fw_name))
152 return tmp;
153 return NULL;
154}
155
145static int fw_lookup_and_allocate_buf(const char *fw_name, 156static int fw_lookup_and_allocate_buf(const char *fw_name,
146 struct firmware_cache *fwc, 157 struct firmware_cache *fwc,
147 struct firmware_buf **buf) 158 struct firmware_buf **buf)
@@ -149,14 +160,13 @@ static int fw_lookup_and_allocate_buf(const char *fw_name,
149 struct firmware_buf *tmp; 160 struct firmware_buf *tmp;
150 161
151 spin_lock(&fwc->lock); 162 spin_lock(&fwc->lock);
152 list_for_each_entry(tmp, &fwc->head, list) 163 tmp = __fw_lookup_buf(fw_name);
153 if (!strcmp(tmp->fw_id, fw_name)) { 164 if (tmp) {
154 kref_get(&tmp->ref); 165 kref_get(&tmp->ref);
155 spin_unlock(&fwc->lock); 166 spin_unlock(&fwc->lock);
156 *buf = tmp; 167 *buf = tmp;
157 return 1; 168 return 1;
158 } 169 }
159
160 tmp = __allocate_fw_buf(fw_name, fwc); 170 tmp = __allocate_fw_buf(fw_name, fwc);
161 if (tmp) 171 if (tmp)
162 list_add(&tmp->list, &fwc->head); 172 list_add(&tmp->list, &fwc->head);
@@ -167,6 +177,18 @@ static int fw_lookup_and_allocate_buf(const char *fw_name,
167 return tmp ? 0 : -ENOMEM; 177 return tmp ? 0 : -ENOMEM;
168} 178}
169 179
180static struct firmware_buf *fw_lookup_buf(const char *fw_name)
181{
182 struct firmware_buf *tmp;
183 struct firmware_cache *fwc = &fw_cache;
184
185 spin_lock(&fwc->lock);
186 tmp = __fw_lookup_buf(fw_name);
187 spin_unlock(&fwc->lock);
188
189 return tmp;
190}
191
170static void __fw_free_buf(struct kref *ref) 192static void __fw_free_buf(struct kref *ref)
171{ 193{
172 struct firmware_buf *buf = to_fwbuf(ref); 194 struct firmware_buf *buf = to_fwbuf(ref);
@@ -852,6 +874,66 @@ request_firmware_nowait(
852 return 0; 874 return 0;
853} 875}
854 876
877/**
878 * cache_firmware - cache one firmware image in kernel memory space
879 * @fw_name: the firmware image name
880 *
881 * Cache firmware in kernel memory so that drivers can use it when
882 * system isn't ready for them to request firmware image from userspace.
883 * Once it returns successfully, driver can use request_firmware or its
884 * nowait version to get the cached firmware without any interacting
885 * with userspace
886 *
887 * Return 0 if the firmware image has been cached successfully
888 * Return !0 otherwise
889 *
890 */
891int cache_firmware(const char *fw_name)
892{
893 int ret;
894 const struct firmware *fw;
895
896 pr_debug("%s: %s\n", __func__, fw_name);
897
898 ret = request_firmware(&fw, fw_name, NULL);
899 if (!ret)
900 kfree(fw);
901
902 pr_debug("%s: %s ret=%d\n", __func__, fw_name, ret);
903
904 return ret;
905}
906
907/**
908 * uncache_firmware - remove one cached firmware image
909 * @fw_name: the firmware image name
910 *
911 * Uncache one firmware image which has been cached successfully
912 * before.
913 *
914 * Return 0 if the firmware cache has been removed successfully
915 * Return !0 otherwise
916 *
917 */
918int uncache_firmware(const char *fw_name)
919{
920 struct firmware_buf *buf;
921 struct firmware fw;
922
923 pr_debug("%s: %s\n", __func__, fw_name);
924
925 if (fw_get_builtin_firmware(&fw, fw_name))
926 return 0;
927
928 buf = fw_lookup_buf(fw_name);
929 if (buf) {
930 fw_free_buf(buf);
931 return 0;
932 }
933
934 return -EINVAL;
935}
936
855static int __init firmware_class_init(void) 937static int __init firmware_class_init(void)
856{ 938{
857 fw_cache_init(); 939 fw_cache_init();
@@ -869,3 +951,5 @@ module_exit(firmware_class_exit);
869EXPORT_SYMBOL(release_firmware); 951EXPORT_SYMBOL(release_firmware);
870EXPORT_SYMBOL(request_firmware); 952EXPORT_SYMBOL(request_firmware);
871EXPORT_SYMBOL(request_firmware_nowait); 953EXPORT_SYMBOL(request_firmware_nowait);
954EXPORT_SYMBOL_GPL(cache_firmware);
955EXPORT_SYMBOL_GPL(uncache_firmware);