hwmon.c (0898782247ae533d1f4e47a06bc5d4870931b284) | hwmon.c (3bf8bdcf3bada771eb12b57f2a30caee69e8ab8d) |
---|---|
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 */ --- 37 unchanged lines hidden (view full) --- 46 enum hwmon_sensor_types type; 47 u32 attr; 48 int index; 49 char name[MAX_SYSFS_ATTR_NAME_LENGTH]; 50}; 51 52#define to_hwmon_attr(d) \ 53 container_of(d, struct hwmon_device_attribute, dev_attr) | 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 */ --- 37 unchanged lines hidden (view full) --- 46 enum hwmon_sensor_types type; 47 u32 attr; 48 int index; 49 char name[MAX_SYSFS_ATTR_NAME_LENGTH]; 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) |
|
54 55/* 56 * Thermal zone information 57 * In addition to the reference to the hwmon device, 58 * also provides the sensor index. 59 */ 60struct hwmon_thermal_data { | 55 56/* 57 * Thermal zone information 58 * In addition to the reference to the hwmon device, 59 * also provides the sensor index. 60 */ 61struct hwmon_thermal_data { |
61 struct hwmon_device *hwdev; /* Reference to hwmon device */ | 62 struct device *dev; /* Reference to hwmon device */ |
62 int index; /* sensor index */ 63}; 64 65static ssize_t 66name_show(struct device *dev, struct device_attribute *attr, char *buf) 67{ 68 return sprintf(buf, "%s\n", to_hwmon_device(dev)->name); 69} --- 20 unchanged lines hidden (view full) --- 90 .is_visible = hwmon_dev_name_is_visible, 91}; 92 93static const struct attribute_group *hwmon_dev_attr_groups[] = { 94 &hwmon_dev_attr_group, 95 NULL 96}; 97 | 63 int index; /* sensor index */ 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} --- 20 unchanged lines hidden (view full) --- 91 .is_visible = hwmon_dev_name_is_visible, 92}; 93 94static const struct attribute_group *hwmon_dev_attr_groups[] = { 95 &hwmon_dev_attr_group, 96 NULL 97}; 98 |
99static void hwmon_free_attrs(struct attribute **attrs) 100{ 101 int i; 102 103 for (i = 0; attrs[i]; i++) { 104 struct device_attribute *dattr = to_dev_attr(attrs[i]); 105 struct hwmon_device_attribute *hattr = to_hwmon_attr(dattr); 106 107 kfree(hattr); 108 } 109 kfree(attrs); 110} 111 |
|
98static void hwmon_dev_release(struct device *dev) 99{ | 112static void hwmon_dev_release(struct device *dev) 113{ |
100 kfree(to_hwmon_device(dev)); | 114 struct hwmon_device *hwdev = to_hwmon_device(dev); 115 116 if (hwdev->group.attrs) 117 hwmon_free_attrs(hwdev->group.attrs); 118 kfree(hwdev->groups); 119 kfree(hwdev); |
101} 102 103static struct class hwmon_class = { 104 .name = "hwmon", 105 .owner = THIS_MODULE, 106 .dev_groups = hwmon_dev_attr_groups, 107 .dev_release = hwmon_dev_release, 108}; --- 5 unchanged lines hidden (view full) --- 114/* 115 * The complex conditional is necessary to avoid a cyclic dependency 116 * between hwmon and thermal_sys modules. 117 */ 118#ifdef CONFIG_THERMAL_OF 119static int hwmon_thermal_get_temp(void *data, int *temp) 120{ 121 struct hwmon_thermal_data *tdata = data; | 120} 121 122static struct class hwmon_class = { 123 .name = "hwmon", 124 .owner = THIS_MODULE, 125 .dev_groups = hwmon_dev_attr_groups, 126 .dev_release = hwmon_dev_release, 127}; --- 5 unchanged lines hidden (view full) --- 133/* 134 * The complex conditional is necessary to avoid a cyclic dependency 135 * between hwmon and thermal_sys modules. 136 */ 137#ifdef CONFIG_THERMAL_OF 138static int hwmon_thermal_get_temp(void *data, int *temp) 139{ 140 struct hwmon_thermal_data *tdata = data; |
122 struct hwmon_device *hwdev = tdata->hwdev; | 141 struct hwmon_device *hwdev = to_hwmon_device(tdata->dev); |
123 int ret; 124 long t; 125 | 142 int ret; 143 long t; 144 |
126 ret = hwdev->chip->ops->read(&hwdev->dev, hwmon_temp, hwmon_temp_input, | 145 ret = hwdev->chip->ops->read(tdata->dev, hwmon_temp, hwmon_temp_input, |
127 tdata->index, &t); 128 if (ret < 0) 129 return ret; 130 131 *temp = t; 132 133 return 0; 134} 135 136static const struct thermal_zone_of_device_ops hwmon_thermal_ops = { 137 .get_temp = hwmon_thermal_get_temp, 138}; 139 | 146 tdata->index, &t); 147 if (ret < 0) 148 return ret; 149 150 *temp = t; 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 |
140static int hwmon_thermal_add_sensor(struct device *dev, 141 struct hwmon_device *hwdev, int index) | 159static int hwmon_thermal_add_sensor(struct device *dev, int index) |
142{ 143 struct hwmon_thermal_data *tdata; 144 struct thermal_zone_device *tzd; 145 146 tdata = devm_kzalloc(dev, sizeof(*tdata), GFP_KERNEL); 147 if (!tdata) 148 return -ENOMEM; 149 | 160{ 161 struct hwmon_thermal_data *tdata; 162 struct thermal_zone_device *tzd; 163 164 tdata = devm_kzalloc(dev, sizeof(*tdata), GFP_KERNEL); 165 if (!tdata) 166 return -ENOMEM; 167 |
150 tdata->hwdev = hwdev; | 168 tdata->dev = dev; |
151 tdata->index = index; 152 | 169 tdata->index = index; 170 |
153 tzd = devm_thermal_zone_of_sensor_register(&hwdev->dev, index, tdata, | 171 tzd = devm_thermal_zone_of_sensor_register(dev, index, tdata, |
154 &hwmon_thermal_ops); 155 /* 156 * If CONFIG_THERMAL_OF is disabled, this returns -ENODEV, 157 * so ignore that error but forward any other error. 158 */ 159 if (IS_ERR(tzd) && (PTR_ERR(tzd) != -ENODEV)) 160 return PTR_ERR(tzd); 161 162 return 0; 163} 164#else | 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 180 return 0; 181} 182#else |
165static int hwmon_thermal_add_sensor(struct device *dev, 166 struct hwmon_device *hwdev, int index) | 183static int hwmon_thermal_add_sensor(struct device *dev, int index) |
167{ 168 return 0; 169} 170#endif /* IS_REACHABLE(CONFIG_THERMAL) && ... */ 171 172static int hwmon_attr_base(enum hwmon_sensor_types type) 173{ 174 if (type == hwmon_in) --- 70 unchanged lines hidden (view full) --- 245 (type == hwmon_in && attr == hwmon_in_label) || 246 (type == hwmon_curr && attr == hwmon_curr_label) || 247 (type == hwmon_power && attr == hwmon_power_label) || 248 (type == hwmon_energy && attr == hwmon_energy_label) || 249 (type == hwmon_humidity && attr == hwmon_humidity_label) || 250 (type == hwmon_fan && attr == hwmon_fan_label); 251} 252 | 184{ 185 return 0; 186} 187#endif /* IS_REACHABLE(CONFIG_THERMAL) && ... */ 188 189static int hwmon_attr_base(enum hwmon_sensor_types type) 190{ 191 if (type == hwmon_in) --- 70 unchanged lines hidden (view full) --- 262 (type == hwmon_in && attr == hwmon_in_label) || 263 (type == hwmon_curr && attr == hwmon_curr_label) || 264 (type == hwmon_power && attr == hwmon_power_label) || 265 (type == hwmon_energy && attr == hwmon_energy_label) || 266 (type == hwmon_humidity && attr == hwmon_humidity_label) || 267 (type == hwmon_fan && attr == hwmon_fan_label); 268} 269 |
253static struct attribute *hwmon_genattr(struct device *dev, 254 const void *drvdata, | 270static struct attribute *hwmon_genattr(const void *drvdata, |
255 enum hwmon_sensor_types type, 256 u32 attr, 257 int index, 258 const char *template, 259 const struct hwmon_ops *ops) 260{ 261 struct hwmon_device_attribute *hattr; 262 struct device_attribute *dattr; --- 11 unchanged lines hidden (view full) --- 274 return ERR_PTR(-ENOENT); 275 276 if ((mode & 0444) && ((is_string && !ops->read_string) || 277 (!is_string && !ops->read))) 278 return ERR_PTR(-EINVAL); 279 if ((mode & 0222) && !ops->write) 280 return ERR_PTR(-EINVAL); 281 | 271 enum hwmon_sensor_types type, 272 u32 attr, 273 int index, 274 const char *template, 275 const struct hwmon_ops *ops) 276{ 277 struct hwmon_device_attribute *hattr; 278 struct device_attribute *dattr; --- 11 unchanged lines hidden (view full) --- 290 return ERR_PTR(-ENOENT); 291 292 if ((mode & 0444) && ((is_string && !ops->read_string) || 293 (!is_string && !ops->read))) 294 return ERR_PTR(-EINVAL); 295 if ((mode & 0222) && !ops->write) 296 return ERR_PTR(-EINVAL); 297 |
282 hattr = devm_kzalloc(dev, sizeof(*hattr), GFP_KERNEL); | 298 hattr = kzalloc(sizeof(*hattr), GFP_KERNEL); |
283 if (!hattr) 284 return ERR_PTR(-ENOMEM); 285 286 if (type == hwmon_chip) { 287 name = template; 288 } else { 289 scnprintf(hattr->name, sizeof(hattr->name), template, 290 index + hwmon_attr_base(type)); --- 196 unchanged lines hidden (view full) --- 487 int i, n; 488 489 for (i = n = 0; info->config[i]; i++) 490 n += hweight32(info->config[i]); 491 492 return n; 493} 494 | 299 if (!hattr) 300 return ERR_PTR(-ENOMEM); 301 302 if (type == hwmon_chip) { 303 name = template; 304 } else { 305 scnprintf(hattr->name, sizeof(hattr->name), template, 306 index + hwmon_attr_base(type)); --- 196 unchanged lines hidden (view full) --- 503 int i, n; 504 505 for (i = n = 0; info->config[i]; i++) 506 n += hweight32(info->config[i]); 507 508 return n; 509} 510 |
495static int hwmon_genattrs(struct device *dev, 496 const void *drvdata, | 511static int hwmon_genattrs(const void *drvdata, |
497 struct attribute **attrs, 498 const struct hwmon_ops *ops, 499 const struct hwmon_channel_info *info) 500{ 501 const char * const *templates; 502 int template_size; 503 int i, aindex = 0; 504 --- 9 unchanged lines hidden (view full) --- 514 515 while (attr_mask) { 516 struct attribute *a; 517 518 attr = __ffs(attr_mask); 519 attr_mask &= ~BIT(attr); 520 if (attr >= template_size) 521 return -EINVAL; | 512 struct attribute **attrs, 513 const struct hwmon_ops *ops, 514 const struct hwmon_channel_info *info) 515{ 516 const char * const *templates; 517 int template_size; 518 int i, aindex = 0; 519 --- 9 unchanged lines hidden (view full) --- 529 530 while (attr_mask) { 531 struct attribute *a; 532 533 attr = __ffs(attr_mask); 534 attr_mask &= ~BIT(attr); 535 if (attr >= template_size) 536 return -EINVAL; |
522 a = hwmon_genattr(dev, drvdata, info->type, attr, i, | 537 a = hwmon_genattr(drvdata, info->type, attr, i, |
523 templates[attr], ops); 524 if (IS_ERR(a)) { 525 if (PTR_ERR(a) != -ENOENT) 526 return PTR_ERR(a); 527 continue; 528 } 529 attrs[aindex++] = a; 530 } 531 } 532 return aindex; 533} 534 535static struct attribute ** | 538 templates[attr], ops); 539 if (IS_ERR(a)) { 540 if (PTR_ERR(a) != -ENOENT) 541 return PTR_ERR(a); 542 continue; 543 } 544 attrs[aindex++] = a; 545 } 546 } 547 return aindex; 548} 549 550static struct attribute ** |
536__hwmon_create_attrs(struct device *dev, const void *drvdata, 537 const struct hwmon_chip_info *chip) | 551__hwmon_create_attrs(const void *drvdata, const struct hwmon_chip_info *chip) |
538{ 539 int ret, i, aindex = 0, nattrs = 0; 540 struct attribute **attrs; 541 542 for (i = 0; chip->info[i]; i++) 543 nattrs += hwmon_num_channel_attrs(chip->info[i]); 544 545 if (nattrs == 0) 546 return ERR_PTR(-EINVAL); 547 | 552{ 553 int ret, i, aindex = 0, nattrs = 0; 554 struct attribute **attrs; 555 556 for (i = 0; chip->info[i]; i++) 557 nattrs += hwmon_num_channel_attrs(chip->info[i]); 558 559 if (nattrs == 0) 560 return ERR_PTR(-EINVAL); 561 |
548 attrs = devm_kcalloc(dev, nattrs + 1, sizeof(*attrs), GFP_KERNEL); | 562 attrs = kcalloc(nattrs + 1, sizeof(*attrs), GFP_KERNEL); |
549 if (!attrs) 550 return ERR_PTR(-ENOMEM); 551 552 for (i = 0; chip->info[i]; i++) { | 563 if (!attrs) 564 return ERR_PTR(-ENOMEM); 565 566 for (i = 0; chip->info[i]; i++) { |
553 ret = hwmon_genattrs(dev, drvdata, &attrs[aindex], chip->ops, | 567 ret = hwmon_genattrs(drvdata, &attrs[aindex], chip->ops, |
554 chip->info[i]); | 568 chip->info[i]); |
555 if (ret < 0) | 569 if (ret < 0) { 570 hwmon_free_attrs(attrs); |
556 return ERR_PTR(ret); | 571 return ERR_PTR(ret); |
572 } |
|
557 aindex += ret; 558 } 559 560 return attrs; 561} 562 563static struct device * 564__hwmon_device_register(struct device *dev, const char *name, void *drvdata, --- 25 unchanged lines hidden (view full) --- 590 if (chip) { 591 struct attribute **attrs; 592 int ngroups = 2; /* terminating NULL plus &hwdev->groups */ 593 594 if (groups) 595 for (i = 0; groups[i]; i++) 596 ngroups++; 597 | 573 aindex += ret; 574 } 575 576 return attrs; 577} 578 579static struct device * 580__hwmon_device_register(struct device *dev, const char *name, void *drvdata, --- 25 unchanged lines hidden (view full) --- 606 if (chip) { 607 struct attribute **attrs; 608 int ngroups = 2; /* terminating NULL plus &hwdev->groups */ 609 610 if (groups) 611 for (i = 0; groups[i]; i++) 612 ngroups++; 613 |
598 hwdev->groups = devm_kcalloc(dev, ngroups, sizeof(*groups), 599 GFP_KERNEL); | 614 hwdev->groups = kcalloc(ngroups, sizeof(*groups), GFP_KERNEL); |
600 if (!hwdev->groups) { 601 err = -ENOMEM; 602 goto free_hwmon; 603 } 604 | 615 if (!hwdev->groups) { 616 err = -ENOMEM; 617 goto free_hwmon; 618 } 619 |
605 attrs = __hwmon_create_attrs(dev, drvdata, chip); | 620 attrs = __hwmon_create_attrs(drvdata, chip); |
606 if (IS_ERR(attrs)) { 607 err = PTR_ERR(attrs); 608 goto free_hwmon; 609 } 610 611 hwdev->group.attrs = attrs; 612 ngroups = 0; 613 hwdev->groups[ngroups++] = &hwdev->group; --- 28 unchanged lines hidden (view full) --- 642 if (info[i]->type != hwmon_temp) 643 continue; 644 645 for (j = 0; info[i]->config[j]; j++) { 646 if (!chip->ops->is_visible(drvdata, hwmon_temp, 647 hwmon_temp_input, j)) 648 continue; 649 if (info[i]->config[j] & HWMON_T_INPUT) { | 621 if (IS_ERR(attrs)) { 622 err = PTR_ERR(attrs); 623 goto free_hwmon; 624 } 625 626 hwdev->group.attrs = attrs; 627 ngroups = 0; 628 hwdev->groups[ngroups++] = &hwdev->group; --- 28 unchanged lines hidden (view full) --- 657 if (info[i]->type != hwmon_temp) 658 continue; 659 660 for (j = 0; info[i]->config[j]; j++) { 661 if (!chip->ops->is_visible(drvdata, hwmon_temp, 662 hwmon_temp_input, j)) 663 continue; 664 if (info[i]->config[j] & HWMON_T_INPUT) { |
650 err = hwmon_thermal_add_sensor(dev, 651 hwdev, j); | 665 err = hwmon_thermal_add_sensor(hdev, j); |
652 if (err) { 653 device_unregister(hdev); 654 /* 655 * Don't worry about hwdev; 656 * hwmon_dev_release(), called 657 * from device_unregister(), 658 * will free it. 659 */ 660 goto ida_remove; 661 } 662 } 663 } 664 } 665 } 666 667 return hdev; 668 669free_hwmon: | 666 if (err) { 667 device_unregister(hdev); 668 /* 669 * Don't worry about hwdev; 670 * hwmon_dev_release(), called 671 * from device_unregister(), 672 * will free it. 673 */ 674 goto ida_remove; 675 } 676 } 677 } 678 } 679 } 680 681 return hdev; 682 683free_hwmon: |
670 kfree(hwdev); | 684 hwmon_dev_release(hdev); |
671ida_remove: 672 ida_simple_remove(&hwmon_ida, id); 673 return ERR_PTR(err); 674} 675 676/** 677 * hwmon_device_register_with_groups - register w/ hwmon 678 * @dev: the parent device --- 248 unchanged lines hidden --- | 685ida_remove: 686 ida_simple_remove(&hwmon_ida, id); 687 return ERR_PTR(err); 688} 689 690/** 691 * hwmon_device_register_with_groups - register w/ hwmon 692 * @dev: the parent device --- 248 unchanged lines hidden --- |