xref: /linux/drivers/gpu/drm/xe/xe_tile_sriov_pf_debugfs.c (revision 08c98f3f2bd7bf5dddd98b17c7caf94d07fad107)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2025 Intel Corporation
4  */
5 
6 #include <linux/debugfs.h>
7 #include <drm/drm_debugfs.h>
8 
9 #include "xe_device.h"
10 #include "xe_device_types.h"
11 #include "xe_gt_sriov_pf_config.h"
12 #include "xe_gt_sriov_pf_debugfs.h"
13 #include "xe_pm.h"
14 #include "xe_tile_debugfs.h"
15 #include "xe_tile_sriov_pf_debugfs.h"
16 #include "xe_sriov.h"
17 #include "xe_sriov_pf.h"
18 
19 /*
20  *      /sys/kernel/debug/dri/BDF/
21  *      ├── sriov		# d_inode->i_private = (xe_device*)
22  *      │   ├── pf		# d_inode->i_private = (xe_device*)
23  *      │   │   ├── tile0	# d_inode->i_private = (xe_tile*)
24  *      │   │   ├── tile1
25  *      │   │   :   :
26  *      │   ├── vf1		# d_inode->i_private = VFID(1)
27  *      │   │   ├── tile0	# d_inode->i_private = (xe_tile*)
28  *      │   │   ├── tile1
29  *      │   │   :   :
30  *      │   ├── vfN		# d_inode->i_private = VFID(N)
31  *      │   │   ├── tile0	# d_inode->i_private = (xe_tile*)
32  *      │   │   ├── tile1
33  *      :   :   :   :
34  */
35 
36 static void *extract_priv(struct dentry *d)
37 {
38 	return d->d_inode->i_private;
39 }
40 
41 __maybe_unused
42 static struct xe_tile *extract_tile(struct dentry *d)
43 {
44 	return extract_priv(d);
45 }
46 
47 static struct xe_device *extract_xe(struct dentry *d)
48 {
49 	return extract_priv(d->d_parent->d_parent);
50 }
51 
52 __maybe_unused
53 static unsigned int extract_vfid(struct dentry *d)
54 {
55 	void *pp = extract_priv(d->d_parent);
56 
57 	return pp == extract_xe(d) ? PFID : (uintptr_t)pp;
58 }
59 
60 /*
61  *      /sys/kernel/debug/dri/BDF/
62  *      ├── sriov
63  *      :   ├── pf
64  *          :   ├── tile0
65  *              :   ├── ggtt_available
66  *                  ├── ggtt_provisioned
67  */
68 
69 static int pf_config_print_available_ggtt(struct xe_tile *tile, struct drm_printer *p)
70 {
71 	return xe_gt_sriov_pf_config_print_available_ggtt(tile->primary_gt, p);
72 }
73 
74 static int pf_config_print_ggtt(struct xe_tile *tile, struct drm_printer *p)
75 {
76 	return xe_gt_sriov_pf_config_print_ggtt(tile->primary_gt, p);
77 }
78 
79 static const struct drm_info_list pf_ggtt_info[] = {
80 	{
81 		"ggtt_available",
82 		.show = xe_tile_debugfs_simple_show,
83 		.data = pf_config_print_available_ggtt,
84 	},
85 	{
86 		"ggtt_provisioned",
87 		.show = xe_tile_debugfs_simple_show,
88 		.data = pf_config_print_ggtt,
89 	},
90 };
91 
92 /*
93  *      /sys/kernel/debug/dri/BDF/
94  *      ├── sriov
95  *      :   ├── pf
96  *          :   ├── tile0
97  *              :   ├── vram_provisioned
98  */
99 
100 static int pf_config_print_vram(struct xe_tile *tile, struct drm_printer *p)
101 {
102 	return xe_gt_sriov_pf_config_print_lmem(tile->primary_gt, p);
103 }
104 
105 static const struct drm_info_list pf_vram_info[] = {
106 	{
107 		"vram_provisioned",
108 		.show = xe_tile_debugfs_simple_show,
109 		.data = pf_config_print_vram,
110 	},
111 };
112 
113 /*
114  *      /sys/kernel/debug/dri/BDF/
115  *      ├── sriov
116  *      │   ├── pf
117  *      │   │   ├── tile0
118  *      │   │   │   ├── ggtt_spare
119  *      │   │   │   ├── vram_spare
120  *      │   │   ├── tile1
121  *      │   │   :   :
122  *      │   ├── vf1
123  *      │   :   ├── tile0
124  *      │       │   ├── ggtt_quota
125  *      │       │   ├── vram_quota
126  *      │       ├── tile1
127  *      │       :   :
128  */
129 
130 #define DEFINE_SRIOV_TILE_CONFIG_DEBUGFS_ATTRIBUTE(NAME, CONFIG, TYPE, FORMAT)	\
131 										\
132 static int NAME##_set(void *data, u64 val)					\
133 {										\
134 	struct xe_tile *tile = extract_tile(data);				\
135 	unsigned int vfid = extract_vfid(data);					\
136 	struct xe_gt *gt = tile->primary_gt;					\
137 	struct xe_device *xe = tile->xe;					\
138 	int err;								\
139 										\
140 	if (val > (TYPE)~0ull)							\
141 		return -EOVERFLOW;						\
142 										\
143 	xe_pm_runtime_get(xe);							\
144 	err = xe_sriov_pf_wait_ready(xe) ?:					\
145 	      xe_gt_sriov_pf_config_set_##CONFIG(gt, vfid, val);		\
146 	xe_pm_runtime_put(xe);							\
147 										\
148 	return err;								\
149 }										\
150 										\
151 static int NAME##_get(void *data, u64 *val)					\
152 {										\
153 	struct xe_tile *tile = extract_tile(data);				\
154 	unsigned int vfid = extract_vfid(data);					\
155 	struct xe_gt *gt = tile->primary_gt;					\
156 										\
157 	*val = xe_gt_sriov_pf_config_get_##CONFIG(gt, vfid);			\
158 	return 0;								\
159 }										\
160 										\
161 DEFINE_DEBUGFS_ATTRIBUTE(NAME##_fops, NAME##_get, NAME##_set, FORMAT)
162 
163 DEFINE_SRIOV_TILE_CONFIG_DEBUGFS_ATTRIBUTE(ggtt, ggtt, u64, "%llu\n");
164 DEFINE_SRIOV_TILE_CONFIG_DEBUGFS_ATTRIBUTE(vram, lmem, u64, "%llu\n");
165 
166 static void pf_add_config_attrs(struct xe_tile *tile, struct dentry *dent, unsigned int vfid)
167 {
168 	xe_tile_assert(tile, tile == extract_tile(dent));
169 	xe_tile_assert(tile, vfid == extract_vfid(dent));
170 
171 	debugfs_create_file_unsafe(vfid ? "ggtt_quota" : "ggtt_spare",
172 				   0644, dent, dent, &ggtt_fops);
173 	if (xe_device_has_lmtt(tile->xe))
174 		debugfs_create_file_unsafe(vfid ? "vram_quota" : "vram_spare",
175 					   0644, dent, dent, &vram_fops);
176 }
177 
178 static void pf_populate_tile(struct xe_tile *tile, struct dentry *dent, unsigned int vfid)
179 {
180 	struct xe_device *xe = tile->xe;
181 	struct drm_minor *minor = xe->drm.primary;
182 	struct xe_gt *gt;
183 	unsigned int id;
184 
185 	pf_add_config_attrs(tile, dent, vfid);
186 
187 	if (!vfid) {
188 		drm_debugfs_create_files(pf_ggtt_info,
189 					 ARRAY_SIZE(pf_ggtt_info),
190 					 dent, minor);
191 		if (xe_device_has_lmtt(xe))
192 			drm_debugfs_create_files(pf_vram_info,
193 						 ARRAY_SIZE(pf_vram_info),
194 						 dent, minor);
195 	}
196 
197 	for_each_gt_on_tile(gt, tile, id)
198 		xe_gt_sriov_pf_debugfs_populate(gt, dent, vfid);
199 }
200 
201 /**
202  * xe_tile_sriov_pf_debugfs_populate() - Populate SR-IOV debugfs tree with tile files.
203  * @tile: the &xe_tile to register
204  * @parent: the parent &dentry that represents the SR-IOV @vfid function
205  * @vfid: the VF identifier
206  *
207  * Add to the @parent directory new debugfs directory that will represent a @tile and
208  * populate it with files that are related to the SR-IOV @vfid function.
209  *
210  * This function can only be called on PF.
211  */
212 void xe_tile_sriov_pf_debugfs_populate(struct xe_tile *tile, struct dentry *parent,
213 				       unsigned int vfid)
214 {
215 	struct xe_device *xe = tile->xe;
216 	struct dentry *dent;
217 	char name[10]; /* should be enough up to "tile%u\0" for 2^16 - 1 */
218 
219 	xe_tile_assert(tile, IS_SRIOV_PF(xe));
220 	xe_tile_assert(tile, extract_priv(parent->d_parent) == xe);
221 	xe_tile_assert(tile, extract_priv(parent) == tile->xe ||
222 		       (uintptr_t)extract_priv(parent) == vfid);
223 
224 	/*
225 	 *      /sys/kernel/debug/dri/BDF/
226 	 *      ├── sriov
227 	 *      │   ├── pf		# parent, d_inode->i_private = (xe_device*)
228 	 *      │   │   ├── tile0	# d_inode->i_private = (xe_tile*)
229 	 *      │   │   ├── tile1
230 	 *      │   │   :   :
231 	 *      │   ├── vf1		# parent, d_inode->i_private = VFID(1)
232 	 *      │   │   ├── tile0	# d_inode->i_private = (xe_tile*)
233 	 *      │   │   ├── tile1
234 	 *      :   :   :   :
235 	 */
236 	snprintf(name, sizeof(name), "tile%u", tile->id);
237 	dent = debugfs_create_dir(name, parent);
238 	if (IS_ERR(dent))
239 		return;
240 	dent->d_inode->i_private = tile;
241 
242 	xe_tile_assert(tile, extract_tile(dent) == tile);
243 	xe_tile_assert(tile, extract_vfid(dent) == vfid);
244 	xe_tile_assert(tile, extract_xe(dent) == xe);
245 
246 	pf_populate_tile(tile, dent, vfid);
247 }
248