xref: /linux/drivers/hwmon/hp-wmi-sensors.c (revision d24e3bf4c5484b29432837269ded253480fa8928)
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 
is_raw_wmi_string(const u8 * pointer,u32 length)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 
convert_raw_wmi_string(const u8 * buf)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 */
hp_wmi_strdup(struct device * dev,const char * src)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 */
hp_wmi_wstrdup(struct device * dev,const u8 * buf)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  */
hp_wmi_get_wobj(const char * guid,u8 instance)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 */
hp_wmi_wobj_instance_count(const char * guid)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 
check_wobj(const union acpi_object * wobj,const acpi_object_type property_map[],int last_prop)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 == ACPI_TYPE_BUFFER &&
530 		    is_raw_wmi_string(elements[prop].buffer.pointer,
531 				      elements[prop].buffer.length))
532 			type = ACPI_TYPE_STRING;
533 		if (type != valid_type)
534 			return -EINVAL;
535 	}
536 
537 	return 0;
538 }
539 
extract_acpi_value(struct device * dev,union acpi_object * element,acpi_object_type type,u32 * out_value,char ** out_string)540 static int extract_acpi_value(struct device *dev,
541 			      union acpi_object *element,
542 			      acpi_object_type type,
543 			      u32 *out_value, char **out_string)
544 {
545 	switch (type) {
546 	case ACPI_TYPE_INTEGER:
547 		*out_value = element->integer.value;
548 		break;
549 
550 	case ACPI_TYPE_STRING:
551 		*out_string = element->type == ACPI_TYPE_BUFFER ?
552 			hp_wmi_wstrdup(dev, element->buffer.pointer) :
553 			hp_wmi_strdup(dev, strim(element->string.pointer));
554 		if (!*out_string)
555 			return -ENOMEM;
556 		break;
557 
558 	default:
559 		return -EINVAL;
560 	}
561 
562 	return 0;
563 }
564 
565 /*
566  * check_numeric_sensor_wobj - validate a HPBIOS_BIOSNumericSensor instance
567  * @wobj: pointer to WMI object instance to check
568  * @out_size: out pointer to count of possible states
569  * @out_is_new: out pointer to whether this is a "new" variant object
570  *
571  * Returns 0 on success, or a negative error code on error.
572  */
check_numeric_sensor_wobj(const union acpi_object * wobj,u8 * out_size,bool * out_is_new)573 static int check_numeric_sensor_wobj(const union acpi_object *wobj,
574 				     u8 *out_size, bool *out_is_new)
575 {
576 	acpi_object_type type = wobj->type;
577 	int prop = HP_WMI_PROPERTY_NAME;
578 	acpi_object_type valid_type;
579 	union acpi_object *elements;
580 	union acpi_object *element;
581 	u32 elem_count;
582 	int last_prop;
583 	bool is_new;
584 	u8 count;
585 	u32 j;
586 	u32 i;
587 
588 	if (type != ACPI_TYPE_PACKAGE)
589 		return -EINVAL;
590 
591 	/*
592 	 * elements is a variable-length array of ACPI objects, one for
593 	 * each property of the WMI object instance, except that the
594 	 * strings in PossibleStates[] are flattened into this array
595 	 * as if each individual string were a property by itself.
596 	 */
597 	elements = wobj->package.elements;
598 
599 	elem_count = wobj->package.count;
600 	if (elem_count <= HP_WMI_PROPERTY_SIZE ||
601 	    elem_count > HP_WMI_MAX_PROPERTIES)
602 		return -EINVAL;
603 
604 	element = &elements[HP_WMI_PROPERTY_SIZE];
605 	type = element->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_BUFFER:
613 		if (!is_raw_wmi_string(element->buffer.pointer,
614 				       element->buffer.length))
615 			return -EINVAL;
616 		fallthrough;
617 
618 	case ACPI_TYPE_STRING:
619 		is_new = false;
620 		last_prop = HP_WMI_PROPERTY_CURRENT_READING;
621 		break;
622 
623 	default:
624 		return -EINVAL;
625 	}
626 
627 	/*
628 	 * In general, the count of PossibleStates[] must be > 0.
629 	 * Also, the old variant lacks the Size property, so we may need to
630 	 * reduce the value of last_prop by 1 when doing arithmetic with it.
631 	 */
632 	if (elem_count < last_prop - !is_new + 1)
633 		return -EINVAL;
634 
635 	count = elem_count - (last_prop - !is_new);
636 
637 	for (i = 0; i < elem_count && prop <= last_prop; i++, prop++) {
638 		type = elements[i].type;
639 		valid_type = hp_wmi_property_map[prop];
640 		if (type == ACPI_TYPE_BUFFER &&
641 		    is_raw_wmi_string(elements[i].buffer.pointer,
642 				      elements[i].buffer.length))
643 			type = ACPI_TYPE_STRING;
644 		if (type != valid_type)
645 			return -EINVAL;
646 
647 		switch (prop) {
648 		case HP_WMI_PROPERTY_OPERATIONAL_STATUS:
649 			/* Old variant: CurrentState follows OperationalStatus. */
650 			if (!is_new)
651 				prop = HP_WMI_PROPERTY_CURRENT_STATE - 1;
652 			break;
653 
654 		case HP_WMI_PROPERTY_SIZE:
655 			/* New variant: Size == count of PossibleStates[]. */
656 			if (count != elements[i].integer.value)
657 				return -EINVAL;
658 			break;
659 
660 		case HP_WMI_PROPERTY_POSSIBLE_STATES:
661 			/* PossibleStates[0] has already been type-checked. */
662 			for (j = 0; i + 1 < elem_count && j + 1 < count; j++) {
663 				type = elements[++i].type;
664 				if (type == ACPI_TYPE_BUFFER &&
665 				    is_raw_wmi_string(elements[i].buffer.pointer,
666 						      elements[i].buffer.length))
667 					type = ACPI_TYPE_STRING;
668 				if (type != valid_type)
669 					return -EINVAL;
670 			}
671 
672 			/* Old variant: BaseUnits follows PossibleStates[]. */
673 			if (!is_new)
674 				prop = HP_WMI_PROPERTY_BASE_UNITS - 1;
675 			break;
676 
677 		case HP_WMI_PROPERTY_CURRENT_STATE:
678 			/* Old variant: PossibleStates[] follows CurrentState. */
679 			if (!is_new)
680 				prop = HP_WMI_PROPERTY_POSSIBLE_STATES - 1;
681 			break;
682 		}
683 	}
684 
685 	if (prop != last_prop + 1)
686 		return -EINVAL;
687 
688 	*out_size = count;
689 	*out_is_new = is_new;
690 
691 	return 0;
692 }
693 
694 static int
numeric_sensor_is_connected(const struct hp_wmi_numeric_sensor * nsensor)695 numeric_sensor_is_connected(const struct hp_wmi_numeric_sensor *nsensor)
696 {
697 	u32 operational_status = nsensor->operational_status;
698 
699 	return operational_status != HP_WMI_STATUS_NO_CONTACT;
700 }
701 
numeric_sensor_has_fault(const struct hp_wmi_numeric_sensor * nsensor)702 static int numeric_sensor_has_fault(const struct hp_wmi_numeric_sensor *nsensor)
703 {
704 	u32 operational_status = nsensor->operational_status;
705 
706 	switch (operational_status) {
707 	case HP_WMI_STATUS_DEGRADED:
708 	case HP_WMI_STATUS_STRESSED:		/* e.g. Overload, overtemp. */
709 	case HP_WMI_STATUS_PREDICTIVE_FAILURE:	/* e.g. Fan removed. */
710 	case HP_WMI_STATUS_ERROR:
711 	case HP_WMI_STATUS_NON_RECOVERABLE_ERROR:
712 	case HP_WMI_STATUS_NO_CONTACT:
713 	case HP_WMI_STATUS_LOST_COMMUNICATION:
714 	case HP_WMI_STATUS_ABORTED:
715 	case HP_WMI_STATUS_SUPPORTING_ENTITY_IN_ERROR:
716 
717 	/* Assume combination by addition; bitwise OR doesn't make sense. */
718 	case HP_WMI_STATUS_COMPLETED + HP_WMI_STATUS_DEGRADED:
719 	case HP_WMI_STATUS_COMPLETED + HP_WMI_STATUS_ERROR:
720 		return true;
721 	}
722 
723 	return false;
724 }
725 
726 /* scale_numeric_sensor - scale sensor reading for hwmon */
scale_numeric_sensor(const struct hp_wmi_numeric_sensor * nsensor)727 static long scale_numeric_sensor(const struct hp_wmi_numeric_sensor *nsensor)
728 {
729 	u32 current_reading = nsensor->current_reading;
730 	s32 unit_modifier = nsensor->unit_modifier;
731 	u32 sensor_type = nsensor->sensor_type;
732 	u32 base_units = nsensor->base_units;
733 	s32 target_modifier;
734 	long val;
735 
736 	/* Fan readings are in RPM units; others are in milliunits. */
737 	target_modifier = sensor_type == HP_WMI_TYPE_AIR_FLOW ? 0 : -3;
738 
739 	val = current_reading;
740 
741 	for (; unit_modifier < target_modifier; unit_modifier++)
742 		val = DIV_ROUND_CLOSEST(val, 10);
743 
744 	for (; unit_modifier > target_modifier; unit_modifier--) {
745 		if (val > LONG_MAX / 10) {
746 			val = LONG_MAX;
747 			break;
748 		}
749 		val *= 10;
750 	}
751 
752 	if (sensor_type == HP_WMI_TYPE_TEMPERATURE) {
753 		switch (base_units) {
754 		case HP_WMI_UNITS_DEGREES_F:
755 			val -= MILLI * 32;
756 			val = val <= LONG_MAX / 5 ?
757 				      DIV_ROUND_CLOSEST(val * 5, 9) :
758 				      DIV_ROUND_CLOSEST(val, 9) * 5;
759 			break;
760 
761 		case HP_WMI_UNITS_DEGREES_K:
762 			val = milli_kelvin_to_millicelsius(val);
763 			break;
764 		}
765 	}
766 
767 	return val;
768 }
769 
770 /*
771  * classify_numeric_sensor - classify a numeric sensor
772  * @nsensor: pointer to numeric sensor struct
773  *
774  * Returns an enum hp_wmi_type value on success,
775  * or a negative value if the sensor type is unsupported.
776  */
classify_numeric_sensor(const struct hp_wmi_numeric_sensor * nsensor)777 static int classify_numeric_sensor(const struct hp_wmi_numeric_sensor *nsensor)
778 {
779 	u32 sensor_type = nsensor->sensor_type;
780 	u32 base_units = nsensor->base_units;
781 	const char *name = nsensor->name;
782 
783 	switch (sensor_type) {
784 	case HP_WMI_TYPE_TEMPERATURE:
785 		/*
786 		 * Some systems have sensors named "X Thermal Index" in "Other"
787 		 * units. Tested CPU sensor examples were found to be in °C,
788 		 * albeit perhaps "differently" accurate; e.g. readings were
789 		 * reliably -6°C vs. coretemp on a HP Compaq Elite 8300, and
790 		 * +8°C on an EliteOne G1 800. But this is still within the
791 		 * realm of plausibility for cheaply implemented motherboard
792 		 * sensors, and chassis readings were about as expected.
793 		 */
794 		if ((base_units == HP_WMI_UNITS_OTHER &&
795 		     strstr(name, HP_WMI_PATTERN_TEMP_SENSOR)) ||
796 		    base_units == HP_WMI_UNITS_DEGREES_C ||
797 		    base_units == HP_WMI_UNITS_DEGREES_F ||
798 		    base_units == HP_WMI_UNITS_DEGREES_K)
799 			return HP_WMI_TYPE_TEMPERATURE;
800 		break;
801 
802 	case HP_WMI_TYPE_VOLTAGE:
803 		if (base_units == HP_WMI_UNITS_VOLTS)
804 			return HP_WMI_TYPE_VOLTAGE;
805 		break;
806 
807 	case HP_WMI_TYPE_CURRENT:
808 		if (base_units == HP_WMI_UNITS_AMPS)
809 			return HP_WMI_TYPE_CURRENT;
810 		break;
811 
812 	case HP_WMI_TYPE_AIR_FLOW:
813 		/*
814 		 * Strangely, HP considers fan RPM sensor type to be
815 		 * "Air Flow" instead of the more intuitive "Tachometer".
816 		 */
817 		if (base_units == HP_WMI_UNITS_RPM)
818 			return HP_WMI_TYPE_AIR_FLOW;
819 		break;
820 	}
821 
822 	return -EINVAL;
823 }
824 
825 static int
populate_numeric_sensor_from_wobj(struct device * dev,struct hp_wmi_numeric_sensor * nsensor,union acpi_object * wobj,bool * out_is_new)826 populate_numeric_sensor_from_wobj(struct device *dev,
827 				  struct hp_wmi_numeric_sensor *nsensor,
828 				  union acpi_object *wobj, bool *out_is_new)
829 {
830 	int last_prop = HP_WMI_PROPERTY_RATE_UNITS;
831 	int prop = HP_WMI_PROPERTY_NAME;
832 	const char **possible_states;
833 	union acpi_object *element;
834 	acpi_object_type type;
835 	char *string;
836 	bool is_new;
837 	u32 value;
838 	u8 size;
839 	int err;
840 
841 	err = check_numeric_sensor_wobj(wobj, &size, &is_new);
842 	if (err)
843 		return err;
844 
845 	possible_states = devm_kcalloc(dev, size, sizeof(*possible_states),
846 				       GFP_KERNEL);
847 	if (!possible_states)
848 		return -ENOMEM;
849 
850 	element = wobj->package.elements;
851 	nsensor->possible_states = possible_states;
852 	nsensor->size = size;
853 
854 	if (!is_new)
855 		last_prop = HP_WMI_PROPERTY_CURRENT_READING;
856 
857 	for (; prop <= last_prop; prop++) {
858 		type = hp_wmi_property_map[prop];
859 
860 		err = extract_acpi_value(dev, element, type, &value, &string);
861 		if (err)
862 			return err;
863 
864 		element++;
865 
866 		switch (prop) {
867 		case HP_WMI_PROPERTY_NAME:
868 			nsensor->name = string;
869 			break;
870 
871 		case HP_WMI_PROPERTY_DESCRIPTION:
872 			nsensor->description = string;
873 			break;
874 
875 		case HP_WMI_PROPERTY_SENSOR_TYPE:
876 			if (value > HP_WMI_TYPE_AIR_FLOW)
877 				return -EINVAL;
878 
879 			nsensor->sensor_type = value;
880 			break;
881 
882 		case HP_WMI_PROPERTY_OTHER_SENSOR_TYPE:
883 			nsensor->other_sensor_type = string;
884 			break;
885 
886 		case HP_WMI_PROPERTY_OPERATIONAL_STATUS:
887 			nsensor->operational_status = value;
888 
889 			/* Old variant: CurrentState follows OperationalStatus. */
890 			if (!is_new)
891 				prop = HP_WMI_PROPERTY_CURRENT_STATE - 1;
892 			break;
893 
894 		case HP_WMI_PROPERTY_SIZE:
895 			break;			/* Already set. */
896 
897 		case HP_WMI_PROPERTY_POSSIBLE_STATES:
898 			*possible_states++ = string;
899 			if (--size)
900 				prop--;
901 
902 			/* Old variant: BaseUnits follows PossibleStates[]. */
903 			if (!is_new && !size)
904 				prop = HP_WMI_PROPERTY_BASE_UNITS - 1;
905 			break;
906 
907 		case HP_WMI_PROPERTY_CURRENT_STATE:
908 			nsensor->current_state = string;
909 
910 			/* Old variant: PossibleStates[] follows CurrentState. */
911 			if (!is_new)
912 				prop = HP_WMI_PROPERTY_POSSIBLE_STATES - 1;
913 			break;
914 
915 		case HP_WMI_PROPERTY_BASE_UNITS:
916 			nsensor->base_units = value;
917 			break;
918 
919 		case HP_WMI_PROPERTY_UNIT_MODIFIER:
920 			/* UnitModifier is signed. */
921 			nsensor->unit_modifier = (s32)value;
922 			break;
923 
924 		case HP_WMI_PROPERTY_CURRENT_READING:
925 			nsensor->current_reading = value;
926 			break;
927 
928 		case HP_WMI_PROPERTY_RATE_UNITS:
929 			nsensor->rate_units = value;
930 			break;
931 
932 		default:
933 			return -EINVAL;
934 		}
935 	}
936 
937 	*out_is_new = is_new;
938 
939 	return 0;
940 }
941 
942 /* update_numeric_sensor_from_wobj - update fungible sensor properties */
943 static void
update_numeric_sensor_from_wobj(struct device * dev,struct hp_wmi_numeric_sensor * nsensor,const union acpi_object * wobj)944 update_numeric_sensor_from_wobj(struct device *dev,
945 				struct hp_wmi_numeric_sensor *nsensor,
946 				const union acpi_object *wobj)
947 {
948 	const union acpi_object *elements;
949 	const union acpi_object *element;
950 	const char *new_string;
951 	char *trimmed;
952 	char *string;
953 	bool is_new;
954 	int offset;
955 	u8 size;
956 	int err;
957 
958 	err = check_numeric_sensor_wobj(wobj, &size, &is_new);
959 	if (err)
960 		return;
961 
962 	elements = wobj->package.elements;
963 
964 	element = &elements[HP_WMI_PROPERTY_OPERATIONAL_STATUS];
965 	nsensor->operational_status = element->integer.value;
966 
967 	/*
968 	 * In general, an index offset is needed after PossibleStates[0].
969 	 * On a new variant, CurrentState is after PossibleStates[]. This is
970 	 * not the case on an old variant, but we still need to offset the
971 	 * read because CurrentState is where Size would be on a new variant.
972 	 */
973 	offset = is_new ? size - 1 : -2;
974 
975 	element = &elements[HP_WMI_PROPERTY_CURRENT_STATE + offset];
976 	string = element->type == ACPI_TYPE_BUFFER ?
977 		convert_raw_wmi_string(element->buffer.pointer) :
978 		element->string.pointer;
979 
980 	if (string) {
981 		trimmed = strim(string);
982 		if (strcmp(trimmed, nsensor->current_state)) {
983 			new_string = hp_wmi_strdup(dev, trimmed);
984 			if (new_string) {
985 				devm_kfree(dev, nsensor->current_state);
986 				nsensor->current_state = new_string;
987 			}
988 		}
989 		if (element->type == ACPI_TYPE_BUFFER)
990 			kfree(string);
991 	}
992 
993 	/* Old variant: -2 (not -1) because it lacks the Size property. */
994 	if (!is_new)
995 		offset = (int)size - 2;	/* size is > 0, i.e. may be 1. */
996 
997 	element = &elements[HP_WMI_PROPERTY_UNIT_MODIFIER + offset];
998 	nsensor->unit_modifier = (s32)element->integer.value;
999 
1000 	element = &elements[HP_WMI_PROPERTY_CURRENT_READING + offset];
1001 	nsensor->current_reading = element->integer.value;
1002 }
1003 
1004 /*
1005  * check_platform_events_wobj - validate a HPBIOS_PlatformEvents instance
1006  * @wobj: pointer to WMI object instance to check
1007  *
1008  * Returns 0 on success, or a negative error code on error.
1009  */
check_platform_events_wobj(const union acpi_object * wobj)1010 static int check_platform_events_wobj(const union acpi_object *wobj)
1011 {
1012 	return check_wobj(wobj, hp_wmi_platform_events_property_map,
1013 			  HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS);
1014 }
1015 
1016 static int
populate_platform_events_from_wobj(struct device * dev,struct hp_wmi_platform_events * pevents,union acpi_object * wobj)1017 populate_platform_events_from_wobj(struct device *dev,
1018 				   struct hp_wmi_platform_events *pevents,
1019 				   union acpi_object *wobj)
1020 {
1021 	int last_prop = HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS;
1022 	int prop = HP_WMI_PLATFORM_EVENTS_PROPERTY_NAME;
1023 	union acpi_object *element;
1024 	acpi_object_type type;
1025 	char *string;
1026 	u32 value;
1027 	int err;
1028 
1029 	err = check_platform_events_wobj(wobj);
1030 	if (err)
1031 		return err;
1032 
1033 	element = wobj->package.elements;
1034 
1035 	for (; prop <= last_prop; prop++, element++) {
1036 		type = hp_wmi_platform_events_property_map[prop];
1037 
1038 		err = extract_acpi_value(dev, element, type, &value, &string);
1039 		if (err)
1040 			return err;
1041 
1042 		switch (prop) {
1043 		case HP_WMI_PLATFORM_EVENTS_PROPERTY_NAME:
1044 			pevents->name = string;
1045 			break;
1046 
1047 		case HP_WMI_PLATFORM_EVENTS_PROPERTY_DESCRIPTION:
1048 			pevents->description = string;
1049 			break;
1050 
1051 		case HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_NAMESPACE:
1052 			if (strcasecmp(HP_WMI_EVENT_NAMESPACE, string))
1053 				return -EINVAL;
1054 
1055 			pevents->source_namespace = string;
1056 			break;
1057 
1058 		case HP_WMI_PLATFORM_EVENTS_PROPERTY_SOURCE_CLASS:
1059 			if (strcasecmp(HP_WMI_EVENT_CLASS, string))
1060 				return -EINVAL;
1061 
1062 			pevents->source_class = string;
1063 			break;
1064 
1065 		case HP_WMI_PLATFORM_EVENTS_PROPERTY_CATEGORY:
1066 			pevents->category = value;
1067 			break;
1068 
1069 		case HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_SEVERITY:
1070 			pevents->possible_severity = value;
1071 			break;
1072 
1073 		case HP_WMI_PLATFORM_EVENTS_PROPERTY_POSSIBLE_STATUS:
1074 			pevents->possible_status = value;
1075 			break;
1076 
1077 		default:
1078 			return -EINVAL;
1079 		}
1080 	}
1081 
1082 	return 0;
1083 }
1084 
1085 /*
1086  * check_event_wobj - validate a HPBIOS_BIOSEvent instance
1087  * @wobj: pointer to WMI object instance to check
1088  *
1089  * Returns 0 on success, or a negative error code on error.
1090  */
check_event_wobj(const union acpi_object * wobj)1091 static int check_event_wobj(const union acpi_object *wobj)
1092 {
1093 	return check_wobj(wobj, hp_wmi_event_property_map,
1094 			  HP_WMI_EVENT_PROPERTY_STATUS);
1095 }
1096 
populate_event_from_wobj(struct device * dev,struct hp_wmi_event * event,union acpi_object * wobj)1097 static int populate_event_from_wobj(struct device *dev,
1098 				    struct hp_wmi_event *event,
1099 				    union acpi_object *wobj)
1100 {
1101 	int prop = HP_WMI_EVENT_PROPERTY_NAME;
1102 	union acpi_object *element;
1103 	acpi_object_type type;
1104 	char *string;
1105 	u32 value;
1106 	int err;
1107 
1108 	err = check_event_wobj(wobj);
1109 	if (err)
1110 		return err;
1111 
1112 	element = wobj->package.elements;
1113 
1114 	for (; prop <= HP_WMI_EVENT_PROPERTY_CATEGORY; prop++, element++) {
1115 		type = hp_wmi_event_property_map[prop];
1116 
1117 		err = extract_acpi_value(dev, element, type, &value, &string);
1118 		if (err)
1119 			return err;
1120 
1121 		switch (prop) {
1122 		case HP_WMI_EVENT_PROPERTY_NAME:
1123 			event->name = string;
1124 			break;
1125 
1126 		case HP_WMI_EVENT_PROPERTY_DESCRIPTION:
1127 			event->description = string;
1128 			break;
1129 
1130 		case HP_WMI_EVENT_PROPERTY_CATEGORY:
1131 			event->category = value;
1132 			break;
1133 
1134 		default:
1135 			return -EINVAL;
1136 		}
1137 	}
1138 
1139 	return 0;
1140 }
1141 
1142 /*
1143  * classify_event - classify an event
1144  * @name: event name
1145  * @category: event category
1146  *
1147  * Classify instances of both HPBIOS_PlatformEvents and HPBIOS_BIOSEvent from
1148  * property values. Recognition criteria are based on multiple ACPI dumps [3].
1149  *
1150  * Returns an enum hp_wmi_type value on success,
1151  * or a negative value if the event type is unsupported.
1152  */
classify_event(const char * event_name,u32 category)1153 static int classify_event(const char *event_name, u32 category)
1154 {
1155 	if (category != HP_WMI_CATEGORY_SENSOR)
1156 		return -EINVAL;
1157 
1158 	/* Fan events have Name "X Stall". */
1159 	if (strstr(event_name, HP_WMI_PATTERN_FAN_ALARM))
1160 		return HP_WMI_TYPE_AIR_FLOW;
1161 
1162 	/* Intrusion events have Name "Hood Intrusion". */
1163 	if (!strcmp(event_name, HP_WMI_PATTERN_INTRUSION_ALARM))
1164 		return HP_WMI_TYPE_INTRUSION;
1165 
1166 	/*
1167 	 * Temperature events have Name either "Thermal Caution" or
1168 	 * "Thermal Critical". Deal only with "Thermal Critical" events.
1169 	 *
1170 	 * "Thermal Caution" events have Status "Stressed", informing us that
1171 	 * the OperationalStatus of the related sensor has become "Stressed".
1172 	 * However, this is already a fault condition that will clear itself
1173 	 * when the sensor recovers, so we have no further interest in them.
1174 	 */
1175 	if (!strcmp(event_name, HP_WMI_PATTERN_TEMP_ALARM))
1176 		return HP_WMI_TYPE_TEMPERATURE;
1177 
1178 	return -EINVAL;
1179 }
1180 
1181 /*
1182  * interpret_info - interpret sensor for hwmon
1183  * @info: pointer to sensor info struct
1184  *
1185  * Should be called after the numeric sensor member has been updated.
1186  */
interpret_info(struct hp_wmi_info * info)1187 static void interpret_info(struct hp_wmi_info *info)
1188 {
1189 	const struct hp_wmi_numeric_sensor *nsensor = &info->nsensor;
1190 
1191 	info->cached_val = scale_numeric_sensor(nsensor);
1192 	info->last_updated = jiffies;
1193 }
1194 
1195 /*
1196  * hp_wmi_update_info - poll WMI to update sensor info
1197  * @state: pointer to driver state
1198  * @info: pointer to sensor info struct
1199  *
1200  * Returns 0 on success, or a negative error code on error.
1201  */
hp_wmi_update_info(struct hp_wmi_sensors * state,struct hp_wmi_info * info)1202 static int hp_wmi_update_info(struct hp_wmi_sensors *state,
1203 			      struct hp_wmi_info *info)
1204 {
1205 	struct hp_wmi_numeric_sensor *nsensor = &info->nsensor;
1206 	struct device *dev = &state->wdev->dev;
1207 	const union acpi_object *wobj;
1208 	u8 instance = info->instance;
1209 	int ret = 0;
1210 
1211 	if (time_after(jiffies, info->last_updated + HZ)) {
1212 		mutex_lock(&state->lock);
1213 
1214 		wobj = wmidev_block_query(state->wdev, instance);
1215 		if (!wobj) {
1216 			ret = -EIO;
1217 			goto out_unlock;
1218 		}
1219 
1220 		update_numeric_sensor_from_wobj(dev, nsensor, wobj);
1221 
1222 		interpret_info(info);
1223 
1224 		kfree(wobj);
1225 
1226 out_unlock:
1227 		mutex_unlock(&state->lock);
1228 	}
1229 
1230 	return ret;
1231 }
1232 
basic_string_show(struct seq_file * seqf,void * ignored)1233 static int basic_string_show(struct seq_file *seqf, void *ignored)
1234 {
1235 	const char *str = seqf->private;
1236 
1237 	seq_printf(seqf, "%s\n", str);
1238 
1239 	return 0;
1240 }
1241 DEFINE_SHOW_ATTRIBUTE(basic_string);
1242 
fungible_show(struct seq_file * seqf,enum hp_wmi_property prop)1243 static int fungible_show(struct seq_file *seqf, enum hp_wmi_property prop)
1244 {
1245 	struct hp_wmi_numeric_sensor *nsensor;
1246 	struct hp_wmi_sensors *state;
1247 	struct hp_wmi_info *info;
1248 	int err;
1249 
1250 	info = seqf->private;
1251 	state = info->state;
1252 	nsensor = &info->nsensor;
1253 
1254 	err = hp_wmi_update_info(state, info);
1255 	if (err)
1256 		return err;
1257 
1258 	switch (prop) {
1259 	case HP_WMI_PROPERTY_OPERATIONAL_STATUS:
1260 		seq_printf(seqf, "%u\n", nsensor->operational_status);
1261 		break;
1262 
1263 	case HP_WMI_PROPERTY_CURRENT_STATE:
1264 		mutex_lock(&state->lock);
1265 		seq_printf(seqf, "%s\n", nsensor->current_state);
1266 		mutex_unlock(&state->lock);
1267 		break;
1268 
1269 	case HP_WMI_PROPERTY_UNIT_MODIFIER:
1270 		seq_printf(seqf, "%d\n", nsensor->unit_modifier);
1271 		break;
1272 
1273 	case HP_WMI_PROPERTY_CURRENT_READING:
1274 		seq_printf(seqf, "%u\n", nsensor->current_reading);
1275 		break;
1276 
1277 	default:
1278 		return -EOPNOTSUPP;
1279 	}
1280 
1281 	return 0;
1282 }
1283 
operational_status_show(struct seq_file * seqf,void * ignored)1284 static int operational_status_show(struct seq_file *seqf, void *ignored)
1285 {
1286 	return fungible_show(seqf, HP_WMI_PROPERTY_OPERATIONAL_STATUS);
1287 }
1288 DEFINE_SHOW_ATTRIBUTE(operational_status);
1289 
current_state_show(struct seq_file * seqf,void * ignored)1290 static int current_state_show(struct seq_file *seqf, void *ignored)
1291 {
1292 	return fungible_show(seqf, HP_WMI_PROPERTY_CURRENT_STATE);
1293 }
1294 DEFINE_SHOW_ATTRIBUTE(current_state);
1295 
possible_states_show(struct seq_file * seqf,void * ignored)1296 static int possible_states_show(struct seq_file *seqf, void *ignored)
1297 {
1298 	struct hp_wmi_numeric_sensor *nsensor = seqf->private;
1299 	u8 i;
1300 
1301 	for (i = 0; i < nsensor->size; i++)
1302 		seq_printf(seqf, "%s%s", i ? "," : "",
1303 			   nsensor->possible_states[i]);
1304 
1305 	seq_puts(seqf, "\n");
1306 
1307 	return 0;
1308 }
1309 DEFINE_SHOW_ATTRIBUTE(possible_states);
1310 
unit_modifier_show(struct seq_file * seqf,void * ignored)1311 static int unit_modifier_show(struct seq_file *seqf, void *ignored)
1312 {
1313 	return fungible_show(seqf, HP_WMI_PROPERTY_UNIT_MODIFIER);
1314 }
1315 DEFINE_SHOW_ATTRIBUTE(unit_modifier);
1316 
current_reading_show(struct seq_file * seqf,void * ignored)1317 static int current_reading_show(struct seq_file *seqf, void *ignored)
1318 {
1319 	return fungible_show(seqf, HP_WMI_PROPERTY_CURRENT_READING);
1320 }
1321 DEFINE_SHOW_ATTRIBUTE(current_reading);
1322 
1323 /* hp_wmi_devm_debugfs_remove - devm callback for debugfs cleanup */
hp_wmi_devm_debugfs_remove(void * res)1324 static void hp_wmi_devm_debugfs_remove(void *res)
1325 {
1326 	debugfs_remove_recursive(res);
1327 }
1328 
1329 /* hp_wmi_debugfs_init - create and populate debugfs directory tree */
hp_wmi_debugfs_init(struct device * dev,struct hp_wmi_info * info,struct hp_wmi_platform_events * pevents,u8 icount,u8 pcount,bool is_new)1330 static void hp_wmi_debugfs_init(struct device *dev, struct hp_wmi_info *info,
1331 				struct hp_wmi_platform_events *pevents,
1332 				u8 icount, u8 pcount, bool is_new)
1333 {
1334 	struct hp_wmi_numeric_sensor *nsensor;
1335 	char buf[HP_WMI_MAX_STR_SIZE];
1336 	struct dentry *debugfs;
1337 	struct dentry *entries;
1338 	struct dentry *dir;
1339 	int err;
1340 	u8 i;
1341 
1342 	/* dev_name() gives a not-very-friendly GUID for WMI devices. */
1343 	scnprintf(buf, sizeof(buf), "hp-wmi-sensors-%u", dev->id);
1344 
1345 	debugfs = debugfs_create_dir(buf, NULL);
1346 	if (IS_ERR(debugfs))
1347 		return;
1348 
1349 	err = devm_add_action_or_reset(dev, hp_wmi_devm_debugfs_remove,
1350 				       debugfs);
1351 	if (err)
1352 		return;
1353 
1354 	entries = debugfs_create_dir("sensor", debugfs);
1355 
1356 	for (i = 0; i < icount; i++, info++) {
1357 		nsensor = &info->nsensor;
1358 
1359 		scnprintf(buf, sizeof(buf), "%u", i);
1360 		dir = debugfs_create_dir(buf, entries);
1361 
1362 		debugfs_create_file("name", 0444, dir,
1363 				    (void *)nsensor->name,
1364 				    &basic_string_fops);
1365 
1366 		debugfs_create_file("description", 0444, dir,
1367 				    (void *)nsensor->description,
1368 				    &basic_string_fops);
1369 
1370 		debugfs_create_u32("sensor_type", 0444, dir,
1371 				   &nsensor->sensor_type);
1372 
1373 		debugfs_create_file("other_sensor_type", 0444, dir,
1374 				    (void *)nsensor->other_sensor_type,
1375 				    &basic_string_fops);
1376 
1377 		debugfs_create_file("operational_status", 0444, dir,
1378 				    info, &operational_status_fops);
1379 
1380 		debugfs_create_file("possible_states", 0444, dir,
1381 				    nsensor, &possible_states_fops);
1382 
1383 		debugfs_create_file("current_state", 0444, dir,
1384 				    info, &current_state_fops);
1385 
1386 		debugfs_create_u32("base_units", 0444, dir,
1387 				   &nsensor->base_units);
1388 
1389 		debugfs_create_file("unit_modifier", 0444, dir,
1390 				    info, &unit_modifier_fops);
1391 
1392 		debugfs_create_file("current_reading", 0444, dir,
1393 				    info, &current_reading_fops);
1394 
1395 		if (is_new)
1396 			debugfs_create_u32("rate_units", 0444, dir,
1397 					   &nsensor->rate_units);
1398 	}
1399 
1400 	if (!pcount)
1401 		return;
1402 
1403 	entries = debugfs_create_dir("platform_events", debugfs);
1404 
1405 	for (i = 0; i < pcount; i++, pevents++) {
1406 		scnprintf(buf, sizeof(buf), "%u", i);
1407 		dir = debugfs_create_dir(buf, entries);
1408 
1409 		debugfs_create_file("name", 0444, dir,
1410 				    (void *)pevents->name,
1411 				    &basic_string_fops);
1412 
1413 		debugfs_create_file("description", 0444, dir,
1414 				    (void *)pevents->description,
1415 				    &basic_string_fops);
1416 
1417 		debugfs_create_file("source_namespace", 0444, dir,
1418 				    (void *)pevents->source_namespace,
1419 				    &basic_string_fops);
1420 
1421 		debugfs_create_file("source_class", 0444, dir,
1422 				    (void *)pevents->source_class,
1423 				    &basic_string_fops);
1424 
1425 		debugfs_create_u32("category", 0444, dir,
1426 				   &pevents->category);
1427 
1428 		debugfs_create_u32("possible_severity", 0444, dir,
1429 				   &pevents->possible_severity);
1430 
1431 		debugfs_create_u32("possible_status", 0444, dir,
1432 				   &pevents->possible_status);
1433 	}
1434 }
1435 
hp_wmi_hwmon_is_visible(const void * drvdata,enum hwmon_sensor_types type,u32 attr,int channel)1436 static umode_t hp_wmi_hwmon_is_visible(const void *drvdata,
1437 				       enum hwmon_sensor_types type,
1438 				       u32 attr, int channel)
1439 {
1440 	const struct hp_wmi_sensors *state = drvdata;
1441 	const struct hp_wmi_info *info;
1442 
1443 	if (type == hwmon_intrusion)
1444 		return state->has_intrusion ? 0644 : 0;
1445 
1446 	if (!state->info_map[type] || !state->info_map[type][channel])
1447 		return 0;
1448 
1449 	info = state->info_map[type][channel];
1450 
1451 	if ((type == hwmon_temp && attr == hwmon_temp_alarm) ||
1452 	    (type == hwmon_fan  && attr == hwmon_fan_alarm))
1453 		return info->has_alarm ? 0444 : 0;
1454 
1455 	return 0444;
1456 }
1457 
hp_wmi_hwmon_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * out_val)1458 static int hp_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
1459 			     u32 attr, int channel, long *out_val)
1460 {
1461 	struct hp_wmi_sensors *state = dev_get_drvdata(dev);
1462 	const struct hp_wmi_numeric_sensor *nsensor;
1463 	struct hp_wmi_info *info;
1464 	int err;
1465 
1466 	if (type == hwmon_intrusion) {
1467 		*out_val = state->intrusion ? 1 : 0;
1468 
1469 		return 0;
1470 	}
1471 
1472 	info = state->info_map[type][channel];
1473 
1474 	if ((type == hwmon_temp && attr == hwmon_temp_alarm) ||
1475 	    (type == hwmon_fan  && attr == hwmon_fan_alarm)) {
1476 		*out_val = info->alarm ? 1 : 0;
1477 		info->alarm = false;
1478 
1479 		return 0;
1480 	}
1481 
1482 	nsensor = &info->nsensor;
1483 
1484 	err = hp_wmi_update_info(state, info);
1485 	if (err)
1486 		return err;
1487 
1488 	if ((type == hwmon_temp && attr == hwmon_temp_fault) ||
1489 	    (type == hwmon_fan  && attr == hwmon_fan_fault))
1490 		*out_val = numeric_sensor_has_fault(nsensor);
1491 	else
1492 		*out_val = info->cached_val;
1493 
1494 	return 0;
1495 }
1496 
hp_wmi_hwmon_read_string(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,const char ** out_str)1497 static int hp_wmi_hwmon_read_string(struct device *dev,
1498 				    enum hwmon_sensor_types type, u32 attr,
1499 				    int channel, const char **out_str)
1500 {
1501 	const struct hp_wmi_sensors *state = dev_get_drvdata(dev);
1502 	const struct hp_wmi_info *info;
1503 
1504 	info = state->info_map[type][channel];
1505 	*out_str = info->nsensor.name;
1506 
1507 	return 0;
1508 }
1509 
hp_wmi_hwmon_write(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long val)1510 static int hp_wmi_hwmon_write(struct device *dev, enum hwmon_sensor_types type,
1511 			      u32 attr, int channel, long val)
1512 {
1513 	struct hp_wmi_sensors *state = dev_get_drvdata(dev);
1514 
1515 	if (val)
1516 		return -EINVAL;
1517 
1518 	mutex_lock(&state->lock);
1519 
1520 	state->intrusion = false;
1521 
1522 	mutex_unlock(&state->lock);
1523 
1524 	return 0;
1525 }
1526 
1527 static const struct hwmon_ops hp_wmi_hwmon_ops = {
1528 	.is_visible  = hp_wmi_hwmon_is_visible,
1529 	.read	     = hp_wmi_hwmon_read,
1530 	.read_string = hp_wmi_hwmon_read_string,
1531 	.write	     = hp_wmi_hwmon_write,
1532 };
1533 
1534 static struct hwmon_chip_info hp_wmi_chip_info = {
1535 	.ops         = &hp_wmi_hwmon_ops,
1536 	.info        = NULL,
1537 };
1538 
match_fan_event(struct hp_wmi_sensors * state,const char * event_description)1539 static struct hp_wmi_info *match_fan_event(struct hp_wmi_sensors *state,
1540 					   const char *event_description)
1541 {
1542 	struct hp_wmi_info **ptr_info = state->info_map[hwmon_fan];
1543 	u8 fan_count = state->channel_count[hwmon_fan];
1544 	struct hp_wmi_info *info;
1545 	const char *name;
1546 	u8 i;
1547 
1548 	/* Fan event has Description "X Speed". Sensor has Name "X[ Speed]". */
1549 
1550 	for (i = 0; i < fan_count; i++, ptr_info++) {
1551 		info = *ptr_info;
1552 		name = info->nsensor.name;
1553 
1554 		if (strstr(event_description, name))
1555 			return info;
1556 	}
1557 
1558 	return NULL;
1559 }
1560 
match_temp_events(struct hp_wmi_sensors * state,const char * event_description,struct hp_wmi_info * temp_info[])1561 static u8 match_temp_events(struct hp_wmi_sensors *state,
1562 			    const char *event_description,
1563 			    struct hp_wmi_info *temp_info[])
1564 {
1565 	struct hp_wmi_info **ptr_info = state->info_map[hwmon_temp];
1566 	u8 temp_count = state->channel_count[hwmon_temp];
1567 	struct hp_wmi_info *info;
1568 	const char *name;
1569 	u8 count = 0;
1570 	bool is_cpu;
1571 	bool is_sys;
1572 	u8 i;
1573 
1574 	/* Description is either "CPU Thermal Index" or "Chassis Thermal Index". */
1575 
1576 	is_cpu = !strcmp(event_description, HP_WMI_PATTERN_CPU_TEMP);
1577 	is_sys = !strcmp(event_description, HP_WMI_PATTERN_SYS_TEMP);
1578 	if (!is_cpu && !is_sys)
1579 		return 0;
1580 
1581 	/*
1582 	 * CPU event: Match one sensor with Name either "CPU Thermal Index" or
1583 	 * "CPU Temperature", or multiple with Name(s) "CPU[#] Temperature".
1584 	 *
1585 	 * Chassis event: Match one sensor with Name either
1586 	 * "Chassis Thermal Index" or "System Ambient Temperature".
1587 	 */
1588 
1589 	for (i = 0; i < temp_count; i++, ptr_info++) {
1590 		info = *ptr_info;
1591 		name = info->nsensor.name;
1592 
1593 		if ((is_cpu && (!strcmp(name, HP_WMI_PATTERN_CPU_TEMP) ||
1594 				!strcmp(name, HP_WMI_PATTERN_CPU_TEMP2))) ||
1595 		    (is_sys && (!strcmp(name, HP_WMI_PATTERN_SYS_TEMP) ||
1596 				!strcmp(name, HP_WMI_PATTERN_SYS_TEMP2)))) {
1597 			temp_info[0] = info;
1598 			return 1;
1599 		}
1600 
1601 		if (is_cpu && (strstr(name, HP_WMI_PATTERN_CPU) &&
1602 			       strstr(name, HP_WMI_PATTERN_TEMP)))
1603 			temp_info[count++] = info;
1604 	}
1605 
1606 	return count;
1607 }
1608 
1609 /* hp_wmi_devm_debugfs_remove - devm callback for WMI event handler removal */
hp_wmi_devm_notify_remove(void * ignored)1610 static void hp_wmi_devm_notify_remove(void *ignored)
1611 {
1612 	wmi_remove_notify_handler(HP_WMI_EVENT_GUID);
1613 }
1614 
1615 /* hp_wmi_notify - WMI event notification handler */
hp_wmi_notify(union acpi_object * wobj,void * context)1616 static void hp_wmi_notify(union acpi_object *wobj, void *context)
1617 {
1618 	struct hp_wmi_info *temp_info[HP_WMI_MAX_INSTANCES] = {};
1619 	struct hp_wmi_sensors *state = context;
1620 	struct device *dev = &state->wdev->dev;
1621 	struct hp_wmi_event event = {};
1622 	struct hp_wmi_info *fan_info;
1623 	acpi_status err;
1624 	int event_type;
1625 	u8 count;
1626 
1627 	/*
1628 	 * The following warning may occur in the kernel log:
1629 	 *
1630 	 *   ACPI Warning: \_SB.WMID._WED: Return type mismatch -
1631 	 *     found Package, expected Integer/String/Buffer
1632 	 *
1633 	 * After using [4] to decode BMOF blobs found in [3], careless copying
1634 	 * of BIOS code seems the most likely explanation for this warning.
1635 	 * HP_WMI_EVENT_GUID refers to \\.\root\WMI\HPBIOS_BIOSEvent on
1636 	 * business-class systems, but it refers to \\.\root\WMI\hpqBEvnt on
1637 	 * non-business-class systems. Per the existing hp-wmi driver, it
1638 	 * looks like an instance of hpqBEvnt delivered as event data may
1639 	 * indeed take the form of a raw ACPI_BUFFER on non-business-class
1640 	 * systems ("may" because ASL shows some BIOSes do strange things).
1641 	 *
1642 	 * In any case, we can ignore this warning, because we always validate
1643 	 * the event data to ensure it is an ACPI_PACKAGE containing a
1644 	 * HPBIOS_BIOSEvent instance.
1645 	 */
1646 
1647 	if (!wobj)
1648 		return;
1649 
1650 	mutex_lock(&state->lock);
1651 
1652 	err = populate_event_from_wobj(dev, &event, wobj);
1653 	if (err) {
1654 		dev_warn(dev, "Bad event data (ACPI type %d)\n", wobj->type);
1655 		goto out_free;
1656 	}
1657 
1658 	event_type = classify_event(event.name, event.category);
1659 	switch (event_type) {
1660 	case HP_WMI_TYPE_AIR_FLOW:
1661 		fan_info = match_fan_event(state, event.description);
1662 		if (fan_info)
1663 			fan_info->alarm = true;
1664 		break;
1665 
1666 	case HP_WMI_TYPE_INTRUSION:
1667 		state->intrusion = true;
1668 		break;
1669 
1670 	case HP_WMI_TYPE_TEMPERATURE:
1671 		count = match_temp_events(state, event.description, temp_info);
1672 		while (count)
1673 			temp_info[--count]->alarm = true;
1674 		break;
1675 
1676 	default:
1677 		break;
1678 	}
1679 
1680 out_free:
1681 	devm_kfree(dev, event.name);
1682 	devm_kfree(dev, event.description);
1683 
1684 	mutex_unlock(&state->lock);
1685 }
1686 
init_platform_events(struct device * dev,struct hp_wmi_platform_events ** out_pevents,u8 * out_pcount)1687 static int init_platform_events(struct device *dev,
1688 				struct hp_wmi_platform_events **out_pevents,
1689 				u8 *out_pcount)
1690 {
1691 	struct hp_wmi_platform_events *pevents_arr;
1692 	struct hp_wmi_platform_events *pevents;
1693 	union acpi_object *wobj;
1694 	u8 count;
1695 	int err;
1696 	u8 i;
1697 
1698 	count = hp_wmi_wobj_instance_count(HP_WMI_PLATFORM_EVENTS_GUID);
1699 	if (!count) {
1700 		*out_pcount = 0;
1701 
1702 		dev_dbg(dev, "No platform events\n");
1703 
1704 		return 0;
1705 	}
1706 
1707 	pevents_arr = devm_kcalloc(dev, count, sizeof(*pevents), GFP_KERNEL);
1708 	if (!pevents_arr)
1709 		return -ENOMEM;
1710 
1711 	for (i = 0, pevents = pevents_arr; i < count; i++, pevents++) {
1712 		wobj = hp_wmi_get_wobj(HP_WMI_PLATFORM_EVENTS_GUID, i);
1713 		if (!wobj)
1714 			return -EIO;
1715 
1716 		err = populate_platform_events_from_wobj(dev, pevents, wobj);
1717 
1718 		kfree(wobj);
1719 
1720 		if (err)
1721 			return err;
1722 	}
1723 
1724 	*out_pevents = pevents_arr;
1725 	*out_pcount = count;
1726 
1727 	dev_dbg(dev, "Found %u platform events\n", count);
1728 
1729 	return 0;
1730 }
1731 
init_numeric_sensors(struct hp_wmi_sensors * state,struct hp_wmi_info * connected[],struct hp_wmi_info ** out_info,u8 * out_icount,u8 * out_count,bool * out_is_new)1732 static int init_numeric_sensors(struct hp_wmi_sensors *state,
1733 				struct hp_wmi_info *connected[],
1734 				struct hp_wmi_info **out_info,
1735 				u8 *out_icount, u8 *out_count,
1736 				bool *out_is_new)
1737 {
1738 	struct hp_wmi_info ***info_map = state->info_map;
1739 	u8 *channel_count = state->channel_count;
1740 	struct device *dev = &state->wdev->dev;
1741 	struct hp_wmi_numeric_sensor *nsensor;
1742 	u8 channel_index[hwmon_max] = {};
1743 	enum hwmon_sensor_types type;
1744 	struct hp_wmi_info *info_arr;
1745 	struct hp_wmi_info *info;
1746 	union acpi_object *wobj;
1747 	u8 count = 0;
1748 	bool is_new;
1749 	u8 icount;
1750 	int wtype;
1751 	int err;
1752 	u8 c;
1753 	u8 i;
1754 
1755 	icount = hp_wmi_wobj_instance_count(HP_WMI_NUMERIC_SENSOR_GUID);
1756 	if (!icount)
1757 		return -ENODATA;
1758 
1759 	info_arr = devm_kcalloc(dev, icount, sizeof(*info), GFP_KERNEL);
1760 	if (!info_arr)
1761 		return -ENOMEM;
1762 
1763 	for (i = 0, info = info_arr; i < icount; i++, info++) {
1764 		wobj = wmidev_block_query(state->wdev, i);
1765 		if (!wobj)
1766 			return -EIO;
1767 
1768 		info->instance = i;
1769 		info->state = state;
1770 		nsensor = &info->nsensor;
1771 
1772 		err = populate_numeric_sensor_from_wobj(dev, nsensor, wobj,
1773 							&is_new);
1774 
1775 		kfree(wobj);
1776 
1777 		if (err)
1778 			return err;
1779 
1780 		if (!numeric_sensor_is_connected(nsensor))
1781 			continue;
1782 
1783 		wtype = classify_numeric_sensor(nsensor);
1784 		if (wtype < 0)
1785 			continue;
1786 
1787 		type = hp_wmi_hwmon_type_map[wtype];
1788 
1789 		channel_count[type]++;
1790 
1791 		info->type = type;
1792 
1793 		interpret_info(info);
1794 
1795 		connected[count++] = info;
1796 	}
1797 
1798 	dev_dbg(dev, "Found %u sensors (%u connected)\n", i, count);
1799 
1800 	for (i = 0; i < count; i++) {
1801 		info = connected[i];
1802 		type = info->type;
1803 		c = channel_index[type]++;
1804 
1805 		if (!info_map[type]) {
1806 			info_map[type] = devm_kcalloc(dev, channel_count[type],
1807 						      sizeof(*info_map),
1808 						      GFP_KERNEL);
1809 			if (!info_map[type])
1810 				return -ENOMEM;
1811 		}
1812 
1813 		info_map[type][c] = info;
1814 	}
1815 
1816 	*out_info = info_arr;
1817 	*out_icount = icount;
1818 	*out_count = count;
1819 	*out_is_new = is_new;
1820 
1821 	return 0;
1822 }
1823 
find_event_attributes(struct hp_wmi_sensors * state,struct hp_wmi_platform_events * pevents,u8 pevents_count)1824 static bool find_event_attributes(struct hp_wmi_sensors *state,
1825 				  struct hp_wmi_platform_events *pevents,
1826 				  u8 pevents_count)
1827 {
1828 	/*
1829 	 * The existence of this HPBIOS_PlatformEvents instance:
1830 	 *
1831 	 *   {
1832 	 *     Name = "Rear Chassis Fan0 Stall";
1833 	 *     Description = "Rear Chassis Fan0 Speed";
1834 	 *     Category = 3;           // "Sensor"
1835 	 *     PossibleSeverity = 25;  // "Critical Failure"
1836 	 *     PossibleStatus = 5;     // "Predictive Failure"
1837 	 *     [...]
1838 	 *   }
1839 	 *
1840 	 * means that this HPBIOS_BIOSEvent instance may occur:
1841 	 *
1842 	 *   {
1843 	 *     Name = "Rear Chassis Fan0 Stall";
1844 	 *     Description = "Rear Chassis Fan0 Speed";
1845 	 *     Category = 3;           // "Sensor"
1846 	 *     Severity = 25;          // "Critical Failure"
1847 	 *     Status = 5;             // "Predictive Failure"
1848 	 *   }
1849 	 *
1850 	 * After the event occurs (e.g. because the fan was unplugged),
1851 	 * polling the related HPBIOS_BIOSNumericSensor instance gives:
1852 	 *
1853 	 *   {
1854 	 *      Name = "Rear Chassis Fan0";
1855 	 *      Description = "Reports rear chassis fan0 speed";
1856 	 *      OperationalStatus = 5; // "Predictive Failure", was 3 ("OK")
1857 	 *      CurrentReading = 0;
1858 	 *      [...]
1859 	 *   }
1860 	 *
1861 	 * In this example, the hwmon fan channel for "Rear Chassis Fan0"
1862 	 * should support the alarm flag and have it be set if the related
1863 	 * HPBIOS_BIOSEvent instance occurs.
1864 	 *
1865 	 * In addition to fan events, temperature (CPU/chassis) and intrusion
1866 	 * events are relevant to hwmon [2]. Note that much information in [2]
1867 	 * is unreliable; it is referenced in addition to ACPI dumps [3] merely
1868 	 * to support the conclusion that sensor and event names/descriptions
1869 	 * are systematic enough to allow this driver to match them.
1870 	 *
1871 	 * Complications and limitations:
1872 	 *
1873 	 * - Strings are freeform and may vary, cf. sensor Name "CPU0 Fan"
1874 	 *   on a Z420 vs. "CPU Fan Speed" on an EliteOne 800 G1.
1875 	 * - Leading/trailing whitespace is a rare but real possibility [3].
1876 	 * - The HPBIOS_PlatformEvents object may not exist or its instances
1877 	 *   may show that the system only has e.g. BIOS setting-related
1878 	 *   events (cf. the ProBook 4540s and ProBook 470 G0 [3]).
1879 	 */
1880 
1881 	struct hp_wmi_info *temp_info[HP_WMI_MAX_INSTANCES] = {};
1882 	const char *event_description;
1883 	struct hp_wmi_info *fan_info;
1884 	bool has_events = false;
1885 	const char *event_name;
1886 	u32 event_category;
1887 	int event_type;
1888 	u8 count;
1889 	u8 i;
1890 
1891 	for (i = 0; i < pevents_count; i++, pevents++) {
1892 		event_name = pevents->name;
1893 		event_description = pevents->description;
1894 		event_category = pevents->category;
1895 
1896 		event_type = classify_event(event_name, event_category);
1897 		switch (event_type) {
1898 		case HP_WMI_TYPE_AIR_FLOW:
1899 			fan_info = match_fan_event(state, event_description);
1900 			if (!fan_info)
1901 				break;
1902 
1903 			fan_info->has_alarm = true;
1904 			has_events = true;
1905 			break;
1906 
1907 		case HP_WMI_TYPE_INTRUSION:
1908 			state->has_intrusion = true;
1909 			has_events = true;
1910 			break;
1911 
1912 		case HP_WMI_TYPE_TEMPERATURE:
1913 			count = match_temp_events(state, event_description,
1914 						  temp_info);
1915 			if (!count)
1916 				break;
1917 
1918 			while (count)
1919 				temp_info[--count]->has_alarm = true;
1920 			has_events = true;
1921 			break;
1922 
1923 		default:
1924 			break;
1925 		}
1926 	}
1927 
1928 	return has_events;
1929 }
1930 
make_chip_info(struct hp_wmi_sensors * state,bool has_events)1931 static int make_chip_info(struct hp_wmi_sensors *state, bool has_events)
1932 {
1933 	const struct hwmon_channel_info **ptr_channel_info;
1934 	struct hp_wmi_info ***info_map = state->info_map;
1935 	u8 *channel_count = state->channel_count;
1936 	struct hwmon_channel_info *channel_info;
1937 	struct device *dev = &state->wdev->dev;
1938 	enum hwmon_sensor_types type;
1939 	u8 type_count = 0;
1940 	u32 *config;
1941 	u32 attr;
1942 	u8 count;
1943 	u8 i;
1944 
1945 	if (channel_count[hwmon_temp])
1946 		channel_count[hwmon_chip] = 1;
1947 
1948 	if (has_events && state->has_intrusion)
1949 		channel_count[hwmon_intrusion] = 1;
1950 
1951 	for (type = hwmon_chip; type < hwmon_max; type++)
1952 		if (channel_count[type])
1953 			type_count++;
1954 
1955 	channel_info = devm_kcalloc(dev, type_count,
1956 				    sizeof(*channel_info), GFP_KERNEL);
1957 	if (!channel_info)
1958 		return -ENOMEM;
1959 
1960 	ptr_channel_info = devm_kcalloc(dev, type_count + 1,
1961 					sizeof(*ptr_channel_info), GFP_KERNEL);
1962 	if (!ptr_channel_info)
1963 		return -ENOMEM;
1964 
1965 	hp_wmi_chip_info.info = ptr_channel_info;
1966 
1967 	for (type = hwmon_chip; type < hwmon_max; type++) {
1968 		count = channel_count[type];
1969 		if (!count)
1970 			continue;
1971 
1972 		config = devm_kcalloc(dev, count + 1,
1973 				      sizeof(*config), GFP_KERNEL);
1974 		if (!config)
1975 			return -ENOMEM;
1976 
1977 		attr = hp_wmi_hwmon_attributes[type];
1978 		channel_info->type = type;
1979 		channel_info->config = config;
1980 		memset32(config, attr, count);
1981 
1982 		*ptr_channel_info++ = channel_info++;
1983 
1984 		if (!has_events || (type != hwmon_temp && type != hwmon_fan))
1985 			continue;
1986 
1987 		attr = type == hwmon_temp ? HWMON_T_ALARM : HWMON_F_ALARM;
1988 
1989 		for (i = 0; i < count; i++)
1990 			if (info_map[type][i]->has_alarm)
1991 				config[i] |= attr;
1992 	}
1993 
1994 	return 0;
1995 }
1996 
add_event_handler(struct hp_wmi_sensors * state)1997 static bool add_event_handler(struct hp_wmi_sensors *state)
1998 {
1999 	struct device *dev = &state->wdev->dev;
2000 	int err;
2001 
2002 	err = wmi_install_notify_handler(HP_WMI_EVENT_GUID,
2003 					 hp_wmi_notify, state);
2004 	if (err) {
2005 		dev_info(dev, "Failed to subscribe to WMI event\n");
2006 		return false;
2007 	}
2008 
2009 	err = devm_add_action_or_reset(dev, hp_wmi_devm_notify_remove, NULL);
2010 	if (err)
2011 		return false;
2012 
2013 	return true;
2014 }
2015 
hp_wmi_sensors_init(struct hp_wmi_sensors * state)2016 static int hp_wmi_sensors_init(struct hp_wmi_sensors *state)
2017 {
2018 	struct hp_wmi_info *connected[HP_WMI_MAX_INSTANCES];
2019 	struct hp_wmi_platform_events *pevents = NULL;
2020 	struct device *dev = &state->wdev->dev;
2021 	struct hp_wmi_info *info;
2022 	struct device *hwdev;
2023 	bool has_events;
2024 	bool is_new;
2025 	u8 icount;
2026 	u8 pcount;
2027 	u8 count;
2028 	int err;
2029 
2030 	err = init_platform_events(dev, &pevents, &pcount);
2031 	if (err)
2032 		return err;
2033 
2034 	err = init_numeric_sensors(state, connected, &info,
2035 				   &icount, &count, &is_new);
2036 	if (err)
2037 		return err;
2038 
2039 	if (IS_ENABLED(CONFIG_DEBUG_FS))
2040 		hp_wmi_debugfs_init(dev, info, pevents, icount, pcount, is_new);
2041 
2042 	if (!count)
2043 		return 0;	/* No connected sensors; debugfs only. */
2044 
2045 	has_events = find_event_attributes(state, pevents, pcount);
2046 
2047 	/* Survive failure to install WMI event handler. */
2048 	if (has_events && !add_event_handler(state))
2049 		has_events = false;
2050 
2051 	err = make_chip_info(state, has_events);
2052 	if (err)
2053 		return err;
2054 
2055 	hwdev = devm_hwmon_device_register_with_info(dev, "hp_wmi_sensors",
2056 						     state, &hp_wmi_chip_info,
2057 						     NULL);
2058 	return PTR_ERR_OR_ZERO(hwdev);
2059 }
2060 
hp_wmi_sensors_probe(struct wmi_device * wdev,const void * context)2061 static int hp_wmi_sensors_probe(struct wmi_device *wdev, const void *context)
2062 {
2063 	struct device *dev = &wdev->dev;
2064 	struct hp_wmi_sensors *state;
2065 
2066 	state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
2067 	if (!state)
2068 		return -ENOMEM;
2069 
2070 	state->wdev = wdev;
2071 
2072 	mutex_init(&state->lock);
2073 
2074 	dev_set_drvdata(dev, state);
2075 
2076 	return hp_wmi_sensors_init(state);
2077 }
2078 
2079 static const struct wmi_device_id hp_wmi_sensors_id_table[] = {
2080 	{ HP_WMI_NUMERIC_SENSOR_GUID, NULL },
2081 	{},
2082 };
2083 
2084 static struct wmi_driver hp_wmi_sensors_driver = {
2085 	.driver   = { .name = "hp-wmi-sensors" },
2086 	.id_table = hp_wmi_sensors_id_table,
2087 	.probe    = hp_wmi_sensors_probe,
2088 };
2089 module_wmi_driver(hp_wmi_sensors_driver);
2090 
2091 MODULE_AUTHOR("James Seo <james@equiv.tech>");
2092 MODULE_DESCRIPTION("HP WMI Sensors driver");
2093 MODULE_LICENSE("GPL");
2094