summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.h
blob: 2c4bb9a941be602db44afae192f4cf3ddec1b4b3 (plain)
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
134
135
136
137
138
139
/* SPDX-License-Identifier: MIT */
/*
 * Copyright © 2016-2019 Intel Corporation
 */

#ifndef _INTEL_GUC_CT_H_
#define _INTEL_GUC_CT_H_

#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/stackdepot.h>
#include <linux/workqueue.h>
#include <linux/ktime.h>
#include <linux/wait.h>

#include "intel_guc_fwif.h"

struct i915_vma;
struct intel_guc;
struct drm_printer;

/**
 * DOC: Command Transport (CT).
 *
 * Buffer based command transport is a replacement for MMIO based mechanism.
 * It can be used to perform both host-2-guc and guc-to-host communication.
 */

/** Represents single command transport buffer.
 *
 * A single command transport buffer consists of two parts, the header
 * record (command transport buffer descriptor) and the actual buffer which
 * holds the commands.
 *
 * @lock: protects access to the commands buffer and buffer descriptor
 * @desc: pointer to the buffer descriptor
 * @cmds: pointer to the commands buffer
 * @size: size of the commands buffer in dwords
 * @resv_space: reserved space in buffer in dwords
 * @head: local shadow copy of head in dwords
 * @tail: local shadow copy of tail in dwords
 * @space: local shadow copy of space in dwords
 * @broken: flag to indicate if descriptor data is broken
 */
struct intel_guc_ct_buffer {
	spinlock_t lock;
	struct guc_ct_buffer_desc *desc;
	u32 *cmds;
	u32 size;
	u32 resv_space;
	u32 tail;
	u32 head;
	atomic_t space;
	bool broken;
};

/** Top-level structure for Command Transport related data
 *
 * Includes a pair of CT buffers for bi-directional communication and tracking
 * for the H2G and G2H requests sent and received through the buffers.
 */
struct intel_guc_ct {
	struct i915_vma *vma;
	bool enabled;

	/* buffers for sending and receiving commands */
	struct {
		struct intel_guc_ct_buffer send;
		struct intel_guc_ct_buffer recv;
	} ctbs;

	struct tasklet_struct receive_tasklet;

	/** @wq: wait queue for g2h chanenl */
	wait_queue_head_t wq;

	struct {
		u16 last_fence; /* last fence used to send request */

		spinlock_t lock; /* protects pending requests list */
		struct list_head pending; /* requests waiting for response */

		struct list_head incoming; /* incoming requests */
		struct work_struct worker; /* handler for incoming requests */

#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)
		struct {
			u16 fence;
			u16 action;
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC)
			depot_stack_handle_t stack;
#endif
		} lost_and_found[SZ_16];
#endif
	} requests;

	/** @stall_time: time of first time a CTB submission is stalled */
	ktime_t stall_time;

#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_GUC)
	int dead_ct_reason;
	bool dead_ct_reported;
	struct work_struct dead_ct_worker;
#endif
};

long intel_guc_ct_max_queue_time_jiffies(void);

void intel_guc_ct_init_early(struct intel_guc_ct *ct);
int intel_guc_ct_init(struct intel_guc_ct *ct);
void intel_guc_ct_fini(struct intel_guc_ct *ct);
int intel_guc_ct_enable(struct intel_guc_ct *ct);
void intel_guc_ct_disable(struct intel_guc_ct *ct);

static inline void intel_guc_ct_sanitize(struct intel_guc_ct *ct)
{
	ct->enabled = false;
}

static inline bool intel_guc_ct_enabled(struct intel_guc_ct *ct)
{
	return ct->enabled;
}

#define INTEL_GUC_CT_SEND_NB		BIT(31)
#define INTEL_GUC_CT_SEND_G2H_DW_SHIFT	0
#define INTEL_GUC_CT_SEND_G2H_DW_MASK	(0xff << INTEL_GUC_CT_SEND_G2H_DW_SHIFT)
#define MAKE_SEND_FLAGS(len) ({ \
	typeof(len) len_ = (len); \
	GEM_BUG_ON(!FIELD_FIT(INTEL_GUC_CT_SEND_G2H_DW_MASK, len_)); \
	(FIELD_PREP(INTEL_GUC_CT_SEND_G2H_DW_MASK, len_) | INTEL_GUC_CT_SEND_NB); \
})
int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 *action, u32 len,
		      u32 *response_buf, u32 response_buf_size, u32 flags);
void intel_guc_ct_event_handler(struct intel_guc_ct *ct);

void intel_guc_ct_print_info(struct intel_guc_ct *ct, struct drm_printer *p);

#endif /* _INTEL_GUC_CT_H_ */