1 /*
2 * rpmsg based on virtio
3 *
4 * Copyright (C) 2018 Linaro, Inc.
5 *
6 * All rights reserved.
7 * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
8 *
9 * SPDX-License-Identifier: BSD-3-Clause
10 */
11
12 #ifndef _RPMSG_VIRTIO_H_
13 #define _RPMSG_VIRTIO_H_
14
15 #include <metal/io.h>
16 #include <metal/mutex.h>
17 #include <metal/cache.h>
18 #include <openamp/rpmsg.h>
19 #include <openamp/virtio.h>
20
21 #if defined __cplusplus
22 extern "C" {
23 #endif
24
25 /* Configurable parameters */
26 #ifndef RPMSG_BUFFER_SIZE
27 #define RPMSG_BUFFER_SIZE (512)
28 #endif
29
30 /* The feature bitmap for virtio rpmsg */
31 #define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */
32
33 #ifdef VIRTIO_CACHED_BUFFERS
34 #warning "VIRTIO_CACHED_BUFFERS is deprecated, please use VIRTIO_USE_DCACHE"
35 #endif
36 #if defined(VIRTIO_CACHED_BUFFERS) || defined(VIRTIO_USE_DCACHE)
37 #define BUFFER_FLUSH(x, s) CACHE_FLUSH(x, s)
38 #define BUFFER_INVALIDATE(x, s) CACHE_INVALIDATE(x, s)
39 #else
40 #define BUFFER_FLUSH(x, s) do { } while (0)
41 #define BUFFER_INVALIDATE(x, s) do { } while (0)
42 #endif /* VIRTIO_CACHED_BUFFERS || VIRTIO_USE_DCACHE */
43
44 /* Callback handler for rpmsg virtio service */
45 typedef int (*rpmsg_virtio_notify_wait_cb)(struct rpmsg_device *rdev, uint32_t id);
46
47 /** @brief Shared memory pool used for RPMsg buffers */
48 struct rpmsg_virtio_shm_pool {
49 /** Base address of the memory pool */
50 void *base;
51
52 /** Available memory size */
53 size_t avail;
54
55 /** Total pool size */
56 size_t size;
57 };
58
59 /**
60 * @brief Configuration of RPMsg device based on virtio
61 *
62 * This structure is used by the RPMsg virtio host to configure the virtiio
63 * layer.
64 */
65 struct rpmsg_virtio_config {
66 /** The size of the buffer used to send data from host to remote */
67 uint32_t h2r_buf_size;
68
69 /** The size of the buffer used to send data from remote to host */
70 uint32_t r2h_buf_size;
71
72 /** The flag for splitting shared memory pool to TX and RX */
73 bool split_shpool;
74 };
75
76 /** @brief Representation of a RPMsg device based on virtio */
77 struct rpmsg_virtio_device {
78 /** RPMsg device */
79 struct rpmsg_device rdev;
80
81 /** Structure containing virtio configuration */
82 struct rpmsg_virtio_config config;
83
84 /** Pointer to the virtio device */
85 struct virtio_device *vdev;
86
87 /** Pointer to receive virtqueue */
88 struct virtqueue *rvq;
89
90 /** Pointer to send virtqueue */
91 struct virtqueue *svq;
92
93 /** Pointer to the shared buffer I/O region */
94 struct metal_io_region *shbuf_io;
95
96 /** Pointer to the shared buffers pool */
97 struct rpmsg_virtio_shm_pool *shpool;
98
99 /**
100 * RPMsg buffer reclaimer that contains buffers released by the
101 * \ref rpmsg_virtio_release_tx_buffer function
102 */
103 struct metal_list reclaimer;
104
105 /**
106 * Callback handler for rpmsg virtio service, called when service
107 * can't get tx buffer
108 */
109 rpmsg_virtio_notify_wait_cb notify_wait_cb;
110 };
111
112 #define RPMSG_REMOTE VIRTIO_DEV_DEVICE
113 #define RPMSG_HOST VIRTIO_DEV_DRIVER
114
115 /**
116 * @brief Set the virtio callback to manage the wait for TX buffer availability.
117 *
118 * @param rvdev Pointer to rpmsg virtio device.
119 * @param notify_wait_cb Callback handler to wait buffer notification.
120 */
rpmsg_virtio_set_wait_cb(struct rpmsg_virtio_device * rvdev,rpmsg_virtio_notify_wait_cb notify_wait_cb)121 static inline void rpmsg_virtio_set_wait_cb(struct rpmsg_virtio_device *rvdev,
122 rpmsg_virtio_notify_wait_cb notify_wait_cb)
123 {
124 rvdev->notify_wait_cb = notify_wait_cb;
125 }
126
127 /**
128 * @brief Get rpmsg virtio device role.
129 *
130 * @param rvdev Pointer to rpmsg virtio device.
131 *
132 * @return VIRTIO_DEV_DEVICE or VIRTIO_DEV_DRIVER
133 */
134 static inline unsigned int
rpmsg_virtio_get_role(struct rpmsg_virtio_device * rvdev)135 rpmsg_virtio_get_role(struct rpmsg_virtio_device *rvdev)
136 {
137 return rvdev->vdev->role;
138 }
139
140 /**
141 * @brief Set rpmsg virtio device status.
142 *
143 * Deprecated: Use virtio_set_status() instead
144 *
145 * @param rvdev Pointer to rpmsg virtio device.
146 * @param status Value to be set as rpmsg virtio device status.
147 */
148 __deprecated
rpmsg_virtio_set_status(struct rpmsg_virtio_device * rvdev,uint8_t status)149 static inline void rpmsg_virtio_set_status(struct rpmsg_virtio_device *rvdev,
150 uint8_t status)
151 {
152 rvdev->vdev->func->set_status(rvdev->vdev, status);
153 }
154
155 /**
156 * @brief Retrieve rpmsg virtio device status.
157 *
158 * Deprecated: Use virtio_get_status() instead
159 *
160 * @param rvdev Pointer to rpmsg virtio device.
161 *
162 * @return The rpmsg virtio device status.
163 */
164 __deprecated
rpmsg_virtio_get_status(struct rpmsg_virtio_device * rvdev)165 static inline uint8_t rpmsg_virtio_get_status(struct rpmsg_virtio_device *rvdev)
166 {
167 return rvdev->vdev->func->get_status(rvdev->vdev);
168 }
169
170 /**
171 * @brief Get the rpmsg virtio device features.
172 *
173 * Deprecated: Use virtio_get_features() instead
174 *
175 * @param rvdev Pointer to the rpmsg virtio device.
176 *
177 * @return The features supported by both the rpmsg driver and rpmsg device.
178 */
179 __deprecated
180 static inline uint32_t
rpmsg_virtio_get_features(struct rpmsg_virtio_device * rvdev)181 rpmsg_virtio_get_features(struct rpmsg_virtio_device *rvdev)
182 {
183 return rvdev->vdev->func->get_features(rvdev->vdev);
184 }
185
186 /**
187 * @brief Retrieve configuration data from the rpmsg virtio device.
188 *
189 * Deprecated: Use virtio_read_config() instead
190 *
191 * @param rvdev Pointer to the rpmsg virtio device.
192 * @param offset Offset of the data within the configuration area.
193 * @param dst Address of the buffer that will hold the data.
194 * @param length Length of the data to be retrieved.
195 */
196 __deprecated
197 static inline void
rpmsg_virtio_read_config(struct rpmsg_virtio_device * rvdev,uint32_t offset,void * dst,int length)198 rpmsg_virtio_read_config(struct rpmsg_virtio_device *rvdev,
199 uint32_t offset, void *dst, int length)
200 {
201 rvdev->vdev->func->read_config(rvdev->vdev, offset, dst, length);
202 }
203
204 /**
205 * @brief Write configuration data to the rpmsg virtio device.
206 *
207 * Deprecated: Use virtio_write_config() instead
208 *
209 * @param rvdev Pointer to the rpmsg virtio device.
210 * @param offset Offset of the data within the configuration area.
211 * @param src Address of the buffer that holds the data to write.
212 * @param length Length of the data to be written.
213 *
214 * @return 0 on success, otherwise error code.
215 */
216 __deprecated
217 static inline void
rpmsg_virtio_write_config(struct rpmsg_virtio_device * rvdev,uint32_t offset,void * src,int length)218 rpmsg_virtio_write_config(struct rpmsg_virtio_device *rvdev,
219 uint32_t offset, void *src, int length)
220 {
221 rvdev->vdev->func->write_config(rvdev->vdev, offset, src, length);
222 }
223
224 /**
225 * @brief Create the rpmsg virtio device virtqueue.
226 *
227 * Deprecated: Use virtio_create_virtqueues() instead
228 *
229 * @param rvdev Pointer to the rpmsg virtio device.
230 * @param flags Create flag.
231 * @param nvqs The virtqueue number.
232 * @param names Virtqueue names.
233 * @param callbacks Virtqueue callback functions.
234 *
235 * @return 0 on success, otherwise error code.
236 */
237 __deprecated
238 static inline int
rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device * rvdev,int flags,unsigned int nvqs,const char * names[],vq_callback * callbacks)239 rpmsg_virtio_create_virtqueues(struct rpmsg_virtio_device *rvdev,
240 int flags, unsigned int nvqs,
241 const char *names[],
242 vq_callback *callbacks)
243 {
244 return virtio_create_virtqueues(rvdev->vdev, flags, nvqs, names,
245 callbacks, NULL);
246 }
247
248 /**
249 * @brief Delete the virtqueues created in rpmsg_virtio_create_virtqueues()
250 *
251 * Deprecated: Use virtio_delete_virtqueues() instead
252 *
253 * @param rvdev Pointer to the rpmsg virtio device
254 */
255 __deprecated
256 static inline void
rpmsg_virtio_delete_virtqueues(struct rpmsg_virtio_device * rvdev)257 rpmsg_virtio_delete_virtqueues(struct rpmsg_virtio_device *rvdev)
258 {
259 virtio_delete_virtqueues(rvdev->vdev);
260 }
261
262 /**
263 * @brief Get rpmsg virtio buffer size
264 *
265 * @param rdev Pointer to the rpmsg device
266 *
267 * @return Next available buffer size for text, negative value for failure
268 */
269 int rpmsg_virtio_get_tx_buffer_size(struct rpmsg_device *rdev);
270
271 /**
272 * @brief Get rpmsg virtio Rx buffer size
273 *
274 * @param rdev Pointer to the rpmsg device
275 *
276 * @return Next available buffer size for text, negative value for failure
277 */
278 int rpmsg_virtio_get_rx_buffer_size(struct rpmsg_device *rdev);
279
280 /**
281 * @brief Get rpmsg virtio Tx buffer size
282 *
283 * This function is same as rpmsg_virtio_get_tx_buffer_size(), keep it here
284 * to maintain the forward compatibility.
285 *
286 * @param rdev Pointer to the rpmsg device.
287 *
288 * @return Next available buffer size for text, negative value for failure.
289 */
rpmsg_virtio_get_buffer_size(struct rpmsg_device * rdev)290 static inline int rpmsg_virtio_get_buffer_size(struct rpmsg_device *rdev)
291 {
292 return rpmsg_virtio_get_tx_buffer_size(rdev);
293 }
294
295 /**
296 * @brief Initialize rpmsg virtio device
297 *
298 * Host side:
299 * Initialize RPMsg virtio queues and shared buffers, the address of shm can be
300 * ANY. In this case, function will get shared memory from system shared memory
301 * pools. If the vdev has the RPMsg name service feature, this API will create
302 * a name service endpoint.
303 *
304 * Remote side:
305 * This API will not return until the driver ready is set by the host side.
306 *
307 * @param rvdev Pointer to the rpmsg virtio device
308 * @param vdev Pointer to the virtio device
309 * @param ns_bind_cb Callback handler for name service announcement without
310 * local endpoints waiting to bind.
311 * @param shm_io Pointer to the share memory I/O region.
312 * @param shpool Pointer to shared memory pool.
313 * rpmsg_virtio_init_shm_pool has to be called first to
314 * fill this structure.
315 *
316 * @return Status of function execution
317 */
318 int rpmsg_init_vdev(struct rpmsg_virtio_device *rvdev,
319 struct virtio_device *vdev,
320 rpmsg_ns_bind_cb ns_bind_cb,
321 struct metal_io_region *shm_io,
322 struct rpmsg_virtio_shm_pool *shpool);
323
324 /**
325 * @brief Initialize rpmsg virtio device with config
326 *
327 * Host side:
328 * Initialize RPMsg virtio queues and shared buffers, the address of shm can be
329 * ANY. In this case, function will get shared memory from system shared memory
330 * pools. If the vdev has the RPMsg name service feature, this API will create
331 * a name service endpoint.
332 * Sizes of virtio data buffers used by the initialized RPMsg instance are set
333 * to values read from the passed configuration structure.
334 *
335 * Remote side:
336 * This API will not return until the driver ready is set by the host side.
337 * Sizes of virtio data buffers are set by the host side. Values passed in the
338 * configuration structure have no effect.
339 *
340 * @param rvdev Pointer to the rpmsg virtio device
341 * @param vdev Pointer to the virtio device
342 * @param ns_bind_cb Callback handler for name service announcement without
343 * local endpoints waiting to bind.
344 * @param shm_io Pointer to the share memory I/O region.
345 * @param shpool Pointer to shared memory pool array.
346 * If the config->split_shpool is turn on, the array will
347 * contain two elements, the shpool of txshpool and
348 * rxshpool, Otherwise, the array has only one element,
349 * and txshpool rxshpool shares a shpool.
350 * And rpmsg_virtio_init_shm_pool has to be called first
351 * to fill each shpool in this array.
352 * @param config Pointer to configuration structure
353 *
354 * @return Status of function execution
355 */
356 int rpmsg_init_vdev_with_config(struct rpmsg_virtio_device *rvdev,
357 struct virtio_device *vdev,
358 rpmsg_ns_bind_cb ns_bind_cb,
359 struct metal_io_region *shm_io,
360 struct rpmsg_virtio_shm_pool *shpool,
361 const struct rpmsg_virtio_config *config);
362
363 /**
364 * @brief Deinitialize rpmsg virtio device
365 *
366 * @param rvdev Pointer to the rpmsg virtio device
367 */
368 void rpmsg_deinit_vdev(struct rpmsg_virtio_device *rvdev);
369
370 /**
371 * @brief Initialize default shared buffers pool
372 *
373 * RPMsg virtio has default shared buffers pool implementation.
374 * The memory assigned to this pool will be dedicated to the RPMsg
375 * virtio. This function has to be called before calling rpmsg_init_vdev,
376 * to initialize the rpmsg_virtio_shm_pool structure.
377 *
378 * @param shpool Pointer to the shared buffers pool structure
379 * @param shbuf Pointer to the beginning of shared buffers
380 * @param size Shared buffers total size
381 */
382 void rpmsg_virtio_init_shm_pool(struct rpmsg_virtio_shm_pool *shpool,
383 void *shbuf, size_t size);
384
385 /**
386 * @brief Get RPMsg device from RPMsg virtio device
387 *
388 * @param rvdev Pointer to RPMsg virtio device
389 *
390 * @return RPMsg device pointed by RPMsg virtio device
391 */
392 static inline struct rpmsg_device *
rpmsg_virtio_get_rpmsg_device(struct rpmsg_virtio_device * rvdev)393 rpmsg_virtio_get_rpmsg_device(struct rpmsg_virtio_device *rvdev)
394 {
395 if (!rvdev)
396 return NULL;
397
398 return &rvdev->rdev;
399 }
400
401 /**
402 * @brief Get buffer in the shared memory pool
403 *
404 * RPMsg virtio has default shared buffers pool implementation.
405 * The memory assigned to this pool will be dedicated to the RPMsg
406 * virtio. If you prefer to have other shared buffers allocation,
407 * you can implement your rpmsg_virtio_shm_pool_get_buffer function.
408 *
409 * @param shpool Pointer to the shared buffers pool
410 * @param size Shared buffers total size
411 *
412 * @return Buffer pointer if free buffer is available, NULL otherwise.
413 */
414 metal_weak void *
415 rpmsg_virtio_shm_pool_get_buffer(struct rpmsg_virtio_shm_pool *shpool,
416 size_t size);
417
418 #if defined __cplusplus
419 }
420 #endif
421
422 #endif /* _RPMSG_VIRTIO_H_ */
423