xref: /OK3568_Linux_fs/kernel/drivers/crypto/caam/error.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * CAAM Error Reporting
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright 2009-2011 Freescale Semiconductor, Inc.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include "compat.h"
9*4882a593Smuzhiyun #include "regs.h"
10*4882a593Smuzhiyun #include "desc.h"
11*4882a593Smuzhiyun #include "error.h"
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #ifdef DEBUG
14*4882a593Smuzhiyun #include <linux/highmem.h>
15*4882a593Smuzhiyun 
caam_dump_sg(const char * prefix_str,int prefix_type,int rowsize,int groupsize,struct scatterlist * sg,size_t tlen,bool ascii)16*4882a593Smuzhiyun void caam_dump_sg(const char *prefix_str, int prefix_type,
17*4882a593Smuzhiyun 		  int rowsize, int groupsize, struct scatterlist *sg,
18*4882a593Smuzhiyun 		  size_t tlen, bool ascii)
19*4882a593Smuzhiyun {
20*4882a593Smuzhiyun 	struct scatterlist *it;
21*4882a593Smuzhiyun 	void *it_page;
22*4882a593Smuzhiyun 	size_t len;
23*4882a593Smuzhiyun 	void *buf;
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun 	for (it = sg; it && tlen > 0 ; it = sg_next(it)) {
26*4882a593Smuzhiyun 		/*
27*4882a593Smuzhiyun 		 * make sure the scatterlist's page
28*4882a593Smuzhiyun 		 * has a valid virtual memory mapping
29*4882a593Smuzhiyun 		 */
30*4882a593Smuzhiyun 		it_page = kmap_atomic(sg_page(it));
31*4882a593Smuzhiyun 		if (unlikely(!it_page)) {
32*4882a593Smuzhiyun 			pr_err("caam_dump_sg: kmap failed\n");
33*4882a593Smuzhiyun 			return;
34*4882a593Smuzhiyun 		}
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 		buf = it_page + it->offset;
37*4882a593Smuzhiyun 		len = min_t(size_t, tlen, it->length);
38*4882a593Smuzhiyun 		print_hex_dump_debug(prefix_str, prefix_type, rowsize,
39*4882a593Smuzhiyun 				     groupsize, buf, len, ascii);
40*4882a593Smuzhiyun 		tlen -= len;
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 		kunmap_atomic(it_page);
43*4882a593Smuzhiyun 	}
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun #else
caam_dump_sg(const char * prefix_str,int prefix_type,int rowsize,int groupsize,struct scatterlist * sg,size_t tlen,bool ascii)46*4882a593Smuzhiyun void caam_dump_sg(const char *prefix_str, int prefix_type,
47*4882a593Smuzhiyun 		  int rowsize, int groupsize, struct scatterlist *sg,
48*4882a593Smuzhiyun 		  size_t tlen, bool ascii)
49*4882a593Smuzhiyun {}
50*4882a593Smuzhiyun #endif /* DEBUG */
51*4882a593Smuzhiyun EXPORT_SYMBOL(caam_dump_sg);
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun bool caam_little_end;
54*4882a593Smuzhiyun EXPORT_SYMBOL(caam_little_end);
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun bool caam_imx;
57*4882a593Smuzhiyun EXPORT_SYMBOL(caam_imx);
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun size_t caam_ptr_sz;
60*4882a593Smuzhiyun EXPORT_SYMBOL(caam_ptr_sz);
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun static const struct {
63*4882a593Smuzhiyun 	u8 value;
64*4882a593Smuzhiyun 	const char *error_text;
65*4882a593Smuzhiyun } desc_error_list[] = {
66*4882a593Smuzhiyun 	{ 0x00, "No error." },
67*4882a593Smuzhiyun 	{ 0x01, "SGT Length Error. The descriptor is trying to read more data than is contained in the SGT table." },
68*4882a593Smuzhiyun 	{ 0x02, "SGT Null Entry Error." },
69*4882a593Smuzhiyun 	{ 0x03, "Job Ring Control Error. There is a bad value in the Job Ring Control register." },
70*4882a593Smuzhiyun 	{ 0x04, "Invalid Descriptor Command. The Descriptor Command field is invalid." },
71*4882a593Smuzhiyun 	{ 0x05, "Reserved." },
72*4882a593Smuzhiyun 	{ 0x06, "Invalid KEY Command" },
73*4882a593Smuzhiyun 	{ 0x07, "Invalid LOAD Command" },
74*4882a593Smuzhiyun 	{ 0x08, "Invalid STORE Command" },
75*4882a593Smuzhiyun 	{ 0x09, "Invalid OPERATION Command" },
76*4882a593Smuzhiyun 	{ 0x0A, "Invalid FIFO LOAD Command" },
77*4882a593Smuzhiyun 	{ 0x0B, "Invalid FIFO STORE Command" },
78*4882a593Smuzhiyun 	{ 0x0C, "Invalid MOVE/MOVE_LEN Command" },
79*4882a593Smuzhiyun 	{ 0x0D, "Invalid JUMP Command. A nonlocal JUMP Command is invalid because the target is not a Job Header Command, or the jump is from a Trusted Descriptor to a Job Descriptor, or because the target Descriptor contains a Shared Descriptor." },
80*4882a593Smuzhiyun 	{ 0x0E, "Invalid MATH Command" },
81*4882a593Smuzhiyun 	{ 0x0F, "Invalid SIGNATURE Command" },
82*4882a593Smuzhiyun 	{ 0x10, "Invalid Sequence Command. A SEQ IN PTR OR SEQ OUT PTR Command is invalid or a SEQ KEY, SEQ LOAD, SEQ FIFO LOAD, or SEQ FIFO STORE decremented the input or output sequence length below 0. This error may result if a built-in PROTOCOL Command has encountered a malformed PDU." },
83*4882a593Smuzhiyun 	{ 0x11, "Skip data type invalid. The type must be 0xE or 0xF."},
84*4882a593Smuzhiyun 	{ 0x12, "Shared Descriptor Header Error" },
85*4882a593Smuzhiyun 	{ 0x13, "Header Error. Invalid length or parity, or certain other problems." },
86*4882a593Smuzhiyun 	{ 0x14, "Burster Error. Burster has gotten to an illegal state" },
87*4882a593Smuzhiyun 	{ 0x15, "Context Register Length Error. The descriptor is trying to read or write past the end of the Context Register. A SEQ LOAD or SEQ STORE with the VLF bit set was executed with too large a length in the variable length register (VSOL for SEQ STORE or VSIL for SEQ LOAD)." },
88*4882a593Smuzhiyun 	{ 0x16, "DMA Error" },
89*4882a593Smuzhiyun 	{ 0x17, "Reserved." },
90*4882a593Smuzhiyun 	{ 0x1A, "Job failed due to JR reset" },
91*4882a593Smuzhiyun 	{ 0x1B, "Job failed due to Fail Mode" },
92*4882a593Smuzhiyun 	{ 0x1C, "DECO Watchdog timer timeout error" },
93*4882a593Smuzhiyun 	{ 0x1D, "DECO tried to copy a key from another DECO but the other DECO's Key Registers were locked" },
94*4882a593Smuzhiyun 	{ 0x1E, "DECO attempted to copy data from a DECO that had an unmasked Descriptor error" },
95*4882a593Smuzhiyun 	{ 0x1F, "LIODN error. DECO was trying to share from itself or from another DECO but the two Non-SEQ LIODN values didn't match or the 'shared from' DECO's Descriptor required that the SEQ LIODNs be the same and they aren't." },
96*4882a593Smuzhiyun 	{ 0x20, "DECO has completed a reset initiated via the DRR register" },
97*4882a593Smuzhiyun 	{ 0x21, "Nonce error. When using EKT (CCM) key encryption option in the FIFO STORE Command, the Nonce counter reached its maximum value and this encryption mode can no longer be used." },
98*4882a593Smuzhiyun 	{ 0x22, "Meta data is too large (> 511 bytes) for TLS decap (input frame; block ciphers) and IPsec decap (output frame, when doing the next header byte update) and DCRC (output frame)." },
99*4882a593Smuzhiyun 	{ 0x23, "Read Input Frame error" },
100*4882a593Smuzhiyun 	{ 0x24, "JDKEK, TDKEK or TDSK not loaded error" },
101*4882a593Smuzhiyun 	{ 0x80, "DNR (do not run) error" },
102*4882a593Smuzhiyun 	{ 0x81, "undefined protocol command" },
103*4882a593Smuzhiyun 	{ 0x82, "invalid setting in PDB" },
104*4882a593Smuzhiyun 	{ 0x83, "Anti-replay LATE error" },
105*4882a593Smuzhiyun 	{ 0x84, "Anti-replay REPLAY error" },
106*4882a593Smuzhiyun 	{ 0x85, "Sequence number overflow" },
107*4882a593Smuzhiyun 	{ 0x86, "Sigver invalid signature" },
108*4882a593Smuzhiyun 	{ 0x87, "DSA Sign Illegal test descriptor" },
109*4882a593Smuzhiyun 	{ 0x88, "Protocol Format Error - A protocol has seen an error in the format of data received. When running RSA, this means that formatting with random padding was used, and did not follow the form: 0x00, 0x02, 8-to-N bytes of non-zero pad, 0x00, F data." },
110*4882a593Smuzhiyun 	{ 0x89, "Protocol Size Error - A protocol has seen an error in size. When running RSA, pdb size N < (size of F) when no formatting is used; or pdb size N < (F + 11) when formatting is used." },
111*4882a593Smuzhiyun 	{ 0xC1, "Blob Command error: Undefined mode" },
112*4882a593Smuzhiyun 	{ 0xC2, "Blob Command error: Secure Memory Blob mode error" },
113*4882a593Smuzhiyun 	{ 0xC4, "Blob Command error: Black Blob key or input size error" },
114*4882a593Smuzhiyun 	{ 0xC5, "Blob Command error: Invalid key destination" },
115*4882a593Smuzhiyun 	{ 0xC8, "Blob Command error: Trusted/Secure mode error" },
116*4882a593Smuzhiyun 	{ 0xF0, "IPsec TTL or hop limit field either came in as 0, or was decremented to 0" },
117*4882a593Smuzhiyun 	{ 0xF1, "3GPP HFN matches or exceeds the Threshold" },
118*4882a593Smuzhiyun };
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun static const struct {
121*4882a593Smuzhiyun 	u8 value;
122*4882a593Smuzhiyun 	const char *error_text;
123*4882a593Smuzhiyun } qi_error_list[] = {
124*4882a593Smuzhiyun 	{ 0x00, "No error" },
125*4882a593Smuzhiyun 	{ 0x1F, "Job terminated by FQ or ICID flush" },
126*4882a593Smuzhiyun 	{ 0x20, "FD format error"},
127*4882a593Smuzhiyun 	{ 0x21, "FD command format error"},
128*4882a593Smuzhiyun 	{ 0x23, "FL format error"},
129*4882a593Smuzhiyun 	{ 0x25, "CRJD specified in FD, but not enabled in FLC"},
130*4882a593Smuzhiyun 	{ 0x30, "Max. buffer size too small"},
131*4882a593Smuzhiyun 	{ 0x31, "DHR exceeds max. buffer size (allocate mode, S/G format)"},
132*4882a593Smuzhiyun 	{ 0x32, "SGT exceeds max. buffer size (allocate mode, S/G format"},
133*4882a593Smuzhiyun 	{ 0x33, "Size over/underflow (allocate mode)"},
134*4882a593Smuzhiyun 	{ 0x34, "Size over/underflow (reuse mode)"},
135*4882a593Smuzhiyun 	{ 0x35, "Length exceeds max. short length (allocate mode, S/G/ format)"},
136*4882a593Smuzhiyun 	{ 0x36, "Memory footprint exceeds max. value (allocate mode, S/G/ format)"},
137*4882a593Smuzhiyun 	{ 0x41, "SBC frame format not supported (allocate mode)"},
138*4882a593Smuzhiyun 	{ 0x42, "Pool 0 invalid / pool 1 size < pool 0 size (allocate mode)"},
139*4882a593Smuzhiyun 	{ 0x43, "Annotation output enabled but ASAR = 0 (allocate mode)"},
140*4882a593Smuzhiyun 	{ 0x44, "Unsupported or reserved frame format or SGHR = 1 (reuse mode)"},
141*4882a593Smuzhiyun 	{ 0x45, "DHR correction underflow (reuse mode, single buffer format)"},
142*4882a593Smuzhiyun 	{ 0x46, "Annotation length exceeds offset (reuse mode)"},
143*4882a593Smuzhiyun 	{ 0x48, "Annotation output enabled but ASA limited by ASAR (reuse mode)"},
144*4882a593Smuzhiyun 	{ 0x49, "Data offset correction exceeds input frame data length (reuse mode)"},
145*4882a593Smuzhiyun 	{ 0x4B, "Annotation output enabled but ASA cannot be expanded (frame list)"},
146*4882a593Smuzhiyun 	{ 0x51, "Unsupported IF reuse mode"},
147*4882a593Smuzhiyun 	{ 0x52, "Unsupported FL use mode"},
148*4882a593Smuzhiyun 	{ 0x53, "Unsupported RJD use mode"},
149*4882a593Smuzhiyun 	{ 0x54, "Unsupported inline descriptor use mode"},
150*4882a593Smuzhiyun 	{ 0xC0, "Table buffer pool 0 depletion"},
151*4882a593Smuzhiyun 	{ 0xC1, "Table buffer pool 1 depletion"},
152*4882a593Smuzhiyun 	{ 0xC2, "Data buffer pool 0 depletion, no OF allocated"},
153*4882a593Smuzhiyun 	{ 0xC3, "Data buffer pool 1 depletion, no OF allocated"},
154*4882a593Smuzhiyun 	{ 0xC4, "Data buffer pool 0 depletion, partial OF allocated"},
155*4882a593Smuzhiyun 	{ 0xC5, "Data buffer pool 1 depletion, partial OF allocated"},
156*4882a593Smuzhiyun 	{ 0xD0, "FLC read error"},
157*4882a593Smuzhiyun 	{ 0xD1, "FL read error"},
158*4882a593Smuzhiyun 	{ 0xD2, "FL write error"},
159*4882a593Smuzhiyun 	{ 0xD3, "OF SGT write error"},
160*4882a593Smuzhiyun 	{ 0xD4, "PTA read error"},
161*4882a593Smuzhiyun 	{ 0xD5, "PTA write error"},
162*4882a593Smuzhiyun 	{ 0xD6, "OF SGT F-bit write error"},
163*4882a593Smuzhiyun 	{ 0xD7, "ASA write error"},
164*4882a593Smuzhiyun 	{ 0xE1, "FLC[ICR]=0 ICID error"},
165*4882a593Smuzhiyun 	{ 0xE2, "FLC[ICR]=1 ICID error"},
166*4882a593Smuzhiyun 	{ 0xE4, "source of ICID flush not trusted (BDI = 0)"},
167*4882a593Smuzhiyun };
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun static const char * const cha_id_list[] = {
170*4882a593Smuzhiyun 	"",
171*4882a593Smuzhiyun 	"AES",
172*4882a593Smuzhiyun 	"DES",
173*4882a593Smuzhiyun 	"ARC4",
174*4882a593Smuzhiyun 	"MDHA",
175*4882a593Smuzhiyun 	"RNG",
176*4882a593Smuzhiyun 	"SNOW f8",
177*4882a593Smuzhiyun 	"Kasumi f8/9",
178*4882a593Smuzhiyun 	"PKHA",
179*4882a593Smuzhiyun 	"CRCA",
180*4882a593Smuzhiyun 	"SNOW f9",
181*4882a593Smuzhiyun 	"ZUCE",
182*4882a593Smuzhiyun 	"ZUCA",
183*4882a593Smuzhiyun };
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun static const char * const err_id_list[] = {
186*4882a593Smuzhiyun 	"No error.",
187*4882a593Smuzhiyun 	"Mode error.",
188*4882a593Smuzhiyun 	"Data size error.",
189*4882a593Smuzhiyun 	"Key size error.",
190*4882a593Smuzhiyun 	"PKHA A memory size error.",
191*4882a593Smuzhiyun 	"PKHA B memory size error.",
192*4882a593Smuzhiyun 	"Data arrived out of sequence error.",
193*4882a593Smuzhiyun 	"PKHA divide-by-zero error.",
194*4882a593Smuzhiyun 	"PKHA modulus even error.",
195*4882a593Smuzhiyun 	"DES key parity error.",
196*4882a593Smuzhiyun 	"ICV check failed.",
197*4882a593Smuzhiyun 	"Hardware error.",
198*4882a593Smuzhiyun 	"Unsupported CCM AAD size.",
199*4882a593Smuzhiyun 	"Class 1 CHA is not reset",
200*4882a593Smuzhiyun 	"Invalid CHA combination was selected",
201*4882a593Smuzhiyun 	"Invalid CHA selected.",
202*4882a593Smuzhiyun };
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun static const char * const rng_err_id_list[] = {
205*4882a593Smuzhiyun 	"",
206*4882a593Smuzhiyun 	"",
207*4882a593Smuzhiyun 	"",
208*4882a593Smuzhiyun 	"Instantiate",
209*4882a593Smuzhiyun 	"Not instantiated",
210*4882a593Smuzhiyun 	"Test instantiate",
211*4882a593Smuzhiyun 	"Prediction resistance",
212*4882a593Smuzhiyun 	"Prediction resistance and test request",
213*4882a593Smuzhiyun 	"Uninstantiate",
214*4882a593Smuzhiyun 	"Secure key generation",
215*4882a593Smuzhiyun 	"",
216*4882a593Smuzhiyun 	"Hardware error",
217*4882a593Smuzhiyun 	"Continuous check"
218*4882a593Smuzhiyun };
219*4882a593Smuzhiyun 
report_ccb_status(struct device * jrdev,const u32 status,const char * error)220*4882a593Smuzhiyun static int report_ccb_status(struct device *jrdev, const u32 status,
221*4882a593Smuzhiyun 			     const char *error)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun 	u8 cha_id = (status & JRSTA_CCBERR_CHAID_MASK) >>
224*4882a593Smuzhiyun 		    JRSTA_CCBERR_CHAID_SHIFT;
225*4882a593Smuzhiyun 	u8 err_id = status & JRSTA_CCBERR_ERRID_MASK;
226*4882a593Smuzhiyun 	u8 idx = (status & JRSTA_DECOERR_INDEX_MASK) >>
227*4882a593Smuzhiyun 		  JRSTA_DECOERR_INDEX_SHIFT;
228*4882a593Smuzhiyun 	char *idx_str;
229*4882a593Smuzhiyun 	const char *cha_str = "unidentified cha_id value 0x";
230*4882a593Smuzhiyun 	char cha_err_code[3] = { 0 };
231*4882a593Smuzhiyun 	const char *err_str = "unidentified err_id value 0x";
232*4882a593Smuzhiyun 	char err_err_code[3] = { 0 };
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	if (status & JRSTA_DECOERR_JUMP)
235*4882a593Smuzhiyun 		idx_str = "jump tgt desc idx";
236*4882a593Smuzhiyun 	else
237*4882a593Smuzhiyun 		idx_str = "desc idx";
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	if (cha_id < ARRAY_SIZE(cha_id_list))
240*4882a593Smuzhiyun 		cha_str = cha_id_list[cha_id];
241*4882a593Smuzhiyun 	else
242*4882a593Smuzhiyun 		snprintf(cha_err_code, sizeof(cha_err_code), "%02x", cha_id);
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	if ((cha_id << JRSTA_CCBERR_CHAID_SHIFT) == JRSTA_CCBERR_CHAID_RNG &&
245*4882a593Smuzhiyun 	    err_id < ARRAY_SIZE(rng_err_id_list) &&
246*4882a593Smuzhiyun 	    strlen(rng_err_id_list[err_id])) {
247*4882a593Smuzhiyun 		/* RNG-only error */
248*4882a593Smuzhiyun 		err_str = rng_err_id_list[err_id];
249*4882a593Smuzhiyun 	} else {
250*4882a593Smuzhiyun 		err_str = err_id_list[err_id];
251*4882a593Smuzhiyun 	}
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	/*
254*4882a593Smuzhiyun 	 * CCB ICV check failures are part of normal operation life;
255*4882a593Smuzhiyun 	 * we leave the upper layers to do what they want with them.
256*4882a593Smuzhiyun 	 */
257*4882a593Smuzhiyun 	if (err_id == JRSTA_CCBERR_ERRID_ICVCHK)
258*4882a593Smuzhiyun 		return -EBADMSG;
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	dev_err_ratelimited(jrdev, "%08x: %s: %s %d: %s%s: %s%s\n", status,
261*4882a593Smuzhiyun 			    error, idx_str, idx, cha_str, cha_err_code,
262*4882a593Smuzhiyun 			    err_str, err_err_code);
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	return -EINVAL;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun 
report_jump_status(struct device * jrdev,const u32 status,const char * error)267*4882a593Smuzhiyun static int report_jump_status(struct device *jrdev, const u32 status,
268*4882a593Smuzhiyun 			      const char *error)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun 	dev_err(jrdev, "%08x: %s: %s() not implemented\n",
271*4882a593Smuzhiyun 		status, error, __func__);
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	return -EINVAL;
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
report_deco_status(struct device * jrdev,const u32 status,const char * error)276*4882a593Smuzhiyun static int report_deco_status(struct device *jrdev, const u32 status,
277*4882a593Smuzhiyun 			      const char *error)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun 	u8 err_id = status & JRSTA_DECOERR_ERROR_MASK;
280*4882a593Smuzhiyun 	u8 idx = (status & JRSTA_DECOERR_INDEX_MASK) >>
281*4882a593Smuzhiyun 		  JRSTA_DECOERR_INDEX_SHIFT;
282*4882a593Smuzhiyun 	char *idx_str;
283*4882a593Smuzhiyun 	const char *err_str = "unidentified error value 0x";
284*4882a593Smuzhiyun 	char err_err_code[3] = { 0 };
285*4882a593Smuzhiyun 	int i;
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	if (status & JRSTA_DECOERR_JUMP)
288*4882a593Smuzhiyun 		idx_str = "jump tgt desc idx";
289*4882a593Smuzhiyun 	else
290*4882a593Smuzhiyun 		idx_str = "desc idx";
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(desc_error_list); i++)
293*4882a593Smuzhiyun 		if (desc_error_list[i].value == err_id)
294*4882a593Smuzhiyun 			break;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	if (i != ARRAY_SIZE(desc_error_list) && desc_error_list[i].error_text)
297*4882a593Smuzhiyun 		err_str = desc_error_list[i].error_text;
298*4882a593Smuzhiyun 	else
299*4882a593Smuzhiyun 		snprintf(err_err_code, sizeof(err_err_code), "%02x", err_id);
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	dev_err(jrdev, "%08x: %s: %s %d: %s%s\n",
302*4882a593Smuzhiyun 		status, error, idx_str, idx, err_str, err_err_code);
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	return -EINVAL;
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun 
report_qi_status(struct device * qidev,const u32 status,const char * error)307*4882a593Smuzhiyun static int report_qi_status(struct device *qidev, const u32 status,
308*4882a593Smuzhiyun 			    const char *error)
309*4882a593Smuzhiyun {
310*4882a593Smuzhiyun 	u8 err_id = status & JRSTA_QIERR_ERROR_MASK;
311*4882a593Smuzhiyun 	const char *err_str = "unidentified error value 0x";
312*4882a593Smuzhiyun 	char err_err_code[3] = { 0 };
313*4882a593Smuzhiyun 	int i;
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(qi_error_list); i++)
316*4882a593Smuzhiyun 		if (qi_error_list[i].value == err_id)
317*4882a593Smuzhiyun 			break;
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun 	if (i != ARRAY_SIZE(qi_error_list) && qi_error_list[i].error_text)
320*4882a593Smuzhiyun 		err_str = qi_error_list[i].error_text;
321*4882a593Smuzhiyun 	else
322*4882a593Smuzhiyun 		snprintf(err_err_code, sizeof(err_err_code), "%02x", err_id);
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	dev_err(qidev, "%08x: %s: %s%s\n",
325*4882a593Smuzhiyun 		status, error, err_str, err_err_code);
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	return -EINVAL;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun 
report_jr_status(struct device * jrdev,const u32 status,const char * error)330*4882a593Smuzhiyun static int report_jr_status(struct device *jrdev, const u32 status,
331*4882a593Smuzhiyun 			    const char *error)
332*4882a593Smuzhiyun {
333*4882a593Smuzhiyun 	dev_err(jrdev, "%08x: %s: %s() not implemented\n",
334*4882a593Smuzhiyun 		status, error, __func__);
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	return -EINVAL;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun 
report_cond_code_status(struct device * jrdev,const u32 status,const char * error)339*4882a593Smuzhiyun static int report_cond_code_status(struct device *jrdev, const u32 status,
340*4882a593Smuzhiyun 				   const char *error)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun 	dev_err(jrdev, "%08x: %s: %s() not implemented\n",
343*4882a593Smuzhiyun 		status, error, __func__);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	return -EINVAL;
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun 
caam_strstatus(struct device * jrdev,u32 status,bool qi_v2)348*4882a593Smuzhiyun int caam_strstatus(struct device *jrdev, u32 status, bool qi_v2)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun 	static const struct stat_src {
351*4882a593Smuzhiyun 		int (*report_ssed)(struct device *jrdev, const u32 status,
352*4882a593Smuzhiyun 				   const char *error);
353*4882a593Smuzhiyun 		const char *error;
354*4882a593Smuzhiyun 	} status_src[16] = {
355*4882a593Smuzhiyun 		{ NULL, "No error" },
356*4882a593Smuzhiyun 		{ NULL, NULL },
357*4882a593Smuzhiyun 		{ report_ccb_status, "CCB" },
358*4882a593Smuzhiyun 		{ report_jump_status, "Jump" },
359*4882a593Smuzhiyun 		{ report_deco_status, "DECO" },
360*4882a593Smuzhiyun 		{ report_qi_status, "Queue Manager Interface" },
361*4882a593Smuzhiyun 		{ report_jr_status, "Job Ring" },
362*4882a593Smuzhiyun 		{ report_cond_code_status, "Condition Code" },
363*4882a593Smuzhiyun 		{ NULL, NULL },
364*4882a593Smuzhiyun 		{ NULL, NULL },
365*4882a593Smuzhiyun 		{ NULL, NULL },
366*4882a593Smuzhiyun 		{ NULL, NULL },
367*4882a593Smuzhiyun 		{ NULL, NULL },
368*4882a593Smuzhiyun 		{ NULL, NULL },
369*4882a593Smuzhiyun 		{ NULL, NULL },
370*4882a593Smuzhiyun 		{ NULL, NULL },
371*4882a593Smuzhiyun 	};
372*4882a593Smuzhiyun 	u32 ssrc = status >> JRSTA_SSRC_SHIFT;
373*4882a593Smuzhiyun 	const char *error = status_src[ssrc].error;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	/*
376*4882a593Smuzhiyun 	 * If there is an error handling function, call it to report the error.
377*4882a593Smuzhiyun 	 * Otherwise print the error source name.
378*4882a593Smuzhiyun 	 */
379*4882a593Smuzhiyun 	if (status_src[ssrc].report_ssed)
380*4882a593Smuzhiyun 		return status_src[ssrc].report_ssed(jrdev, status, error);
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun 	if (error)
383*4882a593Smuzhiyun 		dev_err(jrdev, "%d: %s\n", ssrc, error);
384*4882a593Smuzhiyun 	else
385*4882a593Smuzhiyun 		dev_err(jrdev, "%d: unknown error source\n", ssrc);
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	return -EINVAL;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun EXPORT_SYMBOL(caam_strstatus);
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun MODULE_LICENSE("GPL");
392*4882a593Smuzhiyun MODULE_DESCRIPTION("FSL CAAM error reporting");
393*4882a593Smuzhiyun MODULE_AUTHOR("Freescale Semiconductor");
394