drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
Extension
.c
Size
36848 bytes
Lines
1262
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

if (err) {
				mlx5_core_dbg(dev, "FWTracer: Failed to read strings DB %d\n",
					      err);
				goto out_free;
			}

			out_value = MLX5_ADDR_OF(mtrc_stdb, out, string_db_data);
			memcpy(tracer->str_db.buffer[i] + offset, out_value,
			       STRINGS_DB_READ_SIZE_BYTES);
			offset += STRINGS_DB_READ_SIZE_BYTES;
		}

		/* Strings database is aligned to 64, need to read leftovers*/
		MLX5_SET(mtrc_stdb, in, read_size,
			 STRINGS_DB_LEFTOVER_SIZE_BYTES);
		for (j = 0; j < leftovers; j++) {
			MLX5_SET(mtrc_stdb, in, start_offset, offset);

			err = mlx5_core_access_reg(dev, in, sizeof(in), out,
						   outlen, MLX5_REG_MTRC_STDB,
						   0, 1);
			if (err) {
				mlx5_core_dbg(dev, "FWTracer: Failed to read strings DB %d\n",
					      err);
				goto out_free;
			}

			out_value = MLX5_ADDR_OF(mtrc_stdb, out, string_db_data);
			memcpy(tracer->str_db.buffer[i] + offset, out_value,
			       STRINGS_DB_LEFTOVER_SIZE_BYTES);
			offset += STRINGS_DB_LEFTOVER_SIZE_BYTES;
		}
	}

	tracer->str_db.loaded = true;

out_free:
	kfree(out);
out:
	return;
}

static void mlx5_fw_tracer_arm(struct mlx5_core_dev *dev)
{
	u32 out[MLX5_ST_SZ_DW(mtrc_ctrl)] = {0};
	u32 in[MLX5_ST_SZ_DW(mtrc_ctrl)] = {0};
	int err;

	MLX5_SET(mtrc_ctrl, in, arm_event, 1);

	err = mlx5_core_access_reg(dev, in, sizeof(in), out, sizeof(out),
				   MLX5_REG_MTRC_CTRL, 0, 1);
	if (err)
		mlx5_core_warn(dev, "FWTracer: Failed to arm tracer event %d\n", err);
}

static const char *VAL_PARM		= "%llx";
static const char *REPLACE_64_VAL_PARM	= "%x%x";
static const char *PARAM_CHAR		= "%";

static bool mlx5_is_valid_spec(const char *str)
{
	/* Parse format specifiers to find the actual type.
	 * Structure: %[flags][width][.precision][length]type
	 * Skip flags, width, precision & length.
	 */
	while (isdigit(*str) || *str == '#' || *str == '.' || *str == 'l')
		str++;

	/* Check if it's a valid integer/hex specifier or %%:
	 * Valid formats: %x, %d, %i, %u, etc.
	 */
	if (*str != 'x' && *str != 'X' && *str != 'd' && *str != 'i' &&
	    *str != 'u' && *str != 'c' && *str != '%')
		return false;

	return true;
}

static bool mlx5_tracer_validate_params(const char *str)
{
	const char *substr = str;

	if (!str)
		return false;

	substr = strstr(substr, PARAM_CHAR);
	while (substr) {
		if (!mlx5_is_valid_spec(substr + 1))
			return false;

Annotation

Implementation Notes