1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * Greybus operations |
4 | * |
5 | * Copyright 2014 Google Inc. |
6 | * Copyright 2014 Linaro Ltd. |
7 | */ |
8 | |
9 | #ifndef __OPERATION_H |
10 | #define __OPERATION_H |
11 | |
12 | #include <linux/completion.h> |
13 | #include <linux/kref.h> |
14 | #include <linux/timer.h> |
15 | #include <linux/types.h> |
16 | #include <linux/workqueue.h> |
17 | |
18 | struct gb_host_device; |
19 | struct gb_operation; |
20 | |
21 | /* The default amount of time a request is given to complete */ |
22 | #define GB_OPERATION_TIMEOUT_DEFAULT 1000 /* milliseconds */ |
23 | |
24 | /* |
25 | * The top bit of the type in an operation message header indicates |
26 | * whether the message is a request (bit clear) or response (bit set) |
27 | */ |
28 | #define GB_MESSAGE_TYPE_RESPONSE ((u8)0x80) |
29 | |
30 | enum gb_operation_result { |
31 | GB_OP_SUCCESS = 0x00, |
32 | GB_OP_INTERRUPTED = 0x01, |
33 | GB_OP_TIMEOUT = 0x02, |
34 | GB_OP_NO_MEMORY = 0x03, |
35 | GB_OP_PROTOCOL_BAD = 0x04, |
36 | GB_OP_OVERFLOW = 0x05, |
37 | GB_OP_INVALID = 0x06, |
38 | GB_OP_RETRY = 0x07, |
39 | GB_OP_NONEXISTENT = 0x08, |
40 | GB_OP_UNKNOWN_ERROR = 0xfe, |
41 | GB_OP_MALFUNCTION = 0xff, |
42 | }; |
43 | |
44 | #define GB_OPERATION_MESSAGE_SIZE_MIN sizeof(struct gb_operation_msg_hdr) |
45 | #define GB_OPERATION_MESSAGE_SIZE_MAX U16_MAX |
46 | |
47 | /* |
48 | * Protocol code should only examine the payload and payload_size fields, and |
49 | * host-controller drivers may use the hcpriv field. All other fields are |
50 | * intended to be private to the operations core code. |
51 | */ |
52 | struct gb_message { |
53 | struct gb_operation *operation; |
54 | struct gb_operation_msg_hdr *; |
55 | |
56 | void *payload; |
57 | size_t payload_size; |
58 | |
59 | void *buffer; |
60 | |
61 | void *hcpriv; |
62 | }; |
63 | |
64 | #define GB_OPERATION_FLAG_INCOMING BIT(0) |
65 | #define GB_OPERATION_FLAG_UNIDIRECTIONAL BIT(1) |
66 | #define GB_OPERATION_FLAG_SHORT_RESPONSE BIT(2) |
67 | #define GB_OPERATION_FLAG_CORE BIT(3) |
68 | |
69 | #define GB_OPERATION_FLAG_USER_MASK (GB_OPERATION_FLAG_SHORT_RESPONSE | \ |
70 | GB_OPERATION_FLAG_UNIDIRECTIONAL) |
71 | |
72 | /* |
73 | * A Greybus operation is a remote procedure call performed over a |
74 | * connection between two UniPro interfaces. |
75 | * |
76 | * Every operation consists of a request message sent to the other |
77 | * end of the connection coupled with a reply message returned to |
78 | * the sender. Every operation has a type, whose interpretation is |
79 | * dependent on the protocol associated with the connection. |
80 | * |
81 | * Only four things in an operation structure are intended to be |
82 | * directly usable by protocol handlers: the operation's connection |
83 | * pointer; the operation type; the request message payload (and |
84 | * size); and the response message payload (and size). Note that a |
85 | * message with a 0-byte payload has a null message payload pointer. |
86 | * |
87 | * In addition, every operation has a result, which is an errno |
88 | * value. Protocol handlers access the operation result using |
89 | * gb_operation_result(). |
90 | */ |
91 | typedef void (*gb_operation_callback)(struct gb_operation *); |
92 | struct gb_operation { |
93 | struct gb_connection *connection; |
94 | struct gb_message *request; |
95 | struct gb_message *response; |
96 | |
97 | unsigned long flags; |
98 | u8 type; |
99 | u16 id; |
100 | int errno; /* Operation result */ |
101 | |
102 | struct work_struct work; |
103 | gb_operation_callback callback; |
104 | struct completion completion; |
105 | struct timer_list timer; |
106 | |
107 | struct kref kref; |
108 | atomic_t waiters; |
109 | |
110 | int active; |
111 | struct list_head links; /* connection->operations */ |
112 | |
113 | void *private; |
114 | }; |
115 | |
116 | static inline bool |
117 | gb_operation_is_incoming(struct gb_operation *operation) |
118 | { |
119 | return operation->flags & GB_OPERATION_FLAG_INCOMING; |
120 | } |
121 | |
122 | static inline bool |
123 | gb_operation_is_unidirectional(struct gb_operation *operation) |
124 | { |
125 | return operation->flags & GB_OPERATION_FLAG_UNIDIRECTIONAL; |
126 | } |
127 | |
128 | static inline bool |
129 | gb_operation_short_response_allowed(struct gb_operation *operation) |
130 | { |
131 | return operation->flags & GB_OPERATION_FLAG_SHORT_RESPONSE; |
132 | } |
133 | |
134 | static inline bool gb_operation_is_core(struct gb_operation *operation) |
135 | { |
136 | return operation->flags & GB_OPERATION_FLAG_CORE; |
137 | } |
138 | |
139 | void gb_connection_recv(struct gb_connection *connection, |
140 | void *data, size_t size); |
141 | |
142 | int gb_operation_result(struct gb_operation *operation); |
143 | |
144 | size_t gb_operation_get_payload_size_max(struct gb_connection *connection); |
145 | struct gb_operation * |
146 | gb_operation_create_flags(struct gb_connection *connection, |
147 | u8 type, size_t request_size, |
148 | size_t response_size, unsigned long flags, |
149 | gfp_t gfp); |
150 | |
151 | static inline struct gb_operation * |
152 | gb_operation_create(struct gb_connection *connection, |
153 | u8 type, size_t request_size, |
154 | size_t response_size, gfp_t gfp) |
155 | { |
156 | return gb_operation_create_flags(connection, type, request_size, |
157 | response_size, flags: 0, gfp); |
158 | } |
159 | |
160 | struct gb_operation * |
161 | gb_operation_create_core(struct gb_connection *connection, |
162 | u8 type, size_t request_size, |
163 | size_t response_size, unsigned long flags, |
164 | gfp_t gfp); |
165 | |
166 | void gb_operation_get(struct gb_operation *operation); |
167 | void gb_operation_put(struct gb_operation *operation); |
168 | |
169 | bool gb_operation_response_alloc(struct gb_operation *operation, |
170 | size_t response_size, gfp_t gfp); |
171 | |
172 | int gb_operation_request_send(struct gb_operation *operation, |
173 | gb_operation_callback callback, |
174 | unsigned int timeout, |
175 | gfp_t gfp); |
176 | int gb_operation_request_send_sync_timeout(struct gb_operation *operation, |
177 | unsigned int timeout); |
178 | static inline int |
179 | gb_operation_request_send_sync(struct gb_operation *operation) |
180 | { |
181 | return gb_operation_request_send_sync_timeout(operation, |
182 | GB_OPERATION_TIMEOUT_DEFAULT); |
183 | } |
184 | |
185 | void gb_operation_cancel(struct gb_operation *operation, int errno); |
186 | void gb_operation_cancel_incoming(struct gb_operation *operation, int errno); |
187 | |
188 | void greybus_message_sent(struct gb_host_device *hd, |
189 | struct gb_message *message, int status); |
190 | |
191 | int gb_operation_sync_timeout(struct gb_connection *connection, int type, |
192 | void *request, int request_size, |
193 | void *response, int response_size, |
194 | unsigned int timeout); |
195 | int gb_operation_unidirectional_timeout(struct gb_connection *connection, |
196 | int type, void *request, int request_size, |
197 | unsigned int timeout); |
198 | |
199 | static inline int gb_operation_sync(struct gb_connection *connection, int type, |
200 | void *request, int request_size, |
201 | void *response, int response_size) |
202 | { |
203 | return gb_operation_sync_timeout(connection, type, |
204 | request, request_size, response, response_size, |
205 | GB_OPERATION_TIMEOUT_DEFAULT); |
206 | } |
207 | |
208 | static inline int gb_operation_unidirectional(struct gb_connection *connection, |
209 | int type, void *request, int request_size) |
210 | { |
211 | return gb_operation_unidirectional_timeout(connection, type, |
212 | request, request_size, GB_OPERATION_TIMEOUT_DEFAULT); |
213 | } |
214 | |
215 | static inline void *gb_operation_get_data(struct gb_operation *operation) |
216 | { |
217 | return operation->private; |
218 | } |
219 | |
220 | static inline void gb_operation_set_data(struct gb_operation *operation, |
221 | void *data) |
222 | { |
223 | operation->private = data; |
224 | } |
225 | |
226 | int gb_operation_init(void); |
227 | void gb_operation_exit(void); |
228 | |
229 | #endif /* !__OPERATION_H */ |
230 | |