brintos

brintos / linux-shallow public Read only

0
0
Text · 5.8 KiB · 1adc7fb Raw
244 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/* Marvell/Qlogic FastLinQ NIC driver3 *4 * Copyright (C) 2020 Marvell International Ltd.5 */6 7#include <linux/kernel.h>8#include <linux/qed/qed_if.h>9#include <linux/vmalloc.h>10#include "qed.h"11#include "qed_devlink.h"12 13enum qed_devlink_param_id {14	QED_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,15	QED_DEVLINK_PARAM_ID_IWARP_CMT,16};17 18struct qed_fw_fatal_ctx {19	enum qed_hw_err_type err_type;20};21 22int qed_report_fatal_error(struct devlink *devlink, enum qed_hw_err_type err_type)23{24	struct qed_devlink *qdl = devlink_priv(devlink);25	struct qed_fw_fatal_ctx fw_fatal_ctx = {26		.err_type = err_type,27	};28 29	if (qdl->fw_reporter)30		devlink_health_report(qdl->fw_reporter,31				      "Fatal error occurred", &fw_fatal_ctx);32 33	return 0;34}35 36static int37qed_fw_fatal_reporter_dump(struct devlink_health_reporter *reporter,38			   struct devlink_fmsg *fmsg, void *priv_ctx,39			   struct netlink_ext_ack *extack)40{41	struct qed_devlink *qdl = devlink_health_reporter_priv(reporter);42	struct qed_fw_fatal_ctx *fw_fatal_ctx = priv_ctx;43	struct qed_dev *cdev = qdl->cdev;44	u32 dbg_data_buf_size;45	u8 *p_dbg_data_buf;46	int err;47 48	/* Having context means that was a dump request after fatal,49	 * so we enable extra debugging while gathering the dump,50	 * just in case51	 */52	cdev->print_dbg_data = fw_fatal_ctx ? true : false;53 54	dbg_data_buf_size = qed_dbg_all_data_size(cdev);55	p_dbg_data_buf = vzalloc(dbg_data_buf_size);56	if (!p_dbg_data_buf) {57		DP_NOTICE(cdev,58			  "Failed to allocate memory for a debug data buffer\n");59		return -ENOMEM;60	}61 62	err = qed_dbg_all_data(cdev, p_dbg_data_buf);63	if (err) {64		DP_NOTICE(cdev, "Failed to obtain debug data\n");65		vfree(p_dbg_data_buf);66		return err;67	}68 69	devlink_fmsg_binary_pair_put(fmsg, "dump_data", p_dbg_data_buf,70				     dbg_data_buf_size);71 72	vfree(p_dbg_data_buf);73 74	return 0;75}76 77static int78qed_fw_fatal_reporter_recover(struct devlink_health_reporter *reporter,79			      void *priv_ctx,80			      struct netlink_ext_ack *extack)81{82	struct qed_devlink *qdl = devlink_health_reporter_priv(reporter);83	struct qed_dev *cdev = qdl->cdev;84 85	qed_recovery_process(cdev);86 87	return 0;88}89 90static const struct devlink_health_reporter_ops qed_fw_fatal_reporter_ops = {91		.name = "fw_fatal",92		.recover = qed_fw_fatal_reporter_recover,93		.dump = qed_fw_fatal_reporter_dump,94};95 96#define QED_REPORTER_FW_GRACEFUL_PERIOD 097 98void qed_fw_reporters_create(struct devlink *devlink)99{100	struct qed_devlink *dl = devlink_priv(devlink);101 102	dl->fw_reporter = devlink_health_reporter_create(devlink, &qed_fw_fatal_reporter_ops,103							 QED_REPORTER_FW_GRACEFUL_PERIOD, dl);104	if (IS_ERR(dl->fw_reporter)) {105		DP_NOTICE(dl->cdev, "Failed to create fw reporter, err = %ld\n",106			  PTR_ERR(dl->fw_reporter));107		dl->fw_reporter = NULL;108	}109}110 111void qed_fw_reporters_destroy(struct devlink *devlink)112{113	struct qed_devlink *dl = devlink_priv(devlink);114	struct devlink_health_reporter *rep;115 116	rep = dl->fw_reporter;117 118	if (!IS_ERR_OR_NULL(rep))119		devlink_health_reporter_destroy(rep);120}121 122static int qed_dl_param_get(struct devlink *dl, u32 id,123			    struct devlink_param_gset_ctx *ctx)124{125	struct qed_devlink *qed_dl = devlink_priv(dl);126	struct qed_dev *cdev;127 128	cdev = qed_dl->cdev;129	ctx->val.vbool = cdev->iwarp_cmt;130 131	return 0;132}133 134static int qed_dl_param_set(struct devlink *dl, u32 id,135			    struct devlink_param_gset_ctx *ctx,136			    struct netlink_ext_ack *extack)137{138	struct qed_devlink *qed_dl = devlink_priv(dl);139	struct qed_dev *cdev;140 141	cdev = qed_dl->cdev;142	cdev->iwarp_cmt = ctx->val.vbool;143 144	return 0;145}146 147static const struct devlink_param qed_devlink_params[] = {148	DEVLINK_PARAM_DRIVER(QED_DEVLINK_PARAM_ID_IWARP_CMT,149			     "iwarp_cmt", DEVLINK_PARAM_TYPE_BOOL,150			     BIT(DEVLINK_PARAM_CMODE_RUNTIME),151			     qed_dl_param_get, qed_dl_param_set, NULL),152};153 154static int qed_devlink_info_get(struct devlink *devlink,155				struct devlink_info_req *req,156				struct netlink_ext_ack *extack)157{158	struct qed_devlink *qed_dl = devlink_priv(devlink);159	struct qed_dev *cdev = qed_dl->cdev;160	struct qed_dev_info *dev_info;161	char buf[100];162	int err;163 164	dev_info = &cdev->common_dev_info;165 166	memcpy(buf, cdev->hwfns[0].hw_info.part_num, sizeof(cdev->hwfns[0].hw_info.part_num));167	buf[sizeof(cdev->hwfns[0].hw_info.part_num)] = 0;168 169	if (buf[0]) {170		err = devlink_info_board_serial_number_put(req, buf);171		if (err)172			return err;173	}174 175	snprintf(buf, sizeof(buf), "%d.%d.%d.%d",176		 GET_MFW_FIELD(dev_info->mfw_rev, QED_MFW_VERSION_3),177		 GET_MFW_FIELD(dev_info->mfw_rev, QED_MFW_VERSION_2),178		 GET_MFW_FIELD(dev_info->mfw_rev, QED_MFW_VERSION_1),179		 GET_MFW_FIELD(dev_info->mfw_rev, QED_MFW_VERSION_0));180 181	err = devlink_info_version_stored_put(req,182					      DEVLINK_INFO_VERSION_GENERIC_FW_MGMT, buf);183	if (err)184		return err;185 186	snprintf(buf, sizeof(buf), "%d.%d.%d.%d",187		 dev_info->fw_major,188		 dev_info->fw_minor,189		 dev_info->fw_rev,190		 dev_info->fw_eng);191 192	return devlink_info_version_running_put(req,193						DEVLINK_INFO_VERSION_GENERIC_FW_APP, buf);194}195 196static const struct devlink_ops qed_dl_ops = {197	.info_get = qed_devlink_info_get,198};199 200struct devlink *qed_devlink_register(struct qed_dev *cdev)201{202	struct qed_devlink *qdevlink;203	struct devlink *dl;204	int rc;205 206	dl = devlink_alloc(&qed_dl_ops, sizeof(struct qed_devlink),207			   &cdev->pdev->dev);208	if (!dl)209		return ERR_PTR(-ENOMEM);210 211	qdevlink = devlink_priv(dl);212	qdevlink->cdev = cdev;213 214	rc = devlink_params_register(dl, qed_devlink_params,215				     ARRAY_SIZE(qed_devlink_params));216	if (rc)217		goto err_unregister;218 219	cdev->iwarp_cmt = false;220 221	qed_fw_reporters_create(dl);222	devlink_register(dl);223	return dl;224 225err_unregister:226	devlink_free(dl);227 228	return ERR_PTR(rc);229}230 231void qed_devlink_unregister(struct devlink *devlink)232{233	if (!devlink)234		return;235 236	devlink_unregister(devlink);237	qed_fw_reporters_destroy(devlink);238 239	devlink_params_unregister(devlink, qed_devlink_params,240				  ARRAY_SIZE(qed_devlink_params));241 242	devlink_free(devlink);243}244