Skip to content

Commit 3d90470

Browse files
committed
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
2 parents e3a6fa0 + d629e5b commit 3d90470

File tree

6 files changed

+157
-6
lines changed

6 files changed

+157
-6
lines changed

drivers/rpmsg/qcom_glink_native.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,15 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops;
200200
#define GLINK_CMD_TX_DATA_CONT 12
201201
#define GLINK_CMD_READ_NOTIF 13
202202
#define GLINK_CMD_RX_DONE_W_REUSE 14
203+
#define GLINK_CMD_SIGNALS 15
203204

204205
#define GLINK_FEATURE_INTENTLESS BIT(1)
205206

207+
#define NATIVE_DTR_SIG NATIVE_DSR_SIG
208+
#define NATIVE_DSR_SIG BIT(31)
209+
#define NATIVE_RTS_SIG NATIVE_CTS_SIG
210+
#define NATIVE_CTS_SIG BIT(30)
211+
206212
static void qcom_glink_rx_done_work(struct work_struct *work);
207213

208214
static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
@@ -221,6 +227,10 @@ static struct glink_channel *qcom_glink_alloc_channel(struct qcom_glink *glink,
221227

222228
channel->glink = glink;
223229
channel->name = kstrdup(name, GFP_KERNEL);
230+
if (!channel->name) {
231+
kfree(channel);
232+
return ERR_PTR(-ENOMEM);
233+
}
224234

225235
init_completion(&channel->open_req);
226236
init_completion(&channel->open_ack);
@@ -1025,6 +1035,52 @@ static int qcom_glink_rx_open_ack(struct qcom_glink *glink, unsigned int lcid)
10251035
return 0;
10261036
}
10271037

1038+
/**
1039+
* qcom_glink_set_flow_control() - convert a signal cmd to wire format and transmit
1040+
* @ept: Rpmsg endpoint for channel.
1041+
* @pause: Pause transmission
1042+
* @dst: destination address of the endpoint
1043+
*
1044+
* Return: 0 on success or standard Linux error code.
1045+
*/
1046+
static int qcom_glink_set_flow_control(struct rpmsg_endpoint *ept, bool pause, u32 dst)
1047+
{
1048+
struct glink_channel *channel = to_glink_channel(ept);
1049+
struct qcom_glink *glink = channel->glink;
1050+
struct glink_msg msg;
1051+
u32 sigs = 0;
1052+
1053+
if (pause)
1054+
sigs |= NATIVE_DTR_SIG | NATIVE_RTS_SIG;
1055+
1056+
msg.cmd = cpu_to_le16(GLINK_CMD_SIGNALS);
1057+
msg.param1 = cpu_to_le16(channel->lcid);
1058+
msg.param2 = cpu_to_le32(sigs);
1059+
1060+
return qcom_glink_tx(glink, &msg, sizeof(msg), NULL, 0, true);
1061+
}
1062+
1063+
static void qcom_glink_handle_signals(struct qcom_glink *glink,
1064+
unsigned int rcid, unsigned int sigs)
1065+
{
1066+
struct glink_channel *channel;
1067+
unsigned long flags;
1068+
bool enable;
1069+
1070+
spin_lock_irqsave(&glink->idr_lock, flags);
1071+
channel = idr_find(&glink->rcids, rcid);
1072+
spin_unlock_irqrestore(&glink->idr_lock, flags);
1073+
if (!channel) {
1074+
dev_err(glink->dev, "signal for non-existing channel\n");
1075+
return;
1076+
}
1077+
1078+
enable = sigs & NATIVE_DSR_SIG || sigs & NATIVE_CTS_SIG;
1079+
1080+
if (channel->ept.flow_cb)
1081+
channel->ept.flow_cb(channel->ept.rpdev, channel->ept.priv, enable);
1082+
}
1083+
10281084
void qcom_glink_native_rx(struct qcom_glink *glink)
10291085
{
10301086
struct glink_msg msg;
@@ -1086,6 +1142,10 @@ void qcom_glink_native_rx(struct qcom_glink *glink)
10861142
qcom_glink_handle_intent_req_ack(glink, param1, param2);
10871143
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
10881144
break;
1145+
case GLINK_CMD_SIGNALS:
1146+
qcom_glink_handle_signals(glink, param1, param2);
1147+
qcom_glink_rx_advance(glink, ALIGN(sizeof(msg), 8));
1148+
break;
10891149
default:
10901150
dev_err(glink->dev, "unhandled rx cmd: %d\n", cmd);
10911151
ret = -EINVAL;
@@ -1446,6 +1506,7 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops = {
14461506
.sendto = qcom_glink_sendto,
14471507
.trysend = qcom_glink_trysend,
14481508
.trysendto = qcom_glink_trysendto,
1509+
.set_flow_control = qcom_glink_set_flow_control,
14491510
};
14501511

14511512
static void qcom_glink_rpdev_release(struct device *dev)

drivers/rpmsg/rpmsg_char.c

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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
*/
5658
struct 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

7377
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,
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+
119135
static 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

310352
static const struct file_operations rpmsg_eptdev_fops = {

drivers/rpmsg/rpmsg_core.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,25 @@ int rpmsg_trysend_offchannel(struct rpmsg_endpoint *ept, u32 src, u32 dst,
330330
}
331331
EXPORT_SYMBOL(rpmsg_trysend_offchannel);
332332

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+
333352
/**
334353
* rpmsg_get_mtu() - get maximum transmission buffer size for sending message.
335354
* @ept: the rpmsg endpoint
@@ -539,6 +558,8 @@ static int rpmsg_dev_probe(struct device *dev)
539558

540559
rpdev->ept = ept;
541560
rpdev->src = ept->addr;
561+
562+
ept->flow_cb = rpdrv->flowcontrol;
542563
}
543564

544565
err = rpdrv->probe(rpdev);

drivers/rpmsg/rpmsg_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ struct rpmsg_device_ops {
5555
* @trysendto: see @rpmsg_trysendto(), optional
5656
* @trysend_offchannel: see @rpmsg_trysend_offchannel(), optional
5757
* @poll: see @rpmsg_poll(), optional
58+
* @set_flow_control: see @rpmsg_set_flow_control(), optional
5859
* @get_mtu: see @rpmsg_get_mtu(), optional
5960
*
6061
* Indirection table for the operations that a rpmsg backend should implement.
@@ -75,6 +76,7 @@ struct rpmsg_endpoint_ops {
7576
void *data, int len);
7677
__poll_t (*poll)(struct rpmsg_endpoint *ept, struct file *filp,
7778
poll_table *wait);
79+
int (*set_flow_control)(struct rpmsg_endpoint *ept, bool pause, u32 dst);
7880
ssize_t (*get_mtu)(struct rpmsg_endpoint *ept);
7981
};
8082

include/linux/rpmsg.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,14 @@ struct rpmsg_device {
6464
};
6565

6666
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);
6768

6869
/**
6970
* struct rpmsg_endpoint - binds a local rpmsg address to its user
7071
* @rpdev: rpmsg channel device
7172
* @refcount: when this drops to zero, the ept is deallocated
7273
* @cb: rx callback handler
74+
* @flow_cb: remote flow control callback handler
7375
* @cb_lock: must be taken before accessing/changing @cb
7476
* @addr: local rpmsg address
7577
* @priv: private data for the driver's use
@@ -92,6 +94,7 @@ struct rpmsg_endpoint {
9294
struct rpmsg_device *rpdev;
9395
struct kref refcount;
9496
rpmsg_rx_cb_t cb;
97+
rpmsg_flowcontrol_cb_t flow_cb;
9598
struct mutex cb_lock;
9699
u32 addr;
97100
void *priv;
@@ -106,13 +109,15 @@ struct rpmsg_endpoint {
106109
* @probe: invoked when a matching rpmsg channel (i.e. device) is found
107110
* @remove: invoked when the rpmsg channel is removed
108111
* @callback: invoked when an inbound message is received on the channel
112+
* @flowcontrol: invoked when remote side flow control request is received
109113
*/
110114
struct rpmsg_driver {
111115
struct device_driver drv;
112116
const struct rpmsg_device_id *id_table;
113117
int (*probe)(struct rpmsg_device *dev);
114118
void (*remove)(struct rpmsg_device *dev);
115119
int (*callback)(struct rpmsg_device *, void *, int, void *, u32);
120+
int (*flowcontrol)(struct rpmsg_device *, void *, bool);
116121
};
117122

118123
static inline u16 rpmsg16_to_cpu(struct rpmsg_device *rpdev, __rpmsg16 val)
@@ -192,6 +197,8 @@ __poll_t rpmsg_poll(struct rpmsg_endpoint *ept, struct file *filp,
192197

193198
ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept);
194199

200+
int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool pause, u32 dst);
201+
195202
#else
196203

197204
static inline int rpmsg_register_device_override(struct rpmsg_device *rpdev,
@@ -316,6 +323,14 @@ static inline ssize_t rpmsg_get_mtu(struct rpmsg_endpoint *ept)
316323
return -ENXIO;
317324
}
318325

326+
static inline int rpmsg_set_flow_control(struct rpmsg_endpoint *ept, bool pause, u32 dst)
327+
{
328+
/* This shouldn't be possible */
329+
WARN_ON(1);
330+
331+
return -ENXIO;
332+
}
333+
319334
#endif /* IS_ENABLED(CONFIG_RPMSG) */
320335

321336
/* use a macro to avoid include chaining to get THIS_MODULE */

include/uapi/linux/rpmsg.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,14 @@ struct rpmsg_endpoint_info {
4343
*/
4444
#define RPMSG_RELEASE_DEV_IOCTL _IOW(0xb5, 0x4, struct rpmsg_endpoint_info)
4545

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+
4656
#endif

0 commit comments

Comments
 (0)