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 */ 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 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 176 adf_cnvnr_freq_counters_remove(struct adf_accel_dev *accel_dev) 177 { 178 } 179