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