Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

Pull rpmsg updates from Bjorn Andersson:
"Add support for the GLINK flow control signals, and expose this to the
user through the rpmsg_char interface. Add missing kstrdup() failure
handling during allocation of GLINK channel objects"

* tag 'rpmsg-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux:
rpmsg: glink: Avoid dereferencing NULL channel
rpmsg: glink: Add check for kstrdup
rpmsg: char: Add RPMSG GET/SET FLOWCONTROL IOCTL support
rpmsg: glink: Add support to handle signals command
rpmsg: core: Add signal API support

+157 -6
+48 -6
drivers/rpmsg/rpmsg_char.c
··· 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; ··· 70 68 struct sk_buff_head queue; 71 69 wait_queue_head_t readq; 72 70 71 + bool remote_flow_restricted; 72 + bool remote_flow_updated; 73 73 }; 74 74 75 75 int rpmsg_chrdev_eptdev_destroy(struct device *dev, void *data) ··· 120 116 return 0; 121 117 } 122 118 119 + static int rpmsg_ept_flow_cb(struct rpmsg_device *rpdev, void *priv, bool enable) 120 + { 121 + struct rpmsg_eptdev *eptdev = priv; 122 + 123 + eptdev->remote_flow_restricted = enable; 124 + eptdev->remote_flow_updated = true; 125 + 126 + wake_up_interruptible(&eptdev->readq); 127 + 128 + return 0; 129 + } 130 + 123 131 static int rpmsg_eptdev_open(struct inode *inode, struct file *filp) 124 132 { 125 133 struct rpmsg_eptdev *eptdev = cdev_to_eptdev(inode->i_cdev); ··· 168 152 return -EINVAL; 169 153 } 170 154 155 + ept->flow_cb = rpmsg_ept_flow_cb; 171 156 eptdev->ept = ept; 172 157 filp->private_data = eptdev; 173 158 mutex_unlock(&eptdev->ept_lock); ··· 189 172 eptdev->ept = NULL; 190 173 } 191 174 mutex_unlock(&eptdev->ept_lock); 175 + eptdev->remote_flow_updated = false; 192 176 193 177 /* Discard all SKBs */ 194 178 skb_queue_purge(&eptdev->queue); ··· 303 285 if (!skb_queue_empty(&eptdev->queue)) 304 286 mask |= EPOLLIN | EPOLLRDNORM; 305 287 288 + if (eptdev->remote_flow_updated) 289 + mask |= EPOLLPRI; 290 + 306 291 mutex_lock(&eptdev->ept_lock); 307 292 mask |= rpmsg_poll(eptdev->ept, filp, wait); 308 293 mutex_unlock(&eptdev->ept_lock); ··· 318 297 { 319 298 struct rpmsg_eptdev *eptdev = fp->private_data; 320 299 321 - if (cmd != RPMSG_DESTROY_EPT_IOCTL) 322 - return -EINVAL; 300 + bool set; 301 + int ret; 323 302 324 - /* Don't allow to destroy a default endpoint. */ 325 - if (eptdev->default_ept) 326 - return -EINVAL; 303 + switch (cmd) { 304 + case RPMSG_GET_OUTGOING_FLOWCONTROL: 305 + eptdev->remote_flow_updated = false; 306 + ret = put_user(eptdev->remote_flow_restricted, (int __user *)arg); 307 + break; 308 + case RPMSG_SET_INCOMING_FLOWCONTROL: 309 + if (arg > 1) { 310 + ret = -EINVAL; 311 + break; 312 + } 313 + set = !!arg; 314 + ret = rpmsg_set_flow_control(eptdev->ept, set, eptdev->chinfo.dst); 315 + break; 316 + case RPMSG_DESTROY_EPT_IOCTL: 317 + /* Don't allow to destroy a default endpoint. */ 318 + if (eptdev->default_ept) { 319 + ret = -EINVAL; 320 + break; 321 + } 322 + ret = rpmsg_chrdev_eptdev_destroy(&eptdev->dev, NULL); 323 + break; 324 + default: 325 + ret = -EINVAL; 326 + } 327 327 328 - return rpmsg_chrdev_eptdev_destroy(&eptdev->dev, NULL); 328 + return ret; 329 329 } 330 330 331 331 static const struct file_operations rpmsg_eptdev_fops = {
+21
drivers/rpmsg/rpmsg_core.c
··· 331 331 EXPORT_SYMBOL(rpmsg_trysend_offchannel); 332 332 333 333 /** 334 + * rpmsg_set_flow_control() - request remote to pause/resume transmission 335 + * @ept: the rpmsg endpoint 336 + * @pause: pause transmission 337 + * @dst: destination address of the endpoint 338 + * 339 + * Return: 0 on success and an appropriate error value on failure. 340 + */ 341 + int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool pause, u32 dst) 342 + { 343 + if (WARN_ON(!ept)) 344 + return -EINVAL; 345 + if (!ept->ops->set_flow_control) 346 + return -EOPNOTSUPP; 347 + 348 + return ept->ops->set_flow_control(ept, pause, dst); 349 + } 350 + EXPORT_SYMBOL_GPL(rpmsg_set_flow_control); 351 + 352 + /** 334 353 * rpmsg_get_mtu() - get maximum transmission buffer size for sending message. 335 354 * @ept: the rpmsg endpoint 336 355 * ··· 558 539 559 540 rpdev->ept = ept; 560 541 rpdev->src = ept->addr; 542 + 543 + ept->flow_cb = rpdrv->flowcontrol; 561 544 } 562 545 563 546 err = rpdrv->probe(rpdev);
+2
drivers/rpmsg/rpmsg_internal.h
··· 55 55 * @trysendto: see @rpmsg_trysendto(), optional 56 56 * @trysend_offchannel: see @rpmsg_trysend_offchannel(), optional 57 57 * @poll: see @rpmsg_poll(), optional 58 + * @set_flow_control: see @rpmsg_set_flow_control(), optional 58 59 * @get_mtu: see @rpmsg_get_mtu(), optional 59 60 * 60 61 * Indirection table for the operations that a rpmsg backend should implement. ··· 76 75 void *data, int len); 77 76 __poll_t (*poll)(struct rpmsg_endpoint *ept, struct file *filp, 78 77 poll_table *wait); 78 + int (*set_flow_control)(struct rpmsg_endpoint *ept, bool pause, u32 dst); 79 79 ssize_t (*get_mtu)(struct rpmsg_endpoint *ept); 80 80 }; 81 81
+15
include/linux/rpmsg.h
··· 64 64 }; 65 65 66 66 typedef int (*rpmsg_rx_cb_t)(struct rpmsg_device *, void *, int, void *, u32); 67 + typedef int (*rpmsg_flowcontrol_cb_t)(struct rpmsg_device *, void *, bool); 67 68 68 69 /** 69 70 * struct rpmsg_endpoint - binds a local rpmsg address to its user 70 71 * @rpdev: rpmsg channel device 71 72 * @refcount: when this drops to zero, the ept is deallocated 72 73 * @cb: rx callback handler 74 + * @flow_cb: remote flow control callback handler 73 75 * @cb_lock: must be taken before accessing/changing @cb 74 76 * @addr: local rpmsg address 75 77 * @priv: private data for the driver's use ··· 94 92 struct rpmsg_device *rpdev; 95 93 struct kref refcount; 96 94 rpmsg_rx_cb_t cb; 95 + rpmsg_flowcontrol_cb_t flow_cb; 97 96 struct mutex cb_lock; 98 97 u32 addr; 99 98 void *priv; ··· 109 106 * @probe: invoked when a matching rpmsg channel (i.e. device) is found 110 107 * @remove: invoked when the rpmsg channel is removed 111 108 * @callback: invoked when an inbound message is received on the channel 109 + * @flowcontrol: invoked when remote side flow control request is received 112 110 */ 113 111 struct rpmsg_driver { 114 112 struct device_driver drv; ··· 117 113 int (*probe)(struct rpmsg_device *dev); 118 114 void (*remove)(struct rpmsg_device *dev); 119 115 int (*callback)(struct rpmsg_device *, void *, int, void *, u32); 116 + int (*flowcontrol)(struct rpmsg_device *, void *, bool); 120 117 }; 121 118 122 119 static inline u16 rpmsg16_to_cpu(struct rpmsg_device *rpdev, __rpmsg16 val) ··· 196 191 poll_table *wait); 197 192 198 193 ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept); 194 + 195 + int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool pause, u32 dst); 199 196 200 197 #else 201 198 ··· 316 309 } 317 310 318 311 static inline ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept) 312 + { 313 + /* This shouldn't be possible */ 314 + WARN_ON(1); 315 + 316 + return -ENXIO; 317 + } 318 + 319 + static inline int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool pause, u32 dst) 319 320 { 320 321 /* This shouldn't be possible */ 321 322 WARN_ON(1);
+10
include/uapi/linux/rpmsg.h
··· 43 43 */ 44 44 #define RPMSG_RELEASE_DEV_IOCTL _IOW(0xb5, 0x4, struct rpmsg_endpoint_info) 45 45 46 + /** 47 + * Get the flow control state of the remote rpmsg char device. 48 + */ 49 + #define RPMSG_GET_OUTGOING_FLOWCONTROL _IOR(0xb5, 0x5, int) 50 + 51 + /** 52 + * Set the flow control state of the local rpmsg char device. 53 + */ 54 + #define RPMSG_SET_INCOMING_FLOWCONTROL _IOR(0xb5, 0x6, int) 55 + 46 56 #endif