Skip to content

Commit 67df4a5

Browse files
committed
drm/xe/pf: Add data structures and handlers for migration rings
Migration data is queued in a per-GT ptr_ring to decouple the worker responsible for handling the data transfer from the .read() and .write() syscalls. Add the data structures and handlers that will be used in future commits. Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com> Link: https://patch.msgid.link/20251112132220.516975-6-michal.winiarski@intel.com Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
1 parent ed46ff0 commit 67df4a5

12 files changed

Lines changed: 762 additions & 13 deletions

drivers/gpu/drm/xe/xe_gt_sriov_pf_control.c

Lines changed: 298 additions & 13 deletions
Large diffs are not rendered by default.

drivers/gpu/drm/xe/xe_gt_sriov_pf_control.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,14 @@ void xe_gt_sriov_pf_control_restart(struct xe_gt *gt);
1616

1717
int xe_gt_sriov_pf_control_pause_vf(struct xe_gt *gt, unsigned int vfid);
1818
int xe_gt_sriov_pf_control_resume_vf(struct xe_gt *gt, unsigned int vfid);
19+
bool xe_gt_sriov_pf_control_check_save_data_done(struct xe_gt *gt, unsigned int vfid);
20+
bool xe_gt_sriov_pf_control_check_save_failed(struct xe_gt *gt, unsigned int vfid);
21+
int xe_gt_sriov_pf_control_process_save_data(struct xe_gt *gt, unsigned int vfid);
1922
int xe_gt_sriov_pf_control_trigger_save_vf(struct xe_gt *gt, unsigned int vfid);
2023
int xe_gt_sriov_pf_control_finish_save_vf(struct xe_gt *gt, unsigned int vfid);
24+
int xe_gt_sriov_pf_control_restore_data_done(struct xe_gt *gt, unsigned int vfid);
25+
bool xe_gt_sriov_pf_control_check_restore_failed(struct xe_gt *gt, unsigned int vfid);
26+
int xe_gt_sriov_pf_control_process_restore_data(struct xe_gt *gt, unsigned int vfid);
2127
int xe_gt_sriov_pf_control_trigger_restore_vf(struct xe_gt *gt, unsigned int vfid);
2228
int xe_gt_sriov_pf_control_finish_restore_vf(struct xe_gt *gt, unsigned int vfid);
2329
int xe_gt_sriov_pf_control_stop_vf(struct xe_gt *gt, unsigned int vfid);

drivers/gpu/drm/xe/xe_gt_sriov_pf_control_types.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,15 @@
3232
* @XE_GT_SRIOV_STATE_PAUSE_FAILED: indicates that a VF pause operation has failed.
3333
* @XE_GT_SRIOV_STATE_PAUSED: indicates that the VF is paused.
3434
* @XE_GT_SRIOV_STATE_SAVE_WIP: indicates that VF save operation is in progress.
35+
* @XE_GT_SRIOV_STATE_SAVE_PROCESS_DATA: indicates that VF migration data is being produced.
36+
* @XE_GT_SRIOV_STATE_SAVE_WAIT_DATA: indicates that PF awaits for space in migration data ring.
37+
* @XE_GT_SRIOV_STATE_SAVE_DATA_DONE: indicates that all migration data was produced by Xe.
3538
* @XE_GT_SRIOV_STATE_SAVE_FAILED: indicates that VF save operation has failed.
3639
* @XE_GT_SRIOV_STATE_SAVED: indicates that VF data is saved.
3740
* @XE_GT_SRIOV_STATE_RESTORE_WIP: indicates that VF restore operation is in progress.
41+
* @XE_GT_SRIOV_STATE_RESTORE_PROCESS_DATA: indicates that VF migration data is being consumed.
42+
* @XE_GT_SRIOV_STATE_RESTORE_WAIT_DATA: indicates that PF awaits for data in migration data ring.
43+
* @XE_GT_SRIOV_STATE_RESTORE_DATA_DONE: indicates that all migration data was produced by the user.
3844
* @XE_GT_SRIOV_STATE_RESTORE_FAILED: indicates that VF restore operation has failed.
3945
* @XE_GT_SRIOV_STATE_RESTORED: indicates that VF data is restored.
4046
* @XE_GT_SRIOV_STATE_RESUME_WIP: indicates the a VF resume operation is in progress.
@@ -70,10 +76,16 @@ enum xe_gt_sriov_control_bits {
7076
XE_GT_SRIOV_STATE_PAUSED,
7177

7278
XE_GT_SRIOV_STATE_SAVE_WIP,
79+
XE_GT_SRIOV_STATE_SAVE_PROCESS_DATA,
80+
XE_GT_SRIOV_STATE_SAVE_WAIT_DATA,
81+
XE_GT_SRIOV_STATE_SAVE_DATA_DONE,
7382
XE_GT_SRIOV_STATE_SAVE_FAILED,
7483
XE_GT_SRIOV_STATE_SAVED,
7584

7685
XE_GT_SRIOV_STATE_RESTORE_WIP,
86+
XE_GT_SRIOV_STATE_RESTORE_PROCESS_DATA,
87+
XE_GT_SRIOV_STATE_RESTORE_WAIT_DATA,
88+
XE_GT_SRIOV_STATE_RESTORE_DATA_DONE,
7789
XE_GT_SRIOV_STATE_RESTORE_FAILED,
7890
XE_GT_SRIOV_STATE_RESTORED,
7991

drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.c

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,27 @@
77

88
#include "abi/guc_actions_sriov_abi.h"
99
#include "xe_bo.h"
10+
#include "xe_gt_sriov_pf_control.h"
1011
#include "xe_gt_sriov_pf_helpers.h"
1112
#include "xe_gt_sriov_pf_migration.h"
1213
#include "xe_gt_sriov_printk.h"
1314
#include "xe_guc.h"
1415
#include "xe_guc_ct.h"
1516
#include "xe_sriov.h"
17+
#include "xe_sriov_packet_types.h"
1618
#include "xe_sriov_pf_migration.h"
1719

20+
#define XE_GT_SRIOV_PF_MIGRATION_RING_SIZE 5
21+
22+
static struct xe_gt_sriov_migration_data *pf_pick_gt_migration(struct xe_gt *gt, unsigned int vfid)
23+
{
24+
xe_gt_assert(gt, IS_SRIOV_PF(gt_to_xe(gt)));
25+
xe_gt_assert(gt, vfid != PFID);
26+
xe_gt_assert(gt, vfid <= xe_sriov_pf_get_totalvfs(gt_to_xe(gt)));
27+
28+
return &gt->sriov.pf.vfs[vfid].migration;
29+
}
30+
1831
/* Return: number of dwords saved/restored/required or a negative error code on failure */
1932
static int guc_action_vf_save_restore(struct xe_guc *guc, u32 vfid, u32 opcode,
2033
u64 addr, u32 ndwords)
@@ -382,6 +395,178 @@ ssize_t xe_gt_sriov_pf_migration_write_guc_state(struct xe_gt *gt, unsigned int
382395
}
383396
#endif /* CONFIG_DEBUG_FS */
384397

398+
/**
399+
* xe_gt_sriov_pf_migration_ring_empty() - Check if a migration ring is empty.
400+
* @gt: the &xe_gt
401+
* @vfid: the VF identifier
402+
*
403+
* Return: true if the ring is empty, otherwise false.
404+
*/
405+
bool xe_gt_sriov_pf_migration_ring_empty(struct xe_gt *gt, unsigned int vfid)
406+
{
407+
return ptr_ring_empty(&pf_pick_gt_migration(gt, vfid)->ring);
408+
}
409+
410+
/**
411+
* xe_gt_sriov_pf_migration_ring_full() - Check if a migration ring is full.
412+
* @gt: the &xe_gt
413+
* @vfid: the VF identifier
414+
*
415+
* Return: true if the ring is full, otherwise false.
416+
*/
417+
bool xe_gt_sriov_pf_migration_ring_full(struct xe_gt *gt, unsigned int vfid)
418+
{
419+
return ptr_ring_full(&pf_pick_gt_migration(gt, vfid)->ring);
420+
}
421+
422+
/**
423+
* xe_gt_sriov_pf_migration_save_produce() - Add VF save data packet to migration ring.
424+
* @gt: the &xe_gt
425+
* @vfid: the VF identifier
426+
* @data: the &xe_sriov_packet
427+
*
428+
* Called by the save migration data producer (PF SR-IOV Control worker) when
429+
* processing migration data.
430+
* Wakes up the save migration data consumer (userspace), that is potentially
431+
* waiting for data when the ring was empty.
432+
*
433+
* Return: 0 on success or a negative error code on failure.
434+
*/
435+
int xe_gt_sriov_pf_migration_save_produce(struct xe_gt *gt, unsigned int vfid,
436+
struct xe_sriov_packet *data)
437+
{
438+
int ret;
439+
440+
ret = ptr_ring_produce(&pf_pick_gt_migration(gt, vfid)->ring, data);
441+
if (ret)
442+
return ret;
443+
444+
wake_up_all(xe_sriov_pf_migration_waitqueue(gt_to_xe(gt), vfid));
445+
446+
return 0;
447+
}
448+
449+
/**
450+
* xe_gt_sriov_pf_migration_restore_consume() - Get VF restore data packet from migration ring.
451+
* @gt: the &xe_gt
452+
* @vfid: the VF identifier
453+
*
454+
* Called by the restore migration data consumer (PF SR-IOV Control worker) when
455+
* processing migration data.
456+
* Wakes up the restore migration data producer (userspace), that is
457+
* potentially waiting to add more data when the ring is full.
458+
*
459+
* Return: Pointer to &xe_sriov_packet on success,
460+
* NULL if ring is empty.
461+
*/
462+
struct xe_sriov_packet *
463+
xe_gt_sriov_pf_migration_restore_consume(struct xe_gt *gt, unsigned int vfid)
464+
{
465+
struct xe_gt_sriov_migration_data *migration = pf_pick_gt_migration(gt, vfid);
466+
struct wait_queue_head *wq = xe_sriov_pf_migration_waitqueue(gt_to_xe(gt), vfid);
467+
struct xe_sriov_packet *data;
468+
469+
data = ptr_ring_consume(&migration->ring);
470+
if (data)
471+
wake_up_all(wq);
472+
473+
return data;
474+
}
475+
476+
static bool pf_restore_data_ready(struct xe_gt *gt, unsigned int vfid)
477+
{
478+
if (xe_gt_sriov_pf_control_check_restore_failed(gt, vfid) ||
479+
!ptr_ring_full(&pf_pick_gt_migration(gt, vfid)->ring))
480+
return true;
481+
482+
return false;
483+
}
484+
485+
/**
486+
* xe_gt_sriov_pf_migration_restore_produce() - Add VF restore data packet to migration ring.
487+
* @gt: the &xe_gt
488+
* @vfid: the VF identifier
489+
* @data: the &xe_sriov_packet
490+
*
491+
* Called by the restore migration data producer (userspace) when processing
492+
* migration data.
493+
* If the ring is full, waits until there is space.
494+
* Queues the restore migration data consumer (PF SR-IOV Control worker), that
495+
* is potentially waiting for data when the ring was empty.
496+
*
497+
* Return: 0 on success or a negative error code on failure.
498+
*/
499+
int xe_gt_sriov_pf_migration_restore_produce(struct xe_gt *gt, unsigned int vfid,
500+
struct xe_sriov_packet *data)
501+
{
502+
int ret;
503+
504+
xe_gt_assert(gt, data->hdr.tile_id == gt->tile->id);
505+
xe_gt_assert(gt, data->hdr.gt_id == gt->info.id);
506+
507+
for (;;) {
508+
if (xe_gt_sriov_pf_control_check_restore_failed(gt, vfid))
509+
return -EIO;
510+
511+
ret = ptr_ring_produce(&pf_pick_gt_migration(gt, vfid)->ring, data);
512+
if (!ret)
513+
break;
514+
515+
ret = wait_event_interruptible(*xe_sriov_pf_migration_waitqueue(gt_to_xe(gt), vfid),
516+
pf_restore_data_ready(gt, vfid));
517+
if (ret)
518+
return ret;
519+
}
520+
521+
return xe_gt_sriov_pf_control_process_restore_data(gt, vfid);
522+
}
523+
524+
/**
525+
* xe_gt_sriov_pf_migration_save_consume() - Get VF save data packet from migration ring.
526+
* @gt: the &xe_gt
527+
* @vfid: the VF identifier
528+
*
529+
* Called by the save migration data consumer (userspace) when
530+
* processing migration data.
531+
* Queues the save migration data producer (PF SR-IOV Control worker), that is
532+
* potentially waiting to add more data when the ring is full.
533+
*
534+
* Return: Pointer to &xe_sriov_packet on success,
535+
* NULL if ring is empty and there's no more data available,
536+
* ERR_PTR(-EAGAIN) if the ring is empty, but data is still produced.
537+
*/
538+
struct xe_sriov_packet *
539+
xe_gt_sriov_pf_migration_save_consume(struct xe_gt *gt, unsigned int vfid)
540+
{
541+
struct xe_gt_sriov_migration_data *migration = pf_pick_gt_migration(gt, vfid);
542+
struct xe_sriov_packet *data;
543+
int ret;
544+
545+
data = ptr_ring_consume(&migration->ring);
546+
if (data) {
547+
ret = xe_gt_sriov_pf_control_process_save_data(gt, vfid);
548+
if (ret)
549+
return ERR_PTR(ret);
550+
551+
return data;
552+
}
553+
554+
if (xe_gt_sriov_pf_control_check_save_data_done(gt, vfid))
555+
return NULL;
556+
557+
if (xe_gt_sriov_pf_control_check_save_failed(gt, vfid))
558+
return ERR_PTR(-EIO);
559+
560+
return ERR_PTR(-EAGAIN);
561+
}
562+
563+
static void action_ring_cleanup(void *arg)
564+
{
565+
struct ptr_ring *r = arg;
566+
567+
ptr_ring_cleanup(r, NULL);
568+
}
569+
385570
/**
386571
* xe_gt_sriov_pf_migration_init() - Initialize support for VF migration.
387572
* @gt: the &xe_gt
@@ -393,6 +578,7 @@ ssize_t xe_gt_sriov_pf_migration_write_guc_state(struct xe_gt *gt, unsigned int
393578
int xe_gt_sriov_pf_migration_init(struct xe_gt *gt)
394579
{
395580
struct xe_device *xe = gt_to_xe(gt);
581+
unsigned int n, totalvfs;
396582
int err;
397583

398584
xe_gt_assert(gt, IS_SRIOV_PF(xe));
@@ -404,5 +590,19 @@ int xe_gt_sriov_pf_migration_init(struct xe_gt *gt)
404590
if (err)
405591
return err;
406592

593+
totalvfs = xe_sriov_pf_get_totalvfs(xe);
594+
for (n = 1; n <= totalvfs; n++) {
595+
struct xe_gt_sriov_migration_data *migration = pf_pick_gt_migration(gt, n);
596+
597+
err = ptr_ring_init(&migration->ring,
598+
XE_GT_SRIOV_PF_MIGRATION_RING_SIZE, GFP_KERNEL);
599+
if (err)
600+
return err;
601+
602+
err = devm_add_action_or_reset(xe->drm.dev, action_ring_cleanup, &migration->ring);
603+
if (err)
604+
return err;
605+
}
606+
407607
return 0;
408608
}

drivers/gpu/drm/xe/xe_gt_sriov_pf_migration.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,25 @@
99
#include <linux/types.h>
1010

1111
struct xe_gt;
12+
struct xe_sriov_packet;
1213

1314
int xe_gt_sriov_pf_migration_init(struct xe_gt *gt);
1415
int xe_gt_sriov_pf_migration_save_guc_state(struct xe_gt *gt, unsigned int vfid);
1516
int xe_gt_sriov_pf_migration_restore_guc_state(struct xe_gt *gt, unsigned int vfid);
1617

18+
bool xe_gt_sriov_pf_migration_ring_empty(struct xe_gt *gt, unsigned int vfid);
19+
bool xe_gt_sriov_pf_migration_ring_full(struct xe_gt *gt, unsigned int vfid);
20+
21+
int xe_gt_sriov_pf_migration_save_produce(struct xe_gt *gt, unsigned int vfid,
22+
struct xe_sriov_packet *data);
23+
struct xe_sriov_packet *
24+
xe_gt_sriov_pf_migration_restore_consume(struct xe_gt *gt, unsigned int vfid);
25+
26+
int xe_gt_sriov_pf_migration_restore_produce(struct xe_gt *gt, unsigned int vfid,
27+
struct xe_sriov_packet *data);
28+
struct xe_sriov_packet *
29+
xe_gt_sriov_pf_migration_save_consume(struct xe_gt *gt, unsigned int vfid);
30+
1731
#ifdef CONFIG_DEBUG_FS
1832
ssize_t xe_gt_sriov_pf_migration_read_guc_state(struct xe_gt *gt, unsigned int vfid,
1933
char __user *buf, size_t count, loff_t *pos);

drivers/gpu/drm/xe/xe_gt_sriov_pf_migration_types.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define _XE_GT_SRIOV_PF_MIGRATION_TYPES_H_
88

99
#include <linux/mutex.h>
10+
#include <linux/ptr_ring.h>
1011
#include <linux/types.h>
1112

1213
/**
@@ -24,6 +25,16 @@ struct xe_gt_sriov_state_snapshot {
2425
} guc;
2526
};
2627

28+
/**
29+
* struct xe_gt_sriov_migration_data - GT-level per-VF migration data.
30+
*
31+
* Used by the PF driver to maintain per-VF migration data.
32+
*/
33+
struct xe_gt_sriov_migration_data {
34+
/** @ring: queue containing VF save / restore migration data */
35+
struct ptr_ring ring;
36+
};
37+
2738
/**
2839
* struct xe_gt_sriov_pf_migration - GT-level data.
2940
*

drivers/gpu/drm/xe/xe_gt_sriov_pf_types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ struct xe_gt_sriov_metadata {
3333

3434
/** @snapshot: snapshot of the VF state data */
3535
struct xe_gt_sriov_state_snapshot snapshot;
36+
37+
/** @migration: per-VF migration data. */
38+
struct xe_gt_sriov_migration_data migration;
3639
};
3740

3841
/**

0 commit comments

Comments
 (0)