drivers/net/ethernet/mellanox/mlx5/core/health.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/mellanox/mlx5/core/health.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/health.c
Extension
.c
Size
27847 bytes
Lines
924
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 mlx5_fw_reporter_ctx {
	u8 err_synd;
	int miss_counter;
};

static void
mlx5_fw_reporter_ctx_pairs_put(struct devlink_fmsg *fmsg,
			       struct mlx5_fw_reporter_ctx *fw_reporter_ctx)
{
	devlink_fmsg_u8_pair_put(fmsg, "syndrome", fw_reporter_ctx->err_synd);
	devlink_fmsg_u32_pair_put(fmsg, "fw_miss_counter", fw_reporter_ctx->miss_counter);
}

static void
mlx5_fw_reporter_heath_buffer_data_put(struct mlx5_core_dev *dev,
				       struct devlink_fmsg *fmsg)
{
	struct mlx5_core_health *health = &dev->priv.health;
	struct health_buffer __iomem *h = health->health;
	u8 rfr_severity;
	int i;

	if (!ioread8(&h->synd))
		return;

	devlink_fmsg_pair_nest_start(fmsg, "health buffer");
	devlink_fmsg_obj_nest_start(fmsg);
	devlink_fmsg_arr_pair_nest_start(fmsg, "assert_var");
	for (i = 0; i < ARRAY_SIZE(h->assert_var); i++)
		devlink_fmsg_u32_put(fmsg, ioread32be(h->assert_var + i));
	devlink_fmsg_arr_pair_nest_end(fmsg);
	devlink_fmsg_u32_pair_put(fmsg, "assert_exit_ptr",
				  ioread32be(&h->assert_exit_ptr));
	devlink_fmsg_u32_pair_put(fmsg, "assert_callra",
				  ioread32be(&h->assert_callra));
	devlink_fmsg_u32_pair_put(fmsg, "time", ioread32be(&h->time));
	devlink_fmsg_u32_pair_put(fmsg, "hw_id", ioread32be(&h->hw_id));
	rfr_severity = ioread8(&h->rfr_severity);
	devlink_fmsg_u8_pair_put(fmsg, "rfr", mlx5_health_get_rfr(rfr_severity));
	devlink_fmsg_u8_pair_put(fmsg, "severity", mlx5_health_get_severity(rfr_severity));
	devlink_fmsg_u8_pair_put(fmsg, "irisc_index", ioread8(&h->irisc_index));
	devlink_fmsg_u8_pair_put(fmsg, "synd", ioread8(&h->synd));
	devlink_fmsg_u32_pair_put(fmsg, "ext_synd", ioread16be(&h->ext_synd));
	devlink_fmsg_u32_pair_put(fmsg, "raw_fw_ver", ioread32be(&h->fw_ver));
	devlink_fmsg_obj_nest_end(fmsg);
	devlink_fmsg_pair_nest_end(fmsg);
}

static int
mlx5_fw_reporter_dump(struct devlink_health_reporter *reporter,
		      struct devlink_fmsg *fmsg, void *priv_ctx,
		      struct netlink_ext_ack *extack)
{
	struct mlx5_core_dev *dev = devlink_health_reporter_priv(reporter);
	int err;

	err = mlx5_fw_tracer_trigger_core_dump_general(dev);
	if (err)
		return err;

	if (priv_ctx) {
		struct mlx5_fw_reporter_ctx *fw_reporter_ctx = priv_ctx;

		mlx5_fw_reporter_ctx_pairs_put(fmsg, fw_reporter_ctx);
	}

	mlx5_fw_reporter_heath_buffer_data_put(dev, fmsg);

	return mlx5_fw_tracer_get_saved_traces_objects(dev->tracer, fmsg);
}

static void mlx5_fw_reporter_err_work(struct work_struct *work)
{
	struct mlx5_fw_reporter_ctx fw_reporter_ctx;
	struct mlx5_core_health *health;

	health = container_of(work, struct mlx5_core_health, report_work);

	if (IS_ERR_OR_NULL(health->fw_reporter))
		return;

	fw_reporter_ctx.err_synd = health->synd;
	fw_reporter_ctx.miss_counter = health->miss_counter;
	if (fw_reporter_ctx.err_synd) {
		devlink_health_report(health->fw_reporter,
				      "FW syndrome reported", &fw_reporter_ctx);
		return;
	}
	if (fw_reporter_ctx.miss_counter)
		devlink_health_report(health->fw_reporter,

Annotation

Implementation Notes