1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2025 Intel Corporation 4 */ 5 6 #include <linux/bitops.h> 7 #include <linux/ctype.h> 8 #include <linux/configfs.h> 9 #include <linux/cleanup.h> 10 #include <linux/find.h> 11 #include <linux/init.h> 12 #include <linux/module.h> 13 #include <linux/pci.h> 14 #include <linux/string.h> 15 16 #include "instructions/xe_mi_commands.h" 17 #include "xe_configfs.h" 18 #include "xe_hw_engine_types.h" 19 #include "xe_module.h" 20 #include "xe_pci_types.h" 21 22 /** 23 * DOC: Xe Configfs 24 * 25 * Overview 26 * ======== 27 * 28 * Configfs is a filesystem-based manager of kernel objects. XE KMD registers a 29 * configfs subsystem called ``xe`` that creates a directory in the mounted 30 * configfs directory. The user can create devices under this directory and 31 * configure them as necessary. See Documentation/filesystems/configfs.rst for 32 * more information about how configfs works. 33 * 34 * Create devices 35 * ============== 36 * 37 * To create a device, the ``xe`` module should already be loaded, but some 38 * attributes can only be set before binding the device. It can be accomplished 39 * by blocking the driver autoprobe:: 40 * 41 * # echo 0 > /sys/bus/pci/drivers_autoprobe 42 * # modprobe xe 43 * 44 * In order to create a device, the user has to create a directory inside ``xe``:: 45 * 46 * # mkdir /sys/kernel/config/xe/0000:03:00.0/ 47 * 48 * Every device created is populated by the driver with entries that can be 49 * used to configure it:: 50 * 51 * /sys/kernel/config/xe/ 52 * ├── 0000:00:02.0 53 * │ └── ... 54 * ├── 0000:00:02.1 55 * │ └── ... 56 * : 57 * └── 0000:03:00.0 58 * ├── survivability_mode 59 * ├── engines_allowed 60 * └── enable_psmi 61 * 62 * After configuring the attributes as per next section, the device can be 63 * probed with:: 64 * 65 * # echo 0000:03:00.0 > /sys/bus/pci/drivers/xe/bind 66 * # # or 67 * # echo 0000:03:00.0 > /sys/bus/pci/drivers_probe 68 * 69 * Configure Attributes 70 * ==================== 71 * 72 * Survivability mode: 73 * ------------------- 74 * 75 * Enable survivability mode on supported cards. This setting only takes 76 * effect when probing the device. Example to enable it:: 77 * 78 * # echo 1 > /sys/kernel/config/xe/0000:03:00.0/survivability_mode 79 * 80 * This attribute can only be set before binding to the device. 81 * 82 * Allowed engines: 83 * ---------------- 84 * 85 * Allow only a set of engine(s) to be available, disabling the other engines 86 * even if they are available in hardware. This is applied after HW fuses are 87 * considered on each tile. Examples: 88 * 89 * Allow only one render and one copy engines, nothing else:: 90 * 91 * # echo 'rcs0,bcs0' > /sys/kernel/config/xe/0000:03:00.0/engines_allowed 92 * 93 * Allow only compute engines and first copy engine:: 94 * 95 * # echo 'ccs*,bcs0' > /sys/kernel/config/xe/0000:03:00.0/engines_allowed 96 * 97 * Note that the engine names are the per-GT hardware names. On multi-tile 98 * platforms, writing ``rcs0,bcs0`` to this file would allow the first render 99 * and copy engines on each tile. 100 * 101 * The requested configuration may not be supported by the platform and driver 102 * may fail to probe. For example: if at least one copy engine is expected to be 103 * available for migrations, but it's disabled. This is intended for debugging 104 * purposes only. 105 * 106 * This attribute can only be set before binding to the device. 107 * 108 * PSMI 109 * ---- 110 * 111 * Enable extra debugging capabilities to trace engine execution. Only useful 112 * during early platform enabling and requires additional hardware connected. 113 * Once it's enabled, additionals WAs are added and runtime configuration is 114 * done via debugfs. Example to enable it:: 115 * 116 * # echo 1 > /sys/kernel/config/xe/0000:03:00.0/enable_psmi 117 * 118 * This attribute can only be set before binding to the device. 119 * 120 * Context restore BB 121 * ------------------ 122 * 123 * Allow to execute a batch buffer during any context switches. When the 124 * GPU is restoring the context, it executes additional commands. It's useful 125 * for testing additional workarounds and validating certain HW behaviors: it's 126 * not intended for normal execution and will taint the kernel with TAINT_TEST 127 * when used. 128 * 129 * The syntax allows to pass straight instructions to be executed by the engine 130 * in a batch buffer or set specific registers. 131 * 132 * #. Generic instruction:: 133 * 134 * <engine-class> cmd <instr> [[dword0] [dword1] [...]] 135 * 136 * #. Simple register setting:: 137 * 138 * <engine-class> reg <address> <value> 139 * 140 * Commands are saved per engine class: all instances of that class will execute 141 * those commands during context switch. The instruction, dword arguments, 142 * addresses and values are in hex format like in the examples below. 143 * 144 * #. Execute a LRI command to write 0xDEADBEEF to register 0x4f10 after the 145 * normal context restore:: 146 * 147 * # echo 'rcs cmd 11000001 4F100 DEADBEEF' \ 148 * > /sys/kernel/config/xe/0000:03:00.0/ctx_restore_post_bb 149 * 150 * #. Execute a LRI command to write 0xDEADBEEF to register 0x4f10 at the 151 * beginning of the context restore:: 152 * 153 * # echo 'rcs cmd 11000001 4F100 DEADBEEF' \ 154 * > /sys/kernel/config/xe/0000:03:00.0/ctx_restore_mid_bb 155 156 * #. Load certain values in a couple of registers (it can be used as a simpler 157 * alternative to the `cmd`) action:: 158 * 159 * # cat > /sys/kernel/config/xe/0000:03:00.0/ctx_restore_post_bb <<EOF 160 * rcs reg 4F100 DEADBEEF 161 * rcs reg 4F104 FFFFFFFF 162 * EOF 163 * 164 * .. note:: 165 * 166 * When using multiple lines, make sure to use a command that is 167 * implemented with a single write syscall, like HEREDOC. 168 * 169 * Currently this is implemented only for post and mid context restore and 170 * these attributes can only be set before binding to the device. 171 * 172 * Remove devices 173 * ============== 174 * 175 * The created device directories can be removed using ``rmdir``:: 176 * 177 * # rmdir /sys/kernel/config/xe/0000:03:00.0/ 178 */ 179 180 /* Similar to struct xe_bb, but not tied to HW (yet) */ 181 struct wa_bb { 182 u32 *cs; 183 u32 len; /* in dwords */ 184 }; 185 186 struct xe_config_group_device { 187 struct config_group group; 188 189 struct xe_config_device { 190 u64 engines_allowed; 191 struct wa_bb ctx_restore_post_bb[XE_ENGINE_CLASS_MAX]; 192 struct wa_bb ctx_restore_mid_bb[XE_ENGINE_CLASS_MAX]; 193 bool survivability_mode; 194 bool enable_psmi; 195 } config; 196 197 /* protects attributes */ 198 struct mutex lock; 199 /* matching descriptor */ 200 const struct xe_device_desc *desc; 201 }; 202 203 static const struct xe_config_device device_defaults = { 204 .engines_allowed = U64_MAX, 205 .survivability_mode = false, 206 .enable_psmi = false, 207 }; 208 209 static void set_device_defaults(struct xe_config_device *config) 210 { 211 *config = device_defaults; 212 } 213 214 struct engine_info { 215 const char *cls; 216 u64 mask; 217 enum xe_engine_class engine_class; 218 }; 219 220 /* Some helpful macros to aid on the sizing of buffer allocation when parsing */ 221 #define MAX_ENGINE_CLASS_CHARS 5 222 #define MAX_ENGINE_INSTANCE_CHARS 2 223 224 static const struct engine_info engine_info[] = { 225 { .cls = "rcs", .mask = XE_HW_ENGINE_RCS_MASK, .engine_class = XE_ENGINE_CLASS_RENDER }, 226 { .cls = "bcs", .mask = XE_HW_ENGINE_BCS_MASK, .engine_class = XE_ENGINE_CLASS_COPY }, 227 { .cls = "vcs", .mask = XE_HW_ENGINE_VCS_MASK, .engine_class = XE_ENGINE_CLASS_VIDEO_DECODE }, 228 { .cls = "vecs", .mask = XE_HW_ENGINE_VECS_MASK, .engine_class = XE_ENGINE_CLASS_VIDEO_ENHANCE }, 229 { .cls = "ccs", .mask = XE_HW_ENGINE_CCS_MASK, .engine_class = XE_ENGINE_CLASS_COMPUTE }, 230 { .cls = "gsccs", .mask = XE_HW_ENGINE_GSCCS_MASK, .engine_class = XE_ENGINE_CLASS_OTHER }, 231 }; 232 233 static struct xe_config_group_device *to_xe_config_group_device(struct config_item *item) 234 { 235 return container_of(to_config_group(item), struct xe_config_group_device, group); 236 } 237 238 static struct xe_config_device *to_xe_config_device(struct config_item *item) 239 { 240 return &to_xe_config_group_device(item)->config; 241 } 242 243 static bool is_bound(struct xe_config_group_device *dev) 244 { 245 unsigned int domain, bus, slot, function; 246 struct pci_dev *pdev; 247 const char *name; 248 bool ret; 249 250 lockdep_assert_held(&dev->lock); 251 252 name = dev->group.cg_item.ci_name; 253 if (sscanf(name, "%x:%x:%x.%x", &domain, &bus, &slot, &function) != 4) 254 return false; 255 256 pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(slot, function)); 257 if (!pdev) 258 return false; 259 260 ret = pci_get_drvdata(pdev); 261 pci_dev_put(pdev); 262 263 if (ret) 264 pci_dbg(pdev, "Already bound to driver\n"); 265 266 return ret; 267 } 268 269 static ssize_t survivability_mode_show(struct config_item *item, char *page) 270 { 271 struct xe_config_device *dev = to_xe_config_device(item); 272 273 return sprintf(page, "%d\n", dev->survivability_mode); 274 } 275 276 static ssize_t survivability_mode_store(struct config_item *item, const char *page, size_t len) 277 { 278 struct xe_config_group_device *dev = to_xe_config_group_device(item); 279 bool survivability_mode; 280 int ret; 281 282 ret = kstrtobool(page, &survivability_mode); 283 if (ret) 284 return ret; 285 286 guard(mutex)(&dev->lock); 287 if (is_bound(dev)) 288 return -EBUSY; 289 290 dev->config.survivability_mode = survivability_mode; 291 292 return len; 293 } 294 295 static ssize_t engines_allowed_show(struct config_item *item, char *page) 296 { 297 struct xe_config_device *dev = to_xe_config_device(item); 298 char *p = page; 299 300 for (size_t i = 0; i < ARRAY_SIZE(engine_info); i++) { 301 u64 mask = engine_info[i].mask; 302 303 if ((dev->engines_allowed & mask) == mask) { 304 p += sprintf(p, "%s*\n", engine_info[i].cls); 305 } else if (mask & dev->engines_allowed) { 306 u16 bit0 = __ffs64(mask), bit; 307 308 mask &= dev->engines_allowed; 309 310 for_each_set_bit(bit, (const unsigned long *)&mask, 64) 311 p += sprintf(p, "%s%u\n", engine_info[i].cls, 312 bit - bit0); 313 } 314 } 315 316 return p - page; 317 } 318 319 /* 320 * Lookup engine_info. If @mask is not NULL, reduce the mask according to the 321 * instance in @pattern. 322 * 323 * Examples of inputs: 324 * - lookup_engine_info("rcs0", &mask): return "rcs" entry from @engine_info and 325 * mask == BIT_ULL(XE_HW_ENGINE_RCS0) 326 * - lookup_engine_info("rcs*", &mask): return "rcs" entry from @engine_info and 327 * mask == XE_HW_ENGINE_RCS_MASK 328 * - lookup_engine_info("rcs", NULL): return "rcs" entry from @engine_info 329 */ 330 static const struct engine_info *lookup_engine_info(const char *pattern, u64 *mask) 331 { 332 for (size_t i = 0; i < ARRAY_SIZE(engine_info); i++) { 333 u8 instance; 334 u16 bit; 335 336 if (!str_has_prefix(pattern, engine_info[i].cls)) 337 continue; 338 339 pattern += strlen(engine_info[i].cls); 340 if (!mask) 341 return *pattern ? NULL : &engine_info[i]; 342 343 if (!strcmp(pattern, "*")) { 344 *mask = engine_info[i].mask; 345 return &engine_info[i]; 346 } 347 348 if (kstrtou8(pattern, 10, &instance)) 349 return NULL; 350 351 bit = __ffs64(engine_info[i].mask) + instance; 352 if (bit >= fls64(engine_info[i].mask)) 353 return NULL; 354 355 *mask = BIT_ULL(bit); 356 return &engine_info[i]; 357 } 358 359 return NULL; 360 } 361 362 static int parse_engine(const char *s, const char *end_chars, u64 *mask, 363 const struct engine_info **pinfo) 364 { 365 char buf[MAX_ENGINE_CLASS_CHARS + MAX_ENGINE_INSTANCE_CHARS + 1]; 366 const struct engine_info *info; 367 size_t len; 368 369 len = strcspn(s, end_chars); 370 if (len >= sizeof(buf)) 371 return -EINVAL; 372 373 memcpy(buf, s, len); 374 buf[len] = '\0'; 375 376 info = lookup_engine_info(buf, mask); 377 if (!info) 378 return -ENOENT; 379 380 if (pinfo) 381 *pinfo = info; 382 383 return len; 384 } 385 386 static ssize_t engines_allowed_store(struct config_item *item, const char *page, 387 size_t len) 388 { 389 struct xe_config_group_device *dev = to_xe_config_group_device(item); 390 ssize_t patternlen, p; 391 u64 mask, val = 0; 392 393 for (p = 0; p < len; p += patternlen + 1) { 394 patternlen = parse_engine(page + p, ",\n", &mask, NULL); 395 if (patternlen < 0) 396 return -EINVAL; 397 398 val |= mask; 399 } 400 401 guard(mutex)(&dev->lock); 402 if (is_bound(dev)) 403 return -EBUSY; 404 405 dev->config.engines_allowed = val; 406 407 return len; 408 } 409 410 static ssize_t enable_psmi_show(struct config_item *item, char *page) 411 { 412 struct xe_config_device *dev = to_xe_config_device(item); 413 414 return sprintf(page, "%d\n", dev->enable_psmi); 415 } 416 417 static ssize_t enable_psmi_store(struct config_item *item, const char *page, size_t len) 418 { 419 struct xe_config_group_device *dev = to_xe_config_group_device(item); 420 bool val; 421 int ret; 422 423 ret = kstrtobool(page, &val); 424 if (ret) 425 return ret; 426 427 guard(mutex)(&dev->lock); 428 if (is_bound(dev)) 429 return -EBUSY; 430 431 dev->config.enable_psmi = val; 432 433 return len; 434 } 435 436 static bool wa_bb_read_advance(bool dereference, char **p, 437 const char *append, size_t len, 438 size_t *max_size) 439 { 440 if (dereference) { 441 if (len >= *max_size) 442 return false; 443 *max_size -= len; 444 if (append) 445 memcpy(*p, append, len); 446 } 447 448 *p += len; 449 450 return true; 451 } 452 453 static ssize_t wa_bb_show(struct xe_config_group_device *dev, 454 struct wa_bb wa_bb[static XE_ENGINE_CLASS_MAX], 455 char *data, size_t sz) 456 { 457 char *p = data; 458 459 guard(mutex)(&dev->lock); 460 461 for (size_t i = 0; i < ARRAY_SIZE(engine_info); i++) { 462 enum xe_engine_class ec = engine_info[i].engine_class; 463 size_t len; 464 465 if (!wa_bb[ec].len) 466 continue; 467 468 len = snprintf(p, sz, "%s:", engine_info[i].cls); 469 if (!wa_bb_read_advance(data, &p, NULL, len, &sz)) 470 return -ENOBUFS; 471 472 for (size_t j = 0; j < wa_bb[ec].len; j++) { 473 len = snprintf(p, sz, " %08x", wa_bb[ec].cs[j]); 474 if (!wa_bb_read_advance(data, &p, NULL, len, &sz)) 475 return -ENOBUFS; 476 } 477 478 if (!wa_bb_read_advance(data, &p, "\n", 1, &sz)) 479 return -ENOBUFS; 480 } 481 482 if (!wa_bb_read_advance(data, &p, "", 1, &sz)) 483 return -ENOBUFS; 484 485 /* Reserve one more to match check for '\0' */ 486 if (!data) 487 p++; 488 489 return p - data; 490 } 491 492 static ssize_t ctx_restore_mid_bb_show(struct config_item *item, char *page) 493 { 494 struct xe_config_group_device *dev = to_xe_config_group_device(item); 495 496 return wa_bb_show(dev, dev->config.ctx_restore_mid_bb, page, SZ_4K); 497 } 498 499 static ssize_t ctx_restore_post_bb_show(struct config_item *item, char *page) 500 { 501 struct xe_config_group_device *dev = to_xe_config_group_device(item); 502 503 return wa_bb_show(dev, dev->config.ctx_restore_post_bb, page, SZ_4K); 504 } 505 506 static void wa_bb_append(struct wa_bb *wa_bb, u32 val) 507 { 508 if (wa_bb->cs) 509 wa_bb->cs[wa_bb->len] = val; 510 511 wa_bb->len++; 512 } 513 514 static ssize_t parse_hex(const char *line, u32 *pval) 515 { 516 char numstr[12]; 517 const char *p; 518 ssize_t numlen; 519 520 p = line + strspn(line, " \t"); 521 if (!*p || *p == '\n') 522 return 0; 523 524 numlen = strcspn(p, " \t\n"); 525 if (!numlen || numlen >= sizeof(numstr) - 1) 526 return -EINVAL; 527 528 memcpy(numstr, p, numlen); 529 numstr[numlen] = '\0'; 530 p += numlen; 531 532 if (kstrtou32(numstr, 16, pval)) 533 return -EINVAL; 534 535 return p - line; 536 } 537 538 /* 539 * Parse lines with the format 540 * 541 * <engine-class> cmd <u32> <u32...> 542 * <engine-class> reg <u32_addr> <u32_val> 543 * 544 * and optionally save them in @wa_bb[i].cs is non-NULL. 545 * 546 * Return the number of dwords parsed. 547 */ 548 static ssize_t parse_wa_bb_lines(const char *lines, 549 struct wa_bb wa_bb[static XE_ENGINE_CLASS_MAX]) 550 { 551 ssize_t dwords = 0, ret; 552 const char *p; 553 554 for (p = lines; *p; p++) { 555 const struct engine_info *info = NULL; 556 u32 val, val2; 557 558 /* Also allow empty lines */ 559 p += strspn(p, " \t\n"); 560 if (!*p) 561 break; 562 563 ret = parse_engine(p, " \t\n", NULL, &info); 564 if (ret < 0) 565 return ret; 566 567 p += ret; 568 p += strspn(p, " \t"); 569 570 if (str_has_prefix(p, "cmd")) { 571 for (p += strlen("cmd"); *p;) { 572 ret = parse_hex(p, &val); 573 if (ret < 0) 574 return -EINVAL; 575 if (!ret) 576 break; 577 578 p += ret; 579 dwords++; 580 wa_bb_append(&wa_bb[info->engine_class], val); 581 } 582 } else if (str_has_prefix(p, "reg")) { 583 p += strlen("reg"); 584 ret = parse_hex(p, &val); 585 if (ret <= 0) 586 return -EINVAL; 587 588 p += ret; 589 ret = parse_hex(p, &val2); 590 if (ret <= 0) 591 return -EINVAL; 592 593 p += ret; 594 dwords += 3; 595 wa_bb_append(&wa_bb[info->engine_class], 596 MI_LOAD_REGISTER_IMM | MI_LRI_NUM_REGS(1)); 597 wa_bb_append(&wa_bb[info->engine_class], val); 598 wa_bb_append(&wa_bb[info->engine_class], val2); 599 } else { 600 return -EINVAL; 601 } 602 } 603 604 return dwords; 605 } 606 607 static ssize_t wa_bb_store(struct wa_bb wa_bb[static XE_ENGINE_CLASS_MAX], 608 struct xe_config_group_device *dev, 609 const char *page, size_t len) 610 { 611 /* tmp_wa_bb must match wa_bb's size */ 612 struct wa_bb tmp_wa_bb[XE_ENGINE_CLASS_MAX] = { }; 613 ssize_t count, class; 614 u32 *tmp; 615 616 /* 1. Count dwords - wa_bb[i].cs is NULL for all classes */ 617 count = parse_wa_bb_lines(page, tmp_wa_bb); 618 if (count < 0) 619 return count; 620 621 guard(mutex)(&dev->lock); 622 623 if (is_bound(dev)) 624 return -EBUSY; 625 626 /* 627 * 2. Allocate a u32 array and set the pointers to the right positions 628 * according to the length of each class' wa_bb 629 */ 630 tmp = krealloc(wa_bb[0].cs, count * sizeof(u32), GFP_KERNEL); 631 if (!tmp) 632 return -ENOMEM; 633 634 if (!count) { 635 memset(wa_bb, 0, sizeof(tmp_wa_bb)); 636 return len; 637 } 638 639 for (class = 0, count = 0; class < XE_ENGINE_CLASS_MAX; ++class) { 640 tmp_wa_bb[class].cs = tmp + count; 641 count += tmp_wa_bb[class].len; 642 tmp_wa_bb[class].len = 0; 643 } 644 645 /* 3. Parse wa_bb lines again, this time saving the values */ 646 count = parse_wa_bb_lines(page, tmp_wa_bb); 647 if (count < 0) 648 return count; 649 650 memcpy(wa_bb, tmp_wa_bb, sizeof(tmp_wa_bb)); 651 652 return len; 653 } 654 655 static ssize_t ctx_restore_mid_bb_store(struct config_item *item, 656 const char *data, size_t sz) 657 { 658 struct xe_config_group_device *dev = to_xe_config_group_device(item); 659 660 return wa_bb_store(dev->config.ctx_restore_mid_bb, dev, data, sz); 661 } 662 663 static ssize_t ctx_restore_post_bb_store(struct config_item *item, 664 const char *data, size_t sz) 665 { 666 struct xe_config_group_device *dev = to_xe_config_group_device(item); 667 668 return wa_bb_store(dev->config.ctx_restore_post_bb, dev, data, sz); 669 } 670 671 CONFIGFS_ATTR(, ctx_restore_mid_bb); 672 CONFIGFS_ATTR(, ctx_restore_post_bb); 673 CONFIGFS_ATTR(, enable_psmi); 674 CONFIGFS_ATTR(, engines_allowed); 675 CONFIGFS_ATTR(, survivability_mode); 676 677 static struct configfs_attribute *xe_config_device_attrs[] = { 678 &attr_ctx_restore_mid_bb, 679 &attr_ctx_restore_post_bb, 680 &attr_enable_psmi, 681 &attr_engines_allowed, 682 &attr_survivability_mode, 683 NULL, 684 }; 685 686 static void xe_config_device_release(struct config_item *item) 687 { 688 struct xe_config_group_device *dev = to_xe_config_group_device(item); 689 690 mutex_destroy(&dev->lock); 691 692 kfree(dev->config.ctx_restore_post_bb[0].cs); 693 kfree(dev); 694 } 695 696 static struct configfs_item_operations xe_config_device_ops = { 697 .release = xe_config_device_release, 698 }; 699 700 static bool xe_config_device_is_visible(struct config_item *item, 701 struct configfs_attribute *attr, int n) 702 { 703 struct xe_config_group_device *dev = to_xe_config_group_device(item); 704 705 if (attr == &attr_survivability_mode) { 706 if (!dev->desc->is_dgfx || dev->desc->platform < XE_BATTLEMAGE) 707 return false; 708 } 709 710 return true; 711 } 712 713 static struct configfs_group_operations xe_config_device_group_ops = { 714 .is_visible = xe_config_device_is_visible, 715 }; 716 717 static const struct config_item_type xe_config_device_type = { 718 .ct_item_ops = &xe_config_device_ops, 719 .ct_group_ops = &xe_config_device_group_ops, 720 .ct_attrs = xe_config_device_attrs, 721 .ct_owner = THIS_MODULE, 722 }; 723 724 static const struct xe_device_desc *xe_match_desc(struct pci_dev *pdev) 725 { 726 struct device_driver *driver = driver_find("xe", &pci_bus_type); 727 struct pci_driver *drv = to_pci_driver(driver); 728 const struct pci_device_id *ids = drv ? drv->id_table : NULL; 729 const struct pci_device_id *found = pci_match_id(ids, pdev); 730 731 return found ? (const void *)found->driver_data : NULL; 732 } 733 734 static struct pci_dev *get_physfn_instead(struct pci_dev *virtfn) 735 { 736 struct pci_dev *physfn = pci_physfn(virtfn); 737 738 pci_dev_get(physfn); 739 pci_dev_put(virtfn); 740 return physfn; 741 } 742 743 static struct config_group *xe_config_make_device_group(struct config_group *group, 744 const char *name) 745 { 746 unsigned int domain, bus, slot, function; 747 struct xe_config_group_device *dev; 748 const struct xe_device_desc *match; 749 struct pci_dev *pdev; 750 char canonical[16]; 751 int vfnumber = 0; 752 int ret; 753 754 ret = sscanf(name, "%x:%x:%x.%x", &domain, &bus, &slot, &function); 755 if (ret != 4) 756 return ERR_PTR(-EINVAL); 757 758 ret = scnprintf(canonical, sizeof(canonical), "%04x:%02x:%02x.%d", domain, bus, 759 PCI_SLOT(PCI_DEVFN(slot, function)), 760 PCI_FUNC(PCI_DEVFN(slot, function))); 761 if (ret != 12 || strcmp(name, canonical)) 762 return ERR_PTR(-EINVAL); 763 764 pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(slot, function)); 765 if (!pdev && function) 766 pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(slot, 0)); 767 if (!pdev && slot) 768 pdev = pci_get_domain_bus_and_slot(domain, bus, PCI_DEVFN(0, 0)); 769 if (!pdev) 770 return ERR_PTR(-ENODEV); 771 772 if (PCI_DEVFN(slot, function) != pdev->devfn) { 773 pdev = get_physfn_instead(pdev); 774 vfnumber = PCI_DEVFN(slot, function) - pdev->devfn; 775 if (!dev_is_pf(&pdev->dev) || vfnumber > pci_sriov_get_totalvfs(pdev)) { 776 pci_dev_put(pdev); 777 return ERR_PTR(-ENODEV); 778 } 779 } 780 781 match = xe_match_desc(pdev); 782 if (match && vfnumber && !match->has_sriov) { 783 pci_info(pdev, "xe driver does not support VFs on this device\n"); 784 match = NULL; 785 } else if (!match) { 786 pci_info(pdev, "xe driver does not support configuration of this device\n"); 787 } 788 789 pci_dev_put(pdev); 790 791 if (!match) 792 return ERR_PTR(-ENOENT); 793 794 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 795 if (!dev) 796 return ERR_PTR(-ENOMEM); 797 798 dev->desc = match; 799 set_device_defaults(&dev->config); 800 801 config_group_init_type_name(&dev->group, name, &xe_config_device_type); 802 803 mutex_init(&dev->lock); 804 805 return &dev->group; 806 } 807 808 static struct configfs_group_operations xe_config_group_ops = { 809 .make_group = xe_config_make_device_group, 810 }; 811 812 static const struct config_item_type xe_configfs_type = { 813 .ct_group_ops = &xe_config_group_ops, 814 .ct_owner = THIS_MODULE, 815 }; 816 817 static struct configfs_subsystem xe_configfs = { 818 .su_group = { 819 .cg_item = { 820 .ci_namebuf = "xe", 821 .ci_type = &xe_configfs_type, 822 }, 823 }, 824 }; 825 826 static struct xe_config_group_device *find_xe_config_group_device(struct pci_dev *pdev) 827 { 828 struct config_item *item; 829 830 mutex_lock(&xe_configfs.su_mutex); 831 item = config_group_find_item(&xe_configfs.su_group, pci_name(pdev)); 832 mutex_unlock(&xe_configfs.su_mutex); 833 834 if (!item) 835 return NULL; 836 837 return to_xe_config_group_device(item); 838 } 839 840 static void dump_custom_dev_config(struct pci_dev *pdev, 841 struct xe_config_group_device *dev) 842 { 843 #define PRI_CUSTOM_ATTR(fmt_, attr_) do { \ 844 if (dev->config.attr_ != device_defaults.attr_) \ 845 pci_info(pdev, "configfs: " __stringify(attr_) " = " fmt_ "\n", \ 846 dev->config.attr_); \ 847 } while (0) 848 849 PRI_CUSTOM_ATTR("%llx", engines_allowed); 850 PRI_CUSTOM_ATTR("%d", enable_psmi); 851 PRI_CUSTOM_ATTR("%d", survivability_mode); 852 853 #undef PRI_CUSTOM_ATTR 854 } 855 856 /** 857 * xe_configfs_check_device() - Test if device was configured by configfs 858 * @pdev: the &pci_dev device to test 859 * 860 * Try to find the configfs group that belongs to the specified pci device 861 * and print a diagnostic message if different than the default value. 862 */ 863 void xe_configfs_check_device(struct pci_dev *pdev) 864 { 865 struct xe_config_group_device *dev = find_xe_config_group_device(pdev); 866 867 if (!dev) 868 return; 869 870 /* memcmp here is safe as both are zero-initialized */ 871 if (memcmp(&dev->config, &device_defaults, sizeof(dev->config))) { 872 pci_info(pdev, "Found custom settings in configfs\n"); 873 dump_custom_dev_config(pdev, dev); 874 } 875 876 config_group_put(&dev->group); 877 } 878 879 /** 880 * xe_configfs_get_survivability_mode - get configfs survivability mode attribute 881 * @pdev: pci device 882 * 883 * Return: survivability_mode attribute in configfs 884 */ 885 bool xe_configfs_get_survivability_mode(struct pci_dev *pdev) 886 { 887 struct xe_config_group_device *dev = find_xe_config_group_device(pdev); 888 bool mode; 889 890 if (!dev) 891 return device_defaults.survivability_mode; 892 893 mode = dev->config.survivability_mode; 894 config_group_put(&dev->group); 895 896 return mode; 897 } 898 899 /** 900 * xe_configfs_get_engines_allowed - get engine allowed mask from configfs 901 * @pdev: pci device 902 * 903 * Return: engine mask with allowed engines set in configfs 904 */ 905 u64 xe_configfs_get_engines_allowed(struct pci_dev *pdev) 906 { 907 struct xe_config_group_device *dev = find_xe_config_group_device(pdev); 908 u64 engines_allowed; 909 910 if (!dev) 911 return device_defaults.engines_allowed; 912 913 engines_allowed = dev->config.engines_allowed; 914 config_group_put(&dev->group); 915 916 return engines_allowed; 917 } 918 919 /** 920 * xe_configfs_get_psmi_enabled - get configfs enable_psmi setting 921 * @pdev: pci device 922 * 923 * Return: enable_psmi setting in configfs 924 */ 925 bool xe_configfs_get_psmi_enabled(struct pci_dev *pdev) 926 { 927 struct xe_config_group_device *dev = find_xe_config_group_device(pdev); 928 bool ret; 929 930 if (!dev) 931 return false; 932 933 ret = dev->config.enable_psmi; 934 config_group_put(&dev->group); 935 936 return ret; 937 } 938 939 /** 940 * xe_configfs_get_ctx_restore_mid_bb - get configfs ctx_restore_mid_bb setting 941 * @pdev: pci device 942 * @class: hw engine class 943 * @cs: pointer to the bb to use - only valid during probe 944 * 945 * Return: Number of dwords used in the mid_ctx_restore setting in configfs 946 */ 947 u32 xe_configfs_get_ctx_restore_mid_bb(struct pci_dev *pdev, 948 enum xe_engine_class class, 949 const u32 **cs) 950 { 951 struct xe_config_group_device *dev = find_xe_config_group_device(pdev); 952 u32 len; 953 954 if (!dev) 955 return 0; 956 957 if (cs) 958 *cs = dev->config.ctx_restore_mid_bb[class].cs; 959 960 len = dev->config.ctx_restore_mid_bb[class].len; 961 config_group_put(&dev->group); 962 963 return len; 964 } 965 966 /** 967 * xe_configfs_get_ctx_restore_post_bb - get configfs ctx_restore_post_bb setting 968 * @pdev: pci device 969 * @class: hw engine class 970 * @cs: pointer to the bb to use - only valid during probe 971 * 972 * Return: Number of dwords used in the post_ctx_restore setting in configfs 973 */ 974 u32 xe_configfs_get_ctx_restore_post_bb(struct pci_dev *pdev, 975 enum xe_engine_class class, 976 const u32 **cs) 977 { 978 struct xe_config_group_device *dev = find_xe_config_group_device(pdev); 979 u32 len; 980 981 if (!dev) 982 return 0; 983 984 *cs = dev->config.ctx_restore_post_bb[class].cs; 985 len = dev->config.ctx_restore_post_bb[class].len; 986 config_group_put(&dev->group); 987 988 return len; 989 } 990 991 int __init xe_configfs_init(void) 992 { 993 int ret; 994 995 config_group_init(&xe_configfs.su_group); 996 mutex_init(&xe_configfs.su_mutex); 997 ret = configfs_register_subsystem(&xe_configfs); 998 if (ret) { 999 mutex_destroy(&xe_configfs.su_mutex); 1000 return ret; 1001 } 1002 1003 return 0; 1004 } 1005 1006 void xe_configfs_exit(void) 1007 { 1008 configfs_unregister_subsystem(&xe_configfs); 1009 mutex_destroy(&xe_configfs.su_mutex); 1010 } 1011