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
37static void *extract_priv(struct dentry *d)
38{
39 return d->d_inode->i_private;
40}
41
42__maybe_unused
43static struct xe_tile *extract_tile(struct dentry *d)
44{
45 return extract_priv(d);
46}
47
48static struct xe_device *extract_xe(struct dentry *d)
49{
50 return extract_priv(d: d->d_parent->d_parent);
51}
52
53__maybe_unused
54static unsigned int extract_vfid(struct dentry *d)
55{
56 void *pp = extract_priv(d: 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
70static 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(gt: tile->primary_gt, p);
73}
74
75static int pf_config_print_ggtt(struct xe_tile *tile, struct drm_printer *p)
76{
77 return xe_gt_sriov_pf_config_print_ggtt(gt: tile->primary_gt, p);
78}
79
80static 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
101static int pf_config_print_vram(struct xe_tile *tile, struct drm_printer *p)
102{
103 return xe_gt_sriov_pf_config_print_lmem(gt: tile->primary_gt, p);
104}
105
106static 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 \
133static 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 \
154static 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 \
164DEFINE_DEBUGFS_ATTRIBUTE(NAME##_fops, NAME##_get, NAME##_set, FORMAT)
165
166DEFINE_SRIOV_TILE_CONFIG_DEBUGFS_ATTRIBUTE(ggtt, ggtt, u64, "%llu\n");
167DEFINE_SRIOV_TILE_CONFIG_DEBUGFS_ATTRIBUTE(vram, lmem, u64, "%llu\n");
168
169static 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(name: vfid ? "ggtt_quota" : "ggtt_spare",
177 mode: 0644, parent: dent, data: dent, fops: &ggtt_fops);
178 if (IS_DGFX(xe))
179 debugfs_create_file_unsafe(name: vfid ? "vram_quota" : "vram_spare",
180 mode: xe_device_has_lmtt(xe) ? 0644 : 0444,
181 parent: dent, data: dent, fops: &vram_fops);
182}
183
184static 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(files: pf_ggtt_info,
195 ARRAY_SIZE(pf_ggtt_info),
196 root: dent, minor);
197 if (IS_DGFX(xe))
198 drm_debugfs_create_files(files: pf_vram_info,
199 ARRAY_SIZE(pf_vram_info),
200 root: dent, minor);
201 }
202
203 for_each_gt_on_tile(gt, tile, id)
204 xe_gt_sriov_pf_debugfs_populate(gt, parent: 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 */
218void 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(buf: name, size: sizeof(name), fmt: "tile%u", tile->id);
243 dent = debugfs_create_dir(name, parent);
244 if (IS_ERR(ptr: 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

source code of linux/drivers/gpu/drm/xe/xe_tile_sriov_pf_debugfs.c