The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/qat/qat_common/adf_heartbeat.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /* SPDX-License-Identifier: BSD-3-Clause */
    2 /* Copyright(c) 2007-2022 Intel Corporation */
    3 /* $FreeBSD$ */
    4 #include <sys/types.h>
    5 #include <linux/random.h>
    6 #include "qat_freebsd.h"
    7 
    8 #include "adf_heartbeat.h"
    9 #include "adf_common_drv.h"
   10 #include "adf_cfg.h"
   11 #include "adf_cfg_strings.h"
   12 #include "icp_qat_fw_init_admin.h"
   13 #include "adf_transport_internal.h"
   14 
   15 #define MAX_HB_TICKS 0xFFFFFFFF
   16 
   17 static int
   18 adf_check_hb_poll_freq(struct adf_accel_dev *accel_dev)
   19 {
   20         u64 curr_hb_check_time = 0;
   21         char timer_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
   22         unsigned int timer_val = ADF_CFG_HB_DEFAULT_VALUE;
   23 
   24         curr_hb_check_time = adf_clock_get_current_time();
   25 
   26         if (!adf_cfg_get_param_value(accel_dev,
   27                                      ADF_GENERAL_SEC,
   28                                      ADF_HEARTBEAT_TIMER,
   29                                      (char *)timer_str)) {
   30                 if (compat_strtouint((char *)timer_str,
   31                                      ADF_CFG_BASE_DEC,
   32                                      &timer_val))
   33                         timer_val = ADF_CFG_HB_DEFAULT_VALUE;
   34         }
   35         if ((curr_hb_check_time - accel_dev->heartbeat->last_hb_check_time) <
   36             timer_val) {
   37                 return EINVAL;
   38         }
   39         accel_dev->heartbeat->last_hb_check_time = curr_hb_check_time;
   40 
   41         return 0;
   42 }
   43 
   44 int
   45 adf_heartbeat_init(struct adf_accel_dev *accel_dev)
   46 {
   47         if (accel_dev->heartbeat)
   48                 adf_heartbeat_clean(accel_dev);
   49 
   50         accel_dev->heartbeat =
   51             malloc(sizeof(*accel_dev->heartbeat), M_QAT, M_WAITOK | M_ZERO);
   52 
   53         return 0;
   54 }
   55 
   56 void
   57 adf_heartbeat_clean(struct adf_accel_dev *accel_dev)
   58 {
   59         free(accel_dev->heartbeat, M_QAT);
   60         accel_dev->heartbeat = NULL;
   61 }
   62 
   63 int
   64 adf_get_hb_timer(struct adf_accel_dev *accel_dev, unsigned int *value)
   65 {
   66         struct adf_hw_device_data *hw_data = accel_dev->hw_device;
   67         char timer_str[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
   68         unsigned int timer_val = ADF_CFG_HB_DEFAULT_VALUE;
   69         u32 clk_per_sec = 0;
   70 
   71         /* HB clock may be different than AE clock */
   72         if (hw_data->get_hb_clock) {
   73                 clk_per_sec = (u32)hw_data->get_hb_clock(hw_data);
   74         } else if (hw_data->get_ae_clock) {
   75                 clk_per_sec = (u32)hw_data->get_ae_clock(hw_data);
   76         } else {
   77                 return EINVAL;
   78         }
   79 
   80         /* Get Heartbeat Timer value from the configuration */
   81         if (!adf_cfg_get_param_value(accel_dev,
   82                                      ADF_GENERAL_SEC,
   83                                      ADF_HEARTBEAT_TIMER,
   84                                      (char *)timer_str)) {
   85                 if (compat_strtouint((char *)timer_str,
   86                                      ADF_CFG_BASE_DEC,
   87                                      &timer_val))
   88                         timer_val = ADF_CFG_HB_DEFAULT_VALUE;
   89         }
   90 
   91         if (timer_val < ADF_MIN_HB_TIMER_MS) {
   92                 device_printf(GET_DEV(accel_dev),
   93                               "%s value cannot be lesser than %u\n",
   94                               ADF_HEARTBEAT_TIMER,
   95                               ADF_MIN_HB_TIMER_MS);
   96                 return EINVAL;
   97         }
   98 
   99         /* Convert msec to clocks */
  100         clk_per_sec = clk_per_sec / 1000;
  101         *value = timer_val * clk_per_sec;
  102 
  103         return 0;
  104 }
  105 
  106 int
  107 adf_get_heartbeat_status(struct adf_accel_dev *accel_dev)
  108 {
  109         struct icp_qat_fw_init_admin_hb_cnt *live_s, *last_s, *curr_s;
  110         struct adf_hw_device_data *hw_device = accel_dev->hw_device;
  111         const size_t max_aes = hw_device->get_num_aes(hw_device);
  112         const size_t hb_ctrs = hw_device->heartbeat_ctr_num;
  113         const size_t stats_size =
  114             max_aes * hb_ctrs * sizeof(struct icp_qat_fw_init_admin_hb_cnt);
  115         int ret = 0;
  116         size_t ae, thr;
  117         u16 *count_s;
  118         unsigned long ae_mask = 0;
  119 
  120         /*
  121          * Memory layout of Heartbeat
  122          *
  123          * +----------------+----------------+---------+
  124          * |   Live value   |   Last value   |  Count  |
  125          * +----------------+----------------+---------+
  126          * \_______________/\_______________/\________/
  127          *         ^                ^            ^
  128          *         |                |            |
  129          *         |                |            max_aes * hb_ctrs *
  130          *         |                |            sizeof(u16)
  131          *         |                |
  132          *         |                max_aes * hb_ctrs *
  133          *         |                sizeof(icp_qat_fw_init_admin_hb_cnt)
  134          *         |
  135          *         max_aes * hb_ctrs *
  136          *         sizeof(icp_qat_fw_init_admin_hb_cnt)
  137          */
  138         live_s = (struct icp_qat_fw_init_admin_hb_cnt *)
  139                      accel_dev->admin->virt_hb_addr;
  140         last_s = live_s + (max_aes * hb_ctrs);
  141         count_s = (u16 *)(last_s + (max_aes * hb_ctrs));
  142 
  143         curr_s = malloc(stats_size, M_QAT, M_WAITOK | M_ZERO);
  144 
  145         memcpy(curr_s, live_s, stats_size);
  146         ae_mask = hw_device->ae_mask;
  147 
  148         for_each_set_bit(ae, &ae_mask, max_aes)
  149         {
  150                 struct icp_qat_fw_init_admin_hb_cnt *curr =
  151                     curr_s + ae * hb_ctrs;
  152                 struct icp_qat_fw_init_admin_hb_cnt *prev =
  153                     last_s + ae * hb_ctrs;
  154                 u16 *count = count_s + ae * hb_ctrs;
  155 
  156                 for (thr = 0; thr < hb_ctrs; ++thr) {
  157                         u16 req = curr[thr].req_heartbeat_cnt;
  158                         u16 resp = curr[thr].resp_heartbeat_cnt;
  159                         u16 last = prev[thr].resp_heartbeat_cnt;
  160 
  161                         if ((thr == ADF_AE_ADMIN_THREAD || req != resp) &&
  162                             resp == last) {
  163                                 u16 retry = ++count[thr];
  164 
  165                                 if (retry >= ADF_CFG_HB_COUNT_THRESHOLD)
  166                                         ret = EIO;
  167                         } else {
  168                                 count[thr] = 0;
  169                         }
  170                 }
  171         }
  172 
  173         /* Copy current stats for the next iteration */
  174         memcpy(last_s, curr_s, stats_size);
  175         free(curr_s, M_QAT);
  176 
  177         return ret;
  178 }
  179 
  180 int
  181 adf_heartbeat_status(struct adf_accel_dev *accel_dev,
  182                      enum adf_device_heartbeat_status *hb_status)
  183 {
  184         /* Heartbeat is not implemented in VFs at the moment so they do not
  185          * set get_heartbeat_status. Also, in case the device is not up,
  186          * unsupported should be returned */
  187         if (!accel_dev || !accel_dev->hw_device ||
  188             !accel_dev->hw_device->get_heartbeat_status ||
  189             !accel_dev->heartbeat) {
  190                 *hb_status = DEV_HB_UNSUPPORTED;
  191                 return 0;
  192         }
  193 
  194         if (!adf_dev_started(accel_dev) ||
  195             test_bit(ADF_STATUS_RESTARTING, &accel_dev->status)) {
  196                 *hb_status = DEV_HB_UNRESPONSIVE;
  197                 accel_dev->heartbeat->last_hb_status = DEV_HB_UNRESPONSIVE;
  198                 return 0;
  199         }
  200 
  201         if (adf_check_hb_poll_freq(accel_dev) == EINVAL) {
  202                 *hb_status = accel_dev->heartbeat->last_hb_status;
  203                 return 0;
  204         }
  205 
  206         accel_dev->heartbeat->hb_sent_counter++;
  207         if (unlikely(accel_dev->hw_device->get_heartbeat_status(accel_dev))) {
  208                 device_printf(GET_DEV(accel_dev),
  209                               "ERROR: QAT is not responding.\n");
  210                 *hb_status = DEV_HB_UNRESPONSIVE;
  211                 accel_dev->heartbeat->last_hb_status = DEV_HB_UNRESPONSIVE;
  212                 accel_dev->heartbeat->hb_failed_counter++;
  213                 return adf_notify_fatal_error(accel_dev);
  214         }
  215 
  216         *hb_status = DEV_HB_ALIVE;
  217         accel_dev->heartbeat->last_hb_status = DEV_HB_ALIVE;
  218 
  219         return 0;
  220 }

Cache object: 80b58d70e7d896ab319bdfda262a6001


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.