@@ -52,6 +52,8 @@ static DEFINE_IDA(rpmsg_minor_ida);
5252 * @readq: wait object for incoming queue
5353 * @default_ept: set to channel default endpoint if the default endpoint should be re-used
5454 * on device open to prevent endpoint address update.
55+ * remote_flow_restricted: to indicate if the remote has requested for flow to be limited
56+ * remote_flow_updated: to indicate if the flow control has been requested
5557 */
5658struct rpmsg_eptdev {
5759 struct device dev ;
@@ -68,6 +70,8 @@ struct rpmsg_eptdev {
6870 struct sk_buff_head queue ;
6971 wait_queue_head_t readq ;
7072
73+ bool remote_flow_restricted ;
74+ bool remote_flow_updated ;
7175};
7276
7377int rpmsg_chrdev_eptdev_destroy (struct device * dev , void * data )
@@ -116,6 +120,18 @@ static int rpmsg_ept_cb(struct rpmsg_device *rpdev, void *buf, int len,
116120 return 0 ;
117121}
118122
123+ static int rpmsg_ept_flow_cb (struct rpmsg_device * rpdev , void * priv , bool enable )
124+ {
125+ struct rpmsg_eptdev * eptdev = priv ;
126+
127+ eptdev -> remote_flow_restricted = enable ;
128+ eptdev -> remote_flow_updated = true;
129+
130+ wake_up_interruptible (& eptdev -> readq );
131+
132+ return 0 ;
133+ }
134+
119135static int rpmsg_eptdev_open (struct inode * inode , struct file * filp )
120136{
121137 struct rpmsg_eptdev * eptdev = cdev_to_eptdev (inode -> i_cdev );
@@ -152,6 +168,7 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
152168 return - EINVAL ;
153169 }
154170
171+ ept -> flow_cb = rpmsg_ept_flow_cb ;
155172 eptdev -> ept = ept ;
156173 filp -> private_data = eptdev ;
157174 mutex_unlock (& eptdev -> ept_lock );
@@ -172,6 +189,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct file *filp)
172189 eptdev -> ept = NULL ;
173190 }
174191 mutex_unlock (& eptdev -> ept_lock );
192+ eptdev -> remote_flow_updated = false;
175193
176194 /* Discard all SKBs */
177195 skb_queue_purge (& eptdev -> queue );
@@ -285,6 +303,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, poll_table *wait)
285303 if (!skb_queue_empty (& eptdev -> queue ))
286304 mask |= EPOLLIN | EPOLLRDNORM ;
287305
306+ if (eptdev -> remote_flow_updated )
307+ mask |= EPOLLPRI ;
308+
288309 mutex_lock (& eptdev -> ept_lock );
289310 mask |= rpmsg_poll (eptdev -> ept , filp , wait );
290311 mutex_unlock (& eptdev -> ept_lock );
@@ -297,14 +318,35 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
297318{
298319 struct rpmsg_eptdev * eptdev = fp -> private_data ;
299320
300- if ( cmd != RPMSG_DESTROY_EPT_IOCTL )
301- return - EINVAL ;
321+ bool set ;
322+ int ret ;
302323
303- /* Don't allow to destroy a default endpoint. */
304- if (eptdev -> default_ept )
305- return - EINVAL ;
324+ switch (cmd ) {
325+ case RPMSG_GET_OUTGOING_FLOWCONTROL :
326+ eptdev -> remote_flow_updated = false;
327+ ret = put_user (eptdev -> remote_flow_restricted , (int __user * )arg );
328+ break ;
329+ case RPMSG_SET_INCOMING_FLOWCONTROL :
330+ if (arg > 1 ) {
331+ ret = - EINVAL ;
332+ break ;
333+ }
334+ set = !!arg ;
335+ ret = rpmsg_set_flow_control (eptdev -> ept , set , eptdev -> chinfo .dst );
336+ break ;
337+ case RPMSG_DESTROY_EPT_IOCTL :
338+ /* Don't allow to destroy a default endpoint. */
339+ if (eptdev -> default_ept ) {
340+ ret = - EINVAL ;
341+ break ;
342+ }
343+ ret = rpmsg_chrdev_eptdev_destroy (& eptdev -> dev , NULL );
344+ break ;
345+ default :
346+ ret = - EINVAL ;
347+ }
306348
307- return rpmsg_chrdev_eptdev_destroy ( & eptdev -> dev , NULL ) ;
349+ return ret ;
308350}
309351
310352static const struct file_operations rpmsg_eptdev_fops = {
0 commit comments