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
adf_get_intstatsssm(struct resource * pmisc_bar_addr,size_t dev)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
adf_get_pperr(struct resource * pmisc_bar_addr,size_t dev)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
adf_get_pperrid(struct resource * pmisc_bar_addr,size_t dev)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
adf_get_uerrssmsh(struct resource * pmisc_bar_addr,size_t dev)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
adf_get_uerrssmshad(struct resource * pmisc_bar_addr,size_t dev)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
adf_get_uerrssmmmp0(struct resource * pmisc_bar_addr,size_t dev)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
adf_get_uerrssmmmp1(struct resource * pmisc_bar_addr,size_t dev)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
adf_get_uerrssmmmp2(struct resource * pmisc_bar_addr,size_t dev)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
adf_get_uerrssmmmp3(struct resource * pmisc_bar_addr,size_t dev)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
adf_get_uerrssmmmp4(struct resource * pmisc_bar_addr,size_t dev)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
adf_get_uerrssmmmpad0(struct resource * pmisc_bar_addr,size_t dev)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
adf_get_uerrssmmmpad1(struct resource * pmisc_bar_addr,size_t dev)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
adf_get_uerrssmmmpad2(struct resource * pmisc_bar_addr,size_t dev)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
adf_get_uerrssmmmpad3(struct resource * pmisc_bar_addr,size_t dev)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
adf_get_uerrssmmmpad4(struct resource * pmisc_bar_addr,size_t dev)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
adf_print_flush(struct adf_accel_dev * accel_dev)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
adf_print_reg(struct adf_accel_dev * accel_dev,const char * name,size_t idx,u32 val)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
adf_print_err_registers(struct adf_accel_dev * accel_dev)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
adf_log_slice_hang(struct adf_accel_dev * accel_dev,u8 accel_num,char * unit_name,u8 unit_number)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
adf_handle_slice_hang(struct adf_accel_dev * accel_dev,u8 accel_num,struct resource * csr,u32 slice_hang_offset)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
adf_check_slice_hang(struct adf_accel_dev * accel_dev)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