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