GNU Linux-libre 6.8.9-gnu
[releases.git] / drivers / hwmon / hp-wmi-sensors.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * hwmon driver for HP (and some HP Compaq) business-class computers that
4  * report numeric sensor data via Windows Management Instrumentation (WMI).
5  *
6  * Copyright (C) 2023 James Seo <james@equiv.tech>
7  *
8  * References:
9  * [1] Hewlett-Packard Development Company, L.P.,
10  *     "HP Client Management Interface Technical White Paper", 2005. [Online].
11  *     Available: https://h20331.www2.hp.com/hpsub/downloads/cmi_whitepaper.pdf
12  * [2] Hewlett-Packard Development Company, L.P.,
13  *     "HP Retail Manageability", 2012. [Online].
14  *     Available: http://h10032.www1.hp.com/ctg/Manual/c03291135.pdf
15  * [3] Linux Hardware Project, A. Ponomarenko et al.,
16  *     "linuxhw/ACPI - Collect ACPI table dumps", 2018. [Online].
17  *     Available: https://github.com/linuxhw/ACPI
18  * [4] P. Rohár, "bmfdec - Decompile binary MOF file (BMF) from WMI buffer",
19  *     2017. [Online]. Available: https://github.com/pali/bmfdec
20  * [5] Microsoft Corporation, "Driver-Defined WMI Data Items", 2017. [Online].
21  *     Available: https://learn.microsoft.com/en-us/windows-hardware/drivers/kernel/driver-defined-wmi-data-items
22  */
23
24 #include <linux/acpi.h>
25 #include <linux/debugfs.h>
26 #include <linux/hwmon.h>
27 #include <linux/jiffies.h>
28 #include <linux/mutex.h>
29 #include <linux/nls.h>
30 #include <linux/units.h>
31 #include <linux/wmi.h>
32
33 #define HP_WMI_EVENT_NAMESPACE          "root\\WMI"
34 #define HP_WMI_EVENT_CLASS              "HPBIOS_BIOSEvent"
35 #define HP_WMI_EVENT_GUID               "95F24279-4D7B-4334-9387-ACCDC67EF61C"
36 #define HP_WMI_NUMERIC_SENSOR_GUID      "8F1F6435-9F42-42C8-BADC-0E9424F20C9A"
37 #define HP_WMI_PLATFORM_EVENTS_GUID     "41227C2D-80E1-423F-8B8E-87E32755A0EB"
38
39 /* Patterns for recognizing sensors and matching events to channels. */
40
41 #define HP_WMI_PATTERN_SYS_TEMP         "Chassis Thermal Index"
42 #define HP_WMI_PATTERN_SYS_TEMP2        "System Ambient Temperature"
43 #define HP_WMI_PATTERN_CPU_TEMP         "CPU Thermal Index"
44 #define HP_WMI_PATTERN_CPU_TEMP2        "CPU Temperature"
45 #define HP_WMI_PATTERN_TEMP_SENSOR      "Thermal Index"
46 #define HP_WMI_PATTERN_TEMP_ALARM       "Thermal Critical"
47 #define HP_WMI_PATTERN_INTRUSION_ALARM  "Hood Intrusion"
48 #define HP_WMI_PATTERN_FAN_ALARM        "Stall"
49 #define HP_WMI_PATTERN_TEMP             "Temperature"
50 #define HP_WMI_PATTERN_CPU              "CPU"
51
52 /* These limits are arbitrary. The WMI implementation may vary by system. */
53
54 #define HP_WMI_MAX_STR_SIZE             128U
55 #define HP_WMI_MAX_PROPERTIES           32U
56 #define HP_WMI_MAX_INSTANCES            32U
57
58 enum hp_wmi_type {
59         HP_WMI_TYPE_OTHER                       = 1,
60         HP_WMI_TYPE_TEMPERATURE                 = 2,
61         HP_WMI_TYPE_VOLTAGE                     = 3,
62         HP_WMI_TYPE_CURRENT                     = 4,
63         HP_WMI_TYPE_AIR_FLOW                    = 12,
64         HP_WMI_TYPE_INTRUSION                   = 0xabadb01, /* Custom. */
65 };
66
67 enum hp_wmi_category {
68         HP_WMI_CATEGORY_SENSOR                  = 3,
69 };
70
71 enum hp_wmi_severity {
72         HP_WMI_SEVERITY_UNKNOWN                 = 0,
73         HP_WMI_SEVERITY_OK                      = 5,
74         HP_WMI_SEVERITY_DEGRADED_WARNING        = 10,
75         HP_WMI_SEVERITY_MINOR_FAILURE           = 15,
76         HP_WMI_SEVERITY_MAJOR_FAILURE           = 20,
77         HP_WMI_SEVERITY_CRITICAL_FAILURE        = 25,
78         HP_WMI_SEVERITY_NON_RECOVERABLE_ERROR   = 30,
79 };
80
81 enum hp_wmi_status {
82         HP_WMI_STATUS_OK                        = 2,
83         HP_WMI_STATUS_DEGRADED                  = 3,
84         HP_WMI_STATUS_STRESSED                  = 4,
85         HP_WMI_STATUS_PREDICTIVE_FAILURE        = 5,
86         HP_WMI_STATUS_ERROR                     = 6,
87         HP_WMI_STATUS_NON_RECOVERABLE_ERROR     = 7,
88         HP_WMI_STATUS_NO_CONTACT                = 12,
89         HP_WMI_STATUS_LOST_COMMUNICATION        = 13,
90         HP_WMI_STATUS_ABORTED                   = 14,
91         HP_WMI_STATUS_SUPPORTING_ENTITY_IN_ERROR = 16,
92
93         /* Occurs combined with one of "OK", "Degraded", and "Error" [1]. */
94         HP_WMI_STATUS_COMPLETED                 = 17,
95 };
96
97 enum hp_wmi_units {
98         HP_WMI_UNITS_OTHER                      = 1,
99         HP_WMI_UNITS_DEGREES_C                  = 2,
100         HP_WMI_UNITS_DEGREES_F                  = 3,
101         HP_WMI_UNITS_DEGREES_K                  = 4,
102         HP_WMI_UNITS_VOLTS                      = 5,
103         HP_WMI_UNITS_AMPS                       = 6,
104         HP_WMI_UNITS_RPM                        = 19,
105 };
106
107 enum hp_wmi_property {
108         HP_WMI_PROPERTY_NAME                    = 0,
109         HP_WMI_PROPERTY_DESCRIPTION             = 1,
110         HP_WMI_PROPERTY_SENSOR_TYPE             = 2,
111         HP_WMI_PROPERTY_OTHER_SENSOR_TYPE       = 3,
112         HP_WMI_PROPERTY_OPERATIONAL_STATUS      = 4,
113         HP_WMI_PROPERTY_SIZE                    = 5,
114         HP_WMI_PROPERTY_POSSIBLE_STATES         = 6,
115         HP_WMI_PROPERTY_CURRENT_STATE           = 7,
116         HP_WMI_PROPERTY_BASE_UNITS              = 8,
117         HP_WMI_PROPERTY_UNIT_MODIFIER           = 9,
118         HP_WMI_PROPERTY_CURRENT_READING         = 10,
119         HP_WMI_PROPERTY_RATE_UNITS              = 11,
120 };
121
122 static const acpi_object_type hp_wmi_property_map[] = {
123         [HP_WMI_PROPERTY_NAME]                  = ACPI_TYPE_STRING,
124         [HP_WMI_PROPERTY_DESCRIPTION]           = ACPI_TYPE_STRING,
125         [HP_WMI_PROPERTY_SENSOR_TYPE]           = ACPI_TYPE_INTEGER,
126         [HP_WMI_PROPERTY_OTHER_SENSOR_TYPE]     = ACPI_TYPE_STRING,
127         [HP_WMI_PROPERTY_OPERATIONAL_STATUS]    = ACPI_TYPE_INTEGER,
128         [HP_WMI_PROPERTY_SIZE]                  = ACPI_TYPE_INTEGER,
129         [HP_WMI_PROPERTY_POSSIBLE_STATES]       = ACPI_TYPE_STRING,
130         [HP_WMI_PROPERTY_CURRENT_STATE]         = ACPI_TYPE_STRING,
131         [HP_WMI_PROPERTY_BASE_UNITS]            = ACPI_TYPE_INTEGER,
132         [HP_WMI_PROPERTY_UNIT_MODIFIER]         = ACPI_TYPE_INTEGER,
133         [HP_WMI_PROPERTY_CURRENT_READING]       = ACPI_TYPE_INTEGER,
134         [HP_WMI_PROPERTY_RATE_UNITS]            = ACPI_TYPE_INTEGER,
135 };
136
137 enum hp_wmi_platform_events_property {
138         HP_WMI_PLATFORM_EVENTS_PROPERTY_NAME                = 0,
139         HP_WMI_PLATFORM_EVENTS_PROPERTY_DESCRIPTION         = 1,
140         HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_NAMESPACE    = 2,
141         HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_CLASS        = 3,
142         HP_WMI_PLATFORM_EVENTS_PROPERTY_CATEGORY            = 4,
143         HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_SEVERITY   = 5,
144         HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS     = 6,
145 };
146
147 static const acpi_object_type hp_wmi_platform_events_property_map[] = {
148         [HP_WMI_PLATFORM_EVENTS_PROPERTY_NAME]              = ACPI_TYPE_STRING,
149         [HP_WMI_PLATFORM_EVENTS_PROPERTY_DESCRIPTION]       = ACPI_TYPE_STRING,
150         [HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_NAMESPACE]  = ACPI_TYPE_STRING,
151         [HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_CLASS]      = ACPI_TYPE_STRING,
152         [HP_WMI_PLATFORM_EVENTS_PROPERTY_CATEGORY]          = ACPI_TYPE_INTEGER,
153         [HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_SEVERITY] = ACPI_TYPE_INTEGER,
154         [HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS]   = ACPI_TYPE_INTEGER,
155 };
156
157 enum hp_wmi_event_property {
158         HP_WMI_EVENT_PROPERTY_NAME              = 0,
159         HP_WMI_EVENT_PROPERTY_DESCRIPTION       = 1,
160         HP_WMI_EVENT_PROPERTY_CATEGORY          = 2,
161         HP_WMI_EVENT_PROPERTY_SEVERITY          = 3,
162         HP_WMI_EVENT_PROPERTY_STATUS            = 4,
163 };
164
165 static const acpi_object_type hp_wmi_event_property_map[] = {
166         [HP_WMI_EVENT_PROPERTY_NAME]            = ACPI_TYPE_STRING,
167         [HP_WMI_EVENT_PROPERTY_DESCRIPTION]     = ACPI_TYPE_STRING,
168         [HP_WMI_EVENT_PROPERTY_CATEGORY]        = ACPI_TYPE_INTEGER,
169         [HP_WMI_EVENT_PROPERTY_SEVERITY]        = ACPI_TYPE_INTEGER,
170         [HP_WMI_EVENT_PROPERTY_STATUS]          = ACPI_TYPE_INTEGER,
171 };
172
173 static const enum hwmon_sensor_types hp_wmi_hwmon_type_map[] = {
174         [HP_WMI_TYPE_TEMPERATURE]               = hwmon_temp,
175         [HP_WMI_TYPE_VOLTAGE]                   = hwmon_in,
176         [HP_WMI_TYPE_CURRENT]                   = hwmon_curr,
177         [HP_WMI_TYPE_AIR_FLOW]                  = hwmon_fan,
178 };
179
180 static const u32 hp_wmi_hwmon_attributes[hwmon_max] = {
181         [hwmon_chip]      = HWMON_C_REGISTER_TZ,
182         [hwmon_temp]      = HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_FAULT,
183         [hwmon_in]        = HWMON_I_INPUT | HWMON_I_LABEL,
184         [hwmon_curr]      = HWMON_C_INPUT | HWMON_C_LABEL,
185         [hwmon_fan]       = HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_FAULT,
186         [hwmon_intrusion] = HWMON_INTRUSION_ALARM,
187 };
188
189 /*
190  * struct hp_wmi_numeric_sensor - a HPBIOS_BIOSNumericSensor instance
191  *
192  * Two variants of HPBIOS_BIOSNumericSensor are known. The first is specified
193  * in [1] and appears to be much more widespread. The second was discovered by
194  * decoding BMOF blobs [4], seems to be found only in some newer ZBook systems
195  * [3], and has two new properties and a slightly different property order.
196  *
197  * These differences don't matter on Windows, where WMI object properties are
198  * accessed by name. For us, supporting both variants gets ugly and hacky at
199  * times. The fun begins now; this struct is defined as per the new variant.
200  *
201  * Effective MOF definition:
202  *
203  *   #pragma namespace("\\\\.\\root\\HP\\InstrumentedBIOS");
204  *   class HPBIOS_BIOSNumericSensor {
205  *     [read] string Name;
206  *     [read] string Description;
207  *     [read, ValueMap {"0","1","2","3","4","5","6","7","8","9",
208  *      "10","11","12"}, Values {"Unknown","Other","Temperature",
209  *      "Voltage","Current","Tachometer","Counter","Switch","Lock",
210  *      "Humidity","Smoke Detection","Presence","Air Flow"}]
211  *     uint32 SensorType;
212  *     [read] string OtherSensorType;
213  *     [read, ValueMap {"0","1","2","3","4","5","6","7","8","9",
214  *      "10","11","12","13","14","15","16","17","18","..",
215  *      "0x8000.."}, Values {"Unknown","Other","OK","Degraded",
216  *      "Stressed","Predictive Failure","Error",
217  *      "Non-Recoverable Error","Starting","Stopping","Stopped",
218  *      "In Service","No Contact","Lost Communication","Aborted",
219  *      "Dormant","Supporting Entity in Error","Completed",
220  *      "Power Mode","DMTF Reserved","Vendor Reserved"}]
221  *     uint32 OperationalStatus;
222  *     [read] uint32 Size;
223  *     [read] string PossibleStates[];
224  *     [read] string CurrentState;
225  *     [read, ValueMap {"0","1","2","3","4","5","6","7","8","9",
226  *      "10","11","12","13","14","15","16","17","18","19","20",
227  *      "21","22","23","24","25","26","27","28","29","30","31",
228  *      "32","33","34","35","36","37","38","39","40","41","42",
229  *      "43","44","45","46","47","48","49","50","51","52","53",
230  *      "54","55","56","57","58","59","60","61","62","63","64",
231  *      "65"}, Values {"Unknown","Other","Degrees C","Degrees F",
232  *      "Degrees K","Volts","Amps","Watts","Joules","Coulombs",
233  *      "VA","Nits","Lumens","Lux","Candelas","kPa","PSI",
234  *      "Newtons","CFM","RPM","Hertz","Seconds","Minutes",
235  *      "Hours","Days","Weeks","Mils","Inches","Feet",
236  *      "Cubic Inches","Cubic Feet","Meters","Cubic Centimeters",
237  *      "Cubic Meters","Liters","Fluid Ounces","Radians",
238  *      "Steradians","Revolutions","Cycles","Gravities","Ounces",
239  *      "Pounds","Foot-Pounds","Ounce-Inches","Gauss","Gilberts",
240  *      "Henries","Farads","Ohms","Siemens","Moles","Becquerels",
241  *      "PPM (parts/million)","Decibels","DbA","DbC","Grays",
242  *      "Sieverts","Color Temperature Degrees K","Bits","Bytes",
243  *      "Words (data)","DoubleWords","QuadWords","Percentage"}]
244  *     uint32 BaseUnits;
245  *     [read] sint32 UnitModifier;
246  *     [read] uint32 CurrentReading;
247  *     [read] uint32 RateUnits;
248  *   };
249  *
250  * Effective MOF definition of old variant [1] (sans redundant info):
251  *
252  *   class HPBIOS_BIOSNumericSensor {
253  *     [read] string Name;
254  *     [read] string Description;
255  *     [read] uint32 SensorType;
256  *     [read] string OtherSensorType;
257  *     [read] uint32 OperationalStatus;
258  *     [read] string CurrentState;
259  *     [read] string PossibleStates[];
260  *     [read] uint32 BaseUnits;
261  *     [read] sint32 UnitModifier;
262  *     [read] uint32 CurrentReading;
263  *   };
264  */
265 struct hp_wmi_numeric_sensor {
266         const char *name;
267         const char *description;
268         u32 sensor_type;
269         const char *other_sensor_type;  /* Explains "Other" SensorType. */
270         u32 operational_status;
271         u8 size;                        /* Count of PossibleStates[]. */
272         const char **possible_states;
273         const char *current_state;
274         u32 base_units;
275         s32 unit_modifier;
276         u32 current_reading;
277         u32 rate_units;
278 };
279
280 /*
281  * struct hp_wmi_platform_events - a HPBIOS_PlatformEvents instance
282  *
283  * Instances of this object reveal the set of possible HPBIOS_BIOSEvent
284  * instances for the current system, but it may not always be present.
285  *
286  * Effective MOF definition:
287  *
288  *   #pragma namespace("\\\\.\\root\\HP\\InstrumentedBIOS");
289  *   class HPBIOS_PlatformEvents {
290  *     [read] string Name;
291  *     [read] string Description;
292  *     [read] string SourceNamespace;
293  *     [read] string SourceClass;
294  *     [read, ValueMap {"0","1","2","3","4",".."}, Values {
295  *      "Unknown","Configuration Change","Button Pressed",
296  *      "Sensor","BIOS Settings","Reserved"}]
297  *     uint32 Category;
298  *     [read, ValueMap{"0","5","10","15","20","25","30",".."},
299  *      Values{"Unknown","OK","Degraded/Warning","Minor Failure",
300  *      "Major Failure","Critical Failure","Non-recoverable Error",
301  *      "DMTF Reserved"}]
302  *     uint32 PossibleSeverity;
303  *     [read, ValueMap {"0","1","2","3","4","5","6","7","8","9",
304  *      "10","11","12","13","14","15","16","17","18","..",
305  *      "0x8000.."}, Values {"Unknown","Other","OK","Degraded",
306  *      "Stressed","Predictive Failure","Error",
307  *      "Non-Recoverable Error","Starting","Stopping","Stopped",
308  *      "In Service","No Contact","Lost Communication","Aborted",
309  *      "Dormant","Supporting Entity in Error","Completed",
310  *      "Power Mode","DMTF Reserved","Vendor Reserved"}]
311  *     uint32 PossibleStatus;
312  *   };
313  */
314 struct hp_wmi_platform_events {
315         const char *name;
316         const char *description;
317         const char *source_namespace;
318         const char *source_class;
319         u32 category;
320         u32 possible_severity;
321         u32 possible_status;
322 };
323
324 /*
325  * struct hp_wmi_event - a HPBIOS_BIOSEvent instance
326  *
327  * Effective MOF definition [1] (corrected below from original):
328  *
329  *   #pragma namespace("\\\\.\\root\\WMI");
330  *   class HPBIOS_BIOSEvent : WMIEvent {
331  *     [read] string Name;
332  *     [read] string Description;
333  *     [read ValueMap {"0","1","2","3","4"}, Values {"Unknown",
334  *      "Configuration Change","Button Pressed","Sensor",
335  *      "BIOS Settings"}]
336  *     uint32 Category;
337  *     [read, ValueMap {"0","5","10","15","20","25","30"},
338  *      Values {"Unknown","OK","Degraded/Warning",
339  *      "Minor Failure","Major Failure","Critical Failure",
340  *      "Non-recoverable Error"}]
341  *     uint32 Severity;
342  *     [read, ValueMap {"0","1","2","3","4","5","6","7","8",
343  *      "9","10","11","12","13","14","15","16","17","18","..",
344  *      "0x8000.."}, Values {"Unknown","Other","OK","Degraded",
345  *      "Stressed","Predictive Failure","Error",
346  *      "Non-Recoverable Error","Starting","Stopping","Stopped",
347  *      "In Service","No Contact","Lost Communication","Aborted",
348  *      "Dormant","Supporting Entity in Error","Completed",
349  *      "Power Mode","DMTF Reserved","Vendor Reserved"}]
350  *     uint32 Status;
351  *   };
352  */
353 struct hp_wmi_event {
354         const char *name;
355         const char *description;
356         u32 category;
357 };
358
359 /*
360  * struct hp_wmi_info - sensor info
361  * @nsensor: numeric sensor properties
362  * @instance: its WMI instance number
363  * @state: pointer to driver state
364  * @has_alarm: whether sensor has an alarm flag
365  * @alarm: alarm flag
366  * @type: its hwmon sensor type
367  * @cached_val: current sensor reading value, scaled for hwmon
368  * @last_updated: when these readings were last updated
369  */
370 struct hp_wmi_info {
371         struct hp_wmi_numeric_sensor nsensor;
372         u8 instance;
373         void *state;                    /* void *: Avoid forward declaration. */
374         bool has_alarm;
375         bool alarm;
376         enum hwmon_sensor_types type;
377         long cached_val;
378         unsigned long last_updated;     /* In jiffies. */
379
380 };
381
382 /*
383  * struct hp_wmi_sensors - driver state
384  * @wdev: pointer to the parent WMI device
385  * @info_map: sensor info structs by hwmon type and channel number
386  * @channel_count: count of hwmon channels by hwmon type
387  * @has_intrusion: whether an intrusion sensor is present
388  * @intrusion: intrusion flag
389  * @lock: mutex to lock polling WMI and changes to driver state
390  */
391 struct hp_wmi_sensors {
392         struct wmi_device *wdev;
393         struct hp_wmi_info **info_map[hwmon_max];
394         u8 channel_count[hwmon_max];
395         bool has_intrusion;
396         bool intrusion;
397
398         struct mutex lock;      /* Lock polling WMI and driver state changes. */
399 };
400
401 static bool is_raw_wmi_string(const u8 *pointer, u32 length)
402 {
403         const u16 *ptr;
404         u16 len;
405
406         /* WMI strings are length-prefixed UTF-16 [5]. */
407         if (length <= sizeof(*ptr))
408                 return false;
409
410         length -= sizeof(*ptr);
411         ptr = (const u16 *)pointer;
412         len = *ptr;
413
414         return len <= length && !(len & 1);
415 }
416
417 static char *convert_raw_wmi_string(const u8 *buf)
418 {
419         const wchar_t *src;
420         unsigned int cps;
421         unsigned int len;
422         char *dst;
423         int i;
424
425         src = (const wchar_t *)buf;
426
427         /* Count UTF-16 code points. Exclude trailing null padding. */
428         cps = *src / sizeof(*src);
429         while (cps && !src[cps])
430                 cps--;
431
432         /* Each code point becomes up to 3 UTF-8 characters. */
433         len = min(cps * 3, HP_WMI_MAX_STR_SIZE - 1);
434
435         dst = kmalloc((len + 1) * sizeof(*dst), GFP_KERNEL);
436         if (!dst)
437                 return NULL;
438
439         i = utf16s_to_utf8s(++src, cps, UTF16_LITTLE_ENDIAN, dst, len);
440         dst[i] = '\0';
441
442         return dst;
443 }
444
445 /* hp_wmi_strdup - devm_kstrdup, but length-limited */
446 static char *hp_wmi_strdup(struct device *dev, const char *src)
447 {
448         char *dst;
449         size_t len;
450
451         len = strnlen(src, HP_WMI_MAX_STR_SIZE - 1);
452
453         dst = devm_kmalloc(dev, (len + 1) * sizeof(*dst), GFP_KERNEL);
454         if (!dst)
455                 return NULL;
456
457         strscpy(dst, src, len + 1);
458
459         return dst;
460 }
461
462 /* hp_wmi_wstrdup - hp_wmi_strdup, but for a raw WMI string */
463 static char *hp_wmi_wstrdup(struct device *dev, const u8 *buf)
464 {
465         char *src;
466         char *dst;
467
468         src = convert_raw_wmi_string(buf);
469         if (!src)
470                 return NULL;
471
472         dst = hp_wmi_strdup(dev, strim(src));   /* Note: Copy is trimmed. */
473
474         kfree(src);
475
476         return dst;
477 }
478
479 /*
480  * hp_wmi_get_wobj - poll WMI for a WMI object instance
481  * @guid: WMI object GUID
482  * @instance: WMI object instance number
483  *
484  * Returns a new WMI object instance on success, or NULL on error.
485  * Caller must kfree() the result.
486  */
487 static union acpi_object *hp_wmi_get_wobj(const char *guid, u8 instance)
488 {
489         struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
490         acpi_status err;
491
492         err = wmi_query_block(guid, instance, &out);
493         if (ACPI_FAILURE(err))
494                 return NULL;
495
496         return out.pointer;
497 }
498
499 /* hp_wmi_wobj_instance_count - find count of WMI object instances */
500 static u8 hp_wmi_wobj_instance_count(const char *guid)
501 {
502         int count;
503
504         count = wmi_instance_count(guid);
505
506         return clamp(count, 0, (int)HP_WMI_MAX_INSTANCES);
507 }
508
509 static int check_wobj(const union acpi_object *wobj,
510                       const acpi_object_type property_map[], int last_prop)
511 {
512         acpi_object_type type = wobj->type;
513         acpi_object_type valid_type;
514         union acpi_object *elements;
515         u32 elem_count;
516         int prop;
517
518         if (type != ACPI_TYPE_PACKAGE)
519                 return -EINVAL;
520
521         elem_count = wobj->package.count;
522         if (elem_count != last_prop + 1)
523                 return -EINVAL;
524
525         elements = wobj->package.elements;
526         for (prop = 0; prop <= last_prop; prop++) {
527                 type = elements[prop].type;
528                 valid_type = property_map[prop];
529                 if (type != valid_type) {
530                         if (type == ACPI_TYPE_BUFFER &&
531                             valid_type == ACPI_TYPE_STRING &&
532                             is_raw_wmi_string(elements[prop].buffer.pointer,
533                                               elements[prop].buffer.length))
534                                 continue;
535                         return -EINVAL;
536                 }
537         }
538
539         return 0;
540 }
541
542 static int extract_acpi_value(struct device *dev,
543                               union acpi_object *element,
544                               acpi_object_type type,
545                               u32 *out_value, char **out_string)
546 {
547         switch (type) {
548         case ACPI_TYPE_INTEGER:
549                 *out_value = element->integer.value;
550                 break;
551
552         case ACPI_TYPE_STRING:
553                 *out_string = element->type == ACPI_TYPE_BUFFER ?
554                         hp_wmi_wstrdup(dev, element->buffer.pointer) :
555                         hp_wmi_strdup(dev, strim(element->string.pointer));
556                 if (!*out_string)
557                         return -ENOMEM;
558                 break;
559
560         default:
561                 return -EINVAL;
562         }
563
564         return 0;
565 }
566
567 /*
568  * check_numeric_sensor_wobj - validate a HPBIOS_BIOSNumericSensor instance
569  * @wobj: pointer to WMI object instance to check
570  * @out_size: out pointer to count of possible states
571  * @out_is_new: out pointer to whether this is a "new" variant object
572  *
573  * Returns 0 on success, or a negative error code on error.
574  */
575 static int check_numeric_sensor_wobj(const union acpi_object *wobj,
576                                      u8 *out_size, bool *out_is_new)
577 {
578         acpi_object_type type = wobj->type;
579         int prop = HP_WMI_PROPERTY_NAME;
580         acpi_object_type valid_type;
581         union acpi_object *elements;
582         u32 elem_count;
583         int last_prop;
584         bool is_new;
585         u8 count;
586         u32 j;
587         u32 i;
588
589         if (type != ACPI_TYPE_PACKAGE)
590                 return -EINVAL;
591
592         /*
593          * elements is a variable-length array of ACPI objects, one for
594          * each property of the WMI object instance, except that the
595          * strings in PossibleStates[] are flattened into this array
596          * as if each individual string were a property by itself.
597          */
598         elements = wobj->package.elements;
599
600         elem_count = wobj->package.count;
601         if (elem_count <= HP_WMI_PROPERTY_SIZE ||
602             elem_count > HP_WMI_MAX_PROPERTIES)
603                 return -EINVAL;
604
605         type = elements[HP_WMI_PROPERTY_SIZE].type;
606         switch (type) {
607         case ACPI_TYPE_INTEGER:
608                 is_new = true;
609                 last_prop = HP_WMI_PROPERTY_RATE_UNITS;
610                 break;
611
612         case ACPI_TYPE_STRING:
613                 is_new = false;
614                 last_prop = HP_WMI_PROPERTY_CURRENT_READING;
615                 break;
616
617         default:
618                 return -EINVAL;
619         }
620
621         /*
622          * In general, the count of PossibleStates[] must be > 0.
623          * Also, the old variant lacks the Size property, so we may need to
624          * reduce the value of last_prop by 1 when doing arithmetic with it.
625          */
626         if (elem_count < last_prop - !is_new + 1)
627                 return -EINVAL;
628
629         count = elem_count - (last_prop - !is_new);
630
631         for (i = 0; i < elem_count && prop <= last_prop; i++, prop++) {
632                 type = elements[i].type;
633                 valid_type = hp_wmi_property_map[prop];
634                 if (type != valid_type)
635                         return -EINVAL;
636
637                 switch (prop) {
638                 case HP_WMI_PROPERTY_OPERATIONAL_STATUS:
639                         /* Old variant: CurrentState follows OperationalStatus. */
640                         if (!is_new)
641                                 prop = HP_WMI_PROPERTY_CURRENT_STATE - 1;
642                         break;
643
644                 case HP_WMI_PROPERTY_SIZE:
645                         /* New variant: Size == count of PossibleStates[]. */
646                         if (count != elements[i].integer.value)
647                                 return -EINVAL;
648                         break;
649
650                 case HP_WMI_PROPERTY_POSSIBLE_STATES:
651                         /* PossibleStates[0] has already been type-checked. */
652                         for (j = 0; i + 1 < elem_count && j + 1 < count; j++) {
653                                 type = elements[++i].type;
654                                 if (type != valid_type)
655                                         return -EINVAL;
656                         }
657
658                         /* Old variant: BaseUnits follows PossibleStates[]. */
659                         if (!is_new)
660                                 prop = HP_WMI_PROPERTY_BASE_UNITS - 1;
661                         break;
662
663                 case HP_WMI_PROPERTY_CURRENT_STATE:
664                         /* Old variant: PossibleStates[] follows CurrentState. */
665                         if (!is_new)
666                                 prop = HP_WMI_PROPERTY_POSSIBLE_STATES - 1;
667                         break;
668                 }
669         }
670
671         if (prop != last_prop + 1)
672                 return -EINVAL;
673
674         *out_size = count;
675         *out_is_new = is_new;
676
677         return 0;
678 }
679
680 static int
681 numeric_sensor_is_connected(const struct hp_wmi_numeric_sensor *nsensor)
682 {
683         u32 operational_status = nsensor->operational_status;
684
685         return operational_status != HP_WMI_STATUS_NO_CONTACT;
686 }
687
688 static int numeric_sensor_has_fault(const struct hp_wmi_numeric_sensor *nsensor)
689 {
690         u32 operational_status = nsensor->operational_status;
691
692         switch (operational_status) {
693         case HP_WMI_STATUS_DEGRADED:
694         case HP_WMI_STATUS_STRESSED:            /* e.g. Overload, overtemp. */
695         case HP_WMI_STATUS_PREDICTIVE_FAILURE:  /* e.g. Fan removed. */
696         case HP_WMI_STATUS_ERROR:
697         case HP_WMI_STATUS_NON_RECOVERABLE_ERROR:
698         case HP_WMI_STATUS_NO_CONTACT:
699         case HP_WMI_STATUS_LOST_COMMUNICATION:
700         case HP_WMI_STATUS_ABORTED:
701         case HP_WMI_STATUS_SUPPORTING_ENTITY_IN_ERROR:
702
703         /* Assume combination by addition; bitwise OR doesn't make sense. */
704         case HP_WMI_STATUS_COMPLETED + HP_WMI_STATUS_DEGRADED:
705         case HP_WMI_STATUS_COMPLETED + HP_WMI_STATUS_ERROR:
706                 return true;
707         }
708
709         return false;
710 }
711
712 /* scale_numeric_sensor - scale sensor reading for hwmon */
713 static long scale_numeric_sensor(const struct hp_wmi_numeric_sensor *nsensor)
714 {
715         u32 current_reading = nsensor->current_reading;
716         s32 unit_modifier = nsensor->unit_modifier;
717         u32 sensor_type = nsensor->sensor_type;
718         u32 base_units = nsensor->base_units;
719         s32 target_modifier;
720         long val;
721
722         /* Fan readings are in RPM units; others are in milliunits. */
723         target_modifier = sensor_type == HP_WMI_TYPE_AIR_FLOW ? 0 : -3;
724
725         val = current_reading;
726
727         for (; unit_modifier < target_modifier; unit_modifier++)
728                 val = DIV_ROUND_CLOSEST(val, 10);
729
730         for (; unit_modifier > target_modifier; unit_modifier--) {
731                 if (val > LONG_MAX / 10) {
732                         val = LONG_MAX;
733                         break;
734                 }
735                 val *= 10;
736         }
737
738         if (sensor_type == HP_WMI_TYPE_TEMPERATURE) {
739                 switch (base_units) {
740                 case HP_WMI_UNITS_DEGREES_F:
741                         val -= MILLI * 32;
742                         val = val <= LONG_MAX / 5 ?
743                                       DIV_ROUND_CLOSEST(val * 5, 9) :
744                                       DIV_ROUND_CLOSEST(val, 9) * 5;
745                         break;
746
747                 case HP_WMI_UNITS_DEGREES_K:
748                         val = milli_kelvin_to_millicelsius(val);
749                         break;
750                 }
751         }
752
753         return val;
754 }
755
756 /*
757  * classify_numeric_sensor - classify a numeric sensor
758  * @nsensor: pointer to numeric sensor struct
759  *
760  * Returns an enum hp_wmi_type value on success,
761  * or a negative value if the sensor type is unsupported.
762  */
763 static int classify_numeric_sensor(const struct hp_wmi_numeric_sensor *nsensor)
764 {
765         u32 sensor_type = nsensor->sensor_type;
766         u32 base_units = nsensor->base_units;
767         const char *name = nsensor->name;
768
769         switch (sensor_type) {
770         case HP_WMI_TYPE_TEMPERATURE:
771                 /*
772                  * Some systems have sensors named "X Thermal Index" in "Other"
773                  * units. Tested CPU sensor examples were found to be in °C,
774                  * albeit perhaps "differently" accurate; e.g. readings were
775                  * reliably -6°C vs. coretemp on a HP Compaq Elite 8300, and
776                  * +8°C on an EliteOne G1 800. But this is still within the
777                  * realm of plausibility for cheaply implemented motherboard
778                  * sensors, and chassis readings were about as expected.
779                  */
780                 if ((base_units == HP_WMI_UNITS_OTHER &&
781                      strstr(name, HP_WMI_PATTERN_TEMP_SENSOR)) ||
782                     base_units == HP_WMI_UNITS_DEGREES_C ||
783                     base_units == HP_WMI_UNITS_DEGREES_F ||
784                     base_units == HP_WMI_UNITS_DEGREES_K)
785                         return HP_WMI_TYPE_TEMPERATURE;
786                 break;
787
788         case HP_WMI_TYPE_VOLTAGE:
789                 if (base_units == HP_WMI_UNITS_VOLTS)
790                         return HP_WMI_TYPE_VOLTAGE;
791                 break;
792
793         case HP_WMI_TYPE_CURRENT:
794                 if (base_units == HP_WMI_UNITS_AMPS)
795                         return HP_WMI_TYPE_CURRENT;
796                 break;
797
798         case HP_WMI_TYPE_AIR_FLOW:
799                 /*
800                  * Strangely, HP considers fan RPM sensor type to be
801                  * "Air Flow" instead of the more intuitive "Tachometer".
802                  */
803                 if (base_units == HP_WMI_UNITS_RPM)
804                         return HP_WMI_TYPE_AIR_FLOW;
805                 break;
806         }
807
808         return -EINVAL;
809 }
810
811 static int
812 populate_numeric_sensor_from_wobj(struct device *dev,
813                                   struct hp_wmi_numeric_sensor *nsensor,
814                                   union acpi_object *wobj, bool *out_is_new)
815 {
816         int last_prop = HP_WMI_PROPERTY_RATE_UNITS;
817         int prop = HP_WMI_PROPERTY_NAME;
818         const char **possible_states;
819         union acpi_object *element;
820         acpi_object_type type;
821         char *string;
822         bool is_new;
823         u32 value;
824         u8 size;
825         int err;
826
827         err = check_numeric_sensor_wobj(wobj, &size, &is_new);
828         if (err)
829                 return err;
830
831         possible_states = devm_kcalloc(dev, size, sizeof(*possible_states),
832                                        GFP_KERNEL);
833         if (!possible_states)
834                 return -ENOMEM;
835
836         element = wobj->package.elements;
837         nsensor->possible_states = possible_states;
838         nsensor->size = size;
839
840         if (!is_new)
841                 last_prop = HP_WMI_PROPERTY_CURRENT_READING;
842
843         for (; prop <= last_prop; prop++) {
844                 type = hp_wmi_property_map[prop];
845
846                 err = extract_acpi_value(dev, element, type, &value, &string);
847                 if (err)
848                         return err;
849
850                 element++;
851
852                 switch (prop) {
853                 case HP_WMI_PROPERTY_NAME:
854                         nsensor->name = string;
855                         break;
856
857                 case HP_WMI_PROPERTY_DESCRIPTION:
858                         nsensor->description = string;
859                         break;
860
861                 case HP_WMI_PROPERTY_SENSOR_TYPE:
862                         if (value > HP_WMI_TYPE_AIR_FLOW)
863                                 return -EINVAL;
864
865                         nsensor->sensor_type = value;
866                         break;
867
868                 case HP_WMI_PROPERTY_OTHER_SENSOR_TYPE:
869                         nsensor->other_sensor_type = string;
870                         break;
871
872                 case HP_WMI_PROPERTY_OPERATIONAL_STATUS:
873                         nsensor->operational_status = value;
874
875                         /* Old variant: CurrentState follows OperationalStatus. */
876                         if (!is_new)
877                                 prop = HP_WMI_PROPERTY_CURRENT_STATE - 1;
878                         break;
879
880                 case HP_WMI_PROPERTY_SIZE:
881                         break;                  /* Already set. */
882
883                 case HP_WMI_PROPERTY_POSSIBLE_STATES:
884                         *possible_states++ = string;
885                         if (--size)
886                                 prop--;
887
888                         /* Old variant: BaseUnits follows PossibleStates[]. */
889                         if (!is_new && !size)
890                                 prop = HP_WMI_PROPERTY_BASE_UNITS - 1;
891                         break;
892
893                 case HP_WMI_PROPERTY_CURRENT_STATE:
894                         nsensor->current_state = string;
895
896                         /* Old variant: PossibleStates[] follows CurrentState. */
897                         if (!is_new)
898                                 prop = HP_WMI_PROPERTY_POSSIBLE_STATES - 1;
899                         break;
900
901                 case HP_WMI_PROPERTY_BASE_UNITS:
902                         nsensor->base_units = value;
903                         break;
904
905                 case HP_WMI_PROPERTY_UNIT_MODIFIER:
906                         /* UnitModifier is signed. */
907                         nsensor->unit_modifier = (s32)value;
908                         break;
909
910                 case HP_WMI_PROPERTY_CURRENT_READING:
911                         nsensor->current_reading = value;
912                         break;
913
914                 case HP_WMI_PROPERTY_RATE_UNITS:
915                         nsensor->rate_units = value;
916                         break;
917
918                 default:
919                         return -EINVAL;
920                 }
921         }
922
923         *out_is_new = is_new;
924
925         return 0;
926 }
927
928 /* update_numeric_sensor_from_wobj - update fungible sensor properties */
929 static void
930 update_numeric_sensor_from_wobj(struct device *dev,
931                                 struct hp_wmi_numeric_sensor *nsensor,
932                                 const union acpi_object *wobj)
933 {
934         const union acpi_object *elements;
935         const union acpi_object *element;
936         const char *new_string;
937         char *trimmed;
938         char *string;
939         bool is_new;
940         int offset;
941         u8 size;
942         int err;
943
944         err = check_numeric_sensor_wobj(wobj, &size, &is_new);
945         if (err)
946                 return;
947
948         elements = wobj->package.elements;
949
950         element = &elements[HP_WMI_PROPERTY_OPERATIONAL_STATUS];
951         nsensor->operational_status = element->integer.value;
952
953         /*
954          * In general, an index offset is needed after PossibleStates[0].
955          * On a new variant, CurrentState is after PossibleStates[]. This is
956          * not the case on an old variant, but we still need to offset the
957          * read because CurrentState is where Size would be on a new variant.
958          */
959         offset = is_new ? size - 1 : -2;
960
961         element = &elements[HP_WMI_PROPERTY_CURRENT_STATE + offset];
962         string = element->type == ACPI_TYPE_BUFFER ?
963                 convert_raw_wmi_string(element->buffer.pointer) :
964                 element->string.pointer;
965
966         if (string) {
967                 trimmed = strim(string);
968                 if (strcmp(trimmed, nsensor->current_state)) {
969                         new_string = hp_wmi_strdup(dev, trimmed);
970                         if (new_string) {
971                                 devm_kfree(dev, nsensor->current_state);
972                                 nsensor->current_state = new_string;
973                         }
974                 }
975                 if (element->type == ACPI_TYPE_BUFFER)
976                         kfree(string);
977         }
978
979         /* Old variant: -2 (not -1) because it lacks the Size property. */
980         if (!is_new)
981                 offset = (int)size - 2; /* size is > 0, i.e. may be 1. */
982
983         element = &elements[HP_WMI_PROPERTY_UNIT_MODIFIER + offset];
984         nsensor->unit_modifier = (s32)element->integer.value;
985
986         element = &elements[HP_WMI_PROPERTY_CURRENT_READING + offset];
987         nsensor->current_reading = element->integer.value;
988 }
989
990 /*
991  * check_platform_events_wobj - validate a HPBIOS_PlatformEvents instance
992  * @wobj: pointer to WMI object instance to check
993  *
994  * Returns 0 on success, or a negative error code on error.
995  */
996 static int check_platform_events_wobj(const union acpi_object *wobj)
997 {
998         return check_wobj(wobj, hp_wmi_platform_events_property_map,
999                           HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS);
1000 }
1001
1002 static int
1003 populate_platform_events_from_wobj(struct device *dev,
1004                                    struct hp_wmi_platform_events *pevents,
1005                                    union acpi_object *wobj)
1006 {
1007         int last_prop = HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS;
1008         int prop = HP_WMI_PLATFORM_EVENTS_PROPERTY_NAME;
1009         union acpi_object *element;
1010         acpi_object_type type;
1011         char *string;
1012         u32 value;
1013         int err;
1014
1015         err = check_platform_events_wobj(wobj);
1016         if (err)
1017                 return err;
1018
1019         element = wobj->package.elements;
1020
1021         for (; prop <= last_prop; prop++, element++) {
1022                 type = hp_wmi_platform_events_property_map[prop];
1023
1024                 err = extract_acpi_value(dev, element, type, &value, &string);
1025                 if (err)
1026                         return err;
1027
1028                 switch (prop) {
1029                 case HP_WMI_PLATFORM_EVENTS_PROPERTY_NAME:
1030                         pevents->name = string;
1031                         break;
1032
1033                 case HP_WMI_PLATFORM_EVENTS_PROPERTY_DESCRIPTION:
1034                         pevents->description = string;
1035                         break;
1036
1037                 case HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_NAMESPACE:
1038                         if (strcasecmp(HP_WMI_EVENT_NAMESPACE, string))
1039                                 return -EINVAL;
1040
1041                         pevents->source_namespace = string;
1042                         break;
1043
1044                 case HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_CLASS:
1045                         if (strcasecmp(HP_WMI_EVENT_CLASS, string))
1046                                 return -EINVAL;
1047
1048                         pevents->source_class = string;
1049                         break;
1050
1051                 case HP_WMI_PLATFORM_EVENTS_PROPERTY_CATEGORY:
1052                         pevents->category = value;
1053                         break;
1054
1055                 case HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_SEVERITY:
1056                         pevents->possible_severity = value;
1057                         break;
1058
1059                 case HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS:
1060                         pevents->possible_status = value;
1061                         break;
1062
1063                 default:
1064                         return -EINVAL;
1065                 }
1066         }
1067
1068         return 0;
1069 }
1070
1071 /*
1072  * check_event_wobj - validate a HPBIOS_BIOSEvent instance
1073  * @wobj: pointer to WMI object instance to check
1074  *
1075  * Returns 0 on success, or a negative error code on error.
1076  */
1077 static int check_event_wobj(const union acpi_object *wobj)
1078 {
1079         return check_wobj(wobj, hp_wmi_event_property_map,
1080                           HP_WMI_EVENT_PROPERTY_STATUS);
1081 }
1082
1083 static int populate_event_from_wobj(struct device *dev,
1084                                     struct hp_wmi_event *event,
1085                                     union acpi_object *wobj)
1086 {
1087         int prop = HP_WMI_EVENT_PROPERTY_NAME;
1088         union acpi_object *element;
1089         acpi_object_type type;
1090         char *string;
1091         u32 value;
1092         int err;
1093
1094         err = check_event_wobj(wobj);
1095         if (err)
1096                 return err;
1097
1098         element = wobj->package.elements;
1099
1100         for (; prop <= HP_WMI_EVENT_PROPERTY_CATEGORY; prop++, element++) {
1101                 type = hp_wmi_event_property_map[prop];
1102
1103                 err = extract_acpi_value(dev, element, type, &value, &string);
1104                 if (err)
1105                         return err;
1106
1107                 switch (prop) {
1108                 case HP_WMI_EVENT_PROPERTY_NAME:
1109                         event->name = string;
1110                         break;
1111
1112                 case HP_WMI_EVENT_PROPERTY_DESCRIPTION:
1113                         event->description = string;
1114                         break;
1115
1116                 case HP_WMI_EVENT_PROPERTY_CATEGORY:
1117                         event->category = value;
1118                         break;
1119
1120                 default:
1121                         return -EINVAL;
1122                 }
1123         }
1124
1125         return 0;
1126 }
1127
1128 /*
1129  * classify_event - classify an event
1130  * @name: event name
1131  * @category: event category
1132  *
1133  * Classify instances of both HPBIOS_PlatformEvents and HPBIOS_BIOSEvent from
1134  * property values. Recognition criteria are based on multiple ACPI dumps [3].
1135  *
1136  * Returns an enum hp_wmi_type value on success,
1137  * or a negative value if the event type is unsupported.
1138  */
1139 static int classify_event(const char *event_name, u32 category)
1140 {
1141         if (category != HP_WMI_CATEGORY_SENSOR)
1142                 return -EINVAL;
1143
1144         /* Fan events have Name "X Stall". */
1145         if (strstr(event_name, HP_WMI_PATTERN_FAN_ALARM))
1146                 return HP_WMI_TYPE_AIR_FLOW;
1147
1148         /* Intrusion events have Name "Hood Intrusion". */
1149         if (!strcmp(event_name, HP_WMI_PATTERN_INTRUSION_ALARM))
1150                 return HP_WMI_TYPE_INTRUSION;
1151
1152         /*
1153          * Temperature events have Name either "Thermal Caution" or
1154          * "Thermal Critical". Deal only with "Thermal Critical" events.
1155          *
1156          * "Thermal Caution" events have Status "Stressed", informing us that
1157          * the OperationalStatus of the related sensor has become "Stressed".
1158          * However, this is already a fault condition that will clear itself
1159          * when the sensor recovers, so we have no further interest in them.
1160          */
1161         if (!strcmp(event_name, HP_WMI_PATTERN_TEMP_ALARM))
1162                 return HP_WMI_TYPE_TEMPERATURE;
1163
1164         return -EINVAL;
1165 }
1166
1167 /*
1168  * interpret_info - interpret sensor for hwmon
1169  * @info: pointer to sensor info struct
1170  *
1171  * Should be called after the numeric sensor member has been updated.
1172  */
1173 static void interpret_info(struct hp_wmi_info *info)
1174 {
1175         const struct hp_wmi_numeric_sensor *nsensor = &info->nsensor;
1176
1177         info->cached_val = scale_numeric_sensor(nsensor);
1178         info->last_updated = jiffies;
1179 }
1180
1181 /*
1182  * hp_wmi_update_info - poll WMI to update sensor info
1183  * @state: pointer to driver state
1184  * @info: pointer to sensor info struct
1185  *
1186  * Returns 0 on success, or a negative error code on error.
1187  */
1188 static int hp_wmi_update_info(struct hp_wmi_sensors *state,
1189                               struct hp_wmi_info *info)
1190 {
1191         struct hp_wmi_numeric_sensor *nsensor = &info->nsensor;
1192         struct device *dev = &state->wdev->dev;
1193         const union acpi_object *wobj;
1194         u8 instance = info->instance;
1195         int ret = 0;
1196
1197         if (time_after(jiffies, info->last_updated + HZ)) {
1198                 mutex_lock(&state->lock);
1199
1200                 wobj = hp_wmi_get_wobj(HP_WMI_NUMERIC_SENSOR_GUID, instance);
1201                 if (!wobj) {
1202                         ret = -EIO;
1203                         goto out_unlock;
1204                 }
1205
1206                 update_numeric_sensor_from_wobj(dev, nsensor, wobj);
1207
1208                 interpret_info(info);
1209
1210                 kfree(wobj);
1211
1212 out_unlock:
1213                 mutex_unlock(&state->lock);
1214         }
1215
1216         return ret;
1217 }
1218
1219 static int basic_string_show(struct seq_file *seqf, void *ignored)
1220 {
1221         const char *str = seqf->private;
1222
1223         seq_printf(seqf, "%s\n", str);
1224
1225         return 0;
1226 }
1227 DEFINE_SHOW_ATTRIBUTE(basic_string);
1228
1229 static int fungible_show(struct seq_file *seqf, enum hp_wmi_property prop)
1230 {
1231         struct hp_wmi_numeric_sensor *nsensor;
1232         struct hp_wmi_sensors *state;
1233         struct hp_wmi_info *info;
1234         int err;
1235
1236         info = seqf->private;
1237         state = info->state;
1238         nsensor = &info->nsensor;
1239
1240         err = hp_wmi_update_info(state, info);
1241         if (err)
1242                 return err;
1243
1244         switch (prop) {
1245         case HP_WMI_PROPERTY_OPERATIONAL_STATUS:
1246                 seq_printf(seqf, "%u\n", nsensor->operational_status);
1247                 break;
1248
1249         case HP_WMI_PROPERTY_CURRENT_STATE:
1250                 seq_printf(seqf, "%s\n", nsensor->current_state);
1251                 break;
1252
1253         case HP_WMI_PROPERTY_UNIT_MODIFIER:
1254                 seq_printf(seqf, "%d\n", nsensor->unit_modifier);
1255                 break;
1256
1257         case HP_WMI_PROPERTY_CURRENT_READING:
1258                 seq_printf(seqf, "%u\n", nsensor->current_reading);
1259                 break;
1260
1261         default:
1262                 return -EOPNOTSUPP;
1263         }
1264
1265         return 0;
1266 }
1267
1268 static int operational_status_show(struct seq_file *seqf, void *ignored)
1269 {
1270         return fungible_show(seqf, HP_WMI_PROPERTY_OPERATIONAL_STATUS);
1271 }
1272 DEFINE_SHOW_ATTRIBUTE(operational_status);
1273
1274 static int current_state_show(struct seq_file *seqf, void *ignored)
1275 {
1276         return fungible_show(seqf, HP_WMI_PROPERTY_CURRENT_STATE);
1277 }
1278 DEFINE_SHOW_ATTRIBUTE(current_state);
1279
1280 static int possible_states_show(struct seq_file *seqf, void *ignored)
1281 {
1282         struct hp_wmi_numeric_sensor *nsensor = seqf->private;
1283         u8 i;
1284
1285         for (i = 0; i < nsensor->size; i++)
1286                 seq_printf(seqf, "%s%s", i ? "," : "",
1287                            nsensor->possible_states[i]);
1288
1289         seq_puts(seqf, "\n");
1290
1291         return 0;
1292 }
1293 DEFINE_SHOW_ATTRIBUTE(possible_states);
1294
1295 static int unit_modifier_show(struct seq_file *seqf, void *ignored)
1296 {
1297         return fungible_show(seqf, HP_WMI_PROPERTY_UNIT_MODIFIER);
1298 }
1299 DEFINE_SHOW_ATTRIBUTE(unit_modifier);
1300
1301 static int current_reading_show(struct seq_file *seqf, void *ignored)
1302 {
1303         return fungible_show(seqf, HP_WMI_PROPERTY_CURRENT_READING);
1304 }
1305 DEFINE_SHOW_ATTRIBUTE(current_reading);
1306
1307 /* hp_wmi_devm_debugfs_remove - devm callback for debugfs cleanup */
1308 static void hp_wmi_devm_debugfs_remove(void *res)
1309 {
1310         debugfs_remove_recursive(res);
1311 }
1312
1313 /* hp_wmi_debugfs_init - create and populate debugfs directory tree */
1314 static void hp_wmi_debugfs_init(struct device *dev, struct hp_wmi_info *info,
1315                                 struct hp_wmi_platform_events *pevents,
1316                                 u8 icount, u8 pcount, bool is_new)
1317 {
1318         struct hp_wmi_numeric_sensor *nsensor;
1319         char buf[HP_WMI_MAX_STR_SIZE];
1320         struct dentry *debugfs;
1321         struct dentry *entries;
1322         struct dentry *dir;
1323         int err;
1324         u8 i;
1325
1326         /* dev_name() gives a not-very-friendly GUID for WMI devices. */
1327         scnprintf(buf, sizeof(buf), "hp-wmi-sensors-%u", dev->id);
1328
1329         debugfs = debugfs_create_dir(buf, NULL);
1330         if (IS_ERR(debugfs))
1331                 return;
1332
1333         err = devm_add_action_or_reset(dev, hp_wmi_devm_debugfs_remove,
1334                                        debugfs);
1335         if (err)
1336                 return;
1337
1338         entries = debugfs_create_dir("sensor", debugfs);
1339
1340         for (i = 0; i < icount; i++, info++) {
1341                 nsensor = &info->nsensor;
1342
1343                 scnprintf(buf, sizeof(buf), "%u", i);
1344                 dir = debugfs_create_dir(buf, entries);
1345
1346                 debugfs_create_file("name", 0444, dir,
1347                                     (void *)nsensor->name,
1348                                     &basic_string_fops);
1349
1350                 debugfs_create_file("description", 0444, dir,
1351                                     (void *)nsensor->description,
1352                                     &basic_string_fops);
1353
1354                 debugfs_create_u32("sensor_type", 0444, dir,
1355                                    &nsensor->sensor_type);
1356
1357                 debugfs_create_file("other_sensor_type", 0444, dir,
1358                                     (void *)nsensor->other_sensor_type,
1359                                     &basic_string_fops);
1360
1361                 debugfs_create_file("operational_status", 0444, dir,
1362                                     info, &operational_status_fops);
1363
1364                 debugfs_create_file("possible_states", 0444, dir,
1365                                     nsensor, &possible_states_fops);
1366
1367                 debugfs_create_file("current_state", 0444, dir,
1368                                     info, &current_state_fops);
1369
1370                 debugfs_create_u32("base_units", 0444, dir,
1371                                    &nsensor->base_units);
1372
1373                 debugfs_create_file("unit_modifier", 0444, dir,
1374                                     info, &unit_modifier_fops);
1375
1376                 debugfs_create_file("current_reading", 0444, dir,
1377                                     info, &current_reading_fops);
1378
1379                 if (is_new)
1380                         debugfs_create_u32("rate_units", 0444, dir,
1381                                            &nsensor->rate_units);
1382         }
1383
1384         if (!pcount)
1385                 return;
1386
1387         entries = debugfs_create_dir("platform_events", debugfs);
1388
1389         for (i = 0; i < pcount; i++, pevents++) {
1390                 scnprintf(buf, sizeof(buf), "%u", i);
1391                 dir = debugfs_create_dir(buf, entries);
1392
1393                 debugfs_create_file("name", 0444, dir,
1394                                     (void *)pevents->name,
1395                                     &basic_string_fops);
1396
1397                 debugfs_create_file("description", 0444, dir,
1398                                     (void *)pevents->description,
1399                                     &basic_string_fops);
1400
1401                 debugfs_create_file("source_namespace", 0444, dir,
1402                                     (void *)pevents->source_namespace,
1403                                     &basic_string_fops);
1404
1405                 debugfs_create_file("source_class", 0444, dir,
1406                                     (void *)pevents->source_class,
1407                                     &basic_string_fops);
1408
1409                 debugfs_create_u32("category", 0444, dir,
1410                                    &pevents->category);
1411
1412                 debugfs_create_u32("possible_severity", 0444, dir,
1413                                    &pevents->possible_severity);
1414
1415                 debugfs_create_u32("possible_status", 0444, dir,
1416                                    &pevents->possible_status);
1417         }
1418 }
1419
1420 static umode_t hp_wmi_hwmon_is_visible(const void *drvdata,
1421                                        enum hwmon_sensor_types type,
1422                                        u32 attr, int channel)
1423 {
1424         const struct hp_wmi_sensors *state = drvdata;
1425         const struct hp_wmi_info *info;
1426
1427         if (type == hwmon_intrusion)
1428                 return state->has_intrusion ? 0644 : 0;
1429
1430         if (!state->info_map[type] || !state->info_map[type][channel])
1431                 return 0;
1432
1433         info = state->info_map[type][channel];
1434
1435         if ((type == hwmon_temp && attr == hwmon_temp_alarm) ||
1436             (type == hwmon_fan  && attr == hwmon_fan_alarm))
1437                 return info->has_alarm ? 0444 : 0;
1438
1439         return 0444;
1440 }
1441
1442 static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
1443                              u32 attr, int channel, long *out_val)
1444 {
1445         struct hp_wmi_sensors *state = dev_get_drvdata(dev);
1446         const struct hp_wmi_numeric_sensor *nsensor;
1447         struct hp_wmi_info *info;
1448         int err;
1449
1450         if (type == hwmon_intrusion) {
1451                 *out_val = state->intrusion ? 1 : 0;
1452
1453                 return 0;
1454         }
1455
1456         info = state->info_map[type][channel];
1457
1458         if ((type == hwmon_temp && attr == hwmon_temp_alarm) ||
1459             (type == hwmon_fan  && attr == hwmon_fan_alarm)) {
1460                 *out_val = info->alarm ? 1 : 0;
1461                 info->alarm = false;
1462
1463                 return 0;
1464         }
1465
1466         nsensor = &info->nsensor;
1467
1468         err = hp_wmi_update_info(state, info);
1469         if (err)
1470                 return err;
1471
1472         if ((type == hwmon_temp && attr == hwmon_temp_fault) ||
1473             (type == hwmon_fan  && attr == hwmon_fan_fault))
1474                 *out_val = numeric_sensor_has_fault(nsensor);
1475         else
1476                 *out_val = info->cached_val;
1477
1478         return 0;
1479 }
1480
1481 static int hp_wmi_hwmon_read_string(struct device *dev,
1482                                     enum hwmon_sensor_types type, u32 attr,
1483                                     int channel, const char **out_str)
1484 {
1485         const struct hp_wmi_sensors *state = dev_get_drvdata(dev);
1486         const struct hp_wmi_info *info;
1487
1488         info = state->info_map[type][channel];
1489         *out_str = info->nsensor.name;
1490
1491         return 0;
1492 }
1493
1494 static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
1495                               u32 attr, int channel, long val)
1496 {
1497         struct hp_wmi_sensors *state = dev_get_drvdata(dev);
1498
1499         if (val)
1500                 return -EINVAL;
1501
1502         mutex_lock(&state->lock);
1503
1504         state->intrusion = false;
1505
1506         mutex_unlock(&state->lock);
1507
1508         return 0;
1509 }
1510
1511 static const struct hwmon_ops hp_wmi_hwmon_ops = {
1512         .is_visible  = hp_wmi_hwmon_is_visible,
1513         .read        = hp_wmi_hwmon_read,
1514         .read_string = hp_wmi_hwmon_read_string,
1515         .write       = hp_wmi_hwmon_write,
1516 };
1517
1518 static struct hwmon_chip_info hp_wmi_chip_info = {
1519         .ops         = &hp_wmi_hwmon_ops,
1520         .info        = NULL,
1521 };
1522
1523 static struct hp_wmi_info *match_fan_event(struct hp_wmi_sensors *state,
1524                                            const char *event_description)
1525 {
1526         struct hp_wmi_info **ptr_info = state->info_map[hwmon_fan];
1527         u8 fan_count = state->channel_count[hwmon_fan];
1528         struct hp_wmi_info *info;
1529         const char *name;
1530         u8 i;
1531
1532         /* Fan event has Description "X Speed". Sensor has Name "X[ Speed]". */
1533
1534         for (i = 0; i < fan_count; i++, ptr_info++) {
1535                 info = *ptr_info;
1536                 name = info->nsensor.name;
1537
1538                 if (strstr(event_description, name))
1539                         return info;
1540         }
1541
1542         return NULL;
1543 }
1544
1545 static u8 match_temp_events(struct hp_wmi_sensors *state,
1546                             const char *event_description,
1547                             struct hp_wmi_info *temp_info[])
1548 {
1549         struct hp_wmi_info **ptr_info = state->info_map[hwmon_temp];
1550         u8 temp_count = state->channel_count[hwmon_temp];
1551         struct hp_wmi_info *info;
1552         const char *name;
1553         u8 count = 0;
1554         bool is_cpu;
1555         bool is_sys;
1556         u8 i;
1557
1558         /* Description is either "CPU Thermal Index" or "Chassis Thermal Index". */
1559
1560         is_cpu = !strcmp(event_description, HP_WMI_PATTERN_CPU_TEMP);
1561         is_sys = !strcmp(event_description, HP_WMI_PATTERN_SYS_TEMP);
1562         if (!is_cpu && !is_sys)
1563                 return 0;
1564
1565         /*
1566          * CPU event: Match one sensor with Name either "CPU Thermal Index" or
1567          * "CPU Temperature", or multiple with Name(s) "CPU[#] Temperature".
1568          *
1569          * Chassis event: Match one sensor with Name either
1570          * "Chassis Thermal Index" or "System Ambient Temperature".
1571          */
1572
1573         for (i = 0; i < temp_count; i++, ptr_info++) {
1574                 info = *ptr_info;
1575                 name = info->nsensor.name;
1576
1577                 if ((is_cpu && (!strcmp(name, HP_WMI_PATTERN_CPU_TEMP) ||
1578                                 !strcmp(name, HP_WMI_PATTERN_CPU_TEMP2))) ||
1579                     (is_sys && (!strcmp(name, HP_WMI_PATTERN_SYS_TEMP) ||
1580                                 !strcmp(name, HP_WMI_PATTERN_SYS_TEMP2)))) {
1581                         temp_info[0] = info;
1582                         return 1;
1583                 }
1584
1585                 if (is_cpu && (strstr(name, HP_WMI_PATTERN_CPU) &&
1586                                strstr(name, HP_WMI_PATTERN_TEMP)))
1587                         temp_info[count++] = info;
1588         }
1589
1590         return count;
1591 }
1592
1593 /* hp_wmi_devm_debugfs_remove - devm callback for WMI event handler removal */
1594 static void hp_wmi_devm_notify_remove(void *ignored)
1595 {
1596         wmi_remove_notify_handler(HP_WMI_EVENT_GUID);
1597 }
1598
1599 /* hp_wmi_notify - WMI event notification handler */
1600 static void hp_wmi_notify(u32 value, void *context)
1601 {
1602         struct hp_wmi_info *temp_info[HP_WMI_MAX_INSTANCES] = {};
1603         struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
1604         struct hp_wmi_sensors *state = context;
1605         struct device *dev = &state->wdev->dev;
1606         struct hp_wmi_event event = {};
1607         struct hp_wmi_info *fan_info;
1608         union acpi_object *wobj;
1609         acpi_status err;
1610         int event_type;
1611         u8 count;
1612
1613         /*
1614          * The following warning may occur in the kernel log:
1615          *
1616          *   ACPI Warning: \_SB.WMID._WED: Return type mismatch -
1617          *     found Package, expected Integer/String/Buffer
1618          *
1619          * After using [4] to decode BMOF blobs found in [3], careless copying
1620          * of BIOS code seems the most likely explanation for this warning.
1621          * HP_WMI_EVENT_GUID refers to \\.\root\WMI\HPBIOS_BIOSEvent on
1622          * business-class systems, but it refers to \\.\root\WMI\hpqBEvnt on
1623          * non-business-class systems. Per the existing hp-wmi driver, it
1624          * looks like an instance of hpqBEvnt delivered as event data may
1625          * indeed take the form of a raw ACPI_BUFFER on non-business-class
1626          * systems ("may" because ASL shows some BIOSes do strange things).
1627          *
1628          * In any case, we can ignore this warning, because we always validate
1629          * the event data to ensure it is an ACPI_PACKAGE containing a
1630          * HPBIOS_BIOSEvent instance.
1631          */
1632
1633         mutex_lock(&state->lock);
1634
1635         err = wmi_get_event_data(value, &out);
1636         if (ACPI_FAILURE(err))
1637                 goto out_unlock;
1638
1639         wobj = out.pointer;
1640
1641         err = populate_event_from_wobj(dev, &event, wobj);
1642         if (err) {
1643                 dev_warn(dev, "Bad event data (ACPI type %d)\n", wobj->type);
1644                 goto out_free_wobj;
1645         }
1646
1647         event_type = classify_event(event.name, event.category);
1648         switch (event_type) {
1649         case HP_WMI_TYPE_AIR_FLOW:
1650                 fan_info = match_fan_event(state, event.description);
1651                 if (fan_info)
1652                         fan_info->alarm = true;
1653                 break;
1654
1655         case HP_WMI_TYPE_INTRUSION:
1656                 state->intrusion = true;
1657                 break;
1658
1659         case HP_WMI_TYPE_TEMPERATURE:
1660                 count = match_temp_events(state, event.description, temp_info);
1661                 while (count)
1662                         temp_info[--count]->alarm = true;
1663                 break;
1664
1665         default:
1666                 break;
1667         }
1668
1669 out_free_wobj:
1670         kfree(wobj);
1671
1672         devm_kfree(dev, event.name);
1673         devm_kfree(dev, event.description);
1674
1675 out_unlock:
1676         mutex_unlock(&state->lock);
1677 }
1678
1679 static int init_platform_events(struct device *dev,
1680                                 struct hp_wmi_platform_events **out_pevents,
1681                                 u8 *out_pcount)
1682 {
1683         struct hp_wmi_platform_events *pevents_arr;
1684         struct hp_wmi_platform_events *pevents;
1685         union acpi_object *wobj;
1686         u8 count;
1687         int err;
1688         u8 i;
1689
1690         count = hp_wmi_wobj_instance_count(HP_WMI_PLATFORM_EVENTS_GUID);
1691         if (!count) {
1692                 *out_pcount = 0;
1693
1694                 dev_dbg(dev, "No platform events\n");
1695
1696                 return 0;
1697         }
1698
1699         pevents_arr = devm_kcalloc(dev, count, sizeof(*pevents), GFP_KERNEL);
1700         if (!pevents_arr)
1701                 return -ENOMEM;
1702
1703         for (i = 0, pevents = pevents_arr; i < count; i++, pevents++) {
1704                 wobj = hp_wmi_get_wobj(HP_WMI_PLATFORM_EVENTS_GUID, i);
1705                 if (!wobj)
1706                         return -EIO;
1707
1708                 err = populate_platform_events_from_wobj(dev, pevents, wobj);
1709
1710                 kfree(wobj);
1711
1712                 if (err)
1713                         return err;
1714         }
1715
1716         *out_pevents = pevents_arr;
1717         *out_pcount = count;
1718
1719         dev_dbg(dev, "Found %u platform events\n", count);
1720
1721         return 0;
1722 }
1723
1724 static int init_numeric_sensors(struct hp_wmi_sensors *state,
1725                                 struct hp_wmi_info *connected[],
1726                                 struct hp_wmi_info **out_info,
1727                                 u8 *out_icount, u8 *out_count,
1728                                 bool *out_is_new)
1729 {
1730         struct hp_wmi_info ***info_map = state->info_map;
1731         u8 *channel_count = state->channel_count;
1732         struct device *dev = &state->wdev->dev;
1733         struct hp_wmi_numeric_sensor *nsensor;
1734         u8 channel_index[hwmon_max] = {};
1735         enum hwmon_sensor_types type;
1736         struct hp_wmi_info *info_arr;
1737         struct hp_wmi_info *info;
1738         union acpi_object *wobj;
1739         u8 count = 0;
1740         bool is_new;
1741         u8 icount;
1742         int wtype;
1743         int err;
1744         u8 c;
1745         u8 i;
1746
1747         icount = hp_wmi_wobj_instance_count(HP_WMI_NUMERIC_SENSOR_GUID);
1748         if (!icount)
1749                 return -ENODATA;
1750
1751         info_arr = devm_kcalloc(dev, icount, sizeof(*info), GFP_KERNEL);
1752         if (!info_arr)
1753                 return -ENOMEM;
1754
1755         for (i = 0, info = info_arr; i < icount; i++, info++) {
1756                 wobj = hp_wmi_get_wobj(HP_WMI_NUMERIC_SENSOR_GUID, i);
1757                 if (!wobj)
1758                         return -EIO;
1759
1760                 info->instance = i;
1761                 info->state = state;
1762                 nsensor = &info->nsensor;
1763
1764                 err = populate_numeric_sensor_from_wobj(dev, nsensor, wobj,
1765                                                         &is_new);
1766
1767                 kfree(wobj);
1768
1769                 if (err)
1770                         return err;
1771
1772                 if (!numeric_sensor_is_connected(nsensor))
1773                         continue;
1774
1775                 wtype = classify_numeric_sensor(nsensor);
1776                 if (wtype < 0)
1777                         continue;
1778
1779                 type = hp_wmi_hwmon_type_map[wtype];
1780
1781                 channel_count[type]++;
1782
1783                 info->type = type;
1784
1785                 interpret_info(info);
1786
1787                 connected[count++] = info;
1788         }
1789
1790         dev_dbg(dev, "Found %u sensors (%u connected)\n", i, count);
1791
1792         for (i = 0; i < count; i++) {
1793                 info = connected[i];
1794                 type = info->type;
1795                 c = channel_index[type]++;
1796
1797                 if (!info_map[type]) {
1798                         info_map[type] = devm_kcalloc(dev, channel_count[type],
1799                                                       sizeof(*info_map),
1800                                                       GFP_KERNEL);
1801                         if (!info_map[type])
1802                                 return -ENOMEM;
1803                 }
1804
1805                 info_map[type][c] = info;
1806         }
1807
1808         *out_info = info_arr;
1809         *out_icount = icount;
1810         *out_count = count;
1811         *out_is_new = is_new;
1812
1813         return 0;
1814 }
1815
1816 static bool find_event_attributes(struct hp_wmi_sensors *state,
1817                                   struct hp_wmi_platform_events *pevents,
1818                                   u8 pevents_count)
1819 {
1820         /*
1821          * The existence of this HPBIOS_PlatformEvents instance:
1822          *
1823          *   {
1824          *     Name = "Rear Chassis Fan0 Stall";
1825          *     Description = "Rear Chassis Fan0 Speed";
1826          *     Category = 3;           // "Sensor"
1827          *     PossibleSeverity = 25;  // "Critical Failure"
1828          *     PossibleStatus = 5;     // "Predictive Failure"
1829          *     [...]
1830          *   }
1831          *
1832          * means that this HPBIOS_BIOSEvent instance may occur:
1833          *
1834          *   {
1835          *     Name = "Rear Chassis Fan0 Stall";
1836          *     Description = "Rear Chassis Fan0 Speed";
1837          *     Category = 3;           // "Sensor"
1838          *     Severity = 25;          // "Critical Failure"
1839          *     Status = 5;             // "Predictive Failure"
1840          *   }
1841          *
1842          * After the event occurs (e.g. because the fan was unplugged),
1843          * polling the related HPBIOS_BIOSNumericSensor instance gives:
1844          *
1845          *   {
1846          *      Name = "Rear Chassis Fan0";
1847          *      Description = "Reports rear chassis fan0 speed";
1848          *      OperationalStatus = 5; // "Predictive Failure", was 3 ("OK")
1849          *      CurrentReading = 0;
1850          *      [...]
1851          *   }
1852          *
1853          * In this example, the hwmon fan channel for "Rear Chassis Fan0"
1854          * should support the alarm flag and have it be set if the related
1855          * HPBIOS_BIOSEvent instance occurs.
1856          *
1857          * In addition to fan events, temperature (CPU/chassis) and intrusion
1858          * events are relevant to hwmon [2]. Note that much information in [2]
1859          * is unreliable; it is referenced in addition to ACPI dumps [3] merely
1860          * to support the conclusion that sensor and event names/descriptions
1861          * are systematic enough to allow this driver to match them.
1862          *
1863          * Complications and limitations:
1864          *
1865          * - Strings are freeform and may vary, cf. sensor Name "CPU0 Fan"
1866          *   on a Z420 vs. "CPU Fan Speed" on an EliteOne 800 G1.
1867          * - Leading/trailing whitespace is a rare but real possibility [3].
1868          * - The HPBIOS_PlatformEvents object may not exist or its instances
1869          *   may show that the system only has e.g. BIOS setting-related
1870          *   events (cf. the ProBook 4540s and ProBook 470 G0 [3]).
1871          */
1872
1873         struct hp_wmi_info *temp_info[HP_WMI_MAX_INSTANCES] = {};
1874         const char *event_description;
1875         struct hp_wmi_info *fan_info;
1876         bool has_events = false;
1877         const char *event_name;
1878         u32 event_category;
1879         int event_type;
1880         u8 count;
1881         u8 i;
1882
1883         for (i = 0; i < pevents_count; i++, pevents++) {
1884                 event_name = pevents->name;
1885                 event_description = pevents->description;
1886                 event_category = pevents->category;
1887
1888                 event_type = classify_event(event_name, event_category);
1889                 switch (event_type) {
1890                 case HP_WMI_TYPE_AIR_FLOW:
1891                         fan_info = match_fan_event(state, event_description);
1892                         if (!fan_info)
1893                                 break;
1894
1895                         fan_info->has_alarm = true;
1896                         has_events = true;
1897                         break;
1898
1899                 case HP_WMI_TYPE_INTRUSION:
1900                         state->has_intrusion = true;
1901                         has_events = true;
1902                         break;
1903
1904                 case HP_WMI_TYPE_TEMPERATURE:
1905                         count = match_temp_events(state, event_description,
1906                                                   temp_info);
1907                         if (!count)
1908                                 break;
1909
1910                         while (count)
1911                                 temp_info[--count]->has_alarm = true;
1912                         has_events = true;
1913                         break;
1914
1915                 default:
1916                         break;
1917                 }
1918         }
1919
1920         return has_events;
1921 }
1922
1923 static int make_chip_info(struct hp_wmi_sensors *state, bool has_events)
1924 {
1925         const struct hwmon_channel_info **ptr_channel_info;
1926         struct hp_wmi_info ***info_map = state->info_map;
1927         u8 *channel_count = state->channel_count;
1928         struct hwmon_channel_info *channel_info;
1929         struct device *dev = &state->wdev->dev;
1930         enum hwmon_sensor_types type;
1931         u8 type_count = 0;
1932         u32 *config;
1933         u32 attr;
1934         u8 count;
1935         u8 i;
1936
1937         if (channel_count[hwmon_temp])
1938                 channel_count[hwmon_chip] = 1;
1939
1940         if (has_events && state->has_intrusion)
1941                 channel_count[hwmon_intrusion] = 1;
1942
1943         for (type = hwmon_chip; type < hwmon_max; type++)
1944                 if (channel_count[type])
1945                         type_count++;
1946
1947         channel_info = devm_kcalloc(dev, type_count,
1948                                     sizeof(*channel_info), GFP_KERNEL);
1949         if (!channel_info)
1950                 return -ENOMEM;
1951
1952         ptr_channel_info = devm_kcalloc(dev, type_count + 1,
1953                                         sizeof(*ptr_channel_info), GFP_KERNEL);
1954         if (!ptr_channel_info)
1955                 return -ENOMEM;
1956
1957         hp_wmi_chip_info.info = ptr_channel_info;
1958
1959         for (type = hwmon_chip; type < hwmon_max; type++) {
1960                 count = channel_count[type];
1961                 if (!count)
1962                         continue;
1963
1964                 config = devm_kcalloc(dev, count + 1,
1965                                       sizeof(*config), GFP_KERNEL);
1966                 if (!config)
1967                         return -ENOMEM;
1968
1969                 attr = hp_wmi_hwmon_attributes[type];
1970                 channel_info->type = type;
1971                 channel_info->config = config;
1972                 memset32(config, attr, count);
1973
1974                 *ptr_channel_info++ = channel_info++;
1975
1976                 if (!has_events || (type != hwmon_temp && type != hwmon_fan))
1977                         continue;
1978
1979                 attr = type == hwmon_temp ? HWMON_T_ALARM : HWMON_F_ALARM;
1980
1981                 for (i = 0; i < count; i++)
1982                         if (info_map[type][i]->has_alarm)
1983                                 config[i] |= attr;
1984         }
1985
1986         return 0;
1987 }
1988
1989 static bool add_event_handler(struct hp_wmi_sensors *state)
1990 {
1991         struct device *dev = &state->wdev->dev;
1992         int err;
1993
1994         err = wmi_install_notify_handler(HP_WMI_EVENT_GUID,
1995                                          hp_wmi_notify, state);
1996         if (err) {
1997                 dev_info(dev, "Failed to subscribe to WMI event\n");
1998                 return false;
1999         }
2000
2001         err = devm_add_action_or_reset(dev, hp_wmi_devm_notify_remove, NULL);
2002         if (err)
2003                 return false;
2004
2005         return true;
2006 }
2007
2008 static int hp_wmi_sensors_init(struct hp_wmi_sensors *state)
2009 {
2010         struct hp_wmi_info *connected[HP_WMI_MAX_INSTANCES];
2011         struct hp_wmi_platform_events *pevents = NULL;
2012         struct device *dev = &state->wdev->dev;
2013         struct hp_wmi_info *info;
2014         struct device *hwdev;
2015         bool has_events;
2016         bool is_new;
2017         u8 icount;
2018         u8 pcount;
2019         u8 count;
2020         int err;
2021
2022         err = init_platform_events(dev, &pevents, &pcount);
2023         if (err)
2024                 return err;
2025
2026         err = init_numeric_sensors(state, connected, &info,
2027                                    &icount, &count, &is_new);
2028         if (err)
2029                 return err;
2030
2031         if (IS_ENABLED(CONFIG_DEBUG_FS))
2032                 hp_wmi_debugfs_init(dev, info, pevents, icount, pcount, is_new);
2033
2034         if (!count)
2035                 return 0;       /* No connected sensors; debugfs only. */
2036
2037         has_events = find_event_attributes(state, pevents, pcount);
2038
2039         /* Survive failure to install WMI event handler. */
2040         if (has_events && !add_event_handler(state))
2041                 has_events = false;
2042
2043         err = make_chip_info(state, has_events);
2044         if (err)
2045                 return err;
2046
2047         hwdev = devm_hwmon_device_register_with_info(dev, "hp_wmi_sensors",
2048                                                      state, &hp_wmi_chip_info,
2049                                                      NULL);
2050         return PTR_ERR_OR_ZERO(hwdev);
2051 }
2052
2053 static int hp_wmi_sensors_probe(struct wmi_device *wdev, const void *context)
2054 {
2055         struct device *dev = &wdev->dev;
2056         struct hp_wmi_sensors *state;
2057
2058         state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
2059         if (!state)
2060                 return -ENOMEM;
2061
2062         state->wdev = wdev;
2063
2064         mutex_init(&state->lock);
2065
2066         dev_set_drvdata(dev, state);
2067
2068         return hp_wmi_sensors_init(state);
2069 }
2070
2071 static const struct wmi_device_id hp_wmi_sensors_id_table[] = {
2072         { HP_WMI_NUMERIC_SENSOR_GUID, NULL },
2073         {},
2074 };
2075
2076 static struct wmi_driver hp_wmi_sensors_driver = {
2077         .driver   = { .name = "hp-wmi-sensors" },
2078         .id_table = hp_wmi_sensors_id_table,
2079         .probe    = hp_wmi_sensors_probe,
2080 };
2081 module_wmi_driver(hp_wmi_sensors_driver);
2082
2083 MODULE_AUTHOR("James Seo <james@equiv.tech>");
2084 MODULE_DESCRIPTION("HP WMI Sensors driver");
2085 MODULE_LICENSE("GPL");