1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2025 Intel Corporation 4 */ 5 6 #include <linux/bitops.h> 7 #include <linux/configfs.h> 8 #include <linux/cleanup.h> 9 #include <linux/find.h> 10 #include <linux/init.h> 11 #include <linux/module.h> 12 #include <linux/pci.h> 13 #include <linux/string.h> 14 15 #include "xe_configfs.h" 16 #include "xe_hw_engine_types.h" 17 #include "xe_module.h" 18 #include "xe_pci_types.h" 19 20 /** 21 * DOC: Xe Configfs 22 * 23 * Overview 24 * ========= 25 * 26 * Configfs is a filesystem-based manager of kernel objects. XE KMD registers a 27 * configfs subsystem called ``xe`` that creates a directory in the mounted 28 * configfs directory. The user can create devices under this directory and 29 * configure them as necessary. See Documentation/filesystems/configfs.rst for 30 * more information about how configfs works. 31 * 32 * Create devices 33 * ============== 34 * 35 * To create a device, the ``xe`` module should already be loaded, but some 36 * attributes can only be set before binding the device. It can be accomplished 37 * by blocking the driver autoprobe: 38 * 39 * # echo 0 > /sys/bus/pci/drivers_autoprobe 40 * # modprobe xe 41 * 42 * In order to create a device, the user has to create a directory inside ``xe``:: 43 * 44 * # mkdir /sys/kernel/config/xe/0000:03:00.0/ 45 * 46 * Every device created is populated by the driver with entries that can be 47 * used to configure it:: 48 * 49 * /sys/kernel/config/xe/ 50 * ├── 0000:00:02.0 51 * │ └── ... 52 * ├── 0000:00:02.1 53 * │ └── ... 54 * : 55 * └── 0000:03:00.0 56 * ├── survivability_mode 57 * ├── engines_allowed 58 * └── enable_psmi 59 * 60 * After configuring the attributes as per next section, the device can be 61 * probed with:: 62 * 63 * # echo 0000:03:00.0 > /sys/bus/pci/drivers/xe/bind 64 * # # or 65 * # echo 0000:03:00.0 > /sys/bus/pci/drivers_probe 66 * 67 * Configure Attributes 68 * ==================== 69 * 70 * Survivability mode: 71 * ------------------- 72 * 73 * Enable survivability mode on supported cards. This setting only takes 74 * effect when probing the device. Example to enable it:: 75 * 76 * # echo 1 > /sys/kernel/config/xe/0000:03:00.0/survivability_mode 77 * 78 * This attribute can only be set before binding to the device. 79 * 80 * Allowed engines: 81 * ---------------- 82 * 83 * Allow only a set of engine(s) to be available, disabling the other engines 84 * even if they are available in hardware. This is applied after HW fuses are 85 * considered on each tile. Examples: 86 * 87 * Allow only one render and one copy engines, nothing else:: 88 * 89 * # echo 'rcs0,bcs0' > /sys/kernel/config/xe/0000:03:00.0/engines_allowed 90 * 91 * Allow only compute engines and first copy engine:: 92 * 93 * # echo 'ccs*,bcs0' > /sys/kernel/config/xe/0000:03:00.0/engines_allowed 94 * 95 * Note that the engine names are the per-GT hardware names. On multi-tile 96 * platforms, writing ``rcs0,bcs0`` to this file would allow the first render 97 * and copy engines on each tile. 98 * 99 * The requested configuration may not be supported by the platform and driver 100 * may fail to probe. For example: if at least one copy engine is expected to be 101 * available for migrations, but it's disabled. This is intended for debugging 102 * purposes only. 103 * 104 * This attribute can only be set before binding to the device. 105 * 106 * PSMI 107 * ---- 108 * 109 * Enable extra debugging capabilities to trace engine execution. Only useful 110 * during early platform enabling and requires additional hardware connected. 111 * Once it's enabled, additionals WAs are added and runtime configuration is 112 * done via debugfs. Example to enable it:: 113 * 114 * # echo 1 > /sys/kernel/config/xe/0000:03:00.0/enable_psmi 115 * 116 * This attribute can only be set before binding to the device. 117 * 118 * Remove devices 119 * ============== 120 * 121 * The created device directories can be removed using ``rmdir``:: 122 * 123 * # rmdir /sys/kernel/config/xe/0000:03:00.0/ 124 */ 125 126 struct xe_config_group_device { 127 struct config_group group; 128 129 struct xe_config_device { 130 u64 engines_allowed; 131 bool survivability_mode; 132 bool enable_psmi; 133 } config; 134 135 /* protects attributes */ 136 struct mutex lock; 137 }; 138 139 static const struct xe_config_device device_defaults = { 140 .engines_allowed = U64_MAX, 141 .survivability_mode = false, 142 .enable_psmi = false, 143 }; 144 145 static void set_device_defaults(struct xe_config_device *config) 146 { 147 *config = device_defaults; 148 } 149 150 struct engine_info { 151 const char *cls; 152 u64 mask; 153 }; 154 155 /* Some helpful macros to aid on the sizing of buffer allocation when parsing */ 156 #define MAX_ENGINE_CLASS_CHARS 5 157 #define MAX_ENGINE_INSTANCE_CHARS 2 158 159 static const struct engine_info engine_info[] = { 160 { .cls = "rcs", .mask = XE_HW_ENGINE_RCS_MASK }, 161 { .cls = "bcs", .mask = XE_HW_ENGINE_BCS_MASK }, 162 { .cls = "vcs", .mask = XE_HW_ENGINE_VCS_MASK }, 163 { .cls = "vecs", .mask = XE_HW_ENGINE_VECS_MASK }, 164 { .cls = "ccs", .mask = XE_HW_ENGINE_CCS_MASK }, 165 { .cls = "gsccs", .mask = XE_HW_ENGINE_GSCCS_MASK }, 166 }; 167 168 static struct xe_config_group_device *to_xe_config_group_device(struct config_item *item) 169 { 170 return container_of(to_config_group(item), struct xe_config_group_device, group); 171 } 172 173 static struct xe_config_device *to_xe_config_device(struct config_item *item) 174 { 175 return &to_xe_config_group_device(item)->config; 176 } 177 178 static bool is_bound(struct xe_config_group_device *dev) 179 { 180 unsigned int domain, bus, slot, function; 181 struct pci_dev *pdev; 182 const char *name; 183 bool ret; 184 185 lockdep_assert_held(&dev->lock); 186 187 name = dev->group.cg_item.ci_name; 188 if (sscanf(name, "%x:%x:%x.%x", &domain, &bus, &slot, &function) != 4) 189 return false; 190 191 pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(slot, function)); 192 if (!pdev) 193 return false; 194 195 ret = pci_get_drvdata(pdev); 196 pci_dev_put(pdev); 197 198 if (ret) 199 pci_dbg(pdev, "Already bound to driver\n"); 200 201 return ret; 202 } 203 204 static ssize_t survivability_mode_show(struct config_item *item, char *page) 205 { 206 struct xe_config_device *dev = to_xe_config_device(item); 207 208 return sprintf(page, "%d\n", dev->survivability_mode); 209 } 210 211 static ssize_t survivability_mode_store(struct config_item *item, const char *page, size_t len) 212 { 213 struct xe_config_group_device *dev = to_xe_config_group_device(item); 214 bool survivability_mode; 215 int ret; 216 217 ret = kstrtobool(page, &survivability_mode); 218 if (ret) 219 return ret; 220 221 guard(mutex)(&dev->lock); 222 if (is_bound(dev)) 223 return -EBUSY; 224 225 dev->config.survivability_mode = survivability_mode; 226 227 return len; 228 } 229 230 static ssize_t engines_allowed_show(struct config_item *item, char *page) 231 { 232 struct xe_config_device *dev = to_xe_config_device(item); 233 char *p = page; 234 235 for (size_t i = 0; i < ARRAY_SIZE(engine_info); i++) { 236 u64 mask = engine_info[i].mask; 237 238 if ((dev->engines_allowed & mask) == mask) { 239 p += sprintf(p, "%s*\n", engine_info[i].cls); 240 } else if (mask & dev->engines_allowed) { 241 u16 bit0 = __ffs64(mask), bit; 242 243 mask &= dev->engines_allowed; 244 245 for_each_set_bit(bit, (const unsigned long *)&mask, 64) 246 p += sprintf(p, "%s%u\n", engine_info[i].cls, 247 bit - bit0); 248 } 249 } 250 251 return p - page; 252 } 253 254 static bool lookup_engine_mask(const char *pattern, u64 *mask) 255 { 256 for (size_t i = 0; i < ARRAY_SIZE(engine_info); i++) { 257 u8 instance; 258 u16 bit; 259 260 if (!str_has_prefix(pattern, engine_info[i].cls)) 261 continue; 262 263 pattern += strlen(engine_info[i].cls); 264 265 if (!strcmp(pattern, "*")) { 266 *mask = engine_info[i].mask; 267 return true; 268 } 269 270 if (kstrtou8(pattern, 10, &instance)) 271 return false; 272 273 bit = __ffs64(engine_info[i].mask) + instance; 274 if (bit >= fls64(engine_info[i].mask)) 275 return false; 276 277 *mask = BIT_ULL(bit); 278 return true; 279 } 280 281 return false; 282 } 283 284 static ssize_t engines_allowed_store(struct config_item *item, const char *page, 285 size_t len) 286 { 287 struct xe_config_group_device *dev = to_xe_config_group_device(item); 288 size_t patternlen, p; 289 u64 mask, val = 0; 290 291 for (p = 0; p < len; p += patternlen + 1) { 292 char buf[MAX_ENGINE_CLASS_CHARS + MAX_ENGINE_INSTANCE_CHARS + 1]; 293 294 patternlen = strcspn(page + p, ",\n"); 295 if (patternlen >= sizeof(buf)) 296 return -EINVAL; 297 298 memcpy(buf, page + p, patternlen); 299 buf[patternlen] = '\0'; 300 301 if (!lookup_engine_mask(buf, &mask)) 302 return -EINVAL; 303 304 val |= mask; 305 } 306 307 guard(mutex)(&dev->lock); 308 if (is_bound(dev)) 309 return -EBUSY; 310 311 dev->config.engines_allowed = val; 312 313 return len; 314 } 315 316 static ssize_t enable_psmi_show(struct config_item *item, char *page) 317 { 318 struct xe_config_device *dev = to_xe_config_device(item); 319 320 return sprintf(page, "%d\n", dev->enable_psmi); 321 } 322 323 static ssize_t enable_psmi_store(struct config_item *item, const char *page, size_t len) 324 { 325 struct xe_config_group_device *dev = to_xe_config_group_device(item); 326 bool val; 327 int ret; 328 329 ret = kstrtobool(page, &val); 330 if (ret) 331 return ret; 332 333 guard(mutex)(&dev->lock); 334 if (is_bound(dev)) 335 return -EBUSY; 336 337 dev->config.enable_psmi = val; 338 339 return len; 340 } 341 342 CONFIGFS_ATTR(, enable_psmi); 343 CONFIGFS_ATTR(, engines_allowed); 344 CONFIGFS_ATTR(, survivability_mode); 345 346 static struct configfs_attribute *xe_config_device_attrs[] = { 347 &attr_enable_psmi, 348 &attr_engines_allowed, 349 &attr_survivability_mode, 350 NULL, 351 }; 352 353 static void xe_config_device_release(struct config_item *item) 354 { 355 struct xe_config_group_device *dev = to_xe_config_group_device(item); 356 357 mutex_destroy(&dev->lock); 358 kfree(dev); 359 } 360 361 static struct configfs_item_operations xe_config_device_ops = { 362 .release = xe_config_device_release, 363 }; 364 365 static const struct config_item_type xe_config_device_type = { 366 .ct_item_ops = &xe_config_device_ops, 367 .ct_attrs = xe_config_device_attrs, 368 .ct_owner = THIS_MODULE, 369 }; 370 371 static const struct xe_device_desc *xe_match_desc(struct pci_dev *pdev) 372 { 373 struct device_driver *driver = driver_find("xe", &pci_bus_type); 374 struct pci_driver *drv = to_pci_driver(driver); 375 const struct pci_device_id *ids = drv ? drv->id_table : NULL; 376 const struct pci_device_id *found = pci_match_id(ids, pdev); 377 378 return found ? (const void *)found->driver_data : NULL; 379 } 380 381 static struct pci_dev *get_physfn_instead(struct pci_dev *virtfn) 382 { 383 struct pci_dev *physfn = pci_physfn(virtfn); 384 385 pci_dev_get(physfn); 386 pci_dev_put(virtfn); 387 return physfn; 388 } 389 390 static struct config_group *xe_config_make_device_group(struct config_group *group, 391 const char *name) 392 { 393 unsigned int domain, bus, slot, function; 394 struct xe_config_group_device *dev; 395 const struct xe_device_desc *match; 396 struct pci_dev *pdev; 397 char canonical[16]; 398 int vfnumber = 0; 399 int ret; 400 401 ret = sscanf(name, "%x:%x:%x.%x", &domain, &bus, &slot, &function); 402 if (ret != 4) 403 return ERR_PTR(-EINVAL); 404 405 ret = scnprintf(canonical, sizeof(canonical), "%04x:%02x:%02x.%d", domain, bus, 406 PCI_SLOT(PCI_DEVFN(slot, function)), 407 PCI_FUNC(PCI_DEVFN(slot, function))); 408 if (ret != 12 || strcmp(name, canonical)) 409 return ERR_PTR(-EINVAL); 410 411 pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(slot, function)); 412 if (!pdev && function) 413 pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(slot, 0)); 414 if (!pdev && slot) 415 pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(0, 0)); 416 if (!pdev) 417 return ERR_PTR(-ENODEV); 418 419 if (PCI_DEVFN(slot, function) != pdev->devfn) { 420 pdev = get_physfn_instead(pdev); 421 vfnumber = PCI_DEVFN(slot, function) - pdev->devfn; 422 if (!dev_is_pf(&pdev->dev) || vfnumber > pci_sriov_get_totalvfs(pdev)) { 423 pci_dev_put(pdev); 424 return ERR_PTR(-ENODEV); 425 } 426 } 427 428 match = xe_match_desc(pdev); 429 if (match && vfnumber && !match->has_sriov) { 430 pci_info(pdev, "xe driver does not support VFs on this device\n"); 431 match = NULL; 432 } else if (!match) { 433 pci_info(pdev, "xe driver does not support configuration of this device\n"); 434 } 435 436 pci_dev_put(pdev); 437 438 if (!match) 439 return ERR_PTR(-ENOENT); 440 441 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 442 if (!dev) 443 return ERR_PTR(-ENOMEM); 444 445 set_device_defaults(&dev->config); 446 447 config_group_init_type_name(&dev->group, name, &xe_config_device_type); 448 449 mutex_init(&dev->lock); 450 451 return &dev->group; 452 } 453 454 static struct configfs_group_operations xe_config_device_group_ops = { 455 .make_group = xe_config_make_device_group, 456 }; 457 458 static const struct config_item_type xe_configfs_type = { 459 .ct_group_ops = &xe_config_device_group_ops, 460 .ct_owner = THIS_MODULE, 461 }; 462 463 static struct configfs_subsystem xe_configfs = { 464 .su_group = { 465 .cg_item = { 466 .ci_namebuf = "xe", 467 .ci_type = &xe_configfs_type, 468 }, 469 }, 470 }; 471 472 static struct xe_config_group_device *find_xe_config_group_device(struct pci_dev *pdev) 473 { 474 struct config_item *item; 475 476 mutex_lock(&xe_configfs.su_mutex); 477 item = config_group_find_item(&xe_configfs.su_group, pci_name(pdev)); 478 mutex_unlock(&xe_configfs.su_mutex); 479 480 if (!item) 481 return NULL; 482 483 return to_xe_config_group_device(item); 484 } 485 486 static void dump_custom_dev_config(struct pci_dev *pdev, 487 struct xe_config_group_device *dev) 488 { 489 #define PRI_CUSTOM_ATTR(fmt_, attr_) do { \ 490 if (dev->config.attr_ != device_defaults.attr_) \ 491 pci_info(pdev, "configfs: " __stringify(attr_) " = " fmt_ "\n", \ 492 dev->config.attr_); \ 493 } while (0) 494 495 PRI_CUSTOM_ATTR("%llx", engines_allowed); 496 PRI_CUSTOM_ATTR("%d", enable_psmi); 497 PRI_CUSTOM_ATTR("%d", survivability_mode); 498 499 #undef PRI_CUSTOM_ATTR 500 } 501 502 /** 503 * xe_configfs_check_device() - Test if device was configured by configfs 504 * @pdev: the &pci_dev device to test 505 * 506 * Try to find the configfs group that belongs to the specified pci device 507 * and print a diagnostic message if different than the default value. 508 */ 509 void xe_configfs_check_device(struct pci_dev *pdev) 510 { 511 struct xe_config_group_device *dev = find_xe_config_group_device(pdev); 512 513 if (!dev) 514 return; 515 516 /* memcmp here is safe as both are zero-initialized */ 517 if (memcmp(&dev->config, &device_defaults, sizeof(dev->config))) { 518 pci_info(pdev, "Found custom settings in configfs\n"); 519 dump_custom_dev_config(pdev, dev); 520 } 521 522 config_group_put(&dev->group); 523 } 524 525 /** 526 * xe_configfs_get_survivability_mode - get configfs survivability mode attribute 527 * @pdev: pci device 528 * 529 * Return: survivability_mode attribute in configfs 530 */ 531 bool xe_configfs_get_survivability_mode(struct pci_dev *pdev) 532 { 533 struct xe_config_group_device *dev = find_xe_config_group_device(pdev); 534 bool mode; 535 536 if (!dev) 537 return device_defaults.survivability_mode; 538 539 mode = dev->config.survivability_mode; 540 config_group_put(&dev->group); 541 542 return mode; 543 } 544 545 /** 546 * xe_configfs_clear_survivability_mode - clear configfs survivability mode 547 * @pdev: pci device 548 */ 549 void xe_configfs_clear_survivability_mode(struct pci_dev *pdev) 550 { 551 struct xe_config_group_device *dev = find_xe_config_group_device(pdev); 552 553 if (!dev) 554 return; 555 556 guard(mutex)(&dev->lock); 557 dev->config.survivability_mode = 0; 558 559 config_group_put(&dev->group); 560 } 561 562 /** 563 * xe_configfs_get_engines_allowed - get engine allowed mask from configfs 564 * @pdev: pci device 565 * 566 * Return: engine mask with allowed engines set in configfs 567 */ 568 u64 xe_configfs_get_engines_allowed(struct pci_dev *pdev) 569 { 570 struct xe_config_group_device *dev = find_xe_config_group_device(pdev); 571 u64 engines_allowed; 572 573 if (!dev) 574 return device_defaults.engines_allowed; 575 576 engines_allowed = dev->config.engines_allowed; 577 config_group_put(&dev->group); 578 579 return engines_allowed; 580 } 581 582 /** 583 * xe_configfs_get_psmi_enabled - get configfs enable_psmi setting 584 * @pdev: pci device 585 * 586 * Return: enable_psmi setting in configfs 587 */ 588 bool xe_configfs_get_psmi_enabled(struct pci_dev *pdev) 589 { 590 struct xe_config_group_device *dev = find_xe_config_group_device(pdev); 591 bool ret; 592 593 if (!dev) 594 return false; 595 596 ret = dev->config.enable_psmi; 597 config_item_put(&dev->group.cg_item); 598 599 return ret; 600 } 601 602 int __init xe_configfs_init(void) 603 { 604 int ret; 605 606 config_group_init(&xe_configfs.su_group); 607 mutex_init(&xe_configfs.su_mutex); 608 ret = configfs_register_subsystem(&xe_configfs); 609 if (ret) { 610 mutex_destroy(&xe_configfs.su_mutex); 611 return ret; 612 } 613 614 return 0; 615 } 616 617 void __exit xe_configfs_exit(void) 618 { 619 configfs_unregister_subsystem(&xe_configfs); 620 mutex_destroy(&xe_configfs.su_mutex); 621 } 622