summaryrefslogtreecommitdiff
path: root/gxp-dci.h
blob: ed71651e49d6f406d09f6bb2d840ba142182e87e (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
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Implementation of DCI (Direct Command Interface) using mailbox.
 *
 * Copyright (C) 2022 Google LLC
 */

#ifndef __GXP_DCI_H__
#define __GXP_DCI_H__

#include <gcip/gcip-mailbox.h>

#include "gxp-mailbox.h"
#include "gxp-vd.h"

/* Basic Buffer descriptor struct for message payloads. */
struct gxp_dci_buffer_descriptor {
	/* Address in the device's virtual address space. */
	u64 address;
	/* Size in bytes. */
	u32 size;
	/* Flags can be used to indicate message type, etc. */
	u32 flags;
};

/* Format used for mailbox command queues. */
struct gxp_dci_command {
	/* Sequence number. Should match the corresponding response. */
	u64 seq;
	/*
	 * Identifies the type of command.
	 * Should be a value from `gxp_mailbox_command_code`
	 */
	u16 code;
	/*
	 * Priority level from 0 to 99, with 0 being the highest. Pending
	 * commands with higher priorities will be executed before lower
	 * priority ones.
	 */
	u8 priority;
	/*
	 * Insert spaces to make padding explicit. This does not affect
	 * alignment.
	 */
	u8 reserved[5];
	/* Struct describing the buffer containing the message payload */
	struct gxp_dci_buffer_descriptor buffer_descriptor;
};

/* Format used for mailbox response queues from kernel. */
struct gxp_dci_response {
	/* Sequence number. Should match the corresponding command. */
	u64 seq;
	/* The status code. Either SUCCESS or an error. */
	u16 status;
	/* Padding. */
	u16 reserved;
	/* Return value, dependent on the command this responds to. */
	u32 retval;
};

/*
 * Wrapper struct for responses consumed by a thread other than the one which
 * sent the command.
 */
struct gxp_dci_async_response {
	struct list_head list_entry;
	struct gxp_dci_response resp;
	/* Queue to add the response to once it is complete or timed out */
	struct list_head *dest_queue;
	/*
	 * The lock that protects queue pointed to by `dest_queue`.
	 * The mailbox code also uses this lock to protect changes to the
	 * `dest_queue` pointer itself when processing this response.
	 */
	spinlock_t *dest_queue_lock;
	/* Queue of clients to notify when this response is processed */
	wait_queue_head_t *dest_queue_waitq;
	/* Specified power states vote during the command execution */
	struct gxp_power_states requested_states;
	/* gxp_eventfd to signal when the response completes. May be NULL */
	struct gxp_eventfd *eventfd;
	/* Handles arrival, timeout of async response. */
	struct gcip_mailbox_async_response *async_resp;
};

enum gxp_dci_response_status {
	GXP_DCI_RESP_OK = GCIP_MAILBOX_STATUS_OK,
	GXP_DCI_RESP_WAITING = GCIP_MAILBOX_STATUS_WAITING_RESPONSE,
	GXP_DCI_RESP_CANCELLED = GCIP_MAILBOX_STATUS_NO_RESPONSE,
};

/*
 * Initializes the DCI to be able to work with user commands.
 * Calling this function means that the device will communicate with the firmware side via DCI.
 */
void gxp_dci_init(struct gxp_mailbox_manager *mgr);

/*
 * The following functions all require their caller have locked
 * gxp->vd_semaphore for reading.
 */

/*
 * Allocates a mailbox which is initialized for DCI.
 * The mailbox must be released by calling `gxp_dci_release`.
 */
struct gxp_mailbox *gxp_dci_alloc(struct gxp_mailbox_manager *mgr,
				  struct gxp_virtual_device *vd, uint virt_core,
				  u8 core_id);

/* Releases a mailbox which is allocated by `gxp_dci_alloc`. */
void gxp_dci_release(struct gxp_mailbox_manager *mgr,
		     struct gxp_virtual_device *vd, uint virt_core,
		     struct gxp_mailbox *mailbox);

/* Executes command and get response through @resp. */
int gxp_dci_execute_cmd(struct gxp_mailbox *mailbox,
			struct gxp_dci_command *cmd,
			struct gxp_dci_response *resp);

/*
 * Executes command asynchronously.
 * The response can be obtained by waiting the `mailbox_resp_queues` of corresponding
 * virtual device of the mailbox which is a queue of `gxp_dci_async_response`.
 */
int gxp_dci_execute_cmd_async(struct gxp_mailbox *mailbox,
			      struct gxp_dci_command *cmd,
			      struct list_head *resp_queue,
			      spinlock_t *queue_lock,
			      wait_queue_head_t *queue_waitq,
			      struct gxp_power_states requested_states,
			      struct gxp_eventfd *eventfd);

#endif /* __GXP_DCI_H__ */