1 /*
2  * Remote processor messaging
3  *
4  * Copyright (C) 2011 Texas Instruments, Inc.
5  * Copyright (C) 2011 Google, Inc.
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_H_
13 #define _RPMSG_H_
14 
15 #include <metal/compiler.h>
16 #include <metal/mutex.h>
17 #include <metal/list.h>
18 #include <metal/utilities.h>
19 #include <string.h>
20 #include <stdbool.h>
21 #include <stdint.h>
22 
23 #if defined __cplusplus
24 extern "C" {
25 #endif
26 
27 /* Configurable parameters */
28 #define RPMSG_NAME_SIZE			(32)
29 #define RPMSG_ADDR_BMP_SIZE		(128)
30 
31 #define RPMSG_NS_EPT_ADDR		(0x35)
32 #define RPMSG_RESERVED_ADDRESSES	(1024)
33 #define RPMSG_ADDR_ANY			0xFFFFFFFF
34 
35 /* Error macros. */
36 #define RPMSG_SUCCESS			0
37 #define RPMSG_ERROR_BASE		-2000
38 #define RPMSG_ERR_NO_MEM		(RPMSG_ERROR_BASE - 1)
39 #define RPMSG_ERR_NO_BUFF		(RPMSG_ERROR_BASE - 2)
40 #define RPMSG_ERR_PARAM			(RPMSG_ERROR_BASE - 3)
41 #define RPMSG_ERR_DEV_STATE		(RPMSG_ERROR_BASE - 4)
42 #define RPMSG_ERR_BUFF_SIZE		(RPMSG_ERROR_BASE - 5)
43 #define RPMSG_ERR_INIT			(RPMSG_ERROR_BASE - 6)
44 #define RPMSG_ERR_ADDR			(RPMSG_ERROR_BASE - 7)
45 #define RPMSG_ERR_PERM			(RPMSG_ERROR_BASE - 8)
46 #define RPMSG_EOPNOTSUPP		(RPMSG_ERROR_BASE - 9)
47 
48 struct rpmsg_endpoint;
49 struct rpmsg_device;
50 
51 /* Returns positive value on success or negative error value on failure */
52 typedef int (*rpmsg_ept_cb)(struct rpmsg_endpoint *ept, void *data,
53 			    size_t len, uint32_t src, void *priv);
54 typedef void (*rpmsg_ept_release_cb)(struct rpmsg_endpoint *ept);
55 typedef void (*rpmsg_ns_unbind_cb)(struct rpmsg_endpoint *ept);
56 typedef void (*rpmsg_ns_bind_cb)(struct rpmsg_device *rdev,
57 				 const char *name, uint32_t dest);
58 
59 /**
60  * @brief Structure that binds a local RPMsg address to its user
61  *
62  * In essence, an RPMsg endpoint represents a listener on the RPMsg bus, as
63  * it binds an RPMsg address with an rx callback handler.
64  */
65 struct rpmsg_endpoint {
66 	/** Name of the service supported */
67 	char name[RPMSG_NAME_SIZE];
68 
69 	/** Pointer to the RPMsg device */
70 	struct rpmsg_device *rdev;
71 
72 	/** Local address of the endpoint */
73 	uint32_t addr;
74 
75 	/** Address of the default remote endpoint binded */
76 	uint32_t dest_addr;
77 
78 	/** Reference count for determining whether the endpoint can be deallocated */
79 	uint32_t refcnt;
80 
81 	/** Callback to inform the user that the endpoint allocation can be safely removed */
82 	rpmsg_ept_release_cb release_cb;
83 
84 	/**
85 	 * User rx callback, return value of this callback is reserved for future
86 	 * use, for now, only allow RPMSG_SUCCESS as return value
87 	 */
88 	rpmsg_ept_cb cb;
89 
90 	/** Endpoint service unbind callback, called when remote ept is destroyed */
91 	rpmsg_ns_unbind_cb ns_unbind_cb;
92 
93 	/** Endpoint node */
94 	struct metal_list node;
95 
96 	/** Private data for the driver's use */
97 	void *priv;
98 };
99 
100 /** @brief RPMsg device operations */
101 struct rpmsg_device_ops {
102 	/** Send RPMsg data */
103 	int (*send_offchannel_raw)(struct rpmsg_device *rdev,
104 				   uint32_t src, uint32_t dst,
105 				   const void *data, int len, int wait);
106 
107 	/** Hold RPMsg RX buffer */
108 	void (*hold_rx_buffer)(struct rpmsg_device *rdev, void *rxbuf);
109 
110 	/** Release RPMsg RX buffer */
111 	void (*release_rx_buffer)(struct rpmsg_device *rdev, void *rxbuf);
112 
113 	/** Get RPMsg TX buffer */
114 	void *(*get_tx_payload_buffer)(struct rpmsg_device *rdev,
115 				       uint32_t *len, int wait);
116 
117 	/** Send RPMsg data without copy */
118 	int (*send_offchannel_nocopy)(struct rpmsg_device *rdev,
119 				      uint32_t src, uint32_t dst,
120 				      const void *data, int len);
121 
122 	/** Release RPMsg TX buffer */
123 	int (*release_tx_buffer)(struct rpmsg_device *rdev, void *txbuf);
124 
125 	/** Get RPMsg RX buffer size */
126 	int (*get_rx_buffer_size)(struct rpmsg_device *rdev);
127 
128 	/** Get RPMsg TX buffer size */
129 	int (*get_tx_buffer_size)(struct rpmsg_device *rdev);
130 };
131 
132 /** @brief Representation of a RPMsg device */
133 struct rpmsg_device {
134 	/** List of endpoints */
135 	struct metal_list endpoints;
136 
137 	/** Name service endpoint */
138 	struct rpmsg_endpoint ns_ept;
139 
140 	/** Table endpoint address allocation */
141 	unsigned long bitmap[metal_bitmap_longs(RPMSG_ADDR_BMP_SIZE)];
142 	unsigned int bitnext;
143 
144 	/** Mutex lock for RPMsg management */
145 	metal_mutex_t lock;
146 
147 	/** Callback handler for name service announcement without local epts waiting to bind */
148 	rpmsg_ns_bind_cb ns_bind_cb;
149 
150 	/** Callback handler for name service announcement, called when remote ept is destroyed */
151 	rpmsg_ns_bind_cb ns_unbind_cb;
152 
153 	/** RPMsg device operations */
154 	struct rpmsg_device_ops ops;
155 
156 	/** Create/destroy namespace message */
157 	bool support_ns;
158 };
159 
160 /**
161  * @brief Send a message across to the remote processor,
162  * specifying source and destination address.
163  *
164  * This function sends `data` of length `len` to the remote `dst` address from
165  * the source `src` address.
166  * The message will be sent to the remote processor which the channel belongs
167  * to.
168  *
169  * @param ept	The rpmsg endpoint
170  * @param src	Source endpoint address of the message
171  * @param dst	Destination endpoint address of the message
172  * @param data	Payload of the message
173  * @param len	Length of the payload
174  * @param wait	Boolean value indicating whether to wait on buffers
175  *
176  * @return Number of bytes it has sent or negative error value on failure.
177  */
178 int rpmsg_send_offchannel_raw(struct rpmsg_endpoint *ept, uint32_t src,
179 			      uint32_t dst, const void *data, int len,
180 			      int wait);
181 
182 /**
183  * @brief Send a message across to the remote processor
184  *
185  * This function sends `data` of length `len` based on the `ept`.
186  * The message will be sent to the remote processor which the channel belongs
187  * to, using `ept`'s source and destination addresses.
188  * In case there are no TX buffers available, the function will block until
189  * one becomes available, or a timeout of 15 seconds elapses. When the latter
190  * happens, -ERESTARTSYS is returned.
191  *
192  * @param ept	The rpmsg endpoint
193  * @param data	Payload of the message
194  * @param len	Length of the payload
195  *
196  * @return Number of bytes it has sent or negative error value on failure.
197  */
rpmsg_send(struct rpmsg_endpoint * ept,const void * data,int len)198 static inline int rpmsg_send(struct rpmsg_endpoint *ept, const void *data,
199 			     int len)
200 {
201 	if (!ept)
202 		return RPMSG_ERR_PARAM;
203 
204 	return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data,
205 					 len, true);
206 }
207 
208 /**
209  * @brief Send a message across to the remote processor, specify dst
210  *
211  * This function sends `data` of length `len` to the remote `dst` address.
212  * The message will be sent to the remote processor which the `ept`
213  * channel belongs to, using `ept`'s source address.
214  * In case there are no TX buffers available, the function will block until
215  * one becomes available, or a timeout of 15 seconds elapses. When the latter
216  * happens, -ERESTARTSYS is returned.
217  *
218  * @param ept	The rpmsg endpoint
219  * @param data	Payload of message
220  * @param len	Length of payload
221  * @param dst	Destination address
222  *
223  * @return Number of bytes it has sent or negative error value on failure.
224  */
rpmsg_sendto(struct rpmsg_endpoint * ept,const void * data,int len,uint32_t dst)225 static inline int rpmsg_sendto(struct rpmsg_endpoint *ept, const void *data,
226 			       int len, uint32_t dst)
227 {
228 	if (!ept)
229 		return RPMSG_ERR_PARAM;
230 
231 	return rpmsg_send_offchannel_raw(ept, ept->addr, dst, data, len, true);
232 }
233 
234 /**
235  * @brief Send a message using explicit src/dst addresses
236  *
237  * This function sends `data` of length `len` to the remote `dst` address,
238  * and uses `src` as the source address.
239  * The message will be sent to the remote processor which the `ept`
240  * channel belongs to.
241  * In case there are no TX buffers available, the function will block until
242  * one becomes available, or a timeout of 15 seconds elapses. When the latter
243  * happens, -ERESTARTSYS is returned.
244  *
245  * @param ept	The rpmsg endpoint
246  * @param src	Source address
247  * @param dst	Destination address
248  * @param data	Payload of message
249  * @param len	Length of payload
250  *
251  * @return Number of bytes it has sent or negative error value on failure.
252  */
rpmsg_send_offchannel(struct rpmsg_endpoint * ept,uint32_t src,uint32_t dst,const void * data,int len)253 static inline int rpmsg_send_offchannel(struct rpmsg_endpoint *ept,
254 					uint32_t src, uint32_t dst,
255 					const void *data, int len)
256 {
257 	return rpmsg_send_offchannel_raw(ept, src, dst, data, len, true);
258 }
259 
260 /**
261  * @brief Send a message across to the remote processor
262  *
263  * This function sends `data` of length `len` on the `ept` channel.
264  * The message will be sent to the remote processor which the `ept`
265  * channel belongs to, using `ept`'s source and destination addresses.
266  * In case there are no TX buffers available, the function will immediately
267  * return -ENOMEM without waiting until one becomes available.
268  *
269  * @param ept	The rpmsg endpoint
270  * @param data	Payload of message
271  * @param len	Length of payload
272  *
273  * @return Number of bytes it has sent or negative error value on failure.
274  */
rpmsg_trysend(struct rpmsg_endpoint * ept,const void * data,int len)275 static inline int rpmsg_trysend(struct rpmsg_endpoint *ept, const void *data,
276 				int len)
277 {
278 	if (!ept)
279 		return RPMSG_ERR_PARAM;
280 
281 	return rpmsg_send_offchannel_raw(ept, ept->addr, ept->dest_addr, data,
282 					 len, false);
283 }
284 
285 /**
286  * @brief Send a message across to the remote processor, specify dst
287  *
288  * This function sends `data` of length `len` to the remote `dst` address.
289  * The message will be sent to the remote processor which the `ept`
290  * channel belongs to, using `ept`'s source address.
291  * In case there are no TX buffers available, the function will immediately
292  * return -ENOMEM without waiting until one becomes available.
293  *
294  * @param ept	The rpmsg endpoint
295  * @param data	Payload of message
296  * @param len	Length of payload
297  * @param dst	Destination address
298  *
299  * @return Number of bytes it has sent or negative error value on failure.
300  */
rpmsg_trysendto(struct rpmsg_endpoint * ept,const void * data,int len,uint32_t dst)301 static inline int rpmsg_trysendto(struct rpmsg_endpoint *ept, const void *data,
302 				  int len, uint32_t dst)
303 {
304 	if (!ept)
305 		return RPMSG_ERR_PARAM;
306 
307 	return rpmsg_send_offchannel_raw(ept, ept->addr, dst, data, len, false);
308 }
309 
310 /**
311  * @brief Send a message using explicit src/dst addresses
312  *
313  * This function sends `data` of length `len` to the remote `dst` address,
314  * and uses `src` as the source address.
315  * The message will be sent to the remote processor which the `ept`
316  * channel belongs to.
317  * In case there are no TX buffers available, the function will immediately
318  * return -ENOMEM without waiting until one becomes available.
319  *
320  * @param ept	The rpmsg endpoint
321  * @param src	Source address
322  * @param dst	Destination address
323  * @param data	Payload of message
324  * @param len	Length of payload
325  *
326  * @return Number of bytes it has sent or negative error value on failure.
327  */
rpmsg_trysend_offchannel(struct rpmsg_endpoint * ept,uint32_t src,uint32_t dst,const void * data,int len)328 static inline int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept,
329 					   uint32_t src, uint32_t dst,
330 					   const void *data, int len)
331 {
332 	return rpmsg_send_offchannel_raw(ept, src, dst, data, len, false);
333 }
334 
335 /**
336  * @brief Holds the rx buffer for usage outside the receive callback.
337  *
338  * Calling this function prevents the RPMsg receive buffer from being released
339  * back to the pool of shmem buffers. This API can only be called at rx
340  * callback context (rpmsg_rx_cb_t). With this API, the application doesn't
341  * need to copy the message in rx callback. Instead, the rx buffer base address
342  * is saved in application context and further processed in application
343  * process. After the message is processed, the application can release the rx
344  * buffer for future reuse in vring by calling the rpmsg_release_rx_buffer()
345  * function.
346  *
347  * @param ept	The rpmsg endpoint
348  * @param rxbuf RX buffer with message payload
349  *
350  * @see rpmsg_release_rx_buffer
351  */
352 void rpmsg_hold_rx_buffer(struct rpmsg_endpoint *ept, void *rxbuf);
353 
354 /**
355  * @brief Releases the rx buffer for future reuse in vring.
356  *
357  * This API can be called at process context when the message in rx buffer is
358  * processed.
359  *
360  * @param ept	The rpmsg endpoint
361  * @param rxbuf	rx buffer with message payload
362  *
363  * @see rpmsg_hold_rx_buffer
364  */
365 void rpmsg_release_rx_buffer(struct rpmsg_endpoint *ept, void *rxbuf);
366 
367 /**
368  * @brief Gets the tx buffer for message payload.
369  *
370  * This API can only be called at process context to get the tx buffer in vring.
371  * By this way, the application can directly put its message into the vring tx
372  * buffer without copy from an application buffer.
373  * It is the application responsibility to correctly fill the allocated tx
374  * buffer by data and passing correct parameters to the rpmsg_send_nocopy() or
375  * rpmsg_sendto_nocopy() function to perform data no-copy-send mechanism.
376  *
377  * @param ept	Pointer to rpmsg endpoint
378  * @param len	Pointer to store tx buffer size
379  * @param wait	Boolean, wait or not for buffer to become available
380  *
381  * @return The tx buffer address on success and NULL on failure
382  *
383  * @see rpmsg_send_offchannel_nocopy
384  * @see rpmsg_sendto_nocopy
385  * @see rpmsg_send_nocopy
386  */
387 void *rpmsg_get_tx_payload_buffer(struct rpmsg_endpoint *ept,
388 				  uint32_t *len, int wait);
389 
390 /**
391  * @brief Releases unused buffer.
392  *
393  * This API can be called when the Tx buffer reserved by
394  * rpmsg_get_tx_payload_buffer needs to be released without having been sent to
395  * the remote side.
396  *
397  * Note that the rpmsg virtio is not able to detect if a buffer has already
398  * been released. The user must prevent a double release (e.g. by resetting its
399  * buffer pointer to zero after the release).
400  *
401  * @param ept	The rpmsg endpoint
402  * @param txbuf	tx buffer with message payload
403  *
404  * @return
405  *   - RPMSG_SUCCESS on success
406  *   - RPMSG_ERR_PARAM on invalid parameter
407  *   - RPMSG_ERR_PERM if service not implemented
408  *
409  * @see rpmsg_get_tx_payload_buffer
410  */
411 int rpmsg_release_tx_buffer(struct rpmsg_endpoint *ept, void *txbuf);
412 
413 /**
414  * @brief Get RPMsg Tx buffer size
415  *
416  * @param ept	The rpmsg endpoint
417  *
418  * @return
419  *   - Next available Tx buffer size on success
420  *   - RPMSG_ERR_PARAM on invalid parameter
421  *   - RPMSG_ERR_PERM if service not implemented
422  */
423 int rpmsg_get_tx_buffer_size(struct rpmsg_endpoint *ept);
424 
425 /**
426  * @brief Get RPMsg Rx buffer size
427  *
428  * @param ept	The rpmsg endpoint
429  *
430  * @return
431  *   - Next available Rx buffer size on success
432  *   - RPMSG_ERR_PARAM on invalid parameter
433  *   - RPMSG_ERR_PERM if service not implemented
434  */
435 int rpmsg_get_rx_buffer_size(struct rpmsg_endpoint *ept);
436 
437 /**
438  * @brief Send a message in tx buffer reserved by
439  * rpmsg_get_tx_payload_buffer() across to the remote processor.
440  *
441  * This function sends buf of length len to the remote dst address,
442  * and uses src as the source address.
443  * The message will be sent to the remote processor which the ept
444  * endpoint belongs to.
445  * The application has to take the responsibility for:
446  *  1. tx buffer reserved (rpmsg_get_tx_payload_buffer() )
447  *  2. filling the data to be sent into the pre-allocated tx buffer
448  *  3. not exceeding the buffer size when filling the data
449  *  4. data cache coherency
450  *
451  * After the rpmsg_send_offchannel_nocopy() function is issued the tx buffer is
452  * no more owned by the sending task and must not be touched anymore unless the
453  * rpmsg_send_offchannel_nocopy() function fails and returns an error. In that
454  * case application should try to re-issue the rpmsg_send_offchannel_nocopy()
455  * again.
456  *
457  * @param ept	The rpmsg endpoint
458  * @param src	The rpmsg endpoint local address
459  * @param dst	The rpmsg endpoint remote address
460  * @param data	TX buffer with message filled
461  * @param len	Length of payload
462  *
463  * @return Number of bytes it has sent or negative error value on failure.
464  *
465  * @see rpmsg_get_tx_payload_buffer
466  * @see rpmsg_sendto_nocopy
467  * @see rpmsg_send_nocopy
468  */
469 int rpmsg_send_offchannel_nocopy(struct rpmsg_endpoint *ept, uint32_t src,
470 				 uint32_t dst, const void *data, int len);
471 
472 /**
473  * @brief Sends a message in tx buffer allocated by
474  * rpmsg_get_tx_payload_buffer() across to the remote processor, specify dst.
475  *
476  * This function sends buf of length len to the remote dst address.
477  * The message will be sent to the remote processor which the ept
478  * endpoint belongs to, using ept's source address.
479  * The application has to take the responsibility for:
480  *  1. tx buffer allocation (rpmsg_get_tx_payload_buffer() )
481  *  2. filling the data to be sent into the pre-allocated tx buffer
482  *  3. not exceeding the buffer size when filling the data
483  *  4. data cache coherency
484  *
485  * After the rpmsg_sendto_nocopy() function is issued the tx buffer is no more
486  * owned by the sending task and must not be touched anymore unless the
487  * rpmsg_sendto_nocopy() function fails and returns an error. In that case the
488  * application should try to re-issue the rpmsg_sendto_nocopy() again.
489  *
490  * @param ept	The rpmsg endpoint
491  * @param data	TX buffer with message filled
492  * @param len	Length of payload
493  * @param dst	Destination address
494  *
495  * @return Number of bytes it has sent or negative error value on failure.
496  *
497  * @see rpmsg_get_tx_payload_buffer
498  * @see rpmsg_send_offchannel_nocopy
499  * @see rpmsg_send_nocopy
500  */
rpmsg_sendto_nocopy(struct rpmsg_endpoint * ept,const void * data,int len,uint32_t dst)501 static inline int rpmsg_sendto_nocopy(struct rpmsg_endpoint *ept,
502 				      const void *data, int len, uint32_t dst)
503 {
504 	if (!ept)
505 		return RPMSG_ERR_PARAM;
506 
507 	return rpmsg_send_offchannel_nocopy(ept, ept->addr, dst, data, len);
508 }
509 
510 /**
511  * @brief Send a message in tx buffer reserved by
512  * rpmsg_get_tx_payload_buffer() across to the remote processor.
513  *
514  * This function sends buf of length len on the ept endpoint.
515  * The message will be sent to the remote processor which the ept
516  * endpoint belongs to, using ept's source and destination addresses.
517  * The application has to take the responsibility for:
518  *  1. tx buffer reserved (rpmsg_get_tx_payload_buffer() )
519  *  2. filling the data to be sent into the pre-allocated tx buffer
520  *  3. not exceeding the buffer size when filling the data
521  *  4. data cache coherency
522  *
523  * After the rpmsg_send_nocopy() function is issued the tx buffer is no more
524  * owned by the sending task and must not be touched anymore unless the
525  * rpmsg_send_nocopy() function fails and returns an error. In that case the
526  * application should try to re-issue the rpmsg_send_nocopy() again.
527  *
528  * @param ept	The rpmsg endpoint
529  * @param data	TX buffer with message filled
530  * @param len	Length of payload
531  *
532  * @return Number of bytes it has sent or negative error value on failure.
533  *
534  * @see rpmsg_get_tx_payload_buffer
535  * @see rpmsg_send_offchannel_nocopy
536  * @see rpmsg_sendto_nocopy
537  */
rpmsg_send_nocopy(struct rpmsg_endpoint * ept,const void * data,int len)538 static inline int rpmsg_send_nocopy(struct rpmsg_endpoint *ept,
539 				    const void *data, int len)
540 {
541 	if (!ept)
542 		return RPMSG_ERR_PARAM;
543 
544 	return rpmsg_send_offchannel_nocopy(ept, ept->addr,
545 					    ept->dest_addr, data, len);
546 }
547 
548 /**
549  * @brief Create rpmsg endpoint and register it to rpmsg device
550  *
551  * Create a RPMsg endpoint, initialize it with a name, source address,
552  * remoteproc address, endpoint callback, and destroy endpoint callback,
553  * and register it to the RPMsg device.
554  *
555  * In essence, an rpmsg endpoint represents a listener on the rpmsg bus, as
556  * it binds an rpmsg address with an rx callback handler.
557  *
558  * Rpmsg client should create an endpoint to discuss with remote. rpmsg client
559  * provide at least a channel name, a callback for message notification and by
560  * default endpoint source address should be set to RPMSG_ADDR_ANY.
561  *
562  * As an option Some rpmsg clients can specify an endpoint with a specific
563  * source address.
564  *
565  * @param ept		Pointer to rpmsg endpoint
566  * @param rdev		RPMsg device associated with the endpoint
567  * @param name		Service name associated to the endpoint (maximum size \ref RPMSG_NAME_SIZE)
568  * @param src		Local address of the endpoint
569  * @param dest		Target address of the endpoint
570  * @param cb		Endpoint callback
571  * @param ns_unbind_cb	Endpoint service unbind callback, called when remote
572  *			ept is destroyed.
573  *
574  * @return 0 on success, or negative error value on failure.
575  */
576 int rpmsg_create_ept(struct rpmsg_endpoint *ept, struct rpmsg_device *rdev,
577 		     const char *name, uint32_t src, uint32_t dest,
578 		     rpmsg_ept_cb cb, rpmsg_ns_unbind_cb ns_unbind_cb);
579 
580 /**
581  * @brief Destroy rpmsg endpoint and unregister it from rpmsg device
582  *
583  * It unregisters the rpmsg endpoint from the rpmsg device and calls the
584  * destroy endpoint callback if it is provided.
585  *
586  * @param ept	Pointer to the rpmsg endpoint
587  */
588 void rpmsg_destroy_ept(struct rpmsg_endpoint *ept);
589 
590 /**
591  * @brief Check if the rpmsg endpoint ready to send
592  *
593  * @param ept	Pointer to rpmsg endpoint
594  *
595  * @return 1 if the rpmsg endpoint has both local addr and destination
596  * addr set, 0 otherwise
597  */
is_rpmsg_ept_ready(struct rpmsg_endpoint * ept)598 static inline unsigned int is_rpmsg_ept_ready(struct rpmsg_endpoint *ept)
599 {
600 	return ept && ept->rdev && ept->dest_addr != RPMSG_ADDR_ANY;
601 }
602 
603 #if defined __cplusplus
604 }
605 #endif
606 
607 #endif				/* _RPMSG_H_ */
608