rpmsg updates for v5.16
For the GLINK implementation this adds support for splitting outgoing messages that are too large to fit in the fifo, it introduces the use of "read notifications", to avoid polling in the case where the outgoing fifo is full and a few bugs are squashed. The return value of rpmsg_create_ept() for when RPMSG is disabled is corrected to return a valid error, the Mediatek rpmsg driver is updated to match the DT binding and a couple of cleanups are done in the virtio rpmsg driver. -----BEGIN PGP SIGNATURE----- iQJPBAABCAA5FiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAmGJXMkbHGJqb3JuLmFu ZGVyc3NvbkBsaW5hcm8ub3JnAAoJEAsfOT8Nma3F1tgP/RNK/m+bsWHDVRvMww1z SCC+E4b8vJIceifqvXataO5vMErFyQdTi9ijFNogqIlJF+ouVp/sHmfCCwFG4urw /IccreIcBWMoY8+efjomLVvCMEzd1RlSG484yKs4p8Jz7hDgGeDHzQOwe0CsTY/L b2Qi6fV6i1/sfK1vlf4dHFA7Y66KwjknvNCasCWkadBSJnJeali9QeRsDYaQCaJL C2QirxX7V2rxJZH248MOuG+E0e1oVgccvp9dACbsasfOrsekWc7Twizaqvdl+RxF q2YXH82WVClOQgyp09tZ8zk4IIVzzxKZlWL/so7sdiEI009HHNc7YhGkRUdzhzma neWPJ6emVUD4Gwgkr2OAkc14wR99iSgdjvN2CcZjOHgBKos2AvjN/JsrGLswVdDU PZs4EXzvgw98hOOTpw0X1E8TZvtt3wcUyoXpWop2+pXOs9rajR0lyorlW8ubXhLN TpC2Yypy8vY4kBn3Ob/sJlu5CNasMg3a4TFhJBCWIrmS+5MxwOtvAi+i4Omg6754 075zhFuxXuFdszWqtJHBukHpmhYkK1shexEnkLdPiCwpG2Q9159ILD2TKVIjAOQy 112o8KSCWcPR0VNoenTunqfw/YiOYmEeIGQBRfsxrFUurmPQMICN+xfei/8vQftg D9hxikFXc7JJl+OahXnvSUZv =jGA6 -----END PGP SIGNATURE----- Merge tag 'rpmsg-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux Pull rpmsg updates from Bjorn Andersson: "For the GLINK implementation this adds support for splitting outgoing messages that are too large to fit in the fifo, it introduces the use of "read notifications", to avoid polling in the case where the outgoing fifo is full and a few bugs are squashed. The return value of rpmsg_create_ept() for when RPMSG is disabled is corrected to return a valid error, the Mediatek rpmsg driver is updated to match the DT binding and a couple of cleanups are done in the virtio rpmsg driver" * tag 'rpmsg-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc/linux: rpmsg: glink: Send READ_NOTIFY command in FIFO full case rpmsg: glink: Remove channel decouple from rpdev release rpmsg: glink: Remove the rpmsg dev in close_ack rpmsg: glink: Add TX_DATA_CONT command while sending rpmsg: virtio_rpmsg_bus: use dev_warn_ratelimited for msg with no recipient rpmsg: virtio: Remove unused including <linux/of_device.h> rpmsg: Change naming of mediatek rpmsg property rpmsg: Fix rpmsg_create_ept return when RPMSG config is not defined rpmsg: glink: Replace strncpy() with strscpy_pad()
This commit is contained in:
commit
becc1fb4f3
|
@ -183,7 +183,7 @@ mtk_rpmsg_match_device_subnode(struct device_node *node, const char *channel)
|
|||
int ret;
|
||||
|
||||
for_each_available_child_of_node(node, child) {
|
||||
ret = of_property_read_string(child, "mtk,rpmsg-name", &name);
|
||||
ret = of_property_read_string(child, "mediatek,rpmsg-name", &name);
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -92,6 +92,8 @@ struct glink_core_rx_intent {
|
|||
* @rcids: idr of all channels with a known remote channel id
|
||||
* @features: remote features
|
||||
* @intentless: flag to indicate that there is no intent
|
||||
* @tx_avail_notify: Waitqueue for pending tx tasks
|
||||
* @sent_read_notify: flag to check cmd sent or not
|
||||
*/
|
||||
struct qcom_glink {
|
||||
struct device *dev;
|
||||
|
@ -118,6 +120,8 @@ struct qcom_glink {
|
|||
unsigned long features;
|
||||
|
||||
bool intentless;
|
||||
wait_queue_head_t tx_avail_notify;
|
||||
bool sent_read_notify;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -301,6 +305,20 @@ static void qcom_glink_tx_write(struct qcom_glink *glink,
|
|||
glink->tx_pipe->write(glink->tx_pipe, hdr, hlen, data, dlen);
|
||||
}
|
||||
|
||||
static void qcom_glink_send_read_notify(struct qcom_glink *glink)
|
||||
{
|
||||
struct glink_msg msg;
|
||||
|
||||
msg.cmd = cpu_to_le16(RPM_CMD_READ_NOTIF);
|
||||
msg.param1 = 0;
|
||||
msg.param2 = 0;
|
||||
|
||||
qcom_glink_tx_write(glink, &msg, sizeof(msg), NULL, 0);
|
||||
|
||||
mbox_send_message(glink->mbox_chan, NULL);
|
||||
mbox_client_txdone(glink->mbox_chan, 0);
|
||||
}
|
||||
|
||||
static int qcom_glink_tx(struct qcom_glink *glink,
|
||||
const void *hdr, size_t hlen,
|
||||
const void *data, size_t dlen, bool wait)
|
||||
|
@ -321,12 +339,21 @@ static int qcom_glink_tx(struct qcom_glink *glink,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!glink->sent_read_notify) {
|
||||
glink->sent_read_notify = true;
|
||||
qcom_glink_send_read_notify(glink);
|
||||
}
|
||||
|
||||
/* Wait without holding the tx_lock */
|
||||
spin_unlock_irqrestore(&glink->tx_lock, flags);
|
||||
|
||||
usleep_range(10000, 15000);
|
||||
wait_event_timeout(glink->tx_avail_notify,
|
||||
qcom_glink_tx_avail(glink) >= tlen, 10 * HZ);
|
||||
|
||||
spin_lock_irqsave(&glink->tx_lock, flags);
|
||||
|
||||
if (qcom_glink_tx_avail(glink) >= tlen)
|
||||
glink->sent_read_notify = false;
|
||||
}
|
||||
|
||||
qcom_glink_tx_write(glink, hdr, hlen, data, dlen);
|
||||
|
@ -986,6 +1013,9 @@ static irqreturn_t qcom_glink_native_intr(int irq, void *data)
|
|||
unsigned int cmd;
|
||||
int ret = 0;
|
||||
|
||||
/* To wakeup any blocking writers */
|
||||
wake_up_all(&glink->tx_avail_notify);
|
||||
|
||||
for (;;) {
|
||||
avail = qcom_glink_rx_avail(glink);
|
||||
if (avail < sizeof(msg))
|
||||
|
@ -1271,6 +1301,8 @@ static int __qcom_glink_send(struct glink_channel *channel,
|
|||
} __packed req;
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
int chunk_size = len;
|
||||
int left_size = 0;
|
||||
|
||||
if (!glink->intentless) {
|
||||
while (!intent) {
|
||||
|
@ -1304,18 +1336,46 @@ static int __qcom_glink_send(struct glink_channel *channel,
|
|||
iid = intent->id;
|
||||
}
|
||||
|
||||
if (wait && chunk_size > SZ_8K) {
|
||||
chunk_size = SZ_8K;
|
||||
left_size = len - chunk_size;
|
||||
}
|
||||
req.msg.cmd = cpu_to_le16(RPM_CMD_TX_DATA);
|
||||
req.msg.param1 = cpu_to_le16(channel->lcid);
|
||||
req.msg.param2 = cpu_to_le32(iid);
|
||||
req.chunk_size = cpu_to_le32(len);
|
||||
req.left_size = cpu_to_le32(0);
|
||||
req.chunk_size = cpu_to_le32(chunk_size);
|
||||
req.left_size = cpu_to_le32(left_size);
|
||||
|
||||
ret = qcom_glink_tx(glink, &req, sizeof(req), data, len, wait);
|
||||
ret = qcom_glink_tx(glink, &req, sizeof(req), data, chunk_size, wait);
|
||||
|
||||
/* Mark intent available if we failed */
|
||||
if (ret && intent)
|
||||
if (ret && intent) {
|
||||
intent->in_use = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (left_size > 0) {
|
||||
data = (void *)((char *)data + chunk_size);
|
||||
chunk_size = left_size;
|
||||
if (chunk_size > SZ_8K)
|
||||
chunk_size = SZ_8K;
|
||||
left_size -= chunk_size;
|
||||
|
||||
req.msg.cmd = cpu_to_le16(RPM_CMD_TX_DATA_CONT);
|
||||
req.msg.param1 = cpu_to_le16(channel->lcid);
|
||||
req.msg.param2 = cpu_to_le32(iid);
|
||||
req.chunk_size = cpu_to_le32(chunk_size);
|
||||
req.left_size = cpu_to_le32(left_size);
|
||||
|
||||
ret = qcom_glink_tx(glink, &req, sizeof(req), data,
|
||||
chunk_size, wait);
|
||||
|
||||
/* Mark intent available if we failed */
|
||||
if (ret && intent) {
|
||||
intent->in_use = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1387,9 +1447,7 @@ static const struct rpmsg_endpoint_ops glink_endpoint_ops = {
|
|||
static void qcom_glink_rpdev_release(struct device *dev)
|
||||
{
|
||||
struct rpmsg_device *rpdev = to_rpmsg_device(dev);
|
||||
struct glink_channel *channel = to_glink_channel(rpdev->ept);
|
||||
|
||||
channel->rpdev = NULL;
|
||||
kfree(rpdev);
|
||||
}
|
||||
|
||||
|
@ -1440,7 +1498,7 @@ static int qcom_glink_rx_open(struct qcom_glink *glink, unsigned int rcid,
|
|||
}
|
||||
|
||||
rpdev->ept = &channel->ept;
|
||||
strncpy(rpdev->id.name, name, RPMSG_NAME_SIZE);
|
||||
strscpy_pad(rpdev->id.name, name, RPMSG_NAME_SIZE);
|
||||
rpdev->src = RPMSG_ADDR_ANY;
|
||||
rpdev->dst = RPMSG_ADDR_ANY;
|
||||
rpdev->ops = &glink_device_ops;
|
||||
|
@ -1494,6 +1552,7 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid)
|
|||
|
||||
rpmsg_unregister_device(glink->dev, &chinfo);
|
||||
}
|
||||
channel->rpdev = NULL;
|
||||
|
||||
qcom_glink_send_close_ack(glink, channel->rcid);
|
||||
|
||||
|
@ -1507,9 +1566,13 @@ static void qcom_glink_rx_close(struct qcom_glink *glink, unsigned int rcid)
|
|||
|
||||
static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int lcid)
|
||||
{
|
||||
struct rpmsg_channel_info chinfo;
|
||||
struct glink_channel *channel;
|
||||
unsigned long flags;
|
||||
|
||||
/* To wakeup any blocking writers */
|
||||
wake_up_all(&glink->tx_avail_notify);
|
||||
|
||||
spin_lock_irqsave(&glink->idr_lock, flags);
|
||||
channel = idr_find(&glink->lcids, lcid);
|
||||
if (WARN(!channel, "close ack on unknown channel\n")) {
|
||||
|
@ -1521,6 +1584,16 @@ static void qcom_glink_rx_close_ack(struct qcom_glink *glink, unsigned int lcid)
|
|||
channel->lcid = 0;
|
||||
spin_unlock_irqrestore(&glink->idr_lock, flags);
|
||||
|
||||
/* Decouple the potential rpdev from the channel */
|
||||
if (channel->rpdev) {
|
||||
strscpy(chinfo.name, channel->name, sizeof(chinfo.name));
|
||||
chinfo.src = RPMSG_ADDR_ANY;
|
||||
chinfo.dst = RPMSG_ADDR_ANY;
|
||||
|
||||
rpmsg_unregister_device(glink->dev, &chinfo);
|
||||
}
|
||||
channel->rpdev = NULL;
|
||||
|
||||
kref_put(&channel->refcount, qcom_glink_channel_release);
|
||||
}
|
||||
|
||||
|
@ -1670,6 +1743,7 @@ struct qcom_glink *qcom_glink_native_probe(struct device *dev,
|
|||
spin_lock_init(&glink->rx_lock);
|
||||
INIT_LIST_HEAD(&glink->rx_queue);
|
||||
INIT_WORK(&glink->rx_work, qcom_glink_work);
|
||||
init_waitqueue_head(&glink->tx_avail_notify);
|
||||
|
||||
spin_lock_init(&glink->idr_lock);
|
||||
idr_init(&glink->lcids);
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/rpmsg.h>
|
||||
#include <linux/rpmsg/byteorder.h>
|
||||
#include <linux/rpmsg/ns.h>
|
||||
|
@ -759,7 +758,7 @@ static int rpmsg_recv_single(struct virtproc_info *vrp, struct device *dev,
|
|||
/* farewell, ept, we don't need you anymore */
|
||||
kref_put(&ept->refcount, __ept_release);
|
||||
} else
|
||||
dev_warn(dev, "msg received with no recipient\n");
|
||||
dev_warn_ratelimited(dev, "msg received with no recipient\n");
|
||||
|
||||
/* publish the real size of the buffer */
|
||||
rpmsg_sg_init(&sg, msg, vrp->buf_size);
|
||||
|
|
|
@ -233,7 +233,7 @@ static inline struct rpmsg_endpoint *rpmsg_create_ept(struct rpmsg_device *rpdev
|
|||
/* This shouldn't be possible */
|
||||
WARN_ON(1);
|
||||
|
||||
return ERR_PTR(-ENXIO);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int rpmsg_send(struct rpmsg_endpoint *ept, void *data, int len)
|
||||
|
|
Loading…
Reference in New Issue