diff --git a/drivers/gpu/drm/xe/xe_sriov_packet.c b/drivers/gpu/drm/xe/xe_sriov_packet.c index 558a3697d639..e9ae9c9744ea 100644 --- a/drivers/gpu/drm/xe/xe_sriov_packet.c +++ b/drivers/gpu/drm/xe/xe_sriov_packet.c @@ -360,8 +360,7 @@ static int pf_descriptor_init(struct xe_device *xe, unsigned int vfid) { struct xe_sriov_packet **desc = pf_pick_descriptor(xe, vfid); struct xe_sriov_packet *data; - unsigned int len = 0; - u32 *klvs; + u32 *klvs, *end; int ret; data = xe_sriov_packet_alloc(xe); @@ -376,20 +375,55 @@ static int pf_descriptor_init(struct xe_device *xe, unsigned int vfid) } klvs = data->vaddr; - klvs[len++] = PREP_GUC_KLV_CONST(MIGRATION_KLV_DEVICE_DEVID_KEY, - MIGRATION_KLV_DEVICE_DEVID_LEN); - klvs[len++] = xe->info.devid; - klvs[len++] = PREP_GUC_KLV_CONST(MIGRATION_KLV_DEVICE_REVID_KEY, - MIGRATION_KLV_DEVICE_REVID_LEN); - klvs[len++] = xe->info.revid; + end = klvs + MIGRATION_DESCRIPTOR_DWORDS; - xe_assert(xe, len == MIGRATION_DESCRIPTOR_DWORDS); + klvs = xe_guc_klv_encode_u32(klvs, end - klvs, + MIGRATION_KLV_DEVICE_DEVID_KEY, + xe->info.devid); + klvs = xe_guc_klv_encode_u32(klvs, end - klvs, + MIGRATION_KLV_DEVICE_REVID_KEY, + xe->info.revid); + xe_assert(xe, !IS_ERR(klvs)); + xe_assert(xe, klvs == end); *desc = data; return 0; } +static int descriptor_decoder(void *arg, u16 key, u16 len, const u32 *value) +{ + struct xe_device *xe = arg; + + xe_sriov_dbg_verbose(xe, "found KLV %#x %s\n", key, xe_guc_klv_key_to_string(key)); + + switch (key) { + case MIGRATION_KLV_DEVICE_DEVID_KEY: + if (*value != xe->info.devid) { + xe_sriov_warn(xe, "Aborting migration, devid mismatch %#06x!=%#06x\n", + *value, xe->info.devid); + return -ENODEV; + } + break; + case MIGRATION_KLV_DEVICE_REVID_KEY: + if (*value != xe->info.revid) { + xe_sriov_warn(xe, "Aborting migration, revid mismatch %#06x!=%#06x\n", + *value, xe->info.revid); + return -ENODEV; + } + break; + default: + if (IS_ENABLED(CONFIG_DRM_XE_DEBUG)) { + struct drm_printer p = xe_dbg_printer(xe); + + xe_sriov_dbg(xe, "unexpected KLV %#x in descriptor!\n", key); + xe_guc_klv_print_one(key, len, value, &p); + } + return 0; + } + return 1; +} + /** * xe_sriov_packet_process_descriptor() - Process migration data descriptor packet. * @xe: the &xe_device @@ -406,6 +440,7 @@ int xe_sriov_packet_process_descriptor(struct xe_device *xe, unsigned int vfid, { u32 num_dwords = data->hdr.size / sizeof(u32); u32 *klvs = data->vaddr; + int ret; xe_assert(xe, data->hdr.type == XE_SRIOV_PACKET_TYPE_DESCRIPTOR); @@ -415,47 +450,18 @@ int xe_sriov_packet_process_descriptor(struct xe_device *xe, unsigned int vfid, return -EINVAL; } - while (num_dwords >= GUC_KLV_LEN_MIN) { - u32 key = FIELD_GET(GUC_KLV_0_KEY, klvs[0]); - u32 len = FIELD_GET(GUC_KLV_0_LEN, klvs[0]); + ret = xe_guc_klv_count(klvs, num_dwords); + if (ret < 0) { + xe_sriov_warn(xe, "Aborting migration, corrupted descriptor KLVs (%pe)\n", + ERR_PTR(ret)); + return ret; + } - klvs += GUC_KLV_LEN_MIN; - num_dwords -= GUC_KLV_LEN_MIN; - - if (len > num_dwords) { - xe_sriov_warn(xe, "Aborting migration, truncated KLV %#x, len %u\n", - key, len); - return -EINVAL; - } - - switch (key) { - case MIGRATION_KLV_DEVICE_DEVID_KEY: - if (*klvs != xe->info.devid) { - xe_sriov_warn(xe, - "Aborting migration, devid mismatch %#06x!=%#06x\n", - *klvs, xe->info.devid); - return -ENODEV; - } - break; - case MIGRATION_KLV_DEVICE_REVID_KEY: - if (*klvs != xe->info.revid) { - xe_sriov_warn(xe, - "Aborting migration, revid mismatch %#06x!=%#06x\n", - *klvs, xe->info.revid); - return -ENODEV; - } - break; - default: - xe_sriov_dbg(xe, - "Skipping unknown migration KLV %#x, len=%u\n", - key, len); - print_hex_dump_bytes("desc: ", DUMP_PREFIX_OFFSET, klvs, - min(SZ_64, len * sizeof(u32))); - break; - } - - klvs += len; - num_dwords -= len; + ret = xe_guc_klv_parser(klvs, num_dwords, xe, descriptor_decoder); + if (ret < 0) { + xe_sriov_warn(xe, "Aborting migration, descriptor parsing failed (%pe)\n", + ERR_PTR(ret)); + return ret; } return 0;