1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright(c) 2007-2022 Intel Corporation */ 3 /* $FreeBSD$ */ 4 #include "adf_dev_err.h" 5 6 struct reg_info { 7 size_t offs; 8 char *name; 9 }; 10 11 static struct reg_info adf_err_regs[] = { 12 { ADF_ERRSOU0, "ERRSOU0" }, 13 { ADF_ERRSOU1, "ERRSOU1" }, 14 { ADF_ERRSOU3, "ERRSOU3" }, 15 { ADF_ERRSOU4, "ERRSOU4" }, 16 { ADF_ERRSOU5, "ERRSOU5" }, 17 { ADF_RICPPINTSTS, "RICPPINTSTS" }, 18 { ADF_RIERRPUSHID, "RIERRPUSHID" }, 19 { ADF_RIERRPULLID, "RIERRPULLID" }, 20 { ADF_CPP_CFC_ERR_STATUS, "CPP_CFC_ERR_STATUS" }, 21 { ADF_CPP_CFC_ERR_PPID, "CPP_CFC_ERR_PPID" }, 22 { ADF_TICPPINTSTS, "TICPPINTSTS" }, 23 { ADF_TIERRPUSHID, "TIERRPUSHID" }, 24 { ADF_TIERRPULLID, "TIERRPULLID" }, 25 { ADF_SECRAMUERR, "SECRAMUERR" }, 26 { ADF_SECRAMUERRAD, "SECRAMUERRAD" }, 27 { ADF_CPPMEMTGTERR, "CPPMEMTGTERR" }, 28 { ADF_ERRPPID, "ERRPPID" }, 29 }; 30 31 static u32 32 adf_get_intstatsssm(struct resource *pmisc_bar_addr, size_t dev) 33 { 34 return ADF_CSR_RD(pmisc_bar_addr, ADF_INTSTATSSM(dev)); 35 } 36 37 static u32 38 adf_get_pperr(struct resource *pmisc_bar_addr, size_t dev) 39 { 40 return ADF_CSR_RD(pmisc_bar_addr, ADF_PPERR(dev)); 41 } 42 43 static u32 44 adf_get_pperrid(struct resource *pmisc_bar_addr, size_t dev) 45 { 46 return ADF_CSR_RD(pmisc_bar_addr, ADF_PPERRID(dev)); 47 } 48 49 static u32 50 adf_get_uerrssmsh(struct resource *pmisc_bar_addr, size_t dev) 51 { 52 return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMSH(dev)); 53 } 54 55 static u32 56 adf_get_uerrssmshad(struct resource *pmisc_bar_addr, size_t dev) 57 { 58 return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMSHAD(dev)); 59 } 60 61 static u32 62 adf_get_uerrssmmmp0(struct resource *pmisc_bar_addr, size_t dev) 63 { 64 return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 0)); 65 } 66 67 static u32 68 adf_get_uerrssmmmp1(struct resource *pmisc_bar_addr, size_t dev) 69 { 70 return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 1)); 71 } 72 73 static u32 74 adf_get_uerrssmmmp2(struct resource *pmisc_bar_addr, size_t dev) 75 { 76 return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 2)); 77 } 78 79 static u32 80 adf_get_uerrssmmmp3(struct resource *pmisc_bar_addr, size_t dev) 81 { 82 return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 3)); 83 } 84 85 static u32 86 adf_get_uerrssmmmp4(struct resource *pmisc_bar_addr, size_t dev) 87 { 88 return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMP(dev, 4)); 89 } 90 91 static u32 92 adf_get_uerrssmmmpad0(struct resource *pmisc_bar_addr, size_t dev) 93 { 94 return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 0)); 95 } 96 97 static u32 98 adf_get_uerrssmmmpad1(struct resource *pmisc_bar_addr, size_t dev) 99 { 100 return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 1)); 101 } 102 103 static u32 104 adf_get_uerrssmmmpad2(struct resource *pmisc_bar_addr, size_t dev) 105 { 106 return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 2)); 107 } 108 109 static u32 110 adf_get_uerrssmmmpad3(struct resource *pmisc_bar_addr, size_t dev) 111 { 112 return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 3)); 113 } 114 115 static u32 116 adf_get_uerrssmmmpad4(struct resource *pmisc_bar_addr, size_t dev) 117 { 118 return ADF_CSR_RD(pmisc_bar_addr, ADF_UERRSSMMMPAD(dev, 4)); 119 } 120 121 struct reg_array_info { 122 u32 (*read)(struct resource *pmisc_bar_addr, size_t dev); 123 char *name; 124 }; 125 126 static struct reg_array_info adf_accel_err_regs[] = { 127 { adf_get_intstatsssm, "INTSTATSSM" }, 128 { adf_get_pperr, "PPERR" }, 129 { adf_get_pperrid, "PPERRID" }, 130 { adf_get_uerrssmsh, "UERRSSMSH" }, 131 { adf_get_uerrssmshad, "UERRSSMSHAD" }, 132 { adf_get_uerrssmmmp0, "UERRSSMMMP0" }, 133 { adf_get_uerrssmmmp1, "UERRSSMMMP1" }, 134 { adf_get_uerrssmmmp2, "UERRSSMMMP2" }, 135 { adf_get_uerrssmmmp3, "UERRSSMMMP3" }, 136 { adf_get_uerrssmmmp4, "UERRSSMMMP4" }, 137 { adf_get_uerrssmmmpad0, "UERRSSMMMPAD0" }, 138 { adf_get_uerrssmmmpad1, "UERRSSMMMPAD1" }, 139 { adf_get_uerrssmmmpad2, "UERRSSMMMPAD2" }, 140 { adf_get_uerrssmmmpad3, "UERRSSMMMPAD3" }, 141 { adf_get_uerrssmmmpad4, "UERRSSMMMPAD4" }, 142 }; 143 144 static char adf_printf_buf[128] = { 0 }; 145 static size_t adf_printf_len; 146 147 static void 148 adf_print_flush(struct adf_accel_dev *accel_dev) 149 { 150 if (adf_printf_len > 0) { 151 device_printf(GET_DEV(accel_dev), "%.128s\n", adf_printf_buf); 152 adf_printf_len = 0; 153 } 154 } 155 156 static void 157 adf_print_reg(struct adf_accel_dev *accel_dev, 158 const char *name, 159 size_t idx, 160 u32 val) 161 { 162 adf_printf_len += snprintf(&adf_printf_buf[adf_printf_len], 163 sizeof(adf_printf_buf) - adf_printf_len, 164 "%s[%zu],%.8x,", 165 name, 166 idx, 167 val); 168 169 if (adf_printf_len >= 80) 170 adf_print_flush(accel_dev); 171 } 172 173 void 174 adf_print_err_registers(struct adf_accel_dev *accel_dev) 175 { 176 struct adf_hw_device_data *hw_data = accel_dev->hw_device; 177 struct adf_bar *misc_bar = 178 &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)]; 179 struct resource *csr = misc_bar->virt_addr; 180 size_t i; 181 unsigned int mask; 182 u32 val; 183 184 for (i = 0; i < ARRAY_SIZE(adf_err_regs); ++i) { 185 val = ADF_CSR_RD(csr, adf_err_regs[i].offs); 186 187 adf_print_reg(accel_dev, adf_err_regs[i].name, 0, val); 188 } 189 190 for (i = 0; i < ARRAY_SIZE(adf_accel_err_regs); ++i) { 191 size_t accel; 192 193 for (accel = 0, mask = hw_data->accel_mask; mask; 194 accel++, mask >>= 1) { 195 if (!(mask & 1)) 196 continue; 197 val = adf_accel_err_regs[i].read(csr, accel); 198 199 adf_print_reg(accel_dev, 200 adf_accel_err_regs[i].name, 201 accel, 202 val); 203 } 204 } 205 206 adf_print_flush(accel_dev); 207 } 208 209 static void 210 adf_log_slice_hang(struct adf_accel_dev *accel_dev, 211 u8 accel_num, 212 char *unit_name, 213 u8 unit_number) 214 { 215 device_printf(GET_DEV(accel_dev), 216 "CPM #%x Slice Hang Detected unit: %s%d.\n", 217 accel_num, 218 unit_name, 219 unit_number); 220 } 221 222 bool 223 adf_handle_slice_hang(struct adf_accel_dev *accel_dev, 224 u8 accel_num, 225 struct resource *csr, 226 u32 slice_hang_offset) 227 { 228 u32 slice_hang = ADF_CSR_RD(csr, slice_hang_offset); 229 230 if (!slice_hang) 231 return false; 232 233 if (slice_hang & ADF_SLICE_HANG_AUTH0_MASK) 234 adf_log_slice_hang(accel_dev, accel_num, "Auth", 0); 235 if (slice_hang & ADF_SLICE_HANG_AUTH1_MASK) 236 adf_log_slice_hang(accel_dev, accel_num, "Auth", 1); 237 if (slice_hang & ADF_SLICE_HANG_AUTH2_MASK) 238 adf_log_slice_hang(accel_dev, accel_num, "Auth", 2); 239 if (slice_hang & ADF_SLICE_HANG_CPHR0_MASK) 240 adf_log_slice_hang(accel_dev, accel_num, "Cipher", 0); 241 if (slice_hang & ADF_SLICE_HANG_CPHR1_MASK) 242 adf_log_slice_hang(accel_dev, accel_num, "Cipher", 1); 243 if (slice_hang & ADF_SLICE_HANG_CPHR2_MASK) 244 adf_log_slice_hang(accel_dev, accel_num, "Cipher", 2); 245 if (slice_hang & ADF_SLICE_HANG_CMP0_MASK) 246 adf_log_slice_hang(accel_dev, accel_num, "Comp", 0); 247 if (slice_hang & ADF_SLICE_HANG_CMP1_MASK) 248 adf_log_slice_hang(accel_dev, accel_num, "Comp", 1); 249 if (slice_hang & ADF_SLICE_HANG_XLT0_MASK) 250 adf_log_slice_hang(accel_dev, accel_num, "Xlator", 0); 251 if (slice_hang & ADF_SLICE_HANG_XLT1_MASK) 252 adf_log_slice_hang(accel_dev, accel_num, "Xlator", 1); 253 if (slice_hang & ADF_SLICE_HANG_MMP0_MASK) 254 adf_log_slice_hang(accel_dev, accel_num, "MMP", 0); 255 if (slice_hang & ADF_SLICE_HANG_MMP1_MASK) 256 adf_log_slice_hang(accel_dev, accel_num, "MMP", 1); 257 if (slice_hang & ADF_SLICE_HANG_MMP2_MASK) 258 adf_log_slice_hang(accel_dev, accel_num, "MMP", 2); 259 if (slice_hang & ADF_SLICE_HANG_MMP3_MASK) 260 adf_log_slice_hang(accel_dev, accel_num, "MMP", 3); 261 if (slice_hang & ADF_SLICE_HANG_MMP4_MASK) 262 adf_log_slice_hang(accel_dev, accel_num, "MMP", 4); 263 264 /* Clear the associated interrupt */ 265 ADF_CSR_WR(csr, slice_hang_offset, slice_hang); 266 267 return true; 268 } 269 270 /** 271 * adf_check_slice_hang() - Check slice hang status 272 * 273 * Return: true if a slice hange interrupt is serviced.. 274 */ 275 bool 276 adf_check_slice_hang(struct adf_accel_dev *accel_dev) 277 { 278 struct adf_hw_device_data *hw_data = accel_dev->hw_device; 279 struct adf_bar *misc_bar = 280 &GET_BARS(accel_dev)[hw_data->get_misc_bar_id(hw_data)]; 281 struct resource *csr = misc_bar->virt_addr; 282 u32 errsou3 = ADF_CSR_RD(csr, ADF_ERRSOU3); 283 u32 errsou5 = ADF_CSR_RD(csr, ADF_ERRSOU5); 284 u32 offset; 285 u32 accel_num; 286 bool handled = false; 287 u32 errsou[] = { errsou3, errsou3, errsou5, errsou5, errsou5 }; 288 u32 mask[] = { ADF_EMSK3_CPM0_MASK, 289 ADF_EMSK3_CPM1_MASK, 290 ADF_EMSK5_CPM2_MASK, 291 ADF_EMSK5_CPM3_MASK, 292 ADF_EMSK5_CPM4_MASK }; 293 unsigned int accel_mask; 294 295 for (accel_num = 0, accel_mask = hw_data->accel_mask; accel_mask; 296 accel_num++, accel_mask >>= 1) { 297 if (!(accel_mask & 1)) 298 continue; 299 if (accel_num >= ARRAY_SIZE(errsou)) { 300 device_printf(GET_DEV(accel_dev), 301 "Invalid accel_num %d.\n", 302 accel_num); 303 break; 304 } 305 306 if (errsou[accel_num] & mask[accel_num]) { 307 if (ADF_CSR_RD(csr, ADF_INTSTATSSM(accel_num)) & 308 ADF_INTSTATSSM_SHANGERR) { 309 offset = ADF_SLICEHANGSTATUS(accel_num); 310 handled |= adf_handle_slice_hang(accel_dev, 311 accel_num, 312 csr, 313 offset); 314 } 315 } 316 } 317 318 return handled; 319 } 320