1 #include <linux/crc32.h>
2 #include "qed.h"
3 #include "qed_dev_api.h"
4 #include "qed_mcp.h"
5 #include "qed_sp.h"
6 #include "qed_selftest.h"
7 
8 int qed_selftest_memory(struct qed_dev *cdev)
9 {
10 	int rc = 0, i;
11 
12 	for_each_hwfn(cdev, i) {
13 		rc = qed_sp_heartbeat_ramrod(&cdev->hwfns[i]);
14 		if (rc)
15 			return rc;
16 	}
17 
18 	return rc;
19 }
20 
21 int qed_selftest_interrupt(struct qed_dev *cdev)
22 {
23 	int rc = 0, i;
24 
25 	for_each_hwfn(cdev, i) {
26 		rc = qed_sp_heartbeat_ramrod(&cdev->hwfns[i]);
27 		if (rc)
28 			return rc;
29 	}
30 
31 	return rc;
32 }
33 
34 int qed_selftest_register(struct qed_dev *cdev)
35 {
36 	struct qed_hwfn *p_hwfn;
37 	struct qed_ptt *p_ptt;
38 	int rc = 0, i;
39 
40 	/* although performed by MCP, this test is per engine */
41 	for_each_hwfn(cdev, i) {
42 		p_hwfn = &cdev->hwfns[i];
43 		p_ptt = qed_ptt_acquire(p_hwfn);
44 		if (!p_ptt) {
45 			DP_ERR(p_hwfn, "failed to acquire ptt\n");
46 			return -EBUSY;
47 		}
48 		rc = qed_mcp_bist_register_test(p_hwfn, p_ptt);
49 		qed_ptt_release(p_hwfn, p_ptt);
50 		if (rc)
51 			break;
52 	}
53 
54 	return rc;
55 }
56 
57 int qed_selftest_clock(struct qed_dev *cdev)
58 {
59 	struct qed_hwfn *p_hwfn;
60 	struct qed_ptt *p_ptt;
61 	int rc = 0, i;
62 
63 	/* although performed by MCP, this test is per engine */
64 	for_each_hwfn(cdev, i) {
65 		p_hwfn = &cdev->hwfns[i];
66 		p_ptt = qed_ptt_acquire(p_hwfn);
67 		if (!p_ptt) {
68 			DP_ERR(p_hwfn, "failed to acquire ptt\n");
69 			return -EBUSY;
70 		}
71 		rc = qed_mcp_bist_clock_test(p_hwfn, p_ptt);
72 		qed_ptt_release(p_hwfn, p_ptt);
73 		if (rc)
74 			break;
75 	}
76 
77 	return rc;
78 }
79 
80 int qed_selftest_nvram(struct qed_dev *cdev)
81 {
82 	struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
83 	struct qed_ptt *p_ptt = qed_ptt_acquire(p_hwfn);
84 	u32 num_images, i, j, nvm_crc, calc_crc;
85 	struct bist_nvm_image_att image_att;
86 	u8 *buf = NULL;
87 	__be32 val;
88 	int rc;
89 
90 	if (!p_ptt) {
91 		DP_ERR(p_hwfn, "failed to acquire ptt\n");
92 		return -EBUSY;
93 	}
94 
95 	/* Acquire from MFW the amount of available images */
96 	rc = qed_mcp_bist_nvm_test_get_num_images(p_hwfn, p_ptt, &num_images);
97 	if (rc || !num_images) {
98 		DP_ERR(p_hwfn, "Failed getting number of images\n");
99 		return -EINVAL;
100 	}
101 
102 	/* Iterate over images and validate CRC */
103 	for (i = 0; i < num_images; i++) {
104 		/* This mailbox returns information about the image required for
105 		 * reading it.
106 		 */
107 		rc = qed_mcp_bist_nvm_test_get_image_att(p_hwfn, p_ptt,
108 							 &image_att, i);
109 		if (rc) {
110 			DP_ERR(p_hwfn,
111 			       "Failed getting image index %d attributes\n",
112 			       i);
113 			goto err0;
114 		}
115 
116 		/* After MFW crash dump is collected - the image's CRC stops
117 		 * being valid.
118 		 */
119 		if (image_att.image_type == NVM_TYPE_MDUMP)
120 			continue;
121 
122 		DP_VERBOSE(p_hwfn, QED_MSG_SP, "image index %d, size %x\n",
123 			   i, image_att.len);
124 
125 		/* Allocate a buffer for holding the nvram image */
126 		buf = kzalloc(image_att.len, GFP_KERNEL);
127 		if (!buf) {
128 			rc = -ENOMEM;
129 			goto err0;
130 		}
131 
132 		/* Read image into buffer */
133 		rc = qed_mcp_nvm_read(p_hwfn->cdev, image_att.nvm_start_addr,
134 				      buf, image_att.len);
135 		if (rc) {
136 			DP_ERR(p_hwfn,
137 			       "Failed reading image index %d from nvm.\n", i);
138 			goto err1;
139 		}
140 
141 		/* Convert the buffer into big-endian format (excluding the
142 		 * closing 4 bytes of CRC).
143 		 */
144 		for (j = 0; j < image_att.len - 4; j += 4) {
145 			val = cpu_to_be32(*(u32 *)&buf[j]);
146 			*(u32 *)&buf[j] = (__force u32)val;
147 		}
148 
149 		/* Calc CRC for the "actual" image buffer, i.e. not including
150 		 * the last 4 CRC bytes.
151 		 */
152 		nvm_crc = *(u32 *)(buf + image_att.len - 4);
153 		calc_crc = crc32(0xffffffff, buf, image_att.len - 4);
154 		calc_crc = (__force u32)~cpu_to_be32(calc_crc);
155 		DP_VERBOSE(p_hwfn, QED_MSG_SP,
156 			   "nvm crc 0x%x, calc_crc 0x%x\n", nvm_crc, calc_crc);
157 
158 		if (calc_crc != nvm_crc) {
159 			rc = -EINVAL;
160 			goto err1;
161 		}
162 
163 		/* Done with this image; Free to prevent double release
164 		 * on subsequent failure.
165 		 */
166 		kfree(buf);
167 		buf = NULL;
168 	}
169 
170 	qed_ptt_release(p_hwfn, p_ptt);
171 	return 0;
172 
173 err1:
174 	kfree(buf);
175 err0:
176 	qed_ptt_release(p_hwfn, p_ptt);
177 	return rc;
178 }
179