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