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