1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2025 Intel Corporation 4 */ 5 6 #include <linux/kobject.h> 7 #include <linux/sysfs.h> 8 9 #include <drm/drm_managed.h> 10 11 #include "xe_assert.h" 12 #include "xe_pci_sriov.h" 13 #include "xe_pm.h" 14 #include "xe_sriov.h" 15 #include "xe_sriov_pf.h" 16 #include "xe_sriov_pf_control.h" 17 #include "xe_sriov_pf_helpers.h" 18 #include "xe_sriov_pf_provision.h" 19 #include "xe_sriov_pf_sysfs.h" 20 #include "xe_sriov_printk.h" 21 22 static int emit_choice(char *buf, int choice, const char * const *array, size_t size) 23 { 24 int pos = 0; 25 int n; 26 27 for (n = 0; n < size; n++) { 28 pos += sysfs_emit_at(buf, pos, "%s%s%s%s", 29 n ? " " : "", 30 n == choice ? "[" : "", 31 array[n], 32 n == choice ? "]" : ""); 33 } 34 pos += sysfs_emit_at(buf, pos, "\n"); 35 36 return pos; 37 } 38 39 /* 40 * /sys/bus/pci/drivers/xe/BDF/ 41 * : 42 * ├── sriov_admin/ 43 * ├── ... 44 * ├── .bulk_profile 45 * │ ├── exec_quantum_ms 46 * │ ├── preempt_timeout_us 47 * │ └── sched_priority 48 * ├── pf/ 49 * │ ├── ... 50 * │ ├── device -> ../../../BDF 51 * │ └── profile 52 * │ ├── exec_quantum_ms 53 * │ ├── preempt_timeout_us 54 * │ └── sched_priority 55 * ├── vf1/ 56 * │ ├── ... 57 * │ ├── device -> ../../../BDF.1 58 * │ ├── stop 59 * │ └── profile 60 * │ ├── exec_quantum_ms 61 * │ ├── preempt_timeout_us 62 * │ └── sched_priority 63 * ├── vf2/ 64 * : 65 * └── vfN/ 66 */ 67 68 struct xe_sriov_kobj { 69 struct kobject base; 70 struct xe_device *xe; 71 unsigned int vfid; 72 }; 73 #define to_xe_sriov_kobj(p) container_of_const((p), struct xe_sriov_kobj, base) 74 75 struct xe_sriov_dev_attr { 76 struct attribute attr; 77 ssize_t (*show)(struct xe_device *xe, char *buf); 78 ssize_t (*store)(struct xe_device *xe, const char *buf, size_t count); 79 }; 80 #define to_xe_sriov_dev_attr(p) container_of_const((p), struct xe_sriov_dev_attr, attr) 81 82 #define XE_SRIOV_DEV_ATTR(NAME) \ 83 struct xe_sriov_dev_attr xe_sriov_dev_attr_##NAME = \ 84 __ATTR(NAME, 0644, xe_sriov_dev_attr_##NAME##_show, xe_sriov_dev_attr_##NAME##_store) 85 86 #define XE_SRIOV_DEV_ATTR_RO(NAME) \ 87 struct xe_sriov_dev_attr xe_sriov_dev_attr_##NAME = \ 88 __ATTR(NAME, 0444, xe_sriov_dev_attr_##NAME##_show, NULL) 89 90 #define XE_SRIOV_DEV_ATTR_WO(NAME) \ 91 struct xe_sriov_dev_attr xe_sriov_dev_attr_##NAME = \ 92 __ATTR(NAME, 0200, NULL, xe_sriov_dev_attr_##NAME##_store) 93 94 struct xe_sriov_vf_attr { 95 struct attribute attr; 96 ssize_t (*show)(struct xe_device *xe, unsigned int vfid, char *buf); 97 ssize_t (*store)(struct xe_device *xe, unsigned int vfid, const char *buf, size_t count); 98 }; 99 #define to_xe_sriov_vf_attr(p) container_of_const((p), struct xe_sriov_vf_attr, attr) 100 101 #define XE_SRIOV_VF_ATTR(NAME) \ 102 struct xe_sriov_vf_attr xe_sriov_vf_attr_##NAME = \ 103 __ATTR(NAME, 0644, xe_sriov_vf_attr_##NAME##_show, xe_sriov_vf_attr_##NAME##_store) 104 105 #define XE_SRIOV_VF_ATTR_RO(NAME) \ 106 struct xe_sriov_vf_attr xe_sriov_vf_attr_##NAME = \ 107 __ATTR(NAME, 0444, xe_sriov_vf_attr_##NAME##_show, NULL) 108 109 #define XE_SRIOV_VF_ATTR_WO(NAME) \ 110 struct xe_sriov_vf_attr xe_sriov_vf_attr_##NAME = \ 111 __ATTR(NAME, 0200, NULL, xe_sriov_vf_attr_##NAME##_store) 112 113 /* device level attributes go here */ 114 115 #define DEFINE_SIMPLE_BULK_PROVISIONING_SRIOV_DEV_ATTR_WO(NAME, ITEM, TYPE) \ 116 \ 117 static ssize_t xe_sriov_dev_attr_##NAME##_store(struct xe_device *xe, \ 118 const char *buf, size_t count) \ 119 { \ 120 TYPE value; \ 121 int err; \ 122 \ 123 err = kstrto##TYPE(buf, 0, &value); \ 124 if (err) \ 125 return err; \ 126 \ 127 err = xe_sriov_pf_provision_bulk_apply_##ITEM(xe, value); \ 128 return err ?: count; \ 129 } \ 130 \ 131 static XE_SRIOV_DEV_ATTR_WO(NAME) 132 133 DEFINE_SIMPLE_BULK_PROVISIONING_SRIOV_DEV_ATTR_WO(exec_quantum_ms, eq, u32); 134 DEFINE_SIMPLE_BULK_PROVISIONING_SRIOV_DEV_ATTR_WO(preempt_timeout_us, pt, u32); 135 136 static const char * const sched_priority_names[] = { 137 [GUC_SCHED_PRIORITY_LOW] = "low", 138 [GUC_SCHED_PRIORITY_NORMAL] = "normal", 139 [GUC_SCHED_PRIORITY_HIGH] = "high", 140 }; 141 142 static bool sched_priority_change_allowed(unsigned int vfid) 143 { 144 /* As of today GuC FW allows to selectively change only the PF priority. */ 145 return vfid == PFID; 146 } 147 148 static bool sched_priority_high_allowed(unsigned int vfid) 149 { 150 /* As of today GuC FW allows to select 'high' priority only for the PF. */ 151 return vfid == PFID; 152 } 153 154 static bool sched_priority_bulk_high_allowed(struct xe_device *xe) 155 { 156 /* all VFs are equal - it's sufficient to check VF1 only */ 157 return sched_priority_high_allowed(VFID(1)); 158 } 159 160 static ssize_t xe_sriov_dev_attr_sched_priority_store(struct xe_device *xe, 161 const char *buf, size_t count) 162 { 163 size_t num_priorities = ARRAY_SIZE(sched_priority_names); 164 int match; 165 int err; 166 167 if (!sched_priority_bulk_high_allowed(xe)) 168 num_priorities--; 169 170 match = __sysfs_match_string(sched_priority_names, num_priorities, buf); 171 if (match < 0) 172 return -EINVAL; 173 174 err = xe_sriov_pf_provision_bulk_apply_priority(xe, match); 175 return err ?: count; 176 } 177 178 static XE_SRIOV_DEV_ATTR_WO(sched_priority); 179 180 static struct attribute *bulk_profile_dev_attrs[] = { 181 &xe_sriov_dev_attr_exec_quantum_ms.attr, 182 &xe_sriov_dev_attr_preempt_timeout_us.attr, 183 &xe_sriov_dev_attr_sched_priority.attr, 184 NULL 185 }; 186 187 static const struct attribute_group bulk_profile_dev_attr_group = { 188 .name = ".bulk_profile", 189 .attrs = bulk_profile_dev_attrs, 190 }; 191 192 static const struct attribute_group *xe_sriov_dev_attr_groups[] = { 193 &bulk_profile_dev_attr_group, 194 NULL 195 }; 196 197 /* and VF-level attributes go here */ 198 199 #define DEFINE_SIMPLE_PROVISIONING_SRIOV_VF_ATTR(NAME, ITEM, TYPE, FORMAT) \ 200 static ssize_t xe_sriov_vf_attr_##NAME##_show(struct xe_device *xe, unsigned int vfid, \ 201 char *buf) \ 202 { \ 203 TYPE value = 0; \ 204 int err; \ 205 \ 206 err = xe_sriov_pf_provision_query_vf_##ITEM(xe, vfid, &value); \ 207 if (err) \ 208 return err; \ 209 \ 210 return sysfs_emit(buf, FORMAT, value); \ 211 } \ 212 \ 213 static ssize_t xe_sriov_vf_attr_##NAME##_store(struct xe_device *xe, unsigned int vfid, \ 214 const char *buf, size_t count) \ 215 { \ 216 TYPE value; \ 217 int err; \ 218 \ 219 err = kstrto##TYPE(buf, 0, &value); \ 220 if (err) \ 221 return err; \ 222 \ 223 err = xe_sriov_pf_provision_apply_vf_##ITEM(xe, vfid, value); \ 224 return err ?: count; \ 225 } \ 226 \ 227 static XE_SRIOV_VF_ATTR(NAME) 228 229 DEFINE_SIMPLE_PROVISIONING_SRIOV_VF_ATTR(exec_quantum_ms, eq, u32, "%u\n"); 230 DEFINE_SIMPLE_PROVISIONING_SRIOV_VF_ATTR(preempt_timeout_us, pt, u32, "%u\n"); 231 232 static ssize_t xe_sriov_vf_attr_sched_priority_show(struct xe_device *xe, unsigned int vfid, 233 char *buf) 234 { 235 size_t num_priorities = ARRAY_SIZE(sched_priority_names); 236 u32 priority; 237 int err; 238 239 err = xe_sriov_pf_provision_query_vf_priority(xe, vfid, &priority); 240 if (err) 241 return err; 242 243 if (!sched_priority_high_allowed(vfid)) 244 num_priorities--; 245 246 xe_assert(xe, priority < num_priorities); 247 return emit_choice(buf, priority, sched_priority_names, num_priorities); 248 } 249 250 static ssize_t xe_sriov_vf_attr_sched_priority_store(struct xe_device *xe, unsigned int vfid, 251 const char *buf, size_t count) 252 { 253 size_t num_priorities = ARRAY_SIZE(sched_priority_names); 254 int match; 255 int err; 256 257 if (!sched_priority_change_allowed(vfid)) 258 return -EOPNOTSUPP; 259 260 if (!sched_priority_high_allowed(vfid)) 261 num_priorities--; 262 263 match = __sysfs_match_string(sched_priority_names, num_priorities, buf); 264 if (match < 0) 265 return -EINVAL; 266 267 err = xe_sriov_pf_provision_apply_vf_priority(xe, vfid, match); 268 return err ?: count; 269 } 270 271 static XE_SRIOV_VF_ATTR(sched_priority); 272 273 static struct attribute *profile_vf_attrs[] = { 274 &xe_sriov_vf_attr_exec_quantum_ms.attr, 275 &xe_sriov_vf_attr_preempt_timeout_us.attr, 276 &xe_sriov_vf_attr_sched_priority.attr, 277 NULL 278 }; 279 280 static umode_t profile_vf_attr_is_visible(struct kobject *kobj, 281 struct attribute *attr, int index) 282 { 283 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 284 285 if (attr == &xe_sriov_vf_attr_sched_priority.attr && 286 !sched_priority_change_allowed(vkobj->vfid)) 287 return attr->mode & 0444; 288 289 return attr->mode; 290 } 291 292 static const struct attribute_group profile_vf_attr_group = { 293 .name = "profile", 294 .attrs = profile_vf_attrs, 295 .is_visible = profile_vf_attr_is_visible, 296 }; 297 298 #define DEFINE_SIMPLE_CONTROL_SRIOV_VF_ATTR(NAME) \ 299 \ 300 static ssize_t xe_sriov_vf_attr_##NAME##_store(struct xe_device *xe, unsigned int vfid, \ 301 const char *buf, size_t count) \ 302 { \ 303 bool yes; \ 304 int err; \ 305 \ 306 if (!vfid) \ 307 return -EPERM; \ 308 \ 309 err = kstrtobool(buf, &yes); \ 310 if (err) \ 311 return err; \ 312 if (!yes) \ 313 return count; \ 314 \ 315 err = xe_sriov_pf_control_##NAME##_vf(xe, vfid); \ 316 return err ?: count; \ 317 } \ 318 \ 319 static XE_SRIOV_VF_ATTR_WO(NAME) 320 321 DEFINE_SIMPLE_CONTROL_SRIOV_VF_ATTR(stop); 322 323 static struct attribute *control_vf_attrs[] = { 324 &xe_sriov_vf_attr_stop.attr, 325 NULL 326 }; 327 328 static umode_t control_vf_attr_is_visible(struct kobject *kobj, 329 struct attribute *attr, int index) 330 { 331 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 332 333 if (vkobj->vfid == PFID) 334 return 0; 335 336 return attr->mode; 337 } 338 339 static const struct attribute_group control_vf_attr_group = { 340 .attrs = control_vf_attrs, 341 .is_visible = control_vf_attr_is_visible, 342 }; 343 344 static const struct attribute_group *xe_sriov_vf_attr_groups[] = { 345 &profile_vf_attr_group, 346 &control_vf_attr_group, 347 NULL 348 }; 349 350 /* no user serviceable parts below */ 351 352 static void action_put_kobject(void *arg) 353 { 354 struct kobject *kobj = arg; 355 356 kobject_put(kobj); 357 } 358 359 static struct kobject *create_xe_sriov_kobj(struct xe_device *xe, unsigned int vfid, 360 const struct kobj_type *ktype) 361 { 362 struct xe_sriov_kobj *vkobj; 363 int err; 364 365 xe_sriov_pf_assert_vfid(xe, vfid); 366 367 vkobj = kzalloc_obj(*vkobj); 368 if (!vkobj) 369 return ERR_PTR(-ENOMEM); 370 371 vkobj->xe = xe; 372 vkobj->vfid = vfid; 373 kobject_init(&vkobj->base, ktype); 374 375 err = devm_add_action_or_reset(xe->drm.dev, action_put_kobject, &vkobj->base); 376 if (err) 377 return ERR_PTR(err); 378 379 return &vkobj->base; 380 } 381 382 static void release_xe_sriov_kobj(struct kobject *kobj) 383 { 384 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 385 386 kfree(vkobj); 387 } 388 389 static ssize_t xe_sriov_dev_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) 390 { 391 struct xe_sriov_dev_attr *vattr = to_xe_sriov_dev_attr(attr); 392 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 393 struct xe_device *xe = vkobj->xe; 394 395 if (!vattr->show) 396 return -EPERM; 397 398 return vattr->show(xe, buf); 399 } 400 401 static ssize_t xe_sriov_dev_attr_store(struct kobject *kobj, struct attribute *attr, 402 const char *buf, size_t count) 403 { 404 struct xe_sriov_dev_attr *vattr = to_xe_sriov_dev_attr(attr); 405 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 406 struct xe_device *xe = vkobj->xe; 407 408 if (!vattr->store) 409 return -EPERM; 410 411 guard(xe_pm_runtime)(xe); 412 return xe_sriov_pf_wait_ready(xe) ?: vattr->store(xe, buf, count); 413 } 414 415 static ssize_t xe_sriov_vf_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) 416 { 417 struct xe_sriov_vf_attr *vattr = to_xe_sriov_vf_attr(attr); 418 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 419 struct xe_device *xe = vkobj->xe; 420 unsigned int vfid = vkobj->vfid; 421 422 xe_sriov_pf_assert_vfid(xe, vfid); 423 424 if (!vattr->show) 425 return -EPERM; 426 427 return vattr->show(xe, vfid, buf); 428 } 429 430 static ssize_t xe_sriov_vf_attr_store(struct kobject *kobj, struct attribute *attr, 431 const char *buf, size_t count) 432 { 433 struct xe_sriov_vf_attr *vattr = to_xe_sriov_vf_attr(attr); 434 struct xe_sriov_kobj *vkobj = to_xe_sriov_kobj(kobj); 435 struct xe_device *xe = vkobj->xe; 436 unsigned int vfid = vkobj->vfid; 437 438 xe_sriov_pf_assert_vfid(xe, vfid); 439 440 if (!vattr->store) 441 return -EPERM; 442 443 guard(xe_pm_runtime)(xe); 444 return xe_sriov_pf_wait_ready(xe) ?: vattr->store(xe, vfid, buf, count); 445 } 446 447 static const struct sysfs_ops xe_sriov_dev_sysfs_ops = { 448 .show = xe_sriov_dev_attr_show, 449 .store = xe_sriov_dev_attr_store, 450 }; 451 452 static const struct sysfs_ops xe_sriov_vf_sysfs_ops = { 453 .show = xe_sriov_vf_attr_show, 454 .store = xe_sriov_vf_attr_store, 455 }; 456 457 static const struct kobj_type xe_sriov_dev_ktype = { 458 .release = release_xe_sriov_kobj, 459 .sysfs_ops = &xe_sriov_dev_sysfs_ops, 460 .default_groups = xe_sriov_dev_attr_groups, 461 }; 462 463 static const struct kobj_type xe_sriov_vf_ktype = { 464 .release = release_xe_sriov_kobj, 465 .sysfs_ops = &xe_sriov_vf_sysfs_ops, 466 .default_groups = xe_sriov_vf_attr_groups, 467 }; 468 469 static int pf_sysfs_error(struct xe_device *xe, int err, const char *what) 470 { 471 if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) 472 xe_sriov_dbg(xe, "Failed to setup sysfs %s (%pe)\n", what, ERR_PTR(err)); 473 return err; 474 } 475 476 static void pf_sysfs_note(struct xe_device *xe, int err, const char *what) 477 { 478 xe_sriov_dbg(xe, "Failed to setup sysfs %s (%pe)\n", what, ERR_PTR(err)); 479 } 480 481 static int pf_setup_root(struct xe_device *xe) 482 { 483 struct kobject *parent = &xe->drm.dev->kobj; 484 struct kobject *root; 485 int err; 486 487 root = create_xe_sriov_kobj(xe, PFID, &xe_sriov_dev_ktype); 488 if (IS_ERR(root)) 489 return pf_sysfs_error(xe, PTR_ERR(root), "root obj"); 490 491 err = kobject_add(root, parent, "sriov_admin"); 492 if (err) 493 return pf_sysfs_error(xe, err, "root init"); 494 495 xe_assert(xe, IS_SRIOV_PF(xe)); 496 xe_assert(xe, !xe->sriov.pf.sysfs.root); 497 xe->sriov.pf.sysfs.root = root; 498 return 0; 499 } 500 501 static int pf_setup_tree(struct xe_device *xe) 502 { 503 unsigned int totalvfs = xe_sriov_pf_get_totalvfs(xe); 504 struct kobject *root, *kobj; 505 unsigned int n; 506 int err; 507 508 xe_assert(xe, IS_SRIOV_PF(xe)); 509 root = xe->sriov.pf.sysfs.root; 510 511 for (n = 0; n <= totalvfs; n++) { 512 kobj = create_xe_sriov_kobj(xe, VFID(n), &xe_sriov_vf_ktype); 513 if (IS_ERR(kobj)) 514 return pf_sysfs_error(xe, PTR_ERR(kobj), "tree obj"); 515 516 if (n) 517 err = kobject_add(kobj, root, "vf%u", n); 518 else 519 err = kobject_add(kobj, root, "pf"); 520 if (err) 521 return pf_sysfs_error(xe, err, "tree init"); 522 523 xe_assert(xe, !xe->sriov.pf.vfs[n].kobj); 524 xe->sriov.pf.vfs[n].kobj = kobj; 525 } 526 527 return 0; 528 } 529 530 static void action_rm_device_link(void *arg) 531 { 532 struct kobject *kobj = arg; 533 534 sysfs_remove_link(kobj, "device"); 535 } 536 537 static int pf_link_pf_device(struct xe_device *xe) 538 { 539 struct kobject *kobj = xe->sriov.pf.vfs[PFID].kobj; 540 int err; 541 542 err = sysfs_create_link(kobj, &xe->drm.dev->kobj, "device"); 543 if (err) 544 return pf_sysfs_error(xe, err, "PF device link"); 545 546 err = devm_add_action_or_reset(xe->drm.dev, action_rm_device_link, kobj); 547 if (err) 548 return pf_sysfs_error(xe, err, "PF unlink action"); 549 550 return 0; 551 } 552 553 /** 554 * xe_sriov_pf_sysfs_init() - Setup PF's SR-IOV sysfs tree. 555 * @xe: the PF &xe_device to setup sysfs 556 * 557 * This function will create additional nodes that will represent PF and VFs 558 * devices, each populated with SR-IOV Xe specific attributes. 559 * 560 * Return: 0 on success or a negative error code on failure. 561 */ 562 int xe_sriov_pf_sysfs_init(struct xe_device *xe) 563 { 564 int err; 565 566 err = pf_setup_root(xe); 567 if (err) 568 return err; 569 570 err = pf_setup_tree(xe); 571 if (err) 572 return err; 573 574 err = pf_link_pf_device(xe); 575 if (err) 576 return err; 577 578 return 0; 579 } 580 581 /** 582 * xe_sriov_pf_sysfs_link_vfs() - Add VF's links in SR-IOV sysfs tree. 583 * @xe: the &xe_device where to update sysfs 584 * @num_vfs: number of enabled VFs to link 585 * 586 * This function is specific for the PF driver. 587 * 588 * This function will add symbolic links between VFs represented in the SR-IOV 589 * sysfs tree maintained by the PF and enabled VF PCI devices. 590 * 591 * The @xe_sriov_pf_sysfs_unlink_vfs() shall be used to remove those links. 592 */ 593 void xe_sriov_pf_sysfs_link_vfs(struct xe_device *xe, unsigned int num_vfs) 594 { 595 unsigned int totalvfs = xe_sriov_pf_get_totalvfs(xe); 596 struct pci_dev *pf_pdev = to_pci_dev(xe->drm.dev); 597 struct pci_dev *vf_pdev = NULL; 598 unsigned int n; 599 int err; 600 601 xe_assert(xe, IS_SRIOV_PF(xe)); 602 xe_assert(xe, num_vfs <= totalvfs); 603 604 for (n = 1; n <= num_vfs; n++) { 605 vf_pdev = xe_pci_sriov_get_vf_pdev(pf_pdev, VFID(n)); 606 if (!vf_pdev) 607 return pf_sysfs_note(xe, -ENOENT, "VF link"); 608 609 err = sysfs_create_link(xe->sriov.pf.vfs[VFID(n)].kobj, 610 &vf_pdev->dev.kobj, "device"); 611 612 /* must balance xe_pci_sriov_get_vf_pdev() */ 613 pci_dev_put(vf_pdev); 614 615 if (err) 616 return pf_sysfs_note(xe, err, "VF link"); 617 } 618 } 619 620 /** 621 * xe_sriov_pf_sysfs_unlink_vfs() - Remove VF's links from SR-IOV sysfs tree. 622 * @xe: the &xe_device where to update sysfs 623 * @num_vfs: number of VFs to unlink 624 * 625 * This function shall be called only on the PF. 626 * This function will remove "device" links added by @xe_sriov_sysfs_link_vfs(). 627 */ 628 void xe_sriov_pf_sysfs_unlink_vfs(struct xe_device *xe, unsigned int num_vfs) 629 { 630 unsigned int n; 631 632 xe_assert(xe, IS_SRIOV_PF(xe)); 633 xe_assert(xe, num_vfs <= xe_sriov_pf_get_totalvfs(xe)); 634 635 for (n = 1; n <= num_vfs; n++) 636 sysfs_remove_link(xe->sriov.pf.vfs[VFID(n)].kobj, "device"); 637 } 638