Linux Audio

Check our new training course

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}
v4.17
 
  1/* QLogic qed NIC Driver
  2 * Copyright (c) 2015-2016  QLogic Corporation
  3 *
  4 * This software is available to you under a choice of one of two
  5 * licenses.  You may choose to be licensed under the terms of the GNU
  6 * General Public License (GPL) Version 2, available from the file
  7 * COPYING in the main directory of this source tree, or the
  8 * OpenIB.org BSD license below:
  9 *
 10 *     Redistribution and use in source and binary forms, with or
 11 *     without modification, are permitted provided that the following
 12 *     conditions are met:
 13 *
 14 *      - Redistributions of source code must retain the above
 15 *        copyright notice, this list of conditions and the following
 16 *        disclaimer.
 17 *
 18 *      - Redistributions in binary form must reproduce the above
 19 *        copyright notice, this list of conditions and the following
 20 *        disclaimer in the documentation and /or other materials
 21 *        provided with the distribution.
 22 *
 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 30 * SOFTWARE.
 31 */
 32
 33#include <linux/crc32.h>
 34#include "qed.h"
 35#include "qed_dev_api.h"
 36#include "qed_mcp.h"
 37#include "qed_sp.h"
 38#include "qed_selftest.h"
 39
 40int qed_selftest_memory(struct qed_dev *cdev)
 41{
 42	int rc = 0, i;
 43
 44	for_each_hwfn(cdev, i) {
 45		rc = qed_sp_heartbeat_ramrod(&cdev->hwfns[i]);
 46		if (rc)
 47			return rc;
 48	}
 49
 50	return rc;
 51}
 52
 53int qed_selftest_interrupt(struct qed_dev *cdev)
 54{
 55	int rc = 0, i;
 56
 57	for_each_hwfn(cdev, i) {
 58		rc = qed_sp_heartbeat_ramrod(&cdev->hwfns[i]);
 59		if (rc)
 60			return rc;
 61	}
 62
 63	return rc;
 64}
 65
 66int qed_selftest_register(struct qed_dev *cdev)
 67{
 68	struct qed_hwfn *p_hwfn;
 69	struct qed_ptt *p_ptt;
 70	int rc = 0, i;
 71
 72	/* although performed by MCP, this test is per engine */
 73	for_each_hwfn(cdev, i) {
 74		p_hwfn = &cdev->hwfns[i];
 75		p_ptt = qed_ptt_acquire(p_hwfn);
 76		if (!p_ptt) {
 77			DP_ERR(p_hwfn, "failed to acquire ptt\n");
 78			return -EBUSY;
 79		}
 80		rc = qed_mcp_bist_register_test(p_hwfn, p_ptt);
 81		qed_ptt_release(p_hwfn, p_ptt);
 82		if (rc)
 83			break;
 84	}
 85
 86	return rc;
 87}
 88
 89int qed_selftest_clock(struct qed_dev *cdev)
 90{
 91	struct qed_hwfn *p_hwfn;
 92	struct qed_ptt *p_ptt;
 93	int rc = 0, i;
 94
 95	/* although performed by MCP, this test is per engine */
 96	for_each_hwfn(cdev, i) {
 97		p_hwfn = &cdev->hwfns[i];
 98		p_ptt = qed_ptt_acquire(p_hwfn);
 99		if (!p_ptt) {
100			DP_ERR(p_hwfn, "failed to acquire ptt\n");
101			return -EBUSY;
102		}
103		rc = qed_mcp_bist_clock_test(p_hwfn, p_ptt);
104		qed_ptt_release(p_hwfn, p_ptt);
105		if (rc)
106			break;
107	}
108
109	return rc;
110}
111
112int qed_selftest_nvram(struct qed_dev *cdev)
113{
114	struct qed_hwfn *p_hwfn = QED_LEADING_HWFN(cdev);
115	struct qed_ptt *p_ptt = qed_ptt_acquire(p_hwfn);
116	u32 num_images, i, j, nvm_crc, calc_crc;
117	struct bist_nvm_image_att image_att;
118	u8 *buf = NULL;
119	__be32 val;
120	int rc;
121
122	if (!p_ptt) {
123		DP_ERR(p_hwfn, "failed to acquire ptt\n");
124		return -EBUSY;
125	}
126
127	/* Acquire from MFW the amount of available images */
128	rc = qed_mcp_bist_nvm_get_num_images(p_hwfn, p_ptt, &num_images);
129	if (rc || !num_images) {
130		DP_ERR(p_hwfn, "Failed getting number of images\n");
131		rc = -EINVAL;
132		goto err0;
133	}
134
135	/* Iterate over images and validate CRC */
136	for (i = 0; i < num_images; i++) {
137		/* This mailbox returns information about the image required for
138		 * reading it.
139		 */
140		rc = qed_mcp_bist_nvm_get_image_att(p_hwfn, p_ptt,
141						    &image_att, i);
142		if (rc) {
143			DP_ERR(p_hwfn,
144			       "Failed getting image index %d attributes\n",
145			       i);
146			goto err0;
147		}
148
149		/* After MFW crash dump is collected - the image's CRC stops
150		 * being valid.
151		 */
152		if (image_att.image_type == NVM_TYPE_MDUMP)
153			continue;
154
155		DP_VERBOSE(p_hwfn, QED_MSG_SP, "image index %d, size %x\n",
156			   i, image_att.len);
157
158		/* Allocate a buffer for holding the nvram image */
159		buf = kzalloc(image_att.len, GFP_KERNEL);
160		if (!buf) {
161			rc = -ENOMEM;
162			goto err0;
163		}
164
165		/* Read image into buffer */
166		rc = qed_mcp_nvm_read(p_hwfn->cdev, image_att.nvm_start_addr,
167				      buf, image_att.len);
168		if (rc) {
169			DP_ERR(p_hwfn,
170			       "Failed reading image index %d from nvm.\n", i);
171			goto err1;
172		}
173
174		/* Convert the buffer into big-endian format (excluding the
175		 * closing 4 bytes of CRC).
176		 */
177		for (j = 0; j < image_att.len - 4; j += 4) {
178			val = cpu_to_be32(*(u32 *)&buf[j]);
179			*(u32 *)&buf[j] = (__force u32)val;
180		}
181
182		/* Calc CRC for the "actual" image buffer, i.e. not including
183		 * the last 4 CRC bytes.
184		 */
185		nvm_crc = *(u32 *)(buf + image_att.len - 4);
186		calc_crc = crc32(0xffffffff, buf, image_att.len - 4);
187		calc_crc = (__force u32)~cpu_to_be32(calc_crc);
188		DP_VERBOSE(p_hwfn, QED_MSG_SP,
189			   "nvm crc 0x%x, calc_crc 0x%x\n", nvm_crc, calc_crc);
190
191		if (calc_crc != nvm_crc) {
192			rc = -EINVAL;
193			goto err1;
194		}
195
196		/* Done with this image; Free to prevent double release
197		 * on subsequent failure.
198		 */
199		kfree(buf);
200		buf = NULL;
201	}
202
203	qed_ptt_release(p_hwfn, p_ptt);
204	return 0;
205
206err1:
207	kfree(buf);
208err0:
209	qed_ptt_release(p_hwfn, p_ptt);
210	return rc;
211}