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