xref: /linux/drivers/gpu/drm/xe/xe_configfs.c (revision 6f17ab9a63e670bd62a287f95e3982f99eafd77e)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2025 Intel Corporation
4  */
5 
6 #include <linux/bitops.h>
7 #include <linux/configfs.h>
8 #include <linux/cleanup.h>
9 #include <linux/find.h>
10 #include <linux/init.h>
11 #include <linux/module.h>
12 #include <linux/pci.h>
13 #include <linux/string.h>
14 
15 #include "xe_configfs.h"
16 #include "xe_hw_engine_types.h"
17 #include "xe_module.h"
18 #include "xe_pci_types.h"
19 
20 /**
21  * DOC: Xe Configfs
22  *
23  * Overview
24  * =========
25  *
26  * Configfs is a filesystem-based manager of kernel objects. XE KMD registers a
27  * configfs subsystem called ``xe`` that creates a directory in the mounted
28  * configfs directory. The user can create devices under this directory and
29  * configure them as necessary. See Documentation/filesystems/configfs.rst for
30  * more information about how configfs works.
31  *
32  * Create devices
33  * ==============
34  *
35  * To create a device, the ``xe`` module should already be loaded, but some
36  * attributes can only be set before binding the device. It can be accomplished
37  * by blocking the driver autoprobe:
38  *
39  *	# echo 0 > /sys/bus/pci/drivers_autoprobe
40  *	# modprobe xe
41  *
42  * In order to create a device, the user has to create a directory inside ``xe``::
43  *
44  *	# mkdir /sys/kernel/config/xe/0000:03:00.0/
45  *
46  * Every device created is populated by the driver with entries that can be
47  * used to configure it::
48  *
49  *	/sys/kernel/config/xe/
50  *	├── 0000:00:02.0
51  *	│   └── ...
52  *	├── 0000:00:02.1
53  *	│   └── ...
54  *	:
55  *	└── 0000:03:00.0
56  *	    ├── survivability_mode
57  *	    ├── engines_allowed
58  *	    └── enable_psmi
59  *
60  * After configuring the attributes as per next section, the device can be
61  * probed with::
62  *
63  *	# echo 0000:03:00.0 > /sys/bus/pci/drivers/xe/bind
64  *	# # or
65  *	# echo 0000:03:00.0 > /sys/bus/pci/drivers_probe
66  *
67  * Configure Attributes
68  * ====================
69  *
70  * Survivability mode:
71  * -------------------
72  *
73  * Enable survivability mode on supported cards. This setting only takes
74  * effect when probing the device. Example to enable it::
75  *
76  *	# echo 1 > /sys/kernel/config/xe/0000:03:00.0/survivability_mode
77  *
78  * This attribute can only be set before binding to the device.
79  *
80  * Allowed engines:
81  * ----------------
82  *
83  * Allow only a set of engine(s) to be available, disabling the other engines
84  * even if they are available in hardware. This is applied after HW fuses are
85  * considered on each tile. Examples:
86  *
87  * Allow only one render and one copy engines, nothing else::
88  *
89  *	# echo 'rcs0,bcs0' > /sys/kernel/config/xe/0000:03:00.0/engines_allowed
90  *
91  * Allow only compute engines and first copy engine::
92  *
93  *	# echo 'ccs*,bcs0' > /sys/kernel/config/xe/0000:03:00.0/engines_allowed
94  *
95  * Note that the engine names are the per-GT hardware names. On multi-tile
96  * platforms, writing ``rcs0,bcs0`` to this file would allow the first render
97  * and copy engines on each tile.
98  *
99  * The requested configuration may not be supported by the platform and driver
100  * may fail to probe. For example: if at least one copy engine is expected to be
101  * available for migrations, but it's disabled. This is intended for debugging
102  * purposes only.
103  *
104  * This attribute can only be set before binding to the device.
105  *
106  * PSMI
107  * ----
108  *
109  * Enable extra debugging capabilities to trace engine execution. Only useful
110  * during early platform enabling and requires additional hardware connected.
111  * Once it's enabled, additionals WAs are added and runtime configuration is
112  * done via debugfs. Example to enable it::
113  *
114  *	# echo 1 > /sys/kernel/config/xe/0000:03:00.0/enable_psmi
115  *
116  * This attribute can only be set before binding to the device.
117  *
118  * Remove devices
119  * ==============
120  *
121  * The created device directories can be removed using ``rmdir``::
122  *
123  *	# rmdir /sys/kernel/config/xe/0000:03:00.0/
124  */
125 
126 struct xe_config_group_device {
127 	struct config_group group;
128 
129 	struct xe_config_device {
130 		u64 engines_allowed;
131 		bool survivability_mode;
132 		bool enable_psmi;
133 	} config;
134 
135 	/* protects attributes */
136 	struct mutex lock;
137 };
138 
139 static const struct xe_config_device device_defaults = {
140 	.engines_allowed = U64_MAX,
141 	.survivability_mode = false,
142 	.enable_psmi = false,
143 };
144 
145 static void set_device_defaults(struct xe_config_device *config)
146 {
147 	*config = device_defaults;
148 }
149 
150 struct engine_info {
151 	const char *cls;
152 	u64 mask;
153 };
154 
155 /* Some helpful macros to aid on the sizing of buffer allocation when parsing */
156 #define MAX_ENGINE_CLASS_CHARS 5
157 #define MAX_ENGINE_INSTANCE_CHARS 2
158 
159 static const struct engine_info engine_info[] = {
160 	{ .cls = "rcs", .mask = XE_HW_ENGINE_RCS_MASK },
161 	{ .cls = "bcs", .mask = XE_HW_ENGINE_BCS_MASK },
162 	{ .cls = "vcs", .mask = XE_HW_ENGINE_VCS_MASK },
163 	{ .cls = "vecs", .mask = XE_HW_ENGINE_VECS_MASK },
164 	{ .cls = "ccs", .mask = XE_HW_ENGINE_CCS_MASK },
165 	{ .cls = "gsccs", .mask = XE_HW_ENGINE_GSCCS_MASK },
166 };
167 
168 static struct xe_config_group_device *to_xe_config_group_device(struct config_item *item)
169 {
170 	return container_of(to_config_group(item), struct xe_config_group_device, group);
171 }
172 
173 static struct xe_config_device *to_xe_config_device(struct config_item *item)
174 {
175 	return &to_xe_config_group_device(item)->config;
176 }
177 
178 static bool is_bound(struct xe_config_group_device *dev)
179 {
180 	unsigned int domain, bus, slot, function;
181 	struct pci_dev *pdev;
182 	const char *name;
183 	bool ret;
184 
185 	lockdep_assert_held(&dev->lock);
186 
187 	name = dev->group.cg_item.ci_name;
188 	if (sscanf(name, "%x:%x:%x.%x", &domain, &bus, &slot, &function) != 4)
189 		return false;
190 
191 	pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(slot, function));
192 	if (!pdev)
193 		return false;
194 
195 	ret = pci_get_drvdata(pdev);
196 	pci_dev_put(pdev);
197 
198 	if (ret)
199 		pci_dbg(pdev, "Already bound to driver\n");
200 
201 	return ret;
202 }
203 
204 static ssize_t survivability_mode_show(struct config_item *item, char *page)
205 {
206 	struct xe_config_device *dev = to_xe_config_device(item);
207 
208 	return sprintf(page, "%d\n", dev->survivability_mode);
209 }
210 
211 static ssize_t survivability_mode_store(struct config_item *item, const char *page, size_t len)
212 {
213 	struct xe_config_group_device *dev = to_xe_config_group_device(item);
214 	bool survivability_mode;
215 	int ret;
216 
217 	ret = kstrtobool(page, &survivability_mode);
218 	if (ret)
219 		return ret;
220 
221 	guard(mutex)(&dev->lock);
222 	if (is_bound(dev))
223 		return -EBUSY;
224 
225 	dev->config.survivability_mode = survivability_mode;
226 
227 	return len;
228 }
229 
230 static ssize_t engines_allowed_show(struct config_item *item, char *page)
231 {
232 	struct xe_config_device *dev = to_xe_config_device(item);
233 	char *p = page;
234 
235 	for (size_t i = 0; i < ARRAY_SIZE(engine_info); i++) {
236 		u64 mask = engine_info[i].mask;
237 
238 		if ((dev->engines_allowed & mask) == mask) {
239 			p += sprintf(p, "%s*\n", engine_info[i].cls);
240 		} else if (mask & dev->engines_allowed) {
241 			u16 bit0 = __ffs64(mask), bit;
242 
243 			mask &= dev->engines_allowed;
244 
245 			for_each_set_bit(bit, (const unsigned long *)&mask, 64)
246 				p += sprintf(p, "%s%u\n", engine_info[i].cls,
247 					     bit - bit0);
248 		}
249 	}
250 
251 	return p - page;
252 }
253 
254 static bool lookup_engine_mask(const char *pattern, u64 *mask)
255 {
256 	for (size_t i = 0; i < ARRAY_SIZE(engine_info); i++) {
257 		u8 instance;
258 		u16 bit;
259 
260 		if (!str_has_prefix(pattern, engine_info[i].cls))
261 			continue;
262 
263 		pattern += strlen(engine_info[i].cls);
264 
265 		if (!strcmp(pattern, "*")) {
266 			*mask = engine_info[i].mask;
267 			return true;
268 		}
269 
270 		if (kstrtou8(pattern, 10, &instance))
271 			return false;
272 
273 		bit = __ffs64(engine_info[i].mask) + instance;
274 		if (bit >= fls64(engine_info[i].mask))
275 			return false;
276 
277 		*mask = BIT_ULL(bit);
278 		return true;
279 	}
280 
281 	return false;
282 }
283 
284 static ssize_t engines_allowed_store(struct config_item *item, const char *page,
285 				     size_t len)
286 {
287 	struct xe_config_group_device *dev = to_xe_config_group_device(item);
288 	size_t patternlen, p;
289 	u64 mask, val = 0;
290 
291 	for (p = 0; p < len; p += patternlen + 1) {
292 		char buf[MAX_ENGINE_CLASS_CHARS + MAX_ENGINE_INSTANCE_CHARS + 1];
293 
294 		patternlen = strcspn(page + p, ",\n");
295 		if (patternlen >= sizeof(buf))
296 			return -EINVAL;
297 
298 		memcpy(buf, page + p, patternlen);
299 		buf[patternlen] = '\0';
300 
301 		if (!lookup_engine_mask(buf, &mask))
302 			return -EINVAL;
303 
304 		val |= mask;
305 	}
306 
307 	guard(mutex)(&dev->lock);
308 	if (is_bound(dev))
309 		return -EBUSY;
310 
311 	dev->config.engines_allowed = val;
312 
313 	return len;
314 }
315 
316 static ssize_t enable_psmi_show(struct config_item *item, char *page)
317 {
318 	struct xe_config_device *dev = to_xe_config_device(item);
319 
320 	return sprintf(page, "%d\n", dev->enable_psmi);
321 }
322 
323 static ssize_t enable_psmi_store(struct config_item *item, const char *page, size_t len)
324 {
325 	struct xe_config_group_device *dev = to_xe_config_group_device(item);
326 	bool val;
327 	int ret;
328 
329 	ret = kstrtobool(page, &val);
330 	if (ret)
331 		return ret;
332 
333 	guard(mutex)(&dev->lock);
334 	if (is_bound(dev))
335 		return -EBUSY;
336 
337 	dev->config.enable_psmi = val;
338 
339 	return len;
340 }
341 
342 CONFIGFS_ATTR(, enable_psmi);
343 CONFIGFS_ATTR(, engines_allowed);
344 CONFIGFS_ATTR(, survivability_mode);
345 
346 static struct configfs_attribute *xe_config_device_attrs[] = {
347 	&attr_enable_psmi,
348 	&attr_engines_allowed,
349 	&attr_survivability_mode,
350 	NULL,
351 };
352 
353 static void xe_config_device_release(struct config_item *item)
354 {
355 	struct xe_config_group_device *dev = to_xe_config_group_device(item);
356 
357 	mutex_destroy(&dev->lock);
358 	kfree(dev);
359 }
360 
361 static struct configfs_item_operations xe_config_device_ops = {
362 	.release	= xe_config_device_release,
363 };
364 
365 static const struct config_item_type xe_config_device_type = {
366 	.ct_item_ops	= &xe_config_device_ops,
367 	.ct_attrs	= xe_config_device_attrs,
368 	.ct_owner	= THIS_MODULE,
369 };
370 
371 static const struct xe_device_desc *xe_match_desc(struct pci_dev *pdev)
372 {
373 	struct device_driver *driver = driver_find("xe", &pci_bus_type);
374 	struct pci_driver *drv = to_pci_driver(driver);
375 	const struct pci_device_id *ids = drv ? drv->id_table : NULL;
376 	const struct pci_device_id *found = pci_match_id(ids, pdev);
377 
378 	return found ? (const void *)found->driver_data : NULL;
379 }
380 
381 static struct pci_dev *get_physfn_instead(struct pci_dev *virtfn)
382 {
383 	struct pci_dev *physfn = pci_physfn(virtfn);
384 
385 	pci_dev_get(physfn);
386 	pci_dev_put(virtfn);
387 	return physfn;
388 }
389 
390 static struct config_group *xe_config_make_device_group(struct config_group *group,
391 							const char *name)
392 {
393 	unsigned int domain, bus, slot, function;
394 	struct xe_config_group_device *dev;
395 	const struct xe_device_desc *match;
396 	struct pci_dev *pdev;
397 	char canonical[16];
398 	int vfnumber = 0;
399 	int ret;
400 
401 	ret = sscanf(name, "%x:%x:%x.%x", &domain, &bus, &slot, &function);
402 	if (ret != 4)
403 		return ERR_PTR(-EINVAL);
404 
405 	ret = scnprintf(canonical, sizeof(canonical), "%04x:%02x:%02x.%d", domain, bus,
406 			PCI_SLOT(PCI_DEVFN(slot, function)),
407 			PCI_FUNC(PCI_DEVFN(slot, function)));
408 	if (ret != 12 || strcmp(name, canonical))
409 		return ERR_PTR(-EINVAL);
410 
411 	pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(slot, function));
412 	if (!pdev && function)
413 		pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(slot, 0));
414 	if (!pdev && slot)
415 		pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(0, 0));
416 	if (!pdev)
417 		return ERR_PTR(-ENODEV);
418 
419 	if (PCI_DEVFN(slot, function) != pdev->devfn) {
420 		pdev = get_physfn_instead(pdev);
421 		vfnumber = PCI_DEVFN(slot, function) - pdev->devfn;
422 		if (!dev_is_pf(&pdev->dev) || vfnumber > pci_sriov_get_totalvfs(pdev)) {
423 			pci_dev_put(pdev);
424 			return ERR_PTR(-ENODEV);
425 		}
426 	}
427 
428 	match = xe_match_desc(pdev);
429 	if (match && vfnumber && !match->has_sriov) {
430 		pci_info(pdev, "xe driver does not support VFs on this device\n");
431 		match = NULL;
432 	} else if (!match) {
433 		pci_info(pdev, "xe driver does not support configuration of this device\n");
434 	}
435 
436 	pci_dev_put(pdev);
437 
438 	if (!match)
439 		return ERR_PTR(-ENOENT);
440 
441 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
442 	if (!dev)
443 		return ERR_PTR(-ENOMEM);
444 
445 	set_device_defaults(&dev->config);
446 
447 	config_group_init_type_name(&dev->group, name, &xe_config_device_type);
448 
449 	mutex_init(&dev->lock);
450 
451 	return &dev->group;
452 }
453 
454 static struct configfs_group_operations xe_config_device_group_ops = {
455 	.make_group	= xe_config_make_device_group,
456 };
457 
458 static const struct config_item_type xe_configfs_type = {
459 	.ct_group_ops	= &xe_config_device_group_ops,
460 	.ct_owner	= THIS_MODULE,
461 };
462 
463 static struct configfs_subsystem xe_configfs = {
464 	.su_group = {
465 		.cg_item = {
466 			.ci_namebuf = "xe",
467 			.ci_type = &xe_configfs_type,
468 		},
469 	},
470 };
471 
472 static struct xe_config_group_device *find_xe_config_group_device(struct pci_dev *pdev)
473 {
474 	struct config_item *item;
475 
476 	mutex_lock(&xe_configfs.su_mutex);
477 	item = config_group_find_item(&xe_configfs.su_group, pci_name(pdev));
478 	mutex_unlock(&xe_configfs.su_mutex);
479 
480 	if (!item)
481 		return NULL;
482 
483 	return to_xe_config_group_device(item);
484 }
485 
486 static void dump_custom_dev_config(struct pci_dev *pdev,
487 				   struct xe_config_group_device *dev)
488 {
489 #define PRI_CUSTOM_ATTR(fmt_, attr_) do { \
490 		if (dev->config.attr_ != device_defaults.attr_) \
491 			pci_info(pdev, "configfs: " __stringify(attr_) " = " fmt_ "\n", \
492 				 dev->config.attr_); \
493 	} while (0)
494 
495 	PRI_CUSTOM_ATTR("%llx", engines_allowed);
496 	PRI_CUSTOM_ATTR("%d", enable_psmi);
497 	PRI_CUSTOM_ATTR("%d", survivability_mode);
498 
499 #undef PRI_CUSTOM_ATTR
500 }
501 
502 /**
503  * xe_configfs_check_device() - Test if device was configured by configfs
504  * @pdev: the &pci_dev device to test
505  *
506  * Try to find the configfs group that belongs to the specified pci device
507  * and print a diagnostic message if different than the default value.
508  */
509 void xe_configfs_check_device(struct pci_dev *pdev)
510 {
511 	struct xe_config_group_device *dev = find_xe_config_group_device(pdev);
512 
513 	if (!dev)
514 		return;
515 
516 	/* memcmp here is safe as both are zero-initialized */
517 	if (memcmp(&dev->config, &device_defaults, sizeof(dev->config))) {
518 		pci_info(pdev, "Found custom settings in configfs\n");
519 		dump_custom_dev_config(pdev, dev);
520 	}
521 
522 	config_group_put(&dev->group);
523 }
524 
525 /**
526  * xe_configfs_get_survivability_mode - get configfs survivability mode attribute
527  * @pdev: pci device
528  *
529  * Return: survivability_mode attribute in configfs
530  */
531 bool xe_configfs_get_survivability_mode(struct pci_dev *pdev)
532 {
533 	struct xe_config_group_device *dev = find_xe_config_group_device(pdev);
534 	bool mode;
535 
536 	if (!dev)
537 		return device_defaults.survivability_mode;
538 
539 	mode = dev->config.survivability_mode;
540 	config_group_put(&dev->group);
541 
542 	return mode;
543 }
544 
545 /**
546  * xe_configfs_clear_survivability_mode - clear configfs survivability mode
547  * @pdev: pci device
548  */
549 void xe_configfs_clear_survivability_mode(struct pci_dev *pdev)
550 {
551 	struct xe_config_group_device *dev = find_xe_config_group_device(pdev);
552 
553 	if (!dev)
554 		return;
555 
556 	guard(mutex)(&dev->lock);
557 	dev->config.survivability_mode = 0;
558 
559 	config_group_put(&dev->group);
560 }
561 
562 /**
563  * xe_configfs_get_engines_allowed - get engine allowed mask from configfs
564  * @pdev: pci device
565  *
566  * Return: engine mask with allowed engines set in configfs
567  */
568 u64 xe_configfs_get_engines_allowed(struct pci_dev *pdev)
569 {
570 	struct xe_config_group_device *dev = find_xe_config_group_device(pdev);
571 	u64 engines_allowed;
572 
573 	if (!dev)
574 		return device_defaults.engines_allowed;
575 
576 	engines_allowed = dev->config.engines_allowed;
577 	config_group_put(&dev->group);
578 
579 	return engines_allowed;
580 }
581 
582 /**
583  * xe_configfs_get_psmi_enabled - get configfs enable_psmi setting
584  * @pdev: pci device
585  *
586  * Return: enable_psmi setting in configfs
587  */
588 bool xe_configfs_get_psmi_enabled(struct pci_dev *pdev)
589 {
590 	struct xe_config_group_device *dev = find_xe_config_group_device(pdev);
591 	bool ret;
592 
593 	if (!dev)
594 		return false;
595 
596 	ret = dev->config.enable_psmi;
597 	config_item_put(&dev->group.cg_item);
598 
599 	return ret;
600 }
601 
602 int __init xe_configfs_init(void)
603 {
604 	int ret;
605 
606 	config_group_init(&xe_configfs.su_group);
607 	mutex_init(&xe_configfs.su_mutex);
608 	ret = configfs_register_subsystem(&xe_configfs);
609 	if (ret) {
610 		mutex_destroy(&xe_configfs.su_mutex);
611 		return ret;
612 	}
613 
614 	return 0;
615 }
616 
617 void __exit xe_configfs_exit(void)
618 {
619 	configfs_unregister_subsystem(&xe_configfs);
620 	mutex_destroy(&xe_configfs.su_mutex);
621 }
622