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_fw_counters.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 <sys/sysctl.h>
    6 #include <sys/systm.h>
    7 #include "adf_accel_devices.h"
    8 #include "adf_fw_counters.h"
    9 #include "adf_common_drv.h"
   10 #include "icp_qat_fw_init_admin.h"
   11 #include <sys/mutex.h>
   12 #include <sys/sbuf.h>
   13 #define ADF_FW_COUNTERS_BUF_SZ 4096
   14 
   15 #define ADF_RAS_EVENT_STR "RAS events"
   16 #define ADF_FW_REQ_STR "Firmware Requests"
   17 #define ADF_FW_RESP_STR "Firmware Responses"
   18 
   19 static void adf_fw_counters_section_del_all(struct list_head *head);
   20 static void adf_fw_counters_del_all(struct adf_accel_dev *accel_dev);
   21 static int
   22 adf_fw_counters_add_key_value_param(struct adf_accel_dev *accel_dev,
   23                                     const char *section_name,
   24                                     const unsigned long sec_name_max_size,
   25                                     const char *key,
   26                                     const void *val);
   27 static int adf_fw_counters_section_add(struct adf_accel_dev *accel_dev,
   28                                        const char *name,
   29                                        const unsigned long name_max_size);
   30 int adf_get_fw_counters(struct adf_accel_dev *accel_dev);
   31 int adf_read_fw_counters(SYSCTL_HANDLER_ARGS);
   32 
   33 int
   34 adf_get_fw_counters(struct adf_accel_dev *accel_dev)
   35 {
   36         struct icp_qat_fw_init_admin_req req;
   37         struct icp_qat_fw_init_admin_resp resp;
   38         unsigned long ae_mask;
   39         int i;
   40         int ret = 0;
   41         char aeidstr[16] = { 0 };
   42         struct adf_hw_device_data *hw_device;
   43 
   44         if (!accel_dev) {
   45                 ret = EFAULT;
   46                 goto fail_clean;
   47         }
   48         if (!adf_dev_started(accel_dev)) {
   49                 device_printf(GET_DEV(accel_dev), "Qat Device not started\n");
   50                 ret = EFAULT;
   51                 goto fail_clean;
   52         }
   53 
   54         hw_device = accel_dev->hw_device;
   55         if (!hw_device) {
   56                 ret = EFAULT;
   57                 goto fail_clean;
   58         }
   59 
   60         adf_fw_counters_del_all(accel_dev);
   61         explicit_bzero(&req, sizeof(struct icp_qat_fw_init_admin_req));
   62         req.cmd_id = ICP_QAT_FW_COUNTERS_GET;
   63         ae_mask = hw_device->ae_mask;
   64         for_each_set_bit(i, &ae_mask, GET_MAX_ACCELENGINES(accel_dev))
   65         {
   66                 explicit_bzero(&resp,
   67                                sizeof(struct icp_qat_fw_init_admin_resp));
   68                 if (adf_put_admin_msg_sync(accel_dev, i, &req, &resp) ||
   69                     resp.status) {
   70                         resp.req_rec_count = ADF_FW_COUNTERS_NO_RESPONSE;
   71                         resp.resp_sent_count = ADF_FW_COUNTERS_NO_RESPONSE;
   72                         resp.ras_event_count = ADF_FW_COUNTERS_NO_RESPONSE;
   73                 }
   74                 explicit_bzero(aeidstr, sizeof(aeidstr));
   75                 snprintf(aeidstr, sizeof(aeidstr), "AE %2d", i);
   76 
   77                 if (adf_fw_counters_section_add(accel_dev,
   78                                                 aeidstr,
   79                                                 sizeof(aeidstr))) {
   80                         ret = ENOMEM;
   81                         goto fail_clean;
   82                 }
   83 
   84                 if (adf_fw_counters_add_key_value_param(
   85                         accel_dev,
   86                         aeidstr,
   87                         sizeof(aeidstr),
   88                         ADF_FW_REQ_STR,
   89                         (void *)&resp.req_rec_count)) {
   90                         adf_fw_counters_del_all(accel_dev);
   91                         ret = ENOMEM;
   92                         goto fail_clean;
   93                 }
   94 
   95                 if (adf_fw_counters_add_key_value_param(
   96                         accel_dev,
   97                         aeidstr,
   98                         sizeof(aeidstr),
   99                         ADF_FW_RESP_STR,
  100                         (void *)&resp.resp_sent_count)) {
  101                         adf_fw_counters_del_all(accel_dev);
  102                         ret = ENOMEM;
  103                         goto fail_clean;
  104                 }
  105 
  106                 if (hw_device->count_ras_event &&
  107                     hw_device->count_ras_event(accel_dev,
  108                                                (void *)&resp.ras_event_count,
  109                                                aeidstr)) {
  110                         adf_fw_counters_del_all(accel_dev);
  111                         ret = ENOMEM;
  112                         goto fail_clean;
  113                 }
  114         }
  115 
  116 fail_clean:
  117         return ret;
  118 }
  119 
  120 int adf_read_fw_counters(SYSCTL_HANDLER_ARGS)
  121 {
  122         struct adf_accel_dev *accel_dev = arg1;
  123         struct adf_fw_counters_section *ptr = NULL;
  124         struct list_head *list = NULL, *list_ptr = NULL;
  125         struct list_head *tmp = NULL, *tmp_val = NULL;
  126         int ret = 0;
  127         struct sbuf *sbuf = NULL;
  128         char *cbuf = NULL;
  129 
  130         if (accel_dev == NULL) {
  131                 return EINVAL;
  132         }
  133         cbuf = malloc(ADF_FW_COUNTERS_BUF_SZ, M_QAT, M_WAITOK | M_ZERO);
  134 
  135         sbuf = sbuf_new(NULL, cbuf, ADF_FW_COUNTERS_BUF_SZ, SBUF_FIXEDLEN);
  136         if (sbuf == NULL) {
  137                 free(cbuf, M_QAT);
  138                 return ENOMEM;
  139         }
  140         ret = adf_get_fw_counters(accel_dev);
  141 
  142         if (ret) {
  143                 sbuf_delete(sbuf);
  144                 free(cbuf, M_QAT);
  145                 return ret;
  146         }
  147 
  148         sbuf_printf(sbuf,
  149                     "\n+------------------------------------------------+\n");
  150         sbuf_printf(
  151             sbuf,
  152             "| FW Statistics for Qat Device                                        |\n");
  153         sbuf_printf(sbuf,
  154                     "+------------------------------------------------+\n");
  155 
  156         list_for_each_prev_safe(list,
  157                                 tmp,
  158                                 &accel_dev->fw_counters_data->ae_sec_list)
  159         {
  160                 ptr = list_entry(list, struct adf_fw_counters_section, list);
  161                 sbuf_printf(sbuf, "%s\n", ptr->name);
  162                 list_for_each_prev_safe(list_ptr, tmp_val, &ptr->param_head)
  163                 {
  164                         struct adf_fw_counters_val *count =
  165                             list_entry(list_ptr,
  166                                        struct adf_fw_counters_val,
  167                                        list);
  168                         sbuf_printf(sbuf, "%s:%s\n", count->key, count->val);
  169                 }
  170         }
  171 
  172         sbuf_finish(sbuf);
  173         ret = SYSCTL_OUT(req, sbuf_data(sbuf), sbuf_len(sbuf));
  174         sbuf_delete(sbuf);
  175         free(cbuf, M_QAT);
  176         return ret;
  177 }
  178 
  179 int
  180 adf_fw_count_ras_event(struct adf_accel_dev *accel_dev,
  181                        u32 *ras_event,
  182                        char *aeidstr)
  183 {
  184         unsigned long count = 0;
  185 
  186         if (!accel_dev || !ras_event || !aeidstr)
  187                 return EINVAL;
  188 
  189         count = (*ras_event == ADF_FW_COUNTERS_NO_RESPONSE ?
  190                      ADF_FW_COUNTERS_NO_RESPONSE :
  191                      (unsigned long)*ras_event);
  192 
  193         return adf_fw_counters_add_key_value_param(
  194             accel_dev, aeidstr, 16, ADF_RAS_EVENT_STR, (void *)&count);
  195 }
  196 
  197 /**
  198  * adf_fw_counters_add() - Create an acceleration device FW counters table.
  199  * @accel_dev:  Pointer to acceleration device.
  200  *
  201  * Function creates a FW counters statistics table for the given
  202  * acceleration device.
  203  * The table stores device specific values of FW Requests sent to the FW and
  204  * FW Responses received from the FW.
  205  * To be used by QAT device specific drivers.
  206  *
  207  * Return: 0 on success, error code otherwise.
  208  */
  209 int
  210 adf_fw_counters_add(struct adf_accel_dev *accel_dev)
  211 {
  212         struct adf_fw_counters_data *fw_counters_data;
  213         struct sysctl_ctx_list *qat_sysctl_ctx;
  214         struct sysctl_oid *qat_sysctl_tree;
  215         struct sysctl_oid *rc = 0;
  216 
  217         fw_counters_data =
  218             malloc(sizeof(*fw_counters_data), M_QAT, M_WAITOK | M_ZERO);
  219 
  220         INIT_LIST_HEAD(&fw_counters_data->ae_sec_list);
  221 
  222         init_rwsem(&fw_counters_data->lock);
  223         accel_dev->fw_counters_data = fw_counters_data;
  224 
  225         qat_sysctl_ctx =
  226             device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev);
  227         qat_sysctl_tree =
  228             device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev);
  229         rc = SYSCTL_ADD_OID(qat_sysctl_ctx,
  230                             SYSCTL_CHILDREN(qat_sysctl_tree),
  231                             OID_AUTO,
  232                             "fw_counters",
  233                             CTLTYPE_STRING | CTLFLAG_RD,
  234                             accel_dev,
  235                             0,
  236                             adf_read_fw_counters,
  237                             "A",
  238                             "QAT FW counters");
  239         if (!rc)
  240                 return ENOMEM;
  241         else
  242                 return 0;
  243 }
  244 
  245 static void
  246 adf_fw_counters_del_all(struct adf_accel_dev *accel_dev)
  247 {
  248         struct adf_fw_counters_data *fw_counters_data =
  249             accel_dev->fw_counters_data;
  250 
  251         down_write(&fw_counters_data->lock);
  252         adf_fw_counters_section_del_all(&fw_counters_data->ae_sec_list);
  253         up_write(&fw_counters_data->lock);
  254 }
  255 
  256 static void
  257 adf_fw_counters_keyval_add(struct adf_fw_counters_val *new,
  258                            struct adf_fw_counters_section *sec)
  259 {
  260         list_add_tail(&new->list, &sec->param_head);
  261 }
  262 
  263 static void
  264 adf_fw_counters_keyval_del_all(struct list_head *head)
  265 {
  266         struct list_head *list_ptr = NULL, *tmp = NULL;
  267 
  268         list_for_each_prev_safe(list_ptr, tmp, head)
  269         {
  270                 struct adf_fw_counters_val *ptr =
  271                     list_entry(list_ptr, struct adf_fw_counters_val, list);
  272                 list_del(list_ptr);
  273                 free(ptr, M_QAT);
  274         }
  275 }
  276 
  277 static void
  278 adf_fw_counters_section_del_all(struct list_head *head)
  279 {
  280         struct adf_fw_counters_section *ptr = NULL;
  281         struct list_head *list = NULL, *tmp = NULL;
  282 
  283         list_for_each_prev_safe(list, tmp, head)
  284         {
  285                 ptr = list_entry(list, struct adf_fw_counters_section, list);
  286                 adf_fw_counters_keyval_del_all(&ptr->param_head);
  287                 list_del(list);
  288                 free(ptr, M_QAT);
  289         }
  290 }
  291 
  292 static struct adf_fw_counters_section *
  293 adf_fw_counters_sec_find(struct adf_accel_dev *accel_dev,
  294                          const char *sec_name,
  295                          const unsigned long sec_name_max_size)
  296 {
  297         struct adf_fw_counters_data *fw_counters_data =
  298             accel_dev->fw_counters_data;
  299         struct list_head *list = NULL;
  300 
  301         list_for_each(list, &fw_counters_data->ae_sec_list)
  302         {
  303                 struct adf_fw_counters_section *ptr =
  304                     list_entry(list, struct adf_fw_counters_section, list);
  305                 if (!strncmp(ptr->name, sec_name, sec_name_max_size))
  306                         return ptr;
  307         }
  308         return NULL;
  309 }
  310 
  311 static int
  312 adf_fw_counters_add_key_value_param(struct adf_accel_dev *accel_dev,
  313                                     const char *section_name,
  314                                     const unsigned long sec_name_max_size,
  315                                     const char *key,
  316                                     const void *val)
  317 {
  318         struct adf_fw_counters_data *fw_counters_data =
  319             accel_dev->fw_counters_data;
  320         struct adf_fw_counters_val *key_val;
  321         struct adf_fw_counters_section *section =
  322             adf_fw_counters_sec_find(accel_dev,
  323                                      section_name,
  324                                      sec_name_max_size);
  325         long tmp = *((const long *)val);
  326 
  327         if (!section)
  328                 return EFAULT;
  329         key_val = malloc(sizeof(*key_val), M_QAT, M_WAITOK | M_ZERO);
  330 
  331         INIT_LIST_HEAD(&key_val->list);
  332 
  333         if (tmp == ADF_FW_COUNTERS_NO_RESPONSE) {
  334                 snprintf(key_val->val,
  335                          FW_COUNTERS_MAX_VAL_LEN_IN_BYTES,
  336                          "No Response");
  337         } else {
  338                 snprintf(key_val->val,
  339                          FW_COUNTERS_MAX_VAL_LEN_IN_BYTES,
  340                          "%ld",
  341                          tmp);
  342         }
  343 
  344         strlcpy(key_val->key, key, sizeof(key_val->key));
  345         down_write(&fw_counters_data->lock);
  346         adf_fw_counters_keyval_add(key_val, section);
  347         up_write(&fw_counters_data->lock);
  348         return 0;
  349 }
  350 
  351 /**
  352  * adf_fw_counters_section_add() - Add AE section entry to FW counters table.
  353  * @accel_dev:  Pointer to acceleration device.
  354  * @name: Name of the section
  355  *
  356  * Function adds a section for each AE where FW Requests/Responses and their
  357  * values will be stored.
  358  * To be used by QAT device specific drivers.
  359  *
  360  * Return: 0 on success, error code otherwise.
  361  */
  362 static int
  363 adf_fw_counters_section_add(struct adf_accel_dev *accel_dev,
  364                             const char *name,
  365                             const unsigned long name_max_size)
  366 {
  367         struct adf_fw_counters_data *fw_counters_data =
  368             accel_dev->fw_counters_data;
  369         struct adf_fw_counters_section *sec =
  370             adf_fw_counters_sec_find(accel_dev, name, name_max_size);
  371 
  372         if (sec)
  373                 return 0;
  374 
  375         sec = malloc(sizeof(*sec), M_QAT, M_WAITOK | M_ZERO);
  376 
  377         strlcpy(sec->name, name, sizeof(sec->name));
  378         INIT_LIST_HEAD(&sec->param_head);
  379 
  380         down_write(&fw_counters_data->lock);
  381 
  382         list_add_tail(&sec->list, &fw_counters_data->ae_sec_list);
  383         up_write(&fw_counters_data->lock);
  384         return 0;
  385 }
  386 
  387 /**
  388  * adf_fw_counters_remove() - Clears acceleration device FW counters table.
  389  * @accel_dev:  Pointer to acceleration device.
  390  *
  391  * Function removes FW counters table from the given acceleration device
  392  * and frees all allocated memory.
  393  * To be used by QAT device specific drivers.
  394  *
  395  * Return: void
  396  */
  397 void
  398 adf_fw_counters_remove(struct adf_accel_dev *accel_dev)
  399 {
  400         struct adf_fw_counters_data *fw_counters_data =
  401             accel_dev->fw_counters_data;
  402 
  403         if (!fw_counters_data)
  404                 return;
  405 
  406         down_write(&fw_counters_data->lock);
  407         adf_fw_counters_section_del_all(&fw_counters_data->ae_sec_list);
  408         up_write(&fw_counters_data->lock);
  409         free(fw_counters_data, M_QAT);
  410         accel_dev->fw_counters_data = NULL;
  411 }

Cache object: d95d6becf2060827ad490bf1e05b3937


[ 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.