1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2023-2024 Intel Corporation 4 */ 5 6 #include <linux/bitfield.h> 7 #include <linux/bsearch.h> 8 9 #include <drm/drm_managed.h> 10 #include <drm/drm_print.h> 11 12 #include "abi/guc_actions_sriov_abi.h" 13 #include "abi/guc_communication_mmio_abi.h" 14 #include "abi/guc_klvs_abi.h" 15 #include "abi/guc_relay_actions_abi.h" 16 #include "regs/xe_gt_regs.h" 17 #include "regs/xe_gtt_defs.h" 18 19 #include "xe_assert.h" 20 #include "xe_device.h" 21 #include "xe_ggtt.h" 22 #include "xe_gt_sriov_printk.h" 23 #include "xe_gt_sriov_vf.h" 24 #include "xe_gt_sriov_vf_types.h" 25 #include "xe_guc.h" 26 #include "xe_guc_hxg_helpers.h" 27 #include "xe_guc_relay.h" 28 #include "xe_lrc.h" 29 #include "xe_mmio.h" 30 #include "xe_sriov.h" 31 #include "xe_sriov_vf.h" 32 #include "xe_uc_fw.h" 33 #include "xe_wopcm.h" 34 35 #define make_u64_from_u32(hi, lo) ((u64)((u64)(u32)(hi) << 32 | (u32)(lo))) 36 37 static int guc_action_vf_reset(struct xe_guc *guc) 38 { 39 u32 request[GUC_HXG_REQUEST_MSG_MIN_LEN] = { 40 FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) | 41 FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) | 42 FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_ACTION_VF2GUC_VF_RESET), 43 }; 44 int ret; 45 46 ret = xe_guc_mmio_send(guc, request, ARRAY_SIZE(request)); 47 48 return ret > 0 ? -EPROTO : ret; 49 } 50 51 #define GUC_RESET_VF_STATE_RETRY_MAX 10 52 static int vf_reset_guc_state(struct xe_gt *gt) 53 { 54 unsigned int retry = GUC_RESET_VF_STATE_RETRY_MAX; 55 struct xe_guc *guc = >->uc.guc; 56 int err; 57 58 do { 59 err = guc_action_vf_reset(guc); 60 if (!err || err != -ETIMEDOUT) 61 break; 62 } while (--retry); 63 64 if (unlikely(err)) 65 xe_gt_sriov_err(gt, "Failed to reset GuC state (%pe)\n", ERR_PTR(err)); 66 return err; 67 } 68 69 /** 70 * xe_gt_sriov_vf_reset - Reset GuC VF internal state. 71 * @gt: the &xe_gt 72 * 73 * It requires functional `GuC MMIO based communication`_. 74 * 75 * Return: 0 on success or a negative error code on failure. 76 */ 77 int xe_gt_sriov_vf_reset(struct xe_gt *gt) 78 { 79 if (!xe_device_uc_enabled(gt_to_xe(gt))) 80 return -ENODEV; 81 82 return vf_reset_guc_state(gt); 83 } 84 85 static int guc_action_match_version(struct xe_guc *guc, 86 struct xe_uc_fw_version *wanted, 87 struct xe_uc_fw_version *found) 88 { 89 u32 request[VF2GUC_MATCH_VERSION_REQUEST_MSG_LEN] = { 90 FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) | 91 FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) | 92 FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, 93 GUC_ACTION_VF2GUC_MATCH_VERSION), 94 FIELD_PREP(VF2GUC_MATCH_VERSION_REQUEST_MSG_1_BRANCH, wanted->branch) | 95 FIELD_PREP(VF2GUC_MATCH_VERSION_REQUEST_MSG_1_MAJOR, wanted->major) | 96 FIELD_PREP(VF2GUC_MATCH_VERSION_REQUEST_MSG_1_MINOR, wanted->minor), 97 }; 98 u32 response[GUC_MAX_MMIO_MSG_LEN]; 99 int ret; 100 101 BUILD_BUG_ON(VF2GUC_MATCH_VERSION_RESPONSE_MSG_LEN > GUC_MAX_MMIO_MSG_LEN); 102 103 ret = xe_guc_mmio_send_recv(guc, request, ARRAY_SIZE(request), response); 104 if (unlikely(ret < 0)) 105 return ret; 106 107 if (unlikely(FIELD_GET(VF2GUC_MATCH_VERSION_RESPONSE_MSG_0_MBZ, response[0]))) 108 return -EPROTO; 109 110 memset(found, 0, sizeof(struct xe_uc_fw_version)); 111 found->branch = FIELD_GET(VF2GUC_MATCH_VERSION_RESPONSE_MSG_1_BRANCH, response[1]); 112 found->major = FIELD_GET(VF2GUC_MATCH_VERSION_RESPONSE_MSG_1_MAJOR, response[1]); 113 found->minor = FIELD_GET(VF2GUC_MATCH_VERSION_RESPONSE_MSG_1_MINOR, response[1]); 114 found->patch = FIELD_GET(VF2GUC_MATCH_VERSION_RESPONSE_MSG_1_PATCH, response[1]); 115 116 return 0; 117 } 118 119 static int guc_action_match_version_any(struct xe_guc *guc, 120 struct xe_uc_fw_version *found) 121 { 122 struct xe_uc_fw_version wanted = { 123 .branch = GUC_VERSION_BRANCH_ANY, 124 .major = GUC_VERSION_MAJOR_ANY, 125 .minor = GUC_VERSION_MINOR_ANY, 126 .patch = 0 127 }; 128 129 return guc_action_match_version(guc, &wanted, found); 130 } 131 132 static void vf_minimum_guc_version(struct xe_gt *gt, struct xe_uc_fw_version *ver) 133 { 134 struct xe_device *xe = gt_to_xe(gt); 135 136 memset(ver, 0, sizeof(struct xe_uc_fw_version)); 137 138 switch (xe->info.platform) { 139 case XE_TIGERLAKE ... XE_PVC: 140 /* 1.1 this is current baseline for Xe driver */ 141 ver->branch = 0; 142 ver->major = 1; 143 ver->minor = 1; 144 break; 145 default: 146 /* 1.2 has support for the GMD_ID KLV */ 147 ver->branch = 0; 148 ver->major = 1; 149 ver->minor = 2; 150 break; 151 } 152 } 153 154 static void vf_wanted_guc_version(struct xe_gt *gt, struct xe_uc_fw_version *ver) 155 { 156 /* for now it's the same as minimum */ 157 return vf_minimum_guc_version(gt, ver); 158 } 159 160 static int vf_handshake_with_guc(struct xe_gt *gt) 161 { 162 struct xe_uc_fw_version *guc_version = >->sriov.vf.guc_version; 163 struct xe_uc_fw_version wanted = {0}; 164 struct xe_guc *guc = >->uc.guc; 165 bool old = false; 166 int err; 167 168 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 169 170 /* select wanted version - prefer previous (if any) */ 171 if (guc_version->major || guc_version->minor) { 172 wanted = *guc_version; 173 old = true; 174 } else { 175 vf_wanted_guc_version(gt, &wanted); 176 xe_gt_assert(gt, wanted.major != GUC_VERSION_MAJOR_ANY); 177 178 /* First time we handshake, so record the minimum wanted */ 179 gt->sriov.vf.wanted_guc_version = wanted; 180 } 181 182 err = guc_action_match_version(guc, &wanted, guc_version); 183 if (unlikely(err)) 184 goto fail; 185 186 if (old) { 187 /* we don't support interface version change */ 188 if (MAKE_GUC_VER_STRUCT(*guc_version) != MAKE_GUC_VER_STRUCT(wanted)) { 189 xe_gt_sriov_err(gt, "New GuC interface version detected: %u.%u.%u.%u\n", 190 guc_version->branch, guc_version->major, 191 guc_version->minor, guc_version->patch); 192 xe_gt_sriov_info(gt, "Previously used version was: %u.%u.%u.%u\n", 193 wanted.branch, wanted.major, 194 wanted.minor, wanted.patch); 195 err = -EREMCHG; 196 goto fail; 197 } else { 198 /* version is unchanged, no need to re-verify it */ 199 return 0; 200 } 201 } 202 203 /* illegal */ 204 if (guc_version->major > wanted.major) { 205 err = -EPROTO; 206 goto unsupported; 207 } 208 209 /* there's no fallback on major version. */ 210 if (guc_version->major != wanted.major) { 211 err = -ENOPKG; 212 goto unsupported; 213 } 214 215 /* check against minimum version supported by us */ 216 vf_minimum_guc_version(gt, &wanted); 217 xe_gt_assert(gt, wanted.major != GUC_VERSION_MAJOR_ANY); 218 if (MAKE_GUC_VER_STRUCT(*guc_version) < MAKE_GUC_VER_STRUCT(wanted)) { 219 err = -ENOKEY; 220 goto unsupported; 221 } 222 223 xe_gt_sriov_dbg(gt, "using GuC interface version %u.%u.%u.%u\n", 224 guc_version->branch, guc_version->major, 225 guc_version->minor, guc_version->patch); 226 227 return 0; 228 229 unsupported: 230 xe_gt_sriov_err(gt, "Unsupported GuC version %u.%u.%u.%u (%pe)\n", 231 guc_version->branch, guc_version->major, 232 guc_version->minor, guc_version->patch, 233 ERR_PTR(err)); 234 fail: 235 xe_gt_sriov_err(gt, "Unable to confirm GuC version %u.%u (%pe)\n", 236 wanted.major, wanted.minor, ERR_PTR(err)); 237 238 /* try again with *any* just to query which version is supported */ 239 if (!guc_action_match_version_any(guc, &wanted)) 240 xe_gt_sriov_notice(gt, "GuC reports interface version %u.%u.%u.%u\n", 241 wanted.branch, wanted.major, wanted.minor, wanted.patch); 242 return err; 243 } 244 245 /** 246 * xe_gt_sriov_vf_bootstrap - Query and setup GuC ABI interface version. 247 * @gt: the &xe_gt 248 * 249 * This function is for VF use only. 250 * It requires functional `GuC MMIO based communication`_. 251 * 252 * Return: 0 on success or a negative error code on failure. 253 */ 254 int xe_gt_sriov_vf_bootstrap(struct xe_gt *gt) 255 { 256 int err; 257 258 if (!xe_device_uc_enabled(gt_to_xe(gt))) 259 return -ENODEV; 260 261 err = vf_reset_guc_state(gt); 262 if (unlikely(err)) 263 return err; 264 265 err = vf_handshake_with_guc(gt); 266 if (unlikely(err)) 267 return err; 268 269 return 0; 270 } 271 272 /** 273 * xe_gt_sriov_vf_guc_versions - Minimum required and found GuC ABI versions 274 * @gt: the &xe_gt 275 * @wanted: pointer to the xe_uc_fw_version to be filled with the wanted version 276 * @found: pointer to the xe_uc_fw_version to be filled with the found version 277 * 278 * This function is for VF use only and it can only be used after successful 279 * version handshake with the GuC. 280 */ 281 void xe_gt_sriov_vf_guc_versions(struct xe_gt *gt, 282 struct xe_uc_fw_version *wanted, 283 struct xe_uc_fw_version *found) 284 { 285 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 286 xe_gt_assert(gt, gt->sriov.vf.guc_version.major); 287 288 if (wanted) 289 *wanted = gt->sriov.vf.wanted_guc_version; 290 291 if (found) 292 *found = gt->sriov.vf.guc_version; 293 } 294 295 static int guc_action_vf_notify_resfix_done(struct xe_guc *guc) 296 { 297 u32 request[GUC_HXG_REQUEST_MSG_MIN_LEN] = { 298 FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) | 299 FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) | 300 FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_ACTION_VF2GUC_NOTIFY_RESFIX_DONE), 301 }; 302 int ret; 303 304 ret = xe_guc_mmio_send(guc, request, ARRAY_SIZE(request)); 305 306 return ret > 0 ? -EPROTO : ret; 307 } 308 309 /** 310 * xe_gt_sriov_vf_notify_resfix_done - Notify GuC about resource fixups apply completed. 311 * @gt: the &xe_gt struct instance linked to target GuC 312 * 313 * Returns: 0 if the operation completed successfully, or a negative error 314 * code otherwise. 315 */ 316 int xe_gt_sriov_vf_notify_resfix_done(struct xe_gt *gt) 317 { 318 struct xe_guc *guc = >->uc.guc; 319 int err; 320 321 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 322 323 err = guc_action_vf_notify_resfix_done(guc); 324 if (unlikely(err)) 325 xe_gt_sriov_err(gt, "Failed to notify GuC about resource fixup done (%pe)\n", 326 ERR_PTR(err)); 327 else 328 xe_gt_sriov_dbg_verbose(gt, "sent GuC resource fixup done\n"); 329 330 return err; 331 } 332 333 static int guc_action_query_single_klv(struct xe_guc *guc, u32 key, 334 u32 *value, u32 value_len) 335 { 336 u32 request[VF2GUC_QUERY_SINGLE_KLV_REQUEST_MSG_LEN] = { 337 FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) | 338 FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) | 339 FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, 340 GUC_ACTION_VF2GUC_QUERY_SINGLE_KLV), 341 FIELD_PREP(VF2GUC_QUERY_SINGLE_KLV_REQUEST_MSG_1_KEY, key), 342 }; 343 u32 response[GUC_MAX_MMIO_MSG_LEN]; 344 u32 length; 345 int ret; 346 347 BUILD_BUG_ON(VF2GUC_QUERY_SINGLE_KLV_RESPONSE_MSG_MAX_LEN > GUC_MAX_MMIO_MSG_LEN); 348 ret = xe_guc_mmio_send_recv(guc, request, ARRAY_SIZE(request), response); 349 if (unlikely(ret < 0)) 350 return ret; 351 352 if (unlikely(FIELD_GET(VF2GUC_QUERY_SINGLE_KLV_RESPONSE_MSG_0_MBZ, response[0]))) 353 return -EPROTO; 354 355 length = FIELD_GET(VF2GUC_QUERY_SINGLE_KLV_RESPONSE_MSG_0_LENGTH, response[0]); 356 if (unlikely(length > value_len)) 357 return -EOVERFLOW; 358 if (unlikely(length < value_len)) 359 return -ENODATA; 360 361 switch (value_len) { 362 default: 363 xe_gt_WARN_ON(guc_to_gt(guc), value_len > 3); 364 fallthrough; 365 case 3: 366 value[2] = FIELD_GET(VF2GUC_QUERY_SINGLE_KLV_RESPONSE_MSG_3_VALUE96, response[3]); 367 fallthrough; 368 case 2: 369 value[1] = FIELD_GET(VF2GUC_QUERY_SINGLE_KLV_RESPONSE_MSG_2_VALUE64, response[2]); 370 fallthrough; 371 case 1: 372 value[0] = FIELD_GET(VF2GUC_QUERY_SINGLE_KLV_RESPONSE_MSG_1_VALUE32, response[1]); 373 fallthrough; 374 case 0: 375 break; 376 } 377 378 return 0; 379 } 380 381 static int guc_action_query_single_klv32(struct xe_guc *guc, u32 key, u32 *value32) 382 { 383 return guc_action_query_single_klv(guc, key, value32, hxg_sizeof(u32)); 384 } 385 386 static int guc_action_query_single_klv64(struct xe_guc *guc, u32 key, u64 *value64) 387 { 388 u32 value[2]; 389 int err; 390 391 err = guc_action_query_single_klv(guc, key, value, hxg_sizeof(value)); 392 if (unlikely(err)) 393 return err; 394 395 *value64 = make_u64_from_u32(value[1], value[0]); 396 return 0; 397 } 398 399 static bool has_gmdid(struct xe_device *xe) 400 { 401 return GRAPHICS_VERx100(xe) >= 1270; 402 } 403 404 /** 405 * xe_gt_sriov_vf_gmdid - Query GMDID over MMIO. 406 * @gt: the &xe_gt 407 * 408 * This function is for VF use only. 409 * 410 * Return: value of GMDID KLV on success or 0 on failure. 411 */ 412 u32 xe_gt_sriov_vf_gmdid(struct xe_gt *gt) 413 { 414 const char *type = xe_gt_is_media_type(gt) ? "media" : "graphics"; 415 struct xe_guc *guc = >->uc.guc; 416 u32 value; 417 int err; 418 419 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 420 xe_gt_assert(gt, !GRAPHICS_VERx100(gt_to_xe(gt)) || has_gmdid(gt_to_xe(gt))); 421 xe_gt_assert(gt, gt->sriov.vf.guc_version.major > 1 || gt->sriov.vf.guc_version.minor >= 2); 422 423 err = guc_action_query_single_klv32(guc, GUC_KLV_GLOBAL_CFG_GMD_ID_KEY, &value); 424 if (unlikely(err)) { 425 xe_gt_sriov_err(gt, "Failed to obtain %s GMDID (%pe)\n", 426 type, ERR_PTR(err)); 427 return 0; 428 } 429 430 xe_gt_sriov_dbg(gt, "%s GMDID = %#x\n", type, value); 431 return value; 432 } 433 434 static int vf_get_ggtt_info(struct xe_gt *gt) 435 { 436 struct xe_gt_sriov_vf_selfconfig *config = >->sriov.vf.self_config; 437 struct xe_guc *guc = >->uc.guc; 438 u64 start, size; 439 int err; 440 441 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 442 443 err = guc_action_query_single_klv64(guc, GUC_KLV_VF_CFG_GGTT_START_KEY, &start); 444 if (unlikely(err)) 445 return err; 446 447 err = guc_action_query_single_klv64(guc, GUC_KLV_VF_CFG_GGTT_SIZE_KEY, &size); 448 if (unlikely(err)) 449 return err; 450 451 if (config->ggtt_size && config->ggtt_size != size) { 452 xe_gt_sriov_err(gt, "Unexpected GGTT reassignment: %lluK != %lluK\n", 453 size / SZ_1K, config->ggtt_size / SZ_1K); 454 return -EREMCHG; 455 } 456 457 xe_gt_sriov_dbg_verbose(gt, "GGTT %#llx-%#llx = %lluK\n", 458 start, start + size - 1, size / SZ_1K); 459 460 config->ggtt_shift = start - (s64)config->ggtt_base; 461 config->ggtt_base = start; 462 config->ggtt_size = size; 463 464 return config->ggtt_size ? 0 : -ENODATA; 465 } 466 467 static int vf_get_lmem_info(struct xe_gt *gt) 468 { 469 struct xe_gt_sriov_vf_selfconfig *config = >->sriov.vf.self_config; 470 struct xe_guc *guc = >->uc.guc; 471 char size_str[10]; 472 u64 size; 473 int err; 474 475 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 476 477 err = guc_action_query_single_klv64(guc, GUC_KLV_VF_CFG_LMEM_SIZE_KEY, &size); 478 if (unlikely(err)) 479 return err; 480 481 if (config->lmem_size && config->lmem_size != size) { 482 xe_gt_sriov_err(gt, "Unexpected LMEM reassignment: %lluM != %lluM\n", 483 size / SZ_1M, config->lmem_size / SZ_1M); 484 return -EREMCHG; 485 } 486 487 string_get_size(size, 1, STRING_UNITS_2, size_str, sizeof(size_str)); 488 xe_gt_sriov_dbg_verbose(gt, "LMEM %lluM %s\n", size / SZ_1M, size_str); 489 490 config->lmem_size = size; 491 492 return config->lmem_size ? 0 : -ENODATA; 493 } 494 495 static int vf_get_submission_cfg(struct xe_gt *gt) 496 { 497 struct xe_gt_sriov_vf_selfconfig *config = >->sriov.vf.self_config; 498 struct xe_guc *guc = >->uc.guc; 499 u32 num_ctxs, num_dbs; 500 int err; 501 502 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 503 504 err = guc_action_query_single_klv32(guc, GUC_KLV_VF_CFG_NUM_CONTEXTS_KEY, &num_ctxs); 505 if (unlikely(err)) 506 return err; 507 508 err = guc_action_query_single_klv32(guc, GUC_KLV_VF_CFG_NUM_DOORBELLS_KEY, &num_dbs); 509 if (unlikely(err)) 510 return err; 511 512 if (config->num_ctxs && config->num_ctxs != num_ctxs) { 513 xe_gt_sriov_err(gt, "Unexpected CTXs reassignment: %u != %u\n", 514 num_ctxs, config->num_ctxs); 515 return -EREMCHG; 516 } 517 if (config->num_dbs && config->num_dbs != num_dbs) { 518 xe_gt_sriov_err(gt, "Unexpected DBs reassignment: %u != %u\n", 519 num_dbs, config->num_dbs); 520 return -EREMCHG; 521 } 522 523 xe_gt_sriov_dbg_verbose(gt, "CTXs %u DBs %u\n", num_ctxs, num_dbs); 524 525 config->num_ctxs = num_ctxs; 526 config->num_dbs = num_dbs; 527 528 return config->num_ctxs ? 0 : -ENODATA; 529 } 530 531 static void vf_cache_gmdid(struct xe_gt *gt) 532 { 533 xe_gt_assert(gt, has_gmdid(gt_to_xe(gt))); 534 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 535 536 gt->sriov.vf.runtime.gmdid = xe_gt_sriov_vf_gmdid(gt); 537 } 538 539 /** 540 * xe_gt_sriov_vf_query_config - Query SR-IOV config data over MMIO. 541 * @gt: the &xe_gt 542 * 543 * This function is for VF use only. 544 * 545 * Return: 0 on success or a negative error code on failure. 546 */ 547 int xe_gt_sriov_vf_query_config(struct xe_gt *gt) 548 { 549 struct xe_device *xe = gt_to_xe(gt); 550 int err; 551 552 err = vf_get_ggtt_info(gt); 553 if (unlikely(err)) 554 return err; 555 556 if (IS_DGFX(xe) && xe_gt_is_main_type(gt)) { 557 err = vf_get_lmem_info(gt); 558 if (unlikely(err)) 559 return err; 560 } 561 562 err = vf_get_submission_cfg(gt); 563 if (unlikely(err)) 564 return err; 565 566 if (has_gmdid(xe)) 567 vf_cache_gmdid(gt); 568 569 return 0; 570 } 571 572 /** 573 * xe_gt_sriov_vf_guc_ids - VF GuC context IDs configuration. 574 * @gt: the &xe_gt 575 * 576 * This function is for VF use only. 577 * 578 * Return: number of GuC context IDs assigned to VF. 579 */ 580 u16 xe_gt_sriov_vf_guc_ids(struct xe_gt *gt) 581 { 582 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 583 xe_gt_assert(gt, gt->sriov.vf.guc_version.major); 584 xe_gt_assert(gt, gt->sriov.vf.self_config.num_ctxs); 585 586 return gt->sriov.vf.self_config.num_ctxs; 587 } 588 589 /** 590 * xe_gt_sriov_vf_lmem - VF LMEM configuration. 591 * @gt: the &xe_gt 592 * 593 * This function is for VF use only. 594 * 595 * Return: size of the LMEM assigned to VF. 596 */ 597 u64 xe_gt_sriov_vf_lmem(struct xe_gt *gt) 598 { 599 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 600 xe_gt_assert(gt, gt->sriov.vf.guc_version.major); 601 xe_gt_assert(gt, gt->sriov.vf.self_config.lmem_size); 602 603 return gt->sriov.vf.self_config.lmem_size; 604 } 605 606 /** 607 * xe_gt_sriov_vf_ggtt - VF GGTT configuration. 608 * @gt: the &xe_gt 609 * 610 * This function is for VF use only. 611 * 612 * Return: size of the GGTT assigned to VF. 613 */ 614 u64 xe_gt_sriov_vf_ggtt(struct xe_gt *gt) 615 { 616 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 617 xe_gt_assert(gt, gt->sriov.vf.guc_version.major); 618 xe_gt_assert(gt, gt->sriov.vf.self_config.ggtt_size); 619 620 return gt->sriov.vf.self_config.ggtt_size; 621 } 622 623 /** 624 * xe_gt_sriov_vf_ggtt_base - VF GGTT base offset. 625 * @gt: the &xe_gt 626 * 627 * This function is for VF use only. 628 * 629 * Return: base offset of the GGTT assigned to VF. 630 */ 631 u64 xe_gt_sriov_vf_ggtt_base(struct xe_gt *gt) 632 { 633 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 634 xe_gt_assert(gt, gt->sriov.vf.guc_version.major); 635 xe_gt_assert(gt, gt->sriov.vf.self_config.ggtt_size); 636 637 return gt->sriov.vf.self_config.ggtt_base; 638 } 639 640 /** 641 * xe_gt_sriov_vf_ggtt_shift - Return shift in GGTT range due to VF migration 642 * @gt: the &xe_gt struct instance 643 * 644 * This function is for VF use only. 645 * 646 * Return: The shift value; could be negative 647 */ 648 s64 xe_gt_sriov_vf_ggtt_shift(struct xe_gt *gt) 649 { 650 struct xe_gt_sriov_vf_selfconfig *config = >->sriov.vf.self_config; 651 652 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 653 xe_gt_assert(gt, xe_gt_is_main_type(gt)); 654 655 return config->ggtt_shift; 656 } 657 658 static int relay_action_handshake(struct xe_gt *gt, u32 *major, u32 *minor) 659 { 660 u32 request[VF2PF_HANDSHAKE_REQUEST_MSG_LEN] = { 661 FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) | 662 FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) | 663 FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, GUC_RELAY_ACTION_VF2PF_HANDSHAKE), 664 FIELD_PREP(VF2PF_HANDSHAKE_REQUEST_MSG_1_MAJOR, *major) | 665 FIELD_PREP(VF2PF_HANDSHAKE_REQUEST_MSG_1_MINOR, *minor), 666 }; 667 u32 response[VF2PF_HANDSHAKE_RESPONSE_MSG_LEN]; 668 int ret; 669 670 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 671 672 ret = xe_guc_relay_send_to_pf(>->uc.guc.relay, 673 request, ARRAY_SIZE(request), 674 response, ARRAY_SIZE(response)); 675 if (unlikely(ret < 0)) 676 return ret; 677 678 if (unlikely(ret != VF2PF_HANDSHAKE_RESPONSE_MSG_LEN)) 679 return -EPROTO; 680 681 if (unlikely(FIELD_GET(VF2PF_HANDSHAKE_RESPONSE_MSG_0_MBZ, response[0]))) 682 return -EPROTO; 683 684 *major = FIELD_GET(VF2PF_HANDSHAKE_RESPONSE_MSG_1_MAJOR, response[1]); 685 *minor = FIELD_GET(VF2PF_HANDSHAKE_RESPONSE_MSG_1_MINOR, response[1]); 686 687 return 0; 688 } 689 690 static void vf_connect_pf(struct xe_device *xe, u16 major, u16 minor) 691 { 692 xe_assert(xe, IS_SRIOV_VF(xe)); 693 694 xe->sriov.vf.pf_version.major = major; 695 xe->sriov.vf.pf_version.minor = minor; 696 } 697 698 static void vf_disconnect_pf(struct xe_device *xe) 699 { 700 vf_connect_pf(xe, 0, 0); 701 } 702 703 static int vf_handshake_with_pf(struct xe_gt *gt) 704 { 705 struct xe_device *xe = gt_to_xe(gt); 706 u32 major_wanted = GUC_RELAY_VERSION_LATEST_MAJOR; 707 u32 minor_wanted = GUC_RELAY_VERSION_LATEST_MINOR; 708 u32 major = major_wanted, minor = minor_wanted; 709 int err; 710 711 err = relay_action_handshake(gt, &major, &minor); 712 if (unlikely(err)) 713 goto failed; 714 715 if (!major && !minor) { 716 err = -ENODATA; 717 goto failed; 718 } 719 720 xe_gt_sriov_dbg(gt, "using VF/PF ABI %u.%u\n", major, minor); 721 vf_connect_pf(xe, major, minor); 722 return 0; 723 724 failed: 725 xe_gt_sriov_err(gt, "Unable to confirm VF/PF ABI version %u.%u (%pe)\n", 726 major, minor, ERR_PTR(err)); 727 vf_disconnect_pf(xe); 728 return err; 729 } 730 731 /** 732 * xe_gt_sriov_vf_connect - Establish connection with the PF driver. 733 * @gt: the &xe_gt 734 * 735 * This function is for VF use only. 736 * 737 * Return: 0 on success or a negative error code on failure. 738 */ 739 int xe_gt_sriov_vf_connect(struct xe_gt *gt) 740 { 741 int err; 742 743 err = vf_handshake_with_pf(gt); 744 if (unlikely(err)) 745 goto failed; 746 747 return 0; 748 749 failed: 750 xe_gt_sriov_err(gt, "Failed to get version info (%pe)\n", ERR_PTR(err)); 751 return err; 752 } 753 754 /** 755 * xe_gt_sriov_vf_default_lrcs_hwsp_rebase - Update GGTT references in HWSP of default LRCs. 756 * @gt: the &xe_gt struct instance 757 */ 758 void xe_gt_sriov_vf_default_lrcs_hwsp_rebase(struct xe_gt *gt) 759 { 760 struct xe_hw_engine *hwe; 761 enum xe_hw_engine_id id; 762 763 for_each_hw_engine(hwe, gt, id) 764 xe_default_lrc_update_memirq_regs_with_address(hwe); 765 } 766 767 /** 768 * xe_gt_sriov_vf_migrated_event_handler - Start a VF migration recovery, 769 * or just mark that a GuC is ready for it. 770 * @gt: the &xe_gt struct instance linked to target GuC 771 * 772 * This function shall be called only by VF. 773 */ 774 void xe_gt_sriov_vf_migrated_event_handler(struct xe_gt *gt) 775 { 776 struct xe_device *xe = gt_to_xe(gt); 777 778 xe_gt_assert(gt, IS_SRIOV_VF(xe)); 779 780 set_bit(gt->info.id, &xe->sriov.vf.migration.gt_flags); 781 /* 782 * We need to be certain that if all flags were set, at least one 783 * thread will notice that and schedule the recovery. 784 */ 785 smp_mb__after_atomic(); 786 787 xe_gt_sriov_info(gt, "ready for recovery after migration\n"); 788 xe_sriov_vf_start_migration_recovery(xe); 789 } 790 791 static bool vf_is_negotiated(struct xe_gt *gt, u16 major, u16 minor) 792 { 793 struct xe_device *xe = gt_to_xe(gt); 794 795 xe_gt_assert(gt, IS_SRIOV_VF(xe)); 796 797 return major == xe->sriov.vf.pf_version.major && 798 minor <= xe->sriov.vf.pf_version.minor; 799 } 800 801 static int vf_prepare_runtime_info(struct xe_gt *gt, unsigned int num_regs) 802 { 803 struct vf_runtime_reg *regs = gt->sriov.vf.runtime.regs; 804 unsigned int regs_size = round_up(num_regs, 4); 805 struct xe_device *xe = gt_to_xe(gt); 806 807 xe_gt_assert(gt, IS_SRIOV_VF(xe)); 808 809 if (regs) { 810 if (num_regs <= gt->sriov.vf.runtime.regs_size) { 811 memset(regs, 0, num_regs * sizeof(*regs)); 812 gt->sriov.vf.runtime.num_regs = num_regs; 813 return 0; 814 } 815 816 drmm_kfree(&xe->drm, regs); 817 gt->sriov.vf.runtime.regs = NULL; 818 gt->sriov.vf.runtime.num_regs = 0; 819 gt->sriov.vf.runtime.regs_size = 0; 820 } 821 822 regs = drmm_kcalloc(&xe->drm, regs_size, sizeof(*regs), GFP_KERNEL); 823 if (unlikely(!regs)) 824 return -ENOMEM; 825 826 gt->sriov.vf.runtime.regs = regs; 827 gt->sriov.vf.runtime.num_regs = num_regs; 828 gt->sriov.vf.runtime.regs_size = regs_size; 829 return 0; 830 } 831 832 static int vf_query_runtime_info(struct xe_gt *gt) 833 { 834 u32 request[VF2PF_QUERY_RUNTIME_REQUEST_MSG_LEN]; 835 u32 response[VF2PF_QUERY_RUNTIME_RESPONSE_MSG_MIN_LEN + 32]; /* up to 16 regs */ 836 u32 limit = (ARRAY_SIZE(response) - VF2PF_QUERY_RUNTIME_RESPONSE_MSG_MIN_LEN) / 2; 837 u32 count, remaining, num, i; 838 u32 start = 0; 839 int ret; 840 841 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 842 xe_gt_assert(gt, limit); 843 844 /* this is part of the 1.0 PF/VF ABI */ 845 if (!vf_is_negotiated(gt, 1, 0)) 846 return -ENOPKG; 847 848 request[0] = FIELD_PREP(GUC_HXG_MSG_0_ORIGIN, GUC_HXG_ORIGIN_HOST) | 849 FIELD_PREP(GUC_HXG_MSG_0_TYPE, GUC_HXG_TYPE_REQUEST) | 850 FIELD_PREP(GUC_HXG_REQUEST_MSG_0_ACTION, 851 GUC_RELAY_ACTION_VF2PF_QUERY_RUNTIME) | 852 FIELD_PREP(VF2PF_QUERY_RUNTIME_REQUEST_MSG_0_LIMIT, limit); 853 854 repeat: 855 request[1] = FIELD_PREP(VF2PF_QUERY_RUNTIME_REQUEST_MSG_1_START, start); 856 ret = xe_guc_relay_send_to_pf(>->uc.guc.relay, 857 request, ARRAY_SIZE(request), 858 response, ARRAY_SIZE(response)); 859 if (unlikely(ret < 0)) 860 goto failed; 861 862 if (unlikely(ret < VF2PF_QUERY_RUNTIME_RESPONSE_MSG_MIN_LEN)) { 863 ret = -EPROTO; 864 goto failed; 865 } 866 if (unlikely((ret - VF2PF_QUERY_RUNTIME_RESPONSE_MSG_MIN_LEN) % 2)) { 867 ret = -EPROTO; 868 goto failed; 869 } 870 871 num = (ret - VF2PF_QUERY_RUNTIME_RESPONSE_MSG_MIN_LEN) / 2; 872 count = FIELD_GET(VF2PF_QUERY_RUNTIME_RESPONSE_MSG_0_COUNT, response[0]); 873 remaining = FIELD_GET(VF2PF_QUERY_RUNTIME_RESPONSE_MSG_1_REMAINING, response[1]); 874 875 xe_gt_sriov_dbg_verbose(gt, "count=%u num=%u ret=%d start=%u remaining=%u\n", 876 count, num, ret, start, remaining); 877 878 if (unlikely(count != num)) { 879 ret = -EPROTO; 880 goto failed; 881 } 882 883 if (start == 0) { 884 ret = vf_prepare_runtime_info(gt, num + remaining); 885 if (unlikely(ret < 0)) 886 goto failed; 887 } else if (unlikely(start + num > gt->sriov.vf.runtime.num_regs)) { 888 ret = -EPROTO; 889 goto failed; 890 } 891 892 for (i = 0; i < num; ++i) { 893 struct vf_runtime_reg *reg = >->sriov.vf.runtime.regs[start + i]; 894 895 reg->offset = response[VF2PF_QUERY_RUNTIME_RESPONSE_MSG_MIN_LEN + 2 * i]; 896 reg->value = response[VF2PF_QUERY_RUNTIME_RESPONSE_MSG_MIN_LEN + 2 * i + 1]; 897 } 898 899 if (remaining) { 900 start += num; 901 goto repeat; 902 } 903 904 return 0; 905 906 failed: 907 vf_prepare_runtime_info(gt, 0); 908 return ret; 909 } 910 911 static void vf_show_runtime_info(struct xe_gt *gt) 912 { 913 struct vf_runtime_reg *vf_regs = gt->sriov.vf.runtime.regs; 914 unsigned int size = gt->sriov.vf.runtime.num_regs; 915 916 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 917 918 for (; size--; vf_regs++) 919 xe_gt_sriov_dbg(gt, "runtime(%#x) = %#x\n", 920 vf_regs->offset, vf_regs->value); 921 } 922 923 /** 924 * xe_gt_sriov_vf_query_runtime - Query SR-IOV runtime data. 925 * @gt: the &xe_gt 926 * 927 * This function is for VF use only. 928 * 929 * Return: 0 on success or a negative error code on failure. 930 */ 931 int xe_gt_sriov_vf_query_runtime(struct xe_gt *gt) 932 { 933 int err; 934 935 err = vf_query_runtime_info(gt); 936 if (unlikely(err)) 937 goto failed; 938 939 if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) 940 vf_show_runtime_info(gt); 941 942 return 0; 943 944 failed: 945 xe_gt_sriov_err(gt, "Failed to get runtime info (%pe)\n", 946 ERR_PTR(err)); 947 return err; 948 } 949 950 static int vf_runtime_reg_cmp(const void *a, const void *b) 951 { 952 const struct vf_runtime_reg *ra = a; 953 const struct vf_runtime_reg *rb = b; 954 955 return (int)ra->offset - (int)rb->offset; 956 } 957 958 static struct vf_runtime_reg *vf_lookup_reg(struct xe_gt *gt, u32 addr) 959 { 960 struct xe_gt_sriov_vf_runtime *runtime = >->sriov.vf.runtime; 961 struct vf_runtime_reg key = { .offset = addr }; 962 963 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 964 965 return bsearch(&key, runtime->regs, runtime->num_regs, sizeof(key), 966 vf_runtime_reg_cmp); 967 } 968 969 /** 970 * xe_gt_sriov_vf_read32 - Get a register value from the runtime data. 971 * @gt: the &xe_gt 972 * @reg: the register to read 973 * 974 * This function is for VF use only. 975 * This function shall be called after VF has connected to PF. 976 * This function is dedicated for registers that VFs can't read directly. 977 * 978 * Return: register value obtained from the PF or 0 if not found. 979 */ 980 u32 xe_gt_sriov_vf_read32(struct xe_gt *gt, struct xe_reg reg) 981 { 982 u32 addr = xe_mmio_adjusted_addr(>->mmio, reg.addr); 983 struct vf_runtime_reg *rr; 984 985 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 986 xe_gt_assert(gt, !reg.vf); 987 988 if (reg.addr == GMD_ID.addr) { 989 xe_gt_sriov_dbg_verbose(gt, "gmdid(%#x) = %#x\n", 990 addr, gt->sriov.vf.runtime.gmdid); 991 return gt->sriov.vf.runtime.gmdid; 992 } 993 994 rr = vf_lookup_reg(gt, addr); 995 if (!rr) { 996 xe_gt_WARN(gt, IS_ENABLED(CONFIG_DRM_XE_DEBUG), 997 "VF is trying to read an inaccessible register %#x+%#x\n", 998 reg.addr, addr - reg.addr); 999 return 0; 1000 } 1001 1002 xe_gt_sriov_dbg_verbose(gt, "runtime[%#x] = %#x\n", addr, rr->value); 1003 return rr->value; 1004 } 1005 1006 /** 1007 * xe_gt_sriov_vf_write32 - Handle a write to an inaccessible register. 1008 * @gt: the &xe_gt 1009 * @reg: the register to write 1010 * @val: value to write 1011 * 1012 * This function is for VF use only. 1013 * Currently it will trigger a WARN if running on debug build. 1014 */ 1015 void xe_gt_sriov_vf_write32(struct xe_gt *gt, struct xe_reg reg, u32 val) 1016 { 1017 u32 addr = xe_mmio_adjusted_addr(>->mmio, reg.addr); 1018 1019 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 1020 xe_gt_assert(gt, !reg.vf); 1021 1022 /* 1023 * In the future, we may want to handle selected writes to inaccessible 1024 * registers in some custom way, but for now let's just log a warning 1025 * about such attempt, as likely we might be doing something wrong. 1026 */ 1027 xe_gt_WARN(gt, IS_ENABLED(CONFIG_DRM_XE_DEBUG), 1028 "VF is trying to write %#x to an inaccessible register %#x+%#x\n", 1029 val, reg.addr, addr - reg.addr); 1030 } 1031 1032 /** 1033 * xe_gt_sriov_vf_print_config - Print VF self config. 1034 * @gt: the &xe_gt 1035 * @p: the &drm_printer 1036 * 1037 * This function is for VF use only. 1038 */ 1039 void xe_gt_sriov_vf_print_config(struct xe_gt *gt, struct drm_printer *p) 1040 { 1041 struct xe_gt_sriov_vf_selfconfig *config = >->sriov.vf.self_config; 1042 struct xe_device *xe = gt_to_xe(gt); 1043 char buf[10]; 1044 1045 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 1046 1047 drm_printf(p, "GGTT range:\t%#llx-%#llx\n", 1048 config->ggtt_base, 1049 config->ggtt_base + config->ggtt_size - 1); 1050 1051 string_get_size(config->ggtt_size, 1, STRING_UNITS_2, buf, sizeof(buf)); 1052 drm_printf(p, "GGTT size:\t%llu (%s)\n", config->ggtt_size, buf); 1053 1054 drm_printf(p, "GGTT shift on last restore:\t%lld\n", config->ggtt_shift); 1055 1056 if (IS_DGFX(xe) && xe_gt_is_main_type(gt)) { 1057 string_get_size(config->lmem_size, 1, STRING_UNITS_2, buf, sizeof(buf)); 1058 drm_printf(p, "LMEM size:\t%llu (%s)\n", config->lmem_size, buf); 1059 } 1060 1061 drm_printf(p, "GuC contexts:\t%u\n", config->num_ctxs); 1062 drm_printf(p, "GuC doorbells:\t%u\n", config->num_dbs); 1063 } 1064 1065 /** 1066 * xe_gt_sriov_vf_print_runtime - Print VF's runtime regs received from PF. 1067 * @gt: the &xe_gt 1068 * @p: the &drm_printer 1069 * 1070 * This function is for VF use only. 1071 */ 1072 void xe_gt_sriov_vf_print_runtime(struct xe_gt *gt, struct drm_printer *p) 1073 { 1074 struct vf_runtime_reg *vf_regs = gt->sriov.vf.runtime.regs; 1075 unsigned int size = gt->sriov.vf.runtime.num_regs; 1076 1077 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 1078 1079 for (; size--; vf_regs++) 1080 drm_printf(p, "%#x = %#x\n", vf_regs->offset, vf_regs->value); 1081 } 1082 1083 /** 1084 * xe_gt_sriov_vf_print_version - Print VF ABI versions. 1085 * @gt: the &xe_gt 1086 * @p: the &drm_printer 1087 * 1088 * This function is for VF use only. 1089 */ 1090 void xe_gt_sriov_vf_print_version(struct xe_gt *gt, struct drm_printer *p) 1091 { 1092 struct xe_device *xe = gt_to_xe(gt); 1093 struct xe_uc_fw_version *guc_version = >->sriov.vf.guc_version; 1094 struct xe_uc_fw_version *wanted = >->sriov.vf.wanted_guc_version; 1095 struct xe_sriov_vf_relay_version *pf_version = &xe->sriov.vf.pf_version; 1096 struct xe_uc_fw_version ver; 1097 1098 xe_gt_assert(gt, IS_SRIOV_VF(gt_to_xe(gt))); 1099 1100 drm_printf(p, "GuC ABI:\n"); 1101 1102 vf_minimum_guc_version(gt, &ver); 1103 drm_printf(p, "\tbase:\t%u.%u.%u.*\n", ver.branch, ver.major, ver.minor); 1104 1105 drm_printf(p, "\twanted:\t%u.%u.%u.*\n", 1106 wanted->branch, wanted->major, wanted->minor); 1107 1108 drm_printf(p, "\thandshake:\t%u.%u.%u.%u\n", 1109 guc_version->branch, guc_version->major, 1110 guc_version->minor, guc_version->patch); 1111 1112 drm_printf(p, "PF ABI:\n"); 1113 1114 drm_printf(p, "\tbase:\t%u.%u\n", 1115 GUC_RELAY_VERSION_BASE_MAJOR, GUC_RELAY_VERSION_BASE_MINOR); 1116 drm_printf(p, "\twanted:\t%u.%u\n", 1117 GUC_RELAY_VERSION_LATEST_MAJOR, GUC_RELAY_VERSION_LATEST_MINOR); 1118 drm_printf(p, "\thandshake:\t%u.%u\n", 1119 pf_version->major, pf_version->minor); 1120 } 1121