Skip to content

Commit 70e2fa9

Browse files
committed
drm/xe/pf: Add minimalistic migration descriptor
The descriptor reuses the KLV format used by GuC and contains metadata that can be used to quickly fail migration when source is incompatible with destination. Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com> Link: https://patch.msgid.link/20251112132220.516975-9-michal.winiarski@intel.com Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
1 parent 1ed3039 commit 70e2fa9

3 files changed

Lines changed: 99 additions & 1 deletion

File tree

drivers/gpu/drm/xe/xe_sriov_packet.c

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "xe_bo.h"
77
#include "xe_device.h"
8+
#include "xe_guc_klv_helpers.h"
89
#include "xe_printk.h"
910
#include "xe_sriov_packet.h"
1011
#include "xe_sriov_packet_types.h"
@@ -350,11 +351,19 @@ ssize_t xe_sriov_packet_write_single(struct xe_device *xe, unsigned int vfid,
350351
return copied;
351352
}
352353

353-
#define MIGRATION_DESCRIPTOR_DWORDS 0
354+
#define MIGRATION_KLV_DEVICE_DEVID_KEY 0xf001u
355+
#define MIGRATION_KLV_DEVICE_DEVID_LEN 1u
356+
#define MIGRATION_KLV_DEVICE_REVID_KEY 0xf002u
357+
#define MIGRATION_KLV_DEVICE_REVID_LEN 1u
358+
359+
#define MIGRATION_DESCRIPTOR_DWORDS (GUC_KLV_LEN_MIN + MIGRATION_KLV_DEVICE_DEVID_LEN + \
360+
GUC_KLV_LEN_MIN + MIGRATION_KLV_DEVICE_REVID_LEN)
354361
static size_t pf_descriptor_init(struct xe_device *xe, unsigned int vfid)
355362
{
356363
struct xe_sriov_packet **desc = pf_pick_descriptor(xe, vfid);
357364
struct xe_sriov_packet *data;
365+
unsigned int len = 0;
366+
u32 *klvs;
358367
int ret;
359368

360369
data = xe_sriov_packet_alloc(xe);
@@ -368,11 +377,92 @@ static size_t pf_descriptor_init(struct xe_device *xe, unsigned int vfid)
368377
return ret;
369378
}
370379

380+
klvs = data->vaddr;
381+
klvs[len++] = PREP_GUC_KLV_CONST(MIGRATION_KLV_DEVICE_DEVID_KEY,
382+
MIGRATION_KLV_DEVICE_DEVID_LEN);
383+
klvs[len++] = xe->info.devid;
384+
klvs[len++] = PREP_GUC_KLV_CONST(MIGRATION_KLV_DEVICE_REVID_KEY,
385+
MIGRATION_KLV_DEVICE_REVID_LEN);
386+
klvs[len++] = xe->info.revid;
387+
388+
xe_assert(xe, len == MIGRATION_DESCRIPTOR_DWORDS);
389+
371390
*desc = data;
372391

373392
return 0;
374393
}
375394

395+
/**
396+
* xe_sriov_packet_process_descriptor() - Process migration data descriptor packet.
397+
* @xe: the &xe_device
398+
* @vfid: the VF identifier
399+
* @data: the &xe_sriov_packet containing the descriptor
400+
*
401+
* The descriptor uses the same KLV format as GuC, and contains metadata used for
402+
* checking migration data compatibility.
403+
*
404+
* Return: 0 on success, -errno on failure.
405+
*/
406+
int xe_sriov_packet_process_descriptor(struct xe_device *xe, unsigned int vfid,
407+
struct xe_sriov_packet *data)
408+
{
409+
u32 num_dwords = data->hdr.size / sizeof(u32);
410+
u32 *klvs = data->vaddr;
411+
412+
xe_assert(xe, data->hdr.type == XE_SRIOV_PACKET_TYPE_DESCRIPTOR);
413+
414+
if (data->hdr.size % sizeof(u32)) {
415+
xe_sriov_warn(xe, "Aborting migration, descriptor not in KLV format (size=%llu)\n",
416+
data->hdr.size);
417+
return -EINVAL;
418+
}
419+
420+
while (num_dwords >= GUC_KLV_LEN_MIN) {
421+
u32 key = FIELD_GET(GUC_KLV_0_KEY, klvs[0]);
422+
u32 len = FIELD_GET(GUC_KLV_0_LEN, klvs[0]);
423+
424+
klvs += GUC_KLV_LEN_MIN;
425+
num_dwords -= GUC_KLV_LEN_MIN;
426+
427+
if (len > num_dwords) {
428+
xe_sriov_warn(xe, "Aborting migration, truncated KLV %#x, len %u\n",
429+
key, len);
430+
return -EINVAL;
431+
}
432+
433+
switch (key) {
434+
case MIGRATION_KLV_DEVICE_DEVID_KEY:
435+
if (*klvs != xe->info.devid) {
436+
xe_sriov_warn(xe,
437+
"Aborting migration, devid mismatch %#06x!=%#06x\n",
438+
*klvs, xe->info.devid);
439+
return -ENODEV;
440+
}
441+
break;
442+
case MIGRATION_KLV_DEVICE_REVID_KEY:
443+
if (*klvs != xe->info.revid) {
444+
xe_sriov_warn(xe,
445+
"Aborting migration, revid mismatch %#06x!=%#06x\n",
446+
*klvs, xe->info.revid);
447+
return -ENODEV;
448+
}
449+
break;
450+
default:
451+
xe_sriov_dbg(xe,
452+
"Skipping unknown migration KLV %#x, len=%u\n",
453+
key, len);
454+
print_hex_dump_bytes("desc: ", DUMP_PREFIX_OFFSET, klvs,
455+
min(SZ_64, len * sizeof(u32)));
456+
break;
457+
}
458+
459+
klvs += len;
460+
num_dwords -= len;
461+
}
462+
463+
return 0;
464+
}
465+
376466
static void pf_pending_init(struct xe_device *xe, unsigned int vfid)
377467
{
378468
struct xe_sriov_packet **data = pf_pick_pending(xe, vfid);

drivers/gpu/drm/xe/xe_sriov_packet.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,7 @@ ssize_t xe_sriov_packet_read_single(struct xe_device *xe, unsigned int vfid,
2424
ssize_t xe_sriov_packet_write_single(struct xe_device *xe, unsigned int vfid,
2525
const char __user *buf, size_t len);
2626
int xe_sriov_packet_save_init(struct xe_device *xe, unsigned int vfid);
27+
int xe_sriov_packet_process_descriptor(struct xe_device *xe, unsigned int vfid,
28+
struct xe_sriov_packet *data);
2729

2830
#endif

drivers/gpu/drm/xe/xe_sriov_pf_migration.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,15 @@ xe_sriov_pf_migration_save_consume(struct xe_device *xe, unsigned int vfid)
177177
static int pf_handle_descriptor(struct xe_device *xe, unsigned int vfid,
178178
struct xe_sriov_packet *data)
179179
{
180+
int ret;
181+
180182
if (data->hdr.tile_id != 0 || data->hdr.gt_id != 0)
181183
return -EINVAL;
182184

185+
ret = xe_sriov_packet_process_descriptor(xe, vfid, data);
186+
if (ret)
187+
return ret;
188+
183189
xe_sriov_packet_free(data);
184190

185191
return 0;

0 commit comments

Comments
 (0)