On Mon, Oct 18, 2021 at 08:05:00PM -0700, Bjorn Andersson wrote: > On Mon 18 Oct 10:52 PDT 2021, Mathieu Poirier wrote: > > > On Sat, Oct 16, 2021 at 12:01:31AM -0500, Bjorn Andersson wrote: > > > On Mon 11 Oct 13:02 CDT 2021, Mathieu Poirier wrote: > > > > > > > Good day Deepak, > > > > > > > > On Thu, Sep 30, 2021 at 09:02:01PM +0530, Deepak Kumar Singh wrote: > > > > > Some transports like Glink support the state notifications between > > > > > clients using signals similar to serial protocol signals. > > > > > Local glink client drivers can send and receive signals to glink > > > > > clients running on remote processors. > > > > > > > > > > Add apis to support sending and receiving of signals by rpmsg clients. > > > > > > > > > > Signed-off-by: Deepak Kumar Singh <deesin@xxxxxxxxxxxxxx> > > > > > --- > > > > > drivers/rpmsg/rpmsg_core.c | 21 +++++++++++++++++++++ > > > > > drivers/rpmsg/rpmsg_internal.h | 2 ++ > > > > > include/linux/rpmsg.h | 15 +++++++++++++++ > > > > > 3 files changed, 38 insertions(+) > > > > > > > > > > diff --git a/drivers/rpmsg/rpmsg_core.c b/drivers/rpmsg/rpmsg_core.c > > > > > index 9151836..5cae50c 100644 > > > > > --- a/drivers/rpmsg/rpmsg_core.c > > > > > +++ b/drivers/rpmsg/rpmsg_core.c > > > > > @@ -327,6 +327,24 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, > > > > > } > > > > > EXPORT_SYMBOL(rpmsg_trysend_offchannel); > > > > > > > > > > +/** > > > > > + * rpmsg_set_flow_control() - sets/clears searial flow control signals > > > > > + * @ept: the rpmsg endpoint > > > > > + * @enable: enable or disable serial flow control > > > > > + * > > > > > + * Returns 0 on success and an appropriate error value on failure. > > > > > + */ > > > > > +int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool enable) > > > > > +{ > > > > > + if (WARN_ON(!ept)) > > > > > + return -EINVAL; > > > > > + if (!ept->ops->set_flow_control) > > > > > + return -ENXIO; > > > > > + > > > > > + return ept->ops->set_flow_control(ept, enable); > > > > > +} > > > > > +EXPORT_SYMBOL(rpmsg_set_flow_control); > > > > > + > > > > > > > > I'm looking at this patchset as the introduction of an out-of-bound > > > > control interface. But looking at the implementation of the GLINK's > > > > set_flow_control() the data is sent in-band, making me perplexed about > > > > introducing a new rpmsg_endpoint_ops for something that could be done > > > > from user space. Especially when user space is triggering the message > > > > with an ioctl in patch 3. > > > > > > > > > > GLINK is built around one fifo per processor pair, similar to a > > > virtqueue. So the signal request is muxed in the same pipe as data > > > requests, but the signal goes alongside data request, not within them. > > > > > > > I reflected more on this and I can see scenarios where sending control flow > > messages alongside other data packet could be the only solution. How the signal > > is implemented is a platform specific choice. I believe the same kind of > > delivery mechanism implemented by kick() functions would be the best way to go > > but if that isn't possible then in-band, as suggested in this patchset, is > > better than nothing. > > > > > > Moreover this interface is case specific and doesn't reflect the > > > > generic nature found in ept->sig_cb. > > > > > > > > > > The previous proposal from Deepak was to essentially expose the normal > > > tty flags all the way down to the rpmsg driver. But I wasn't sure how > > > those various flags should be interpreted in the typical rpmsg driver. > > > > That is interesting. I was hoping to keep the user level signal interfaces > > generic and let the drivers do as they please with them. I see your point > > though and this might be one of those cases where there isn't a right or wrong > > answer. > > > > I'm definitely in favor of something generic, my objection was simply to > inherit the tty interface as that generic thing. > > If nothing else I myself have a hard time understanding the actual > meaning of those bits and tend to have to look them up every time. > > > > > > > I therefor asked Deepak to change it so the rpmsg api would contain a > > > single "pause incoming data"/"resume incoming data" - given that this is > > > a wish that we've seen in a number of discussions. > > > > > > > This will work for as long as we have a single usecase for it, i.e flow control. > > I fear things will quickly get out of hands when more messages are needed, hence > > the idea of keeping things as generic as possible. > > > > Do you have any other types of signals in mind? > I currently don't have anything in mind but I know it will happen at one point, hence hoping to proceed differently than having one ioctl per signal. > > > > > > Unfortunately I don't have any good suggestion for how we could > > > implement this in the virtio backend at this time, but with the muxing > > > of all the different channels in the same virtqueue it would be good for > > > a driver to able to pause the inflow on a specific endpoint, to avoid > > > stalling other communication when a driver can't receive more messages. > > > > Humm... > > > > For application to remote processor things would work the same as it does for > > GLINK, whether the communication is done from a rpmsg_driver (as in > > rpmsg_client_sample.c) or from user space via something like the rpmsg_char.c > > driver. > > > > For remote processor to application processor the interruptions would need to > > carry the destination address of the endpoint, which might not be possible. > > > > All this discussion proves that we really need to think about this before moving > > forward, especially with Arnaud's ongoing refactoring of the rpmsg_char driver. > > > > The concept of flow control comes pretty natural in both GLINK and SMD, > given that an endpoint is the local representation of an established > link to an entity on the other side - while in virtio rpmsg endpoints > doesn't really have a state and a limited sense of there being something > on the other side. > > So I agree that flow controlling in virtio rpmsg could have unforeseen > consequences e.g. by a service being blocked forever because it's > waiting for "flow resume" from an endpoint that never existed. > > But I believe the impact of this is that we need to accept that there > will be cases where the flow control requests can't be fulfilled; such > as a loose rpmsg_endpoint without a predefined dst address or when > communicating with a remote that predates the protocol extensions that > will be necessary. > > Regards, > Bjorn > > > Thanks, > > Mathieu > > > > > > > > Regards, > > > Bjorn > > > > > > > > /* > > > > > * match a rpmsg channel with a channel info struct. > > > > > * this is used to make sure we're not creating rpmsg devices for channels > > > > > @@ -514,6 +532,9 @@ static int rpmsg_dev_probe(struct device *dev) > > > > > > > > > > rpdev->ept = ept; > > > > > rpdev->src = ept->addr; > > > > > + > > > > > + if (rpdrv->signals) > > > > > + ept->sig_cb = rpdrv->signals; > > > > > } > > > > > > > > > > err = rpdrv->probe(rpdev); > > > > > diff --git a/drivers/rpmsg/rpmsg_internal.h b/drivers/rpmsg/rpmsg_internal.h > > > > > index a76c344..dcb2ec1 100644 > > > > > --- a/drivers/rpmsg/rpmsg_internal.h > > > > > +++ b/drivers/rpmsg/rpmsg_internal.h > > > > > @@ -53,6 +53,7 @@ struct rpmsg_device_ops { > > > > > * @trysendto: see @rpmsg_trysendto(), optional > > > > > * @trysend_offchannel: see @rpmsg_trysend_offchannel(), optional > > > > > * @poll: see @rpmsg_poll(), optional > > > > > + * @set_flow_control: see @rpmsg_set_flow_control(), optional > > > > > * > > > > > * Indirection table for the operations that a rpmsg backend should implement. > > > > > * In addition to @destroy_ept, the backend must at least implement @send and > > > > > @@ -72,6 +73,7 @@ struct rpmsg_endpoint_ops { > > > > > void *data, int len); > > > > > __poll_t (*poll)(struct rpmsg_endpoint *ept, struct file *filp, > > > > > poll_table *wait); > > > > > + int (*set_flow_control)(struct rpmsg_endpoint *ept, bool enable); > > > > > }; > > > > > > > > > > struct device *rpmsg_find_device(struct device *parent, > > > > > diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h > > > > > index d97dcd0..b805c70 100644 > > > > > --- a/include/linux/rpmsg.h > > > > > +++ b/include/linux/rpmsg.h > > > > > @@ -62,12 +62,14 @@ struct rpmsg_device { > > > > > }; > > > > > > > > > > typedef int (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32); > > > > > +typedef int (*rpmsg_rx_sig_t)(struct rpmsg_device *, 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 > > > > > + * @sig_cb: rx serial signal handler > > > > > * @cb_lock: must be taken before accessing/changing @cb > > > > > * @addr: local rpmsg address > > > > > * @priv: private data for the driver's use > > > > > @@ -90,6 +92,7 @@ struct rpmsg_endpoint { > > > > > struct rpmsg_device *rpdev; > > > > > struct kref refcount; > > > > > rpmsg_rx_cb_t cb; > > > > > + rpmsg_rx_sig_t sig_cb; > > > > > struct mutex cb_lock; > > > > > u32 addr; > > > > > void *priv; > > > > > @@ -104,6 +107,7 @@ struct rpmsg_endpoint { > > > > > * @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 > > > > > + * @signals: invoked when a serial signal change is received on the channel > > > > > */ > > > > > struct rpmsg_driver { > > > > > struct device_driver drv; > > > > > @@ -111,6 +115,7 @@ struct rpmsg_driver { > > > > > int (*probe)(struct rpmsg_device *dev); > > > > > void (*remove)(struct rpmsg_device *dev); > > > > > int (*callback)(struct rpmsg_device *, void *, int, void *, u32); > > > > > + int (*signals)(struct rpmsg_device *rpdev, void *priv, u32); > > > > > }; > > > > > > > > > > static inline u16 rpmsg16_to_cpu(struct rpmsg_device *rpdev, __rpmsg16 val) > > > > > @@ -186,6 +191,8 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst, > > > > > __poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp, > > > > > poll_table *wait); > > > > > > > > > > +int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool enable); > > > > > + > > > > > #else > > > > > > > > > > static inline int rpmsg_register_device(struct rpmsg_device *rpdev) > > > > > @@ -296,6 +303,14 @@ static inline __poll_t rpmsg_poll(struct rpmsg_endpoint *ept, > > > > > return 0; > > > > > } > > > > > > > > > > +static inline int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool enable); > > > > > +{ > > > > > + /* 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 */ > > > > > -- > > > > > The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, > > > > > a Linux Foundation Collaborative Project > > > > >