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