Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  fan_attr.c - Create extra attributes for ACPI Fan driver
0004  *
0005  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
0006  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
0007  *  Copyright (C) 2022 Intel Corporation. All rights reserved.
0008  */
0009 
0010 #include <linux/kernel.h>
0011 #include <linux/module.h>
0012 #include <linux/init.h>
0013 #include <linux/acpi.h>
0014 
0015 #include "fan.h"
0016 
0017 MODULE_LICENSE("GPL");
0018 
0019 static ssize_t show_state(struct device *dev, struct device_attribute *attr, char *buf)
0020 {
0021     struct acpi_fan_fps *fps = container_of(attr, struct acpi_fan_fps, dev_attr);
0022     int count;
0023 
0024     if (fps->control == 0xFFFFFFFF || fps->control > 100)
0025         count = scnprintf(buf, PAGE_SIZE, "not-defined:");
0026     else
0027         count = scnprintf(buf, PAGE_SIZE, "%lld:", fps->control);
0028 
0029     if (fps->trip_point == 0xFFFFFFFF || fps->trip_point > 9)
0030         count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:");
0031     else
0032         count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->trip_point);
0033 
0034     if (fps->speed == 0xFFFFFFFF)
0035         count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:");
0036     else
0037         count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->speed);
0038 
0039     if (fps->noise_level == 0xFFFFFFFF)
0040         count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:");
0041     else
0042         count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->noise_level * 100);
0043 
0044     if (fps->power == 0xFFFFFFFF)
0045         count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined\n");
0046     else
0047         count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld\n", fps->power);
0048 
0049     return count;
0050 }
0051 
0052 static ssize_t show_fan_speed(struct device *dev, struct device_attribute *attr, char *buf)
0053 {
0054     struct acpi_device *acpi_dev = container_of(dev, struct acpi_device, dev);
0055     struct acpi_fan_fst fst;
0056     int status;
0057 
0058     status = acpi_fan_get_fst(acpi_dev, &fst);
0059     if (status)
0060         return status;
0061 
0062     return sprintf(buf, "%lld\n", fst.speed);
0063 }
0064 
0065 static ssize_t show_fine_grain_control(struct device *dev, struct device_attribute *attr, char *buf)
0066 {
0067     struct acpi_device *acpi_dev = container_of(dev, struct acpi_device, dev);
0068     struct acpi_fan *fan = acpi_driver_data(acpi_dev);
0069 
0070     return sprintf(buf, "%d\n", fan->fif.fine_grain_ctrl);
0071 }
0072 
0073 int acpi_fan_create_attributes(struct acpi_device *device)
0074 {
0075     struct acpi_fan *fan = acpi_driver_data(device);
0076     int i, status;
0077 
0078     sysfs_attr_init(&fan->fine_grain_control.attr);
0079     fan->fine_grain_control.show = show_fine_grain_control;
0080     fan->fine_grain_control.store = NULL;
0081     fan->fine_grain_control.attr.name = "fine_grain_control";
0082     fan->fine_grain_control.attr.mode = 0444;
0083     status = sysfs_create_file(&device->dev.kobj, &fan->fine_grain_control.attr);
0084     if (status)
0085         return status;
0086 
0087     /* _FST is present if we are here */
0088     sysfs_attr_init(&fan->fst_speed.attr);
0089     fan->fst_speed.show = show_fan_speed;
0090     fan->fst_speed.store = NULL;
0091     fan->fst_speed.attr.name = "fan_speed_rpm";
0092     fan->fst_speed.attr.mode = 0444;
0093     status = sysfs_create_file(&device->dev.kobj, &fan->fst_speed.attr);
0094     if (status)
0095         goto rem_fine_grain_attr;
0096 
0097     for (i = 0; i < fan->fps_count; ++i) {
0098         struct acpi_fan_fps *fps = &fan->fps[i];
0099 
0100         snprintf(fps->name, ACPI_FPS_NAME_LEN, "state%d", i);
0101         sysfs_attr_init(&fps->dev_attr.attr);
0102         fps->dev_attr.show = show_state;
0103         fps->dev_attr.store = NULL;
0104         fps->dev_attr.attr.name = fps->name;
0105         fps->dev_attr.attr.mode = 0444;
0106         status = sysfs_create_file(&device->dev.kobj, &fps->dev_attr.attr);
0107         if (status) {
0108             int j;
0109 
0110             for (j = 0; j < i; ++j)
0111                 sysfs_remove_file(&device->dev.kobj, &fan->fps[j].dev_attr.attr);
0112             goto rem_fst_attr;
0113         }
0114     }
0115 
0116     return 0;
0117 
0118 rem_fst_attr:
0119     sysfs_remove_file(&device->dev.kobj, &fan->fst_speed.attr);
0120 
0121 rem_fine_grain_attr:
0122     sysfs_remove_file(&device->dev.kobj, &fan->fine_grain_control.attr);
0123 
0124     return status;
0125 }
0126 
0127 void acpi_fan_delete_attributes(struct acpi_device *device)
0128 {
0129     struct acpi_fan *fan = acpi_driver_data(device);
0130     int i;
0131 
0132     for (i = 0; i < fan->fps_count; ++i)
0133         sysfs_remove_file(&device->dev.kobj, &fan->fps[i].dev_attr.attr);
0134 
0135     sysfs_remove_file(&device->dev.kobj, &fan->fst_speed.attr);
0136     sysfs_remove_file(&device->dev.kobj, &fan->fine_grain_control.attr);
0137 }