Linux Audio

Check our new training course

Yocto distribution development and maintenance

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