xref: /linux/drivers/gpu/drm/xe/xe_tile_sriov_pf_debugfs.c (revision f6e8dc9edf963dbc99085e54f6ced6da9daa6100)
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 	xe_pm_runtime_get(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 	xe_pm_runtime_put(xe);							\
150 										\
151 	return err;								\
152 }										\
153 										\
154 static int NAME##_get(void *data, u64 *val)					\
155 {										\
156 	struct xe_tile *tile = extract_tile(data);				\
157 	unsigned int vfid = extract_vfid(data);					\
158 	struct xe_gt *gt = tile->primary_gt;					\
159 										\
160 	*val = xe_gt_sriov_pf_config_get_##CONFIG(gt, vfid);			\
161 	return 0;								\
162 }										\
163 										\
164 DEFINE_DEBUGFS_ATTRIBUTE(NAME##_fops, NAME##_get, NAME##_set, FORMAT)
165 
166 DEFINE_SRIOV_TILE_CONFIG_DEBUGFS_ATTRIBUTE(ggtt, ggtt, u64, "%llu\n");
167 DEFINE_SRIOV_TILE_CONFIG_DEBUGFS_ATTRIBUTE(vram, lmem, u64, "%llu\n");
168 
169 static void pf_add_config_attrs(struct xe_tile *tile, struct dentry *dent, unsigned int vfid)
170 {
171 	struct xe_device *xe = tile->xe;
172 
173 	xe_tile_assert(tile, tile == extract_tile(dent));
174 	xe_tile_assert(tile, vfid == extract_vfid(dent));
175 
176 	debugfs_create_file_unsafe(vfid ? "ggtt_quota" : "ggtt_spare",
177 				   0644, dent, dent, &ggtt_fops);
178 	if (IS_DGFX(xe))
179 		debugfs_create_file_unsafe(vfid ? "vram_quota" : "vram_spare",
180 					   xe_device_has_lmtt(xe) ? 0644 : 0444,
181 					   dent, dent, &vram_fops);
182 }
183 
184 static void pf_populate_tile(struct xe_tile *tile, struct dentry *dent, unsigned int vfid)
185 {
186 	struct xe_device *xe = tile->xe;
187 	struct drm_minor *minor = xe->drm.primary;
188 	struct xe_gt *gt;
189 	unsigned int id;
190 
191 	pf_add_config_attrs(tile, dent, vfid);
192 
193 	if (!vfid) {
194 		drm_debugfs_create_files(pf_ggtt_info,
195 					 ARRAY_SIZE(pf_ggtt_info),
196 					 dent, minor);
197 		if (IS_DGFX(xe))
198 			drm_debugfs_create_files(pf_vram_info,
199 						 ARRAY_SIZE(pf_vram_info),
200 						 dent, minor);
201 	}
202 
203 	for_each_gt_on_tile(gt, tile, id)
204 		xe_gt_sriov_pf_debugfs_populate(gt, dent, vfid);
205 }
206 
207 /**
208  * xe_tile_sriov_pf_debugfs_populate() - Populate SR-IOV debugfs tree with tile files.
209  * @tile: the &xe_tile to register
210  * @parent: the parent &dentry that represents the SR-IOV @vfid function
211  * @vfid: the VF identifier
212  *
213  * Add to the @parent directory new debugfs directory that will represent a @tile and
214  * populate it with files that are related to the SR-IOV @vfid function.
215  *
216  * This function can only be called on PF.
217  */
218 void xe_tile_sriov_pf_debugfs_populate(struct xe_tile *tile, struct dentry *parent,
219 				       unsigned int vfid)
220 {
221 	struct xe_device *xe = tile->xe;
222 	struct dentry *dent;
223 	char name[10]; /* should be enough up to "tile%u\0" for 2^16 - 1 */
224 
225 	xe_tile_assert(tile, IS_SRIOV_PF(xe));
226 	xe_tile_assert(tile, extract_priv(parent->d_parent) == xe);
227 	xe_tile_assert(tile, extract_priv(parent) == tile->xe ||
228 		       (uintptr_t)extract_priv(parent) == vfid);
229 
230 	/*
231 	 *      /sys/kernel/debug/dri/BDF/
232 	 *      ├── sriov
233 	 *      │   ├── pf		# parent, d_inode->i_private = (xe_device*)
234 	 *      │   │   ├── tile0	# d_inode->i_private = (xe_tile*)
235 	 *      │   │   ├── tile1
236 	 *      │   │   :   :
237 	 *      │   ├── vf1		# parent, d_inode->i_private = VFID(1)
238 	 *      │   │   ├── tile0	# d_inode->i_private = (xe_tile*)
239 	 *      │   │   ├── tile1
240 	 *      :   :   :   :
241 	 */
242 	snprintf(name, sizeof(name), "tile%u", tile->id);
243 	dent = debugfs_create_dir(name, parent);
244 	if (IS_ERR(dent))
245 		return;
246 	dent->d_inode->i_private = tile;
247 
248 	xe_tile_assert(tile, extract_tile(dent) == tile);
249 	xe_tile_assert(tile, extract_vfid(dent) == vfid);
250 	xe_tile_assert(tile, extract_xe(dent) == xe);
251 
252 	pf_populate_tile(tile, dent, vfid);
253 }
254