1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2025 Intel Corporation 4 */ 5 6 #include "xe_assert.h" 7 #include "xe_device.h" 8 #include "xe_gt_sriov_pf_config.h" 9 #include "xe_gt_sriov_pf_policy.h" 10 #include "xe_lmtt.h" 11 #include "xe_sriov.h" 12 #include "xe_sriov_pf_helpers.h" 13 #include "xe_sriov_pf_provision.h" 14 #include "xe_sriov_pf_provision_types.h" 15 #include "xe_sriov_printk.h" 16 17 static const char *mode_to_string(enum xe_sriov_provisioning_mode mode) 18 { 19 switch (mode) { 20 case XE_SRIOV_PROVISIONING_MODE_AUTO: 21 return "auto"; 22 case XE_SRIOV_PROVISIONING_MODE_CUSTOM: 23 return "custom"; 24 default: 25 return "<invalid>"; 26 } 27 } 28 29 static bool pf_auto_provisioning_mode(struct xe_device *xe) 30 { 31 xe_assert(xe, IS_SRIOV_PF(xe)); 32 33 return xe->sriov.pf.provision.mode == XE_SRIOV_PROVISIONING_MODE_AUTO; 34 } 35 36 static int pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs) 37 { 38 struct xe_gt *gt; 39 unsigned int id; 40 int result = 0; 41 int err; 42 43 for_each_gt(gt, xe, id) { 44 err = xe_gt_sriov_pf_config_set_fair_sched(gt, num_vfs); 45 result = result ?: err; 46 err = xe_gt_sriov_pf_config_set_fair(gt, VFID(1), num_vfs); 47 result = result ?: err; 48 } 49 50 return result; 51 } 52 53 static void pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs) 54 { 55 struct xe_gt *gt; 56 unsigned int id; 57 unsigned int n; 58 59 for_each_gt(gt, xe, id) 60 for (n = 1; n <= num_vfs; n++) 61 xe_gt_sriov_pf_config_release(gt, n, true); 62 } 63 64 static void pf_unprovision_all_vfs(struct xe_device *xe) 65 { 66 pf_unprovision_vfs(xe, xe_sriov_pf_get_totalvfs(xe)); 67 } 68 69 /** 70 * xe_sriov_pf_provision_vfs() - Provision VFs in auto-mode. 71 * @xe: the PF &xe_device 72 * @num_vfs: the number of VFs to auto-provision 73 * 74 * This function can only be called on PF. 75 * 76 * Return: 0 on success or a negative error code on failure. 77 */ 78 int xe_sriov_pf_provision_vfs(struct xe_device *xe, unsigned int num_vfs) 79 { 80 xe_assert(xe, IS_SRIOV_PF(xe)); 81 82 if (!pf_auto_provisioning_mode(xe)) 83 return 0; 84 85 return pf_provision_vfs(xe, num_vfs); 86 } 87 88 /** 89 * xe_sriov_pf_unprovision_vfs() - Unprovision VFs in auto-mode. 90 * @xe: the PF &xe_device 91 * @num_vfs: the number of VFs to unprovision 92 * 93 * This function can only be called on PF. 94 * 95 * Return: 0 on success or a negative error code on failure. 96 */ 97 int xe_sriov_pf_unprovision_vfs(struct xe_device *xe, unsigned int num_vfs) 98 { 99 xe_assert(xe, IS_SRIOV_PF(xe)); 100 101 if (!pf_auto_provisioning_mode(xe)) 102 return 0; 103 104 pf_unprovision_vfs(xe, num_vfs); 105 return 0; 106 } 107 108 static int pf_reprovision_default(struct xe_device *xe) 109 { 110 struct xe_gt *gt; 111 unsigned int id; 112 int result = 0; 113 int err; 114 115 guard(mutex)(xe_sriov_pf_master_mutex(xe)); 116 117 for_each_gt(gt, xe, id) { 118 err = xe_gt_sriov_pf_policy_set_sched_if_idle_locked(gt, false); 119 result = result ?: err; 120 err = xe_gt_sriov_pf_config_set_exec_quantum_locked(gt, PFID, 0); 121 result = result ?: err; 122 err = xe_gt_sriov_pf_config_set_preempt_timeout_locked(gt, PFID, 0); 123 result = result ?: err; 124 } 125 126 return result; 127 } 128 129 /** 130 * xe_sriov_pf_reprovision_default() - Reprovision default PF in auto-mode. 131 * @xe: the PF &xe_device 132 * 133 * This function can only be called on PF. 134 * 135 * Return: 0 on success or a negative error code on failure. 136 */ 137 int xe_sriov_pf_reprovision_default(struct xe_device *xe) 138 { 139 xe_assert(xe, IS_SRIOV_PF(xe)); 140 141 if (!pf_auto_provisioning_mode(xe)) 142 return 0; 143 144 return pf_reprovision_default(xe); 145 } 146 147 /** 148 * xe_sriov_pf_provision_set_mode() - Change VFs provision mode. 149 * @xe: the PF &xe_device 150 * @mode: the new VFs provisioning mode 151 * 152 * When changing from AUTO to CUSTOM mode, any already allocated VFs resources 153 * will remain allocated and will not be released upon VFs disabling. 154 * 155 * When changing back to AUTO mode, if VFs are not enabled, already allocated 156 * VFs resources will be immediately released. If VFs are still enabled, such 157 * mode change is rejected. 158 * 159 * This function can only be called on PF. 160 * 161 * Return: 0 on success or a negative error code on failure. 162 */ 163 int xe_sriov_pf_provision_set_mode(struct xe_device *xe, enum xe_sriov_provisioning_mode mode) 164 { 165 xe_assert(xe, IS_SRIOV_PF(xe)); 166 167 if (mode == xe->sriov.pf.provision.mode) 168 return 0; 169 170 if (mode == XE_SRIOV_PROVISIONING_MODE_AUTO) { 171 if (xe_sriov_pf_num_vfs(xe)) { 172 xe_sriov_dbg(xe, "can't restore %s: VFs must be disabled!\n", 173 mode_to_string(mode)); 174 return -EBUSY; 175 } 176 pf_unprovision_all_vfs(xe); 177 } 178 179 xe_sriov_dbg(xe, "mode %s changed to %s by %ps\n", 180 mode_to_string(xe->sriov.pf.provision.mode), 181 mode_to_string(mode), __builtin_return_address(0)); 182 xe->sriov.pf.provision.mode = mode; 183 return 0; 184 } 185 186 /** 187 * xe_sriov_pf_provision_bulk_apply_eq() - Change execution quantum for all VFs and PF. 188 * @xe: the PF &xe_device 189 * @eq: execution quantum in [ms] to set 190 * 191 * Change execution quantum (EQ) provisioning on all tiles/GTs. 192 * 193 * This function can only be called on PF. 194 * 195 * Return: 0 on success or a negative error code on failure. 196 */ 197 int xe_sriov_pf_provision_bulk_apply_eq(struct xe_device *xe, u32 eq) 198 { 199 struct xe_gt *gt; 200 unsigned int id; 201 int result = 0; 202 int err; 203 204 guard(mutex)(xe_sriov_pf_master_mutex(xe)); 205 206 for_each_gt(gt, xe, id) { 207 err = xe_gt_sriov_pf_config_bulk_set_exec_quantum_locked(gt, eq); 208 result = result ?: err; 209 } 210 211 return result; 212 } 213 214 /** 215 * xe_sriov_pf_provision_apply_vf_eq() - Change VF's execution quantum. 216 * @xe: the PF &xe_device 217 * @vfid: the VF identifier 218 * @eq: execution quantum in [ms] to set 219 * 220 * Change VF's execution quantum (EQ) provisioning on all tiles/GTs. 221 * 222 * This function can only be called on PF. 223 * 224 * Return: 0 on success or a negative error code on failure. 225 */ 226 int xe_sriov_pf_provision_apply_vf_eq(struct xe_device *xe, unsigned int vfid, u32 eq) 227 { 228 struct xe_gt *gt; 229 unsigned int id; 230 int result = 0; 231 int err; 232 233 guard(mutex)(xe_sriov_pf_master_mutex(xe)); 234 235 for_each_gt(gt, xe, id) { 236 err = xe_gt_sriov_pf_config_set_exec_quantum_locked(gt, vfid, eq); 237 result = result ?: err; 238 } 239 240 return result; 241 } 242 243 static int pf_report_unclean(struct xe_gt *gt, unsigned int vfid, 244 const char *what, u32 found, u32 expected) 245 { 246 char name[8]; 247 248 xe_sriov_dbg(gt_to_xe(gt), "%s on GT%u has %s=%u (expected %u)\n", 249 xe_sriov_function_name(vfid, name, sizeof(name)), 250 gt->info.id, what, found, expected); 251 return -EUCLEAN; 252 } 253 254 /** 255 * xe_sriov_pf_provision_query_vf_eq() - Query VF's execution quantum. 256 * @xe: the PF &xe_device 257 * @vfid: the VF identifier 258 * @eq: placeholder for the returned execution quantum in [ms] 259 * 260 * Query VF's execution quantum (EQ) provisioning from all tiles/GTs. 261 * If values across tiles/GTs are inconsistent then -EUCLEAN error will be returned. 262 * 263 * This function can only be called on PF. 264 * 265 * Return: 0 on success or a negative error code on failure. 266 */ 267 int xe_sriov_pf_provision_query_vf_eq(struct xe_device *xe, unsigned int vfid, u32 *eq) 268 { 269 struct xe_gt *gt; 270 unsigned int id; 271 int count = 0; 272 u32 value; 273 274 guard(mutex)(xe_sriov_pf_master_mutex(xe)); 275 276 for_each_gt(gt, xe, id) { 277 value = xe_gt_sriov_pf_config_get_exec_quantum_locked(gt, vfid); 278 if (!count++) 279 *eq = value; 280 else if (value != *eq) 281 return pf_report_unclean(gt, vfid, "EQ", value, *eq); 282 } 283 284 return !count ? -ENODATA : 0; 285 } 286 287 /** 288 * xe_sriov_pf_provision_bulk_apply_pt() - Change preemption timeout for all VFs and PF. 289 * @xe: the PF &xe_device 290 * @pt: preemption timeout in [us] to set 291 * 292 * Change preemption timeout (PT) provisioning on all tiles/GTs. 293 * 294 * This function can only be called on PF. 295 * 296 * Return: 0 on success or a negative error code on failure. 297 */ 298 int xe_sriov_pf_provision_bulk_apply_pt(struct xe_device *xe, u32 pt) 299 { 300 struct xe_gt *gt; 301 unsigned int id; 302 int result = 0; 303 int err; 304 305 guard(mutex)(xe_sriov_pf_master_mutex(xe)); 306 307 for_each_gt(gt, xe, id) { 308 err = xe_gt_sriov_pf_config_bulk_set_preempt_timeout_locked(gt, pt); 309 result = result ?: err; 310 } 311 312 return result; 313 } 314 315 /** 316 * xe_sriov_pf_provision_apply_vf_pt() - Change VF's preemption timeout. 317 * @xe: the PF &xe_device 318 * @vfid: the VF identifier 319 * @pt: preemption timeout in [us] to set 320 * 321 * Change VF's preemption timeout (PT) provisioning on all tiles/GTs. 322 * 323 * This function can only be called on PF. 324 * 325 * Return: 0 on success or a negative error code on failure. 326 */ 327 int xe_sriov_pf_provision_apply_vf_pt(struct xe_device *xe, unsigned int vfid, u32 pt) 328 { 329 struct xe_gt *gt; 330 unsigned int id; 331 int result = 0; 332 int err; 333 334 guard(mutex)(xe_sriov_pf_master_mutex(xe)); 335 336 for_each_gt(gt, xe, id) { 337 err = xe_gt_sriov_pf_config_set_preempt_timeout_locked(gt, vfid, pt); 338 result = result ?: err; 339 } 340 341 return result; 342 } 343 344 /** 345 * xe_sriov_pf_provision_query_vf_pt() - Query VF's preemption timeout. 346 * @xe: the PF &xe_device 347 * @vfid: the VF identifier 348 * @pt: placeholder for the returned preemption timeout in [us] 349 * 350 * Query VF's preemption timeout (PT) provisioning from all tiles/GTs. 351 * If values across tiles/GTs are inconsistent then -EUCLEAN error will be returned. 352 * 353 * This function can only be called on PF. 354 * 355 * Return: 0 on success or a negative error code on failure. 356 */ 357 int xe_sriov_pf_provision_query_vf_pt(struct xe_device *xe, unsigned int vfid, u32 *pt) 358 { 359 struct xe_gt *gt; 360 unsigned int id; 361 int count = 0; 362 u32 value; 363 364 guard(mutex)(xe_sriov_pf_master_mutex(xe)); 365 366 for_each_gt(gt, xe, id) { 367 value = xe_gt_sriov_pf_config_get_preempt_timeout_locked(gt, vfid); 368 if (!count++) 369 *pt = value; 370 else if (value != *pt) 371 return pf_report_unclean(gt, vfid, "PT", value, *pt); 372 } 373 374 return !count ? -ENODATA : 0; 375 } 376 377 /** 378 * xe_sriov_pf_provision_bulk_apply_priority() - Change scheduling priority of all VFs and PF. 379 * @xe: the PF &xe_device 380 * @prio: scheduling priority to set 381 * 382 * Change the scheduling priority provisioning on all tiles/GTs. 383 * 384 * This function can only be called on PF. 385 * 386 * Return: 0 on success or a negative error code on failure. 387 */ 388 int xe_sriov_pf_provision_bulk_apply_priority(struct xe_device *xe, u32 prio) 389 { 390 bool sched_if_idle; 391 struct xe_gt *gt; 392 unsigned int id; 393 int result = 0; 394 int err; 395 396 /* 397 * Currently, priority changes that involves VFs are only allowed using 398 * the 'sched_if_idle' policy KLV, so only LOW and NORMAL are supported. 399 */ 400 xe_assert(xe, prio < GUC_SCHED_PRIORITY_HIGH); 401 sched_if_idle = prio == GUC_SCHED_PRIORITY_NORMAL; 402 403 for_each_gt(gt, xe, id) { 404 err = xe_gt_sriov_pf_policy_set_sched_if_idle(gt, sched_if_idle); 405 result = result ?: err; 406 } 407 408 return result; 409 } 410 411 /** 412 * xe_sriov_pf_provision_apply_vf_priority() - Change VF's scheduling priority. 413 * @xe: the PF &xe_device 414 * @vfid: the VF identifier 415 * @prio: scheduling priority to set 416 * 417 * Change VF's scheduling priority provisioning on all tiles/GTs. 418 * 419 * This function can only be called on PF. 420 * 421 * Return: 0 on success or a negative error code on failure. 422 */ 423 int xe_sriov_pf_provision_apply_vf_priority(struct xe_device *xe, unsigned int vfid, u32 prio) 424 { 425 struct xe_gt *gt; 426 unsigned int id; 427 int result = 0; 428 int err; 429 430 for_each_gt(gt, xe, id) { 431 err = xe_gt_sriov_pf_config_set_sched_priority(gt, vfid, prio); 432 result = result ?: err; 433 } 434 435 return result; 436 } 437 438 /** 439 * xe_sriov_pf_provision_query_vf_priority() - Query VF's scheduling priority. 440 * @xe: the PF &xe_device 441 * @vfid: the VF identifier 442 * @prio: placeholder for the returned scheduling priority 443 * 444 * Query VF's scheduling priority provisioning from all tiles/GTs. 445 * If values across tiles/GTs are inconsistent then -EUCLEAN error will be returned. 446 * 447 * This function can only be called on PF. 448 * 449 * Return: 0 on success or a negative error code on failure. 450 */ 451 int xe_sriov_pf_provision_query_vf_priority(struct xe_device *xe, unsigned int vfid, u32 *prio) 452 { 453 struct xe_gt *gt; 454 unsigned int id; 455 int count = 0; 456 u32 value; 457 458 for_each_gt(gt, xe, id) { 459 value = xe_gt_sriov_pf_config_get_sched_priority(gt, vfid); 460 if (!count++) 461 *prio = value; 462 else if (value != *prio) 463 return pf_report_unclean(gt, vfid, "priority", value, *prio); 464 } 465 466 return !count ? -ENODATA : 0; 467 } 468 469 static u64 vram_per_tile(struct xe_tile *tile, u64 total) 470 { 471 struct xe_device *xe = tile->xe; 472 unsigned int tcount = xe->info.tile_count; 473 u64 alignment = xe_lmtt_page_size(&tile->sriov.pf.lmtt); 474 475 total = round_up(total, tcount * alignment); 476 return div_u64(total, tcount); 477 } 478 479 /** 480 * xe_sriov_pf_provision_bulk_apply_vram() - Change VRAM provisioning for all VFs. 481 * @xe: the PF &xe_device 482 * @size: the VRAM size in [bytes] to set 483 * 484 * Change all VFs VRAM (LMEM) provisioning on all tiles. 485 * 486 * This function can only be called on PF. 487 * 488 * Return: 0 on success or a negative error code on failure. 489 */ 490 int xe_sriov_pf_provision_bulk_apply_vram(struct xe_device *xe, u64 size) 491 { 492 unsigned int num_vfs = xe_sriov_pf_get_totalvfs(xe); 493 struct xe_tile *tile; 494 unsigned int id; 495 int result = 0; 496 int err; 497 498 xe_assert(xe, xe_device_has_lmtt(xe)); 499 500 guard(mutex)(xe_sriov_pf_master_mutex(xe)); 501 502 for_each_tile(tile, xe, id) { 503 err = xe_gt_sriov_pf_config_bulk_set_lmem_locked(tile->primary_gt, 504 VFID(1), num_vfs, 505 vram_per_tile(tile, size)); 506 result = result ?: err; 507 } 508 509 return result; 510 } 511 512 /** 513 * xe_sriov_pf_provision_apply_vf_vram() - Change single VF VRAM allocation. 514 * @xe: the PF &xe_device 515 * @vfid: the VF identifier (can't be 0 == PFID) 516 * @size: VRAM size to set 517 * 518 * Change VF's VRAM provisioning on all tiles/GTs. 519 * 520 * This function can only be called on PF. 521 * 522 * Return: 0 on success or a negative error code on failure. 523 */ 524 int xe_sriov_pf_provision_apply_vf_vram(struct xe_device *xe, unsigned int vfid, u64 size) 525 { 526 struct xe_tile *tile; 527 unsigned int id; 528 int result = 0; 529 int err; 530 531 xe_assert(xe, vfid); 532 xe_assert(xe, xe_device_has_lmtt(xe)); 533 534 guard(mutex)(xe_sriov_pf_master_mutex(xe)); 535 536 for_each_tile(tile, xe, id) { 537 err = xe_gt_sriov_pf_config_set_lmem_locked(tile->primary_gt, vfid, 538 vram_per_tile(tile, size)); 539 result = result ?: err; 540 } 541 542 return result; 543 } 544 545 /** 546 * xe_sriov_pf_provision_query_vf_vram() - Query VF's VRAM allocation. 547 * @xe: the PF &xe_device 548 * @vfid: the VF identifier (can't be 0 == PFID) 549 * @size: placeholder for the returned VRAM size 550 * 551 * Query VF's VRAM provisioning from all tiles/GTs. 552 * 553 * This function can only be called on PF. 554 * 555 * Return: 0 on success or a negative error code on failure. 556 */ 557 int xe_sriov_pf_provision_query_vf_vram(struct xe_device *xe, unsigned int vfid, u64 *size) 558 { 559 struct xe_tile *tile; 560 unsigned int id; 561 u64 total = 0; 562 563 xe_assert(xe, vfid); 564 565 guard(mutex)(xe_sriov_pf_master_mutex(xe)); 566 567 for_each_tile(tile, xe, id) 568 total += xe_gt_sriov_pf_config_get_lmem_locked(tile->primary_gt, vfid); 569 570 *size = total; 571 return 0; 572 } 573