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

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/mellanox/mlx5/core/hwmon.c
Extension
.c
Size
10868 bytes
Lines
424
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 temp_channel_desc {
	u32 sensor_index;
	char sensor_name[32];
};

/* chip_channel_config and channel_info arrays must be 0-terminated, hence + 1 */
struct mlx5_hwmon {
	struct mlx5_core_dev *mdev;
	struct device *hwmon_dev;
	struct hwmon_channel_info chip_info;
	u32 chip_channel_config[CHIP_CONFIG_NUM + 1];
	struct hwmon_channel_info temp_info;
	u32 *temp_channel_config;
	const struct hwmon_channel_info *channel_info[CHANNELS_TYPE_NUM + 1];
	struct hwmon_chip_info chip;
	struct temp_channel_desc *temp_channel_desc;
	u32 asic_platform_scount;
	u32 module_scount;
};

static int mlx5_hwmon_query_mtmp(struct mlx5_core_dev *mdev, u32 sensor_index, u32 *mtmp_out)
{
	u32 mtmp_in[MLX5_ST_SZ_DW(mtmp_reg)] = {};

	MLX5_SET(mtmp_reg, mtmp_in, sensor_index, sensor_index);

	return mlx5_core_access_reg(mdev, mtmp_in,  sizeof(mtmp_in),
				    mtmp_out, MLX5_ST_SZ_BYTES(mtmp_reg),
				    MLX5_REG_MTMP, 0, 0);
}

static int mlx5_hwmon_reset_max_temp(struct mlx5_core_dev *mdev, int sensor_index)
{
	u32 mtmp_out[MLX5_ST_SZ_DW(mtmp_reg)] = {};
	u32 mtmp_in[MLX5_ST_SZ_DW(mtmp_reg)] = {};

	MLX5_SET(mtmp_reg, mtmp_in, sensor_index, sensor_index);
	MLX5_SET(mtmp_reg, mtmp_in, mtr, 1);

	return mlx5_core_access_reg(mdev, mtmp_in,  sizeof(mtmp_in),
				    mtmp_out, sizeof(mtmp_out),
				    MLX5_REG_MTMP, 0, 0);
}

static int mlx5_hwmon_enable_max_temp(struct mlx5_core_dev *mdev, int sensor_index)
{
	u32 mtmp_out[MLX5_ST_SZ_DW(mtmp_reg)] = {};
	u32 mtmp_in[MLX5_ST_SZ_DW(mtmp_reg)] = {};
	int err;

	err = mlx5_hwmon_query_mtmp(mdev, sensor_index, mtmp_in);
	if (err)
		return err;

	MLX5_SET(mtmp_reg, mtmp_in, mte, 1);
	return mlx5_core_access_reg(mdev, mtmp_in,  sizeof(mtmp_in),
				    mtmp_out, sizeof(mtmp_out),
				    MLX5_REG_MTMP, 0, 1);
}

static int mlx5_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
			   int channel, long *val)
{
	struct mlx5_hwmon *hwmon = dev_get_drvdata(dev);
	u32 mtmp_out[MLX5_ST_SZ_DW(mtmp_reg)] = {};
	int err;

	if (type != hwmon_temp)
		return -EOPNOTSUPP;

	err = mlx5_hwmon_query_mtmp(hwmon->mdev, hwmon->temp_channel_desc[channel].sensor_index,
				    mtmp_out);
	if (err)
		return err;

	switch (attr) {
	case hwmon_temp_input:
		*val = mtmp_temp_to_mdeg(MLX5_GET(mtmp_reg, mtmp_out, temperature));
		return 0;
	case hwmon_temp_highest:
		*val = mtmp_temp_to_mdeg(MLX5_GET(mtmp_reg, mtmp_out, max_temperature));
		return 0;
	case hwmon_temp_crit:
		*val = mtmp_temp_to_mdeg(MLX5_GET(mtmp_reg, mtmp_out, temp_threshold_hi));
		return 0;
	default:
		return -EOPNOTSUPP;
	}
}

Annotation

Implementation Notes