LCOV - code coverage report
Current view: top level - drivers/base/firmware_loader - firmware.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 14 0.0 %
Date: 2023-08-24 13:40:31 Functions: 0 1 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: GPL-2.0 */
       2             : #ifndef __FIRMWARE_LOADER_H
       3             : #define __FIRMWARE_LOADER_H
       4             : 
       5             : #include <linux/bitops.h>
       6             : #include <linux/firmware.h>
       7             : #include <linux/types.h>
       8             : #include <linux/kref.h>
       9             : #include <linux/list.h>
      10             : #include <linux/completion.h>
      11             : 
      12             : /**
      13             :  * enum fw_opt - options to control firmware loading behaviour
      14             :  *
      15             :  * @FW_OPT_UEVENT: Enables the fallback mechanism to send a kobject uevent
      16             :  *      when the firmware is not found. Userspace is in charge to load the
      17             :  *      firmware using the sysfs loading facility.
      18             :  * @FW_OPT_NOWAIT: Used to describe the firmware request is asynchronous.
      19             :  * @FW_OPT_USERHELPER: Enable the fallback mechanism, in case the direct
      20             :  *      filesystem lookup fails at finding the firmware.  For details refer to
      21             :  *      firmware_fallback_sysfs().
      22             :  * @FW_OPT_NO_WARN: Quiet, avoid printing warning messages.
      23             :  * @FW_OPT_NOCACHE: Disables firmware caching. Firmware caching is used to
      24             :  *      cache the firmware upon suspend, so that upon resume races against the
      25             :  *      firmware file lookup on storage is avoided. Used for calls where the
      26             :  *      file may be too big, or where the driver takes charge of its own
      27             :  *      firmware caching mechanism.
      28             :  * @FW_OPT_NOFALLBACK_SYSFS: Disable the sysfs fallback mechanism. Takes
      29             :  *      precedence over &FW_OPT_UEVENT and &FW_OPT_USERHELPER.
      30             :  * @FW_OPT_FALLBACK_PLATFORM: Enable fallback to device fw copy embedded in
      31             :  *      the platform's main firmware. If both this fallback and the sysfs
      32             :  *      fallback are enabled, then this fallback will be tried first.
      33             :  * @FW_OPT_PARTIAL: Allow partial read of firmware instead of needing to read
      34             :  *      entire file.
      35             :  */
      36             : enum fw_opt {
      37             :         FW_OPT_UEVENT                   = BIT(0),
      38             :         FW_OPT_NOWAIT                   = BIT(1),
      39             :         FW_OPT_USERHELPER               = BIT(2),
      40             :         FW_OPT_NO_WARN                  = BIT(3),
      41             :         FW_OPT_NOCACHE                  = BIT(4),
      42             :         FW_OPT_NOFALLBACK_SYSFS         = BIT(5),
      43             :         FW_OPT_FALLBACK_PLATFORM        = BIT(6),
      44             :         FW_OPT_PARTIAL                  = BIT(7),
      45             : };
      46             : 
      47             : enum fw_status {
      48             :         FW_STATUS_UNKNOWN,
      49             :         FW_STATUS_LOADING,
      50             :         FW_STATUS_DONE,
      51             :         FW_STATUS_ABORTED,
      52             : };
      53             : 
      54             : /*
      55             :  * Concurrent request_firmware() for the same firmware need to be
      56             :  * serialized.  struct fw_state is simple state machine which hold the
      57             :  * state of the firmware loading.
      58             :  */
      59             : struct fw_state {
      60             :         struct completion completion;
      61             :         enum fw_status status;
      62             : };
      63             : 
      64             : struct fw_priv {
      65             :         struct kref ref;
      66             :         struct list_head list;
      67             :         struct firmware_cache *fwc;
      68             :         struct fw_state fw_st;
      69             :         void *data;
      70             :         size_t size;
      71             :         size_t allocated_size;
      72             :         size_t offset;
      73             :         u32 opt_flags;
      74             : #ifdef CONFIG_FW_LOADER_PAGED_BUF
      75             :         bool is_paged_buf;
      76             :         struct page **pages;
      77             :         int nr_pages;
      78             :         int page_array_size;
      79             : #endif
      80             : #ifdef CONFIG_FW_LOADER_USER_HELPER
      81             :         bool need_uevent;
      82             :         struct list_head pending_list;
      83             : #endif
      84             :         const char *fw_name;
      85             : };
      86             : 
      87             : extern struct mutex fw_lock;
      88             : extern struct firmware_cache fw_cache;
      89             : 
      90             : static inline bool __fw_state_check(struct fw_priv *fw_priv,
      91             :                                     enum fw_status status)
      92             : {
      93           0 :         struct fw_state *fw_st = &fw_priv->fw_st;
      94             : 
      95           0 :         return fw_st->status == status;
      96             : }
      97             : 
      98           0 : static inline int __fw_state_wait_common(struct fw_priv *fw_priv, long timeout)
      99             : {
     100           0 :         struct fw_state *fw_st = &fw_priv->fw_st;
     101             :         long ret;
     102             : 
     103           0 :         ret = wait_for_completion_killable_timeout(&fw_st->completion, timeout);
     104           0 :         if (ret != 0 && fw_st->status == FW_STATUS_ABORTED)
     105             :                 return -ENOENT;
     106           0 :         if (!ret)
     107             :                 return -ETIMEDOUT;
     108             : 
     109           0 :         return ret < 0 ? ret : 0;
     110             : }
     111             : 
     112             : static inline void __fw_state_set(struct fw_priv *fw_priv,
     113             :                                   enum fw_status status)
     114             : {
     115           0 :         struct fw_state *fw_st = &fw_priv->fw_st;
     116             : 
     117           0 :         WRITE_ONCE(fw_st->status, status);
     118             : 
     119             :         if (status == FW_STATUS_DONE || status == FW_STATUS_ABORTED) {
     120             : #ifdef CONFIG_FW_LOADER_USER_HELPER
     121             :                 /*
     122             :                  * Doing this here ensures that the fw_priv is deleted from
     123             :                  * the pending list in all abort/done paths.
     124             :                  */
     125             :                 list_del_init(&fw_priv->pending_list);
     126             : #endif
     127           0 :                 complete_all(&fw_st->completion);
     128             :         }
     129             : }
     130             : 
     131             : static inline void fw_state_aborted(struct fw_priv *fw_priv)
     132             : {
     133           0 :         __fw_state_set(fw_priv, FW_STATUS_ABORTED);
     134             : }
     135             : 
     136             : static inline bool fw_state_is_aborted(struct fw_priv *fw_priv)
     137             : {
     138           0 :         return __fw_state_check(fw_priv, FW_STATUS_ABORTED);
     139             : }
     140             : 
     141             : static inline void fw_state_start(struct fw_priv *fw_priv)
     142             : {
     143             :         __fw_state_set(fw_priv, FW_STATUS_LOADING);
     144             : }
     145             : 
     146             : static inline void fw_state_done(struct fw_priv *fw_priv)
     147             : {
     148           0 :         __fw_state_set(fw_priv, FW_STATUS_DONE);
     149             : }
     150             : 
     151             : static inline bool fw_state_is_done(struct fw_priv *fw_priv)
     152             : {
     153             :         return __fw_state_check(fw_priv, FW_STATUS_DONE);
     154             : }
     155             : 
     156             : static inline bool fw_state_is_loading(struct fw_priv *fw_priv)
     157             : {
     158             :         return __fw_state_check(fw_priv, FW_STATUS_LOADING);
     159             : }
     160             : 
     161             : int alloc_lookup_fw_priv(const char *fw_name, struct firmware_cache *fwc,
     162             :                          struct fw_priv **fw_priv, void *dbuf, size_t size,
     163             :                          size_t offset, u32 opt_flags);
     164             : int assign_fw(struct firmware *fw, struct device *device);
     165             : void free_fw_priv(struct fw_priv *fw_priv);
     166             : void fw_state_init(struct fw_priv *fw_priv);
     167             : 
     168             : #ifdef CONFIG_FW_LOADER
     169             : bool firmware_is_builtin(const struct firmware *fw);
     170             : bool firmware_request_builtin_buf(struct firmware *fw, const char *name,
     171             :                                   void *buf, size_t size);
     172             : #else /* module case */
     173             : static inline bool firmware_is_builtin(const struct firmware *fw)
     174             : {
     175             :         return false;
     176             : }
     177             : static inline bool firmware_request_builtin_buf(struct firmware *fw,
     178             :                                                 const char *name,
     179             :                                                 void *buf, size_t size)
     180             : {
     181             :         return false;
     182             : }
     183             : #endif
     184             : 
     185             : #ifdef CONFIG_FW_LOADER_PAGED_BUF
     186             : void fw_free_paged_buf(struct fw_priv *fw_priv);
     187             : int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed);
     188             : int fw_map_paged_buf(struct fw_priv *fw_priv);
     189             : bool fw_is_paged_buf(struct fw_priv *fw_priv);
     190             : #else
     191             : static inline void fw_free_paged_buf(struct fw_priv *fw_priv) {}
     192             : static inline int fw_grow_paged_buf(struct fw_priv *fw_priv, int pages_needed) { return -ENXIO; }
     193             : static inline int fw_map_paged_buf(struct fw_priv *fw_priv) { return -ENXIO; }
     194             : static inline bool fw_is_paged_buf(struct fw_priv *fw_priv) { return false; }
     195             : #endif
     196             : 
     197             : #endif /* __FIRMWARE_LOADER_H */

Generated by: LCOV version 1.14