cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

qed_selftest.c (4077B)


      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}