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