1 | /* SPDX-License-Identifier: MIT */ |
2 | /* |
3 | * Copyright © 2016-2019 Intel Corporation |
4 | */ |
5 | |
6 | #ifndef _INTEL_GUC_CT_H_ |
7 | #define _INTEL_GUC_CT_H_ |
8 | |
9 | #include <linux/interrupt.h> |
10 | #include <linux/spinlock.h> |
11 | #include <linux/stackdepot.h> |
12 | #include <linux/workqueue.h> |
13 | #include <linux/ktime.h> |
14 | #include <linux/wait.h> |
15 | |
16 | #include "intel_guc_fwif.h" |
17 | |
18 | struct i915_vma; |
19 | struct intel_guc; |
20 | struct drm_printer; |
21 | |
22 | /** |
23 | * DOC: Command Transport (CT). |
24 | * |
25 | * Buffer based command transport is a replacement for MMIO based mechanism. |
26 | * It can be used to perform both host-2-guc and guc-to-host communication. |
27 | */ |
28 | |
29 | /** Represents single command transport buffer. |
30 | * |
31 | * A single command transport buffer consists of two parts, the header |
32 | * record (command transport buffer descriptor) and the actual buffer which |
33 | * holds the commands. |
34 | * |
35 | * @lock: protects access to the commands buffer and buffer descriptor |
36 | * @desc: pointer to the buffer descriptor |
37 | * @cmds: pointer to the commands buffer |
38 | * @size: size of the commands buffer in dwords |
39 | * @resv_space: reserved space in buffer in dwords |
40 | * @head: local shadow copy of head in dwords |
41 | * @tail: local shadow copy of tail in dwords |
42 | * @space: local shadow copy of space in dwords |
43 | * @broken: flag to indicate if descriptor data is broken |
44 | */ |
45 | struct intel_guc_ct_buffer { |
46 | spinlock_t lock; |
47 | struct guc_ct_buffer_desc *desc; |
48 | u32 *cmds; |
49 | u32 size; |
50 | u32 resv_space; |
51 | u32 tail; |
52 | u32 head; |
53 | atomic_t space; |
54 | bool broken; |
55 | }; |
56 | |
57 | /** Top-level structure for Command Transport related data |
58 | * |
59 | * Includes a pair of CT buffers for bi-directional communication and tracking |
60 | * for the H2G and G2H requests sent and received through the buffers. |
61 | */ |
62 | struct intel_guc_ct { |
63 | struct i915_vma *vma; |
64 | bool enabled; |
65 | |
66 | /* buffers for sending and receiving commands */ |
67 | struct { |
68 | struct intel_guc_ct_buffer send; |
69 | struct intel_guc_ct_buffer recv; |
70 | } ctbs; |
71 | |
72 | struct tasklet_struct receive_tasklet; |
73 | |
74 | /** @wq: wait queue for g2h chanenl */ |
75 | wait_queue_head_t wq; |
76 | |
77 | struct { |
78 | u16 last_fence; /* last fence used to send request */ |
79 | |
80 | spinlock_t lock; /* protects pending requests list */ |
81 | struct list_head pending; /* requests waiting for response */ |
82 | |
83 | struct list_head incoming; /* incoming requests */ |
84 | struct work_struct worker; /* handler for incoming requests */ |
85 | |
86 | #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM) |
87 | struct { |
88 | u16 fence; |
89 | u16 action; |
90 | #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC) |
91 | depot_stack_handle_t stack; |
92 | #endif |
93 | } lost_and_found[SZ_16]; |
94 | #endif |
95 | } requests; |
96 | |
97 | /** @stall_time: time of first time a CTB submission is stalled */ |
98 | ktime_t stall_time; |
99 | |
100 | #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC) |
101 | int dead_ct_reason; |
102 | bool dead_ct_reported; |
103 | struct work_struct dead_ct_worker; |
104 | #endif |
105 | }; |
106 | |
107 | long intel_guc_ct_max_queue_time_jiffies(void); |
108 | |
109 | void intel_guc_ct_init_early(struct intel_guc_ct *ct); |
110 | int intel_guc_ct_init(struct intel_guc_ct *ct); |
111 | void intel_guc_ct_fini(struct intel_guc_ct *ct); |
112 | int intel_guc_ct_enable(struct intel_guc_ct *ct); |
113 | void intel_guc_ct_disable(struct intel_guc_ct *ct); |
114 | |
115 | static inline void intel_guc_ct_sanitize(struct intel_guc_ct *ct) |
116 | { |
117 | ct->enabled = false; |
118 | } |
119 | |
120 | static inline bool intel_guc_ct_enabled(struct intel_guc_ct *ct) |
121 | { |
122 | return ct->enabled; |
123 | } |
124 | |
125 | #define INTEL_GUC_CT_SEND_NB BIT(31) |
126 | #define INTEL_GUC_CT_SEND_G2H_DW_SHIFT 0 |
127 | #define INTEL_GUC_CT_SEND_G2H_DW_MASK (0xff << INTEL_GUC_CT_SEND_G2H_DW_SHIFT) |
128 | #define MAKE_SEND_FLAGS(len) ({ \ |
129 | typeof(len) len_ = (len); \ |
130 | GEM_BUG_ON(!FIELD_FIT(INTEL_GUC_CT_SEND_G2H_DW_MASK, len_)); \ |
131 | (FIELD_PREP(INTEL_GUC_CT_SEND_G2H_DW_MASK, len_) | INTEL_GUC_CT_SEND_NB); \ |
132 | }) |
133 | int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 *action, u32 len, |
134 | u32 *response_buf, u32 response_buf_size, u32 flags); |
135 | void intel_guc_ct_event_handler(struct intel_guc_ct *ct); |
136 | |
137 | void intel_guc_ct_print_info(struct intel_guc_ct *ct, struct drm_printer *p); |
138 | |
139 | #endif /* _INTEL_GUC_CT_H_ */ |
140 | |