.. | .. |
---|
4 | 4 | * |
---|
5 | 5 | * Copyright (c) 2003 Manuel Estrada Sainz |
---|
6 | 6 | * |
---|
7 | | - * Please see Documentation/firmware_class/ for more information. |
---|
| 7 | + * Please see Documentation/driver-api/firmware/ for more information. |
---|
8 | 8 | * |
---|
9 | 9 | */ |
---|
10 | 10 | |
---|
.. | .. |
---|
12 | 12 | |
---|
13 | 13 | #include <linux/capability.h> |
---|
14 | 14 | #include <linux/device.h> |
---|
| 15 | +#include <linux/kernel_read_file.h> |
---|
15 | 16 | #include <linux/module.h> |
---|
16 | 17 | #include <linux/init.h> |
---|
17 | 18 | #include <linux/timer.h> |
---|
.. | .. |
---|
33 | 34 | #include <linux/syscore_ops.h> |
---|
34 | 35 | #include <linux/reboot.h> |
---|
35 | 36 | #include <linux/security.h> |
---|
| 37 | +#include <linux/xz.h> |
---|
36 | 38 | |
---|
37 | 39 | #include <generated/utsrelease.h> |
---|
38 | 40 | |
---|
.. | .. |
---|
89 | 91 | DEFINE_MUTEX(fw_lock); |
---|
90 | 92 | |
---|
91 | 93 | static struct firmware_cache fw_cache; |
---|
| 94 | +bool fw_load_abort_all; |
---|
92 | 95 | |
---|
93 | 96 | /* Builtin firmware support */ |
---|
94 | 97 | |
---|
.. | .. |
---|
163 | 166 | return __fw_state_wait_common(fw_priv, MAX_SCHEDULE_TIMEOUT); |
---|
164 | 167 | } |
---|
165 | 168 | |
---|
166 | | -static int fw_cache_piggyback_on_request(const char *name); |
---|
| 169 | +static void fw_cache_piggyback_on_request(struct fw_priv *fw_priv); |
---|
167 | 170 | |
---|
168 | 171 | static struct fw_priv *__allocate_fw_priv(const char *fw_name, |
---|
169 | 172 | struct firmware_cache *fwc, |
---|
170 | | - void *dbuf, size_t size) |
---|
| 173 | + void *dbuf, |
---|
| 174 | + size_t size, |
---|
| 175 | + size_t offset, |
---|
| 176 | + u32 opt_flags) |
---|
171 | 177 | { |
---|
172 | 178 | struct fw_priv *fw_priv; |
---|
| 179 | + |
---|
| 180 | + /* For a partial read, the buffer must be preallocated. */ |
---|
| 181 | + if ((opt_flags & FW_OPT_PARTIAL) && !dbuf) |
---|
| 182 | + return NULL; |
---|
| 183 | + |
---|
| 184 | + /* Only partial reads are allowed to use an offset. */ |
---|
| 185 | + if (offset != 0 && !(opt_flags & FW_OPT_PARTIAL)) |
---|
| 186 | + return NULL; |
---|
173 | 187 | |
---|
174 | 188 | fw_priv = kzalloc(sizeof(*fw_priv), GFP_ATOMIC); |
---|
175 | 189 | if (!fw_priv) |
---|
.. | .. |
---|
185 | 199 | fw_priv->fwc = fwc; |
---|
186 | 200 | fw_priv->data = dbuf; |
---|
187 | 201 | fw_priv->allocated_size = size; |
---|
| 202 | + fw_priv->offset = offset; |
---|
| 203 | + fw_priv->opt_flags = opt_flags; |
---|
188 | 204 | fw_state_init(fw_priv); |
---|
189 | 205 | #ifdef CONFIG_FW_LOADER_USER_HELPER |
---|
190 | 206 | INIT_LIST_HEAD(&fw_priv->pending_list); |
---|
.. | .. |
---|
209 | 225 | /* Returns 1 for batching firmware requests with the same name */ |
---|
210 | 226 | static int alloc_lookup_fw_priv(const char *fw_name, |
---|
211 | 227 | struct firmware_cache *fwc, |
---|
212 | | - struct fw_priv **fw_priv, void *dbuf, |
---|
213 | | - size_t size, enum fw_opt opt_flags) |
---|
| 228 | + struct fw_priv **fw_priv, |
---|
| 229 | + void *dbuf, |
---|
| 230 | + size_t size, |
---|
| 231 | + size_t offset, |
---|
| 232 | + u32 opt_flags) |
---|
214 | 233 | { |
---|
215 | 234 | struct fw_priv *tmp; |
---|
216 | 235 | |
---|
217 | 236 | spin_lock(&fwc->lock); |
---|
218 | | - if (!(opt_flags & FW_OPT_NOCACHE)) { |
---|
| 237 | + /* |
---|
| 238 | + * Do not merge requests that are marked to be non-cached or |
---|
| 239 | + * are performing partial reads. |
---|
| 240 | + */ |
---|
| 241 | + if (!(opt_flags & (FW_OPT_NOCACHE | FW_OPT_PARTIAL))) { |
---|
219 | 242 | tmp = __lookup_fw_priv(fw_name); |
---|
220 | 243 | if (tmp) { |
---|
221 | 244 | kref_get(&tmp->ref); |
---|
.. | .. |
---|
226 | 249 | } |
---|
227 | 250 | } |
---|
228 | 251 | |
---|
229 | | - tmp = __allocate_fw_priv(fw_name, fwc, dbuf, size); |
---|
| 252 | + tmp = __allocate_fw_priv(fw_name, fwc, dbuf, size, offset, opt_flags); |
---|
230 | 253 | if (tmp) { |
---|
231 | 254 | INIT_LIST_HEAD(&tmp->list); |
---|
232 | 255 | if (!(opt_flags & FW_OPT_NOCACHE)) |
---|
.. | .. |
---|
252 | 275 | list_del(&fw_priv->list); |
---|
253 | 276 | spin_unlock(&fwc->lock); |
---|
254 | 277 | |
---|
255 | | -#ifdef CONFIG_FW_LOADER_USER_HELPER |
---|
256 | | - if (fw_priv->is_paged_buf) { |
---|
257 | | - int i; |
---|
258 | | - vunmap(fw_priv->data); |
---|
259 | | - for (i = 0; i < fw_priv->nr_pages; i++) |
---|
260 | | - __free_page(fw_priv->pages[i]); |
---|
261 | | - vfree(fw_priv->pages); |
---|
262 | | - } else |
---|
263 | | -#endif |
---|
264 | | - if (!fw_priv->allocated_size) |
---|
| 278 | + if (fw_is_paged_buf(fw_priv)) |
---|
| 279 | + fw_free_paged_buf(fw_priv); |
---|
| 280 | + else if (!fw_priv->allocated_size) |
---|
265 | 281 | vfree(fw_priv->data); |
---|
| 282 | + |
---|
266 | 283 | kfree_const(fw_priv->fw_name); |
---|
267 | 284 | kfree(fw_priv); |
---|
268 | 285 | } |
---|
.. | .. |
---|
274 | 291 | if (!kref_put(&fw_priv->ref, __free_fw_priv)) |
---|
275 | 292 | spin_unlock(&fwc->lock); |
---|
276 | 293 | } |
---|
| 294 | + |
---|
| 295 | +#ifdef CONFIG_FW_LOADER_PAGED_BUF |
---|
| 296 | +bool fw_is_paged_buf(struct fw_priv *fw_priv) |
---|
| 297 | +{ |
---|
| 298 | + return fw_priv->is_paged_buf; |
---|
| 299 | +} |
---|
| 300 | + |
---|
| 301 | +void fw_free_paged_buf(struct fw_priv *fw_priv) |
---|
| 302 | +{ |
---|
| 303 | + int i; |
---|
| 304 | + |
---|
| 305 | + if (!fw_priv->pages) |
---|
| 306 | + return; |
---|
| 307 | + |
---|
| 308 | + vunmap(fw_priv->data); |
---|
| 309 | + |
---|
| 310 | + for (i = 0; i < fw_priv->nr_pages; i++) |
---|
| 311 | + __free_page(fw_priv->pages[i]); |
---|
| 312 | + kvfree(fw_priv->pages); |
---|
| 313 | + fw_priv->pages = NULL; |
---|
| 314 | + fw_priv->page_array_size = 0; |
---|
| 315 | + fw_priv->nr_pages = 0; |
---|
| 316 | +} |
---|
| 317 | + |
---|
| 318 | +int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) |
---|
| 319 | +{ |
---|
| 320 | + /* If the array of pages is too small, grow it */ |
---|
| 321 | + if (fw_priv->page_array_size < pages_needed) { |
---|
| 322 | + int new_array_size = max(pages_needed, |
---|
| 323 | + fw_priv->page_array_size * 2); |
---|
| 324 | + struct page **new_pages; |
---|
| 325 | + |
---|
| 326 | + new_pages = kvmalloc_array(new_array_size, sizeof(void *), |
---|
| 327 | + GFP_KERNEL); |
---|
| 328 | + if (!new_pages) |
---|
| 329 | + return -ENOMEM; |
---|
| 330 | + memcpy(new_pages, fw_priv->pages, |
---|
| 331 | + fw_priv->page_array_size * sizeof(void *)); |
---|
| 332 | + memset(&new_pages[fw_priv->page_array_size], 0, sizeof(void *) * |
---|
| 333 | + (new_array_size - fw_priv->page_array_size)); |
---|
| 334 | + kvfree(fw_priv->pages); |
---|
| 335 | + fw_priv->pages = new_pages; |
---|
| 336 | + fw_priv->page_array_size = new_array_size; |
---|
| 337 | + } |
---|
| 338 | + |
---|
| 339 | + while (fw_priv->nr_pages < pages_needed) { |
---|
| 340 | + fw_priv->pages[fw_priv->nr_pages] = |
---|
| 341 | + alloc_page(GFP_KERNEL | __GFP_HIGHMEM); |
---|
| 342 | + |
---|
| 343 | + if (!fw_priv->pages[fw_priv->nr_pages]) |
---|
| 344 | + return -ENOMEM; |
---|
| 345 | + fw_priv->nr_pages++; |
---|
| 346 | + } |
---|
| 347 | + |
---|
| 348 | + return 0; |
---|
| 349 | +} |
---|
| 350 | + |
---|
| 351 | +int fw_map_paged_buf(struct fw_priv *fw_priv) |
---|
| 352 | +{ |
---|
| 353 | + /* one pages buffer should be mapped/unmapped only once */ |
---|
| 354 | + if (!fw_priv->pages) |
---|
| 355 | + return 0; |
---|
| 356 | + |
---|
| 357 | + vunmap(fw_priv->data); |
---|
| 358 | + fw_priv->data = vmap(fw_priv->pages, fw_priv->nr_pages, 0, |
---|
| 359 | + PAGE_KERNEL_RO); |
---|
| 360 | + if (!fw_priv->data) |
---|
| 361 | + return -ENOMEM; |
---|
| 362 | + |
---|
| 363 | + return 0; |
---|
| 364 | +} |
---|
| 365 | +#endif |
---|
| 366 | + |
---|
| 367 | +/* |
---|
| 368 | + * XZ-compressed firmware support |
---|
| 369 | + */ |
---|
| 370 | +#ifdef CONFIG_FW_LOADER_COMPRESS |
---|
| 371 | +/* show an error and return the standard error code */ |
---|
| 372 | +static int fw_decompress_xz_error(struct device *dev, enum xz_ret xz_ret) |
---|
| 373 | +{ |
---|
| 374 | + if (xz_ret != XZ_STREAM_END) { |
---|
| 375 | + dev_warn(dev, "xz decompression failed (xz_ret=%d)\n", xz_ret); |
---|
| 376 | + return xz_ret == XZ_MEM_ERROR ? -ENOMEM : -EINVAL; |
---|
| 377 | + } |
---|
| 378 | + return 0; |
---|
| 379 | +} |
---|
| 380 | + |
---|
| 381 | +/* single-shot decompression onto the pre-allocated buffer */ |
---|
| 382 | +static int fw_decompress_xz_single(struct device *dev, struct fw_priv *fw_priv, |
---|
| 383 | + size_t in_size, const void *in_buffer) |
---|
| 384 | +{ |
---|
| 385 | + struct xz_dec *xz_dec; |
---|
| 386 | + struct xz_buf xz_buf; |
---|
| 387 | + enum xz_ret xz_ret; |
---|
| 388 | + |
---|
| 389 | + xz_dec = xz_dec_init(XZ_SINGLE, (u32)-1); |
---|
| 390 | + if (!xz_dec) |
---|
| 391 | + return -ENOMEM; |
---|
| 392 | + |
---|
| 393 | + xz_buf.in_size = in_size; |
---|
| 394 | + xz_buf.in = in_buffer; |
---|
| 395 | + xz_buf.in_pos = 0; |
---|
| 396 | + xz_buf.out_size = fw_priv->allocated_size; |
---|
| 397 | + xz_buf.out = fw_priv->data; |
---|
| 398 | + xz_buf.out_pos = 0; |
---|
| 399 | + |
---|
| 400 | + xz_ret = xz_dec_run(xz_dec, &xz_buf); |
---|
| 401 | + xz_dec_end(xz_dec); |
---|
| 402 | + |
---|
| 403 | + fw_priv->size = xz_buf.out_pos; |
---|
| 404 | + return fw_decompress_xz_error(dev, xz_ret); |
---|
| 405 | +} |
---|
| 406 | + |
---|
| 407 | +/* decompression on paged buffer and map it */ |
---|
| 408 | +static int fw_decompress_xz_pages(struct device *dev, struct fw_priv *fw_priv, |
---|
| 409 | + size_t in_size, const void *in_buffer) |
---|
| 410 | +{ |
---|
| 411 | + struct xz_dec *xz_dec; |
---|
| 412 | + struct xz_buf xz_buf; |
---|
| 413 | + enum xz_ret xz_ret; |
---|
| 414 | + struct page *page; |
---|
| 415 | + int err = 0; |
---|
| 416 | + |
---|
| 417 | + xz_dec = xz_dec_init(XZ_DYNALLOC, (u32)-1); |
---|
| 418 | + if (!xz_dec) |
---|
| 419 | + return -ENOMEM; |
---|
| 420 | + |
---|
| 421 | + xz_buf.in_size = in_size; |
---|
| 422 | + xz_buf.in = in_buffer; |
---|
| 423 | + xz_buf.in_pos = 0; |
---|
| 424 | + |
---|
| 425 | + fw_priv->is_paged_buf = true; |
---|
| 426 | + fw_priv->size = 0; |
---|
| 427 | + do { |
---|
| 428 | + if (fw_grow_paged_buf(fw_priv, fw_priv->nr_pages + 1)) { |
---|
| 429 | + err = -ENOMEM; |
---|
| 430 | + goto out; |
---|
| 431 | + } |
---|
| 432 | + |
---|
| 433 | + /* decompress onto the new allocated page */ |
---|
| 434 | + page = fw_priv->pages[fw_priv->nr_pages - 1]; |
---|
| 435 | + xz_buf.out = kmap(page); |
---|
| 436 | + xz_buf.out_pos = 0; |
---|
| 437 | + xz_buf.out_size = PAGE_SIZE; |
---|
| 438 | + xz_ret = xz_dec_run(xz_dec, &xz_buf); |
---|
| 439 | + kunmap(page); |
---|
| 440 | + fw_priv->size += xz_buf.out_pos; |
---|
| 441 | + /* partial decompression means either end or error */ |
---|
| 442 | + if (xz_buf.out_pos != PAGE_SIZE) |
---|
| 443 | + break; |
---|
| 444 | + } while (xz_ret == XZ_OK); |
---|
| 445 | + |
---|
| 446 | + err = fw_decompress_xz_error(dev, xz_ret); |
---|
| 447 | + if (!err) |
---|
| 448 | + err = fw_map_paged_buf(fw_priv); |
---|
| 449 | + |
---|
| 450 | + out: |
---|
| 451 | + xz_dec_end(xz_dec); |
---|
| 452 | + return err; |
---|
| 453 | +} |
---|
| 454 | + |
---|
| 455 | +static int fw_decompress_xz(struct device *dev, struct fw_priv *fw_priv, |
---|
| 456 | + size_t in_size, const void *in_buffer) |
---|
| 457 | +{ |
---|
| 458 | + /* if the buffer is pre-allocated, we can perform in single-shot mode */ |
---|
| 459 | + if (fw_priv->data) |
---|
| 460 | + return fw_decompress_xz_single(dev, fw_priv, in_size, in_buffer); |
---|
| 461 | + else |
---|
| 462 | + return fw_decompress_xz_pages(dev, fw_priv, in_size, in_buffer); |
---|
| 463 | +} |
---|
| 464 | +#endif /* CONFIG_FW_LOADER_COMPRESS */ |
---|
277 | 465 | |
---|
278 | 466 | /* direct firmware loading support */ |
---|
279 | 467 | static char fw_path_para[256]; |
---|
.. | .. |
---|
294 | 482 | MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path"); |
---|
295 | 483 | |
---|
296 | 484 | static int |
---|
297 | | -fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv) |
---|
| 485 | +fw_get_filesystem_firmware(struct device *device, struct fw_priv *fw_priv, |
---|
| 486 | + const char *suffix, |
---|
| 487 | + int (*decompress)(struct device *dev, |
---|
| 488 | + struct fw_priv *fw_priv, |
---|
| 489 | + size_t in_size, |
---|
| 490 | + const void *in_buffer)) |
---|
298 | 491 | { |
---|
299 | | - loff_t size; |
---|
| 492 | + size_t size; |
---|
300 | 493 | int i, len; |
---|
301 | 494 | int rc = -ENOENT; |
---|
302 | 495 | char *path; |
---|
303 | | - enum kernel_read_file_id id = READING_FIRMWARE; |
---|
304 | 496 | size_t msize = INT_MAX; |
---|
| 497 | + void *buffer = NULL; |
---|
305 | 498 | |
---|
306 | 499 | /* Already populated data member means we're loading into a buffer */ |
---|
307 | | - if (fw_priv->data) { |
---|
308 | | - id = READING_FIRMWARE_PREALLOC_BUFFER; |
---|
| 500 | + if (!decompress && fw_priv->data) { |
---|
| 501 | + buffer = fw_priv->data; |
---|
309 | 502 | msize = fw_priv->allocated_size; |
---|
310 | 503 | } |
---|
311 | 504 | |
---|
.. | .. |
---|
314 | 507 | return -ENOMEM; |
---|
315 | 508 | |
---|
316 | 509 | for (i = 0; i < ARRAY_SIZE(fw_path); i++) { |
---|
| 510 | + size_t file_size = 0; |
---|
| 511 | + size_t *file_size_ptr = NULL; |
---|
| 512 | + |
---|
317 | 513 | /* skip the unset customized path */ |
---|
318 | 514 | if (!fw_path[i][0]) |
---|
319 | 515 | continue; |
---|
320 | 516 | |
---|
321 | | - len = snprintf(path, PATH_MAX, "%s/%s", |
---|
322 | | - fw_path[i], fw_priv->fw_name); |
---|
| 517 | + len = snprintf(path, PATH_MAX, "%s/%s%s", |
---|
| 518 | + fw_path[i], fw_priv->fw_name, suffix); |
---|
323 | 519 | if (len >= PATH_MAX) { |
---|
324 | 520 | rc = -ENAMETOOLONG; |
---|
325 | 521 | break; |
---|
326 | 522 | } |
---|
327 | 523 | |
---|
328 | 524 | fw_priv->size = 0; |
---|
329 | | - rc = kernel_read_file_from_path(path, &fw_priv->data, &size, |
---|
330 | | - msize, id); |
---|
331 | | - if (rc) { |
---|
332 | | - if (rc == -ENOENT) |
---|
333 | | - dev_dbg(device, "loading %s failed with error %d\n", |
---|
334 | | - path, rc); |
---|
335 | | - else |
---|
| 525 | + |
---|
| 526 | + /* |
---|
| 527 | + * The total file size is only examined when doing a partial |
---|
| 528 | + * read; the "full read" case needs to fail if the whole |
---|
| 529 | + * firmware was not completely loaded. |
---|
| 530 | + */ |
---|
| 531 | + if ((fw_priv->opt_flags & FW_OPT_PARTIAL) && buffer) |
---|
| 532 | + file_size_ptr = &file_size; |
---|
| 533 | + |
---|
| 534 | + /* load firmware files from the mount namespace of init */ |
---|
| 535 | + rc = kernel_read_file_from_path_initns(path, fw_priv->offset, |
---|
| 536 | + &buffer, msize, |
---|
| 537 | + file_size_ptr, |
---|
| 538 | + READING_FIRMWARE); |
---|
| 539 | + if (rc < 0) { |
---|
| 540 | + if (rc != -ENOENT) |
---|
336 | 541 | dev_warn(device, "loading %s failed with error %d\n", |
---|
337 | 542 | path, rc); |
---|
| 543 | + else |
---|
| 544 | + dev_dbg(device, "loading %s failed for no such file or directory.\n", |
---|
| 545 | + path); |
---|
338 | 546 | continue; |
---|
339 | 547 | } |
---|
340 | | - dev_dbg(device, "direct-loading %s\n", fw_priv->fw_name); |
---|
341 | | - fw_priv->size = size; |
---|
| 548 | + size = rc; |
---|
| 549 | + rc = 0; |
---|
| 550 | + |
---|
| 551 | + dev_dbg(device, "Loading firmware from %s\n", path); |
---|
| 552 | + if (decompress) { |
---|
| 553 | + dev_dbg(device, "f/w decompressing %s\n", |
---|
| 554 | + fw_priv->fw_name); |
---|
| 555 | + rc = decompress(device, fw_priv, size, buffer); |
---|
| 556 | + /* discard the superfluous original content */ |
---|
| 557 | + vfree(buffer); |
---|
| 558 | + buffer = NULL; |
---|
| 559 | + if (rc) { |
---|
| 560 | + fw_free_paged_buf(fw_priv); |
---|
| 561 | + continue; |
---|
| 562 | + } |
---|
| 563 | + } else { |
---|
| 564 | + dev_dbg(device, "direct-loading %s\n", |
---|
| 565 | + fw_priv->fw_name); |
---|
| 566 | + if (!fw_priv->data) |
---|
| 567 | + fw_priv->data = buffer; |
---|
| 568 | + fw_priv->size = size; |
---|
| 569 | + } |
---|
342 | 570 | fw_state_done(fw_priv); |
---|
343 | 571 | break; |
---|
344 | 572 | } |
---|
.. | .. |
---|
362 | 590 | static void fw_set_page_data(struct fw_priv *fw_priv, struct firmware *fw) |
---|
363 | 591 | { |
---|
364 | 592 | fw->priv = fw_priv; |
---|
365 | | -#ifdef CONFIG_FW_LOADER_USER_HELPER |
---|
366 | | - fw->pages = fw_priv->pages; |
---|
367 | | -#endif |
---|
368 | 593 | fw->size = fw_priv->size; |
---|
369 | 594 | fw->data = fw_priv->data; |
---|
370 | 595 | |
---|
.. | .. |
---|
449 | 674 | } |
---|
450 | 675 | #endif |
---|
451 | 676 | |
---|
452 | | -int assign_fw(struct firmware *fw, struct device *device, |
---|
453 | | - enum fw_opt opt_flags) |
---|
| 677 | +int assign_fw(struct firmware *fw, struct device *device) |
---|
454 | 678 | { |
---|
455 | 679 | struct fw_priv *fw_priv = fw->priv; |
---|
456 | 680 | int ret; |
---|
.. | .. |
---|
469 | 693 | * should be fixed in devres or driver core. |
---|
470 | 694 | */ |
---|
471 | 695 | /* don't cache firmware handled without uevent */ |
---|
472 | | - if (device && (opt_flags & FW_OPT_UEVENT) && |
---|
473 | | - !(opt_flags & FW_OPT_NOCACHE)) { |
---|
| 696 | + if (device && (fw_priv->opt_flags & FW_OPT_UEVENT) && |
---|
| 697 | + !(fw_priv->opt_flags & FW_OPT_NOCACHE)) { |
---|
474 | 698 | ret = fw_add_devm_name(device, fw_priv->fw_name); |
---|
475 | 699 | if (ret) { |
---|
476 | 700 | mutex_unlock(&fw_lock); |
---|
.. | .. |
---|
482 | 706 | * After caching firmware image is started, let it piggyback |
---|
483 | 707 | * on request firmware. |
---|
484 | 708 | */ |
---|
485 | | - if (!(opt_flags & FW_OPT_NOCACHE) && |
---|
486 | | - fw_priv->fwc->state == FW_LOADER_START_CACHE) { |
---|
487 | | - if (fw_cache_piggyback_on_request(fw_priv->fw_name)) |
---|
488 | | - kref_get(&fw_priv->ref); |
---|
489 | | - } |
---|
| 709 | + if (!(fw_priv->opt_flags & FW_OPT_NOCACHE) && |
---|
| 710 | + fw_priv->fwc->state == FW_LOADER_START_CACHE) |
---|
| 711 | + fw_cache_piggyback_on_request(fw_priv); |
---|
490 | 712 | |
---|
491 | 713 | /* pass the pages buffer to driver at the last minute */ |
---|
492 | 714 | fw_set_page_data(fw_priv, fw); |
---|
.. | .. |
---|
501 | 723 | static int |
---|
502 | 724 | _request_firmware_prepare(struct firmware **firmware_p, const char *name, |
---|
503 | 725 | struct device *device, void *dbuf, size_t size, |
---|
504 | | - enum fw_opt opt_flags) |
---|
| 726 | + size_t offset, u32 opt_flags) |
---|
505 | 727 | { |
---|
506 | 728 | struct firmware *firmware; |
---|
507 | 729 | struct fw_priv *fw_priv; |
---|
.. | .. |
---|
520 | 742 | } |
---|
521 | 743 | |
---|
522 | 744 | ret = alloc_lookup_fw_priv(name, &fw_cache, &fw_priv, dbuf, size, |
---|
523 | | - opt_flags); |
---|
| 745 | + offset, opt_flags); |
---|
524 | 746 | |
---|
525 | 747 | /* |
---|
526 | 748 | * bind with 'priv' now to avoid warning in failure path |
---|
.. | .. |
---|
569 | 791 | static int |
---|
570 | 792 | _request_firmware(const struct firmware **firmware_p, const char *name, |
---|
571 | 793 | struct device *device, void *buf, size_t size, |
---|
572 | | - enum fw_opt opt_flags) |
---|
| 794 | + size_t offset, u32 opt_flags) |
---|
573 | 795 | { |
---|
574 | 796 | struct firmware *fw = NULL; |
---|
| 797 | + bool nondirect = false; |
---|
575 | 798 | int ret; |
---|
576 | 799 | |
---|
577 | 800 | if (!firmware_p) |
---|
.. | .. |
---|
583 | 806 | } |
---|
584 | 807 | |
---|
585 | 808 | ret = _request_firmware_prepare(&fw, name, device, buf, size, |
---|
586 | | - opt_flags); |
---|
| 809 | + offset, opt_flags); |
---|
587 | 810 | if (ret <= 0) /* error or already assigned */ |
---|
588 | 811 | goto out; |
---|
589 | 812 | |
---|
590 | | - ret = fw_get_filesystem_firmware(device, fw->priv); |
---|
| 813 | + ret = fw_get_filesystem_firmware(device, fw->priv, "", NULL); |
---|
| 814 | + |
---|
| 815 | + /* Only full reads can support decompression, platform, and sysfs. */ |
---|
| 816 | + if (!(opt_flags & FW_OPT_PARTIAL)) |
---|
| 817 | + nondirect = true; |
---|
| 818 | + |
---|
| 819 | +#ifdef CONFIG_FW_LOADER_COMPRESS |
---|
| 820 | + if (ret == -ENOENT && nondirect) |
---|
| 821 | + ret = fw_get_filesystem_firmware(device, fw->priv, ".xz", |
---|
| 822 | + fw_decompress_xz); |
---|
| 823 | +#endif |
---|
| 824 | + if (ret == -ENOENT && nondirect) |
---|
| 825 | + ret = firmware_fallback_platform(fw->priv); |
---|
| 826 | + |
---|
591 | 827 | if (ret) { |
---|
592 | 828 | if (!(opt_flags & FW_OPT_NO_WARN)) |
---|
593 | 829 | dev_warn(device, |
---|
594 | 830 | "Direct firmware load for %s failed with error %d\n", |
---|
595 | 831 | name, ret); |
---|
596 | | - ret = firmware_fallback_sysfs(fw, name, device, opt_flags, ret); |
---|
| 832 | + if (nondirect) |
---|
| 833 | + ret = firmware_fallback_sysfs(fw, name, device, |
---|
| 834 | + opt_flags, ret); |
---|
597 | 835 | } else |
---|
598 | | - ret = assign_fw(fw, device, opt_flags); |
---|
| 836 | + ret = assign_fw(fw, device); |
---|
599 | 837 | |
---|
600 | 838 | out: |
---|
601 | 839 | if (ret < 0) { |
---|
.. | .. |
---|
636 | 874 | |
---|
637 | 875 | /* Need to pin this module until return */ |
---|
638 | 876 | __module_get(THIS_MODULE); |
---|
639 | | - ret = _request_firmware(firmware_p, name, device, NULL, 0, |
---|
| 877 | + ret = _request_firmware(firmware_p, name, device, NULL, 0, 0, |
---|
640 | 878 | FW_OPT_UEVENT); |
---|
641 | 879 | module_put(THIS_MODULE); |
---|
642 | 880 | return ret; |
---|
.. | .. |
---|
649 | 887 | * @name: name of firmware file |
---|
650 | 888 | * @device: device for which firmware is being loaded |
---|
651 | 889 | * |
---|
652 | | - * This function is similar in behaviour to request_firmware(), except |
---|
653 | | - * it doesn't produce warning messages when the file is not found. |
---|
654 | | - * The sysfs fallback mechanism is enabled if direct filesystem lookup fails, |
---|
655 | | - * however, however failures to find the firmware file with it are still |
---|
656 | | - * suppressed. It is therefore up to the driver to check for the return value |
---|
657 | | - * of this call and to decide when to inform the users of errors. |
---|
| 890 | + * This function is similar in behaviour to request_firmware(), except it |
---|
| 891 | + * doesn't produce warning messages when the file is not found. The sysfs |
---|
| 892 | + * fallback mechanism is enabled if direct filesystem lookup fails. However, |
---|
| 893 | + * failures to find the firmware file with it are still suppressed. It is |
---|
| 894 | + * therefore up to the driver to check for the return value of this call and to |
---|
| 895 | + * decide when to inform the users of errors. |
---|
658 | 896 | **/ |
---|
659 | 897 | int firmware_request_nowarn(const struct firmware **firmware, const char *name, |
---|
660 | 898 | struct device *device) |
---|
.. | .. |
---|
663 | 901 | |
---|
664 | 902 | /* Need to pin this module until return */ |
---|
665 | 903 | __module_get(THIS_MODULE); |
---|
666 | | - ret = _request_firmware(firmware, name, device, NULL, 0, |
---|
| 904 | + ret = _request_firmware(firmware, name, device, NULL, 0, 0, |
---|
667 | 905 | FW_OPT_UEVENT | FW_OPT_NO_WARN); |
---|
668 | 906 | module_put(THIS_MODULE); |
---|
669 | 907 | return ret; |
---|
.. | .. |
---|
687 | 925 | int ret; |
---|
688 | 926 | |
---|
689 | 927 | __module_get(THIS_MODULE); |
---|
690 | | - ret = _request_firmware(firmware_p, name, device, NULL, 0, |
---|
| 928 | + ret = _request_firmware(firmware_p, name, device, NULL, 0, 0, |
---|
691 | 929 | FW_OPT_UEVENT | FW_OPT_NO_WARN | |
---|
692 | | - FW_OPT_NOFALLBACK); |
---|
| 930 | + FW_OPT_NOFALLBACK_SYSFS); |
---|
693 | 931 | module_put(THIS_MODULE); |
---|
694 | 932 | return ret; |
---|
695 | 933 | } |
---|
696 | 934 | EXPORT_SYMBOL_GPL(request_firmware_direct); |
---|
| 935 | + |
---|
| 936 | +/** |
---|
| 937 | + * firmware_request_platform() - request firmware with platform-fw fallback |
---|
| 938 | + * @firmware: pointer to firmware image |
---|
| 939 | + * @name: name of firmware file |
---|
| 940 | + * @device: device for which firmware is being loaded |
---|
| 941 | + * |
---|
| 942 | + * This function is similar in behaviour to request_firmware, except that if |
---|
| 943 | + * direct filesystem lookup fails, it will fallback to looking for a copy of the |
---|
| 944 | + * requested firmware embedded in the platform's main (e.g. UEFI) firmware. |
---|
| 945 | + **/ |
---|
| 946 | +int firmware_request_platform(const struct firmware **firmware, |
---|
| 947 | + const char *name, struct device *device) |
---|
| 948 | +{ |
---|
| 949 | + int ret; |
---|
| 950 | + |
---|
| 951 | + /* Need to pin this module until return */ |
---|
| 952 | + __module_get(THIS_MODULE); |
---|
| 953 | + ret = _request_firmware(firmware, name, device, NULL, 0, 0, |
---|
| 954 | + FW_OPT_UEVENT | FW_OPT_FALLBACK_PLATFORM); |
---|
| 955 | + module_put(THIS_MODULE); |
---|
| 956 | + return ret; |
---|
| 957 | +} |
---|
| 958 | +EXPORT_SYMBOL_GPL(firmware_request_platform); |
---|
697 | 959 | |
---|
698 | 960 | /** |
---|
699 | 961 | * firmware_request_cache() - cache firmware for suspend so resume can use it |
---|
.. | .. |
---|
744 | 1006 | return -EOPNOTSUPP; |
---|
745 | 1007 | |
---|
746 | 1008 | __module_get(THIS_MODULE); |
---|
747 | | - ret = _request_firmware(firmware_p, name, device, buf, size, |
---|
| 1009 | + ret = _request_firmware(firmware_p, name, device, buf, size, 0, |
---|
748 | 1010 | FW_OPT_UEVENT | FW_OPT_NOCACHE); |
---|
749 | 1011 | module_put(THIS_MODULE); |
---|
750 | 1012 | return ret; |
---|
751 | 1013 | } |
---|
752 | 1014 | EXPORT_SYMBOL(request_firmware_into_buf); |
---|
| 1015 | + |
---|
| 1016 | +/** |
---|
| 1017 | + * request_partial_firmware_into_buf() - load partial firmware into a previously allocated buffer |
---|
| 1018 | + * @firmware_p: pointer to firmware image |
---|
| 1019 | + * @name: name of firmware file |
---|
| 1020 | + * @device: device for which firmware is being loaded and DMA region allocated |
---|
| 1021 | + * @buf: address of buffer to load firmware into |
---|
| 1022 | + * @size: size of buffer |
---|
| 1023 | + * @offset: offset into file to read |
---|
| 1024 | + * |
---|
| 1025 | + * This function works pretty much like request_firmware_into_buf except |
---|
| 1026 | + * it allows a partial read of the file. |
---|
| 1027 | + */ |
---|
| 1028 | +int |
---|
| 1029 | +request_partial_firmware_into_buf(const struct firmware **firmware_p, |
---|
| 1030 | + const char *name, struct device *device, |
---|
| 1031 | + void *buf, size_t size, size_t offset) |
---|
| 1032 | +{ |
---|
| 1033 | + int ret; |
---|
| 1034 | + |
---|
| 1035 | + if (fw_cache_is_setup(device, name)) |
---|
| 1036 | + return -EOPNOTSUPP; |
---|
| 1037 | + |
---|
| 1038 | + __module_get(THIS_MODULE); |
---|
| 1039 | + ret = _request_firmware(firmware_p, name, device, buf, size, offset, |
---|
| 1040 | + FW_OPT_UEVENT | FW_OPT_NOCACHE | |
---|
| 1041 | + FW_OPT_PARTIAL); |
---|
| 1042 | + module_put(THIS_MODULE); |
---|
| 1043 | + return ret; |
---|
| 1044 | +} |
---|
| 1045 | +EXPORT_SYMBOL(request_partial_firmware_into_buf); |
---|
753 | 1046 | |
---|
754 | 1047 | /** |
---|
755 | 1048 | * release_firmware() - release the resource associated with a firmware image |
---|
.. | .. |
---|
773 | 1066 | struct device *device; |
---|
774 | 1067 | void *context; |
---|
775 | 1068 | void (*cont)(const struct firmware *fw, void *context); |
---|
776 | | - enum fw_opt opt_flags; |
---|
| 1069 | + u32 opt_flags; |
---|
777 | 1070 | }; |
---|
778 | 1071 | |
---|
779 | 1072 | static void request_firmware_work_func(struct work_struct *work) |
---|
.. | .. |
---|
783 | 1076 | |
---|
784 | 1077 | fw_work = container_of(work, struct firmware_work, work); |
---|
785 | 1078 | |
---|
786 | | - _request_firmware(&fw, fw_work->name, fw_work->device, NULL, 0, |
---|
| 1079 | + _request_firmware(&fw, fw_work->name, fw_work->device, NULL, 0, 0, |
---|
787 | 1080 | fw_work->opt_flags); |
---|
788 | 1081 | fw_work->cont(fw, fw_work->context); |
---|
789 | 1082 | put_device(fw_work->device); /* taken in request_firmware_nowait() */ |
---|
.. | .. |
---|
964 | 1257 | return 0; |
---|
965 | 1258 | } |
---|
966 | 1259 | |
---|
967 | | -static int fw_cache_piggyback_on_request(const char *name) |
---|
| 1260 | +static void fw_cache_piggyback_on_request(struct fw_priv *fw_priv) |
---|
968 | 1261 | { |
---|
969 | | - struct firmware_cache *fwc = &fw_cache; |
---|
| 1262 | + const char *name = fw_priv->fw_name; |
---|
| 1263 | + struct firmware_cache *fwc = fw_priv->fwc; |
---|
970 | 1264 | struct fw_cache_entry *fce; |
---|
971 | | - int ret = 0; |
---|
972 | 1265 | |
---|
973 | 1266 | spin_lock(&fwc->name_lock); |
---|
974 | 1267 | if (__fw_entry_found(name)) |
---|
.. | .. |
---|
976 | 1269 | |
---|
977 | 1270 | fce = alloc_fw_cache_entry(name); |
---|
978 | 1271 | if (fce) { |
---|
979 | | - ret = 1; |
---|
980 | 1272 | list_add(&fce->list, &fwc->fw_names); |
---|
| 1273 | + kref_get(&fw_priv->ref); |
---|
981 | 1274 | pr_debug("%s: fw: %s\n", __func__, name); |
---|
982 | 1275 | } |
---|
983 | 1276 | found: |
---|
984 | 1277 | spin_unlock(&fwc->name_lock); |
---|
985 | | - return ret; |
---|
986 | 1278 | } |
---|
987 | 1279 | |
---|
988 | 1280 | static void free_fw_cache_entry(struct fw_cache_entry *fce) |
---|
.. | .. |
---|
1151 | 1443 | case PM_SUSPEND_PREPARE: |
---|
1152 | 1444 | case PM_RESTORE_PREPARE: |
---|
1153 | 1445 | /* |
---|
1154 | | - * kill pending fallback requests with a custom fallback |
---|
1155 | | - * to avoid stalling suspend. |
---|
| 1446 | + * Here, kill pending fallback requests will only kill |
---|
| 1447 | + * non-uevent firmware request to avoid stalling suspend. |
---|
1156 | 1448 | */ |
---|
1157 | | - kill_pending_fw_fallback_reqs(true); |
---|
| 1449 | + kill_pending_fw_fallback_reqs(false); |
---|
1158 | 1450 | device_cache_fw_images(); |
---|
1159 | 1451 | break; |
---|
1160 | 1452 | |
---|
.. | .. |
---|
1213 | 1505 | unregister_pm_notifier(&fw_cache.pm_notify); |
---|
1214 | 1506 | } |
---|
1215 | 1507 | #else |
---|
1216 | | -static int fw_cache_piggyback_on_request(const char *name) |
---|
| 1508 | +static void fw_cache_piggyback_on_request(struct fw_priv *fw_priv) |
---|
1217 | 1509 | { |
---|
1218 | | - return 0; |
---|
1219 | 1510 | } |
---|
1220 | 1511 | static inline int register_fw_pm_ops(void) |
---|
1221 | 1512 | { |
---|
.. | .. |
---|
1240 | 1531 | * Kill all pending fallback requests to avoid both stalling shutdown, |
---|
1241 | 1532 | * and avoid a deadlock with the usermode_lock. |
---|
1242 | 1533 | */ |
---|
1243 | | - kill_pending_fw_fallback_reqs(false); |
---|
| 1534 | + kill_pending_fw_fallback_reqs(true); |
---|
1244 | 1535 | |
---|
1245 | 1536 | return NOTIFY_DONE; |
---|
1246 | 1537 | } |
---|