linux-stable/include/linux/rpmsg.h
Linus Torvalds becc1fb4f3 rpmsg updates for v5.16
For the GLINK implementation this adds support for splitting outgoing
 messages that are too large to fit in the fifo, it introduces the use of
 "read notifications", to avoid polling in the case where the outgoing
 fifo is full and a few bugs are squashed.
 
 The return value of rpmsg_create_ept() for when RPMSG is disabled is
 corrected to return a valid error, the Mediatek rpmsg driver is updated
 to match the DT binding and a couple of cleanups are done in the virtio
 rpmsg driver.
 -----BEGIN PGP SIGNATURE-----
 
 iQJPBAABCAA5FiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAmGJXMkbHGJqb3JuLmFu
 ZGVyc3NvbkBsaW5hcm8ub3JnAAoJEAsfOT8Nma3F1tgP/RNK/m+bsWHDVRvMww1z
 SCC+E4b8vJIceifqvXataO5vMErFyQdTi9ijFNogqIlJF+ouVp/sHmfCCwFG4urw
 /IccreIcBWMoY8+efjomLVvCMEzd1RlSG484yKs4p8Jz7hDgGeDHzQOwe0CsTY/L
 b2Qi6fV6i1/sfK1vlf4dHFA7Y66KwjknvNCasCWkadBSJnJeali9QeRsDYaQCaJL
 C2QirxX7V2rxJZH248MOuG+E0e1oVgccvp9dACbsasfOrsekWc7Twizaqvdl+RxF
 q2YXH82WVClOQgyp09tZ8zk4IIVzzxKZlWL/so7sdiEI009HHNc7YhGkRUdzhzma
 neWPJ6emVUD4Gwgkr2OAkc14wR99iSgdjvN2CcZjOHgBKos2AvjN/JsrGLswVdDU
 PZs4EXzvgw98hOOTpw0X1E8TZvtt3wcUyoXpWop2+pXOs9rajR0lyorlW8ubXhLN
 TpC2Yypy8vY4kBn3Ob/sJlu5CNasMg3a4TFhJBCWIrmS+5MxwOtvAi+i4Omg6754
 075zhFuxXuFdszWqtJHBukHpmhYkK1shexEnkLdPiCwpG2Q9159ILD2TKVIjAOQy
 112o8KSCWcPR0VNoenTunqfw/YiOYmEeIGQBRfsxrFUurmPQMICN+xfei/8vQftg
 D9hxikFXc7JJl+OahXnvSUZv
 =jGA6
 -----END PGP SIGNATURE-----

Merge tag 'rpmsg-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux

Pull rpmsg updates from Bjorn Andersson:
 "For the GLINK implementation this adds support for splitting outgoing
  messages that are too large to fit in the fifo, it introduces the use
  of "read notifications", to avoid polling in the case where the
  outgoing fifo is full and a few bugs are squashed.

  The return value of rpmsg_create_ept() for when RPMSG is disabled is
  corrected to return a valid error, the Mediatek rpmsg driver is
  updated to match the DT binding and a couple of cleanups are done in
  the virtio rpmsg driver"

* tag 'rpmsg-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux:
  rpmsg: glink: Send READ_NOTIFY command in FIFO full case
  rpmsg: glink: Remove channel decouple from rpdev release
  rpmsg: glink: Remove the rpmsg dev in close_ack
  rpmsg: glink: Add TX_DATA_CONT command while sending
  rpmsg: virtio_rpmsg_bus: use dev_warn_ratelimited for msg with no recipient
  rpmsg: virtio: Remove unused including <linux/of_device.h>
  rpmsg: Change naming of mediatek rpmsg property
  rpmsg: Fix rpmsg_create_ept return when RPMSG config is not defined
  rpmsg: glink: Replace strncpy() with strscpy_pad()
2021-11-10 09:05:11 -08:00

327 lines
8.6 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause */
/*
* Remote processor messaging
*
* Copyright (C) 2011 Texas Instruments, Inc.
* Copyright (C) 2011 Google, Inc.
* All rights reserved.
*/
#ifndef _LINUX_RPMSG_H
#define _LINUX_RPMSG_H
#include <linux/types.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/mod_devicetable.h>
#include <linux/kref.h>
#include <linux/mutex.h>
#include <linux/poll.h>
#include <linux/rpmsg/byteorder.h>
#include <uapi/linux/rpmsg.h>
struct rpmsg_device;
struct rpmsg_endpoint;
struct rpmsg_device_ops;
struct rpmsg_endpoint_ops;
/**
* struct rpmsg_channel_info - channel info representation
* @name: name of service
* @src: local address
* @dst: destination address
*/
struct rpmsg_channel_info {
char name[RPMSG_NAME_SIZE];
u32 src;
u32 dst;
};
/**
* rpmsg_device - device that belong to the rpmsg bus
* @dev: the device struct
* @id: device id (used to match between rpmsg drivers and devices)
* @driver_override: driver name to force a match
* @src: local address
* @dst: destination address
* @ept: the rpmsg endpoint of this channel
* @announce: if set, rpmsg will announce the creation/removal of this channel
* @little_endian: True if transport is using little endian byte representation
*/
struct rpmsg_device {
struct device dev;
struct rpmsg_device_id id;
char *driver_override;
u32 src;
u32 dst;
struct rpmsg_endpoint *ept;
bool announce;
bool little_endian;
const struct rpmsg_device_ops *ops;
};
typedef int (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32);
/**
* struct rpmsg_endpoint - binds a local rpmsg address to its user
* @rpdev: rpmsg channel device
* @refcount: when this drops to zero, the ept is deallocated
* @cb: rx callback handler
* @cb_lock: must be taken before accessing/changing @cb
* @addr: local rpmsg address
* @priv: private data for the driver's use
*
* In essence, an rpmsg endpoint represents a listener on the rpmsg bus, as
* it binds an rpmsg address with an rx callback handler.
*
* Simple rpmsg drivers shouldn't use this struct directly, because
* things just work: every rpmsg driver provides an rx callback upon
* registering to the bus, and that callback is then bound to its rpmsg
* address when the driver is probed. When relevant inbound messages arrive
* (i.e. messages which their dst address equals to the src address of
* the rpmsg channel), the driver's handler is invoked to process it.
*
* More complicated drivers though, that do need to allocate additional rpmsg
* addresses, and bind them to different rx callbacks, must explicitly
* create additional endpoints by themselves (see rpmsg_create_ept()).
*/
struct rpmsg_endpoint {
struct rpmsg_device *rpdev;
struct kref refcount;
rpmsg_rx_cb_t cb;
struct mutex cb_lock;
u32 addr;
void *priv;
const struct rpmsg_endpoint_ops *ops;
};
/**
* struct rpmsg_driver - rpmsg driver struct
* @drv: underlying device driver
* @id_table: rpmsg ids serviced by this driver
* @probe: invoked when a matching rpmsg channel (i.e. device) is found
* @remove: invoked when the rpmsg channel is removed
* @callback: invoked when an inbound message is received on the channel
*/
struct rpmsg_driver {
struct device_driver drv;
const struct rpmsg_device_id *id_table;
int (*probe)(struct rpmsg_device *dev);
void (*remove)(struct rpmsg_device *dev);
int (*callback)(struct rpmsg_device *, void *, int, void *, u32);
};
static inline u16 rpmsg16_to_cpu(struct rpmsg_device *rpdev, __rpmsg16 val)
{
if (!rpdev)
return __rpmsg16_to_cpu(rpmsg_is_little_endian(), val);
else
return __rpmsg16_to_cpu(rpdev->little_endian, val);
}
static inline __rpmsg16 cpu_to_rpmsg16(struct rpmsg_device *rpdev, u16 val)
{
if (!rpdev)
return __cpu_to_rpmsg16(rpmsg_is_little_endian(), val);
else
return __cpu_to_rpmsg16(rpdev->little_endian, val);
}
static inline u32 rpmsg32_to_cpu(struct rpmsg_device *rpdev, __rpmsg32 val)
{
if (!rpdev)
return __rpmsg32_to_cpu(rpmsg_is_little_endian(), val);
else
return __rpmsg32_to_cpu(rpdev->little_endian, val);
}
static inline __rpmsg32 cpu_to_rpmsg32(struct rpmsg_device *rpdev, u32 val)
{
if (!rpdev)
return __cpu_to_rpmsg32(rpmsg_is_little_endian(), val);
else
return __cpu_to_rpmsg32(rpdev->little_endian, val);
}
static inline u64 rpmsg64_to_cpu(struct rpmsg_device *rpdev, __rpmsg64 val)
{
if (!rpdev)
return __rpmsg64_to_cpu(rpmsg_is_little_endian(), val);
else
return __rpmsg64_to_cpu(rpdev->little_endian, val);
}
static inline __rpmsg64 cpu_to_rpmsg64(struct rpmsg_device *rpdev, u64 val)
{
if (!rpdev)
return __cpu_to_rpmsg64(rpmsg_is_little_endian(), val);
else
return __cpu_to_rpmsg64(rpdev->little_endian, val);
}
#if IS_ENABLED(CONFIG_RPMSG)
int rpmsg_register_device(struct rpmsg_device *rpdev);
int rpmsg_unregister_device(struct device *parent,
struct rpmsg_channel_info *chinfo);
int __register_rpmsg_driver(struct rpmsg_driver *drv, struct module *owner);
void unregister_rpmsg_driver(struct rpmsg_driver *drv);
void rpmsg_destroy_ept(struct rpmsg_endpoint *);
struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *,
rpmsg_rx_cb_t cb, void *priv,
struct rpmsg_channel_info chinfo);
int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len);
int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
void *data, int len);
int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len);
int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst);
int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
void *data, int len);
__poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp,
poll_table *wait);
ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept);
#else
static inline int rpmsg_register_device(struct rpmsg_device *rpdev)
{
return -ENXIO;
}
static inline int rpmsg_unregister_device(struct device *parent,
struct rpmsg_channel_info *chinfo)
{
/* This shouldn't be possible */
WARN_ON(1);
return -ENXIO;
}
static inline int __register_rpmsg_driver(struct rpmsg_driver *drv,
struct module *owner)
{
/* This shouldn't be possible */
WARN_ON(1);
return -ENXIO;
}
static inline void unregister_rpmsg_driver(struct rpmsg_driver *drv)
{
/* This shouldn't be possible */
WARN_ON(1);
}
static inline void rpmsg_destroy_ept(struct rpmsg_endpoint *ept)
{
/* This shouldn't be possible */
WARN_ON(1);
}
static inline struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev,
rpmsg_rx_cb_t cb,
void *priv,
struct rpmsg_channel_info chinfo)
{
/* This shouldn't be possible */
WARN_ON(1);
return NULL;
}
static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
{
/* This shouldn't be possible */
WARN_ON(1);
return -ENXIO;
}
static inline int rpmsg_sendto(struct rpmsg_endpoint *ept, void *data, int len,
u32 dst)
{
/* This shouldn't be possible */
WARN_ON(1);
return -ENXIO;
}
static inline int rpmsg_send_offchannel(struct rpmsg_endpoint *ept, u32 src,
u32 dst, void *data, int len)
{
/* This shouldn't be possible */
WARN_ON(1);
return -ENXIO;
}
static inline int rpmsg_trysend(struct rpmsg_endpoint *ept, void *data, int len)
{
/* This shouldn't be possible */
WARN_ON(1);
return -ENXIO;
}
static inline int rpmsg_trysendto(struct rpmsg_endpoint *ept, void *data,
int len, u32 dst)
{
/* This shouldn't be possible */
WARN_ON(1);
return -ENXIO;
}
static inline int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src,
u32 dst, void *data, int len)
{
/* This shouldn't be possible */
WARN_ON(1);
return -ENXIO;
}
static inline __poll_t rpmsg_poll(struct rpmsg_endpoint *ept,
struct file *filp, poll_table *wait)
{
/* This shouldn't be possible */
WARN_ON(1);
return 0;
}
static inline ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept)
{
/* This shouldn't be possible */
WARN_ON(1);
return -ENXIO;
}
#endif /* IS_ENABLED(CONFIG_RPMSG) */
/* use a macro to avoid include chaining to get THIS_MODULE */
#define register_rpmsg_driver(drv) \
__register_rpmsg_driver(drv, THIS_MODULE)
/**
* module_rpmsg_driver() - Helper macro for registering an rpmsg driver
* @__rpmsg_driver: rpmsg_driver struct
*
* Helper macro for rpmsg drivers which do not do anything special in module
* init/exit. This eliminates a lot of boilerplate. Each module may only
* use this macro once, and calling it replaces module_init() and module_exit()
*/
#define module_rpmsg_driver(__rpmsg_driver) \
module_driver(__rpmsg_driver, register_rpmsg_driver, \
unregister_rpmsg_driver)
#endif /* _LINUX_RPMSG_H */