File Index
Files and directories
Sign in
FILE

dell-wmi-ddv.c

File preview with syntax highlighting.

linux-6.19.14/drivers/platform/x86/dell/dell-wmi-ddv.c C
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Linux driver for WMI sensor information on Dell notebooks.
   4 *
   5 * Copyright (C) 2022 Armin Wolf <W_Armin@gmx.de>
   6 */
   7
   8#define pr_format(fmt) KBUILD_MODNAME ": " fmt
   9
  10#include <linux/acpi.h>
  11#include <linux/bitfield.h>
  12#include <linux/debugfs.h>
  13#include <linux/device.h>
  14#include <linux/device/driver.h>
  15#include <linux/dev_printk.h>
  16#include <linux/errno.h>
  17#include <linux/kconfig.h>
  18#include <linux/kernel.h>
  19#include <linux/hwmon.h>
  20#include <linux/kstrtox.h>
  21#include <linux/math64.h>
  22#include <linux/module.h>
  23#include <linux/mutex.h>
  24#include <linux/limits.h>
  25#include <linux/pm.h>
  26#include <linux/power_supply.h>
  27#include <linux/printk.h>
  28#include <linux/seq_file.h>
  29#include <linux/sysfs.h>
  30#include <linux/types.h>
  31#include <linux/wmi.h>
  32
  33#include <acpi/battery.h>
  34
  35#include <linux/unaligned.h>
  36
  37#define DRIVER_NAME	"dell-wmi-ddv"
  38
  39#define DELL_DDV_SUPPORTED_VERSION_MIN	2
  40#define DELL_DDV_SUPPORTED_VERSION_MAX	3
  41#define DELL_DDV_GUID	"8A42EA14-4F2A-FD45-6422-0087F7A7E608"
  42
  43/* Battery indices 1, 2 and 3 */
  44#define DELL_DDV_NUM_BATTERIES		3
  45
  46#define SBS_MANUFACTURE_YEAR_MASK	GENMASK(15, 9)
  47#define SBS_MANUFACTURE_MONTH_MASK	GENMASK(8, 5)
  48#define SBS_MANUFACTURE_DAY_MASK	GENMASK(4, 0)
  49
  50#define MA_FAILURE_MODE_MASK			GENMASK(11, 8)
  51#define MA_FAILURE_MODE_PERMANENT		0x9
  52#define MA_FAILURE_MODE_OVERHEAT		0xA
  53#define MA_FAILURE_MODE_OVERCURRENT		0xB
  54
  55#define MA_PERMANENT_FAILURE_CODE_MASK		GENMASK(13, 12)
  56#define MA_PERMANENT_FAILURE_FUSE_BLOWN		0x0
  57#define MA_PERMANENT_FAILURE_CELL_IMBALANCE	0x1
  58#define MA_PERMANENT_FAILURE_OVERVOLTAGE	0x2
  59#define MA_PERMANENT_FAILURE_FET_FAILURE	0x3
  60
  61#define MA_OVERHEAT_FAILURE_CODE_MASK		GENMASK(15, 12)
  62#define MA_OVERHEAT_FAILURE_START		0x5
  63#define MA_OVERHEAT_FAILURE_CHARGING		0x7
  64#define MA_OVERHEAT_FAILURE_DISCHARGING		0x8
  65
  66#define MA_OVERCURRENT_FAILURE_CODE_MASK	GENMASK(15, 12)
  67#define MA_OVERCURRENT_FAILURE_CHARGING		0x6
  68#define MA_OVERCURRENT_FAILURE_DISCHARGING	0xB
  69
  70#define DELL_EPPID_LENGTH	20
  71#define DELL_EPPID_EXT_LENGTH	23
  72
  73static bool force;
  74module_param_unsafe(force, bool, 0);
  75MODULE_PARM_DESC(force, "Force loading without checking for supported WMI interface versions");
  76
  77enum dell_ddv_method {
  78	DELL_DDV_BATTERY_DESIGN_CAPACITY	= 0x01,
  79	DELL_DDV_BATTERY_FULL_CHARGE_CAPACITY	= 0x02,
  80	DELL_DDV_BATTERY_MANUFACTURE_NAME	= 0x03,
  81	DELL_DDV_BATTERY_MANUFACTURE_DATE	= 0x04,
  82	DELL_DDV_BATTERY_SERIAL_NUMBER		= 0x05,
  83	DELL_DDV_BATTERY_CHEMISTRY_VALUE	= 0x06,
  84	DELL_DDV_BATTERY_TEMPERATURE		= 0x07,
  85	DELL_DDV_BATTERY_CURRENT		= 0x08,
  86	DELL_DDV_BATTERY_VOLTAGE		= 0x09,
  87	DELL_DDV_BATTERY_MANUFACTURER_ACCESS	= 0x0A,
  88	DELL_DDV_BATTERY_RELATIVE_CHARGE_STATE	= 0x0B,
  89	DELL_DDV_BATTERY_CYCLE_COUNT		= 0x0C,
  90	DELL_DDV_BATTERY_EPPID			= 0x0D,
  91	DELL_DDV_BATTERY_RAW_ANALYTICS_START	= 0x0E,
  92	DELL_DDV_BATTERY_RAW_ANALYTICS		= 0x0F,
  93	DELL_DDV_BATTERY_DESIGN_VOLTAGE		= 0x10,
  94	DELL_DDV_BATTERY_RAW_ANALYTICS_A_BLOCK	= 0x11, /* version 3 */
  95
  96	DELL_DDV_INTERFACE_VERSION		= 0x12,
  97
  98	DELL_DDV_FAN_SENSOR_INFORMATION		= 0x20,
  99	DELL_DDV_THERMAL_SENSOR_INFORMATION	= 0x22,
 100};
 101
 102struct fan_sensor_entry {
 103	u8 type;
 104	__le16 rpm;
 105} __packed;
 106
 107struct thermal_sensor_entry {
 108	u8 type;
 109	s8 now;
 110	s8 min;
 111	s8 max;
 112	u8 unknown;
 113} __packed;
 114
 115struct combined_channel_info {
 116	struct hwmon_channel_info info;
 117	u32 config[];
 118};
 119
 120struct combined_chip_info {
 121	struct hwmon_chip_info chip;
 122	const struct hwmon_channel_info *info[];
 123};
 124
 125struct dell_wmi_ddv_sensors {
 126	bool active;
 127	struct mutex lock;	/* protect caching */
 128	unsigned long timestamp;
 129	union acpi_object *obj;
 130	u64 entries;
 131};
 132
 133struct dell_wmi_ddv_data {
 134	struct acpi_battery_hook hook;
 135	struct device_attribute eppid_attr;
 136	struct mutex translation_cache_lock;	/* Protects the translation cache */
 137	struct power_supply *translation_cache[DELL_DDV_NUM_BATTERIES];
 138	struct dell_wmi_ddv_sensors fans;
 139	struct dell_wmi_ddv_sensors temps;
 140	struct wmi_device *wdev;
 141};
 142
 143static const char * const fan_labels[] = {
 144	"CPU Fan",
 145	"Chassis Motherboard Fan",
 146	"Video Fan",
 147	"Power Supply Fan",
 148	"Chipset Fan",
 149	"Memory Fan",
 150	"PCI Fan",
 151	"HDD Fan",
 152};
 153
 154static const char * const fan_dock_labels[] = {
 155	"Docking Chassis/Motherboard Fan",
 156	"Docking Video Fan",
 157	"Docking Power Supply Fan",
 158	"Docking Chipset Fan",
 159};
 160
 161static int dell_wmi_ddv_query_type(struct wmi_device *wdev, enum dell_ddv_method method, u32 arg,
 162				   union acpi_object **result, acpi_object_type type)
 163{
 164	struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
 165	const struct acpi_buffer in = {
 166		.length = sizeof(arg),
 167		.pointer = &arg,
 168	};
 169	union acpi_object *obj;
 170	acpi_status ret;
 171
 172	ret = wmidev_evaluate_method(wdev, 0x0, method, &in, &out);
 173	if (ACPI_FAILURE(ret))
 174		return -EIO;
 175
 176	obj = out.pointer;
 177	if (!obj)
 178		return -ENODATA;
 179
 180	if (obj->type != type) {
 181		kfree(obj);
 182		return -ENOMSG;
 183	}
 184
 185	*result = obj;
 186
 187	return 0;
 188}
 189
 190static int dell_wmi_ddv_query_integer(struct wmi_device *wdev, enum dell_ddv_method method,
 191				      u32 arg, u32 *res)
 192{
 193	union acpi_object *obj;
 194	int ret;
 195
 196	ret = dell_wmi_ddv_query_type(wdev, method, arg, &obj, ACPI_TYPE_INTEGER);
 197	if (ret < 0)
 198		return ret;
 199
 200	if (obj->integer.value <= U32_MAX)
 201		*res = (u32)obj->integer.value;
 202	else
 203		ret = -ERANGE;
 204
 205	kfree(obj);
 206
 207	return ret;
 208}
 209
 210static int dell_wmi_ddv_query_buffer(struct wmi_device *wdev, enum dell_ddv_method method,
 211				     u32 arg, union acpi_object **result)
 212{
 213	union acpi_object *obj;
 214	u64 buffer_size;
 215	int ret;
 216
 217	ret = dell_wmi_ddv_query_type(wdev, method, arg, &obj, ACPI_TYPE_PACKAGE);
 218	if (ret < 0)
 219		return ret;
 220
 221	if (obj->package.count != 2 ||
 222	    obj->package.elements[0].type != ACPI_TYPE_INTEGER ||
 223	    obj->package.elements[1].type != ACPI_TYPE_BUFFER) {
 224		ret = -ENOMSG;
 225
 226		goto err_free;
 227	}
 228
 229	buffer_size = obj->package.elements[0].integer.value;
 230
 231	if (!buffer_size) {
 232		ret = -ENODATA;
 233
 234		goto err_free;
 235	}
 236
 237	if (buffer_size > obj->package.elements[1].buffer.length) {
 238		dev_warn(&wdev->dev,
 239			 FW_WARN "WMI buffer size (%llu) exceeds ACPI buffer size (%d)\n",
 240			 buffer_size, obj->package.elements[1].buffer.length);
 241		ret = -EMSGSIZE;
 242
 243		goto err_free;
 244	}
 245
 246	*result = obj;
 247
 248	return 0;
 249
 250err_free:
 251	kfree(obj);
 252
 253	return ret;
 254}
 255
 256static int dell_wmi_ddv_query_string(struct wmi_device *wdev, enum dell_ddv_method method,
 257				     u32 arg, union acpi_object **result)
 258{
 259	return dell_wmi_ddv_query_type(wdev, method, arg, result, ACPI_TYPE_STRING);
 260}
 261
 262/*
 263 * Needs to be called with lock held, except during initialization.
 264 */
 265static int dell_wmi_ddv_update_sensors(struct wmi_device *wdev, enum dell_ddv_method method,
 266				       struct dell_wmi_ddv_sensors *sensors, size_t entry_size)
 267{
 268	u64 buffer_size, rem, entries;
 269	union acpi_object *obj;
 270	u8 *buffer;
 271	int ret;
 272
 273	if (sensors->obj) {
 274		if (time_before(jiffies, sensors->timestamp + HZ))
 275			return 0;
 276
 277		kfree(sensors->obj);
 278		sensors->obj = NULL;
 279	}
 280
 281	ret = dell_wmi_ddv_query_buffer(wdev, method, 0, &obj);
 282	if (ret < 0)
 283		return ret;
 284
 285	/* buffer format sanity check */
 286	buffer_size = obj->package.elements[0].integer.value;
 287	buffer = obj->package.elements[1].buffer.pointer;
 288	entries = div64_u64_rem(buffer_size, entry_size, &rem);
 289	if (rem != 1 || buffer[buffer_size - 1] != 0xff) {
 290		ret = -ENOMSG;
 291		goto err_free;
 292	}
 293
 294	if (!entries) {
 295		ret = -ENODATA;
 296		goto err_free;
 297	}
 298
 299	sensors->obj = obj;
 300	sensors->entries = entries;
 301	sensors->timestamp = jiffies;
 302
 303	return 0;
 304
 305err_free:
 306	kfree(obj);
 307
 308	return ret;
 309}
 310
 311static umode_t dell_wmi_ddv_is_visible(const void *drvdata, enum hwmon_sensor_types type, u32 attr,
 312				       int channel)
 313{
 314	return 0444;
 315}
 316
 317static int dell_wmi_ddv_fan_read_channel(struct dell_wmi_ddv_data *data, u32 attr, int channel,
 318					 long *val)
 319{
 320	struct fan_sensor_entry *entry;
 321	int ret;
 322
 323	ret = dell_wmi_ddv_update_sensors(data->wdev, DELL_DDV_FAN_SENSOR_INFORMATION,
 324					  &data->fans, sizeof(*entry));
 325	if (ret < 0)
 326		return ret;
 327
 328	if (channel >= data->fans.entries)
 329		return -ENXIO;
 330
 331	entry = (struct fan_sensor_entry *)data->fans.obj->package.elements[1].buffer.pointer;
 332	switch (attr) {
 333	case hwmon_fan_input:
 334		*val = get_unaligned_le16(&entry[channel].rpm);
 335		return 0;
 336	default:
 337		break;
 338	}
 339
 340	return -EOPNOTSUPP;
 341}
 342
 343static int dell_wmi_ddv_temp_read_channel(struct dell_wmi_ddv_data *data, u32 attr, int channel,
 344					  long *val)
 345{
 346	struct thermal_sensor_entry *entry;
 347	int ret;
 348
 349	ret = dell_wmi_ddv_update_sensors(data->wdev, DELL_DDV_THERMAL_SENSOR_INFORMATION,
 350					  &data->temps, sizeof(*entry));
 351	if (ret < 0)
 352		return ret;
 353
 354	if (channel >= data->temps.entries)
 355		return -ENXIO;
 356
 357	entry = (struct thermal_sensor_entry *)data->temps.obj->package.elements[1].buffer.pointer;
 358	switch (attr) {
 359	case hwmon_temp_input:
 360		*val = entry[channel].now * 1000;
 361		return 0;
 362	case hwmon_temp_min:
 363		*val = entry[channel].min * 1000;
 364		return 0;
 365	case hwmon_temp_max:
 366		*val = entry[channel].max * 1000;
 367		return 0;
 368	default:
 369		break;
 370	}
 371
 372	return -EOPNOTSUPP;
 373}
 374
 375static int dell_wmi_ddv_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
 376			     int channel, long *val)
 377{
 378	struct dell_wmi_ddv_data *data = dev_get_drvdata(dev);
 379	int ret;
 380
 381	switch (type) {
 382	case hwmon_fan:
 383		mutex_lock(&data->fans.lock);
 384		ret = dell_wmi_ddv_fan_read_channel(data, attr, channel, val);
 385		mutex_unlock(&data->fans.lock);
 386		return ret;
 387	case hwmon_temp:
 388		mutex_lock(&data->temps.lock);
 389		ret = dell_wmi_ddv_temp_read_channel(data, attr, channel, val);
 390		mutex_unlock(&data->temps.lock);
 391		return ret;
 392	default:
 393		break;
 394	}
 395
 396	return -EOPNOTSUPP;
 397}
 398
 399static int dell_wmi_ddv_fan_read_string(struct dell_wmi_ddv_data *data, int channel,
 400					const char **str)
 401{
 402	struct fan_sensor_entry *entry;
 403	int ret;
 404	u8 type;
 405
 406	ret = dell_wmi_ddv_update_sensors(data->wdev, DELL_DDV_FAN_SENSOR_INFORMATION,
 407					  &data->fans, sizeof(*entry));
 408	if (ret < 0)
 409		return ret;
 410
 411	if (channel >= data->fans.entries)
 412		return -ENXIO;
 413
 414	entry = (struct fan_sensor_entry *)data->fans.obj->package.elements[1].buffer.pointer;
 415	type = entry[channel].type;
 416	switch (type) {
 417	case 0x00 ... 0x07:
 418		*str = fan_labels[type];
 419		break;
 420	case 0x11 ... 0x14:
 421		*str = fan_dock_labels[type - 0x11];
 422		break;
 423	default:
 424		*str = "Unknown Fan";
 425		break;
 426	}
 427
 428	return 0;
 429}
 430
 431static int dell_wmi_ddv_temp_read_string(struct dell_wmi_ddv_data *data, int channel,
 432					 const char **str)
 433{
 434	struct thermal_sensor_entry *entry;
 435	int ret;
 436
 437	ret = dell_wmi_ddv_update_sensors(data->wdev, DELL_DDV_THERMAL_SENSOR_INFORMATION,
 438					  &data->temps, sizeof(*entry));
 439	if (ret < 0)
 440		return ret;
 441
 442	if (channel >= data->temps.entries)
 443		return -ENXIO;
 444
 445	entry = (struct thermal_sensor_entry *)data->temps.obj->package.elements[1].buffer.pointer;
 446	switch (entry[channel].type) {
 447	case 0x00:
 448		*str = "CPU";
 449		break;
 450	case 0x11:
 451		*str = "Video";
 452		break;
 453	case 0x22:
 454		*str = "Memory"; /* sometimes called DIMM */
 455		break;
 456	case 0x33:
 457		*str = "Other";
 458		break;
 459	case 0x44:
 460		*str = "Ambient"; /* sometimes called SKIN */
 461		break;
 462	case 0x52:
 463		*str = "SODIMM";
 464		break;
 465	case 0x55:
 466		*str = "HDD";
 467		break;
 468	case 0x62:
 469		*str = "SODIMM 2";
 470		break;
 471	case 0x73:
 472		*str = "NB";
 473		break;
 474	case 0x83:
 475		*str = "Charger";
 476		break;
 477	case 0xbb:
 478		*str = "Memory 3";
 479		break;
 480	default:
 481		*str = "Unknown";
 482		break;
 483	}
 484
 485	return 0;
 486}
 487
 488static int dell_wmi_ddv_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr,
 489				    int channel, const char **str)
 490{
 491	struct dell_wmi_ddv_data *data = dev_get_drvdata(dev);
 492	int ret;
 493
 494	switch (type) {
 495	case hwmon_fan:
 496		switch (attr) {
 497		case hwmon_fan_label:
 498			mutex_lock(&data->fans.lock);
 499			ret = dell_wmi_ddv_fan_read_string(data, channel, str);
 500			mutex_unlock(&data->fans.lock);
 501			return ret;
 502		default:
 503			break;
 504		}
 505		break;
 506	case hwmon_temp:
 507		switch (attr) {
 508		case hwmon_temp_label:
 509			mutex_lock(&data->temps.lock);
 510			ret = dell_wmi_ddv_temp_read_string(data, channel, str);
 511			mutex_unlock(&data->temps.lock);
 512			return ret;
 513		default:
 514			break;
 515		}
 516		break;
 517	default:
 518		break;
 519	}
 520
 521	return -EOPNOTSUPP;
 522}
 523
 524static const struct hwmon_ops dell_wmi_ddv_ops = {
 525	.is_visible = dell_wmi_ddv_is_visible,
 526	.read = dell_wmi_ddv_read,
 527	.read_string = dell_wmi_ddv_read_string,
 528};
 529
 530static struct hwmon_channel_info *dell_wmi_ddv_channel_create(struct device *dev, u64 count,
 531							      enum hwmon_sensor_types type,
 532							      u32 config)
 533{
 534	struct combined_channel_info *cinfo;
 535	int i;
 536
 537	cinfo = devm_kzalloc(dev, struct_size(cinfo, config, count + 1), GFP_KERNEL);
 538	if (!cinfo)
 539		return ERR_PTR(-ENOMEM);
 540
 541	cinfo->info.type = type;
 542	cinfo->info.config = cinfo->config;
 543
 544	for (i = 0; i < count; i++)
 545		cinfo->config[i] = config;
 546
 547	return &cinfo->info;
 548}
 549
 550static void dell_wmi_ddv_hwmon_cache_invalidate(struct dell_wmi_ddv_sensors *sensors)
 551{
 552	if (!sensors->active)
 553		return;
 554
 555	mutex_lock(&sensors->lock);
 556	kfree(sensors->obj);
 557	sensors->obj = NULL;
 558	mutex_unlock(&sensors->lock);
 559}
 560
 561static void dell_wmi_ddv_hwmon_cache_destroy(void *data)
 562{
 563	struct dell_wmi_ddv_sensors *sensors = data;
 564
 565	sensors->active = false;
 566	mutex_destroy(&sensors->lock);
 567	kfree(sensors->obj);
 568}
 569
 570static struct hwmon_channel_info *dell_wmi_ddv_channel_init(struct wmi_device *wdev,
 571							    enum dell_ddv_method method,
 572							    struct dell_wmi_ddv_sensors *sensors,
 573							    size_t entry_size,
 574							    enum hwmon_sensor_types type,
 575							    u32 config)
 576{
 577	struct hwmon_channel_info *info;
 578	int ret;
 579
 580	ret = dell_wmi_ddv_update_sensors(wdev, method, sensors, entry_size);
 581	if (ret < 0)
 582		return ERR_PTR(ret);
 583
 584	mutex_init(&sensors->lock);
 585	sensors->active = true;
 586
 587	ret = devm_add_action_or_reset(&wdev->dev, dell_wmi_ddv_hwmon_cache_destroy, sensors);
 588	if (ret < 0)
 589		return ERR_PTR(ret);
 590
 591	info = dell_wmi_ddv_channel_create(&wdev->dev, sensors->entries, type, config);
 592	if (IS_ERR(info))
 593		devm_release_action(&wdev->dev, dell_wmi_ddv_hwmon_cache_destroy, sensors);
 594
 595	return info;
 596}
 597
 598static int dell_wmi_ddv_hwmon_add(struct dell_wmi_ddv_data *data)
 599{
 600	struct wmi_device *wdev = data->wdev;
 601	struct combined_chip_info *cinfo;
 602	struct hwmon_channel_info *info;
 603	struct device *hdev;
 604	int index = 0;
 605	int ret;
 606
 607	if (!devres_open_group(&wdev->dev, dell_wmi_ddv_hwmon_add, GFP_KERNEL))
 608		return -ENOMEM;
 609
 610	cinfo = devm_kzalloc(&wdev->dev, struct_size(cinfo, info, 4), GFP_KERNEL);
 611	if (!cinfo) {
 612		ret = -ENOMEM;
 613
 614		goto err_release;
 615	}
 616
 617	cinfo->chip.ops = &dell_wmi_ddv_ops;
 618	cinfo->chip.info = cinfo->info;
 619
 620	info = dell_wmi_ddv_channel_create(&wdev->dev, 1, hwmon_chip, HWMON_C_REGISTER_TZ);
 621	if (IS_ERR(info)) {
 622		ret = PTR_ERR(info);
 623
 624		goto err_release;
 625	}
 626
 627	cinfo->info[index] = info;
 628	index++;
 629
 630	info = dell_wmi_ddv_channel_init(wdev, DELL_DDV_FAN_SENSOR_INFORMATION, &data->fans,
 631					 sizeof(struct fan_sensor_entry), hwmon_fan,
 632					 (HWMON_F_INPUT | HWMON_F_LABEL));
 633	if (!IS_ERR(info)) {
 634		cinfo->info[index] = info;
 635		index++;
 636	}
 637
 638	info = dell_wmi_ddv_channel_init(wdev, DELL_DDV_THERMAL_SENSOR_INFORMATION, &data->temps,
 639					 sizeof(struct thermal_sensor_entry), hwmon_temp,
 640					 (HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |
 641					 HWMON_T_LABEL));
 642	if (!IS_ERR(info)) {
 643		cinfo->info[index] = info;
 644		index++;
 645	}
 646
 647	if (index < 2) {
 648		/* Finding no available sensors is not an error */
 649		ret = 0;
 650
 651		goto err_release;
 652	}
 653
 654	hdev = devm_hwmon_device_register_with_info(&wdev->dev, "dell_ddv", data, &cinfo->chip,
 655						    NULL);
 656	if (IS_ERR(hdev)) {
 657		ret = PTR_ERR(hdev);
 658
 659		goto err_release;
 660	}
 661
 662	devres_close_group(&wdev->dev, dell_wmi_ddv_hwmon_add);
 663
 664	return 0;
 665
 666err_release:
 667	devres_release_group(&wdev->dev, dell_wmi_ddv_hwmon_add);
 668
 669	return ret;
 670}
 671
 672static int dell_wmi_ddv_battery_translate(struct dell_wmi_ddv_data *data,
 673					  struct power_supply *battery, u32 *index)
 674{
 675	u32 serial_dec, serial_hex, serial;
 676	union power_supply_propval val;
 677	int ret;
 678
 679	guard(mutex)(&data->translation_cache_lock);
 680
 681	for (int i = 0; i < ARRAY_SIZE(data->translation_cache); i++) {
 682		if (data->translation_cache[i] == battery) {
 683			dev_dbg(&data->wdev->dev, "Translation cache hit for battery index %u\n",
 684				i + 1);
 685			*index = i + 1;
 686			return 0;
 687		}
 688	}
 689
 690	dev_dbg(&data->wdev->dev, "Translation cache miss\n");
 691
 692	/*
 693	 * Perform a translation between a ACPI battery and a battery index.
 694	 * We have to use power_supply_get_property_direct() here because this
 695	 * function will also get called from the callbacks of the power supply
 696	 * extension.
 697	 */
 698	ret = power_supply_get_property_direct(battery, POWER_SUPPLY_PROP_SERIAL_NUMBER, &val);
 699	if (ret < 0)
 700		return ret;
 701
 702	/*
 703	 * Some devices display the serial number of the ACPI battery (string!) as a decimal
 704	 * number while other devices display it as a hexadecimal number. Because of this we
 705	 * have to check both cases.
 706	 */
 707	ret = kstrtou32(val.strval, 16, &serial_hex);
 708	if (ret < 0)
 709		return ret;	/* Should never fail */
 710
 711	ret = kstrtou32(val.strval, 10, &serial_dec);
 712	if (ret < 0)
 713		serial_dec = 0; /* Can fail, thus we only mark serial_dec as invalid */
 714
 715	for (int i = 0; i < ARRAY_SIZE(data->translation_cache); i++) {
 716		ret = dell_wmi_ddv_query_integer(data->wdev, DELL_DDV_BATTERY_SERIAL_NUMBER, i + 1,
 717						 &serial);
 718		if (ret < 0)
 719			return ret;
 720
 721		/* A serial number of 0 signals that this index is not associated with a battery */
 722		if (!serial)
 723			continue;
 724
 725		if (serial == serial_dec || serial == serial_hex) {
 726			dev_dbg(&data->wdev->dev, "Translation cache update for battery index %u\n",
 727				i + 1);
 728			data->translation_cache[i] = battery;
 729			*index = i + 1;
 730			return 0;
 731		}
 732	}
 733
 734	return -ENODEV;
 735}
 736
 737static void dell_wmi_battery_invalidate(struct dell_wmi_ddv_data *data,
 738					struct power_supply *battery)
 739{
 740	guard(mutex)(&data->translation_cache_lock);
 741
 742	for (int i = 0; i < ARRAY_SIZE(data->translation_cache); i++) {
 743		if (data->translation_cache[i] == battery) {
 744			data->translation_cache[i] = NULL;
 745			return;
 746		}
 747	}
 748}
 749
 750static ssize_t eppid_show(struct device *dev, struct device_attribute *attr, char *buf)
 751{
 752	struct dell_wmi_ddv_data *data = container_of(attr, struct dell_wmi_ddv_data, eppid_attr);
 753	union acpi_object *obj;
 754	u32 index;
 755	int ret;
 756
 757	ret = dell_wmi_ddv_battery_translate(data, to_power_supply(dev), &index);
 758	if (ret < 0)
 759		return ret;
 760
 761	ret = dell_wmi_ddv_query_string(data->wdev, DELL_DDV_BATTERY_EPPID, index, &obj);
 762	if (ret < 0)
 763		return ret;
 764
 765	if (obj->string.length != DELL_EPPID_LENGTH && obj->string.length != DELL_EPPID_EXT_LENGTH)
 766		dev_info_once(&data->wdev->dev, FW_INFO "Suspicious ePPID length (%d)\n",
 767			      obj->string.length);
 768
 769	ret = sysfs_emit(buf, "%s\n", obj->string.pointer);
 770
 771	kfree(obj);
 772
 773	return ret;
 774}
 775
 776static int dell_wmi_ddv_get_health(struct dell_wmi_ddv_data *data, u32 index,
 777				   union power_supply_propval *val)
 778{
 779	u32 value, code;
 780	int ret;
 781
 782	ret = dell_wmi_ddv_query_integer(data->wdev, DELL_DDV_BATTERY_MANUFACTURER_ACCESS, index,
 783					 &value);
 784	if (ret < 0)
 785		return ret;
 786
 787	switch (FIELD_GET(MA_FAILURE_MODE_MASK, value)) {
 788	case MA_FAILURE_MODE_PERMANENT:
 789		code = FIELD_GET(MA_PERMANENT_FAILURE_CODE_MASK, value);
 790		switch (code) {
 791		case MA_PERMANENT_FAILURE_FUSE_BLOWN:
 792			val->intval = POWER_SUPPLY_HEALTH_BLOWN_FUSE;
 793			return 0;
 794		case MA_PERMANENT_FAILURE_CELL_IMBALANCE:
 795			val->intval = POWER_SUPPLY_HEALTH_CELL_IMBALANCE;
 796			return 0;
 797		case MA_PERMANENT_FAILURE_OVERVOLTAGE:
 798			val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
 799			return 0;
 800		case MA_PERMANENT_FAILURE_FET_FAILURE:
 801			val->intval = POWER_SUPPLY_HEALTH_DEAD;
 802			return 0;
 803		default:
 804			dev_notice_once(&data->wdev->dev, "Unknown permanent failure code %u\n",
 805					code);
 806			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
 807			return 0;
 808		}
 809	case MA_FAILURE_MODE_OVERHEAT:
 810		code = FIELD_GET(MA_OVERHEAT_FAILURE_CODE_MASK, value);
 811		switch (code) {
 812		case MA_OVERHEAT_FAILURE_START:
 813		case MA_OVERHEAT_FAILURE_CHARGING:
 814		case MA_OVERHEAT_FAILURE_DISCHARGING:
 815			val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
 816			return 0;
 817		default:
 818			dev_notice_once(&data->wdev->dev, "Unknown overheat failure code %u\n",
 819					code);
 820			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
 821			return 0;
 822		}
 823	case MA_FAILURE_MODE_OVERCURRENT:
 824		code = FIELD_GET(MA_OVERCURRENT_FAILURE_CODE_MASK, value);
 825		switch (code) {
 826		case MA_OVERCURRENT_FAILURE_CHARGING:
 827		case MA_OVERCURRENT_FAILURE_DISCHARGING:
 828			val->intval = POWER_SUPPLY_HEALTH_OVERCURRENT;
 829			return 0;
 830		default:
 831			dev_notice_once(&data->wdev->dev, "Unknown overcurrent failure code %u\n",
 832					code);
 833			val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
 834			return 0;
 835		}
 836	default:
 837		val->intval = POWER_SUPPLY_HEALTH_GOOD;
 838		return 0;
 839	}
 840}
 841
 842static int dell_wmi_ddv_get_manufacture_date(struct dell_wmi_ddv_data *data, u32 index,
 843					     enum power_supply_property psp,
 844					     union power_supply_propval *val)
 845{
 846	u16 year, month, day;
 847	u32 value;
 848	int ret;
 849
 850	ret = dell_wmi_ddv_query_integer(data->wdev, DELL_DDV_BATTERY_MANUFACTURE_DATE,
 851					 index, &value);
 852	if (ret < 0)
 853		return ret;
 854	if (value > U16_MAX)
 855		return -ENXIO;
 856
 857	/*
 858	 * Some devices report a invalid manufacture date value
 859	 * like 0.0.1980. Because of this we have to check the
 860	 * whole value before exposing parts of it to user space.
 861	 */
 862	year = FIELD_GET(SBS_MANUFACTURE_YEAR_MASK, value) + 1980;
 863	month = FIELD_GET(SBS_MANUFACTURE_MONTH_MASK, value);
 864	if (month < 1 || month > 12)
 865		return -ENODATA;
 866
 867	day = FIELD_GET(SBS_MANUFACTURE_DAY_MASK, value);
 868	if (day < 1 || day > 31)
 869		return -ENODATA;
 870
 871	switch (psp) {
 872	case POWER_SUPPLY_PROP_MANUFACTURE_YEAR:
 873		val->intval = year;
 874		return 0;
 875	case POWER_SUPPLY_PROP_MANUFACTURE_MONTH:
 876		val->intval = month;
 877		return 0;
 878	case POWER_SUPPLY_PROP_MANUFACTURE_DAY:
 879		val->intval = day;
 880		return 0;
 881	default:
 882		return -EINVAL;
 883	}
 884}
 885
 886static int dell_wmi_ddv_get_property(struct power_supply *psy, const struct power_supply_ext *ext,
 887				     void *drvdata, enum power_supply_property psp,
 888				     union power_supply_propval *val)
 889{
 890	struct dell_wmi_ddv_data *data = drvdata;
 891	u32 index, value;
 892	int ret;
 893
 894	ret = dell_wmi_ddv_battery_translate(data, psy, &index);
 895	if (ret < 0)
 896		return ret;
 897
 898	switch (psp) {
 899	case POWER_SUPPLY_PROP_HEALTH:
 900		return dell_wmi_ddv_get_health(data, index, val);
 901	case POWER_SUPPLY_PROP_TEMP:
 902		ret = dell_wmi_ddv_query_integer(data->wdev, DELL_DDV_BATTERY_TEMPERATURE, index,
 903						 &value);
 904		if (ret < 0)
 905			return ret;
 906
 907		/* Use 2732 instead of 2731.5 to avoid unnecessary rounding and to emulate
 908		 * the behaviour of the OEM application which seems to round down the result.
 909		 */
 910		val->intval = value - 2732;
 911		return 0;
 912	case POWER_SUPPLY_PROP_MANUFACTURE_YEAR:
 913	case POWER_SUPPLY_PROP_MANUFACTURE_MONTH:
 914	case POWER_SUPPLY_PROP_MANUFACTURE_DAY:
 915		return dell_wmi_ddv_get_manufacture_date(data, index, psp, val);
 916	default:
 917		return -EINVAL;
 918	}
 919}
 920
 921static const enum power_supply_property dell_wmi_ddv_properties[] = {
 922	POWER_SUPPLY_PROP_HEALTH,
 923	POWER_SUPPLY_PROP_TEMP,
 924	POWER_SUPPLY_PROP_MANUFACTURE_YEAR,
 925	POWER_SUPPLY_PROP_MANUFACTURE_MONTH,
 926	POWER_SUPPLY_PROP_MANUFACTURE_DAY,
 927};
 928
 929static const struct power_supply_ext dell_wmi_ddv_extension = {
 930	.name = DRIVER_NAME,
 931	.properties = dell_wmi_ddv_properties,
 932	.num_properties = ARRAY_SIZE(dell_wmi_ddv_properties),
 933	.get_property = dell_wmi_ddv_get_property,
 934};
 935
 936static int dell_wmi_ddv_add_battery(struct power_supply *battery, struct acpi_battery_hook *hook)
 937{
 938	struct dell_wmi_ddv_data *data = container_of(hook, struct dell_wmi_ddv_data, hook);
 939	int ret;
 940
 941	/*
 942	 * We cannot do the battery matching here since the battery might be absent, preventing
 943	 * us from reading the serial number.
 944	 */
 945
 946	ret = device_create_file(&battery->dev, &data->eppid_attr);
 947	if (ret < 0)
 948		return ret;
 949
 950	ret = power_supply_register_extension(battery, &dell_wmi_ddv_extension, &data->wdev->dev,
 951					      data);
 952	if (ret < 0) {
 953		device_remove_file(&battery->dev, &data->eppid_attr);
 954
 955		return ret;
 956	}
 957
 958	return 0;
 959}
 960
 961static int dell_wmi_ddv_remove_battery(struct power_supply *battery, struct acpi_battery_hook *hook)
 962{
 963	struct dell_wmi_ddv_data *data = container_of(hook, struct dell_wmi_ddv_data, hook);
 964
 965	device_remove_file(&battery->dev, &data->eppid_attr);
 966	power_supply_unregister_extension(battery, &dell_wmi_ddv_extension);
 967
 968	dell_wmi_battery_invalidate(data, battery);
 969
 970	return 0;
 971}
 972
 973static int dell_wmi_ddv_battery_add(struct dell_wmi_ddv_data *data)
 974{
 975	int ret;
 976
 977	ret = devm_mutex_init(&data->wdev->dev, &data->translation_cache_lock);
 978	if (ret < 0)
 979		return ret;
 980
 981	data->hook.name = "Dell DDV Battery Extension";
 982	data->hook.add_battery = dell_wmi_ddv_add_battery;
 983	data->hook.remove_battery = dell_wmi_ddv_remove_battery;
 984
 985	sysfs_attr_init(&data->eppid_attr.attr);
 986	data->eppid_attr.attr.name = "eppid";
 987	data->eppid_attr.attr.mode = 0444;
 988	data->eppid_attr.show = eppid_show;
 989
 990	return devm_battery_hook_register(&data->wdev->dev, &data->hook);
 991}
 992
 993static int dell_wmi_ddv_buffer_read(struct seq_file *seq, enum dell_ddv_method method)
 994{
 995	struct device *dev = seq->private;
 996	struct dell_wmi_ddv_data *data = dev_get_drvdata(dev);
 997	union acpi_object *obj;
 998	u64 size;
 999	u8 *buf;
1000	int ret;
1001
1002	ret = dell_wmi_ddv_query_buffer(data->wdev, method, 0, &obj);
1003	if (ret < 0)
1004		return ret;
1005
1006	size = obj->package.elements[0].integer.value;
1007	buf = obj->package.elements[1].buffer.pointer;
1008	ret = seq_write(seq, buf, size);
1009	kfree(obj);
1010
1011	return ret;
1012}
1013
1014static int dell_wmi_ddv_fan_read(struct seq_file *seq, void *offset)
1015{
1016	return dell_wmi_ddv_buffer_read(seq, DELL_DDV_FAN_SENSOR_INFORMATION);
1017}
1018
1019static int dell_wmi_ddv_temp_read(struct seq_file *seq, void *offset)
1020{
1021	return dell_wmi_ddv_buffer_read(seq, DELL_DDV_THERMAL_SENSOR_INFORMATION);
1022}
1023
1024static void dell_wmi_ddv_debugfs_remove(void *data)
1025{
1026	struct dentry *entry = data;
1027
1028	debugfs_remove(entry);
1029}
1030
1031static void dell_wmi_ddv_debugfs_init(struct wmi_device *wdev)
1032{
1033	struct dentry *entry;
1034	char name[64];
1035
1036	scnprintf(name, ARRAY_SIZE(name), "%s-%s", DRIVER_NAME, dev_name(&wdev->dev));
1037	entry = debugfs_create_dir(name, NULL);
1038
1039	debugfs_create_devm_seqfile(&wdev->dev, "fan_sensor_information", entry,
1040				    dell_wmi_ddv_fan_read);
1041	debugfs_create_devm_seqfile(&wdev->dev, "thermal_sensor_information", entry,
1042				    dell_wmi_ddv_temp_read);
1043
1044	devm_add_action_or_reset(&wdev->dev, dell_wmi_ddv_debugfs_remove, entry);
1045}
1046
1047static int dell_wmi_ddv_probe(struct wmi_device *wdev, const void *context)
1048{
1049	struct dell_wmi_ddv_data *data;
1050	u32 version;
1051	int ret;
1052
1053	ret = dell_wmi_ddv_query_integer(wdev, DELL_DDV_INTERFACE_VERSION, 0, &version);
1054	if (ret < 0)
1055		return ret;
1056
1057	dev_dbg(&wdev->dev, "WMI interface version: %d\n", version);
1058	if (version < DELL_DDV_SUPPORTED_VERSION_MIN || version > DELL_DDV_SUPPORTED_VERSION_MAX) {
1059		if (!force)
1060			return -ENODEV;
1061
1062		dev_warn(&wdev->dev, "Loading despite unsupported WMI interface version (%u)\n",
1063			 version);
1064	}
1065
1066	data = devm_kzalloc(&wdev->dev, sizeof(*data), GFP_KERNEL);
1067	if (!data)
1068		return -ENOMEM;
1069
1070	dev_set_drvdata(&wdev->dev, data);
1071	data->wdev = wdev;
1072
1073	dell_wmi_ddv_debugfs_init(wdev);
1074
1075	if (IS_REACHABLE(CONFIG_ACPI_BATTERY)) {
1076		ret = dell_wmi_ddv_battery_add(data);
1077		if (ret < 0)
1078			dev_warn(&wdev->dev, "Unable to register ACPI battery hook: %d\n", ret);
1079	}
1080
1081	if (IS_REACHABLE(CONFIG_HWMON)) {
1082		ret = dell_wmi_ddv_hwmon_add(data);
1083		if (ret < 0)
1084			dev_warn(&wdev->dev, "Unable to register hwmon interface: %d\n", ret);
1085	}
1086
1087	return 0;
1088}
1089
1090static int dell_wmi_ddv_resume(struct device *dev)
1091{
1092	struct dell_wmi_ddv_data *data = dev_get_drvdata(dev);
1093
1094	/* Force re-reading of all active sensors */
1095	dell_wmi_ddv_hwmon_cache_invalidate(&data->fans);
1096	dell_wmi_ddv_hwmon_cache_invalidate(&data->temps);
1097
1098	return 0;
1099}
1100
1101static DEFINE_SIMPLE_DEV_PM_OPS(dell_wmi_ddv_dev_pm_ops, NULL, dell_wmi_ddv_resume);
1102
1103static const struct wmi_device_id dell_wmi_ddv_id_table[] = {
1104	{ DELL_DDV_GUID, NULL },
1105	{ }
1106};
1107MODULE_DEVICE_TABLE(wmi, dell_wmi_ddv_id_table);
1108
1109static struct wmi_driver dell_wmi_ddv_driver = {
1110	.driver = {
1111		.name = DRIVER_NAME,
1112		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
1113		.pm = pm_sleep_ptr(&dell_wmi_ddv_dev_pm_ops),
1114	},
1115	.id_table = dell_wmi_ddv_id_table,
1116	.probe = dell_wmi_ddv_probe,
1117	.no_singleton = true,
1118};
1119module_wmi_driver(dell_wmi_ddv_driver);
1120
1121MODULE_AUTHOR("Armin Wolf <W_Armin@gmx.de>");
1122MODULE_DESCRIPTION("Dell WMI sensor driver");
1123MODULE_LICENSE("GPL");
~/ Read-only file preview.