Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
   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
  58enum 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
  67enum hp_wmi_category {
  68	HP_WMI_CATEGORY_SENSOR			= 3,
  69};
  70
  71enum 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
  81enum 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
  97enum 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
 107enum 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
 122static 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
 137enum 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
 147static 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
 157enum 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
 165static 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
 173static 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
 180static 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 */
 265struct 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 */
 314struct 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 */
 353struct 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 */
 370struct 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 */
 391struct 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
 401static 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
 417static 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 */
 446static 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 */
 463static 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 */
 487static 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 */
 500static 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
 509static 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
 542static 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 */
 575static 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
 680static int
 681numeric_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
 688static 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 */
 713static 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 */
 763static 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
 811static int
 812populate_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 */
 929static void
 930update_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 */
 996static 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
1002static int
1003populate_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 */
1077static 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
1083static 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 */
1139static 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 */
1173static 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 */
1188static 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
1212out_unlock:
1213		mutex_unlock(&state->lock);
1214	}
1215
1216	return ret;
1217}
1218
1219static 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}
1227DEFINE_SHOW_ATTRIBUTE(basic_string);
1228
1229static 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
1268static int operational_status_show(struct seq_file *seqf, void *ignored)
1269{
1270	return fungible_show(seqf, HP_WMI_PROPERTY_OPERATIONAL_STATUS);
1271}
1272DEFINE_SHOW_ATTRIBUTE(operational_status);
1273
1274static int current_state_show(struct seq_file *seqf, void *ignored)
1275{
1276	return fungible_show(seqf, HP_WMI_PROPERTY_CURRENT_STATE);
1277}
1278DEFINE_SHOW_ATTRIBUTE(current_state);
1279
1280static 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}
1293DEFINE_SHOW_ATTRIBUTE(possible_states);
1294
1295static int unit_modifier_show(struct seq_file *seqf, void *ignored)
1296{
1297	return fungible_show(seqf, HP_WMI_PROPERTY_UNIT_MODIFIER);
1298}
1299DEFINE_SHOW_ATTRIBUTE(unit_modifier);
1300
1301static int current_reading_show(struct seq_file *seqf, void *ignored)
1302{
1303	return fungible_show(seqf, HP_WMI_PROPERTY_CURRENT_READING);
1304}
1305DEFINE_SHOW_ATTRIBUTE(current_reading);
1306
1307/* hp_wmi_devm_debugfs_remove - devm callback for debugfs cleanup */
1308static 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 */
1314static void hp_wmi_debugfs_init(struct device *dev, struct hp_wmi_info *info,
1315				struct hp_wmi_platform_events *pevents,
1316				u8 icount, u8 pcount, bool is_new)
1317{
1318	struct hp_wmi_numeric_sensor *nsensor;
1319	char buf[HP_WMI_MAX_STR_SIZE];
1320	struct dentry *debugfs;
1321	struct dentry *entries;
1322	struct dentry *dir;
1323	int err;
1324	u8 i;
1325
1326	/* dev_name() gives a not-very-friendly GUID for WMI devices. */
1327	scnprintf(buf, sizeof(buf), "hp-wmi-sensors-%u", dev->id);
1328
1329	debugfs = debugfs_create_dir(buf, NULL);
1330	if (IS_ERR(debugfs))
1331		return;
1332
1333	err = devm_add_action_or_reset(dev, hp_wmi_devm_debugfs_remove,
1334				       debugfs);
1335	if (err)
1336		return;
1337
1338	entries = debugfs_create_dir("sensor", debugfs);
1339
1340	for (i = 0; i < icount; i++, info++) {
1341		nsensor = &info->nsensor;
1342
1343		scnprintf(buf, sizeof(buf), "%u", i);
1344		dir = debugfs_create_dir(buf, entries);
1345
1346		debugfs_create_file("name", 0444, dir,
1347				    (void *)nsensor->name,
1348				    &basic_string_fops);
1349
1350		debugfs_create_file("description", 0444, dir,
1351				    (void *)nsensor->description,
1352				    &basic_string_fops);
1353
1354		debugfs_create_u32("sensor_type", 0444, dir,
1355				   &nsensor->sensor_type);
1356
1357		debugfs_create_file("other_sensor_type", 0444, dir,
1358				    (void *)nsensor->other_sensor_type,
1359				    &basic_string_fops);
1360
1361		debugfs_create_file("operational_status", 0444, dir,
1362				    info, &operational_status_fops);
1363
1364		debugfs_create_file("possible_states", 0444, dir,
1365				    nsensor, &possible_states_fops);
1366
1367		debugfs_create_file("current_state", 0444, dir,
1368				    info, &current_state_fops);
1369
1370		debugfs_create_u32("base_units", 0444, dir,
1371				   &nsensor->base_units);
1372
1373		debugfs_create_file("unit_modifier", 0444, dir,
1374				    info, &unit_modifier_fops);
1375
1376		debugfs_create_file("current_reading", 0444, dir,
1377				    info, &current_reading_fops);
1378
1379		if (is_new)
1380			debugfs_create_u32("rate_units", 0444, dir,
1381					   &nsensor->rate_units);
1382	}
1383
1384	if (!pcount)
1385		return;
1386
1387	entries = debugfs_create_dir("platform_events", debugfs);
1388
1389	for (i = 0; i < pcount; i++, pevents++) {
1390		scnprintf(buf, sizeof(buf), "%u", i);
1391		dir = debugfs_create_dir(buf, entries);
1392
1393		debugfs_create_file("name", 0444, dir,
1394				    (void *)pevents->name,
1395				    &basic_string_fops);
1396
1397		debugfs_create_file("description", 0444, dir,
1398				    (void *)pevents->description,
1399				    &basic_string_fops);
1400
1401		debugfs_create_file("source_namespace", 0444, dir,
1402				    (void *)pevents->source_namespace,
1403				    &basic_string_fops);
1404
1405		debugfs_create_file("source_class", 0444, dir,
1406				    (void *)pevents->source_class,
1407				    &basic_string_fops);
1408
1409		debugfs_create_u32("category", 0444, dir,
1410				   &pevents->category);
1411
1412		debugfs_create_u32("possible_severity", 0444, dir,
1413				   &pevents->possible_severity);
1414
1415		debugfs_create_u32("possible_status", 0444, dir,
1416				   &pevents->possible_status);
1417	}
1418}
1419
1420static 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
1442static 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
1481static 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
1494static 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
1511static 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
1518static struct hwmon_chip_info hp_wmi_chip_info = {
1519	.ops         = &hp_wmi_hwmon_ops,
1520	.info        = NULL,
1521};
1522
1523static 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
1545static 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 */
1594static 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 */
1600static void hp_wmi_notify(u32 value, void *context)
1601{
1602	struct hp_wmi_info *temp_info[HP_WMI_MAX_INSTANCES] = {};
1603	struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
1604	struct hp_wmi_sensors *state = context;
1605	struct device *dev = &state->wdev->dev;
1606	struct hp_wmi_event event = {};
1607	struct hp_wmi_info *fan_info;
1608	union acpi_object *wobj;
1609	acpi_status err;
1610	int event_type;
1611	u8 count;
1612
1613	/*
1614	 * The following warning may occur in the kernel log:
1615	 *
1616	 *   ACPI Warning: \_SB.WMID._WED: Return type mismatch -
1617	 *     found Package, expected Integer/String/Buffer
1618	 *
1619	 * After using [4] to decode BMOF blobs found in [3], careless copying
1620	 * of BIOS code seems the most likely explanation for this warning.
1621	 * HP_WMI_EVENT_GUID refers to \\.\root\WMI\HPBIOS_BIOSEvent on
1622	 * business-class systems, but it refers to \\.\root\WMI\hpqBEvnt on
1623	 * non-business-class systems. Per the existing hp-wmi driver, it
1624	 * looks like an instance of hpqBEvnt delivered as event data may
1625	 * indeed take the form of a raw ACPI_BUFFER on non-business-class
1626	 * systems ("may" because ASL shows some BIOSes do strange things).
1627	 *
1628	 * In any case, we can ignore this warning, because we always validate
1629	 * the event data to ensure it is an ACPI_PACKAGE containing a
1630	 * HPBIOS_BIOSEvent instance.
1631	 */
1632
1633	mutex_lock(&state->lock);
1634
1635	err = wmi_get_event_data(value, &out);
1636	if (ACPI_FAILURE(err))
1637		goto out_unlock;
1638
1639	wobj = out.pointer;
1640
1641	err = populate_event_from_wobj(dev, &event, wobj);
1642	if (err) {
1643		dev_warn(dev, "Bad event data (ACPI type %d)\n", wobj->type);
1644		goto out_free_wobj;
1645	}
1646
1647	event_type = classify_event(event.name, event.category);
1648	switch (event_type) {
1649	case HP_WMI_TYPE_AIR_FLOW:
1650		fan_info = match_fan_event(state, event.description);
1651		if (fan_info)
1652			fan_info->alarm = true;
1653		break;
1654
1655	case HP_WMI_TYPE_INTRUSION:
1656		state->intrusion = true;
1657		break;
1658
1659	case HP_WMI_TYPE_TEMPERATURE:
1660		count = match_temp_events(state, event.description, temp_info);
1661		while (count)
1662			temp_info[--count]->alarm = true;
1663		break;
1664
1665	default:
1666		break;
1667	}
1668
1669out_free_wobj:
1670	kfree(wobj);
1671
1672	devm_kfree(dev, event.name);
1673	devm_kfree(dev, event.description);
1674
1675out_unlock:
1676	mutex_unlock(&state->lock);
1677}
1678
1679static int init_platform_events(struct device *dev,
1680				struct hp_wmi_platform_events **out_pevents,
1681				u8 *out_pcount)
1682{
1683	struct hp_wmi_platform_events *pevents_arr;
1684	struct hp_wmi_platform_events *pevents;
1685	union acpi_object *wobj;
1686	u8 count;
1687	int err;
1688	u8 i;
1689
1690	count = hp_wmi_wobj_instance_count(HP_WMI_PLATFORM_EVENTS_GUID);
1691	if (!count) {
1692		*out_pcount = 0;
1693
1694		dev_dbg(dev, "No platform events\n");
1695
1696		return 0;
1697	}
1698
1699	pevents_arr = devm_kcalloc(dev, count, sizeof(*pevents), GFP_KERNEL);
1700	if (!pevents_arr)
1701		return -ENOMEM;
1702
1703	for (i = 0, pevents = pevents_arr; i < count; i++, pevents++) {
1704		wobj = hp_wmi_get_wobj(HP_WMI_PLATFORM_EVENTS_GUID, i);
1705		if (!wobj)
1706			return -EIO;
1707
1708		err = populate_platform_events_from_wobj(dev, pevents, wobj);
1709
1710		kfree(wobj);
1711
1712		if (err)
1713			return err;
1714	}
1715
1716	*out_pevents = pevents_arr;
1717	*out_pcount = count;
1718
1719	dev_dbg(dev, "Found %u platform events\n", count);
1720
1721	return 0;
1722}
1723
1724static int init_numeric_sensors(struct hp_wmi_sensors *state,
1725				struct hp_wmi_info *connected[],
1726				struct hp_wmi_info **out_info,
1727				u8 *out_icount, u8 *out_count,
1728				bool *out_is_new)
1729{
1730	struct hp_wmi_info ***info_map = state->info_map;
1731	u8 *channel_count = state->channel_count;
1732	struct device *dev = &state->wdev->dev;
1733	struct hp_wmi_numeric_sensor *nsensor;
1734	u8 channel_index[hwmon_max] = {};
1735	enum hwmon_sensor_types type;
1736	struct hp_wmi_info *info_arr;
1737	struct hp_wmi_info *info;
1738	union acpi_object *wobj;
1739	u8 count = 0;
1740	bool is_new;
1741	u8 icount;
1742	int wtype;
1743	int err;
1744	u8 c;
1745	u8 i;
1746
1747	icount = hp_wmi_wobj_instance_count(HP_WMI_NUMERIC_SENSOR_GUID);
1748	if (!icount)
1749		return -ENODATA;
1750
1751	info_arr = devm_kcalloc(dev, icount, sizeof(*info), GFP_KERNEL);
1752	if (!info_arr)
1753		return -ENOMEM;
1754
1755	for (i = 0, info = info_arr; i < icount; i++, info++) {
1756		wobj = hp_wmi_get_wobj(HP_WMI_NUMERIC_SENSOR_GUID, i);
1757		if (!wobj)
1758			return -EIO;
1759
1760		info->instance = i;
1761		info->state = state;
1762		nsensor = &info->nsensor;
1763
1764		err = populate_numeric_sensor_from_wobj(dev, nsensor, wobj,
1765							&is_new);
1766
1767		kfree(wobj);
1768
1769		if (err)
1770			return err;
1771
1772		if (!numeric_sensor_is_connected(nsensor))
1773			continue;
1774
1775		wtype = classify_numeric_sensor(nsensor);
1776		if (wtype < 0)
1777			continue;
1778
1779		type = hp_wmi_hwmon_type_map[wtype];
1780
1781		channel_count[type]++;
1782
1783		info->type = type;
1784
1785		interpret_info(info);
1786
1787		connected[count++] = info;
1788	}
1789
1790	dev_dbg(dev, "Found %u sensors (%u connected)\n", i, count);
1791
1792	for (i = 0; i < count; i++) {
1793		info = connected[i];
1794		type = info->type;
1795		c = channel_index[type]++;
1796
1797		if (!info_map[type]) {
1798			info_map[type] = devm_kcalloc(dev, channel_count[type],
1799						      sizeof(*info_map),
1800						      GFP_KERNEL);
1801			if (!info_map[type])
1802				return -ENOMEM;
1803		}
1804
1805		info_map[type][c] = info;
1806	}
1807
1808	*out_info = info_arr;
1809	*out_icount = icount;
1810	*out_count = count;
1811	*out_is_new = is_new;
1812
1813	return 0;
1814}
1815
1816static bool find_event_attributes(struct hp_wmi_sensors *state,
1817				  struct hp_wmi_platform_events *pevents,
1818				  u8 pevents_count)
1819{
1820	/*
1821	 * The existence of this HPBIOS_PlatformEvents instance:
1822	 *
1823	 *   {
1824	 *     Name = "Rear Chassis Fan0 Stall";
1825	 *     Description = "Rear Chassis Fan0 Speed";
1826	 *     Category = 3;           // "Sensor"
1827	 *     PossibleSeverity = 25;  // "Critical Failure"
1828	 *     PossibleStatus = 5;     // "Predictive Failure"
1829	 *     [...]
1830	 *   }
1831	 *
1832	 * means that this HPBIOS_BIOSEvent instance may occur:
1833	 *
1834	 *   {
1835	 *     Name = "Rear Chassis Fan0 Stall";
1836	 *     Description = "Rear Chassis Fan0 Speed";
1837	 *     Category = 3;           // "Sensor"
1838	 *     Severity = 25;          // "Critical Failure"
1839	 *     Status = 5;             // "Predictive Failure"
1840	 *   }
1841	 *
1842	 * After the event occurs (e.g. because the fan was unplugged),
1843	 * polling the related HPBIOS_BIOSNumericSensor instance gives:
1844	 *
1845	 *   {
1846	 *      Name = "Rear Chassis Fan0";
1847	 *      Description = "Reports rear chassis fan0 speed";
1848	 *      OperationalStatus = 5; // "Predictive Failure", was 3 ("OK")
1849	 *      CurrentReading = 0;
1850	 *      [...]
1851	 *   }
1852	 *
1853	 * In this example, the hwmon fan channel for "Rear Chassis Fan0"
1854	 * should support the alarm flag and have it be set if the related
1855	 * HPBIOS_BIOSEvent instance occurs.
1856	 *
1857	 * In addition to fan events, temperature (CPU/chassis) and intrusion
1858	 * events are relevant to hwmon [2]. Note that much information in [2]
1859	 * is unreliable; it is referenced in addition to ACPI dumps [3] merely
1860	 * to support the conclusion that sensor and event names/descriptions
1861	 * are systematic enough to allow this driver to match them.
1862	 *
1863	 * Complications and limitations:
1864	 *
1865	 * - Strings are freeform and may vary, cf. sensor Name "CPU0 Fan"
1866	 *   on a Z420 vs. "CPU Fan Speed" on an EliteOne 800 G1.
1867	 * - Leading/trailing whitespace is a rare but real possibility [3].
1868	 * - The HPBIOS_PlatformEvents object may not exist or its instances
1869	 *   may show that the system only has e.g. BIOS setting-related
1870	 *   events (cf. the ProBook 4540s and ProBook 470 G0 [3]).
1871	 */
1872
1873	struct hp_wmi_info *temp_info[HP_WMI_MAX_INSTANCES] = {};
1874	const char *event_description;
1875	struct hp_wmi_info *fan_info;
1876	bool has_events = false;
1877	const char *event_name;
1878	u32 event_category;
1879	int event_type;
1880	u8 count;
1881	u8 i;
1882
1883	for (i = 0; i < pevents_count; i++, pevents++) {
1884		event_name = pevents->name;
1885		event_description = pevents->description;
1886		event_category = pevents->category;
1887
1888		event_type = classify_event(event_name, event_category);
1889		switch (event_type) {
1890		case HP_WMI_TYPE_AIR_FLOW:
1891			fan_info = match_fan_event(state, event_description);
1892			if (!fan_info)
1893				break;
1894
1895			fan_info->has_alarm = true;
1896			has_events = true;
1897			break;
1898
1899		case HP_WMI_TYPE_INTRUSION:
1900			state->has_intrusion = true;
1901			has_events = true;
1902			break;
1903
1904		case HP_WMI_TYPE_TEMPERATURE:
1905			count = match_temp_events(state, event_description,
1906						  temp_info);
1907			if (!count)
1908				break;
1909
1910			while (count)
1911				temp_info[--count]->has_alarm = true;
1912			has_events = true;
1913			break;
1914
1915		default:
1916			break;
1917		}
1918	}
1919
1920	return has_events;
1921}
1922
1923static int make_chip_info(struct hp_wmi_sensors *state, bool has_events)
1924{
1925	const struct hwmon_channel_info **ptr_channel_info;
1926	struct hp_wmi_info ***info_map = state->info_map;
1927	u8 *channel_count = state->channel_count;
1928	struct hwmon_channel_info *channel_info;
1929	struct device *dev = &state->wdev->dev;
1930	enum hwmon_sensor_types type;
1931	u8 type_count = 0;
1932	u32 *config;
1933	u32 attr;
1934	u8 count;
1935	u8 i;
1936
1937	if (channel_count[hwmon_temp])
1938		channel_count[hwmon_chip] = 1;
1939
1940	if (has_events && state->has_intrusion)
1941		channel_count[hwmon_intrusion] = 1;
1942
1943	for (type = hwmon_chip; type < hwmon_max; type++)
1944		if (channel_count[type])
1945			type_count++;
1946
1947	channel_info = devm_kcalloc(dev, type_count,
1948				    sizeof(*channel_info), GFP_KERNEL);
1949	if (!channel_info)
1950		return -ENOMEM;
1951
1952	ptr_channel_info = devm_kcalloc(dev, type_count + 1,
1953					sizeof(*ptr_channel_info), GFP_KERNEL);
1954	if (!ptr_channel_info)
1955		return -ENOMEM;
1956
1957	hp_wmi_chip_info.info = ptr_channel_info;
1958
1959	for (type = hwmon_chip; type < hwmon_max; type++) {
1960		count = channel_count[type];
1961		if (!count)
1962			continue;
1963
1964		config = devm_kcalloc(dev, count + 1,
1965				      sizeof(*config), GFP_KERNEL);
1966		if (!config)
1967			return -ENOMEM;
1968
1969		attr = hp_wmi_hwmon_attributes[type];
1970		channel_info->type = type;
1971		channel_info->config = config;
1972		memset32(config, attr, count);
1973
1974		*ptr_channel_info++ = channel_info++;
1975
1976		if (!has_events || (type != hwmon_temp && type != hwmon_fan))
1977			continue;
1978
1979		attr = type == hwmon_temp ? HWMON_T_ALARM : HWMON_F_ALARM;
1980
1981		for (i = 0; i < count; i++)
1982			if (info_map[type][i]->has_alarm)
1983				config[i] |= attr;
1984	}
1985
1986	return 0;
1987}
1988
1989static bool add_event_handler(struct hp_wmi_sensors *state)
1990{
1991	struct device *dev = &state->wdev->dev;
1992	int err;
1993
1994	err = wmi_install_notify_handler(HP_WMI_EVENT_GUID,
1995					 hp_wmi_notify, state);
1996	if (err) {
1997		dev_info(dev, "Failed to subscribe to WMI event\n");
1998		return false;
1999	}
2000
2001	err = devm_add_action_or_reset(dev, hp_wmi_devm_notify_remove, NULL);
2002	if (err)
2003		return false;
2004
2005	return true;
2006}
2007
2008static int hp_wmi_sensors_init(struct hp_wmi_sensors *state)
2009{
2010	struct hp_wmi_info *connected[HP_WMI_MAX_INSTANCES];
2011	struct hp_wmi_platform_events *pevents = NULL;
2012	struct device *dev = &state->wdev->dev;
2013	struct hp_wmi_info *info;
2014	struct device *hwdev;
2015	bool has_events;
2016	bool is_new;
2017	u8 icount;
2018	u8 pcount;
2019	u8 count;
2020	int err;
2021
2022	err = init_platform_events(dev, &pevents, &pcount);
2023	if (err)
2024		return err;
2025
2026	err = init_numeric_sensors(state, connected, &info,
2027				   &icount, &count, &is_new);
2028	if (err)
2029		return err;
2030
2031	if (IS_ENABLED(CONFIG_DEBUG_FS))
2032		hp_wmi_debugfs_init(dev, info, pevents, icount, pcount, is_new);
2033
2034	if (!count)
2035		return 0;	/* No connected sensors; debugfs only. */
2036
2037	has_events = find_event_attributes(state, pevents, pcount);
2038
2039	/* Survive failure to install WMI event handler. */
2040	if (has_events && !add_event_handler(state))
2041		has_events = false;
2042
2043	err = make_chip_info(state, has_events);
2044	if (err)
2045		return err;
2046
2047	hwdev = devm_hwmon_device_register_with_info(dev, "hp_wmi_sensors",
2048						     state, &hp_wmi_chip_info,
2049						     NULL);
2050	return PTR_ERR_OR_ZERO(hwdev);
2051}
2052
2053static int hp_wmi_sensors_probe(struct wmi_device *wdev, const void *context)
2054{
2055	struct device *dev = &wdev->dev;
2056	struct hp_wmi_sensors *state;
2057
2058	state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
2059	if (!state)
2060		return -ENOMEM;
2061
2062	state->wdev = wdev;
2063
2064	mutex_init(&state->lock);
2065
2066	dev_set_drvdata(dev, state);
2067
2068	return hp_wmi_sensors_init(state);
2069}
2070
2071static const struct wmi_device_id hp_wmi_sensors_id_table[] = {
2072	{ HP_WMI_NUMERIC_SENSOR_GUID, NULL },
2073	{},
2074};
2075
2076static struct wmi_driver hp_wmi_sensors_driver = {
2077	.driver   = { .name = "hp-wmi-sensors" },
2078	.id_table = hp_wmi_sensors_id_table,
2079	.probe    = hp_wmi_sensors_probe,
2080};
2081module_wmi_driver(hp_wmi_sensors_driver);
2082
2083MODULE_AUTHOR("James Seo <james@equiv.tech>");
2084MODULE_DESCRIPTION("HP WMI Sensors driver");
2085MODULE_LICENSE("GPL");