1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 #include <sys/types.h>
4 #include <sys/sysctl.h>
5 #include <sys/systm.h>
6 #include "adf_cnvnr_freq_counters.h"
7 #include "adf_common_drv.h"
8 #include "adf_cfg.h"
9 #include "icp_qat_fw_init_admin.h"
10
11 #define ADF_CNVNR_ERR_MASK 0xFFF
12
13 #define LINE \
14 "+-----------------------------------------------------------------+\n"
15 #define BANNER \
16 "| CNV Error Freq Statistics for Qat Device |\n"
17 #define NEW_LINE "\n"
18 #define REPORT_ENTRY_FORMAT \
19 "|[AE %2d]: TotalErrors: %5d : LastError: %s [%5d] |\n"
20 #define MAX_LINE_LENGTH 128
21 #define MAX_REPORT_SIZE ((ADF_MAX_ACCELENGINES + 3) * MAX_LINE_LENGTH)
22
23 #define PRINT_LINE(line) \
24 (snprintf( \
25 report_ptr, MAX_REPORT_SIZE - (report_ptr - report), "%s", line))
26
27 const char *cnvnr_err_str[] = {"No Error ",
28 "Checksum Error",
29 "Length Error-P",
30 "Decomp Error ",
31 "Xlat Error ",
32 "Length Error-C",
33 "Unknown Error "};
34
35 /* Handler for HB status check */
qat_cnvnr_ctrs_dbg_read(SYSCTL_HANDLER_ARGS)36 static int qat_cnvnr_ctrs_dbg_read(SYSCTL_HANDLER_ARGS)
37 {
38 struct adf_accel_dev *accel_dev = arg1;
39 struct adf_hw_device_data *hw_device;
40 struct icp_qat_fw_init_admin_req request;
41 struct icp_qat_fw_init_admin_resp response;
42 unsigned long dc_ae_msk = 0;
43 u8 num_aes = 0, ae = 0, error_type = 0, bytes_written = 0;
44 s16 latest_error = 0;
45 char report[MAX_REPORT_SIZE];
46 char *report_ptr = report;
47
48 /* Defensive check */
49 if (!accel_dev || accel_dev->accel_id > ADF_MAX_DEVICES)
50 return EINVAL;
51
52 if (!adf_dev_started(accel_dev)) {
53 device_printf(GET_DEV(accel_dev), "QAT Device not started\n");
54 return EINVAL;
55 }
56
57 hw_device = accel_dev->hw_device;
58 if (!hw_device) {
59 device_printf(GET_DEV(accel_dev), "Failed to get hw_device.\n");
60 return EFAULT;
61 }
62
63 /* Clean report memory */
64 explicit_bzero(report, sizeof(report));
65
66 /* Adding banner to report */
67 bytes_written = PRINT_LINE(NEW_LINE);
68 if (bytes_written <= 0)
69 return EINVAL;
70 report_ptr += bytes_written;
71
72 bytes_written = PRINT_LINE(LINE);
73 if (bytes_written <= 0)
74 return EINVAL;
75 report_ptr += bytes_written;
76
77 bytes_written = PRINT_LINE(BANNER);
78 if (bytes_written <= 0)
79 return EINVAL;
80 report_ptr += bytes_written;
81
82 bytes_written = PRINT_LINE(LINE);
83 if (bytes_written <= 0)
84 return EINVAL;
85 report_ptr += bytes_written;
86
87 if (accel_dev->au_info)
88 dc_ae_msk = accel_dev->au_info->dc_ae_msk;
89
90 /* Extracting number of Acceleration Engines */
91 num_aes = hw_device->get_num_aes(hw_device);
92 for (ae = 0; ae < num_aes; ae++) {
93 if (accel_dev->au_info && !test_bit(ae, &dc_ae_msk))
94 continue;
95 explicit_bzero(&response,
96 sizeof(struct icp_qat_fw_init_admin_resp));
97 request.cmd_id = ICP_QAT_FW_CNV_STATS_GET;
98 if (adf_put_admin_msg_sync(
99 accel_dev, ae, &request, &response) ||
100 response.status) {
101 return EFAULT;
102 }
103 error_type = CNV_ERROR_TYPE_GET(response.latest_error);
104 if (error_type == CNV_ERR_TYPE_DECOMP_PRODUCED_LENGTH_ERROR ||
105 error_type == CNV_ERR_TYPE_DECOMP_CONSUMED_LENGTH_ERROR) {
106 latest_error =
107 CNV_ERROR_LENGTH_DELTA_GET(response.latest_error);
108 } else if (error_type == CNV_ERR_TYPE_DECOMPRESSION_ERROR ||
109 error_type == CNV_ERR_TYPE_TRANSLATION_ERROR) {
110 latest_error =
111 CNV_ERROR_DECOMP_STATUS_GET(response.latest_error);
112 } else {
113 latest_error =
114 response.latest_error & ADF_CNVNR_ERR_MASK;
115 }
116
117 bytes_written =
118 snprintf(report_ptr,
119 MAX_REPORT_SIZE - (report_ptr - report),
120 REPORT_ENTRY_FORMAT,
121 ae,
122 response.error_count,
123 cnvnr_err_str[error_type],
124 latest_error);
125 if (bytes_written <= 0) {
126 printf("ERROR: No space left in CnV ctrs line buffer\n"
127 "\tAcceleration ID: %d, Engine: %d\n",
128 accel_dev->accel_id,
129 ae);
130 break;
131 }
132 report_ptr += bytes_written;
133 }
134
135 sysctl_handle_string(oidp, report, sizeof(report), req);
136 return 0;
137 }
138
139 int
adf_cnvnr_freq_counters_add(struct adf_accel_dev * accel_dev)140 adf_cnvnr_freq_counters_add(struct adf_accel_dev *accel_dev)
141 {
142 struct sysctl_ctx_list *qat_sysctl_ctx;
143 struct sysctl_oid *qat_cnvnr_ctrs_sysctl_tree;
144 struct sysctl_oid *oid_rc;
145
146 /* Defensive checks */
147 if (!accel_dev)
148 return EINVAL;
149
150 /* Creating context and tree */
151 qat_sysctl_ctx =
152 device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev);
153 qat_cnvnr_ctrs_sysctl_tree =
154 device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev);
155
156 /* Create "cnv_error" string type leaf - with callback */
157 oid_rc = SYSCTL_ADD_PROC(qat_sysctl_ctx,
158 SYSCTL_CHILDREN(qat_cnvnr_ctrs_sysctl_tree),
159 OID_AUTO,
160 "cnv_error",
161 CTLTYPE_STRING | CTLFLAG_RD,
162 accel_dev,
163 0,
164 qat_cnvnr_ctrs_dbg_read,
165 "IU",
166 "QAT CnVnR status");
167
168 if (!oid_rc) {
169 printf("ERROR: Memory allocation failed\n");
170 return ENOMEM;
171 }
172 return 0;
173 }
174
175 void
adf_cnvnr_freq_counters_remove(struct adf_accel_dev * accel_dev)176 adf_cnvnr_freq_counters_remove(struct adf_accel_dev *accel_dev)
177 {
178 }
179