forked from OpenDingux/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement thermal zone support for mlx5 based HW. The NIC uses temperature sensor provided by ASIC to report current temperature to thermal core. Signed-off-by: Sandipan Patra <[email protected]> Reviewed-by: Gal Pressman <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
- Loading branch information
Showing
6 changed files
with
164 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB | ||
// Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. | ||
|
||
#include <linux/kernel.h> | ||
#include <linux/types.h> | ||
#include <linux/device.h> | ||
#include <linux/thermal.h> | ||
#include <linux/err.h> | ||
#include <linux/mlx5/driver.h> | ||
#include "mlx5_core.h" | ||
#include "thermal.h" | ||
|
||
#define MLX5_THERMAL_POLL_INT_MSEC 1000 | ||
#define MLX5_THERMAL_NUM_TRIPS 0 | ||
#define MLX5_THERMAL_ASIC_SENSOR_INDEX 0 | ||
|
||
/* Bit string indicating the writeablility of trip points if any */ | ||
#define MLX5_THERMAL_TRIP_MASK (BIT(MLX5_THERMAL_NUM_TRIPS) - 1) | ||
|
||
struct mlx5_thermal { | ||
struct mlx5_core_dev *mdev; | ||
struct thermal_zone_device *tzdev; | ||
}; | ||
|
||
static int mlx5_thermal_get_mtmp_temp(struct mlx5_core_dev *mdev, u32 id, int *p_temp) | ||
{ | ||
u32 mtmp_out[MLX5_ST_SZ_DW(mtmp_reg)] = {}; | ||
u32 mtmp_in[MLX5_ST_SZ_DW(mtmp_reg)] = {}; | ||
int err; | ||
|
||
MLX5_SET(mtmp_reg, mtmp_in, sensor_index, id); | ||
|
||
err = mlx5_core_access_reg(mdev, mtmp_in, sizeof(mtmp_in), | ||
mtmp_out, sizeof(mtmp_out), | ||
MLX5_REG_MTMP, 0, 0); | ||
|
||
if (err) | ||
return err; | ||
|
||
*p_temp = MLX5_GET(mtmp_reg, mtmp_out, temperature); | ||
|
||
return 0; | ||
} | ||
|
||
static int mlx5_thermal_get_temp(struct thermal_zone_device *tzdev, | ||
int *p_temp) | ||
{ | ||
struct mlx5_thermal *thermal = tzdev->devdata; | ||
struct mlx5_core_dev *mdev = thermal->mdev; | ||
int err; | ||
|
||
err = mlx5_thermal_get_mtmp_temp(mdev, MLX5_THERMAL_ASIC_SENSOR_INDEX, p_temp); | ||
|
||
if (err) | ||
return err; | ||
|
||
/* The unit of temp returned is in 0.125 C. The thermal | ||
* framework expects the value in 0.001 C. | ||
*/ | ||
*p_temp *= 125; | ||
|
||
return 0; | ||
} | ||
|
||
static struct thermal_zone_device_ops mlx5_thermal_ops = { | ||
.get_temp = mlx5_thermal_get_temp, | ||
}; | ||
|
||
int mlx5_thermal_init(struct mlx5_core_dev *mdev) | ||
{ | ||
struct mlx5_thermal *thermal; | ||
struct thermal_zone_device *tzd; | ||
const char *data = "mlx5"; | ||
|
||
tzd = thermal_zone_get_zone_by_name(data); | ||
if (!IS_ERR(tzd)) | ||
return 0; | ||
|
||
thermal = kzalloc(sizeof(*thermal), GFP_KERNEL); | ||
if (!thermal) | ||
return -ENOMEM; | ||
|
||
thermal->mdev = mdev; | ||
thermal->tzdev = thermal_zone_device_register(data, | ||
MLX5_THERMAL_NUM_TRIPS, | ||
MLX5_THERMAL_TRIP_MASK, | ||
thermal, | ||
&mlx5_thermal_ops, | ||
NULL, 0, MLX5_THERMAL_POLL_INT_MSEC); | ||
if (IS_ERR(thermal->tzdev)) { | ||
dev_err(mdev->device, "Failed to register thermal zone device (%s) %ld\n", | ||
data, PTR_ERR(thermal->tzdev)); | ||
kfree(thermal); | ||
return -EINVAL; | ||
} | ||
|
||
mdev->thermal = thermal; | ||
return 0; | ||
} | ||
|
||
void mlx5_thermal_uninit(struct mlx5_core_dev *mdev) | ||
{ | ||
if (!mdev->thermal) | ||
return; | ||
|
||
thermal_zone_device_unregister(mdev->thermal->tzdev); | ||
kfree(mdev->thermal); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB | ||
* Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES. | ||
*/ | ||
#ifndef __MLX5_THERMAL_DRIVER_H | ||
#define __MLX5_THERMAL_DRIVER_H | ||
|
||
#if IS_ENABLED(CONFIG_THERMAL) | ||
int mlx5_thermal_init(struct mlx5_core_dev *mdev); | ||
void mlx5_thermal_uninit(struct mlx5_core_dev *mdev); | ||
#else | ||
static inline int mlx5_thermal_init(struct mlx5_core_dev *mdev) | ||
{ | ||
mdev->thermal = NULL; | ||
return 0; | ||
} | ||
|
||
static inline void mlx5_thermal_uninit(struct mlx5_core_dev *mdev) { } | ||
#endif | ||
|
||
#endif /* __MLX5_THERMAL_DRIVER_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters