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