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