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_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 */ 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 /* Defensive check */ 50 if (!accel_dev || accel_dev->accel_id > ADF_MAX_DEVICES) 51 return EINVAL; 52 53 if (!adf_dev_started(accel_dev)) { 54 device_printf(GET_DEV(accel_dev), "QAT Device not started\n"); 55 return EINVAL; 56 } 57 58 hw_device = accel_dev->hw_device; 59 if (!hw_device) { 60 device_printf(GET_DEV(accel_dev), "Failed to get hw_device.\n"); 61 return EFAULT; 62 } 63 64 /* Clean report memory */ 65 explicit_bzero(report, sizeof(report)); 66 67 /* Adding banner to report */ 68 bytes_written = PRINT_LINE(NEW_LINE); 69 if (bytes_written <= 0) 70 return EINVAL; 71 report_ptr += bytes_written; 72 73 bytes_written = PRINT_LINE(LINE); 74 if (bytes_written <= 0) 75 return EINVAL; 76 report_ptr += bytes_written; 77 78 bytes_written = PRINT_LINE(BANNER); 79 if (bytes_written <= 0) 80 return EINVAL; 81 report_ptr += bytes_written; 82 83 bytes_written = PRINT_LINE(LINE); 84 if (bytes_written <= 0) 85 return EINVAL; 86 report_ptr += bytes_written; 87 88 if (accel_dev->au_info) 89 dc_ae_msk = accel_dev->au_info->dc_ae_msk; 90 91 /* Extracting number of Acceleration Engines */ 92 num_aes = hw_device->get_num_aes(hw_device); 93 for (ae = 0; ae < num_aes; ae++) { 94 if (accel_dev->au_info && !test_bit(ae, &dc_ae_msk)) 95 continue; 96 explicit_bzero(&response, 97 sizeof(struct icp_qat_fw_init_admin_resp)); 98 request.cmd_id = ICP_QAT_FW_CNV_STATS_GET; 99 if (adf_put_admin_msg_sync( 100 accel_dev, ae, &request, &response) || 101 response.status) { 102 return EFAULT; 103 } 104 error_type = CNV_ERROR_TYPE_GET(response.latest_error); 105 if (error_type == CNV_ERR_TYPE_DECOMP_PRODUCED_LENGTH_ERROR || 106 error_type == CNV_ERR_TYPE_DECOMP_CONSUMED_LENGTH_ERROR) { 107 latest_error = 108 CNV_ERROR_LENGTH_DELTA_GET(response.latest_error); 109 } else if (error_type == CNV_ERR_TYPE_DECOMPRESSION_ERROR || 110 error_type == CNV_ERR_TYPE_TRANSLATION_ERROR) { 111 latest_error = 112 CNV_ERROR_DECOMP_STATUS_GET(response.latest_error); 113 } else { 114 latest_error = 115 response.latest_error & ADF_CNVNR_ERR_MASK; 116 } 117 118 bytes_written = 119 snprintf(report_ptr, 120 MAX_REPORT_SIZE - (report_ptr - report), 121 REPORT_ENTRY_FORMAT, 122 ae, 123 response.error_count, 124 cnvnr_err_str[error_type], 125 latest_error); 126 if (bytes_written <= 0) { 127 printf("ERROR: No space left in CnV ctrs line buffer\n" 128 "\tAcceleration ID: %d, Engine: %d\n", 129 accel_dev->accel_id, 130 ae); 131 break; 132 } 133 report_ptr += bytes_written; 134 } 135 136 sysctl_handle_string(oidp, report, sizeof(report), req); 137 return 0; 138 } 139 140 int 141 adf_cnvnr_freq_counters_add(struct adf_accel_dev *accel_dev) 142 { 143 struct sysctl_ctx_list *qat_sysctl_ctx; 144 struct sysctl_oid *qat_cnvnr_ctrs_sysctl_tree; 145 struct sysctl_oid *oid_rc; 146 147 /* Defensive checks */ 148 if (!accel_dev) 149 return EINVAL; 150 151 /* Creating context and tree */ 152 qat_sysctl_ctx = 153 device_get_sysctl_ctx(accel_dev->accel_pci_dev.pci_dev); 154 qat_cnvnr_ctrs_sysctl_tree = 155 device_get_sysctl_tree(accel_dev->accel_pci_dev.pci_dev); 156 157 /* Create "cnv_error" string type leaf - with callback */ 158 oid_rc = SYSCTL_ADD_PROC(qat_sysctl_ctx, 159 SYSCTL_CHILDREN(qat_cnvnr_ctrs_sysctl_tree), 160 OID_AUTO, 161 "cnv_error", 162 CTLTYPE_STRING | CTLFLAG_RD, 163 accel_dev, 164 0, 165 qat_cnvnr_ctrs_dbg_read, 166 "IU", 167 "QAT CnVnR status"); 168 169 if (!oid_rc) { 170 printf("ERROR: Memory allocation failed\n"); 171 return ENOMEM; 172 } 173 return 0; 174 } 175 176 void 177 adf_cnvnr_freq_counters_remove(struct adf_accel_dev *accel_dev) 178 { 179 } 180