xref: /linux/drivers/platform/x86/lenovo/wmi-capdata.c (revision 1fd1dc41724319406b0aff221a352a400b0ddfc5)
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