hwmon.c (c9ebbe6f23f43f4520d9e3c4fe1384963848088e) hwmon.c (d560168b5d0fb4a70c74b386564072a819d9bf71)
1/*
2 * hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
3 *
4 * This file defines the sysfs class "hwmon", for use by sensors drivers.
5 *
6 * Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 */
12
13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14
1/*
2 * hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
3 *
4 * This file defines the sysfs class "hwmon", for use by sensors drivers.
5 *
6 * Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 */
12
13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14
15#include <linux/bitops.h>
15#include <linux/device.h>
16#include <linux/err.h>
17#include <linux/gfp.h>
18#include <linux/hwmon.h>
19#include <linux/idr.h>
20#include <linux/module.h>
21#include <linux/pci.h>
22#include <linux/slab.h>
23#include <linux/string.h>
16#include <linux/device.h>
17#include <linux/err.h>
18#include <linux/gfp.h>
19#include <linux/hwmon.h>
20#include <linux/idr.h>
21#include <linux/module.h>
22#include <linux/pci.h>
23#include <linux/slab.h>
24#include <linux/string.h>
25#include <linux/thermal.h>
24
25#define HWMON_ID_PREFIX "hwmon"
26#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
27
28struct hwmon_device {
29 const char *name;
30 struct device dev;
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;
34
35 struct attribute_group group;
36 const struct attribute_group **groups;
31};
37};
38
32#define to_hwmon_device(d) container_of(d, struct hwmon_device, dev)
33
39#define to_hwmon_device(d) container_of(d, struct hwmon_device, dev)
40
41struct hwmon_device_attribute {
42 struct device_attribute dev_attr;
43 const struct hwmon_ops *ops;
44 enum hwmon_sensor_types type;
45 u32 attr;
46 int index;
47};
48
49#define to_hwmon_attr(d) \
50 container_of(d, struct hwmon_device_attribute, dev_attr)
51
52/*
53 * Thermal zone information
54 * In addition to the reference to the hwmon device,
55 * also provides the sensor index.
56 */
57struct hwmon_thermal_data {
58 struct hwmon_device *hwdev; /* Reference to hwmon device */
59 int index; /* sensor index */
60};
61
34static ssize_t
35show_name(struct device *dev, struct device_attribute *attr, char *buf)
36{
37 return sprintf(buf, "%s\n", to_hwmon_device(dev)->name);
38}
39static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
40
41static struct attribute *hwmon_dev_attrs[] = {

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

73 .name = "hwmon",
74 .owner = THIS_MODULE,
75 .dev_groups = hwmon_dev_attr_groups,
76 .dev_release = hwmon_dev_release,
77};
78
79static DEFINE_IDA(hwmon_ida);
80
62static ssize_t
63show_name(struct device *dev, struct device_attribute *attr, char *buf)
64{
65 return sprintf(buf, "%s\n", to_hwmon_device(dev)->name);
66}
67static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
68
69static struct attribute *hwmon_dev_attrs[] = {

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

101 .name = "hwmon",
102 .owner = THIS_MODULE,
103 .dev_groups = hwmon_dev_attr_groups,
104 .dev_release = hwmon_dev_release,
105};
106
107static DEFINE_IDA(hwmon_ida);
108
81/**
82 * hwmon_device_register_with_groups - register w/ hwmon
83 * @dev: the parent device
84 * @name: hwmon name attribute
85 * @drvdata: driver data to attach to created device
86 * @groups: List of attribute groups to create
87 *
88 * hwmon_device_unregister() must be called when the device is no
89 * longer needed.
90 *
91 * Returns the pointer to the new device.
92 */
93struct device *
94hwmon_device_register_with_groups(struct device *dev, const char *name,
95 void *drvdata,
96 const struct attribute_group **groups)
109/* Thermal zone handling */
110
111#if IS_REACHABLE(CONFIG_THERMAL) && defined(CONFIG_THERMAL_OF)
112static int hwmon_thermal_get_temp(void *data, int *temp)
97{
113{
114 struct hwmon_thermal_data *tdata = data;
115 struct hwmon_device *hwdev = tdata->hwdev;
116 int ret;
117 long t;
118
119 ret = hwdev->chip->ops->read(&hwdev->dev, hwmon_temp, hwmon_temp_input,
120 tdata->index, &t);
121 if (ret < 0)
122 return ret;
123
124 *temp = t;
125
126 return 0;
127}
128
129static struct thermal_zone_of_device_ops hwmon_thermal_ops = {
130 .get_temp = hwmon_thermal_get_temp,
131};
132
133static int hwmon_thermal_add_sensor(struct device *dev,
134 struct hwmon_device *hwdev, int index)
135{
136 struct hwmon_thermal_data *tdata;
137
138 tdata = devm_kzalloc(dev, sizeof(*tdata), GFP_KERNEL);
139 if (!tdata)
140 return -ENOMEM;
141
142 tdata->hwdev = hwdev;
143 tdata->index = index;
144
145 devm_thermal_zone_of_sensor_register(&hwdev->dev, index, tdata,
146 &hwmon_thermal_ops);
147
148 return 0;
149}
150#else
151static int hwmon_thermal_add_sensor(struct device *dev,
152 struct hwmon_device *hwdev, int index)
153{
154 return 0;
155}
156#endif /* IS_REACHABLE(CONFIG_THERMAL) && defined(CONFIG_THERMAL_OF) */
157
158/* sysfs attribute management */
159
160static ssize_t hwmon_attr_show(struct device *dev,
161 struct device_attribute *devattr, char *buf)
162{
163 struct hwmon_device_attribute *hattr = to_hwmon_attr(devattr);
164 long val;
165 int ret;
166
167 ret = hattr->ops->read(dev, hattr->type, hattr->attr, hattr->index,
168 &val);
169 if (ret < 0)
170 return ret;
171
172 return sprintf(buf, "%ld\n", val);
173}
174
175static ssize_t hwmon_attr_store(struct device *dev,
176 struct device_attribute *devattr,
177 const char *buf, size_t count)
178{
179 struct hwmon_device_attribute *hattr = to_hwmon_attr(devattr);
180 long val;
181 int ret;
182
183 ret = kstrtol(buf, 10, &val);
184 if (ret < 0)
185 return ret;
186
187 ret = hattr->ops->write(dev, hattr->type, hattr->attr, hattr->index,
188 val);
189 if (ret < 0)
190 return ret;
191
192 return count;
193}
194
195static int hwmon_attr_base(enum hwmon_sensor_types type)
196{
197 if (type == hwmon_in)
198 return 0;
199 return 1;
200}
201
202static struct attribute *hwmon_genattr(struct device *dev,
203 const void *drvdata,
204 enum hwmon_sensor_types type,
205 u32 attr,
206 int index,
207 const char *template,
208 const struct hwmon_ops *ops)
209{
210 struct hwmon_device_attribute *hattr;
211 struct device_attribute *dattr;
212 struct attribute *a;
213 umode_t mode;
214 char *name;
215
216 /* The attribute is invisible if there is no template string */
217 if (!template)
218 return ERR_PTR(-ENOENT);
219
220 mode = ops->is_visible(drvdata, type, attr, index);
221 if (!mode)
222 return ERR_PTR(-ENOENT);
223
224 if ((mode & S_IRUGO) && !ops->read)
225 return ERR_PTR(-EINVAL);
226 if ((mode & S_IWUGO) && !ops->write)
227 return ERR_PTR(-EINVAL);
228
229 if (type == hwmon_chip) {
230 name = (char *)template;
231 } else {
232 name = devm_kzalloc(dev, strlen(template) + 16, GFP_KERNEL);
233 if (!name)
234 return ERR_PTR(-ENOMEM);
235 scnprintf(name, strlen(template) + 16, template,
236 index + hwmon_attr_base(type));
237 }
238
239 hattr = devm_kzalloc(dev, sizeof(*hattr), GFP_KERNEL);
240 if (!hattr)
241 return ERR_PTR(-ENOMEM);
242
243 hattr->type = type;
244 hattr->attr = attr;
245 hattr->index = index;
246 hattr->ops = ops;
247
248 dattr = &hattr->dev_attr;
249 dattr->show = hwmon_attr_show;
250 dattr->store = hwmon_attr_store;
251
252 a = &dattr->attr;
253 sysfs_attr_init(a);
254 a->name = name;
255 a->mode = mode;
256
257 return a;
258}
259
260static const char * const hwmon_chip_attr_templates[] = {
261 [hwmon_chip_temp_reset_history] = "temp_reset_history",
262 [hwmon_chip_update_interval] = "update_interval",
263 [hwmon_chip_alarms] = "alarms",
264};
265
266static const char * const hwmon_temp_attr_templates[] = {
267 [hwmon_temp_input] = "temp%d_input",
268 [hwmon_temp_type] = "temp%d_type",
269 [hwmon_temp_lcrit] = "temp%d_lcrit",
270 [hwmon_temp_lcrit_hyst] = "temp%d_lcrit_hyst",
271 [hwmon_temp_min] = "temp%d_min",
272 [hwmon_temp_min_hyst] = "temp%d_min_hyst",
273 [hwmon_temp_max] = "temp%d_max",
274 [hwmon_temp_max_hyst] = "temp%d_max_hyst",
275 [hwmon_temp_crit] = "temp%d_crit",
276 [hwmon_temp_crit_hyst] = "temp%d_crit_hyst",
277 [hwmon_temp_emergency] = "temp%d_emergency",
278 [hwmon_temp_emergency_hyst] = "temp%d_emergency_hyst",
279 [hwmon_temp_alarm] = "temp%d_alarm",
280 [hwmon_temp_lcrit_alarm] = "temp%d_lcrit_alarm",
281 [hwmon_temp_min_alarm] = "temp%d_min_alarm",
282 [hwmon_temp_max_alarm] = "temp%d_max_alarm",
283 [hwmon_temp_crit_alarm] = "temp%d_crit_alarm",
284 [hwmon_temp_emergency_alarm] = "temp%d_emergency_alarm",
285 [hwmon_temp_fault] = "temp%d_fault",
286 [hwmon_temp_offset] = "temp%d_offset",
287 [hwmon_temp_label] = "temp%d_label",
288 [hwmon_temp_lowest] = "temp%d_lowest",
289 [hwmon_temp_highest] = "temp%d_highest",
290 [hwmon_temp_reset_history] = "temp%d_reset_history",
291};
292
293static const char * const *__templates[] = {
294 [hwmon_chip] = hwmon_chip_attr_templates,
295 [hwmon_temp] = hwmon_temp_attr_templates,
296};
297
298static const int __templates_size[] = {
299 [hwmon_chip] = ARRAY_SIZE(hwmon_chip_attr_templates),
300 [hwmon_temp] = ARRAY_SIZE(hwmon_temp_attr_templates),
301};
302
303static int hwmon_num_channel_attrs(const struct hwmon_channel_info *info)
304{
305 int i, n;
306
307 for (i = n = 0; info->config[i]; i++)
308 n += hweight32(info->config[i]);
309
310 return n;
311}
312
313static int hwmon_genattrs(struct device *dev,
314 const void *drvdata,
315 struct attribute **attrs,
316 const struct hwmon_ops *ops,
317 const struct hwmon_channel_info *info)
318{
319 const char * const *templates;
320 int template_size;
321 int i, aindex = 0;
322
323 if (info->type >= ARRAY_SIZE(__templates))
324 return -EINVAL;
325
326 templates = __templates[info->type];
327 template_size = __templates_size[info->type];
328
329 for (i = 0; info->config[i]; i++) {
330 u32 attr_mask = info->config[i];
331 u32 attr;
332
333 while (attr_mask) {
334 struct attribute *a;
335
336 attr = __ffs(attr_mask);
337 attr_mask &= ~BIT(attr);
338 if (attr >= template_size)
339 return -EINVAL;
340 a = hwmon_genattr(dev, drvdata, info->type, attr, i,
341 templates[attr], ops);
342 if (IS_ERR(a)) {
343 if (PTR_ERR(a) != -ENOENT)
344 return PTR_ERR(a);
345 continue;
346 }
347 attrs[aindex++] = a;
348 }
349 }
350 return aindex;
351}
352
353static struct attribute **
354__hwmon_create_attrs(struct device *dev, const void *drvdata,
355 const struct hwmon_chip_info *chip)
356{
357 int ret, i, aindex = 0, nattrs = 0;
358 struct attribute **attrs;
359
360 for (i = 0; chip->info[i]; i++)
361 nattrs += hwmon_num_channel_attrs(chip->info[i]);
362
363 if (nattrs == 0)
364 return ERR_PTR(-EINVAL);
365
366 attrs = devm_kcalloc(dev, nattrs + 1, sizeof(*attrs), GFP_KERNEL);
367 if (!attrs)
368 return ERR_PTR(-ENOMEM);
369
370 for (i = 0; chip->info[i]; i++) {
371 ret = hwmon_genattrs(dev, drvdata, &attrs[aindex], chip->ops,
372 chip->info[i]);
373 if (ret < 0)
374 return ERR_PTR(ret);
375 aindex += ret;
376 }
377
378 return attrs;
379}
380
381static struct device *
382__hwmon_device_register(struct device *dev, const char *name, void *drvdata,
383 const struct hwmon_chip_info *chip,
384 const struct attribute_group **groups)
385{
98 struct hwmon_device *hwdev;
386 struct hwmon_device *hwdev;
99 int err, id;
387 struct device *hdev;
388 int i, j, err, id;
100
101 /* Do not accept invalid characters in hwmon name attribute */
102 if (name && (!strlen(name) || strpbrk(name, "-* \t\n")))
103 return ERR_PTR(-EINVAL);
104
105 id = ida_simple_get(&hwmon_ida, 0, 0, GFP_KERNEL);
106 if (id < 0)
107 return ERR_PTR(id);
108
109 hwdev = kzalloc(sizeof(*hwdev), GFP_KERNEL);
110 if (hwdev == NULL) {
111 err = -ENOMEM;
112 goto ida_remove;
113 }
114
389
390 /* Do not accept invalid characters in hwmon name attribute */
391 if (name && (!strlen(name) || strpbrk(name, "-* \t\n")))
392 return ERR_PTR(-EINVAL);
393
394 id = ida_simple_get(&hwmon_ida, 0, 0, GFP_KERNEL);
395 if (id < 0)
396 return ERR_PTR(id);
397
398 hwdev = kzalloc(sizeof(*hwdev), GFP_KERNEL);
399 if (hwdev == NULL) {
400 err = -ENOMEM;
401 goto ida_remove;
402 }
403
404 hdev = &hwdev->dev;
405
406 if (chip && chip->ops->is_visible) {
407 struct attribute **attrs;
408 int ngroups = 2;
409
410 if (groups)
411 for (i = 0; groups[i]; i++)
412 ngroups++;
413
414 hwdev->groups = devm_kcalloc(dev, ngroups, sizeof(*groups),
415 GFP_KERNEL);
416 if (!hwdev->groups)
417 return ERR_PTR(-ENOMEM);
418
419 attrs = __hwmon_create_attrs(dev, drvdata, chip);
420 if (IS_ERR(attrs)) {
421 err = PTR_ERR(attrs);
422 goto free_hwmon;
423 }
424
425 hwdev->group.attrs = attrs;
426 ngroups = 0;
427 hwdev->groups[ngroups++] = &hwdev->group;
428
429 if (groups) {
430 for (i = 0; groups[i]; i++)
431 hwdev->groups[ngroups++] = groups[i];
432 }
433
434 hdev->groups = hwdev->groups;
435 } else {
436 hdev->groups = groups;
437 }
438
115 hwdev->name = name;
439 hwdev->name = name;
116 hwdev->dev.class = &hwmon_class;
117 hwdev->dev.parent = dev;
118 hwdev->dev.groups = groups;
119 hwdev->dev.of_node = dev ? dev->of_node : NULL;
120 dev_set_drvdata(&hwdev->dev, drvdata);
121 dev_set_name(&hwdev->dev, HWMON_ID_FORMAT, id);
122 err = device_register(&hwdev->dev);
440 hdev->class = &hwmon_class;
441 hdev->parent = dev;
442 hdev->of_node = dev ? dev->of_node : NULL;
443 hwdev->chip = chip;
444 dev_set_drvdata(hdev, drvdata);
445 dev_set_name(hdev, HWMON_ID_FORMAT, id);
446 err = device_register(hdev);
123 if (err)
447 if (err)
124 goto free;
448 goto free_hwmon;
125
449
126 return &hwdev->dev;
450 if (chip && chip->ops->is_visible && chip->ops->read &&
451 chip->info[0]->type == hwmon_chip &&
452 (chip->info[0]->config[0] & HWMON_C_REGISTER_TZ)) {
453 const struct hwmon_channel_info **info = chip->info;
127
454
128free:
455 for (i = 1; info[i]; i++) {
456 if (info[i]->type != hwmon_temp)
457 continue;
458
459 for (j = 0; info[i]->config[j]; j++) {
460 if (!chip->ops->is_visible(drvdata, hwmon_temp,
461 hwmon_temp_input, j))
462 continue;
463 if (info[i]->config[j] & HWMON_T_INPUT)
464 hwmon_thermal_add_sensor(dev, hwdev, j);
465 }
466 }
467 }
468
469 return hdev;
470
471free_hwmon:
129 kfree(hwdev);
130ida_remove:
131 ida_simple_remove(&hwmon_ida, id);
132 return ERR_PTR(err);
133}
472 kfree(hwdev);
473ida_remove:
474 ida_simple_remove(&hwmon_ida, id);
475 return ERR_PTR(err);
476}
477
478/**
479 * hwmon_device_register_with_groups - register w/ hwmon
480 * @dev: the parent device
481 * @name: hwmon name attribute
482 * @drvdata: driver data to attach to created device
483 * @groups: List of attribute groups to create
484 *
485 * hwmon_device_unregister() must be called when the device is no
486 * longer needed.
487 *
488 * Returns the pointer to the new device.
489 */
490struct device *
491hwmon_device_register_with_groups(struct device *dev, const char *name,
492 void *drvdata,
493 const struct attribute_group **groups)
494{
495 return __hwmon_device_register(dev, name, drvdata, NULL, groups);
496}
134EXPORT_SYMBOL_GPL(hwmon_device_register_with_groups);
135
136/**
497EXPORT_SYMBOL_GPL(hwmon_device_register_with_groups);
498
499/**
500 * hwmon_device_register_with_info - register w/ hwmon
501 * @dev: the parent device
502 * @name: hwmon name attribute
503 * @drvdata: driver data to attach to created device
504 * @info: Pointer to hwmon chip information
505 * @groups - pointer to list of driver specific attribute groups
506 *
507 * hwmon_device_unregister() must be called when the device is no
508 * longer needed.
509 *
510 * Returns the pointer to the new device.
511 */
512struct device *
513hwmon_device_register_with_info(struct device *dev, const char *name,
514 void *drvdata,
515 const struct hwmon_chip_info *chip,
516 const struct attribute_group **groups)
517{
518 if (chip && (!chip->ops || !chip->info))
519 return ERR_PTR(-EINVAL);
520
521 return __hwmon_device_register(dev, name, drvdata, chip, groups);
522}
523EXPORT_SYMBOL_GPL(hwmon_device_register_with_info);
524
525/**
137 * hwmon_device_register - register w/ hwmon
138 * @dev: the device to register
139 *
140 * hwmon_device_unregister() must be called when the device is no
141 * longer needed.
142 *
143 * Returns the pointer to the new device.
144 */

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

206 return hwdev;
207
208error:
209 devres_free(ptr);
210 return hwdev;
211}
212EXPORT_SYMBOL_GPL(devm_hwmon_device_register_with_groups);
213
526 * hwmon_device_register - register w/ hwmon
527 * @dev: the device to register
528 *
529 * hwmon_device_unregister() must be called when the device is no
530 * longer needed.
531 *
532 * Returns the pointer to the new device.
533 */

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

595 return hwdev;
596
597error:
598 devres_free(ptr);
599 return hwdev;
600}
601EXPORT_SYMBOL_GPL(devm_hwmon_device_register_with_groups);
602
603/**
604 * devm_hwmon_device_register_with_info - register w/ hwmon
605 * @dev: the parent device
606 * @name: hwmon name attribute
607 * @drvdata: driver data to attach to created device
608 * @info: Pointer to hwmon chip information
609 * @groups - pointer to list of driver specific attribute groups
610 *
611 * Returns the pointer to the new device. The new device is automatically
612 * unregistered with the parent device.
613 */
614struct device *
615devm_hwmon_device_register_with_info(struct device *dev, const char *name,
616 void *drvdata,
617 const struct hwmon_chip_info *chip,
618 const struct attribute_group **groups)
619{
620 struct device **ptr, *hwdev;
621
622 if (!dev)
623 return ERR_PTR(-EINVAL);
624
625 ptr = devres_alloc(devm_hwmon_release, sizeof(*ptr), GFP_KERNEL);
626 if (!ptr)
627 return ERR_PTR(-ENOMEM);
628
629 hwdev = hwmon_device_register_with_info(dev, name, drvdata, chip,
630 groups);
631 if (IS_ERR(hwdev))
632 goto error;
633
634 *ptr = hwdev;
635 devres_add(dev, ptr);
636
637 return hwdev;
638
639error:
640 devres_free(ptr);
641 return hwdev;
642}
643EXPORT_SYMBOL_GPL(devm_hwmon_device_register_with_info);
644
214static int devm_hwmon_match(struct device *dev, void *res, void *data)
215{
216 struct device **hwdev = res;
217
218 return *hwdev == data;
219}
220
221/**

--- 64 unchanged lines hidden ---
645static int devm_hwmon_match(struct device *dev, void *res, void *data)
646{
647 struct device **hwdev = res;
648
649 return *hwdev == data;
650}
651
652/**

--- 64 unchanged lines hidden ---