Skip to content

Commit 1ed3039

Browse files
committed
drm/xe/pf: Add support for encap/decap of bitstream to/from packet
Add debugfs handlers for migration state and handle bitstream .read()/.write() to convert from bitstream to/from migration data packets. As descriptor/trailer are handled at this layer - add handling for both save and restore side. Reviewed-by: Michal Wajdeczko <michal.wajdeczko@intel.com> Link: https://patch.msgid.link/20251112132220.516975-8-michal.winiarski@intel.com Signed-off-by: Michał Winiarski <michal.winiarski@intel.com>
1 parent 644a699 commit 1ed3039

7 files changed

Lines changed: 474 additions & 0 deletions

drivers/gpu/drm/xe/xe_sriov_packet.c

Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,67 @@
88
#include "xe_printk.h"
99
#include "xe_sriov_packet.h"
1010
#include "xe_sriov_packet_types.h"
11+
#include "xe_sriov_pf_helpers.h"
12+
#include "xe_sriov_pf_migration.h"
13+
#include "xe_sriov_printk.h"
14+
15+
static struct mutex *pf_migration_mutex(struct xe_device *xe, unsigned int vfid)
16+
{
17+
xe_assert(xe, IS_SRIOV_PF(xe));
18+
xe_assert(xe, vfid <= xe_sriov_pf_get_totalvfs(xe));
19+
20+
return &xe->sriov.pf.vfs[vfid].migration.lock;
21+
}
22+
23+
static struct xe_sriov_packet **pf_pick_pending(struct xe_device *xe, unsigned int vfid)
24+
{
25+
xe_assert(xe, IS_SRIOV_PF(xe));
26+
xe_assert(xe, vfid <= xe_sriov_pf_get_totalvfs(xe));
27+
lockdep_assert_held(pf_migration_mutex(xe, vfid));
28+
29+
return &xe->sriov.pf.vfs[vfid].migration.pending;
30+
}
31+
32+
static struct xe_sriov_packet **
33+
pf_pick_descriptor(struct xe_device *xe, unsigned int vfid)
34+
{
35+
xe_assert(xe, IS_SRIOV_PF(xe));
36+
xe_assert(xe, vfid <= xe_sriov_pf_get_totalvfs(xe));
37+
lockdep_assert_held(pf_migration_mutex(xe, vfid));
38+
39+
return &xe->sriov.pf.vfs[vfid].migration.descriptor;
40+
}
41+
42+
static struct xe_sriov_packet **pf_pick_trailer(struct xe_device *xe, unsigned int vfid)
43+
{
44+
xe_assert(xe, IS_SRIOV_PF(xe));
45+
xe_assert(xe, vfid <= xe_sriov_pf_get_totalvfs(xe));
46+
lockdep_assert_held(pf_migration_mutex(xe, vfid));
47+
48+
return &xe->sriov.pf.vfs[vfid].migration.trailer;
49+
}
50+
51+
static struct xe_sriov_packet **pf_pick_read_packet(struct xe_device *xe,
52+
unsigned int vfid)
53+
{
54+
struct xe_sriov_packet **data;
55+
56+
data = pf_pick_descriptor(xe, vfid);
57+
if (*data)
58+
return data;
59+
60+
data = pf_pick_pending(xe, vfid);
61+
if (!*data)
62+
*data = xe_sriov_pf_migration_save_consume(xe, vfid);
63+
if (*data)
64+
return data;
65+
66+
data = pf_pick_trailer(xe, vfid);
67+
if (*data)
68+
return data;
69+
70+
return NULL;
71+
}
1172

1273
static bool pkt_needs_bo(struct xe_sriov_packet *data)
1374
{
@@ -135,3 +196,235 @@ int xe_sriov_packet_init_from_hdr(struct xe_sriov_packet *data)
135196

136197
return pkt_init(data);
137198
}
199+
200+
static ssize_t pkt_hdr_read(struct xe_sriov_packet *data,
201+
char __user *buf, size_t len)
202+
{
203+
loff_t offset = sizeof(data->hdr) - data->hdr_remaining;
204+
205+
if (!data->hdr_remaining)
206+
return -EINVAL;
207+
208+
if (len > data->hdr_remaining)
209+
len = data->hdr_remaining;
210+
211+
if (copy_to_user(buf, (void *)&data->hdr + offset, len))
212+
return -EFAULT;
213+
214+
data->hdr_remaining -= len;
215+
216+
return len;
217+
}
218+
219+
static ssize_t pkt_data_read(struct xe_sriov_packet *data,
220+
char __user *buf, size_t len)
221+
{
222+
if (len > data->remaining)
223+
len = data->remaining;
224+
225+
if (copy_to_user(buf, data->vaddr + (data->hdr.size - data->remaining), len))
226+
return -EFAULT;
227+
228+
data->remaining -= len;
229+
230+
return len;
231+
}
232+
233+
static ssize_t pkt_read_single(struct xe_sriov_packet **data,
234+
unsigned int vfid, char __user *buf, size_t len)
235+
{
236+
ssize_t copied = 0;
237+
238+
if ((*data)->hdr_remaining)
239+
copied = pkt_hdr_read(*data, buf, len);
240+
else
241+
copied = pkt_data_read(*data, buf, len);
242+
243+
if ((*data)->remaining == 0 && (*data)->hdr_remaining == 0) {
244+
xe_sriov_packet_free(*data);
245+
*data = NULL;
246+
}
247+
248+
return copied;
249+
}
250+
251+
/**
252+
* xe_sriov_packet_read_single() - Read migration data from a single packet.
253+
* @xe: the &xe_device
254+
* @vfid: the VF identifier
255+
* @buf: start address of userspace buffer
256+
* @len: requested read size from userspace
257+
*
258+
* Return: number of bytes that has been successfully read,
259+
* 0 if no more migration data is available,
260+
* -errno on failure.
261+
*/
262+
ssize_t xe_sriov_packet_read_single(struct xe_device *xe, unsigned int vfid,
263+
char __user *buf, size_t len)
264+
{
265+
struct xe_sriov_packet **data = pf_pick_read_packet(xe, vfid);
266+
267+
if (!data)
268+
return -ENODATA;
269+
if (IS_ERR(*data))
270+
return PTR_ERR(*data);
271+
272+
return pkt_read_single(data, vfid, buf, len);
273+
}
274+
275+
static ssize_t pkt_hdr_write(struct xe_sriov_packet *data,
276+
const char __user *buf, size_t len)
277+
{
278+
loff_t offset = sizeof(data->hdr) - data->hdr_remaining;
279+
int ret;
280+
281+
if (len > data->hdr_remaining)
282+
len = data->hdr_remaining;
283+
284+
if (copy_from_user((void *)&data->hdr + offset, buf, len))
285+
return -EFAULT;
286+
287+
data->hdr_remaining -= len;
288+
289+
if (!data->hdr_remaining) {
290+
ret = xe_sriov_packet_init_from_hdr(data);
291+
if (ret)
292+
return ret;
293+
}
294+
295+
return len;
296+
}
297+
298+
static ssize_t pkt_data_write(struct xe_sriov_packet *data,
299+
const char __user *buf, size_t len)
300+
{
301+
if (len > data->remaining)
302+
len = data->remaining;
303+
304+
if (copy_from_user(data->vaddr + (data->hdr.size - data->remaining), buf, len))
305+
return -EFAULT;
306+
307+
data->remaining -= len;
308+
309+
return len;
310+
}
311+
312+
/**
313+
* xe_sriov_packet_write_single() - Write migration data to a single packet.
314+
* @xe: the &xe_device
315+
* @vfid: the VF identifier
316+
* @buf: start address of userspace buffer
317+
* @len: requested write size from userspace
318+
*
319+
* Return: number of bytes that has been successfully written,
320+
* -errno on failure.
321+
*/
322+
ssize_t xe_sriov_packet_write_single(struct xe_device *xe, unsigned int vfid,
323+
const char __user *buf, size_t len)
324+
{
325+
struct xe_sriov_packet **data = pf_pick_pending(xe, vfid);
326+
int ret;
327+
ssize_t copied;
328+
329+
if (IS_ERR_OR_NULL(*data)) {
330+
*data = xe_sriov_packet_alloc(xe);
331+
if (!*data)
332+
return -ENOMEM;
333+
}
334+
335+
if ((*data)->hdr_remaining)
336+
copied = pkt_hdr_write(*data, buf, len);
337+
else
338+
copied = pkt_data_write(*data, buf, len);
339+
340+
if ((*data)->hdr_remaining == 0 && (*data)->remaining == 0) {
341+
ret = xe_sriov_pf_migration_restore_produce(xe, vfid, *data);
342+
if (ret) {
343+
xe_sriov_packet_free(*data);
344+
return ret;
345+
}
346+
347+
*data = NULL;
348+
}
349+
350+
return copied;
351+
}
352+
353+
#define MIGRATION_DESCRIPTOR_DWORDS 0
354+
static size_t pf_descriptor_init(struct xe_device *xe, unsigned int vfid)
355+
{
356+
struct xe_sriov_packet **desc = pf_pick_descriptor(xe, vfid);
357+
struct xe_sriov_packet *data;
358+
int ret;
359+
360+
data = xe_sriov_packet_alloc(xe);
361+
if (!data)
362+
return -ENOMEM;
363+
364+
ret = xe_sriov_packet_init(data, 0, 0, XE_SRIOV_PACKET_TYPE_DESCRIPTOR,
365+
0, MIGRATION_DESCRIPTOR_DWORDS * sizeof(u32));
366+
if (ret) {
367+
xe_sriov_packet_free(data);
368+
return ret;
369+
}
370+
371+
*desc = data;
372+
373+
return 0;
374+
}
375+
376+
static void pf_pending_init(struct xe_device *xe, unsigned int vfid)
377+
{
378+
struct xe_sriov_packet **data = pf_pick_pending(xe, vfid);
379+
380+
*data = NULL;
381+
}
382+
383+
#define MIGRATION_TRAILER_SIZE 0
384+
static int pf_trailer_init(struct xe_device *xe, unsigned int vfid)
385+
{
386+
struct xe_sriov_packet **trailer = pf_pick_trailer(xe, vfid);
387+
struct xe_sriov_packet *data;
388+
int ret;
389+
390+
data = xe_sriov_packet_alloc(xe);
391+
if (!data)
392+
return -ENOMEM;
393+
394+
ret = xe_sriov_packet_init(data, 0, 0, XE_SRIOV_PACKET_TYPE_TRAILER,
395+
0, MIGRATION_TRAILER_SIZE);
396+
if (ret) {
397+
xe_sriov_packet_free(data);
398+
return ret;
399+
}
400+
401+
*trailer = data;
402+
403+
return 0;
404+
}
405+
406+
/**
407+
* xe_sriov_packet_save_init() - Initialize the pending save migration packets.
408+
* @xe: the &xe_device
409+
* @vfid: the VF identifier
410+
*
411+
* Return: 0 on success, -errno on failure.
412+
*/
413+
int xe_sriov_packet_save_init(struct xe_device *xe, unsigned int vfid)
414+
{
415+
int ret;
416+
417+
scoped_cond_guard(mutex_intr, return -EINTR, pf_migration_mutex(xe, vfid)) {
418+
ret = pf_descriptor_init(xe, vfid);
419+
if (ret)
420+
return ret;
421+
422+
ret = pf_trailer_init(xe, vfid);
423+
if (ret)
424+
return ret;
425+
426+
pf_pending_init(xe, vfid);
427+
}
428+
429+
return 0;
430+
}

drivers/gpu/drm/xe/xe_sriov_packet.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,10 @@ int xe_sriov_packet_init(struct xe_sriov_packet *data, u8 tile_id, u8 gt_id,
1919
enum xe_sriov_packet_type, loff_t offset, size_t size);
2020
int xe_sriov_packet_init_from_hdr(struct xe_sriov_packet *data);
2121

22+
ssize_t xe_sriov_packet_read_single(struct xe_device *xe, unsigned int vfid,
23+
char __user *buf, size_t len);
24+
ssize_t xe_sriov_packet_write_single(struct xe_device *xe, unsigned int vfid,
25+
const char __user *buf, size_t len);
26+
int xe_sriov_packet_save_init(struct xe_device *xe, unsigned int vfid);
27+
2228
#endif

drivers/gpu/drm/xe/xe_sriov_pf_control.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "xe_device.h"
77
#include "xe_gt_sriov_pf_control.h"
8+
#include "xe_sriov_packet.h"
89
#include "xe_sriov_pf_control.h"
910
#include "xe_sriov_printk.h"
1011

@@ -165,6 +166,10 @@ int xe_sriov_pf_control_trigger_save_vf(struct xe_device *xe, unsigned int vfid)
165166
unsigned int id;
166167
int ret;
167168

169+
ret = xe_sriov_packet_save_init(xe, vfid);
170+
if (ret)
171+
return ret;
172+
168173
for_each_gt(gt, xe, id) {
169174
ret = xe_gt_sriov_pf_control_trigger_save_vf(gt, vfid);
170175
if (ret)

drivers/gpu/drm/xe/xe_sriov_pf_debugfs.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "xe_sriov_pf_control.h"
1414
#include "xe_sriov_pf_debugfs.h"
1515
#include "xe_sriov_pf_helpers.h"
16+
#include "xe_sriov_pf_migration.h"
1617
#include "xe_sriov_pf_provision.h"
1718
#include "xe_sriov_pf_service.h"
1819
#include "xe_sriov_printk.h"
@@ -162,6 +163,7 @@ static void pf_populate_pf(struct xe_device *xe, struct dentry *pfdent)
162163
* /sys/kernel/debug/dri/BDF/
163164
* ├── sriov
164165
* │ ├── vf1
166+
* │ │ ├── migration_data
165167
* │ │ ├── pause
166168
* │ │ ├── reset
167169
* │ │ ├── resume
@@ -250,6 +252,38 @@ DEFINE_VF_CONTROL_ATTRIBUTE(reset_vf);
250252
DEFINE_VF_CONTROL_ATTRIBUTE_RW(save_vf);
251253
DEFINE_VF_CONTROL_ATTRIBUTE_RW(restore_vf);
252254

255+
static ssize_t data_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
256+
{
257+
struct dentry *dent = file_dentry(file)->d_parent;
258+
struct xe_device *xe = extract_xe(dent);
259+
unsigned int vfid = extract_vfid(dent);
260+
261+
if (*pos)
262+
return -ESPIPE;
263+
264+
return xe_sriov_pf_migration_write(xe, vfid, buf, count);
265+
}
266+
267+
static ssize_t data_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
268+
{
269+
struct dentry *dent = file_dentry(file)->d_parent;
270+
struct xe_device *xe = extract_xe(dent);
271+
unsigned int vfid = extract_vfid(dent);
272+
273+
if (*ppos)
274+
return -ESPIPE;
275+
276+
return xe_sriov_pf_migration_read(xe, vfid, buf, count);
277+
}
278+
279+
static const struct file_operations data_vf_fops = {
280+
.owner = THIS_MODULE,
281+
.open = simple_open,
282+
.write = data_write,
283+
.read = data_read,
284+
.llseek = default_llseek,
285+
};
286+
253287
static void pf_populate_vf(struct xe_device *xe, struct dentry *vfdent)
254288
{
255289
debugfs_create_file("pause", 0200, vfdent, xe, &pause_vf_fops);
@@ -258,6 +292,7 @@ static void pf_populate_vf(struct xe_device *xe, struct dentry *vfdent)
258292
debugfs_create_file("reset", 0200, vfdent, xe, &reset_vf_fops);
259293
debugfs_create_file("save", 0600, vfdent, xe, &save_vf_fops);
260294
debugfs_create_file("restore", 0600, vfdent, xe, &restore_vf_fops);
295+
debugfs_create_file("migration_data", 0600, vfdent, xe, &data_vf_fops);
261296
}
262297

263298
static void pf_populate_with_tiles(struct xe_device *xe, struct dentry *dent, unsigned int vfid)

0 commit comments

Comments
 (0)