1 /* Broadcom NetXtreme-C/E network driver.
3 * Copyright (c) 2023 Broadcom Limited
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation.
10 #include <linux/dev_printk.h>
11 #include <linux/errno.h>
12 #include <linux/hwmon.h>
13 #include <linux/hwmon-sysfs.h>
14 #include <linux/pci.h>
18 #include "bnxt_hwrm.h"
19 #include "bnxt_hwmon.h"
21 void bnxt_hwmon_notify_event(struct bnxt
*bp
)
28 switch (bp
->thermal_threshold_type
) {
29 case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_WARN
:
30 attr
= hwmon_temp_max_alarm
;
32 case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_CRITICAL
:
33 attr
= hwmon_temp_crit_alarm
;
35 case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_FATAL
:
36 case ASYNC_EVENT_CMPL_ERROR_REPORT_THERMAL_EVENT_DATA1_THRESHOLD_TYPE_SHUTDOWN
:
37 attr
= hwmon_temp_emergency_alarm
;
43 hwmon_notify_event(&bp
->pdev
->dev
, hwmon_temp
, attr
, 0);
46 static int bnxt_hwrm_temp_query(struct bnxt
*bp
, u8
*temp
)
48 struct hwrm_temp_monitor_query_output
*resp
;
49 struct hwrm_temp_monitor_query_input
*req
;
52 rc
= hwrm_req_init(bp
, req
, HWRM_TEMP_MONITOR_QUERY
);
55 resp
= hwrm_req_hold(bp
, req
);
56 rc
= hwrm_req_send_silent(bp
, req
);
62 } else if (resp
->flags
&
63 TEMP_MONITOR_QUERY_RESP_FLAGS_THRESHOLD_VALUES_AVAILABLE
) {
64 bp
->fw_cap
|= BNXT_FW_CAP_THRESHOLD_TEMP_SUPPORTED
;
65 bp
->warn_thresh_temp
= resp
->warn_threshold
;
66 bp
->crit_thresh_temp
= resp
->critical_threshold
;
67 bp
->fatal_thresh_temp
= resp
->fatal_threshold
;
68 bp
->shutdown_thresh_temp
= resp
->shutdown_threshold
;
71 hwrm_req_drop(bp
, req
);
75 static umode_t
bnxt_hwmon_is_visible(const void *_data
, enum hwmon_sensor_types type
,
76 u32 attr
, int channel
)
78 const struct bnxt
*bp
= _data
;
80 if (type
!= hwmon_temp
)
84 case hwmon_temp_input
:
88 case hwmon_temp_emergency
:
89 case hwmon_temp_max_alarm
:
90 case hwmon_temp_crit_alarm
:
91 case hwmon_temp_emergency_alarm
:
92 if (!(bp
->fw_cap
& BNXT_FW_CAP_THRESHOLD_TEMP_SUPPORTED
))
100 static int bnxt_hwmon_read(struct device
*dev
, enum hwmon_sensor_types type
, u32 attr
,
101 int channel
, long *val
)
103 struct bnxt
*bp
= dev_get_drvdata(dev
);
108 case hwmon_temp_input
:
109 rc
= bnxt_hwrm_temp_query(bp
, &temp
);
114 *val
= bp
->warn_thresh_temp
* 1000;
116 case hwmon_temp_crit
:
117 *val
= bp
->crit_thresh_temp
* 1000;
119 case hwmon_temp_emergency
:
120 *val
= bp
->fatal_thresh_temp
* 1000;
122 case hwmon_temp_max_alarm
:
123 rc
= bnxt_hwrm_temp_query(bp
, &temp
);
125 *val
= temp
>= bp
->warn_thresh_temp
;
127 case hwmon_temp_crit_alarm
:
128 rc
= bnxt_hwrm_temp_query(bp
, &temp
);
130 *val
= temp
>= bp
->crit_thresh_temp
;
132 case hwmon_temp_emergency_alarm
:
133 rc
= bnxt_hwrm_temp_query(bp
, &temp
);
135 *val
= temp
>= bp
->fatal_thresh_temp
;
142 static const struct hwmon_channel_info
*bnxt_hwmon_info
[] = {
143 HWMON_CHANNEL_INFO(temp
, HWMON_T_INPUT
| HWMON_T_MAX
| HWMON_T_CRIT
|
144 HWMON_T_EMERGENCY
| HWMON_T_MAX_ALARM
|
145 HWMON_T_CRIT_ALARM
| HWMON_T_EMERGENCY_ALARM
),
149 static const struct hwmon_ops bnxt_hwmon_ops
= {
150 .is_visible
= bnxt_hwmon_is_visible
,
151 .read
= bnxt_hwmon_read
,
154 static const struct hwmon_chip_info bnxt_hwmon_chip_info
= {
155 .ops
= &bnxt_hwmon_ops
,
156 .info
= bnxt_hwmon_info
,
159 static ssize_t
temp1_shutdown_show(struct device
*dev
,
160 struct device_attribute
*attr
, char *buf
)
162 struct bnxt
*bp
= dev_get_drvdata(dev
);
164 return sysfs_emit(buf
, "%u\n", bp
->shutdown_thresh_temp
* 1000);
167 static ssize_t
temp1_shutdown_alarm_show(struct device
*dev
,
168 struct device_attribute
*attr
, char *buf
)
170 struct bnxt
*bp
= dev_get_drvdata(dev
);
174 rc
= bnxt_hwrm_temp_query(bp
, &temp
);
178 return sysfs_emit(buf
, "%u\n", temp
>= bp
->shutdown_thresh_temp
);
181 static DEVICE_ATTR_RO(temp1_shutdown
);
182 static DEVICE_ATTR_RO(temp1_shutdown_alarm
);
184 static struct attribute
*bnxt_temp_extra_attrs
[] = {
185 &dev_attr_temp1_shutdown
.attr
,
186 &dev_attr_temp1_shutdown_alarm
.attr
,
190 static umode_t
bnxt_temp_extra_attrs_visible(struct kobject
*kobj
,
191 struct attribute
*attr
, int index
)
193 struct device
*dev
= kobj_to_dev(kobj
);
194 struct bnxt
*bp
= dev_get_drvdata(dev
);
196 /* Shutdown temperature setting in NVM is optional */
197 if (!(bp
->fw_cap
& BNXT_FW_CAP_THRESHOLD_TEMP_SUPPORTED
) ||
198 !bp
->shutdown_thresh_temp
)
204 static const struct attribute_group bnxt_temp_extra_group
= {
205 .attrs
= bnxt_temp_extra_attrs
,
206 .is_visible
= bnxt_temp_extra_attrs_visible
,
208 __ATTRIBUTE_GROUPS(bnxt_temp_extra
);
210 void bnxt_hwmon_uninit(struct bnxt
*bp
)
213 hwmon_device_unregister(bp
->hwmon_dev
);
214 bp
->hwmon_dev
= NULL
;
218 void bnxt_hwmon_init(struct bnxt
*bp
)
220 struct pci_dev
*pdev
= bp
->pdev
;
223 /* temp1_xxx is only sensor, ensure not registered if it will fail */
224 rc
= bnxt_hwrm_temp_query(bp
, NULL
);
225 if (rc
== -EACCES
|| rc
== -EOPNOTSUPP
) {
226 bnxt_hwmon_uninit(bp
);
233 bp
->hwmon_dev
= hwmon_device_register_with_info(&pdev
->dev
,
235 &bnxt_hwmon_chip_info
,
236 bnxt_temp_extra_groups
);
237 if (IS_ERR(bp
->hwmon_dev
)) {
238 bp
->hwmon_dev
= NULL
;
239 dev_warn(&pdev
->dev
, "Cannot register hwmon device\n");