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