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