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