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)
354361static 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+
376466static void pf_pending_init (struct xe_device * xe , unsigned int vfid )
377467{
378468 struct xe_sriov_packet * * data = pf_pick_pending (xe , vfid );
0 commit comments