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 void intel_guc_ct_init_early(struct intel_guc_ct *ct);
108 int intel_guc_ct_init(struct intel_guc_ct *ct);
109 void intel_guc_ct_fini(struct intel_guc_ct *ct);
110 int intel_guc_ct_enable(struct intel_guc_ct *ct);
111 void intel_guc_ct_disable(struct intel_guc_ct *ct);
112 
113 static inline void intel_guc_ct_sanitize(struct intel_guc_ct *ct)
114 {
115 	ct->enabled = false;
116 }
117 
118 static inline bool intel_guc_ct_enabled(struct intel_guc_ct *ct)
119 {
120 	return ct->enabled;
121 }
122 
123 #define INTEL_GUC_CT_SEND_NB		BIT(31)
124 #define INTEL_GUC_CT_SEND_G2H_DW_SHIFT	0
125 #define INTEL_GUC_CT_SEND_G2H_DW_MASK	(0xff << INTEL_GUC_CT_SEND_G2H_DW_SHIFT)
126 #define MAKE_SEND_FLAGS(len) ({ \
127 	typeof(len) len_ = (len); \
128 	GEM_BUG_ON(!FIELD_FIT(INTEL_GUC_CT_SEND_G2H_DW_MASK, len_)); \
129 	(FIELD_PREP(INTEL_GUC_CT_SEND_G2H_DW_MASK, len_) | INTEL_GUC_CT_SEND_NB); \
130 })
131 int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 *action, u32 len,
132 		      u32 *response_buf, u32 response_buf_size, u32 flags);
133 void intel_guc_ct_event_handler(struct intel_guc_ct *ct);
134 
135 void intel_guc_ct_print_info(struct intel_guc_ct *ct, struct drm_printer *p);
136 
137 #endif /* _INTEL_GUC_CT_H_ */
138