blob: 48bfaecaf6dca30fc3113c92d739dfd8187f3ca8 [file] [log] [blame]
Mintz, Yuval7a4b21b2016-10-31 07:14:22 +02001#include <linux/crc32.h>
Sudarsana Reddy Kalluru03dc76c2016-04-28 20:20:52 -04002#include "qed.h"
3#include "qed_dev_api.h"
4#include "qed_mcp.h"
5#include "qed_sp.h"
Baoyou Xie72e8d5f2016-09-07 19:07:00 +08006#include "qed_selftest.h"
Sudarsana Reddy Kalluru03dc76c2016-04-28 20:20:52 -04007
8int 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
21int 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
34int 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
57int 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}
Mintz, Yuval7a4b21b2016-10-31 07:14:22 +020079
80int 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
173err1:
174 kfree(buf);
175err0:
176 qed_ptt_release(p_hwfn, p_ptt);
177 return rc;
178}