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

Generated by: LCOV version 1.14