Skip to content

Commit

Permalink
Merge tag 'rpmsg-v5.16' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…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()
  • Loading branch information
Linus Torvalds committed Nov 10, 2021
2 parents cb690f5 + b16a37e commit becc1fb
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 12 deletions.
2 changes: 1 addition & 1 deletion drivers/rpmsg/mtk_rpmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
90 changes: 82 additions & 8 deletions drivers/rpmsg/qcom_glink_native.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -118,6 +120,8 @@ struct qcom_glink {
unsigned long features;

bool intentless;
wait_queue_head_t tx_avail_notify;
bool sent_read_notify;
};

enum {
Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand All @@ -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")) {
Expand All @@ -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);
}

Expand Down Expand Up @@ -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);
Expand Down
3 changes: 1 addition & 2 deletions drivers/rpmsg/virtio_rpmsg_bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion include/linux/rpmsg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit becc1fb

Please sign in to comment.