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