1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2023 Intel Corporation
*
* Authors:
* Matthew Brost <matthew.brost@intel.com>
*/
#ifndef XE_SPIN_H
#define XE_SPIN_H
#include <stdint.h>
#include <stdbool.h>
#include "xe_query.h"
#include "lib/igt_dummyload.h"
#include "lib/intel_blt.h"
/* Wrapper to integrate with igt_dummyload, aka igt_spin */
igt_spin_t *xe_spin_create(int fd, const struct igt_spin_factory *opt);
void xe_spin_free(int fd, struct igt_spin *spin);
/*
* xe_spin: abstract a bo mapped in the GPU that when exec'ed will spin the
* engine in which it's exec'ed
*/
/**
* struct xe_spin_mem_copy
* @src: source BLT object
* @dst: destination BLT object
* @src_offset: source offset
* @dst_offset: destination offset
*
* Used to perform memory copy with the spinner.
*/
struct xe_spin_mem_copy {
int fd;
struct blt_mem_object *src;
struct blt_mem_object *dst;
uint64_t src_offset;
uint64_t dst_offset;
};
/**
* struct xe_spin_opts
* @addr: offset of spinner within vm
* @preempt: allow spinner to be preempted or not
* @multi_queue_switch: Add a SEMAPHORE_WAIT multi-queue switch point
* and have the queue switch happen after command is parsed.
* @multi_queue_switch_on_wait: Add a SEMAPHORE_WAIT multi-queue switch point
* and have the queue switch only happen if waiting on the semaphore.
* @ctx_ticks: number of ticks after which spinner is stopped, applied if > 0
* @use_queue_timestamp: Use QUEUE_TIMESTAMP register instead of CTX_TIMESTAMP
* @mem_copy: container of objects used for memory copy (optional)
*
* Used to initialize struct xe_spin spinner behavior.
*/
struct xe_spin_opts {
uint64_t addr;
bool preempt;
bool multi_queue_switch;
bool multi_queue_switch_on_wait;
uint32_t ctx_ticks;
bool write_timestamp;
bool use_queue_timestamp;
struct xe_spin_mem_copy *mem_copy;
};
/* Mapped GPU object */
struct xe_spin {
uint32_t batch[128];
uint64_t pad;
uint32_t start;
uint32_t end;
uint32_t wait_cond;
uint32_t ticks_delta;
uint64_t exec_sync;
uint32_t timestamp;
};
uint32_t xe_spin_nsec_to_ticks(int fd, int gt_id, uint64_t nsec);
void xe_spin_init(struct xe_spin *spin, struct xe_spin_opts *opts);
#define xe_spin_init_opts(fd, ...) \
xe_spin_init(fd, &((struct xe_spin_opts){__VA_ARGS__}))
void xe_spin_reset(int fd, igt_spin_t *spin);
bool xe_spin_started(struct xe_spin *spin);
void xe_spin_wait_started(struct xe_spin *spin);
void xe_spin_end(struct xe_spin *spin);
void xe_spin_sync_wait(int fd, struct igt_spin *spin);
void xe_spin_preempt_wait(struct xe_spin *spin);
void xe_spin_preempt_nowait(struct xe_spin *spin);
/*
* xe_cork: higher level API that simplifies exec'ing an xe_spin by taking care
* of vm creation, exec call, etc.
*/
struct xe_cork_opts {
uint64_t ahnd;
bool debug;
};
struct xe_cork {
struct xe_spin *spin;
int fd;
uint32_t vm;
uint32_t bo;
uint32_t exec_queue;
uint32_t syncobj;
uint64_t addr[XE_MAX_ENGINE_INSTANCE];
struct drm_xe_sync sync[2];
struct drm_xe_exec exec;
size_t bo_size;
struct xe_spin_opts spin_opts;
struct xe_cork_opts cork_opts;
bool ended;
uint16_t class;
uint16_t width;
uint16_t num_placements;
};
struct xe_cork *xe_cork_create(int fd, struct drm_xe_engine_class_instance *hwe,
uint32_t vm, uint16_t width, uint16_t num_placements,
struct xe_cork_opts *opts);
#define xe_cork_create_opts(fd, hwe, vm, width, num_placements, ...) \
xe_cork_create(fd, hwe, vm, width, num_placements, \
&((struct xe_cork_opts){__VA_ARGS__}))
void xe_cork_destroy(int fd, struct xe_cork *ctx);
void xe_cork_sync_start(int fd, struct xe_cork *ctx);
void xe_cork_sync_end(int fd, struct xe_cork *ctx);
#endif /* XE_SPIN_H */
|