Commit a01d9524 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull rpmsg updates from Bjorn Andersson:
 "In addition to some bug fixes and cleanups this adds support for
  exposing the virtio based transport to user space using the rpmsg_char
  driver"

* tag 'rpmsg-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/andersson/remoteproc:
  rpmsg: qcom_glink_native: fix error return code of qcom_glink_rx_data()
  rpmsg: char: Return an error if device already open
  rpmsg: virtio: Register the rpmsg_char device
  rpmsg: char: Use rpmsg_sendto to specify the message destination address
  rpmsg: Add short description of the IOCTL defined in UAPI.
  rpmsg: Move RPMSG_ADDR_ANY in user API
  rpmsg: char: Rename rpmsg_char_init to rpmsg_chrdev_init
parents 0c01a4c4 26594c6b
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -857,6 +857,7 @@ static int qcom_glink_rx_data(struct qcom_glink *glink, size_t avail)
			dev_err(glink->dev,
				"no intent found for channel %s intent %d",
				channel->name, liid);
			ret = -ENOENT;
			goto advance_rx;
		}
	}
@@ -1332,6 +1333,20 @@ static int qcom_glink_trysend(struct rpmsg_endpoint *ept, void *data, int len)
	return __qcom_glink_send(channel, data, len, false);
}

static int qcom_glink_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
{
	struct glink_channel *channel = to_glink_channel(ept);

	return __qcom_glink_send(channel, data, len, true);
}

static int qcom_glink_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
{
	struct glink_channel *channel = to_glink_channel(ept);

	return __qcom_glink_send(channel, data, len, false);
}

/*
 * Finds the device_node for the glink child interested in this channel.
 */
@@ -1364,7 +1379,9 @@ static const struct rpmsg_device_ops glink_device_ops = {
static const struct rpmsg_endpoint_ops glink_endpoint_ops = {
	.destroy_ept = qcom_glink_destroy_ept,
	.send = qcom_glink_send,
	.sendto = qcom_glink_sendto,
	.trysend = qcom_glink_trysend,
	.trysendto = qcom_glink_trysendto,
};

static void qcom_glink_rpdev_release(struct device *dev)
+16 −0
Original line number Diff line number Diff line
@@ -974,6 +974,20 @@ static int qcom_smd_trysend(struct rpmsg_endpoint *ept, void *data, int len)
	return __qcom_smd_send(qsept->qsch, data, len, false);
}

static int qcom_smd_sendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
{
	struct qcom_smd_endpoint *qsept = to_smd_endpoint(ept);

	return __qcom_smd_send(qsept->qsch, data, len, true);
}

static int qcom_smd_trysendto(struct rpmsg_endpoint *ept, void *data, int len, u32 dst)
{
	struct qcom_smd_endpoint *qsept = to_smd_endpoint(ept);

	return __qcom_smd_send(qsept->qsch, data, len, false);
}

static __poll_t qcom_smd_poll(struct rpmsg_endpoint *ept,
				  struct file *filp, poll_table *wait)
{
@@ -1038,7 +1052,9 @@ static const struct rpmsg_device_ops qcom_smd_device_ops = {
static const struct rpmsg_endpoint_ops qcom_smd_endpoint_ops = {
	.destroy_ept = qcom_smd_destroy_ept,
	.send = qcom_smd_send,
	.sendto = qcom_smd_sendto,
	.trysend = qcom_smd_trysend,
	.trysendto = qcom_smd_trysendto,
	.poll = qcom_smd_poll,
};

+7 −4
Original line number Diff line number Diff line
@@ -127,6 +127,9 @@ static int rpmsg_eptdev_open(struct inode *inode, struct file *filp)
	struct rpmsg_device *rpdev = eptdev->rpdev;
	struct device *dev = &eptdev->dev;

	if (eptdev->ept)
		return -EBUSY;

	get_device(dev);

	ept = rpmsg_create_ept(rpdev, rpmsg_ept_cb, eptdev, eptdev->chinfo);
@@ -239,9 +242,9 @@ static ssize_t rpmsg_eptdev_write_iter(struct kiocb *iocb,
	}

	if (filp->f_flags & O_NONBLOCK)
		ret = rpmsg_trysend(eptdev->ept, kbuf, len);
		ret = rpmsg_trysendto(eptdev->ept, kbuf, len, eptdev->chinfo.dst);
	else
		ret = rpmsg_send(eptdev->ept, kbuf, len);
		ret = rpmsg_sendto(eptdev->ept, kbuf, len, eptdev->chinfo.dst);

unlock_eptdev:
	mutex_unlock(&eptdev->ept_lock);
@@ -543,7 +546,7 @@ static struct rpmsg_driver rpmsg_chrdev_driver = {
	},
};

static int rpmsg_char_init(void)
static int rpmsg_chrdev_init(void)
{
	int ret;

@@ -569,7 +572,7 @@ static int rpmsg_char_init(void)

	return ret;
}
postcore_initcall(rpmsg_char_init);
postcore_initcall(rpmsg_chrdev_init);

static void rpmsg_chrdev_exit(void)
{
+57 −5
Original line number Diff line number Diff line
@@ -813,14 +813,57 @@ static void rpmsg_xmit_done(struct virtqueue *svq)
	wake_up_interruptible(&vrp->sendq);
}

/*
 * Called to expose to user a /dev/rpmsg_ctrlX interface allowing to
 * create endpoint-to-endpoint communication without associated RPMsg channel.
 * The endpoints are rattached to the ctrldev RPMsg device.
 */
static struct rpmsg_device *rpmsg_virtio_add_ctrl_dev(struct virtio_device *vdev)
{
	struct virtproc_info *vrp = vdev->priv;
	struct virtio_rpmsg_channel *vch;
	struct rpmsg_device *rpdev_ctrl;
	int err = 0;

	vch = kzalloc(sizeof(*vch), GFP_KERNEL);
	if (!vch)
		return ERR_PTR(-ENOMEM);

	/* Link the channel to the vrp */
	vch->vrp = vrp;

	/* Assign public information to the rpmsg_device */
	rpdev_ctrl = &vch->rpdev;
	rpdev_ctrl->ops = &virtio_rpmsg_ops;

	rpdev_ctrl->dev.parent = &vrp->vdev->dev;
	rpdev_ctrl->dev.release = virtio_rpmsg_release_device;
	rpdev_ctrl->little_endian = virtio_is_little_endian(vrp->vdev);

	err = rpmsg_chrdev_register_device(rpdev_ctrl);
	if (err) {
		kfree(vch);
		return ERR_PTR(err);
	}

	return rpdev_ctrl;
}

static void rpmsg_virtio_del_ctrl_dev(struct rpmsg_device *rpdev_ctrl)
{
	if (!rpdev_ctrl)
		return;
	kfree(to_virtio_rpmsg_channel(rpdev_ctrl));
}

static int rpmsg_probe(struct virtio_device *vdev)
{
	vq_callback_t *vq_cbs[] = { rpmsg_recv_done, rpmsg_xmit_done };
	static const char * const names[] = { "input", "output" };
	struct virtqueue *vqs[2];
	struct virtproc_info *vrp;
	struct virtio_rpmsg_channel *vch;
	struct rpmsg_device *rpdev_ns;
	struct virtio_rpmsg_channel *vch = NULL;
	struct rpmsg_device *rpdev_ns, *rpdev_ctrl;
	void *bufs_va;
	int err = 0, i;
	size_t total_buf_space;
@@ -894,12 +937,18 @@ static int rpmsg_probe(struct virtio_device *vdev)

	vdev->priv = vrp;

	rpdev_ctrl = rpmsg_virtio_add_ctrl_dev(vdev);
	if (IS_ERR(rpdev_ctrl)) {
		err = PTR_ERR(rpdev_ctrl);
		goto free_coherent;
	}

	/* if supported by the remote processor, enable the name service */
	if (virtio_has_feature(vdev, VIRTIO_RPMSG_F_NS)) {
		vch = kzalloc(sizeof(*vch), GFP_KERNEL);
		if (!vch) {
			err = -ENOMEM;
			goto free_coherent;
			goto free_ctrldev;
		}

		/* Link the channel to our vrp */
@@ -915,7 +964,7 @@ static int rpmsg_probe(struct virtio_device *vdev)

		err = rpmsg_ns_register_device(rpdev_ns);
		if (err)
			goto free_coherent;
			goto free_vch;
	}

	/*
@@ -939,8 +988,11 @@ static int rpmsg_probe(struct virtio_device *vdev)

	return 0;

free_coherent:
free_vch:
	kfree(vch);
free_ctrldev:
	rpmsg_virtio_del_ctrl_dev(rpdev_ctrl);
free_coherent:
	dma_free_coherent(vdev->dev.parent, total_buf_space,
			  bufs_va, vrp->bufs_dma);
vqs_del:
+1 −2
Original line number Diff line number Diff line
@@ -18,8 +18,7 @@
#include <linux/mutex.h>
#include <linux/poll.h>
#include <linux/rpmsg/byteorder.h>

#define RPMSG_ADDR_ANY		0xFFFFFFFF
#include <uapi/linux/rpmsg.h>

struct rpmsg_device;
struct rpmsg_endpoint;
Loading