drivers/net/ethernet/qlogic/qed/qed_devlink.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/qlogic/qed/qed_devlink.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/qlogic/qed/qed_devlink.c
Extension
.c
Size
6009 bytes
Lines
246
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct qed_fw_fatal_ctx {
	enum qed_hw_err_type err_type;
};

int qed_report_fatal_error(struct devlink *devlink, enum qed_hw_err_type err_type)
{
	struct qed_devlink *qdl = devlink_priv(devlink);
	struct qed_fw_fatal_ctx fw_fatal_ctx = {
		.err_type = err_type,
	};

	if (qdl->fw_reporter)
		devlink_health_report(qdl->fw_reporter,
				      "Fatal error occurred", &fw_fatal_ctx);

	return 0;
}

static int
qed_fw_fatal_reporter_dump(struct devlink_health_reporter *reporter,
			   struct devlink_fmsg *fmsg, void *priv_ctx,
			   struct netlink_ext_ack *extack)
{
	struct qed_devlink *qdl = devlink_health_reporter_priv(reporter);
	struct qed_fw_fatal_ctx *fw_fatal_ctx = priv_ctx;
	struct qed_dev *cdev = qdl->cdev;
	u32 dbg_data_buf_size;
	u8 *p_dbg_data_buf;
	int err;

	/* Having context means that was a dump request after fatal,
	 * so we enable extra debugging while gathering the dump,
	 * just in case
	 */
	cdev->print_dbg_data = fw_fatal_ctx ? true : false;

	dbg_data_buf_size = qed_dbg_all_data_size(cdev);
	p_dbg_data_buf = vzalloc(dbg_data_buf_size);
	if (!p_dbg_data_buf) {
		DP_NOTICE(cdev,
			  "Failed to allocate memory for a debug data buffer\n");
		return -ENOMEM;
	}

	err = qed_dbg_all_data(cdev, p_dbg_data_buf);
	if (err) {
		DP_NOTICE(cdev, "Failed to obtain debug data\n");
		vfree(p_dbg_data_buf);
		return err;
	}

	devlink_fmsg_binary_pair_put(fmsg, "dump_data", p_dbg_data_buf,
				     dbg_data_buf_size);

	vfree(p_dbg_data_buf);

	return 0;
}

static int
qed_fw_fatal_reporter_recover(struct devlink_health_reporter *reporter,
			      void *priv_ctx,
			      struct netlink_ext_ack *extack)
{
	struct qed_devlink *qdl = devlink_health_reporter_priv(reporter);
	struct qed_dev *cdev = qdl->cdev;

	qed_recovery_process(cdev);

	return 0;
}

#define QED_REPORTER_FW_GRACEFUL_PERIOD 0

static const struct devlink_health_reporter_ops qed_fw_fatal_reporter_ops = {
		.name = "fw_fatal",
		.recover = qed_fw_fatal_reporter_recover,
		.dump = qed_fw_fatal_reporter_dump,
		.default_graceful_period = QED_REPORTER_FW_GRACEFUL_PERIOD,
};

void qed_fw_reporters_create(struct devlink *devlink)
{
	struct qed_devlink *dl = devlink_priv(devlink);

	dl->fw_reporter = devlink_health_reporter_create(devlink,
		&qed_fw_fatal_reporter_ops, dl);
	if (IS_ERR(dl->fw_reporter)) {
		DP_NOTICE(dl->cdev, "Failed to create fw reporter, err = %ld\n",
			  PTR_ERR(dl->fw_reporter));

Annotation

Implementation Notes