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