Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | // SPDX-License-Identifier: GPL-2.0-or-later /* * fan_attr.c - Create extra attributes for ACPI Fan driver * * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> * Copyright (C) 2022 Intel Corporation. All rights reserved. */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/acpi.h> #include "fan.h" MODULE_LICENSE("GPL"); static ssize_t show_state(struct device *dev, struct device_attribute *attr, char *buf) { struct acpi_fan_fps *fps = container_of(attr, struct acpi_fan_fps, dev_attr); int count; if (fps->control == 0xFFFFFFFF || fps->control > 100) count = scnprintf(buf, PAGE_SIZE, "not-defined:"); else count = scnprintf(buf, PAGE_SIZE, "%lld:", fps->control); if (fps->trip_point == 0xFFFFFFFF || fps->trip_point > 9) count += sysfs_emit_at(buf, count, "not-defined:"); else count += sysfs_emit_at(buf, count, "%lld:", fps->trip_point); if (fps->speed == 0xFFFFFFFF) count += sysfs_emit_at(buf, count, "not-defined:"); else count += sysfs_emit_at(buf, count, "%lld:", fps->speed); if (fps->noise_level == 0xFFFFFFFF) count += sysfs_emit_at(buf, count, "not-defined:"); else count += sysfs_emit_at(buf, count, "%lld:", fps->noise_level * 100); if (fps->power == 0xFFFFFFFF) count += sysfs_emit_at(buf, count, "not-defined\n"); else count += sysfs_emit_at(buf, count, "%lld\n", fps->power); return count; } static ssize_t show_fan_speed(struct device *dev, struct device_attribute *attr, char *buf) { struct acpi_device *acpi_dev = container_of(dev, struct acpi_device, dev); struct acpi_fan_fst fst; int status; status = acpi_fan_get_fst(acpi_dev, &fst); if (status) return status; return sprintf(buf, "%lld\n", fst.speed); } static ssize_t show_fine_grain_control(struct device *dev, struct device_attribute *attr, char *buf) { struct acpi_device *acpi_dev = container_of(dev, struct acpi_device, dev); struct acpi_fan *fan = acpi_driver_data(acpi_dev); return sprintf(buf, "%d\n", fan->fif.fine_grain_ctrl); } int acpi_fan_create_attributes(struct acpi_device *device) { struct acpi_fan *fan = acpi_driver_data(device); int i, status; sysfs_attr_init(&fan->fine_grain_control.attr); fan->fine_grain_control.show = show_fine_grain_control; fan->fine_grain_control.store = NULL; fan->fine_grain_control.attr.name = "fine_grain_control"; fan->fine_grain_control.attr.mode = 0444; status = sysfs_create_file(&device->dev.kobj, &fan->fine_grain_control.attr); if (status) return status; /* _FST is present if we are here */ sysfs_attr_init(&fan->fst_speed.attr); fan->fst_speed.show = show_fan_speed; fan->fst_speed.store = NULL; fan->fst_speed.attr.name = "fan_speed_rpm"; fan->fst_speed.attr.mode = 0444; status = sysfs_create_file(&device->dev.kobj, &fan->fst_speed.attr); if (status) goto rem_fine_grain_attr; for (i = 0; i < fan->fps_count; ++i) { struct acpi_fan_fps *fps = &fan->fps[i]; snprintf(fps->name, ACPI_FPS_NAME_LEN, "state%d", i); sysfs_attr_init(&fps->dev_attr.attr); fps->dev_attr.show = show_state; fps->dev_attr.store = NULL; fps->dev_attr.attr.name = fps->name; fps->dev_attr.attr.mode = 0444; status = sysfs_create_file(&device->dev.kobj, &fps->dev_attr.attr); if (status) { int j; for (j = 0; j < i; ++j) sysfs_remove_file(&device->dev.kobj, &fan->fps[j].dev_attr.attr); goto rem_fst_attr; } } return 0; rem_fst_attr: sysfs_remove_file(&device->dev.kobj, &fan->fst_speed.attr); rem_fine_grain_attr: sysfs_remove_file(&device->dev.kobj, &fan->fine_grain_control.attr); return status; } void acpi_fan_delete_attributes(struct acpi_device *device) { struct acpi_fan *fan = acpi_driver_data(device); int i; for (i = 0; i < fan->fps_count; ++i) sysfs_remove_file(&device->dev.kobj, &fan->fps[i].dev_attr.attr); sysfs_remove_file(&device->dev.kobj, &fan->fst_speed.attr); sysfs_remove_file(&device->dev.kobj, &fan->fine_grain_control.attr); } |