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