File Index
Files and directories
Sign in
FILE

xe_gt_sriov_pf_debugfs.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/xe/xe_gt_sriov_pf_debugfs.c C
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright © 2023-2024 Intel Corporation
  4 */
  5
  6#include <linux/debugfs.h>
  7
  8#include <drm/drm_print.h>
  9#include <drm/drm_debugfs.h>
 10
 11#include "xe_bo.h"
 12#include "xe_debugfs.h"
 13#include "xe_device.h"
 14#include "xe_gt.h"
 15#include "xe_gt_debugfs.h"
 16#include "xe_gt_sriov_pf_config.h"
 17#include "xe_gt_sriov_pf_control.h"
 18#include "xe_gt_sriov_pf_debugfs.h"
 19#include "xe_gt_sriov_pf_helpers.h"
 20#include "xe_gt_sriov_pf_migration.h"
 21#include "xe_gt_sriov_pf_monitor.h"
 22#include "xe_gt_sriov_pf_policy.h"
 23#include "xe_gt_sriov_pf_service.h"
 24#include "xe_pm.h"
 25#include "xe_sriov_pf.h"
 26#include "xe_sriov_pf_provision.h"
 27
 28/*
 29 *      /sys/kernel/debug/dri/BDF/
 30 *      ├── sriov		# d_inode->i_private = (xe_device*)
 31 *      │   ├── pf		# d_inode->i_private = (xe_device*)
 32 *      │   │   ├── tile0	# d_inode->i_private = (xe_tile*)
 33 *      │   │   │   ├── gt0	# d_inode->i_private = (xe_gt*)
 34 *      │   │   │   ├── gt1	# d_inode->i_private = (xe_gt*)
 35 *      │   │   ├── tile1
 36 *      │   │   │   :
 37 *      │   ├── vf1		# d_inode->i_private = VFID(1)
 38 *      │   │   ├── tile0	# d_inode->i_private = (xe_tile*)
 39 *      │   │   │   ├── gt0	# d_inode->i_private = (xe_gt*)
 40 *      │   │   │   ├── gt1	# d_inode->i_private = (xe_gt*)
 41 *      │   │   ├── tile1
 42 *      │   │   │   :
 43 *      :   :
 44 *      │   ├── vfN		# d_inode->i_private = VFID(N)
 45 */
 46
 47static void *extract_priv(struct dentry *d)
 48{
 49	return d->d_inode->i_private;
 50}
 51
 52static struct xe_gt *extract_gt(struct dentry *d)
 53{
 54	return extract_priv(d);
 55}
 56
 57static struct xe_device *extract_xe(struct dentry *d)
 58{
 59	return extract_priv(d->d_parent->d_parent->d_parent);
 60}
 61
 62static unsigned int extract_vfid(struct dentry *d)
 63{
 64	void *priv = extract_priv(d->d_parent->d_parent);
 65
 66	return priv == extract_xe(d) ? PFID : (uintptr_t)priv;
 67}
 68
 69/*
 70 *      /sys/kernel/debug/dri/BDF/
 71 *      ├── sriov
 72 *      :   ├── pf
 73 *          :   ├── tile0
 74 *              :   ├── gt0
 75 *                  :   ├── contexts_provisioned
 76 *                      ├── doorbells_provisioned
 77 *                      ├── runtime_registers
 78 *                      ├── adverse_events
 79 */
 80
 81static const struct drm_info_list pf_info[] = {
 82	{
 83		"contexts_provisioned",
 84		.show = xe_gt_debugfs_simple_show,
 85		.data = xe_gt_sriov_pf_config_print_ctxs,
 86	},
 87	{
 88		"doorbells_provisioned",
 89		.show = xe_gt_debugfs_simple_show,
 90		.data = xe_gt_sriov_pf_config_print_dbs,
 91	},
 92	{
 93		"runtime_registers",
 94		.show = xe_gt_debugfs_simple_show,
 95		.data = xe_gt_sriov_pf_service_print_runtime,
 96	},
 97	{
 98		"adverse_events",
 99		.show = xe_gt_debugfs_simple_show,
100		.data = xe_gt_sriov_pf_monitor_print_events,
101	},
102};
103
104/*
105 *      /sys/kernel/debug/dri/BDF/
106 *      ├── sriov
107 *      :   ├── pf
108 *          :   ├── tile0
109 *              :   ├── gt0
110 *                  :   ├── reset_engine
111 *                      ├── sample_period
112 *                      ├── sched_if_idle
113 */
114
115#define DEFINE_SRIOV_GT_POLICY_DEBUGFS_ATTRIBUTE(POLICY, TYPE, FORMAT)		\
116										\
117static int POLICY##_set(void *data, u64 val)					\
118{										\
119	struct xe_gt *gt = extract_gt(data);					\
120	struct xe_device *xe = gt_to_xe(gt);					\
121	int err;								\
122										\
123	if (val > (TYPE)~0ull)							\
124		return -EOVERFLOW;						\
125										\
126	xe_pm_runtime_get(xe);							\
127	err = xe_gt_sriov_pf_policy_set_##POLICY(gt, val);			\
128	if (!err)								\
129		xe_sriov_pf_provision_set_custom_mode(xe);			\
130	xe_pm_runtime_put(xe);							\
131										\
132	return err;								\
133}										\
134										\
135static int POLICY##_get(void *data, u64 *val)					\
136{										\
137	struct xe_gt *gt = extract_gt(data);					\
138										\
139	*val = xe_gt_sriov_pf_policy_get_##POLICY(gt);				\
140	return 0;								\
141}										\
142										\
143DEFINE_DEBUGFS_ATTRIBUTE(POLICY##_fops, POLICY##_get, POLICY##_set, FORMAT)
144
145DEFINE_SRIOV_GT_POLICY_DEBUGFS_ATTRIBUTE(reset_engine, bool, "%llu\n");
146DEFINE_SRIOV_GT_POLICY_DEBUGFS_ATTRIBUTE(sched_if_idle, bool, "%llu\n");
147DEFINE_SRIOV_GT_POLICY_DEBUGFS_ATTRIBUTE(sample_period, u32, "%llu\n");
148
149static void pf_add_policy_attrs(struct xe_gt *gt, struct dentry *parent)
150{
151	xe_gt_assert(gt, gt == extract_gt(parent));
152	xe_gt_assert(gt, PFID == extract_vfid(parent));
153
154	debugfs_create_file_unsafe("reset_engine", 0644, parent, parent, &reset_engine_fops);
155	debugfs_create_file_unsafe("sched_if_idle", 0644, parent, parent, &sched_if_idle_fops);
156	debugfs_create_file_unsafe("sample_period_ms", 0644, parent, parent, &sample_period_fops);
157}
158
159/*
160 *      /sys/kernel/debug/dri/BDF/
161 *      ├── sriov
162 *      :   ├── pf
163 *          │   ├── tile0
164 *          │   :   ├── gt0
165 *          │       :   ├── doorbells_spare
166 *          │           ├── contexts_spare
167 *          │           ├── exec_quantum_ms
168 *          │           ├── preempt_timeout_us
169 *          │           ├── sched_priority
170 *          ├── vf1
171 *          :   ├── tile0
172 *              :   ├── gt0
173 *                  :   ├── doorbells_quota
174 *                      ├── contexts_quota
175 *                      ├── exec_quantum_ms
176 *                      ├── preempt_timeout_us
177 *                      ├── sched_priority
178 */
179
180#define DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(CONFIG, TYPE, FORMAT)		\
181										\
182static int CONFIG##_set(void *data, u64 val)					\
183{										\
184	struct xe_gt *gt = extract_gt(data);					\
185	unsigned int vfid = extract_vfid(data);					\
186	struct xe_device *xe = gt_to_xe(gt);					\
187	int err;								\
188										\
189	if (val > (TYPE)~0ull)							\
190		return -EOVERFLOW;						\
191										\
192	xe_pm_runtime_get(xe);							\
193	err = xe_sriov_pf_wait_ready(xe) ?:					\
194	      xe_gt_sriov_pf_config_set_##CONFIG(gt, vfid, val);		\
195	if (!err)								\
196		xe_sriov_pf_provision_set_custom_mode(xe);			\
197	xe_pm_runtime_put(xe);							\
198										\
199	return err;								\
200}										\
201										\
202static int CONFIG##_get(void *data, u64 *val)					\
203{										\
204	struct xe_gt *gt = extract_gt(data);					\
205	unsigned int vfid = extract_vfid(data);					\
206										\
207	*val = xe_gt_sriov_pf_config_get_##CONFIG(gt, vfid);			\
208	return 0;								\
209}										\
210										\
211DEFINE_DEBUGFS_ATTRIBUTE(CONFIG##_fops, CONFIG##_get, CONFIG##_set, FORMAT)
212
213DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(ctxs, u32, "%llu\n");
214DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(dbs, u32, "%llu\n");
215DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(exec_quantum, u32, "%llu\n");
216DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(preempt_timeout, u32, "%llu\n");
217DEFINE_SRIOV_GT_CONFIG_DEBUGFS_ATTRIBUTE(sched_priority, u32, "%llu\n");
218
219/*
220 *      /sys/kernel/debug/dri/BDF/
221 *      ├── sriov
222 *      :   ├── pf
223 *          │   ├── tile0
224 *          │   :   ├── gt0
225 *          │       :   ├── threshold_cat_error_count
226 *          │           ├── threshold_doorbell_time_us
227 *          │           ├── threshold_engine_reset_count
228 *          │           ├── threshold_guc_time_us
229 *          │           ├── threshold_irq_time_us
230 *          │           ├── threshold_page_fault_count
231 *          ├── vf1
232 *          :   ├── tile0
233 *              :   ├── gt0
234 *                  :   ├── threshold_cat_error_count
235 *                      ├── threshold_doorbell_time_us
236 *                      ├── threshold_engine_reset_count
237 *                      ├── threshold_guc_time_us
238 *                      ├── threshold_irq_time_us
239 *                      ├── threshold_page_fault_count
240 */
241
242static int set_threshold(void *data, u64 val, enum xe_guc_klv_threshold_index index)
243{
244	struct xe_gt *gt = extract_gt(data);
245	unsigned int vfid = extract_vfid(data);
246	struct xe_device *xe = gt_to_xe(gt);
247	int err;
248
249	if (val > (u32)~0ull)
250		return -EOVERFLOW;
251
252	xe_pm_runtime_get(xe);
253	err = xe_gt_sriov_pf_config_set_threshold(gt, vfid, index, val);
254	if (!err)
255		xe_sriov_pf_provision_set_custom_mode(xe);
256	xe_pm_runtime_put(xe);
257
258	return err;
259}
260
261static int get_threshold(void *data, u64 *val, enum xe_guc_klv_threshold_index index)
262{
263	struct xe_gt *gt = extract_gt(data);
264	unsigned int vfid = extract_vfid(data);
265
266	*val = xe_gt_sriov_pf_config_get_threshold(gt, vfid, index);
267	return 0;
268}
269
270#define DEFINE_SRIOV_GT_THRESHOLD_DEBUGFS_ATTRIBUTE(THRESHOLD, INDEX)		\
271										\
272static int THRESHOLD##_set(void *data, u64 val)					\
273{										\
274	return set_threshold(data, val, INDEX);					\
275}										\
276										\
277static int THRESHOLD##_get(void *data, u64 *val)				\
278{										\
279	return get_threshold(data, val, INDEX);					\
280}										\
281										\
282DEFINE_DEBUGFS_ATTRIBUTE(THRESHOLD##_fops, THRESHOLD##_get, THRESHOLD##_set, "%llu\n")
283
284/* generate all threshold attributes */
285#define define_threshold_attribute(TAG, NAME, ...) \
286	DEFINE_SRIOV_GT_THRESHOLD_DEBUGFS_ATTRIBUTE(NAME, MAKE_XE_GUC_KLV_THRESHOLD_INDEX(TAG));
287MAKE_XE_GUC_KLV_THRESHOLDS_SET(define_threshold_attribute)
288#undef define_threshold_attribute
289
290static void pf_add_config_attrs(struct xe_gt *gt, struct dentry *parent, unsigned int vfid)
291{
292	xe_gt_assert(gt, gt == extract_gt(parent));
293	xe_gt_assert(gt, vfid == extract_vfid(parent));
294
295	debugfs_create_file_unsafe(vfid ? "doorbells_quota" : "doorbells_spare",
296				   0644, parent, parent, &dbs_fops);
297	debugfs_create_file_unsafe(vfid ? "contexts_quota" : "contexts_spare",
298				   0644, parent, parent, &ctxs_fops);
299	debugfs_create_file_unsafe("exec_quantum_ms", 0644, parent, parent,
300				   &exec_quantum_fops);
301	debugfs_create_file_unsafe("preempt_timeout_us", 0644, parent, parent,
302				   &preempt_timeout_fops);
303	debugfs_create_file_unsafe("sched_priority", 0644, parent, parent,
304				   &sched_priority_fops);
305
306	/* register all threshold attributes */
307#define register_threshold_attribute(TAG, NAME, ...) \
308	debugfs_create_file_unsafe("threshold_" #NAME, 0644, parent, parent, \
309				   &NAME##_fops);
310	MAKE_XE_GUC_KLV_THRESHOLDS_SET(register_threshold_attribute)
311#undef register_threshold_attribute
312}
313
314/*
315 *      /sys/kernel/debug/dri/BDF/
316 *      ├── sriov
317 *      :   ├── vf1
318 *          :   ├── tile0
319 *              :   ├── gt0
320 *                  :   ├── control { stop, pause, resume }
321 */
322
323static const struct {
324	const char *cmd;
325	int (*fn)(struct xe_gt *gt, unsigned int vfid);
326} control_cmds[] = {
327	{ "stop", xe_gt_sriov_pf_control_stop_vf },
328	{ "pause", xe_gt_sriov_pf_control_pause_vf },
329	{ "resume", xe_gt_sriov_pf_control_resume_vf },
330};
331
332static ssize_t control_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
333{
334	struct dentry *dent = file_dentry(file);
335	struct dentry *parent = dent->d_parent;
336	struct xe_gt *gt = extract_gt(parent);
337	struct xe_device *xe = gt_to_xe(gt);
338	unsigned int vfid = extract_vfid(parent);
339	int ret = -EINVAL;
340	char cmd[32];
341	size_t n;
342
343	xe_gt_assert(gt, vfid);
344	xe_gt_sriov_pf_assert_vfid(gt, vfid);
345
346	if (*pos)
347		return -ESPIPE;
348
349	if (count > sizeof(cmd) - 1)
350		return -EINVAL;
351
352	ret = simple_write_to_buffer(cmd, sizeof(cmd) - 1, pos, buf, count);
353	if (ret < 0)
354		return ret;
355	cmd[ret] = '\0';
356
357	for (n = 0; n < ARRAY_SIZE(control_cmds); n++) {
358		xe_gt_assert(gt, sizeof(cmd) > strlen(control_cmds[n].cmd));
359
360		if (sysfs_streq(cmd, control_cmds[n].cmd)) {
361			xe_pm_runtime_get(xe);
362			ret = control_cmds[n].fn ? (*control_cmds[n].fn)(gt, vfid) : 0;
363			xe_pm_runtime_put(xe);
364			break;
365		}
366	}
367
368	return (ret < 0) ? ret : count;
369}
370
371static ssize_t control_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
372{
373	char help[128];
374	size_t n;
375
376	help[0] = '\0';
377	for (n = 0; n < ARRAY_SIZE(control_cmds); n++) {
378		strlcat(help, control_cmds[n].cmd, sizeof(help));
379		strlcat(help, "\n", sizeof(help));
380	}
381
382	return simple_read_from_buffer(buf, count, ppos, help, strlen(help));
383}
384
385static const struct file_operations control_ops = {
386	.owner		= THIS_MODULE,
387	.open		= simple_open,
388	.write		= control_write,
389	.read		= control_read,
390	.llseek		= default_llseek,
391};
392
393/*
394 *      /sys/kernel/debug/dri/BDF/
395 *      ├── sriov
396 *      :   ├── vf1
397 *          :   ├── tile0
398 *              :   ├── gt0
399 *                  :   ├── config_blob
400 */
401
402struct config_blob_data {
403	size_t size;
404	u8 blob[];
405};
406
407static int config_blob_open(struct inode *inode, struct file *file)
408{
409	struct dentry *dent = file_dentry(file);
410	struct dentry *parent = dent->d_parent;
411	struct xe_gt *gt = extract_gt(parent);
412	unsigned int vfid = extract_vfid(parent);
413	struct config_blob_data *cbd;
414	ssize_t ret;
415
416	ret = xe_gt_sriov_pf_config_save(gt, vfid, NULL, 0);
417	if (!ret)
418		return -ENODATA;
419	if (ret < 0)
420		return ret;
421
422	cbd = kzalloc(struct_size(cbd, blob, ret), GFP_KERNEL);
423	if (!cbd)
424		return -ENOMEM;
425
426	ret = xe_gt_sriov_pf_config_save(gt, vfid, cbd->blob, ret);
427	if (ret < 0) {
428		kfree(cbd);
429		return ret;
430	}
431
432	cbd->size = ret;
433	file->private_data = cbd;
434	return nonseekable_open(inode, file);
435}
436
437static ssize_t config_blob_read(struct file *file, char __user *buf,
438				size_t count, loff_t *pos)
439{
440	struct config_blob_data *cbd = file->private_data;
441
442	return simple_read_from_buffer(buf, count, pos, cbd->blob, cbd->size);
443}
444
445static ssize_t config_blob_write(struct file *file, const char __user *buf,
446				 size_t count, loff_t *pos)
447{
448	struct dentry *dent = file_dentry(file);
449	struct dentry *parent = dent->d_parent;
450	struct xe_gt *gt = extract_gt(parent);
451	unsigned int vfid = extract_vfid(parent);
452	ssize_t ret;
453	void *tmp;
454
455	if (*pos)
456		return -EINVAL;
457
458	if (!count)
459		return -ENODATA;
460
461	if (count > SZ_4K)
462		return -EINVAL;
463
464	tmp = kzalloc(count, GFP_KERNEL);
465	if (!tmp)
466		return -ENOMEM;
467
468	if (copy_from_user(tmp, buf, count)) {
469		ret = -EFAULT;
470	} else {
471		ret = xe_gt_sriov_pf_config_restore(gt, vfid, tmp, count);
472		if (!ret)
473			ret = count;
474	}
475	kfree(tmp);
476	return ret;
477}
478
479static int config_blob_release(struct inode *inode, struct file *file)
480{
481	kfree(file->private_data);
482	return 0;
483}
484
485static const struct file_operations config_blob_ops = {
486	.owner		= THIS_MODULE,
487	.open		= config_blob_open,
488	.read		= config_blob_read,
489	.write		= config_blob_write,
490	.release	= config_blob_release,
491};
492
493static void pf_add_compat_attrs(struct xe_gt *gt, struct dentry *dent, unsigned int vfid)
494{
495	struct xe_device *xe = gt_to_xe(gt);
496
497	if (!xe_gt_is_main_type(gt))
498		return;
499
500	if (vfid) {
501		debugfs_create_symlink("ggtt_quota", dent, "../ggtt_quota");
502		if (xe_device_has_lmtt(xe))
503			debugfs_create_symlink("lmem_quota", dent, "../vram_quota");
504	} else {
505		debugfs_create_symlink("ggtt_spare", dent, "../ggtt_spare");
506		debugfs_create_symlink("ggtt_available", dent, "../ggtt_available");
507		debugfs_create_symlink("ggtt_provisioned", dent, "../ggtt_provisioned");
508		if (xe_device_has_lmtt(xe)) {
509			debugfs_create_symlink("lmem_spare", dent, "../vram_spare");
510			debugfs_create_symlink("lmem_provisioned", dent, "../vram_provisioned");
511		}
512	}
513}
514
515static void pf_populate_gt(struct xe_gt *gt, struct dentry *dent, unsigned int vfid)
516{
517	struct xe_device *xe = gt_to_xe(gt);
518	struct drm_minor *minor = xe->drm.primary;
519
520	if (vfid) {
521		pf_add_config_attrs(gt, dent, vfid);
522
523		debugfs_create_file("control", 0600, dent, NULL, &control_ops);
524
525		/* for testing/debugging purposes only! */
526		if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) {
527			debugfs_create_file("config_blob",
528					    IS_ENABLED(CONFIG_DRM_XE_DEBUG_SRIOV) ? 0600 : 0400,
529					    dent, NULL, &config_blob_ops);
530		}
531
532	} else {
533		pf_add_config_attrs(gt, dent, PFID);
534		pf_add_policy_attrs(gt, dent);
535
536		drm_debugfs_create_files(pf_info, ARRAY_SIZE(pf_info), dent, minor);
537	}
538
539	/* for backward compatibility only */
540	pf_add_compat_attrs(gt, dent, vfid);
541}
542
543/**
544 * xe_gt_sriov_pf_debugfs_populate() - Create SR-IOV GT-level debugfs directories and files.
545 * @gt: the &xe_gt to register
546 * @parent: the parent &dentry that represents a &xe_tile
547 * @vfid: the VF identifier
548 *
549 * Add to the @parent directory new debugfs directory that will represent a @gt and
550 * populate it with GT files that are related to the SR-IOV @vfid function.
551 *
552 * This function can only be called on PF.
553 */
554void xe_gt_sriov_pf_debugfs_populate(struct xe_gt *gt, struct dentry *parent, unsigned int vfid)
555{
556	struct dentry *dent;
557	char name[8]; /* should be enough up to "gt%u\0" for 2^8 - 1 */
558
559	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));
560	xe_gt_assert(gt, extract_priv(parent) == gt->tile);
561	xe_gt_assert(gt, extract_priv(parent->d_parent) == gt_to_xe(gt) ||
562		     (uintptr_t)extract_priv(parent->d_parent) == vfid);
563
564	/*
565	 *      /sys/kernel/debug/dri/BDF/
566	 *      ├── sriov
567	 *      │   ├── pf
568	 *      │   │   ├── tile0		# parent
569	 *      │   │   │   ├── gt0		# d_inode->i_private = (xe_gt*)
570	 *      │   │   │   ├── gt1
571	 *      │   │   :   :
572	 *      │   ├── vf1
573	 *      │   │   ├── tile0		# parent
574	 *      │   │   │   ├── gt0		# d_inode->i_private = (xe_gt*)
575	 *      │   │   │   ├── gt1
576	 *      │   :   :   :
577	 */
578	snprintf(name, sizeof(name), "gt%u", gt->info.id);
579	dent = debugfs_create_dir(name, parent);
580	if (IS_ERR(dent))
581		return;
582	dent->d_inode->i_private = gt;
583
584	xe_gt_assert(gt, extract_gt(dent) == gt);
585	xe_gt_assert(gt, extract_vfid(dent) == vfid);
586
587	pf_populate_gt(gt, dent, vfid);
588}
589
590static void pf_add_links(struct xe_gt *gt, struct dentry *dent)
591{
592	unsigned int totalvfs = xe_gt_sriov_pf_get_totalvfs(gt);
593	unsigned int vfid;
594	char name[16];		/* should be more than enough for "vf%u\0" and VFID(UINT_MAX) */
595	char symlink[64];	/* should be more enough for "../../sriov/vf%u/tile%u/gt%u\0" */
596
597	for (vfid = 0; vfid <= totalvfs; vfid++) {
598		if (vfid)
599			snprintf(name, sizeof(name), "vf%u", vfid);
600		else
601			snprintf(name, sizeof(name), "pf");
602		snprintf(symlink, sizeof(symlink), "../../sriov/%s/tile%u/gt%u",
603			 name, gt->tile->id, gt->info.id);
604		debugfs_create_symlink(name, dent, symlink);
605	}
606}
607
608/**
609 * xe_gt_sriov_pf_debugfs_register - Register SR-IOV PF specific entries in GT debugfs.
610 * @gt: the &xe_gt to register
611 * @dent: the &dentry that represents the GT directory
612 *
613 * Instead of actual files, create symlinks for PF and each VF to their GT specific
614 * attributes that should be already exposed in the dedicated debugfs SR-IOV tree.
615 */
616void xe_gt_sriov_pf_debugfs_register(struct xe_gt *gt, struct dentry *dent)
617{
618	xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));
619	xe_gt_assert(gt, dent->d_inode->i_private == gt);
620
621	pf_add_links(gt, dent);
622}
~/ Read-only file preview.