net/mlx5: Expose port.c/mlx5_query_module_num() function
[linux-2.6-block.git] / drivers / net / ethernet / mellanox / mlx5 / core / thermal.c
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 // Copyright (c) 2023, NVIDIA CORPORATION & AFFILIATES.
3
4 #include <linux/kernel.h>
5 #include <linux/types.h>
6 #include <linux/device.h>
7 #include <linux/thermal.h>
8 #include <linux/err.h>
9 #include <linux/mlx5/driver.h>
10 #include "mlx5_core.h"
11 #include "thermal.h"
12
13 #define MLX5_THERMAL_POLL_INT_MSEC      1000
14 #define MLX5_THERMAL_NUM_TRIPS          0
15 #define MLX5_THERMAL_ASIC_SENSOR_INDEX  0
16
17 /* Bit string indicating the writeablility of trip points if any */
18 #define MLX5_THERMAL_TRIP_MASK  (BIT(MLX5_THERMAL_NUM_TRIPS) - 1)
19
20 struct mlx5_thermal {
21         struct mlx5_core_dev *mdev;
22         struct thermal_zone_device *tzdev;
23 };
24
25 static int mlx5_thermal_get_mtmp_temp(struct mlx5_core_dev *mdev, u32 id, int *p_temp)
26 {
27         u32 mtmp_out[MLX5_ST_SZ_DW(mtmp_reg)] = {};
28         u32 mtmp_in[MLX5_ST_SZ_DW(mtmp_reg)] = {};
29         int err;
30
31         MLX5_SET(mtmp_reg, mtmp_in, sensor_index, id);
32
33         err = mlx5_core_access_reg(mdev, mtmp_in,  sizeof(mtmp_in),
34                                    mtmp_out, sizeof(mtmp_out),
35                                    MLX5_REG_MTMP, 0, 0);
36
37         if (err)
38                 return err;
39
40         *p_temp = MLX5_GET(mtmp_reg, mtmp_out, temperature);
41
42         return 0;
43 }
44
45 static int mlx5_thermal_get_temp(struct thermal_zone_device *tzdev,
46                                  int *p_temp)
47 {
48         struct mlx5_thermal *thermal = thermal_zone_device_priv(tzdev);
49         struct mlx5_core_dev *mdev = thermal->mdev;
50         int err;
51
52         err = mlx5_thermal_get_mtmp_temp(mdev, MLX5_THERMAL_ASIC_SENSOR_INDEX, p_temp);
53
54         if (err)
55                 return err;
56
57         /* The unit of temp returned is in 0.125 C. The thermal
58          * framework expects the value in 0.001 C.
59          */
60         *p_temp *= 125;
61
62         return 0;
63 }
64
65 static struct thermal_zone_device_ops mlx5_thermal_ops = {
66         .get_temp = mlx5_thermal_get_temp,
67 };
68
69 int mlx5_thermal_init(struct mlx5_core_dev *mdev)
70 {
71         char data[THERMAL_NAME_LENGTH];
72         struct mlx5_thermal *thermal;
73         int err;
74
75         if (!mlx5_core_is_pf(mdev) && !mlx5_core_is_ecpf(mdev))
76                 return 0;
77
78         err = snprintf(data, sizeof(data), "mlx5_%s", dev_name(mdev->device));
79         if (err < 0 || err >= sizeof(data)) {
80                 mlx5_core_err(mdev, "Failed to setup thermal zone name, %d\n", err);
81                 return -EINVAL;
82         }
83
84         thermal = kzalloc(sizeof(*thermal), GFP_KERNEL);
85         if (!thermal)
86                 return -ENOMEM;
87
88         thermal->mdev = mdev;
89         thermal->tzdev = thermal_zone_device_register_with_trips(data,
90                                                                  NULL,
91                                                                  MLX5_THERMAL_NUM_TRIPS,
92                                                                  MLX5_THERMAL_TRIP_MASK,
93                                                                  thermal,
94                                                                  &mlx5_thermal_ops,
95                                                                  NULL, 0, MLX5_THERMAL_POLL_INT_MSEC);
96         if (IS_ERR(thermal->tzdev)) {
97                 err = PTR_ERR(thermal->tzdev);
98                 mlx5_core_err(mdev, "Failed to register thermal zone device (%s) %d\n", data, err);
99                 kfree(thermal);
100                 return err;
101         }
102
103         mdev->thermal = thermal;
104         return 0;
105 }
106
107 void mlx5_thermal_uninit(struct mlx5_core_dev *mdev)
108 {
109         if (!mdev->thermal)
110                 return;
111
112         thermal_zone_device_unregister(mdev->thermal->tzdev);
113         kfree(mdev->thermal);
114 }