1*14b24e2bSVaishali Kulkarni /*
2*14b24e2bSVaishali Kulkarni * CDDL HEADER START
3*14b24e2bSVaishali Kulkarni *
4*14b24e2bSVaishali Kulkarni * The contents of this file are subject to the terms of the
5*14b24e2bSVaishali Kulkarni * Common Development and Distribution License, v.1,  (the "License").
6*14b24e2bSVaishali Kulkarni * You may not use this file except in compliance with the License.
7*14b24e2bSVaishali Kulkarni *
8*14b24e2bSVaishali Kulkarni * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*14b24e2bSVaishali Kulkarni * or http://opensource.org/licenses/CDDL-1.0.
10*14b24e2bSVaishali Kulkarni * See the License for the specific language governing permissions
11*14b24e2bSVaishali Kulkarni * and limitations under the License.
12*14b24e2bSVaishali Kulkarni *
13*14b24e2bSVaishali Kulkarni * When distributing Covered Code, include this CDDL HEADER in each
14*14b24e2bSVaishali Kulkarni * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*14b24e2bSVaishali Kulkarni * If applicable, add the following below this CDDL HEADER, with the
16*14b24e2bSVaishali Kulkarni * fields enclosed by brackets "[]" replaced with your own identifying
17*14b24e2bSVaishali Kulkarni * information: Portions Copyright [yyyy] [name of copyright owner]
18*14b24e2bSVaishali Kulkarni *
19*14b24e2bSVaishali Kulkarni * CDDL HEADER END
20*14b24e2bSVaishali Kulkarni */
21*14b24e2bSVaishali Kulkarni 
22*14b24e2bSVaishali Kulkarni /*
23*14b24e2bSVaishali Kulkarni * Copyright 2014-2017 Cavium, Inc.
24*14b24e2bSVaishali Kulkarni * The contents of this file are subject to the terms of the Common Development
25*14b24e2bSVaishali Kulkarni * and Distribution License, v.1,  (the "License").
26*14b24e2bSVaishali Kulkarni 
27*14b24e2bSVaishali Kulkarni * You may not use this file except in compliance with the License.
28*14b24e2bSVaishali Kulkarni 
29*14b24e2bSVaishali Kulkarni * You can obtain a copy of the License at available
30*14b24e2bSVaishali Kulkarni * at http://opensource.org/licenses/CDDL-1.0
31*14b24e2bSVaishali Kulkarni 
32*14b24e2bSVaishali Kulkarni * See the License for the specific language governing permissions and
33*14b24e2bSVaishali Kulkarni * limitations under the License.
34*14b24e2bSVaishali Kulkarni */
35*14b24e2bSVaishali Kulkarni 
36*14b24e2bSVaishali Kulkarni #include "bcm_osal.h"
37*14b24e2bSVaishali Kulkarni #include "ecore.h"
38*14b24e2bSVaishali Kulkarni #include "ecore_sp_commands.h"
39*14b24e2bSVaishali Kulkarni #include "ecore_dev_api.h"
40*14b24e2bSVaishali Kulkarni #include "ecore_mcp.h"
41*14b24e2bSVaishali Kulkarni #include "nvm_map.h"
42*14b24e2bSVaishali Kulkarni #include "ecore_selftest_api.h"
43*14b24e2bSVaishali Kulkarni 
ecore_selftest_memory(struct ecore_dev * p_dev)44*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_selftest_memory(struct ecore_dev *p_dev)
45*14b24e2bSVaishali Kulkarni {
46*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
47*14b24e2bSVaishali Kulkarni 	int i;
48*14b24e2bSVaishali Kulkarni 
49*14b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, i) {
50*14b24e2bSVaishali Kulkarni 		rc = ecore_sp_heartbeat_ramrod(&p_dev->hwfns[i]);
51*14b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
52*14b24e2bSVaishali Kulkarni 			return rc;
53*14b24e2bSVaishali Kulkarni 	}
54*14b24e2bSVaishali Kulkarni 
55*14b24e2bSVaishali Kulkarni 	return rc;
56*14b24e2bSVaishali Kulkarni }
57*14b24e2bSVaishali Kulkarni 
ecore_selftest_interrupt(struct ecore_dev * p_dev)58*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_selftest_interrupt(struct ecore_dev *p_dev)
59*14b24e2bSVaishali Kulkarni {
60*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
61*14b24e2bSVaishali Kulkarni 	int i;
62*14b24e2bSVaishali Kulkarni 
63*14b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, i) {
64*14b24e2bSVaishali Kulkarni 		rc = ecore_sp_heartbeat_ramrod(&p_dev->hwfns[i]);
65*14b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
66*14b24e2bSVaishali Kulkarni 			return rc;
67*14b24e2bSVaishali Kulkarni 	}
68*14b24e2bSVaishali Kulkarni 
69*14b24e2bSVaishali Kulkarni 	return rc;
70*14b24e2bSVaishali Kulkarni }
71*14b24e2bSVaishali Kulkarni 
ecore_selftest_register(struct ecore_dev * p_dev)72*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_selftest_register(struct ecore_dev *p_dev)
73*14b24e2bSVaishali Kulkarni {
74*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn;
75*14b24e2bSVaishali Kulkarni 	struct ecore_ptt *p_ptt;
76*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
77*14b24e2bSVaishali Kulkarni 	int i;
78*14b24e2bSVaishali Kulkarni 
79*14b24e2bSVaishali Kulkarni 
80*14b24e2bSVaishali Kulkarni 	/* although performed by MCP, this test is per engine */
81*14b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, i) {
82*14b24e2bSVaishali Kulkarni 		p_hwfn = &p_dev->hwfns[i];
83*14b24e2bSVaishali Kulkarni 		p_ptt = ecore_ptt_acquire(p_hwfn);
84*14b24e2bSVaishali Kulkarni 		if (!p_ptt) {
85*14b24e2bSVaishali Kulkarni 			DP_ERR(p_hwfn, "failed to acquire ptt\n");
86*14b24e2bSVaishali Kulkarni 			return ECORE_BUSY;
87*14b24e2bSVaishali Kulkarni 		}
88*14b24e2bSVaishali Kulkarni 		rc = ecore_mcp_bist_register_test(p_hwfn, p_ptt);
89*14b24e2bSVaishali Kulkarni 		ecore_ptt_release(p_hwfn, p_ptt);
90*14b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
91*14b24e2bSVaishali Kulkarni 			break;
92*14b24e2bSVaishali Kulkarni 	}
93*14b24e2bSVaishali Kulkarni 
94*14b24e2bSVaishali Kulkarni 	return rc;
95*14b24e2bSVaishali Kulkarni }
96*14b24e2bSVaishali Kulkarni 
ecore_selftest_clock(struct ecore_dev * p_dev)97*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_selftest_clock(struct ecore_dev *p_dev)
98*14b24e2bSVaishali Kulkarni {
99*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn;
100*14b24e2bSVaishali Kulkarni 	struct ecore_ptt *p_ptt;
101*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc = ECORE_SUCCESS;
102*14b24e2bSVaishali Kulkarni 	int i;
103*14b24e2bSVaishali Kulkarni 
104*14b24e2bSVaishali Kulkarni 	/* although performed by MCP, this test is per engine */
105*14b24e2bSVaishali Kulkarni 	for_each_hwfn(p_dev, i) {
106*14b24e2bSVaishali Kulkarni 		p_hwfn = &p_dev->hwfns[i];
107*14b24e2bSVaishali Kulkarni 		p_ptt = ecore_ptt_acquire(p_hwfn);
108*14b24e2bSVaishali Kulkarni 		if (!p_ptt) {
109*14b24e2bSVaishali Kulkarni 			DP_ERR(p_hwfn, "failed to acquire ptt\n");
110*14b24e2bSVaishali Kulkarni 			return ECORE_BUSY;
111*14b24e2bSVaishali Kulkarni 		}
112*14b24e2bSVaishali Kulkarni 		rc = ecore_mcp_bist_clock_test(p_hwfn, p_ptt);
113*14b24e2bSVaishali Kulkarni 		ecore_ptt_release(p_hwfn, p_ptt);
114*14b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS)
115*14b24e2bSVaishali Kulkarni 			break;
116*14b24e2bSVaishali Kulkarni 	}
117*14b24e2bSVaishali Kulkarni 
118*14b24e2bSVaishali Kulkarni 	return rc;
119*14b24e2bSVaishali Kulkarni }
120*14b24e2bSVaishali Kulkarni 
ecore_selftest_nvram(struct ecore_dev * p_dev)121*14b24e2bSVaishali Kulkarni enum _ecore_status_t ecore_selftest_nvram(struct ecore_dev *p_dev)
122*14b24e2bSVaishali Kulkarni {
123*14b24e2bSVaishali Kulkarni 	struct ecore_hwfn *p_hwfn = ECORE_LEADING_HWFN(p_dev);
124*14b24e2bSVaishali Kulkarni 	struct ecore_ptt *p_ptt = ecore_ptt_acquire(p_hwfn);
125*14b24e2bSVaishali Kulkarni 	u32 num_images, i, j, nvm_crc, calc_crc;
126*14b24e2bSVaishali Kulkarni 	struct bist_nvm_image_att image_att;
127*14b24e2bSVaishali Kulkarni 	u8 *buf = OSAL_NULL;
128*14b24e2bSVaishali Kulkarni 	OSAL_BE32 val;
129*14b24e2bSVaishali Kulkarni 	enum _ecore_status_t rc;
130*14b24e2bSVaishali Kulkarni 
131*14b24e2bSVaishali Kulkarni 	if (!p_ptt) {
132*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "failed to acquire ptt\n");
133*14b24e2bSVaishali Kulkarni 		return ECORE_BUSY;
134*14b24e2bSVaishali Kulkarni 	}
135*14b24e2bSVaishali Kulkarni 
136*14b24e2bSVaishali Kulkarni 	/* Acquire from MFW the amount of available images */
137*14b24e2bSVaishali Kulkarni 	rc = ecore_mcp_bist_nvm_test_get_num_images(p_hwfn, p_ptt, &num_images);
138*14b24e2bSVaishali Kulkarni 	if ((rc != ECORE_SUCCESS) || (num_images == 0)) {
139*14b24e2bSVaishali Kulkarni 		DP_ERR(p_hwfn, "Failed getting number of images\n");
140*14b24e2bSVaishali Kulkarni 		return ECORE_INVAL;
141*14b24e2bSVaishali Kulkarni 	}
142*14b24e2bSVaishali Kulkarni 
143*14b24e2bSVaishali Kulkarni 	/* Iterate over images and validate CRC */
144*14b24e2bSVaishali Kulkarni 	for (i = 0; i < num_images; i++) {
145*14b24e2bSVaishali Kulkarni 		/* This mailbox returns information about the image required for
146*14b24e2bSVaishali Kulkarni 		 * reading it.
147*14b24e2bSVaishali Kulkarni 		 */
148*14b24e2bSVaishali Kulkarni 		rc = ecore_mcp_bist_nvm_test_get_image_att(p_hwfn, p_ptt,
149*14b24e2bSVaishali Kulkarni 							   &image_att, i);
150*14b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS) {
151*14b24e2bSVaishali Kulkarni 			DP_ERR(p_hwfn,
152*14b24e2bSVaishali Kulkarni 			       "Failed getting image index %d attributes\n",
153*14b24e2bSVaishali Kulkarni 			       i);
154*14b24e2bSVaishali Kulkarni 			goto err0;
155*14b24e2bSVaishali Kulkarni 		}
156*14b24e2bSVaishali Kulkarni 
157*14b24e2bSVaishali Kulkarni 		/* After MFW crash dump is collected - the image's CRC stops
158*14b24e2bSVaishali Kulkarni 		 * being valid.
159*14b24e2bSVaishali Kulkarni 		 */
160*14b24e2bSVaishali Kulkarni 		if (image_att.image_type == NVM_TYPE_MDUMP)
161*14b24e2bSVaishali Kulkarni 			continue;
162*14b24e2bSVaishali Kulkarni 
163*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP, "image index %d, size %x\n", i,
164*14b24e2bSVaishali Kulkarni 			   image_att.len);
165*14b24e2bSVaishali Kulkarni 
166*14b24e2bSVaishali Kulkarni 		/* Allocate a buffer for holding the nvram image */
167*14b24e2bSVaishali Kulkarni 		buf = OSAL_ZALLOC(p_hwfn->p_dev, GFP_KERNEL, image_att.len);
168*14b24e2bSVaishali Kulkarni 		if (!buf) {
169*14b24e2bSVaishali Kulkarni 			DP_ERR(p_hwfn,
170*14b24e2bSVaishali Kulkarni 			       "Failed allocating memory for image index %d.\n",
171*14b24e2bSVaishali Kulkarni 			       i);
172*14b24e2bSVaishali Kulkarni 			rc = ECORE_NOMEM;
173*14b24e2bSVaishali Kulkarni 			goto err0;
174*14b24e2bSVaishali Kulkarni 		}
175*14b24e2bSVaishali Kulkarni 
176*14b24e2bSVaishali Kulkarni 		/* Read image into buffer */
177*14b24e2bSVaishali Kulkarni 		rc = ecore_mcp_nvm_read(p_hwfn->p_dev, image_att.nvm_start_addr,
178*14b24e2bSVaishali Kulkarni 					buf, image_att.len);
179*14b24e2bSVaishali Kulkarni 		if (rc != ECORE_SUCCESS) {
180*14b24e2bSVaishali Kulkarni 			DP_ERR(p_hwfn,
181*14b24e2bSVaishali Kulkarni 			       "Failed reading image index %d from nvm.\n", i);
182*14b24e2bSVaishali Kulkarni 			goto err1;
183*14b24e2bSVaishali Kulkarni 		}
184*14b24e2bSVaishali Kulkarni 
185*14b24e2bSVaishali Kulkarni 		/* Convert the buffer into big-endian format (excluding the
186*14b24e2bSVaishali Kulkarni 		 * closing 4 bytes of CRC).
187*14b24e2bSVaishali Kulkarni 		 */
188*14b24e2bSVaishali Kulkarni 		for (j = 0; j < image_att.len - 4; j += 4) {
189*14b24e2bSVaishali Kulkarni 			val = OSAL_CPU_TO_BE32(*(u32 *)&buf[j]);
190*14b24e2bSVaishali Kulkarni 			*(u32 *)&buf[j] = val;
191*14b24e2bSVaishali Kulkarni 		}
192*14b24e2bSVaishali Kulkarni 
193*14b24e2bSVaishali Kulkarni 		/* Calc CRC for the "actual" image buffer, i.e. not including
194*14b24e2bSVaishali Kulkarni 		 * the last 4 CRC bytes.
195*14b24e2bSVaishali Kulkarni 		 */
196*14b24e2bSVaishali Kulkarni 		nvm_crc = *(u32 *)(buf + image_att.len - 4);
197*14b24e2bSVaishali Kulkarni 		calc_crc = OSAL_CRC32(0xffffffff , buf, image_att.len - 4);
198*14b24e2bSVaishali Kulkarni 		calc_crc = ~OSAL_CPU_TO_BE32(calc_crc);
199*14b24e2bSVaishali Kulkarni 		DP_VERBOSE(p_hwfn, ECORE_MSG_SP,
200*14b24e2bSVaishali Kulkarni 			   "nvm crc 0x%x, calc_crc 0x%x\n", nvm_crc, calc_crc);
201*14b24e2bSVaishali Kulkarni 
202*14b24e2bSVaishali Kulkarni 		if (calc_crc != nvm_crc) {
203*14b24e2bSVaishali Kulkarni 			rc = ECORE_UNKNOWN_ERROR;
204*14b24e2bSVaishali Kulkarni 			goto err1;
205*14b24e2bSVaishali Kulkarni 		}
206*14b24e2bSVaishali Kulkarni 
207*14b24e2bSVaishali Kulkarni 		/* Done with this image */
208*14b24e2bSVaishali Kulkarni 		OSAL_FREE(p_hwfn->p_dev, buf);
209*14b24e2bSVaishali Kulkarni 		buf = OSAL_NULL;
210*14b24e2bSVaishali Kulkarni 	}
211*14b24e2bSVaishali Kulkarni 
212*14b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
213*14b24e2bSVaishali Kulkarni 	return ECORE_SUCCESS;
214*14b24e2bSVaishali Kulkarni 
215*14b24e2bSVaishali Kulkarni err1:
216*14b24e2bSVaishali Kulkarni 	OSAL_FREE(p_hwfn->p_dev, buf);
217*14b24e2bSVaishali Kulkarni err0:
218*14b24e2bSVaishali Kulkarni 	ecore_ptt_release(p_hwfn, p_ptt);
219*14b24e2bSVaishali Kulkarni 	return rc;
220*14b24e2bSVaishali Kulkarni }
221*14b24e2bSVaishali Kulkarni