hwmon.c (44e3ad882bb268563766c45cd842a229dd3a4902) hwmon.c (1597b374af22266266e1e20612208c4b11359ad4)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
4 *
5 * This file defines the sysfs class "hwmon", for use by sensors drivers.
6 *
7 * Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
8 */
9
10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11
12#include <linux/bitops.h>
13#include <linux/device.h>
14#include <linux/err.h>
15#include <linux/gfp.h>
16#include <linux/hwmon.h>
17#include <linux/idr.h>
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
4 *
5 * This file defines the sysfs class "hwmon", for use by sensors drivers.
6 *
7 * Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
8 */
9
10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11
12#include <linux/bitops.h>
13#include <linux/device.h>
14#include <linux/err.h>
15#include <linux/gfp.h>
16#include <linux/hwmon.h>
17#include <linux/idr.h>
18#include <linux/list.h>
18#include <linux/module.h>
19#include <linux/pci.h>
20#include <linux/slab.h>
21#include <linux/string.h>
22#include <linux/thermal.h>
23
24#define CREATE_TRACE_POINTS
25#include <trace/events/hwmon.h>
26
27#define HWMON_ID_PREFIX "hwmon"
28#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
29
30struct hwmon_device {
31 const char *name;
32 struct device dev;
33 const struct hwmon_chip_info *chip;
19#include <linux/module.h>
20#include <linux/pci.h>
21#include <linux/slab.h>
22#include <linux/string.h>
23#include <linux/thermal.h>
24
25#define CREATE_TRACE_POINTS
26#include <trace/events/hwmon.h>
27
28#define HWMON_ID_PREFIX "hwmon"
29#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
30
31struct hwmon_device {
32 const char *name;
33 struct device dev;
34 const struct hwmon_chip_info *chip;
34
35 struct list_head tzdata;
35 struct attribute_group group;
36 const struct attribute_group **groups;
37};
38
39#define to_hwmon_device(d) container_of(d, struct hwmon_device, dev)
40
41#define MAX_SYSFS_ATTR_NAME_LENGTH 32
42

--- 7 unchanged lines hidden (view full) ---

50};
51
52#define to_hwmon_attr(d) \
53 container_of(d, struct hwmon_device_attribute, dev_attr)
54#define to_dev_attr(a) container_of(a, struct device_attribute, attr)
55
56/*
57 * Thermal zone information
36 struct attribute_group group;
37 const struct attribute_group **groups;
38};
39
40#define to_hwmon_device(d) container_of(d, struct hwmon_device, dev)
41
42#define MAX_SYSFS_ATTR_NAME_LENGTH 32
43

--- 7 unchanged lines hidden (view full) ---

51};
52
53#define to_hwmon_attr(d) \
54 container_of(d, struct hwmon_device_attribute, dev_attr)
55#define to_dev_attr(a) container_of(a, struct device_attribute, attr)
56
57/*
58 * Thermal zone information
58 * In addition to the reference to the hwmon device,
59 * also provides the sensor index.
60 */
61struct hwmon_thermal_data {
59 */
60struct hwmon_thermal_data {
61 struct list_head node; /* hwmon tzdata list entry */
62 struct device *dev; /* Reference to hwmon device */
63 int index; /* sensor index */
62 struct device *dev; /* Reference to hwmon device */
63 int index; /* sensor index */
64 struct thermal_zone_device *tzd;/* thermal zone device */
64};
65
66static ssize_t
67name_show(struct device *dev, struct device_attribute *attr, char *buf)
68{
69 return sprintf(buf, "%s\n", to_hwmon_device(dev)->name);
70}
71static DEVICE_ATTR_RO(name);

--- 79 unchanged lines hidden (view full) ---

151
152 return 0;
153}
154
155static const struct thermal_zone_of_device_ops hwmon_thermal_ops = {
156 .get_temp = hwmon_thermal_get_temp,
157};
158
65};
66
67static ssize_t
68name_show(struct device *dev, struct device_attribute *attr, char *buf)
69{
70 return sprintf(buf, "%s\n", to_hwmon_device(dev)->name);
71}
72static DEVICE_ATTR_RO(name);

--- 79 unchanged lines hidden (view full) ---

152
153 return 0;
154}
155
156static const struct thermal_zone_of_device_ops hwmon_thermal_ops = {
157 .get_temp = hwmon_thermal_get_temp,
158};
159
160static void hwmon_thermal_remove_sensor(void *data)
161{
162 list_del(data);
163}
164
159static int hwmon_thermal_add_sensor(struct device *dev, int index)
160{
165static int hwmon_thermal_add_sensor(struct device *dev, int index)
166{
167 struct hwmon_device *hwdev = to_hwmon_device(dev);
161 struct hwmon_thermal_data *tdata;
162 struct thermal_zone_device *tzd;
168 struct hwmon_thermal_data *tdata;
169 struct thermal_zone_device *tzd;
170 int err;
163
164 tdata = devm_kzalloc(dev, sizeof(*tdata), GFP_KERNEL);
165 if (!tdata)
166 return -ENOMEM;
167
168 tdata->dev = dev;
169 tdata->index = index;
170
171 tzd = devm_thermal_zone_of_sensor_register(dev, index, tdata,
172 &hwmon_thermal_ops);
173 /*
174 * If CONFIG_THERMAL_OF is disabled, this returns -ENODEV,
175 * so ignore that error but forward any other error.
176 */
177 if (IS_ERR(tzd) && (PTR_ERR(tzd) != -ENODEV))
178 return PTR_ERR(tzd);
179
171
172 tdata = devm_kzalloc(dev, sizeof(*tdata), GFP_KERNEL);
173 if (!tdata)
174 return -ENOMEM;
175
176 tdata->dev = dev;
177 tdata->index = index;
178
179 tzd = devm_thermal_zone_of_sensor_register(dev, index, tdata,
180 &hwmon_thermal_ops);
181 /*
182 * If CONFIG_THERMAL_OF is disabled, this returns -ENODEV,
183 * so ignore that error but forward any other error.
184 */
185 if (IS_ERR(tzd) && (PTR_ERR(tzd) != -ENODEV))
186 return PTR_ERR(tzd);
187
188 err = devm_add_action(dev, hwmon_thermal_remove_sensor, &tdata->node);
189 if (err)
190 return err;
191
192 tdata->tzd = tzd;
193 list_add(&tdata->node, &hwdev->tzdata);
194
180 return 0;
181}
182
183static int hwmon_thermal_register_sensors(struct device *dev)
184{
185 struct hwmon_device *hwdev = to_hwmon_device(dev);
186 const struct hwmon_chip_info *chip = hwdev->chip;
187 const struct hwmon_channel_info **info = chip->info;

--- 18 unchanged lines hidden (view full) ---

206 if (err)
207 return err;
208 }
209 }
210
211 return 0;
212}
213
195 return 0;
196}
197
198static int hwmon_thermal_register_sensors(struct device *dev)
199{
200 struct hwmon_device *hwdev = to_hwmon_device(dev);
201 const struct hwmon_chip_info *chip = hwdev->chip;
202 const struct hwmon_channel_info **info = chip->info;

--- 18 unchanged lines hidden (view full) ---

221 if (err)
222 return err;
223 }
224 }
225
226 return 0;
227}
228
229static void hwmon_thermal_notify(struct device *dev, int index)
230{
231 struct hwmon_device *hwdev = to_hwmon_device(dev);
232 struct hwmon_thermal_data *tzdata;
233
234 list_for_each_entry(tzdata, &hwdev->tzdata, node) {
235 if (tzdata->index == index) {
236 thermal_zone_device_update(tzdata->tzd,
237 THERMAL_EVENT_UNSPECIFIED);
238 }
239 }
240}
241
214#else
215static int hwmon_thermal_register_sensors(struct device *dev)
216{
217 return 0;
218}
242#else
243static int hwmon_thermal_register_sensors(struct device *dev)
244{
245 return 0;
246}
247
248static void hwmon_thermal_notify(struct device *dev, int index) { }
249
219#endif /* IS_REACHABLE(CONFIG_THERMAL) && ... */
220
221static int hwmon_attr_base(enum hwmon_sensor_types type)
222{
223 if (type == hwmon_in || type == hwmon_intrusion)
224 return 0;
225 return 1;
226}

--- 311 unchanged lines hidden (view full) ---

538 [hwmon_power] = ARRAY_SIZE(hwmon_power_attr_templates),
539 [hwmon_energy] = ARRAY_SIZE(hwmon_energy_attr_templates),
540 [hwmon_humidity] = ARRAY_SIZE(hwmon_humidity_attr_templates),
541 [hwmon_fan] = ARRAY_SIZE(hwmon_fan_attr_templates),
542 [hwmon_pwm] = ARRAY_SIZE(hwmon_pwm_attr_templates),
543 [hwmon_intrusion] = ARRAY_SIZE(hwmon_intrusion_attr_templates),
544};
545
250#endif /* IS_REACHABLE(CONFIG_THERMAL) && ... */
251
252static int hwmon_attr_base(enum hwmon_sensor_types type)
253{
254 if (type == hwmon_in || type == hwmon_intrusion)
255 return 0;
256 return 1;
257}

--- 311 unchanged lines hidden (view full) ---

569 [hwmon_power] = ARRAY_SIZE(hwmon_power_attr_templates),
570 [hwmon_energy] = ARRAY_SIZE(hwmon_energy_attr_templates),
571 [hwmon_humidity] = ARRAY_SIZE(hwmon_humidity_attr_templates),
572 [hwmon_fan] = ARRAY_SIZE(hwmon_fan_attr_templates),
573 [hwmon_pwm] = ARRAY_SIZE(hwmon_pwm_attr_templates),
574 [hwmon_intrusion] = ARRAY_SIZE(hwmon_intrusion_attr_templates),
575};
576
577int hwmon_notify_event(struct device *dev, enum hwmon_sensor_types type,
578 u32 attr, int channel)
579{
580 char sattr[MAX_SYSFS_ATTR_NAME_LENGTH];
581 const char * const *templates;
582 const char *template;
583 int base;
584
585 if (type >= ARRAY_SIZE(__templates))
586 return -EINVAL;
587 if (attr >= __templates_size[type])
588 return -EINVAL;
589
590 templates = __templates[type];
591 template = templates[attr];
592
593 base = hwmon_attr_base(type);
594
595 scnprintf(sattr, MAX_SYSFS_ATTR_NAME_LENGTH, template, base + channel);
596 sysfs_notify(&dev->kobj, NULL, sattr);
597 kobject_uevent(&dev->kobj, KOBJ_CHANGE);
598
599 if (type == hwmon_temp)
600 hwmon_thermal_notify(dev, channel);
601
602 return 0;
603}
604EXPORT_SYMBOL_GPL(hwmon_notify_event);
605
546static int hwmon_num_channel_attrs(const struct hwmon_channel_info *info)
547{
548 int i, n;
549
550 for (i = n = 0; info->config[i]; i++)
551 n += hweight32(info->config[i]);
552
553 return n;

--- 134 unchanged lines hidden (view full) ---

688 hdev->of_node = dev ? dev->of_node : NULL;
689 hwdev->chip = chip;
690 dev_set_drvdata(hdev, drvdata);
691 dev_set_name(hdev, HWMON_ID_FORMAT, id);
692 err = device_register(hdev);
693 if (err)
694 goto free_hwmon;
695
606static int hwmon_num_channel_attrs(const struct hwmon_channel_info *info)
607{
608 int i, n;
609
610 for (i = n = 0; info->config[i]; i++)
611 n += hweight32(info->config[i]);
612
613 return n;

--- 134 unchanged lines hidden (view full) ---

748 hdev->of_node = dev ? dev->of_node : NULL;
749 hwdev->chip = chip;
750 dev_set_drvdata(hdev, drvdata);
751 dev_set_name(hdev, HWMON_ID_FORMAT, id);
752 err = device_register(hdev);
753 if (err)
754 goto free_hwmon;
755
756 INIT_LIST_HEAD(&hwdev->tzdata);
757
696 if (dev && dev->of_node && chip && chip->ops->read &&
697 chip->info[0]->type == hwmon_chip &&
698 (chip->info[0]->config[0] & HWMON_C_REGISTER_TZ)) {
699 err = hwmon_thermal_register_sensors(hdev);
700 if (err) {
701 device_unregister(hdev);
702 /*
703 * Don't worry about hwdev; hwmon_dev_release(), called

--- 266 unchanged lines hidden ---
758 if (dev && dev->of_node && chip && chip->ops->read &&
759 chip->info[0]->type == hwmon_chip &&
760 (chip->info[0]->config[0] & HWMON_C_REGISTER_TZ)) {
761 err = hwmon_thermal_register_sensors(hdev);
762 if (err) {
763 device_unregister(hdev);
764 /*
765 * Don't worry about hwdev; hwmon_dev_release(), called

--- 266 unchanged lines hidden ---