xref: /freebsd/sys/dev/qat/qat_common/adf_dev_err.c (revision cb7aa33ac6cd46a5434798e50363136e64f3ae98)
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