Re: [PATCH V1 1/3] rpmsg: core: Add signal API support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
> > > > > 



[Index of Archives]     [Linux Sound]     [ALSA Users]     [ALSA Devel]     [Linux Audio Users]     [Linux Media]     [Kernel]     [Photo Sharing]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux