1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Lenovo Capability Data WMI Data Block driver. 4 * 5 * Lenovo Capability Data provides information on tunable attributes used by 6 * the "Other Mode" WMI interface. 7 * 8 * Capability Data 00 includes if the attribute is supported by the hardware, 9 * and the default_value. All attributes are independent of thermal modes. 10 * 11 * Capability Data 01 includes if the attribute is supported by the hardware, 12 * and the default_value, max_value, min_value, and step increment. Each 13 * attribute has multiple pages, one for each of the thermal modes managed by 14 * the Gamezone interface. 15 * 16 * Fan Test Data includes the max/min fan speed RPM for each fan. This is 17 * reference data for self-test. If the fan is in good condition, it is capable 18 * to spin faster than max RPM or slower than min RPM. 19 * 20 * Copyright (C) 2025 Derek J. Clark <derekjohn.clark@gmail.com> 21 * - Initial implementation (formerly named lenovo-wmi-capdata01) 22 * 23 * Copyright (C) 2025 Rong Zhang <i@rong.moe> 24 * - Unified implementation 25 */ 26 27 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 28 29 #include <linux/acpi.h> 30 #include <linux/bitfield.h> 31 #include <linux/bug.h> 32 #include <linux/cleanup.h> 33 #include <linux/component.h> 34 #include <linux/container_of.h> 35 #include <linux/device.h> 36 #include <linux/dev_printk.h> 37 #include <linux/err.h> 38 #include <linux/export.h> 39 #include <linux/gfp_types.h> 40 #include <linux/limits.h> 41 #include <linux/module.h> 42 #include <linux/mutex.h> 43 #include <linux/mutex_types.h> 44 #include <linux/notifier.h> 45 #include <linux/overflow.h> 46 #include <linux/stddef.h> 47 #include <linux/types.h> 48 #include <linux/wmi.h> 49 50 #include "wmi-capdata.h" 51 52 #define LENOVO_CAPABILITY_DATA_00_GUID "362A3AFE-3D96-4665-8530-96DAD5BB300E" 53 #define LENOVO_CAPABILITY_DATA_01_GUID "7A8F5407-CB67-4D6E-B547-39B3BE018154" 54 #define LENOVO_FAN_TEST_DATA_GUID "B642801B-3D21-45DE-90AE-6E86F164FB21" 55 56 #define ACPI_AC_CLASS "ac_adapter" 57 #define ACPI_AC_NOTIFY_STATUS 0x80 58 59 #define LWMI_FEATURE_ID_FAN_TEST 0x05 60 61 #define LWMI_ATTR_ID_FAN_TEST \ 62 (FIELD_PREP(LWMI_ATTR_DEV_ID_MASK, LWMI_DEVICE_ID_FAN) | \ 63 FIELD_PREP(LWMI_ATTR_FEAT_ID_MASK, LWMI_FEATURE_ID_FAN_TEST)) 64 65 enum lwmi_cd_type { 66 LENOVO_CAPABILITY_DATA_00, 67 LENOVO_CAPABILITY_DATA_01, 68 LENOVO_FAN_TEST_DATA, 69 CD_TYPE_NONE = -1, 70 }; 71 72 #define LWMI_CD_TABLE_ITEM(_type) \ 73 [_type] = { \ 74 .name = #_type, \ 75 .type = _type, \ 76 } 77 78 static const struct lwmi_cd_info { 79 const char *name; 80 enum lwmi_cd_type type; 81 } lwmi_cd_table[] = { 82 LWMI_CD_TABLE_ITEM(LENOVO_CAPABILITY_DATA_00), 83 LWMI_CD_TABLE_ITEM(LENOVO_CAPABILITY_DATA_01), 84 LWMI_CD_TABLE_ITEM(LENOVO_FAN_TEST_DATA), 85 }; 86 87 struct lwmi_cd_priv { 88 struct notifier_block acpi_nb; /* ACPI events */ 89 struct wmi_device *wdev; 90 struct cd_list *list; 91 92 /* 93 * A capdata device may be a component master of another capdata device. 94 * E.g., lenovo-wmi-other <-> capdata00 <-> capdata_fan 95 * |- master |- component 96 * |- sub-master 97 * |- sub-component 98 */ 99 struct lwmi_cd_sub_master_priv { 100 struct device *master_dev; 101 cd_list_cb_t master_cb; 102 struct cd_list *sub_component_list; /* ERR_PTR(-ENODEV) implies no sub-component. */ 103 bool registered; /* Has the sub-master been registered? */ 104 } *sub_master; 105 }; 106 107 struct cd_list { 108 struct mutex list_mutex; /* list R/W mutex */ 109 enum lwmi_cd_type type; 110 u8 count; 111 112 union { 113 DECLARE_FLEX_ARRAY(struct capdata00, cd00); 114 DECLARE_FLEX_ARRAY(struct capdata01, cd01); 115 DECLARE_FLEX_ARRAY(struct capdata_fan, cd_fan); 116 }; 117 }; 118 119 static struct wmi_driver lwmi_cd_driver; 120 121 /** 122 * lwmi_cd_match() - Match rule for the master driver. 123 * @dev: Pointer to the capability data parent device. 124 * @type: Pointer to capability data type (enum lwmi_cd_type *) to match. 125 * 126 * Return: int. 127 */ 128 static int lwmi_cd_match(struct device *dev, void *type) 129 { 130 struct lwmi_cd_priv *priv; 131 132 if (dev->driver != &lwmi_cd_driver.driver) 133 return false; 134 135 priv = dev_get_drvdata(dev); 136 return priv->list->type == *(enum lwmi_cd_type *)type; 137 } 138 139 /** 140 * lwmi_cd_match_add_all() - Add all match rule for the master driver. 141 * @master: Pointer to the master device. 142 * @matchptr: Pointer to the returned component_match pointer. 143 * 144 * Adds all component matches to the list stored in @matchptr for the @master 145 * device. @matchptr must be initialized to NULL. 146 */ 147 void lwmi_cd_match_add_all(struct device *master, struct component_match **matchptr) 148 { 149 int i; 150 151 if (WARN_ON(*matchptr)) 152 return; 153 154 for (i = 0; i < ARRAY_SIZE(lwmi_cd_table); i++) { 155 /* Skip sub-components. */ 156 if (lwmi_cd_table[i].type == LENOVO_FAN_TEST_DATA) 157 continue; 158 159 component_match_add(master, matchptr, lwmi_cd_match, 160 (void *)&lwmi_cd_table[i].type); 161 if (IS_ERR(*matchptr)) 162 return; 163 } 164 } 165 EXPORT_SYMBOL_NS_GPL(lwmi_cd_match_add_all, "LENOVO_WMI_CAPDATA"); 166 167 /** 168 * lwmi_cd_call_master_cb() - Call the master callback for the sub-component. 169 * @priv: Pointer to the capability data private data. 170 * 171 * Call the master callback and pass the sub-component list to it if the 172 * dependency chain (master <-> sub-master <-> sub-component) is complete. 173 */ 174 static void lwmi_cd_call_master_cb(struct lwmi_cd_priv *priv) 175 { 176 struct cd_list *sub_component_list = priv->sub_master->sub_component_list; 177 178 /* 179 * Call the callback only if the dependency chain is ready: 180 * - Binding between master and sub-master: fills master_dev and master_cb 181 * - Binding between sub-master and sub-component: fills sub_component_list 182 * 183 * If a binding has been unbound before the other binding is bound, the 184 * corresponding members filled by the former are guaranteed to be cleared. 185 * 186 * This function is only called in bind callbacks, and the component 187 * framework guarantees bind/unbind callbacks may never execute 188 * simultaneously, which implies that it's impossible to have a race 189 * condition. 190 * 191 * Hence, this check is sufficient to ensure that the callback is called 192 * at most once and with the correct state, without relying on a specific 193 * sequence of binding establishment. 194 */ 195 if (!sub_component_list || 196 !priv->sub_master->master_dev || 197 !priv->sub_master->master_cb) 198 return; 199 200 if (PTR_ERR(sub_component_list) == -ENODEV) 201 sub_component_list = NULL; 202 else if (WARN_ON(IS_ERR(sub_component_list))) 203 return; 204 205 priv->sub_master->master_cb(priv->sub_master->master_dev, 206 sub_component_list); 207 208 /* 209 * Userspace may unbind a device from its driver and bind it again 210 * through sysfs. Let's call this operation "reprobe" to distinguish it 211 * from component "rebind". 212 * 213 * When reprobing capdata00/01 or the master device, the master device 214 * is unbound from us with appropriate cleanup before we bind to it and 215 * call master_cb. Everything is fine in this case. 216 * 217 * When reprobing capdata_fan, the master device has never been unbound 218 * from us (hence no cleanup is done)[1], but we call master_cb the 219 * second time. To solve this issue, we clear master_cb and master_dev 220 * so we won't call master_cb twice while a binding is still complete. 221 * 222 * Note that we can't clear sub_component_list, otherwise reprobing 223 * capdata01 or the master device causes master_cb to be never called 224 * after we rebind to the master device. 225 * 226 * [1]: The master device does not need capdata_fan in run time, so 227 * losing capdata_fan will not break the binding to the master device. 228 */ 229 priv->sub_master->master_cb = NULL; 230 priv->sub_master->master_dev = NULL; 231 } 232 233 /** 234 * lwmi_cd_component_bind() - Bind component to master device. 235 * @cd_dev: Pointer to the lenovo-wmi-capdata driver parent device. 236 * @om_dev: Pointer to the lenovo-wmi-other driver parent device. 237 * @data: lwmi_cd_binder object pointer used to return the capability data. 238 * 239 * On lenovo-wmi-other's master bind, provide a pointer to the local capdata 240 * list. This is used to call lwmi_cd*_get_data to look up attribute data 241 * from the lenovo-wmi-other driver. 242 * 243 * If cd_dev is a sub-master, try to call the master callback. 244 * 245 * Return: 0 246 */ 247 static int lwmi_cd_component_bind(struct device *cd_dev, 248 struct device *om_dev, void *data) 249 { 250 struct lwmi_cd_priv *priv = dev_get_drvdata(cd_dev); 251 struct lwmi_cd_binder *binder = data; 252 253 switch (priv->list->type) { 254 case LENOVO_CAPABILITY_DATA_00: 255 binder->cd00_list = priv->list; 256 257 priv->sub_master->master_dev = om_dev; 258 priv->sub_master->master_cb = binder->cd_fan_list_cb; 259 lwmi_cd_call_master_cb(priv); 260 261 break; 262 case LENOVO_CAPABILITY_DATA_01: 263 binder->cd01_list = priv->list; 264 break; 265 default: 266 return -EINVAL; 267 } 268 269 return 0; 270 } 271 272 /** 273 * lwmi_cd_component_unbind() - Unbind component to master device. 274 * @cd_dev: Pointer to the lenovo-wmi-capdata driver parent device. 275 * @om_dev: Pointer to the lenovo-wmi-other driver parent device. 276 * @data: Unused. 277 * 278 * If cd_dev is a sub-master, clear the collected data from the master device to 279 * prevent the binding establishment between the sub-master and the sub- 280 * component (if it's about to happen) from calling the master callback. 281 */ 282 static void lwmi_cd_component_unbind(struct device *cd_dev, 283 struct device *om_dev, void *data) 284 { 285 struct lwmi_cd_priv *priv = dev_get_drvdata(cd_dev); 286 287 switch (priv->list->type) { 288 case LENOVO_CAPABILITY_DATA_00: 289 priv->sub_master->master_dev = NULL; 290 priv->sub_master->master_cb = NULL; 291 return; 292 default: 293 return; 294 } 295 } 296 297 static const struct component_ops lwmi_cd_component_ops = { 298 .bind = lwmi_cd_component_bind, 299 .unbind = lwmi_cd_component_unbind, 300 }; 301 302 /** 303 * lwmi_cd_sub_master_bind() - Bind sub-component of sub-master device 304 * @dev: The sub-master capdata basic device. 305 * 306 * Call component_bind_all to bind the sub-component device to the sub-master 307 * device. On success, collect the pointer to the sub-component list and try 308 * to call the master callback. 309 * 310 * Return: 0 on success, or an error code. 311 */ 312 static int lwmi_cd_sub_master_bind(struct device *dev) 313 { 314 struct lwmi_cd_priv *priv = dev_get_drvdata(dev); 315 struct cd_list *sub_component_list; 316 int ret; 317 318 ret = component_bind_all(dev, &sub_component_list); 319 if (ret) 320 return ret; 321 322 priv->sub_master->sub_component_list = sub_component_list; 323 lwmi_cd_call_master_cb(priv); 324 325 return 0; 326 } 327 328 /** 329 * lwmi_cd_sub_master_unbind() - Unbind sub-component of sub-master device 330 * @dev: The sub-master capdata basic device 331 * 332 * Clear the collected pointer to the sub-component list to prevent the binding 333 * establishment between the sub-master and the sub-component (if it's about to 334 * happen) from calling the master callback. Then, call component_unbind_all to 335 * unbind the sub-component device from the sub-master device. 336 */ 337 static void lwmi_cd_sub_master_unbind(struct device *dev) 338 { 339 struct lwmi_cd_priv *priv = dev_get_drvdata(dev); 340 341 priv->sub_master->sub_component_list = NULL; 342 343 component_unbind_all(dev, NULL); 344 } 345 346 static const struct component_master_ops lwmi_cd_sub_master_ops = { 347 .bind = lwmi_cd_sub_master_bind, 348 .unbind = lwmi_cd_sub_master_unbind, 349 }; 350 351 /** 352 * lwmi_cd_sub_master_add() - Register a sub-master with its sub-component 353 * @priv: Pointer to the sub-master capdata device private data. 354 * @sub_component_type: Type of the sub-component. 355 * 356 * Match the sub-component type and register the current capdata device as a 357 * sub-master. If the given sub-component type is CD_TYPE_NONE, mark the sub- 358 * component as non-existent without registering sub-master. 359 * 360 * Return: 0 on success, or an error code. 361 */ 362 static int lwmi_cd_sub_master_add(struct lwmi_cd_priv *priv, 363 enum lwmi_cd_type sub_component_type) 364 { 365 struct component_match *master_match = NULL; 366 int ret; 367 368 priv->sub_master = devm_kzalloc(&priv->wdev->dev, sizeof(*priv->sub_master), GFP_KERNEL); 369 if (!priv->sub_master) 370 return -ENOMEM; 371 372 if (sub_component_type == CD_TYPE_NONE) { 373 /* The master callback will be called with NULL on bind. */ 374 priv->sub_master->sub_component_list = ERR_PTR(-ENODEV); 375 priv->sub_master->registered = false; 376 return 0; 377 } 378 379 /* 380 * lwmi_cd_match() needs a pointer to enum lwmi_cd_type, but on-stack 381 * data cannot be used here. Steal one from lwmi_cd_table. 382 */ 383 component_match_add(&priv->wdev->dev, &master_match, lwmi_cd_match, 384 (void *)&lwmi_cd_table[sub_component_type].type); 385 if (IS_ERR(master_match)) 386 return PTR_ERR(master_match); 387 388 ret = component_master_add_with_match(&priv->wdev->dev, &lwmi_cd_sub_master_ops, 389 master_match); 390 if (ret) 391 return ret; 392 393 priv->sub_master->registered = true; 394 return 0; 395 } 396 397 /** 398 * lwmi_cd_sub_master_del() - Unregister a sub-master if it's registered 399 * @priv: Pointer to the sub-master capdata device private data. 400 */ 401 static void lwmi_cd_sub_master_del(struct lwmi_cd_priv *priv) 402 { 403 if (!priv->sub_master->registered) 404 return; 405 406 component_master_del(&priv->wdev->dev, &lwmi_cd_sub_master_ops); 407 priv->sub_master->registered = false; 408 } 409 410 /** 411 * lwmi_cd_sub_component_bind() - Bind sub-component to sub-master device. 412 * @sc_dev: Pointer to the sub-component capdata parent device. 413 * @sm_dev: Pointer to the sub-master capdata parent device. 414 * @data: Pointer used to return the capability data list pointer. 415 * 416 * On sub-master's bind, provide a pointer to the local capdata list. 417 * This is used by the sub-master to call the master callback. 418 * 419 * Return: 0 420 */ 421 static int lwmi_cd_sub_component_bind(struct device *sc_dev, 422 struct device *sm_dev, void *data) 423 { 424 struct lwmi_cd_priv *priv = dev_get_drvdata(sc_dev); 425 struct cd_list **listp = data; 426 427 *listp = priv->list; 428 429 return 0; 430 } 431 432 static const struct component_ops lwmi_cd_sub_component_ops = { 433 .bind = lwmi_cd_sub_component_bind, 434 }; 435 436 /* 437 * lwmi_cd*_get_data - Get the data of the specified attribute 438 * @list: The lenovo-wmi-capdata pointer to its cd_list struct. 439 * @attribute_id: The capdata attribute ID to be found. 440 * @output: Pointer to a capdata* struct to return the data. 441 * 442 * Retrieves the capability data struct pointer for the given 443 * attribute. 444 * 445 * Return: 0 on success, or -EINVAL. 446 */ 447 #define DEF_LWMI_CDXX_GET_DATA(_cdxx, _cd_type, _output_t) \ 448 int lwmi_##_cdxx##_get_data(struct cd_list *list, u32 attribute_id, _output_t *output) \ 449 { \ 450 u8 idx; \ 451 \ 452 if (WARN_ON(list->type != _cd_type)) \ 453 return -EINVAL; \ 454 \ 455 guard(mutex)(&list->list_mutex); \ 456 for (idx = 0; idx < list->count; idx++) { \ 457 if (list->_cdxx[idx].id != attribute_id) \ 458 continue; \ 459 memcpy(output, &list->_cdxx[idx], sizeof(list->_cdxx[idx])); \ 460 return 0; \ 461 } \ 462 return -EINVAL; \ 463 } 464 465 DEF_LWMI_CDXX_GET_DATA(cd00, LENOVO_CAPABILITY_DATA_00, struct capdata00); 466 EXPORT_SYMBOL_NS_GPL(lwmi_cd00_get_data, "LENOVO_WMI_CAPDATA"); 467 468 DEF_LWMI_CDXX_GET_DATA(cd01, LENOVO_CAPABILITY_DATA_01, struct capdata01); 469 EXPORT_SYMBOL_NS_GPL(lwmi_cd01_get_data, "LENOVO_WMI_CAPDATA"); 470 471 DEF_LWMI_CDXX_GET_DATA(cd_fan, LENOVO_FAN_TEST_DATA, struct capdata_fan); 472 EXPORT_SYMBOL_NS_GPL(lwmi_cd_fan_get_data, "LENOVO_WMI_CAPDATA"); 473 474 /** 475 * lwmi_cd_cache() - Cache all WMI data block information 476 * @priv: lenovo-wmi-capdata driver data. 477 * 478 * Loop through each WMI data block and cache the data. 479 * 480 * Return: 0 on success, or an error. 481 */ 482 static int lwmi_cd_cache(struct lwmi_cd_priv *priv) 483 { 484 size_t size; 485 int idx; 486 void *p; 487 488 switch (priv->list->type) { 489 case LENOVO_CAPABILITY_DATA_00: 490 p = &priv->list->cd00[0]; 491 size = sizeof(priv->list->cd00[0]); 492 break; 493 case LENOVO_CAPABILITY_DATA_01: 494 p = &priv->list->cd01[0]; 495 size = sizeof(priv->list->cd01[0]); 496 break; 497 case LENOVO_FAN_TEST_DATA: 498 /* Done by lwmi_cd_alloc() => lwmi_cd_fan_list_alloc_cache(). */ 499 return 0; 500 default: 501 return -EINVAL; 502 } 503 504 guard(mutex)(&priv->list->list_mutex); 505 for (idx = 0; idx < priv->list->count; idx++, p += size) { 506 union acpi_object *ret_obj __free(kfree) = NULL; 507 508 ret_obj = wmidev_block_query(priv->wdev, idx); 509 if (!ret_obj) 510 return -ENODEV; 511 512 if (ret_obj->type != ACPI_TYPE_BUFFER || 513 ret_obj->buffer.length < size) 514 continue; 515 516 memcpy(p, ret_obj->buffer.pointer, size); 517 } 518 519 return 0; 520 } 521 522 /** 523 * lwmi_cd_fan_list_alloc_cache() - Alloc and cache Fan Test Data list 524 * @priv: lenovo-wmi-capdata driver data. 525 * @listptr: Pointer to returned cd_list pointer. 526 * 527 * Return: count of fans found, or an error. 528 */ 529 static int lwmi_cd_fan_list_alloc_cache(struct lwmi_cd_priv *priv, struct cd_list **listptr) 530 { 531 struct cd_list *list; 532 size_t size; 533 u32 count; 534 int idx; 535 536 /* Emit unaligned access to u8 buffer with __packed. */ 537 struct cd_fan_block { 538 u32 nr; 539 u32 data[]; /* id[nr], max_rpm[nr], min_rpm[nr] */ 540 } __packed * block; 541 542 union acpi_object *ret_obj __free(kfree) = wmidev_block_query(priv->wdev, 0); 543 if (!ret_obj) 544 return -ENODEV; 545 546 if (ret_obj->type == ACPI_TYPE_BUFFER) { 547 block = (struct cd_fan_block *)ret_obj->buffer.pointer; 548 size = ret_obj->buffer.length; 549 550 count = size >= sizeof(*block) ? block->nr : 0; 551 if (size < struct_size(block, data, count * 3)) { 552 dev_warn(&priv->wdev->dev, 553 "incomplete fan test data block: %zu < %zu, ignoring\n", 554 size, struct_size(block, data, count * 3)); 555 count = 0; 556 } else if (count > U8_MAX) { 557 dev_warn(&priv->wdev->dev, 558 "too many fans reported: %u > %u, truncating\n", 559 count, U8_MAX); 560 count = U8_MAX; 561 } 562 } else { 563 /* 564 * This is usually caused by a dummy ACPI method. Do not return an error 565 * as failing to probe this device will result in sub-master device being 566 * unbound. This behavior aligns with lwmi_cd_cache(). 567 */ 568 count = 0; 569 } 570 571 list = devm_kzalloc(&priv->wdev->dev, struct_size(list, cd_fan, count), GFP_KERNEL); 572 if (!list) 573 return -ENOMEM; 574 575 for (idx = 0; idx < count; idx++) { 576 /* Do not calculate array index using count, as it may be truncated. */ 577 list->cd_fan[idx] = (struct capdata_fan) { 578 .id = block->data[idx], 579 .max_rpm = block->data[idx + block->nr], 580 .min_rpm = block->data[idx + (2 * block->nr)], 581 }; 582 } 583 584 *listptr = list; 585 return count; 586 } 587 588 /** 589 * lwmi_cd_alloc() - Allocate a cd_list struct in drvdata 590 * @priv: lenovo-wmi-capdata driver data. 591 * @type: The type of capability data. 592 * 593 * Allocate a cd_list struct large enough to contain data from all WMI data 594 * blocks provided by the interface. 595 * 596 * Return: 0 on success, or an error. 597 */ 598 static int lwmi_cd_alloc(struct lwmi_cd_priv *priv, enum lwmi_cd_type type) 599 { 600 struct cd_list *list; 601 size_t list_size; 602 int count, ret; 603 604 count = wmidev_instance_count(priv->wdev); 605 606 switch (type) { 607 case LENOVO_CAPABILITY_DATA_00: 608 list_size = struct_size(list, cd00, count); 609 break; 610 case LENOVO_CAPABILITY_DATA_01: 611 list_size = struct_size(list, cd01, count); 612 break; 613 case LENOVO_FAN_TEST_DATA: 614 count = lwmi_cd_fan_list_alloc_cache(priv, &list); 615 if (count < 0) 616 return count; 617 618 goto got_list; 619 default: 620 return -EINVAL; 621 } 622 623 list = devm_kzalloc(&priv->wdev->dev, list_size, GFP_KERNEL); 624 if (!list) 625 return -ENOMEM; 626 627 got_list: 628 ret = devm_mutex_init(&priv->wdev->dev, &list->list_mutex); 629 if (ret) 630 return ret; 631 632 list->type = type; 633 list->count = count; 634 priv->list = list; 635 636 return 0; 637 } 638 639 /** 640 * lwmi_cd_setup() - Cache all WMI data block information 641 * @priv: lenovo-wmi-capdata driver data. 642 * @type: The type of capability data. 643 * 644 * Allocate a cd_list struct large enough to contain data from all WMI data 645 * blocks provided by the interface. Then loop through each data block and 646 * cache the data. 647 * 648 * Return: 0 on success, or an error code. 649 */ 650 static int lwmi_cd_setup(struct lwmi_cd_priv *priv, enum lwmi_cd_type type) 651 { 652 int ret; 653 654 ret = lwmi_cd_alloc(priv, type); 655 if (ret) 656 return ret; 657 658 return lwmi_cd_cache(priv); 659 } 660 661 /** 662 * lwmi_cd01_notifier_call() - Call method for cd01 notifier. 663 * block call chain. 664 * @nb: The notifier_block registered to lenovo-wmi-events driver. 665 * @action: Unused. 666 * @data: The ACPI event. 667 * 668 * For LWMI_EVENT_THERMAL_MODE, set current_mode and notify platform_profile 669 * of a change. 670 * 671 * Return: notifier_block status. 672 */ 673 static int lwmi_cd01_notifier_call(struct notifier_block *nb, unsigned long action, 674 void *data) 675 { 676 struct acpi_bus_event *event = data; 677 struct lwmi_cd_priv *priv; 678 int ret; 679 680 if (strcmp(event->device_class, ACPI_AC_CLASS) != 0) 681 return NOTIFY_DONE; 682 683 priv = container_of(nb, struct lwmi_cd_priv, acpi_nb); 684 685 switch (event->type) { 686 case ACPI_AC_NOTIFY_STATUS: 687 ret = lwmi_cd_cache(priv); 688 if (ret) 689 return NOTIFY_BAD; 690 691 return NOTIFY_OK; 692 default: 693 return NOTIFY_DONE; 694 } 695 } 696 697 /** 698 * lwmi_cd01_unregister() - Unregister the cd01 ACPI notifier_block. 699 * @data: The ACPI event notifier_block to unregister. 700 */ 701 static void lwmi_cd01_unregister(void *data) 702 { 703 struct notifier_block *acpi_nb = data; 704 705 unregister_acpi_notifier(acpi_nb); 706 } 707 708 static int lwmi_cd_probe(struct wmi_device *wdev, const void *context) 709 { 710 const struct lwmi_cd_info *info = context; 711 struct lwmi_cd_priv *priv; 712 int ret; 713 714 if (!info) 715 return -EINVAL; 716 717 priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL); 718 if (!priv) 719 return -ENOMEM; 720 721 priv->wdev = wdev; 722 dev_set_drvdata(&wdev->dev, priv); 723 724 ret = lwmi_cd_setup(priv, info->type); 725 if (ret) 726 goto out; 727 728 switch (info->type) { 729 case LENOVO_CAPABILITY_DATA_00: { 730 enum lwmi_cd_type sub_component_type = LENOVO_FAN_TEST_DATA; 731 struct capdata00 capdata00; 732 733 ret = lwmi_cd00_get_data(priv->list, LWMI_ATTR_ID_FAN_TEST, &capdata00); 734 if (ret || !(capdata00.supported & LWMI_SUPP_VALID)) { 735 dev_dbg(&wdev->dev, "capdata00 declares no fan test support\n"); 736 sub_component_type = CD_TYPE_NONE; 737 } 738 739 /* Sub-master (capdata00) <-> sub-component (capdata_fan) */ 740 ret = lwmi_cd_sub_master_add(priv, sub_component_type); 741 if (ret) 742 goto out; 743 744 /* Master (lenovo-wmi-other) <-> sub-master (capdata00) */ 745 ret = component_add(&wdev->dev, &lwmi_cd_component_ops); 746 if (ret) 747 lwmi_cd_sub_master_del(priv); 748 749 goto out; 750 } 751 case LENOVO_CAPABILITY_DATA_01: 752 priv->acpi_nb.notifier_call = lwmi_cd01_notifier_call; 753 754 ret = register_acpi_notifier(&priv->acpi_nb); 755 if (ret) 756 goto out; 757 758 ret = devm_add_action_or_reset(&wdev->dev, lwmi_cd01_unregister, 759 &priv->acpi_nb); 760 if (ret) 761 goto out; 762 763 ret = component_add(&wdev->dev, &lwmi_cd_component_ops); 764 goto out; 765 case LENOVO_FAN_TEST_DATA: 766 ret = component_add(&wdev->dev, &lwmi_cd_sub_component_ops); 767 goto out; 768 default: 769 return -EINVAL; 770 } 771 out: 772 if (ret) { 773 dev_err(&wdev->dev, "failed to register %s: %d\n", 774 info->name, ret); 775 } else { 776 dev_dbg(&wdev->dev, "registered %s with %u items\n", 777 info->name, priv->list->count); 778 } 779 return ret; 780 } 781 782 static void lwmi_cd_remove(struct wmi_device *wdev) 783 { 784 struct lwmi_cd_priv *priv = dev_get_drvdata(&wdev->dev); 785 786 switch (priv->list->type) { 787 case LENOVO_CAPABILITY_DATA_00: 788 lwmi_cd_sub_master_del(priv); 789 fallthrough; 790 case LENOVO_CAPABILITY_DATA_01: 791 component_del(&wdev->dev, &lwmi_cd_component_ops); 792 break; 793 case LENOVO_FAN_TEST_DATA: 794 component_del(&wdev->dev, &lwmi_cd_sub_component_ops); 795 break; 796 default: 797 WARN_ON(1); 798 } 799 } 800 801 #define LWMI_CD_WDEV_ID(_type) \ 802 .guid_string = _type##_GUID, \ 803 .context = &lwmi_cd_table[_type], 804 805 static const struct wmi_device_id lwmi_cd_id_table[] = { 806 { LWMI_CD_WDEV_ID(LENOVO_CAPABILITY_DATA_00) }, 807 { LWMI_CD_WDEV_ID(LENOVO_CAPABILITY_DATA_01) }, 808 { LWMI_CD_WDEV_ID(LENOVO_FAN_TEST_DATA) }, 809 {} 810 }; 811 812 static struct wmi_driver lwmi_cd_driver = { 813 .driver = { 814 .name = "lenovo_wmi_capdata", 815 .probe_type = PROBE_PREFER_ASYNCHRONOUS, 816 }, 817 .id_table = lwmi_cd_id_table, 818 .probe = lwmi_cd_probe, 819 .remove = lwmi_cd_remove, 820 .no_singleton = true, 821 }; 822 823 module_wmi_driver(lwmi_cd_driver); 824 825 MODULE_DEVICE_TABLE(wmi, lwmi_cd_id_table); 826 MODULE_AUTHOR("Derek J. Clark <derekjohn.clark@gmail.com>"); 827 MODULE_AUTHOR("Rong Zhang <i@rong.moe>"); 828 MODULE_DESCRIPTION("Lenovo Capability Data WMI Driver"); 829 MODULE_LICENSE("GPL"); 830