@@ -170,10 +170,19 @@ static struct fw_priv *__allocate_fw_priv(const char *fw_name,
170170 struct firmware_cache * fwc ,
171171 void * dbuf ,
172172 size_t size ,
173+ size_t offset ,
173174 u32 opt_flags )
174175{
175176 struct fw_priv * fw_priv ;
176177
178+ /* For a partial read, the buffer must be preallocated. */
179+ if ((opt_flags & FW_OPT_PARTIAL ) && !dbuf )
180+ return NULL ;
181+
182+ /* Only partial reads are allowed to use an offset. */
183+ if (offset != 0 && !(opt_flags & FW_OPT_PARTIAL ))
184+ return NULL ;
185+
177186 fw_priv = kzalloc (sizeof (* fw_priv ), GFP_ATOMIC );
178187 if (!fw_priv )
179188 return NULL ;
@@ -188,6 +197,7 @@ static struct fw_priv *__allocate_fw_priv(const char *fw_name,
188197 fw_priv -> fwc = fwc ;
189198 fw_priv -> data = dbuf ;
190199 fw_priv -> allocated_size = size ;
200+ fw_priv -> offset = offset ;
191201 fw_priv -> opt_flags = opt_flags ;
192202 fw_state_init (fw_priv );
193203#ifdef CONFIG_FW_LOADER_USER_HELPER
@@ -216,12 +226,17 @@ static int alloc_lookup_fw_priv(const char *fw_name,
216226 struct fw_priv * * fw_priv ,
217227 void * dbuf ,
218228 size_t size ,
229+ size_t offset ,
219230 u32 opt_flags )
220231{
221232 struct fw_priv * tmp ;
222233
223234 spin_lock (& fwc -> lock );
224- if (!(opt_flags & FW_OPT_NOCACHE )) {
235+ /*
236+ * Do not merge requests that are marked to be non-cached or
237+ * are performing partial reads.
238+ */
239+ if (!(opt_flags & (FW_OPT_NOCACHE | FW_OPT_PARTIAL ))) {
225240 tmp = __lookup_fw_priv (fw_name );
226241 if (tmp ) {
227242 kref_get (& tmp -> ref );
@@ -232,7 +247,7 @@ static int alloc_lookup_fw_priv(const char *fw_name,
232247 }
233248 }
234249
235- tmp = __allocate_fw_priv (fw_name , fwc , dbuf , size , opt_flags );
250+ tmp = __allocate_fw_priv (fw_name , fwc , dbuf , size , offset , opt_flags );
236251 if (tmp ) {
237252 INIT_LIST_HEAD (& tmp -> list );
238253 if (!(opt_flags & FW_OPT_NOCACHE ))
@@ -490,6 +505,9 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv,
490505 return - ENOMEM ;
491506
492507 for (i = 0 ; i < ARRAY_SIZE (fw_path ); i ++ ) {
508+ size_t file_size = 0 ;
509+ size_t * file_size_ptr = NULL ;
510+
493511 /* skip the unset customized path */
494512 if (!fw_path [i ][0 ])
495513 continue ;
@@ -503,9 +521,18 @@ fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv,
503521
504522 fw_priv -> size = 0 ;
505523
524+ /*
525+ * The total file size is only examined when doing a partial
526+ * read; the "full read" case needs to fail if the whole
527+ * firmware was not completely loaded.
528+ */
529+ if ((fw_priv -> opt_flags & FW_OPT_PARTIAL ) && buffer )
530+ file_size_ptr = & file_size ;
531+
506532 /* load firmware files from the mount namespace of init */
507- rc = kernel_read_file_from_path_initns (path , 0 , & buffer , msize ,
508- NULL ,
533+ rc = kernel_read_file_from_path_initns (path , fw_priv -> offset ,
534+ & buffer , msize ,
535+ file_size_ptr ,
509536 READING_FIRMWARE );
510537 if (rc < 0 ) {
511538 if (rc != - ENOENT )
@@ -696,7 +723,7 @@ int assign_fw(struct firmware *fw, struct device *device)
696723static int
697724_request_firmware_prepare (struct firmware * * firmware_p , const char * name ,
698725 struct device * device , void * dbuf , size_t size ,
699- u32 opt_flags )
726+ size_t offset , u32 opt_flags )
700727{
701728 struct firmware * firmware ;
702729 struct fw_priv * fw_priv ;
@@ -715,7 +742,7 @@ _request_firmware_prepare(struct firmware **firmware_p, const char *name,
715742 }
716743
717744 ret = alloc_lookup_fw_priv (name , & fw_cache , & fw_priv , dbuf , size ,
718- opt_flags );
745+ offset , opt_flags );
719746
720747 /*
721748 * bind with 'priv' now to avoid warning in failure path
@@ -762,9 +789,10 @@ static void fw_abort_batch_reqs(struct firmware *fw)
762789static int
763790_request_firmware (const struct firmware * * firmware_p , const char * name ,
764791 struct device * device , void * buf , size_t size ,
765- u32 opt_flags )
792+ size_t offset , u32 opt_flags )
766793{
767794 struct firmware * fw = NULL ;
795+ bool nondirect = false;
768796 int ret ;
769797
770798 if (!firmware_p )
@@ -776,26 +804,32 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
776804 }
777805
778806 ret = _request_firmware_prepare (& fw , name , device , buf , size ,
779- opt_flags );
807+ offset , opt_flags );
780808 if (ret <= 0 ) /* error or already assigned */
781809 goto out ;
782810
783811 ret = fw_get_filesystem_firmware (device , fw -> priv , "" , NULL );
812+
813+ /* Only full reads can support decompression, platform, and sysfs. */
814+ if (!(opt_flags & FW_OPT_PARTIAL ))
815+ nondirect = true;
816+
784817#ifdef CONFIG_FW_LOADER_COMPRESS
785- if (ret == - ENOENT )
818+ if (ret == - ENOENT && nondirect )
786819 ret = fw_get_filesystem_firmware (device , fw -> priv , ".xz" ,
787820 fw_decompress_xz );
788821#endif
789-
790- if (ret == - ENOENT )
822+ if (ret == - ENOENT && nondirect )
791823 ret = firmware_fallback_platform (fw -> priv );
792824
793825 if (ret ) {
794826 if (!(opt_flags & FW_OPT_NO_WARN ))
795827 dev_warn (device ,
796828 "Direct firmware load for %s failed with error %d\n" ,
797829 name , ret );
798- ret = firmware_fallback_sysfs (fw , name , device , opt_flags , ret );
830+ if (nondirect )
831+ ret = firmware_fallback_sysfs (fw , name , device ,
832+ opt_flags , ret );
799833 } else
800834 ret = assign_fw (fw , device );
801835
@@ -838,7 +872,7 @@ request_firmware(const struct firmware **firmware_p, const char *name,
838872
839873 /* Need to pin this module until return */
840874 __module_get (THIS_MODULE );
841- ret = _request_firmware (firmware_p , name , device , NULL , 0 ,
875+ ret = _request_firmware (firmware_p , name , device , NULL , 0 , 0 ,
842876 FW_OPT_UEVENT );
843877 module_put (THIS_MODULE );
844878 return ret ;
@@ -865,7 +899,7 @@ int firmware_request_nowarn(const struct firmware **firmware, const char *name,
865899
866900 /* Need to pin this module until return */
867901 __module_get (THIS_MODULE );
868- ret = _request_firmware (firmware , name , device , NULL , 0 ,
902+ ret = _request_firmware (firmware , name , device , NULL , 0 , 0 ,
869903 FW_OPT_UEVENT | FW_OPT_NO_WARN );
870904 module_put (THIS_MODULE );
871905 return ret ;
@@ -889,7 +923,7 @@ int request_firmware_direct(const struct firmware **firmware_p,
889923 int ret ;
890924
891925 __module_get (THIS_MODULE );
892- ret = _request_firmware (firmware_p , name , device , NULL , 0 ,
926+ ret = _request_firmware (firmware_p , name , device , NULL , 0 , 0 ,
893927 FW_OPT_UEVENT | FW_OPT_NO_WARN |
894928 FW_OPT_NOFALLBACK_SYSFS );
895929 module_put (THIS_MODULE );
@@ -914,7 +948,7 @@ int firmware_request_platform(const struct firmware **firmware,
914948
915949 /* Need to pin this module until return */
916950 __module_get (THIS_MODULE );
917- ret = _request_firmware (firmware , name , device , NULL , 0 ,
951+ ret = _request_firmware (firmware , name , device , NULL , 0 , 0 ,
918952 FW_OPT_UEVENT | FW_OPT_FALLBACK_PLATFORM );
919953 module_put (THIS_MODULE );
920954 return ret ;
@@ -970,13 +1004,44 @@ request_firmware_into_buf(const struct firmware **firmware_p, const char *name,
9701004 return - EOPNOTSUPP ;
9711005
9721006 __module_get (THIS_MODULE );
973- ret = _request_firmware (firmware_p , name , device , buf , size ,
1007+ ret = _request_firmware (firmware_p , name , device , buf , size , 0 ,
9741008 FW_OPT_UEVENT | FW_OPT_NOCACHE );
9751009 module_put (THIS_MODULE );
9761010 return ret ;
9771011}
9781012EXPORT_SYMBOL (request_firmware_into_buf );
9791013
1014+ /**
1015+ * request_partial_firmware_into_buf() - load partial firmware into a previously allocated buffer
1016+ * @firmware_p: pointer to firmware image
1017+ * @name: name of firmware file
1018+ * @device: device for which firmware is being loaded and DMA region allocated
1019+ * @buf: address of buffer to load firmware into
1020+ * @size: size of buffer
1021+ * @offset: offset into file to read
1022+ *
1023+ * This function works pretty much like request_firmware_into_buf except
1024+ * it allows a partial read of the file.
1025+ */
1026+ int
1027+ request_partial_firmware_into_buf (const struct firmware * * firmware_p ,
1028+ const char * name , struct device * device ,
1029+ void * buf , size_t size , size_t offset )
1030+ {
1031+ int ret ;
1032+
1033+ if (fw_cache_is_setup (device , name ))
1034+ return - EOPNOTSUPP ;
1035+
1036+ __module_get (THIS_MODULE );
1037+ ret = _request_firmware (firmware_p , name , device , buf , size , offset ,
1038+ FW_OPT_UEVENT | FW_OPT_NOCACHE |
1039+ FW_OPT_PARTIAL );
1040+ module_put (THIS_MODULE );
1041+ return ret ;
1042+ }
1043+ EXPORT_SYMBOL (request_partial_firmware_into_buf );
1044+
9801045/**
9811046 * release_firmware() - release the resource associated with a firmware image
9821047 * @fw: firmware resource to release
@@ -1009,7 +1074,7 @@ static void request_firmware_work_func(struct work_struct *work)
10091074
10101075 fw_work = container_of (work , struct firmware_work , work );
10111076
1012- _request_firmware (& fw , fw_work -> name , fw_work -> device , NULL , 0 ,
1077+ _request_firmware (& fw , fw_work -> name , fw_work -> device , NULL , 0 , 0 ,
10131078 fw_work -> opt_flags );
10141079 fw_work -> cont (fw , fw_work -> context );
10151080 put_device (fw_work -> device ); /* taken in request_firmware_nowait() */
0 commit comments