@@ -52,6 +52,8 @@ static DEFINE_IDA(rpmsg_minor_ida);
52
52
* @readq: wait object for incoming queue
53
53
* @default_ept: set to channel default endpoint if the default endpoint should be re-used
54
54
* 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
55
57
*/
56
58
struct rpmsg_eptdev {
57
59
struct device dev ;
@@ -68,6 +70,8 @@ struct rpmsg_eptdev {
68
70
struct sk_buff_head queue ;
69
71
wait_queue_head_t readq ;
70
72
73
+ bool remote_flow_restricted ;
74
+ bool remote_flow_updated ;
71
75
};
72
76
73
77
int 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,
116
120
return 0 ;
117
121
}
118
122
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
+
119
135
static int rpmsg_eptdev_open (struct inode * inode , struct file * filp )
120
136
{
121
137
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)
152
168
return - EINVAL ;
153
169
}
154
170
171
+ ept -> flow_cb = rpmsg_ept_flow_cb ;
155
172
eptdev -> ept = ept ;
156
173
filp -> private_data = eptdev ;
157
174
mutex_unlock (& eptdev -> ept_lock );
@@ -172,6 +189,7 @@ static int rpmsg_eptdev_release(struct inode *inode, struct file *filp)
172
189
eptdev -> ept = NULL ;
173
190
}
174
191
mutex_unlock (& eptdev -> ept_lock );
192
+ eptdev -> remote_flow_updated = false;
175
193
176
194
/* Discard all SKBs */
177
195
skb_queue_purge (& eptdev -> queue );
@@ -285,6 +303,9 @@ static __poll_t rpmsg_eptdev_poll(struct file *filp, poll_table *wait)
285
303
if (!skb_queue_empty (& eptdev -> queue ))
286
304
mask |= EPOLLIN | EPOLLRDNORM ;
287
305
306
+ if (eptdev -> remote_flow_updated )
307
+ mask |= EPOLLPRI ;
308
+
288
309
mutex_lock (& eptdev -> ept_lock );
289
310
mask |= rpmsg_poll (eptdev -> ept , filp , wait );
290
311
mutex_unlock (& eptdev -> ept_lock );
@@ -297,14 +318,35 @@ static long rpmsg_eptdev_ioctl(struct file *fp, unsigned int cmd,
297
318
{
298
319
struct rpmsg_eptdev * eptdev = fp -> private_data ;
299
320
300
- if ( cmd != RPMSG_DESTROY_EPT_IOCTL )
301
- return - EINVAL ;
321
+ bool set ;
322
+ int ret ;
302
323
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
+ }
306
348
307
- return rpmsg_chrdev_eptdev_destroy ( & eptdev -> dev , NULL ) ;
349
+ return ret ;
308
350
}
309
351
310
352
static const struct file_operations rpmsg_eptdev_fops = {
0 commit comments